commit 81944a304a686d944208e97105f1640e1768843b Author: flym Date: Tue Oct 14 16:57:01 2025 +0800 inited diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..70d62db --- /dev/null +++ b/.gitignore @@ -0,0 +1,57 @@ +# Prerequisites +*.d + +# Object files +*.o +*.ko +*.obj +*.elf + +# Linker output +*.ilk +*.map +*.exp +# *.ld +sdk.ld + +# Precompiled Headers +*.gch +*.pch + +# Libraries +*.lib +*.la +*.lo + +# Shared objects (inc. Windows DLLs) +# *.dll +*.so +*.so.* +*.dylib + +# Executables +# *.exe +*.out +*.app +*.i*86 +*.x86_64 +*.hex + +# Debug files +*.dSYM/ +*.su +*.idb +*.pdb + +# Kernel Module Compile Results +*.mod* +*.cmd +.tmp_versions/ +modules.order +Module.symvers +Mkfile.old +dkms.conf +tags +filenametags +cscope.out +*.bc diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 0000000..04061a2 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,138 @@ +{ + "configurations": [ + { + "cStandard": "c99", + "compilerPath": "C:/JL/pi32/bin/clang.exe", + "cppStandard": "c++11", + "defines": [ + "SUPPORT_MS_EXTENSIONS", + "CONFIG_CPU_BR23", + "CONFIG_RELEASE_ENABLE", + "CONFIG_EQ_SUPPORT_ASYNC", + "EQ_CORE_V2", + "CONFIG_MIXER_CYCLIC", + "CONFIG_FREE_RTOS_ENABLE", + "SUPPORT_BLUETOOTH_PROFILE_RELEASE", + "CONFIG_SOUNDBOX", + "EVENT_HANDLER_NUM_CONFIG=2", + "EVENT_TOUCH_ENABLE_CONFIG=0", + "EVENT_POOL_SIZE_CONFIG=256", + "CONFIG_EVENT_KEY_MAP_ENABLE=0", + "TIMER_POOL_NUM_CONFIG=15", + "APP_ASYNC_POOL_NUM_CONFIG=0", + "VFS_ENABLE=1", + "USE_SDFILE_NEW=1", + "SDFILE_STORAGE=1", + "VFS_FILE_POOL_NUM_CONFIG=1", + "FS_VERSION=0x020001", + "FATFS_VERSION=0x020101", + "SDFILE_VERSION=0x020000", + "VM_MAX_SIZE_CONFIG=64*1024", + "VM_ITEM_MAX_NUM=256", + "CONFIG_TWS_ENABLE", + "CONFIG_SOUNDBOX_CASE_ENABLE", + "CONFIG_NEW_CFG_TOOL_ENABLE", + "AUDIO_REC_POOL_NUM=1", + "AUDIO_DEC_POOL_NUM=3", + "AUDIO_LOCAL_DEC_USE_MALLOC", + "CONFIG_TONE_LOCK_BY_BT_TIME", + "CONFIG_LMP_CONN_SUSPEND_ENABLE", + "CONFIG_BTCTRLER_TASK_DEL_ENABLE", + "CONFIG_UPDATA_ENABLE", + "CONFIG_OTA_UPDATA_ENABLE", + "CONFIG_ITEM_FORMAT_VM", + "CONFIG_DNS_ENABLE", + "CONFIG_MMU_ENABLE", + "CONFIG_SBC_CODEC_HW", + "CONFIG_MSBC_CODEC_HW", + "CONFIG_AEC_M=640", + "CONFIG_AUDIO_ONCHIP", + "CONFIG_MEDIA_DEVELOP_ENABLE", + "CONFIG_MEDIA_EFFECT_DISABLE", + "__GCC_PI32V2__", + "CONFIG_NEW_ECC_ENABLE", + "__PI32V2__" + ], + "includePath": [ + "${workspaceFolder}/include_lib", + "${workspaceFolder}/include_lib\\driver", + "${workspaceFolder}/include_lib\\driver\\device", + "${workspaceFolder}/include_lib\\driver\\cpu\\br23", + "${workspaceFolder}/include_lib\\system", + "${workspaceFolder}/include_lib\\system\\generic", + "${workspaceFolder}/include_lib\\system\\device", + "${workspaceFolder}/include_lib\\system\\fs", + "${workspaceFolder}/include_lib\\system\\ui", + "${workspaceFolder}/include_lib\\btctrler", + "${workspaceFolder}/include_lib\\btctrler\\port\\br23", + "${workspaceFolder}/include_lib\\update", + "${workspaceFolder}/include_lib\\agreement", + "${workspaceFolder}/include_lib\\btstack\\third_party\\common", + "${workspaceFolder}/include_lib\\btstack\\third_party\\rcsp", + "${workspaceFolder}/include_lib\\media\\media_develop", + "${workspaceFolder}/include_lib\\media\\media_develop\\media", + "${workspaceFolder}/include_lib\\media\\media_develop\\media\\cpu\\br23", + "${workspaceFolder}/include_lib\\media\\media_develop\\media\\cpu\\br23\\asm", + "${workspaceFolder}/cpu\\br23\\audio_mic", + "${workspaceFolder}/apps\\soundbox\\include", + "${workspaceFolder}/apps\\soundbox\\include\\task_manager", + "${workspaceFolder}/apps\\soundbox\\include\\task_manager\\bt", + "${workspaceFolder}/apps\\soundbox\\include\\user_api", + "${workspaceFolder}/apps\\common", + "${workspaceFolder}/apps\\common\\device", + "${workspaceFolder}/apps\\common\\audio", + "${workspaceFolder}/apps\\common\\audio\\stream", + "${workspaceFolder}/apps\\common\\power_manage", + "${workspaceFolder}/apps\\common\\charge_box", + "${workspaceFolder}/apps\\common\\third_party_profile\\common", + "${workspaceFolder}/apps\\common\\third_party_profile\\interface", + "${workspaceFolder}/apps\\common\\third_party_profile\\jieli", + "${workspaceFolder}/apps\\common\\third_party_profile\\jieli\\trans_data_demo", + "${workspaceFolder}/apps\\common\\third_party_profile\\jieli\\online_db", + "${workspaceFolder}/apps\\common\\third_party_profile\\jieli\\JL_rcsp", + "${workspaceFolder}/apps\\common\\third_party_profile\\jieli\\JL_rcsp\\rcsp_updata", + "${workspaceFolder}/apps\\common\\third_party_profile\\jieli\\JL_rcsp\\bt_trans_data", + "${workspaceFolder}/apps\\common\\third_party_profile\\jieli\\JL_rcsp\\adv_rcsp_protocol", + "${workspaceFolder}/apps\\common\\third_party_profile\\jieli\\JL_rcsp\\adv_app_setting", + "${workspaceFolder}/apps\\common\\dev_manager", + "${workspaceFolder}/apps\\common\\file_operate", + "${workspaceFolder}/apps\\common\\music", + "${workspaceFolder}/apps\\common\\include", + "${workspaceFolder}/apps\\common\\config\\include", + "${workspaceFolder}/apps\\soundbox\\board\\br23", + "${workspaceFolder}/cpu\\br23", + "${workspaceFolder}/cpu\\br23\\audio_common", + "${workspaceFolder}/cpu\\br23\\audio_dec", + "${workspaceFolder}/cpu\\br23\\audio_enc", + "${workspaceFolder}/cpu\\br23\\audio_effect", + "${workspaceFolder}/cpu\\br23\\localtws", + "${workspaceFolder}/include_lib\\btstack", + "${workspaceFolder}/apps\\common\\third_party_profile\\tuya_protocol", + "${workspaceFolder}/apps\\common\\third_party_profile\\tuya_protocol\\app\\demo", + "${workspaceFolder}/apps\\common\\third_party_profile\\tuya_protocol\\app\\product_test", + "${workspaceFolder}/apps\\common\\third_party_profile\\tuya_protocol\\app\\uart_common", + "${workspaceFolder}/apps\\common\\third_party_profile\\tuya_protocol\\extern_components\\mbedtls", + "${workspaceFolder}/apps\\common\\third_party_profile\\tuya_protocol\\port", + "${workspaceFolder}/apps\\common\\third_party_profile\\tuya_protocol\\sdk\\include", + "${workspaceFolder}/apps\\common\\third_party_profile\\tuya_protocol\\sdk\\lib", + "${workspaceFolder}/apps\\common\\usb", + "${workspaceFolder}/apps\\common\\usb\\device", + "${workspaceFolder}/apps\\common\\usb\\host", + "${workspaceFolder}/apps\\soundbox\\smartbox", + "${workspaceFolder}/apps\\soundbox\\smartbox\\bt_manage\\bt_trans_data", + "${workspaceFolder}/apps\\soundbox\\smartbox\\bt_manage", + "${workspaceFolder}/apps\\soundbox\\smartbox\\smartbox_setting", + "${workspaceFolder}/apps\\soundbox\\smartbox\\smartbox_setting\\smartbox_misc_setting", + "${workspaceFolder}/apps\\soundbox\\smartbox\\smartbox_setting_opt", + "${workspaceFolder}/apps\\soundbox\\smartbox\\smartbox_update", + "${workspaceFolder}/apps\\soundbox\\smartbox\\file_transfer", + "${workspaceFolder}/apps\\soundbox\\smartbox\\tuya", + "${workspaceFolder}/apps\\soundbox\\include\\ui\\color_led", + "C:/JL/pi32/pi32v2-include" + ], + "intelliSenseMode": "clang-x86", + "name": "AC695N_TEST_GB" + } + ], + "version": 4 +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..ade47e1 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,28 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "all", + "type": "shell", + "windows": { + "command": ".vscode/winmk.bat all" + }, + "command": "make all -j`nproc`", + "problemMatcher": [], + "group": { + "kind": "build", + "isDefault": true + } + } + ,{ + "label": "clean", + "type": "shell", + "windows": { + "command": ".vscode/winmk.bat clean" + }, + "command": "make clean -j`nproc`", + "problemMatcher": [], + "group": "build" + } + ] +} diff --git a/.vscode/winmk.bat b/.vscode/winmk.bat new file mode 100644 index 0000000..3a2e7a1 --- /dev/null +++ b/.vscode/winmk.bat @@ -0,0 +1,3 @@ +SET SCRIPT_PATH=%~dp0% +SET PATH=%SCRIPT_PATH%\..\tools\utils;%PATH% +make "%1" -j %NUMBER_OF_PROCESSORS% diff --git a/AC695N_soundbox.cbp b/AC695N_soundbox.cbp new file mode 100644 index 0000000..e8e04f5 --- /dev/null +++ b/AC695N_soundbox.cbp @@ -0,0 +1,2371 @@ + + + + + + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..941b375 --- /dev/null +++ b/Makefile @@ -0,0 +1,972 @@ + +# make 编译并下载 +# make VERBOSE=1 显示编译详细过程 +# make clean 清除编译临时文件 +# +# 注意: Linux 下编译方式: +# 1. 从 http://pkgman.jieliapp.com/doc/all 处找到下载链接 +# 2. 下载后,解压到 /opt/jieli 目录下,保证 +# /opt/jieli/common/bin/clang 存在(注意目录层次) +# 3. 确认 ulimit -n 的结果足够大(建议大于8096),否则链接可能会因为打开文件太多而失败 +# 可以通过 ulimit -n 8096 来设置一个较大的值 +# + +# 工具路径设置 +ifeq ($(OS), Windows_NT) +# Windows 下工具链位置 +TOOL_DIR := C:/JL/pi32/bin +CC := clang.exe +CXX := clang.exe +LD := pi32v2-lto-wrapper.exe +AR := pi32v2-lto-ar.exe +MKDIR := mkdir_win -p +RM := rm -rf + +SYS_LIB_DIR := C:/JL/pi32/pi32v2-lib/r3 +SYS_INC_DIR := C:/JL/pi32/pi32v2-include +EXT_CFLAGS := # Windows 下不需要 -D__SHELL__ +export PATH:=$(TOOL_DIR);$(PATH) + +## 后处理脚本 +FIXBAT := tools\utils\fixbat.exe # 用于处理 utf8->gbk 编码问题 +POST_SCRIPT := cpu\br23\tools\download.bat +RUN_POST_SCRIPT := $(POST_SCRIPT) +else +# Linux 下工具链位置 +TOOL_DIR := /opt/jieli/pi32v2/bin +CC := clang +CXX := clang++ +LD := lto-wrapper +AR := lto-ar +MKDIR := mkdir -p +RM := rm -rf +export OBJDUMP := $(TOOL_DIR)/objdump +export OBJCOPY := $(TOOL_DIR)/objcopy +export OBJSIZEDUMP := $(TOOL_DIR)/objsizedump + +SYS_LIB_DIR := $(TOOL_DIR)/../lib/r3 +SYS_INC_DIR := $(TOOL_DIR)/../include +EXT_CFLAGS := -D__SHELL__ # Linux 下需要这个保证正确处理 download.c +export PATH:=$(TOOL_DIR):$(PATH) + +## 后处理脚本 +FIXBAT := touch # Linux下不需要处理 bat 编码问题 +POST_SCRIPT := cpu/br23/tools/download.sh +RUN_POST_SCRIPT := bash $(POST_SCRIPT) +endif + +CC := $(TOOL_DIR)/$(CC) +CXX := $(TOOL_DIR)/$(CXX) +LD := $(TOOL_DIR)/$(LD) +AR := $(TOOL_DIR)/$(AR) +# 输出文件设置 +OUT_ELF := cpu/br23/tools/sdk.elf +OBJ_FILE := $(OUT_ELF).objs.txt +# 编译路径设置 +BUILD_DIR := objs + +# 编译参数设置 +CFLAGS := \ + -target pi32v2 \ + -mcpu=r3 \ + -integrated-as \ + -flto \ + -flto \ + -g \ + -Wuninitialized \ + -Wno-invalid-noreturn \ + -fno-common \ + -integrated-as \ + -Oz \ + -fallow-pointer-null \ + -fprefer-gnu-section \ + -Wno-shift-negative-value \ + -fms-extensions \ + + +# C++额外的编译参数 +CXXFLAGS := + + +# 宏定义 +DEFINES := \ + -DSUPPORT_MS_EXTENSIONS \ + -DCONFIG_CPU_BR23 \ + -DCONFIG_RELEASE_ENABLE \ + -DCONFIG_EQ_SUPPORT_ASYNC \ + -DEQ_CORE_V2 \ + -DCONFIG_MIXER_CYCLIC \ + -DCONFIG_FREE_RTOS_ENABLE \ + -DSUPPORT_BLUETOOTH_PROFILE_RELEASE \ + -DCONFIG_SOUNDBOX \ + -DEVENT_HANDLER_NUM_CONFIG=2 \ + -DEVENT_TOUCH_ENABLE_CONFIG=0 \ + -DEVENT_POOL_SIZE_CONFIG=256 \ + -DCONFIG_EVENT_KEY_MAP_ENABLE=0 \ + -DTIMER_POOL_NUM_CONFIG=15 \ + -DAPP_ASYNC_POOL_NUM_CONFIG=0 \ + -DVFS_ENABLE=1 \ + -DUSE_SDFILE_NEW=1 \ + -DSDFILE_STORAGE=1 \ + -DVFS_FILE_POOL_NUM_CONFIG=1 \ + -DFS_VERSION=0x020001 \ + -DFATFS_VERSION=0x020101 \ + -DSDFILE_VERSION=0x020000 \ + -DVM_MAX_SIZE_CONFIG=64*1024 \ + -DVM_ITEM_MAX_NUM=256 \ + -DCONFIG_TWS_ENABLE \ + -DCONFIG_SOUNDBOX_CASE_ENABLE \ + -DCONFIG_NEW_CFG_TOOL_ENABLE \ + -DAUDIO_REC_POOL_NUM=1 \ + -DAUDIO_DEC_POOL_NUM=3 \ + -DAUDIO_LOCAL_DEC_USE_MALLOC \ + -DCONFIG_TONE_LOCK_BY_BT_TIME \ + -DCONFIG_LMP_CONN_SUSPEND_ENABLE \ + -DCONFIG_BTCTRLER_TASK_DEL_ENABLE \ + -DCONFIG_UPDATA_ENABLE \ + -DCONFIG_OTA_UPDATA_ENABLE \ + -DCONFIG_ITEM_FORMAT_VM \ + -DCONFIG_DNS_ENABLE \ + -DCONFIG_MMU_ENABLE \ + -DCONFIG_SBC_CODEC_HW \ + -DCONFIG_MSBC_CODEC_HW \ + -DCONFIG_AEC_M=640 \ + -DCONFIG_AUDIO_ONCHIP \ + -DCONFIG_MEDIA_DEVELOP_ENABLE \ + -DCONFIG_MEDIA_EFFECT_DISABLE \ + -D__GCC_PI32V2__ \ + -DCONFIG_NEW_ECC_ENABLE \ + + +DEFINES += $(EXT_CFLAGS) # 额外的一些定义 + +# 头文件搜索路径 +INCLUDES := \ + -Iinclude_lib \ + -Iinclude_lib/driver \ + -Iinclude_lib/driver/device \ + -Iinclude_lib/driver/cpu/br23 \ + -Iinclude_lib/system \ + -Iinclude_lib/system/generic \ + -Iinclude_lib/system/device \ + -Iinclude_lib/system/fs \ + -Iinclude_lib/system/ui \ + -Iinclude_lib/btctrler \ + -Iinclude_lib/btctrler/port/br23 \ + -Iinclude_lib/update \ + -Iinclude_lib/agreement \ + -Iinclude_lib/btstack/third_party/common \ + -Iinclude_lib/btstack/third_party/rcsp \ + -Iinclude_lib/media/media_develop \ + -Iinclude_lib/media/media_develop/media \ + -Iinclude_lib/media/media_develop/media/cpu/br23 \ + -Iinclude_lib/media/media_develop/media/cpu/br23/asm \ + -Icpu/br23/audio_mic \ + -Iapps/soundbox/include \ + -Iapps/soundbox/include/task_manager \ + -Iapps/soundbox/include/task_manager/bt \ + -Iapps/soundbox/include/user_api \ + -Iapps/common \ + -Iapps/common/device \ + -Iapps/common/audio \ + -Iapps/common/audio/stream \ + -Iapps/common/power_manage \ + -Iapps/common/charge_box \ + -Iapps/common/third_party_profile/common \ + -Iapps/common/third_party_profile/interface \ + -Iapps/common/third_party_profile/jieli \ + -Iapps/common/third_party_profile/jieli/trans_data_demo \ + -Iapps/common/third_party_profile/jieli/online_db \ + -Iapps/common/third_party_profile/jieli/JL_rcsp \ + -Iapps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata \ + -Iapps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data \ + -Iapps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol \ + -Iapps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting \ + -Iapps/common/dev_manager \ + -Iapps/common/file_operate \ + -Iapps/common/music \ + -Iapps/common/include \ + -Iapps/common/config/include \ + -Iapps/soundbox/board/br23 \ + -Icpu/br23 \ + -Icpu/br23/audio_common \ + -Icpu/br23/audio_dec \ + -Icpu/br23/audio_enc \ + -Icpu/br23/audio_effect \ + -Icpu/br23/localtws \ + -Iinclude_lib/btstack \ + -Iapps/common/third_party_profile/tuya_protocol \ + -Iapps/common/third_party_profile/tuya_protocol/app/demo \ + -Iapps/common/third_party_profile/tuya_protocol/app/product_test \ + -Iapps/common/third_party_profile/tuya_protocol/app/uart_common \ + -Iapps/common/third_party_profile/tuya_protocol/extern_components/mbedtls \ + -Iapps/common/third_party_profile/tuya_protocol/port \ + -Iapps/common/third_party_profile/tuya_protocol/sdk/include \ + -Iapps/common/third_party_profile/tuya_protocol/sdk/lib \ + -Iapps/common/usb \ + -Iapps/common/usb/device \ + -Iapps/common/usb/host \ + -Iapps/soundbox/smartbox \ + -Iapps/soundbox/smartbox/bt_manage/bt_trans_data \ + -Iapps/soundbox/smartbox/bt_manage \ + -Iapps/soundbox/smartbox/smartbox_setting \ + -Iapps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting \ + -Iapps/soundbox/smartbox/smartbox_setting_opt \ + -Iapps/soundbox/smartbox/smartbox_update \ + -Iapps/soundbox/smartbox/file_transfer \ + -Iapps/soundbox/smartbox/tuya \ + -Iapps/soundbox/include/ui/color_led \ + -I$(SYS_INC_DIR) \ + + +# 需要编译的 .c 文件 +c_SRC_FILES := \ + apps/common/audio/audio_digital_vol.c \ + apps/common/audio/audio_utils.c \ + apps/common/audio/decode/audio_key_tone.c \ + apps/common/audio/decode/decode.c \ + apps/common/audio/encode/encode_write_file.c \ + apps/common/audio/sine_make.c \ + apps/common/audio/stream/stream_entry.c \ + apps/common/audio/stream/stream_src.c \ + apps/common/audio/stream/stream_sync.c \ + apps/common/audio/uartPcmSender.c \ + apps/common/bt_common/bt_test_api.c \ + apps/common/charge_box/chargeIc_manage.c \ + apps/common/charge_box/chgbox_box.c \ + apps/common/charge_box/chgbox_ctrl.c \ + apps/common/charge_box/chgbox_det.c \ + apps/common/charge_box/chgbox_handshake.c \ + apps/common/charge_box/chgbox_ui.c \ + apps/common/charge_box/chgbox_ui_drv_pwmled.c \ + apps/common/charge_box/chgbox_ui_drv_timer.c \ + apps/common/charge_box/chgbox_wireless.c \ + apps/common/config/app_config.c \ + apps/common/config/bt_profile_config.c \ + apps/common/config/ci_transport_uart.c \ + apps/common/debug/debug.c \ + apps/common/debug/debug_lite.c \ + apps/common/dev_manager/dev_manager.c \ + apps/common/dev_manager/dev_reg.c \ + apps/common/dev_manager/dev_update.c \ + apps/common/device/detection.c \ + apps/common/device/fm/bk1080/Bk1080.c \ + apps/common/device/fm/fm_inside/fm_inside.c \ + apps/common/device/fm/fm_manage.c \ + apps/common/device/fm/qn8035/QN8035.c \ + apps/common/device/fm/rda5807/RDA5807.c \ + apps/common/device/fm_emitter/ac3433/ac3433.c \ + apps/common/device/fm_emitter/fm_emitter_manage.c \ + apps/common/device/fm_emitter/fm_inside/fm_emitter_inside.c \ + apps/common/device/fm_emitter/qn8007/qn8007.c \ + apps/common/device/fm_emitter/qn8027/qn8027.c \ + apps/common/device/gSensor/SC7A20.c \ + apps/common/device/gSensor/da230.c \ + apps/common/device/gSensor/gSensor_manage.c \ + apps/common/device/nandflash/nandflash.c \ + apps/common/device/norflash/norflash.c \ + apps/common/fat_nor/nor_fs.c \ + apps/common/fat_nor/phone_rec_fs.c \ + apps/common/fat_nor/virfat_flash.c \ + apps/common/file_operate/file_api.c \ + apps/common/file_operate/file_bs_deal.c \ + apps/common/file_operate/file_manager.c \ + apps/common/iap/iAP_des.c \ + apps/common/iap/iAP_device.c \ + apps/common/iap/iAP_iic.c \ + apps/common/key/adkey.c \ + apps/common/key/adkey_rtcvdd.c \ + apps/common/key/ctmu_touch_key.c \ + apps/common/key/iokey.c \ + apps/common/key/irkey.c \ + apps/common/key/key_driver.c \ + apps/common/key/rdec_key.c \ + apps/common/key/slidekey.c \ + apps/common/key/touch_key.c \ + apps/common/music/breakpoint.c \ + apps/common/music/general_player.c \ + apps/common/music/music_decrypt.c \ + apps/common/music/music_id3.c \ + apps/common/music/music_player.c \ + apps/common/rec_nor/nor_interface.c \ + apps/common/rec_nor/nor_rec_fs.c \ + apps/common/third_party_profile/common/3th_profile_api.c \ + apps/common/third_party_profile/common/custom_cfg.c \ + apps/common/third_party_profile/common/mic_rec.c \ + apps/common/third_party_profile/interface/app_protocol_api.c \ + apps/common/third_party_profile/interface/app_protocol_common.c \ + apps/common/third_party_profile/interface/app_protocol_dma.c \ + apps/common/third_party_profile/interface/app_protocol_gma.c \ + apps/common/third_party_profile/interface/app_protocol_mma.c \ + apps/common/third_party_profile/interface/app_protocol_ota.c \ + apps/common/third_party_profile/interface/app_protocol_tme.c \ + apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_bt_name_setting.c \ + apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_key_setting.c \ + apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_led_setting.c \ + apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_mic_setting.c \ + apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_time_stamp_setting.c \ + apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_work_setting.c \ + apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_opt.c \ + apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_tws_sync.c \ + apps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata/rcsp_adv_user_update.c \ + apps/common/third_party_profile/jieli/hid_user.c \ + apps/common/third_party_profile/jieli/le_client_demo.c \ + apps/common/third_party_profile/jieli/multi_demo/le_multi_client.c \ + apps/common/third_party_profile/jieli/multi_demo/le_multi_common.c \ + apps/common/third_party_profile/jieli/multi_demo/le_multi_trans.c \ + apps/common/third_party_profile/jieli/online_db/online_db_deal.c \ + apps/common/third_party_profile/jieli/online_db/spp_online_db.c \ + apps/common/third_party_profile/jieli/trans_data_demo/le_trans_data.c \ + apps/common/third_party_profile/jieli/trans_data_demo/spp_trans_data.c \ + apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_client.c \ + apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_common.c \ + apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_trans.c \ + apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ble_app_demo.c \ + apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ota.c \ + apps/common/third_party_profile/tuya_protocol/app/product_test/tuya_ble_app_production_test.c \ + apps/common/third_party_profile/tuya_protocol/app/uart_common/tuya_ble_app_uart_common_handler.c \ + apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/aes.c \ + apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/ccm.c \ + apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/hmac.c \ + apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/md5.c \ + apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha1.c \ + apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha256.c \ + apps/common/third_party_profile/tuya_protocol/port/JL_to_tuya_ble_port_peripheral.c \ + apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port.c \ + apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port_AD697x.c \ + apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port_peripheral.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_api.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_bulk_data.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_data_handler.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event_handler.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event_handler_weak.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_feature_weather.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_gatt_send_queue.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_heap.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_main.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_mem.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_mutli_tsf_protocol.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_queue.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_storage.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_unix_time.c \ + apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_utils.c \ + apps/common/ui/lcd/lcd_ui_api.c \ + apps/common/ui/lcd_simple/lcd_simple_api.c \ + apps/common/ui/lcd_simple/ui.c \ + apps/common/ui/lcd_simple/ui_mainmenu.c \ + apps/common/ui/led7/led7_ui_api.c \ + apps/common/update/norflash_ufw_update.c \ + apps/common/update/norflash_update.c \ + apps/common/update/testbox_update.c \ + apps/common/update/uart_update.c \ + apps/common/update/uart_update_master.c \ + apps/common/update/update.c \ + apps/common/usb/device/cdc.c \ + apps/common/usb/device/descriptor.c \ + apps/common/usb/device/hid.c \ + apps/common/usb/device/msd.c \ + apps/common/usb/device/msd_upgrade.c \ + apps/common/usb/device/task_pc.c \ + apps/common/usb/device/uac1.c \ + apps/common/usb/device/uac_stream.c \ + apps/common/usb/device/usb_device.c \ + apps/common/usb/device/user_setup.c \ + apps/common/usb/host/adb.c \ + apps/common/usb/host/aoa.c \ + apps/common/usb/host/apple_mfi.c \ + apps/common/usb/host/audio.c \ + apps/common/usb/host/audio_demo.c \ + apps/common/usb/host/hid.c \ + apps/common/usb/host/usb_bulk_transfer.c \ + apps/common/usb/host/usb_ctrl_transfer.c \ + apps/common/usb/host/usb_host.c \ + apps/common/usb/host/usb_storage.c \ + apps/common/usb/usb_config.c \ + apps/common/usb/usb_host_config.c \ + apps/soundbox/aec/br23/audio_aec.c \ + apps/soundbox/aec/br23/audio_aec_demo.c \ + apps/soundbox/app_main.c \ + apps/soundbox/board/br23/board_ac6083a/board_ac6083a.c \ + apps/soundbox/board/br23/board_ac6083a/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac6083a/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac6083a/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac6083a/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac6083a/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac6083a_iap/board_ac6083a_iap.c \ + apps/soundbox/board/br23/board_ac6083a_iap/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac6083a_iap/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac6083a_iap/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac6083a_iap/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac6083a_iap/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac6951_kgb_v1/board_ac6951_kgb_v1.c \ + apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac6951g/board_ac6951g.c \ + apps/soundbox/board/br23/board_ac6951g/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac6951g/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac6951g/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac6951g/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac6951g/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac6952e_lighter/board_ac6952e_lighter.c \ + apps/soundbox/board/br23/board_ac6952e_lighter/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac6952e_lighter/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac6952e_lighter/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac6952e_lighter/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac6952e_lighter/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac6954a_demo/board_ac6954a_demo.c \ + apps/soundbox/board/br23/board_ac6954a_demo/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac6954a_demo/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac6954a_demo/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac6954a_demo/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac6954a_demo/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac6955f_headset_mono/board_ac6955f_headset_mono.c \ + apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac695x_audio_effects/board_ac695x_audio_effects.c \ + apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac695x_btemitter/board_ac695x_btemitter.c \ + apps/soundbox/board/br23/board_ac695x_btemitter/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac695x_btemitter/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac695x_btemitter/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac695x_btemitter/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac695x_btemitter/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac695x_charging_bin/board_ac695x_charging_bin.c \ + apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac695x_cvp_develop/board_ac695x_cvp_develop.c \ + apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac695x_demo/board_ac695x_demo.c \ + apps/soundbox/board/br23/board_ac695x_demo/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac695x_demo/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac695x_demo/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac695x_demo/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac695x_demo/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac695x_lcd/board_ac695x_lcd.c \ + apps/soundbox/board/br23/board_ac695x_lcd/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac695x_lcd/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac695x_lcd/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac695x_lcd/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac695x_lcd/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac695x_megaphone/board_ac695x_megaphone.c \ + apps/soundbox/board/br23/board_ac695x_megaphone/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac695x_megaphone/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac695x_megaphone/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac695x_megaphone/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac695x_megaphone/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/board_ac695x_multimedia_charging_bin.c \ + apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac695x_smartbox/board_ac695x_smartbox.c \ + apps/soundbox/board/br23/board_ac695x_smartbox/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac695x_smartbox/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac695x_smartbox/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac695x_smartbox/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac695x_smartbox/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac695x_soundcard/board_ac695x_soundcard.c \ + apps/soundbox/board/br23/board_ac695x_soundcard/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac695x_soundcard/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac695x_soundcard/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac695x_soundcard/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac695x_soundcard/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac695x_tws/board_ac695x_tws.c \ + apps/soundbox/board/br23/board_ac695x_tws/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac695x_tws/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac695x_tws/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac695x_tws/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac695x_tws/key_table/touch_key_table.c \ + apps/soundbox/board/br23/board_ac695x_tws_box/board_ac695x_tws_box.c \ + apps/soundbox/board/br23/board_ac695x_tws_box/key_table/adkey_table.c \ + apps/soundbox/board/br23/board_ac695x_tws_box/key_table/iokey_table.c \ + apps/soundbox/board/br23/board_ac695x_tws_box/key_table/irkey_table.c \ + apps/soundbox/board/br23/board_ac695x_tws_box/key_table/rdec_key_table.c \ + apps/soundbox/board/br23/board_ac695x_tws_box/key_table/touch_key_table.c \ + apps/soundbox/board/br23/irq_config.c \ + apps/soundbox/common/app_sound_box_tool.c \ + apps/soundbox/common/dev_status.c \ + apps/soundbox/common/init.c \ + apps/soundbox/common/task_table.c \ + apps/soundbox/common/tone_table.c \ + apps/soundbox/common/user_cfg_new.c \ + apps/soundbox/font/fontinit.c \ + apps/soundbox/log_config/app_config.c \ + apps/soundbox/log_config/lib_btctrler_config.c \ + apps/soundbox/log_config/lib_btstack_config.c \ + apps/soundbox/log_config/lib_driver_config.c \ + apps/soundbox/log_config/lib_media_config.c \ + apps/soundbox/log_config/lib_system_config.c \ + apps/soundbox/log_config/lib_update_config.c \ + apps/soundbox/power_manage/app_charge.c \ + apps/soundbox/power_manage/app_chargestore.c \ + apps/soundbox/power_manage/app_power_manage.c \ + apps/soundbox/smartbox/browser/browser.c \ + apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_adv.c \ + apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_module.c \ + apps/soundbox/smartbox/bt_manage/smartbox_bt_manage.c \ + apps/soundbox/smartbox/cmd_data_deal/cmd_recieve.c \ + apps/soundbox/smartbox/cmd_data_deal/cmd_recieve_no_respone.c \ + apps/soundbox/smartbox/cmd_data_deal/cmd_respone.c \ + apps/soundbox/smartbox/cmd_data_deal/cmd_user.c \ + apps/soundbox/smartbox/cmd_data_deal/command.c \ + apps/soundbox/smartbox/cmd_data_deal/data_recieve.c \ + apps/soundbox/smartbox/cmd_data_deal/data_recieve_no_respone.c \ + apps/soundbox/smartbox/cmd_data_deal/data_respone.c \ + apps/soundbox/smartbox/config.c \ + apps/soundbox/smartbox/event.c \ + apps/soundbox/smartbox/feature.c \ + apps/soundbox/smartbox/file_transfer/dev_format.c \ + apps/soundbox/smartbox/file_transfer/file_delete.c \ + apps/soundbox/smartbox/file_transfer/file_transfer.c \ + apps/soundbox/smartbox/func_cmd/bt_func.c \ + apps/soundbox/smartbox/func_cmd/fm_func.c \ + apps/soundbox/smartbox/func_cmd/linein_func.c \ + apps/soundbox/smartbox/func_cmd/music_func.c \ + apps/soundbox/smartbox/func_cmd/rtc_func.c \ + apps/soundbox/smartbox/function.c \ + apps/soundbox/smartbox/smartbox.c \ + apps/soundbox/smartbox/smartbox_rcsp_manage.c \ + apps/soundbox/smartbox/smartbox_setting/adv_bt_name_setting.c \ + apps/soundbox/smartbox/smartbox_setting/adv_key_setting.c \ + apps/soundbox/smartbox/smartbox_setting/adv_led_setting.c \ + apps/soundbox/smartbox/smartbox_setting/adv_mic_setting.c \ + apps/soundbox/smartbox/smartbox_setting/adv_time_stamp_setting.c \ + apps/soundbox/smartbox/smartbox_setting/adv_work_setting.c \ + apps/soundbox/smartbox/smartbox_setting/smartbox_color_led_setting.c \ + apps/soundbox/smartbox/smartbox_setting/smartbox_eq_setting.c \ + apps/soundbox/smartbox/smartbox_setting/smartbox_high_low_vol_setting.c \ + apps/soundbox/smartbox/smartbox_setting/smartbox_karaoke_eq_setting.c \ + apps/soundbox/smartbox/smartbox_setting/smartbox_karaoke_setting.c \ + apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_drc_setting.c \ + apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_reverbration_setting.c \ + apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_setting.c \ + apps/soundbox/smartbox/smartbox_setting/smartbox_music_info_setting.c \ + apps/soundbox/smartbox/smartbox_setting/smartbox_vol_setting.c \ + apps/soundbox/smartbox/smartbox_setting_opt/smartbox_adv_bluetooth.c \ + apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_opt.c \ + apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_sync.c \ + apps/soundbox/smartbox/smartbox_task.c \ + apps/soundbox/smartbox/smartbox_update/rcsp_ch_loader_download.c \ + apps/soundbox/smartbox/smartbox_update/smartbox_update.c \ + apps/soundbox/smartbox/smartbox_update/smartbox_update_tws.c \ + apps/soundbox/smartbox/switch_device.c \ + apps/soundbox/smartbox/tuya/tuya_demo.c \ + apps/soundbox/soundcard/lamp.c \ + apps/soundbox/soundcard/notice.c \ + apps/soundbox/soundcard/peripheral.c \ + apps/soundbox/soundcard/soundcard.c \ + apps/soundbox/task_manager/app_common.c \ + apps/soundbox/task_manager/app_task_switch.c \ + apps/soundbox/task_manager/bt/bt.c \ + apps/soundbox/task_manager/bt/bt_ble.c \ + apps/soundbox/task_manager/bt/bt_emitter.c \ + apps/soundbox/task_manager/bt/bt_event_fun.c \ + apps/soundbox/task_manager/bt/bt_key_fun.c \ + apps/soundbox/task_manager/bt/bt_product_test.c \ + apps/soundbox/task_manager/bt/bt_switch_fun.c \ + apps/soundbox/task_manager/bt/bt_tws.c \ + apps/soundbox/task_manager/bt/vol_sync.c \ + apps/soundbox/task_manager/fm/fm.c \ + apps/soundbox/task_manager/fm/fm_api.c \ + apps/soundbox/task_manager/fm/fm_rw.c \ + apps/soundbox/task_manager/idle/idle.c \ + apps/soundbox/task_manager/linein/linein.c \ + apps/soundbox/task_manager/linein/linein_api.c \ + apps/soundbox/task_manager/linein/linein_dev.c \ + apps/soundbox/task_manager/music/music.c \ + apps/soundbox/task_manager/pc/pc.c \ + apps/soundbox/task_manager/power_off/power_off.c \ + apps/soundbox/task_manager/power_on/power_on.c \ + apps/soundbox/task_manager/record/record.c \ + apps/soundbox/task_manager/rtc/alarm_api.c \ + apps/soundbox/task_manager/rtc/alarm_user.c \ + apps/soundbox/task_manager/rtc/rtc.c \ + apps/soundbox/task_manager/rtc/virtual_rtc.c \ + apps/soundbox/task_manager/sleep/sleep.c \ + apps/soundbox/task_manager/spdif/hdmi_cec_drv.c \ + apps/soundbox/task_manager/spdif/spdif.c \ + apps/soundbox/task_manager/task_key.c \ + apps/soundbox/third_party_profile/ancs_client_demo/ancs_client_demo.c \ + apps/soundbox/third_party_profile/app_protocol_deal.c \ + apps/soundbox/third_party_profile/trans_data_demo/trans_data_demo.c \ + apps/soundbox/ui/color_led/color_led_app.c \ + apps/soundbox/ui/color_led/color_led_table.c \ + apps/soundbox/ui/color_led/driver/color_led.c \ + apps/soundbox/ui/color_led/driver/color_led_driver.c \ + apps/soundbox/ui/lcd/STYLE_02/bt_action.c \ + apps/soundbox/ui/lcd/STYLE_02/clock_action.c \ + apps/soundbox/ui/lcd/STYLE_02/file_brower.c \ + apps/soundbox/ui/lcd/STYLE_02/fm_action.c \ + apps/soundbox/ui/lcd/STYLE_02/linein_action.c \ + apps/soundbox/ui/lcd/STYLE_02/music_action.c \ + apps/soundbox/ui/lcd/STYLE_02/record_action.c \ + apps/soundbox/ui/lcd/STYLE_02/system_action.c \ + apps/soundbox/ui/lcd/lyrics_api.c \ + apps/soundbox/ui/lcd/ui_sys_param_api.c \ + apps/soundbox/ui/lcd_simple/my_demo.c \ + apps/soundbox/ui/led7/ui_bt.c \ + apps/soundbox/ui/led7/ui_common.c \ + apps/soundbox/ui/led7/ui_fm.c \ + apps/soundbox/ui/led7/ui_fm_emitter.c \ + apps/soundbox/ui/led7/ui_idle.c \ + apps/soundbox/ui/led7/ui_linein.c \ + apps/soundbox/ui/led7/ui_music.c \ + apps/soundbox/ui/led7/ui_pc.c \ + apps/soundbox/ui/led7/ui_record.c \ + apps/soundbox/ui/led7/ui_rtc.c \ + apps/soundbox/ui/led/pwm_led_api.c \ + apps/soundbox/ui/led/pwm_led_para_table.c \ + apps/soundbox/user_api/app_pwmled_api.c \ + apps/soundbox/user_api/app_record_api.c \ + apps/soundbox/user_api/app_special_play_api.c \ + apps/soundbox/user_api/app_status_api.c \ + apps/soundbox/user_api/dev_multiplex_api.c \ + apps/soundbox/user_api/product_info_api.c \ + apps/soundbox/version.c \ + cpu/br23/adc_api.c \ + cpu/br23/app_timer.c \ + cpu/br23/audio_common/app_audio.c \ + cpu/br23/audio_common/audio_fmtx.c \ + cpu/br23/audio_common/audio_iis.c \ + cpu/br23/audio_common/audio_link.c \ + cpu/br23/audio_dec/audio_dec.c \ + cpu/br23/audio_dec/audio_dec_bt.c \ + cpu/br23/audio_dec/audio_dec_file.c \ + cpu/br23/audio_dec/audio_dec_fm.c \ + cpu/br23/audio_dec/audio_dec_linein.c \ + cpu/br23/audio_dec/audio_dec_midi_ctrl.c \ + cpu/br23/audio_dec/audio_dec_midi_file.c \ + cpu/br23/audio_dec/audio_dec_pc.c \ + cpu/br23/audio_dec/audio_dec_record.c \ + cpu/br23/audio_dec/audio_dec_spdif.c \ + cpu/br23/audio_dec/audio_dec_tone.c \ + cpu/br23/audio_dec/audio_spectrum.c \ + cpu/br23/audio_dec/audio_sync.c \ + cpu/br23/audio_dec/audio_usb_mic.c \ + cpu/br23/audio_dec/lfwordana_enc_api.c \ + cpu/br23/audio_dec/tone_player.c \ + cpu/br23/audio_effect/audio_dynamic_eq_demo.c \ + cpu/br23/audio_effect/audio_eff_default_parm.c \ + cpu/br23/audio_effect/audio_eq_drc_demo.c \ + cpu/br23/audio_effect/audio_gain_process_demo.c \ + cpu/br23/audio_effect/audio_sound_track_2_p_x.c \ + cpu/br23/audio_effect/audio_surround_demo.c \ + cpu/br23/audio_effect/audio_vbass_demo.c \ + cpu/br23/audio_effect/audio_voice_changer_demo.c \ + cpu/br23/audio_effect/effects_adj.c \ + cpu/br23/audio_effect/eq_config.c \ + cpu/br23/audio_enc/audio_adc_demo.c \ + cpu/br23/audio_enc/audio_enc.c \ + cpu/br23/audio_enc/audio_enc_file.c \ + cpu/br23/audio_enc/audio_enc_recoder.c \ + cpu/br23/audio_enc/audio_mic_codec.c \ + cpu/br23/audio_enc/audio_recorder_mix.c \ + cpu/br23/audio_enc/audio_sbc_codec.c \ + cpu/br23/audio_mic/effect_linein.c \ + cpu/br23/audio_mic/effect_parm.c \ + cpu/br23/audio_mic/effect_reg.c \ + cpu/br23/audio_mic/loud_speaker.c \ + cpu/br23/audio_mic/mic_effect.c \ + cpu/br23/audio_mic/mic_stream.c \ + cpu/br23/audio_mic/simpleAGC.c \ + cpu/br23/audio_mic/vollevel_detect.c \ + cpu/br23/charge.c \ + cpu/br23/chargebox_hw.c \ + cpu/br23/chargestore.c \ + cpu/br23/clock_manager.c \ + cpu/br23/ctmu.c \ + cpu/br23/iic_eeprom_test.c \ + cpu/br23/iic_hw.c \ + cpu/br23/iic_slave_test.c \ + cpu/br23/iic_soft.c \ + cpu/br23/irflt.c \ + cpu/br23/led_spi.c \ + cpu/br23/ledc_test.c \ + cpu/br23/localtws/localtws.c \ + cpu/br23/localtws/localtws_dec.c \ + cpu/br23/mcpwm.c \ + cpu/br23/overlay_code.c \ + cpu/br23/plcnt.c \ + cpu/br23/port_wkup.c \ + cpu/br23/pwm_led.c \ + cpu/br23/setup.c \ + cpu/br23/spi.c \ + cpu/br23/spi_test.c \ + cpu/br23/uart_bt_product.c \ + cpu/br23/uart_dev.c \ + cpu/br23/uart_test.c \ + cpu/br23/ui_driver/LED_1888/LED1888.c \ + cpu/br23/ui_driver/interface/ui_platform.c \ + cpu/br23/ui_driver/lcd_seg/lcd_seg3x9_driver.c \ + cpu/br23/ui_driver/lcd_spi/lcd_drive.c \ + cpu/br23/ui_driver/lcd_spi/spi_lcd_st7735s.c \ + cpu/br23/ui_driver/lcd_spi/spi_lcd_st7789v.c \ + cpu/br23/ui_driver/lcd_spi/spi_lcd_st7789vw.c \ + cpu/br23/ui_driver/lcd_spi/spi_oled.c \ + cpu/br23/ui_driver/led7/led7_driver.c \ + cpu/br23/ui_driver/ui_common.c \ + + +# 需要编译的 .S 文件 +S_SRC_FILES := \ + apps/soundbox/sdk_version.z.S \ + + +# 需要编译的 .s 文件 +s_SRC_FILES := + + +# 需要编译的 .cpp 文件 +cpp_SRC_FILES := + + +# 需要编译的 .cc 文件 +cc_SRC_FILES := + + +# 需要编译的 .cxx 文件 +cxx_SRC_FILES := + + +# 链接参数 +LFLAGS := \ + -flto \ + --plugin-opt=-pi32v2-always-use-itblock=false \ + --plugin-opt=-enable-ipra=true \ + --plugin-opt=-pi32v2-merge-max-offset=4096 \ + --plugin-opt=-pi32v2-enable-simd=true \ + --plugin-opt=mcpu=r3 \ + --plugin-opt=-global-merge-on-const \ + --plugin-opt=-inline-threshold=5 \ + --plugin-opt=-inline-max-allocated-size=32 \ + --plugin-opt=-inline-normal-into-special-section=true \ + --plugin-opt=-dont-used-symbol-list=malloc,free,sprintf,printf,puts,putchar \ + --plugin-opt=save-temps \ + --plugin-opt=-pi32v2-enable-rep-memop \ + --sort-common \ + --dont-complain-call-overflow \ + --plugin-opt=-used-symbol-file=cpu/br23/sdk_used_list.used \ + --gc-sections \ + --start-group \ + include_lib/liba/br23/cpu.a \ + include_lib/liba/br23/system.a \ + include_lib/liba/br23/aec.a \ + include_lib/liba/br23/media.a \ + include_lib/liba/br23/media_app.a \ + include_lib/liba/br23/libAptFilt_pi32v2_OnChip.a \ + include_lib/liba/br23/libEchoSuppress_pi32v2_OnChip.a \ + include_lib/liba/br23/libNoiseSuppress_pi32v2_OnChip.a \ + include_lib/liba/br23/libSplittingFilter_pi32v2_OnChip.a \ + include_lib/liba/br23/libDelayEstimate_pi32v2_OnChip.a \ + include_lib/liba/br23/libSingleMicSystem_pi32v2_OnChip.a \ + include_lib/liba/br23/libSMS_TDE_pi32v2_OnChip.a \ + include_lib/liba/br23/lib_esco_repair.a \ + include_lib/liba/br23/mp3_dec_lib.a \ + include_lib/liba/br23/mp3tsy_dec_lib.a \ + include_lib/liba/br23/wma_dec_lib.a \ + include_lib/liba/br23/wtg_dec_lib.a \ + include_lib/liba/br23/wtgv2_dec_lib.a \ + include_lib/liba/br23/wav_dec_lib.a \ + include_lib/liba/br23/flac_dec_lib.a \ + include_lib/liba/br23/ape_dec_lib.a \ + include_lib/liba/br23/m4a_tws_lib.a \ + include_lib/liba/br23/amr_dec_lib.a \ + include_lib/liba/br23/dts_dec_lib.a \ + include_lib/liba/br23/mp3_decstream_lib.a \ + include_lib/liba/br23/wma_decstream_lib.a \ + include_lib/liba/br23/sbc_eng_lib.a \ + include_lib/liba/br23/compressor.a \ + include_lib/liba/br23/crossover_coff.a \ + include_lib/liba/br23/limiter.a \ + include_lib/liba/br23/lib_mp2_code.a \ + include_lib/liba/br23/lib_adpcm_code.a \ + include_lib/liba/br23/mp3_enc_lib.a \ + include_lib/liba/br23/opus_enc_lib.a \ + include_lib/liba/br23/speex_enc_lib.a \ + include_lib/liba/br23/lib_pitch_speed.a \ + include_lib/liba/br23/lib_reverb_cal.a \ + include_lib/liba/br23/lib_rmono2stereo.a \ + include_lib/liba/br23/bfilterfun_lib.a \ + include_lib/liba/br23/libFFT_pi32v2_OnChip.a \ + include_lib/liba/br23/libOpcore_maskrom_pi32v2_OnChip.a \ + include_lib/liba/br23/lib_resample_cal.a \ + include_lib/liba/br23/lib_resample_fast_cal.a \ + include_lib/liba/br23/crypto_toolbox_Ospeed.a \ + include_lib/liba/br23/lib_g726_decode.a \ + include_lib/liba/br23/lib_g726_code.a \ + include_lib/liba/br23/limiter_noiseGate.a \ + include_lib/liba/br23/howling.a \ + include_lib/liba/br23/noisegate.a \ + include_lib/liba/br23/shiftPhase.a \ + include_lib/liba/br23/pemafrow.a \ + include_lib/liba/br23/lib_howlings_phf.a \ + include_lib/liba/br23/math.a \ + include_lib/liba/br23/bt_hash_enc.a \ + include_lib/liba/br23/filtparam_cal_lib.a \ + include_lib/liba/br23/agreement.a \ + include_lib/liba/br23/lib_sur_cal.a \ + include_lib/liba/br23/loudness.a \ + include_lib/liba/br23/rcsp_stack.a \ + include_lib/liba/br23/lib_usbaudio_plc.a \ + include_lib/liba/br23/coeff_calculate.a \ + include_lib/liba/br23/rms.a \ + include_lib/liba/br23/SpectrumShow.a \ + include_lib/liba/br23/gma_stack.a \ + include_lib/liba/br23/dueros_stack.a \ + include_lib/liba/br23/tme_stack.a \ + include_lib/liba/br23/lib_adpcm_ima_code.a \ + include_lib/liba/br23/lib_midi_dec.a \ + include_lib/liba/br23/lib_word_ana.a \ + include_lib/liba/br23/drc.a \ + include_lib/liba/br23/DynamicEQ.a \ + include_lib/liba/br23/lib_voiceChager.a \ + include_lib/liba/br23/VirtualBass.a \ + apps/common/third_party_profile/tuya_protocol/sdk/lib/libtuya_lib.a \ + include_lib/liba/br23/lib_dns.a \ + include_lib/liba/br23/btstack.a \ + include_lib/liba/br23/btctrler.a \ + --end-group \ + include_lib/liba/br23/update.a \ + include_lib/liba/br23/res.a \ + include_lib/liba/br23/ui_dot.a \ + include_lib/liba/br23/ui_s.a \ + include_lib/liba/br23/font.a \ + -Tcpu/br23/sdk.ld \ + -M=cpu/br23/tools/sdk.map \ + --plugin-opt=mcpu=r3 \ + --plugin-opt=-mattr=+fprev1 \ + + +LIBPATHS := \ + -L$(SYS_LIB_DIR) \ + + +LIBS := \ + $(SYS_LIB_DIR)/libm.a \ + $(SYS_LIB_DIR)/libc.a \ + $(SYS_LIB_DIR)/libm.a \ + $(SYS_LIB_DIR)/libcompiler-rt.a \ + + + +c_OBJS := $(c_SRC_FILES:%.c=%.c.o) +S_OBJS := $(S_SRC_FILES:%.S=%.S.o) +s_OBJS := $(s_SRC_FILES:%.s=%.s.o) +cpp_OBJS := $(cpp_SRC_FILES:%.cpp=%.cpp.o) +cxx_OBJS := $(cxx_SRC_FILES:%.cxx=%.cxx.o) +cc_OBJS := $(cc_SRC_FILES:%.cc=%.cc.o) + +OBJS := $(c_OBJS) $(S_OBJS) $(s_OBJS) $(cpp_OBJS) $(cxx_OBJS) $(cc_OBJS) +DEP_FILES := $(OBJS:%.o=%.d) + + +OBJS := $(addprefix $(BUILD_DIR)/, $(OBJS)) +DEP_FILES := $(addprefix $(BUILD_DIR)/, $(DEP_FILES)) + + +VERBOSE ?= 0 +ifeq ($(VERBOSE), 1) +QUITE := +else +QUITE := @ +endif + +# 一些旧的 make 不支持 file 函数,需要 make 的时候指定 LINK_AT=0 make +LINK_AT ?= 1 + +# 表示下面的不是一个文件的名字,无论是否存在 all, clean, pre_build 这样的文件 +# 还是要执行命令 +# see: https://www.gnu.org/software/make/manual/html_node/Phony-Targets.html +.PHONY: all clean pre_build + +# 不要使用 make 预设置的规则 +# see: https://www.gnu.org/software/make/manual/html_node/Suffix-Rules.html +.SUFFIXES: + +all: pre_build $(OUT_ELF) + $(info +POST-BUILD) + $(QUITE) $(RUN_POST_SCRIPT) sdk + +pre_build: + $(info +PRE-BUILD) + $(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -D__LD__ -E -P cpu/br23/sdk_used_list.c -o cpu/br23/sdk_used_list.used + $(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -D__LD__ -E -P cpu/br23/sdk_ld.c -o cpu/br23/sdk.ld + $(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -D__LD__ -E -P cpu/br23/tools/download.c -o $(POST_SCRIPT) + $(QUITE) $(FIXBAT) $(POST_SCRIPT) + +clean: + $(QUITE) $(RM) $(OUT_ELF) + $(QUITE) $(RM) $(BUILD_DIR) + + + +ifeq ($(LINK_AT), 1) +$(OUT_ELF): $(OBJS) + $(info +LINK $@) + $(shell $(MKDIR) $(@D)) + $(file >$(OBJ_FILE), $(OBJS)) + $(QUITE) $(LD) -o $(OUT_ELF) @$(OBJ_FILE) $(LFLAGS) $(LIBPATHS) $(LIBS) +else +$(OUT_ELF): $(OBJS) + $(info +LINK $@) + $(shell $(MKDIR) $(@D)) + $(QUITE) $(LD) -o $(OUT_ELF) $(OBJS) $(LFLAGS) $(LIBPATHS) $(LIBS) +endif + + +$(BUILD_DIR)/%.c.o : %.c + $(info +CC $<) + @$(MKDIR) $(@D) + @$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -MM -MT $@ $< -o $(@:.o=.d) + $(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@ + +$(BUILD_DIR)/%.S.o : %.S + $(info +AS $<) + @$(MKDIR) $(@D) + @$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -MM -MT $@ $< -o $(@:.o=.d) + $(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@ + +$(BUILD_DIR)/%.s.o : %.s + $(info +AS $<) + @$(MKDIR) $(@D) + @$(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -MM -MT $@ $< -o $(@:.o=.d) + $(QUITE) $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@ + +$(BUILD_DIR)/%.cpp.o : %.cpp + $(info +CXX $<) + @$(MKDIR) $(@D) + @$(CXX) $(CFLAGS) $(CXXFLAGS) $(DEFINES) $(INCLUDES) -MM -MT $@ $< -o $(@:.o=.d) + $(QUITE) $(CXX) $(CXXFLAGS) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@ + +$(BUILD_DIR)/%.cxx.o : %.cxx + $(info +CXX $<) + @$(MKDIR) $(@D) + @$(CXX) $(CFLAGS) $(CXXFLAGS) $(DEFINES) $(INCLUDES) -MM -MT $@ $< -o $(@:.o=.d) + $(QUITE) $(CXX) $(CXXFLAGS) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@ + +$(BUILD_DIR)/%.cc.o : %.cc + $(info +CXX $<) + @$(MKDIR) $(@D) + @$(CXX) $(CFLAGS) $(CXXFLAGS) $(DEFINES) $(INCLUDES) -MM -MT $@ $< -o $(@:.o=.d) + $(QUITE) $(CXX) $(CXXFLAGS) $(CFLAGS) $(DEFINES) $(INCLUDES) -c $< -o $@ + +-include $(DEP_FILES) diff --git a/Release_file.bat b/Release_file.bat new file mode 100644 index 0000000..fd106d1 --- /dev/null +++ b/Release_file.bat @@ -0,0 +1,35 @@ +@echo off +cd %~dp0 +chcp 65001 1>nul +@REM chcp 936 1>nul +set "Package_Path=%cd%" + +@REM 客户名称 +set "Customer=JL" +@REM 项目名称 +set "Project=YY-XX" +@REM 主控 +set "IC=AC695X" +@REM SDK版本 +set "SDK_VERSION=3.1.0" +@REM 发布文件目录 +set "RELEASE_PATH=release" +@REM 打包源 +set "PACKAGE_SOURCE=cpu\br25\tools" +@REM Lod bat +set "LOD_BAT=cpu\br25\tools\download.bat" +@REM FW文件 +set "FW_FILE=cpu\br25\tools\download\standard\jl_isd.fw" +@REM Log 文件 +set "LOG_FILE=cpu\br25\tools\download\standard\info.log" +@REM 是否开启git 远程仓库检测 +set "GET_CHECK_EN=N" +@REM 不需要打包的文件类型 只能设置一个类型更多类型可以在C:\UserTool\7z\7z.bat中设置 +@REM set "EXCLUDE_TYPE=*.key" + +@REM 运行打包处理 +call C:\UserTool\run.bat + + +pause +exit diff --git a/SDK版本_AC695N_soundbox_sdk_release_3.1.0.txt b/SDK版本_AC695N_soundbox_sdk_release_3.1.0.txt new file mode 100644 index 0000000..add1046 --- /dev/null +++ b/SDK版本_AC695N_soundbox_sdk_release_3.1.0.txt @@ -0,0 +1,2 @@ +sdk版本:AC695N_soundbox_sdk_release_3.1.0 + diff --git a/apps/common/audio/audio_digital_vol.c b/apps/common/audio/audio_digital_vol.c new file mode 100644 index 0000000..ecbf687 --- /dev/null +++ b/apps/common/audio/audio_digital_vol.c @@ -0,0 +1,754 @@ +#include "audio_digital_vol.h" + + +#define DIGITAL_FADE_EN 1 +#define DIGITAL_FADE_STEP 4 + +#define BG_DVOL_MAX 14 +#define BG_DVOL_MID 10 +#define BG_DVOL_MIN 6 +#define BG_DVOL_MAX_FADE 5 /*>= BG_DVOL_MAX:自动淡出BG_DVOL_MAX_FADE*/ +#define BG_DVOL_MID_FADE 3 /*>= BG_DVOL_MID:自动淡出BG_DVOL_MID_FADE*/ +#define BG_DVOL_MIN_FADE 1 /*>= BG_DVOL_MIN:自动淡出BG_DVOL_MIN_FADE*/ + +#define ASM_ENABLE 1 +#define L_sat(b,a) __asm__ volatile("%0=sat16(%1)(s)":"=&r"(b) : "r"(a)); +#define L_sat32(b,a,n) __asm__ volatile("%0=%1>>%2(s)":"=&r"(b) : "r"(a),"r"(n)); + +typedef struct { + u8 bg_dvol_fade_out; + struct list_head dvol_head; +} dvol_t; +static dvol_t dvol_attr; + +//static struct digital_volume d_volume; +/* + *数字音量级数 DIGITAL_VOL_MAX + *数组长度 DIGITAL_VOL_MAX + 1 + */ +#define DIGITAL_VOL_MAX 31 +const u16 dig_vol_table[DIGITAL_VOL_MAX + 1] = { + 0 , //0 + 93 , //1 + 111 , //2 + 132 , //3 + 158 , //4 + 189 , //5 + 226 , //6 + 270 , //7 + 323 , //8 + 386 , //9 + 462 , //10 + 552 , //11 + 660 , //12 + 789 , //13 + 943 , //14 + 1127, //15 + 1347, //16 + 1610, //17 + 1925, //18 + 2301, //19 + 2751, //20 + 3288, //21 + 3930, //22 + 4698, //23 + 5616, //24 + 6713, //25 + 8025, //26 + 9592, //27 + 11466,//28 + 15200,//29 + 16000,//30 + 16384 //31 +}; + +int audio_digital_vol_init(void) +{ + INIT_LIST_HEAD(&dvol_attr.dvol_head); + return 0; +} + +/*背景音乐淡出使能*/ +void audio_digital_vol_bg_fade(u8 fade_out) +{ + printf("audio_digital_vol_bg_fade:%d", fade_out); + dvol_attr.bg_dvol_fade_out = fade_out; +} + +/* + *fade_step一般不超过两级数字音量的最小差值 + *(1)通话如果用数字音量,一般步进小一点,音量调节的时候不会有杂音 + *(2)淡出的时候可以快一点,尽快淡出到0 + */ +dvol_handle *audio_digital_vol_open(u8 vol, u8 vol_max, u16 fade_step) +{ + dvol_handle *dvol = NULL; + dvol = zalloc(sizeof(dvol_handle)); + if (dvol) { + u8 vol_level; + dvol->fade = DIGITAL_FADE_EN; + dvol->vol = (vol > vol_max) ? vol_max : vol; + if (vol > vol_max) { + printf("[warning]cur digital_vol(%d) > digital_vol_max(%d)!!", vol, vol_max); + } + dvol->vol_max = vol_max; + vol_level = dvol->vol * DIGITAL_VOL_MAX / vol_max; + dvol->vol_target = dig_vol_table[vol_level]; + dvol->vol_fade = dvol->vol_target; + dvol->fade_step = fade_step; + dvol->toggle = 1; +#if BG_DVOL_FADE_ENABLE + dvol->vol_bk = -1; + local_irq_disable(); + list_add(&dvol->entry, &dvol_attr.dvol_head); + if (dvol_attr.bg_dvol_fade_out) { + dvol_handle *hdl; + list_for_each_entry(hdl, &dvol_attr.dvol_head, entry) { + if (hdl != dvol) { + hdl->vol_bk = hdl->vol; + if (hdl->vol >= BG_DVOL_MAX) { + hdl->vol -= BG_DVOL_MAX_FADE; + } else if (hdl->vol >= BG_DVOL_MID) { + hdl->vol -= BG_DVOL_MID_FADE; + } else if (hdl->vol >= BG_DVOL_MIN) { + hdl->vol -= BG_DVOL_MIN_FADE; + } else { + hdl->vol_bk = -1; + continue; + } + u8 vol_level = hdl->vol * DIGITAL_VOL_MAX / hdl->vol_max; + hdl->vol_target = dig_vol_table[vol_level]; + //y_printf("bg_dvol fade_out:%x,vol_bk:%d,vol_set:%d,tartget:%d",hdl,hdl->vol_bk,hdl->vol,hdl->vol_target); + } + } + } + local_irq_enable(); +#endif + printf("digital_vol_open:%x-%d-%d-%d\n", dvol, dvol->vol, dvol->vol_max, fade_step); + } + return dvol; +} + +void audio_digital_vol_close(dvol_handle *dvol) +{ + printf("digital_vol_close:%x\n", dvol); + if (dvol) { +#if BG_DVOL_FADE_ENABLE + local_irq_disable(); + list_del(&dvol->entry); + dvol_handle *hdl; + list_for_each_entry(hdl, &dvol_attr.dvol_head, entry) { + if ((hdl != dvol) && (hdl->vol_bk >= 0)) { + //y_printf("bg_dvol fade_in:%x,%d",hdl,hdl->vol_bk); + hdl->vol = hdl->vol_bk; + u8 vol_level = hdl->vol_bk * DIGITAL_VOL_MAX / hdl->vol_max; + hdl->vol_target = dig_vol_table[vol_level]; + hdl->vol_bk = -1; + } + } + local_irq_enable(); +#endif + free(dvol); + dvol = NULL; + } +} + +/* u8 audio_digital_vol_get(void) +{ + return d_volume.vol; +} */ + +void audio_digital_vol_set(dvol_handle *dvol, u8 vol) +{ + if (dvol == NULL) { + return; + } + if (dvol->toggle == 0) { + return; + } + dvol->vol = (vol > dvol->vol_max) ? dvol->vol_max : vol; +#if BG_DVOL_FADE_ENABLE + if (dvol->vol_bk != -1) { + dvol->vol_bk = vol; + } +#endif + dvol->fade = DIGITAL_FADE_EN; + u8 vol_level = dvol->vol * DIGITAL_VOL_MAX / dvol->vol_max; + dvol->vol_target = dig_vol_table[vol_level]; + printf("digital_vol:%d-%d-%d-%d\n", vol, vol_level, dvol->vol_fade, dvol->vol_target); +} + +void audio_digital_vol_reset_fade(dvol_handle *dvol) +{ + if (dvol) { + dvol->vol_fade = 0; + } +} + +int audio_digital_vol_run(dvol_handle *dvol, void *data, u32 len) +{ + s32 valuetemp; + s16 *buf; + + if (dvol->toggle == 0) { + return -1; + } + + buf = data; + len >>= 1; //byte to point + + for (u32 i = 0; i < len; i += 2) { + ///left channel + if (dvol->fade) { + if (dvol->vol_fade > dvol->vol_target) { + dvol->vol_fade -= dvol->fade_step; + if (dvol->vol_fade < dvol->vol_target) { + dvol->vol_fade = dvol->vol_target; + } + } else if (dvol->vol_fade < dvol->vol_target) { + dvol->vol_fade += dvol->fade_step; + if (dvol->vol_fade > dvol->vol_target) { + dvol->vol_fade = dvol->vol_target; + } + } + } else { + dvol->vol_fade = dvol->vol_target; + } + + valuetemp = buf[i]; + if (valuetemp < 0) { + valuetemp = -valuetemp; + valuetemp = (valuetemp * dvol->vol_fade) >> 14 ; + valuetemp = -valuetemp; + } else { + valuetemp = (valuetemp * dvol->vol_fade) >> 14 ; + } + if (valuetemp < -32768) { + valuetemp = -32768; + } else if (valuetemp > 32767) { + valuetemp = 32767; + } + buf[i] = (s16)valuetemp; + + ///right channel + valuetemp = buf[i + 1]; + if (valuetemp < 0) { + valuetemp = -valuetemp; + valuetemp = (valuetemp * dvol->vol_fade) >> 14 ; + valuetemp = -valuetemp; + } else { + valuetemp = (valuetemp * dvol->vol_fade) >> 14 ; + } + if (valuetemp < -32768) { + valuetemp = -32768; + } else if (valuetemp > 32767) { + valuetemp = 32767; + } + buf[i + 1] = (s16)valuetemp; + } + return 0; +} + + +/*************************支持重入的数字音量调节****************************/ + + + +/* + *fade_step一般不超过两级数字音量的最小差值 + *(1)通话如果用数字音量,一般步进小一点,音量调节的时候不会有杂音 + *(2)淡出的时候可以快一点,尽快淡出到0 + */ +void *user_audio_digital_volume_open(u8 vol, u8 vol_max, u16 fade_step) +{ + struct digital_volume *d_volume = zalloc(sizeof(struct digital_volume)); + if (!d_volume) { + log_e("d_volume NULL\n"); + return NULL; + } + u8 vol_level; + d_volume->fade = 0; + d_volume->vol = vol; + d_volume->vol_max = vol_max; + vol_level = vol * DIGITAL_VOL_MAX / vol_max; + d_volume->vol_target = dig_vol_table[vol_level]; + //d_volume->vol_fade = 0;//d_volume->vol_target;//打开时,从0开始淡入 + d_volume->vol_fade = d_volume->vol_target; + d_volume->fade_step = fade_step; + d_volume->toggle = 1; + d_volume->ch_num = 2;//默认双声道 + d_volume->user_vol_tab = NULL; + d_volume->user_vol_max = 0; + + os_mutex_create(&d_volume->mutex); + printf("digital_vol_open:%d-%d-%d\n", vol, vol_max, fade_step); + return d_volume; +} + +int user_audio_digital_volume_close(void *_d_volume) +{ + struct digital_volume *d_volume = (struct digital_volume *)_d_volume; + if (!d_volume) { + log_e("d_volume NULL\n"); + return -1; + } + /* os_mutex_pend(&d_volume->mutex, 0); */ + d_volume->toggle = 0; + d_volume->user_vol_tab = NULL; + d_volume->user_vol_max = 0; + + if (d_volume) { + free(d_volume); + d_volume = NULL; + } + /* os_mutex_post(&d_volume->mutex); */ + printf("digital_vol_close\n"); + return 0; +} + +u8 user_audio_digital_volume_get(void *_d_volume) +{ + struct digital_volume *d_volume = (struct digital_volume *)_d_volume; + if (!d_volume) { + log_e("d_volume NULL\n"); + return 0; + } + /* os_mutex_pend(&d_volume->mutex, 0); */ + u8 vol = d_volume->vol; + /* os_mutex_post(&d_volume->mutex); */ + return vol; +} + +int user_audio_digital_volume_set(void *_d_volume, u8 vol) +{ + struct digital_volume *d_volume = (struct digital_volume *)_d_volume; + if (!d_volume) { + log_e("d_volume NULL\n"); + return -1; + } + + u8 vol_level; + if (d_volume->toggle == 0) { + return 0; + } + /* os_mutex_pend(&d_volume->mutex, 0); */ + d_volume->vol = vol; + d_volume->fade = DIGITAL_FADE_EN; + if (!d_volume->user_vol_tab) { + vol_level = d_volume->vol * DIGITAL_VOL_MAX / d_volume->vol_max; + d_volume->vol_target = dig_vol_table[vol_level]; + } else { + u8 d_vol_max = d_volume->user_vol_max - 1; + vol_level = d_volume->vol * d_vol_max / d_volume->vol_max; + d_volume->vol_target = d_volume->user_vol_tab[vol_level]; + } + + /* os_mutex_post(&d_volume->mutex); */ + /* printf("digital_vol:%d-%d-%d-%d\n", vol, vol_level, d_volume->vol_fade, d_volume->vol_target); */ + return 0; +} + +int user_audio_digital_volume_reset_fade(void *_d_volume) +{ + struct digital_volume *d_volume = (struct digital_volume *)_d_volume; + if (!d_volume) { + log_e("d_volume NULL\n"); + return -1; + } + + os_mutex_pend(&d_volume->mutex, 0); + d_volume->vol_fade = 0; + os_mutex_post(&d_volume->mutex); + return 0; +} + +#if ASM_ENABLE + +#define audio_vol_mix(data,len, ch_num,volumeNOW,volumeDest,step){ \ + int i, j; \ + int fade = 0; \ + if (volumeNOW != volumeDest) \ + { \ + fade = 1; \ + } \ + if(d_volume->fade == 0)\ + {\ + fade = 0;\ + d_volume->vol_fade = d_volume->vol_target;\ + }\ + if (ch_num == 2) \ + { \ + len = len >> 1; \ + } \ + else if (ch_num == 3) \ + { \ + len = (len*5462)>>14; /*等效除3,因为5462向上取整得到的*/\ + } \ + else if(ch_num == 4) \ + { \ + len = len >> 2; \ + } \ + if (fade) \ + { \ + short *in_ptr = data; \ + for (i = 0; i < len; i++) \ + { \ + if (volumeNOW < volumeDest) \ + { \ + volumeNOW = volumeNOW + step; \ + if (volumeNOW > volumeDest) \ + { \ + volumeNOW = volumeDest; \ + } \ + } \ + else if (volumeNOW > volumeDest) \ + { \ + volumeNOW = volumeNOW - step; \ + if (volumeNOW < volumeDest) \ + { \ + volumeNOW = volumeDest; \ + } \ + } \ + { \ + int tmp; \ + int reptime = ch_num; \ + __asm__ volatile( \ + " 1 : \n\t" \ + " rep %0 { \n\t" \ + " %1 = h[%2](s) \n\t" \ + " %1 =%1* %3 \n\t "\ + " %1 =%1 >>>14 \n\t"\ + " h[%2++=2]= %1 \n\t"\ + " }\n\t" \ + " if(%0!=0 )goto 1b \n\t" \ + : "=&r"(reptime), \ + "=&r"(tmp), \ + "=&r"(in_ptr) \ + :"r"(volumeNOW), \ + "0"(reptime),\ + "2"(in_ptr)\ + : "cc", "memory"); \ + } \ + } \ + } \ + else \ + { \ + for (i = 0; i < ch_num; i++) \ + { \ + short *in_ptr = &data[i]; \ + { \ + int tmp; \ + int chnumv=ch_num*2;\ + int reptime = len;\ + __asm__ volatile(\ + " 1 : \n\t"\ + " rep %0 { \n\t"\ + " %1 = h[%2](s) \n\t"\ + " %1 = %1 *%3 \n\t "\ + " %1= %1 >>>14 \n\t"\ + " h[%2++=%4]= %1 \n\t"\ + " }\n\t"\ + " if(%0!=0 )goto 1b \n\t"\ + : "=&r"(reptime),\ + "=&r"(tmp),\ + "=&r"(in_ptr) \ + :"r"(volumeNOW), \ + "r"(chnumv),\ + "0"(reptime),\ + "2"(in_ptr)\ + : "cc", "memory");\ + } \ + }\ + }\ +} + +#else + +#define audio_vol_mix(data,len, ch_num,volumeNOW,volumeDest,step){ \ + int i, j; \ + int fade = 0; \ + if (volumeNOW != volumeDest) \ + { \ + fade = 1; \ + } \ + if(d_volume->fade == 0)\ + {\ + fade = 0;\ + d_volume->vol_fade = d_volume->vol_target;\ + }\ + if (ch_num == 2) \ + { \ + len = len >> 1; \ + } \ + else if (ch_num == 3) \ + { \ + len = (len*5462)>>14; /*等效除3,因为5462向上取整得到的*/\ + } \ + else if(ch_num == 4) \ + { \ + len = len >> 2; \ + } \ + if (fade) \ + { \ + short *in_ptr = data; \ + for (i = 0; i < len; i++) \ + { \ + if (volumeNOW < volumeDest) \ + { \ + volumeNOW = volumeNOW + step; \ + if (volumeNOW > volumeDest) \ + { \ + volumeNOW = volumeDest; \ + } \ + } \ + else if (volumeNOW > volumeDest) \ + { \ + volumeNOW = volumeNOW - step; \ + if (volumeNOW < volumeDest) \ + { \ + volumeNOW = volumeDest; \ + } \ + } \ + for (j = 0; j < ch_num; j++) \ + { \ + int tmp = (*in_ptr*volumeNOW) >> 14; \ + L_sat(tmp, tmp); \ + *in_ptr = tmp; \ + in_ptr++; \ + } \ + } \ + } \ + else \ + { \ + for (i = 0; i < ch_num; i++) \ + { \ + short *in_ptr = &data[i]; \ + for (j = 0; j < len; j++)\ + {\ + int tmp= (*in_ptr*volumeNOW) >> 14; \ + L_sat(tmp, tmp); \ + *in_ptr = tmp;\ + in_ptr += ch_num;\ + }\ + }\ + }\ +} + +#endif + + + +int user_audio_digital_volume_run(void *_d_volume, void *data, u32 len, u8 ch_num) +{ + + struct digital_volume *d_volume = (struct digital_volume *)_d_volume; + if (!d_volume) { + log_e("d_volume NULL\n"); + return -1; + } + + s32 valuetemp; + s16 *buf; + + if (d_volume->toggle == 0) { + return -1; + } + if (ch_num > 4) { + return -1; + } + os_mutex_pend(&d_volume->mutex, 0); + + + if (ch_num) { + d_volume->ch_num = ch_num; + } + buf = data; + len >>= 1; //byte to point + /* printf("d_volume->vol_target %d %d %d %d\n", d_volume->vol_target, ch_num, d_volume->vol_fade, d_volume->fade_step); */ +#if 1 + audio_vol_mix(buf, len, ch_num, d_volume->vol_fade, d_volume->vol_target, d_volume->fade_step); +#else + + /* printf("d_volume->vol_target %d %d\n", d_volume->vol_target, ch_num); */ + for (u32 i = 0; i < len; i += d_volume->ch_num) {//ch_num 1/2/3/4 + ///FL channel + if (d_volume->fade) { + if (d_volume->vol_fade > d_volume->vol_target) { + d_volume->vol_fade -= d_volume->fade_step; + if (d_volume->vol_fade < d_volume->vol_target) { + d_volume->vol_fade = d_volume->vol_target; + } + } else if (d_volume->vol_fade < d_volume->vol_target) { + d_volume->vol_fade += d_volume->fade_step; + if (d_volume->vol_fade > d_volume->vol_target) { + d_volume->vol_fade = d_volume->vol_target; + } + } + } else { + d_volume->vol_fade = d_volume->vol_target; + } + + valuetemp = buf[i]; + if (valuetemp < 0) { + valuetemp = -valuetemp; + valuetemp = (valuetemp * d_volume->vol_fade) >> 14 ; + valuetemp = -valuetemp; + } else { + valuetemp = (valuetemp * d_volume->vol_fade) >> 14 ; + } + if (valuetemp < -32768) { + valuetemp = -32768; + } else if (valuetemp > 32767) { + valuetemp = 32767; + } + buf[i] = (s16)valuetemp; + + if (d_volume->ch_num > 1) { //双声道 + ///FR channel + valuetemp = buf[i + 1]; + if (valuetemp < 0) { + valuetemp = -valuetemp; + valuetemp = (valuetemp * d_volume->vol_fade) >> 14 ; + valuetemp = -valuetemp; + } else { + valuetemp = (valuetemp * d_volume->vol_fade) >> 14 ; + } + + if (valuetemp < -32768) { + valuetemp = -32768; + } else if (valuetemp > 32767) { + valuetemp = 32767; + } + buf[i + 1] = (s16)valuetemp; + + if (d_volume->ch_num > 2) { //三声道 + //RL channel + valuetemp = buf[i + 2]; + if (valuetemp < 0) { + valuetemp = -valuetemp; + valuetemp = (valuetemp * d_volume->vol_fade) >> 14 ; + valuetemp = -valuetemp; + } else { + valuetemp = (valuetemp * d_volume->vol_fade) >> 14 ; + } + if (valuetemp < -32768) { + valuetemp = -32768; + } else if (valuetemp > 32767) { + valuetemp = 32767; + } + buf[i + 2] = (s16)valuetemp; + + + if (d_volume->ch_num > 3) { //四声道 + ///RR channel + valuetemp = buf[i + 3]; + if (valuetemp < 0) { + valuetemp = -valuetemp; + valuetemp = (valuetemp * d_volume->vol_fade) >> 14 ; + valuetemp = -valuetemp; + } else { + valuetemp = (valuetemp * d_volume->vol_fade) >> 14 ; + } + if (valuetemp < -32768) { + valuetemp = -32768; + } else if (valuetemp > 32767) { + valuetemp = 32767; + } + buf[i + 3] = (s16)valuetemp; + } + } + } + } +#endif + os_mutex_post(&d_volume->mutex); + return 0; +} + + + +/* + *user_vol_max:音量级数 + *user_vol_tab:自定义音量表,自定义表长user_vol_max+1 + */ +void user_audio_digital_set_volume_tab(void *_d_volume, u16 *user_vol_tab, u8 user_vol_max) +{ + struct digital_volume *d_volume = (struct digital_volume *)_d_volume; + if (!d_volume) { + log_e("d_volume NULL\n"); + return ; + } + + os_mutex_pend(&d_volume->mutex, 0); + if (user_vol_tab) { + d_volume->user_vol_tab = user_vol_tab; + d_volume->user_vol_max = user_vol_max; + } + os_mutex_post(&d_volume->mutex); +} + + + +/* + *priv:用户自定义指针 + *void (*handler)(void *priv, void *data, int len, u8 ch_num):用户自定义回调 + * */ +void *user_audio_process_open(void *parm, void *priv, void (*handler)(void *priv, void *data, int len, u8 ch_num)) +{ + struct user_audio_parm *user_hdl = zalloc(sizeof(struct user_audio_parm)); + if (!user_hdl) { + log_e("user_hdl NULL\n"); + return NULL; + } + user_hdl->priv = priv; + user_hdl->handler = handler; + + struct user_audio_digital_parm *dvol_parm = (struct user_audio_digital_parm *)parm; + if (dvol_parm->en) { + log_i("vol :%d vol_max:%d fade_step:%d\n", dvol_parm->vol, dvol_parm->vol_max, dvol_parm->fade_step); + user_hdl->dvol_hdl = user_audio_digital_volume_open(dvol_parm->vol, dvol_parm->vol_max, dvol_parm->fade_step); + } + log_i("%s ok\n", __FUNCTION__); + return user_hdl; +} + + +int user_audio_process_close(void *_uparm_hdl) +{ + struct user_audio_parm *user_hdl = (struct user_audio_parm *)_uparm_hdl; + if (!user_hdl) { + log_e("user_hdl NULL\n"); + return -1; + } + if (user_hdl->dvol_hdl) { + user_audio_digital_volume_close(user_hdl->dvol_hdl); + user_hdl->dvol_hdl = NULL; + } + free(user_hdl); + user_hdl = NULL; + log_i("%s ok\n", __FUNCTION__); + return 0; +} + +void user_audio_process_handler_run(void *_uparm_hdl, void *data, u32 len, u8 ch_num) +{ + struct user_audio_parm *user_hdl = (struct user_audio_parm *)_uparm_hdl; + if (!user_hdl) { + log_e("user_hdl NULL\n"); + return; + } + + + if (user_hdl->handler) { + user_hdl->handler(user_hdl->priv, data, len, ch_num); + } + + if (user_hdl->dvol_hdl) { + user_audio_digital_volume_run(user_hdl->dvol_hdl, data, len, ch_num); + } + +} + + + + + diff --git a/apps/common/audio/audio_digital_vol.h b/apps/common/audio/audio_digital_vol.h new file mode 100644 index 0000000..68bbb33 --- /dev/null +++ b/apps/common/audio/audio_digital_vol.h @@ -0,0 +1,79 @@ +#ifndef _AUDIO_DIGITAL_VOL_H_ +#define _AUDIO_DIGITAL_VOL_H_ + +#include "generic/typedef.h" +#include "os/os_type.h" +#include "os/os_api.h" +#include "generic/list.h" + +#define BG_DVOL_FADE_ENABLE 1 /*多路声音叠加,背景声音自动淡出小声*/ + +typedef struct { + u8 toggle; /*数字音量开关*/ + u8 fade; /*淡入淡出标志*/ + u8 vol; /*淡入淡出当前音量(level)*/ + u8 vol_max; /*淡入淡出最大音量(level)*/ + s16 vol_fade; /*淡入淡出对应的起始音量*/ +#if BG_DVOL_FADE_ENABLE + s16 vol_bk; /*后台自动淡出前音量值*/ + struct list_head entry; +#endif + volatile s16 vol_target; /*淡入淡出对应的目标音量*/ + volatile u16 fade_step; /*淡入淡出的步进*/ +} dvol_handle; + + +int audio_digital_vol_init(void); +void audio_digital_vol_bg_fade(u8 fade_out); +dvol_handle *audio_digital_vol_open(u8 vol, u8 vol_max, u16 fade_step); +void audio_digital_vol_close(dvol_handle *dvol); +void audio_digital_vol_set(dvol_handle *dvol, u8 vol); +u8 audio_digital_vol_get(void); +int audio_digital_vol_run(dvol_handle *dvol, void *data, u32 len); +void audio_digital_vol_reset_fade(dvol_handle *dvol); + +/*************************自定义支持重入的数字音量调节****************************/ +void *user_audio_digital_volume_open(u8 vol, u8 vol_max, u16 fade_step); +int user_audio_digital_volume_close(void *_d_volume); +u8 user_audio_digital_volume_get(void *_d_volume); +int user_audio_digital_volume_set(void *_d_volume, u8 vol); +int user_audio_digital_volume_reset_fade(void *_d_volume); +int user_audio_digital_volume_run(void *_d_volume, void *data, u32 len, u8 ch_num); +void user_audio_digital_handler_run(void *_d_volume, void *data, u32 len); +void user_audio_digital_set_volume_tab(void *_d_volume, u16 *user_vol_tab, u8 user_vol_max); + +void *user_audio_process_open(void *parm, void *priv, void (*handler)(void *priv, void *data, int len, u8 ch_num)); +int user_audio_process_close(void *_uparm_hdl); +void user_audio_process_handler_run(void *_uparm_hdl, void *data, u32 len, u8 ch_num); + +struct user_audio_digital_parm { + u8 en; + u8 vol; + u8 vol_max; + u16 fade_step; +}; + +struct digital_volume { + u8 toggle; /*数字音量开关*/ + u8 fade; /*淡入淡出标志*/ + u8 vol; /*淡入淡出当前音量*/ + u8 vol_max; /*淡入淡出最大音量*/ + s16 vol_fade; /*淡入淡出对应的起始音量*/ + volatile s16 vol_target; /*淡入淡出对应的目标音量*/ + volatile u16 fade_step; /*淡入淡出的步进*/ + + OS_MUTEX mutex; + u8 ch_num; + void *priv; + u8 user_vol_max; /*自定义音量表级数*/ + volatile s16 *user_vol_tab; /*自定义音量表*/ + +}; + +struct user_audio_parm { + void *priv; + void (*handler)(void *priv, void *data, int len, u8 ch_num);/*用户自定义回调处理*/ + struct digital_volume *dvol_hdl; +}; + +#endif diff --git a/apps/common/audio/audio_utils.c b/apps/common/audio/audio_utils.c new file mode 100644 index 0000000..79e2db9 --- /dev/null +++ b/apps/common/audio/audio_utils.c @@ -0,0 +1,27 @@ +/* + ************************************************************ + * Audio Utils + * 数字信号处理常用模块合集 + * + ************************************************************ + */ + +#include "audio_utils.h" + +/* +********************************************************************* +* Audio Digital Phase Inverter +* Description: 数字反相器,用来反转数字音频信号的相位 +* Arguments : dat 数据buf地址 +* len 数据长度(unit:byte) +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void digital_phase_inverter_s16(s16 *dat, int len) +{ + for (int i = 0; i < len / 2; i++) { + dat[i] = (dat[i] == -32768) ? 32767 : -dat[i]; + /* dat[i] = -1 - dat[i]; */ + } +} diff --git a/apps/common/audio/audio_utils.h b/apps/common/audio/audio_utils.h new file mode 100644 index 0000000..e11465a --- /dev/null +++ b/apps/common/audio/audio_utils.h @@ -0,0 +1,18 @@ +#ifndef _AUDIO_UTILS_H_ +#define _AUDIO_UTILS_H_ + +#include "generic/typedef.h" + +/* +********************************************************************* +* Audio Digital Phase Inverter +* Description: 数字反相器,用来反转数字音频信号的相位 +* Arguments : dat 数据buf地址 +* len 数据长度(unit:byte) +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void digital_phase_inverter_s16(s16 *dat, int len); + +#endif/*_AUDIO_UTILS_H_*/ diff --git a/apps/common/audio/decode/audio_key_tone.c b/apps/common/audio/decode/audio_key_tone.c new file mode 100644 index 0000000..2b3c727 --- /dev/null +++ b/apps/common/audio/decode/audio_key_tone.c @@ -0,0 +1,682 @@ +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "app_config.h" +#include "audio_config.h" +#include "audio_dec.h" +#include "tone_player.h" +#include "sine_make.h" + +#if TCFG_KEY_TONE_EN + +// 按键提示音任务名 +#define AUDIO_KEY_TONE_TASK_NAME "key_tone" + +// 按键提示音数字音量控制 +#if SYS_DIGVOL_GROUP_EN +#define AUDIO_KEY_TONE_DIGVOL_EN 0 +#define AUDIO_KEY_TONE_DIGVOL_NAME "key_tone" +#else +#define AUDIO_KEY_TONE_DIGVOL_EN 0 +#endif + + +////////////////////////////////////////////////////////////////////////////// + +/* + * 使用audio_dec_app.h里面的接口,可以实现普通文件、正弦波文件、正弦波数组播放 + */ + +// 参数 +struct __key_tone_play_info { + const char *file_name; // 文件名 + struct audio_sin_param *sin; // 正弦波数组 + u8 sin_num; // 正弦波数组长度 + u8 preemption; // 1-抢占,0-叠加 + void (*evt_handler)(void *priv, int flag); // 事件回调 + void *evt_priv; // 事件回调私有句柄 +}; + +// 按键提示音 +struct __key_tone { + volatile u8 busy; // 任务工作中 + volatile u8 start; // 运行标志 + volatile u8 play; +#if AUDIO_KEY_TONE_DIGVOL_EN + u8 volume; // 音量 +#endif + struct __key_tone_play_info play_info; // 输入参数 + struct audio_dec_sine_app_hdl *dec_sin; // 文件播放句柄 + struct audio_dec_file_app_hdl *dec_file; // sine播放句柄 + void (*evt_handler)(void *priv, int flag); // 事件回调 + void *evt_priv; // 事件回调私有句柄 + const char *evt_owner; // 事件回调所在任务 +}; + +////////////////////////////////////////////////////////////////////////////// + +static struct __key_tone *key_tone = NULL; + +////////////////////////////////////////////////////////////////////////////// + +/* +********************************************************************* +* Audio Key Tone Get File Ext Name +* Description: 获取文件名后缀 +* Arguments : *name 文件名 +* Return : 后缀 +* Note(s) : None. +********************************************************************* +*/ +static char *get_file_ext_name(char *name) +{ + int len = strlen(name); + char *ext = (char *)name; + + while (len--) { + if (*ext++ == '.') { + break; + } + } + if (len <= 0) { + ext = name + (strlen(name) - 3); + } + + return ext; +} + +/* +********************************************************************* +* Audio Key Tone Post Event +* Description: 解码事件 +* Arguments : *ktone 按键提示音解码句柄 +* end_flag 结束标志 +* Return : true 成功 +* Note(s) : None. +********************************************************************* +*/ +static int key_tone_dec_event_handler(struct __key_tone *ktone, u8 end_flag) +{ + int argv[4]; + if (!ktone->evt_handler) { + log_i("evt_handler null\n"); + return false; + } + argv[0] = (int)ktone->evt_handler; + argv[1] = 2; + argv[2] = (int)ktone->evt_priv; + argv[3] = (int)end_flag; //0正常关闭,1被打断关闭 + + int ret = os_taskq_post_type(ktone->evt_owner, Q_CALLBACK, 4, argv); + if (ret) { + return false; + } + return true; +} + +/* +********************************************************************* +* Audio Key Tone Reelease +* Description: 提示音解码器释放 +* Arguments : *ktone 按键提示音解码句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +static void key_tone_dec_hdl_release(struct __key_tone *ktone) +{ + if (ktone->dec_file) { + audio_dec_file_app_close(ktone->dec_file); + ktone->dec_file = NULL; + } + if (ktone->dec_sin) { + audio_dec_sine_app_close(ktone->dec_sin); + ktone->dec_sin = NULL; + } + /* app_audio_state_exit(APP_AUDIO_STATE_WTONE); */ + /* clock_remove_set(DEC_TONE_CLK); */ +} + +/* +********************************************************************* +* Audio Key Tone Init OK +* Description: 解码初始化完成 +* Arguments : *ktone 按键提示音解码句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +static void key_tone_dec_hdl_init_ok(struct __key_tone *ktone) +{ + /* app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_vol()); */ + /* clock_add_set(DEC_TONE_CLK); */ +} + +/* +********************************************************************* +* Audio Key Tone Close +* Description: 关闭提示音解码 +* Arguments : *ktone 按键提示音解码句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +static void key_tone_play_close(struct __key_tone *ktone) +{ + /* log_i("ktone:0x%x, sin:0x%x, file:0x%x \n", ktone, ktone->dec_file, ktone->dec_file); */ + if (ktone->dec_file || ktone->dec_sin) { + key_tone_dec_hdl_release(ktone); + key_tone_dec_event_handler(ktone, 1); + } +} + +/* +********************************************************************* +* Audio Key Tone Event Callback +* Description: 解码回调处理 +* Arguments : *ktone 按键提示音解码句柄 +* event 事件 +* *param 事件参数 +* Return : 0 正常 +* Note(s) : None. +********************************************************************* +*/ +static int key_tone_dec_app_evt_cb(struct __key_tone *ktone, enum audio_dec_app_event event, int *param) +{ + switch (event) { + case AUDIO_DEC_APP_EVENT_START_INIT_OK: + log_i("key_tone start init ok\n"); + key_tone_dec_hdl_init_ok(ktone); + break; + case AUDIO_DEC_APP_EVENT_PLAY_END: + log_i("key_tone play end\n"); + key_tone_dec_hdl_release(ktone); + key_tone_dec_event_handler(ktone, 0); + break; + case AUDIO_DEC_APP_EVENT_STREAM_OPEN: { +#if AUDIO_KEY_TONE_DIGVOL_EN + struct audio_dec_stream_entries_hdl *entries_hdl = (struct audio_dec_stream_entries_hdl *)param; + void *dvol_entry = NULL; + audio_dig_vol_param temp_digvol_param = { + .vol_start = ktone->volume,//get_max_sys_vol(), + .vol_max = get_max_sys_vol(), + .ch_total = audio_output_channel_num(), + .fade_en = 0, + .fade_points_step = 5, + .fade_gain_step = 10, + .vol_list = NULL, + }; + dvol_entry = sys_digvol_group_ch_open(AUDIO_KEY_TONE_DIGVOL_NAME, -1, &temp_digvol_param); + (entries_hdl->entries_addr)[entries_hdl->entries_cnt++] = dvol_entry; +#endif // SYS_DIGVOL_GROUP_EN + } + break; + + case AUDIO_DEC_APP_EVENT_DEC_CLOSE: + +#if AUDIO_KEY_TONE_DIGVOL_EN + sys_digvol_group_ch_close(AUDIO_KEY_TONE_DIGVOL_NAME); +#endif // SYS_DIGVOL_GROUP_EN + + break; + case AUDIO_DEC_APP_EVENT_STREAM_CLOSE: { + } + break; + + default : + break; + } + + return 0; +} + +/* +********************************************************************* +* Audio Key Tone Sin Event Callback +* Description: sine提示音解码回调 +* Arguments : *priv 私有句柄 +* event 事件 +* *param 事件参数 +* Return : 0 正常 +* Note(s) : None. +********************************************************************* +*/ +static int key_tone_dec_sine_app_evt_cb(void *priv, enum audio_dec_app_event event, int *param) +{ + struct audio_dec_sine_app_hdl *sine_dec = priv; + struct __key_tone *ktone = sine_dec->priv; + switch (event) { + case AUDIO_DEC_APP_EVENT_DEC_PROBE: + if (sine_dec->sin_maker) { + break; + } + audio_dec_sine_app_probe(sine_dec); + if (!sine_dec->sin_maker) { + return -ENOENT; + } + break; + + default : + return key_tone_dec_app_evt_cb(ktone, event, param); + } + + return 0; +} + +/* +********************************************************************* +* Audio Key Tone File Event Callback +* Description: file提示音解码回调 +* Arguments : *priv 私有句柄 +* event 事件 +* *param 事件参数 +* Return : 0 正常 +* Note(s) : None. +********************************************************************* +*/ +static int key_tone_dec_file_app_evt_cb(void *priv, enum audio_dec_app_event event, int *param) +{ + struct audio_dec_file_app_hdl *file_dec = priv; + struct __key_tone *ktone = file_dec->priv; + switch (event) { + case AUDIO_DEC_APP_EVENT_DEC_PROBE: + break; + default : + return key_tone_dec_app_evt_cb(ktone, event, param); + } + + return 0; +} + +/* +********************************************************************* +* Audio Key Tone Run +* Description: 按键提示音运行 +* Arguments : *ktone 按键提示音解码句柄 +* Return : 0 正常 +* Note(s) : None. +********************************************************************* +*/ +static int key_tone_play_run(struct __key_tone *ktone) +{ + if (!ktone->start) { + return -1; + } + + struct __key_tone_play_info info = {0}; + local_irq_disable(); + if (!ktone->play) { + local_irq_enable(); + return 0; + } + // 保存播放参数 + memcpy(&info, &ktone->play_info, sizeof(struct __key_tone_play_info)); + ktone->play = 0; + local_irq_enable(); + + // 关闭现有play + key_tone_play_close(ktone); + + // 设置参数 + ktone->evt_handler = info.evt_handler; + ktone->evt_priv = info.evt_priv; + ktone->evt_owner = "app_core"; + + // 正弦波数组播放 + if (info.sin && info.sin_num) { + ktone->dec_sin = audio_dec_sine_app_create_by_parm(info.sin, info.sin_num, !info.preemption); + if (ktone->dec_sin == NULL) { + return -1; + } + ktone->dec_sin->dec->evt_cb = key_tone_dec_sine_app_evt_cb; + ktone->dec_sin->priv = ktone; + audio_dec_sine_app_open(ktone->dec_sin); + return 0; + } + + // 判断文件名后缀 + u8 file_name[16]; + char *format = NULL; + FILE *file = fopen(info.file_name, "r"); + if (!file) { + return -1; + } + fget_name(file, file_name, 16); + format = get_file_ext_name((char *)file_name); + fclose(file); + + // 正弦波文件播放 + if (ASCII_StrCmpNoCase(format, "sin", 3) == 0) { + ktone->dec_sin = audio_dec_sine_app_create(info.file_name, !info.preemption); + if (ktone->dec_sin == NULL) { + return -1; + } + ktone->dec_sin->dec->evt_cb = key_tone_dec_sine_app_evt_cb; + ktone->dec_sin->priv = ktone; + audio_dec_sine_app_open(ktone->dec_sin); + return 0; + } + + // 普通文件播放 + ktone->dec_file = audio_dec_file_app_create(info.file_name, !info.preemption); + if (ktone->dec_file == NULL) { + return -1; + } + if (ktone->dec_file->dec->dec_type == AUDIO_CODING_SBC) { + audio_dec_app_set_frame_info(ktone->dec_file->dec, 0x4e, ktone->dec_file->dec->dec_type); + } + ktone->dec_file->dec->evt_cb = key_tone_dec_file_app_evt_cb; + ktone->dec_file->priv = ktone; + audio_dec_file_app_open(ktone->dec_file); + return 0; +} + +/* +********************************************************************* +* Audio Key Tone Task Run +* Description: 按键提示音任务处理 +* Arguments : *p 按键提示音解码句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +static void key_tone_task_deal(void *p) +{ + int res = 0; + int msg[16]; + struct __key_tone *ktone = (struct __key_tone *)p; + ktone->start = 1; + ktone->busy = 1; + while (1) { + __os_taskq_pend(msg, ARRAY_SIZE(msg), portMAX_DELAY); + res = key_tone_play_run(ktone); + if (res) { + ///等待删除线程 + key_tone_play_close(ktone); + ktone->busy = 0; + while (1) { + os_time_dly(10000); + } + } + } +} + +/* +********************************************************************* +* Audio Key Tone Destroy +* Description: 注销按键提示音播放 +* Arguments : None. +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_key_tone_destroy(void) +{ + if (!key_tone) { + return ; + } + + key_tone->start = 0; + + while (key_tone->busy) { + os_taskq_post_msg(AUDIO_KEY_TONE_TASK_NAME, 1, 0); + os_time_dly(1); + } + + task_kill(AUDIO_KEY_TONE_TASK_NAME); + + local_irq_disable(); + free(key_tone); + key_tone = NULL; + local_irq_enable(); +} + +/* +********************************************************************* +* Audio Key Tone Init +* Description: 按键提示音初始化 +* Arguments : None. +* Return : true 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_key_tone_init(void) +{ + int err = 0; + if (key_tone) { + return true; + } + struct __key_tone *ktone = zalloc(sizeof(struct __key_tone)); + err = task_create(key_tone_task_deal, (void *)ktone, AUDIO_KEY_TONE_TASK_NAME); + if (err != OS_NO_ERR) { + log_e("%s creat fail %x\n", __FUNCTION__, err); + free(ktone); + return false; + } +#if AUDIO_KEY_TONE_DIGVOL_EN + ktone->volume = get_max_sys_vol(); +#endif + key_tone = ktone; + return true; +} + +////////////////////////////////////////////////////////////////////////////// + +// 正弦波序号 +#define KTONE_SINE_NORAML 0 + +// 按键提示音序号 +enum { + KTONE_IDEX_NORAML = 0, + KTONE_IDEX_NUM_0, + KTONE_IDEX_NUM_1, + + KTONE_IDEX_MAX, +}; + +// 序号对应表 +static const char *const key_tone_index[] = { + [KTONE_IDEX_NORAML] = DEFAULT_SINE_TONE(KTONE_SINE_NORAML), + [KTONE_IDEX_NUM_0] = SDFILE_RES_ROOT_PATH"tone/0.*", + [KTONE_IDEX_NUM_1] = SDFILE_RES_ROOT_PATH"tone/1.*", +}; + +/* + * 正弦波参数配置: + * freq : 实际频率 * 512 + * points : 正弦波点数 + * win : 正弦窗 + * decay : 衰减系数(百分比), 正弦窗模式下为频率设置:频率*512 + */ +static const struct sin_param sine_16k_normal[] = { + /*{0, 1000, 0, 100},*/ + {200 << 9, 4000, 0, 100}, +}; + + +////////////////////////////////////////////////////////////////////////////// + +/* +********************************************************************* +* Audio Key Tone Get Sine Param Data +* Description: 获取正弦波数组 +* Arguments : id 正弦波序号 +* *num 正弦波数组长度 +* Return : 正弦波数组 +* Note(s) : None. +********************************************************************* +*/ +static const struct sin_param *get_sine_param_data(u8 id, u8 *num) +{ + const struct sin_param *param_data = NULL; + switch (id) { + case KTONE_SINE_NORAML: + param_data = sine_16k_normal; + *num = ARRAY_SIZE(sine_16k_normal); + break; + default: + return NULL; + } + return param_data; +}; + +/* +********************************************************************* +* Audio Key Tone Open With Callback +* Description: 打开文件播放 +* Arguments : *file_name 文件名 +* *sin 正弦波数组 +* sin_num 正弦波数组长度 +* preemption 1-抢断播放;0-叠加播放 +* evt_handler 事件回调 +* evt_priv 事件回调参数 +* Return : 0 正常 +* Note(s) : None. +********************************************************************* +*/ +static int ktone_play_open_with_callback_base(const char *file_name, struct audio_sin_param *sin, u8 sin_num, u8 preemption, void (*evt_handler)(void *priv, int flag), void *evt_priv) +{ + struct __key_tone *ktone = key_tone; + if ((!ktone) || (!ktone->start)) { + return -1; + } + + struct __key_tone_play_info info = {0}; + info.preemption = preemption; + info.evt_handler = evt_handler; + info.evt_priv = evt_priv; + if (sin && sin_num) { + info.sin = sin; + info.sin_num = sin_num; + } else { + info.file_name = file_name; + if (IS_DEFAULT_SINE(file_name)) { + info.sin = get_sine_param_data(DEFAULT_SINE_ID(file_name), &info.sin_num); + } + } + + local_irq_disable(); + memcpy(&ktone->play_info, &info, sizeof(struct __key_tone_play_info)); + ktone->play = 1; + local_irq_enable(); + + os_taskq_post_msg(AUDIO_KEY_TONE_TASK_NAME, 1, 0); + + return 0; +} + +/* +********************************************************************* +* Audio Key Tone Play Sine +* Description: 播放正弦波数组 +* Arguments : *sin 正弦波数组 +* sin_num 正弦波数组长度 +* preemption 1-抢断播放;0-叠加播放 +* Return : 0 正常 +* Note(s) : None. +********************************************************************* +*/ +int audio_key_tone_play_sin(struct audio_sin_param *sin, u8 sin_num, u8 preemption) +{ + /* y_printf("n:0x%x \n", name); */ + return ktone_play_open_with_callback_base(NULL, sin, sin_num, preemption, NULL, NULL); +} + +/* +********************************************************************* +* Audio Key Tone Play File +* Description: 播放文件 +* Arguments : *name 文件名 +* preemption 1-抢断播放;0-叠加播放 +* Return : 0 正常 +* Note(s) : None. +********************************************************************* +*/ +int audio_key_tone_play_name(const char *name, u8 preemption) +{ + /* y_printf("n:0x%x \n", name); */ + return ktone_play_open_with_callback_base(name, NULL, 0, preemption, NULL, NULL); +} + +/* +********************************************************************* +* Audio Key Tone Play Index +* Description: 按序号播放文件 +* Arguments : index 序号 +* preemption 1-抢断播放;0-叠加播放 +* Return : 0 正常 +* Note(s) : 使用key_tone_index[]数组 +********************************************************************* +*/ +int audio_key_tone_play_index(u8 index, u8 preemption) +{ + if (index >= KTONE_IDEX_MAX) { + return -1; + } + return audio_key_tone_play_name(key_tone_index[index], preemption); +} + +/* +********************************************************************* +* Audio Key Tone Play +* Description: 按键提示音播放 +* Arguments : None. +* Return : None. +* Note(s) : 默认播放 +********************************************************************* +*/ +void audio_key_tone_play(void) +{ + audio_key_tone_play_index(KTONE_IDEX_NORAML, 0); + /* audio_key_tone_play_index(KTONE_IDEX_NUM_0, 0); */ + /* audio_key_tone_play_sin(sine_16k_normal, ARRAY_SIZE(sine_16k_normal), 0); */ +} + +/* +********************************************************************* +* Audio Key Tone Check Play +* Description: 检测按键提示音是否在播放 +* Arguments : None. +* Return : true 正在播放 +* Note(s) : None. +********************************************************************* +*/ +int audio_key_tone_is_play(void) +{ + if ((!key_tone) || (!key_tone->start)) { + return false; + } + if (key_tone->dec_file || key_tone->dec_sin) { + return true; + } + return false; +} + +/* +********************************************************************* +* Audio Key Tone Set Digvol +* Description: 设置按键提示音的音量 +* Arguments : volume 音量 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_key_tone_digvol_set(u8 volume) +{ +#if AUDIO_KEY_TONE_DIGVOL_EN + log_i("vol:%d \n", volume); + if (!key_tone) { + return ; + } + key_tone->volume = volume; + void *vol_hdl = audio_dig_vol_group_hdl_get(sys_digvol_group, AUDIO_KEY_TONE_DIGVOL_NAME); + if (vol_hdl == NULL) { + return; + } + audio_dig_vol_set(vol_hdl, AUDIO_DIG_VOL_ALL_CH, volume); +#endif +} + + +#endif + diff --git a/apps/common/audio/decode/decode.c b/apps/common/audio/decode/decode.c new file mode 100644 index 0000000..2edb949 --- /dev/null +++ b/apps/common/audio/decode/decode.c @@ -0,0 +1,303 @@ + +#include "application/audio_dec_app.h" +#include "app_config.h" +#include "audio_config.h" +#include "app_main.h" + + +////////////////////////////////////////////////////////////////////////////// +extern struct audio_decoder_task decode_task; +extern struct audio_mixer mixer; +extern struct audio_dac_hdl dac_hdl; +#if AUDIO_DAC_MULTI_CHANNEL_ENABLE +extern struct audio_dac_channel default_dac; +#endif + +extern const int audio_dec_app_mix_en; + +extern u32 audio_output_channel_num(void); + +////////////////////////////////////////////////////////////////////////////// +struct audio_dec_app_audio_state_hdl { + struct audio_mixer *p_mixer; + u32 dec_mix : 1; // 1:叠加模式 + u32 flag; +}; + +////////////////////////////////////////////////////////////////////////////// +const struct audio_dec_format_hdl decode_format_list[] = { + {"wtg", AUDIO_CODING_G729}, + {"msbc", AUDIO_CODING_MSBC}, + {"sbc", AUDIO_CODING_SBC}, + {"mty", AUDIO_CODING_MTY}, + {"aac", AUDIO_CODING_AAC}, + {"mp3", AUDIO_CODING_MP3}, + {"wma", AUDIO_CODING_WMA}, + {"wav", AUDIO_CODING_WAV}, +#if (defined(TCFG_DEC_MIDI_ENABLE) && TCFG_DEC_MIDI_ENABLE) + //midi 文件播放,需要对应音色文件配合 + {"midi", AUDIO_CODING_MIDI}, + {"mid", AUDIO_CODING_MIDI}, +#endif //TCFG_DEC_MIDI_ENABLE + +#if TCFG_DEC_WTGV2_ENABLE + {"wts", AUDIO_CODING_WTGV2}, +#endif + {0, 0}, +}; + +#if defined(CONFIG_MEDIA_DEVELOP_ENABLE) +static struct audio_stream_entry *audio_dec_app_entries[2] = {NULL}; +#endif + +////////////////////////////////////////////////////////////////////////////// + +/*----------------------------------------------------------------------------*/ +/**@brief 解码创建参数初始化 + @param *dec: 解码句柄 + @return 0-正常 + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +int audio_dec_app_create_param_init(struct audio_dec_app_hdl *dec) +{ + dec->p_decode_task = &decode_task; +#if defined(CONFIG_MEDIA_DEVELOP_ENABLE) + if (!audio_dec_app_mix_en) { +#if AUDIO_DAC_MULTI_CHANNEL_ENABLE + audio_dec_app_entries[0] = &default_dac.entry; +#else + audio_dec_app_entries[0] = &dac_hdl.entry; +#endif + dec->entries = audio_dec_app_entries; + } else +#endif + { + dec->p_mixer = &mixer; + } +#if defined(CONFIG_MEDIA_DEVELOP_ENABLE) + u8 dac_connect_mode = app_audio_output_mode_get(); + if (dac_connect_mode == DAC_OUTPUT_FRONT_LR_REAR_LR) { + dec->out_ch_num = 4; + } else { + dec->out_ch_num = audio_output_channel_num(); + } +#else + dec->p_dac_hdl = &dac_hdl; +#endif + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 文件解码创建参数初始化 + @param *file_dec: 文件解码句柄 + @return 0-正常 + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +int audio_dec_file_app_create_param_init(struct audio_dec_file_app_hdl *file_dec) +{ + file_dec->format = decode_format_list; + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 解码输出状态设置 + @param *dec: 解码句柄 + @param flag: 解码标签 + @return 0-正常 + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_dec_app_audio_state_switch(struct audio_dec_app_hdl *dec, u32 flag) +{ + u8 need_set_audio = 1; + /* if ((dec->dec_mix) && (audio_mixer_get_ch_num(dec->p_mixer) > 1)) { */ + /* need_set_audio = 0; */ + /* } */ + if (app_audio_get_state() == APP_AUDIO_STATE_IDLE) { + need_set_audio = 1; + } + if (need_set_audio) { + if (flag == AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MUSIC) { + app_audio_state_switch(APP_AUDIO_STATE_MUSIC, get_max_sys_vol()); + } else { +#ifdef TCFG_WTONT_ONCE_VOL + extern u8 get_tone_once_vol(void); + app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_once_vol()); +#else + app_audio_state_switch(APP_AUDIO_STATE_WTONE, get_tone_vol()); +#endif + } + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 解码输出状态退出 + @param *p_aud_state: 输出状态 + @return 0-正常 + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_dec_app_audio_state_exit(struct audio_dec_app_audio_state_hdl *p_aud_state) +{ + u8 need_set_audio = 1; + /* if ((p_aud_state->dec_mix) && (audio_mixer_get_ch_num(p_aud_state->p_mixer) > 1)) { */ + /* need_set_audio = 0; */ + /* } */ + /* if (app_audio_get_state() == APP_AUDIO_STATE_IDLE) { */ + /* need_set_audio = 1; */ + /* } */ + if (need_set_audio) { + if (p_aud_state->flag == AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MUSIC) { + app_audio_state_exit(APP_AUDIO_STATE_MUSIC); + } else { + app_audio_state_exit(APP_AUDIO_STATE_WTONE); + } + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 文件解码初始化完成 + @param *file_dec: 文件解码句柄 + @return 0-正常 + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +int audio_dec_file_app_init_ok(struct audio_dec_file_app_hdl *file_dec) +{ + audio_dec_app_audio_state_switch(file_dec->dec, file_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 文件解码结束 + @param *file_dec: 文件解码句柄 + @return 0-正常 + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +int audio_dec_file_app_play_end(struct audio_dec_file_app_hdl *file_dec) +{ + struct audio_dec_app_audio_state_hdl aud_state = {0}; + aud_state.p_mixer = file_dec->dec->p_mixer; + aud_state.dec_mix = file_dec->dec->dec_mix; + aud_state.flag = file_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK; + audio_dec_file_app_close(file_dec); + audio_dec_app_audio_state_exit(&aud_state); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 正弦波解码初始化完成 + @param *sine_dec: 正弦波解码句柄 + @return 0-正常 + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +int audio_dec_sine_app_init_ok(struct audio_dec_sine_app_hdl *sine_dec) +{ + audio_dec_app_audio_state_switch(sine_dec->dec, sine_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK); + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief 正弦波解码结束 + @param *sine_dec: 正弦波解码句柄 + @return 0-正常 + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +int audio_dec_sine_app_play_end(struct audio_dec_sine_app_hdl *sine_dec) +{ + struct audio_dec_app_audio_state_hdl aud_state = {0}; + aud_state.p_mixer = sine_dec->dec->p_mixer; + aud_state.dec_mix = sine_dec->dec->dec_mix; + aud_state.flag = sine_dec->flag & AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK; + audio_dec_sine_app_close(sine_dec); + audio_dec_app_audio_state_exit(&aud_state); + return 0; +} + +#if (!defined(CONFIG_MEDIA_DEVELOP_ENABLE)) +void audio_dec_app_output_sr_set(struct audio_dec_app_hdl *dec) +{ + /* #if defined(CONFIG_CPU_BR23) */ + /* extern u32 audio_output_rate(int input_rate); */ + /* dec->src_out_sr = audio_output_rate(dec->src_out_sr); */ + /* #endif */ + if (dec->sample_rate == 0) { + dec->sample_rate = dec->src_out_sr; + } +} +#endif + + +////////////////////////////////////////////////////////////////////////////// +// test +#if 0 +#include "tone_player.h" + +void audio_dec_file_test(void) +{ + struct audio_dec_file_app_hdl *hdl; + hdl = audio_dec_file_app_create(TONE_POWER_ON, 1); + if (hdl) { + audio_dec_file_app_open(hdl); + } + os_time_dly(2); + hdl = audio_dec_file_app_create(TONE_POWER_OFF, 1); + if (hdl) { + audio_dec_file_app_open(hdl); + } + os_time_dly(300); +} + +static const struct audio_sin_param sine_test[] = { + /*{0, 1000, 0, 100},*/ + {200 << 9, 4000, 0, 100}, +}; +static const struct audio_sin_param sine_test1[] = { + {450 << 9, 24960, 1, 16.667 * 512}, + {0, 16000, 0, 100}, +}; +void audio_dec_sine_test(void) +{ + struct audio_dec_sine_app_hdl *hdl; + /* hdl = audio_dec_sine_app_create(SDFILE_RES_ROOT_PATH"tone/vol_max.sin", 1); */ + hdl = audio_dec_sine_app_create_by_parm(sine_test1, ARRAY_SIZE(sine_test1), 1); + if (hdl) { + audio_dec_sine_app_open(hdl); + } + os_time_dly(2); + hdl = audio_dec_sine_app_create_by_parm(sine_test, ARRAY_SIZE(sine_test), 1); + if (hdl) { + audio_dec_sine_app_open(hdl); + } + /* os_time_dly(300); */ +} + +void audio_dec_usb_file_test(void) +{ + tone_play_stop(); + clk_set("sys", 192 * 1000000L); + + struct audio_dec_file_app_hdl *hdl; + /* hdl = audio_dec_file_app_create("storage/udisk/C/1.mp3", 1); */ + hdl = audio_dec_file_app_create("storage/udisk/C/1.wav", 1); + if (hdl) { + audio_dec_file_app_open(hdl); + } + os_time_dly(2); + /* hdl = audio_dec_file_app_create("storage/udisk/C/2.mp3", 1); */ + hdl = audio_dec_file_app_create("storage/udisk/C/2.wav", 1); + if (hdl) { + audio_dec_file_app_open(hdl); + } + os_time_dly(300); +} + +#endif /*test*/ + + diff --git a/apps/common/audio/encode/encode_write.h b/apps/common/audio/encode/encode_write.h new file mode 100644 index 0000000..d723f5d --- /dev/null +++ b/apps/common/audio/encode/encode_write.h @@ -0,0 +1,71 @@ + +#ifndef _ENCODE_WRITE_H +#define _ENCODE_WRITE_H + +#include "app_config.h" +#include "system/includes.h" +#include "system/os/os_cpu.h" +#include "system/fs/fs.h" +#include "dev_manager.h" + + +enum { + ENC_WRITE_FILE_EVT_WRITE_ERR = 0x10, + ENC_WRITE_FILE_EVT_FILE_CLOSE, // 0-err, 非0-起始簇号 + + ENC_WRITE_FLASH_EVT_WRITE_ERR = 0x20, + ENC_WRITE_FLASH_EVT_OUTOF_LEN, +}; + +struct audio_enc_write_input { + int (*get)(void *, s16 **frame, u16 frame_len); + void (*put)(void *, s16 *frame); +}; + +////////////////////////////////////////////////////////////////////////////// +int enc_write_file_resume(void *hdl); // 调用该函数激活写文件 + +void enc_write_file_close(void *hdl); +void *enc_write_file_open(char *logo, const char *folder, const char *filename); + +int enc_write_file_start(void *hdl); +void enc_write_file_stop(void *hdl, u32 delay_ms); // delay_ms:超时等待完成 + +// 录音结束后需要重新写头部数据 +void enc_write_file_set_head_handler(void *hdl, int (*set_head)(void *, char **head), void *set_head_hdl); +void enc_write_file_set_evt_handler(void *hdl, void (*evt_cb)(void *, int, int), void *evt_hdl); +void enc_write_file_set_input(void *hdl, struct audio_enc_write_input *input, void *input_hdl, u32 input_frame_len); + +int get_enc_file_len(void *hdl); +// cut_size:结束后砍掉的尾部长度 +// limit_size:文件小于该长度时,不保留文件 +void enc_write_file_set_limit(void *hdl, u32 cut_size, u32 limit_size); + + +////////////////////////////////////////////////////////////////////////////// +int enc_write_flash_resume(void *hdl); // 调用该函数激活写 + +void enc_write_flash_close(void *hdl); +void *enc_write_flash_open(const char *dev_name, void *arg, u32 addr_start, u32 max_len); + +int enc_write_flash_start(void *hdl); +void enc_write_flash_stop(void *hdl, u32 delay_ms); // delay_ms:超时等待完成 + +// 录音结束后需要重新写头部数据 +void enc_write_flash_set_head_handler(void *hdl, int (*set_head)(void *, char **head), void *set_head_hdl); +void enc_write_flash_set_evt_handler(void *hdl, void (*evt_cb)(void *, int, int), void *evt_hdl); +void enc_write_flash_set_input(void *hdl, struct audio_enc_write_input *input, void *input_hdl, u32 input_frame_len); + +// cut_size:结束后砍掉的尾部长度 +// limit_size:文件小于该长度时,不保留文件 +void enc_write_flash_set_limit(void *hdl, u32 cut_size, u32 limit_size); + +void last_enc_file_codeing_type_save(u32 type); +int last_enc_file_path_get(char path[64]); + + +void *get_wfil_head_hdl(void *enc_whdl); +FILE *get_wfil_file(void *enc_whdl); + +#endif + diff --git a/apps/common/audio/encode/encode_write_file.c b/apps/common/audio/encode/encode_write_file.c new file mode 100644 index 0000000..cf80571 --- /dev/null +++ b/apps/common/audio/encode/encode_write_file.c @@ -0,0 +1,560 @@ +#include "encode_write.h" +#include "file_operate/file_bs_deal.h" +#include "audio_enc.h" +#include "media/audio_base.h" +#include "dev_manager.h" +#include "app_config.h" +#include "spi/nor_fs.h" +#include "rec_nor/nor_interface.h" + +#if TCFG_ENC_WRITE_FILE_ENABLE + +extern FILE *file_api_auto_create_file(const char *path, const char *folder, const char *filename, u32 *file_index); + + // *INDENT-OFF* +struct enc_write_file{ + volatile u32 init_ok : 1; + volatile u32 wait_idle : 1; + volatile u32 start : 1; + volatile u32 wait_stop : 1; + u32 write_err : 1; + OS_SEM sem_task_run; + + struct __dev *dev; + const char *folder; + const char *filename; + void *fmnt; + FILE *file; + u32 cut_size; + u32 limit_size; + int file_size; + u32 input_frame_len; + void *input_hdl; + struct audio_enc_write_input *input; + u32 write_err_no_check; + + void *evt_hdl; + void (*evt_cb)(void *, int, int); + + void *set_head_hdl; + int (*set_head)(void *, char **head); +}; + +static volatile u32 enc_file_index = (u32) - 1; +static volatile u32 enc_file_coding_type = 0; +extern u8 record_part; +void last_enc_file_codeing_type_save(u32 type) +{ + enc_file_coding_type = type; +} + +//获取最后录音文件的序号. 用于录音播放, -1表示无效 +int last_enc_file_path_get(char path[64]) +{ +#if TCFG_NOR_REC || FLASH_INSIDE_REC_ENABLE + int index = 0; + char logo[20] = {0}; + +#if TCFG_NOR_REC + strcpy(logo, "rec_nor"); + sprintf(path, "%s%s%s", dev_manager_get_root_path_by_logo(logo), REC_FOLDER_NAME"/AC69****",".WAV"); +#elif FLASH_INSIDE_REC_ENABLE + char index_str[5] = {0}; + index = flashinsize_rec_get_index(); + memset(logo, 0, 20); + memset(path, 0, 64); + strcpy(logo, "rec_sdfile"); + + index_str[0] = index / 1000 + '0'; + index_str[1] = index % 1000 / 100 + '0'; + index_str[2] = index % 100 / 10 + '0'; + index_str[3] = index % 10 + '0'; + sprintf(path, "%s%s%s%s", dev_manager_get_root_path_by_logo(logo), REC_FOLDER_NAME"/AC69", index_str, ".WAV"); +#endif + printf("rec file =%s\n", path); + return 0; + +#else + + char index_str[5] = {0}; + char *logo = dev_manager_get_phy_logo(dev_manager_find_active(0));//最后活动设备 + printf("enc file idex = %d, dev_path = %s\n", enc_file_index, dev_manager_get_root_path_by_logo(logo)); + if (enc_file_index != (u32) - 1) { + index_str[0] = enc_file_index / 1000 + '0'; + index_str[1] = enc_file_index % 1000 / 100 + '0'; + index_str[2] = enc_file_index % 100 / 10 + '0'; + index_str[3] = enc_file_index % 10 + '0'; + if ((enc_file_coding_type == AUDIO_CODING_WAV) || (enc_file_coding_type == AUDIO_CODING_PCM)) { + sprintf(path, "%s%s%s%s", dev_manager_get_root_path_by_logo(logo), REC_FOLDER_NAME"/AC69", index_str, ".WAV"); + } else if (enc_file_coding_type == AUDIO_CODING_G726) { + sprintf(path, "%s%s%s%s", dev_manager_get_root_path_by_logo(logo), REC_FOLDER_NAME"/AC69", index_str, ".wav"); + } else if (enc_file_coding_type == AUDIO_CODING_MP3) { + sprintf(path, "%s%s%s%s", dev_manager_get_root_path_by_logo(logo), REC_FOLDER_NAME"/AC69", index_str, ".MP3"); + } else { + return -1; + } + printf("rec file =%s\n", path); + return 0; + } + return -1; +#endif +} + +static void enc_write_file_task(void *p) +{ + int ret, len; + int pend_dly = -1; + struct enc_write_file *wfil = p; + s16 *frame; + + while (1) { + if (pend_dly) { + os_sem_pend(&wfil->sem_task_run, pend_dly); + } + if (!wfil->init_ok) { + wfil->wait_idle = 0; + wfil->start = 0; + wfil->wait_stop = 0; + break; + } + pend_dly++; + if (!wfil->start) { + continue; + } + len = wfil->input->get(wfil->input_hdl, &frame, wfil->input_frame_len); + if (len) { + if (wfil->write_err == 0) { + ret = fwrite(wfil->file, frame, len); + wfil->file_size = fpos(wfil->file); +#if TCFG_NOR_REC || FLASH_INSIDE_REC_ENABLE + int max_capacity = 0; +#if TCFG_NOR_REC + max_capacity = get_rec_capacity(wfil->file); +#elif FLASH_INSIDE_REC_ENABLE + max_capacity = flashinsize_rec_get_capacity(); +#endif + if (wfil->file_size + len > (max_capacity - 4096)) { + log_w("rec is overflow!!!!!!!!!!!!!"); + wfil->write_err_no_check = 1; + wfil->write_err = 1; + } else { + wfil->write_err_no_check = 0; + } +#endif + } else { + ret = 0; + } + if (ret != len) { + if (wfil->write_err == 0) { + log_e("write file err "); + if (wfil->evt_cb) { + wfil->evt_cb(wfil->evt_hdl, ENC_WRITE_FILE_EVT_WRITE_ERR, 0); + } + } + wfil->write_err = 1; + } else { + pend_dly = 0; + } + if (wfil->input->put) { + wfil->input->put(wfil->input_hdl, frame); + } + } else { + wfil->wait_stop = 0; + } + } + while (1) { + os_time_dly(100); + } +} + +int enc_write_file_resume(void *hdl) +{ + struct enc_write_file *wfil = hdl; + if (wfil->start && (wfil->write_err == 0)) { + os_sem_set(&wfil->sem_task_run, 0); + os_sem_post(&wfil->sem_task_run); + return 0; + } + return -1; +} + +void enc_write_file_close(void *hdl) +{ + struct enc_write_file *wfil = hdl; + + if (wfil->init_ok) { + wfil->wait_idle = 1; + wfil->init_ok = 0; + os_sem_set(&wfil->sem_task_run, 0); + os_sem_post(&wfil->sem_task_run); + while (wfil->wait_idle) { + os_time_dly(1); + } + task_kill("enc_write"); + } + + if (wfil->file) { + int f_len = fpos(wfil->file); + struct vfs_attr attr = {0}; + do { + if (f_len <= wfil->cut_size) { + enc_file_index = (u32) - 1; + fdelete(wfil->file); + break; + } + f_len -= wfil->cut_size; + if (f_len <= wfil->limit_size) { + enc_file_index = (u32) - 1; + fdelete(wfil->file); + break; + } + + if (wfil->set_head && (wfil->write_err_no_check || wfil->write_err == 0)) { + char *head; + int len = wfil->set_head(wfil->set_head_hdl, &head); + if (f_len <= len) { + enc_file_index = (u32) - 1; + fdelete(wfil->file); + break; + } + if (len) { + fseek(wfil->file, 0, SEEK_SET); + fwrite(wfil->file, head, len); + } + } + fseek(wfil->file, f_len, SEEK_SET); + fget_attrs(wfil->file, &attr); + fclose(wfil->file); + char *dev_logo = NULL; +#if (TCFG_RECORD_FOLDER_DEV_ENABLE) + dev_logo = dev_manager_get_rec_logo(wfil->dev); +#else + dev_logo = dev_manager_get_logo(wfil->dev); +#endif + dev_manager_set_valid_by_logo(dev_logo, 1); + } while (0); + if (wfil->evt_cb) { + wfil->evt_cb(wfil->evt_hdl, ENC_WRITE_FILE_EVT_FILE_CLOSE, attr.sclust); + } + wfil->file = NULL; + } + free(wfil); +} + +static u32 get_creat_path_len(char *root_path, const char *folder, const char *filename) +{ + return (strlen(root_path) + strlen(folder) + strlen(filename) + strlen("/") + 1); +} + +static char *create_path(char *path, char *root_path, const char *folder, const char *filename) +{ + strcat(path, root_path); + strcat(path, folder); + strcat(path, "/"); + strcat(path, filename); +#if TCFG_NOR_REC +#elif FLASH_INSIDE_REC_ENABLE + int index = 0; + int last_num = -1; + char *file_num_str; + + index = sdfile_rec_scan_ex(); + last_num = index + 1; + file_num_str = strrchr(path, '.') - 4; + + if (last_num > 9999) { + last_num = 0; + } + file_num_str[0] = last_num / 1000 + '0'; + file_num_str[1] = last_num % 1000 / 100 + '0'; + file_num_str[2] = last_num % 100 / 10 + '0'; + file_num_str[3] = last_num % 10 + '0'; +#endif + printf(">>>[test]:create path =%s\n", path); + return path; +} + +void *enc_write_file_open(char *logo, const char *folder, const char *filename) +{ + if (!logo || !folder || !filename) { + return NULL; + } + int err; + struct enc_write_file *wfil = zalloc(sizeof(struct enc_write_file)); + if (!wfil) { + return NULL; + } + struct __dev *dev = dev_manager_find_spec(logo, 0); + if(!dev){ + free(wfil); + return NULL; + } + + char *root_path = dev_manager_get_root_path(dev); + wfil->dev = dev; + wfil->folder = folder; + wfil->filename = filename; + char *path = NULL; + u32 path_len = get_creat_path_len(root_path, folder, filename); + printf("path_len %d\n", path_len); + path = zalloc(path_len); + if(path == NULL){ + goto _exit; + } + create_path(path, root_path, folder, filename); + wfil->file = fopen(path, "w+"); + free(path); + path = NULL; + if (!wfil->file) { + log_e("file create err "); + goto _exit; + } + enc_file_index = get_last_num(); //获取最后的数字 + + /* r_printf(">>>[test]:enc_file_index = %d\n", enc_file_index); */ + os_sem_create(&wfil->sem_task_run, 0); + err = task_create(enc_write_file_task, wfil, "enc_write"); + if (err != OS_NO_ERR) { + log_e("task create err "); + goto _exit; + } + wfil->init_ok = 1; + + return wfil; + +_exit: + printf("\n--func=%s, line=%d\n", __FUNCTION__, __LINE__); + enc_write_file_close(wfil); + printf("\n--func=%s, line=%d\n", __FUNCTION__, __LINE__); + return NULL; +} + +int enc_write_file_start(void *hdl) +{ + struct enc_write_file *wfil = hdl; + + if (wfil->init_ok) { + wfil->start = 1; + return 0; + } + return -1; +} + +void enc_write_file_stop(void *hdl, u32 delay_ms) +{ + struct enc_write_file *wfil = hdl; + + if (wfil->start) { + wfil->wait_stop = 1; + u32 dly = 0; + do { + if (!wfil->wait_stop) { + break; + } + if (wfil->write_err) { + break; + } + os_time_dly(1); + dly += 10; + } while (dly < delay_ms); + wfil->start = 0; + } +} + +void enc_write_file_set_head_handler(void *hdl, int (*set_head)(void *, char **head), void *set_head_hdl) +{ + struct enc_write_file *wfil = hdl; + wfil->set_head = set_head; + wfil->set_head_hdl = set_head_hdl; +} + +void enc_write_file_set_evt_handler(void *hdl, void (*evt_cb)(void *, int, int), void *evt_hdl) +{ + struct enc_write_file *wfil = hdl; + wfil->evt_cb = evt_cb; + wfil->evt_hdl = evt_hdl; +} + +void enc_write_file_set_input(void *hdl, struct audio_enc_write_input *input, void *input_hdl, u32 input_frame_len) +{ + struct enc_write_file *wfil = hdl; + wfil->input = input; + wfil->input_hdl = input_hdl; + wfil->input_frame_len = input_frame_len; +} + +void enc_write_file_set_limit(void *hdl, u32 cut_size, u32 limit_size) +{ + struct enc_write_file *wfil = hdl; + wfil->cut_size = cut_size; + wfil->limit_size = limit_size; +} + +int get_enc_file_len(void *hdl) +{ + struct enc_write_file *wfil = hdl; + int filelen = 0; + if (!wfil) { + return -1; + } + if (wfil->file) { + filelen = wfil->file_size; + /* filelen = fpos(wfil->file); */ + /* filelen = flen(wfil->file); */ + } + return filelen; +} + + +void *get_wfil_head_hdl(void *enc_whdl) +{ + struct enc_write_file *wfil = (struct enc_write_file *)enc_whdl; + return wfil->set_head_hdl; +} + +FILE *get_wfil_file(void *enc_whdl) +{ + struct enc_write_file *wfil = (struct enc_write_file *)enc_whdl; + return wfil->file; +} + +////////////////////////////////////////////////////////////////////////////// +#if 0 + +#define W_OUTBUF_LEN (1 * 1024) +struct enc_write_test { + volatile u32 start : 1; + volatile u32 err : 1; + void *hdl; + OS_SEM sem_in; + OS_SEM sem_out; + u8 output_buf[W_OUTBUF_LEN]; + cbuffer_t output_cbuf; + s16 output_frame[512 / 2]; //align 4Bytes + }; + + static void enc_w_evt(void *hdl, int err) +{ + struct enc_write_test *tst = hdl; + printf("err: %d ", err); + if (err) { + tst->err = 1; + os_sem_set(&tst->sem_in, 0); + os_sem_post(&tst->sem_in); + os_sem_set(&tst->sem_out, 0); + os_sem_post(&tst->sem_out); + } +} +static int enc_w_set_head(void *hdl, char **head) +{ + struct enc_write_test *tst = hdl; + u8 hdtab[] = "i'm head!!! "; + memcpy(tst->output_frame, hdtab, sizeof(hdtab)); + *head = tst->output_frame; + return sizeof(hdtab); +} + +static int enc_w_get(void *hdl, s16 **frame, u16 frame_len) +{ + int rlen; + struct enc_write_test *tst = hdl; + do { + rlen = cbuf_read(&tst->output_cbuf, tst->output_frame, frame_len); + if (rlen == frame_len) { + break; + } + if (rlen == -EINVAL) { + return 0; + } + if (!tst->start) { + return 0; + } + if (tst->err) { + return 0; + } + os_sem_set(&tst->sem_in, 0); + os_sem_post(&tst->sem_in); + + os_sem_pend(&tst->sem_out, 2); + } while (1); + + *frame = tst->output_frame; + return rlen; +} +static void enc_w_put(void *hdl, s16 *frame) +{ +} + +const struct audio_enc_write_input enc_w_input = { + .get = enc_w_get, + .put = enc_w_put, +}; + +void enc_w_test(void) +{ + struct enc_write_test *tst = zalloc(sizeof(struct enc_write_test)); + printf("%s,%d ", __func__, __LINE__); + if (!tst) { + return ; + } + printf("%s,%d ", __func__, __LINE__); + os_sem_create(&tst->sem_in, 0); + os_sem_create(&tst->sem_out, 0); + cbuf_init(&tst->output_cbuf, tst->output_buf, W_OUTBUF_LEN); + + printf("%s,%d ", __func__, __LINE__); + tst->hdl = enc_write_file_open("sd0", "/"REC_FOLDER_NAME, "AC690000.MP3"); + printf("%s,%d ", __func__, __LINE__); + if (!tst->hdl) { + goto __exit; + } + + printf("%s,%d ", __func__, __LINE__); + enc_write_file_set_evt_handler(tst->hdl, enc_w_evt, tst); + enc_write_file_set_input(tst->hdl, &enc_w_input, tst, sizeof(tst->output_frame)); + enc_write_file_set_head_handler(tst->hdl, enc_w_set_head, tst); + enc_write_file_set_limit(tst->hdl, 123, 5000); + printf("%s,%d ", __func__, __LINE__); + + tst->start = 1; + + enc_write_file_start(tst->hdl); + + int cnt = 0; + u8 str[] = "This is a test string."; + while (cnt < 1000) { + /* printf("%s,%d ", __func__, __LINE__); */ + int len = cbuf_write(&tst->output_cbuf, str, sizeof(str)); + os_sem_set(&tst->sem_out, 0); + os_sem_post(&tst->sem_out); + enc_write_file_resume(tst->hdl); + /* printf("%s,%d ", __func__, __LINE__); */ + if (len != sizeof(str)) { + putchar('N'); + os_sem_pend(&tst->sem_in, 2); + } else { + putchar('Y'); + cnt++; + } + if (tst->err) { + os_sem_set(&tst->sem_out, 0); + os_sem_post(&tst->sem_out); + break; + } + } + +__exit: + printf("%s,%d ", __func__, __LINE__); + tst->start = 0; + if (tst->hdl) { + enc_write_file_stop(tst->hdl, 1000); + enc_write_file_close(tst->hdl); + tst->hdl = 0; + } + printf("%s,%d ", __func__, __LINE__); + free(tst); +} +#endif + +#endif + diff --git a/apps/common/audio/sine_make.c b/apps/common/audio/sine_make.c new file mode 100644 index 0000000..aff8a74 --- /dev/null +++ b/apps/common/audio/sine_make.c @@ -0,0 +1,316 @@ +/***************************************************************** +>file name : apps/common/sine_make.c +>author : lichao +>create time : Sun 05 May 2019 08:37:35 PM CST +*****************************************************************/ +#include "system/includes.h" +#include "sine_make.h" + +#define SINE_USE_MALLOC 1 + +struct audio_sin_maker { + u8 open; + u8 id; + u8 sin_num; + u8 channel; + u8 repeat; + u8 next_param; + u16 fade_points; + /*int sample_rate;*/ + int volume; + int points; + int sin_index; + int win_sin_index; + const struct sin_param *sin; +}; + +#ifndef SINE_USE_MALLOC +static struct audio_sin_maker sin_maker_handle; +#endif + +void *sin_tone_open(const struct sin_param *param, int num, u8 channel, u8 repeat) +{ + if (!param || !num) { + return NULL; + } + +#ifdef SINE_USE_MALLOC + struct audio_sin_maker *sin = zalloc(sizeof(struct audio_sin_maker)); +#else + struct audio_sin_maker *sin = &sin_maker_handle; +#endif + + if (!sin) { + return NULL; + } + if (sin->open) { + return NULL; + } + + sin->sin = param; + sin->sin_num = num; + sin->open = 1; + sin->points = param[0].points; + sin->id = 0; + sin->channel = channel; + sin->repeat = repeat; +#if (defined CONFIG_CPU_BR18 || \ + CONFIG_CPU_BR21) + /*这里如果加多fade points,会导致结束的时候有噪声,不是在淡出尾部*/ + sin->fade_points = 0; +#else + sin->fade_points = 480; +#endif + sin->next_param = 1; + + return (void *)sin; +} +#if !defined(SINE_MAKE_IN_MASK) +const int sf_sin_tab1[513] = { + 0x00000000, 0x0000c910, 0x0001921f, 0x00025b2d, 0x0003243a, 0x0003ed45, 0x0004b64e, 0x00057f53, + 0x00064855, 0x00071154, 0x0007da4e, 0x0008a343, 0x00096c33, 0x000a351d, 0x000afe00, 0x000bc6dd, + 0x000c8fb3, 0x000d5881, 0x000e2147, 0x000eea03, 0x000fb2b7, 0x00107b61, 0x00114401, 0x00120c96, + 0x0012d521, 0x00139d9f, 0x00146611, 0x00152e77, 0x0015f6d0, 0x0016bf1b, 0x00178758, 0x00184f87, + 0x001917a7, 0x0019dfb7, 0x001aa7b7, 0x001b6fa7, 0x001c3786, 0x001cff53, 0x001dc70f, 0x001e8eb8, + 0x001f564e, 0x00201dd1, 0x0020e541, 0x0021ac9b, 0x002273e2, 0x00233b13, 0x0024022e, 0x0024c933, + 0x00259021, 0x002656f8, 0x00271db7, 0x0027e45f, 0x0028aaed, 0x00297163, 0x002a37bf, 0x002afe01, + 0x002bc429, 0x002c8a35, 0x002d5026, 0x002e15fb, 0x002edbb4, 0x002fa14f, 0x003066ce, 0x00312c2e, + 0x0031f170, 0x0032b694, 0x00337b98, 0x0034407c, 0x00350540, 0x0035c9e4, 0x00368e66, 0x003752c6, + 0x00381705, 0x0038db21, 0x00399f19, 0x003a62ef, 0x003b26a0, 0x003bea2c, 0x003cad94, 0x003d70d7, + 0x003e33f3, 0x003ef6e9, 0x003fb9b8, 0x00407c60, 0x00413ee0, 0x00420138, 0x0042c367, 0x0043856d, + 0x0044474a, 0x004508fc, 0x0045ca83, 0x00468be0, 0x00474d11, 0x00480e16, 0x0048ceef, 0x00498f9a, + 0x004a5019, 0x004b1069, 0x004bd08b, 0x004c907f, 0x004d5043, 0x004e0fd8, 0x004ecf3c, 0x004f8e70, + 0x00504d72, 0x00510c43, 0x0051cae3, 0x0052894f, 0x00534789, 0x0054058f, 0x0054c362, 0x00558100, + 0x00563e6a, 0x0056fb9e, 0x0057b89d, 0x00587565, 0x005931f7, 0x0059ee52, 0x005aaa76, 0x005b6662, + 0x005c2215, 0x005cdd8f, 0x005d98d0, 0x005e53d8, 0x005f0ea5, 0x005fc937, 0x0060838f, 0x00613dab, + 0x0061f78b, 0x0062b12e, 0x00636a95, 0x006423be, 0x0064dcaa, 0x00659557, 0x00664dc6, 0x006705f5, + 0x0067bde5, 0x00687595, 0x00692d05, 0x0069e433, 0x006a9b21, 0x006b51cc, 0x006c0836, 0x006cbe5c, + 0x006d7440, 0x006e29e0, 0x006edf3d, 0x006f9454, 0x00704927, 0x0070fdb5, 0x0071b1fd, 0x007265ff, + 0x007319ba, 0x0073cd2f, 0x0074805c, 0x00753341, 0x0075e5dd, 0x00769831, 0x00774a3c, 0x0077fbfe, + 0x0078ad75, 0x00795ea2, 0x007a0f84, 0x007ac01a, 0x007b7065, 0x007c2064, 0x007cd016, 0x007d7f7c, + 0x007e2e93, 0x007edd5d, 0x007f8bd9, 0x00803a06, 0x0080e7e4, 0x00819573, 0x008242b1, 0x0082ef9f, + 0x00839c3d, 0x00844889, 0x0084f484, 0x0085a02c, 0x00864b82, 0x0086f686, 0x0087a136, 0x00884b92, + 0x0088f59b, 0x00899f4e, 0x008a48ad, 0x008af1b7, 0x008b9a6b, 0x008c42c9, 0x008cead0, 0x008d9281, + 0x008e39da, 0x008ee0db, 0x008f8784, 0x00902dd5, 0x0090d3cd, 0x0091796b, 0x00921eb0, 0x0092c39a, + 0x0093682a, 0x00940c5f, 0x0094b039, 0x009553b7, 0x0095f6d9, 0x0096999f, 0x00973c07, 0x0097de12, + 0x00987fc0, 0x0099210f, 0x0099c200, 0x009a6293, 0x009b02c6, 0x009ba299, 0x009c420c, 0x009ce11f, + 0x009d7fd1, 0x009e1e22, 0x009ebc12, 0x009f599f, 0x009ff6cb, 0x00a09393, 0x00a12ff9, 0x00a1cbfb, + 0x00a26799, 0x00a302d3, 0x00a39da9, 0x00a4381a, 0x00a4d225, 0x00a56bcb, 0x00a6050a, 0x00a69de3, + 0x00a73656, 0x00a7ce61, 0x00a86605, 0x00a8fd41, 0x00a99415, 0x00aa2a80, 0x00aac082, 0x00ab561b, + 0x00abeb4a, 0x00ac800f, 0x00ad1469, 0x00ada859, 0x00ae3bde, 0x00aecef7, 0x00af61a5, 0x00aff3e6, + 0x00b085bb, 0x00b11722, 0x00b1a81d, 0x00b238aa, 0x00b2c8c9, 0x00b3587a, 0x00b3e7bc, 0x00b4768f, + 0x00b504f3, 0x00b592e7, 0x00b6206c, 0x00b6ad7f, 0x00b73a23, 0x00b7c655, 0x00b85216, 0x00b8dd65, + 0x00b96842, 0x00b9f2ac, 0x00ba7ca4, 0x00bb0629, 0x00bb8f3b, 0x00bc17d9, 0x00bca003, 0x00bd27b8, + 0x00bdaef9, 0x00be35c5, 0x00bebc1b, 0x00bf41fc, 0x00bfc767, 0x00c04c5c, 0x00c0d0da, 0x00c154e1, + 0x00c1d870, 0x00c25b89, 0x00c2de29, 0x00c36051, 0x00c3e200, 0x00c46337, 0x00c4e3f5, 0x00c56439, + 0x00c5e403, 0x00c66354, 0x00c6e22a, 0x00c76085, 0x00c7de65, 0x00c85bca, 0x00c8d8b3, 0x00c95521, + 0x00c9d112, 0x00ca4c87, 0x00cac77f, 0x00cb41fa, 0x00cbbbf8, 0x00cc3578, 0x00ccae79, 0x00cd26fd, + 0x00cd9f02, 0x00ce1689, 0x00ce8d90, 0x00cf0417, 0x00cf7a1f, 0x00cfefa8, 0x00d064af, 0x00d0d937, + 0x00d14d3d, 0x00d1c0c2, 0x00d233c6, 0x00d2a649, 0x00d31849, 0x00d389c7, 0x00d3fac3, 0x00d46b3b, + 0x00d4db31, 0x00d54aa4, 0x00d5b993, 0x00d627fe, 0x00d695e5, 0x00d70348, 0x00d77026, 0x00d7dc7f, + 0x00d84853, 0x00d8b3a1, 0x00d91e6a, 0x00d988ad, 0x00d9f26a, 0x00da5ba0, 0x00dac450, 0x00db2c79, + 0x00db941a, 0x00dbfb34, 0x00dc61c7, 0x00dcc7d1, 0x00dd2d53, 0x00dd924d, 0x00ddf6be, 0x00de5aa6, + 0x00debe05, 0x00df20db, 0x00df8327, 0x00dfe4e9, 0x00e04621, 0x00e0a6cf, 0x00e106f2, 0x00e1668a, + 0x00e1c598, 0x00e2241a, 0x00e28210, 0x00e2df7b, 0x00e33c5a, 0x00e398ac, 0x00e3f473, 0x00e44fac, + 0x00e4aa59, 0x00e50479, 0x00e55e0b, 0x00e5b710, 0x00e60f88, 0x00e66771, 0x00e6becc, 0x00e71599, + 0x00e76bd8, 0x00e7c187, 0x00e816a8, 0x00e86b39, 0x00e8bf3c, 0x00e912ae, 0x00e96591, 0x00e9b7e4, + 0x00ea09a7, 0x00ea5ad9, 0x00eaab7b, 0x00eafb8c, 0x00eb4b0c, 0x00eb99fb, 0x00ebe858, 0x00ec3624, + 0x00ec835e, 0x00ecd007, 0x00ed1c1d, 0x00ed67a1, 0x00edb293, 0x00edfcf2, 0x00ee46be, 0x00ee8ff8, + 0x00eed89e, 0x00ef20b0, 0x00ef6830, 0x00efaf1b, 0x00eff573, 0x00f03b37, 0x00f08066, 0x00f0c501, + 0x00f10908, 0x00f14c7a, 0x00f18f57, 0x00f1d19f, 0x00f21352, 0x00f25470, 0x00f294f8, 0x00f2d4eb, + 0x00f31447, 0x00f3530e, 0x00f3913f, 0x00f3ced9, 0x00f40bdd, 0x00f4484b, 0x00f48422, 0x00f4bf62, + 0x00f4fa0b, 0x00f5341d, 0x00f56d97, 0x00f5a67b, 0x00f5dec6, 0x00f6167a, 0x00f64d97, 0x00f6841b, + 0x00f6ba07, 0x00f6ef5b, 0x00f72417, 0x00f7583a, 0x00f78bc5, 0x00f7beb7, 0x00f7f110, 0x00f822d1, + 0x00f853f8, 0x00f88486, 0x00f8b47b, 0x00f8e3d6, 0x00f91298, 0x00f940c0, 0x00f96e4e, 0x00f99b43, + 0x00f9c79d, 0x00f9f35e, 0x00fa1e84, 0x00fa4910, 0x00fa7302, 0x00fa9c59, 0x00fac516, 0x00faed37, + 0x00fb14be, 0x00fb3bab, 0x00fb61fc, 0x00fb87b2, 0x00fbaccd, 0x00fbd14d, 0x00fbf531, 0x00fc187a, + 0x00fc3b28, 0x00fc5d3a, 0x00fc7eb0, 0x00fc9f8a, 0x00fcbfc9, 0x00fcdf6c, 0x00fcfe73, 0x00fd1cdd, + 0x00fd3aac, 0x00fd57de, 0x00fd7474, 0x00fd906e, 0x00fdabcc, 0x00fdc68c, 0x00fde0b1, 0x00fdfa38, + 0x00fe1324, 0x00fe2b72, 0x00fe4323, 0x00fe5a38, 0x00fe70b0, 0x00fe868b, 0x00fe9bc9, 0x00feb069, + 0x00fec46d, 0x00fed7d4, 0x00feea9d, 0x00fefcc9, 0x00ff0e58, 0x00ff1f49, 0x00ff2f9d, 0x00ff3f54, + 0x00ff4e6d, 0x00ff5ce9, 0x00ff6ac7, 0x00ff7808, 0x00ff84ab, 0x00ff90b1, 0x00ff9c18, 0x00ffa6e3, + 0x00ffb10f, 0x00ffba9e, 0x00ffc38f, 0x00ffcbe2, 0x00ffd397, 0x00ffdaaf, 0x00ffe129, 0x00ffe705, + 0x00ffec43, 0x00fff0e3, 0x00fff4e6, 0x00fff84a, 0x00fffb11, 0x00fffd39, 0x00fffec4, 0x00ffffb1, + 0x00ffffff, +}; +#else +extern const int sf_sin_tab1[513] ; +#endif + + +#define SINE_INT_ZOOM 16384 +#define SINE_INT_ZBIT 14 +#define __int64 long long +/*软件索引实现sin生成*/ +static int get_sine_value(int mx_idx) +{ + int ret = 0; + int idx = 0; + int tm_idx = mx_idx & 0x1FFFFFF; //2^25 + int phase = tm_idx & 0x3FFF; + int tp_idx0 = tm_idx >> 14; + int tp_idx1 = tp_idx0 + 1; + int sign = 1, dt0, dt1; + + if (tp_idx0 > 1024) { + sign = -1; + tp_idx0 = 2048 - tp_idx0; + } + if (tp_idx0 < 513) { + dt0 = sf_sin_tab1[tp_idx0]; + } else { + dt0 = sf_sin_tab1[1024 - tp_idx0]; + } + + if (tp_idx1 > 1024) { + sign = -1; + tp_idx1 = 2048 - tp_idx1; + } + if (tp_idx1 < 513) { + dt1 = sf_sin_tab1[tp_idx1]; + } else { + dt1 = sf_sin_tab1[1024 - tp_idx1]; + } + + ret = ((__int64)dt0 * (SINE_INT_ZOOM - phase) + (__int64)dt1 * phase) >> SINE_INT_ZBIT; + + ret *= sign; + return ret; +} + +static void hw_sin_value(int a, int *sin_res, u8 precision) +{ + u64 s64 = a; + + *sin_res = __asm_sine(s64, precision); +} + +int sin_tone_make(void *_maker, void *data, int len) +{ + struct audio_sin_maker *maker = (struct audio_sin_maker *)_maker; + s16 *pcm = (s16 *)data; + int sin_value = 0; + int win_sin_value = 0; + int add_idx = 0, sub_vol = 0, win_add_idx = 0; + int offset = 0; + u8 id = maker->id; + u8 sin_num = maker->sin_num; + u8 repeat = maker->repeat; + u8 channel = maker->channel; + int sin_index; + int win_sin_index; + int volume; + u32 reamin_points = len / 2 / channel; + + do { + if (maker->next_param) { + maker->volume = SINE_TOTAL_VOLUME; + maker->sin_index = 0; + maker->win_sin_index = 0; + maker->next_param = 0; + } + + u8 win = maker->sin[id].win; + add_idx = ((u64)(1 << 25) * maker->sin[id].freq / DEFAULT_SINE_SAMPLE_RATE) >> 9; + if (win) { + win_add_idx = ((u64)(1 << 25) * maker->sin[id].decay / DEFAULT_SINE_SAMPLE_RATE) >> 9; + /*sub_vol = 0;*/ + } else { + sub_vol = maker->sin[id].decay; + } + + sin_index = maker->sin_index; + win_sin_index = maker->win_sin_index; + volume = maker->volume; + u32 points = 0; + if (maker->fade_points) { + points = maker->fade_points > reamin_points ? reamin_points : maker->fade_points; + sub_vol = 0; + maker->fade_points -= points; + } else { + points = maker->points > reamin_points ? reamin_points : maker->points; + maker->points -= points; + } + reamin_points -= points; + while (points--) { + /*hw_sin_value(sin_index, &sin_value, 0);*/ + sin_value = __asm_sine((s64)sin_index, 2); + if (win) { + /*hw_sin_value(win_sin_index, &win_sin_value, 0);*/ + win_sin_value = __asm_sine((s64)win_sin_index, 2); + sin_value = ((s64)sin_value * (s64)win_sin_value) >> 34; + win_sin_index += win_add_idx; + win_sin_index &= 0x1ffffff; + } else { + sin_value = ((s64)volume * sin_value) >> 34; + } + sin_index += add_idx; + sin_index &= 0x1ffffff; + + volume -= sub_vol; + if (volume < 0) { + volume = 0; + } + + *pcm++ = sin_value; + if (channel == 2) { + *pcm++ = sin_value; + } else if (channel == 4) { + *pcm++ = sin_value; + *pcm++ = sin_value; + *pcm++ = sin_value; + } + } + + maker->volume = volume; + maker->sin_index = sin_index; + maker->win_sin_index = win_sin_index; + if (!maker->points) { + if (++id >= sin_num) { + if (!repeat) { + break; + } + id = 0; + } + maker->points = maker->sin[id].points; + maker->id = id; + maker->next_param = 1; + } + + if (!reamin_points) { + break; + } + } while (1); + + return len - (reamin_points * 2 * channel); +} + +int sin_tone_points(void *_maker) +{ + struct audio_sin_maker *maker = (struct audio_sin_maker *)_maker; + int points = 0; + u8 i = 0; + + for (i = 0; i < maker->sin_num; i++) { + points += maker->sin[i].points; + } + + return points; +} + +void sin_tone_close(void *_maker) +{ + struct audio_sin_maker *maker = (struct audio_sin_maker *)_maker; + +#ifdef SINE_USE_MALLOC + if (maker) { + free(maker); + } +#else + if (sin_maker_handle.open) { + sin_maker_handle.open = 0; + } +#endif + +} + diff --git a/apps/common/audio/sine_make.h b/apps/common/audio/sine_make.h new file mode 100644 index 0000000..6cb853d --- /dev/null +++ b/apps/common/audio/sine_make.h @@ -0,0 +1,22 @@ +#ifndef __SINE_MAKE_H_ +#define __SINE_MAKE_H_ + +#include "generic/typedef.h" + +#define DEFAULT_SINE_SAMPLE_RATE 16000 +#define SINE_TOTAL_VOLUME 26843546//16106128//20132660 //26843546 + +struct sin_param { + //int idx_increment; + int freq; + int points; + int win; + int decay; +}; + +int sin_tone_make(void *_maker, void *data, int len); +void *sin_tone_open(const struct sin_param *param, int num, u8 channel, u8 repeat); +int sin_tone_points(void *_maker); +void sin_tone_close(void *_maker); + +#endif/*__SINE_MAKE_H_*/ diff --git a/apps/common/audio/stream/stream_entry.c b/apps/common/audio/stream/stream_entry.c new file mode 100644 index 0000000..93beb04 --- /dev/null +++ b/apps/common/audio/stream/stream_entry.c @@ -0,0 +1,71 @@ +#include "stream_entry.h" + + +static int stream_entry_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + struct __stream_entry *hdl = container_of(entry, struct __stream_entry, entry); + if (in->data_len == 0) { + return 0; + } + + if (hdl->is_end == 0) { + //中间节点才需要往后传数据,终节点不用 + out->data = in->data; + out->data_len = in->data_len; + out->channel = in->channel; + out->data_sync = in->data_sync; + out->sample_rate = in->sample_rate; + } + + if (hdl->data_callback) { + return hdl->data_callback(hdl->data_priv, in); + } + + return in->data_len; +} + +static void stream_entry_output_data_process_len(struct audio_stream_entry *entry, int len) +{ +} + +struct __stream_entry *stream_entry_open(void *priv, int (*data_callback)(void *priv, struct audio_data_frame *in), u8 is_end) +{ + struct __stream_entry *hdl; + hdl = zalloc(sizeof(struct __stream_entry)); + if (hdl == NULL) { + return NULL; + } + + hdl->is_end = is_end; + hdl->data_priv = priv; + hdl->data_callback = data_callback; + hdl->entry.data_process_len = stream_entry_output_data_process_len; + hdl->entry.data_handler = stream_entry_data_handler; + + return hdl; +} + +void stream_entry_close(struct __stream_entry **hdl) +{ + if (hdl && (*hdl)) { + struct __stream_entry *stream = *hdl; + audio_stream_del_entry(&stream->entry); + local_irq_disable(); + free(stream); + *hdl = NULL; + local_irq_enable(); + } +} + +void stream_entry_resume(struct __stream_entry *hdl) +{ + if (hdl) { + audio_stream_resume(&hdl->entry); + } +} + + + + diff --git a/apps/common/audio/stream/stream_entry.h b/apps/common/audio/stream/stream_entry.h new file mode 100644 index 0000000..76b1f35 --- /dev/null +++ b/apps/common/audio/stream/stream_entry.h @@ -0,0 +1,20 @@ +#ifndef __STREAM_ENTRY_H__ +#define __STREAM_ENTRY_H__ + +#include "system/includes.h" +#include "media/includes.h" + +// struct __stream_entry; +struct __stream_entry { + u8 is_end; + void *data_priv; + int (*data_callback)(void *priv, struct audio_data_frame *in); + struct audio_stream_entry entry; +}; + +struct __stream_entry *stream_entry_open(void *priv, int (*data_callback)(void *priv, struct audio_data_frame *in), u8 is_end); +void stream_entry_close(struct __stream_entry **hdl); +void stream_entry_resume(struct __stream_entry *hdl); + +#endif// __STREAM_ENTRY_H__ + diff --git a/apps/common/audio/stream/stream_src.c b/apps/common/audio/stream/stream_src.c new file mode 100644 index 0000000..f7558b9 --- /dev/null +++ b/apps/common/audio/stream/stream_src.c @@ -0,0 +1,182 @@ +#include "stream_src.h" + +static void stream_src_irq_cb(void *hdl) +{ + struct __stream_src *stream = hdl; + audio_stream_resume(&stream->entry); +} + +static int stream_src_output_handler(void *hdl, void *buf, int len) +{ + struct __stream_src *stream = hdl; + if (!stream) { + return 0; + } + + if (stream->out_buf) { + if (stream->out_points < stream->out_total) { + return 0; + } else { + stream->out_buf = NULL; + return len; + } + } + + stream->out_buf = buf; + stream->out_points = 0; + stream->out_total = len / 2; + return 0; +} + + +static int stream_src_run(struct __stream_src *stream, s16 *data, int len) +{ + if (stream->src_hdl == NULL) { + return 0; + } + return audio_src_resample_write(stream->src_hdl, data, len); +} + +static void stream_src_output_data_process_len(struct audio_stream_entry *entry, int len) +{ + struct __stream_src *stream = container_of(entry, struct __stream_src, entry); + if (stream) { + stream->out_points += len / 2; + } +} + +static void stream_src_check(struct __stream_src *stream, u16 sr, u8 ch_num) +{ + if ((stream->src_always == 0) && (stream->target_sr == sr)) { + audio_hw_src_stop(stream->src_hdl); + audio_hw_src_close(stream->src_hdl); + free(stream->src_hdl); + stream->src_hdl = NULL; + return ; + } + if (stream->src_hdl == NULL) { + stream->src_hdl = zalloc(sizeof(struct audio_src_handle)); + ASSERT(stream->src_hdl); + audio_hw_src_open(stream->src_hdl, ch_num, SRC_TYPE_RESAMPLE); + audio_hw_src_set_rate(stream->src_hdl, sr, stream->target_sr); + audio_src_set_output_handler(stream->src_hdl, stream, stream_src_output_handler); + audio_src_set_rise_irq_handler(stream->src_hdl, stream, stream_src_irq_cb); + } else { + audio_hw_src_set_rate(stream->src_hdl, sr, stream->target_sr); + } +} + +static int stream_src_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + struct __stream_src *stream = container_of(entry, struct __stream_src, entry); + out->sample_rate = stream->target_sr; + if (in->data_len) { + out->no_subsequent = 1; + } + //输出剩余数据 + if (stream->out_buf && (stream->out_points < stream->out_total)) { + struct audio_data_frame frame; + memset(&frame, 0, sizeof(frame)); + frame.channel = in->channel; + frame.sample_rate = stream->target_sr; + frame.data_sync = in->data_sync; + while (1) { + frame.data_len = (stream->out_total - stream->out_points) * 2; + frame.data = &stream->out_buf[stream->out_points]; + int len = stream->out_points; + audio_stream_run(entry, &frame); + break; + } + //未输出完退出 + if (stream->out_points < stream->out_total) { + return 0; + } + } else { + //printf("=========\n"); + } + + //同步检查 + stream_src_check(stream, in->sample_rate, in->channel); + + int len = 0; + u8 cnt = 0; + len = stream_src_run(stream, in->data, in->data_len); + + if (stream->out_buf && (stream->out_points < stream->out_total)) { + struct audio_data_frame frame; + memset(&frame, 0, sizeof(frame)); + frame.channel = in->channel; + frame.sample_rate = stream->target_sr; + frame.data_sync = in->data_sync; + while (1) { + frame.data_len = (stream->out_total - stream->out_points) * 2; + frame.data = &stream->out_buf[stream->out_points]; + int len = stream->out_points; + audio_stream_run(entry, &frame); + break; + } + if (stream->out_points < stream->out_total) { + return len; + } + if (!len) { + len = stream_src_run(stream, in->data, in->data_len); + } + + } else { + out->data_len = 0; + //printf("^^^^^^^^^^/n"); + } + + return len; +} + + +void stream_src_set_target_rate(struct __stream_src *hdl, u16 sr) +{ + if (hdl) { + hdl->target_sr = sr; + } +} + +struct __stream_src *stream_src_open(u16 target_sr, u8 always) +{ + struct __stream_src *stream = zalloc(sizeof(struct __stream_src)); + ASSERT(stream); + + stream->src_always = always; + stream->target_sr = target_sr; + + stream->entry.data_process_len = stream_src_output_data_process_len; + stream->entry.data_handler = stream_src_data_handler; + + return stream; +} + +void stream_src_close(struct __stream_src **hdl) +{ + if (hdl && (*hdl)) { + struct __stream_src *stream = *hdl; + audio_stream_del_entry(&stream->entry); + if (stream->src_hdl) { + audio_hw_src_stop(stream->src_hdl); + audio_hw_src_close(stream->src_hdl); + free(stream->src_hdl); + stream->src_hdl = NULL; + } + local_irq_disable(); + free(stream); + *hdl = NULL; + local_irq_enable(); + } +} + +void stream_src_resume(struct __stream_src *hdl) +{ + if (hdl) { + audio_stream_resume(&hdl->entry); + } +} + + diff --git a/apps/common/audio/stream/stream_src.h b/apps/common/audio/stream/stream_src.h new file mode 100644 index 0000000..2cb081d --- /dev/null +++ b/apps/common/audio/stream/stream_src.h @@ -0,0 +1,23 @@ +#ifndef __STREAM_SRC_H__ +#define __STREAM_SRC_H__ + +#include "system/includes.h" +#include "media/includes.h" + +struct __stream_src { + s16 *out_buf; + int out_points; + int out_total; + u8 src_always; + u16 target_sr; + struct audio_src_handle *src_hdl; + struct audio_stream_entry entry; +}; + +struct __stream_src *stream_src_open(u16 target_sr, u8 always); +void stream_src_close(struct __stream_src **hdl); +void stream_src_resume(struct __stream_src *hdl); +void stream_src_set_target_rate(struct __stream_src *hdl, u16 sr); + +#endif// __STREAM_SRC_H__ + diff --git a/apps/common/audio/stream/stream_sync.c b/apps/common/audio/stream/stream_sync.c new file mode 100644 index 0000000..754c042 --- /dev/null +++ b/apps/common/audio/stream/stream_sync.c @@ -0,0 +1,198 @@ +#include "stream_sync.h" + +static void stream_sync_irq_cb(void *hdl) +{ + struct __stream_sync *stream = hdl; + audio_stream_resume(&stream->entry); +} + +static int stream_sync_output_handler(void *hdl, void *buf, int len) +{ + struct __stream_sync *stream = hdl; + if (!stream) { + return 0; + } + + if (stream->out_buf) { + if (stream->out_points < stream->out_total) { + return 0; + } else { + stream->out_buf = NULL; + return len; + } + } + + stream->out_buf = buf; + stream->out_points = 0; + stream->out_total = len / 2; + return 0; +} + + +static int stream_sync_run(struct __stream_sync *stream, s16 *data, int len) +{ + int data_size = stream->cb.get_size(stream->cb.priv); +#if 0 + if (!stream->sync.start) { + if (data_size < stream->sync.begin_size) { + return 0; + } + stream->sync.start = 1; + } +#endif + stream->sync.start = 1; + audio_buf_sync_adjust(&stream->sync, data_size); + return audio_src_resample_write(stream->sync.src_sync, data, len); +} + +static void stream_sync_output_data_process_len(struct audio_stream_entry *entry, int len) +{ + struct __stream_sync *stream = container_of(entry, struct __stream_sync, entry); + if (stream) { + stream->out_points += len / 2; + } +} + +static int stream_sync_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + struct __stream_sync *stream = container_of(entry, struct __stream_sync, entry); + out->sample_rate = stream->sample_rate; + if (in->data_len) { + out->no_subsequent = 1; + } + //输出剩余数据 + if (stream->out_buf && (stream->out_points < stream->out_total)) { + struct audio_data_frame frame; + memset(&frame, 0, sizeof(frame)); + frame.channel = in->channel; + frame.sample_rate = stream->sample_rate; + frame.data_sync = in->data_sync; + while (1) { + frame.data_len = (stream->out_total - stream->out_points) * 2; + frame.data = &stream->out_buf[stream->out_points]; + int len = stream->out_points; + audio_stream_run(entry, &frame); +#if 0 + if (len == stream->out_points) { + break; + } + if (stream->out_points == stream->out_total) { + break; + } +#else + break; +#endif + } + //未输出完退出 + if (stream->out_points < stream->out_total) { + return 0; + } + } else { + //printf("=========\n"); + } + + int len = 0; + u8 cnt = 0; + len = stream_sync_run(stream, in->data, in->data_len); + + if (stream->out_buf && (stream->out_points < stream->out_total)) { + struct audio_data_frame frame; + memset(&frame, 0, sizeof(frame)); + frame.channel = in->channel; + frame.sample_rate = stream->sample_rate; + frame.data_sync = in->data_sync; + while (1) { + frame.data_len = (stream->out_total - stream->out_points) * 2; + frame.data = &stream->out_buf[stream->out_points]; + int len = stream->out_points; + audio_stream_run(entry, &frame); +#if 0 + if (len == stream->out_points) { + break; + } + if (stream->out_points == stream->out_total) { + break; + } +#else + break; +#endif + } + if (stream->out_points < stream->out_total) { + return len; + } + if (!len) { + len = stream_sync_run(stream, in->data, in->data_len); + } + + } else { + out->data_len = 0; + //printf("^^^^^^^^^^/n"); + } + + return len; +} + + +struct __stream_sync *stream_sync_open(struct stream_sync_info *info, u8 always) +{ + struct audio_buf_sync_open_param param = {0}; + + struct __stream_sync *stream = zalloc(sizeof(struct __stream_sync)); + ASSERT(stream); + + param.total_len = info->get_total(info->priv); + param.begin_per = info->begin_per; + param.top_per = info->top_per; + param.bottom_per = info->bottom_per; + param.inc_step = info->inc_step; + param.dec_step = info->dec_step; + param.max_step = info->max_step; + param.in_sr = info->i_sr; + param.out_sr = info->o_sr; + param.ch_num = info->ch_num; + if (always) { + param.check_in_out = 0; + } else { + param.check_in_out = 1; + } + param.output_hdl = stream; + param.output_handler = stream_sync_output_handler; + int ret = audio_buf_sync_open(&stream->sync, ¶m); + ASSERT(ret == true); + audio_src_set_rise_irq_handler(stream->sync.src_sync, stream, stream_sync_irq_cb); + + stream->sample_rate = info->o_sr; + stream->cb.priv = info->priv; + stream->cb.get_size = info->get_size; + stream->cb.get_total = info->get_total; + + stream->entry.data_process_len = stream_sync_output_data_process_len; + stream->entry.data_handler = stream_sync_data_handler; + + return stream; +} + +void stream_sync_close(struct __stream_sync **hdl) +{ + if (hdl && (*hdl)) { + struct __stream_sync *stream = *hdl; + audio_stream_del_entry(&stream->entry); + stream->sync.start = 0; + audio_buf_sync_close(&stream->sync); + local_irq_disable(); + free(stream); + *hdl = NULL; + local_irq_enable(); + } +} + +void stream_sync_resume(struct __stream_sync *hdl) +{ + if (hdl) { + audio_stream_resume(&hdl->entry); + } +} + + diff --git a/apps/common/audio/stream/stream_sync.h b/apps/common/audio/stream/stream_sync.h new file mode 100644 index 0000000..3ec775c --- /dev/null +++ b/apps/common/audio/stream/stream_sync.h @@ -0,0 +1,44 @@ +#ifndef __STREAM_SYNC_H__ +#define __STREAM_SYNC_H__ + +#include "system/includes.h" +#include "media/includes.h" + +struct stream_sync_info { + u16 i_sr; + u16 o_sr; + u8 ch_num; + int begin_per; // 起始百分比 + int top_per; // 最大百分比 + int bottom_per; // 最小百分比 + u8 inc_step; // 每次调整增加步伐 + u8 dec_step; // 每次调整减少步伐 + u8 max_step; // 最大调整步伐 + void *priv; // get_total,get_size私有句柄 + int (*get_total)(void *priv); // 获取buf总长 + int (*get_size)(void *priv); // 获取buf数据长度 +}; + +struct __stream_sync_cb { + void *priv; // get_total,get_size私有句柄 + int (*get_total)(void *priv); // 获取buf总长 + int (*get_size)(void *priv); // 获取buf数据长度 +}; + + +struct __stream_sync { + s16 *out_buf; + int out_points; + int out_total; + u16 sample_rate; + struct __stream_sync_cb cb; + struct audio_buf_sync_hdl sync; + struct audio_stream_entry entry; +}; + +struct __stream_sync *stream_sync_open(struct stream_sync_info *info, u8 always); +void stream_sync_close(struct __stream_sync **hdl); +void stream_sync_resume(struct __stream_sync *hdl); + +#endif// __STREAM_SYNC_H__ + diff --git a/apps/common/audio/uartPcmSender.c b/apps/common/audio/uartPcmSender.c new file mode 100644 index 0000000..24a0d32 --- /dev/null +++ b/apps/common/audio/uartPcmSender.c @@ -0,0 +1,142 @@ +#include "app_config.h" + +#ifdef AUDIO_PCM_DEBUG +#include "system/includes.h" +#include "asm/uart_dev.h" + +/* + *串口导出数据配置 + *注意IO口设置不要和普通log输出uart冲突 + */ +#define PCM_UART1_TX_PORT IO_PORT_DP /*数据导出发送IO*/ +#define PCM_UART1_RX_PORT -1 +#define PCM_UART1_BAUDRATE 2000000 /*数据导出波特率,不用修改,和接收端设置一直*/ + +#if ((TCFG_UART0_ENABLE == ENABLE_THIS_MOUDLE) && (PCM_UART1_TX_PORT == TCFG_UART0_TX_PORT)) +//IO口配置冲突,请检查修改 +#error "PCM_UART1_TX_PORT conflict with TCFG_UART0_TX_PORT" +#endif/*PCM_UART1_TX_PORT*/ + + +static u8 uart_cbuf[32] __attribute__((aligned(4))); +const uart_bus_t *uart_bus = NULL; + +//设备事件响应demo +void uart_event_handler(struct sys_event *e) +{ + u8 uart_rxbuf[12] = {0}; + u8 uart_txbuf[12] = {0}; + const uart_bus_t *_uart_bus; + u32 uart_rxcnt = 0; + u8 i = 0; + + if (0) {//!strcmp(e->arg, "uart_rx_overflow")) { + if (e->u.dev.event == DEVICE_EVENT_CHANGE) { + printf("uart event: %s\n", e->arg); + _uart_bus = (const uart_bus_t *)e->u.dev.value; + uart_rxcnt = _uart_bus->read(uart_rxbuf, sizeof(uart_rxbuf), 0); + if (uart_rxcnt) { + g_printf("rx:%s", uart_rxbuf); + } + } + } + if (0) { //(!strcmp(e->arg, "uart_rx_outtime")) { + if (e->u.dev.event == DEVICE_EVENT_CHANGE) { + printf("uart event: %s\n", e->arg); + _uart_bus = (const uart_bus_t *)e->u.dev.value; + uart_rxcnt = _uart_bus->read(uart_rxbuf, sizeof(uart_rxbuf), 0); + if (uart_rxcnt) { + printf("get_buffer:\n"); + for (int i = 0; i < uart_rxcnt; i++) { + putbyte(uart_rxbuf[i]); + if (i % 16 == 15) { + putchar('\n'); + } + } + if (uart_rxcnt % 16) { + putchar('\n'); + } + _uart_bus->write(uart_rxbuf, uart_rxcnt); + } + printf("uart out\n"); + } + } +} +SYS_EVENT_HANDLER(SYS_DEVICE_EVENT, uart_event_handler, 0); + +void gpio_change(void *priv); +static void uart_isr_hook(void *arg, u32 status) +{ + const uart_bus_t *ubus = arg; + struct sys_event e; + + //当CONFIG_UARTx_ENABLE_TX_DMA(x = 0, 1)为1时,不要在中断里面调用ubus->write(),因为中断不能pend信号量 + if (status == UT_RX) { + printf("uart_rx_isr\n"); +#if 1//(UART_DEV_USAGE_TEST_SEL == 1) + e.type = SYS_DEVICE_EVENT; + e.arg = "uart_rx_overflow"; + e.u.dev.event = DEVICE_EVENT_CHANGE; + e.u.dev.value = (int)ubus; + sys_event_notify(&e); +#endif + } + if (status == UT_RX_OT) { + printf("uart_rx_ot_isr\n"); +#if 1//(UART_DEV_USAGE_TEST_SEL == 1) + e.type = SYS_DEVICE_EVENT; + e.arg = "uart_rx_outtime"; + e.u.dev.event = DEVICE_EVENT_CHANGE; + e.u.dev.value = (int)ubus; + sys_event_notify(&e); +#endif + } + if (status == UT_TX) { + /* putchar('T'); */ + /* gpio_change(0); */ + } +} + +void uartSendData(void *buf, u16 len) //发送数据的接口。 +{ + if (uart_bus) { + uart_bus->write(buf, len); //把数据写到DMA + } +} + +/* char *TickPage = "uart online"; */ +/* void uartTickSend(void *priv){ */ +/* if(uartTickSendFlag){ */ +/* r_printf("sizeof:%d\n", sizeof(TickPage)); */ +/* uartSendData(TickPage, sizeof(TickPage)); */ +/* } */ +/* } */ + +void uartSendInit() +{ + struct uart_platform_data_t u_arg = {0}; + u_arg.tx_pin = PCM_UART1_TX_PORT; + u_arg.rx_pin = PCM_UART1_RX_PORT; + u_arg.rx_cbuf = uart_cbuf; + u_arg.rx_cbuf_size = 32; + u_arg.frame_length = 6; + u_arg.rx_timeout = 100; + u_arg.isr_cbfun = uart_isr_hook; + u_arg.baud = PCM_UART1_BAUDRATE; + u_arg.is_9bit = 0; + + + r_printf("uart_dev_open() ...\n"); + uart_bus = uart_dev_open(&u_arg); + r_printf("comming %s,%d\n", __func__, __LINE__); + if (uart_bus != NULL) { + r_printf("success\n"); + gpio_set_hd(PCM_UART1_TX_PORT, 1); + gpio_set_hd0(PCM_UART1_TX_PORT, 1); + //os_task_create(uart_u_task, (void *)uart_bus, 31, 512, 0, "uart_u_task"); + } else { + r_printf("false\n"); + } +} + +#endif diff --git a/apps/common/bt_common/bt_test_api.c b/apps/common/bt_common/bt_test_api.c new file mode 100644 index 0000000..9c9dbf5 --- /dev/null +++ b/apps/common/bt_common/bt_test_api.c @@ -0,0 +1,97 @@ + +#include "typedef.h" +#include "app_config.h" +#include "task.h" + +#define LOG_TAG "[BT_DUT]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +//bredr test api +extern void ble_enter_dut_tx_mode(void *param); +extern void bt_ble_adv_enable(u8 enable); +extern void bredr_fcc_init(u8 mode, u8 fre); + +#if 0 + +static void bt_dut_api(void) +{ + log_info("bt in dut \n"); +#if TCFG_AUTO_SHUT_DOWN_TIME + extern void sys_auto_shut_down_disable(void); + sys_auto_shut_down_disable(); +#endif + +#if TCFG_USER_TWS_ENABLE + extern void tws_cancle_all_noconn(); + tws_cancle_all_noconn() ; +#else + //sys_timer_del(app_var.auto_stop_page_scan_timer); + extern void bredr_close_all_scan(); + bredr_close_all_scan(); +#endif + +#if TCFG_USER_BLE_ENABLE +#if (CONFIG_BT_MODE == BT_NORMAL) + bt_ble_adv_enable(0); +#endif +#endif +} + +void bit_clr_ie(unsigned char index); +/* !!!Notice:when this api is called and sleep mode should be sure to exit; */ +void bt_fix_fre_api(u8 fre) +{ + bt_dut_api(); + + bit_clr_ie(IRQ_BREDR_IDX); + bit_clr_ie(IRQ_BT_CLKN_IDX); + + bredr_fcc_init(BT_FRE, fre); +} +#endif + +//ble test api +enum { + PAYLOAD_TYPE_PRBS9 = 0, + PAYLOAD_TYPE_11110000, + PAYLOAD_TYPE_10101010, + PAYLOAD_TYPE_PRBS15, + PAYLOAD_TYPE_11111111, + PAYLOAD_TYPE_00000000, + PAYLOAD_TYPE_00001111, + PAYLOAD_TYPE_01010101, + + PAYLOAD_TYPE_SINGLE_CARRIER = 0xf0, +}; + +struct ble_dut_param_set { + u8 ch_index; //tx ch index;(0~39 -> 2402~2480) + u8 payload_type; //tx payload type + u8 payload_len; //payload_len(0~0xff) when continuous_tx = 0; + u8 continuous_tx; //enable or disable continuous transmission mode(0/1) +}; + +/* !!!Notice:when this api is called and sleep mode should be sure to exit; */ +void ble_fix_fre_api() +{ +#if TCFG_USER_BLE_ENABLE +#if (CONFIG_BT_MODE == BT_NORMAL) + bt_ble_adv_enable(0); +#endif + os_time_dly(10); + + struct ble_dut_param_set dut_param = { + .ch_index = 0, + .payload_type = PAYLOAD_TYPE_10101010, + .payload_len = 0x20, + .continuous_tx = 1, + }; + ble_enter_dut_tx_mode(&dut_param); +#endif +} + diff --git a/apps/common/charge_box/chargeIc_manage.c b/apps/common/charge_box/chargeIc_manage.c new file mode 100644 index 0000000..d787002 --- /dev/null +++ b/apps/common/charge_box/chargeIc_manage.c @@ -0,0 +1,249 @@ +#include "chargeIc_manage.h" +#include "device/device.h" +#include "app_config.h" +#include "app_main.h" +#include "user_cfg.h" +#include "chgbox_det.h" +#include "chgbox_ctrl.h" +#include "chgbox_wireless.h" + +#if (TCFG_CHARGE_BOX_ENABLE) + +#define LOG_TAG_CONST APP_CHGBOX +#define LOG_TAG "[CHG_IC]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +//充电涓流转恒流的电压点--使用内置充电时有效 +#define CHARGE_CURRENT_CHANGE (3000) +#define CHARGE_FULL_MA (CHARGE_FULL_mA_30) +#define CHARGE_SLOW_MA (CHARGE_mA_40) +#define CHARGE_WL_FAST_MA (CHARGE_mA_200)//无线充电时,使用200mA充电电流 +#define CHARGE_FAST_MA (CHARGE_mA_320)//线充是使用320mA充电电流 + +#if (TCFG_CHARGE_MOUDLE_OUTSIDE == DISABLE) +static volatile u8 inside_ma; +static int charge_timer; +#endif +#if TCFG_SHORT_PROTECT_ENABLE +extern void short_det_wakeup_disable(); +extern void short_det_wakeup_enable(); +#endif +static volatile u8 charge_en; + +/*------------------------------------------------------------------------------------*/ +/**@brief 根据电池电压设置电流档位 + @param 无 + @return 无 + @note 开始充电时调用该接口切到对应档位 +*/ +/*------------------------------------------------------------------------------------*/ +#if (TCFG_CHARGE_MOUDLE_OUTSIDE == DISABLE) +void chargebox_charge_change_current(void *priv) +{ + u8 inside_target = CHARGE_FAST_MA; + u16 vbat_volt = get_vbat_voltage(); + charge_timer = 0; + if (vbat_volt > CHARGE_CURRENT_CHANGE) { +#if TCFG_WIRELESS_ENABLE + if (sys_info.status[WIRELESS_DET] == STATUS_ONLINE) { + inside_target = CHARGE_WL_FAST_MA; + } +#endif + CHARGE_mA_SEL(inside_target); + inside_ma = inside_target; + } else { + //涓流充电时,10s查看一次电量 + CHARGE_mA_SEL(CHARGE_SLOW_MA); + inside_ma = CHARGE_SLOW_MA; + charge_timer = sys_timeout_add(NULL, chargebox_charge_change_current, 10000); + } +} +#endif + +/*------------------------------------------------------------------------------------*/ +/**@brief 开始对电池仓充电 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +void chargebox_charge_start(void) +{ + log_info("charge start!\n"); +#if TCFG_CHARGE_MOUDLE_OUTSIDE + gpio_direction_input(TCFG_STOP_CHARGE_IO); + usb_charge_full_wakeup_deal();//外挂充电,开充电时主动去查询一次是否充满 +#else + //先切根据电压切换电流档位,再开充电 + chargebox_charge_change_current(NULL); + charge_start(); +#endif + charge_en = 1; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 停止对电池仓充电 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +void chargebox_charge_close(void) +{ + log_info("charge close!\n"); +#if TCFG_CHARGE_MOUDLE_OUTSIDE + gpio_direction_output(TCFG_STOP_CHARGE_IO, 1); +#else + if (charge_timer) { + sys_timer_del(charge_timer); + charge_timer = 0; + } + charge_close(); + CHARGE_mA_SEL(CHARGE_SLOW_MA); + inside_ma = CHARGE_SLOW_MA; +#endif + charge_en = 0; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 获取系统是否在充电 + @param 无 + @return 1:正在充电, 0:充电关闭 + @note +*/ +/*------------------------------------------------------------------------------------*/ +u8 chargebox_get_charge_en(void) +{ + return charge_en; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电升压开关 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +void chargeIc_boost_ctrl(u8 en) +{ +#if TCFG_SHORT_PROTECT_ENABLE + if (en == 0) { + short_det_wakeup_disable(); + } +#endif + gpio_direction_output(TCFG_BOOST_CTRL_IO, en); + log_debug("boost_ctrl:%s\n", en ? "open" : "close"); +#if TCFG_LDO_DET_ENABLE + ldo_wakeup_deal(NULL); +#else + sys_info.status[LDO_DET] = en ? STATUS_ONLINE : STATUS_OFFLINE; +#endif +#if TCFG_CURRENT_LIMIT_ENABLE + //开升压时才去检测耳机充电电流 + ear_current_detect_enable(en); +#endif +#if TCFG_SHORT_PROTECT_ENABLE + if (en) { + short_det_wakeup_enable(); + } +#endif +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 耳机充电电源开关 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +void chargeIc_pwr_ctrl(u8 en) +{ +#if (TCFG_PWR_CTRL_TYPE == PWR_CTRL_TYPE_PU_PD) + if (en == 0) { + gpio_set_pull_up(TCFG_PWR_CTRL_IO, 0); + gpio_set_pull_down(TCFG_PWR_CTRL_IO, 1); + } else { + gpio_set_pull_down(TCFG_PWR_CTRL_IO, 0); + gpio_set_pull_up(TCFG_PWR_CTRL_IO, 1); + } +#elif (TCFG_PWR_CTRL_TYPE == PWR_CTRL_TYPE_OUTPUT_0) + if (en == 0) { + gpio_direction_input(TCFG_PWR_CTRL_IO); + } else { + gpio_direction_output(TCFG_PWR_CTRL_IO, 0); + } +#elif (TCFG_PWR_CTRL_TYPE == PWR_CTRL_TYPE_OUTPUT_1) + if (en == 0) { + gpio_direction_input(TCFG_PWR_CTRL_IO); + } else { + gpio_direction_output(TCFG_PWR_CTRL_IO, 1); + } +#endif + log_debug("vol_ctrl:%s\n", en ? "open" : "close"); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电IC初始化 + @param null + @return null + @note 初始化充电IC相关的引脚 +*/ +/*------------------------------------------------------------------------------------*/ +void chargeIc_init(void) +{ + //使能IO输出低电平 + gpio_set_die(TCFG_BOOST_CTRL_IO, 0); + gpio_set_pull_down(TCFG_BOOST_CTRL_IO, 0); + gpio_set_pull_up(TCFG_BOOST_CTRL_IO, 0); + gpio_direction_output(TCFG_BOOST_CTRL_IO, 0); + + //PWR_CTRL初始化 + gpio_set_die(TCFG_PWR_CTRL_IO, 0); + gpio_set_pull_up(TCFG_PWR_CTRL_IO, 0); + gpio_direction_input(TCFG_PWR_CTRL_IO); +#if (TCFG_PWR_CTRL_TYPE == PWR_CTRL_TYPE_PU_PD) + gpio_set_pull_down(TCFG_PWR_CTRL_IO, 1); +#else + gpio_set_pull_down(TCFG_PWR_CTRL_IO, 0); +#endif + +#if TCFG_CHARGE_MOUDLE_OUTSIDE + //充电控制脚,高阻时正常充电,输出1时充电截止 + charge_en = 1; + gpio_set_die(TCFG_STOP_CHARGE_IO, 1); + gpio_set_pull_down(TCFG_STOP_CHARGE_IO, 0); + gpio_set_pull_up(TCFG_STOP_CHARGE_IO, 0); + if (charge_en == 1) { + gpio_direction_input(TCFG_STOP_CHARGE_IO); + } else { + gpio_direction_output(TCFG_STOP_CHARGE_IO, 1); + } +#else + //内置充电初始化 + CHGBG_EN(0); + CHARGE_EN(0); + CHARGE_WKUP_PND_CLR(); + + LVCMP_EN(1); + LVCMP_EDGE_SEL(0); + LVCMP_PND_CLR(); + LVCMP_EDGE_WKUP_EN(1); + LVCMP_CMP_SEL(1); + u16 charge_4202_trim_val = get_vbat_trim(); + if (charge_4202_trim_val == 0xf) { + log_info("vbat not trim, use default config!!!!!!"); + } + CHARGE_FULL_V_SEL(charge_4202_trim_val); + CHARGE_FULL_mA_SEL(CHARGE_FULL_MA); + CHARGE_mA_SEL(CHARGE_SLOW_MA); + inside_ma = CHARGE_SLOW_MA; + charge_en = 0; +#endif +} + +#endif diff --git a/apps/common/charge_box/chargeIc_manage.h b/apps/common/charge_box/chargeIc_manage.h new file mode 100644 index 0000000..40f4356 --- /dev/null +++ b/apps/common/charge_box/chargeIc_manage.h @@ -0,0 +1,20 @@ +#ifndef _CHARGEIC_MANAGE_H +#define _CHARGEIC_MANAGE_H + +#include "printf.h" +#include "cpu.h" +#include "timer.h" +#include "app_config.h" +#include "event.h" +#include "system/includes.h" + +void chargeIc_init(void); +void chargeIc_boost_ctrl(u8 en); +void chargeIc_pwr_ctrl(u8 en); +void chargebox_charge_start(void); +void chargebox_charge_close(void); +u8 chargebox_get_charge_en(void); + +#endif + + diff --git a/apps/common/charge_box/chgbox_box.c b/apps/common/charge_box/chgbox_box.c new file mode 100644 index 0000000..deaf52a --- /dev/null +++ b/apps/common/charge_box/chgbox_box.c @@ -0,0 +1,563 @@ +#include "app_config.h" +#include "system/includes.h" +#include "chgbox_box.h" +#include "user_cfg.h" +#include "device/vm.h" +#include "app_task.h" +#include "app_main.h" +#include "chargeIc_manage.h" +#include "chgbox_ctrl.h" +#include "device/chargebox.h" +#include "asm/power/p33.h" +#include "chgbox_det.h" + +#if(TCFG_CHARGE_BOX_ENABLE) + +#define LOG_TAG_CONST APP_CHGBOX +#define LOG_TAG "[APP_CBOX]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +#define LOG_CLI_ENABLE +#include "debug.h" + + +#define CHGBOX_THR_NAME "chgbox_n" +OS_MUTEX power_mutex; + +//电池参数,电池不同,参数不同 +//使用不同的电池要更新此表,不然数据可能会不准确 +#define POWER_TOP_LVL 4200 +#define POWER_BOOT_LVL 3100 +#define POWER_LVL_MAX 11 + +const u16 voltage_table[2][POWER_LVL_MAX] = { + {0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100}, + {POWER_BOOT_LVL, 3600, 3660, 3720, 3780, 3840, 3900, 3950, 4000, 4050, POWER_TOP_LVL}, +}; + +/*------------------------------------------------------------------------------------*/ +/**@brief 获取充电仓电量值 + @param 无 + @return 0~100 的电量值 + @note 电量根据电池电量表换算成0~100 +*/ +/*------------------------------------------------------------------------------------*/ +u8 get_box_power_lvl() +{ + u16 max, min, power; + u8 i; + + power = get_vbat_voltage(); + + if (power <= POWER_BOOT_LVL) { + return 0; + } + if (power >= POWER_TOP_LVL) { + return 100; + } + + for (i = 0; i < POWER_LVL_MAX; i++) { + if (power < voltage_table[1][i]) { + break; + } + } + min = voltage_table[1][i - 1]; + max = voltage_table[1][i]; + return ((u8)(((power - min) * 10 / (max - min)) + voltage_table[0][i - 1])); +} + +//通信的时候不能进入低功耗 +static volatile u8 is_comm_active = 0; +static u8 comm_idle_query(void) +{ + return (!is_comm_active); +} +REGISTER_LP_TARGET(comm_lp_target) = { + .name = "chgbox_comm", + .is_idle = comm_idle_query, +}; + +/*------------------------------------------------------------------------------------*/ +/**@brief 进入发送数据关处理 + @param 无 + @return 无 + @note 通信前要设置相关接口 +*/ +/*------------------------------------------------------------------------------------*/ +void enter_hook(void) +{ + //进入发送数据前,先关闭升压输出 + os_mutex_pend(&power_mutex, 0); + if (sys_info.charge) { + chargeIc_pwr_ctrl(0); + } + chargebox_api_open_port(EAR_L); + chargebox_api_open_port(EAR_R); + is_comm_active = 1; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 发送数据后恢复处理 + @param 无 + @return 无 + @note 根据状态恢复通信口 +*/ +/*------------------------------------------------------------------------------------*/ +void exit_hook(void) +{ + //退出发送数据后,是否需要打开升压输出 + if (sys_info.charge && (sys_info.temperature_limit == 0)) { + chargebox_check_output_short(); + chargebox_api_shutdown_port(EAR_L); + chargebox_api_shutdown_port(EAR_R); + if (sys_info.current_limit == 0) { + chargeIc_pwr_ctrl(1); + } + } else { + chargebox_api_close_port(EAR_L); + chargebox_api_close_port(EAR_R); + } + is_comm_active = 0; + os_mutex_post(&power_mutex); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 发消息到通信处理线程 + @param msg:待发送消息 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +void app_chargebox_send_mag(int msg) +{ + //有数据需要发送,自动关机计时器复位 + sys_info.life_cnt = 0; + os_taskq_post_msg(CHGBOX_THR_NAME, 1, msg); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓事件发送函数 + @param event:待发送事件 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +void app_chargebox_event_to_user(u8 event) +{ + struct sys_event e; + e.type = SYS_DEVICE_EVENT; + e.arg = (void *)DEVICE_EVENT_FROM_CHARGEBOX; + e.u.dev.event = event; + sys_event_notify(&e); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 耳机在线检测 + @param ret_l:左耳命令回应标志 + ret_r:右耳命令回应标志 + @return 无 + @note 检测并发相应的出入仓事件 +*/ +/*------------------------------------------------------------------------------------*/ +void app_chargebox_api_check_online(bool ret_l, bool ret_r) +{ + if (ret_l == TRUE) { + if (ear_info.online[EAR_L] == 0) { + //发事件,耳机入舱 + app_chargebox_event_to_user(CHGBOX_EVENT_EAR_L_ONLINE); + } + ear_info.online[EAR_L] = TCFG_EAR_OFFLINE_MAX; + } else { + if (ear_info.online[EAR_L]) { + ear_info.online[EAR_L]--; + if (ear_info.online[EAR_L] == 0) { + ear_info.power[EAR_L] = 0xff; + //发事件,耳机离舱 + app_chargebox_event_to_user(CHGBOX_EVENT_EAR_L_OFFLINE); + } + } + } + if (ret_r == TRUE) { + if (ear_info.online[EAR_R] == 0) { + //发事件,耳机入舱 + app_chargebox_event_to_user(CHGBOX_EVENT_EAR_R_ONLINE); + } + ear_info.online[EAR_R] = TCFG_EAR_OFFLINE_MAX; + } else { + if (ear_info.online[EAR_R]) { + ear_info.online[EAR_R]--; + if (ear_info.online[EAR_R] == 0) { + ear_info.power[EAR_R] = 0xff; + //发事件,耳机离舱 + app_chargebox_event_to_user(CHGBOX_EVENT_EAR_R_OFFLINE); + } + } + } + + if ((ear_info.online[EAR_L] == 0) && (ear_info.online[EAR_R] == 0)) { + chargebox_api_reset(); + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 发送 耳机关机 指令 + @param 无 + @return TRUE:发送成功 FALSE:发送失败 + @note +*/ +/*------------------------------------------------------------------------------------*/ +u8 app_chargebox_api_send_shutdown(void) +{ + u8 ret0, ret1; + enter_hook(); + ret0 = chargebox_send_shut_down(EAR_L); + ret1 = chargebox_send_shut_down(EAR_R); + exit_hook(); + if ((ret0 == TRUE) && (ret1 == TRUE)) { + log_debug("send shutdown ok!\n"); + return TRUE; + } else { + log_error("shut down, L:%d,R:%d\n", ret0, ret1); + } + return FALSE; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 发送合盖指令 + @param 无 + @return 无 + @note 发指令并检测在线 +*/ +/*------------------------------------------------------------------------------------*/ +u8 app_chargebox_api_send_close_cid(void) +{ + u8 online_cnt = 0;; + u8 ret0, ret1; + if (ear_info.online[EAR_L]) { + online_cnt += 1; + } + if (ear_info.online[EAR_R]) { + online_cnt += 1; + } + enter_hook(); + ret0 = chargebox_send_close_cid(EAR_L, online_cnt); + ret1 = chargebox_send_close_cid(EAR_R, online_cnt); + exit_hook(); + app_chargebox_api_check_online(ret0, ret1); + if ((ret0 == TRUE) && (ret1 == TRUE)) { + log_debug("send close CID ok\n"); + return TRUE; + } else { + log_error("LID close, L:%d,R:%d\n", ret0, ret1); + } + return FALSE; +} + +//存放左、右、公共地址 +static u8 adv_addr_tmp_buf[3][6]; +/*------------------------------------------------------------------------------------*/ +/**@brief 记录左/右耳机地址 + @param lr:1--左耳机 0--右耳机 + inbuf:输入地址的buf指针 + @return 无 + @note 记录地址到对应的buf +*/ +/*------------------------------------------------------------------------------------*/ +void get_lr_adr_cb(u8 lr, u8 *inbuf) +{ + if (lr) { + memcpy(&adv_addr_tmp_buf[1][0], inbuf, 6); + } else { + memcpy(&adv_addr_tmp_buf[0][0], inbuf, 6); + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 修改广播地址回调 + @param + @return 无 + @note 修改广播地址,并把广播地址更新到对应的buf +*/ +/*------------------------------------------------------------------------------------*/ +void exchange_addr_succ_cb(void) +{ + u8 i; + for (i = 0; i < 6; i++) { + adv_addr_tmp_buf[2][i] = adv_addr_tmp_buf[0][i] + adv_addr_tmp_buf[1][i]; + } + sys_info.chg_addr_ok = 1; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 获取广播地址 + @param + @return NULL:无广播地址 其他:返回数组地址 + @note +*/ +/*------------------------------------------------------------------------------------*/ +u8 *get_chargebox_adv_addr(void) +{ + if (sys_info.chg_addr_ok) { + return &adv_addr_tmp_buf[2][0]; + } else { + return NULL; + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 从vm读取广播地址 + @param 无 + @return TRUE:读取成功 0:读取不到地址 + @note 读取成功就记录在对应的数组中 +*/ +/*------------------------------------------------------------------------------------*/ +u8 chgbox_addr_read_from_vm(void) +{ + if (6 == syscfg_read(CFG_CHGBOX_ADDR, &adv_addr_tmp_buf[2][0], 6)) { + sys_info.chg_addr_ok = 1; + log_info("Read adv addr OK:"); + put_buf(&adv_addr_tmp_buf[2][0], 6); + return TRUE; + } else { + sys_info.chg_addr_ok = 0; + log_error("Read adv addr error\n"); + return FALSE; + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓获取两耳机地址扫描 + @param 无 + @return 1:无操作 0:配对中 + @note 没有检测到广播地址(chg_addr_ok==0)做配对扫描,获取广播地址(左右耳在线且开盖) +*/ +/*------------------------------------------------------------------------------------*/ +u8 chgbox_addr_save_to_vm(void) +{ + if (6 == syscfg_write(CFG_CHGBOX_ADDR, &adv_addr_tmp_buf[2][0], 6)) { + log_info("Write adv addr OK!\n"); + return TRUE; + } else { + log_error("Write adv addr error!\n"); + return FALSE; + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓获取两耳机地址扫描 + @param 无 + @return 1:无操作 0:配对中 + @note 没有检测到广播地址(chg_addr_ok==0)做配对扫描,获取广播地址(左右耳在线且开盖) +*/ +/*------------------------------------------------------------------------------------*/ +u8 chgbox_adv_addr_scan(void) +{ + //注意:部分耳机要收到open_power指令后才跑蓝牙流程,才能拿到地址 + static u8 caa_cnt = 0; + if (!sys_info.chg_addr_ok) { + if (ear_info.online[EAR_L] && ear_info.online[EAR_R] && sys_info.chgbox_status == CHG_STATUS_COMM) { + caa_cnt++; + if (caa_cnt < 8) { + //0~4是直接返回1,不做操作,留给外面的200Ms操作发open_power指令 + if (caa_cnt == 5) { //交换地址(配对) + log_debug("ss-0\n"); + app_chargebox_send_mag(CHGBOX_MSG_SEND_PAIR); + } + if (caa_cnt > 4) { + log_debug("ss-1\n"); + return 0;//发配对指令后不发其他命令,避免干扰 + } + } else { + caa_cnt = 0; //如果拿不到地址(chg_addr_ok==0),清0循环 + } + } + } + log_debug("ss-2\n"); + return 1; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓交换地址app + @param 无 + @return 交换地址是否成功 + @note 如果左右耳机在线,则交换地址,若交换成功就记录下地址 +*/ +/*------------------------------------------------------------------------------------*/ +u8 app_chargebox_api_exchange_addr(void) +{ + u8 ret = FALSE; + if (ear_info.online[EAR_L] && ear_info.online[EAR_R]) { + enter_hook(); + ret = chargebox_exchange_addr(get_lr_adr_cb, exchange_addr_succ_cb); + exit_hook(); + } + + if (ret) { + //交换地址成功后记录地址 + chgbox_addr_save_to_vm(); + } + return ret; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 私有命令例子 + * @param 无 + * @return 无 + * @note 1、自定义命令必须在0xC0和0xFE之间 + * 2、发送长度必须小于32字节 + * 3、读回来的数据在lr_buf 长度在lr_len + */ +/*------------------------------------------------------------------------------------*/ +void app_chargebox_api_send_cmd_demo(void) +{ + extern u8 lr_buf[2][32]; + extern u8 lr_len[2]; + u8 buf[3]; + buf[0] = CMD_USER; + buf[1] = 0x12; + buf[2] = 0x34; + enter_hook(); + if (chargebox_api_write_read(EAR_L, buf, 3, 4) == TRUE) { + //耳机有回复数据 + log_dump(lr_buf[EAR_L], lr_len[EAR_L]); + } + if (chargebox_api_write_read(EAR_R, buf, 3, 4) == TRUE) { + //耳机有回复数据 + log_dump(lr_buf[EAR_R], lr_len[EAR_R]); + } + exit_hook(); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓发送电量命令获取电量 + @param flag:1 合盖 0 开盖 + @return 无 + @note 发送仓电量、充电态、A耳机的电量 给B耳机,获取B耳机的电量,根据回应判断B是否在线 (两个耳机都进行) +*/ +/*------------------------------------------------------------------------------------*/ +void app_chargebox_api_send_power(u8 flag) +{ + u8 power; + u8 ret0, ret1, is_charge = 0; + power = get_box_power_lvl();//获取仓的电量 + if (sys_info.status[USB_DET] == STATUS_ONLINE) { + is_charge = 1; + } + enter_hook(); + if (flag == 0) { + ret0 = chargebox_send_power_open(EAR_L, power, is_charge, ear_info.power[EAR_R]); + ret1 = chargebox_send_power_open(EAR_R, power, is_charge, ear_info.power[EAR_L]); + } else { + ret0 = chargebox_send_power_close(EAR_L, power, is_charge, ear_info.power[EAR_R]); + ret1 = chargebox_send_power_close(EAR_R, power, is_charge, ear_info.power[EAR_L]); + } + exit_hook(); + app_chargebox_api_check_online(ret0, ret1); + if (ret0 == TRUE) { + ear_info.power[EAR_L] = chargebox_get_power(EAR_L); + log_info("Ear_L:%d_%d", ear_info.power[EAR_L]&BIT(7) ? 1 : 0, ear_info.power[EAR_L] & (~BIT(7))); + } else { + /* log_error("Can't got L\n"); */ + } + if (ret1 == TRUE) { + ear_info.power[EAR_R] = chargebox_get_power(EAR_R); + log_info("Ear_R:%d_%d", ear_info.power[EAR_R]&BIT(7) ? 1 : 0, ear_info.power[EAR_R] & (~BIT(7))); + } else { + /* log_error("Can't got R\n"); */ + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓通信线程 + @param priv:扩展参数 + @return 无 + @note 该线程负责给左右耳发送数据 +*/ +/*------------------------------------------------------------------------------------*/ +void app_chargebox_task_handler(void *priv) +{ + int msg[32]; + log_info("data thread running! \n"); + + while (1) { + if (os_task_pend("taskq", msg, ARRAY_SIZE(msg)) != OS_TASKQ) { + continue; + } + switch (msg[1]) { + case CHGBOX_MSG_SEND_POWER_OPEN: + app_chargebox_api_send_power(0); + break; + case CHGBOX_MSG_SEND_POWER_CLOSE: + app_chargebox_api_send_power(1); + break; + case CHGBOX_MSG_SEND_CLOSE_LID: + app_chargebox_api_send_close_cid(); + break; + case CHGBOX_MSG_SEND_SHUTDOWN: + app_chargebox_api_send_shutdown(); + break; + case CHGBOX_MSG_SEND_PAIR: + log_info("CHANGE ear ADDR\n"); + if (app_chargebox_api_exchange_addr() == TRUE) { + sys_info.pair_succ = 1; + } else { + log_error("pair_fail\n"); + } + break; + default: + log_info("default msg: %d\n", msg[1]); + break; + } + } +} + +CHARGEBOX_PLATFORM_DATA_BEGIN(chargebox_data) +.L_port = TCFG_CHARGEBOX_L_PORT, + .R_port = TCFG_CHARGEBOX_R_PORT, + CHARGEBOX_PLATFORM_DATA_END() + + /*------------------------------------------------------------------------------------*/ + /**@brief 充电仓提前初始化内容 + @param priv:扩展参数 + @return 无 + @note + */ + /*------------------------------------------------------------------------------------*/ + void app_chargebox_timer_handle(void *priv) +{ + static u8 ms200_cnt = 0; + static u8 ms500_cnt = 0; + + ms200_cnt++; + if (ms200_cnt >= 2) { + ms200_cnt = 0; + app_chargebox_event_to_user(CHGBOX_EVENT_200MS); + } + ms500_cnt++; + if (ms500_cnt >= 5) { + ms500_cnt = 0; + app_chargebox_event_to_user(CHGBOX_EVENT_500MS); + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓提前初始化内容 + @param 无 + @return 无 + @note 读取广播地址、初始化模块、创建通信线程、注册相关函数到timer +*/ +/*------------------------------------------------------------------------------------*/ +int chargebox_advanced_init(void) +{ + chgbox_addr_read_from_vm(); + chargebox_api_init(&chargebox_data); + task_create(app_chargebox_task_handler, NULL, CHGBOX_THR_NAME); + os_mutex_create(&power_mutex); + sys_timer_add(NULL, app_chargebox_timer_handle, 100);//推事件处理 + return 0; +} + +__initcall(chargebox_advanced_init); + +#endif diff --git a/apps/common/charge_box/chgbox_box.h b/apps/common/charge_box/chgbox_box.h new file mode 100644 index 0000000..0bec25f --- /dev/null +++ b/apps/common/charge_box/chgbox_box.h @@ -0,0 +1,78 @@ +#ifndef _CHGBOX_BOX_H_ +#define _CHGBOX_BOX_H_ + +#include "typedef.h" +#include "system/event.h" +#include "device/chargebox.h" + +enum { + CHGBOX_MSG_SEND_POWER_OPEN, + CHGBOX_MSG_SEND_POWER_CLOSE, + CHGBOX_MSG_SEND_CLOSE_LID, + CHGBOX_MSG_SEND_SHUTDOWN, + CHGBOX_MSG_SEND_PAIR, +}; + +enum { + CHGBOX_EVENT_200MS, + CHGBOX_EVENT_500MS, + CHGBOX_EVENT_USB_IN, + CHGBOX_EVENT_USB_OUT, + CHGBOX_EVENT_OPEN_LID, + CHGBOX_EVENT_CLOSE_LID, + CHGBOX_EVENT_EAR_L_ONLINE, + CHGBOX_EVENT_EAR_L_OFFLINE, + CHGBOX_EVENT_EAR_R_ONLINE, + CHGBOX_EVENT_EAR_R_OFFLINE, + CHGBOX_EVENT_ENTER_LOWPOWER, + CHGBOX_EVENT_EXIT_LOWPOWER, + CHGBOX_EVENT_EAR_FULL, + CHGBOX_EVENT_LOCAL_FULL, + CHGBOX_EVENT_NEED_SHUTDOWN, + CHGBOX_EVENT_WL_DATA_OVER, + CHGBOX_EVENT_WIRELESS_ONLINE, + CHGBOX_EVENT_WIRELESS_OFFLINE, + CHGBOX_EVENT_ENTER_CURRENT_PROTECT, + CHGBOX_EVENT_EXIT_CURRENT_PROTECT, + CHGBOX_EVENT_ENTER_TEMP_PROTECT, + CHGBOX_EVENT_EXIT_TEMP_PROTECT, + CHGBOX_EVENT_HANDSHAKE_OK, +}; + +#if(TCFG_CHARGE_BOX_ENABLE) +extern void chargebox_init(const struct chargebox_platform_data *data); +extern void chargebox_open(u8 l_r, u8 mode); +extern void chargebox_close(u8 l_r); +extern u8 chargebox_write(u8 l_r, u8 *data, u8 len); +extern void chargebox_set_baud(u8 l_r, u32 baudrate); + +#define CHARGEBOX_PLATFORM_DATA_BEGIN(data)\ + static const struct chargebox_platform_data data = { + +#define CHARGEBOX_PLATFORM_DATA_END()\ + .baudrate = 9600,\ + .init = chargebox_init,\ + .open = chargebox_open,\ + .close = chargebox_close,\ + .write = chargebox_write,\ + .set_baud = chargebox_set_baud,\ + }; +#else +#define CHARGEBOX_PLATFORM_DATA_BEGIN(data)\ + static const struct chargebox_platform_data data = { + +#define CHARGEBOX_PLATFORM_DATA_END()\ + .baudrate = 9600,\ + .init = NULL,\ + .open = NULL,\ + .close = NULL,\ + .write = NULL,\ + .set_baud = NULL,\ + }; +#endif + +extern void app_chargebox_send_mag(int msg); +extern void app_chargebox_event_to_user(u8 event); +extern u8 chgbox_adv_addr_scan(void); +#endif //_APP_CHARGEBOX_H_ + diff --git a/apps/common/charge_box/chgbox_ctrl.c b/apps/common/charge_box/chgbox_ctrl.c new file mode 100644 index 0000000..a5f2027 --- /dev/null +++ b/apps/common/charge_box/chgbox_ctrl.c @@ -0,0 +1,1216 @@ +#include "system/includes.h" +#include "app_config.h" +#include "app_task.h" +#include "chargeIc_manage.h" +#include "chgbox_ctrl.h" +#include "chgbox_box.h" +#include "chgbox_det.h" +#include "chgbox_wireless.h" +#include "key_event_deal.h" +#include "device/chargebox.h" +#include "chgbox_ui.h" +#include "chgbox_handshake.h" +#include "asm/pwm_led.h" +#include "le_smartbox_module.h" + +#if(TCFG_CHARGE_BOX_ENABLE) + +#define LOG_TAG_CONST APP_CHGBOX +#define LOG_TAG "[CHG_CTRL]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +//强制给耳机充电的时间,为0则不需要强制充电 +#define CHGBOX_FORCE_CHARGE_TIMES 240 //耳机电池不带保护建议设置2min + +//蓝牙开启后多久自动关闭 +#define CHGBOX_BT_AUTO_OFF_TIMES 360 //3min未检测到升级就关闭蓝牙 + +//耳机满电检测次数,满电电压 +#define CHG_EAR_FULL_DET_CNT 6 //注意调用位置,再计算总时间 +#define CHG_EAR_FULL_DET_LEVEL 100 //电压值 +#define TEMP_PROTECT_TIMEOUT 300000 //温度保护超时未恢复关机时间 + +void chargebox_set_newstatus(u8 newstatus); + +SYS_INFO sys_info; +EAR_INFO ear_info; +static int temp_protect_timer; +static u32 bt_auto_off_cnt; +static int auto_shutdown_timer = 0;//timer 句柄 +extern void chgbox_enter_soft_power_off(void); +extern void usb_key_check_entry(u32 timeout); +extern u16 get_curr_channel_state(); +extern OS_MUTEX power_mutex; +/*------------------------------------------------------------------------------------*/ +/**@brief 自动关机计数 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +static void sys_auto_shutdown_deal(void *priv) +{ +#if TCFG_APP_BT_EN + if (bt_auto_off_cnt) { + return; + } +#endif + sys_info.life_cnt++; + if (sys_info.life_cnt > TCFG_CHARGGBOX_AUTO_SHUT_DOWN_TIME) { + log_info("charegebox enter soft poweroff\n"); + chgbox_enter_soft_power_off(); + } +} + +void sys_auto_shutdown_reset(void) +{ + sys_info.life_cnt = 0; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 自动关机使能 + @param 无 + @return 无 + @note 将自动关机处理函数注册到timer里 +*/ +/*------------------------------------------------------------------------------------*/ +void sys_auto_shutdown_enable(void) +{ + if (!auto_shutdown_timer) { + sys_info.life_cnt = 0; + auto_shutdown_timer = sys_timer_add(NULL, sys_auto_shutdown_deal, 1000); + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 自动关机关闭 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +void sys_auto_shutdown_disable(void) +{ + if (auto_shutdown_timer) { + sys_timer_del(auto_shutdown_timer); + auto_shutdown_timer = 0; + sys_info.life_cnt = 0; + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 超时时关闭自动升压 + @param 无 + @return 无 + @note 若USB在线或者无线充在线则延长超时时间 +*/ +/*------------------------------------------------------------------------------------*/ +static void chargebox_temp_protect_timeout(void *priv) +{ + temp_protect_timer = 0; + if (sys_info.status[USB_DET] == STATUS_ONLINE || sys_info.status[WIRELESS_DET] == STATUS_ONLINE) { + temp_protect_timer = sys_timeout_add(NULL, chargebox_temp_protect_timeout, TEMP_PROTECT_TIMEOUT); + } else { + chargeIc_boost_ctrl(0); + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 通过IO状态判断输出是否短路 + @param 无 + @return 0:没有发送消息, 1:初次触发短路/过流保护发送消息 + @note 在开启升压输出前调用 +*/ +/*------------------------------------------------------------------------------------*/ +u8 chargebox_check_output_short(void) +{ + if (sys_info.current_limit) { + return 0; + } + gpio_set_pull_up(TCFG_CHARGEBOX_L_PORT, 1); + gpio_set_pull_up(TCFG_CHARGEBOX_R_PORT, 1); + gpio_direction_input(TCFG_CHARGEBOX_L_PORT); + gpio_direction_input(TCFG_CHARGEBOX_R_PORT); + if ((gpio_read(TCFG_CHARGEBOX_L_PORT) == 0) || (gpio_read(TCFG_CHARGEBOX_R_PORT) == 0)) { + log_error("gpio status err, mabe short, L:%d, R:%d!\n", gpio_read(TCFG_CHARGEBOX_L_PORT), gpio_read(TCFG_CHARGEBOX_R_PORT)); + sys_info.current_limit = 1; + app_chargebox_event_to_user(CHGBOX_EVENT_ENTER_CURRENT_PROTECT); + return 1; + } + return 0; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电过程中短路触发的保护唤醒时调用 + @param 无 + @return 无 + @note 在唤醒中断里面调用 +*/ +/*------------------------------------------------------------------------------------*/ +void chargebox_set_output_short(void) +{ + if (sys_info.current_limit) { + return; + } + chargeIc_boost_ctrl(0);//关闭升压 + chargeIc_pwr_ctrl(0);//关闭充电开关 + sys_info.current_limit = 1; + app_chargebox_event_to_user(CHGBOX_EVENT_ENTER_CURRENT_PROTECT); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电舱公共消息处理接口 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +static int chargebox_common_event_handler(struct chargebox_event *e) +{ + switch (e->event) { +#if (TCFG_WIRELESS_ENABLE) + case CHGBOX_EVENT_WL_DATA_OVER: + wireless_data_over_run(); + break; + case CHGBOX_EVENT_WIRELESS_ONLINE: + log_info("WL_ONLINE_1\n"); + wireless_api_open(); + sys_auto_shutdown_reset(); + break; + case CHGBOX_EVENT_WIRELESS_OFFLINE: + log_info("WL_OFF_1\n"); + wireless_api_close(); + sys_auto_shutdown_reset(); + break; +#endif +#if TCFG_TEMPERATURE_ENABLE + case CHGBOX_EVENT_ENTER_TEMP_PROTECT: + //关闭给耳机充电 + if (sys_info.charge) { + chargeIc_pwr_ctrl(0); + chargebox_api_open_port(EAR_L); + chargebox_api_open_port(EAR_R); + if (temp_protect_timer) { + sys_timer_del(temp_protect_timer); + } + temp_protect_timer = sys_timeout_add(NULL, chargebox_temp_protect_timeout, TEMP_PROTECT_TIMEOUT); + } + //关闭给电池充电 + if (sys_info.status[USB_DET] == STATUS_ONLINE) { + chargebox_charge_close(); + } + break; + case CHGBOX_EVENT_EXIT_TEMP_PROTECT: + //恢复给耳机充电 + if (sys_info.charge) { + os_mutex_pend(&power_mutex, 0); + u8 msg_flag = chargebox_check_output_short(); + if (sys_info.current_limit) { + chargeIc_boost_ctrl(1); + chargebox_api_shutdown_port(EAR_L); + chargebox_api_shutdown_port(EAR_R); + chargeIc_pwr_ctrl(1); + } else if (msg_flag == 0) { + sys_info.force_charge = 0; + sys_info.earfull = 1; + app_chargebox_event_to_user(CHGBOX_EVENT_EAR_FULL);//让进入休眠 + } + os_mutex_post(&power_mutex); + if (temp_protect_timer) { + sys_timer_del(temp_protect_timer); + temp_protect_timer = 0; + } + } + //恢复给电池充电 + if (sys_info.status[USB_DET] == STATUS_ONLINE) { + chargebox_charge_start(); + } + break; +#endif + case CHGBOX_EVENT_USB_IN: + if (sys_info.current_limit) { + sys_info.current_limit = 0; + app_chargebox_event_to_user(CHGBOX_EVENT_EXIT_CURRENT_PROTECT); + } + //判断当前无线充是否在线,在线不响应 + if ((sys_info.status[WIRELESS_DET] == STATUS_OFFLINE) && (app_get_curr_task() != APP_PC_TASK)) { +#if TCFG_USB_KEY_UPDATE_ENABLE + //先检测是否USB升级工具插入 + usb_key_check_entry(3); +#endif +#if TCFG_HANDSHAKE_ENABLE + chgbox_handshake_run_app(); + chgbox_handshake_set_repeat(2);//多握手几次 +#else + app_chargebox_event_to_user(CHGBOX_EVENT_HANDSHAKE_OK); +#endif + } else { + app_chargebox_event_to_user(CHGBOX_EVENT_HANDSHAKE_OK); + } + break; + case CHGBOX_EVENT_USB_OUT: + chargebox_charge_close(); +#if TCFG_HANDSHAKE_ENABLE + chgbox_handshake_set_repeat(0); +#endif +#if TCFG_APP_PC_EN + if (app_get_curr_task() != APP_IDLE_TASK) { + app_task_switch_to(APP_IDLE_TASK); + } +#endif + break; + case CHGBOX_EVENT_HANDSHAKE_OK: + if ((sys_info.status[USB_DET] == STATUS_ONLINE) && (sys_info.temperature_limit == 0)) { + chargebox_charge_start(); + } +#if TCFG_APP_PC_EN + if (app_get_curr_task() != APP_PC_TASK) { + app_task_switch_to(APP_PC_TASK); + } +#endif + break; + } + return true; +} + +/******************************************************************************/ +/*************************合盖充电模式相关处理**********************************/ +/******************************************************************************/ +static u8 ear_power_check_time;//耳机电量检测次数 + +/*------------------------------------------------------------------------------------*/ +/**@brief 合盖充电模式 合盖处理 + @param 无 + @return 无 + @note 先发合盖命令给耳机(里面会有检测耳机在线的检测),再打开升压进行充电 +*/ +/*------------------------------------------------------------------------------------*/ +static void charge_app_lid_close_deal(void) +{ + if (sys_info.lid_cnt & BIT(7)) { + if (sys_info.lid_cnt & (~BIT(7))) { + sys_info.lid_cnt--; + app_chargebox_send_mag(CHGBOX_MSG_SEND_CLOSE_LID); + } else { + sys_info.lid_cnt = 0; + ear_power_check_time = 0; + u8 msg_flag = chargebox_check_output_short(); + if (sys_info.current_limit == 0) { + sys_info.charge = 1;//发完盒盖命令再开升压 + //先关闭IO,在打开开关输出5V + if (sys_info.temperature_limit == 0) { + os_mutex_pend(&power_mutex, 0); + chargeIc_boost_ctrl(1); + chargebox_api_shutdown_port(EAR_L); + chargebox_api_shutdown_port(EAR_R); + chargeIc_pwr_ctrl(1); + os_mutex_post(&power_mutex); + } else { + //过温保护,盒盖再推一次消息 + app_chargebox_event_to_user(CHGBOX_EVENT_ENTER_TEMP_PROTECT); + } + //如果两只耳机都能检测在仓,说明耳机都有电,不需要强制充电 + if (ear_info.online[EAR_L] && ear_info.online[EAR_R]) { + sys_info.force_charge = 0; + } + } else if (msg_flag == 0) { + //电流异常进入耳机关机流程 + sys_info.force_charge = 0; + sys_info.earfull = 1; + app_chargebox_event_to_user(CHGBOX_EVENT_EAR_FULL);//让进入休眠 + } + } + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 合盖充电模式 让耳机进入关机 处理 + @param 无 + @return 无 + @note 先发命令让耳机关机,再关闭相关IO +*/ +/*------------------------------------------------------------------------------------*/ +static void charge_app_shut_down_deal(void) +{ + if (sys_info.shut_cnt & BIT(7)) { + if (sys_info.shut_cnt & (~BIT(7))) { + sys_info.shut_cnt--; + app_chargebox_send_mag(CHGBOX_MSG_SEND_SHUTDOWN); + } else { + //关机命令后,电源线断电 + sys_info.shut_cnt = 0; + chargebox_api_shutdown_port(EAR_L); + chargebox_api_shutdown_port(EAR_R); + } + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 耳机电量满检测 + @param 无 + @return 无 + @note 检测耳机电量,若满则发满电事件 +*/ +/*------------------------------------------------------------------------------------*/ +void app_chargebox_ear_full_det(void *priv) +{ + if (sys_info.chgbox_status != CHG_STATUS_CHARGE) { + return; + } + + /* log_info("L:%d,F:%d,C:%d\n",ear_info.online[EAR_L],sys_info.ear_l_full,ear_info.full_cnt[EAR_L]); */ + if (ear_info.online[EAR_L]) { //在线 + if ((ear_info.power[EAR_L] & 0x7f) == CHG_EAR_FULL_DET_LEVEL && sys_info.ear_l_full == 0) { //power的最高bit为标志位 + ear_info.full_cnt[EAR_L]++; + if (ear_info.full_cnt[EAR_L] >= CHG_EAR_FULL_DET_CNT) { + sys_info.ear_l_full = 1; //充满标志置位 + } + } else { + ear_info.full_cnt[EAR_L] = 0; + } + } else { + ear_info.full_cnt[EAR_L] = 0; //左计数清0 + sys_info.ear_l_full = 0; //左充满标志清0 + } + + if (ear_info.online[EAR_R]) { //在线 + if ((ear_info.power[EAR_R] & 0x7f) == CHG_EAR_FULL_DET_LEVEL && sys_info.ear_r_full == 0) { //power的最高bit为标志位 + ear_info.full_cnt[EAR_R]++; + if (ear_info.full_cnt[EAR_R] >= CHG_EAR_FULL_DET_CNT) { + sys_info.ear_r_full = 1; //充满标志置位 + } + } else { + ear_info.full_cnt[EAR_R] = 0; + } + } else { + ear_info.full_cnt[EAR_R] = 0; //右计数清0 + sys_info.ear_r_full = 0; //右充满标志清0 + } + + if (sys_info.earfull == 0) { + //同时在线两个在线都满了、单个在线电满了 + if ((sys_info.ear_r_full && sys_info.ear_l_full) + || (sys_info.ear_l_full && ear_info.online[EAR_R] == 0) + || (sys_info.ear_r_full && ear_info.online[EAR_L] == 0)) { + if (sys_info.force_charge == 0) { //强制充电已过 + sys_info.earfull = 1; + log_info("ear online full\n"); + app_chargebox_event_to_user(CHGBOX_EVENT_EAR_FULL); + } + } + } else { //没满但在线 + if ((!sys_info.ear_l_full && ear_info.online[EAR_L]) + || (!sys_info.ear_r_full && ear_info.online[EAR_R])) { + sys_info.earfull = 0;//总标志清0 + } + } + + ///已过强制充电时间,但两都不在线,走full,里面会判断仓是否充电 + if (ear_info.online[EAR_L] == 0 && ear_info.online[EAR_R] == 0 && sys_info.force_charge == 0) { + log_info("no ear and force charge end\n"); + sys_info.earfull = 1; + app_chargebox_event_to_user(CHGBOX_EVENT_EAR_FULL); + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 获取tws电量 + @param 无 + @return 无 + @note 检测电量,发送命令获取tws电量 +*/ +/*------------------------------------------------------------------------------------*/ +static void charge_app_send_power(void) +{ + if (sys_info.shut_cnt || sys_info.lid_cnt || sys_info.earfull || sys_info.force_charge) { + return; + } + ear_power_check_time++; + if (ear_power_check_time > 25) { //5s + ear_power_check_time = 0; + app_chargebox_send_mag(CHGBOX_MSG_SEND_POWER_CLOSE); + //发完命令后还要等对方回复,线程会切换,定时去查询 + sys_timeout_add(NULL, app_chargebox_ear_full_det, 200); + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 自动关机检测 + @param 无 + @return 无 + @note 根据条件判断是否使能自动关机 +*/ +/*------------------------------------------------------------------------------------*/ +static void charge_app_check_enable_auto_shutdown(void) +{ + //1、充电不在线时,判断耳机是否充满,充满则关机 + //2、充满关机使能后,USB在线时耳机和充电舱都充满则关机 +#if TCFG_WIRELESS_ENABLE + if ((sys_info.status[USB_DET] == STATUS_OFFLINE) && (sys_info.status[WIRELESS_DET] == STATUS_OFFLINE)) { +#else + if (sys_info.status[USB_DET] == STATUS_OFFLINE) { +#endif + if (sys_info.earfull) { + sys_auto_shutdown_enable(); + return; + } + } else { +#if TCFG_CHARGE_FULL_ENTER_SOFTOFF + if (sys_info.status[USB_DET] == STATUS_ONLINE) { + if (sys_info.localfull && sys_info.earfull) { + sys_auto_shutdown_enable(); + } + } +#endif + } +} + +#define LDO_NOT_SUCC_TIMES 20 //次数,注意时间尺度 +static u8 ldo_not_succ_cnt = 0; //LDO无法升压 计数 +/*------------------------------------------------------------------------------------*/ +/**@brief 合盖充电半秒处理 + @param 无 + @return 无 + @note 充电升压不成功处理、强制充电超时计数 +*/ +/*------------------------------------------------------------------------------------*/ +static void charge_deal_half_second(void) +{ + //没有接充电线,充电IC不升压,超时进入休眠 +#if TCFG_WIRELESS_ENABLE + if ((sys_info.status[USB_DET] == STATUS_OFFLINE) && (sys_info.status[WIRELESS_DET] == STATUS_OFFLINE)) { +#else + if (sys_info.status[USB_DET] == STATUS_OFFLINE) { +#endif + if (sys_info.status[LDO_DET] == STATUS_OFFLINE) { //无法升压 + if (ldo_not_succ_cnt < LDO_NOT_SUCC_TIMES) { + ldo_not_succ_cnt++; + if (ldo_not_succ_cnt == LDO_NOT_SUCC_TIMES) { + log_info("auto shutdown by ldo not succ\n"); + if (sys_info.force_charge || sys_info.temperature_limit) { + sys_info.force_charge = 0; + sys_info.earfull = 1; + //走这个分支,如果仓还在充电就等仓满再关 + app_chargebox_event_to_user(CHGBOX_EVENT_EAR_FULL);//进入休眠 + } else { + sys_auto_shutdown_enable(); + } + } + } + } else { + ldo_not_succ_cnt = 0; + } + } + + //强制充电超时计数(有可能是耳机不在线,有可能是耳机完全没电,先保持充电一段时间) + if (sys_info.force_charge) { + sys_info.force_charge--; + } + + if (ear_info.online[EAR_L] && ear_info.online[EAR_R]) { + sys_info.force_charge = 0; + } + +#if TCFG_APP_BT_EN + if (get_curr_channel_state()) { + bt_auto_off_cnt = CHGBOX_BT_AUTO_OFF_TIMES; + } else if (bt_auto_off_cnt) { + bt_auto_off_cnt--; + if (bt_auto_off_cnt == 0) { + app_task_switch_to(APP_IDLE_TASK); + } + } +#endif +} + +static int charge_chargebox_event_handler(struct chargebox_event *e) +{ + switch (e->event) { + case CHGBOX_EVENT_200MS: + charge_app_lid_close_deal(); + charge_app_send_power(); + charge_app_shut_down_deal(); + break; + case CHGBOX_EVENT_500MS: + charge_deal_half_second(); + break; +#if TCFG_WIRELESS_ENABLE + case CHGBOX_EVENT_WIRELESS_ONLINE: + sys_auto_shutdown_disable(); + break; + case CHGBOX_EVENT_WIRELESS_OFFLINE: + charge_app_check_enable_auto_shutdown(); + break; +#endif + case CHGBOX_EVENT_USB_IN: + log_info("USB_IN_1\n"); + chgbox_ui_update_status(UI_MODE_CHARGE, CHGBOX_UI_USB_IN); + sys_auto_shutdown_disable(); + if (sys_info.status[LID_DET] == STATUS_ONLINE) { + //开盖插入USB + chargebox_set_newstatus(CHG_STATUS_COMM); //设置新模式 + } + break; + case CHGBOX_EVENT_USB_OUT: + log_info("USB_OUT_1\n"); + chgbox_ui_update_status(UI_MODE_CHARGE, CHGBOX_UI_USB_OUT); + charge_app_check_enable_auto_shutdown(); + if (sys_info.status[LID_DET] == STATUS_ONLINE) { + //开盖拔出USB + chargebox_set_newstatus(CHG_STATUS_COMM); //设置新模式 + } + break; + case CHGBOX_EVENT_OPEN_LID: + log_info("OPEN_LID_1\n"); +#if SMART_BOX_EN + bt_ble_rcsp_adv_enable(); +#endif + chargebox_set_newstatus(CHG_STATUS_COMM); //设置新模式 + break; + case CHGBOX_EVENT_CLOSE_LID: + log_info("CLOSE_LID_1\n"); + //开盖超时进来的,可以不做任何操作 +#if SMART_BOX_EN + bt_ble_rcsp_adv_disable(); +#endif + break; + case CHGBOX_EVENT_EAR_L_ONLINE: + log_info("EAR_L_IN_1\n"); + chgbox_ui_update_status(UI_MODE_CHARGE, CHGBOX_UI_EAR_L_IN); + break; + case CHGBOX_EVENT_EAR_L_OFFLINE: + log_info("EAR_L_OUT_1\n"); + chgbox_ui_update_status(UI_MODE_CHARGE, CHGBOX_UI_EAR_L_OUT); + break; + case CHGBOX_EVENT_EAR_R_ONLINE: + log_info("EAR_R_IN_1\n"); + chgbox_ui_update_status(UI_MODE_CHARGE, CHGBOX_UI_EAR_R_IN); + break; + case CHGBOX_EVENT_EAR_R_OFFLINE: + log_info("EAR_R_OUT_1\n"); + chgbox_ui_update_status(UI_MODE_CHARGE, CHGBOX_UI_EAR_R_OUT); + break; + case CHGBOX_EVENT_ENTER_LOWPOWER: + case CHGBOX_EVENT_NEED_SHUTDOWN: + //关闭升压,进入低电模式 + chargebox_set_newstatus(CHG_STATUS_LOWPOWER); //设置新模式 + break; + case CHGBOX_EVENT_EAR_FULL: + //耳机充满后发送shutdown指令 + log_info("EAR_FULL_1\n"); + if (!sys_info.current_limit) { + chgbox_ui_update_status(UI_MODE_CHARGE, CHGBOX_UI_EAR_FULL); + } + //充满电时,先关闭输出再打开IO + chargeIc_pwr_ctrl(0); + chargebox_api_open_port(EAR_L); + chargebox_api_open_port(EAR_R); + chargeIc_boost_ctrl(0); + sys_info.shut_cnt = BIT(7) | TCFG_SEND_SHUT_DOWN_MAX; + sys_info.lid_cnt = 0; + sys_info.charge = 0;//此时充电结束 + charge_app_check_enable_auto_shutdown(); + break; + case CHGBOX_EVENT_LOCAL_FULL: + log_info("LOCAL_FULL_1\n"); + chgbox_ui_update_status(UI_MODE_CHARGE, CHGBOX_UI_LOCAL_FULL); + charge_app_check_enable_auto_shutdown(); + break; + case CHGBOX_EVENT_ENTER_CURRENT_PROTECT: + log_info("CHGBOX_EVENT_OVER_CURRENT"); + chargeIc_pwr_ctrl(0);//关闭充电开关 + chargeIc_boost_ctrl(0);//关闭升压 + sys_info.force_charge = 0; + sys_info.earfull = 1; + app_chargebox_event_to_user(CHGBOX_EVENT_EAR_FULL);//让进入休眠 + chgbox_ui_update_status(UI_MODE_CHARGE, CHGBOX_UI_OVER_CURRENT); + break; + case CHGBOX_EVENT_EXIT_CURRENT_PROTECT: + ear_power_check_time = 0; + sys_info.shut_cnt = 0; + sys_info.lid_cnt = BIT(7) | TCFG_SEND_CLOSE_LID_MAX; + sys_info.charge = 0;//先关闭,等合盖命令发完才打开升压 + sys_info.ear_l_full = 0; + sys_info.ear_r_full = 0; + sys_info.earfull = 0; + sys_info.force_charge = CHGBOX_FORCE_CHARGE_TIMES; + sys_auto_shutdown_disable(); + break; + } + return 0; +} + + + + + + + +/******************************************************************************/ +/*************************开盖通信模式相关处理**********************************/ +/******************************************************************************/ +#define KEY_PAIR_CNT 10 +#define COMM_LIFE_MAX (60*2)//一分钟超时 +static u8 goto_pair_cnt;//配对功能按键时间计数 +static u8 auto_exit_cnt;//退出开盖通信模式计数 + +/*------------------------------------------------------------------------------------*/ +/**@brief 配对状态检测处理 + @param 无 + @return 无 + @note 当 pair_status==2时,判断是否配对成功 +*/ +/*------------------------------------------------------------------------------------*/ +static void comm_pair_connecting(void) +{ + if (sys_info.pair_status == 2) { + if (sys_info.pair_succ) { + sys_info.pair_status = 0; + chgbox_ui_update_status(UI_MODE_COMM, CHGBOX_UI_PAIR_SUCC); + } else { + app_chargebox_send_mag(CHGBOX_MSG_SEND_PAIR); + } + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 开盖通信模式超时 + @param 无 + @return 无 + @note 开盖时间过长,切换模式 +*/ +/*------------------------------------------------------------------------------------*/ +static void comm_app_auto_exit(void) +{ + if (auto_exit_cnt++ > COMM_LIFE_MAX) { +#if SMART_BOX_EN + bt_ble_rcsp_adv_disable(); +#endif + if (sys_info.lowpower_flag) { + chargebox_set_newstatus(CHG_STATUS_LOWPOWER); //设置新模式 + } else { + chargebox_set_newstatus(CHG_STATUS_CHARGE); //设置新模式 + } + } +#if TCFG_APP_BT_EN + if (get_curr_channel_state()) { + bt_auto_off_cnt = CHGBOX_BT_AUTO_OFF_TIMES; + } else if (bt_auto_off_cnt) { + bt_auto_off_cnt--; + if (bt_auto_off_cnt == 0) { + app_task_switch_to(APP_IDLE_TASK); + } + } +#endif +} + +static int comm_chargebox_event_handler(struct chargebox_event *e) +{ + switch (e->event) { + case CHGBOX_EVENT_200MS: + if (chgbox_adv_addr_scan()) { + app_chargebox_send_mag(CHGBOX_MSG_SEND_POWER_OPEN); + } + break; + case CHGBOX_EVENT_500MS: + comm_pair_connecting(); + comm_app_auto_exit(); + break; + case CHGBOX_EVENT_USB_IN: + log_info("USB_IN_2\n"); + chgbox_ui_update_status(UI_MODE_COMM, CHGBOX_UI_USB_IN); + app_chargebox_send_mag(CHGBOX_MSG_SEND_POWER_OPEN); + auto_exit_cnt = 0; + break; + case CHGBOX_EVENT_USB_OUT: + log_info("USB_OUT_2\n"); + chgbox_ui_update_status(UI_MODE_COMM, CHGBOX_UI_USB_OUT); + app_chargebox_send_mag(CHGBOX_MSG_SEND_POWER_OPEN); + auto_exit_cnt = 0; + break; + case CHGBOX_EVENT_LOCAL_FULL: + log_info("LOCAL_FULL_2\n"); + chgbox_ui_update_status(UI_MODE_COMM, CHGBOX_UI_LOCAL_FULL); + break; + case CHGBOX_EVENT_CLOSE_LID: + log_info("CLOSE_LID_2\n"); +#if SMART_BOX_EN + bt_ble_rcsp_adv_disable(); +#endif + if (sys_info.lowpower_flag) { + chargebox_set_newstatus(CHG_STATUS_LOWPOWER); //设置新模式 + } else { + chargebox_set_newstatus(CHG_STATUS_CHARGE); //设置新模式 + } + break; + case CHGBOX_EVENT_NEED_SHUTDOWN: + chargebox_set_newstatus(CHG_STATUS_LOWPOWER); //设置新模式 + break; + case CHGBOX_EVENT_EAR_L_ONLINE: + log_info("EAR_L_IN_2\n"); + auto_exit_cnt = 0; + if (chgbox_get_ui_power_on() == 0) { + chgbox_ui_update_status(UI_MODE_COMM, CHGBOX_UI_EAR_L_IN); + } + break; + case CHGBOX_EVENT_EAR_L_OFFLINE: + log_info("EAR_L_OUT_2\n"); + auto_exit_cnt = 0; +#if SMART_BOX_EN + bt_ble_rcsp_adv_disable(); +#endif + chgbox_ui_update_status(UI_MODE_COMM, CHGBOX_UI_EAR_L_OUT); + break; + case CHGBOX_EVENT_EAR_R_ONLINE: + log_info("EAR_R_IN_2\n"); + auto_exit_cnt = 0; + if (chgbox_get_ui_power_on() == 0) { + chgbox_ui_update_status(UI_MODE_COMM, CHGBOX_UI_EAR_R_IN); + } + break; + case CHGBOX_EVENT_EAR_R_OFFLINE: + log_info("EAR_R_OUT_2\n"); + auto_exit_cnt = 0; +#if SMART_BOX_EN + bt_ble_rcsp_adv_disable(); +#endif + chgbox_ui_update_status(UI_MODE_COMM, CHGBOX_UI_EAR_R_OUT); + break; + } + return 0; +} + + +/******************************************************************************/ +/*************************低电模式处理*****************************************/ +/******************************************************************************/ +/*------------------------------------------------------------------------------------*/ +/**@brief 低电休眠计数 + @param 无 + @return 无 + @note 先发关机指令,再休眠 +*/ +/*------------------------------------------------------------------------------------*/ +static void lowpower_shut_down_deal(void) +{ + if (sys_info.shut_cnt & BIT(7)) { + if (sys_info.shut_cnt & (~BIT(7))) { + sys_info.shut_cnt--; + app_chargebox_send_mag(CHGBOX_MSG_SEND_SHUTDOWN); + } else { + //关机命令后,电源线断电 + sys_info.charge = 0; + sys_info.shut_cnt = 0; + chargebox_api_shutdown_port(EAR_L); + chargebox_api_shutdown_port(EAR_R); + } + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 低电合盖命令计数 + @param 无 + @return 无 + @note lid_cnt标志置位后先发合盖命令,再置位shut_cnt标志 +*/ +/*------------------------------------------------------------------------------------*/ +static void lowpower_lid_close_deal(void) +{ + if (sys_info.lid_cnt & BIT(7)) { + if (sys_info.lid_cnt & (~BIT(7))) { + sys_info.lid_cnt--; + app_chargebox_send_mag(CHGBOX_MSG_SEND_CLOSE_LID); + } else { + sys_info.lid_cnt = 0; + sys_info.shut_cnt = BIT(7) | TCFG_SEND_SHUT_DOWN_MAX; + } + } +} + +static int lowpower_chargebox_event_handler(struct chargebox_event *e) +{ + switch (e->event) { + case CHGBOX_EVENT_200MS: + lowpower_lid_close_deal(); + lowpower_shut_down_deal(); + break; + case CHGBOX_EVENT_500MS: + break; +#if TCFG_WIRELESS_ENABLE + case CHGBOX_EVENT_WIRELESS_ONLINE: + sys_auto_shutdown_disable(); + break; + case CHGBOX_EVENT_WIRELESS_OFFLINE: + sys_auto_shutdown_enable(); + break; +#endif + case CHGBOX_EVENT_USB_IN: + log_info("USB_IN_3\n"); + sys_auto_shutdown_disable(); + chgbox_ui_update_status(UI_MODE_LOWPOWER, CHGBOX_UI_USB_IN); + break; + case CHGBOX_EVENT_USB_OUT: + log_info("USB_OUT_3\n"); +#if TCFG_WIRELESS_ENABLE + if (sys_info.status[WIRELESS_DET] == STATUS_OFFLINE) +#endif + { + sys_auto_shutdown_enable(); + } + chgbox_ui_update_status(UI_MODE_LOWPOWER, CHGBOX_UI_USB_OUT); + break; + case CHGBOX_EVENT_OPEN_LID: + log_info("OPEN_LID_3\n"); + chgbox_ui_update_status(UI_MODE_LOWPOWER, CHGBOX_UI_OPEN_LID); +#if SMART_BOX_EN + bt_ble_rcsp_adv_enable(); +#endif + chargebox_set_newstatus(CHG_STATUS_COMM); //设置新模式 + break; + case CHGBOX_EVENT_CLOSE_LID: + log_info("CLOSE_LID_3\n"); + chgbox_ui_update_status(UI_MODE_LOWPOWER, CHGBOX_UI_CLOSE_LID); +#if SMART_BOX_EN + bt_ble_rcsp_adv_disable(); +#endif + break; + case CHGBOX_EVENT_NEED_SHUTDOWN: + if ((!sys_info.lid_cnt) && (sys_info.shut_cnt)) { + power_set_soft_poweroff(); + } + break; + case CHGBOX_EVENT_EXIT_LOWPOWER: + log_info("exit lower\n"); + if (sys_info.status[LID_DET] == STATUS_ONLINE) { + chargebox_set_newstatus(CHG_STATUS_COMM); //设置新模式 + } else { + chargebox_set_newstatus(CHG_STATUS_CHARGE); //设置新模式 + } + break; + } + return 0; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓事件处理 + @param event:传入的事件结构体,携带事件信息 + @return 无 + @note 分模式处理相关各种事件(相同事件在不同模式可能会有不同处理) +*/ +/*------------------------------------------------------------------------------------*/ +int charge_box_ctrl_event_handler(struct chargebox_event *chg_event) +{ + chargebox_common_event_handler(chg_event); + if (sys_info.chgbox_status == CHG_STATUS_CHARGE) { + charge_chargebox_event_handler(chg_event); + } else if (sys_info.chgbox_status == CHG_STATUS_COMM) { + comm_chargebox_event_handler(chg_event); + } else if (sys_info.chgbox_status == CHG_STATUS_LOWPOWER) { + lowpower_chargebox_event_handler(chg_event); + } + return 0; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓按键处理 + @param event:按键事件 + @return 无 + @note 分模式处理相关按键 +*/ +/*------------------------------------------------------------------------------------*/ +int charge_box_key_event_handler(u16 event) +{ + if (sys_info.chgbox_status == CHG_STATUS_CHARGE) { + sys_info.life_cnt = 0; + switch (event) { + case KEY_BOX_POWER_CLICK: + log_info("KEY_POWER_CLICK_chg\n"); + if (sys_info.status[LID_DET] == STATUS_ONLINE) { + //开盖拔出USB + chargebox_set_newstatus(CHG_STATUS_COMM); //设置新模式 + } else { + chgbox_ui_update_status(UI_MODE_CHARGE, CHGBOX_UI_KEY_CLICK); + } + break; + case KEY_BOX_POWER_FIVE: + log_info("KEY_POWER_FIVE_chg\n"); +#if TCFG_APP_BT_EN + if (app_get_curr_task() == APP_IDLE_TASK) { + bt_auto_off_cnt = CHGBOX_BT_AUTO_OFF_TIMES; + app_task_switch_to(APP_BT_TASK); + } +#endif + break; + default: + break; + } + } else if (sys_info.chgbox_status == CHG_STATUS_COMM) { + auto_exit_cnt = 0; + switch (event) { + case KEY_BOX_POWER_CLICK: + log_info("KEY_POWER_CLICK_comm\n"); + chgbox_ui_update_status(UI_MODE_COMM, CHGBOX_UI_KEY_CLICK); + break; + case KEY_BOX_POWER_LONG: + log_info("KEY_POWER_LONG\n"); + if (sys_info.pair_status == 0) { + sys_info.pair_status = 1; + goto_pair_cnt = 0; + chgbox_ui_update_status(UI_MODE_COMM, CHGBOX_UI_KEY_LONG); + } + break; + case KEY_BOX_POWER_HOLD: + /* log_info("KEY_POWER_HOLD\n"); */ + if (sys_info.pair_status == 1) { + goto_pair_cnt++; + if (goto_pair_cnt >= KEY_PAIR_CNT) { + sys_info.pair_status = 2; + sys_info.pair_succ = 0; + chgbox_ui_update_status(UI_MODE_COMM, CHGBOX_UI_PAIR_START); + } + } + break; + case KEY_BOX_POWER_UP: + log_info("KEY_POWER_UP\n"); + if (sys_info.pair_status != 2) { + sys_info.pair_status = 0; + chgbox_ui_update_status(UI_MODE_COMM, CHGBOX_UI_PAIR_STOP); + } + break; + case KEY_BOX_POWER_FIVE: + log_info("KEY_POWER_FIVE_comm\n"); +#if TCFG_APP_BT_EN + if (app_get_curr_task() == APP_IDLE_TASK) { + bt_auto_off_cnt = CHGBOX_BT_AUTO_OFF_TIMES; + app_task_switch_to(APP_BT_TASK); + } +#endif + break; + default: + break; + } + } else if (sys_info.chgbox_status == CHG_STATUS_LOWPOWER) { + switch (event) { + case KEY_BOX_POWER_CLICK: + log_info("KEY_POWER_CLICK_low\n"); + if (sys_info.status[USB_DET] == STATUS_OFFLINE) { + chgbox_ui_update_status(UI_MODE_LOWPOWER, CHGBOX_UI_KEY_CLICK); + } + break; + default: + break; + } + } + return 0; +} + + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓模式设置函数 + @param newstatus:新的模式 + @return 无 + @note 退出当前模式,设置新的模式的参数 +*/ +/*------------------------------------------------------------------------------------*/ +void chargebox_set_newstatus(u8 newstatus) +{ + ///先退出当前状态 + log_info("chargebbox exit:%d\n", sys_info.chgbox_status); + if (newstatus == sys_info.chgbox_status) { + log_info("chargebbox status same\n"); + return; + } + + if (sys_info.chgbox_status == CHG_STATUS_COMM) { + sys_auto_shutdown_enable(); + if (sys_info.pair_status) { + sys_info.pair_status = 0; + chgbox_ui_update_status(UI_MODE_COMM, CHGBOX_UI_ALL_OFF); + } + } else if (sys_info.chgbox_status == CHG_STATUS_CHARGE) { + sys_info.lid_cnt = 0; + sys_info.shut_cnt = 0; + sys_info.charge = 0;//不在充电状态 + //关闭充电输出时,需要把IO打开 + chargeIc_boost_ctrl(0); + chargeIc_pwr_ctrl(0); + chargebox_api_open_port(EAR_L); + chargebox_api_open_port(EAR_R); + sys_auto_shutdown_enable(); + } else if (sys_info.chgbox_status == CHG_STATUS_LOWPOWER) { + sys_info.shut_cnt = 0; + sys_info.lid_cnt = 0; + } + + ///设置新状态 + sys_info.chgbox_status = newstatus; + if (newstatus == CHG_STATUS_COMM) { + sys_auto_shutdown_disable(); + sys_info.shut_cnt = 0; + sys_info.pair_status = 0; + sys_info.pair_succ = 0; + sys_info.ear_l_full = 0; + sys_info.ear_r_full = 0; + sys_info.earfull = 0; + goto_pair_cnt = 0; + auto_exit_cnt = 0; + chgbox_ui_update_status(UI_MODE_COMM, CHGBOX_UI_OPEN_LID); + } else if (newstatus == CHG_STATUS_CHARGE) { + ear_power_check_time = 0; + sys_info.shut_cnt = 0; + sys_info.lid_cnt = BIT(7) | TCFG_SEND_CLOSE_LID_MAX; + sys_info.charge = 0;//先关闭,等合盖命令发完才打开升压 + sys_info.ear_l_full = 0; + sys_info.ear_r_full = 0; + sys_info.earfull = 0; + sys_info.force_charge = CHGBOX_FORCE_CHARGE_TIMES; + sys_auto_shutdown_disable(); + if (sys_info.current_limit == 0) { + chgbox_ui_update_status(UI_MODE_CHARGE, CHGBOX_UI_CLOSE_LID); + } + } else if (newstatus == CHG_STATUS_LOWPOWER) { + sys_info.shut_cnt = 0; + sys_info.lid_cnt = 0; + if (sys_info.status[USB_DET] == STATUS_ONLINE) { + sys_auto_shutdown_disable(); + chgbox_ui_update_status(UI_MODE_LOWPOWER, CHGBOX_UI_USB_IN); + } else { + sys_auto_shutdown_enable(); + chgbox_ui_update_status(UI_MODE_LOWPOWER, CHGBOX_UI_LOWPOWER); + } + + if (!sys_info.earfull) { + sys_info.lid_cnt = BIT(7) | TCFG_SEND_CLOSE_LID_MAX; + } +#if TCFG_APP_BT_EN + app_task_switch_to(APP_IDLE_TASK); + bt_auto_off_cnt = 0; +#endif + } + log_info("chargebbox newstatus:%d\n", newstatus); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 获取对耳的在线状态,是否同时在线 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +u8 get_tws_ear_status(void) +{ + return (ear_info.online[EAR_L] && ear_info.online[EAR_R]); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 获取仓的合盖状态 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +u8 get_chgbox_lid_status(void) +{ + return (sys_info.status[LID_DET] == STATUS_ONLINE); +} + + +/*------------------------------------------------------------------------------------*/ +/**@brief 仓控制初始化函数 + @param 无 + @return 无 + @note 根据上电状态选择进入开盖通信、低电量或合盖充电模式,初始化一些控制量 +*/ +/*------------------------------------------------------------------------------------*/ +void charge_box_ctrl_init(void) +{ + //充电IC初始不成功,进行休眠(电压低等原因) + if (!sys_info.init_ok) { + log_error("chargeIc not ok, need softoff!\n"); + chgbox_enter_soft_power_off(); + return; + } + + sys_info.power_on = 0; + sys_info.shut_cnt = 0; + sys_info.pair_status = 0; + sys_info.pair_succ = 0; + sys_info.charge = 0;//先关闭,等合盖命令发完才打开升压 + sys_info.ear_l_full = 0; + sys_info.ear_r_full = 0; + sys_info.earfull = 0; + + goto_pair_cnt = 0; + auto_exit_cnt = 0; + + ///进入模式判断 + if (sys_info.status[LID_DET] == STATUS_ONLINE) { + sys_info.chgbox_status = CHG_STATUS_COMM; //开盖 + sys_auto_shutdown_disable(); + if (sys_info.wireless_wakeup == 0) { + chgbox_ui_update_status(UI_MODE_COMM, CHGBOX_UI_OPEN_LID); + } + } else { + if (sys_info.lowpower_flag) { + sys_info.chgbox_status = CHG_STATUS_LOWPOWER; //低电量 + sys_info.lid_cnt = 0; + if (sys_info.status[USB_DET] == STATUS_ONLINE) { + sys_auto_shutdown_disable(); + chgbox_ui_update_status(UI_MODE_LOWPOWER, CHGBOX_UI_USB_IN); + } else { + sys_auto_shutdown_enable(); + if (sys_info.wireless_wakeup == 0) { + chgbox_ui_update_status(UI_MODE_LOWPOWER, CHGBOX_UI_LOWPOWER); + } + } + } else { + sys_info.chgbox_status = CHG_STATUS_CHARGE; //合盖充电 + ear_power_check_time = 0; + sys_info.lid_cnt = BIT(7) | TCFG_SEND_CLOSE_LID_MAX; + sys_info.force_charge = CHGBOX_FORCE_CHARGE_TIMES; + sys_auto_shutdown_disable(); + if (sys_info.wireless_wakeup == 0) { + chgbox_ui_update_status(UI_MODE_CHARGE, CHGBOX_UI_POWER); + } + } + } + + chgbox_ui_set_power_on(1);//ui上电标志 + + if (sys_info.status[USB_DET] == STATUS_ONLINE) { + app_chargebox_event_to_user(CHGBOX_EVENT_USB_IN); + } + log_info("chgbox_poweron_status:%d\n", sys_info.chgbox_status); + sys_info.wireless_wakeup = 0; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 智能充电仓初始化函数 + @param 无 + @return 无 + @note 充电ic、霍尔传感器、无线充、lighting握手、ui、流程控制的初始化 +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_init_app(void) +{ + //注意:提前初始化的内容放在了 __initcall(chargebox_advanced_init); + chargeIc_init(); + chargebox_det_init(); +#if (TCFG_WIRELESS_ENABLE) + wireless_init_api(); +#endif +#if (TCFG_HANDSHAKE_ENABLE) + chgbox_handshake_init(); +#endif +#if TCFG_CHARGE_BOX_UI_ENABLE + chgbox_ui_manage_init(); +#endif + charge_box_ctrl_init(); +} + +#endif diff --git a/apps/common/charge_box/chgbox_ctrl.h b/apps/common/charge_box/chgbox_ctrl.h new file mode 100644 index 0000000..8ce89d1 --- /dev/null +++ b/apps/common/charge_box/chgbox_ctrl.h @@ -0,0 +1,85 @@ +#ifndef _CHGBOX_CTRL_H_ +#define _CHGBOX_CTRL_H_ +#include "event.h" + +#define STATUS_OFFLINE 0 +#define STATUS_ONLINE 1 + +enum { + USB_DET, //usb检测 + LID_DET, //盖子检测 + LDO_DET, //升压成功检测 + WIRELESS_DET, //无线充检测 + DET_MAX, +}; + +enum { + KEY_POWER_CLICK, + KEY_POWER_LONG, + KEY_POWER_HOLD, + KEY_POWER_UP, + KEY_POWER_DOUBLE, + KEY_POWER_THIRD, +}; + +//充电仓当然状态 +enum { + CHG_STATUS_COMM, //开盖通信 + CHG_STATUS_CHARGE, //合盖充电 + CHG_STATUS_LOWPOWER, //充电仓电压低 +}; + + +//检测几次不在线后才认为耳机拔出 +#define TCFG_EAR_OFFLINE_MAX 4 +//发送shutdown的个数 +#define TCFG_SEND_SHUT_DOWN_MAX 5 +//发送closelid的个数 -- 需要 EAR_OFFLINE_MAX 大 +#define TCFG_SEND_CLOSE_LID_MAX 5 + + +typedef struct _SYS_INFO { + volatile u8 charge: 1; //是否处于充电状态 + volatile u8 ear_l_full: 1; //左耳机是否充满 + volatile u8 ear_r_full: 1; //右耳机是否充满 + volatile u8 earfull: 1; //是否充满 + volatile u8 localfull: 1; //本机是否充满 + volatile u8 led_flag: 1; //led活跃状态 + volatile u8 lowpower_flag: 1; //低电标记 + volatile u8 power_on: 1; //上电/唤醒 + + volatile u8 pair_succ: 1; //配对成功 + volatile u8 init_ok: 1; //充电IC是否初始化成功 + volatile u8 chg_addr_ok: 1; //获取广播地址成功 + volatile u8 current_limit: 1; //过流 + volatile u8 temperature_limit: 1;//过热过冷 + volatile u8 wireless_wakeup: 1; //标记无线充唤醒 + volatile u8 reserev: 2; //保留bit + + volatile u8 pair_status; //处于配对状态 + volatile u8 shut_cnt; //关机命令计数器 + volatile u8 lid_cnt; //关盖命令计数器 + volatile u8 life_cnt; //超时休眠 + volatile u8 force_charge; //强制充电(耳机完全没电时需要先充电) + volatile u8 chgbox_status; //充电仓状态:开盖、合盖、低电等 + volatile u8 status[DET_MAX]; + } SYS_INFO; + + typedef struct _EAR_INFO { + volatile u8 online[2]; //在线离线计数 + volatile u8 power[2]; //电量 + volatile u8 full_cnt[2]; //电量充满计数 +} EAR_INFO; + + +extern SYS_INFO sys_info; +extern EAR_INFO ear_info; + +u8 chargebox_check_output_short(void); +void chargebox_set_output_short(void); +void app_charge_box_ctrl_init(void); +int charge_box_ctrl_event_handler(struct chargebox_event *chg_event); +int charge_box_key_event_handler(u16 event); + +void chgbox_init_app(void); +#endif diff --git a/apps/common/charge_box/chgbox_det.c b/apps/common/charge_box/chgbox_det.c new file mode 100644 index 0000000..6d7dedb --- /dev/null +++ b/apps/common/charge_box/chgbox_det.c @@ -0,0 +1,806 @@ +#include "gpio.h" +#include "asm/adc_api.h" +#include "asm/charge.h" +#include "asm/efuse.h" +#include "asm/power/p33.h" +#include "system/event.h" +#include "app_config.h" +#include "chgbox_det.h" +#include "chgbox_box.h" +#include "chgbox_ctrl.h" +#include "system/timer.h" +#include "chargeIc_manage.h" + +#if(TCFG_CHARGE_BOX_ENABLE) + +#define LOG_TAG_CONST APP_CHGBOX +#define LOG_TAG "[IC_SELF]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#define LOW_LEVEL 0 +#define HIGHT_LEVEL 1 +#define DETECT_PERIOD 20//ms + +//USB上下线检测时间配置 +#define USB_DET_ONLINE_LEVEL (HIGHT_LEVEL)//高电平表示在线 +#define USB_DET_OFFLINE_TIME (500/DETECT_PERIOD) +#define USB_DET_ONLINE_TIME (200/DETECT_PERIOD) + +//HALL开关检测时间配置 +#define HALL_DET_OPEN_LEVEL (HIGHT_LEVEL)//高电平表示开盖 +#define HALL_DET_OPEN_TIME (100/DETECT_PERIOD) +#define HALL_DET_CLOSE_TIME (300/DETECT_PERIOD) + +//升压检测电压及时间配置 +#define LDO_SUCC_VOLTAGE (4300) +#define LDO_DET_ON_TIME (60/DETECT_PERIOD) +#define LDO_DET_OFF_TIME (60/DETECT_PERIOD) + +//满电检测时间 +#define CHARGE_FULL_LEVEL (HIGHT_LEVEL)//高电平表示充满 +#define STAT_FULL_POWER_TIME (1000/DETECT_PERIOD) + +//给耳机充电电流限制 +#define CURRENT_DETECT_PERIOD (1000) +#define CHARGE_CURRENT_LIMIT (200)//mA +#define CHARGE_CURRENT_RES (500)//500mΩ + +//充电温度限制 +#define CHARGE_TEMP_DETECT_PERIOD (10000)//温度检测周期 +#define CHARGE_TEMP_ABNORMAL_LOW (330)//温度异常的低值33k +#define CHARGE_TEMP_NORMAL_LOW (250)//温度正常的低值25k +#define CHARGE_TEMP_NORMAL_HIGH (53)//温度正常的低值5.3k +#define CHARGE_TEMP_ABNORMAL_HIGH (43)//温度异常的低值4.3k +#define CHARGE_TEMP_AVG_COUNTS (10)//取10次平均值 + +//充电舱欠压,不开机电压 +#define POWER_ON_SHUTDOWN_VOLT (2800) + +//电池电压检测,进入退出低电检测电压及时间配置 +#define POWER_DETECT_PERIOD (10000) +#define LOWPOWER_ENTER_VOLTAGE (3300) +#define LOWPOWER_EXIT_VOLTAGE (3320) +#define BAT_AVE_COUNTS (10) //检测n次 +#define BAT_CUT_COUNTS (2) //首尾各去n个后计算均值 +static u16 battery_value_tab[BAT_AVE_COUNTS]; +static volatile u16 cur_bat_volt = 0;//当前充电盒子的电量 +static volatile u8 battery_detect_skip = 0;//在USB插拔期间电压不稳定,不采集电压 +static volatile u8 detect_init_ok; +static u16 cur_ear_curr, ear_static_current;//耳机端充电电流检测静态值 + +extern void delay_2ms(int cnt); +extern u8 get_cur_total_ad_ch(void); +extern void clr_wdt(void); + +/*------------------------------------------------------------------------------------*/ +/**@brief 电池电量检测 + @param 无 + @return 无 + @note 用于检测电池的电量,作出低电判断等 +*/ +/*------------------------------------------------------------------------------------*/ +static int power_det_timer; +static void power_detect_func(void *priv) +{ + static u8 bat_cnt = 0; + u16 ad_min, bat_volt_tmp; + u8 i, j, k, low_flag; + + if (battery_detect_skip) { + usr_timer_del(power_det_timer); + power_det_timer = 0; + bat_cnt = 0; + return; + } + + battery_value_tab[bat_cnt++] = adc_get_voltage(TCFG_BAT_DET_AD_CH) * 4; //注意电路分压 + + if (bat_cnt == BAT_AVE_COUNTS) { //n次检测后排序 + for (i = 1; i < BAT_AVE_COUNTS; i++) { + for (j = i; j > 0; j--) { + if (battery_value_tab[j] < battery_value_tab[j - 1]) { + ad_min = battery_value_tab[j]; + battery_value_tab[j] = battery_value_tab[j - 1]; + battery_value_tab[j - 1] = ad_min; + } + } + } + bat_volt_tmp = 0; + for (k = BAT_CUT_COUNTS; k < (BAT_AVE_COUNTS - BAT_CUT_COUNTS); k++) { + bat_volt_tmp = battery_value_tab[k] + bat_volt_tmp; + } + bat_volt_tmp = (bat_volt_tmp / (BAT_AVE_COUNTS - (BAT_CUT_COUNTS * 2))); //均值 + //更新电池电量,USB在线时只能增,USB不在线是只能减 + if (sys_info.status[USB_DET] == STATUS_ONLINE) { + if (bat_volt_tmp > cur_bat_volt) { + cur_bat_volt = bat_volt_tmp; + } + } else { + if (bat_volt_tmp < cur_bat_volt) { + cur_bat_volt = bat_volt_tmp; + } + } + + low_flag = adc_check_vbat_lowpower(); + + log_info("vbat power: %dmV\n", cur_bat_volt); + + //低电与退出低电检测 + if (sys_info.lowpower_flag) { + if ((cur_bat_volt > LOWPOWER_EXIT_VOLTAGE) && (low_flag == 0)) { + sys_info.lowpower_flag = 0; + app_chargebox_event_to_user(CHGBOX_EVENT_EXIT_LOWPOWER); + log_info("Exit cbox lowpower\n"); + } + } else { + if (cur_bat_volt <= LOWPOWER_ENTER_VOLTAGE || low_flag) { + sys_info.lowpower_flag = 1; + app_chargebox_event_to_user(CHGBOX_EVENT_ENTER_LOWPOWER); + log_info("Enter cbox lowpower\n"); + } + } + usr_timer_del(power_det_timer); + power_det_timer = 0; + bat_cnt = 0;//清0,进行下一次统计 + } +} + +static void power_detect_start(void *priv) +{ + if (!power_det_timer) { + adc_check_vbat_lowpower(); + power_det_timer = usr_timer_add(NULL, power_detect_func, DETECT_PERIOD, 1); + } +} + +static void power_detect_init(void) +{ + sys_timer_add(NULL, power_detect_start, POWER_DETECT_PERIOD); + power_det_timer = usr_timer_add(NULL, power_detect_func, DETECT_PERIOD, 1); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief usb上下线检测 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +static int usb_det_timer; +static void usb_detect_func(void *priv) +{ + static u16 usb_in_det_cnt = 0; + static u16 usb_out_det_cnt = 0; +#if TCFG_CHARGE_MOUDLE_OUTSIDE + extern void usb_det_wakeup_set_edge(u8 edge); + u8 io_level = gpio_read(TCFG_USB_ONLE_DET_IO); +#else + u8 io_level = get_lvcmp_det(); +#endif + + battery_detect_skip = 1; + sys_info.life_cnt = 0;//状态变化时,清除休眠计时 + if (((USB_DET_ONLINE_LEVEL == LOW_LEVEL) && (!io_level)) || ((USB_DET_ONLINE_LEVEL == HIGHT_LEVEL) && io_level)) {//插入 + usb_in_det_cnt++; + if (usb_in_det_cnt >= USB_DET_ONLINE_TIME) { + usr_timer_del(usb_det_timer); + usb_det_timer = 0; + usb_in_det_cnt = 0; + usb_out_det_cnt = 0; + battery_detect_skip = 0; + if (sys_info.status[USB_DET] == STATUS_OFFLINE) { + sys_info.status[USB_DET] = STATUS_ONLINE; + app_chargebox_event_to_user(CHGBOX_EVENT_USB_IN); + log_info("usb online!"); +#if (TCFG_CHARGE_MOUDLE_OUTSIDE) + usb_det_wakeup_set_edge(io_level); +#else + LVCMP_EDGE_SEL(1); //检测ldoin比vbat电压低的情况(充电仓给电池充满后会关断,此时电压会掉下来) +#endif + } + } + } else {//拔出 + usb_out_det_cnt++; + if (usb_out_det_cnt >= USB_DET_OFFLINE_TIME) { + usr_timer_del(usb_det_timer); + usb_det_timer = 0; + usb_in_det_cnt = 0; + usb_out_det_cnt = 0; + battery_detect_skip = 0; + if (sys_info.status[USB_DET] == STATUS_ONLINE) { + sys_info.localfull = 0; ///充满标志清0 + sys_info.status[USB_DET] = STATUS_OFFLINE; + app_chargebox_event_to_user(CHGBOX_EVENT_USB_OUT); + log_info("usb offline!"); +#if (TCFG_CHARGE_MOUDLE_OUTSIDE) + usb_det_wakeup_set_edge(io_level); +#else + LVCMP_EDGE_SEL(0);//拔出后重新检测插入 +#endif + } + } + } +} + +void usb_wakeup_deal(void) +{ + if (detect_init_ok && (!usb_det_timer)) { + usb_det_timer = usr_timer_add(NULL, usb_detect_func, DETECT_PERIOD, 1); + } +} + +static void usb_detect_init(void) +{ + usb_det_timer = usr_timer_add(NULL, usb_detect_func, DETECT_PERIOD, 1); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 霍尔传感器开合盖检测 + @param 无 + @return 无 + @note 传感器上下线处理,设置状态、发送相关事件 +*/ +/*------------------------------------------------------------------------------------*/ +static int hall_det_timer; +extern void hall_det_wakeup_set_edge(u8 edge); +static void hall_detect_func(void *priv) +{ + static u16 hall_open_det_cnt = 0; + static u16 hall_close_det_cnt = 0; + u8 io_level = gpio_read(TCFG_HALL_PORT); + + sys_info.life_cnt = 0; + + if (((HALL_DET_OPEN_LEVEL == LOW_LEVEL) && (!io_level)) || ((HALL_DET_OPEN_LEVEL == HIGHT_LEVEL) && io_level)) { + hall_open_det_cnt++; + if (hall_open_det_cnt >= HALL_DET_OPEN_TIME) { + usr_timer_del(hall_det_timer); + hall_det_timer = 0; + hall_open_det_cnt = 0; + hall_close_det_cnt = 0; + if (sys_info.status[LID_DET] == STATUS_OFFLINE) { + sys_info.status[LID_DET] = STATUS_ONLINE; + app_chargebox_event_to_user(CHGBOX_EVENT_OPEN_LID); + hall_det_wakeup_set_edge(io_level); + log_info("hall open!\n"); + } + } + } else { + hall_close_det_cnt++; + if (hall_close_det_cnt >= HALL_DET_CLOSE_TIME) { + usr_timer_del(hall_det_timer); + hall_det_timer = 0; + hall_open_det_cnt = 0; + hall_close_det_cnt = 0; + if (sys_info.status[LID_DET] == STATUS_ONLINE) { + sys_info.status[LID_DET] = STATUS_OFFLINE; + app_chargebox_event_to_user(CHGBOX_EVENT_CLOSE_LID); + hall_det_wakeup_set_edge(io_level); + log_info("hall close!\n"); + } + } + } +} + +void hall_wakeup_deal(void) +{ + if (detect_init_ok && (!hall_det_timer)) { + hall_det_timer = usr_timer_add(NULL, hall_detect_func, DETECT_PERIOD, 1); + } +} + +static void hall_detect_init(void) +{ + hall_det_timer = usr_timer_add(NULL, hall_detect_func, DETECT_PERIOD, 1); +} + +#if TCFG_LDO_DET_ENABLE +/*------------------------------------------------------------------------------------*/ +/**@brief LDO升压成功检测 + @param 无 + @return 无 + @note 用于检测ldo升压是否正常 +*/ +/*------------------------------------------------------------------------------------*/ +static int ldo_det_timer; +static void ldo_detect_func(void *priv) +{ + static u16 ldo_on_detect_cnt = 0; + static u16 ldo_off_detect_cnt = 0; + u32 ldo_voltage = adc_get_voltage(TCFG_CHG_LDO_DET_AD_CH) * 23 / 13; + if (ldo_voltage >= LDO_SUCC_VOLTAGE) { + ldo_on_detect_cnt++; + if (ldo_on_detect_cnt >= LDO_DET_ON_TIME) { + usr_timer_del(ldo_det_timer); + ldo_det_timer = 0; + ldo_on_detect_cnt = 0; + ldo_off_detect_cnt = 0; + if (sys_info.status[LDO_DET] == STATUS_OFFLINE) { + sys_info.status[LDO_DET] = STATUS_ONLINE; + log_info("LDO ON\n"); + } + } + } else { + if (ldo_voltage < LDO_SUCC_VOLTAGE) { //注意分压 + ldo_off_detect_cnt++; + if (ldo_off_detect_cnt >= LDO_DET_OFF_TIME) { + usr_timer_del(ldo_det_timer); + ldo_det_timer = 0; + ldo_on_detect_cnt = 0; + ldo_off_detect_cnt = 0; + if (sys_info.status[LDO_DET] == STATUS_ONLINE) { + sys_info.status[LDO_DET] = STATUS_OFFLINE; + log_info("LDO OFF\n"); + } + } + } + } +} + +//提供升压使能和关闭的时候调用下 +void ldo_wakeup_deal(void *priv) +{ + if (detect_init_ok && (!ldo_det_timer)) { + ldo_det_timer = usr_timer_add(NULL, ldo_detect_func, DETECT_PERIOD, 1); + } +} + +static void ldo_detect_init(void) +{ + sys_timer_add(NULL, ldo_wakeup_deal, 10000);//10s起来检测一次 + ldo_det_timer = usr_timer_add(NULL, ldo_detect_func, DETECT_PERIOD, 1); +} +#endif + +/*------------------------------------------------------------------------------------*/ +/**@brief 舱电池充满检测 + @param 无 + @return 无 + @note 用于检测是否充满电池 +*/ +/*------------------------------------------------------------------------------------*/ +static int usb_charge_full_det_timer; +static void usb_charge_full_detect_func(void *priv) +{ + static u16 charge_full_det_cnt = 0; + u8 io_level = 0; + + if (chargebox_get_charge_en() == 0) { + goto __detect_del; + } + + if ((sys_info.status[USB_DET] == STATUS_OFFLINE) || sys_info.localfull) { + goto __detect_del; + } + +#if TCFG_CHARGE_MOUDLE_OUTSIDE + io_level = gpio_read(TCFG_CHARGE_FULL_DET_IO); +#else + io_level = CHARGE_FULL_FLAG_GET() && LVCMP_DET_GET(); +#endif + if (((CHARGE_FULL_LEVEL == LOW_LEVEL) && (!io_level)) || ((CHARGE_FULL_LEVEL == HIGHT_LEVEL) && io_level)) { + charge_full_det_cnt++; + if (charge_full_det_cnt > STAT_FULL_POWER_TIME) { + sys_info.localfull = 1; ///注意清0动作在usb拔出动作那里 + app_chargebox_event_to_user(CHGBOX_EVENT_LOCAL_FULL); + log_info("Usb charge is Full\n"); + goto __detect_del; + } + } else { + charge_full_det_cnt = 0; + goto __detect_del; + } + return; +__detect_del: + usr_timer_del(usb_charge_full_det_timer); + usb_charge_full_det_timer = 0; + charge_full_det_cnt = 0; +#if (!TCFG_CHARGE_MOUDLE_OUTSIDE) + if (sys_info.localfull == 0) { + CHARGE_EDGE_DETECT_EN(1); + CHARGE_LEVEL_DETECT_EN(1); + } +#endif +} + +void usb_charge_full_wakeup_deal(void) +{ + if (detect_init_ok && (!usb_charge_full_det_timer)) { + usb_charge_full_det_timer = usr_timer_add(NULL, usb_charge_full_detect_func, DETECT_PERIOD, 1); + } +} + +static void usb_charge_full_detect_init(void) +{ + usb_charge_full_det_timer = usr_timer_add(NULL, usb_charge_full_detect_func, DETECT_PERIOD, 1); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 耳机充电电流检测 + @param 无 + @return 无 + @note 用于检测给耳机充电电流是否正常 +*/ +/*------------------------------------------------------------------------------------*/ +#if TCFG_CURRENT_LIMIT_ENABLE +static int current_det_slow_timer, current_det_fast_timer; +static void ear_current_detect_func(void *priv) +{ + static u8 current_cnt = 0; + static u16 ear_current = 0; + if (sys_info.current_limit) { + goto __ear_current_end; + } + current_cnt++; + ear_current += adc_get_voltage(TCFG_CURRENT_DET_AD_CH) * 1000 / CHARGE_CURRENT_RES; + if (current_cnt < 5) { + return; + } + ear_current = ear_current / current_cnt; + if (ear_current > ear_static_current) { + ear_current = ear_current - ear_static_current; + } else { + ear_current = 0; + } + cur_ear_curr = ear_current; + if (ear_current > CHARGE_CURRENT_LIMIT) { + sys_info.current_limit = 1; + app_chargebox_event_to_user(CHGBOX_EVENT_ENTER_CURRENT_PROTECT); + log_error("ear_current over limit: %d\n", ear_current); + } + log_info("ear_current: %d mA\n", ear_current); +__ear_current_end: + current_cnt = 0; + ear_current = 0; + usr_timer_del(current_det_fast_timer); + current_det_fast_timer = 0; +} + +static void ear_current_detect_start(void *priv) +{ + if (sys_info.current_limit) { + usr_timer_del(current_det_slow_timer); + current_det_slow_timer = 0; + return; + } + if (!current_det_fast_timer) { + current_det_fast_timer = usr_timer_add(NULL, ear_current_detect_func, DETECT_PERIOD, 1); + } +} + +void ear_current_detect_enable(u8 en) +{ + cur_ear_curr = 0; + if (en == 0) { + if (current_det_slow_timer) { + sys_timer_del(current_det_slow_timer); + current_det_slow_timer = 0; + } + if (current_det_fast_timer) { + usr_timer_del(current_det_fast_timer); + current_det_fast_timer = 0; + } + } else { + if (sys_info.current_limit) { + return; + } + if (!current_det_slow_timer) { + current_det_slow_timer = sys_timer_add(NULL, ear_current_detect_start, CURRENT_DETECT_PERIOD); + } + if (!current_det_fast_timer) { + current_det_fast_timer = usr_timer_add(NULL, ear_current_detect_func, DETECT_PERIOD, 1); + } + } +} + +#endif + +/*------------------------------------------------------------------------------------*/ +/**@brief 温度检测 + @param 无 + @return 无 + @note 用于检测电池温度是否正常 +*/ +/*------------------------------------------------------------------------------------*/ +#if TCFG_TEMPERATURE_ENABLE +static int temperature_timer; +static void charge_temperatue_detect(void *priv) +{ + static u8 detect_cnt = 0; + static u32 adc_totle = 0; + u32 adc_avg, ntc_res; + adc_totle += adc_get_value(TCFG_CHARGE_TEMP_AD_CH); + detect_cnt++; + if (detect_cnt >= CHARGE_TEMP_AVG_COUNTS) { + adc_avg = adc_totle / detect_cnt; + ntc_res = TCFG_RES_UP * adc_avg / (1024 - adc_avg); + if (adc_avg > 0x3e0) { + detect_cnt = 0; + adc_totle = 0; + usr_timer_del(temperature_timer); + temperature_timer = 0; + return; + } + log_info("ntc_ad: %x, ntc_res: %d\n", adc_avg, ntc_res); + if (sys_info.temperature_limit == 0) { + if ((ntc_res > CHARGE_TEMP_ABNORMAL_LOW) || (ntc_res < CHARGE_TEMP_ABNORMAL_HIGH)) { + sys_info.temperature_limit = 1; + app_chargebox_event_to_user(CHGBOX_EVENT_ENTER_TEMP_PROTECT); + } + } else { + if ((ntc_res > CHARGE_TEMP_NORMAL_HIGH) && (ntc_res < CHARGE_TEMP_NORMAL_LOW)) { + sys_info.temperature_limit = 0; + app_chargebox_event_to_user(CHGBOX_EVENT_EXIT_TEMP_PROTECT); + } + } + usr_timer_del(temperature_timer); + temperature_timer = 0; + detect_cnt = 0; + adc_totle = 0; + } +} + +static void charge_temperatue_detect_start(void *priv) +{ + if (!temperature_timer) { + temperature_timer = usr_timer_add(NULL, charge_temperatue_detect, DETECT_PERIOD, 1);//10ms + } +} + +static void charge_temperatue_detect_init(void) +{ + sys_timer_add(NULL, charge_temperatue_detect_start, CHARGE_TEMP_DETECT_PERIOD); + temperature_timer = usr_timer_add(NULL, charge_temperatue_detect, DETECT_PERIOD, 1);//20ms +} +#endif + +/*------------------------------------------------------------------------------------*/ +/**@brief 获取当前仓电池电量 + @param 无 + @return 电量 + @note +*/ +/*------------------------------------------------------------------------------------*/ +u16 get_vbat_voltage(void) +{ + if (cur_bat_volt > 4200) { + return 4200; + } else { + return cur_bat_volt; + } +} + + +/*------------------------------------------------------------------------------------*/ +/**@brief 获取当前给耳机充电的充电电流 + @param 无 + @return 电流mA + @note +*/ +/*------------------------------------------------------------------------------------*/ +u16 get_ear_current(void) +{ + return cur_ear_curr; +} + + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电舱检测初始化 + @param 无 + @return 无 + @note 初始化电池电量检测、5v升压、升压检测、usb在线检测、满电检测 + 的IO初始化。检测usb是否在线、电池的初始电量情况 +*/ +/*------------------------------------------------------------------------------------*/ +void chargebox_det_init(void) +{ + //IO init + u16 status_init_cnt = 0; + u16 shut_down_cnt = 0; + u16 i = 0; + u8 io_level; + u16 val; + u32 volt_sum = 0; + u32 ntc_sum = 0; + u32 curr_sum = 0; + u8 total_ad_ch = 0; + + sys_info.localfull = 0; + sys_info.temperature_limit = 0; + sys_info.status[USB_DET] = STATUS_OFFLINE; + sys_info.status[LID_DET] = STATUS_OFFLINE; + + //电池电量检测初始化 +#if (TCFG_BAT_DET_AD_CH != AD_CH_VBAT) + gpio_set_die(TCFG_BAT_DET_IO, 0); + gpio_set_direction(TCFG_BAT_DET_IO, 1); + gpio_set_pull_down(TCFG_BAT_DET_IO, 0); + gpio_set_pull_up(TCFG_BAT_DET_IO, 0); + adc_add_sample_ch(TCFG_BAT_DET_AD_CH); + adc_set_sample_freq(AD_CH_LDOREF, 2); +#else + adc_set_sample_freq(AD_CH_VBAT, 2); + adc_set_sample_freq(AD_CH_LDOREF, 2); +#endif + + //耳机充电电流检测初始化 +#if TCFG_CURRENT_LIMIT_ENABLE + gpio_set_die(TCFG_CURRENT_DET_IO, 0); + gpio_set_direction(TCFG_CURRENT_DET_IO, 1); + gpio_set_pull_down(TCFG_CURRENT_DET_IO, 0); + gpio_set_pull_up(TCFG_CURRENT_DET_IO, 0); + adc_add_sample_ch(TCFG_CURRENT_DET_AD_CH); +#endif + + //温度检测初始化 +#if TCFG_TEMPERATURE_ENABLE + gpio_set_pull_down(TCFG_CHARGE_TEMP_IO, 0); + gpio_set_pull_up(TCFG_CHARGE_TEMP_IO, !TCFG_CHARGE_EXTERN_UP_ENABLE); + gpio_direction_input(TCFG_CHARGE_TEMP_IO); + gpio_set_die(TCFG_CHARGE_TEMP_IO, 0); + adc_add_sample_ch(TCFG_CHARGE_TEMP_AD_CH); +#endif + + //hall开合盖检测初始化 + gpio_set_direction(TCFG_HALL_PORT, 1); + gpio_set_die(TCFG_HALL_PORT, 1); + gpio_set_pull_down(TCFG_HALL_PORT, 0); + gpio_set_pull_up(TCFG_HALL_PORT, 0); + +#if TCFG_LDO_DET_ENABLE + //5v升压检测初始化 + gpio_set_die(TCFG_CHG_LDO_DET_IO, 0); + gpio_set_direction(TCFG_CHG_LDO_DET_IO, 1); + gpio_set_pull_down(TCFG_CHG_LDO_DET_IO, 0); + gpio_set_pull_up(TCFG_CHG_LDO_DET_IO, 0); + adc_add_sample_ch(TCFG_CHG_LDO_DET_AD_CH); +#endif + + //usb在线检测IO初始化 +#if TCFG_CHARGE_MOUDLE_OUTSIDE + gpio_set_direction(TCFG_USB_ONLE_DET_IO, 1); + gpio_set_die(TCFG_USB_ONLE_DET_IO, 1); + gpio_set_pull_down(TCFG_USB_ONLE_DET_IO, 0); + gpio_set_pull_up(TCFG_USB_ONLE_DET_IO, 0); + + //满电检测IO初始化 + gpio_set_direction(TCFG_CHARGE_FULL_DET_IO, 1); + gpio_set_die(TCFG_CHARGE_FULL_DET_IO, 1); + gpio_set_pull_down(TCFG_CHARGE_FULL_DET_IO, 0); + gpio_set_pull_up(TCFG_CHARGE_FULL_DET_IO, 1); +#endif + + total_ad_ch = get_cur_total_ad_ch();//ad总通道数 + sys_info.init_ok = 1; + + //检测hall是否开盖 + status_init_cnt = 0; + for (i = 0; i < 20; i++) { + io_level = gpio_read(TCFG_HALL_PORT); + if (((HALL_DET_OPEN_LEVEL == LOW_LEVEL) && (!io_level)) || ((HALL_DET_OPEN_LEVEL == HIGHT_LEVEL) && io_level)) { + sys_info.status[LID_DET] = STATUS_ONLINE; + } else { + sys_info.status[LID_DET] = STATUS_OFFLINE; + break; + } + } + hall_det_wakeup_set_edge(io_level); + + //检测usb是否在线 + status_init_cnt = 0; + for (i = 0; i < 20; i++) { +#if TCFG_CHARGE_MOUDLE_OUTSIDE + io_level = gpio_read(TCFG_USB_ONLE_DET_IO); +#else + io_level = get_lvcmp_det(); +#endif + if (((USB_DET_ONLINE_LEVEL == LOW_LEVEL) && (!io_level)) || ((USB_DET_ONLINE_LEVEL == HIGHT_LEVEL) && io_level)) { + status_init_cnt++; + sys_info.status[USB_DET] = STATUS_ONLINE; + } else { + sys_info.status[USB_DET] = STATUS_OFFLINE; + break; + } + } +#if (TCFG_CHARGE_MOUDLE_OUTSIDE) + usb_det_wakeup_set_edge(io_level); +#else + LVCMP_EDGE_SEL(io_level); +#endif + +#if TCFG_CHARGE_MOUDLE_OUTSIDE + //usb在线且默认充电开启时判断是否充满 + if ((sys_info.status[USB_DET] == STATUS_ONLINE) && chargebox_get_charge_en()) { + status_init_cnt = 0; + for (i = 0; i < 20; i++) { + io_level = gpio_read(TCFG_CHARGE_FULL_DET_IO); + if (((CHARGE_FULL_LEVEL == LOW_LEVEL) && (!io_level)) || ((CHARGE_FULL_LEVEL == HIGHT_LEVEL) && io_level)) { + status_init_cnt++; + sys_info.localfull = 1; + } else { + sys_info.localfull = 0; + break; + } + } + } +#endif + + //检测是否处于低电量状态 + for (i = 0; i < 5; i++) { + clr_wdt(); + delay_2ms(total_ad_ch + 2);//等待所有通道采完 + val = adc_get_voltage(TCFG_BAT_DET_AD_CH) * 4; //注意电路分压 + volt_sum += val; + log_info("Volt:%d", val); + +#if TCFG_TEMPERATURE_ENABLE + val = adc_get_value(TCFG_CHARGE_TEMP_AD_CH); + ntc_sum += val; +#endif + +#if TCFG_CURRENT_LIMIT_ENABLE + val = adc_get_value(TCFG_CURRENT_DET_AD_CH) * 1000 / CHARGE_CURRENT_RES; + curr_sum += val; +#endif + } + + cur_bat_volt = volt_sum / 5; //电池电压初始值 + if (cur_bat_volt < LOWPOWER_ENTER_VOLTAGE) {//是否小于低电电压 + sys_info.lowpower_flag = 1; + //判断是否小于关机电压,直接关机 + if ((cur_bat_volt < POWER_ON_SHUTDOWN_VOLT) && (sys_info.status[USB_DET] == STATUS_OFFLINE)) { + if (sys_info.wireless_wakeup == 0) { + sys_info.init_ok = 0; + } + } + } + +#if TCFG_CURRENT_LIMIT_ENABLE + ear_static_current = curr_sum / 5; + log_info("ear_static_current: %d mA\n", ear_static_current); +#endif + +#if TCFG_TEMPERATURE_ENABLE + u32 ntc_res, adc_avg; + adc_avg = ntc_sum / 5; + if (adc_avg < 0x3e0) { + ntc_res = TCFG_RES_UP * adc_avg / (1024 - adc_avg); + if ((ntc_res < CHARGE_TEMP_ABNORMAL_HIGH) || (ntc_res > CHARGE_TEMP_ABNORMAL_LOW)) { + sys_info.temperature_limit = 1; + if (chargebox_get_charge_en()) { + chargebox_charge_close(); + } + } + } else { + log_info("mabe NTC not connect!\n"); + } +#endif + + power_detect_init(); + usb_detect_init(); + hall_detect_init(); + usb_charge_full_detect_init(); +#if TCFG_LDO_DET_ENABLE + ldo_detect_init(); +#endif +#if TCFG_TEMPERATURE_ENABLE + charge_temperatue_detect_init(); +#endif + + log_info("usb status: %d\n", sys_info.status[USB_DET]); + log_info("lid status: %d\n", sys_info.status[LID_DET]); + log_info("ldo status: %d\n", sys_info.status[LDO_DET]); + log_info("localfull : %d\n", sys_info.localfull); + log_info("lowpower_flag: %d\n", sys_info.lowpower_flag); + log_info("sys_info.init_ok: %d\n", sys_info.init_ok); + log_info("power_on volt: %d\n", cur_bat_volt); + log_info("temperature status: %d\n", sys_info.temperature_limit); + detect_init_ok = 1; +} + +#endif diff --git a/apps/common/charge_box/chgbox_det.h b/apps/common/charge_box/chgbox_det.h new file mode 100644 index 0000000..ab9a474 --- /dev/null +++ b/apps/common/charge_box/chgbox_det.h @@ -0,0 +1,16 @@ +#ifndef _CHGBOX_DET_H_ +#define _CHGBOX_DET_H_ + +#include "typedef.h" + +u16 get_vbat_voltage(void); +u16 get_ear_current(void); +void chargebox_det_init(void); +void usb_wakeup_deal(void); +void usb_wakeup_deal(void); +void hall_wakeup_deal(void); +void ldo_wakeup_deal(void *priv); +void usb_charge_full_wakeup_deal(void); +void ear_current_detect_enable(u8 en); + +#endif diff --git a/apps/common/charge_box/chgbox_handshake.c b/apps/common/charge_box/chgbox_handshake.c new file mode 100644 index 0000000..a0733a1 --- /dev/null +++ b/apps/common/charge_box/chgbox_handshake.c @@ -0,0 +1,241 @@ +#include "gpio.h" +#include "app_config.h" +#include "system/includes.h" +#include "chgbox_ctrl.h" +#include "asm/adc_api.h" +#include "chgbox_box.h" +#include "device/chargebox.h" +#include "chgbox_handshake.h" + +#if (TCFG_CHARGE_BOX_ENABLE && TCFG_HANDSHAKE_ENABLE) + +#define LOG_TAG_CONST APP_CHGBOX +#define LOG_TAG "[CHG_HS]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void chgbox_timer_delay_us(u8 us); +static u8 hs_cur_sys_clk = 0; //当前时钟匹配值 +static u32 hs_small_clk = 0; //小于48m的系统时钟,记录,用来恢复 +static u8 chgbox_hs_repeat_times = 0; //重复次数 +static int hs_timer; + +static struct _hs_hdl hs_ctrl = { + .port = TCFG_HANDSHAKE_IO, //初始化IO + .send_delay_us = chgbox_timer_delay_us, //注册延时函数 +}; + +/*------------------------------------------------------------------------------------*/ +/**@brief lighting握手初始化 + @param 无 + @return 无 + @note 初始化io及注册延时 +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_handshake_init(void) +{ + handshake_ctrl_init(&hs_ctrl); +} + +static u16 delay_tap[HS_DELAY_240M + 1][HS_DELAY_16US + 1] = { + 19, 39, 52, 141, 158, 309, 355,//48m + 23, 45, 59, 146, 165, 315, 359,//60m + 27, 51, 66, 148, 170, 318, 367,//80m + 30, 55, 73, 151, 173, 320, 369,//96m + 32, 58, 75, 154, 177, 323, 370,//120m + 37, 60, 79, 157, 178, 325, 374,//160m + 38, 62, 82, 158, 179, 327, 376,//192m + 40, 64, 84, 159, 184, 328, 378,//240m +}; + +/*------------------------------------------------------------------------------------*/ +/**@brief 获取当前的时钟,设置对应的表值 + @param 无 + @return 无 + @note 该值匹配delay_tap +*/ +/*------------------------------------------------------------------------------------*/ +static void set_hs_cur_sys_clk(void) +{ + u32 cur_clock = 0; + cur_clock = clk_get("sys"); +#if (TCFG_CLOCK_SYS_SRC == SYS_CLOCK_INPUT_PLL_RCL) + if (cur_clock != 48000000) { //转成48m,结束后恢复原来的时钟 + hs_small_clk = cur_clock; + clk_set("sys", 48 * 1000000L); + hs_cur_sys_clk = HS_DELAY_48M; + puts("rest 48m\n"); + if (clk_get("lsb") != 48000000L) { + ASSERT(0, "clock err: %d", clk_get("lsb")); + } + } +#else + if (cur_clock < 48000000) { //小于48m时,转成48m,结束后恢复原来的时钟 + hs_small_clk = cur_clock; + clk_set("sys", 48 * 1000000L); + hs_cur_sys_clk = HS_DELAY_48M; + puts("rest 48m\n"); + } else { + switch (cur_clock) { + case 48000000: + hs_cur_sys_clk = HS_DELAY_48M; + break; + case 60000000: + hs_cur_sys_clk = HS_DELAY_60M; + break; + case 80000000: + hs_cur_sys_clk = HS_DELAY_80M; + break; + case 96000000: + hs_cur_sys_clk = HS_DELAY_96M; + break; + case 120000000: + hs_cur_sys_clk = HS_DELAY_120M; + break; + case 160000000: + hs_cur_sys_clk = HS_DELAY_160M; + break; + case 192000000: + hs_cur_sys_clk = HS_DELAY_192M; + break; + case 240000000: + hs_cur_sys_clk = HS_DELAY_240M; + break; + } + } +#endif +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 握手后重设置时钟 + @param 无 + @return 无 + @note 有改过时钟才重设置 +*/ +/*------------------------------------------------------------------------------------*/ +static void after_handshake_resume_small_clk(void) +{ + u32 cur_clock = 0; + if (hs_small_clk) { + clk_set("sys", hs_small_clk); + hs_small_clk = 0;//清0 + cur_clock = clk_get("sys"); + printf("after handshake app :%d\n", cur_clock); + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief lighting握手延时 + @param 无 + @return 无 + @note 提供不同的ms级延时 +*/ +/*------------------------------------------------------------------------------------*/ +static void chgbox_timer_delay_ms(u8 ms) +{ + //delay 值要根据不同的频率去调整,小于48m的要先设置48m,方便延时 + JL_TIMER2->CNT = 0; +#if (TCFG_CLOCK_SYS_SRC == SYS_CLOCK_INPUT_PLL_RCL) + JL_TIMER2->PRD = ms * clk_get("lsb") / (2 * 1000); + JL_TIMER2->CON = BIT(0) | BIT(6) | BIT(14); //系统时钟,lsb, div 2 +#else + JL_TIMER2->PRD = ms * clk_get("timer") / 1000; + JL_TIMER2->CON = BIT(0) | BIT(3) | BIT(14); //1分频,osc时钟,24m,24次就1us +#endif + while (!(JL_TIMER2->CON & BIT(15))); //等pending + JL_TIMER2->CON = 0; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief lighting握手延时 + @param 无 + @return 无 + @note 提供不同的us级延时 +*/ +/*------------------------------------------------------------------------------------*/ +SEC(.chargebox_code) +void chgbox_timer_delay_us(u8 us) +{ + //delay 值要根据不同的频率去调整,小于48m的要先设置48m,方便延时 + JL_TIMER2->CNT = 0; +#if (TCFG_CLOCK_SYS_SRC == SYS_CLOCK_INPUT_PLL_RCL) + JL_TIMER2->PRD = delay_tap[hs_cur_sys_clk][us];//这里不允许做乘除法 + JL_TIMER2->CON = BIT(0) | BIT(6) | BIT(14); //系统时钟,lsb, div 2, 必须为24M +#else + JL_TIMER2->PRD = delay_tap[hs_cur_sys_clk][us]; + JL_TIMER2->CON = BIT(0) | BIT(3) | BIT(14); //1分频,osc时钟,24m,24次就1us +#endif + while (!(JL_TIMER2->CON & BIT(15))); //等pending + JL_TIMER2->CON = 0; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief lighting握手 + @param 无 + @return 无 + @note 注意:为了精确的时间,会关闭其他中断 +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_handshake_run_app(void) +{ + set_hs_cur_sys_clk(); + + local_irq_disable(); + chgbox_timer_delay_ms(2); + handshake_send_app(HS_CMD0); + chgbox_timer_delay_ms(2); + handshake_send_app(HS_CMD1); + chgbox_timer_delay_ms(2); + handshake_send_app(HS_CMD2); + chgbox_timer_delay_ms(2); + handshake_send_app(HS_CMD3); + local_irq_enable(); + + after_handshake_resume_small_clk(); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief lighting重复握手 + @param null + @return 无 + @note 用定时器实现重复握手增加握手成功几率 +*/ +/*------------------------------------------------------------------------------------*/ +static void chgbox_handshake_deal(void *priv) +{ + chgbox_handshake_run_app(); + chgbox_hs_repeat_times--; + if (chgbox_hs_repeat_times == 0) { + sys_timer_del(hs_timer); + hs_timer = 0; + app_chargebox_event_to_user(CHGBOX_EVENT_HANDSHAKE_OK); + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief lighting重复握手初始化 + @param times:重复次数 + @return 无 + @note 初始化多次握手的次数 +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_handshake_set_repeat(u8 times) +{ + chgbox_hs_repeat_times = times; + if (chgbox_hs_repeat_times) { + if (hs_timer == 0) { + hs_timer = sys_timer_add(NULL, chgbox_handshake_deal, 200); + } + } else { + if (hs_timer) { + sys_timer_del(hs_timer); + hs_timer = 0; + } + } +} + +#endif diff --git a/apps/common/charge_box/chgbox_handshake.h b/apps/common/charge_box/chgbox_handshake.h new file mode 100644 index 0000000..0b8510b --- /dev/null +++ b/apps/common/charge_box/chgbox_handshake.h @@ -0,0 +1,8 @@ +#ifndef _CHGBOX_HANDSHAKE_H_ +#define _CHGBOX_HANDSHAKE_H_ + +void chgbox_handshake_run_app(void); +void chgbox_handshake_init(void); +void chgbox_handshake_set_repeat(u8 times); + +#endif diff --git a/apps/common/charge_box/chgbox_ui.c b/apps/common/charge_box/chgbox_ui.c new file mode 100644 index 0000000..5123925 --- /dev/null +++ b/apps/common/charge_box/chgbox_ui.c @@ -0,0 +1,453 @@ +#include "typedef.h" +#include "asm/pwm_led.h" +#include "system/includes.h" +#include "chgbox_ctrl.h" +#include "chargeIc_manage.h" +#include "chgbox_ui.h" +#include "app_config.h" + +#if (TCFG_CHARGE_BOX_ENABLE) + +#define LOG_TAG_CONST APP_CHGBOX +#define LOG_TAG "[CHGBOXUI]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +#define LOG_DUMP_ENABLE +#define LOG_CLI_ENABLE +#include "debug.h" + +#if (TCFG_CHARGE_BOX_UI_ENABLE) + +//关于仓ui的说明,分为三个部分 +//1.ui状态层 +//2.ui中间层 +//3.ui驱动层 +//状态层主要就是外部把仓的状态传进来,中间层是一个过渡,如不想用本驱动,可以自己更换中间层 +//或者只使用本驱动层作其他使用 + +///////////////////////////////////////////////////////////////////////////////////////////// +//ui状态层 +typedef struct _chgbox_ui_var_ { + int ui_timer; + u8 ui_power_on; //上电标志 +} _chgbox_ui_var; + +static _chgbox_ui_var chgbox_ui_var; +#define __this (&chgbox_ui_var) + +/*------------------------------------------------------------------------------------*/ +/**@brief UI超时函数 + @param priv:ui状态 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_ui_update_timeout(void *priv) +{ + u8 ledmode = (u8)priv; + __this->ui_timer = 0; + chgbox_led_set_mode(ledmode); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief UI超时设置 + @param priv:传到func的参数 + func:超时后的回调函数 + msec:N毫秒后调用func + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +u16 chgbox_ui_timeout_add(int priv, void (*func)(void *priv), u32 msec) +{ + if (__this->ui_timer) { + sys_timer_del(__this->ui_timer); + __this->ui_timer = 0; + } + if (func != NULL) { + __this->ui_timer = sys_timeout_add((void *)priv, func, msec); + } + return __this->ui_timer; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 设置ui上电标志位 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_ui_set_power_on(u8 flag) +{ + __this->ui_power_on = flag; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 获取ui上电标志位 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +u8 chgbox_get_ui_power_on(void) +{ + return __this->ui_power_on; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓电量态ui更新 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_ui_update_local_power(void) +{ + //配对状态,不显示舱电量UI + if (sys_info.pair_status) { + return; + } + if (sys_info.status[USB_DET] == STATUS_ONLINE) { + chgbox_ui_timeout_add(0, NULL, 0); + if (sys_info.localfull) { + chgbox_led_set_mode(CHGBOX_LED_GREEN_ON);//充满后绿灯常亮 + } else { + chgbox_led_set_mode(CHGBOX_LED_RED_SLOW_BRE);//充电中灯慢闪 + } + } else { + if (sys_info.lowpower_flag) { + chgbox_led_set_mode(CHGBOX_LED_RED_FAST_BRE); //快闪4秒 + chgbox_ui_timeout_add(CHGBOX_LED_RED_OFF, chgbox_ui_update_timeout, 4000); + } else { + chgbox_led_set_mode(CHGBOX_LED_GREEN_ON); + chgbox_ui_timeout_add(CHGBOX_LED_GREEN_OFF, chgbox_ui_update_timeout, 8000); + } + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓公共态ui更新 + @param status:UI状态 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_ui_updata_default_status(u8 status) +{ + switch (status) { + case CHGBOX_UI_ALL_OFF: + chgbox_ui_timeout_add(0, NULL, 0); + chgbox_led_set_mode(CHGBOX_LED_ALL_OFF); + break; + case CHGBOX_UI_ALL_ON: + chgbox_ui_timeout_add(0, NULL, 0); + chgbox_led_set_mode(CHGBOX_LED_ALL_ON); + break; + case CHGBOX_UI_POWER: + chgbox_ui_update_local_power(); + break; + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓合盖充电ui更新 + @param status:UI状态 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_ui_updata_charge_status(u8 status) +{ + switch (status) { + case CHGBOX_UI_USB_IN: + case CHGBOX_UI_KEY_CLICK: + case CHGBOX_UI_LOCAL_FULL: + chgbox_ui_update_local_power(); + break; + case CHGBOX_UI_USB_OUT: + chgbox_ui_timeout_add(0, NULL, 0); + chgbox_led_set_mode(CHGBOX_LED_ALL_OFF); + break; + case CHGBOX_UI_CLOSE_LID: + if (sys_info.status[USB_DET] == STATUS_ONLINE) { + chgbox_ui_update_local_power(); + } else { + chgbox_ui_timeout_add(0, NULL, 0); + chgbox_led_set_mode(CHGBOX_LED_GREEN_OFF); + } + break; + case CHGBOX_UI_EAR_FULL: + break; + case CHGBOX_UI_OVER_CURRENT: + if (sys_info.status[USB_DET] == STATUS_ONLINE) { + chgbox_ui_update_local_power(); + } else { + chgbox_led_set_mode(CHGBOX_LED_RED_FAST_BRE); //快闪4秒 + chgbox_ui_timeout_add(CHGBOX_LED_RED_OFF, chgbox_ui_update_timeout, 4000); + } + break; + default: + chgbox_ui_updata_default_status(status); + break; + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓开盖通信ui更新 + @param status:UI状态 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_ui_updata_comm_status(u8 status) +{ + switch (status) { + case CHGBOX_UI_USB_IN: + case CHGBOX_UI_LOCAL_FULL: + case CHGBOX_UI_KEY_CLICK: + case CHGBOX_UI_OPEN_LID: + chgbox_ui_update_local_power(); + break; + case CHGBOX_UI_USB_OUT: + if (!sys_info.pair_status) { + chgbox_ui_timeout_add(0, NULL, 0); + chgbox_led_set_mode(CHGBOX_LED_RED_OFF); + } + break; + case CHGBOX_UI_EAR_L_IN: + case CHGBOX_UI_EAR_R_IN: + case CHGBOX_UI_EAR_L_OUT: + case CHGBOX_UI_EAR_R_OUT: + if (!sys_info.pair_status) { + if (sys_info.status[USB_DET] == STATUS_ONLINE) { + if (sys_info.localfull) { + chgbox_led_set_mode(CHGBOX_LED_RED_OFF); + chgbox_ui_timeout_add(CHGBOX_LED_RED_ON, chgbox_ui_update_timeout, 500); + } + } else { + chgbox_led_set_mode(CHGBOX_LED_GREEN_ON); + chgbox_ui_timeout_add(CHGBOX_LED_GREEN_OFF, chgbox_ui_update_timeout, 500); + } + } + break; + case CHGBOX_UI_KEY_LONG: + chgbox_ui_timeout_add(0, NULL, 0); + chgbox_led_set_mode(CHGBOX_LED_BLUE_ON); + break; + case CHGBOX_UI_PAIR_START: + chgbox_ui_timeout_add(0, NULL, 0); + chgbox_led_set_mode(CHGBOX_LED_BLUE_FAST_FLASH); + break; + case CHGBOX_UI_PAIR_SUCC: + if (sys_info.status[USB_DET] == STATUS_OFFLINE) { + chgbox_ui_timeout_add(CHGBOX_LED_BLUE_OFF, chgbox_ui_update_timeout, 500); + } else { + if (!sys_info.localfull) { + chgbox_ui_timeout_add(CHGBOX_LED_RED_SLOW_FLASH, chgbox_ui_update_timeout, 500); + } else { + chgbox_ui_timeout_add(0, NULL, 0); + chgbox_led_set_mode(CHGBOX_LED_BLUE_ON); + } + } + break; + case CHGBOX_UI_PAIR_STOP: + if (sys_info.status[USB_DET] == STATUS_ONLINE) { + chgbox_ui_update_local_power(); + } else { + chgbox_ui_timeout_add(0, NULL, 0); + chgbox_led_set_mode(CHGBOX_LED_BLUE_OFF); + } + break; + default: + chgbox_ui_updata_default_status(status); + break; + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓低电量ui更新 + @param status:UI状态 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_ui_updata_lowpower_status(u8 status) +{ + switch (status) { + case CHGBOX_UI_LOCAL_FULL: + case CHGBOX_UI_LOWPOWER: + case CHGBOX_UI_KEY_CLICK: + case CHGBOX_UI_OPEN_LID: + case CHGBOX_UI_CLOSE_LID: + case CHGBOX_UI_USB_OUT: + case CHGBOX_UI_USB_IN: + chgbox_ui_update_local_power(); + break; + default: + chgbox_ui_updata_default_status(status); + break; + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓UI更新仓状态 + @param mode: 充电仓当前的UI模式(与充电仓的三个模式对应) + status:充电仓当前状态 + @return + @note 各个模式根据状态控制ui变化 +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_ui_update_status(u8 mode, u8 status) +{ + switch (mode) { + case UI_MODE_CHARGE: + chgbox_ui_updata_charge_status(status); + break; + case UI_MODE_COMM: + chgbox_ui_updata_comm_status(status); + break; + case UI_MODE_LOWPOWER: + chgbox_ui_updata_lowpower_status(status); + break; + } + chgbox_ui_set_power_on(0); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓UI初始化 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_ui_manage_init(void) +{ + chgbox_led_init(); +} + + +///////////////////////////////////////////////////////////////////////////////////////////// +//ui中间层 + +/*------------------------------------------------------------------------------------*/ +/**@brief 充电仓设置呼吸灯模式 + @param mode: 灯模式 + @return 无 + @note 设置充电仓灯的状态,不同的亮暗或闪烁可以调配 +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_led_set_mode(u8 mode) +{ + u8 i; + log_info("CHG_LED_mode:%d\n", mode); + switch (mode) { + case CHGBOX_LED_RED_OFF://红灯 + chgbox_set_led_stu(CHG_LED_RED, 0, 0, 1); + break; + case CHGBOX_LED_RED_FAST_OFF: + chgbox_set_led_stu(CHG_LED_RED, 0, 0, 0); + break; + case CHGBOX_LED_RED_ON://红灯 + chgbox_set_led_stu(CHG_LED_RED, 1, 0, 1); + break; + case CHGBOX_LED_RED_FAST_ON: + chgbox_set_led_stu(CHG_LED_RED, 1, 0, 0); + break; + case CHGBOX_LED_RED_SLOW_FLASH: + chgbox_set_led_bre(CHG_LED_RED, LED_FLASH_SLOW, 0, 0xffff); + break; + case CHGBOX_LED_RED_FLAST_FLASH: + chgbox_set_led_bre(CHG_LED_RED, LED_FLASH_FAST, 0, 0xffff); + break; + case CHGBOX_LED_RED_SLOW_BRE: + chgbox_set_led_bre(CHG_LED_RED, LED_FLASH_SLOW, 1, 0xffff); + break; + case CHGBOX_LED_RED_FAST_BRE: + chgbox_set_led_bre(CHG_LED_RED, LED_FLASH_FAST, 1, 0xffff); + break; + case CHGBOX_LED_GREEN_OFF: + chgbox_set_led_stu(CHG_LED_GREEN, 0, 1, 1); + break; + case CHGBOX_LED_GREEN_FAST_OFF: + chgbox_set_led_stu(CHG_LED_GREEN, 0, 0, 0); + break; + case CHGBOX_LED_GREEN_ON: + chgbox_set_led_stu(CHG_LED_GREEN, 1, 1, 1); + break; + case CHGBOX_LED_GREEN_FAST_ON: + chgbox_set_led_stu(CHG_LED_GREEN, 1, 0, 0); + break; + case CHGBOX_LED_GREEN_SLOW_FLASH: + chgbox_set_led_bre(CHG_LED_GREEN, LED_FLASH_SLOW, 0, 0xffff); + break; + case CHGBOX_LED_GREEN_FAST_FLASH: + chgbox_set_led_bre(CHG_LED_GREEN, LED_FLASH_FAST, 0, 0xffff); + break; + case CHGBOX_LED_GREEN_SLOW_BRE: + chgbox_set_led_bre(CHG_LED_GREEN, LED_FLASH_SLOW, 1, 0xffff); + break; + case CHGBOX_LED_GREEN_FAST_BRE: + chgbox_set_led_bre(CHG_LED_GREEN, LED_FLASH_FAST, 1, 0xffff); + break; + case CHGBOX_LED_BLUE_OFF: + chgbox_set_led_stu(CHG_LED_BLUE, 0, 0, 1); + break; + case CHGBOX_LED_BLUE_FAST_OFF: + chgbox_set_led_stu(CHG_LED_BLUE, 0, 0, 0); + break; + case CHGBOX_LED_BLUE_ON: + chgbox_set_led_stu(CHG_LED_BLUE, 1, 0, 1); + break; + case CHGBOX_LED_BLUE_FAST_ON: + chgbox_set_led_stu(CHG_LED_BLUE, 1, 0, 0); + break; + case CHGBOX_LED_BLUE_SLOW_FLASH: + chgbox_set_led_bre(CHG_LED_BLUE, LED_FLASH_SLOW, 0, 0xffff); + break; + case CHGBOX_LED_BLUE_FAST_FLASH: + chgbox_set_led_bre(CHG_LED_BLUE, LED_FLASH_FAST, 0, 0xffff); + break; + case CHGBOX_LED_BLUE_SLOW_BRE: + chgbox_set_led_bre(CHG_LED_BLUE, LED_FLASH_SLOW, 1, 0xffff); + break; + case CHGBOX_LED_BLUE_FAST_BRE: + chgbox_set_led_bre(CHG_LED_BLUE, LED_FLASH_FAST, 1, 0xffff); + break; + case CHGBOX_LED_ALL_OFF: + chgbox_set_led_all_off(1); + break; + case CHGBOX_LED_ALL_FAST_OFF: + chgbox_set_led_all_off(0); + break; + case CHGBOX_LED_ALL_ON: + chgbox_set_led_all_on(1); + break; + case CHGBOX_LED_ALL_FAST_ON: + chgbox_set_led_all_on(0); + break; + } +} + +#else + +void chgbox_ui_set_power_on(u8 flag) +{ +} + +u8 chgbox_get_ui_power_on(void) +{ + return 0; +} + +void chgbox_ui_update_status(u8 mode, u8 status) +{ +} + +void chgbox_ui_manage_init(void) +{ +} + +#endif + +#endif diff --git a/apps/common/charge_box/chgbox_ui.h b/apps/common/charge_box/chgbox_ui.h new file mode 100644 index 0000000..bca59da --- /dev/null +++ b/apps/common/charge_box/chgbox_ui.h @@ -0,0 +1,121 @@ +#ifndef _CHGBOX_UI_H_ +#define _CHGBOX_UI_H_ + +#include "typedef.h" +//关于仓ui的说明,分为三个部分 +//1.ui状态层 +//2.ui中间层 +//3.ui驱动层 +//状态层主要就是外部把仓的状态传进来,中间层是一个过渡,如不想用本驱动,可以自己更换中间层 +//或者只使用本驱动层作其他使用 +///////////////////////////////////////////////////////////////////////////////////////////// +//ui状态层 +typedef enum { + CHGBOX_UI_NULL = 0, + + CHGBOX_UI_ALL_OFF, + CHGBOX_UI_ALL_ON, + + CHGBOX_UI_POWER, + CHGBOX_UI_EAR_FULL, + CHGBOX_UI_LOCAL_FULL, + CHGBOX_UI_LOWPOWER, + + CHGBOX_UI_EAR_L_IN, + CHGBOX_UI_EAR_R_IN, + CHGBOX_UI_EAR_L_OUT, + CHGBOX_UI_EAR_R_OUT, + + CHGBOX_UI_KEY_CLICK, + CHGBOX_UI_KEY_LONG, + CHGBOX_UI_PAIR_START, + CHGBOX_UI_PAIR_SUCC, + CHGBOX_UI_PAIR_STOP, + + CHGBOX_UI_OPEN_LID, + CHGBOX_UI_CLOSE_LID, + + CHGBOX_UI_USB_IN, + CHGBOX_UI_USB_OUT, + + CHGBOX_UI_OVER_CURRENT, +} UI_STATUS; + +enum { + UI_MODE_CHARGE, + UI_MODE_COMM, + UI_MODE_LOWPOWER, +}; + +void chgbox_ui_manage_init(void); +void chgbox_ui_update_status(u8 mode, u8 status); +void chgbox_ui_set_power_on(u8 flag); +u8 chgbox_get_ui_power_on(void); + + + +///////////////////////////////////////////////////////////////////////////////////////////// +//ui中间层 + +//点灯模式 +enum { + CHGBOX_LED_RED_OFF,//呼吸灭 + CHGBOX_LED_RED_FAST_OFF,//直接灭 + CHGBOX_LED_RED_ON,//呼吸亮 + CHGBOX_LED_RED_FAST_ON,//直接亮 + CHGBOX_LED_RED_SLOW_FLASH,//慢闪 + CHGBOX_LED_RED_FLAST_FLASH,//快闪 + CHGBOX_LED_RED_SLOW_BRE,//呼吸慢闪 + CHGBOX_LED_RED_FAST_BRE,//呼吸快闪 + + CHGBOX_LED_GREEN_OFF, + CHGBOX_LED_GREEN_FAST_OFF, + CHGBOX_LED_GREEN_ON, + CHGBOX_LED_GREEN_FAST_ON, + CHGBOX_LED_GREEN_SLOW_FLASH, + CHGBOX_LED_GREEN_FAST_FLASH, + CHGBOX_LED_GREEN_SLOW_BRE, + CHGBOX_LED_GREEN_FAST_BRE, + + CHGBOX_LED_BLUE_ON, + CHGBOX_LED_BLUE_FAST_ON, + CHGBOX_LED_BLUE_OFF, + CHGBOX_LED_BLUE_FAST_OFF, + CHGBOX_LED_BLUE_SLOW_FLASH, + CHGBOX_LED_BLUE_FAST_FLASH, + CHGBOX_LED_BLUE_SLOW_BRE, + CHGBOX_LED_BLUE_FAST_BRE, + + CHGBOX_LED_ALL_OFF, + CHGBOX_LED_ALL_FAST_OFF, + CHGBOX_LED_ALL_ON, + CHGBOX_LED_ALL_FAST_ON, +}; +void chgbox_led_set_mode(u8 mode); + + +///////////////////////////////////////////////////////////////////////////////////////////// +//ui驱动层 +//定义n个灯 +enum { + CHG_LED_RED, + CHG_LED_GREEN, + CHG_LED_BLUE, + CHG_LED_MAX, +}; + +//闪烁快慢 +enum { + LED_FLASH_FAST, + LED_FLASH_SLOW, +}; + +//led驱动初始化 +void chgbox_led_init(void); +void chgbox_set_led_stu(u8 led_type, u8 on_off, u8 sp_flicker, u8 fade); +void chgbox_set_led_bre(u8 led_type, u8 speed_mode, u8 is_bre, u16 time); +void chgbox_set_led_all_off(u8 fade); +void chgbox_set_led_all_on(u8 fade); + +#endif //_APP_CHARGEBOX_H_ + diff --git a/apps/common/charge_box/chgbox_ui_drv_pwmled.c b/apps/common/charge_box/chgbox_ui_drv_pwmled.c new file mode 100644 index 0000000..25c0801 --- /dev/null +++ b/apps/common/charge_box/chgbox_ui_drv_pwmled.c @@ -0,0 +1,270 @@ +#include "typedef.h" +#include "asm/pwm_led.h" +#include "system/includes.h" +#include "chgbox_ctrl.h" +#include "chargeIc_manage.h" +#include "chgbox_ui.h" +#include "app_config.h" + +//使用PEMLED推灯,支持低功耗 + +#if (TCFG_CHARGE_BOX_ENABLE) + +#define LOG_TAG_CONST APP_CHGBOX +#define LOG_TAG "[CHGBOXUI]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +#define LOG_DUMP_ENABLE +#define LOG_CLI_ENABLE +#include "debug.h" + +#if (TCFG_CHARGE_BOX_UI_ENABLE && TCFG_CHGBOX_UI_PWMLED) + +#define CFG_LED_LIGHT 200 //10 ~ 500, 值越大, 亮度越高 + +#define CFG_SINGLE_FAST_FLASH_FREQ 500 //LED单独快闪速度, ms闪烁一次(100 ~ 1000) +#define CFG_SINGLE_FAST_LIGHT_TIME 150 //单灯快闪灯亮持续时间, 单位ms + +#define CFG_SINGLE_SLOW_FLASH_FREQ 1000 //LED单独慢闪速度, ms闪烁一次(1000 ~ 20000) +#define CFG_SINGLE_SLOW_LIGHT_TIME 300 //单灯慢闪灯亮持续时间, 单位ms +/***************** LED0/LED1单独每隔5S单闪时, 可供调节参数 ********************/ +#define CFG_LED_5S_FLASH_LIGHT_TIME 100 //LED 5S 闪烁时灯亮持续时间, 单位ms +/***************** 呼吸模式配置参数, 可供调节参数 ********************/ +#define CFG_LED_SLOW_BREATH_TIME 1000 //呼吸时间灭->亮->灭, 单位ms +#define CFG_LED_FAST_BREATH_TIME 500 //呼吸时间灭->亮->灭, 单位ms +#define CFG_LED_BREATH_BRIGHT 300 //呼吸亮度, 范围: 0 ~ 500 +#define CFG_LED_BREATH_BLINK_TIME 100 //灭灯延时, 单位ms + +const pwm_led_on_para pwm_led_on_para_table[] = { + /* + u16 led0_bright;//led0_bright, LED0亮度: 0 ~ 500 + u16 led1_bright;//led1_bright, LED1亮度: 0 ~ 500 + */ + {CFG_LED_LIGHT, CFG_LED_LIGHT},//PWM_LED_ON 亮 +}; + +const pwm_led_one_flash_para pwm_led_one_flash_para_table[] = { + /* + u16 led0_bright;//led0_bright: led0亮度(0 ~ 500), + u16 led1_bright;//led1_bright: led1亮度(0 ~ 500), + u32 period;//period: 闪灯周期(ms), 多少ms闪一下(100 ~ 20000), 100ms - 20S, + u32 start_light_time;//start_light_time: 在周期中开始亮灯的时间, -1: 周期最后亮灯, 默认填-1即可, + u32 light_time;//light_time: 灯亮持续时间, + */ + {CFG_LED_LIGHT, CFG_LED_LIGHT, CFG_SINGLE_SLOW_FLASH_FREQ, -1, CFG_SINGLE_SLOW_LIGHT_TIME},//PWM_LED_SLOW_FLASH 慢闪 + {CFG_LED_LIGHT, CFG_LED_LIGHT, CFG_SINGLE_FAST_FLASH_FREQ, -1, CFG_SINGLE_FAST_LIGHT_TIME},//PWM_LED_FAST_FLASH 快闪 + {CFG_LED_LIGHT, CFG_LED_LIGHT, 5000, 10, CFG_LED_5S_FLASH_LIGHT_TIME},//PWM_LED_ONE_FLASH_5S 5秒连闪1下 +}; + +const pwm_led_double_flash_para pwm_led_double_flash_para_table[] = { + /* + u16 led0_bright;//led0_bright: led0亮度, + u16 led1_bright;//led1_bright: led1亮度, + u32 period;//period: 闪灯周期(ms), 多少ms闪一下 + u32 first_light_time;//first_light_time: 第一次亮灯持续时间, + u32 gap_time;//gap_time: 两次亮灯时间间隔, + u32 second_light_time;//second_light_time: 第二次亮灯持续时间, + */ + {CFG_LED_LIGHT, CFG_LED_LIGHT, 5000, 100, 200, 100}, //PWM_LED_DOUBLE_FLASH_5S 5秒连闪两下 +}; + +const pwm_led_breathe_para pwm_led_breathe_para_table[] = { + /* + u16 breathe_time;//breathe_time: 呼吸周期(灭->最亮->灭), 设置范围: 500ms以上; + u16 led0_bright;//led0_bright: led0呼吸到最亮的亮度(0 ~ 500); + u16 led1_bright;//led1_bright: led1呼吸到最亮的亮度(0 ~ 500); + u32 led0_light_delay_time;//led0_light_delay_time: led0最高亮度延时(0 ~ 100ms); + u32 led1_light_delay_time;//led1_light_delay_time: led1最高亮度延时(0 ~ 100ms); + u32 led_blink_delay_time;//led_blink_delay_time: led0和led1灭灯延时(0 ~ 20000ms), 0 ~ 20S; + */ + {CFG_LED_SLOW_BREATH_TIME, CFG_LED_BREATH_BRIGHT, CFG_LED_BREATH_BRIGHT, 0, 0, CFG_LED_BREATH_BLINK_TIME},//PWM_LED_BREATHE 慢呼吸灯模式 + {CFG_LED_FAST_BREATH_TIME, CFG_LED_BREATH_BRIGHT, CFG_LED_BREATH_BRIGHT, 0, 0, CFG_LED_BREATH_BLINK_TIME},//PWM_LED_BREATHE 快呼吸灯模式 +}; + +static void chgbox_led_set_enable(u8 gpio) +{ + gpio_set_pull_up(gpio, 1); + gpio_set_pull_down(gpio, 1); + gpio_set_die(gpio, 1); + gpio_set_output_value(gpio, 1); + gpio_set_direction(gpio, 0); +} + +static void chgbox_led_set_disable(u8 gpio) +{ + gpio_set_pull_down(gpio, 0); + gpio_set_pull_up(gpio, 0); + gpio_direction_input(gpio); +} + +static void chgbox_ui_mode_set(u8 display, u8 sub) +{ + pwm_led_para para = {0}; + if (display == PWM_LED_NULL) { + return; + } + switch (display) { +//灯常灭 + case PWM_LED0_OFF: + break; +//灯常亮 + case PWM_LED0_ON: + para.on = pwm_led_on_para_table[0]; + break; + +//单灯单闪 + case PWM_LED0_SLOW_FLASH: + para.one_flash = pwm_led_one_flash_para_table[0]; + break; + case PWM_LED0_FAST_FLASH: + para.one_flash = pwm_led_one_flash_para_table[1]; + break; + case PWM_LED0_ONE_FLASH_5S: + para.one_flash = pwm_led_one_flash_para_table[2]; + break; + +//单灯双闪 + case PWM_LED0_DOUBLE_FLASH_5S: + para.double_flash = pwm_led_double_flash_para_table[0]; + break; + +//呼吸模式 + case PWM_LED0_BREATHE: + para.breathe = pwm_led_breathe_para_table[sub]; + break; + } + pwm_led_mode_set_with_para(display, para); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 设置灯为常亮、常暗模式 + @param led_type: 灯序号 + on_off: 1-->常亮 0-->常暗 + sp_flicker:是否闪烁标志 1-->在亮--亮 暗--暗过程中取反一下 + fade: 1-->快速响应 0-->渐变响应 + @return 无 + @note 把灯设置为 常亮/常暗 模式(默认同时设置其他灯为常暗) +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_set_led_stu(u8 led_type, u8 on_off, u8 sp_flicker, u8 fade) +{ + chgbox_led_set_disable(CHG_RED_LED_IO); + chgbox_led_set_disable(CHG_GREEN_LED_IO); + chgbox_led_set_disable(CHG_BLUE_LED_IO); + if (on_off) { + chgbox_ui_mode_set(PWM_LED0_ON, 0); + } else { + chgbox_ui_mode_set(PWM_LED0_OFF, 0); + } + switch (led_type) { + case CHG_LED_RED: + chgbox_led_set_enable(CHG_RED_LED_IO); + break; + case CHG_LED_GREEN: + chgbox_led_set_enable(CHG_GREEN_LED_IO); + break; + case CHG_LED_BLUE: + chgbox_led_set_enable(CHG_BLUE_LED_IO); + break; + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 设置灯为呼吸模式 + @param led_type: 灯序号 + speed_mode:闪烁参数选择,这里默认为快、慢两种 + is_bre:是否为呼吸模式 + time:呼吸/闪烁多少次 + @return 无 + @note 把灯设置为呼吸模式(默认同时其他灯为常暗) +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_set_led_bre(u8 led_type, u8 speed_mode, u8 is_bre, u16 time) +{ + chgbox_led_set_disable(CHG_RED_LED_IO); + chgbox_led_set_disable(CHG_GREEN_LED_IO); + chgbox_led_set_disable(CHG_BLUE_LED_IO); + if (is_bre) { + if (speed_mode == LED_FLASH_FAST) { + chgbox_ui_mode_set(PWM_LED0_BREATHE, 1); + } else { + chgbox_ui_mode_set(PWM_LED0_BREATHE, 0); + } + } else { + if (speed_mode == LED_FLASH_FAST) { + chgbox_ui_mode_set(PWM_LED0_FAST_FLASH, 0); + } else { + chgbox_ui_mode_set(PWM_LED0_SLOW_FLASH, 0); + } + } + switch (led_type) { + case CHG_LED_RED: + chgbox_led_set_enable(CHG_RED_LED_IO); + break; + case CHG_LED_GREEN: + chgbox_led_set_enable(CHG_GREEN_LED_IO); + break; + case CHG_LED_BLUE: + chgbox_led_set_enable(CHG_BLUE_LED_IO); + break; + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 呼吸灯全暗 + @param fade:是否淡入 + @return 无 + @note 把所有的灯设置为常暗模式 +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_set_led_all_off(u8 fade) +{ + chgbox_led_set_disable(CHG_RED_LED_IO); + chgbox_led_set_disable(CHG_GREEN_LED_IO); + chgbox_led_set_disable(CHG_BLUE_LED_IO); + chgbox_ui_mode_set(PWM_LED0_OFF, 0); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 呼吸灯全亮 + @param fade:是否淡入 + @return 无 + @note 把所有的灯设置为常亮模式 +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_set_led_all_on(u8 fade) +{ + chgbox_led_set_disable(CHG_RED_LED_IO); + chgbox_led_set_disable(CHG_GREEN_LED_IO); + chgbox_led_set_disable(CHG_BLUE_LED_IO); + chgbox_ui_mode_set(PWM_LED0_ON, 0); + chgbox_led_set_enable(CHG_RED_LED_IO); + chgbox_led_set_enable(CHG_GREEN_LED_IO); + chgbox_led_set_enable(CHG_BLUE_LED_IO); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief led呼吸灯初始化 + @param 无 + @return 无 + @note 初始化每个led:渐亮、亮、渐暗、暗,最大亮度,对应IO的初始化.mc_clk的初始化,用于 + 控制pwm +*/ +/*-----------------------------------------------------------------------------------*/ +extern const struct led_platform_data chgbox_pwm_led_data; +void chgbox_led_init(void) +{ + chgbox_led_set_disable(CHG_RED_LED_IO); + chgbox_led_set_disable(CHG_GREEN_LED_IO); + chgbox_led_set_disable(CHG_BLUE_LED_IO); + pwm_led_init(&chgbox_pwm_led_data); +} + +#endif + +#endif + + + + diff --git a/apps/common/charge_box/chgbox_ui_drv_timer.c b/apps/common/charge_box/chgbox_ui_drv_timer.c new file mode 100644 index 0000000..9a6e067 --- /dev/null +++ b/apps/common/charge_box/chgbox_ui_drv_timer.c @@ -0,0 +1,755 @@ +#include "typedef.h" +#include "asm/pwm_led.h" +#include "system/includes.h" +#include "chgbox_ctrl.h" +#include "chargeIc_manage.h" +#include "chgbox_ui.h" +#include "app_config.h" + +//使用timer推灯,灭灯才能进入低功耗 + +#if (TCFG_CHARGE_BOX_ENABLE) + +#define LOG_TAG_CONST APP_CHGBOX +#define LOG_TAG "[CHGBOXUI]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +#define LOG_DUMP_ENABLE +#define LOG_CLI_ENABLE +#include "debug.h" + +#if (TCFG_CHARGE_BOX_UI_ENABLE && TCFG_CHGBOX_UI_TIMERLED) + +//常亮、常暗、呼吸 +enum { + GHGBOX_LED_MODE_ON, + GHGBOX_LED_MODE_OFF, + GHGBOX_LED_MODE_BRE, + CHGBOX_LED_MODE_FLASH, +}; + +//呼吸灯的步骤 渐亮--亮--渐暗--暗 +enum { + SOFT_LED_STEP_UP = 0, + SOFT_LED_STEP_LIGHT, + SOFT_LED_STEP_DOWN, + SOFT_LED_STEP_DARK, +}; + +typedef struct _CHG_SOFT_PWM_LED { + //初始化,亮暗接口接口 + void (*led_init)(void); + void (*led_on_off)(u8 on_off); + + u16 bre_times; //呼吸次数,0xffff为循环 + + u16 up_times; //渐亮次数 + u16 light_times; //亮次数 + u16 down_times; //渐暗次数 + u16 dark_times; //暗次数 + + u16 step_cnt; + u8 step; //步骤 + + u8 p_cnt; //占空比计数 + u8 cur_duty; //当前占空比 + u8 max_duty; //最大占空比,控制最大亮度 + + u8 busy; //忙标志,更换参数时作保护用 + u8 idle; //LED可以进低功耗 + + u8 sp_flicker; //特殊闪烁标志(用于处理亮-->亮,暗-->暗变化时灯光无反应的现象) + u16 sp_flicker_cnt;//特殊闪烁维持时间 + + u8 mode; //亮灯模式 +} CHG_SOFT_PWM_LED; + +#define MC_TIMER_UNIT_US 30 //多少us起一次中断 +#define SOFT_MC_PWM_MAX 128 //pwm周期(==MC_TIMER_UNIT_US * SOFT_MC_PWM_MAX 单位us) +#define BRIGHTNESS_MAX 40 //亮度0~100 + +//注意时间尺度,即是mc_clk初始化出来的时间 +#define UP_TIMES_DEFAULT 50 +#define DOWN_TIMES_DEFAULT 50 +#define SP_FLICKER_CNT_DEFAULT 30 //特殊闪烁时长计数 + + +CHG_SOFT_PWM_LED chgbox_led[CHG_LED_MAX]; + +//led亮的时候不能进入低功耗 +static volatile u8 is_led_active = 0; +static u8 led_idle_query(void) +{ + return (!is_led_active); +} +REGISTER_LP_TARGET(led_lp_target) = { + .name = "chgbox_led", + .is_idle = led_idle_query, +}; + +/*------------------------------------------------------------------------------------*/ +/**@brief 设置灯为常亮、常暗模式 + @param led_type: 灯序号 + on_off: 1-->常亮 0-->常暗 + sp_flicker:是否闪烁标志 1-->在亮--亮 暗--暗过程中取反一下 + fade: 1-->快速响应 0-->渐变响应 + @return 无 + @note 把灯设置为 常亮/常暗 模式(默认同时设置其他灯为常暗) +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_set_led_stu(u8 led_type, u8 on_off, u8 sp_flicker, u8 fade) +{ + //只开关一个灯,其他关掉 + u8 i; + for (i = 0; i < CHG_LED_MAX; i++) { + chgbox_led[i].busy = 1; + + if (led_type == i) { + + //设置特殊闪烁 + chgbox_led[i].sp_flicker = sp_flicker; + chgbox_led[i].sp_flicker_cnt = SP_FLICKER_CNT_DEFAULT; + + if (on_off) { + if (fade) { + //要根据当前占空比,把cnt计算好,避免亮度突变 + chgbox_led[i].step_cnt = chgbox_led[i].up_times * chgbox_led[i].cur_duty / chgbox_led[i].max_duty; + } else { + chgbox_led[i].step_cnt = 0; + chgbox_led[i].cur_duty = chgbox_led[i].max_duty; + chgbox_led[i].sp_flicker = 0; + } + chgbox_led[i].mode = GHGBOX_LED_MODE_ON; //常亮 + chgbox_led[i].up_times = UP_TIMES_DEFAULT; + } else { + if (fade) { + //要根据当前占空比,把cnt计算好 + chgbox_led[i].step_cnt = chgbox_led[i].down_times - chgbox_led[i].down_times * chgbox_led[i].cur_duty / chgbox_led[i].max_duty; + } else { + chgbox_led[i].step_cnt = 0; + chgbox_led[i].cur_duty = 0; + chgbox_led[i].sp_flicker = 0; + } + chgbox_led[i].mode = GHGBOX_LED_MODE_OFF; //常暗 + chgbox_led[i].down_times = DOWN_TIMES_DEFAULT; + } + } else { + if (fade) { + chgbox_led[i].step_cnt = chgbox_led[i].down_times - chgbox_led[i].down_times * chgbox_led[i].cur_duty / chgbox_led[i].max_duty; + } else { + chgbox_led[i].step_cnt = 0; + chgbox_led[i].cur_duty = 0; + } + chgbox_led[i].mode = GHGBOX_LED_MODE_OFF; //其他灯常暗 + chgbox_led[i].sp_flicker = 0; + chgbox_led[i].down_times = 20; + } + is_led_active = 1; + chgbox_led[i].idle = 0; + chgbox_led[i].bre_times = 0; + chgbox_led[i].busy = 0; + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 设置灯为呼吸模式 + @param led_type: 灯序号 + speed_mode:闪烁参数选择,这里默认为快、慢两种 + is_bre:是否为呼吸模式 + time:呼吸/闪烁多少次 + @return 无 + @note 把灯设置为呼吸模式(默认同时其他灯为常暗) +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_set_led_bre(u8 led_type, u8 speed_mode, u8 is_bre, u16 time) +{ + //只开关一个灯,其他关掉 + u8 i; + for (i = 0; i < CHG_LED_MAX; i++) { + chgbox_led[i].busy = 1; + + if (led_type == i) { + if (is_bre) { + chgbox_led[i].mode = GHGBOX_LED_MODE_BRE; //呼吸 + } else { + chgbox_led[i].mode = CHGBOX_LED_MODE_FLASH; //闪烁 + } + chgbox_led[i].bre_times = time; //循环 + if (speed_mode == LED_FLASH_FAST) { + chgbox_led[i].up_times = 50; + chgbox_led[i].light_times = 10; + chgbox_led[i].down_times = 50; + chgbox_led[i].dark_times = 10; + } else if (speed_mode == LED_FLASH_SLOW) { + chgbox_led[i].up_times = 200; + chgbox_led[i].light_times = 40; + chgbox_led[i].down_times = 200; + chgbox_led[i].dark_times = 40; + } + //要根据当前占空比,把cnt计算好, + chgbox_led[i].step_cnt = chgbox_led[i].up_times * chgbox_led[i].cur_duty / chgbox_led[i].max_duty; + } else { + chgbox_led[i].mode = GHGBOX_LED_MODE_OFF; //常暗 + chgbox_led[i].down_times = 20; + chgbox_led[i].step_cnt = chgbox_led[i].down_times - chgbox_led[i].down_times * chgbox_led[i].cur_duty / chgbox_led[i].max_duty; + chgbox_led[i].bre_times = 0; + } + is_led_active = 1; + chgbox_led[i].idle = 0; + chgbox_led[i].busy = 0; + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 呼吸灯全暗 + @param fade:是否淡入 + @return 无 + @note 把所有的灯设置为常暗模式 +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_set_led_all_off(u8 fade) +{ + u8 i; + for (i = 0; i < CHG_LED_MAX; i++) { + chgbox_led[i].busy = 1; + + if (fade) { + chgbox_led[i].step_cnt = chgbox_led[i].down_times - chgbox_led[i].down_times * chgbox_led[i].cur_duty / chgbox_led[i].max_duty; + } else { + chgbox_led[i].step_cnt = 0; + chgbox_led[i].sp_flicker = 0; + chgbox_led[i].cur_duty = 0; + } + chgbox_led[i].mode = GHGBOX_LED_MODE_OFF; //常暗 + chgbox_led[i].down_times = DOWN_TIMES_DEFAULT; + chgbox_led[i].bre_times = 0; + chgbox_led[i].idle = 0; + is_led_active = 1; + chgbox_led[i].busy = 0; + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 呼吸灯全亮 + @param fade:是否淡入 + @return 无 + @note 把所有的灯设置为常亮模式 +*/ +/*------------------------------------------------------------------------------------*/ +void chgbox_set_led_all_on(u8 fade) +{ + u8 i; + for (i = 0; i < CHG_LED_MAX; i++) { + chgbox_led[i].busy = 1; + is_led_active = 1; + if (fade) { + chgbox_led[i].step_cnt = chgbox_led[i].up_times * chgbox_led[i].cur_duty / chgbox_led[i].max_duty; + } else { + chgbox_led[i].step_cnt = 0; + chgbox_led[i].sp_flicker = 0; + chgbox_led[i].cur_duty = chgbox_led[i].max_duty; + } + chgbox_led[i].mode = GHGBOX_LED_MODE_ON; //常亮 + chgbox_led[i].up_times = UP_TIMES_DEFAULT; + chgbox_led[i].bre_times = 0; + chgbox_led[i].idle = 0; + chgbox_led[i].busy = 0; + } +} + +//////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////// +//硬件、软pwm驱动部分(时钟、占空比控制等) +//蓝灯初始化 +static void chg_red_led_init() +{ +#if (CHG_RED_LED_IO != NO_CONFIG_PORT) + gpio_set_die(CHG_RED_LED_IO, 1); + gpio_set_pull_down(CHG_RED_LED_IO, 0); + gpio_set_pull_up(CHG_RED_LED_IO, 0); + gpio_set_die(CHG_RED_LED_IO, 0); + gpio_set_dieh(CHG_RED_LED_IO, 0); + //初始化为暗态 + gpio_direction_output(CHG_RED_LED_IO, !CHG_LED_MODE); +#endif +} + +//蓝灯高低电平控制 +//on_off:1:输出高平电 0:输出低电平 +SEC(.chargebox_code)//频繁调用的放ram里 +static void chg_set_red_led(u8 on_off) +{ +#if CHG_RED_LED_IO != NO_CONFIG_PORT + u8 io_num; + io_num = CHG_RED_LED_IO % 16; + +#if (CHG_LED_MODE == 0) + on_off = !on_off; +#endif + + if (on_off) { +#if(CHG_RED_LED_IO <= IO_PORTA_15) + JL_PORTA->OUT |= BIT(io_num); +#elif(CHG_RED_LED_IO <= IO_PORTB_15) + JL_PORTB->OUT |= BIT(io_num); +#elif(CHG_RED_LED_IO <= IO_PORTC_15) + JL_PORTC->OUT |= BIT(io_num); +#elif(CHG_RED_LED_IO <= IO_PORTD_07) + JL_PORTD->OUT |= BIT(io_num); +#elif(CHG_RED_LED_IO == IO_PORT_DP) + JL_USB_IO->CON0 |= BIT(0); +#elif(CHG_RED_LED_IO == IO_PORT_DM) + JL_USB_IO->CON0 |= BIT(1); +#endif + } else { +#if(CHG_RED_LED_IO <= IO_PORTA_15) + JL_PORTA->OUT &= ~BIT(io_num); +#elif(CHG_RED_LED_IO <= IO_PORTB_15) + JL_PORTB->OUT &= ~BIT(io_num); +#elif(CHG_RED_LED_IO <= IO_PORTC_15) + JL_PORTC->OUT &= ~BIT(io_num); +#elif(CHG_RED_LED_IO <= IO_PORTD_07) + JL_PORTD->OUT &= ~BIT(io_num); +#elif(CHG_RED_LED_IO == IO_PORT_DP) + JL_USB_IO->CON0 &= ~BIT(0); +#elif(CHG_RED_LED_IO == IO_PORT_DM) + JL_USB_IO->CON0 &= ~BIT(1); +#endif + } +#endif +} + +//绿灯初始化 +static void chg_green_led_init() +{ +#if (CHG_GREEN_LED_IO != NO_CONFIG_PORT) + gpio_set_die(CHG_GREEN_LED_IO, 1); + gpio_set_pull_down(CHG_GREEN_LED_IO, 0); + gpio_set_pull_up(CHG_GREEN_LED_IO, 0); + gpio_set_die(CHG_GREEN_LED_IO, 0); + gpio_set_dieh(CHG_GREEN_LED_IO, 0); + //初始化为暗态 + gpio_direction_output(CHG_GREEN_LED_IO, !CHG_LED_MODE); +#endif +} + +//绿灯高低电平控制 +//on_off:1:输出高平电 0:输出低电平 +SEC(.chargebox_code)//频繁调用的放ram里 +static void chg_set_green_led(u8 on_off) +{ +#if (CHG_GREEN_LED_IO != NO_CONFIG_PORT) + u8 io_num; + io_num = CHG_GREEN_LED_IO % 16; + +#if (CHG_LED_MODE == 0) + on_off = !on_off; +#endif + + if (on_off) { +#if(CHG_GREEN_LED_IO <= IO_PORTA_15) + JL_PORTA->OUT |= BIT(io_num); +#elif(CHG_GREEN_LED_IO <= IO_PORTB_15) + JL_PORTB->OUT |= BIT(io_num); +#elif(CHG_GREEN_LED_IO <= IO_PORTC_15) + JL_PORTC->OUT |= BIT(io_num); +#elif(CHG_GREEN_LED_IO <= IO_PORTD_07) + JL_PORTD->OUT |= BIT(io_num); +#elif(CHG_GREEN_LED_IO == IO_PORT_DP) + JL_USB_IO->CON0 |= BIT(0); +#elif(CHG_GREEN_LED_IO == IO_PORT_DM) + JL_USB_IO->CON0 |= BIT(1); +#endif + + } else { +#if(CHG_GREEN_LED_IO <= IO_PORTA_15) + JL_PORTA->OUT &= ~BIT(io_num); +#elif(CHG_GREEN_LED_IO <= IO_PORTB_15) + JL_PORTB->OUT &= ~BIT(io_num); +#elif(CHG_GREEN_LED_IO <= IO_PORTC_15) + JL_PORTC->OUT &= ~BIT(io_num); +#elif(CHG_GREEN_LED_IO <= IO_PORTD_07) + JL_PORTD->OUT &= ~BIT(io_num); +#elif(CHG_GREEN_LED_IO == IO_PORT_DP) + JL_USB_IO->CON0 &= ~BIT(0); +#elif(CHG_GREEN_LED_IO == IO_PORT_DM) + JL_USB_IO->CON0 &= ~BIT(1); +#endif + } +#endif +} + +//蓝灯初始化 +static void chg_blue_led_init() +{ +#if (CHG_BLUE_LED_IO != NO_CONFIG_PORT) + gpio_set_die(CHG_BLUE_LED_IO, 1); + gpio_set_pull_down(CHG_BLUE_LED_IO, 0); + gpio_set_pull_up(CHG_BLUE_LED_IO, 0); + gpio_direction_output(CHG_BLUE_LED_IO, 0); + gpio_set_die(CHG_BLUE_LED_IO, 0); + gpio_set_dieh(CHG_BLUE_LED_IO, 0); + //初始化为暗态 + gpio_direction_output(CHG_BLUE_LED_IO, !CHG_LED_MODE); +#endif +} + +//蓝灯高低电平控制 +//on_off:1:输出高平电 0:输出低电平 +SEC(.chargebox_code) +static void chg_set_blue_led(u8 on_off) +{ +#if (CHG_BLUE_LED_IO != NO_CONFIG_PORT) + u8 io_num; + io_num = CHG_BLUE_LED_IO % 16; + +#if (CHG_LED_MODE == 0) + on_off = !on_off; +#endif + + if (on_off) { +#if(CHG_BLUE_LED_IO <= IO_PORTA_15) + JL_PORTA->OUT |= BIT(io_num); +#elif(CHG_BLUE_LED_IO <= IO_PORTB_15) + JL_PORTB->OUT |= BIT(io_num); +#elif(CHG_BLUE_LED_IO <= IO_PORTC_15) + JL_PORTC->OUT |= BIT(io_num); +#elif(CHG_BLUE_LED_IO <= IO_PORTD_07) + JL_PORTD->OUT |= BIT(io_num); +#elif(CHG_BLUE_LED_IO == IO_PORT_DP) + JL_USB_IO->CON0 |= BIT(0); +#elif(CHG_BLUE_LED_IO == IO_PORT_DM) + JL_USB_IO->CON0 |= BIT(1); +#endif + } else { +#if(CHG_BLUE_LED_IO <= IO_PORTA_15) + JL_PORTA->OUT &= ~BIT(io_num); +#elif(CHG_BLUE_LED_IO <= IO_PORTB_15) + JL_PORTB->OUT &= ~BIT(io_num); +#elif(CHG_BLUE_LED_IO <= IO_PORTC_15) + JL_PORTC->OUT &= ~BIT(io_num); +#elif(CHG_BLUE_LED_IO <= IO_PORTD_07) + JL_PORTD->OUT &= ~BIT(io_num); +#elif(CHG_BLUE_LED_IO == IO_PORT_DP) + JL_USB_IO->CON0 &= ~BIT(0); +#elif(CHG_BLUE_LED_IO == IO_PORT_DM) + JL_USB_IO->CON0 &= ~BIT(1); +#endif + } +#endif +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 呼吸灯占空比控制 + @param i:灯序号 + @return 无 + @note 根据常亮、常暗、呼吸等模式控制占空比 +*/ +/*------------------------------------------------------------------------------------*/ +SEC(.chargebox_code) +static u8 soft_pwm_led_ctrl(u8 i) +{ + u8 ret = 0; + switch (chgbox_led[i].mode) { + case GHGBOX_LED_MODE_ON: //常亮 + if (chgbox_led[i].sp_flicker) { //暗一下(包括了渐暗+暗 两个过程) + if (chgbox_led[i].cur_duty > 0) { + chgbox_led[i].step_cnt++; + if (chgbox_led[i].step_cnt >= chgbox_led[i].down_times) { + chgbox_led[i].step_cnt = 0; + chgbox_led[i].cur_duty = 0; + } else { + chgbox_led[i].cur_duty = (chgbox_led[i].down_times - chgbox_led[i].step_cnt) * chgbox_led[i].max_duty / chgbox_led[i].down_times; + } + } else { + if (chgbox_led[i].sp_flicker_cnt) { //持续暗的时间 + chgbox_led[i].sp_flicker_cnt--; + if (chgbox_led[i].sp_flicker_cnt == 0) { + chgbox_led[i].sp_flicker = 0; //结束暗一下流程 + } + } + } + } else if (chgbox_led[i].cur_duty < chgbox_led[i].max_duty) { + chgbox_led[i].step_cnt++; + if (chgbox_led[i].step_cnt >= chgbox_led[i].up_times) { + chgbox_led[i].step_cnt = 0; + chgbox_led[i].cur_duty = chgbox_led[i].max_duty; + } else { + //这里为了避免灯光突变,根据改变前的亮度来计算了cnt + chgbox_led[i].cur_duty = chgbox_led[i].step_cnt * chgbox_led[i].max_duty / chgbox_led[i].up_times; + } + } + break; + case GHGBOX_LED_MODE_OFF://常暗 + if (chgbox_led[i].sp_flicker) { //亮一下 + if (chgbox_led[i].cur_duty < chgbox_led[i].max_duty) { + chgbox_led[i].step_cnt++; + if (chgbox_led[i].step_cnt >= chgbox_led[i].up_times) { + chgbox_led[i].step_cnt = 0; + chgbox_led[i].cur_duty = chgbox_led[i].max_duty; + } else { + //这里为了避免灯光突变,根据改变前的亮度来计算了cnt + chgbox_led[i].cur_duty = chgbox_led[i].step_cnt * chgbox_led[i].max_duty / chgbox_led[i].up_times; + } + } else { + if (chgbox_led[i].sp_flicker_cnt) { //持续亮的时间 + chgbox_led[i].sp_flicker_cnt--; + if (chgbox_led[i].sp_flicker_cnt == 0) { + chgbox_led[i].sp_flicker = 0; //结束亮一下流程 + } + } + } + } else if (chgbox_led[i].cur_duty > 0) { + chgbox_led[i].step_cnt++; + if (chgbox_led[i].step_cnt >= chgbox_led[i].down_times) { + chgbox_led[i].step_cnt = 0; + chgbox_led[i].cur_duty = 0; + } else { + //这里为了避免灯光突变,根据改变前的亮度来计算了cnt + chgbox_led[i].cur_duty = (chgbox_led[i].down_times - chgbox_led[i].step_cnt) * chgbox_led[i].max_duty / chgbox_led[i].down_times; + } + } else { + ret = 1; + } + break; + case GHGBOX_LED_MODE_BRE://呼吸灯模式 + if (chgbox_led[i].bre_times == 0) { + ret = 1; + break; + } + + if (chgbox_led[i].step == SOFT_LED_STEP_UP) { + chgbox_led[i].step_cnt++; + if (chgbox_led[i].step_cnt >= chgbox_led[i].up_times) { //当前段结束 + chgbox_led[i].step_cnt = 0; + chgbox_led[i].step++; //进入下一个步骤 + } else { + chgbox_led[i].cur_duty = chgbox_led[i].step_cnt * chgbox_led[i].max_duty / chgbox_led[i].up_times; + } + } else if (chgbox_led[i].step == SOFT_LED_STEP_LIGHT) { + chgbox_led[i].step_cnt++; + chgbox_led[i].cur_duty = chgbox_led[i].max_duty; + if (chgbox_led[i].step_cnt >= chgbox_led[i].light_times) { + chgbox_led[i].step_cnt = 0; + chgbox_led[i].step++; + } + } else if (chgbox_led[i].step == SOFT_LED_STEP_DOWN) { + chgbox_led[i].step_cnt++; + if (chgbox_led[i].step_cnt >= chgbox_led[i].down_times) { + chgbox_led[i].step_cnt = 0; + chgbox_led[i].step++; + } else { + chgbox_led[i].cur_duty = (chgbox_led[i].down_times - chgbox_led[i].step_cnt) * chgbox_led[i].max_duty / chgbox_led[i].down_times; + } + } else if (chgbox_led[i].step == SOFT_LED_STEP_DARK) { + chgbox_led[i].step_cnt++; + chgbox_led[i].cur_duty = 0; + if (chgbox_led[i].step_cnt >= chgbox_led[i].dark_times) { + chgbox_led[i].step_cnt = 0; + chgbox_led[i].step = 0; //重新开始下一次呼吸 + if (chgbox_led[i].bre_times != 0xffff) { //非循环 + chgbox_led[i].bre_times--; //呼吸次数递减 + } + } + } + break; + case CHGBOX_LED_MODE_FLASH: + if (chgbox_led[i].bre_times == 0) { + ret = 1; + break; + } + if (chgbox_led[i].step == SOFT_LED_STEP_UP) { + chgbox_led[i].cur_duty = chgbox_led[i].max_duty; + chgbox_led[i].step_cnt++; + if (chgbox_led[i].step_cnt >= chgbox_led[i].up_times + chgbox_led[i].light_times) { + chgbox_led[i].step_cnt = 0; + chgbox_led[i].step = SOFT_LED_STEP_DOWN; + } + } else if (chgbox_led[i].step == SOFT_LED_STEP_DOWN) { + chgbox_led[i].cur_duty = 0; + chgbox_led[i].step_cnt++; + if (chgbox_led[i].step_cnt >= chgbox_led[i].down_times + chgbox_led[i].dark_times) { + chgbox_led[i].step_cnt = 0; + chgbox_led[i].step = SOFT_LED_STEP_UP; + if (chgbox_led[i].bre_times != 0xffff) { //非循环 + chgbox_led[i].bre_times--; //次数递减 + } + } + } else { + chgbox_led[i].bre_times = 0; + chgbox_led[i].cur_duty = 0; + } + break; + } + return ret; +} + +#define TIMER_USE_MC_PWM 0 +#if TIMER_USE_MC_PWM == 0 +#define JL_TIMERx JL_TIMER5 +#define IRQ_TIMEX_IDX IRQ_TIME5_IDX +#define TIMERX_IOS_BIT 21 +#define TIMERX_IOS_CLK 12000000 +#endif + +/*------------------------------------------------------------------------------------*/ +/**@brief mc_clk中断回调 + @param 无 + @return 无 + @note 用于循环所有的呼吸灯,包括亮暗控制,占空比设置等 +*/ +/*------------------------------------------------------------------------------------*/ +SEC(.chargebox_code) +___interrupt +void soft_pwm_led_isr(void) +{ +#if TIMER_USE_MC_PWM + JL_MCPWM->TMR0_CON |= BIT(10); //清pending +#else + JL_TIMERx->CON |= BIT(14); +#endif + u8 i, led_idle = 0; + + for (i = 0; i < CHG_LED_MAX; i++) { //循环所有的灯 + if (!chgbox_led[i].busy) { + if (chgbox_led[i].p_cnt < (chgbox_led[i].cur_duty)) { //占空比 + chgbox_led[i].led_on_off(1); //亮 + } else { + chgbox_led[i].led_on_off(0); + } + chgbox_led[i].p_cnt++; + if (chgbox_led[i].p_cnt >= SOFT_MC_PWM_MAX) { //完成一个PWM周期 + chgbox_led[i].p_cnt = 0; + chgbox_led[i].idle = soft_pwm_led_ctrl(i);//占空比控制 + } + } + led_idle += chgbox_led[i].idle; + } + if (led_idle == CHG_LED_MAX) { + is_led_active = 0; + } +} + +#if TIMER_USE_MC_PWM +static const u32 timer_div_mc[] = { + 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192, 16384, 32768 +}; +#else +static const u32 timer_div_mc[] = { + 1, 4, 16, 64, 1 * 2, 4 * 2, 16 * 2, 64 * 2, 1 * 256, 4 * 256, 16 * 256, 64 * 256, 1 * 2 * 256, 4 * 2 * 256, 16 * 2 * 256, 64 * 2 * 256 +}; +#endif +#define MC_MAX_TIME_CNT 0x7fff +#define MC_MIN_TIME_CNT 0x10 +/*------------------------------------------------------------------------------------*/ +/**@brief mc_clk的初始化 + @param 无 + @return 无 + @note 初始clk,注册中断,MC_TIMER_UNIT_US 为起中断的时间,单位us +*/ +/*------------------------------------------------------------------------------------*/ +void mc_clk_init(void) +{ +#if TIMER_USE_MC_PWM + //br25 没有mcpwm + u32 prd_cnt; + u8 index; + + JL_MCPWM->TMR0_CON = BIT(10); //清pending,清其他bit + JL_MCPWM->MCPWM_CON0 = 0; + + for (index = 0; index < (sizeof(timer_div_mc) / sizeof(timer_div_mc[0])); index++) { + prd_cnt = MC_TIMER_UNIT_US * (clk_get("lsb") / 1000000) / timer_div_mc[index]; + if (prd_cnt > MC_MIN_TIME_CNT && prd_cnt < MC_MAX_TIME_CNT) { + break; + } + } + + JL_MCPWM->TMR0_CNT = 0; + JL_MCPWM->TMR0_PR = prd_cnt; + JL_MCPWM->TMR0_CON |= index << 3; //分频系数 + + request_irq(IRQ_MCTMRX_IDX, 3, soft_pwm_led_isr, 0); + + JL_MCPWM->TMR0_CON |= BIT(8); //允许定时溢出中断 + JL_MCPWM->TMR0_CON |= BIT(0); //递增模式 + + JL_MCPWM->MCPWM_CON0 |= BIT(8); //只开mc timer 0 + log_info("prd_cnt:%d,index:%d,t0:%x,MCP:%x\n", prd_cnt, index, JL_MCPWM->TMR0_CON, JL_MCPWM->MCPWM_CON0); + log_info("lsb:%d\n", clk_get("lsb")); +#else + u32 timer_clk; + u32 prd_cnt; + u8 index; + JL_TIMERx->CON = BIT(14); + JL_TIMERx->CNT = 0; + +#if (TCFG_CLOCK_SYS_SRC == SYS_CLOCK_INPUT_PLL_RCL) + timer_clk = TIMERX_IOS_CLK; +#else + timer_clk = clk_get("timer"); +#endif + + for (index = 0; index < (sizeof(timer_div_mc) / sizeof(timer_div_mc[0])); index++) { + prd_cnt = MC_TIMER_UNIT_US * (timer_clk / 1000000) / timer_div_mc[index]; + if (prd_cnt > MC_MIN_TIME_CNT && prd_cnt < MC_MAX_TIME_CNT) { + break; + } + } + //初始化timer + request_irq(IRQ_TIMEX_IDX, 3, soft_pwm_led_isr, 0); + JL_TIMERx->PRD = prd_cnt; +#if (TCFG_CLOCK_SYS_SRC == SYS_CLOCK_INPUT_PLL_RCL) + JL_IOMAP->CON0 |= BIT(TIMERX_IOS_BIT); + JL_TIMERx->CON = (index << 4) | BIT(0) | BIT(2);//省晶振使用pll12m为时钟源 +#else + JL_TIMERx->CON = (index << 4) | (0b10 << 2) | (0b01 << 0);//OSC时钟 +#endif +#endif +} + +/*------------------------------------------------------------------------------------*/ +/**@brief led呼吸灯初始化 + @param 无 + @return 无 + @note 初始化每个led:渐亮、亮、渐暗、暗,最大亮度,对应IO的初始化.mc_clk的初始化,用于 + 控制pwm +*/ +/*-----------------------------------------------------------------------------------*/ +void chgbox_led_init(void) +{ + u8 i; + for (i = 0; i < CHG_LED_MAX; i++) { //循环所有的灯 + memset(&chgbox_led[i], 0x0, sizeof(CHG_SOFT_PWM_LED)); + chgbox_led[i].up_times = UP_TIMES_DEFAULT; + chgbox_led[i].light_times = 100; + chgbox_led[i].down_times = DOWN_TIMES_DEFAULT; + chgbox_led[i].dark_times = 10; + chgbox_led[i].bre_times = 0; + + //可根据需要修改初始化,但要把初始化与亮灭注册进来 + if (i == CHG_LED_RED) { + chgbox_led[i].led_on_off = chg_set_red_led; + chgbox_led[i].led_init = chg_red_led_init; + chgbox_led[i].max_duty = SOFT_MC_PWM_MAX * BRIGHTNESS_MAX / 100; + chgbox_led[i].mode = GHGBOX_LED_MODE_OFF; + } else if (i == CHG_LED_GREEN) { + chgbox_led[i].led_on_off = chg_set_green_led; + chgbox_led[i].led_init = chg_green_led_init; + chgbox_led[i].max_duty = SOFT_MC_PWM_MAX * BRIGHTNESS_MAX / 100; + chgbox_led[i].mode = GHGBOX_LED_MODE_OFF; + } else if (i == CHG_LED_BLUE) { + chgbox_led[i].led_on_off = chg_set_blue_led; + chgbox_led[i].led_init = chg_blue_led_init; + chgbox_led[i].max_duty = SOFT_MC_PWM_MAX * BRIGHTNESS_MAX / 100; + chgbox_led[i].mode = GHGBOX_LED_MODE_OFF; + } + chgbox_led[i].led_init(); + } + mc_clk_init(); +} + +#endif + +#endif diff --git a/apps/common/charge_box/chgbox_wireless.c b/apps/common/charge_box/chgbox_wireless.c new file mode 100644 index 0000000..726b48f --- /dev/null +++ b/apps/common/charge_box/chgbox_wireless.c @@ -0,0 +1,575 @@ +#include "gpio.h" +#include "app_config.h" +#include "system/includes.h" +#include "device/wireless_charge.h" +#include "chgbox_ctrl.h" +#include "asm/adc_api.h" +#include "chgbox_box.h" +#include "device/chargebox.h" +#include "chgbox_wireless.h" + +#if (TCFG_CHARGE_BOX_ENABLE) + +#define LOG_TAG_CONST APP_CHGBOX +#define LOG_TAG "[CHG_WL]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +extern void delay_2ms(int cnt); +extern void wireless_port_set_wakeup_enable(u8 enable); + +/////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////无线充///////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////////////// +#if(defined TCFG_WIRELESS_ENABLE) && (TCFG_WIRELESS_ENABLE) + +_wireless_hdl wl_hdl; +#define __this (&wl_hdl) + +static u16 wl_send_buff[10] __attribute__((aligned(4))); //10 * =20byte +static int wl_100ms_timer, wl_ad_timer, wl_ad_timeout; +static u32 g_wireless_voltage; +static u8 wl_send_over_msg, wl_init_ok; + +//控制充电口电压范围 +#define VOLTAGE_MIN 6100 +#define VOLTAGE_MAX 6200 + +//取中间 (AD_OK_COUNTS-AD_CUT_COUNTS*2)计算均值(去掉头部与尾部) +#define AD_OK_COUNTS 5 +#define AD_CUT_COUNTS 1 + +//无线充上线检测 +#define WL_ONLINE_VOLT 3500 ///电压大于3.5才认为是有充电器放上来 +#define WL_ONLINE_TIMES 3 +#define WL_OFFLINE_TIMES 5 + +static u16 power_table[AD_OK_COUNTS]; +static u16 power_table_tmp[AD_OK_COUNTS]; + +//无线充电通信的时候不能进入低功耗 +static volatile u8 is_wl_comm_active = 0; +static u8 wl_comm_idle_query(void) +{ + return (!is_wl_comm_active); +} +REGISTER_LP_TARGET(wl_comm_lp_target) = { + .name = "chgbox_wl_comm", + .is_idle = wl_comm_idle_query, +}; + +/*------------------------------------------------------------------------------------*/ +/**@brief timer2中断回调 + @param 无 + @return 无 + @note 注意调用的所有代码需放在ram里 +*/ +/*------------------------------------------------------------------------------------*/ +SEC(.chargebox_code) +___interrupt +static void wl_timer2_isr(void) +{ + JL_TIMER2->CON |= BIT(14); + wireless_250us_run(); +} + +static const u32 timer_div[] = { + /*0000*/ 1, + /*0001*/ 4, + /*0010*/ 16, + /*0011*/ 64, + /*0100*/ 2, + /*0101*/ 8, + /*0110*/ 32, + /*0111*/ 128, + /*1000*/ 256, + /*1001*/ 4 * 256, + /*1010*/ 16 * 256, + /*1011*/ 64 * 256, + /*1100*/ 2 * 256, + /*1101*/ 8 * 256, + /*1110*/ 32 * 256, + /*1111*/ 128 * 256, +}; +#define MAX_TIME_CNT 0x7fff +#define MIN_TIME_CNT 0x100 +#define WL_TIMER_UNIT_US 250 //单位us +/*------------------------------------------------------------------------------------*/ +/**@brief 开启timer2模块 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +static void wl_timer2_open(void) +{ + u32 prd_cnt, timer_clk; + u8 index; +#if (TCFG_CLOCK_SYS_SRC == SYS_CLOCK_INPUT_PLL_RCL) + timer_clk = clk_get("lsb"); +#else + timer_clk = clk_get("timer"); +#endif + JL_TIMER2->CON = BIT(14);//清pending + for (index = 0; index < (sizeof(timer_div) / sizeof(timer_div[0])); index++) { + prd_cnt = WL_TIMER_UNIT_US * (timer_clk / 1000000) / timer_div[index]; + if (prd_cnt > MIN_TIME_CNT && prd_cnt < MAX_TIME_CNT) { + break; + } + } + JL_TIMER2->CNT = 0; + JL_TIMER2->PRD = prd_cnt; + request_irq(IRQ_TIME2_IDX, 3, wl_timer2_isr, 0); +#if (TCFG_CLOCK_SYS_SRC == SYS_CLOCK_INPUT_PLL_RCL) + JL_TIMER2->CON = (index << 4) | BIT(0); //lsb clk +#else + JL_TIMER2->CON = (index << 4) | BIT(0) | BIT(3); //osc clk +#endif + is_wl_comm_active = 1; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 关闭timer2模块 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +static void wl_timer2_close(void) +{ + JL_TIMER2->CON = BIT(14); + is_wl_comm_active = 0; +} + +///dcdc en IO初始化 +static void dcdc_io_init(void) +{ +#if TCFG_DCDC_CTRL_EN + gpio_set_die(TCFG_DCDC_EN_IO, 0); + gpio_set_pull_down(TCFG_DCDC_EN_IO, 0); + gpio_set_pull_up(TCFG_DCDC_EN_IO, 0); + gpio_direction_output(TCFG_DCDC_EN_IO, 0); +#endif +} + +/*------------------------------------------------------------------------------------*/ +/**@brief DCDC使能 + @param 无 + @return 无 + @note 使能后才能正常充电 +*/ +/*------------------------------------------------------------------------------------*/ +static void dcdc_set_en(u8 en) +{ +#if TCFG_DCDC_CTRL_EN + log_info("dcdc en: %d\n", en); + if (en) { + gpio_direction_output(TCFG_DCDC_EN_IO, 1); + } else { + gpio_direction_output(TCFG_DCDC_EN_IO, 0); + } +#endif +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 无线充通信口初始化 + @param 无 + @return 无 +*/ +/*------------------------------------------------------------------------------------*/ +static void wpc_io_init(void) +{ + gpio_set_die(TCFG_WPC_COMM_IO, 1); + gpio_set_pull_down(TCFG_WPC_COMM_IO, 0); + gpio_set_pull_up(TCFG_WPC_COMM_IO, 0); + gpio_direction_output(TCFG_WPC_COMM_IO, 0); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 无线充AD检测上下线IO初始化 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +static void wl_ad_det_init(u8 die_en) +{ + gpio_set_die(TCFG_WL_AD_DET_IO, die_en); + gpio_set_direction(TCFG_WL_AD_DET_IO, 1); + gpio_set_pull_down(TCFG_WL_AD_DET_IO, 0); + gpio_set_pull_up(TCFG_WL_AD_DET_IO, 0); + if (!die_en) { + gpio_set_pull_down(TCFG_WL_AD_DET_IO, 1); + adc_add_sample_ch(TCFG_WL_AD_DET_CH); + wireless_port_set_wakeup_enable(0); + } else { + wireless_port_set_wakeup_enable(1); + } +} + +SEC(.chargebox_code) +static u32 wl_read_ad_io_status(void) +{ + u32 v = 0; + u32 mask = TCFG_WL_AD_DET_IO % IO_GROUP_NUM; +#if (TCFG_WL_AD_DET_IO <= IO_PORTA_15) + v = !!(JL_PORTA->IN & BIT(mask)); +#elif(TCFG_WL_AD_DET_IO <= IO_PORTB_15) + v = !!(JL_PORTB->IN & BIT(mask)); +#elif(TCFG_WL_AD_DET_IO <= IO_PORTC_15) + v = !!(JL_PORTC->IN & BIT(mask)); +#elif(TCFG_WL_AD_DET_IO <= IO_PORTD_7) + v = !!(JL_PORTD->IN & BIT(mask)); +#endif + return v; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 获取无线充输入电压 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +static u16 get_wireless_voltage(void) +{ + u16 volt; + //注意分压,上下拉及外部路相关, 默认开下拉四分一 + volt = adc_get_voltage(TCFG_WL_AD_DET_CH) * 4; + return volt; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 无线充100ms调用 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +static void wireless_100ms_run_app(void *priv) +{ + if (sys_info.temperature_limit) { + if (sys_info.status[WIRELESS_DET] == STATUS_ONLINE) { + sys_info.status[WIRELESS_DET] = STATUS_OFFLINE; + app_chargebox_event_to_user(CHGBOX_EVENT_WIRELESS_OFFLINE); + } + return; + } + //查看是否有数据需要发送 + wireless_100ms_run(); + if (__this->info.busy) { + wl_timer2_open(); + } +} +/*------------------------------------------------------------------------------------*/ +/**@brief 通过电压数组计算均值 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +static u16 wireless_calc_power(void) +{ + u8 i, j, k; + u16 ad_sum, ad_min; + memcpy(power_table_tmp, power_table, sizeof(power_table)); + for (i = 1; i < AD_OK_COUNTS; i++) { + for (j = i; j > 0; j--) { + if (power_table_tmp[j] < power_table_tmp[j - 1]) { + ad_min = power_table_tmp[j]; + power_table_tmp[j] = power_table_tmp[j - 1]; + power_table_tmp[j - 1] = ad_min; + } + } + } + ad_sum = 0; + for (k = AD_CUT_COUNTS; k < (AD_OK_COUNTS - AD_CUT_COUNTS); k++) { + ad_sum = power_table_tmp[k] + ad_sum; + } + ad_sum = (ad_sum / (AD_OK_COUNTS - (AD_CUT_COUNTS * 2))); + return ad_sum; +} + +static void wireless_ad_detect_run(void *priv) +{ + static u8 power_cnt = 0; + u16 power_tmp; + power_tmp = get_wireless_voltage(); + power_table[power_cnt++] = power_tmp; + if (power_cnt >= AD_OK_COUNTS) { + usr_timer_del(wl_ad_timer); + wl_ad_timer = 0; + wl_ad_timeout = 0; + power_cnt = 0; + g_wireless_voltage = wireless_calc_power(); + if (g_wireless_voltage < WL_ONLINE_VOLT) { + sys_info.status[WIRELESS_DET] = STATUS_OFFLINE; + app_chargebox_event_to_user(CHGBOX_EVENT_WIRELESS_OFFLINE); + } + log_info("wireless_power: %d mV\n", g_wireless_voltage); + } +} + +static void wireless_ad_detect_start(void *priv) +{ + if (wl_ad_timer == 0) { + wl_ad_timer = usr_timer_add(NULL, wireless_ad_detect_run, 10, 1);//10ms + } +} + +static void wireless_ad_detect_init(void) +{ + if (wl_ad_timeout == 0) { + wl_ad_timeout = sys_timeout_add(NULL, wireless_ad_detect_start, 25); + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 获取无线充当前提供的电压 + @param 无 + @return 无 + @note +*/ +/*------------------------------------------------------------------------------------*/ +u16 get_wireless_power(void) +{ + return g_wireless_voltage; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 无线充通信io设置 + @param 无 + @return 无 + @note 供库调用,注意代码要放ram +*/ +/*------------------------------------------------------------------------------------*/ +SEC(.chargebox_code) +void wpc_io_set(u8 mode) +{ + u8 io_num; + switch (mode) { + case IO_HIGH: + gpio_direction_output(TCFG_WPC_COMM_IO, 1); + break; + case IO_LOW: + gpio_direction_output(TCFG_WPC_COMM_IO, 0); + wl_timer2_close(); //最后一个动作后关闭 + if (wl_send_over_msg) { + app_chargebox_event_to_user(CHGBOX_EVENT_WL_DATA_OVER); + } + break; + case IO_INIT: + gpio_set_die(TCFG_WPC_COMM_IO, 1); + gpio_set_pull_down(TCFG_WPC_COMM_IO, 0); + gpio_set_pull_up(TCFG_WPC_COMM_IO, 0); + gpio_direction_output(TCFG_WPC_COMM_IO, 0); + break; + case IO_OVERTURN://翻转 + io_num = TCFG_WPC_COMM_IO % IO_GROUP_NUM; +#if(TCFG_WPC_COMM_IO <= IO_PORTA_15) + JL_PORTA->OUT ^= BIT(io_num); +#elif(TCFG_WPC_COMM_IO <= IO_PORTB_15) + JL_PORTB->OUT ^= BIT(io_num); +#elif(TCFG_WPC_COMM_IO <= IO_PORTC_15) + JL_PORTC->OUT ^= BIT(io_num); +#elif(TCFG_WPC_COMM_IO <= IO_PORTD_7) + JL_PORTD->OUT ^= BIT(io_num); +#endif + break; + case IO_DIR_IN: //高阻 + gpio_direction_input(TCFG_WPC_COMM_IO); + break; + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 无线充发送一个数据包封装 + @param 无 + @return 无 + @note 仅在握手阶段调用!!! +*/ +/*------------------------------------------------------------------------------------*/ +static bool wireless_send_pack_deal(void) +{ + bool ret = true; + local_irq_disable(); + wl_timer2_open(); + __this->info.busy = 1; + while (__this->info.busy) { + asm("nop"); + if (JL_TIMER2->CON & BIT(15)) { + JL_TIMER2->CON |= BIT(14); + wireless_250us_run(); + } + if (wl_read_ad_io_status() == 0) { + ret = false; + break; + } + } + wl_timer2_close(); + local_irq_enable(); + if (ret == false) { + sys_info.status[WIRELESS_DET] = STATUS_OFFLINE; + app_chargebox_event_to_user(CHGBOX_EVENT_WIRELESS_OFFLINE); + } + return ret; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 打开无线充模块 + @param 无 + @return 无 + @note 检测到无线充上线时调用,发送相关的初始化指令 +*/ +/*------------------------------------------------------------------------------------*/ +void wireless_api_open(void) +{ + if (sys_info.temperature_limit) { + sys_info.status[WIRELESS_DET] = STATUS_OFFLINE; + app_chargebox_event_to_user(CHGBOX_EVENT_WIRELESS_OFFLINE); + return; + } + + wireless_open(VOLTAGE_MIN, VOLTAGE_MAX); + + //发送信号强度包 + get_signal_value(); + if (wireless_send_pack_deal() == false) { + goto __err_exit; + } + + //发送身份包 + delay_2ms(3); + get_identification(); + if (wireless_send_pack_deal() == false) { + goto __err_exit; + } + + //发送配置包 + delay_2ms(3); + get_configuration(); + if (wireless_send_pack_deal() == false) { + goto __err_exit; + } + + wl_ad_det_init(0);//初始化成模拟口 + app_chargebox_event_to_user(CHGBOX_EVENT_WL_DATA_OVER); + wl_100ms_timer = sys_timer_add(NULL, wireless_100ms_run_app, 100); + wl_send_over_msg = 1; + return; + +__err_exit: + wireless_close(); + return; +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 关闭无线充模块 + @param 无 + @return 无 + @note 无线充下线时调用 +*/ +/*------------------------------------------------------------------------------------*/ +void wireless_api_close(void) +{ + wireless_close(); + dcdc_set_en(0); + wl_ad_det_init(1); + wl_send_over_msg = 0; + if (wl_100ms_timer) { + sys_timer_del(wl_100ms_timer); + wl_100ms_timer = 0; + } +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 无线充上线检测 + @param 无 + @return 无 + @note 利用AD值检测无线充的上线 +*/ +/*------------------------------------------------------------------------------------*/ +static int wireless_on_det_timer; +static void wireless_online_det(void *priv) +{ + u16 power_voltage; + static u16 wl_on_detect_cnt = 0; + static u16 wl_off_detect_cnt = 0; + sys_info.life_cnt = 0; + power_voltage = get_wireless_voltage(); + if (power_voltage >= WL_ONLINE_VOLT) { + wl_on_detect_cnt++; + wl_off_detect_cnt = 0; + g_wireless_voltage += power_voltage; + if (wl_on_detect_cnt >= WL_ONLINE_TIMES) { + wl_on_detect_cnt = 0; + g_wireless_voltage = g_wireless_voltage / WL_ONLINE_TIMES; + sys_info.status[WIRELESS_DET] = STATUS_ONLINE; + app_chargebox_event_to_user(CHGBOX_EVENT_WIRELESS_ONLINE); + goto __online_det_exit; + } + } else { + wl_off_detect_cnt++; + wl_on_detect_cnt = 0; + g_wireless_voltage = 0; + if (wl_off_detect_cnt >= WL_OFFLINE_TIMES) { + wl_off_detect_cnt = 0; + goto __online_det_exit; + } + } + return; +__online_det_exit: + wl_ad_det_init(1);//初始化成数字口 + usr_timer_del(wireless_on_det_timer); + wireless_on_det_timer = 0; +} + +void wireless_io_wakeup_deal(void) +{ + if (!wl_init_ok) { + return; + } + if ((sys_info.status[WIRELESS_DET] == STATUS_OFFLINE) && (wireless_on_det_timer == 0)) { + wl_ad_det_init(0);//初始化成AD口 + wireless_on_det_timer = usr_timer_add(NULL, wireless_online_det, 5, 1);//6ms + } +} + +void wireless_data_over_run(void) +{ + if (sys_info.status[WIRELESS_DET] == STATUS_OFFLINE) { + return; + } + wireless_ad_detect_init(); +} + +/*------------------------------------------------------------------------------------*/ +/**@brief 无线充模块初始化 + @param 无 + @return 无 + @note 初始化控制结构体、ad、对应的io,注册相关接口 +*/ +/*------------------------------------------------------------------------------------*/ +void wireless_init_api(void) +{ + ///注意顺序不能改变 + memset(__this, 0x0, sizeof(_wireless_hdl)); + //AD采集初始化 + wl_ad_det_init(1); + dcdc_io_init(); + wpc_io_init(); + wl_send_over_msg = 0; + __this->get_wl_power = get_wireless_power; + __this->dcdc_en_set = dcdc_set_en; + __this->wpc_set = wpc_io_set; + __this->send_buff = wl_send_buff; + wireless_lib_init(__this, VOLTAGE_MIN, VOLTAGE_MAX); + wl_init_ok = 1; +} +#endif//end of WIRELESS_ENABLE + +#endif diff --git a/apps/common/charge_box/chgbox_wireless.h b/apps/common/charge_box/chgbox_wireless.h new file mode 100644 index 0000000..c0e3b94 --- /dev/null +++ b/apps/common/charge_box/chgbox_wireless.h @@ -0,0 +1,14 @@ +#ifndef _CHGBOX_WIRELESS_H_ +#define _CHGBOX_WIRELESS_H_ + +#include "device/wireless_charge.h" + +//api函数声明 +u16 get_wireless_power(void); +void wireless_api_close(void); +void wireless_api_open(void); +void wireless_init_api(void); +void wireless_io_wakeup_deal(void); +void wireless_data_over_run(void); + +#endif diff --git a/apps/common/config/app_config.c b/apps/common/config/app_config.c new file mode 100644 index 0000000..6509126 --- /dev/null +++ b/apps/common/config/app_config.c @@ -0,0 +1,121 @@ +#include "system/includes.h" +#include "app_config.h" +#include "config/config_interface.h" + +#define LOG_TAG "[APP-CONFIG]" +#define LOG_ERROR_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#include "debug.h" + + +extern void dec_eq_test(); +static int sdfile_test(const char *name); +int jl_cfg_dec_test(void); + +ci_transport_config_uart_t config = { + CI_TRANSPORT_CONFIG_UART, + 115200, + 0, + 0, + NULL, +}; + +#if (TCFG_ONLINE_ENABLE || TCFG_SOUNDBOX_TOOL_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +void config_online_init() +{ + log_info("-------online Config Start-------"); + config_layer_init(ci_transport_uart_instance(), &config); +} +__initcall(config_online_init); +#endif +#endif + +void config_test(void) +{ + +#if 1 + log_info("-------EQ online Config Start-------"); + + sys_clk_set(SYS_48M); + + //Setup dev input + config_layer_init(ci_transport_uart_instance(), &config); + + dec_eq_test(); + while (1) { + extern void clr_wdt(); + clr_wdt(); + } +#endif + +#if 0 + log_info("-------SDFile test Start------"); + +#ifdef SDFILE_DEV + +#define SDFILE_NAME1 SDFILE_ROOT_PATH"xx.bin" + + void *mnt = mount(SDFILE_DEV, SDFILE_MOUNT_PATH, "jlfs", 0, NULL); + if (mnt == NULL) { + log_error("mount jlfs failed"); + } + + sdfile_test(SDFILE_NAME1); + +#endif /*SDFILE_DEV*/ + +#endif + +#if 0 + log_info("--------JL CFG test Start------"); + + jl_cfg_dec_test(); +#endif + while (1); +} + +static int sdfile_test(const char *name) +{ + log_d("SDFILE file path: %s", name); + FILE *fp = NULL; + u8 buf[16]; + u8 len; + + fp = fopen(name, "r"); + if (!fp) { + log_d("sdfile open file ERR!"); + return -1; + } + + len = fread(fp, buf, sizeof(buf)); + + if (len != sizeof(buf)) { + log_d("0-read file ERR!"); + goto _end; + } + + put_buf(buf, sizeof(buf)); + + fseek(fp, 16, SEEK_SET); + + len = fread(fp, buf, sizeof(buf)); + + if (len != sizeof(buf)) { + log_d("1-read file ERR!"); + goto _end; + } + + put_buf(buf, sizeof(buf)); + + log_d("SDFILE ok!"); + +_end: + if (fp) { + fclose(fp); + } + + + return 0; +} diff --git a/apps/common/config/bt_profile_config.c b/apps/common/config/bt_profile_config.c new file mode 100644 index 0000000..0b12fa8 --- /dev/null +++ b/apps/common/config/bt_profile_config.c @@ -0,0 +1,197 @@ +#include "system/includes.h" +#include "app_config.h" +#include "btcontroller_config.h" +#include "btstack/bt_profile_config.h" +#include "bt_common.h" + +#define LOG_TAG "[BT-CFG]" +#define LOG_ERROR_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#include "debug.h" + + +#if TCFG_APP_BT_EN + +typedef struct { + // linked list - assert: first field + void *offset_item; + + // data is contained in same memory + u32 service_record_handle; + u8 *service_record; +} service_record_item_t; + +extern const u8 sdp_pnp_service_data[]; +extern const u8 sdp_a2dp_service_data[]; +extern const u8 sdp_avctp_ct_service_data[]; +extern const u8 sdp_avctp_ta_service_data[]; +extern const u8 sdp_hfp_service_data[]; +extern const u8 sdp_spp_service_data[]; +extern const u8 sdp_hid_service_data[]; +extern service_record_item_t sdp_record_item_begin[]; +extern service_record_item_t sdp_record_item_end[]; + +#define SDP_RECORD_HANDLER_REGISTER(handler) \ + const service_record_item_t handler \ + sec(.sdp_record_item) + +#if TCFG_USER_BLE_ENABLE + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) +const int config_stack_modules = (BT_BTSTACK_CLASSIC | BT_BTSTACK_LE_ADV); +#else +const int config_stack_modules = BT_BTSTACK_CLASSIC | BT_BTSTACK_LE; +#endif + +#else +const int config_stack_modules = BT_BTSTACK_CLASSIC; +#endif + +#if (USER_SUPPORT_PROFILE_PNP==1) +SDP_RECORD_HANDLER_REGISTER(pnp_sdp_record_item) = { + .service_record = (u8 *)sdp_pnp_service_data, + .service_record_handle = 0x1000A, +}; +#endif + +#if (USER_SUPPORT_PROFILE_A2DP==1) +u8 a2dp_profile_support = 1; +SDP_RECORD_HANDLER_REGISTER(a2dp_sdp_record_item) = { + .service_record = (u8 *)sdp_a2dp_service_data, + .service_record_handle = 0x00010001, +}; +#endif +#if (USER_SUPPORT_PROFILE_AVCTP==1) +u8 acp_profile_support = 1; +SDP_RECORD_HANDLER_REGISTER(arp_ct_sdp_record_item) = { + .service_record = (u8 *)sdp_avctp_ct_service_data, + .service_record_handle = 0x00010002, +}; +#if BT_SUPPORT_MUSIC_VOL_SYNC +SDP_RECORD_HANDLER_REGISTER(arp_ta_sdp_record_item) = { + .service_record = (u8 *)sdp_avctp_ta_service_data, + .service_record_handle = 0x00010005, +}; +#endif +#endif +#if (USER_SUPPORT_PROFILE_HFP==1) +u8 hfp_profile_support = 1; +SDP_RECORD_HANDLER_REGISTER(hfp_sdp_record_item) = { + .service_record = (u8 *)sdp_hfp_service_data, + .service_record_handle = 0x00010003, +}; +#endif +#if (USER_SUPPORT_PROFILE_SPP==1) + +u8 spp_up_profile_support = 1; +//FE010000-1234-5678-ABCD-00805F9B34FB +const u8 sdp_user_spp_service_data[96] = { + 0x36, 0x00, 0x5B, 0x09, 0x00, 0x00, 0x0A, 0x00, 0x01, 0x00, 0x11, 0x09, 0x00, 0x01, 0x36, 0x00, + 0x11, 0x1C, 0xfe, 0x01, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0xab, 0xcd, 0x00, 0x80, 0x5F, 0x9b, + 0x34, 0xfb, 0x09, 0x00, 0x04, 0x36, 0x00, 0x0E, 0x36, 0x00, 0x03, 0x19, 0x01, 0x00, 0x36, 0x00, + 0x05, 0x19, 0x00, 0x03, 0x08, 0x0a, 0x09, 0x00, 0x09, 0x36, 0x00, 0x17, 0x36, 0x00, 0x14, 0x1C, + 0xfe, 0x01, 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0xab, 0xcd, 0x00, 0x80, 0x5F, 0x9b, 0x34, 0xfb, + 0x09, 0x01, 0x00, 0x09, 0x01, 0x00, 0x25, 0x06, 0x4A, 0x4C, 0x5F, 0x53, 0x50, 0x50, 0x00, 0x00, +}; +SDP_RECORD_HANDLER_REGISTER(spp_user_sdp_record_item) = { + .service_record = (u8 *)sdp_user_spp_service_data, + .service_record_handle = 0x00010011, +}; + +u8 spp_profile_support = 1; +SDP_RECORD_HANDLER_REGISTER(spp_sdp_record_item) = { + .service_record = (u8 *)sdp_spp_service_data, + .service_record_handle = 0x00010004, +}; + +#endif +#if (USER_SUPPORT_PROFILE_HID==1) +u8 hid_profile_support = 1; +SDP_RECORD_HANDLER_REGISTER(hid_sdp_record_item) = { + .service_record = (u8 *)sdp_hid_service_data, + .service_record_handle = 0x00010006, +}; +#endif +#if (USER_SUPPORT_PROFILE_PBAP==1) +extern const u8 sdp_pbap_service_data[]; +u8 pbap_profile_support = 1; +SDP_RECORD_HANDLER_REGISTER(pbap_sdp_record_item) = { + .service_record = (u8 *)sdp_pbap_service_data, + .service_record_handle = 0x00010007, +}; +#endif +/*注意hid_conn_depend_on_dev_company置1之后,安卓手机会默认断开HID连接 */ +const u8 hid_conn_depend_on_dev_company = 1; +const u8 sdp_get_remote_pnp_info = 0; + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) +const u8 adt_profile_support = 1; +#else +const u8 adt_profile_support = 0; +#endif + +#if (TCFG_BD_NUM == 2) +const u8 a2dp_mutual_support = 1; +const u8 more_addr_reconnect_support = 1; +const u8 more_hfp_cmd_support = 1; + +#if USER_SUPPORT_DUAL_A2DP_SOURCE +const u8 more_avctp_cmd_support = 1; +#else +const u8 more_avctp_cmd_support = 1; +#endif + +#else +const u8 a2dp_mutual_support = 0; +const u8 more_addr_reconnect_support = 0; +const u8 more_hfp_cmd_support = 1; +#if ((RCSP_ADV_EN || SMART_BOX_EN) && JL_EARPHONE_APP_EN) +const u8 more_avctp_cmd_support = 1; +#else +const u8 more_avctp_cmd_support = 1; +#endif +#endif +#if TCFG_USER_EMITTER_ENABLE +const u8 hci_inquiry_support = 1; +const u8 btstack_emitter_support = 1; /*定义用于优化代码编译*/ + +#if USER_SUPPORT_PROFILE_A2DP +const u8 emitter_hfp_hf_support = 0; /*置1时做发射器连接手机时只支持hfp*/ +#else +const u8 emitter_hfp_hf_support = 1; /*置1时做发射器连接手机时只支持hfp*/ +#endif + +extern const u8 sdp_a2dp_source_service_data[]; + +#if (USER_SUPPORT_PROFILE_A2DP==0) +u8 a2dp_profile_support = 2; +#endif + +SDP_RECORD_HANDLER_REGISTER(a2dp_src_sdp_record_item) = { + .service_record = (u8 *)sdp_a2dp_source_service_data, + .service_record_handle = 0x0001000B, +}; +#if (USER_SUPPORT_PROFILE_HFP_AG==1) +extern const u8 sdp_hfp_ag_service_data[]; +u8 hfp_ag_profile_support = 1; +SDP_RECORD_HANDLER_REGISTER(hfp_ag_sdp_record_item) = { + .service_record = (u8 *)sdp_hfp_ag_service_data, + .service_record_handle = 0x00010008, +}; +#endif +#else +const u8 hci_inquiry_support = 0; +const u8 btstack_emitter_support = 0; /*定义用于优化代码编译*/ +#endif +// u8 l2cap_debug_enable = 0xff; +u8 rfcomm_debug_enable = 0xf; +u8 profile_debug_enable = 0xff; +u8 ble_debug_enable = 0xff; +u8 btstack_tws_debug_enable = 0xf; + +#else +const u8 btstack_emitter_support = 1; /*定义用于优化代码编译*/ +const u8 a2dp_mutual_support = 1; +const u8 adt_profile_support = 0; +#endif diff --git a/apps/common/config/ci_transport_uart.c b/apps/common/config/ci_transport_uart.c new file mode 100644 index 0000000..35544c3 --- /dev/null +++ b/apps/common/config/ci_transport_uart.c @@ -0,0 +1,354 @@ +#include "system/includes.h" +#include "config/config_interface.h" +#include "system/event.h" +#include "app_online_cfg.h" +#include "asm/uart_dev.h" +#include "app_config.h" +#include "app_sound_box_tool.h" + +#define LOG_TAG "[CI-UART]" +#define LOG_ERROR_ENABLE +#define LOG_INFO_ENABLE +#define LOG_DUMP_ENABLE +#include "debug.h" + +#if (TCFG_ONLINE_ENABLE || TCFG_SOUNDBOX_TOOL_ENABLE) +struct config_uart { + u32 baudrate; + int flowcontrol; + const char *dev_name; +}; + +struct uart_hdl { + + struct config_uart config; + + uart_bus_t *udev; + void *dbuf; + + void *pRxBuffer; + + u8 ucRxIndex; + u8 rx_type; + + u16 data_length; + + void *pTxBuffer; + + void (*packet_handler)(const u8 *packet, int size); +}; + + +typedef struct { + //head + u16 preamble; + u8 type; + u16 length; + u8 crc8; + u16 crc16; + u8 payload[0]; +} _GNU_PACKED_ uart_packet_t; + +#define UART_FORMAT_HEAD sizeof(uart_packet_t) + +typedef struct { + //head + u16 preamble0; + u8 preamble1; + u16 crc16; + u8 length; + u8 type; + u8 sq; + u8 payload[0]; +} _GNU_PACKED_ uart_tool_packet_t; + +#define UART_TOOL_FORMAT_HEAD sizeof(uart_tool_packet_t) + +extern u16 crc_get_16bit(const void *src, u32 len); + +static void dummy_handler(const u8 *packet, int size); + +#define UART_PREAMBLE 0xBED6 +#define UART_NEW_TOOL_PREAMBLE0 0xAA5A +#define UART_NEW_TOOL_PREAMBLE1 0xA5 + +#define UART_RX_SIZE 0x100 +#define UART_TX_SIZE 0x30 +#define UART_DB_SIZE 0x100 +#define UART_BAUD_RATE 115200 + +#ifdef HAVE_MALLOC +static struct uart_hdl *hdl; +#define __this (hdl) +#else +static struct uart_hdl hdl; +#define __this (&hdl) + +static u8 pRxBuffer_static[UART_RX_SIZE] __attribute__((aligned(4))); //rx memory +static u8 pTxBuffer_static[UART_TX_SIZE] __attribute__((aligned(4))); //tx memory +static u8 devBuffer_static[UART_DB_SIZE] __attribute__((aligned(4))); //dev DMA memory +#endif + +void ci_data_rx_handler(u8 type) +{ + u16 crc16; + uart_tool_packet_t *p_newtool; + + __this->rx_type = type; + + if (type == CI_UART && __this->udev) { + __this->data_length += __this->udev->read(&__this->pRxBuffer[__this->data_length], (UART_RX_SIZE - __this->data_length), 0);//串口读取buf剩余空间的长度,实际长度比buf长,导致越界改写问题 + } + + /* log_info("Rx : %d", __this->data_length); */ + /* log_info_hexdump(__this->pRxBuffer, __this->data_length); */ + if (__this->data_length > UART_RX_SIZE) { + log_error("Wired"); + } + + u8 *tmp_buf = NULL; + tmp_buf = __this->pRxBuffer; + if (__this->data_length >= 2) { + unsigned i = 0; + for (i = 0; i < __this->data_length - 1; ++i) { + if ((tmp_buf[i] == 0x5A) && (tmp_buf[i + 1] == 0xAA) && (tmp_buf[i + 2] == 0xA5)) { + break; + } + } + if (i != 0) { + __this->data_length -= i; + /* printf("__this->data_length %d i %d\n", __this->data_length, i); */ + if (__this->data_length > 0) { + memmove(&__this->pRxBuffer[0], &tmp_buf[i], __this->data_length); + } + } + } + + if (__this->data_length <= UART_TOOL_FORMAT_HEAD) { + return; + } + + p_newtool = __this->pRxBuffer; + + if ((p_newtool->preamble0 != UART_NEW_TOOL_PREAMBLE0) || (p_newtool->preamble1 != UART_NEW_TOOL_PREAMBLE1)) { + log_error("preamble err\n"); + log_info_hexdump(__this->pRxBuffer, __this->data_length); + goto reset_buf; + } + + if (__this->data_length >= p_newtool->length + 6) { + crc16 = crc_get_16bit(&p_newtool->length, p_newtool->length + 1); + /* log_info("CRC16 0x%x / 0x%x", crc16, p_newtool->crc16); */ + if (p_newtool->crc16 != crc16) { + log_error("crc16 err\n"); + log_info_hexdump(__this->pRxBuffer, __this->data_length); + goto reset_buf; + } + /* log_info_hexdump(p_newtool, p_newtool->length + 6); */ + online_cfg_tool_data_deal(p_newtool, p_newtool->length + 6); + } else { + return; + } + +reset_buf: + __this->data_length = 0; +} + +static void ci_uart_isr_cb(void *ut_bus, u32 status) +{ + if (status == UT_TX) { + return ; + } + struct sys_event e; + e.type = SYS_DEVICE_EVENT; + e.arg = (void *)DEVICE_EVENT_FROM_CI_UART; + e.u.dev.event = 0; + e.u.dev.value = 0; + sys_event_notify(&e); +} + +static int ci_uart_init() +{ + struct uart_platform_data_t ut = {0}; +#if (TCFG_ONLINE_ENABLE || TCFG_SOUNDBOX_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) + ut.tx_pin = TCFG_TOOL_TX_PORT; + ut.rx_pin = TCFG_TOOL_RX_PORT; +#endif +#endif + ut.baud = __this->config.baudrate; + ut.rx_timeout = 1; + ut.isr_cbfun = ci_uart_isr_cb; + ut.rx_cbuf = devBuffer_static; + ut.rx_cbuf_size = UART_DB_SIZE; + ut.frame_length = UART_DB_SIZE; + /* JL_CLOCK->CLK_CON1 |= BIT(11); */ + /* JL_CLOCK->CLK_CON1 &= ~BIT(10); */ + __this->dbuf = devBuffer_static; + __this->data_length = 0; + __this->udev = (uart_bus_t *)uart_dev_open(&ut); + if (__this->udev == NULL) { + log_error("open uart dev err\n"); + return -1; + } + return 0; +} + +static void ci_uart_putbyte(char a) +{ + if (__this->udev) { + __this->udev->putbyte(a); + } +} + +void ci_uart_write(char *buf, u16 len) +{ + if (__this->udev) { + __this->udev->write(buf, len); + } +} + +static void dummy_handler(const u8 *packet, int size) +{ + log_error("Dummy"); +} + +static void clock_critical_enter(void) +{ + +} +static void clock_critical_exit(void) +{ + if (__this->udev) { + __this->udev->set_baud(__this->config.baudrate); + } +} +CLOCK_CRITICAL_HANDLE_REG(ci, clock_critical_enter, clock_critical_exit) + +static void ci_dev_init(const void *config) +{ +#ifdef HAVE_MALLOC + __this = malloc(sizeof(struct uart_hdl)); + ASSERT(__this, "Fatal error"); + + memset(__this, 0x0, sizeof(struct uart_hdl)); + + __this->pRxBuffer = malloc(UART_RX_SIZE); + ASSERT(__this->pRxBuffer, "Fatal error"); + + __this->pTxBuffer = malloc(UART_TX_SIZE); + ASSERT(__this->pTxBuffer, "Fatal error"); +#else + log_info("Static"); + __this->pRxBuffer = pRxBuffer_static; + __this->pTxBuffer = pTxBuffer_static; +#endif + + __this->packet_handler = dummy_handler; + + ci_transport_config_uart_t *ci_config_uart = (ci_transport_config_uart_t *)config; + + __this->config.baudrate = ci_config_uart->baudrate_init; + __this->config.flowcontrol = ci_config_uart->flowcontrol; + __this->config.dev_name = ci_config_uart->device_name; + + log_info("baudrate : %d", __this->config.baudrate); + log_info("flowcontrol: %d", __this->config.flowcontrol); +} + +static int ci_dev_open(void) +{ + ci_uart_init(); + return 0; +} + +static int ci_dev_close(void) +{ + return 0; +} + +static void ci_dev_register_packet_handler(void (*handler)(const u8 *packet, int size)) +{ + __this->packet_handler = handler; +} + +static int ci_dev_send_packet(const u8 *packet, int size) +{ + /* dev_stream_out(); */ + int i = 0; + uart_packet_t *p = (uart_packet_t *)__this->pTxBuffer; + + p->preamble = UART_PREAMBLE; + p->type = 0; + p->length = size; + p->crc8 = crc_get_16bit(p, UART_FORMAT_HEAD - 3) & 0xff; + p->crc16 = crc_get_16bit(packet, size); + + size += UART_FORMAT_HEAD; + ASSERT(size <= UART_TX_SIZE, "Fatal Error"); + + memcpy(p->payload, packet, size); + + /* log_info("Tx : %d", size); */ + /* log_info_hexdump(p, size); */ + if (__this->rx_type == CI_UART) { +#if 0 + while (size--) { + ci_uart_putbyte(((char *)p)[i++]); + } +#else + ci_uart_write(p, size); +#endif + } + + return 0; +} + +static int ci_dev_can_send_packet_now(uint8_t packet_type) +{ + return 0; +} + +// get dev api skeletons +static const ci_transport_t ci_transport_uart = { + /* const char * name; */ "CI_UART", + /* void (*init) (const void *transport_config); */ &ci_dev_init, + /* int (*open)(void); */ &ci_dev_open, + /* int (*close)(void); */ &ci_dev_close, + /* void (*register_packet_handler)(void (*handler)(...); */ &ci_dev_register_packet_handler, + /* int (*can_send_packet_now)(uint8_t packet_type); */ &ci_dev_can_send_packet_now, + /* int (*send_packet)(...); */ &ci_dev_send_packet, +}; + +const ci_transport_t *ci_transport_uart_instance(void) +{ + return &ci_transport_uart; +} + + + +#endif + +#ifdef CONFIG_AC608N +//该函数在蓝牙库实现,608没有蓝牙库,在此重定义 +u16 crc_get_16bit(const void *src, u32 len) +{ + /* log_info(__func__); */ + u8 *p = (u8 *)src; + u16 ret; + OS_SR_ALLOC(); + // vm_mutex_enter(); + OS_ENTER_CRITICAL(); + JL_CRC->REG = 0 ; + + while (len--) { + JL_CRC->FIFO = *p++; + } + __asm__ volatile("csync"); + ret = JL_CRC->REG; + OS_EXIT_CRITICAL(); + // vm_mutex_exit(); + /* printf("CRC16 %02x\r\n", ret); */ + return ret; +} +#endif diff --git a/apps/common/config/include/bt_profile_cfg.h b/apps/common/config/include/bt_profile_cfg.h new file mode 100644 index 0000000..6ed83be --- /dev/null +++ b/apps/common/config/include/bt_profile_cfg.h @@ -0,0 +1,89 @@ + +#ifndef _BT_PROFILE_CFG_H_ +#define _BT_PROFILE_CFG_H_ + +#include "app_config.h" +#include "btcontroller_modules.h" + + +#if (TRANS_DATA_EN || RCSP_BTMATE_EN || RCSP_ADV_EN || SMART_BOX_EN ||ANCS_CLIENT_EN) +#define BT_FOR_APP_EN 1 +#else +#define BT_FOR_APP_EN 0 +#ifndef AI_APP_PROTOCOL +#define AI_APP_PROTOCOL 0 +#endif +#endif + +///---sdp service record profile- 用户选择支持协议--/// +#if (BT_FOR_APP_EN || APP_ONLINE_DEBUG || AI_APP_PROTOCOL) +#if (LL_SYNC_EN || TUYA_DEMO_EN || TUYA_MULTI_BLE_EN) +#undef USER_SUPPORT_PROFILE_SPP +#define USER_SUPPORT_PROFILE_SPP 0 +#else +#undef USER_SUPPORT_PROFILE_SPP +#define USER_SUPPORT_PROFILE_SPP 1 +#endif +#endif + + +//ble demo的例子 +#define DEF_BLE_DEMO_NULL 0 //ble 没有使能 +#define DEF_BLE_DEMO_ADV 1 //only adv,can't connect +#define DEF_BLE_DEMO_TRANS_DATA 2 // +#define DEF_BLE_DEMO_DUEROS_DMA 3 // +#define DEF_BLE_DEMO_RCSP_DEMO 4 // +#define DEF_BLE_DEMO_ADV_RCSP 5 +#define DEF_BLE_DEMO_GMA 6 +#define DEF_BLE_DEMO_CLIENT 7 // +#define DEF_BLE_TME_ADV 8 +#define DEF_BLE_ANCS_ADV 9 +#define DEF_BLE_DEMO_MI 10 +#define DEF_BLE_DEMO_TUYA 11 +#define DEF_BLE_DEMO_MULTI 12 +#define DEF_BLE_DEMO_TUYA_MULTI 13 + +//配置选择的demo +#if TCFG_USER_BLE_ENABLE + +#if AI_APP_PROTOCOL +#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_NULL + +#elif (SMART_BOX_EN | RCSP_BTMATE_EN) +#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_RCSP_DEMO + +#elif TRANS_DATA_EN +#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_TRANS_DATA + +#elif RCSP_ADV_EN +#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_ADV_RCSP + +#elif TUYA_DEMO_EN +#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_TUYA + +#elif BLE_CLIENT_EN +#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_CLIENT + +#elif TRANS_MULTI_BLE_EN +#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_MULTI + +#elif TUYA_MULTI_BLE_EN +#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_TUYA_MULTI + +#elif ANCS_CLIENT_EN +#define TCFG_BLE_DEMO_SELECT DEF_BLE_ANCS_ADV + +#else +#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_ADV +#endif + +#else +#define TCFG_BLE_DEMO_SELECT DEF_BLE_DEMO_NULL//ble is closed +#endif + +//配对加密使能 +#define TCFG_BLE_SECURITY_EN 0 + + + +#endif diff --git a/apps/common/debug/debug.c b/apps/common/debug/debug.c new file mode 100644 index 0000000..7bd1c91 --- /dev/null +++ b/apps/common/debug/debug.c @@ -0,0 +1,63 @@ +#include "app_config.h" +#include "typedef.h" + + + +#ifndef CONFIG_DEBUG_ENABLE + +int putchar(int a) +{ + return a; +} + +int puts(const char *out) +{ + return 0; +} + +int printf(const char *format, ...) +{ + return 0; +} + + +void put_buf(const u8 *buf, int len) +{ + +} + +void put_u8hex(u8 dat) +{ + +} + +void put_u16hex(u16 dat) +{ + +} + +void put_u32hex(u32 dat) +{ + +} + +void log_print(int level, const char *tag, const char *format, ...) +{ + +} + +#ifndef CONFIG_DEBUG_LITE_ENABLE +void log_putbyte(char c) +{ + +} +#endif /* #ifndef CONFIG_DEBUG_LITE_ENABLE */ + +int assert_printf(const char *format, ...) +{ + cpu_assert_debug(); + + return 0; +} + +#endif diff --git a/apps/common/debug/debug_lite.c b/apps/common/debug/debug_lite.c new file mode 100644 index 0000000..b3d37d9 --- /dev/null +++ b/apps/common/debug/debug_lite.c @@ -0,0 +1,68 @@ +#include "app_config.h" +#include "typedef.h" + +#ifdef CONFIG_DEBUG_LITE_ENABLE + +extern void putbyte(char a); + +#define putbyte_lite putbyte + +void log_putbyte(char c) +{ + putbyte_lite(c); +} + +void puts_lite(const char *out) +{ + while (*out != '\0') { + putbyte_lite(*out); + out++; + } +} + +int printf_lite(const char *format, ...) +{ + va_list args; + + va_start(args, format); + + return print(NULL, 0, format, args); +} + +void put_buf_lite(void *_buf, u32 len) +{ + u8 *buf = (u8 *)_buf; + printf_lite("\n0x%x\n", buf); + for (int i = 0; i < len; i++) { + if (((i % 16) == 0) && (i != 0)) { + putbyte_lite('\n'); + } + printf_lite("%x", buf[i]); + putbyte_lite(' '); + } + putbyte_lite('\n'); +} + +#else + + +void puts_lite(const char *out) +{ + +} + + +void put_buf_lite(void *_buf, u32 len) +{ + +} + + +int printf_lite(const char *format, ...) +{ + return 0; +} + +#endif /* #ifdef CONFIG_DEBUG_LITE_ENABLE */ + + diff --git a/apps/common/dev_manager/dev_manager.c b/apps/common/dev_manager/dev_manager.c new file mode 100644 index 0000000..057d08d --- /dev/null +++ b/apps/common/dev_manager/dev_manager.c @@ -0,0 +1,1097 @@ +#include "dev_manager.h" +#include "dev_reg.h" +#include "app_config.h" +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +#include "dev_multiplex_api.h" +#endif +#include "spi/nor_fs.h" +#include "dev_update.h" + +// *INDENT-OFF* + +#if (TCFG_DEV_MANAGER_ENABLE) + +#define DEV_MANAGER_TASK_NAME "dev_mg" +#define DEV_MANAGER_SCAN_DISK_MAX_DEEPTH 9 + +///设备管理总控制句柄 +struct __dev_manager { + struct list_head list; + OS_MUTEX mutex; + OS_SEM sem; + u32 counter; +}; +static struct __dev_manager dev_mg; +#define __this (&dev_mg) + + +///设备节点结构体 +struct __dev { + struct list_head entry; + struct __dev_reg *parm;//设备参数 + struct imount *fmnt; + volatile u8 valid: 1;//有效设备标记, 这里有效是指是否有可播放文件 + volatile u32 active_stamp;///活动设备时间戳,通过时间戳记录当前最后活动设备 +}; + + +static u32 __dev_manager_get_time_stamp(void) +{ + u32 counter = __this->counter; + __this->counter ++; + return counter; +} + +int __dev_manager_add(char *logo, u8 need_mount) +{ + if (logo == NULL) { + return DEV_MANAGER_ADD_ERR_PARM; + } + int i; + printf("%s add start\n", logo); + struct __dev_reg *p = NULL; + struct __dev_reg *n; + + for(n=(struct __dev_reg *)dev_reg; n->logo != NULL; n++){ + if (!strcmp(n->logo, logo)) { + p = n; + break; + } + } + + if (p) { + ///挂载文件系统 + if (dev_manager_list_check_by_logo(logo)) { + printf("dev online aready, err!!!\n"); + return DEV_MANAGER_ADD_IN_LIST_AREADY; + } + struct __dev *dev = (struct __dev *)zalloc(sizeof(struct __dev)); + if(dev == NULL){ + return DEV_MANAGER_ADD_ERR_NOMEM; + } + os_mutex_pend(&__this->mutex, 0); + if(need_mount){ + dev->fmnt = mount(p->name, p->storage_path, p->fs_type, 3, NULL); + } + dev->parm = p; + dev->valid = (dev->fmnt ? 1 : 0); + dev->active_stamp = __dev_manager_get_time_stamp();//timer_get_ms(); + list_add_tail(&dev->entry, &__this->list); + os_mutex_post(&__this->mutex); + printf("%s, %s add ok, dev->fmnt = %x, %d\n", __FUNCTION__, logo, (int)dev->fmnt, dev->active_stamp); + if(dev->fmnt == NULL){ + return DEV_MANAGER_ADD_ERR_MOUNT_FAIL; + } + return DEV_MANAGER_ADD_OK; + } + printf("dev_manager_add can not find logo %s\n",logo); + return DEV_MANAGER_ADD_ERR_NOT_FOUND; +} + +static int __dev_manager_del(char *logo) +{ + if (logo == NULL) { + return -1; + } + struct __dev *dev, *n; + os_mutex_pend(&__this->mutex, 0); + list_for_each_entry_safe(dev, n, &__this->list, entry) { + if (!strcmp(dev->parm->logo, logo)) { + ///卸载文件系统 + if(dev->fmnt){ + unmount(dev->parm->storage_path); + } + list_del(&dev->entry); + free(dev); + printf("%s, %s del ok\n", __FUNCTION__, logo); + break; + } + } + os_mutex_post(&__this->mutex); + return 0; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 设备增加接口 + @param logo:逻辑盘符,如:sd0/sd1/udisk0等 + @return 0:成功,非0是失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int dev_manager_add(char *logo) +{ + if(logo == NULL){ + return -1; + } + int ret = 0; +#if TCFG_RECORD_FOLDER_DEV_ENABLE + char rec_dev_logo[16] = {0}; + sprintf(rec_dev_logo, "%s%s", logo, "_rec"); + ret = __dev_manager_add(rec_dev_logo, 1); + if(ret == DEV_MANAGER_ADD_OK){ + ret = __dev_manager_add(logo, 1); + if(ret){ + __dev_manager_del(logo); + __dev_manager_del(rec_dev_logo); + } + }else if(ret == DEV_MANAGER_ADD_ERR_NOT_FOUND){ + ret = __dev_manager_add(logo, 1); + } + else{ + ret = __dev_manager_add(logo, 0); + } +#else + ret = __dev_manager_add(logo, 1); +#endif//TCFG_RECORD_FOLDER_DEV_ENABLE + + return ret; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 设备删除接口 + @param logo:逻辑盘符,如:sd0/sd1/udisk0等 + @return 0:成功,非0是失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int dev_manager_del(char *logo) +{ + if(logo == NULL){ + return -1; + } + __dev_manager_del(logo); +#if TCFG_RECORD_FOLDER_DEV_ENABLE + char rec_dev_logo[16] = {0}; + sprintf(rec_dev_logo, "%s%s", logo, "_rec"); + __dev_manager_del(rec_dev_logo); +#endif//TCFG_RECORD_FOLDER_DEV_ENABLE + + return 0; +} +//*----------------------------------------------------------------------------*/ +/**@brief 通过设备节点检查设备是否在线 + @param dev:设备节点 + @return 成功返回设备节点, 失败返回NULL + @note 通过设备节点检查设备是否在设备链表中 +*/ +/*----------------------------------------------------------------------------*/ +struct __dev *dev_manager_check(struct __dev *dev) +{ + if (dev == NULL) { + return NULL; + } + struct __dev *p; + list_for_each_entry(p, &__this->list, entry) { + if(!(p->fmnt)){ + continue; + } + if (dev == p) { + return p; + } + } + return NULL; +} +//*----------------------------------------------------------------------------*/ +/**@brief 通过盘符检查设备是否在线 + @param logo:逻辑盘符,如:sd0/sd1/udisk0 + @return 成功返回设备节点, 失败返回NULL + @note 通过设备节点检查设备是否在设备链表中 +*/ +/*----------------------------------------------------------------------------*/ +struct __dev *dev_manager_check_by_logo(char *logo) +{ + if (logo == NULL) { + return NULL; + } + struct __dev *dev; + list_for_each_entry(dev, &__this->list, entry) { + if(!(dev->fmnt)){ + continue; + } + if (!strcmp(dev->parm->logo, logo)) { + return dev; + } + } + return NULL; +} +//*----------------------------------------------------------------------------*/ +/**@brief 获取设备总数 + @param valid: + 1:有效可播放设备, 0;所有设备,包括有可播放设备及无可播放设备 + @return 设备总数 + @note 根据使用情景决定接口参数 +*/ +/*----------------------------------------------------------------------------*/ +u32 dev_manager_get_total(u8 valid) +{ + u32 total_valid = 0; + u32 total = 0; + struct __dev *dev; + os_mutex_pend(&__this->mutex, 0); + list_for_each_entry(dev, &__this->list, entry) { + if(!(dev->fmnt)){ + continue; + } + if (dev->valid) { + total_valid++; + } + total ++; + } + os_mutex_post(&__this->mutex); + return (valid ? total_valid : total); +} +//*----------------------------------------------------------------------------*/ +/**@brief 获取设备列表第一个设备 + @param valid: + 1:有效可播放设备, 0;所有设备,包括有可播放设备及无可播放设备 + @return 成功返回设备设备节点,失败返回NULL + @note 根据使用情景决定接口参数 +*/ +/*----------------------------------------------------------------------------*/ +struct __dev *dev_manager_find_first(u8 valid) +{ + struct __dev *dev = NULL; + os_mutex_pend(&__this->mutex, 0); + list_for_each_entry(dev, &__this->list, entry) { + if(!(dev->fmnt)){ + continue; + } + if(valid){ + if (dev->valid) { + os_mutex_post(&__this->mutex); + return dev; + } + }else{ + os_mutex_post(&__this->mutex); + return dev; + } + } + os_mutex_post(&__this->mutex); + return NULL; +} +//*----------------------------------------------------------------------------*/ +/**@brief 获取设备列表最后一个设备 + @param valid: + 1:有效可播放设备中查找 + 0:所有设备,包括有可播放设备及无可播放设备中查找 + @return 成功返回设备设备节点,失败返回NULL + @note 根据使用情景决定接口参数 +*/ +/*----------------------------------------------------------------------------*/ +struct __dev *dev_manager_find_last(u8 valid) +{ + struct __dev *dev = NULL; + os_mutex_pend(&__this->mutex, 0); + list_for_each_entry_reverse(dev, &__this->list, entry) { + if(!(dev->fmnt)){ + continue; + } + if(valid){ + if (dev->valid) { + os_mutex_post(&__this->mutex); + return dev; + } + }else{ + os_mutex_post(&__this->mutex); + return dev; + } + } + os_mutex_post(&__this->mutex); + return NULL; +} +//*----------------------------------------------------------------------------*/ +/**@brief 获取上一个设备节点 + @param + dev:当前设备节点 + valid: + 1:有效可播放设备中查找, + 0:所有设备,包括有可播放设备及无可播放设备中查找 + @return 成功返回设备设备节点,失败返回NULL + @note 根据当前设置的参数设备节点,找链表中的上一个设备 +*/ +/*----------------------------------------------------------------------------*/ +struct __dev *dev_manager_find_prev(struct __dev *dev, u8 valid) +{ + if (dev == NULL) { + return NULL; + } + struct __dev *p = NULL; + os_mutex_pend(&__this->mutex, 0); + if (dev_manager_check(dev) == NULL) { + ///传入的参数无效, 返回活动设备 + os_mutex_post(&__this->mutex); + return dev_manager_find_active(valid); + } + list_for_each_entry(p, &dev->entry, entry) { + if((void*)p == (void*)(&__this->list)){ + continue; + } + if(!(p->fmnt)){ + continue; + } + if(valid){ + if (p->valid) { + os_mutex_post(&__this->mutex); + return p; + } + }else{ + os_mutex_post(&__this->mutex); + return p; + } + } + os_mutex_post(&__this->mutex); + return NULL; +} +//*----------------------------------------------------------------------------*/ +/**@brief 获取下一个设备节点 + @param + dev:当前设备节点 + valid: + 1:有效可播放设备中查找, + 0:所有设备,包括有可播放设备及无可播放设备中查找 + @return 成功返回设备设备节点,失败返回NULL + @note 根据当前设置的参数设备节点,找链表中的下一个设备 +*/ +/*----------------------------------------------------------------------------*/ +struct __dev *dev_manager_find_next(struct __dev *dev, u8 valid) +{ + if (dev == NULL) { + return NULL; + } + struct __dev *p = NULL; + os_mutex_pend(&__this->mutex, 0); + if (dev_manager_check(dev) == NULL) { + ///传入的参数无效, 返回活动设备 + os_mutex_post(&__this->mutex); + return dev_manager_find_active(valid); + } + + list_for_each_entry_reverse(p, &dev->entry, entry) { + if((void*)p == (void*)(&__this->list)){ + continue; + } + if(!(p->fmnt)){ + continue; + } + if(valid){ + if (p->valid) { + os_mutex_post(&__this->mutex); + return p; + } + }else{ + os_mutex_post(&__this->mutex); + return p; + } + } + os_mutex_post(&__this->mutex); + return NULL; +} +//*----------------------------------------------------------------------------*/ +/**@brief 获取当前活动设备节点 + @param + valid: + 1:有效可播放设备中查找, + 0:所有设备,包括有可播放设备及无可播放设备中查找 + @return 成功返回设备设备节点,失败返回NULL + @note +*/ +/*----------------------------------------------------------------------------*/ +struct __dev *dev_manager_find_active(u8 valid) +{ + struct __dev *dev = NULL; + struct __dev *active = NULL; + os_mutex_pend(&__this->mutex, 0); + list_for_each_entry(dev, &__this->list, entry) { + if(!(dev->fmnt)){ + continue; + } + if(valid){ + if (dev->valid) { + if (active) { + if (active->active_stamp < dev->active_stamp) { + active = dev; + } + } else { + active = dev; + } + } + }else{ + if (active) { + if (active->active_stamp < dev->active_stamp) { + active = dev; + } + } else { + active = dev; + } + + } + } + os_mutex_post(&__this->mutex); + return active; +} +//*----------------------------------------------------------------------------*/ +/**@brief 获取指定设备节点 + @param + logo:指定逻辑盘符,如:sd0/sd1/udisk0 + valid: + 1:有效可播放设备中查找, + 0:所有设备,包括有可播放设备及无可播放设备中查找 + @return 成功返回设备设备节点,失败返回NULL + @note +*/ +/*----------------------------------------------------------------------------*/ +struct __dev *dev_manager_find_spec(char *logo, u8 valid) +{ + if (logo == NULL) { + return NULL; + } + struct __dev *dev = NULL; + os_mutex_pend(&__this->mutex, 0); + list_for_each_entry(dev, &__this->list, entry) { + if(!(dev->fmnt)){ + continue; + } + if (!strcmp(dev->parm->logo, logo)) { + if(valid){ + if (dev->valid) { + os_mutex_post(&__this->mutex); + return dev; + } + }else{ + os_mutex_post(&__this->mutex); + return dev; + } + } + } + os_mutex_post(&__this->mutex); + return NULL; +} +//*----------------------------------------------------------------------------*/ +/**@brief 获取指定序号设备节点 + @param + index:指定序号,指的是在设备链表中的顺序 + valid: + 1:有效可播放设备中查找, + 0:所有设备,包括有可播放设备及无可播放设备中查找 + @return 成功返回设备设备节点,失败返回NULL + @note +*/ +/*----------------------------------------------------------------------------*/ +struct __dev *dev_manager_find_by_index(u32 index, u8 valid) +{ + struct __dev *dev = NULL; + u32 i = 0; + os_mutex_pend(&__this->mutex, 0); + list_for_each_entry(dev, &__this->list, entry) { + if(!(dev->fmnt)){ + continue; + } + if(valid){ + if (dev->valid) { + if (i == index) { + os_mutex_post(&__this->mutex); + return dev; + } + i++; + } + }else{ + if (i == index) { + os_mutex_post(&__this->mutex); + return dev; + } + i++; + } + } + os_mutex_post(&__this->mutex); + return NULL; +} +//*----------------------------------------------------------------------------*/ +/**@brief 设备扫盘释放 + @param + fsn:扫描句柄 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void dev_manager_scan_disk_release(struct vfscan *fsn) +{ + if (fsn) { + fscan_release(fsn); + } +} +//*----------------------------------------------------------------------------*/ +/**@brief 设备扫盘 + @param + dev:设备节点 + path:指定扫描目录 + parm:扫描参数,包括文件后缀等 + cycle_mode:播放循环模式 + callback:扫描打断回调 + @return 成功返回扫描控制句柄,失败返回NULL + @note +*/ +/*----------------------------------------------------------------------------*/ +struct vfscan *dev_manager_scan_disk(struct __dev *dev, const char *path, const char *parm, u8 cycle_mode, struct __scan_callback *callback) +{ + if (dev_manager_check(dev) == NULL) { + return NULL; + } +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + +#if (TCFG_DM_MULTIPLEX_WITH_SD_PORT == 0) //0:sd0 1:sd1 //dm 参与复用的sd配置 + if(!memcmp(dev->parm->logo ,"sd0",strlen("sd0"))){ +#else + if(!memcmp(dev->parm->logo ,"sd1",strlen("sd1"))){ +#endif + dev_usb_change_sd(); + } + + if(!memcmp(dev->parm->logo ,"udisk",strlen("udisk"))) + dev_sd_change_usb(); + + if (dev_manager_online_check(dev, 1) == NULL) { + printf("mult remount fail !!!\n"); + return NULL; + } +#endif + char *fsn_path = NULL; + char *tmp_path = NULL; + if (path) { + if (*path == '/') { + path++; + } + tmp_path = zalloc(strlen(dev->parm->root_path) + strlen(path) + 1); + if (tmp_path == NULL) { + return NULL; + } + sprintf(tmp_path, "%s%s", dev->parm->root_path, path); + fsn_path = tmp_path; + } else { + fsn_path = dev->parm->root_path; + } + printf("fsn_path = %s, scan parm = %s\n", fsn_path, parm); + struct vfscan *fsn; + /* clock_add_set(SCAN_DISK_CLK); */ + if(callback && callback->enter){ + callback->enter(dev);//扫描前处理, 可以在注册的回调里提高系统时钟等处理 + } + fsn = fscan_interrupt( + (const char *)fsn_path, + parm, + DEV_MANAGER_SCAN_DISK_MAX_DEEPTH, + ((callback) ? callback->scan_break : NULL)); + /* clock_remove_set(SCAN_DISK_CLK); */ + if(callback && callback->exit){ + callback->exit(dev);//扫描后处理, 可以在注册的回调里还原到enter前的状态 + } + if (fsn) { + if (fsn->file_number == 0) { + printf("dev nofile\n"); +#if (TCFG_DEV_UPDATE_IF_NOFILE_ENABLE) + ///没有文件找升级文件 + dev_update_check(dev->parm->logo); +#endif/*TCFG_DEV_UPDATE_IF_NOFILE_ENABLE*/ + ///没有文件,释放fsn, 减少外面流程的处理 + dev_manager_scan_disk_release(fsn); + fsn = NULL; + } else { + fsn->cycle_mode = cycle_mode; + } + } + + if (tmp_path) { + free(tmp_path); + } + return fsn; +} +//*----------------------------------------------------------------------------*/ +/**@brief 通过设备节点标记指定设备是否有效 + @param + dev:设备节点 + flag: + 1:设备有效, + 0:设备无效 + @return + @note 这里有无效是指是否有可播放文件 +*/ +/*----------------------------------------------------------------------------*/ +void dev_manager_set_valid(struct __dev *dev, u8 flag) +{ + os_mutex_pend(&__this->mutex, 0); + if (dev_manager_check(dev)) { + dev->valid = flag; + } + os_mutex_post(&__this->mutex); +} +//*----------------------------------------------------------------------------*/ +/**@brief 通过逻辑盘符标记指定设备是否有效 + @param + logo:逻辑盘符,如:sd0/sd1/udisk0 + flag: + 1:设备有效, + 0:设备无效 + @return + @note 这里有无效是指是否有可播放文件 +*/ +/*----------------------------------------------------------------------------*/ +void dev_manager_set_valid_by_logo(char *logo, u8 flag) +{ + if (logo == NULL) { + return ; + } + struct __dev *dev = NULL; + os_mutex_pend(&__this->mutex, 0); + dev = dev_manager_check_by_logo(logo); + if (dev) { + dev->valid = flag; + } + os_mutex_post(&__this->mutex); +} +//*----------------------------------------------------------------------------*/ +/**@brief 激活指定设备节点的设备 + @param + dev:设备节点 + @return + @note 该接口可以将设备变为最新活动设备 +*/ +/*----------------------------------------------------------------------------*/ +void dev_manager_set_active(struct __dev *dev) +{ + os_mutex_pend(&__this->mutex, 0); + if (dev_manager_check(dev)) { + dev->active_stamp = __dev_manager_get_time_stamp();//timer_get_ms(); + } + os_mutex_post(&__this->mutex); +} +//*----------------------------------------------------------------------------*/ +/**@brief 激活指定逻辑盘符的设备 + @param + logo:逻辑盘符,如:sd0/sd1/udisk0 + @return + @note 该接口可以将设备变为最新活动设备 +*/ +/*----------------------------------------------------------------------------*/ +void dev_manager_set_active_by_logo(char *logo) +{ + if (logo == NULL) { + return ; + } + struct __dev *dev = NULL; + os_mutex_pend(&__this->mutex, 0); + dev = dev_manager_check_by_logo(logo); + if (dev) { + dev->active_stamp = __dev_manager_get_time_stamp();//timer_get_ms(); + } + os_mutex_post(&__this->mutex); +} +//*----------------------------------------------------------------------------*/ +/**@brief 获取设备节点的逻辑盘符 + @param + dev:设备节点 + @return 成功返回逻辑盘符,如:sd0/sd1/udisk0,失败返回NULL + @note +*/ +/*----------------------------------------------------------------------------*/ +char *dev_manager_get_logo(struct __dev *dev) +{ + char *logo = NULL; + os_mutex_pend(&__this->mutex, 0); + if (dev_manager_check(dev) == NULL) { + os_mutex_post(&__this->mutex); + return NULL; + } + logo = dev->parm->logo; + os_mutex_post(&__this->mutex); + return logo; +} +//*----------------------------------------------------------------------------*/ +/**@brief 获取物理设备节点的逻辑盘符(去掉_rec后缀) + @param + dev:设备节点 + @return 成功返回逻辑盘符,如:sd0/sd1/udisk0,失败返回NULL + @note 物理逻辑盘符是指非录音文件夹设备盘符(录音文件夹设备如:sd0_rec) +*/ +/*----------------------------------------------------------------------------*/ +char *dev_manager_get_phy_logo(struct __dev *dev) +{ + char *logo = dev_manager_get_logo(dev); + char phy_dev_logo[16] = {0}; + if (logo) { + char *str = strstr(logo, "_rec"); + if (str) { + strncpy(phy_dev_logo, logo, strlen(logo) - strlen(str)); + struct __dev *phy_dev = dev_manager_find_spec(phy_dev_logo, 0); + return dev_manager_get_logo(phy_dev); + } + } + return logo; +} +//*----------------------------------------------------------------------------*/ +/**@brief 获取录音文件夹设备节点的逻辑盘符(追加_rec后缀) + @param + dev:设备节点 + @return 成功返回逻辑盘符,如:sd0_rec/sd1_rec/udisk0_rec,失败返回NULL + @note +*/ +/*----------------------------------------------------------------------------*/ +char *dev_manager_get_rec_logo(struct __dev *dev) +{ + char *logo = dev_manager_get_logo(dev); + char rec_dev_logo[16] = {0}; + if (logo) { + char *str = strstr(logo, "_rec"); + if (!str) { + sprintf(rec_dev_logo, "%s%s", logo, "_rec"); + struct __dev *rec_dev = dev_manager_find_spec(rec_dev_logo, 0); + return dev_manager_get_logo(rec_dev); + } + } + return logo; +} +//*----------------------------------------------------------------------------*/ +/**@brief 通过设备节点获取设备文件系统根目录 + @param + dev:设备节点 + @return 成功返回根目录,失败返回NULL + @note +*/ +/*----------------------------------------------------------------------------*/ +char *dev_manager_get_root_path(struct __dev *dev) +{ + char *path = NULL; + os_mutex_pend(&__this->mutex, 0); + if (dev_manager_check(dev) == NULL) { + os_mutex_post(&__this->mutex); + return NULL; + } + path = dev->parm->root_path; + os_mutex_post(&__this->mutex); + return path; +} +//*----------------------------------------------------------------------------*/ +/**@brief 通过逻辑盘符获取设备文件系统根目录 + @param + logo:逻辑盘符,如:sd0/sd1/udisk0 + @return 成功返回根目录,失败返回NULL + @note +*/ +/*----------------------------------------------------------------------------*/ +char *dev_manager_get_root_path_by_logo(char *logo) +{ + char *path = NULL; + os_mutex_pend(&__this->mutex, 0); + struct __dev *dev = dev_manager_check_by_logo(logo); + if (dev == NULL) { + os_mutex_post(&__this->mutex); + return NULL; + } + path = dev->parm->root_path; + os_mutex_post(&__this->mutex); + return path; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 通过设备节点获取设备mount信息 + @param + dev:设备节点 + @return 成功返回对应指针,失败返回NULL + @note +*/ +/*----------------------------------------------------------------------------*/ +struct imount *dev_manager_get_mount_hdl(struct __dev *dev) +{ + if (dev == NULL) { + return NULL; + }else{ + return dev->fmnt; + } +} +//*----------------------------------------------------------------------------*/ +/**@brief 通过逻辑盘符判断设备是否在线 + @param + logo:逻辑盘符,如:sd0/sd1/udisk0 + valid: + 1:检查有效可播放设备 + 0:检查所有设备 + @return 1:在线 0:不在线 + @note +*/ +/*----------------------------------------------------------------------------*/ +int dev_manager_online_check_by_logo(char *logo, u8 valid) +{ + struct __dev *dev = dev_manager_find_spec(logo, valid); + return (dev ? 1 : 0); +} +//*----------------------------------------------------------------------------*/ +/**@brief 通过设备节点判断设备是否在线 + @param + dev:设备节点 + valid: + 1:检查有效可播放设备 + 0:检查所有设备 + @return 1:在线 0:不在线 + @note +*/ +/*----------------------------------------------------------------------------*/ +int dev_manager_online_check(struct __dev *dev, u8 valid) +{ + if (dev_manager_check(dev) == NULL) { + return 0; + }else{ + if(valid){ + return (dev->valid ? 1 : 0); + }else{ + return 1; + } + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief 通过逻辑盘符判断设备是否在设备链表中 + @param + logo:逻辑盘符,如:sd0/sd1/udisk0 + @return 1:在设备链表中, 0:不在设备链表中 + @note 该接口会检查所有在设备链表中的设备,忽略mount,valid等状态 +*/ +/*----------------------------------------------------------------------------*/ +struct __dev *dev_manager_list_check_by_logo(char *logo) +{ + if (logo == NULL) { + return 0; + } + struct __dev *dev; + os_mutex_pend(&__this->mutex, 0); + list_for_each_entry(dev, &__this->list, entry) { + if (!strcmp(dev->parm->logo, logo)) { + os_mutex_post(&__this->mutex); + return dev; + } + } + os_mutex_post(&__this->mutex); + return NULL; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 检查链表中没有挂载的设备并重新挂载 + @param + logo:逻辑盘符,如:sd0/sd1/udisk0 + @return 1:在设备链表中, 0:不在设备链表中 + @note 该接口会检查所有在设备链表中的设备,忽略mount,valid等状态 +*/ +/*----------------------------------------------------------------------------*/ +void dev_manager_list_check_mount(void) +{ + struct __dev *dev; + os_mutex_pend(&__this->mutex, 0); + list_for_each_entry(dev, &__this->list, entry) { + if(dev->valid == 0){ + if(dev->fmnt){ + unmount(dev->parm->storage_path); + dev->fmnt = NULL; + } + } + if(dev->fmnt == NULL){ + struct __dev_reg *p = dev->parm; + dev->fmnt = mount(p->name, p->storage_path, p->fs_type, 3, NULL); + dev->valid = (dev->fmnt ? 1 : 0); + } + } + os_mutex_post(&__this->mutex); +} + +//*----------------------------------------------------------------------------*/ +/**@brief 设备挂载 + @param + logo:逻辑盘符,如:sd0/sd1/udisk0 + @return 0:成功, -1:失败 + @note 需要主动mount设备可以调用改接口 +*/ +/*----------------------------------------------------------------------------*/ +static int __dev_manager_mount(char *logo) +{ + int ret = 0; + os_mutex_pend(&__this->mutex, 0); + struct __dev *dev = dev_manager_list_check_by_logo(logo); + if (dev == NULL) { + os_mutex_post(&__this->mutex); + return -1; + } + if(dev->fmnt == NULL){ + struct __dev_reg *p = dev->parm; + dev->fmnt = mount(p->name, p->storage_path, p->fs_type, 3, NULL); + dev->valid = (dev->fmnt ? 1 : 0); + } + ret = (dev->valid ? 0 : -1); + os_mutex_post(&__this->mutex); + return ret; +} +//*----------------------------------------------------------------------------*/ +/**@brief 设备卸载 + @param + logo:逻辑盘符,如:sd0/sd1/udisk0 + @return 0:成功, -1:失败 + @note 需要主动unmount设备可以调用改接口 +*/ +/*----------------------------------------------------------------------------*/ +static int __dev_manager_unmount(char *logo) +{ + os_mutex_pend(&__this->mutex, 0); + struct __dev *dev = dev_manager_check_by_logo(logo); + if (dev == NULL) { + os_mutex_post(&__this->mutex); + return -1; + } + if(dev->fmnt){ + unmount(dev->parm->storage_path); + dev->fmnt = NULL; + } + dev->valid = 0; + os_mutex_post(&__this->mutex); + return 0; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 设备挂载 + @param + logo:逻辑盘符,如:sd0/sd1/udisk0 + @return 0:成功, -1:失败 + @note 慎用 +*/ +/*----------------------------------------------------------------------------*/ +int dev_manager_mount(char *logo) +{ + int ret = __dev_manager_mount(logo); + if(ret == 0){ +#if TCFG_RECORD_FOLDER_DEV_ENABLE + char rec_dev_logo[16] = {0}; + sprintf(rec_dev_logo, "%s%s", logo, "_rec"); + ret = __dev_manager_mount(rec_dev_logo); + if(ret){ + __dev_manager_unmount(logo); + } +#endif + } + return ret; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 设备卸载 + @param + logo:逻辑盘符,如:sd0/sd1/udisk0 + @return 0:成功, -1:失败 + @note 慎用 +*/ +/*----------------------------------------------------------------------------*/ +int dev_manager_unmount(char *logo) +{ +#if TCFG_RECORD_FOLDER_DEV_ENABLE + char rec_dev_logo[16] = {0}; + sprintf(rec_dev_logo, "%s%s", logo, "_rec"); + __dev_manager_unmount(rec_dev_logo); +#endif + __dev_manager_unmount(logo); + return 0; +} + + +//*----------------------------------------------------------------------------*/ +/**@brief 设备检测线程处理 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +extern void hidden_file(u8 flag); +static void dev_manager_task(void *p) +{ + int res = 0; + int msg[8] = {0}; + ///过滤隐藏 和 .开头名名的字文件 + hidden_file(1); + ///设备初始化, + devices_init(); + +#if SDFILE_STORAGE && TCFG_CODE_FLASH_ENABLE + dev_manager_add(SDFILE_DEV); +#endif + +#if TCFG_NOR_REC + dev_manager_add("rec_nor"); +#endif + +#if TCFG_NOR_FAT + dev_manager_add("fat_nor"); +#endif + +#if TCFG_NOR_FS + dev_manager_add("res_nor"); +#endif + +#if TCFG_VIR_UDISK_ENABLE + dev_manager_add("vir_udisk0"); +#endif + +#if TCFG_VIRFAT_FLASH_ENABLE + dev_manager_add("virfat_flash"); + dev_manager_set_valid_by_logo("virfat_flash", 0);///将设备设置为无效设备 +#endif + +#if FLASH_INSIDE_REC_ENABLE + set_rec_capacity(512*1024);//需要先设置容量,注意要小于Ini文件设置大小. + _sdfile_rec_init(); + dev_manager_add("rec_sdfile"); +#endif + + os_sem_post(&__this->sem); + + while (1) { + res = os_task_pend("taskq", msg, ARRAY_SIZE(msg)); + switch (res) { + case OS_TASKQ: + switch (msg[0]) { + case Q_EVENT: + break; + case Q_MSG: + break; + default: + break; + } + break; + default: + break; + } + } +} + +void dev_manager_var_init() +{ + memset(__this, 0, sizeof(struct __dev_manager)); + INIT_LIST_HEAD(&__this->list); + os_mutex_create(&__this->mutex); +} + +#endif/*TCFG_DEV_MANAGER_ENABLE*/ +//*----------------------------------------------------------------------------*/ +/**@brief 设备管理器初始化 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void dev_manager_init(void) +{ +#if (TCFG_DEV_MANAGER_ENABLE) + dev_manager_var_init(); + + os_sem_create(&__this->sem, 0); + + int err = task_create(dev_manager_task, NULL, DEV_MANAGER_TASK_NAME); + if (err != OS_NO_ERR) { + ASSERT(0, "task_create fail!!! %x\n", err); + } + os_sem_pend(&__this->sem, 0); +#else + devices_init(); +#endif +} + diff --git a/apps/common/dev_manager/dev_manager.h b/apps/common/dev_manager/dev_manager.h new file mode 100644 index 0000000..d7573c9 --- /dev/null +++ b/apps/common/dev_manager/dev_manager.h @@ -0,0 +1,93 @@ +#ifndef __DEV_MANAGER_H__ +#define __DEV_MANAGER_H__ + +#include "system/includes.h" +#include "typedef.h" +#include "system/fs/fs.h" + +enum { + DEV_MANAGER_ADD_OK = 0x0, + DEV_MANAGER_ADD_IN_LIST_AREADY, + DEV_MANAGER_ADD_ERR_PARM, + DEV_MANAGER_ADD_ERR_NOMEM, + DEV_MANAGER_ADD_ERR_NOT_FOUND, + DEV_MANAGER_ADD_ERR_MOUNT_FAIL, +}; + + +struct __dev; + +struct __scan_callback { + void (*enter)(struct __dev *dev); + void (*exit)(struct __dev *dev); + int (*scan_break)(void); +}; + +//dev_manager增加设备节点 +int dev_manager_add(char *logo); +//dev_manager删除设备节点 +int dev_manager_del(char *logo); +//dev_manager获取设备总数 +u32 dev_manager_get_total(u8 valid); +//dev_manager通过设备节点检查设备是否在设备链表中 +struct __dev *dev_manager_check(struct __dev *dev); +//dev_manager通过逻辑盘符检查设备是否在设备链表中 +struct __dev *dev_manager_check_by_logo(char *logo); +//dev_manager查找第一个设备 +struct __dev *dev_manager_find_first(u8 valid); +//dev_manager查找最后一个设备 +struct __dev *dev_manager_find_last(u8 valid); +//dev_manager查找参数设备的前一个设备 +struct __dev *dev_manager_find_prev(struct __dev *dev, u8 valid); +//dev_manager查找参数设备的后一个设备 +struct __dev *dev_manager_find_next(struct __dev *dev, u8 valid); +//dev_manager查找最后活动设备 +struct __dev *dev_manager_find_active(u8 valid); +//dev_manager查找指定逻辑盘符对应的设备 +struct __dev *dev_manager_find_spec(char *logo, u8 valid); +//dev_manager查找指定序号设备 +struct __dev *dev_manager_find_by_index(u32 index, u8 valid); +//dev_manager扫盘句柄释放 +void dev_manager_scan_disk_release(struct vfscan *fsn); +//dev_manager扫盘 +struct vfscan *dev_manager_scan_disk(struct __dev *dev, const char *path, const char *parm, u8 cycle_mode, struct __scan_callback *callback); +//dev_manager设定指定设备节点设备有效 +void dev_manager_set_valid(struct __dev *dev, u8 flag); +//dev_manager设定指定设备节点设备为最后活动设备 +void dev_manager_set_active(struct __dev *dev); +//dev_manager设定指定逻辑盘符的设备有效 +void dev_manager_set_valid_by_logo(char *logo, u8 flag); +//dev_manager设定指定逻辑盘符的设备为最后活动设备 +void dev_manager_set_active_by_logo(char *logo); +//dev_manager获取指定设备节点的逻辑盘符 +char *dev_manager_get_logo(struct __dev *dev); +//获取物理设备节点的逻辑盘符(去掉_rec后缀) +char *dev_manager_get_phy_logo(struct __dev *dev); +//获取录音文件夹设备节点的逻辑盘符(追加_rec后缀) +char *dev_manager_get_rec_logo(struct __dev *dev); +//dev_manager获取指定设备节点的文件系统根目录 +char *dev_manager_get_root_path(struct __dev *dev); +//dev_manager获取指定逻辑盘符的设备的文件系统根目录 +char *dev_manager_get_root_path_by_logo(char *logo); +//dev_manager通过设备节点获取设备mount信息 +struct imount *dev_manager_get_mount_hdl(struct __dev *dev); +//dev_manager通过设备节点检查设备是否在线 +int dev_manager_online_check(struct __dev *dev, u8 valid); +//dev_manager通过逻辑盘符检查设备是否在线 +int dev_manager_online_check_by_logo(char *logo, u8 valid); +//通过逻辑盘符判断设备是否在设备链表中 +struct __dev *dev_manager_list_check_by_logo(char *logo); +//检查链表中没有挂载的设备并重新挂载 +void dev_manager_list_check_mount(void); +//设备挂载 +int dev_manager_mount(char *logo); +//设备卸载 +int dev_manager_unmount(char *logo); + +//dev_manager初始化 +void dev_manager_init(void); + +void dev_manager_var_init(); + +#endif//__DEV_MANAGER_H__ + diff --git a/apps/common/dev_manager/dev_reg.c b/apps/common/dev_manager/dev_reg.c new file mode 100644 index 0000000..5949eb5 --- /dev/null +++ b/apps/common/dev_manager/dev_reg.c @@ -0,0 +1,165 @@ +#include "dev_reg.h" +#include "app_config.h" + + +//*----------------------------------------------------------------------------*/ +/**@brief 设备配置表 + @param 具体配置项请看struct __dev_reg结构体描述 + @return + @note 注意: + 例如logo逻辑盘符sd0_rec/sd1_rec/udisk_rec是做录音文件夹区分使用的, + 在定义新的设备逻辑盘发的时候, 注意避开"_rec"后缀作为设备逻辑盘符 +*/ +/*----------------------------------------------------------------------------*/ + + +const struct __dev_reg dev_reg[] = { +#if SDFILE_STORAGE && TCFG_CODE_FLASH_ENABLE + //内置flash + { + /*logo*/ SDFILE_DEV, + /*name*/ NULL, + /*storage_path*/ SDFILE_MOUNT_PATH, + /*root_path*/ SDFILE_RES_ROOT_PATH, + /*fs_type*/ "sdfile", + }, +#endif +#if FLASH_INSIDE_REC_ENABLE + //内置录音 + { + /*logo*/ "rec_sdfile", + /*name*/ NULL, + /*storage_path*/ "mnt/rec_sdfile", + /*root_path*/ "mnt/rec_sdfile/C/", + /*fs_type*/ "rec_sdfile", + }, +#endif +#if (TCFG_SD0_ENABLE) + //sd0 + { + /*logo*/ "sd0", + /*name*/ "sd0", + /*storage_path*/ "storage/sd0", + /*root_path*/ "storage/sd0/C/", + /*fs_type*/ "fat", + }, +#endif +#if (TCFG_SD1_ENABLE) + //sd1 + { + /*logo*/ "sd1", + /*name*/ "sd1", + /*storage_path*/ "storage/sd1", + /*root_path*/ "storage/sd1/C/", + /*fs_type*/ "fat", + }, +#endif +#if (TCFG_UDISK_ENABLE) + //u盘 + { + /*logo*/ "udisk0", + /*name*/ "udisk0", + /*storage_path*/ "storage/udisk0", + /*root_path*/ "storage/udisk0/C/", + /*fs_type*/ "fat", + }, +#endif +#if (TCFG_SD0_ENABLE && TCFG_RECORD_FOLDER_DEV_ENABLE) + //sd0录音文件夹分区 + { + /*logo*/ "sd0_rec", + /*name*/ "sd0", + /*storage_path*/ "storage/sd0", + /*root_path*/ "storage/sd0/C/"REC_FOLDER_NAME, + /*fs_type*/ "fat", + }, +#endif +#if (TCFG_SD1_ENABLE && TCFG_RECORD_FOLDER_DEV_ENABLE) + //sd1录音文件夹分区 + { + /*logo*/ "sd1_rec", + /*name*/ "sd1", + /*storage_path*/ "storage/sd1", + /*root_path*/ "storage/sd1/C/"REC_FOLDER_NAME, + /*fs_type*/ "fat", + }, +#endif +#if (TCFG_UDISK_ENABLE && TCFG_RECORD_FOLDER_DEV_ENABLE) + //u盘录音文件夹分区 + { + /*logo*/ "udisk0_rec", + /*name*/ "udisk0", + /*storage_path*/ "storage/udisk0", + /*root_path*/ "storage/udisk0/C/"REC_FOLDER_NAME, + /*fs_type*/ "fat", + }, +#endif +#if TCFG_NOR_FAT + //外挂fat分区 + { + /*logo*/ "fat_nor", + /*name*/ "fat_nor", + /*storage_path*/ "storage/fat_nor", + /*root_path*/ "storage/fat_nor/C/", + /*fs_type*/ "fat", + }, +#endif +#if TCFG_NOR_FS + //外挂flash资源分区 + { + /*logo*/ "res_nor", + /*name*/ "res_nor", + /*storage_path*/ "storage/res_nor", + /*root_path*/ "storage/res_nor/C/", + /*fs_type*/ "nor_sdfile", + }, +#endif +#if TCFG_NOR_REC + ///外挂录音分区 + { + /*logo*/ "rec_nor", + /*name*/ "rec_nor", + /*storage_path*/ "storage/rec_nor", + /*root_path*/ "storage/rec_nor/C/", + /*fs_type*/ "rec_fs", + }, +#endif + { + /*logo*/ "nor_ui", + /*name*/ "nor_ui", + /*storage_path*/ "storage/nor_ui", + /*root_path*/ "storage/nor_ui/C/", + /*fs_type*/ "nor_sdfile", + }, +#if TCFG_VIR_UDISK_ENABLE + // 虚拟U盘 + { + /*logo*/ "vir_udisk0", + /*name*/ "vir_udisk0", + /*storage_path*/ "storage/vir_udisk0", + /*root_path*/ "storage/vir_udisk0/C/", + /*fs_type*/ "fat", + }, +#endif +#if TCFG_VIRFAT_FLASH_ENABLE + //flash 虚拟fat + { + /*logo*/ "virfat_flash", + /*name*/ "virfat_flash", + /*storage_path*/ "storage/virfat_flash", + /*root_path*/ "storage/virfat_flash/C/", + /*fs_type*/ "sdfile_fat", + }, +#endif + //<新加设备参数请在reg end前添加!! + //type == type) { + parm = (struct __update_dev_reg *)update_dev_list[i]; + } + } + + if (parm == NULL) { + return NULL; + } + return (void *)&parm->u.sd; +} + + +struct strg_update { + void *fd; + char *update_path; +}; +static struct strg_update strg_update = {0}; +#define __this (&strg_update) + +static u16 strg_f_open(void) +{ + if (!__this->update_path) { + printf("file path err "); + return false; + } + + if (__this->fd) { + return true; + /* fclose(__this->fd); + __this->fd = NULL; */ + } + __this->fd = fopen(__this->update_path, "r"); + if (!__this->fd) { + printf("file open err "); + return false; + } + return true; +} + +static u16 strg_f_read(void *fp, u8 *buff, u16 len) +{ + if (!__this->fd) { + return (u16) - 1; + } + + len = fread(__this->fd, buff, len); + return len; +} + +static int strg_f_seek(void *fp, u8 type, u32 offset) +{ + if (!__this->fd) { + return (int) - 1; + } + + int ret = fseek(__this->fd, offset, type); + /* return 0; // 0k */ + return ret; +} +static u16 strg_f_stop(u8 err) +{ + if (__this->fd) { + fclose(__this->fd); + __this->fd = NULL; + } + return true; +} + +static int strg_update_set_file_path_and_hdl(char *update_path, void *fd) +{ + __this->update_path = update_path; + __this->fd = fd; + + return true; +} + +static const update_op_api_t strg_dev_update_op = { + .f_open = strg_f_open, + .f_read = strg_f_read, + .f_seek = strg_f_seek, + .f_stop = strg_f_stop, +}; + +static void dev_update_param_private_handle(UPDATA_PARM *p) +{ + u16 up_type = p->parm_type; + +#ifdef CONFIG_SD_UPDATE_ENABLE + if ((up_type == SD0_UPDATA) || (up_type == SD1_UPDATA)) { + int sd_start = (u32)p + sizeof(UPDATA_PARM); + void *sd = NULL; + sd = dev_update_get_parm(up_type); + if (sd) { + memcpy((void *)sd_start, sd, UPDATE_PRIV_PARAM_LEN); + } else { + memset((void *)sd_start, 0, UPDATE_PRIV_PARAM_LEN); + } + } +#endif + +#ifdef CONFIG_USB_UPDATE_ENABLE + if (up_type == USB_UPDATA) { + printf("usb updata "); + int usb_start = (u32)p + sizeof(UPDATA_PARM); + memset((void *)usb_start, 0, UPDATE_PRIV_PARAM_LEN); + } +#endif + memcpy(p->file_patch, updata_file_name, strlen(updata_file_name)); +} + +static void dev_update_before_jump_handle(u16 up_type) +{ +#ifdef DEV_UPDATE_SUPPORT_JUMP +#if TCFG_BLUETOOTH_BACK_MODE //后台模式需要把蓝牙关掉 + if (BT_MODULES_IS_SUPPORT(BT_MODULE_LE)) { + ll_hci_destory(); + } + hci_controller_destory(); +#endif + update_close_hw("null"); + ram_protect_close(); + save_spi_port(); + + printf("update jump to mask...\n"); + /* JL_UART0->CON0 = 0; */ + /* JL_UART1->CON0 = 0; */ + __JUMP_TO_MASKROM(); +#else + cpu_reset(); +#endif //DEV_UPDATE_SUPPORT_JUMP +} + +static void dev_update_state_cbk(int type, u32 state, void *priv) +{ + update_ret_code_t *ret_code = (update_ret_code_t *)priv; + + switch (state) { + case UPDATE_CH_EXIT: + if ((0 == ret_code->stu) && (0 == ret_code->err_code)) { + update_mode_api_v2(type, + dev_update_param_private_handle, + dev_update_before_jump_handle); + } else { + printf("update fail, cpu reset!!!\n"); + cpu_reset(); + } + break; + } +} +u16 dev_update_check(char *logo) +{ + if (update_success_boot_check() == true) { + return UPDATA_NON; + } + struct __dev *dev = dev_manager_find_spec(logo, 0); + if (dev) { +#if DEV_UPDATE_EN + //<查找设备升级配置 + struct __update_dev_reg *parm = NULL; + for (int i = 0; i < ARRAY_SIZE(update_dev_list); i++) { + if (0 == strcmp(update_dev_list[i]->logo, logo)) { + parm = (struct __update_dev_reg *)update_dev_list[i]; + } + } + if (parm == NULL) { + printf("dev update without parm err!!!\n"); + return UPDATA_PARM_ERR; + } + //<尝试按照路径打开升级文件 + char *updata_file = (char *)updata_file_name; + if (*updata_file == '/') { + updata_file ++; + } + memset(update_path, 0, sizeof(update_path)); + sprintf(update_path, "%s%s", dev_manager_get_root_path(dev), updata_file); + printf("update_path: %s\n", update_path); + FILE *fd = fopen(update_path, "r"); + if (!fd) { + ///没有升级文件, 继续跑其他解码相关的流程 + printf("open update file err!!!\n"); + return UPDATA_DEV_ERR; + } + +#if(USER_UART_UPDATE_ENABLE) && (UART_UPDATE_ROLE == UART_UPDATE_MASTER) + uart_update_send_update_ready(update_path); + while (get_uart_update_sta()) { + os_time_dly(10); + } +#else + ///进行升级 + /* storage_update_loader_download_init_with_file_hdl( + parm->type, + update_path, + (void *)fd, + dev_update_callback, + (void *)parm, + 0); */ + + strg_update_set_file_path_and_hdl(update_path, (void *)fd); + + update_mode_info_t info = { + .type = parm->type, + .state_cbk = dev_update_state_cbk, + .p_op_api = &strg_dev_update_op, + .task_en = 0, + }; + app_active_update_task_init(&info); + +#endif// USER_UART_UPDATE_ENABLE + +#endif//DEV_UPDATE_EN + } + return UPDATA_READY; +} + + + diff --git a/apps/common/dev_manager/dev_update.h b/apps/common/dev_manager/dev_update.h new file mode 100644 index 0000000..dc7a0e6 --- /dev/null +++ b/apps/common/dev_manager/dev_update.h @@ -0,0 +1,10 @@ +#ifndef __DEV_UPDATE_H__ +#define __DEV_UPDATE_H__ + +#include "typedef.h" +#include "system/includes.h" + +void *dev_update_get_parm(int type); +u16 dev_update_check(char *logo); + +#endif//__DEV_UPDATE_H__ diff --git a/apps/common/device/detection.c b/apps/common/device/detection.c new file mode 100644 index 0000000..9d60a3a --- /dev/null +++ b/apps/common/device/detection.c @@ -0,0 +1,93 @@ +#include "system/includes.h" +#include "app_config.h" +#include "app_action.h" +#include "gpio.h" +#include "app_main.h" +#include "update.h" +#include "user_cfg.h" + + + + +u16 VDET_SAM_VALUE = 0; +/* #define VDET_FIX_VALUE 372 */ +#define VDET_FIX_VALUE 330 + +u16 vdet_timer = 0; + +typedef enum __VDET_STATUS { + VDET_OFF = 0, + VDET_ON, + NULL_VDET, +} VDET_STATUS; + +typedef struct __VDET_VAR { + u8 pre_status; + u8 cur_status; + u8 status_cnt; + u8 original_status; +} VDET_VAR; + + +VDET_VAR g_VDET_VAR = {0}; + +VDET_STATUS vdet_check(u8 cnt) +{ + VDET_SAM_VALUE = adc_get_value(AD_CH_PB1); + printf("aaaaaaaaaaaaaaaaaaaaaa=%d\n", VDET_SAM_VALUE); + if (VDET_SAM_VALUE > VDET_FIX_VALUE) { + g_VDET_VAR.cur_status = 1; + } else { + g_VDET_VAR.cur_status = 0; + } + if (g_VDET_VAR.cur_status != g_VDET_VAR.pre_status) { + g_VDET_VAR.original_status = g_VDET_VAR.pre_status; + g_VDET_VAR.pre_status = g_VDET_VAR.cur_status; + g_VDET_VAR.status_cnt = 0; + } else { + g_VDET_VAR.status_cnt++; + } + if (g_VDET_VAR.status_cnt < cnt) { + ///检测到插入//消抖 + return NULL_VDET; + } + g_VDET_VAR.status_cnt = 0; + + ///检测到插入 + if ((VDET_ON == g_VDET_VAR.cur_status) && (!g_VDET_VAR.original_status)) { + return VDET_ON; + } else if ((VDET_OFF == g_VDET_VAR.cur_status) && g_VDET_VAR.original_status) { + return VDET_OFF; + } + return NULL_VDET; +} + +void vdet_detect(void) +{ + VDET_STATUS res; + res = vdet_check(20); + if (VDET_ON == res) { + printf("VDET=============ON\n"); + } else if (VDET_OFF == res) { + printf("VDET=============OFF\n"); + } +} + +void vdet_init(void) +{ + adc_add_sample_ch(AD_CH_PB1); + gpio_set_die(IO_PORTB_01, 0); + gpio_set_direction(IO_PORTB_01, 1); + gpio_set_pull_down(IO_PORTB_01, 0); + gpio_set_pull_up(IO_PORTB_01, 0); +} + +void vdet_check_init(void) +{ + if (vdet_timer == 0) { + vdet_timer = sys_timer_add(NULL, vdet_detect, 10); + } + vdet_init(); +} + + diff --git a/apps/common/device/fm/bk1080/BK1080.h b/apps/common/device/fm/bk1080/BK1080.h new file mode 100644 index 0000000..e426609 --- /dev/null +++ b/apps/common/device/fm/bk1080/BK1080.h @@ -0,0 +1,31 @@ +/*--------------------------------------------------------------------------*/ +/**@file bk1080.h + @brief BK1080收音 + @details + @author + @date 2011-3-30 + @note +*/ +/*----------------------------------------------------------------------------*/ +#ifndef _BK_1080_H_ +#define _BK_1080_H_ + +#if(TCFG_FM_BK1080_ENABLE == ENABLE) + + +#define XTAL_CLOCK 1 +#define CHIP_DEV_ID 0x80 + + +void bk1080_init(void *priv); +void bk1080_setfreq(u16 curFreq); +bool bk1080_set_fre(void *priv, u16 freq); +void bk1080_powerdown(void *priv); +void bk1080_mute(void *priv, u8 flag); +bool bk1080_read_id(void *priv); +void bk1080_setch(u8 db); + + +#endif + +#endif /* _BK_1080_H_ */ diff --git a/apps/common/device/fm/bk1080/Bk1080.c b/apps/common/device/fm/bk1080/Bk1080.c new file mode 100644 index 0000000..ec66bc7 --- /dev/null +++ b/apps/common/device/fm/bk1080/Bk1080.c @@ -0,0 +1,467 @@ +/*--------------------------------------------------------------------------*/ +/**@file bk1080.c + @brief BK1080收音底层驱动 + @details + @author + @date 2011-3-30 + @note +*/ +/*----------------------------------------------------------------------------*/ + +#include "app_config.h" + +#include "system/includes.h" +#include "fm/fm_manage.h" +#include "BK1080.h" + +#if(TCFG_FM_BK1080_ENABLE && TCHFG_SOFT_I2C_ENABLE) + + +extern void delay_2ms(int cnt); + +#define delay_n10ms(x) \ + delay_2ms(x*5) + +static struct _fm_dev_info *fm_dev_info; + +/** +*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 必看 @@@@@@@@@@@@@@@@@@@@@@@@@@@ +*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 必看 @@@@@@@@@@@@@@@@@@@@@@@@@@@ +* +*BK1080H可以使用外部晶振 +* +*BK1080E不能使用外部晶振,因此主控需要提供一个时钟 +*BK1080E需要的时钟范围是:32.768kHz~38.4MHz +*可以通过以下bk1080e_set_clk函数让主控在PA0输出一个24MHz的时钟 +*该函数使用时加到int fm_dev_init(void *_data)函数的第一行 +*该时钟及输出的IO口可配置,如需要可联系原厂提供帮助 +* +*/ +/* void bk1080e_set_clk(void){ */ +/* JL_PORTA->DIR &= ~BIT(0); */ +/* JL_CLOCK->CLK_CON0 &=~ BIT(12); */ + +/* JL_CLOCK->CLK_CON0 &=~ BIT(11); */ +/* JL_CLOCK->CLK_CON0 |= BIT(10); */ +/* } */ + + +/*------------BK1080 Initialization Table-----------------*/ +/* +const u16 HW_Reg[]= +{ + 0x0008, + 0x1080, +#if XTAL_CLOCK //reg2 + 0x1201, //for internal crystal clock +#else + 0x0201, //for extern clock +#endif + 0x0000, + 0x40C0, + 0x0A1F, //reg5 RSSI[15:8] BAND[7:6] SPACE[5:4],Europe standar + 0x002E, + 0x02FF, + 0x5B11, + 0x0000, + 0x411E, + 0x0000, + 0xCE00, + 0x0000, + 0x0000, + 0x1000, //reg15 + 0x0010, + 0x0000, + 0x13FF, + 0x9852, + 0x0000, + 0x0000, + 0x0008, + 0x0000, + 0x51E1, + 0x28DC, + 0x2645, + 0x00E4, + 0x1CD8, + 0x3A50, + 0xEAF0, + 0x3000, //reg31 + 0x0200, + 0x0000, +}; +*/ + +const u16 HW_Reg[] = { + 0x0800, + 0x8010, +#if XTAL_CLOCK //reg2 + 0x0112, //for internal crystal clock +#else + 0x0142, //for extern clock, system mute +#endif + 0x0000, + 0xC040, + 0x1F0A, //reg5 RSSI[15:8] BAND[7:6] SPACE[5:4],Europe standar + 0x2E00, + 0xFF02, + 0x115B, + 0x0000, + 0x1E41, + 0x0000, + 0x00CE, + 0x0000, + 0x0000, + 0x0010, //reg15 + 0x1000, + 0x0000, + 0xFF13, + 0x5298, + 0x0000, + 0x0000, + 0x0800, + 0x0000, + 0xE151, + 0xDC38, + 0x4526, + 0xE400, + 0xD81C, + 0x503A, + 0xF0EA, + 0x0030, //reg31 + 0x0002, + 0x0000, +}; + + +u8 bk1080_iic_write(u8 w_chip_id, u8 register_address, u8 *buf, u32 data_len) +{ + u8 ret = 1; + iic_start(fm_dev_info->iic_hdl); + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, w_chip_id)) { + ret = 0; + log_e("\n fm iic wr err 0\n"); + goto __gcend; + } + + delay(fm_dev_info->iic_delay); + + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, register_address)) { + ret = 0; + log_e("\n fm iic wr err 1\n"); + goto __gcend; + } + u8 *pbuf = buf; + + while (data_len--) { + delay(fm_dev_info->iic_delay); + + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, *pbuf++)) { + ret = 0; + log_e("\n fm iic wr err 2\n"); + goto __gcend; + } + } + +__gcend: + iic_stop(fm_dev_info->iic_hdl); + + return ret; +} + +u8 bk1080_iic_readn(u8 r_chip_id, u8 register_address, u8 *buf, u8 data_len) +{ + u8 read_len = 0; + + iic_start(fm_dev_info->iic_hdl); + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, (r_chip_id & 0x01) ? (r_chip_id - 1) : (r_chip_id))) { + log_e("\n fm iic rd err 0\n"); + read_len = 0; + goto __gdend; + } + + + delay(fm_dev_info->iic_delay); + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, register_address)) { + log_e("\n fm iic rd err 1\n"); + read_len = 0; + goto __gdend; + } + + /* delay(fm_dev_info->iic_delay); */ + /* iic_start(fm_dev_info->iic_hdl); */ + /* if (0 == iic_tx_byte(fm_dev_info->iic_hdl, r_chip_id)) { */ + /* log_e("\n fm iic rd err 2\n"); */ + /* read_len = 0; */ + /* goto __gdend; */ + /* } */ + + delay(fm_dev_info->iic_delay); + + for (; data_len > 1; data_len--) { + *buf++ = iic_rx_byte(fm_dev_info->iic_hdl, 1); + read_len ++; + } + + *buf = iic_rx_byte(fm_dev_info->iic_hdl, 0); + +__gdend: + + iic_stop(fm_dev_info->iic_hdl); + delay(fm_dev_info->iic_delay); + + return read_len; +} + +#define app_IIC_write bk1080_iic_write +#define app_IIC_readn bk1080_iic_readn + +/*----------------------------------------------------------------------------*/ +/**@brief BK1080读寄存器函数 + @param num 需要的数目 + @return 无 + @note void BEKEN_I2c_Read(u8 reg,u8 *pBuf,u8 num) +*/ +/*----------------------------------------------------------------------------*/ +static void BEKEN_I2c_Read(u8 reg, u8 *pBuf, u8 num) +{ + reg = reg << 1; + reg |= 0x01; + app_IIC_readn(CHIP_DEV_ID, reg, pBuf, num); +} + +/*----------------------------------------------------------------------------*/ +/**@brief BK1080读寄存器函数 + @param num 需要的数目 + @return 无 + @note void BEKEN_I2c_Write(u8 reg,u8 *pBuf,u8 num) +*/ +/*----------------------------------------------------------------------------*/ +static void BEKEN_I2c_Write(u8 reg, u8 *pBuf, u8 num) +{ + reg = reg << 1; + app_IIC_write(CHIP_DEV_ID, reg, pBuf, num); +} + +/*----------------------------------------------------------------------------*/ +/**@brief BK1080 初始化 + @param 无 + @return 无 + @note void init_BK1080(void) +*/ +/*----------------------------------------------------------------------------*/ +void bk1080_init(void *priv) +{ + if (priv != NULL) { + fm_dev_info = priv; + } + u8 temp[2]; + //delay_n10ms(100); //delay 1s,please revise delay time according to your MCU + + BEKEN_I2c_Write(0, (u8 *)HW_Reg, 68); //start from reg2,total 60 byte + + delay_n10ms(25); //delay 250ms + temp[0] = HW_Reg[25]; + temp[1] = HW_Reg[25] >> 8; + temp[1] &= 0x7f; + BEKEN_I2c_Write(25, temp, 2); + + temp[1] |= 0x80; + BEKEN_I2c_Write(25, temp, 2); + + /* dac_channel_on(FM_IIC_CHANNEL, FADE_ON); */ + + delay_n10ms(5); //delay 50ms +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 设置一个频点 BK1080 + @param curFreq:设置频点 + @return 无 + @note void bk1080_setfreq(u16 curFreq) +*/ +/*----------------------------------------------------------------------------*/ +void bk1080_setfreq(u16 curFreq) +{ + u8 curChan; + u16 temp; + + curChan = curFreq - (REAL_FREQ_MIN / 10); + + temp = curChan << 8; + BEKEN_I2c_Write(0x03, (u8 *)&temp, 2); //write reg3,with 2 bytes + + temp |= 0x80; + BEKEN_I2c_Write(0x03, (u8 *)&temp, 2); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 设置一个频点BK1080 + @param fre 频点 875~1080 + @return 1:当前频点有台,0:当前频点无台 + @note bool bk1080_set_fre(u16 freq) +*/ +/*----------------------------------------------------------------------------*/ +bool bk1080_set_fre(void *priv, u16 freq) +{ + static u16 last_tuned_freq; + static u16 g_last_freq_deviation_value; + u8 temp[4]; + u16 cur_freq_deviation; + + bk1080_setfreq(freq); + delay_n10ms(4); //延时时间>=30ms + +/////////////////////////////////////////////////////////////////// +//new added 2009-05-30 + + BEKEN_I2c_Read(0x07, temp, 2); //start from reg 0x7,with 2bytes + + cur_freq_deviation = (temp[0] << 8) | temp[1]; + cur_freq_deviation = cur_freq_deviation >> 4; + + BEKEN_I2c_Read(0x0a, &temp[2], 2); + +///////////////////////////////////////////////////////////////////// + if (temp[2] & 0x10) { //check AFCRL bit12 + last_tuned_freq = freq; //save last tuned freqency + g_last_freq_deviation_value = cur_freq_deviation; + return 0; + } + + if (temp[3] < 8) { //RSSI<10 //搜台较少可减少该值,假台较多可增大该值 //8 + last_tuned_freq = freq; //save last tuned freqency + g_last_freq_deviation_value = cur_freq_deviation; + return 0; + } + + if ((temp[1] & 0x0f) < 2) { //SNR<2 //搜台较少可减少该值,假台较多可增大该值 + last_tuned_freq = freq; //save last tuned freqency + g_last_freq_deviation_value = cur_freq_deviation; + return 0; + } +///////////////////////////////////////////////////////////////////////// +//add frequency devation check + if ((cur_freq_deviation >= 192) && (cur_freq_deviation <= (0xfff - 192))) { //0x64 //搜台较少可减少该值,假台较多可增大该值 + last_tuned_freq = freq; //save last tuned freqency + g_last_freq_deviation_value = cur_freq_deviation; + + return 0; + } + +/////////////////////////////////////////////////////////////////////////// +//new added 2009-05-30 + if ((freq > 875) && ((freq - last_tuned_freq) == 1)) { //start_freq)&&( (freq-last_tuned_freq)==1) ) + if (g_last_freq_deviation_value & 0x800) { + last_tuned_freq = freq; //save last tuned freqency + g_last_freq_deviation_value = cur_freq_deviation; + return 0; + } + + if (g_last_freq_deviation_value < 150) { //搜台较少可减少该值,假台较多可增大该值 + last_tuned_freq = freq; //save last tuned freqency + g_last_freq_deviation_value = cur_freq_deviation; + return 0; + } + } + + if ((freq >= 875) && ((last_tuned_freq - freq) == 1)) { //start_freq)&&( (last_tuned_freq - freq)==1) ) + if ((g_last_freq_deviation_value & 0x800) == 0) { + last_tuned_freq = freq; //save last tuned freqency + g_last_freq_deviation_value = cur_freq_deviation; + return 0; + } + + if (g_last_freq_deviation_value > (0xfff - 150)) { //搜台较少可减少该值,假台较多可增大该值 + last_tuned_freq = freq; //save last tuned freqency + g_last_freq_deviation_value = cur_freq_deviation; + return 0; + } + } + + last_tuned_freq = freq; //save last tuned freqency + g_last_freq_deviation_value = cur_freq_deviation; + + return 1; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭 BK1080的电源 + @param 无 + @return 无 + @note void BK1080_PowerDown(void) +*/ +/*----------------------------------------------------------------------------*/ +void bk1080_powerdown(void *priv) +{ + u16 temp = 0x4102; + //temp[0] = 0x02; //write 0x0241 into reg2 + //temp[1] = 0x41; + BEKEN_I2c_Write(0x02, (u8 *)&temp, 2); + + /* dac_channel_off(FM_IIC_CHANNEL, FADE_ON); */ + delay_n10ms(5); //delay 50ms +} + +/*----------------------------------------------------------------------------*/ +/**@brief FM 模块静音控制 + @param dir:1-mute 0-unmute + @return 无 + @note void BK1080_mute(dir) +*/ +/*----------------------------------------------------------------------------*/ +void bk1080_mute(void *priv, u8 flag) +{ + u8 TmpData8[2]; + + BEKEN_I2c_Read(2, TmpData8, 2); + if (flag) { + TmpData8[0] |= 0x40; //mute + } else { + TmpData8[0] &= 0xbf; + } + + BEKEN_I2c_Write(2, TmpData8, 2); +} + +/*----------------------------------------------------------------------------*/ +/**@brief FM模块检测,获取BK1080 模块ID + @param 无 + @return 检测到BK1080模块返回1,否则返回0 + @note bool BK1080_Read_ID(void) +*/ +/*----------------------------------------------------------------------------*/ +bool bk1080_read_id(void *priv) +{ + u16 bk_id; + + if (fm_dev_info == NULL) { + fm_dev_info = (struct _fm_dev_info *)priv; + } + + BEKEN_I2c_Read(0x01, (u8 *)&bk_id, 2); //read reg3,with 2 bytes + + printf("bk1080_read_id %x", bk_id); + if (0x8010 == bk_id) { + return TRUE; + } + return FALSE; +} + +void bk1080_test(void) +{ + printf("bk1080 test\n"); +} + +REGISTER_FM(bk1080) = { + .logo = "bk1080", + .init = bk1080_init, + .close = bk1080_powerdown, + .set_fre = bk1080_set_fre, + .mute = bk1080_mute, + .read_id = bk1080_read_id, +}; + + +#endif diff --git a/apps/common/device/fm/fm_inside/fm_inside.c b/apps/common/device/fm/fm_inside/fm_inside.c new file mode 100644 index 0000000..c02a77a --- /dev/null +++ b/apps/common/device/fm/fm_inside/fm_inside.c @@ -0,0 +1,110 @@ +#include "app_config.h" +#include "system/includes.h" +#include "fm/fm_manage.h" +#include "asm/fm_inside_api.h" +#include "asm/dac.h" +#include "audio_config.h" +#include "media/audio_base.h" +#include "overlay_code.h" +#include "clock_cfg.h" +#include "fm_inside.h" + + +#if TCFG_APP_FM_EN +#if(TCFG_FM_INSIDE_ENABLE == ENABLE) + + +int fm_dec_open(u8 source, u32 sample_rate); +void fm_dec_close(void); +void fm_dig_mute(u8 mute); + +///--------------------------FM_INSIDE_API------------------------ +void fm_inside_init(void *priv) +{ + puts("fm_insice_init\n"); + + overlay_load_code(OVERLAY_FM); + + clock_add_set(FM_INSIDE_CLK); + + /* fm_dec_open(0xff, 37500); */ + + /* fm_inside_default_config(); */ + + /* #if CONFIG_CLOCK_BY_TYPE + u32 fm_clk = matching_code_type(AUDIO_ANOTHER_CLK_TYPE_FM, 1); + fm_inside_io_ctrl(SET_FM_INSIDE_SYS_CLK, fm_clk / 1000000L); + #else + fm_inside_io_ctrl(SET_FM_INSIDE_SYS_CLK, FM_CLOCK / 1000000L); + #endif */ + + fm_inside_mem_init(); + + fm_inside_io_ctrl(SET_FM_INSIDE_AGC_PARAM, FMSCAN_AGC, FMSCAN_ADD_DIFFER, FMSCAN_P_DIFFER, FMSCAN_N_DIFFER); + fm_inside_io_ctrl(SET_FM_INSIDE_COUNTRY_PARAM, REAL_FREQ_MIN, REAL_FREQ_MAX, FREQ_STEP); + fm_inside_io_ctrl(SET_FM_INSIDE_SCAN_ARG1, FMSCAN_SEEK_CNT_MIN, FMSCAN_SEEK_CNT_MAX, FMSCAN_CNR, FM_IF); + fm_inside_io_ctrl(SET_FM_INSIDE_SCAN_ARG2, FMSCAN_960_CNR, FMSCAN_1080_CNR); + + fm_inside_on(); //fm analog init + fm_inside_set_stereo(0); //set[0,128], 0 mono, 1~128 stereo. +} + +bool fm_inside_set_fre(void *priv, u16 fre) +{ + u8 ret; + u32 freq ; + //fm_printf("[%d]", fre); + freq = fre * 10; + ret = fm_inside_freq_set(freq); + return ret; +} + +bool fm_inside_read_id(void *priv) +{ + return (bool)fm_inside_id_read(); +} + +void fm_inside_powerdown(void *priv) +{ + fm_inside_off(); + /* dac_channel_off(FM_INSI_CHANNEL, FADE_ON); */ + fm_dec_close(); + clock_remove_set(FM_INSIDE_CLK); +} + +void fm_inside_mute(void *priv, u8 flag) +{ + if (!flag) { + /* fm_dec_open(0xff, 37500); */ + } + + if (flag) { + fm_dig_mute(flag); + } + + //fm_inside_int_set(!flag); + + if (!flag) { + /* os_time_dly(3); */ + fm_dig_mute(flag); + } + + if (flag) { + /* fm_dec_close(); */ + } +} + + +REGISTER_FM(fm_inside) = { + .logo = "fm_inside", + .init = fm_inside_init, + .close = fm_inside_powerdown, + .set_fre = fm_inside_set_fre, + .mute = fm_inside_mute, + .read_id = fm_inside_read_id, +}; + + +#endif // FM_INSIDE +#endif + diff --git a/apps/common/device/fm/fm_inside/fm_inside.h b/apps/common/device/fm/fm_inside/fm_inside.h new file mode 100644 index 0000000..0f28b05 --- /dev/null +++ b/apps/common/device/fm/fm_inside/fm_inside.h @@ -0,0 +1,45 @@ +#ifndef _FM_INSIDE_H_ +#define _FM_INSIDE_H_ + +#if(TCFG_FM_INSIDE_ENABLE == ENABLE) + +#if DAC2IIS_EN +#define FM_DAC_OUT_SAMPLERATE 44100L +#else +#define FM_DAC_OUT_SAMPLERATE 44100L +#endif + +/************************************************************ +* FM调试说明 +*真台少: 假台多: 叠台多: +*减小 FMSCAN_CNR(主) 加大 FMSCAN_CNR(主) 减小:FMSCAN_AGC +*减小 FMSCAN_P_DIFFER(主) 加大 FMSCAN_P_DIFFER(主) +*加大 FMSCAN_N_DIFFER(次) 减小 FMSCAN_N_DIFFER(次) +* +*注意:不要插串口测试搜台数 +*************************************************************/ + +#define FMSCAN_SEEK_CNT_MIN 400 //最小过零点数 400左右 +#define FMSCAN_SEEK_CNT_MAX 600 //最大过零点数 600左右 +#define FMSCAN_960_CNR 34 //谐波96M的基础cnr 30~40 +#define FMSCAN_1080_CNR 34 //谐波108M的基础cnr 30~40 +#define FMSCAN_AGC -1 //AGC阈值 -55左右,默认最大增益 +#define FMSCAN_ADD_DIFFER -67 //低于此值增加noise differ, -67左右 + +#define FMSCAN_CNR 2 //cnr 1以上 +#define FMSCAN_P_DIFFER 2 //power differ 1以上 +#define FMSCAN_N_DIFFER 8 //noise differ 8左右 + +#define FM_IF 3 //0,1.875; 1,2.143; 2,1.5; 3,cnr低的中频听台 + + + +void fm_inside_init(void *priv); +bool fm_inside_set_fre(void *priv, u16 fre); +bool fm_inside_read_id(void *priv); +void fm_inside_powerdown(void *priv); +void fm_inside_mute(void *priv, u8 flag); + +#endif +#endif // _FM_INSIDE_H_ + diff --git a/apps/common/device/fm/fm_manage.c b/apps/common/device/fm/fm_manage.c new file mode 100644 index 0000000..085bdaf --- /dev/null +++ b/apps/common/device/fm/fm_manage.c @@ -0,0 +1,317 @@ +#include "app_config.h" +#include "system/includes.h" +#include "fm/fm_manage.h" +#include "rda5807/RDA5807.h" +#include "bk1080/BK1080.h" +#include "qn8035/QN8035.h" +#include "fm_inside/fm_inside.h" +#include "asm/audio_linein.h" +#include "audio_config.h" +#include "audio_dec/audio_dec_fm.h" +#if TCFG_APP_FM_EN + + +#define LOG_TAG_CONST APP_FM +#define LOG_TAG "[APP_FM]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +static FM_INTERFACE *t_fm_hdl = NULL; +static FM_INTERFACE *fm_hdl = NULL; +static struct _fm_dev_info *fm_dev_info; +static struct _fm_dev_platform_data *fm_dev_platform_data; +int linein_dec_open(u8 source, u32 sample_rate); +void linein_dec_close(void); + +int fm_dev_init(void *_data) +{ + fm_dev_platform_data = (struct _fm_dev_platform_data *)_data; + return 0; + + fm_dev_info = (struct _fm_dev_info *)malloc(sizeof(struct _fm_dev_info)); + if (fm_dev_info == NULL) { + printf("fm_dev_init info malloc err!"); + return -1; + } + + fm_dev_platform_data = (struct _fm_dev_platform_data *)_data; + memset(fm_dev_info, 0x00, sizeof(struct _fm_dev_info)); + fm_dev_info->iic_hdl = fm_dev_platform_data->iic_hdl; + fm_dev_info->iic_delay = fm_dev_platform_data->iic_delay; + + /* iic_init(fm_dev_info->iic_hdl); + + extern void bk1080_test(void); + bk1080_test(); */ + + fm_manage_check_online(); + if (!fm_hdl) { + /* printf("fm_manage could not find dev\n"); */ + return -1; + } else { + extern void wdt_clear(); + wdt_clear(); + memcpy(fm_dev_info->logo, fm_hdl->logo, strlen(fm_hdl->logo)); + /* printf("fm_manage found dev %s\n", fm_dev_info->logo); */ + + /* fm_manage_init(); */ + /* fm_manage_set_fre(875); */ + /* fm_manage_mute(0); */ + /* u16 iii = 875; */ + /* while(!fm_manage_set_fre(iii) && (iii < 1080)) { */ + /* printf("fm fre no %d\n", iii); */ + /* iii++; */ + /* os_time_dly(1); */ + /* } */ + /* printf("fm fre %d\n", iii); */ + /* while(1) { */ + /* os_time_dly(1); */ + /* } */ + } + + return 0; +} + +u8 fm_dev_iic_write(u8 w_chip_id, u8 register_address, u8 *buf, u32 data_len) +{ + u8 ret = 1; + iic_start(fm_dev_info->iic_hdl); + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, w_chip_id)) { + ret = 0; + log_e("\n fm iic wr err 0\n"); + goto __gcend; + } + + delay(fm_dev_info->iic_delay); + + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, register_address)) { + ret = 0; + log_e("\n fm iic wr err 1\n"); + goto __gcend; + } + u8 *pbuf = buf; + + while (data_len--) { + delay(fm_dev_info->iic_delay); + + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, *pbuf++)) { + ret = 0; + log_e("\n fm iic wr err 2\n"); + goto __gcend; + } + } + +__gcend: + iic_stop(fm_dev_info->iic_hdl); + + return ret; +} + +u8 fm_dev_iic_readn(u8 r_chip_id, u8 register_address, u8 *buf, u8 data_len) +{ + u8 read_len = 0; + + iic_start(fm_dev_info->iic_hdl); + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, (r_chip_id & 0x01) ? (r_chip_id - 1) : (r_chip_id))) { + log_e("\n fm iic rd err 0\n"); + read_len = 0; + goto __gdend; + } + + + delay(fm_dev_info->iic_delay); + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, register_address)) { + log_e("\n fm iic rd err 1\n"); + read_len = 0; + goto __gdend; + } + + delay(fm_dev_info->iic_delay); + iic_start(fm_dev_info->iic_hdl); + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, r_chip_id)) { + log_e("\n fm iic rd err 2\n"); + read_len = 0; + goto __gdend; + } + + delay(fm_dev_info->iic_delay); + + for (; data_len > 1; data_len--) { + *buf++ = iic_rx_byte(fm_dev_info->iic_hdl, 1); + read_len ++; + } + + *buf = iic_rx_byte(fm_dev_info->iic_hdl, 0); + +__gdend: + + iic_stop(fm_dev_info->iic_hdl); + delay(fm_dev_info->iic_delay); + + return read_len; +} + + +void fm_manage_check_online(void) +{ + /* printf("fm check online dev \n"); */ + /* printf("addr %x %x\n", fm_dev_begin, fm_dev_end); */ + ////先找外挂fm + list_for_each_fm(t_fm_hdl) { + /* printf("find %x %x %s\n", t_fm_hdl, t_fm_hdl->read_id((void *)fm_dev_info), t_fm_hdl->logo); */ + if (t_fm_hdl->read_id((void *)fm_dev_info) && + (memcmp(t_fm_hdl->logo, "fm_inside", strlen(t_fm_hdl->logo)))) { + fm_hdl = t_fm_hdl; + printf("fm find dev %s \n", t_fm_hdl->logo); + return; + } + } + /* printf("no ex fm dev !!!\n"); */ + + list_for_each_fm(t_fm_hdl) { + /* printf("# find %x %x %s\n", t_fm_hdl, t_fm_hdl->read_id((void *)fm_dev_info), t_fm_hdl->logo); */ + if (t_fm_hdl->read_id((void *)fm_dev_info) && + (!memcmp(t_fm_hdl->logo, "fm_inside", strlen(t_fm_hdl->logo)))) { + fm_hdl = t_fm_hdl; + printf("fm find dev %s \n", t_fm_hdl->logo); + return; + } + } +} +/* early_initcall(fm_manage_check_online); */ + +int fm_manage_init() +{ + fm_dev_info = (struct _fm_dev_info *)malloc(sizeof(struct _fm_dev_info)); + if (fm_dev_info == NULL) { + printf("fm_dev_init info malloc err!"); + return -1; + } + + memset(fm_dev_info, 0x00, sizeof(struct _fm_dev_info)); + +#if TCHFG_SOFT_I2C_ENABLE + fm_dev_info->iic_hdl = fm_dev_platform_data->iic_hdl; + fm_dev_info->iic_delay = fm_dev_platform_data->iic_delay; + iic_init(fm_dev_info->iic_hdl); +#endif + + fm_manage_check_online(); + if (!fm_hdl) { + printf("fm_manage could not find dev\n"); + return -1; + } else { + memcpy(fm_dev_info->logo, fm_hdl->logo, strlen(fm_hdl->logo)); + printf("fm_manage found dev %s\n", fm_dev_info->logo); + } + + if (fm_hdl) { + fm_hdl->init((void *)fm_dev_info); + } + + return 0; +} + + + +int fm_manage_start() +{ + + if (!fm_hdl || !fm_dev_info) { + printf("fm_manage could not find dev\n"); + return -1; + } + if (memcmp(fm_dev_info->logo, "fm_inside", strlen(fm_dev_info->logo))) {//不开启内部收音开启linein +#if (TCFG_FM_INPUT_WAY != LINEIN_INPUT_WAY_ADC) + if (!app_audio_get_volume(APP_AUDIO_STATE_MUSIC)) { + audio_linein_mute(1); //模拟输出时候,dac为0也有数据 + } +#endif +#if (TCFG_FM_INPUT_WAY == LINEIN_INPUT_WAY_ADC) + linein_dec_open(TCFG_FMIN_LR_CH, 44100); +#else + if (TCFG_FMIN_LR_CH & (BIT(0) | BIT(1))) { + audio_linein0_open(TCFG_FMIN_LR_CH, 1); + } else if (TCFG_FMIN_LR_CH & (BIT(2) | BIT(3))) { + audio_linein1_open(TCFG_FMIN_LR_CH, 1); + } else if (TCFG_FMIN_LR_CH & (BIT(4) | BIT(5))) { + audio_linein2_open(TCFG_FMIN_LR_CH, 1); + } + audio_linein_gain(1); // high gain +#endif +#if (TCFG_FM_INPUT_WAY != LINEIN_INPUT_WAY_ADC) + if (app_audio_get_volume(APP_AUDIO_STATE_MUSIC)) { + audio_linein_mute(0); + app_audio_set_volume(APP_AUDIO_STATE_MUSIC, app_audio_get_volume(APP_AUDIO_STATE_MUSIC), 1);//防止无法调整 + } + //模拟输出时候,dac为0也有数据 +#endif + + } else { + fm_dec_open(0xff, 37500);//打开内置收音解码通道 + } + return 0; +} + +static u16 cur_fmrx_freq = 0; +bool fm_manage_set_fre(u16 fre) +{ + if (fm_hdl) { + cur_fmrx_freq = fre; + return fm_hdl->set_fre((void *)fm_dev_info, fre); + } + return 0; +} + +u16 fm_manage_get_fre() +{ + if (fm_hdl) { + return cur_fmrx_freq; + } + return 0; +} + + + +void fm_manage_close(void) +{ + + if (fm_hdl) { + fm_hdl->close((void *)fm_dev_info); + fm_hdl = NULL; + } + + if (fm_dev_info != NULL) { + free(fm_dev_info); + fm_dev_info = NULL; + } + + if (t_fm_hdl && memcmp(t_fm_hdl->logo, "fm_inside", strlen(t_fm_hdl->logo))) { //不使用内部收音开启linein +#if (TCFG_FM_INPUT_WAY == LINEIN_INPUT_WAY_ADC) + linein_dec_close(); +#else + if (TCFG_FMIN_LR_CH & (BIT(0) | BIT(1))) { + audio_linein0_close(TCFG_FMIN_LR_CH, 0); + } else if (TCFG_FMIN_LR_CH & (BIT(2) | BIT(3))) { + audio_linein1_close(TCFG_FMIN_LR_CH, 0); + } else if (TCFG_FMIN_LR_CH & (BIT(4) | BIT(5))) { + audio_linein2_close(TCFG_FMIN_LR_CH, 0); + } +#endif + + } +} + + +void fm_manage_mute(u8 mute) +{ + if (fm_hdl) { + fm_hdl->mute((void *)fm_dev_info, mute); + } +} + +#endif diff --git a/apps/common/device/fm/qn8035/QN8035.c b/apps/common/device/fm/qn8035/QN8035.c new file mode 100644 index 0000000..9f7acd2 --- /dev/null +++ b/apps/common/device/fm/qn8035/QN8035.c @@ -0,0 +1,712 @@ +/*--------------------------------------------------------------------------*/ +/**@file qn8035.c + @brief qn8035收音底层驱动 + @details + @author + @date 2011-11-24 + @note +*/ +/*----------------------------------------------------------------------------*/ + +#include "app_config.h" +#include "system/includes.h" +#include "fm/fm_manage.h" +#include "QN8035.h" + +#if(TCFG_FM_QN8035_ENABLE && TCHFG_SOFT_I2C_ENABLE) + + +//#include "sdmmc_api.h" + +//if antenna match circuit is used a inductor,macro USING_INDUCTOR will be set to 1 +#define USING_INDUCTOR 0 + +#define INVERSE_IMR 1 + +//if using san noise floor as CCA algorithm,macro SCAN_NOISE_FLOOR_CCA will be set to 1 +#define SCAN_NOISE_FLOOR_CCA 1 +//if using pilot as CCA algorithm,macro PILOT_CCA will be set to 1 +//#define PILOT_CCA 0 + + +//长天线配置: +//u8 _xdata qnd_PreNoiseFloor = 40,qnd_NoiseFloor = 40; +bool qn8035_online; +//短天线配置: + + + +static struct _fm_dev_info *fm_dev_info = NULL; + +extern void delay_2ms(int cnt); + +#define delay_n10ms(x) \ + delay_2ms(x*5) + + + +u16 aa; +u8 qnd_PrevMode; +u8 qnd_CH_STEP = 1; +u8 qnd_ChipID; + +/*----------------------------------------------------------------------------*/ +/**@brief QN8035 读寄存器函数 + @param addr:寄存器地址 + @return 无 + @note u8 QND_ReadReg(u8 addr) + //5_5_9_5 + //4_5_8_5 + //2_5_8_5 +*/ + +#define qn8035_rssi 4 //越大台越少 +#define qn8035_if2 0x05 //越大台越多 +#define qn8035_snr_th1 0x08 //越大台越少 // +#define qn8035_snr_th2 0x05 +#define qn8035_pilot_cca 0 +#define qn8035_inductor 1 +#define qn8075_snr 25 +u8 qnd_PreNoiseFloor = 35; //越大台越少 +u8 qnd_NoiseFloor = 35; + + +u8 QND_ReadReg(u8 addr) +{ + u8 byte; + + iic_start(fm_dev_info->iic_hdl); //I2C启动 + iic_tx_byte(fm_dev_info->iic_hdl, 0x20); //写命令 + iic_tx_byte(fm_dev_info->iic_hdl, addr); //写地址 + + iic_start(fm_dev_info->iic_hdl); //写转为读命令,需要再次启动I2C + iic_tx_byte(fm_dev_info->iic_hdl, 0x21); //读命令 + byte = iic_rx_byte(fm_dev_info->iic_hdl, 1); + + iic_stop(fm_dev_info->iic_hdl); //I2C停止 + return byte; +} + +#if 0 //IIC SD IO复用 +u8 sd_iic_readQN(u8 addr) +{ + u8 p_status; + u8 res; + + /*Wait SD I/O release*/ + if (device_active == DEVICE_SDMMCA) { + p_status = pause_decode(0); + } + sdmmca_force_idle(); + sdmmcb_force_idle(); + while (check_sd_controller()); //根据SD ID等待控制器繁忙 + IO_MC0 &= ~BIT(3); + + /*IIC Communicate*/ + res = QND_ReadReg(addr); + + /*Reset SD I/O*/ + IO_MC0 |= BIT(3); + unlock_cmd_chk(); + if ((p_status == MAD_PLAY) && (device_active == DEVICE_SDMMCA)) { + start_decode(); + } + + return res; +} +#endif + +u8 qn8035_iic_write(u8 w_chip_id, u8 register_address, u8 *buf, u32 data_len) +{ + u8 ret = 1; + + if (fm_dev_info == NULL) { + puts("fm_dev_info not init !!!!!"); + return 0; + } + + iic_start(fm_dev_info->iic_hdl); + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, w_chip_id)) { + ret = 0; + log_e("\n fm iic wr err 0\n"); + goto __gcend; + } + + delay(fm_dev_info->iic_delay); + + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, register_address)) { + ret = 0; + log_e("\n fm iic wr err 1\n"); + goto __gcend; + } + u8 *pbuf = buf; + + while (data_len--) { + delay(fm_dev_info->iic_delay); + + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, *pbuf++)) { + ret = 0; + log_e("\n fm iic wr err 2\n"); + goto __gcend; + } + } + +__gcend: + iic_stop(fm_dev_info->iic_hdl); + + return ret; +} + +u8 qn8035_iic_readn(u8 r_chip_id, u8 register_address, u8 *buf, u8 data_len) +{ + u8 read_len = 0; + + if (fm_dev_info == NULL) { + puts("fm_dev_info not init !!!!!"); + return 0; + } + + iic_start(fm_dev_info->iic_hdl); + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, (r_chip_id & 0x01) ? (r_chip_id - 1) : (r_chip_id))) { + log_e("\n fm iic rd err 0\n"); + read_len = 0; + goto __gdend; + } + + + delay(fm_dev_info->iic_delay); + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, register_address)) { + log_e("\n fm iic rd err 1\n"); + read_len = 0; + goto __gdend; + } + + /* delay(fm_dev_info->iic_delay); */ + /* iic_start(fm_dev_info->iic_hdl); */ + /* if (0 == iic_tx_byte(fm_dev_info->iic_hdl, r_chip_id)) { */ + /* log_e("\n fm iic rd err 2\n"); */ + /* read_len = 0; */ + /* goto __gdend; */ + /* } */ + + delay(fm_dev_info->iic_delay); + + for (; data_len > 1; data_len--) { + *buf++ = iic_rx_byte(fm_dev_info->iic_hdl, 1); + read_len ++; + } + + *buf = iic_rx_byte(fm_dev_info->iic_hdl, 0); + +__gdend: + + iic_stop(fm_dev_info->iic_hdl); + delay(fm_dev_info->iic_delay); + + return read_len; +} + +#define app_IIC_write qn8035_iic_write +#define app_IIC_readn qn8035_iic_readn + +/*----------------------------------------------------------------------------*/ +/**@brief QN8035 写寄存器函数 + @param addr:寄存器地址 data:写入数据 + @return 无 + @note void QND_WriteReg(u8 addr,u8 data) +*/ +/*----------------------------------------------------------------------------*/ +void QND_WriteReg(u8 addr, u8 data) +{ + app_IIC_write(0x20, addr, &data, 1); +} + + +/********************************************************************** +void QNF_SetCh(UINT16 start,UINT16 stop,UINT8 step) +********************************************************************** +Description: set channel frequency +Parameters: + freq: channel frequency to be set,frequency unit is 10KHZ +Return Value: + None +**********************************************************************/ +void QNF_SetCh(u16 start, u16 stop, u8 step) +{ + u8 temp; + + start = FREQ2CHREG(start); + stop = FREQ2CHREG(stop); + //writing lower 8 bits of CCA channel start index + QND_WriteReg(CH_START, (u8)start); + //writing lower 8 bits of CCA channel stop index + QND_WriteReg(CH_STOP, (u8)stop); + //writing lower 8 bits of channel index + QND_WriteReg(CH, (u8)start); + //writing higher bits of CCA channel start,stop and step index + temp = (u8)((start >> 8) & CH_CH); + temp |= ((u8)(start >> 6) & CH_CH_START); + temp |= ((u8)(stop >> 4) & CH_CH_STOP); + temp |= (step << 6); + QND_WriteReg(CH_STEP, temp); +} + + +/********************************************************************** +int QND_Delay() +********************************************************************** +Description: Delay for some ms, to be customized according to user + application platform + +Parameters: + ms: ms counts +Return Value: + None + +**********************************************************************/ +void QND_Delay(u16 ms) +{ +// Delay(25*ms); //rc +// delay16(1500*ms); + delay_n10ms(1); +} + +void qn8035_mute1(bool On) +{ + QND_WriteReg(0x4a, On ? 0x30 : 0x10); + //QND_WriteReg(0x4a, 0x30); +} +#define QNF_SetMute(x,y) qn8035_mute(x,y) +/********************************************************************** +void QNF_SetMute(u8 On) +********************************************************************** +Description: set register specified bit + +Parameters: +On: 1: mute, 0: unmute +Return Value: +None +**********************************************************************/ +u8 qn8035_mute(void *priv, u8 On) +{ + QND_WriteReg(REG_DAC, On ? 0x1B : 0x10); + //QND_WriteReg(0x4a, On?0x30:0x10); + return 0; +} + +#if SCAN_NOISE_FLOOR_CCA +/*********************************************************************** +Description: scan a noise floor from 87.5M to 108M by step 200K +Parameters: +Return Value: +1: scan a noise floor successfully. +0: chip would not normally work. +**********************************************************************/ +u8 QND_ScanNoiseFloor(u16 start, u16 stop) +{ + u8 regValue; + u8 timeOut = 255; //time out is 2.55S + + QND_WriteReg(CCA_SNR_TH_1, 0x00); + QND_WriteReg(CCA_SNR_TH_2, 0x05); + QND_WriteReg(0x40, 0xf0); + //config CCS frequency rang by step 200KHZ + QNF_SetCh(start, stop, 2); + /* + QND_WriteReg(CH_START,0x26); + QND_WriteReg(CH_STOP,0xc0); + QND_WriteReg(CH_STEP,0xb8); + */ + //enter CCA mode,channel index is decided by internal CCA + QND_WriteReg(SYSTEM1, 0x12); + while (1) { + regValue = QN_IIC_read(SYSTEM1); + //if it seeks a potential channel, the loop will be quited + if ((regValue & CHSC) == 0) { + break; + } + delay_n10ms(1); //delay 10ms + //if it was time out,chip would not normally work. + if ((timeOut--) == 0) { + QND_WriteReg(0x40, 0x70); + return 0; + } + } + QND_WriteReg(0x40, 0x70); + qnd_NoiseFloor = QN_IIC_read(0x3f); + if (((qnd_PreNoiseFloor - qnd_NoiseFloor) > 2) || ((qnd_NoiseFloor - qnd_PreNoiseFloor) > 2)) { + qnd_PreNoiseFloor = qnd_NoiseFloor; + } + //TRACE("NF:%d,timeOut:%d\n",qnd_NoiseFloor,255-timeOut); + return 1; +} +#endif +/********************************************************************** +void QNF_SetRegBit(u8 reg, u8 bitMask, u8 data_val) +********************************************************************** +Description: set register specified bit + +Parameters: + reg: register that will be set + bitMask: mask specified bit of register + data_val: data will be set for specified bit +Return Value: + None +***********************************************************************/ +void QND_RXSetTH(void) +{ + u8 rssi_th; + + rssi_th = qnd_PreNoiseFloor + qn8035_rssi - 28 ; //10 越小台多0- + ///increase reference PLL charge pump current. + QND_WriteReg(REG_REF, 0x7a); + //NFILT program is enabled + QND_WriteReg(0x1b, 0x78); + //using Filter3 + QND_WriteReg(CCA1, 0x75); + //setting CCA IF counter error range value(768). + QND_WriteReg(CCA_CNT2, qn8035_if2); //0x03 大台多 1-5 +//#if PILOT_CCA + if (qn8035_pilot_cca) { + QND_WriteReg(PLT1, 0x00); + } +//#endif + //selection the time of CCA FSM wait SNR calculator to settle:20ms + //0x00: 20ms(default) + //0x40: 40ms + //0x80: 60ms + //0xC0: 100m + // QNF_SetRegBit(CCA_SNR_TH_1 , 0xC0, 0x00); + //selection the time of CCA FSM wait RF front end and AGC to settle:20ms + //0x00: 10ms + //0x40: 20ms(default) + //0x80: 40ms + //0xC0: 60ms + // QNF_SetRegBit(CCA_SNR_TH_2, 0xC0, 0x40); + // QNF_SetRegBit(CCA, 30); //setting CCA RSSI threshold is 30 + QND_WriteReg(CCA_SNR_TH_2, qn8035_snr_th2); //0xc5 + QND_WriteReg(CCA, (QN_IIC_read(CCA) & 0xc0) | rssi_th); +//#if PILOT_CCA + if (qn8035_pilot_cca) { + QND_WriteReg(CCA_SNR_TH_1, qn8035_snr_th1); //setting SNR threshold for CCA + } else { + QND_WriteReg(CCA_SNR_TH_1, qn8035_snr_th1); //小台多 8-12 //setting SNR threshold for CCA 9 + } +//#endif +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief QN0835 初始化 + @param 无 + @return 无 + @note u8 qn8035_init(void *priv) +*/ +/*----------------------------------------------------------------------------*/ +u8 qn8035_init(void *priv) +{ + if (fm_dev_info == NULL) { + fm_dev_info = (struct _fm_dev_info *)priv; + } + puts("qn8035_init\n"); + QND_WriteReg(0x00, 0x81); + delay_n10ms(1); + + /*********User sets chip working clock **********/ + //Following is where change the input clock wave type,as sine-wave or square-wave. + //default set is 32.768KHZ square-wave input. + QND_WriteReg(0x01, QND_SINE_WAVE_CLOCK); + //QND_WriteReg(0x58,0x93); + //Following is where change the input clock frequency. + QND_WriteReg(XTAL_DIV0, QND_XTAL_DIV0); + QND_WriteReg(XTAL_DIV1, QND_XTAL_DIV1); + QND_WriteReg(XTAL_DIV2, QND_XTAL_DIV2); + /********User sets chip working clock end ********/ + + QND_WriteReg(0x54, 0x47);//mod PLL setting + //select SNR as filter3,SM step is 2db + QND_WriteReg(0x19, 0xc4); + QND_WriteReg(0x33, 0x9e);//set HCC and SM Hystersis 5db + QND_WriteReg(0x2d, 0xd6);//notch filter threshold adjusting + QND_WriteReg(0x43, 0x10);//notch filter threshold enable + QND_WriteReg(0x47, 0x39); + //QND_WriteReg(0x57, 0x21);//only for qn8035B test + //enter receiver mode directly + QND_WriteReg(0x00, 0x11); + //Enable the channel condition filter3 adaptation,Let ccfilter3 adjust freely + QND_WriteReg(0x1d, 0xa9); + QND_WriteReg(0x4f, 0x40);//dsiable auto tuning + QND_WriteReg(0x34, SMSTART_VAL); ///set SMSTART + QND_WriteReg(0x35, SNCSTART_VAL); ///set SNCSTART + QND_WriteReg(0x36, HCCSTART_VAL); ///set HCCSTART + QNF_SetMute((void *)fm_dev_info, 0); + + //dac_channel_on(FM_IIC_CHANNEL, FADE_ON); + + return 0; + +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭 QN0835的电源 + @param 无 + @return 无 + @note u8 QN8035_powerdown(void *priv) +*/ +/*----------------------------------------------------------------------------*/ +u8 qn8035_powerdown(void *priv) +{ + if (fm_dev_info == NULL) { + fm_dev_info = (struct _fm_dev_info *)priv; + } + puts("qn8035_powerdown\n"); +// QND_SetSysMode(0); + QNF_SetMute((void *)fm_dev_info, 1); + QND_WriteReg(SYSTEM1, 0x20); + + //dac_channel_off(FM_IIC_CHANNEL, FADE_ON); + return 0; +} +/********************************************************************** +void QND_TuneToCH(UINT16 ch) +********************************************************************** +Description: Tune to the specific channel. +Parameters: + ch:Set the frequency (10kHz) to be tuned, +eg: 101.30MHz will be set to 10130. +Return Value: + None +**********************************************************************/ +void QND_TuneToCH(u16 channel) +{ + u8 reg; + u16 ch; + ch = channel * 10; + //increase reference PLL charge pump current. + QND_WriteReg(REG_REF, 0x7a); + + /********** QNF_RXInit ****************/ + QND_WriteReg(0x1b, 0x70); //Let NFILT adjust freely + QND_WriteReg(0x2c, 0x52); + QND_WriteReg(0x45, 0x50); //Set aud_thrd will affect ccfilter3's tap number + QND_WriteReg(0x40, 0x70); //set SNR as SM,SNC,HCC MPX + QND_WriteReg(0x41, 0xca); + /********** End of QNF_RXInit ****************/ +#if INVERSE_IMR + reg = QN_IIC_read(CCA) & ~0x40; + if ((ch == 9340) || (ch == 9390) || (ch == 9530) || (ch == 9980) || (ch == 10480)) { + reg |= 0x40; // inverse IMR. + } else { + reg &= ~0x40; + } + QND_WriteReg(CCA, reg); +#endif + QNF_SetMute((void *)fm_dev_info, 1); + QNF_SetCh(ch, ch, 1); + //enable CCA mode with user write into frequency + QND_WriteReg(0x00, 0x13); +//#if USING_INDUCTOR + if (qn8035_inductor) { + //Auto tuning + QND_WriteReg(0x4f, 0x80); + reg = QN_IIC_read(0x4f); + reg >>= 1; + QND_WriteReg(0x4f, reg); + } +//#endif + ///avoid the "POP" noise. + //QND_Delay(CH_SETUP_DELAY_TIME); + //QND_Delay(500); + + delay_n10ms(10); + + ///decrease reference PLL charge pump current. + QND_WriteReg(REG_REF, 0x70); + QNF_SetMute((void *)fm_dev_info, 0); +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief 设置一个频点QN0835 + @param fre 频点 875~1080 + @return 1:当前频点有台,0:当前频点无台 + @note bool set_fre_QN8035(u16 freq) +*/ +/*----------------------------------------------------------------------------*/ +bool QND_RXValidCH(u16 freq) +{ + /* printf("set_8035_frq %d ", freq); */ + u8 regValue; + u8 timeOut; + u8 isValidChannelFlag; +// UINT8 snr,snc,temp1,temp2; +#if PILOT_CCA + u8 snr, readCnt, stereoCount = 0; +#endif + /* freq = freq * 10; */ +#if SCAN_NOISE_FLOOR_CCA + switch (freq) { + case 8750: + QND_ScanNoiseFloor(8750, 8800); + QND_RXSetTH(); + break; + case 8810: + QND_ScanNoiseFloor(8810, 9200); + QND_RXSetTH(); + break; + case 9210: + QND_ScanNoiseFloor(9210, 9600); + QND_RXSetTH(); + break; + case 9610: + QND_ScanNoiseFloor(9610, 10000); + QND_RXSetTH(); + break; + case 10010: + QND_ScanNoiseFloor(10010, 10400); + QND_RXSetTH(); + break; + case 10410: + QND_ScanNoiseFloor(10410, 10800); + QND_RXSetTH(); + break; + default: + //QND_Delay(350); + break; + } +#endif + QNF_SetCh(freq, freq, 1); +//#if USING_INDUCTOR + if (qn8035_inductor) { + //Auto tuning + QND_WriteReg(0x00, 0x11); + QND_WriteReg(0x4f, 0x80); + regValue = QN_IIC_read(0x4f); + regValue = (regValue >> 1); + QND_WriteReg(0x4f, regValue); + } + +//#endif + //entering into RX mode and CCA mode,channels index decide by CCA. + QND_WriteReg(0x00, 0x12); + timeOut = 20; // time out is 100ms + while (1) { + regValue = QN_IIC_read(SYSTEM1); + //if it seeks a potential channel, the loop will be quited + if ((regValue & CHSC) == 0) { + break; + } + delay_n10ms(1); //delay 5ms + //if it was time out,chip would not normally work. + if ((timeOut--) == 0) { + return 0; + } + } + //reading out the rxcca_fail flag of RXCCA status + isValidChannelFlag = (QN_IIC_read(STATUS1) & RXCCA_FAIL ? 0 : 1); + if (isValidChannelFlag) { +//#if PILOT_CCA + if (qn8035_pilot_cca) { + + for (readCnt = 10; readCnt > 0; readCnt--) { + delay_n10ms(2); + stereoCount += ((QN_IIC_read(STATUS1) & ST_MO_RX) ? 0 : 1); + if (stereoCount >= 3) { + return 1; + } + } + + + delay_n10ms(10); + snr = QN_IIC_read(SNR); + if (snr > qn8075_snr) { + return 1; + } + } else { + return 1; + } +//#endif + } + return 0; +} +/**/ +u8 qn8035_set_fre(void *priv, u16 fre) +{ + if (QND_RXValidCH(fre)) { + QND_TuneToCH(fre); + return TRUE; + } + return FALSE; +} + + +void QND_SetVol(u8 vol) +{ + u8 sVol; + u8 regVal; + sVol = vol * 3 + 2; + regVal = QN_IIC_read(VOL_CTL); + regVal = (regVal & 0xC0) | (sVol / 6) | ((5 - (sVol % 6)) << 3); + //regVal = (regVal&0xC0)|0x02|0x06; + QND_WriteReg(VOL_CTL, regVal); +} + +/* +void QND_SetVol(u8 vol) +{ + u8 sVol; + u8 regVal; + sVol=vol*3+2; + regVal = QN_IIC_read(VOL_CTL); + regVal = regVal&0xC0; + regVal |= (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(5)); + regVal &= ~BIT(4); + + QND_WriteReg(VOL_CTL,regVal); +} +*/ + +/*----------------------------------------------------------------------------*/ +/**@brief FM模块检测,获取QN0835 模块ID + @param 无 + @return 检测到QN0835模块返回1,否则返回0 + @note u8 QN8035_Read_ID(void *priv) +*/ +/*----------------------------------------------------------------------------*/ +u8 qn8035_read_id(void *priv) +{ + u8 cChipID; + + if (fm_dev_info == NULL) { + fm_dev_info = (struct _fm_dev_info *)priv; + } + + cChipID = QN_IIC_read(CID2); + cChipID &= 0xfc; + if (0x84 == cChipID) { + qn8035_online = 1; + return 1; + } else { + qn8035_online = 0; + return 0; + } +} + +void qn8035_setch(u8 db) +{ + QND_RXSetTH(); +} + +REGISTER_FM(qn8035) = { + .logo = "qn8035", + .init = qn8035_init, + .close = qn8035_powerdown, + .set_fre = qn8035_set_fre, + .mute = qn8035_mute, + .read_id = qn8035_read_id, +}; + +#endif diff --git a/apps/common/device/fm/qn8035/QN8035.h b/apps/common/device/fm/qn8035/QN8035.h new file mode 100644 index 0000000..93bba14 --- /dev/null +++ b/apps/common/device/fm/qn8035/QN8035.h @@ -0,0 +1,278 @@ +/************************************************Copyright(c)*********************************** +** Quintic(Nanjing) Microelectronics Co,Ltd. +** +** http://www.quinticcorp.com +** +**--------------------File Info---------------------------------------------------------------- +** File Name: qndriver.h +** subversion number: 160 +**---------------------------------------------------------------------------------------- +************************************************************************************************/ + +#ifndef _QN_0835_H +#define _QN_0835_H + +#if(TCFG_FM_QN8035_ENABLE == ENABLE) + +#define PILOT_CCA 1 // 0: disable stereo judgement for the country has many mono FM stations +#define CCA_PILOT_SNR_FILTER 35 //25 + +#define FREQ2CHREG(freq) ((freq-6000)/5) + +/**********************************QN8035's clock source selection************** +1.QN8035's default clock source is 32768HZ. +2.setting QN8035's clock source and clock source type(like sine-wave clock or digital clock). +3.user need to modify clock source according to actual hardware platform. +4.clock formula,the details please refer to the QN8035's datasheet + XTAL_DIV = Round(Clock/32768); + PLL_DLT = Round((28500000*512*XTAL_DIV)/Clock)-442368 +*******************************************************************************/ +#define QND_SINE_WAVE_CLOCK 0x00 //inject sine-wave clock +#define QND_DIGITAL_CLOCK 0x80 //inject digital clock,default is inject digital clock + +//crystal clock is 32768HZ + +#define QND_XTAL_DIV0 0x01 +#define QND_XTAL_DIV1 0x08 +#define QND_XTAL_DIV2 0x5C +/* +//crystal clock is 32768HZ +#define QND_XTAL_DIV0 0x01 +#define QND_XTAL_DIV1 0x08 +#define QND_XTAL_DIV2 0x5C + +//crystal clock is 1MHZ +#define QND_XTAL_DIV0 0x1F +#define QND_XTAL_DIV1 0x00 +#define QND_XTAL_DIV2 0x38 + +//crystal clock is 4MHZ +#define QND_XTAL_DIV0 0x7A +#define QND_XTAL_DIV1 0x00 +#define QND_XTAL_DIV2 0x54 + +//crystal clock is 6MHZ +#define QND_XTAL_DIV0 0xB7 +#define QND_XTAL_DIV1 0x00 +#define QND_XTAL_DIV2 0x54 + +//crystal clock is 7.3728MHZ +#define QND_XTAL_DIV0 0xE1 +#define QND_XTAL_DIV1 0x08 +#define QND_XTAL_DIV2 0x5C + +//crystal clock is 8MHZ +#define QND_XTAL_DIV0 0xF4 +#define QND_XTAL_DIV1 0x00 +#define QND_XTAL_DIV2 0x54 + +//crystal clock is 10MHZ +#define QND_XTAL_DIV0 0x31 +#define QND_XTAL_DIV1 0x01 +#define QND_XTAL_DIV2 0x54 + +//crystal clock is 11.0592MHZ +#define QND_XTAL_DIV0 0x52 +#define QND_XTAL_DIV1 0xA1 +#define QND_XTAL_DIV2 0x70 + +//crystal clock is 12MHZ +#define QND_XTAL_DIV0 0x6E +#define QND_XTAL_DIV1 0x01 +#define QND_XTAL_DIV2 0x54 + +//crystal clock is 16MHZ +#define QND_XTAL_DIV0 0xE8 +#define QND_XTAL_DIV1 0x01 +#define QND_XTAL_DIV2 0x54 + +//crystal clock is 20MHZ +#define QND_XTAL_DIV0 0x62 +#define QND_XTAL_DIV1 0x02 +#define QND_XTAL_DIV2 0x54 + +//crystal clock is 24MHZ +#define QND_XTAL_DIV0 0xDC +#define QND_XTAL_DIV1 0x02 +#define QND_XTAL_DIV2 0x54 + +//crystal clock is 26MHZ +#define QND_XTAL_DIV0 0x19 +#define QND_XTAL_DIV1 0x03 +#define QND_XTAL_DIV2 0x54 +*/ + + + +//following is definition step +#define QND_STEP_CONSTANT 0x40 //(QND_FSTEP_100KHZ << 6) +#define CHIPID_QN8035 0x84 + +#define R_TXRX_MASK 0x30 + +#define QND_MODE_SLEEP 0 +#define QND_MODE_WAKEUP 1 +// RX / TX value is using upper 8 bit + +#define QND_MODE_RX 0x8000 +#define QND_MODE_TX 0x4000 + +#define QND_MODE_FM 0x0000 + + + +#define QND_CONFIG_VOLUME 0x07 + + + +#define CHIPSUBID_QN8035A0 0x01 +#define CHIPSUBID_QN8035A1 0x02 + + +enum { + CCA_SENSITIVITY_LEVEL_0 = 0x1E06, + CCA_SENSITIVITY_LEVEL_1 = 0x1E07, //if using the pilot as CCA,reference this item. + CCA_SENSITIVITY_LEVEL_2 = 0x1E08, + CCA_SENSITIVITY_LEVEL_3 = 0x1E09, + CCA_SENSITIVITY_LEVEL_4 = 0x1E0A, //if not using the pilot as CCA,reference this item. + CCA_SENSITIVITY_LEVEL_5 = 0x1E0B, + CCA_SENSITIVITY_LEVEL_6 = 0x1E0C, + CCA_SENSITIVITY_LEVEL_7 = 0x1E0D, + CCA_SENSITIVITY_LEVEL_8 = 0x1E0E, + CCA_SENSITIVITY_LEVEL_9 = 0x1E0F +}; + + +/********************************************************************************************** +// Performance configuration +***********************************************************************************************/ +#define SMSTART_VAL 12//19 +#define HCCSTART_VAL 18//33 +#define SNCSTART_VAL 51//55 + + + +/********************************************************************************************** +// limitation configuration +***********************************************************************************************/ + + + + + + +//#define CCA_PILOT_SNR_FILTER 20//18 +#define CCA_PILOT_READ_DELAY 80//60 +#define CCA_PILOT_READ_COUNT 12//10 +#define CCA_PILOT_READ_COUNT_DELAY 5// 2 +#define CCA_PILOT_TH 3 + + + +#define CCA_TIME_OUT 200 + + +/********************************************************************************************** + definition register +**********************************************************************************************/ +#define SYSTEM1 0x00 +#define CCA 0x01 +#define SNR 0x02 +#define RSSISIG 0x03 +#define STATUS1 0x04 +#define CID1 0x05 +#define CID2 0x06 +#define CH 0x07 +#define CH_START 0x08 +#define CH_STOP 0x09 +#define CH_STEP 0x0A +#define RDSD0 0x0B +#define RDSD1 0x0C +#define RDSD2 0x0D +#define RDSD3 0x0E +#define RDSD4 0x0F +#define RDSD5 0x10 +#define RDSD6 0x11 +#define RDSD7 0x12 +#define STATUS2 0x13 +#define VOL_CTL 0x14 +#define XTAL_DIV0 0x15 +#define XTAL_DIV1 0x16 +#define XTAL_DIV2 0x17 +#define INT_CTRL 0x18 +#define SMP_HLD_THRD 0x19 +#define RXAGC_GAIN 0x1A +#define GAIN_SEL 0x1B +#define SYSTEM_CTL1 0x1C +#define SYSTEM_CTL2 0x1D +#define RDSCOSTAS 0x1E +#define REG_TEST 0x1F +#define STATUS4 0x20 +#define RDSAGC2 0x21 +#define CCA1 0x27 +#define CCA2 0x28 +#define CCA3 0x29 +#define CCA4 0x2A +#define CCA5 0x2B +#define PLT1 0X2F +#define PLT2 0x30 +#define SMSTART 0x34 +#define SNCSTART 0x35 +#define HCCSTART 0x36 +#define CCA_CNT1 0x37 +#define CCA_CNT2 0x38 +#define CCA_SNR_TH_1 0x39 +#define CCA_SNR_TH_2 0x3A +#define NCCFIR3 0x40 +#define REG_REF 0x49 +#define REG_DAC 0x4C +/******************************************************************************* + definition operation bit of register +*******************************************************************************/ +#define CCA_CH_DIS 0x01 +#define CHSC 0x02 +#define RDSEN 0x08 +#define CH_CH 0x03 +#define CH_CH_START 0x0c +#define CH_CH_STOP 0x30 +#define STNBY_MODE 0x20 +#define RX_MODE 0x10 +#define IMR 0x40 +#define RDS_RXUPD 0x80 +#define ST_MO_RX 0x01 +#define STNBY_RX_MASK 0x30 +#define RXCCA_MASK 0x03 +#define RX_CCA 0x02 +#define RXCCA_FAIL 0x08 +#define RX_MONO 0x04 +#define ICPREF 0x0F + + +#define QND_READ(adr) QND_ReadReg(adr) +#define QND_WRITE(adr, value) QND_WriteReg(adr, value) + + +void QNF_SetRegBit(u8 reg, u8 bitMask, u8 data_val); +u8 QND_ScanNoiseFloor(u16 start, u16 stop); +void QND_RXSetTH(void); +void QND_SetVol(u8 vol); +bool QND_RXValidCH(u16 freq); + +u8 qn8035_init(void *priv); +u8 qn8035_set_fre(void *priv, u16 freq); +u8 qn8035_mute(void *priv, u8 On); +u8 qn8035_read_id(void *priv); +u8 qn8035_powerdown(void *priv); +void qn8035_setch(u8 db); + +//extern _no_init bool _bit qn8035_online; + +#define QN_IIC_read(a) \ + QND_ReadReg(a) + + +#endif +#endif + + + diff --git a/apps/common/device/fm/rda5807/RDA5807.c b/apps/common/device/fm/rda5807/RDA5807.c new file mode 100644 index 0000000..b66a738 --- /dev/null +++ b/apps/common/device/fm/rda5807/RDA5807.c @@ -0,0 +1,592 @@ +/*--------------------------------------------------------------------------*/ +/**@file rda5807.c + @brief RDA5807收音底层驱动 + @details + @author + @date 2011-11-24 + @note +*/ +/*----------------------------------------------------------------------------*/ + +#include "app_config.h" +#include "system/includes.h" +#include "fm/fm_manage.h" +#include "RDA5807.h" + + +#if(TCFG_FM_RDA5807_ENABLE == ENABLE) + +extern void delay_2ms(int cnt); + +static struct _fm_dev_info *fm_dev_info = NULL; + +#define delay_n10ms(x) \ + delay_2ms(x*5) + +u8 rda5807_dat[12]; +u8 read_dat[10]; +u8 fm_type; + +/*--------------RDA5807SP Initial Table----------------*/ +static const u8 rda5807sp[] = { + 0xC0, 0x01, +#if defined(_FM_STEP_50K_) + 0x1b, 0x92, + 0x0C, 0x00, +#else //Step 100K + 0x00, 0x10, + 0x04, 0x00, +#endif + + RDA5807_RSSI | 0x80, 0xBF, //05H: + 0x80, 0x00, + 0x5F, 0x1A, //07H + 0x5e, 0xc6, + 0x00, 0x00, + 0x40, 0x6e, //0AH: + 0x2d, 0x80, + 0x58, 0x03, + 0x58, 0x04, + 0x58, 0x04, + 0x58, 0x04, + 0x00, 0x47, //10H: + 0x90, 0x00, + 0xF5, 0x87, + 0x7F, 0x0B, //13H: + 0x04, 0xF1, + 0x5E, 0xc0, //15H: 0x42, 0xc0 + 0x41, 0xe0, + 0x50, 0x6f, + 0x55, 0x92, + 0x00, 0x7d, + 0x10, 0xC0,//1AH + 0x07, 0x80, + 0x41, 0x1d,//1CH, + 0x40, 0x06, + 0x1f, 0x9B, + 0x4c, 0x2b,//1FH. + 0x81, 0x10, //20H: + 0x45, 0xa0,// 21H + +#if defined(_FM_STEP_50K_) + 0x55, 0x3F, //22H +#else + 0x19, 0x3F, //22H +#endif + + 0xaf, 0x40, + 0x06, 0x81, + 0x1b, 0x2a, //25H + 0x0D, 0x04, + 0x80, 0x9F, //0x80, 0x2F, + 0x17, 0x8A, + 0xD3, 0x49, + 0x11, 0x42, + 0xA0, 0xC4, //2BH + 0x3E, 0xBB, + 0x00, 0x00, + 0x58, 0x04, + 0x58, 0x04, //2FH + 0x58, 0x04, + 0x00, 0x74, + 0x3D, 0x00, + 0x03, 0x0C, + 0x2F, 0x68, + 0x38, 0x77, //35H +}; + +/*--------------RDA5807HP Initial Table----------------*/ +static const u8 rda5807hp[] = { //HP + //0x00,0x01, + //fm_dat[0] =0xC0; fm_dat[1] =0x05; + 0xc0, + 0x01, + 0x00, 0x00, + 0x04, 0x00, + 0x80 | RDA5807_RSSI, 0xBF, //0xBF, //05H + 0x40, 0x00, + 0x46, 0xC6, + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, //0AH + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x00, + 0x00, 0x06, //10H + 0x00, 0x19, // + 0x2A, 0x11, + 0x00, 0x2E, + 0x2A, 0x30, + 0xB8, 0x3C, //15H + 0x90, 0x00, + 0x2A, 0x91, + 0x84, 0x12, + 0x00, 0xA8, + 0xC4, 0x00, //1AH + 0xE0, 0x00, + 0x30, 0x1D, //0x24,0x + 0x81, 0x6A, + 0x46, 0x08, + 0x00, 0x86, //1FH + 0x06, 0x61, //20H // if 0x1661, 设置0xc05调整灵敏度 if 0x0661,设置0x23调整信噪比阀值 + 0x00, 0x00, + 0x10, 0x9E, + 0x24, 0xC9, // 0x23 //0x25,0x4A //0x23,0xC7 //值大台少 + 0x04, 0x08, //0830 + 0x0d, 0x18, //0x06, + 0xE1, 0x05, + 0x3B, 0x6C, + 0x2B, 0xEC, + 0x09, 0x0F, + 0x34, 0x14, //2AH + 0x14, 0x50, + 0x09, 0x6D, + 0x2D, 0x96, + 0x01, 0xDA, + 0x2A, 0x7B, + 0x08, 0x21, //30H + 0x13, 0xD5, + 0x48, 0x91, + 0x00, 0xbc, + 0x08, 0x96, //34H + 0x15, 0x3C, //35H + 0x0B, 0x80, //36H + 0x25, 0xC7, //37H + 0x00, 0x00, //38H +}; + + +/*--------------RDA5807MP Initial Table----------------*/ +static const u8 rda5807mp[] = { +//#if defined(_SHARE_CRYSTAL_24MHz_) +// 0xC4,0x51, //02H: +//#elif defined(_SHARE_CRYSTAL_12MHz_) +// 0xC4,0x11, //02H: +//#elif defined(_SHARE_CRYSTAL_32KHz_) +// 0xC4,0x01, //02H: +//#else + 0xC0, + 0x05, +//#endif + 0x00, + 0x10, + 0x04, + 0x00, + RDA5807_RSSI | 0xC0, + 0xBF, //05h + 0x60, + 0x00, + 0x42, + 0x1A,//11 + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, //0x0ah + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, //0x10h + 0x00, + 0x19, + 0x2a, + 0x11, + 0xB0,//0x80; 20110804 + 0x42,//0x53; + 0x2a,//0x22; 20110804 + 0x11,//加大音量0x31 wengyidong + 0xb8,//0xf8; 20110804 + 0x31,//0x30; //0x15h + 0xc0, + 0x00, + 0x2a, + 0x91, + 0x94, + 0x00, + 0x00, + 0xa8, + 0xc4, + 0x00, //0x1ah + 0xf7,//0xe0; 20110804 + 0x0f,//0x00; + 0x2a,//0x3a;20110804 + 0xdc,//0x14; //0x1ch + 0x80,//0x81;20110804 + 0x6f,//0x6a; + 0x46, + 0x08, + 0x00, + 0x86, + 0x06, + 0x61, //0x20h + 0x00, + 0x00, + 0x10, + 0x9e, + 0x23,//0x22; 20110804 + 0xc8,//0x44; + 0x04, + 0x06,//0x08; //0x24h 20110804 + 0x0e,//0x0d; + 0x1c,//0x18; //0x25h +}; + +u8 rda5807_iic_write(u8 w_chip_id, u8 register_address, u8 *buf, u32 data_len) +{ + u8 ret = 1; + + if (fm_dev_info == NULL) { + puts("fm_dev_info not init !!!!!"); + return 0; + } + + iic_start(fm_dev_info->iic_hdl); + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, w_chip_id)) { + ret = 0; + log_e("\n fm iic wr err 0\n"); + goto __gcend; + } + + delay(fm_dev_info->iic_delay); + + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, register_address)) { + ret = 0; + log_e("\n fm iic wr err 1\n"); + goto __gcend; + } + u8 *pbuf = buf; + + while (data_len--) { + delay(fm_dev_info->iic_delay); + + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, *pbuf++)) { + ret = 0; + log_e("\n fm iic wr err 2\n"); + goto __gcend; + } + } + +__gcend: + iic_stop(fm_dev_info->iic_hdl); + + return ret; +} + +u8 rda5807_iic_readn(u8 r_chip_id, u8 register_address, u8 *buf, u8 data_len) +{ + u8 read_len = 0; + + if (fm_dev_info == NULL) { + puts("fm_dev_info not init !!!!!"); + return 0; + } + + iic_start(fm_dev_info->iic_hdl); + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, (r_chip_id & 0x01) ? (r_chip_id - 1) : (r_chip_id))) { + log_e("\n fm iic rd err 0\n"); + read_len = 0; + goto __gdend; + } + + + delay(fm_dev_info->iic_delay); + if (0 == iic_tx_byte(fm_dev_info->iic_hdl, register_address)) { + log_e("\n fm iic rd err 1\n"); + read_len = 0; + goto __gdend; + } + + /* delay(fm_dev_info->iic_delay); */ + /* iic_start(fm_dev_info->iic_hdl); */ + /* if (0 == iic_tx_byte(fm_dev_info->iic_hdl, r_chip_id)) { */ + /* log_e("\n fm iic rd err 2\n"); */ + /* read_len = 0; */ + /* goto __gdend; */ + /* } */ + + delay(fm_dev_info->iic_delay); + + for (; data_len > 1; data_len--) { + *buf++ = iic_rx_byte(fm_dev_info->iic_hdl, 1); + read_len ++; + } + + *buf = iic_rx_byte(fm_dev_info->iic_hdl, 0); + +__gdend: + + iic_stop(fm_dev_info->iic_hdl); + delay(fm_dev_info->iic_delay); + + return read_len; +} + +#define app_IIC_write rda5807_iic_write +#define app_IIC_readn rda5807_iic_readn + +/*----------------------------------------------------------------------------*/ +/**@brief RDA5807写寄存器函数 + @param num 需要的数目 + @return 无 + @note void rda5807_write(u8 num) +*/ +/*----------------------------------------------------------------------------*/ +void rda5807_write(u8 num) +{ + app_IIC_write(RDA5807_WR_ADDRESS, 0xff, (u8 *)rda5807_dat, num); +} +/*----------------------------------------------------------------------------*/ +/**@brief RDA5807读寄存器函数 + @param 需要读取的数目 + @return 无 + @note void rda5807_read(u8 num) +*/ +/*----------------------------------------------------------------------------*/ +void rda5807_read(u8 num) +{ + app_IIC_readn(RDA5807_RD_ADDRESS, 0xff, read_dat, num); +} + +/*----------------------------------------------------------------------------*/ +/**@brief RDA5807HP 初始化 + @param 无 + @return 无 + @note void rda5807hp_init(void) +*/ +/*----------------------------------------------------------------------------*/ +void rda5807hp_init(void) +{ + app_IIC_write(RDA5807_WR_ADDRESS, 0xff, (u8 *)rda5807hp, 110); +} + +/*----------------------------------------------------------------------------*/ +/**@brief RDA5807写SP 初始化 + @param num 需要的数目 + @return 无 + @note void rda5807sp_init(void) +*/ +/*----------------------------------------------------------------------------*/ +void rda5807sp_init(void) +{ + app_IIC_write(RDA5807_WR_ADDRESS, 0xff, (u8 *)rda5807sp, 104); +} + +/*----------------------------------------------------------------------------*/ +/**@brief RDA5807MP 初始化 + @param 无 + @return 无 + @note void rda5807mp_init(void) +*/ +/*----------------------------------------------------------------------------*/ +void rda5807mp_init(void) +{ + app_IIC_write(RDA5807_WR_ADDRESS, 0xff, (u8 *)rda5807mp, 72); + +} + +/*----------------------------------------------------------------------------*/ +/**@brief RDA5807 初始化 + @param 无 + @return 无 + @note void init_RDA5807(void) +*/ +/*----------------------------------------------------------------------------*/ +u8 rda5807_init(void *priv) +{ + u8 i; + + rda5807_dat[0] = 0x00; + rda5807_dat[1] = 0x02; + + puts("rda5807_init\n"); + + rda5807_write(2); + + + delay_n10ms(5); + /* os_time_dly(5); */ + + puts("fm_type check\n"); + + if (fm_type == 3) { //SP + for (i = 0; i < 12; i++) { + rda5807_dat[i] = rda5807sp[i]; + } + rda5807_dat[6] = RDA5807_RSSI | 0x80; + } else if (fm_type == 4) { //HP + for (i = 0; i < 12; i++) { + rda5807_dat[i] = rda5807hp[i]; + } + } else if (fm_type == 7) { //MP + for (i = 0; i < 12; i++) { + rda5807_dat[i] = rda5807mp[i]; + } + rda5807_dat[6] = RDA5807_RSSI | 0xC0; + } + + + rda5807_write(12); + delay_n10ms(5); + /* os_time_dly(5); */ + +#if 1 + rda5807_dat[7] &= ~0x0F; + rda5807_dat[7] |= 0x0f; +#endif + + if (fm_type == 3) { //sp + rda5807sp_init();// 110 + } else if (fm_type == 4) { //hp + rda5807hp_init();// 110 + } else { //MP + rda5807mp_init(); //72 + } + + /* dac_channel_on(FM_IIC_CHANNEL, FADE_ON); */ + + + delay_n10ms(5); + /* os_time_dly(5); */ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 设置一个频点RDA5807 + @param fre 频点 875~1080 + @return 1:当前频点有台,0:当前频点无台 + @note bool set_fre_RDA5807(u16 fre) +*/ +/*----------------------------------------------------------------------------*/ +u8 rda5807_set_fre(void *priv, u16 fre) +{ + u16 pll; + u8 i; + + i = 0; + fre /= 10; + + printf("set_5807_frq %d ", fre); + + pll = (fre - 870); + rda5807_dat[2] = pll >> 2; + rda5807_dat[3] = ((pll & 0x0003) << 6) | 0x10; + + rda5807_write(4); + delay_n10ms(5); + /* os_time_dly(5); */ + + do { + rda5807_read(4); + i++; + //delay_n10ms(1); + if (rda5807_true()) { + puts(" 1 \n"); + return 1; + } + } while (i < 2); + + puts(" 0 \n"); + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭RDA5807的电源 + @param 无 + @return 无 + @note void RDA5807_PowerDown(void) +*/ +/*----------------------------------------------------------------------------*/ +u8 rda5807_powerdown(void *priv) +{ + rda5807_dat[1] &= ~(1 << 0); + rda5807_write(2); + + /* dac_channel_off(FM_IIC_CHANNEL, FADE_ON); */ + delay_n10ms(5); + /* os_time_dly(5); */ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief FM 模块静音控制 + @param dir:1-mute 0-unmute + @return 无 + @note void RDA5807_mute(dir) +*/ +/*----------------------------------------------------------------------------*/ +u8 rda5807_mute(void *priv, u8 dir) +{ + if (dir) { + rda5807_dat[0] &= 0xBF;// mute on + } else { + rda5807_dat[0] |= 0x40;// mute off + } + rda5807_write(2); + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief FM模块检测,获取RDA5807 模块ID + @param 无 + @return 检测到RDA5807模块返回1,否则返回0 + @note bool RDA5807_Read_ID(void) +*/ +/*----------------------------------------------------------------------------*/ +u8 rda5807_read_id(void *priv) +{ + + if (fm_dev_info == NULL) { + fm_dev_info = (struct _fm_dev_info *)priv; + } + + rda5807_dat[0] = 0x00; + rda5807_dat[1] = 0x02; + rda5807_write(2); + delay_n10ms(1); + /* os_time_dly(1); */ + + rda5807_read(10); + app_IIC_readn(RDA5807_RD_ADDRESS, 0xff, (u8 *)rda5807_dat, 10); + + if (read_dat[8] == 0x58 && read_dat[9] == 0x04) { //FM_RDA5807SP + fm_type = 3; + } else if (read_dat[8] == 0x58 && read_dat[9] == 0x01) { //FM_RDA5807HP + fm_type = 4; + } else if (read_dat[8] == 0x58 && read_dat[9] == 0x08) { //5807MP + fm_type = 7; + } else if (read_dat[4] == 0x58 && read_dat[5] == 0x03) { //FM_RDA5807SP; + fm_type = 3; + } else { + puts("rda5807_read_id fail\n"); + fm_type = 0; + return 0; + } + + printf("rda5807_read_id OK fm_type = %d\n", fm_type); + return 1; +} + +REGISTER_FM(rda5807) = { + .logo = "rda5807", + .init = rda5807_init, + .close = rda5807_powerdown, + .set_fre = rda5807_set_fre, + .mute = rda5807_mute, + .read_id = rda5807_read_id, +}; + +#endif + + + diff --git a/apps/common/device/fm/rda5807/RDA5807.h b/apps/common/device/fm/rda5807/RDA5807.h new file mode 100644 index 0000000..3724e88 --- /dev/null +++ b/apps/common/device/fm/rda5807/RDA5807.h @@ -0,0 +1,30 @@ +#ifndef _RDA_5807_H_ +#define _RDA_5807_H_ + + +#if(TCFG_FM_RDA5807_ENABLE == ENABLE) + + +u8 rda5807_init(void *priv); +u8 rda5807_set_fre(void *priv, u16 fre); +u8 rda5807_powerdown(void *priv); +u8 rda5807_mute(void *priv, u8 dir); +u8 rda5807_read_id(void *priv); +void rda5807_setch(u8 db); + +//extern u8 rda5807_dat[12]; +//extern u8 read_dat[10]; +//extern u8 fm_type; + +#define RDA5807_WR_ADDRESS 0x20 ///> 1)) ///<接收信号强度 + + +#endif +#endif diff --git a/apps/common/device/fm_emitter/ac3433/ac3433.c b/apps/common/device/fm_emitter/ac3433/ac3433.c new file mode 100644 index 0000000..a469644 --- /dev/null +++ b/apps/common/device/fm_emitter/ac3433/ac3433.c @@ -0,0 +1,302 @@ +#include "app_config.h" +#include "system/includes.h" +#include "fm_emitter/fm_emitter_manage.h" +#include "ac3433.h" + + +#if(TCFG_FM_EMITTER_AC3433_ENABLE == ENABLE) + + +#if IIC_SD_MULT_EN +extern bool iic_sd_mult_sd_suspend(void); +extern void iic_sd_mult_sd_resume(void); +#endif + + + +volatile u32 ac3433_iic_delay_cnt = 0; + +void ac3433_set_iic_delay(u32 delay_cnt) +{ + ac3433_iic_delay_cnt = delay_cnt; +} +void ac3433_iic_delay(void) +{ + delay(ac3433_iic_delay_cnt); +} + +void ac3433_mult_detect(void) +{ +#if ADKEY_IIC_MULT_EN + while (g_adkey_busy) { + clear_wdt(); + delay(5); + } +#endif + +#if AUX_SD_MULT_EN + while (g_ad_aux_busy) { + clear_wdt(); + delay(5); + } +#endif + +#if IIC_SD_MULT_EN + while (1) { + if (iic_sd_mult_sd_suspend()) { + JL_PORTB->PU |= (BIT(3) | BIT(4) | BIT(5)); + break; + } + clear_wdt(); + delay(5); + } + iic_data_h(); + iic_data_in(); + iic_clk_h(); + iic_clk_in(); + + iic_start(); + ac3433_iic_delay(); + ac3433_iic_delay(); + ac3433_iic_delay(); + ac3433_iic_delay(); + ac3433_iic_delay(); + iic_stop(); +#endif +} + +void ac3433_mult_release() +{ +#if IIC_SD_MULT_EN + iic_sd_mult_sd_resume(); +#endif +} + +extern void uart_tx_dac_api(void); +extern void uart_tx_dac(void); + +void ac3433_uart_isr_callback(u8 uto_buf, void *p, u8 isr_flag) +{ + printf("ac3433_uart_isr_callback\n"); + + if (isr_flag == UART_ISR_TYPE_WRITE_OVER) { + JL_UART0->CON0 &= ~BIT(2); //disable tx isr + uart_tx_dac(); + } +} + +s32 ac3433_uart_init(u32 baud) +{ + puts("--------ac3433_uart_init\n"); + + JL_IOMAP->CON3 &= ~BIT(3); + JL_IOMAP->CON1 &= ~(BIT(8) | BIT(9) | BIT(10) | BIT(11)); //output channel0 ->UT0_TX + + //任意IO口输出,所选则的IO口需要设置为输出, 且开上下拉. + AC3433_UART_DATA_PORT->DIR &= ~AC3433_UART_DATA_BIT; + AC3433_UART_DATA_PORT->DIE &= ~AC3433_UART_DATA_BIT; + AC3433_UART_DATA_PORT->OUT &= ~AC3433_UART_DATA_BIT; + AC3433_UART_DATA_PORT->PD |= AC3433_UART_DATA_BIT; + AC3433_UART_DATA_PORT->PU |= AC3433_UART_DATA_BIT; + + set_uart_isr_callback(0, ac3433_uart_isr_callback); + JL_UART0->BAUD = (UART_CLK / baud) / 3 - 1; + JL_UART0->CON0 = BIT(13) | BIT(12) | BIT(10) | BIT(6) | BIT(4) | BIT(0); + + return 0; + +} + +void ac3433_tx_dac_data(void) +{ + uart_tx_dac_api(); +} + +void ac3433_iic_init(void) +{ + iic_init(); + ac3433_set_iic_delay(5000); +} + +void ac3433_write_data(u8 chip_id, u8 iic_addr, u8 iic_dat) +{ + g_iic_busy = 1; + ac3433_mult_detect(); + iic_start(); //I2C启动 + iic_sendbyte(chip_id); //写命令 + + if (0xff != iic_addr) { + iic_sendbyte(iic_addr); //写地址 + } + + iic_sendbyte(iic_dat); //写数据 + + iic_stop(); //I2C停止时序 + + if (iic_dat == FT33_ADDR_READ) { + iic_start(); + iic_sendbyte(FT33_ADDR_READ); + iic_revbyte(0); + iic_revbyte(1); + iic_stop(); + } + ac3433_mult_release(); + g_iic_busy = 0; +} + +void ac3433_write(u8 chip_id, u8 iic_addr, u8 *iic_dat, u8 n) +{ + g_iic_busy = 1; + ac3433_mult_detect(); + iic_start(); //I2C启动 + iic_sendbyte(chip_id); //写命令 + + if (0xff != iic_addr) { + iic_sendbyte(iic_addr); //写地址 + } + for (; n > 0; n--) { + iic_sendbyte(*iic_dat++); //写数据 + } + iic_stop(); //I2C停止时序 + ac3433_mult_release(); + g_iic_busy = 0; +} + +void ac3433_read(u8 chip_id, u8 iic_addr, u8 *iic_dat) +{ + g_iic_busy = 1; + ac3433_mult_detect(); + iic_start(); //I2C启动 + iic_sendbyte(chip_id); //写命令 + if (0xff != iic_addr) { + iic_sendbyte(iic_addr); //写地址 + } + *iic_dat = iic_revbyte(1); + if (*iic_dat == FT33_ADDR_READ) { + iic_start(); + iic_sendbyte(FT33_ADDR_READ); + iic_revbyte(0); + iic_revbyte(1); + iic_stop(); + } + iic_stop(); + ac3433_mult_release(); + g_iic_busy = 0; +} + +void ac3433_readn(u8 chip_id, u8 iic_addr, u8 *iic_dat, u8 n) +{ + g_iic_busy = 1; + ac3433_mult_detect(); + iic_start(); //I2C启动 + iic_sendbyte(chip_id); //写命令 + if (0xff != iic_addr) { + iic_sendbyte(iic_addr); //写地址 + } + for (; n > 1; n--) { + *iic_dat++ = iic_revbyte(0); //读数据 + } + *iic_dat++ = iic_revbyte(1); + iic_stop(); //I2C停止时序 + ac3433_mult_release(); + g_iic_busy = 0; +} + +void ac3433_write_and(u8 chip_id, u8 iic_addr, u8 n) +{ + u8 read_data; + ac3433_read(FT33_ADDR_READ, iic_addr, &read_data); + read_data = read_data & n; + ac3433_write_data(chip_id, iic_addr, read_data); +} + +void ac3433_write_or(u8 chip_id, u8 iic_addr, u8 n) +{ + u8 read_data; + ac3433_read(FT33_ADDR_READ, iic_addr, &read_data); + read_data = read_data | n; + ac3433_write_data(chip_id, iic_addr, read_data); +} + +void ac3433_interface_register(void) +{ + ft33_init_interface_register(ac3433_iic_init); + ft33_write_data_interface_register(ac3433_write_data); + ft33_write_datan_interface_register(ac3433_write); + ft33_write_and_interface_register(ac3433_write_and); + ft33_write_or_interface_register(ac3433_write_or); + ft33_read_data_interface_register(ac3433_read); + ft33_read_datan_interface_register(ac3433_readn); + ft33_set_iic_delay_interface_register(ac3433_set_iic_delay); +} + +/*----------------------------------------------------------------------------*/ +/**@brief AC3433 初始化函数 + @param fre:初始化时设置的频点 + @return 无 + @note void ac3433_init(u16 fre) +*/ +/*----------------------------------------------------------------------------*/ + +void ac3433_init(u16 fre) +{ + +#if (FMTX_CHIP_OSC_SELECT == OSC_24M) + ft33_set_clk(24000000L); +#else + ft33_set_clk(12000000L); +#endif + ac3433_interface_register(); + ft33_set_data_mode(0); + ft33_set_channel(2); //1:MONO 2:STEREO + ft33_set_prem_cof(3); + if (ft33_init(fre) == false) { + printf("warning !!! ac3433 init err\n"); + } + ft33_set_icp(1); + ft33_set_cpib(7); + + ac3433_uart_init(AC3433_UART_RATE); + timer3_init(ac3433_tx_dac_data); +} + +/* +void ac3433_set_freq(u16 fre) +fre 是频率值 +例子:90MHZ应该传入900 +*/ +/*----------------------------------------------------------------------------*/ +/**@brief AC3433 频点设置函数 + @param fre:设置频点 + @return 无 + @note void ac3433_set_freq(u16 fre) +*/ +/*----------------------------------------------------------------------------*/ +void irq_enable(u32 idx); +void irq_disable(u32 idx); +void ac3433_set_freq(u16 fre) +{ + irq_disable(63); + ft33_set_freq(fre); + irq_enable(63); +} + +void ac3433_set_power(u8 power, u16 freq) +{ + if (power > AC3433_TX_POWER_MAX || power < AC3433_TX_POWER_MIN) { + power = AC3433_TX_POWER_MAX; + } + ft33_set_power(power); +} + +REGISTER_FM_EMITTER(ac3433) = { + .name = "ac3433", + .init = ac3433_init, + .start = NULL, + .stop = NULL, + .set_fre = ac3433_set_freq, + .set_power = ac3433_set_power, +}; + +#endif //AC3433 + diff --git a/apps/common/device/fm_emitter/ac3433/ac3433.h b/apps/common/device/fm_emitter/ac3433/ac3433.h new file mode 100644 index 0000000..69c0927 --- /dev/null +++ b/apps/common/device/fm_emitter/ac3433/ac3433.h @@ -0,0 +1,24 @@ +#ifndef _AC3433_H_ +#define _AC3433_H_ + +/******************************************************/ +#define AC3433_TX_POWER_MIN 0 +#define AC3433_TX_POWER_MAX 7 +/******************************************************/ + +/******************************************************/ +#define AC3433_UART_SEL UART0_OUTPUT_CHAL +#define AC3433_UART_RATE 2000000 + +#define AC3433_UART_DATA_PORT JL_PORTB +#define AC3433_UART_DATA_BIT BIT(2) +/******************************************************/ + +void ac3433_iic_delay(void); +void ac3433_init(u16 fre); +void ac3433_set_freq(u16 fre); +void ac3433_set_power(u8 power, u16 freq); + +#endif + + diff --git a/apps/common/device/fm_emitter/fm_emitter_manage.c b/apps/common/device/fm_emitter/fm_emitter_manage.c new file mode 100644 index 0000000..1d3bf17 --- /dev/null +++ b/apps/common/device/fm_emitter/fm_emitter_manage.c @@ -0,0 +1,158 @@ +#include "app_config.h" +#include "circular_buf.h" +#include "system/includes.h" +#include "fm_emitter/fm_emitter_manage.h" +#include "ac3433/ac3433.h" +#include "qn8007/qn8007.h" +#include "qn8027/qn8027.h" +#include "fm_inside/fm_emitter_inside.h" +#include "audio_config.h" +#include "system/includes.h" + +#if TCFG_APP_FM_EMITTER_EN + +static FM_EMITTER_INTERFACE *fm_emitter_hdl = NULL; + +/************************************************* + * + * Fmtx fre save vm + * + *************************************************/ +static int fm_emitter_manage_timer = 0; +static u8 fm_emitter_manage_cnt = 0; +static u16 cur_fmtx_freq = 0; + +static void fm_emitter_manage_save_fre(void) +{ + printf("fm_emitter_manage_save_fre %d\n", cur_fmtx_freq); + if (fm_emitter_hdl) { + u8 tbuf[2]; + tbuf[0] = (cur_fmtx_freq >> 8) & 0xFF; + tbuf[1] = cur_fmtx_freq & 0xFF; + int ret = syscfg_write(VM_FM_EMITTER_FREQ, tbuf, 2); + if (ret != 2) { + printf("fm last fre write err!\n"); + } + } else { + printf("%s %d no hdl\n", __func__, __LINE__); + } +} + +static void fm_emitter_manage_fre_save_do(void *priv) +{ + //printf("fm_emitter_manage_fre_save_do %d\n", fm_emitter_manage_cnt); + local_irq_disable(); + if (++fm_emitter_manage_cnt >= 5) { + sys_hi_timer_del(fm_emitter_manage_timer); + fm_emitter_manage_timer = 0; + fm_emitter_manage_cnt = 0; + local_irq_enable(); + fm_emitter_manage_save_fre(); + return; + } + local_irq_enable(); +} + +static void fm_emitter_manage_fre_change(void) +{ + local_irq_disable(); + fm_emitter_manage_cnt = 0; + if (fm_emitter_manage_timer == 0) { + fm_emitter_manage_timer = sys_hi_timer_add(NULL, fm_emitter_manage_fre_save_do, 1000); + } + local_irq_enable(); +} + + +void fm_emitter_manage_init(u16 fre, void (*fmtx_isr_cb)(s16 *, u32)) +{ + printf("fm_emitter_manage_init \n"); + int found = 0; + u8 tbuf[2]; + int ret = 0; + list_for_each_fm_emitter(fm_emitter_hdl) { + printf("fm_emitter_hdl %x\n", fm_emitter_hdl); + if (!memcmp(fm_emitter_hdl->name, "fm_emitter_inside", strlen(fm_emitter_hdl->name))) { + printf("fm fine dev %s \n", fm_emitter_hdl->name); + found = 1; + break; + } + } + + if (found) { + if (!fre) { + ret = syscfg_read(VM_FM_EMITTER_FREQ, tbuf, 2); + if (ret == 2) { + fre = (tbuf[0] << 8) | tbuf[1]; + if (fre < 875) { + fre = 875; + } else if (fre > 1080) { + fre = 1080; + } + printf("fm last fre: %d\n", fre); + } else { + fre = 875; + printf("fm last fre read err!\n"); + } + } + fm_emitter_hdl->init(fre); + cur_fmtx_freq = fre; + fm_emitter_hdl->data_cb(fmtx_isr_cb); + + tbuf[0] = (fre >> 8) & 0xFF; + tbuf[1] = fre & 0xFF; + /* ret = syscfg_write(VM_FM_EMITTER_FREQ, tbuf, 2); */ + if (ret != 2) { + printf("fm last fre init write err!\n"); + } + } + fm_emitter_manage_fre_change(); +} + + +void fm_emitter_manage_start(void) +{ + if (fm_emitter_hdl) { + fm_emitter_hdl->start(); + } +} + +void fm_emitter_manage_stop(void) +{ + if (fm_emitter_hdl) { + fm_emitter_hdl->stop(); + } +} + +u16 fm_emitter_manage_get_fre() +{ + return cur_fmtx_freq; +} + + + +void fm_emitter_manage_set_fre(u16 fre) +{ + if (fm_emitter_hdl) { + if (fre < 875) { + fre = 875; + } else if (fre > 1080) { + fre = 1080; + } + fm_emitter_hdl->set_fre(fre); + cur_fmtx_freq = fre; + fm_emitter_manage_fre_change(); + } else { + printf("%s %d no hdl\n", __func__, __LINE__); + } +} + + +void fm_emitter_manage_set_power(u8 power, u16 fre) +{ + if (fm_emitter_hdl) { + fm_emitter_hdl->set_power(power, fre); + } +} + +#endif diff --git a/apps/common/device/fm_emitter/fm_inside/fm_emitter_inside.c b/apps/common/device/fm_emitter/fm_inside/fm_emitter_inside.c new file mode 100644 index 0000000..d1d817b --- /dev/null +++ b/apps/common/device/fm_emitter/fm_inside/fm_emitter_inside.c @@ -0,0 +1,87 @@ +#include "app_config.h" +#include "system/includes.h" +#include "fm_emitter/fm_emitter_manage.h" +#include "fm_emitter_inside.h" + +#if(TCFG_FM_EMITTER_INSIDE_ENABLE == ENABLE) + +#define FM_EMITTER_INSIDE_USE_STEREO 0 // 1:fm 发射使用立体声 0:非立体声 + + +//***************************************************************** +//695 1:pb11 超强驱动天线 0:pb10 普通天线 +//696 1:pb3 超强驱动天线 0:pb1 普通天线,使用pb1需要需要改变唤醒IO +//***************************************************************** +#define FM_EMITTER_INSIDE_USE_CH 1 + +static void fm_emitter_inside_init(u16 fre) +{ + printf("fm emitter inside init \n"); + extern void fm_emitter_init(void); + extern void fm_emitter_set_freq(u16 fre); + extern void fmtx_stereo_onoff(u8 onoff); + extern void fm_emitter_set_ch(u8 ch); + extern void fm_emitter_set_power(u8 level); +#if FM_EMITTER_INSIDE_USE_STEREO + fmtx_stereo_onoff(1); +#endif +#if FM_EMITTER_INSIDE_USE_CH + fm_emitter_set_ch(1); + fm_emitter_init(); + fm_emitter_set_power(3);//功率等级0~3,最高发射功率为3级,在初始化之后设置,只用于强驱 +#else + fm_emitter_init(); +#endif + + if (fre) { + fm_emitter_set_freq(fre); + } + +} + +static void fm_emitter_inside_start(void) +{ + extern void fmtx_on(); + fmtx_on(); +} +static void fm_emitter_inside_stop(void) +{ + extern void fmtx_off(); + fmtx_off(); +} + +static void fm_emitter_inside_set_fre(u16 fre) +{ + extern void fm_emitter_set_freq(u16 fre); + fm_emitter_set_freq(fre); +} + +//************************************************** +//功率调节只适用于超强驱动,使用普通IO发射不调用这个函数 +//等级0-3,3为最高输出功率,默认使用等级3最高功率 +//功率设置放在初始化之后 +//该功率调节为全频点功率调节,所以参数 fre 无效,填0即可 +//************************************************** +static void fm_emitter_inside_set_power(u8 level, u16 fre) +{ + extern void fm_emitter_set_power(u8 level); + fm_emitter_set_power(level); +} + +static void fm_emitter_inside_set_data_cb(void *cb) +{ + extern void fm_emitter_set_data_cb(void *cb); + fm_emitter_set_data_cb(cb); +} + +REGISTER_FM_EMITTER(fm_emitter_inside) = { + .name = "fm_emitter_inside", + .init = fm_emitter_inside_init, + .start = fm_emitter_inside_start, + .stop = fm_emitter_inside_stop, + .set_fre = fm_emitter_inside_set_fre, + .set_power = fm_emitter_inside_set_power, + .data_cb = fm_emitter_inside_set_data_cb, +}; + +#endif diff --git a/apps/common/device/fm_emitter/fm_inside/fm_emitter_inside.h b/apps/common/device/fm_emitter/fm_inside/fm_emitter_inside.h new file mode 100644 index 0000000..3ccae65 --- /dev/null +++ b/apps/common/device/fm_emitter/fm_inside/fm_emitter_inside.h @@ -0,0 +1,20 @@ +/*--------------------------------------------------------------------------*/ +/**@file fm_inside.c + @brief 692x内部收音底层驱动 + @details + @author junqian + @date 2018-3-20 + @note +*/ +/*----------------------------------------------------------------------------*/ +#ifndef _FM_EMITTER_INSIDE_H_ +#define _FM_EMITTER_INSIDE_H_ + +#if(TCFG_FM_EMITTER_INSIDE_ENABLE == ENABLE) + + + +#endif + +#endif + diff --git a/apps/common/device/fm_emitter/qn8007/qn8007.c b/apps/common/device/fm_emitter/qn8007/qn8007.c new file mode 100644 index 0000000..0097f78 --- /dev/null +++ b/apps/common/device/fm_emitter/qn8007/qn8007.c @@ -0,0 +1,260 @@ + +#include "app_config.h" +#include "system/includes.h" +#include "fm_emitter/fm_emitter_manage.h" +#include "qn8007.h" + +#if(TCFG_FM_EMITTER_QN8007_ENABLE == ENABLE) + + +u8 qn8007_read(u8 reg_addr) +{ + u8 read_dat; + iic_readn(QN8007_ADDR_READ, reg_addr, &read_dat, 1); + return read_dat; +} + +void qn8007_write(u8 reg_addr, u8 reg_data) +{ + iic_write(QN8007_ADDR_WRITE, reg_addr, ®_data, 1); +} + +void qn8007_write_Bit(u8 reg, u8 start, u8 len, u8 data) +{ + u8 temp; + temp = qn8007_read(reg); + SFR(temp, start, len, data); + qn8007_write(reg, temp); +} + +void qn8007_init(u16 fre) +{ + u8 chipid_minor = 0, chipid_major = 0; + u8 retry = 0, temp = 0; + + /*qn8007有时会初始化失败没有发射,这里先判断写进去的与读出来的一不一致*/ + while ((temp != 0x29) && (retry < 5)) { + qn8007_write(QN8007_SYSTEM2, 0x80); //reset all reg + delay_n10ms(1); + qn8007_write(QN8007_REG_XLT3, 0x04); + qn8007_write(QN8007_ANACTL1, 0x29); //select 24M + temp = qn8007_read(QN8007_ANACTL1); + retry ++; + printf("temp = %x retry = %d\n", temp, retry); + } + + qn8007_write(QN8007_SYSTEM2, 0x48); //recalibrate + qn8007_write(QN8007_SYSTEM2, 0x08); + +#if (FMTX_CHIP_CLK_SOURCE == CLK_BY_EXTERN_OSC) + qn8007_write(QN8007_REG_XLT3, 0x04); //外挂晶振 +#else + qn8007_write(QN8007_REG_XLT3, 0x14); //外部时钟输入 +#endif + +#if (FMTX_CHIP_OSC_SELECT == OSC_12M) + qn8007_write(QN8007_ANACTL1, 0x21); //select 12M +#else + qn8007_write(QN8007_ANACTL1, 0x29); //select 24M +#endif + delay_n10ms(40); + qn8007_write(QN8007_PAC_TARGET, 0xff); //发射功率默认最大 + + chipid_minor = qn8007_read(QN8007_CID1); + chipid_major = qn8007_read(QN8007_CID2); + delay_n10ms(10); + printf("\nchipid: %x, %x\n", chipid_minor, chipid_major); + + if (((chipid_minor & 0x03) == 0) && ((chipid_major & 0x0f) == 1)) { + //B1 + puts("\nchipid->B1"); + + qn8007_write(0x3C, 0x89); //for RDS SYNC + qn8007_write(0x4a, 0xba); + qn8007_write(0x5c, 0x05); + qn8007_write(0x52, 0x0c); //mute + qn8007_write(0x57, 0x80); + qn8007_write(0x57, 0x00); + delay_n10ms(10); + qn8007_write(0x52, 0x00); + + } else if (((chipid_minor & 0x03) == 1) && ((chipid_major & 0x0f) == 0)) { + //A1 + puts("\nchipid->A1"); + + qn8007_write(0x55, 0x56); + delay_n10ms(1); + qn8007_write(0x4A, 0x3D); //0x4A + delay_n10ms(1); + qn8007_write(0x38, 0x74); //0x38 + delay_n10ms(1); + qn8007_write(0x42, 0xb5); //0x42 + delay_n10ms(1); + qn8007_write(0x40, 0x7f); //0x40 + delay_n10ms(1); + qn8007_write(0x42, 0xbd); //0x42 + qn8007_write(0x23, 0x4f); //0x23 //John remark: to avoid Qn8005/6 audio output clipping when FM deviation=75KHz & Mono mode + qn8007_write(0x4f, 0x02); //0x4f //John remark: to avoid Qn8005/6 audio output clipping when FM deviation=75KHz & Mono mode + + } else if (((chipid_minor & 0x03) == 0) && ((chipid_major & 0x0f) == 0)) { + //A0 + puts("\nchipid->A0"); + + qn8007_write(QN8007_CCA, 0x00); + delay_n10ms(1); + qn8007_write(0x23, 0x6e); + delay_n10ms(1); + qn8007_write(0x4a, 0x3d); + delay_n10ms(1); + qn8007_write(0x4c, 0x0f); + delay_n10ms(1); + qn8007_write(0x4e, 0x9a); + delay_n10ms(1); + qn8007_write(0x4f, 0x11); + delay_n10ms(1); + qn8007_write(0x50, 0xe0); + delay_n10ms(1); + qn8007_write(0x57, 0x80); + delay_n10ms(1); + qn8007_write(0x57, 0x00); + delay_n10ms(10); + } + + qn8007_write(QN8007_SYSTEM1, 0x41); //enter transmit + delay_n10ms(10); + qn8007_set_freq(fre); +} + +void qn8007_transmit_start(void) +{ +#if 0 + u8 value = qn8007_read(QN8007_SYSTEM1); + value &= ~QN8007_RXREQ; + value |= QN8007_TXREQ; + value &= ~QN8007_STNBY; + qn8007_write(QN8007_SYSTEM1, value); +#endif + qn8007_write_Bit(QN8007_SYSTEM1, 6, 1, 1); + qn8007_write_Bit(QN8007_SYSTEM1, 4, 1, 0); +} + +void qn8007_transmit_stop(void) +{ +#if 0 + u8 value = qn8007_read(QN8007_SYSTEM1); + value &= ~QN8007_RXREQ; + value &= ~QN8007_TXREQ; + value |= QN8007_STNBY; + qn8007_write(QN8007_SYSTEM1, value); +#endif + qn8007_write_Bit(QN8007_SYSTEM1, 6, 1, 0); + qn8007_write_Bit(QN8007_SYSTEM1, 4, 1, 1); +} + +void qn8007_set_freq(u16 freq) +{ + u8 tStep; + + freq = freq * 10; + freq = ((freq - 7600) / 5); + qn8007_write(QN8007_CH, (u8)freq); + tStep = qn8007_read(QN8007_CH_STEP); + tStep &= ~0x03; + tStep |= (((u8)(freq >> 8)) & 0x03); + qn8007_write(QN8007_CH_STEP, tStep); +} + +void qn8007_set_power(u8 power, u16 freq) +{ + if (power >= QN8007_TX_POWER_MAX || power < QN8007_TX_POWER_MIN) { + power = QN8007_TX_POWER_MAX; + } + qn8007_write(QN8007_PAC_TARGET, power); + qn8007_transmit_stop(); + qn8007_transmit_start(); + qn8007_set_freq(freq); +} +void qn8007_mute(u8 mute) +{ + if (mute) { + qn8007_write_Bit(QN8007_ANACTL1, 7, 1, 1); + } else { + qn8007_write_Bit(QN8007_ANACTL1, 7, 1, 0); + } +} + + +/*----------------------------------------------------------------------------*/ +/* qn8007自动扫台功能 + ch_start:扫描的起始频点 + ch_stop:扫描的停止频点 + return:扫描结束后得到的频点 +*/ +/*----------------------------------------------------------------------------*/ +u16 qn8007_channel_scan(u16 ch_start, u16 ch_stop) +{ + u8 temp = 0; + u8 fre_low = 0, fre_high = 0; + u16 fre = 0; + u16 ch_stp = 0, ch_sta = 0; + + ch_sta = (ch_start - 760) * 2; + ch_stp = (ch_stop - 760) * 2; + + qn8007_write(QN8007_CH_START, (u8)(ch_sta & 0xff)); //Lower 8 bits + qn8007_write(QN8007_CH_STOP, (u8)(ch_stp & 0xff)); //Lower 8 bits + + /* temp = qn8007_read(QN8007_CH_START); */ + /* printf("QN8007_CH_START = %x\n",temp); */ + /* temp = qn8007_read(QN8007_CH_STOP); */ + /* printf("QN8007_CH_STOP = %x\n",temp); */ + + qn8007_write_Bit(QN8007_CH_STEP, 2, 2, (u8)((ch_sta >> 8) & 0x03)); //Highest 2 bits + qn8007_write_Bit(QN8007_CH_STEP, 4, 2, (u8)((ch_stp >> 8) & 0x03)); //Highest 2 bits + + /* temp = qn8007_read(QN8007_CH_STEP); */ + /* temp &= ~(0x30); */ + /* temp |= 0x20; */ + /* qn8007_write(QN8007_CH_STEP,temp); */ + + /* temp = qn8007_read(QN8007_CH_STEP); */ + /* temp &= ~(0x0C); */ + /* temp |= 0x00; */ + /* qn8007_write(QN8007_CH_STEP,temp); */ + + /* temp = qn8007_read(QN8007_CH_STEP); */ + /* printf("QN8007_CH_STEP = %x\n",temp); */ + + qn8007_write_Bit(QN8007_SYSTEM1, 5, 1, 1); //Channel Scan mode + qn8007_write_Bit(QN8007_SYSTEM1, 0, 1, 0); //CH is determined by channel scan + + /* temp = qn8007_read(QN8007_SYSTEM1); */ + /* temp |= BIT(5); */ + /* temp &= ~BIT(0); */ + /* printf("SYSTEM1=%x\n",temp); */ + /* qn8007_write(QN8007_SYSTEM1,temp); */ + + while (qn8007_read(QN8007_SYSTEM1)&BIT(5)); //等待扫描完毕 + + fre_low = qn8007_read(QN8007_CH); + fre_high = qn8007_read(QN8007_CH_STEP); + fre_high &= 0x03; + fre = fre_low | (((u16)fre_high) << 8); + fre = (fre * 5 + 7600) / 10; + printf("auto scan finish,fre=%d\n", fre); + return fre; + +} + +REGISTER_FM_EMITTER(qn8007) = { + .name = "qn8007", + .init = qn8007_init, + .start = qn8007_transmit_start, + .stop = qn8007_transmit_stop, + .set_fre = qn8007_set_freq, + .set_power = qn8007_set_power, +}; + +#endif //QN8007 + + diff --git a/apps/common/device/fm_emitter/qn8007/qn8007.h b/apps/common/device/fm_emitter/qn8007/qn8007.h new file mode 100644 index 0000000..080c649 --- /dev/null +++ b/apps/common/device/fm_emitter/qn8007/qn8007.h @@ -0,0 +1,82 @@ +#ifndef __QN8007_H__ +#define __QN8007_H__ + +#include "typedef.h" + +/***********************************************************/ +/*power = (0.37*PAC_TARGET+68)dB,PAC_TARGET range is 31-131*/ +#define QN8007_TX_POWER_MIN 31 +#define QN8007_TX_POWER_MAX 131 +/***********************************************************/ + +/************QN8007 Address****************/ +#define QN8007_ADDR_WRITE 0x56 +#define QN8007_ADDR_READ 0x57 +/******************************************/ + + +/********QN8007 User Control Registers********/ +#define QN8007_SYSTEM1 0x00 +#define QN8007_SYSTEM2 0x01 +#define QN8007_DEV_ADD 0x02 +#define QN8007_ANACTL1 0x03 +#define QN8007_REG_VGA 0x04 +#define QN8007_CID1 0x05 +#define QN8007_CID2 0x06 +#define QN8007_I2S 0x07 +#define QN8007_CH 0x08 +#define QN8007_CH_START 0x09 +#define QN8007_CH_STOP 0x0A +#define QN8007_CH_STEP 0x0B +#define QN8007_PAC_TARGET 0x0C +#define QN8007_TXAGC_GAIN 0x0D +#define QN8007_TX_FDEV 0x0E +#define QN8007_GAIN_TXPLT 0x0F +#define QN8007_RDSD0 0X10 +#define QN8007_RDSD1 0x11 +#define QN8007_RDSD2 0x12 +#define QN8007_RDSD4 0x14 +#define QN8007_RDSD5 0x15 +#define QN8007_RDSD6 0x16 +#define QN8007_RDSD7 0x17 +#define QN8007_RDSFDEV 0x18 +#define QN8007_CCA 0x19 +#define QN8007_STATUS1 0x1A +#define QN8007_STATUS2 0x1B +#define QN8007_REG_XLT3 0x49 +#define QN8007_PAC_CAL 0x59 +#define QN8007_PAG_CAL 0x5A +/*********************************************/ +// SYSTEM1 +#define QN8007_RXREQ 0x80 +#define QN8007_TXREQ 0x40 +#define QN8007_CHSC 0x20 +#define QN8007_STNBY 0x10 +#define QN8007_RXI2S 0x08 +#define QN8007_TXI2S 0x04 +#define QN8007_RDSEN 0x02 +#define QN8007_CCA_CH_DIS 0x01 +// SYSTEM2 +#define QN8007_SWRST 0x80 +#define QN8007_RECAL 0x40 +#define QN8007_FORCE_MO 0x20 +#define QN8007_ST_MO_TX 0x10 +#define QN8007_PETC 0x08 +#define QN8007_RDSTXRDY 0x04 +#define QN8007_TMOUT1 0x02 +#define QN8007_TMOUT0 0x01 +// channel +#define QN8007_CH_AUTO 0 +#define QN8007_CH_USER 1 + +extern void qn8007_init(u16 fre); +extern void qn8007_transmit_start(void); +extern void qn8007_transmit_stop(void); +extern void qn8007_set_freq(u16 freq); +extern void qn8007_set_power(u8 power, u16 freq); +extern u16 qn8007_channel_scan(u16 ch_start, u16 ch_stop); + +#endif + + + diff --git a/apps/common/device/fm_emitter/qn8027/qn8027.c b/apps/common/device/fm_emitter/qn8027/qn8027.c new file mode 100644 index 0000000..6624e5b --- /dev/null +++ b/apps/common/device/fm_emitter/qn8027/qn8027.c @@ -0,0 +1,174 @@ + +#include "app_config.h" +#include "system/includes.h" +#include "fm_emitter/fm_emitter_manage.h" +#include "qn8027.h" + + +#if(TCFG_FM_EMITTER_QN8027_ENABLE == ENABLE) + + + + + + +/*----------------------------------------------------------------------------*/ +/**@brief QN8027 写寄存器函数 + @param addr:寄存器地址 data:写入数据 + @return 无 + @note void qn8027_write(u8 iic_addr,u8 iic_data) +*/ +/*----------------------------------------------------------------------------*/ +void qn8027_write(u8 reg_addr, u8 reg_data) +{ + iic_write(QN8027_ADDR_WRITE, reg_addr, ®_data, 1); +} + +/*----------------------------------------------------------------------------*/ +/**@brief QN8027 读寄存器函数 + @param addr:要读寄存器地址 + @return 读取到的寄存器的值 + @note u8 qn8027_read(u8 iic_addr) +*/ +/*----------------------------------------------------------------------------*/ +u8 qn8027_read(u8 reg_addr) +{ + u8 Byte_RecivData; + iic_start(); //I2C启动 + iic_sendbyte(QN8027_ADDR_WRITE); //写命令 + iic_sendbyte(reg_addr); //写地址 + iic_start(); //写转为读命令,需要再次启动I2C + iic_sendbyte(QN8027_ADDR_READ); //读命令 + Byte_RecivData = iic_revbyte(1); + iic_stop(); //I2C停止 + return Byte_RecivData; +} + + +void qn8027_write_Bit(u8 reg, u8 start, u8 len, u8 data) +{ + u8 temp; + temp = qn8027_read(reg); + SFR(temp, start, len, data); + qn8027_write(reg, temp); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief QN8027 初始化函数 + @param fre:初始化时设置的频点 + @return 无 + @note void qn8027_init(u16 fre) +*/ +/*----------------------------------------------------------------------------*/ + +void qn8027_init(u16 fre) +{ + u8 read_data; + + puts("qn8027_init\n"); + printf("qn8027_id:%x:%x\n", qn8027_read(QN8027_CID1), qn8027_read(QN8027_CID2)); + + qn8027_write(QN8027_SYSTEM, 0x81); //reset all reg + delay_n10ms(2); + +#if (FMTX_CHIP_CLK_SOURCE == CLK_BY_EXTERN_OSC) + qn8027_write(QN8027_REG_XTL, 0x3f); //外挂晶振 +#else + qn8027_write(QN8027_REG_XTL, 0xff); //外部时钟输入 +#endif + +#if (FMTX_CHIP_OSC_SELECT == OSC_24M) + qn8027_write(QN8027_REG_VGA, 0x91); //24M +#else + qn8027_write(QN8027_REG_VGA, 0x21); //12M +#endif + qn8027_write(QN8027_SYSTEM, 0x41); //reset FSM + qn8027_write(QN8027_SYSTEM, 0x01); + delay_n10ms(2); + + qn8027_write(0x18, 0xe4); //SNR improve xx1x x1xx + qn8027_write(0x1b, 0xf0); //最大发射功率 + qn8027_write(QN8027_CH1, 0x7e); //设置发射频率 + +#if PA_OFF_WHEN_NO_AUDIO + qn8027_write(QN8027_GPLT, 0xA9); //当没有音频信号输入时,一分钟后关闭发射 +#else + qn8027_write(QN8027_GPLT, 0xB9); //放弃QN8027 PA关闭功能当没有音频信号输入时 +#endif + qn8027_write(QN8027_FDEV, 64); + + qn8027_write(QN8027_SYSTEM, 0x22); //发射 + + delay_n10ms(10); + qn8027_set_freq(fre); + +} +/* +void qn8027_set_freq(u16 fre) +fre 是频率值 +例子:90MHZ应该传入900 +*/ +/*----------------------------------------------------------------------------*/ +/**@brief QN8027 频点设置函数 + @param fre:设置频点 + @return 无 + @note void qn8027_set_freq(u16 fre) +*/ +/*----------------------------------------------------------------------------*/ +void qn8027_set_freq(u16 fre) +{ + u8 ch_temp0; + u16 ch_temp1; + ch_temp1 = (fre - 760) * 2; + ch_temp0 = (ch_temp1 >> 8) & 0x3; + ch_temp0 = (0x20 | ch_temp0); + qn8027_write(QN8027_CH1, ch_temp1 & 0xff); + qn8027_write(QN8027_SYSTEM, ch_temp0); +} + +void qn8027_set_power(u8 power, u16 freq) +{ + if (power > QN8027_TX_POWER_MAX || power < QN8027_TX_POWER_MIN) { + power = QN8027_TX_POWER_MAX; + } + qn8027_write(QN8027_PAC, power | BIT(7)); + delay_n10ms(1); + qn8027_write(QN8027_SYSTEM, 0x01); //enter IDLE mode + delay_n10ms(1); + qn8027_write(QN8027_SYSTEM, 0x22); //enter TX mode + delay_n10ms(1); + qn8027_set_freq(freq); +} + +void qn8027_transmit_start(void) +{ + qn8027_write_Bit(QN8027_SYSTEM, 5, 1, 1); +} + +void qn8027_transmit_stop(void) +{ + qn8027_write_Bit(QN8027_SYSTEM, 5, 1, 0); +} + +void qn8027_mute(u8 mute) +{ + if (mute) { + qn8027_write_Bit(QN8027_SYSTEM, 3, 1, 1); + + } else { + qn8027_write_Bit(QN8027_SYSTEM, 3, 1, 0); + } +} + + +REGISTER_FM_EMITTER(qn8027) = { + .name = "qn8027", + .init = qn8027_init, + .start = qn8027_transmit_start, + .stop = qn8027_transmit_stop, + .set_fre = qn8027_set_freq, + .set_power = qn8027_set_power, +}; +#endif //QN8027 + diff --git a/apps/common/device/fm_emitter/qn8027/qn8027.h b/apps/common/device/fm_emitter/qn8027/qn8027.h new file mode 100644 index 0000000..e8d5c13 --- /dev/null +++ b/apps/common/device/fm_emitter/qn8027/qn8027.h @@ -0,0 +1,46 @@ +#ifndef _QN8027_H_ +#define _QN8027_H_ + +/******************************************************/ +/*Power = (0.62*PA_TRRGT+71)dB,PA_TRRGT range is 20-75*/ +#define QN8027_TX_POWER_MIN 20 +#define QN8027_TX_POWER_MAX 75 +/******************************************************/ + +/************QN8027 Address****************/ +#define QN8027_ADDR_WRITE 0x58 +#define QN8027_ADDR_READ 0x59 +/******************************************/ + +/********QN8027 User Control Registers********/ +#define QN8027_SYSTEM 0x00 +#define QN8027_CH1 0x01 +#define QN8027_GPLT 0x02 +#define QN8027_REG_XTL 0x03 +#define QN8027_REG_VGA 0x04 +#define QN8027_CID1 0x05 +#define QN8027_CID2 0x06 +#define QN8027_STATUS 0x07 +#define QN8027_RDSD0 0x08 +#define QN8027_RDSD1 0x09 +#define QN8027_RDSD2 0x0A +#define QN8027_RDSD3 0x0B +#define QN8027_RDSD4 0x0C +#define QN8027_RDSD5 0x0D +#define QN8027_RDSD6 0x0E +#define QN8027_RDSD7 0x0F +#define QN8027_PAC 0x10 +#define QN8027_FDEV 0x11 +#define QN8027_RDS 0x12 +/*********************************************/ + +void qn8027_init(u16 fre); +void qn8027_set_freq(u16 fre); +void qn8027_set_power(u8 power, u16 freq); +void qn8027_transmit_start(void); +void qn8027_transmit_stop(void); +void qn8027_mute(u8 mute); + +#endif + + diff --git a/apps/common/device/gSensor/EPMotion.h b/apps/common/device/gSensor/EPMotion.h new file mode 100644 index 0000000..3edce01 --- /dev/null +++ b/apps/common/device/gSensor/EPMotion.h @@ -0,0 +1,257 @@ +/*******************************************************************************/ +/** + ****************************************************************************** + * @file EPMotion.h + * @author ycwang@miramems.com + * @version V2.0 + * @date 2019-01-31 + * @brief + ****************************************************************************** + * @attention + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, MiraMEMS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + */ +/*******************************************************************************/ +#ifndef __EPMOTION_h +#define __EPMOTION_h + +/******************************************************************************* +Includes +********************************************************************************/ +#include "mira_std.h" + +/******************************************************************************* +Macro definitions - Algorithm Build Options +********************************************************************************/ +#define D_TAP_ENABLE 1 +#define M_TAP_ENABLE 1 +#define STEP_ENABLE 1 + +/******************************************************************************* +Typedef definitions +********************************************************************************/ +enum { + DEBUG_ERR = 1, + DEBUG_MSG = 1 << 1, + DEBUG_DATA = 1 << 2, + DEBUG_RAW = 1 << 3, +}; + +typedef enum { + PIN_NONE, + PIN_ONE, + PIN_TWO +} tPIN_NUM; + +typedef enum { + PIN_LEVEL_NONE, + PIN_LEVEL_LOW, + PIN_LEVEL_HIGH +} tPIN_LEVEL; + +typedef enum { + NO_LATCHED, + LATCHED_250MS, + LATCHED_500MS, + LATCHED_1S, + LATCHED_2S, + LATCHED_4S, + LATCHED_8S, + LATCHED_1MS = 10, + LATCHED_2MS, + LATCHED_25MS, + LATCHED_50MS, + LATCHED_100MS, + LATCHED +} tLATCH_MODE; + +typedef enum { + TEVENT_NONE, + TEVENT_TAP_NOTIFY, +} EPMotion_EVENT; + +typedef enum { + NONE_T, + D_TAP_T, + M_TAP_T, + STEP_T, +} tAlgorithm; + +typedef enum { + DISABLE_T, + ENABLE_T +} tSwitchCmd; + +struct tInt_Pin_Config { + tPIN_NUM num; + tPIN_LEVEL level; +}; + +struct tREG_Func { + s8_m(*read)(u8_m addr, u8_m *data_m, u8_m len); + s8_m(*write)(u8_m addr, u8_m data_m); +}; + +struct tDEBUG_Func { + s32_m(*myprintf)(const char *fmt, ...); +}; + +struct EPMotion_op_s { + struct tInt_Pin_Config pin; + s8_m(*mir3da_event_handle)(EPMotion_EVENT event, u8_m data_m); + struct tREG_Func reg; + struct tDEBUG_Func debug; +}; + +/******************************************************************************* +Global variables and functions +********************************************************************************/ + +/******************************************************************************* +* Function Name: EPMotion_Init +* Description : This function initializes the EPMotion. +* Arguments : EPMotion_op_s *ops +* Return Value : 0: OK; -1: Type Error; -2: OP Error; -3: Chip Error +********************************************************************************/ +s8_m EPMotion_Init(struct EPMotion_op_s *ops); + +/******************************************************************************* +* Function Name: EPMotion_Tap_Set_Parma +* Description : This function sets tap parmas. +* Arguments : +* threshold - set interrupt threshold 0~31 ,(threshold*125)mg +* default is 21(2625mg) +* latch_mode - set interrupt latched mode ,(tLATCH_MODE) +* default is NO_LATCHED +* duration - set interrupt duration 0~7(50~700)ms, +* default is 0(50ms) +* Return Value : None +********************************************************************************/ +void EPMotion_Tap_Set_Parma(u8_m threshold, tLATCH_MODE latch_mode, u8_m duration); + +#if D_TAP_ENABLE +/******************************************************************************* +* Function Name: EPMotion_Tap_Set_Filter +* Description : This function sets filter. +* Arguments : +* level - set level of checking data 1~3 ,default is 1 +* ths - set the value of filter ,(ths*1)mg +* Return Value : None +********************************************************************************/ +void EPMotion_D_Tap_Set_Filter(u8_m level, u16_m ths); +#endif + +#if M_TAP_ENABLE +/******************************************************************************* +* Function Name: EPMotion_M_Tap_Set_Dur +* Description : This function sets M tap duration. +* Arguments : +* m_dur_int - set interrupt duration 20~70,(m_dur_int*10)ms, +* default is 50(500ms) +* m_dur_event - set m tap event duration 20~6000,(m_dur_event*10)ms, +* default is 100(1000ms) +*EPMotion_M_Tap_Set_Dur第一个参数是设置两次敲击间隔的最大时间 第二参数是连续多次敲击总的有效时间 +* Return Value : None +********************************************************************************/ +void EPMotion_M_Tap_Set_Dur(u8_m m_dur_int, u16_m m_dur_event); +#endif + +/******************************************************************************* +* Function Name: EPMotion_Reset_Tap_INT +* Description : This function reset tap INT. +* Arguments : None +* Return Value : None +********************************************************************************/ +void EPMotion_Reset_Tap_INT(void); + +/******************************************************************************* +* Function Name: EPMotion_Resume_Tap_INT +* Description : This function resume tap INT. +* Arguments : None +* Return Value : None +********************************************************************************/ +void EPMotion_Resume_Tap_INT(void); + +#if STEP_ENABLE +/******************************************************************************* +* Function Name: EPMotion_Reset_Step +* Description : This function reset step counter. +* Arguments : None +* Return Value : None +********************************************************************************/ +void EPMotion_Reset_Step(void); + +/******************************************************************************* +* Function Name: EPMotion_Get_Step +* Description : This function gets the step. +* Arguments : None +* Return Value : step +********************************************************************************/ +u16_m EPMotion_Get_Step(void); +#endif + +/******************************************************************************* +* Function Name: EPMotion_Control +* Description : This function initializes the xMotion. +* Arguments : name - select which algorithm to control + cmd - enable/disable +* Return Value : 0->Success, -1->Init Fail£¬-2£¬No Supported +********************************************************************************/ +s8_m EPMotion_Control(tAlgorithm name, tSwitchCmd cmd); + +/******************************************************************************* +* Function Name: EPMotion_Process_Data +* Description : This function runs the EPMotion Algorithm. +* Arguments : None +* Return Value : None +********************************************************************************/ +void EPMotion_Process_Data(s8_m int_active); + +/******************************************************************************* +* Function Name: EPMotion_Chip_Read_XYZ +* Description : This function reads the chip xyz. +* Arguments : x, y, z - acc data +* Return Value : 0: OK; -1: Error +********************************************************************************/ +s8_m EPMotion_Chip_Read_XYZ(s16_m *x, s16_m *y, s16_m *z); + +/******************************************************************************* +* Function Name: EPMotion_Get_Version +* Description : This function gets EPMotion version. +* Arguments : ver - EPMotion version Num +* Return Value : None +********************************************************************************/ +void EPMotion_Get_Version(u8_m *ver); + +/******************************************************************************* +* Function Name: EPMotion_Chip_Power_On +* Description : This function enables the chip. +* Arguments : None +* Return Value : 0: OK; -1: Error +********************************************************************************/ +s8_m EPMotion_Chip_Power_On(void); + +/******************************************************************************* +* Function Name: EPMotion_Chip_Power_Off +* Description : This function disables on the chip. +* Arguments : None +* Return Value : 0: OK; -1: Error +********************************************************************************/ +s8_m EPMotion_Chip_Power_Off(void); + +/******************************************************************************* +* Function Name: EPMotion_Set_Debug_level +* Description : This function sets the debug log level +* Arguments : Log level +* Return Value : None +********************************************************************************/ +void EPMotion_Set_Debug_level(u8_m level); +#endif + + diff --git a/apps/common/device/gSensor/SC7A20.c b/apps/common/device/gSensor/SC7A20.c new file mode 100644 index 0000000..b93106f --- /dev/null +++ b/apps/common/device/gSensor/SC7A20.c @@ -0,0 +1,320 @@ +#include "gSensor/SC7A20.h" +#include "gSensor/gSensor_manage.h" +#include "app_config.h" + +#include "gSensor/SC7A20.h" +#include "math.h" + + +#if TCFG_SC7A20_EN + +u8 volatile sl_click_timer_en = 0; + + +#define SL_Sensor_Algo_Release_Enable 1 + + +u8 Click_time = 0X00; +u8 Click_add_flag = 0X00; + + +u32 SL_MEMS_i2cRead(u8 addr, u8 reg, u8 len, u8 *buf) +{ + return _gravity_sensor_get_ndata(addr, reg, buf, len); +} + +u8 SL_MEMS_i2cWrite(u8 addr, u8 reg, u8 data) +{ + gravity_sensor_command(addr, reg, data); + return 0; +} + +char SC7A20_Check() +{ + u8 reg_value = 0; + u8 i; + SL_MEMS_i2cRead(SC7A20_R_ADDR, SC7A20_WHO_AM_I, 1, ®_value); + if (reg_value == 0x11) { + return 0x01; + } else { + return 0x00; + } +} + +u8 SC7A20_Config(void) +{ + u8 Check_Flag = 0; + u8 write_num = 0, i = 0; + + u8 ODR = 0x7f; //400HZ/6f 200HZ + u8 HP = 0x0c; //开启高通滤波 + u8 click_int = 0x80; //将Click中断映射到INT1 + u8 range = 0x90; //4g量程 + u8 fifo_en = 0x40; //使能fifo + u8 fifo_mode = 0x80; //Stream模式 + u8 click_mode = 0x15; //单击3轴触发 + + Check_Flag = SC7A20_Check(); + if (Check_Flag == 1) { + SL_MEMS_i2cWrite(SC7A20_W_ADDR, SC7A20_CTRL_REG1, ODR); + SL_MEMS_i2cWrite(SC7A20_W_ADDR, SC7A20_CTRL_REG2, HP); + SL_MEMS_i2cWrite(SC7A20_W_ADDR, SC7A20_CTRL_REG3, click_int);// click int1 + SL_MEMS_i2cWrite(SC7A20_W_ADDR, SC7A20_CTRL_REG4, range); + SL_MEMS_i2cWrite(SC7A20_W_ADDR, SC7A20_CTRL_REG5, fifo_en); + SL_MEMS_i2cWrite(SC7A20_W_ADDR, SC7A20_FIFO_CTRL_REG, fifo_mode); + SL_MEMS_i2cWrite(SC7A20_W_ADDR, SC7A20_CLICK_CFG, click_mode);//单Z轴 + SL_MEMS_i2cWrite(SC7A20_W_ADDR, SC7A20_CLICK_THS, SC7A20_CLICK_TH);//62.6mg(4g)*10 + SL_MEMS_i2cWrite(SC7A20_W_ADDR, SC7A20_TIME_LIMIT, SC7A20_CLICK_WINDOWS); + SL_MEMS_i2cWrite(SC7A20_W_ADDR, SC7A20_TIME_LATENCY, SC7A20_CLICK_LATENCY); + SL_MEMS_i2cWrite(SC7A20_W_ADDR, SC7A20_CTRL_REG6, SC7A20_INT_LEVEL); + return 0; + } else { + return -1; + } +} + + +#if SL_Sensor_Algo_Release_Enable==0 +extern signed short SL_DEBUG_DATA[10][128]; +extern u8 SL_DEBUG_DATA_LEN; +#endif + +u8 sl_pp_num = 0; + +u8 SL_Get_CLICK_PP_CNT(u8 fun_flag) +{ + if (fun_flag == 0) { + sl_pp_num = 0; + } + return sl_pp_num; +} + +unsigned int SL_Click_Sqrt(unsigned int sqrt_data) +{ + unsigned int SL_SQRT_LOW, SL_SQRT_UP, SL_SQRT_MID; + u8 sl_sqrt_num = 0; + + SL_SQRT_LOW = 0; + SL_SQRT_UP = sqrt_data; + SL_SQRT_MID = (SL_SQRT_UP + SL_SQRT_LOW) / 2; + while (sl_sqrt_num < 200) { + if (SL_SQRT_MID * SL_SQRT_MID > sqrt_data) { + SL_SQRT_UP = SL_SQRT_MID; + } else { + SL_SQRT_LOW = SL_SQRT_MID; + } + if (SL_SQRT_UP - SL_SQRT_LOW == 1) { + if (SL_SQRT_UP * SL_SQRT_UP - sqrt_data > sqrt_data - SL_SQRT_LOW * SL_SQRT_LOW) { + return SL_SQRT_LOW; + } else { + return SL_SQRT_UP; + } + } + SL_SQRT_MID = (SL_SQRT_UP + SL_SQRT_LOW) / 2; + sl_sqrt_num++; + } + return 0; +} + +char SC7A20_Click_Read(int TH1, int TH2) +{ + u8 i = 0, j = 0, k = 0; + u8 click_num = 0; + u8 fifo_len; + unsigned int sc7a20_data = 0; + unsigned int fifo_data_xyz[32]; + u8 click_result = 0x00; + unsigned int click_sum = 0; + u8 data1[6]; + signed char data[6]; + + g_printf("INT_HAPPEN!\r\n"); + + SL_MEMS_i2cRead(SC7A20_R_ADDR, SC7A20_SRC_REG, 1, &fifo_len); + if ((fifo_len & 0x40) == 0x40) { + fifo_len = 32; + } else { + fifo_len = fifo_len & 0x1f; + } + + for (i = 0; i < fifo_len; i++) { + SL_MEMS_i2cRead(SC7A20_R_ADDR, 0xA8, 6, &data1[0]); + data[1] = (signed char)data1[1]; + data[3] = (signed char)data1[3]; + data[5] = (signed char)data1[5]; + sc7a20_data = (data[1]) * (data[1]) + (data[3]) * (data[3]) + (data[5]) * (data[5]); + sc7a20_data = SL_Click_Sqrt(sc7a20_data); + fifo_data_xyz[i] = sc7a20_data; + +#if SL_Sensor_Algo_Release_Enable==0 + SL_DEBUG_DATA[0][i] = data[1]; + SL_DEBUG_DATA[1][i] = data[3]; + SL_DEBUG_DATA[2][i] = data[5]; + SL_DEBUG_DATA[3][i] = fifo_data_xyz[i]; + SL_DEBUG_DATA_LEN = fifo_len; +#endif + } + + k = 0; + for (i = 1; i < fifo_len - 1; i++) { + if ((fifo_data_xyz[i + 1] > TH1) && (fifo_data_xyz[i - 1] < 30)) { + g_printf("in_th\r\n"); + if (click_num == 0) { + click_sum = 0; //first peak + for (j = 0; j < i - 1; j++) { + if (fifo_data_xyz[j] > fifo_data_xyz[j + 1]) { + click_sum += fifo_data_xyz[j] - fifo_data_xyz[j + 1]; + } else { + click_sum += fifo_data_xyz[j + 1] - fifo_data_xyz[j]; + } + } +#if SL_Sensor_Algo_Release_Enable==0 + g_printf("click_sum:%d!\r\n", click_sum); +#endif + if (click_sum > TH2) { + sl_pp_num++; + break; + } + k = i; + } else { + k = i; //sencond peak + } + } + + if (k != 0) { + if (fifo_data_xyz[i - 1] - fifo_data_xyz[i + 1] > TH1 - 10) { + if (i - k < 5) { + click_num = 1; + break; + } + } + } + } + if (click_num == 1) { + click_result = 1; + } else { + click_result = 0; + } + + return click_result; +} + +//GPIO?????,??INT2 +//Service function in Int Function +//u8 sl_click_timer_en =0; +u8 sl_click_status = 0; +unsigned short click_timer_cnt = 0; +unsigned short click_timer_total_cnt = 0; +u8 click_click_final_cnt = 0; + +char SC7A20_Click_Alog(void) +{ + u8 click_status = 0; + + SL_MEMS_i2cWrite(SC7A20_W_ADDR, SC7A20_CTRL_REG3, 0x00); + click_status = SC7A20_Click_Read(SC7A20_TH1, SC7A20_TH2); //40,50 + + g_printf("click_status = 0x%x\n", click_status); + if (click_status == 1) { + if (sl_click_timer_en == 0) { + //set click timer flag + sl_click_timer_en = 1; + //clear click timer cnt value + click_timer_cnt = 0; + click_timer_total_cnt = 0; + click_click_final_cnt = 0; + } + sl_click_status = 1; + } + SL_MEMS_i2cWrite(SC7A20_W_ADDR, SC7A20_CTRL_REG3, 0x80); + return click_status; +} + +//This fuction is execute in 50ms timer when the timer is opened +char SC7A20_click_status(void) +{ + u8 click_e_cnt = 0; + if (sl_click_timer_en == 1) { + click_timer_cnt++; + if ((click_timer_cnt < click_pp_num) && (sl_click_status == 1)) { + g_printf("status:%d\r\n", sl_click_status); + g_printf("fin_num:%d\r\n", click_click_final_cnt); + sl_click_status = 0; + click_timer_total_cnt = click_timer_total_cnt + click_timer_cnt; + click_timer_cnt = 0; + click_click_final_cnt++; + } + + click_e_cnt = SL_Get_CLICK_PP_CNT(1); + + if ((((click_timer_cnt >= click_pp_num) || (click_timer_total_cnt >= click_max_num)) && (click_e_cnt < 1)) || + ((click_timer_cnt >= click_pp_num) && (click_e_cnt > 0))) +// if((click_timer_cnt>=click_pp_num)||(click_timer_total_cnt>=click_max_num)) + { + //clear click timer flag + sl_click_timer_en = 0; + //clear click timer cnt value + click_timer_cnt = 0; + click_timer_total_cnt = 0; + g_printf("fin_num:%d\r\n", click_click_final_cnt); + if (click_e_cnt > 0) { + click_e_cnt = SL_Get_CLICK_PP_CNT(0); + return 0; + } else { + return click_click_final_cnt; + } + } + } + return 0; +} + +void SC7A20_int_io_detect(u8 int_io_status) +{ + static u8 int_io_status_old; + /* u8 int_io_status = 0; */ + /* int_io_status = gpio_read(INT_IO); */ + if ((int_io_status) && (int_io_status_old == 0)) { + log_e("sc7a20_int_io_detect\n"); + SC7A20_Click_Alog(); + } else { + } + int_io_status_old = int_io_status; +} + +void SC7A20_ctl(u8 cmd, void *arg) +{ + switch (cmd) { + case GSENSOR_RESET_INT: + break; + case GSENSOR_RESUME_INT: + break; + case GSENSOR_INT_DET: + SC7A20_int_io_detect(*(u8 *)arg); + break; + default: + + break; + } +} + + +static u8 sc7a20_idle_query(void) +{ + return !sl_click_timer_en; +} + +REGISTER_GRAVITY_SENSOR(gSensor) = { + .logo = "sc7a20", + .gravity_sensor_init = SC7A20_Config, + .gravity_sensor_check = SC7A20_click_status, + .gravity_sensor_ctl = SC7A20_ctl, +}; + +REGISTER_LP_TARGET(sc7a20_lp_target) = { + .name = "sc7a20", + .is_idle = sc7a20_idle_query, +}; + + +#endif + diff --git a/apps/common/device/gSensor/SC7A20.h b/apps/common/device/gSensor/SC7A20.h new file mode 100644 index 0000000..55a8e65 --- /dev/null +++ b/apps/common/device/gSensor/SC7A20.h @@ -0,0 +1,116 @@ +/* +Copyright (c) 2019 Silan MEMS. All Rights Reserved. +*/ +#ifndef SC7A20_H +#define SC7A20_H + +/********添加IIC头文件******************/ +//#include "i2c.h" +/***************************************/ + + +/***使用驱动前请根据实际接线情况配置(7bit)IIC地址******/ +/**SC7A20的SDO 脚接地: 0x18****************/ +/**SC7A20的SDO 脚接电源: 0x19****************/ +#define SC7A20_W_ADDR (0x19U << 1 | 0x0) +#define SC7A20_R_ADDR (0x19U << 1 | 0x1) +/*******************************************************/ + +#define SC7A20_CLICK_TH 0x38 //Click触发阈值,如果单次敲击无法触发中断,请将下面这个参数适当调小,如果单次敲击太过灵敏,请将下面这个参数适当调大 +#define SC7A20_CLICK_WINDOWS 0x05 //Click有效窗口 +#define SC7A20_CLICK_LATENCY 0x10 //Click中断持续时间,odr = 0x10时, 时间 = 16 * 2.5ms +#define SC7A20_INT_LEVEL 0x02 //0x02为中断时低电平,0x0为高电平 +//如果中断能够触发,但是无法识别为单击,请调小如下函数中的参数 TH1 +//如果单击能够触发,摇晃都会触发多击,请调小如下函数中的参数 TH2 +//如果单击能够触发,多击功能比较难实现,请调大如下函数中的参数 TH2 +#define SC7A20_TH1 40 +#define SC7A20_TH2 50 + +#define click_pp_num (unsigned short)10*25 //10对应0.5s(不需要管后面的*25) +#define click_max_num (unsigned short)60*25 // 60对应3s + + + +/*************驱动初始化函数**************/ +unsigned char SC7A20_Config(void); +/**SC7A20_Config 函数中, ODR 默认0x7f 400HZ/6f 200HZ ************/ +/**SC7A20_Config 函数中, HP 默认0xOC 开启高通滤波 ************/ +/**SC7A20_Config 函数中, click_int 默认0x80 将Click中断映射到INT1************/ +/**SC7A20_Config 函数中, range 默认0x90 4g量程************/ +/**SC7A20_Config 函数中, fifo_en 默认0x40 使能fifo************/ +/**SC7A20_Config 函数中, fifo_mode 默认0x80 Stream模式************/ +/**SC7A20_Config 函数中, click_mode 默认0x15 单击3轴触发************/ +/**SC7A20_Config 函数中, click_th 默认0x38 Click触发阈值************/ +/**SC7A20_Config 函数中, click_window 默认0x05 Click有效窗口************/ +/**SC7A20_Config 函数中, click_latency 默认0x10 Click中断持续时间************/ + +/*************返回数据情况如下*****************/ +/**return : 1 IIC通讯正常IC在线***************/ +/**return : 0; IIC通讯异常或IC不在线***************/ + +/*************单击状态检测**************/ +char SC7A20_Click_Read(int TH1, int TH2); +/*************TH1 调节单击灵敏度,默认9000*****************/ +/*************TH2 默认6000*****************/ +/*************TH3 默认7000*****************/ +/*************返回数据情况如下*****************/ +/**return : 1 单次敲击有效***************/ +/**return : 0; 单次敲击无效***************/ + + +/*************外部中断调用Click敲击函数**************/ +char SC7A20_Click_Alog(void); +/*************返回数据情况如下*****************/ +/**return : 1 单次敲击有效***************/ +/**return : 0; 单次敲击无效***************/ + + +/*************定时器中断调用Click状态函数**************/ +char SC7A20_click_status(void); +/*************返回数据情况如下*****************/ +/**return : N N次敲击有效***************/ + + +/**reg map***************/ +#define SC7A20_OUT_TEMP_L 0x0C +#define SC7A20_OUT_TEMP_H 0x0D +#define SC7A20_WHO_AM_I 0x0F +#define SC7A20_USER_CAL_START 0x13 +#define SC7A20_USER_CAL_END 0x1A +#define SC7A20_NVM_WR 0x1E +#define SC7A20_TEMP_CFG 0x1F +#define SC7A20_CTRL_REG1 0x20 +#define SC7A20_CTRL_REG2 0x21 +#define SC7A20_CTRL_REG3 0x22 +#define SC7A20_CTRL_REG4 0x23 +#define SC7A20_CTRL_REG5 0x24 +#define SC7A20_CTRL_REG6 0x25 +#define SC7A20_REFERENCE 0x26 +#define SC7A20_STATUS_REG 0x27 +#define SC7A20_OUT_X_L 0x28 +#define SC7A20_OUT_X_H 0x29 +#define SC7A20_OUT_Y_L 0x2A +#define SC7A20_OUT_Y_H 0x2B +#define SC7A20_OUT_Z_L 0x2C +#define SC7A20_OUT_Z_H 0x2D +#define SC7A20_FIFO_CTRL_REG 0x2E +#define SC7A20_SRC_REG 0x2F +#define SC7A20_INT1_CFG 0x30 +#define SC7A20_INT1_SOURCE 0x31 +#define SC7A20_INT1_THS 0x32 +#define SC7A20_INT1_DURATION 0x33 +#define SC7A20_INT2_CFG 0x34 +#define SC7A20_INT2_SOURCE 0x35 +#define SC7A20_INT2_THS 0x36 +#define SC7A20_INT2_DURATION 0x37 +#define SC7A20_CLICK_CFG 0x38 +#define SC7A20_CLICK_SRC 0x39 +#define SC7A20_CLICK_THS 0x3A +#define SC7A20_TIME_LIMIT 0x3B +#define SC7A20_TIME_LATENCY 0x3C +#define SC7A20_TIME_WINDOW 0x3D +#define SC7A20_ACT_THS 0x3E +#define SC7A20_ACT_DURATION 0x3F + +#endif // SC7A20_H + diff --git a/apps/common/device/gSensor/da230.c b/apps/common/device/gSensor/da230.c new file mode 100644 index 0000000..c3eeee3 --- /dev/null +++ b/apps/common/device/gSensor/da230.c @@ -0,0 +1,393 @@ +#include "gSensor/EPMotion.h" +#include "gSensor/da230.h" +#include "gSensor/gSensor_manage.h" +#include "app_config.h" + +#if TCFG_DA230_EN + +#define LOG_TAG "[DA230]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +static u8 da230_init_ok = 0; +static u8 tap_data = 0; +static u8 tap_start = 0; +static u8 event_ocur = 0; +static u8 da230_is_idle = 1; + +void da230_set_idle_flag(u8 flag) +{ + da230_is_idle = flag; +} + +u32 da230_register_read(u8 addr, u8 *data) +{ + _gravity_sensor_get_ndata(I2C_ADDR_DA230_R, addr, data, 1); + return 0; +} + +s8_m da230_register_write(u8_m addr, u8_m data) +{ + gravity_sensor_command(I2C_ADDR_DA230_W, addr, data); + return 0; +} + +s8_m da230_read_nbyte_data(u8_m addr, u8_m *data, u8_m len) +{ + _gravity_sensor_get_ndata(I2C_ADDR_DA230_R, addr, data, len); + return 0; +} + +s8_m da230_register_mask_write(unsigned char addr, unsigned char mask, unsigned char data) +{ + int res = 0; + unsigned char tmp_data; + + /* iic_readn(I2C_ADDR_DA230_R, addr, &tmp_data, 1); */ + da230_read_nbyte_data(addr, &tmp_data, 1); + + tmp_data &= ~mask; + tmp_data |= data & mask; + /* iic_write(I2C_ADDR_DA230_W, addr, &tmp_data, 1); */ + da230_register_write(addr, tmp_data); + + return 1; +} + +s8_m handleEvent(EPMotion_EVENT event, u8 data) +{ + event_ocur = 0; + tap_start = 0; + da230_set_idle_flag(1); + log_info("da230_set_idle_flag:1"); + switch (event) { + case TEVENT_TAP_NOTIFY: { + tap_data = data; + printf("*******DATA:%d \n", data); + } + break; + default: + break; + } + + return 0; +} + +u32 da230_register_write_bit(u8 addr, u8 start, u8 len, u8 data) +{ + u32 res = 0; + u8 tmp_data; + + res = da230_register_read(addr, &tmp_data); + if (res) { + return res; + } + + SFR(tmp_data, start, len, data); + + res = da230_register_write(addr, tmp_data); + + return res; +} + +u32 da230_close_i2c_pullup(void) +{ + u32 res = 0; + + res |= da230_register_write(0x7f, 0x83); + res |= da230_register_write(0x7f, 0x69); + res |= da230_register_write(0x7f, 0xBD); + + /**********将0x8f bit1写0,去掉da230内部i2c弱上拉*********/ + res |= da230_register_write_bit(0x8f, 1, 1, 0); + + return res; +} +#if 0 +u32 da230_read_block_data(u8 base_addr, u8 count, u8 *data) +{ + u32 i = 0; + + for (i = 0; i < count; i++) { + if (da230_register_read(base_addr + i, (data + i))) { + return -1; + } + } + + return count; +} + + +u32 da230_register_read_continuously(u8 addr, u8 count, u8 *data) +{ + u32 res = 0; + + res = (count == da230_read_block_data(addr, count, data)) ? 0 : 1; + + return res; +} + +u32 da230_open_step_counter(void) +{ + u32 res = 0; + + res |= da230_register_write(NSA_REG_STEP_CONGIF1, 0x01); + res |= da230_register_write(NSA_REG_STEP_CONGIF2, 0x62); + res |= da230_register_write(NSA_REG_STEP_CONGIF3, 0x46); + res |= da230_register_write(NSA_REG_STEP_CONGIF4, 0x32); + res |= da230_register_write(NSA_REG_STEP_FILTER, 0xa2); + + return res; +} + +u16 da230_get_step(void) +{ + u8 tmp_data[4] = {0}; + u16 f_step = 0; + + if (da230_register_read_continuously(NSA_REG_STEPS_MSB, 4, tmp_data) == 0) { + if (0x40 == tmp_data[2] && 0x07 == tmp_data[3]) { + f_step = ((tmp_data[0] << 8 | tmp_data[1])) / 2; + } + } + + + return (f_step); +} + +u32 da230_close_step_counter(void) +{ + u32 res = 0; + + res = da230_register_write(NSA_REG_STEP_FILTER, 0x22); + + return res; +} + + +u32 da230_register_write_bit(u8 addr, u8 start, u8 len, u8 data) +{ + u32 res = 0; + u8 tmp_data; + + res = da230_register_read(addr, &tmp_data); + if (res) { + return res; + } + + SFR(tmp_data, start, len, data); + + res = da230_register_write(addr, tmp_data); + + return res; +} + +u32 da230_open_i2c_pullup(void) +{ + u32 res = 0; + + res |= da230_register_write(0x7f, 0x83); + res |= da230_register_write(0x7f, 0x69); + res |= da230_register_write(0x7f, 0xBD); + + /**********将0x8f bit1写1,开启da230内部i2c弱上拉*********/ + res |= da230_register_write_bit(0x8f, 1, 1, 1); + + return res; +} +#endif + +struct EPMotion_op_s ops_handle = { + {PIN_ONE, PIN_LEVEL_LOW}, + handleEvent, + {da230_read_nbyte_data, da230_register_write}, + printf +}; +u8 da230_init(void) +{ + u8 data = 0; + + JL_PORTB->DIR &= ~BIT(2); + JL_PORTB->DIE |= BIT(2); + JL_PORTB->OUT |= BIT(2); + da230_register_read(NSA_REG_WHO_AM_I, &data); + + if (data != 0x13) { + log_e("da230 init err1!!!!!!!\n"); + return -1; + } + + if (EPMotion_Init(&ops_handle)) { + log_e("da230 init err2!!!!!!!\n"); + return -1; + } + + EPMotion_Set_Debug_level(DEBUG_ERR); + EPMotion_Tap_Set_Parma(0x0d, LATCHED_100MS, 0x00); //0x05~0x1f + //EPMotion_D_Tap_Set_Filter(1, 130); + EPMotion_M_Tap_Set_Dur(70, 500); +// EPMotion_M_Tap_Set_Dur(60,150); + da230_register_mask_write(0x10, 0xe0, 0xc0); + EPMotion_Control(M_TAP_T, ENABLE_T); +// EPMotion_Tap_Set_Parma(0x08,LATCHED_25MS,0x00); //0x05~0x1f + + + //close i2c pullup + da230_close_i2c_pullup(); + da230_register_mask_write(0x8f, 0x02, 0x00); + + da230_init_ok = 1; + + log_info("da230 init success!!!\n"); + + return 0; +} + +u32 da230_set_enable(u8 enable) +{ + u32 res = 0; + + if (da230_init_ok) { + + if (enable) { + EPMotion_Chip_Power_On(); + } else { + EPMotion_Chip_Power_Off(); + } + } + + return res; +} + + +void da230_read_XYZ(short *x, short *y, short *z) +{ + if (da230_init_ok) { + EPMotion_Chip_Read_XYZ(x, y, z); + } +} + +#if 0 +u16 da230_open_interrupt(u16 num) +{ + u16 res = 0; + res = da230_register_write(NSA_REG_INTERRUPT_SETTINGS1, 0x87); + res = da230_register_write(NSA_REG_ACTIVE_THRESHOLD, 0x05); + switch (num) { + case 0: + res = da230_register_write(NSA_REG_INTERRUPT_MAPPING1, 0x04); + break; + case 1: + res = da230_register_write(NSA_REG_INTERRUPT_MAPPING3, 0x04); + break; + } + return res; +} +#endif + +void da230_check_tap_int(void) +{ + static int count = 0; + if (tap_start) { + if (event_ocur == 1) { + count = 0; + } + if ((count % 5) == 0) { + //printf("====process event %d\r\n",event_ocur); +// gpio_direction_output(IO_PORT_DM, 1); + EPMotion_Process_Data(event_ocur); +// gpio_direction_output(IO_PORT_DM, 0); + } + count++; + + if (count >= 300000) { + count = 0; + } + } +} + +void da230_low_energy_mode(void) +{ + da230_register_write(0x11, 0x04); +} + +void da230_int_io_detect(u8 int_io_status) +{ + static u8 int_io_status_old = 0; + /* u8 int_io_status = 0; */ + if (da230_init_ok) { + /* int_io_status = gpio_read(INT_IO); */ + if ((int_io_status) && (int_io_status_old == 0)) { + log_e("da230_int_io_detect\n"); + if (tap_start == 0) { + tap_start = 1; + da230_set_idle_flag(0); + log_info("da230_set_idle_flag:0"); + } + event_ocur = 1; + putchar('A'); + } else { + event_ocur = 0; + } + int_io_status_old = int_io_status; + + da230_check_tap_int(); + + } + +} + +static char da230_check_event() +{ + u8 tmp_tap_data = 0; + tmp_tap_data = tap_data; + if (tap_data) { + tap_data = 0; + printf("tmp_tap_data = %d\n", tmp_tap_data); + } + return tmp_tap_data; + /* return EPMotion_Process_Data(); */ +} + +void da230_ctl(u8 cmd, void *arg) +{ + switch (cmd) { + case GSENSOR_RESET_INT: + EPMotion_Reset_Tap_INT(); + break; + case GSENSOR_RESUME_INT: + EPMotion_Resume_Tap_INT(); + break; + case GSENSOR_INT_DET: + da230_int_io_detect(*(u8 *)arg); + break; + default: + + break; + } +} + +static u8 da230_idle_query(void) +{ + return da230_is_idle; +} + +REGISTER_GRAVITY_SENSOR(gSensor) = { + .logo = "da230", + .gravity_sensor_init = da230_init, + .gravity_sensor_check = da230_check_event, + .gravity_sensor_ctl = da230_ctl, +}; + +REGISTER_LP_TARGET(da230_lp_target) = { + .name = "da230", + .is_idle = da230_idle_query, +}; + +#endif + + diff --git a/apps/common/device/gSensor/da230.h b/apps/common/device/gSensor/da230.h new file mode 100644 index 0000000..6593fbc --- /dev/null +++ b/apps/common/device/gSensor/da230.h @@ -0,0 +1,25 @@ +#ifndef __da230_h +#define __da230_h + +#include "typedef.h" +#include "mira_std.h" + + + +#define LATCHED_MODE LATCHED_1S //interrupt latched mode +#define INTERRUPT_THRESHOLD 15 //interrupt threshold 0~31 ,(threshold*125)mg +#define INTERRUPT_DURATION 5 //interrupt duration 0~7 ,(50~700)ms 0:50ms 1:100ms 2:150ms 3:200ms 4:250ms 5:375ms 6:500ms 7:700ms +#define TAP_SAMPLE_LEVEL 1 //采样次数 = 25-TAP_SAMPLE_LEVEL*5 +#define TAP_FILTER 30 //噪声大小,大于TAP_FILTER认为是噪声 + +#define I2C_ADDR_DA230_W 0x4e +#define I2C_ADDR_DA230_R 0x4f + +extern u32 da230_register_read(u8 addr, u8 *data); +extern s8_m da230_register_write(u8_m addr, u8_m data); +extern u32 da230_register_write_bit(u8 addr, u8 start, u8 len, u8 data); + +// extern u8 da230_int_event_detect(void); + +#endif + diff --git a/apps/common/device/gSensor/gSensor_manage.c b/apps/common/device/gSensor/gSensor_manage.c new file mode 100644 index 0000000..4e3af14 --- /dev/null +++ b/apps/common/device/gSensor/gSensor_manage.c @@ -0,0 +1,215 @@ +#include "gSensor/gSensor_manage.h" +#include "device/device.h" +#include "app_config.h" +#include "debug.h" +#include "key_event_deal.h" +#include "btstack/avctp_user.h" +#include "app_main.h" +#include "tone_player.h" +#include "user_cfg.h" +/* #include "audio_config.h" */ +/* #include "app_power_manage.h" */ +/* #include "system/timer.h" */ +/* #include "event.h" */ + +#if TCFG_USER_TWS_ENABLE +#include "bt_tws.h" +#endif + +#if TCFG_GSENSOR_ENABLE + +#define LOG_TAG "[GSENSOR]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +static const struct gsensor_platform_data *platform_data; +G_SENSOR_INTERFACE *gSensor_hdl = NULL; +G_SENSOR_INFO __gSensor_info = {.iic_delay = 30}; +#define gSensor_info (&__gSensor_info) + +#if TCFG_GSENOR_USER_IIC_TYPE +#define iic_init(iic) hw_iic_init(iic) +#define iic_uninit(iic) hw_iic_uninit(iic) +#define iic_start(iic) hw_iic_start(iic) +#define iic_stop(iic) hw_iic_stop(iic) +#define iic_tx_byte(iic, byte) hw_iic_tx_byte(iic, byte) +#define iic_rx_byte(iic, ack) hw_iic_rx_byte(iic, ack) +#define iic_read_buf(iic, buf, len) hw_iic_read_buf(iic, buf, len) +#define iic_write_buf(iic, buf, len) hw_iic_write_buf(iic, buf, len) +#define iic_suspend(iic) hw_iic_suspend(iic) +#define iic_resume(iic) hw_iic_resume(iic) +#else +#define iic_init(iic) soft_iic_init(iic) +#define iic_uninit(iic) soft_iic_uninit(iic) +#define iic_start(iic) soft_iic_start(iic) +#define iic_stop(iic) soft_iic_stop(iic) +#define iic_tx_byte(iic, byte) soft_iic_tx_byte(iic, byte) +#define iic_rx_byte(iic, ack) soft_iic_rx_byte(iic, ack) +#define iic_read_buf(iic, buf, len) soft_iic_read_buf(iic, buf, len) +#define iic_write_buf(iic, buf, len) soft_iic_write_buf(iic, buf, len) +#define iic_suspend(iic) soft_iic_suspend(iic) +#define iic_resume(iic) soft_iic_resume(iic) +#endif + +void gSensor_event_to_user(u8 event) +{ + struct sys_event e; + e.type = SYS_KEY_EVENT; + e.u.key.event = event; + e.u.key.value = 0; + sys_event_notify(&e); +} + +void gSensor_int_io_detect(void *priv) +{ + u8 int_io_status = 0; + u8 det_result = 0; + int_io_status = gpio_read(platform_data->gSensor_int_io); + //log_info("status %d\n",int_io_status); + gSensor_hdl->gravity_sensor_ctl(GSENSOR_INT_DET, &int_io_status); + if (gSensor_hdl->gravity_sensor_check == NULL) { + return; + } + det_result = gSensor_hdl->gravity_sensor_check(); + if (det_result == 1) { + log_info("GSENSOR_EVENT_CLICK\n"); + gSensor_event_to_user(KEY_EVENT_CLICK); + } else if (det_result == 2) { + log_info("GSENSOR_EVENT_DOUBLE_CLICK\n"); + gSensor_event_to_user(KEY_EVENT_DOUBLE_CLICK); + } else if (det_result == 3) { + log_info("GSENSOR_EVENT_THREE_CLICK\n"); + gSensor_event_to_user(KEY_EVENT_TRIPLE_CLICK); + } +} + +u8 gravity_sensor_command(u8 w_chip_id, u8 register_address, u8 function_command) +{ + u8 ret = 1; + iic_start(gSensor_info->iic_hdl); + if (0 == iic_tx_byte(gSensor_info->iic_hdl, w_chip_id)) { + ret = 0; + log_e("\n gsen iic wr err 0\n"); + goto __gcend; + } + + delay(gSensor_info->iic_delay); + + if (0 == iic_tx_byte(gSensor_info->iic_hdl, register_address)) { + ret = 0; + log_e("\n gsen iic wr err 1\n"); + goto __gcend; + } + + delay(gSensor_info->iic_delay); + + if (0 == iic_tx_byte(gSensor_info->iic_hdl, function_command)) { + ret = 0; + log_e("\n gsen iic wr err 2\n"); + goto __gcend; + } + +__gcend: + iic_stop(gSensor_info->iic_hdl); + + return ret; +} + +u8 _gravity_sensor_get_ndata(u8 r_chip_id, u8 register_address, u8 *buf, u8 data_len) +{ + u8 read_len = 0; + + iic_start(gSensor_info->iic_hdl); + if (0 == iic_tx_byte(gSensor_info->iic_hdl, r_chip_id - 1)) { + log_e("\n gsen iic rd err 0\n"); + read_len = 0; + goto __gdend; + } + + + delay(gSensor_info->iic_delay); + if (0 == iic_tx_byte(gSensor_info->iic_hdl, register_address)) { + log_e("\n gsen iic rd err 1\n"); + read_len = 0; + goto __gdend; + } + + iic_start(gSensor_info->iic_hdl); + if (0 == iic_tx_byte(gSensor_info->iic_hdl, r_chip_id)) { + log_e("\n gsen iic rd err 2\n"); + read_len = 0; + goto __gdend; + } + + delay(gSensor_info->iic_delay); + + for (; data_len > 1; data_len--) { + *buf++ = iic_rx_byte(gSensor_info->iic_hdl, 1); + read_len ++; + } + + *buf = iic_rx_byte(gSensor_info->iic_hdl, 0); + read_len ++; + +__gdend: + + iic_stop(gSensor_info->iic_hdl); + delay(gSensor_info->iic_delay); + + return read_len; +} + +//u8 gravity_sen_dev_cur; /*当前挂载的Gravity sensor*/ +int gravity_sensor_init(void *_data) +{ + int retval = 0; + platform_data = (const struct gsensor_platform_data *)_data; + gSensor_info->iic_hdl = platform_data->iic; + retval = iic_init(gSensor_info->iic_hdl); + + log_e("\n gravity_sensor_init\n"); + + if (retval < 0) { + log_e("\n open iic for gsensor err\n"); + return retval; + } else { + log_info("\n iic open succ\n"); + } + + retval = -EINVAL; + list_for_each_gsensor(gSensor_hdl) { + if (!memcmp(gSensor_hdl->logo, platform_data->gSensor_name, strlen(platform_data->gSensor_name))) { + retval = 0; + break; + } + } + + if (retval < 0) { + log_e(">>>gSensor_hdl logo err\n"); + return retval; + } + + gpio_set_pull_up(platform_data->gSensor_int_io, 0); + gpio_set_pull_down(platform_data->gSensor_int_io, 0); + gpio_set_direction(platform_data->gSensor_int_io, 1); + gpio_set_die(platform_data->gSensor_int_io, 1); + + + if (gSensor_hdl->gravity_sensor_init()) { + log_e(">>>>gSensor_Int ERROR\n"); + } else { + log_info(">>>>gSensor_Int SUCC\n"); + gSensor_info->init_flag = 1; + sys_s_hi_timer_add(NULL, gSensor_int_io_detect, 2); //2ms + } + return 0; +} + + +#endif // CONFIG_GSENSOR_ENABLE + + diff --git a/apps/common/device/gSensor/gSensor_manage.h b/apps/common/device/gSensor/gSensor_manage.h new file mode 100644 index 0000000..6ba79b3 --- /dev/null +++ b/apps/common/device/gSensor/gSensor_manage.h @@ -0,0 +1,83 @@ +#ifndef _GSENSOR_MANAGE_H +#define _GSENSOR_MANAGE_H +#include "printf.h" +#include "cpu.h" +//#include "iic.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "timer.h" +#include "app_config.h" +#include "event.h" +#include "system/includes.h" + +#define ACCEL_OF_GRAVITY 10 +#define ACCEL_DATA_GAIN 10 + +enum { + GSENSOR_RESET_INT = 0, + GSENSOR_RESUME_INT, + GSENSOR_INT_DET, +}; + +enum { + GET_ACCEL_DATA = 0, +}; + +typedef struct { + short x; + short y; + short z; +} axis_info_t; + +typedef struct { + u8 logo[20]; + u8(*gravity_sensor_init)(void); + char (*gravity_sensor_check)(void); + void (*gravity_sensor_ctl)(u8 cmd, void *arg); +} G_SENSOR_INTERFACE; + + +struct gsensor_platform_data { + u8 iic; + char gSensor_name[20]; + int gSensor_int_io; +}; + +typedef struct { + u8 iic_hdl; + u8 iic_delay; //这个延时并非影响iic的时钟频率,而是2Byte数据之间的延时 + u8 ctl_flag; + int init_flag; + int check_cnt; + int check_timer_hdl; +} G_SENSOR_INFO; + +int gravity_sensor_init(void *_data); +u8 gravity_sensor_command(u8 w_chip_id, u8 register_address, u8 function_command); +u8 _gravity_sensor_get_ndata(u8 r_chip_id, u8 register_address, u8 *buf, u8 data_len); + +extern G_SENSOR_INTERFACE gsensor_dev_begin[]; +extern G_SENSOR_INTERFACE gsensor_dev_end[]; + +#define REGISTER_GRAVITY_SENSOR(gSensor) \ + static G_SENSOR_INTERFACE gSensor SEC_USED(.gsensor_dev) + +#define list_for_each_gsensor(c) \ + for (c=gsensor_dev_begin; c
© COPYRIGHT 2014 MiraMEMS
+ */ +/*******************************************************************************/ +#ifndef __mira_std_h +#define __mira_std_h + +/******************************************************************************* +Macro definitions - Register define for Gsensor asic +********************************************************************************/ +#define NSA_REG_SPI_I2C 0x00 +#define NSA_REG_WHO_AM_I 0x01 +#define NSA_REG_ACC_X_LSB 0x02 +#define NSA_REG_ACC_X_MSB 0x03 +#define NSA_REG_ACC_Y_LSB 0x04 +#define NSA_REG_ACC_Y_MSB 0x05 +#define NSA_REG_ACC_Z_LSB 0x06 +#define NSA_REG_ACC_Z_MSB 0x07 +#define NSA_REG_MOTION_FLAG 0x09 +#define NSA_REG_G_RANGE 0x0f +#define NSA_REG_ODR_AXIS_DISABLE 0x10 +#define NSA_REG_POWERMODE_BW 0x11 +#define NSA_REG_SWAP_POLARITY 0x12 +#define NSA_REG_FIFO_CTRL 0x14 +#define NSA_REG_INTERRUPT_SETTINGS0 0x15 +#define NSA_REG_INTERRUPT_SETTINGS1 0x16 +#define NSA_REG_INTERRUPT_SETTINGS2 0x17 +#define NSA_REG_INTERRUPT_MAPPING1 0x19 +#define NSA_REG_INTERRUPT_MAPPING2 0x1a +#define NSA_REG_INTERRUPT_MAPPING3 0x1b +#define NSA_REG_INT_PIN_CONFIG 0x20 +#define NSA_REG_INT_LATCH 0x21 +#define NSA_REG_ACTIVE_DURATION 0x27 +#define NSA_REG_ACTIVE_THRESHOLD 0x28 +#define NSA_REG_TAP_DURATION 0x2A +#define NSA_REG_TAP_THRESHOLD 0x2B +#define NSA_REG_ENGINEERING_MODE 0x7f +#define NSA_REG_SENS_COMP 0x8c +#define NSA_REG_MEMS_OPTION 0x8f +#define NSA_REG_CHIP_INFO 0xc0 + +/******************************************************************************* +Typedef definitions +********************************************************************************/ +#define ARM_BIT_8 0 + +#if ARM_BIT_8 +//如下数据类型是在8位机上定义的,在其它平台(比如32位)可能存在差别,需要根据实际情况修改 。 +typedef unsigned char u8_m; /* 无符号8位整型变量*/ +typedef signed char s8_m; /* 有符号8位整型变量*/ +typedef unsigned int u16_m; /* 无符号16位整型变量*/ +typedef signed int s16_m; /* 有符号16位整型变量*/ +typedef unsigned long u32_m; /* 无符号32位整型变量*/ +typedef signed long s32_m; /* 有符号32位整型变量*/ +typedef float fp32_m; /* 单精度浮点数(32位长度)*/ +typedef double fp64_m; /* 双精度浮点数(64位长度)*/ +#else +//如下数据类型是在32位机上定义的,在其它平台(比如8位)可能存在差别,需要根据实际情况修改 。 +typedef unsigned char u8_m; /* 无符号8位整型变量*/ +typedef signed char s8_m; /* 有符号8位整型变量*/ +typedef unsigned short u16_m; /* 无符号16位整型变量*/ +typedef signed short s16_m; /* 有符号16位整型变量*/ +typedef unsigned int u32_m; /* 无符号32位整型变量*/ +typedef signed int s32_m; /* 有符号32位整型变量*/ +typedef float fp32_m; /* 单精度浮点数(32位长度)*/ +typedef double fp64_m; /* 双精度浮点数(64位长度)*/ +#endif + +typedef struct AccData_tag { + s16_m ax; //加速度计原始数据结构体 数据格式 0 0 1024 + s16_m ay; + s16_m az; + +} AccData; + +#define mir3da_abs(x) (((x) > 0) ? (x) : (-(x))) +s32_m mir3da_sqrt(s32_m val); +void mir3da_memset(void *dest, u8_m count); +void *mir3da_memcpy(void *dest, void *source, u8_m count); +#endif + + diff --git a/apps/common/device/nandflash/nandflash.c b/apps/common/device/nandflash/nandflash.c new file mode 100644 index 0000000..25963bc --- /dev/null +++ b/apps/common/device/nandflash/nandflash.c @@ -0,0 +1,683 @@ +#include "nandflash.h" +#include "timer.h" +#include "app_config.h" +#include "asm/clock.h" + +#if TCFG_NANDFLASH_DEV_ENABLE + +#undef LOG_TAG_CONST +#define LOG_TAG "[FLASH]" +#define LOG_ERROR_ENABLE +#define LOG_INFO_ENABLE +#include "debug.h" + +#define NAND_FLASH_TIMEOUT 500 +#define NAND_PAGE_SIZE 2048 +#define MAX_NANDFLASH_PART_NUM 4 +#define NAND_BLOCK_SIZE 0x20000 + +struct nandflash_partition { + const char *name; + u32 start_addr; + u32 size; + struct device device; +}; + +static struct nandflash_partition nor_part[MAX_NANDFLASH_PART_NUM]; + +struct nandflash_info { + u32 flash_id; + int spi_num; + int spi_err; + u8 spi_cs_io; + u8 spi_r_width; + u8 part_num; + u8 open_cnt; + struct nandflash_partition *const part_list; + OS_MUTEX mutex; + u32 max_end_addr; +}; + +static struct nandflash_info _nandflash = { + .spi_num = (int) - 1, + .part_list = nor_part, +}; + +int nand_flash_read(u32 addr, u8 *buf, u32 len); +int nand_flash_erase(u32 addr); + + +#define spi_cs_init() \ + do { \ + gpio_set_die(_nandflash.spi_cs_io, 1); \ + gpio_set_direction(_nandflash.spi_cs_io, 0); \ + gpio_write(_nandflash.spi_cs_io, 1); \ + } while (0) + +#define spi_cs_uninit() \ + do { \ + gpio_set_die(_nandflash.spi_cs_io, 0); \ + gpio_set_direction(_nandflash.spi_cs_io, 1); \ + gpio_set_pull_up(_nandflash.spi_cs_io, 0); \ + gpio_set_pull_down(_nandflash.spi_cs_io, 0); \ + } while (0) +#define spi_cs_h() gpio_write(_nandflash.spi_cs_io, 1) +#define spi_cs_l() gpio_write(_nandflash.spi_cs_io, 0) +#define spi_read_byte() spi_recv_byte(_nandflash.spi_num, &_nandflash.spi_err) +#define spi_write_byte(x) spi_send_byte(_nandflash.spi_num, x) +#define spi_dma_read(x, y) spi_dma_recv(_nandflash.spi_num, x, y) +#define spi_dma_write(x, y) spi_dma_send(_nandflash.spi_num, x, y) +#define spi_set_width(x) spi_set_bit_mode(_nandflash.spi_num, x) + +static struct nandflash_partition *nandflash_find_part(const char *name) +{ + struct nandflash_partition *part = NULL; + u32 idx; + for (idx = 0; idx < MAX_NANDFLASH_PART_NUM; idx++) { + part = &_nandflash.part_list[idx]; + if (part->name == NULL) { + continue; + } + if (!strcmp(part->name, name)) { + return part; + } + } + return NULL; +} + +static struct nandflash_partition *nandflash_new_part(const char *name, u32 addr, u32 size) +{ + struct nandflash_partition *part; + u32 idx; + for (idx = 0; idx < MAX_NANDFLASH_PART_NUM; idx++) { + part = &_nandflash.part_list[idx]; + if (part->name == NULL) { + break; + } + } + if (part->name != NULL) { + log_error("create nandflash part fail\n"); + return NULL; + } + memset(part, 0, sizeof(*part)); + part->name = name; + part->start_addr = addr; + part->size = size; + if (part->start_addr + part->size > _nandflash.max_end_addr) { + _nandflash.max_end_addr = part->start_addr + part->size; + } + _nandflash.part_num++; + return part; +} + +static void nandflash_delete_part(const char *name) +{ + struct nandflash_partition *part; + u32 idx; + for (idx = 0; idx < MAX_NANDFLASH_PART_NUM; idx++) { + part = &_nandflash.part_list[idx]; + if (part->name == NULL) { + continue; + } + if (!strcmp(part->name, name)) { + part->name = NULL; + _nandflash.part_num--; + } + } +} + +static int nandflash_verify_part(struct nandflash_partition *p) +{ + struct nandflash_partition *part = NULL; + u32 idx; + for (idx = 0; idx < MAX_NANDFLASH_PART_NUM; idx++) { + part = &_nandflash.part_list[idx]; + if (part->name == NULL) { + continue; + } + if ((p->start_addr >= part->start_addr) && (p->start_addr < part->start_addr + part->size)) { + if (strcmp(p->name, part->name) != 0) { + return -1; + } + } + } + return 0; +} + +u16 nand_flash_read_id() +{ + u16 id; + spi_cs_l();//SPI_CS(0); + spi_write_byte(0xff); //命令头 + spi_cs_h();//SPI_CS(1); + os_time_dly(1); + spi_cs_l();//SPI_CS(0) + spi_write_byte(GD_READ_ID); + spi_write_byte(0x0); + id = spi_read_byte(); + id <<= 8; + id |= spi_read_byte(); + spi_cs_h();//SPI_CS(1);yy + return id; +} + +static void nand_write_enable() +{ + spi_cs_l();//SPI_CS(0); + spi_write_byte(GD_WRITE_ENABLE); + spi_cs_h();//SPI_CS(1); +} + +static void nand_write_disable() +{ + spi_cs_l();//SPI_CS(0); + spi_write_byte(GD_WRITE_DISABLE); + spi_cs_h();//SPI_CS(1); +} + +static void nand_set_features(u8 cmd, u8 dat) +{ + nand_write_enable(); + spi_cs_l();//SPI_CS(0); + spi_write_byte(GD_SET_FEATURES); //命令头 + spi_write_byte(cmd); //发送protection寄存器地址 + spi_write_byte(dat); //需要设置的数据 + spi_cs_h();;//SPI_CS(1); + nand_write_disable(); +} + +static u8 nand_get_features(u8 cmd) +{ + spi_cs_l(); + spi_write_byte(GD_GET_FEATURES); //命令头 + spi_write_byte(cmd); //发送protection寄存器地址 + cmd = spi_read_byte(); + spi_cs_h(); + return cmd; +} + +static u8 nand_flash_wait_ok(u32 timeout) +{ + u8 sta; + do { + sta = nand_get_features(GD_GET_STATUS); + if ((sta & NAND_STATUS_OIP) == 0) { + break; + } +#if 0 + if (sta & NAND_STATUS_OIP) { //ing + continue; + } + if (sta & NAND_STATUS_E_FAIL) { //erase fail + break; + } + if ((sta & NAND_STATUS_ECCS) == 0x20) { //ecc error + break; + } +#endif + } while (timeout--); + if (timeout == 0) { + puts("nand_flash_wait_ok timeout!\r\n"); + sta = -1; + } + return 0; +} + + +void nand_flash_reset(void) +{ + spi_cs_l(); + spi_write_byte(0xff); //命令头 + spi_cs_h(); +} + +static u16 block_page_get(u32 addr, u32 *cache_addr) +{ + u32 page = 0; + u32 block = 0, bp_mix = 0; + + //<地址超1页范围 + if (addr >= NAND_PAGE_SIZE) { + if (addr >= NAND_BLOCK_SIZE) { + while (addr >= NAND_BLOCK_SIZE) { + block++; + addr -= NAND_BLOCK_SIZE; + } + goto _page_count; + } else { + goto _page_count; + } + } + //<地址不超1页范围 + else { + goto _end_count; + } + +_page_count: + while (addr >= NAND_PAGE_SIZE) { + page++; + addr -= NAND_PAGE_SIZE; + } + +_end_count: + *cache_addr = addr; + bp_mix = (block << 6) | page; //16位构成里高8位为block号码,低8位里高两位依然为block,低6位为page号码 + //printf_u16(g_real_page); + //printf_u16(bp_mix); + //printf_u16(block); + //printf_u16(page); + return bp_mix; +} + +#define block_change(x) (x) + +int nand_flash_erase(u32 address) +{ + u32 bp_mix = 0; + u32 cache_addr; +// puts("erase\n"); + bp_mix = block_page_get(address, &cache_addr); + nand_write_enable(); + spi_cs_l();//SPI_CS(0); + spi_write_byte(GD_BLOCK_ERASE); + spi_write_byte(0xff); //8位dummy bits(值任意) + spi_write_byte(bp_mix >> 8); + spi_write_byte(bp_mix); + spi_cs_h();//SPI_CS(1); + nand_write_disable(); + nand_flash_wait_ok(NAND_FLASH_TIMEOUT); + return nand_get_features(GD_GET_STATUS); +} + +static void nand_flash_erase_all() +{ + nand_set_features(0xA0, 0x00); + for (int i = 0; i <= 1024; i++) { + nand_flash_erase(128000 * i); + } + r_printf("nandflash erase all!!!"); +} + +static void nand_page_read_to_cache(u32 block_page_addr) //PageRead +{ + spi_cs_l();//SPI_CS(0); + spi_write_byte(GD_PAGE_READ_CACHE); //PageRead to cache + spi_write_byte(0xff); //send the Page/Block Add + spi_write_byte((u8)((block_page_addr) >> 8)); + spi_write_byte((u8)block_page_addr); + spi_cs_h();//SPI_CS(1); + nand_flash_wait_ok(NAND_FLASH_TIMEOUT); +} + +static void nand_read_from_cache(u8 *buf, u32 cache_addr, u32 len) //ReadCache +{ + /* cache_addr |= 0x4000; */ + spi_cs_l();//SPI_CS(0); + spi_write_byte(GD_READ_FROM_CACHE); //PageRead to cache + spi_write_byte((u8)((cache_addr) >> 8)); + spi_write_byte((u8)cache_addr); + spi_write_byte(0xFF); //send 1byte dummy clk + spi_dma_read(buf, len); + spi_cs_h();//SPI_CS(1); +} + +#if 1 +static void nand_program_load(u8 *buf, u32 cache_addr, u32 len) +{ + spi_cs_l();//SPI_CS(0); + spi_write_byte(GD_PROGRAM_LOAD); //PageLoad to cache ,change the data + spi_write_byte((u8)((cache_addr) >> 8)); + spi_write_byte((u8)cache_addr); + spi_dma_write(buf, len); //将数据放到总线上 + spi_cs_h();//SPI_CS(1); +} + +static int nand_program_excute(u32 block_page_addr) +{ + int reg; + nand_write_enable(); + spi_cs_l();//SPI_CS(0); + spi_write_byte(GD_PROGRAM_EXECUTE); + spi_write_byte(0xff); //send the Page/Block Add + spi_write_byte((u8)((block_page_addr) >> 8)); + spi_write_byte((u8)block_page_addr); + spi_cs_h();//SPI_CS(1); + nand_write_disable(); + reg = nand_flash_wait_ok(NAND_FLASH_TIMEOUT); + return reg; +} + + +static int nand_write(u32 addr, u16 len, u8 *buf) +{ + int reg; + u32 bp_mix = 0; + u32 cache_addr; + + bp_mix = block_page_get(addr, &cache_addr); + bp_mix = block_change(bp_mix); + //printf_u16(cache_addr); + nand_program_load(buf, cache_addr, len); + reg = nand_program_excute(bp_mix); + return reg; +}/**/ + + +static void nand_program_load_random_data(u8 *buf, u16 cache_addr, u16 len) +{ + spi_cs_l();//SPI_CS(0); + spi_write_byte(GD_PROGRAM_LOAD_RANDOM_DATA); + spi_write_byte((u8)((cache_addr) >> 8)); + spi_write_byte((u8)cache_addr); + spi_dma_write(buf, len); //将数据放到总线上 + spi_cs_h();//SPI_CS(1); + nand_flash_wait_ok(NAND_FLASH_TIMEOUT); +} + +int nand_internal_data_move(u32 addr, u16 len, u8 *buf) +{ + u32 bp_mix = 0; + u32 cache_addr; + + bp_mix = block_page_get(addr, &cache_addr); + bp_mix = block_change(bp_mix); + + //<1、PAGE READ to cache + nand_page_read_to_cache(bp_mix); + //<2、PROGRAM LOAD RANDOM DATA + nand_program_load_random_data(buf, cache_addr, len); + //<3、WRITE ENABLE + //<4、PROGRAM EXECUTE + nand_program_excute(bp_mix); + //<5、GET FEATURE + return nand_get_features(GD_GET_STATUS); +} + +int nand_flash_write(u32 offset, u8 *buf, u16 len) +{ + /* printf("%s() %x l: %x @:%x \n",__func__,buf,len,offset); */ + int reg; + int _len = len; + u8 *_buf = (u8 *)buf; + os_mutex_pend(&_nandflash.mutex, 0); + u32 first_page_len = NAND_PAGE_SIZE - (offset % NAND_PAGE_SIZE); + /* printf("first_page_len %x %x \n", first_page_len, offset % NAND_PAGE_SIZE); */ + first_page_len = _len > first_page_len ? first_page_len : _len; + reg = nand_write(offset, first_page_len, _buf); + if (reg) { + goto __exit; + } + _len -= first_page_len; + _buf += first_page_len; + offset += first_page_len; + while (_len) { + u32 cnt = _len > NAND_PAGE_SIZE ? NAND_PAGE_SIZE : _len; + reg = nand_write(offset, cnt, _buf); + if (reg) { + goto __exit; + } + _len -= cnt; + offset += cnt; + _buf += cnt; + } +__exit: + os_mutex_post(&_nandflash.mutex); + return 0; +} + +#endif + +static void nand_read(u32 addr, u32 len, u8 *buf) +{ + u32 bp_mix = 0; + u32 cache_addr; + bp_mix = block_page_get(addr, &cache_addr); + bp_mix = block_change(bp_mix); + nand_page_read_to_cache(bp_mix); + nand_read_from_cache(buf, cache_addr, len); +} + + +int nand_flash_read(u32 offset, u8 *buf, u32 len) +{ + /* printf("%s() %x l: %x @:%x \n",__func__,buf,len,offset); */ + int reg = 0; + int _len = len; + u8 *_buf = (u8 *)buf; + os_mutex_pend(&_nandflash.mutex, 0); + u32 first_page_len = NAND_PAGE_SIZE - (offset % NAND_PAGE_SIZE); + /* printf("first_page_len %x %x \n", first_page_len, offset % NAND_PAGE_SIZE); */ + first_page_len = _len > first_page_len ? first_page_len : _len; + nand_read(offset, first_page_len, _buf); + _len -= first_page_len; + _buf += first_page_len; + offset += first_page_len; + while (_len) { + u32 cnt = _len > NAND_PAGE_SIZE ? NAND_PAGE_SIZE : _len; + nand_read(offset, cnt, _buf); + _len -= cnt; + offset += cnt; + _buf += cnt; + } + os_mutex_post(&_nandflash.mutex); + return reg; +} + + +int _nandflash_init(const char *name, struct nandflash_dev_platform_data *pdata) +{ + log_info("nandflash_init ! %x %x", pdata->spi_cs_port, pdata->spi_read_width); + if (_nandflash.spi_num == (int) - 1) { + _nandflash.spi_num = pdata->spi_hw_num; + _nandflash.spi_cs_io = pdata->spi_cs_port; + _nandflash.spi_r_width = pdata->spi_read_width; + _nandflash.flash_id = 0; + os_mutex_create(&_nandflash.mutex); + _nandflash.max_end_addr = 0; + _nandflash.part_num = 0; + } + ASSERT(_nandflash.spi_num == pdata->spi_hw_num); + ASSERT(_nandflash.spi_cs_io == pdata->spi_cs_port); + ASSERT(_nandflash.spi_r_width == pdata->spi_read_width); + struct nandflash_partition *part; + part = nandflash_find_part(name); + if (!part) { + part = nandflash_new_part(name, pdata->start_addr, pdata->size); + ASSERT(part, "not enough nandflash partition memory in array\n"); + ASSERT(nandflash_verify_part(part) == 0, "nandflash partition %s overlaps\n", name); + log_info("nandflash new partition %s\n", part->name); + } else { + ASSERT(0, "nandflash partition name already exists\n"); + } + return 0; +} + +static void clock_critical_enter() +{ + +} +static void clock_critical_exit() +{ + if (!(_nandflash.flash_id == 0 || _nandflash.flash_id == 0xffff)) { + spi_set_baud(_nandflash.spi_num, spi_get_baud(_nandflash.spi_num)); + } +} +CLOCK_CRITICAL_HANDLE_REG(spi_nandflash, clock_critical_enter, clock_critical_exit); + +int _nandflash_open(void *arg) +{ + int reg = 0; + os_mutex_pend(&_nandflash.mutex, 0); + log_info("nandflash open\n"); + if (!_nandflash.open_cnt) { + spi_cs_init(); + spi_open(_nandflash.spi_num); + _nandflash.flash_id = nand_flash_read_id(); + log_info("nandflash_read_id: 0x%x\n", _nandflash.flash_id); + if ((_nandflash.flash_id == 0) || (_nandflash.flash_id == 0xffff)) { + log_error("read nandflash id error !\n"); + reg = -ENODEV; + goto __exit; + } + log_info("nandflash open success !\n"); + } + if (_nandflash.flash_id == 0 || _nandflash.flash_id == 0xffff) { + log_error("re-open nandflash id error !\n"); + reg = -EFAULT; + goto __exit; + } + _nandflash.open_cnt++; + nand_flash_erase_all(); +__exit: + os_mutex_post(&_nandflash.mutex); + return reg; +} + +int _nandflash_close(void) +{ + os_mutex_pend(&_nandflash.mutex, 0); + log_info("nandflash close\n"); + if (_nandflash.open_cnt) { + _nandflash.open_cnt--; + } + if (!_nandflash.open_cnt) { + spi_close(_nandflash.spi_num); + spi_cs_uninit(); + + log_info("nandflash close done\n"); + } + os_mutex_post(&_nandflash.mutex); + return 0; +} + + +int _nandflash_ioctl(u32 cmd, u32 arg, u32 unit, void *_part) +{ + int reg = 0; + struct nandflash_partition *part = _part; + os_mutex_pend(&_nandflash.mutex, 0); + switch (cmd) { + case IOCTL_GET_STATUS: + *(u32 *)arg = 1; + break; + case IOCTL_GET_ID: + *((u32 *)arg) = _nandflash.flash_id; + break; + case IOCTL_GET_BLOCK_SIZE: + *(u32 *)arg = 512; + break; + case IOCTL_ERASE_BLOCK: + reg = nand_flash_erase(arg); + break; + case IOCTL_GET_CAPACITY: + *(u32 *)arg = 128 * 1024 / unit; + break; + case IOCTL_FLUSH: + break; + case IOCTL_CMD_RESUME: + break; + case IOCTL_CMD_SUSPEND: + break; + default: + reg = -EINVAL; + break; + } +__exit: + os_mutex_post(&_nandflash.mutex); + return reg; +} + + +/************************************************************************************* + * 挂钩 device_api + ************************************************************************************/ + +static int nandflash_dev_init(const struct dev_node *node, void *arg) +{ + struct nandflash_dev_platform_data *pdata = arg; + return _nandflash_init(node->name, pdata); +} + +static int nandflash_dev_open(const char *name, struct device **device, void *arg) +{ + struct nandflash_partition *part; + part = nandflash_find_part(name); + if (!part) { + log_error("no nandflash partition is found\n"); + return -ENODEV; + } + *device = &part->device; + (*device)->private_data = part; + if (atomic_read(&part->device.ref)) { + return 0; + } + return _nandflash_open(arg); +} +static int nandflash_dev_close(struct device *device) +{ + return _nandflash_close(); +} +static int nandflash_dev_read(struct device *device, void *buf, u32 len, u32 offset) +{ + int reg; + offset = offset * 512; + len = len * 512; + /* r_printf("flash read sector = %d, num = %d\n", offset, len); */ + struct nandflash_partition *part; + part = (struct nandflash_partition *)device->private_data; + if (!part) { + log_error("nandflash partition invalid\n"); + return -EFAULT; + } + offset += part->start_addr; + reg = nand_flash_read(offset, buf, len); + if (reg) { + r_printf(">>>[r error]:\n"); + len = 0; + } + len = len / 512; + return len; +} +static int nandflash_dev_write(struct device *device, void *buf, u32 len, u32 offset) +{ + /* r_printf("flash write sector = %d, num = %d\n", offset, len); */ + int reg = 0; + offset = offset * 512; + len = len * 512; + struct nandflash_partition *part = device->private_data; + if (!part) { + log_error("nandflash partition invalid\n"); + return -EFAULT; + } + offset += part->start_addr; + reg = nand_flash_write(offset, buf, len); + if (reg) { + r_printf(">>>[w error]:\n"); + len = 0; + } + len = len / 512; + return len; +} +static bool nandflash_dev_online(const struct dev_node *node) +{ + return 1; +} +static int nandflash_dev_ioctl(struct device *device, u32 cmd, u32 arg) +{ + struct nandflash_partition *part = device->private_data; + if (!part) { + log_error("nandflash partition invalid\n"); + return -EFAULT; + } + return _nandflash_ioctl(cmd, arg, 512, part); +} +const struct device_operations nandflash_dev_ops = { + .init = nandflash_dev_init, + .online = nandflash_dev_online, + .open = nandflash_dev_open, + .read = nandflash_dev_read, + .write = nandflash_dev_write, + .ioctl = nandflash_dev_ioctl, + .close = nandflash_dev_close, +}; +#endif diff --git a/apps/common/device/norflash/norflash.c b/apps/common/device/norflash/norflash.c new file mode 100644 index 0000000..8affea1 --- /dev/null +++ b/apps/common/device/norflash/norflash.c @@ -0,0 +1,912 @@ +#include "norflash.h" +#include "app_config.h" +#include "asm/clock.h" +#include "system/timer.h" + +#if defined(TCFG_NORFLASH_DEV_ENABLE) && TCFG_NORFLASH_DEV_ENABLE + +#undef LOG_TAG_CONST +#define LOG_TAG "[FLASH]" +#define LOG_ERROR_ENABLE +#define LOG_INFO_ENABLE +#include "debug.h" + + +#define MAX_NORFLASH_PART_NUM 4 + +struct norflash_partition { + const char *name; + u32 start_addr; + u32 size; + struct device device; +}; + +static struct norflash_partition nor_part[MAX_NORFLASH_PART_NUM]; + +struct norflash_info { + u32 flash_id; + u32 flash_capacity; + int spi_num; + int spi_err; + u8 spi_cs_io; + u8 spi_r_width; + u8 part_num; + u8 open_cnt; + struct norflash_partition *const part_list; + OS_MUTEX mutex; + u32 max_end_addr; +}; + +static struct norflash_info _norflash = { + .spi_num = (int) - 1, + .part_list = nor_part, +}; + +int _norflash_read(u32 addr, u8 *buf, u32 len, u8 cache); +int _norflash_eraser(u8 eraser, u32 addr); +static void _norflash_cache_sync_timer(void *priv); +static int _norflash_write_pages(u32 addr, u8 *buf, u32 len); + + +#define spi_cs_init() \ + do { \ + gpio_set_die(_norflash.spi_cs_io, 1); \ + gpio_set_direction(_norflash.spi_cs_io, 0); \ + gpio_write(_norflash.spi_cs_io, 1); \ + } while (0) + +#define spi_cs_uninit() \ + do { \ + gpio_set_die(_norflash.spi_cs_io, 0); \ + gpio_set_direction(_norflash.spi_cs_io, 1); \ + gpio_set_pull_up(_norflash.spi_cs_io, 0); \ + gpio_set_pull_down(_norflash.spi_cs_io, 0); \ + } while (0) +#define spi_cs_h() gpio_write(_norflash.spi_cs_io, 1) +#define spi_cs_l() gpio_write(_norflash.spi_cs_io, 0) +#define spi_read_byte() spi_recv_byte(_norflash.spi_num, &_norflash.spi_err) +#define spi_write_byte(x) spi_send_byte(_norflash.spi_num, x) +#define spi_dma_read(x, y) spi_dma_recv(_norflash.spi_num, x, y) +#define spi_dma_write(x, y) spi_dma_send(_norflash.spi_num, x, y) +#define spi_set_width(x) spi_set_bit_mode(_norflash.spi_num, x) + +static struct norflash_partition *norflash_find_part(const char *name) +{ + struct norflash_partition *part = NULL; + u32 idx; + for (idx = 0; idx < MAX_NORFLASH_PART_NUM; idx++) { + part = &_norflash.part_list[idx]; + if (part->name == NULL) { + continue; + } + if (!strcmp(part->name, name)) { + return part; + } + } + return NULL; +} + +static struct norflash_partition *norflash_new_part(const char *name, u32 addr, u32 size) +{ + struct norflash_partition *part; + u32 idx; + for (idx = 0; idx < MAX_NORFLASH_PART_NUM; idx++) { + part = &_norflash.part_list[idx]; + if (part->name == NULL) { + break; + } + } + if (part->name != NULL) { + log_error("create norflash part fail\n"); + return NULL; + } + memset(part, 0, sizeof(*part)); + part->name = name; + part->start_addr = addr; + part->size = size; + if (part->start_addr + part->size > _norflash.max_end_addr) { + _norflash.max_end_addr = part->start_addr + part->size; + } + _norflash.part_num++; + return part; +} + +static void norflash_delete_part(const char *name) +{ + struct norflash_partition *part; + u32 idx; + for (idx = 0; idx < MAX_NORFLASH_PART_NUM; idx++) { + part = &_norflash.part_list[idx]; + if (part->name == NULL) { + continue; + } + if (!strcmp(part->name, name)) { + part->name = NULL; + _norflash.part_num--; + } + } +} + +static int norflash_verify_part(struct norflash_partition *p) +{ + struct norflash_partition *part = NULL; + u32 idx; + for (idx = 0; idx < MAX_NORFLASH_PART_NUM; idx++) { + part = &_norflash.part_list[idx]; + if (part->name == NULL) { + continue; + } + if ((p->start_addr >= part->start_addr) && (p->start_addr < part->start_addr + part->size)) { + if (strcmp(p->name, part->name) != 0) { + return -1; + } + } + } + return 0; +} + + + +#define FLASH_CACHE_ENABLE 1 + +#if FLASH_CACHE_ENABLE +static u32 flash_cache_addr; +static u8 *flash_cache_buf = NULL; //缓存4K的数据,与flash里的数据一样。 +static u8 flash_cache_is_dirty; +static u16 flash_cache_timer; + +#define FLASH_CACHE_SYNC_T_INTERVAL 60 + +static int _check_0xff(u8 *buf, u32 len) +{ + for (u32 i = 0; i < len; i ++) { + if ((*(buf + i)) != 0xff) { + return 1; + } + } + return 0; +} +#endif + + +static u32 _pow(u32 num, int n) +{ + u32 powint = 1; + int i; + for (i = 1; i <= n; i++) { + powint *= num; + } + return powint; +} + +static int _norflash_wait_ok() +{ + u32 timeout = 8 * 1000 * 1000 / 100; + while (timeout--) { + spi_cs_l(); + spi_write_byte(WINBOND_READ_SR1); + u8 reg_1 = spi_read_byte(); + spi_cs_h(); + if (!(reg_1 & BIT(0))) { + break; + } + delay(100); + } + if (timeout == 0) { + log_error("norflash_wait_ok timeout!\r\n"); + return 1; + } + return 0; +} + +static void _norflash_send_write_enable() +{ + spi_cs_l(); + spi_write_byte(WINBOND_WRITE_ENABLE); + spi_cs_h(); +} +static u8 is4byte_mode; +static void _norflash_send_addr(u32 addr) +{ + if (is4byte_mode) { + spi_write_byte(addr >> 24); + } + spi_write_byte(addr >> 16); + spi_write_byte(addr >> 8); + spi_write_byte(addr); +} + +static u32 _norflash_read_id() +{ + u8 id[3]; + spi_cs_l(); + spi_write_byte(WINBOND_JEDEC_ID); + for (u8 i = 0; i < sizeof(id); i++) { + id[i] = spi_read_byte(); + } + spi_cs_h(); + return id[0] << 16 | id[1] << 8 | id[2]; +} + +int _norflash_init(const char *name, struct norflash_dev_platform_data *pdata) +{ + log_info("norflash_init ! %x %x", pdata->spi_cs_port, pdata->spi_read_width); + if (_norflash.spi_num == (int) - 1) { + _norflash.spi_num = pdata->spi_hw_num; + _norflash.spi_cs_io = pdata->spi_cs_port; + _norflash.spi_r_width = pdata->spi_read_width; + _norflash.flash_id = 0; + _norflash.flash_capacity = 0; + os_mutex_create(&_norflash.mutex); + _norflash.max_end_addr = 0; + _norflash.part_num = 0; + } + ASSERT(_norflash.spi_num == pdata->spi_hw_num); + ASSERT(_norflash.spi_cs_io == pdata->spi_cs_port); + ASSERT(_norflash.spi_r_width == pdata->spi_read_width); + struct norflash_partition *part; + part = norflash_find_part(name); + if (!part) { + part = norflash_new_part(name, pdata->start_addr, pdata->size); + ASSERT(part, "not enough norflash partition memory in array\n"); + ASSERT(norflash_verify_part(part) == 0, "norflash partition %s overlaps\n", name); + log_info("norflash new partition %s\n", part->name); + } else { + ASSERT(0, "norflash partition name already exists\n"); + } + return 0; +} + +static void clock_critical_enter() +{ + +} +static void clock_critical_exit() +{ + if (!(_norflash.flash_id == 0 || _norflash.flash_id == 0xffff)) { + spi_set_baud(_norflash.spi_num, spi_get_baud(_norflash.spi_num)); + } +} +CLOCK_CRITICAL_HANDLE_REG(spi_norflash, clock_critical_enter, clock_critical_exit); + +void norflash_enter_4byte_addr() +{ + spi_cs_l(); + spi_write_byte(0xb7); + spi_cs_h(); +} +void norflash_exit_4byte_addr() +{ + spi_cs_l(); + spi_write_byte(0xe9); + spi_cs_h(); +} +int _norflash_open(void *arg) +{ + int reg = 0; + os_mutex_pend(&_norflash.mutex, 0); + log_info("norflash open\n"); + if (!_norflash.open_cnt) { + spi_cs_init(); + spi_open(_norflash.spi_num); + _norflash.flash_id = _norflash_read_id(); + log_info("norflash_read_id: 0x%x\n", _norflash.flash_id); + if ((_norflash.flash_id == 0) || (_norflash.flash_id == 0xffffff)) { + log_error("read norflash id error !\n"); + reg = -ENODEV; + goto __exit; + } + _norflash.flash_capacity = 64 * _pow(2, (_norflash.flash_id & 0xff) - 0x10) * 1024; + log_info("norflash_capacity: 0x%x\n", _norflash.flash_capacity); + + is4byte_mode = 0; + if (_norflash.flash_capacity > 16 * 1024 * 1024) { + norflash_enter_4byte_addr(); + is4byte_mode = 1; + } +#if FLASH_CACHE_ENABLE + flash_cache_buf = (u8 *)malloc(4096); + ASSERT(flash_cache_buf, "flash_cache_buf is not ok\n"); + flash_cache_addr = 4096;//先给一个大于4096的数 + _norflash_read(0, flash_cache_buf, 4096, 1); + flash_cache_addr = 0; +#endif + log_info("norflash open success !\n"); + } + if (_norflash.flash_id == 0 || _norflash.flash_id == 0xffffff) { + log_error("re-open norflash id error !\n"); + reg = -EFAULT; + goto __exit; + } + ASSERT(_norflash.max_end_addr <= _norflash.flash_capacity, "max partition end address is greater than flash capacity\n"); + _norflash.open_cnt++; + +__exit: + os_mutex_post(&_norflash.mutex); + return reg; +} + +int _norflash_close(void) +{ + os_mutex_pend(&_norflash.mutex, 0); + log_info("norflash close\n"); + if (_norflash.open_cnt) { + _norflash.open_cnt--; + } + if (!_norflash.open_cnt) { +#if FLASH_CACHE_ENABLE + if (flash_cache_is_dirty) { + flash_cache_is_dirty = 0; + _norflash_eraser(FLASH_SECTOR_ERASER, flash_cache_addr); + _norflash_write_pages(flash_cache_addr, flash_cache_buf, 4096); + } + free(flash_cache_buf); + flash_cache_buf = NULL; +#endif + spi_close(_norflash.spi_num); + spi_cs_uninit(); + + log_info("norflash close done\n"); + } + os_mutex_post(&_norflash.mutex); + return 0; +} + +int _norflash_read(u32 addr, u8 *buf, u32 len, u8 cache) +{ + int reg = 0; + u32 align_addr; + os_mutex_pend(&_norflash.mutex, 0); + /* y_printf("flash read addr = %d, len = %d\n", addr, len); */ +#if FLASH_CACHE_ENABLE + if (!cache) { + goto __no_cache1; + } + u32 r_len = 4096 - (addr % 4096); + if ((addr >= flash_cache_addr) && (addr < (flash_cache_addr + 4096))) { + if (len <= r_len) { + memcpy(buf, flash_cache_buf + (addr - flash_cache_addr), len); + goto __exit; + } else { + memcpy(buf, flash_cache_buf + (addr - flash_cache_addr), r_len); + addr += r_len; + buf += r_len; + len -= r_len; + } + } +__no_cache1: +#endif + spi_cs_l(); + if (_norflash.spi_r_width == 2) { + spi_write_byte(WINBOND_FAST_READ_DUAL_OUTPUT); + _norflash_send_addr(addr); + spi_write_byte(0); + spi_set_width(SPI_MODE_UNIDIR_2BIT); + spi_dma_read(buf, len); + spi_set_width(SPI_MODE_BIDIR_1BIT); + } else if (_norflash.spi_r_width == 4) { + spi_write_byte(0x6b); + _norflash_send_addr(addr); + spi_write_byte(0); + spi_set_width(SPI_MODE_UNIDIR_4BIT); + spi_dma_read(buf, len); + spi_set_width(SPI_MODE_BIDIR_1BIT); + } else { + spi_write_byte(WINBOND_FAST_READ_DATA); + _norflash_send_addr(addr); + spi_write_byte(0); + spi_dma_read(buf, len); + } + spi_cs_h(); +//#if FLASH_CACHE_ENABLE +// if (!cache) { +// goto __no_cache2; +// } +// align_addr = (addr + len) / 4096 * 4096; +// if ((int)len - (int)((addr + len) - align_addr) >= 4096) { +// align_addr -= 4096; +// if (flash_cache_addr != align_addr) { +// flash_cache_addr = align_addr; +// memcpy(flash_cache_buf, buf + (align_addr - addr), 4096); +// } +// } +//__no_cache2: +//#endif +__exit: + os_mutex_post(&_norflash.mutex); + return reg; +} + +static int _norflash_write_pages(u32 addr, u8 *buf, u32 len) +{ + /* y_printf("flash write addr = %d, num = %d\n", addr, len); */ + + int reg; + u32 first_page_len = 256 - (addr % 256); + first_page_len = len > first_page_len ? first_page_len : len; + _norflash_send_write_enable(); + spi_cs_l(); + spi_write_byte(WINBOND_PAGE_PROGRAM); + _norflash_send_addr(addr) ; + spi_dma_write(buf, first_page_len); + spi_cs_h(); + reg = _norflash_wait_ok(); + if (reg) { + return 1; + } + addr += first_page_len; + buf += first_page_len; + len -= first_page_len; + while (len) { + u32 cnt = len > 256 ? 256 : len; + _norflash_send_write_enable(); + spi_cs_l(); + spi_write_byte(WINBOND_PAGE_PROGRAM); + _norflash_send_addr(addr) ; + spi_dma_write(buf, cnt); + spi_cs_h(); + reg = _norflash_wait_ok(); + if (reg) { + return 1; + } + addr += cnt; + buf += cnt; + len -= cnt; + } + return 0; +} + +#if FLASH_CACHE_ENABLE +static void _norflash_cache_sync_timer(void *priv) +{ + int reg = 0; + os_mutex_pend(&_norflash.mutex, 0); + if (flash_cache_is_dirty) { + flash_cache_is_dirty = 0; + reg = _norflash_eraser(FLASH_SECTOR_ERASER, flash_cache_addr); + if (reg) { + goto __exit; + } + reg = _norflash_write_pages(flash_cache_addr, flash_cache_buf, 4096); + } + if (flash_cache_timer) { + sys_timeout_del(flash_cache_timer); + flash_cache_timer = 0; + } +__exit: + os_mutex_post(&_norflash.mutex); +} +#endif + +int _norflash_write(u32 addr, void *buf, u32 len, u8 cache) +{ + int reg = 0; + os_mutex_pend(&_norflash.mutex, 0); + + u8 *w_buf = (u8 *)buf; + u32 w_len = len; + + /* y_printf("flash write addr = %d, num = %d\n", addr, len); */ +#if FLASH_CACHE_ENABLE + if (!cache) { + reg = _norflash_write_pages(addr, w_buf, w_len); + goto __exit; + } + u32 align_addr = addr / 4096 * 4096; + u32 align_len = 4096 - (addr - align_addr); + align_len = w_len > align_len ? align_len : w_len; + if (align_addr != flash_cache_addr) { + if (flash_cache_is_dirty) { + flash_cache_is_dirty = 0; + reg = _norflash_eraser(FLASH_SECTOR_ERASER, flash_cache_addr); + if (reg) { + goto __exit; + } + reg = _norflash_write_pages(flash_cache_addr, flash_cache_buf, 4096); + if (reg) { + goto __exit; + } + } + _norflash_read(align_addr, flash_cache_buf, 4096, 0); + flash_cache_addr = align_addr; + } + memcpy(flash_cache_buf + (addr - align_addr), w_buf, align_len); + if ((addr + align_len) % 4096) { + flash_cache_is_dirty = 1; + if (flash_cache_timer) { + sys_timer_re_run(flash_cache_timer); + } else { + flash_cache_timer = sys_timeout_add(0, _norflash_cache_sync_timer, FLASH_CACHE_SYNC_T_INTERVAL); + } + } else { + flash_cache_is_dirty = 0; + reg = _norflash_eraser(FLASH_SECTOR_ERASER, align_addr); + if (reg) { + goto __exit; + } + reg = _norflash_write_pages(align_addr, flash_cache_buf, 4096); + if (reg) { + goto __exit; + } + } + addr += align_len; + w_buf += align_len; + w_len -= align_len; + while (w_len) { + u32 cnt = w_len > 4096 ? 4096 : w_len; + _norflash_read(addr, flash_cache_buf, 4096, 0); + flash_cache_addr = addr; + memcpy(flash_cache_buf, w_buf, cnt); + if ((addr + cnt) % 4096) { + flash_cache_is_dirty = 1; + if (flash_cache_timer) { + sys_timer_re_run(flash_cache_timer); + } else { + flash_cache_timer = sys_timeout_add(0, _norflash_cache_sync_timer, FLASH_CACHE_SYNC_T_INTERVAL); + } + } else { + flash_cache_is_dirty = 0; + reg = _norflash_eraser(FLASH_SECTOR_ERASER, addr); + if (reg) { + goto __exit; + } + reg = _norflash_write_pages(addr, flash_cache_buf, 4096); + if (reg) { + goto __exit; + } + } + addr += cnt; + w_buf += cnt; + w_len -= cnt; + } +#else + reg = _norflash_write_pages(addr, w_buf, w_len); +#endif +__exit: + os_mutex_post(&_norflash.mutex); + return reg; +} + +int _norflash_eraser(u8 eraser, u32 addr) +{ + u8 eraser_cmd; + switch (eraser) { + case FLASH_PAGE_ERASER: + eraser_cmd = WINBOND_PAGE_ERASE; + addr = addr / 256 * 256; + break; + case FLASH_SECTOR_ERASER: + eraser_cmd = WINBOND_SECTOR_ERASE; + //r_printf(">>>[test]:addr = %d\n", addr); + addr = addr / 4096 * 4096; + break; + case FLASH_BLOCK_ERASER: + eraser_cmd = WINBOND_BLOCK_ERASE; + addr = addr / 65536 * 65536; + break; + case FLASH_CHIP_ERASER: + eraser_cmd = WINBOND_CHIP_ERASE; + break; + } + _norflash_send_write_enable(); + spi_cs_l(); + spi_write_byte(eraser_cmd); + if (eraser_cmd != WINBOND_CHIP_ERASE) { + _norflash_send_addr(addr); + } + spi_cs_h(); + return _norflash_wait_ok(); +} + +int _norflash_ioctl(u32 cmd, u32 arg, u32 unit, void *_part) +{ + int reg = 0; + struct norflash_partition *part = _part; + os_mutex_pend(&_norflash.mutex, 0); + switch (cmd) { + case IOCTL_GET_STATUS: + *(u32 *)arg = 1; + break; + case IOCTL_GET_ID: + *((u32 *)arg) = _norflash.flash_id; + break; + case IOCTL_GET_CAPACITY: + if (_norflash.flash_capacity == 0) { + *(u32 *)arg = 0; + } else if (_norflash.part_num == 1 && part->start_addr == 0) { + *(u32 *)arg = _norflash.flash_capacity / unit; + } else { + *(u32 *)arg = part->size / unit; + } + break; + case IOCTL_GET_BLOCK_SIZE: + *(u32 *)arg = 512; + break; + case IOCTL_ERASE_PAGE: + reg = _norflash_eraser(FLASH_PAGE_ERASER, arg * unit + part->start_addr); + break; + case IOCTL_ERASE_SECTOR: + reg = _norflash_eraser(FLASH_SECTOR_ERASER, arg * unit + part->start_addr); + break; + case IOCTL_ERASE_BLOCK: + reg = _norflash_eraser(FLASH_BLOCK_ERASER, arg * unit + part->start_addr); + break; + case IOCTL_ERASE_CHIP: + reg = _norflash_eraser(FLASH_CHIP_ERASER, 0); + break; + case IOCTL_FLUSH: + break; + case IOCTL_CMD_RESUME: + break; + case IOCTL_CMD_SUSPEND: + break; + case IOCTL_GET_PART_INFO: + u32 *info = (u32 *)arg; + u32 *start_addr = &info[0]; + u32 *part_size = &info[1]; + *start_addr = part->start_addr; + *part_size = part->size; + break; + default: + reg = -EINVAL; + break; + } +__exit: + os_mutex_post(&_norflash.mutex); + return reg; +} + + +/************************************************************************************* + * 挂钩 device_api + ************************************************************************************/ + +static int norflash_dev_init(const struct dev_node *node, void *arg) +{ + struct norflash_dev_platform_data *pdata = arg; + return _norflash_init(node->name, pdata); +} + +static int norflash_dev_open(const char *name, struct device **device, void *arg) +{ + struct norflash_partition *part; + part = norflash_find_part(name); + if (!part) { + log_error("no norflash partition is found\n"); + return -ENODEV; + } + *device = &part->device; + (*device)->private_data = part; + if (atomic_read(&part->device.ref)) { + return 0; + } + return _norflash_open(arg); +} +static int norflash_dev_close(struct device *device) +{ + return _norflash_close(); +} +static int norflash_dev_read(struct device *device, void *buf, u32 len, u32 offset) +{ + int reg; + /* printf("flash read sector = %d, num = %d\n", offset, len); */ + offset = offset * 512; + len = len * 512; + struct norflash_partition *part; + part = (struct norflash_partition *)device->private_data; + if (!part) { + log_error("norflash partition invalid\n"); + return -EFAULT; + } + offset += part->start_addr; + reg = _norflash_read(offset, buf, len, 1); + if (reg) { + r_printf(">>>[r error]:\n"); + len = 0; + } + + len = len / 512; + return len; +} +static int norflash_dev_write(struct device *device, void *buf, u32 len, u32 offset) +{ + /* printf("flash write sector = %d, num = %d\n", offset, len); */ + int reg = 0; + offset = offset * 512; + len = len * 512; + struct norflash_partition *part = device->private_data; + if (!part) { + log_error("norflash partition invalid\n"); + return -EFAULT; + } + offset += part->start_addr; + reg = _norflash_write(offset, buf, len, 1); + if (reg) { + r_printf(">>>[w error]:\n"); + len = 0; + } + len = len / 512; + return len; +} +static bool norflash_dev_online(const struct dev_node *node) +{ + return 1; +} +static int norflash_dev_ioctl(struct device *device, u32 cmd, u32 arg) +{ + struct norflash_partition *part = device->private_data; + if (!part) { + log_error("norflash partition invalid\n"); + return -EFAULT; + } + return _norflash_ioctl(cmd, arg, 512, part); +} + +#if 0 //下面这组接口不再使用 +int hook_norflash_init(struct norflash_dev_platform_data *pdata) +{ + return _norflash_init("xxxx", pdata); +} + +int hook_norflash_open(void) +{ + return _norflash_open(NULL); +} + +int hook_norflash_spirec_read(u8 *buf, u32 addr, u32 len) +{ + /* return _norflash_read(addr, buf, len); */ + return _norflash_read(addr, buf, len, 0); +} + +int hook_norflash_spirec_write(u8 *buf, u32 addr, u32 len) +{ + return _norflash_write_pages(addr, buf, len); +} + +void hook_norflash_spirec_eraser(u32 addr) +{ + _norflash_eraser(FLASH_SECTOR_ERASER, addr); +} +#endif + +/* + * 1. 外部调用时以512字节为单位的地址和长度,且需要驱动write自己处理擦除, + * 请使用norflash_dev_ops接口,否则使用本文件内的其他ops + * + * 2. 如果不需要驱动自己处理擦除,可以把宏FLASH_CACHE_ENABLE清零,或者把 + * norflash_dev_read()里面调用的_norflash_read()的实参cache填0, + * norflash_dev_write()同理 + * + * 3. norflash_dev_ops可以被多个设备名注册,每个设备名被认为是不同分区,所以 + * 需要填不同的分区起始地址和大小,若分区地址有重叠或者最大分区结束地址大于 + * flash容量,会触发ASSERT() + * + * 4. 关于IOCTL_GET_CAPACITY,有多个分区注册时返回分区的大小,如果只注册了1 + * 个分区,分区起始地址 == 0时返回flash容量,起始地址 != 0时返回分区大小, + * norflash_dev_ops返回的长度以512字节为单位 + * + * 5. 本文件内的各个ops可以同时使用 + */ +const struct device_operations norflash_dev_ops = { + .init = norflash_dev_init, + .online = norflash_dev_online, + .open = norflash_dev_open, + .read = norflash_dev_read, + .write = norflash_dev_write, + .ioctl = norflash_dev_ioctl, + .close = norflash_dev_close, +}; + + +static int norfs_dev_init(const struct dev_node *node, void *arg) +{ + struct norflash_dev_platform_data *pdata = arg; + return _norflash_init(node->name, pdata); +} + +static int norfs_dev_open(const char *name, struct device **device, void *arg) +{ + struct norflash_partition *part; + part = norflash_find_part(name); + if (!part) { + log_error("no norflash partition is found\n"); + return -ENODEV; + } + *device = &part->device; + (*device)->private_data = part; + if (atomic_read(&part->device.ref)) { + return 0; + } + return _norflash_open(arg); +} +static int norfs_dev_close(struct device *device) +{ + return _norflash_close(); +} +static int norfs_dev_read(struct device *device, void *buf, u32 len, u32 offset) +{ + int reg; + /* printf("flash read sector = %d, num = %d\n", offset, len); */ + struct norflash_partition *part; + part = (struct norflash_partition *)device->private_data; + if (!part) { + log_error("norflash partition invalid\n"); + return -EFAULT; + } + offset += part->start_addr; + reg = _norflash_read(offset, buf, len, 0); + if (reg) { + r_printf(">>>[r error]:\n"); + len = 0; + } + + return len; +} +static int norfs_dev_write(struct device *device, void *buf, u32 len, u32 offset) +{ + /* printf("flash write sector = %d, num = %d\n", offset, len); */ + int reg = 0; + struct norflash_partition *part = device->private_data; + if (!part) { + log_error("norflash partition invalid\n"); + return -EFAULT; + } + offset += part->start_addr; + reg = _norflash_write(offset, buf, len, 0); + if (reg) { + r_printf(">>>[w error]:\n"); + len = 0; + } + return len; +} +static bool norfs_dev_online(const struct dev_node *node) +{ + return 1; +} +static int norfs_dev_ioctl(struct device *device, u32 cmd, u32 arg) +{ + struct norflash_partition *part = device->private_data; + if (!part) { + log_error("norflash partition invalid\n"); + return -EFAULT; + } + return _norflash_ioctl(cmd, arg, 1, part); +} + +/* + * 1. 外部调用时以1字节为单位的地址和长度,且驱动write自己不处理擦除, + * 请使用norfs_dev_ops接口,否则使用本文件内的其他ops。注意:有些文件系 + * 统需要满足这个条件的驱动,如果期望修改成驱动内部处理擦除,需要测试所 + * 有关联的文件系统是否支持,或者新建一个符合需求的ops + * + * 2. 如果需要驱动自己处理擦除,需要把宏FLASH_CACHE_ENABLE置1,且 + * norfs_dev_read()里面调用的_norflash_read()的实参cache填1, + * norfs_dev_write()同理 + * + * 3. norfs_dev_ops可以被多个设备名注册,每个设备名被认为是不同分区,所以 + * 需要填不同的分区起始地址和大小,若分区地址有重叠或者最大分区结束地址大于 + * flash容量,会触发ASSERT() + * + * 4. 关于IOCTL_GET_CAPACITY,有多个分区注册时返回分区的大小,如果只注册了1 + * 个分区,分区起始地址 == 0时返回flash容量,起始地址 != 0时返回分区大小 + * norfs_dev_ops返回的长度以1字节为单位 + * + * 5. 本文件内的各个ops可以同时使用 + */ +const struct device_operations norfs_dev_ops = { + .init = norfs_dev_init, + .online = norfs_dev_online, + .open = norfs_dev_open, + .read = norfs_dev_read, + .write = norfs_dev_write, + .ioctl = norfs_dev_ioctl, + .close = norfs_dev_close, +}; + +/* + * 对ops的读写单位有另外需求,或者驱动内部是否支持擦除,可以参照上面的ops, + * 不同条件自由组合,建立新的ops + */ + +#endif diff --git a/apps/common/fat_nor/nor_fs.c b/apps/common/fat_nor/nor_fs.c new file mode 100644 index 0000000..263ed88 --- /dev/null +++ b/apps/common/fat_nor/nor_fs.c @@ -0,0 +1,1297 @@ +/***********************************Jieli tech************************************************ + File : nor_fs.c + By : Huxi + Email: xi_hu@zh-jieli.com + date : 2016-11-30 14:30 +********************************************************************************************/ +#include "spi/nor_fs.h" +#include "os/os_api.h" +#include "asm/crc16.h" +/* #include */ +#include "stdlib.h" +#include "fs/fs.h" +/* #include "jlfat/ff_opr.h" */ +#include "system/includes.h" + + + + +#if (VFS_ENABLE == 1) +//文件头 +/* typedef struct __RECFILEHEAD { */ +/* u16 crc; */ +/* u8 head_len; */ +/* u8 reserv[5]; */ +/* u32 file_len; */ +/* u32 index; */ +/* } RECFILEHEAD, *PRECFILEHEAD __attribute__((aligned(4))); */ + + +#define RECFILEHEAD SDFILE_FILE_HEAD + +static int offset_addr = 0; +/* int max_rec_len = 0; */ + + +#define NO_DEBUG_EN + +#ifdef NO_DEBUG_EN +#undef r_printf +#undef y_printf +#define r_printf(...) +#define y_printf(...) +#endif + +u8 norfs_mutex_dis = 0; +OS_MUTEX norfs_mutex; ///<互斥信号量 +void norfs_mutex_init(void) ///<信号量初始化 +{ + if (norfs_mutex_dis) { + return; + } + static u8 init = 0; + if (init) { + return; + } + init = 1; + os_mutex_create(&norfs_mutex); +} +void norfs_mutex_enter(void) ///<申请信号量 +{ + if (norfs_mutex_dis) { + return; + } + norfs_mutex_init(); + os_mutex_pend(&norfs_mutex, 0); +} +void norfs_mutex_exit(void) ///<释放信号量 +{ + if (norfs_mutex_dis) { + return; + } + os_mutex_post(&norfs_mutex); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 提供给录音文件系统的物理读函数 + @param addr:读取的地址,字节单位。 + @param len:读取的长度,字节单位。 + @param buf:读取的目标BUFF。 + @return u16:读取的长度 + @author liujie + @note u8 recfs_read(u32 addr,u8 *buf,u16 len) +*/ +/*----------------------------------------------------------------------------*/ +u16 recfs_read(RECFILESYSTEM *pfs, u32 addr, u8 *buf, u16 len) +{ + putchar('r'); + norfs_mutex_enter(); + pfs->read(buf, addr, len); + norfs_mutex_exit(); + return len; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提供给录音文件系统的物理写函数 + @param addr:要写入设备的地址,字节单位。 + @param len:需要写入的长度,字节单位。 + @param buf:数据来源BUFF。 + @return u16:写入的长度 + @author liujie + @note u16 recfs_wirte(u32 addr,u8 *buf,u16 len) +*/ +/*----------------------------------------------------------------------------*/ +u16 recfs_wirte(RECFILESYSTEM *pfs, u32 addr, u8 *buf, u16 len) +{ + putchar('w'); + norfs_mutex_enter(); + pfs->write(buf, addr, len); + norfs_mutex_exit(); + return len; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 提供给录音文件系统的物理写函数(对齐) + @param pfs:文件系统句柄 + @param addr:要写入设备的地址,字节单位。 + @param len:需要写入的长度,字节单位。 + @param buf:数据来源BUFF。 + @return u16:写入的长度 + @author liujie + @note u16 recfs_wirte_align(RECFILESYSTEM *pfs, u32 addr,u8 *buf,u16 len) +*/ +/*----------------------------------------------------------------------------*/ +u16 recfs_wirte_align(RECFILESYSTEM *pfs, u32 addr, u8 *buf, u16 len) +{ + u32 align_addr = addr % FLASH_PAGE_SIZE; + u16 rlen = FLASH_PAGE_SIZE - align_addr; + u16 total_len = len; + u8 *tmpbuf = pfs->buf; + + if (len == 90) { + align_addr = 0; + } + + addr -= align_addr; + /* u32 addr2 = addr; */ + + if (align_addr) { + memset(tmpbuf, 0xff, FLASH_PAGE_SIZE); + if (rlen > len) { + rlen = len; + } + memcpy(tmpbuf + align_addr, buf, rlen); + putchar('C'); + recfs_wirte(pfs, addr, tmpbuf, FLASH_PAGE_SIZE); + memset(tmpbuf, 0, FLASH_PAGE_SIZE); + len -= rlen; + buf += rlen; + addr += FLASH_PAGE_SIZE; + } + + while (len >= FLASH_PAGE_SIZE) { + putchar('A'); + memset(tmpbuf, 0xff, FLASH_PAGE_SIZE); + memcpy(tmpbuf, buf, FLASH_PAGE_SIZE); + recfs_wirte(pfs, addr, tmpbuf, FLASH_PAGE_SIZE); + len -= FLASH_PAGE_SIZE; + buf += FLASH_PAGE_SIZE; + addr += FLASH_PAGE_SIZE; + } + + if (len) { + putchar('B'); + memset(tmpbuf, 0xff, FLASH_PAGE_SIZE); + memcpy(tmpbuf, buf, len); + /* recfs_wirte(pfs, addr, tmpbuf, FLASH_PAGE_SIZE); */ + /* put_buf(tmpbuf,len); */ + recfs_wirte(pfs, addr, tmpbuf, len); + } + + /* void *tmpbuf2 = malloc(512); */ + /* if (!tmpbuf2){ */ + /* r_printf(">>>[test]:no 512 cache\n"); */ + /* } */ + /* memset(tmpbuf2, 0, 512); */ + /* recfs_read(pfs, addr2, tmpbuf2, 512); */ + /* put_buf(tmpbuf2,512); */ + /* free(tmpbuf2); */ + return total_len; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提供给录音文件系统的物理擦除函数 + @param pfs:要写入设备的地址,字节单位。 + @param start_sector:需要擦除的第一个扇区。 + @param end_sector:需要擦除的最后一个扇区。 + @return u16:擦除的扇区数目 + @author liujie + @note u16 rec_erase_sector(RECFILESYSTEM *pfs,u16 start_sector,u16 end_sector) +*/ +/*----------------------------------------------------------------------------*/ +u16 rec_erase_sector(RECFILESYSTEM *pfs, u16 start_sector, u16 end_sector) +{ +// u8 sr; + + if ((start_sector < pfs->first_sector) || (start_sector > pfs->last_sector)) { + return 0 ; + } + if ((end_sector < pfs->first_sector) || (end_sector > pfs->last_sector)) { + return 0 ; + } + u16 sector_cnt = 0; + /* r_printf(">>>[test]:start_sector = %d, end_sector =%d\n", start_sector , end_sector); */ + while (1) { + + norfs_mutex_enter(); + pfs->eraser(((u32)start_sector << pfs->sector_size) + offset_addr); + norfs_mutex_exit(); + sector_cnt++; + if (start_sector == end_sector) { + break; + } + start_sector++; + if (start_sector > pfs->last_sector) { + start_sector = pfs->first_sector; + } + } + //return len;//返回擦除的sector数目 + return sector_cnt; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 录音文件seek函数 + @param pfile:文件句柄 + @param type:seek的格式 + @param offsize:seek的偏移量。 + @return u8:返回值 + @author liujie + @note u8 recf_seek (REC_FILE *pfile, u8 type, u32 offsize) +*/ +/*----------------------------------------------------------------------------*/ +u8 recf_seek(REC_FILE *pfile, u8 type, int offsize) +{ + u32 file_len; + if (NULL == pfile) { + return 0; + } + /* y_printf(">>>[test]:pfile->len = %d,type = %d, offsize = %d\n",pfile->len, type, offsize); */ + file_len = pfile->len;//(u32)pfile->index.sector << pfile->pfs->sector_size; + if (NOR_FS_SEEK_SET == type) { + if (abs(offsize) >= file_len) { + return REC_FILE_END; + } + pfile->rw_p = offsize + sizeof(RECFILEHEAD); + } else { // if(NOR_FS_SEEK_CUR == type) + offsize += pfile->rw_p; + if (offsize >= file_len) { + return REC_FILE_END; + } + pfile->rw_p += offsize; + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 录音文件读函数 + @param pfile:文件句柄 + @param buff:数据BUFF + @param btr:需要读取的数据长度,字节单位 + @return u16:读取回来的长度 + @author liujie + @note u16 recf_read(REC_FILE _xdata *pfile ,u8 _xdata *buff , u16 btr) +*/ +/*----------------------------------------------------------------------------*/ +u16 recf_read(REC_FILE *pfile, u8 *buff, u16 btr) +{ + u32 file_len, addr; + u16 read_len = btr; + u16 len, len0; + u32 max_addr, min_addr; + max_addr = offset_addr + ((u32)(pfile->pfs->last_sector + 1) << pfile->pfs->sector_size) ; + min_addr = offset_addr + ((u32)(pfile->pfs->first_sector) << pfile->pfs->sector_size) ; + file_len = (u32)pfile->len; + if ((u32)(btr + pfile->rw_p) >= file_len) { + if (pfile->rw_p >= file_len) { + return 0; + } + read_len = file_len - pfile->rw_p; + } + /* if (pfile->rw_p){ */ + /* addr = pfile->rw_p + ((u32)pfile->index.sector << pfile->pfs->sector_size) + 16; */ + /* }else */ + addr = pfile->rw_p + ((u32)pfile->index.sector << pfile->pfs->sector_size); + /* if (offset_addr){ */ + addr += offset_addr; + /* } */ + + + len0 = read_len; + /* y_printf(">>>[test]:r_addr = %d,max_addr =%d, min_addr=%d, pfile->rw_p =%d\n", addr, max_addr, min_addr, pfile->rw_p); */ + //y_printf(">>>[test]:r_len0 = %d,btr = %d, file_len = %d\n",len0, btr, file_len); + while (len0) { + if (addr >= max_addr) { + addr = addr - max_addr + min_addr; + } + if ((addr + len0) > max_addr) { + len = max_addr - addr; + } else { + len = len0; + } + /* y_printf(">>>[test]2222r_addr = %d,max_addr =%d, min_addr=%d, pfile->rw_p =%d\n",addr, max_addr, min_addr, pfile->rw_p); */ + recfs_read(pfile->pfs, addr, buff, len); + /* y_printf(">>>[test]:2222r_len0 = %d\n",len0); */ + pfile->rw_p += len; + len0 -= len; + buff += len; + addr += len; + } + return read_len; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 录音文件写函数 + @param pfile:文件句柄 + @param buff:数据BUFF + @param btr:需要写入的数据长度,字节单位 + @return u16:写入的长度 + @author liujie + @note u16 recf_write(REC_FILE *pfile,u8 *buff,u16 btw) +*/ +/*----------------------------------------------------------------------------*/ +u16 recf_write(REC_FILE *pfile, u8 *buff, u16 btw) +{ + u32 addr; + u32 max_addr, min_addr; + u16 sector; + u16 len0 = 0; + u16 len = 0;; + max_addr = offset_addr + ((u32)(pfile->pfs->last_sector + 1) << pfile->pfs->sector_size) ; + min_addr = offset_addr + ((u32)(pfile->pfs->first_sector) << pfile->pfs->sector_size) ; + addr = pfile->rw_p + ((u32)pfile->index.sector << pfile->pfs->sector_size); + /* if (offset_addr){ */ + addr += offset_addr; + /* } */ + /* y_printf(">>>[test]:addr = %d,max_addr =%d, min_addr=%d, pfile->rw_p =%d\n",addr, max_addr, min_addr, pfile->rw_p); */ + //pfile->len + while (1) { + if ((pfile->rw_p + btw) > pfile->len) { + //获取更多的空间; + sector = (pfile->len + (1L << pfile->pfs->sector_size) - 1) >> pfile->pfs->sector_size; + sector += pfile->index.sector; + if (sector > pfile->pfs->last_sector) { + sector = sector - pfile->pfs->last_sector + pfile->pfs->first_sector - 1; + } + if (pfile->index.sector != sector) { + /* r_printf(">>>[test]:goto erase\n"); */ + rec_erase_sector(pfile->pfs, sector, sector); + /* r_printf(">>>[test]:exit erase\n"); */ + pfile->len = pfile->len + (1L << pfile->pfs->sector_size); + } else { + /* y_printf(">>>[test]:not erase, sector = %d\n", sector); */ + break; + } + + } else { + break; + } + } + if ((pfile->rw_p + btw) > pfile->len) { + len = pfile->len - pfile->rw_p ; + y_printf(">>>[test]:len = %d, pfile->len = %d,pfile->rw_p =%d \n", len, pfile->len, pfile->rw_p); + } else { + len = btw; + } + len0 = len; + + while (len0) { + if (addr >= max_addr) { + addr = addr - max_addr + min_addr; + /* r_printf(">>>[test]:write the end, goto first addr write\n"); */ + } + + if ((addr + len0) > max_addr) { + btw = max_addr - addr; + } else { + btw = len0; + } + /* y_printf(">>>[test]:btw = %d\n", btw); */ + recfs_wirte_align(pfile->pfs, addr, buff, btw); + /* y_printf(">>>[test]:len0 = %d\n",len0); */ + addr += btw; + buff += btw; + len0 -= btw; + + } + + pfile->rw_p += len; + if (pfile->rw_p > pfile->w_len) { + pfile->w_len = pfile->rw_p; + } + return len; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 清除索引 + @param pfs:文件系统句柄 + @return void + @author liujie + @note void recfs_idx_clear(RECFILESYSTEM *pfs) +*/ +/*----------------------------------------------------------------------------*/ +void recfs_idx_clear(RECFILESYSTEM *pfs) +{ + RECFILEHEAD file_h; + u32 addr; + u16 curr_sector; + + curr_sector = pfs->first_sector; + memset(&file_h, 0, sizeof(RECFILEHEAD)); + + while (curr_sector <= pfs->last_sector) { + addr = (u32)curr_sector << pfs->sector_size; + /* if (offset_addr){ */ + addr += offset_addr; + /* } */ + recfs_wirte_align(pfs, addr, (u8 *)(&file_h), sizeof(RECFILEHEAD)); + + curr_sector++; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief delete a rec_file + @param pfs:文件系统句柄 + @return void + @author phew +*/ +/*----------------------------------------------------------------------------*/ +void recfs_clear_file(REC_FILE *pfile) +{ + RECFILEHEAD file_h; + u32 addr; + u16 curr_sector; + + curr_sector = pfile->index.sector; + memset(&file_h, 0, sizeof(RECFILEHEAD)); + addr = (u32)curr_sector << pfile->pfs->sector_size; + addr += offset_addr; + recfs_wirte_align(pfile->pfs, addr, (u8 *)(&file_h), sizeof(RECFILEHEAD)); + +} + +/*----------------------------------------------------------------------------*/ +/**@brief 扫描文件系统 + @param pfs:文件系统句柄 + @return u32:总文件数 + @author liujie + @note u32 recfs_scan(RECFILESYSTEM *pfs) +*/ +/*----------------------------------------------------------------------------*/ +/*扫描出最少的文件*/ +u32 recfs_scan(RECFILESYSTEM *pfs) +{ + RECFILEHEAD file_h __attribute__((aligned(4))); + RECF_INDEX_INFO max_index; + //RECF_INDEX_INFO min_index; + u32 addr; + u32 total_len; + u16 crc; + u16 file_cnt = 0; + u16 curr_sector = pfs->first_sector; + pfs->total_file = 0; + max_index.index = 0; + max_index.sector = pfs->first_sector; + total_len = (u32)((u32)pfs->last_sector + 1 - (u32)pfs->first_sector) << pfs->sector_size; + while (1) { + addr = (u32)curr_sector << pfs->sector_size; + /* if (offset_addr){ */ + addr += offset_addr; + /* } */ + /* r_printf(">>>[test]:addr=0x%x\n", addr); */ + recfs_read(pfs, addr, (u8 *)(&file_h), sizeof(RECFILEHEAD)); + /* put_buf(&file_h , 16); */ + crc = CRC16(&file_h.data_crc, sizeof(RECFILEHEAD) - 2); + /* y_printf(">>>[test]:crc = 0x%x, file_h.len = %d, file_h.index = %d\n", crc, file_h.len, file_h.index); */ + if ((0 != crc) && (crc == file_h.head_crc) && (file_h.len <= total_len)) { + if (file_h.index >= max_index.index) { + max_index.index = file_h.index; + max_index.sector = curr_sector; + } + + /* + if(file_h.index <= pfs->index.index) + { + min_index.index = file_h.index; + min_index.sector = curr_sector; + } + */ + r_printf(">>>[test]:addr=%d\n", addr); + file_cnt++; + if (0 != file_h.len) { + curr_sector += file_h.len >> pfs->sector_size; + if (file_h.len % (1L << pfs->sector_size)) { + curr_sector++; + } + } else { + curr_sector++; + } + + } else { + curr_sector++; + } + if (curr_sector > pfs->last_sector) { + //curr_sector = pfs->first_sector; + break; + } + } + + if (max_index.index < 0) { + //清空整个MEM() + y_printf(">>>[test]:goto clear index.sector\n"); + recfs_idx_clear(pfs); + pfs->total_file = 0; + pfs->index.index = 0; + pfs->index.sector = pfs->first_sector; + } else { + pfs->index.index = max_index.index; + pfs->index.sector = max_index.sector; + /* y_printf(">>>[test]:recfs_scan pfs->index.sector = %d, pfs->index.index = %d\n", pfs->index.sector, pfs->index.index); */ + pfs->total_file = file_cnt; + /* y_printf(">>>[test]:recfs_scan file_cnt = %d\n", file_cnt); */ + } + + return file_cnt; +} +/*----------------------------------------------------------------------------*/ +/**@brief 检查指定扇区是否存爱文件 + @param pfs:文件系统的句柄 + @param pfile_h:文件头指针 + @param sector:需要分析的扇区 + @return u16:下一个有效扇区 + @author liujie + @note u16 check_head(RECFILESYSTEM *pfs,RECFILEHEAD *pfile_h,u16 sector) +*/ +/*----------------------------------------------------------------------------*/ +u16 check_head(RECFILESYSTEM *pfs, RECFILEHEAD *pfile_h, u16 sector) +{ + //RECFILEHEAD file_h; + u32 addr; + u32 total_len; + addr = sector; + addr = addr << pfs->sector_size; + /* if (offset_addr){ */ + addr += offset_addr; + /* } */ + + total_len = (u32)((u32)pfs->last_sector + 1 - (u32)pfs->first_sector) << pfs->sector_size; + y_printf(">>>[test]: check head addr = %d\n", addr); + recfs_read(pfs, addr, (u8 *)pfile_h, sizeof(RECFILEHEAD)); + if ((CRC16(&pfile_h->data_crc, sizeof(RECFILEHEAD) - 2) == pfile_h->head_crc) + && (pfile_h->len <= total_len) + ) { + r_printf(">>>[test]:AAAAAAAAAAA\n"); + sector = sector + (pfile_h->len >> pfs->sector_size); + r_printf(">>>[test]:sector = %d\n", sector); + if (pfile_h->len % (1L << pfs->sector_size)) { + r_printf(">>>[test]:BBBBBBBBBBB\n"); + sector++; + } else { + } + /* + if(sector > pfs->last_sector) + { + sector -= pfs->last_sector; + } + */ + } else { + } + return sector; +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief 建立一个文件 + @param pfs:文件系统的句柄 + @param pfile:文件的句柄 + @return u32:建立文件索引 + @author liujie + @note u32 create_recfile(RECFILESYSTEM *pfs,REC_FILE *pfile) +*/ +/*----------------------------------------------------------------------------*/ +u32 create_recfile(RECFILESYSTEM *pfs, REC_FILE *pfile) +{ + RECFILEHEAD file_h; + u16 sector, sec0; + u16 sec_len; + + memset((u8 *)pfile, 0, sizeof(REC_FILE)); + pfile->pfs = pfs; + sector = pfs->index.sector; + /* y_printf(">>>[test]:create pfs->index.sector = %d\n", pfs->index.sector); */ + sec0 = check_head(pfs, &file_h, sector); + if (sector != sec0) { + if (sec0 > pfs->last_sector) { + sec0 = sec0 - pfs->last_sector + pfs->first_sector - 1; + } + sector = sec0; + } + pfile->index.index = pfs->index.index + 1; + pfile->index.sector = sec0; + sec_len = rec_erase_sector(pfs, sector, sec0); + /* y_printf(">>>[test]:sec_len = %d\n",sec_len); */ + pfile->len = (u32)sec_len << pfs->sector_size; + pfile->w_len = sizeof(RECFILEHEAD); + pfile->rw_p = sizeof(RECFILEHEAD); + pfile->addr = pfile->rw_p + (pfile->index.sector << pfile->pfs->sector_size) + offset_addr; + /* y_printf(">>>[test]:rw_p = %d\n", pfile->rw_p); */ + return pfile->index.index; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭一个文件 + @param pfile:文件的句柄 + @return u32:建立文件索引 + @author liujie + @note u32 close_recfile(REC_FILE *pfile) +*/ +/*----------------------------------------------------------------------------*/ +u32 close_recfile(REC_FILE *pfile) +{ + RECFILEHEAD file_h; + + memset(&file_h, 0xff, sizeof(RECFILEHEAD)); + //file_h->crc; + pfile->w_len = pfile->rw_p; + + pfile->len = pfile->w_len; + pfile->rw_p = 0;//sizeof(RECFILEHEAD); + file_h.len = pfile->w_len; + file_h.index = pfile->index.index; + file_h.addr = pfile->addr; + memcpy(file_h.name, pfile->priv_data, NORFS_DATA_LEN); + r_printf(">>>[test]:file_h.priv_data = %s, len = %d\n", file_h.name, NORFS_DATA_LEN); + + file_h.head_crc = CRC16(&file_h.data_crc, sizeof(RECFILEHEAD) - 2); + r_printf(">>>[test]:pfile->index.sector = %d\n", pfile->index.sector); + /* recf_seek(pfile, NOR_FS_SEEK_SET, 0); */ + /* recf_seek(pfile, NOR_FS_SEEK_SET, 90); */ + + //memset(&file_h,0,sizeof(RECFILEHEAD)); + //recfs_read((u32)pfile->index.sector<pfs->sector_size,(u8 *)&file_h,sizeof(RECFILEHEAD)); + + recf_write(pfile, (u8 *)&file_h, sizeof(RECFILEHEAD)); + /* put_buf(&file_h , 32); */ + pfile->pfs->index.index = pfile->index.index; + pfile->pfs->index.sector = pfile->index.sector; + + //memset(&file_h,0,sizeof(RECFILEHEAD)); + //recfs_read((u32)pfile->index.sector<pfs->sector_size,(u8 *)&file_h,sizeof(RECFILEHEAD)); + + /* r_printf(">>>[test]:file_h.len = %d\n", file_h.len); */ + return file_h.len; +} + +void recf_save_sr(REC_FILE *pfile, u16 sr) +{ + if (pfile) { + pfile->sr = sr; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按照索引号,搜索一个文件 + @param index:索引号 + @param pfile:文件的句柄 + @return u32:找到文件的索引 + @author liujie + @note u32 revf_index_scan(u32 index,REC_FILE *pfile) +*/ +/*----------------------------------------------------------------------------*/ +u32 revf_index_scan(u32 index, REC_FILE *pfile) +{ + RECFILEHEAD file_h; + RECFILESYSTEM *pfs; + u32 addr; + u32 total_len; + u16 curr_sector, crc; + + pfs = pfile->pfs; + curr_sector = pfs->index.sector; + total_len = (u32)((u32)pfs->last_sector + 1 - (u32)pfs->first_sector) << pfs->sector_size; + /* r_printf(">>>[test]:pfile->pfs->index.sector = %d, total_len = %d\n", pfile->pfs->index.sector, total_len); */ + + while (1) { + addr = (u32)curr_sector << pfs->sector_size; + /* if (offset_addr){ */ + addr += offset_addr; + /* r_printf(">>>[test]:offset_addr = 0x%x, addr = 0x%x\n", offset_addr, addr); */ + /* } */ + + recfs_read(pfs, addr, (u8 *)(&file_h), sizeof(RECFILEHEAD)); + /* put_buf(&file_h , 32); */ + crc = CRC16(&file_h.data_crc, sizeof(RECFILEHEAD) - 2); + /* y_printf(">>>[test]:crc = 0x%x, file_h.len = %d, file_h.index = %d\n", crc, file_h.len, file_h.index); */ + if ((0 != crc) && (crc == file_h.head_crc) && (file_h.len <= total_len)) { + if (file_h.index == index) { + r_printf(">>>[test]:go in AAAAAA\n"); + pfile->index.index = index; + pfile->index.sector = curr_sector; + pfile->len = file_h.len; + pfile->w_len = file_h.len; + pfile->rw_p = sizeof(RECFILEHEAD); + pfile->addr = file_h.addr; + /* pfile->sr = (u16)(((u16)file_h.reserv[1] << 8) | file_h.reserv[0]);//利用了保留区 */ + memcpy(pfile->priv_data, file_h.name, NORFS_DATA_LEN); + return index; + } else { + if (0 == file_h.len) { + curr_sector++; + } + curr_sector = curr_sector + (file_h.len >> pfs->sector_size); + if (file_h.len % (1L << pfs->sector_size)) { + curr_sector++; + } + } + } else { + curr_sector++; + } + + if (curr_sector > pfs->last_sector) { + curr_sector = pfs->first_sector; + } + /* r_printf(">>>[test]:pfile->index.sector = %d, curr_sector = %d\n", pfile->index.sector, curr_sector); */ + if (pfs->index.sector == curr_sector) { + break; + } + + } + return index - 1; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按照索引号打开一个文件 + @param index:索引号 + @param pfs:文件系统的句柄 + @param pfile:文件的句柄 + @return u32:找到文件的索引 + @author liujie + @note u32 open_recfile(u32 index,RECFILESYSTEM *pfs,REC_FILE *pfile) +*/ +/*----------------------------------------------------------------------------*/ +u32 open_recfile(u32 index, RECFILESYSTEM *pfs, REC_FILE *pfile) +{ + memset((u8 *)pfile, 0, sizeof(REC_FILE)); + pfile->pfs = pfs; + pfile->rw_p = sizeof(RECFILEHEAD); + return revf_index_scan(index, pfile); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 初始化文件系统信息 + @param pfs:文件系统的句柄 + @param sector_start:起始扇区 + @param sector_end:结束扇区 + @param sector_size:扇区大小(1L<first_sector = sector_start; + pfs->last_sector = sector_end; + pfs->sector_size = sector_size; +} + + +RECFILESYSTEM recfs; +REC_FILE recfile; +#if 1 +/* NOR_FS_HDL *nor_fs_hdl; */ +static int nor_fs_index = 0; +int max_rec_capacity = 256 * 1024; +int nor_fs_set_rec_capacity(int capacity) //需要先设置容量。 +{ + /* ASSERT(capacity <= max_rec_len , "capacity must smaller than max_rec_len!!!!!!! "); */ + max_rec_capacity = capacity; + return max_rec_capacity; +} +#define NOR_FS_SECTOR_S (4*1024L) +#define NOR_FS_S_SECTOR (1) +#define NOR_FS_E_SECTOR (max_rec_capacity/NOR_FS_SECTOR_S-1) + +static void *fd; +#if 0 +extern int hook_norflash_open(void); +extern int hook_norflash_spirec_read(u8 *buf, u32 addr, u32 len); +extern int hook_norflash_spirec_write(u8 *buf, u32 addr, u32 len); +extern void hook_norflash_spirec_eraser(u32 addr); +#endif +#if 1 +/* static int hook_norflash_open(void) */ +/* { */ +/* fd = dev_open("norfs_rec", NULL); */ +/* if (fd == NULL) { */ +/* log_e("error!!!!!!,fd == NULL"); */ +/* return false; */ +/* } */ +/* return true; */ +/* } */ +static int hook_norflash_spirec_read(u8 *buf, u32 addr, u32 len) +{ + return dev_bulk_read(fd, buf, addr, len); +} + +static int hook_norflash_spirec_write(u8 *buf, u32 addr, u32 len) +{ + return dev_bulk_write(fd, buf, addr, len); +} + +static void hook_norflash_spirec_eraser(u32 addr) +{ + dev_ioctl(fd, IOCTL_ERASE_SECTOR, addr); +} + +static int hook_norflash_get_capacity(void) +{ + int capacity; + dev_ioctl(fd, IOCTL_GET_CAPACITY, (u32)&capacity); + return capacity; +} +#endif + + +static u32 init_recfs(void) +{ + memset(&recfs, 0, sizeof(RECFILESYSTEM)); + recfs.eraser = hook_norflash_spirec_eraser; + recfs.read = hook_norflash_spirec_read; + recfs.write = hook_norflash_spirec_write; + + return true; +} + +/* u16 tmp_buf2[512]; ///test buff */ +__BANK_INIT +u32 nor_fs_init(void) +{ + init_recfs(); + /* u16 i = 0; */ + /* memset(tmp_buf2, 0, 256); */ + /* for (i = 0; i< 512; i++) */ + /* { */ + /* tmp_buf2[i] = i; */ + /* } */ + /* put_buf(tmp_buf2, 64); */ + init_nor_fs(&recfs, NOR_FS_S_SECTOR, NOR_FS_E_SECTOR, 12); + recfs_scan(&recfs); + y_printf(">>>[test]:nor_fs_init\n"); + nor_fs_index = recfs.index.index; + return recfs.index.index; +} + +void nor_rec_get_priv_info(u8 *info) +{ + memcpy(info, &recfile.priv_data, 16); +} + +void nor_rec_set_priv_info(u8 *info) //用于设置数据格式和电话信息. +{ + memcpy(&recfile.priv_data, info, 16); +} + +u16 nor_rec_get_sr(void) +{ + return recfile.sr; +} + +void nor_rec_set_sr(u16 sr) +{ + recfile.sr = sr; +} + +int recfs_scan_ex() +{ + recfs_scan(&recfs); + return recfs.index.index; +} + + +void clear_norfs_fileindex(void) +{ + recfs_idx_clear(&recfs); +} + +u32 delete_rec_file(u32 index) +{ + int num; + num = open_recfile(index, &recfs, &recfile); + if (num != index) { + log_e("open error"); + return -1; + } + recfs_clear_file(&recfile); + return 0; +} + +u32 nor_get_absolute_addr(void) +{ + return recfile.addr; +} + +u32 nor_get_start_addr(void) +{ + return offset_addr; +} + +u32 nor_get_capacity(void) +{ + return max_rec_capacity; +} + +u32 nor_get_index(void) +{ + return nor_fs_index; +} + +int nor_set_offset_addr(int offset) +{ + offset_addr = offset; + return offset_addr; +} + +static int get_ext_name(char *path, char *ext) +{ + int len = strlen(path); + char *name = (char *)path; + while (len--) { + if (*name++ == '.') { + break; + } + } + if (len <= 0) { + name = path + (strlen(path) - 3); + } + memcpy(ext, name, 3); + ext[3] = 0; + return 1; +} + +static int get_filename_by_path(char *filename, char *path) +{ + int len = strlen(path); + char *name = (char *)path; + name = path + len; + for (int i = len; i >= 0; i--) { + if (*name-- == '/') { + break; + } + if ((len - i) > 15) { + r_printf(">>>[test]:i= %d,len = %d\n", i, len); + log_w("filename is too long!!!!!!!!"); + break; + } + } + + memcpy(filename, name + 2, 15); + filename[15] = 0; + return 1; + +} +static int first_flag = 1; +static int nor_fs_open(FILE *_file, const char *path, const char *mode) +{ + int index; + int reg; + /* _file->private_data = nor_fs_hdl; */ + /* REC_FILE *recfile = recfile; */ + /* RECFILESYSTEM *recfs = recfs; */ + y_printf(">>>[test]:nor_fs_open\n"); + + if (mode[0] == 'w') { + y_printf(">>>[test]:goto create\n"); + char ext[4] = {0}; + char filename[16] = {0}; + get_ext_name((char *)path, (char *)ext); + if (memcmp(ext, "WAV", 3) == 0 || memcmp(ext, "wav", 3) == 0) { + first_flag = 1; + } else { + first_flag = 0; + } + + index = create_recfile(&recfs, &recfile); + get_filename_by_path((char *)filename, (char *) path); + nor_rec_set_priv_info((u8 *)filename); + r_printf(">>>[test]:path = %s, ext = %s, filename = %s\n", path, ext, filename); + + nor_fs_index = index; + y_printf(">>>[test]: create_recfile nor_fs_hdl->index= %d\n", nor_fs_index); + return 0; + } else if (mode[0] == 'r') { + y_printf(">>>[test]: open_recfile nor_fs_hdl->index= %d\n", nor_fs_index); + if (nor_fs_index) { + index = nor_fs_index; + } else { + log_e("error!!!!!!!!!"); + index = 0; + return 1; + } + reg = open_recfile(index, &recfs, &recfile); + return 0; + } + return 0; +} + +int music_flash_file_set_index(u8 file_sel, u32 index) +{ + y_printf(">>>[test]:goto flash_file_play_set_index\n"); + recfs_scan(&recfs); + switch (file_sel) { + case FSEL_NEXT_FILE: + r_printf(">>>[test]:flash FSEL_NEXT_FILE\n"); + nor_fs_index++; + if (nor_fs_index > recfs.index.index) { + log_w("play on the end, goto first play!!!!!!!!!"); + nor_fs_index = 1; + /* music_flash_file_set_index(FSEL_CURR_FILE, 1); */ + } + break; + case FSEL_PREV_FILE: + r_printf(">>>[test]:flash FSEL_PREV_FILE\n"); + nor_fs_index--; + if (nor_fs_index <= 0) { + log_e("index <= 0 err!!!, play first"); + nor_fs_index = 1; + /* music_flash_file_set_index(FSEL_CURR_FILE, 1); */ + } + break; + case FSEL_CURR_FILE: + r_printf(">>>[test]:flash FSEL_CURR_FILE\n"); + if (index <= (recfs.index.index - recfs.total_file)) { + nor_fs_index = (recfs.index.index - recfs.total_file) + 1; + } else if (index && (index <= recfs.index.index)) { + nor_fs_index = index; + } else { + log_e("error!!!!!!! no file"); + return 1; + } + break; + } + if (nor_fs_index <= (recfs.index.index - recfs.total_file)) { + nor_fs_index = (recfs.index.index - recfs.total_file) + 1; + } + return 0; +} + +static int nor_fs_write(FILE *_file, void *buff, u32 len) +{ + u16 w_len; + /* REC_FILE *recfile = nor_fs_hdl->recfile; */ + /* r_printf(">>>[test]:goto nor_fs write\n"); */ + /* if (len != 90){ */ + /* void *tmp_buf = malloc(512); */ + /* memset(tmp_buf, 0xff, 512); */ + /* memcpy(tmp_buf, tmp_buf2, 512); */ + /* #<{(| memcpy(tmp_buf, buff, len); |)}># */ + /* w_len = recf_write(&recfile, tmp_buf, len); */ + /* put_buf(tmp_buf, len); */ + /* free(tmp_buf); */ + /* return w_len; */ + /* } */ + /* r_printf(">>>[test]:goto nor_fs write\n"); */ + if (first_flag == 1) { + memset(buff, 0xff, 90); + first_flag = 0; + } + w_len = recf_write(&recfile, buff, len); + /* put_buf(buff, 32); */ + return w_len; +} + +static int nor_fs_read(FILE *_file, void *buff, u32 len) +{ + u16 r_len; + + + /* r_printf(">>>[test]:goto nor_fs read\n"); */ + if (((u32)buff % 4) != 0) { + void *tmp_buf = malloc(512); + r_len = recf_read(&recfile, tmp_buf, len); + memcpy(buff, tmp_buf, len); + free(tmp_buf); + /* put_buf(buff, 32); */ + return r_len; + } + r_len = recf_read(&recfile, buff, len); + /* put_buf(buff, 32); */ + return r_len; +} + +static int nor_fs_close(FILE *_file) +{ + int reg; + r_printf(">>>[test]:goto nor_fs close\n"); + reg = close_recfile(&recfile); + return reg; +} + +static int nor_fs_seek(FILE *_file, int offsize, int type) +{ + int reg; + /* y_printf(">>>[test]:goto nor_fs seek\n"); */ + reg = recf_seek(&recfile, (u8) type, offsize); + return reg; +} + +static int nor_fs_mount(struct imount *mt, int cache_num) +{ + y_printf("\n >>>[test]:func = %s,line= %d\n", __FUNCTION__, __LINE__); + struct vfs_partition *app_part = &mt->part; + fd = mt->dev.fd; + /* hook_norflash_open(); */ + max_rec_capacity = hook_norflash_get_capacity(); + r_printf(">>>[test]:capacity = 0x%x , offset = %d\n", max_rec_capacity, offset_addr); + nor_fs_init(); + + app_part->offset = 0 + offset_addr; + app_part->dir[0] = 'C'; + app_part->dir[1] = '\0'; + + mt->part_num = 1; + + return 0; + +} + +static int nor_fs_flen(FILE *_file) +{ + RECFILEHEAD file_h; + y_printf(">>>[test]:goto nor_fs_flen\n"); + r_printf(">>>[test]:pfile->len = %d\n", recfile.len); + return recfile.len; +} + +static int nor_fs_fpos(FILE *_file) +{ + RECFILEHEAD file_h; + /* y_printf(">>>[test]:goto nor_fs_fpos\n"); */ + /* r_printf(">>>[test]:pfile->fpos(rw_p) = %d\n", recfile.rw_p); */ + return recfile.rw_p; +} + +REGISTER_VFS_OPERATIONS(nor_fs_vfs_ops) = { + .fs_type = "nor_fs", + .mount = nor_fs_mount, + .unmount = NULL, + .format = NULL, + .fopen = nor_fs_open, + .fwrite = nor_fs_write, + .fread = nor_fs_read, + .fseek = nor_fs_seek, + .flen = nor_fs_flen, + .fpos = nor_fs_fpos, + .fclose = nor_fs_close, + .fscan = NULL, + .fscan_release = NULL, + .fsel = NULL, + .fdelete = NULL, + .fget_name = NULL, + .frename = NULL, + .fget_free_space = NULL, + .fget_attr = NULL, + .fset_attr = NULL, + .fget_attrs = NULL, + .fset_vol = NULL, + .fmove = NULL, + .ioctl = NULL, +}; + +int nor_fs_ops_init(void) +{ + return 0; +} + +#endif +#endif + + +#if 0 +/* RECFILESYSTEM recfs; */ +/* REC_FILE recfile; */ +/* extern const struct norflash_dev_platform_data *norflash_dev_data; */ +/* #define NOR_FS_SECTOR_S (4*1024L) */ +/* #define NOR_FS_S_SECTOR (1) */ +/* #define NOR_FS_E_SECTOR (255) //(1*1024L*1024L/NOR_FS_SECTOR_S-1) */ + +/* extern int _norflash_init(struct norflash_dev_platform_data *pdata); */ +/* extern int hook_norflash_open(void); */ +/* extern int hook_norflash_spirec_read(u8 *buf, u32 addr, u32 len); */ +/* extern int hook_norflash_spirec_write(u8 *buf, u32 addr, u32 len); */ +/* extern void hook_norflash_spirec_eraser(u32 addr); */ +/* static u32 init_recfs(void) */ +/* { */ +/* memset(&recfs, 0, sizeof(RECFILESYSTEM)); */ +/* recfs.eraser = hook_norflash_spirec_eraser; */ +/* recfs.read = hook_norflash_spirec_read; */ +/* recfs.write = hook_norflash_spirec_write; */ +/* */ +/* #<{(| init_nor_fs(&recfs, NOR_FS_S_SECTOR, NOR_FS_E_SECTOR, 12); |)}># */ +/* #<{(| recfs_scan(&recfs); |)}># */ +/* #<{(| return recfs.index.index; |)}># */ +/* _norflash_init(&norflash_dev_data); */ +/* return true; */ +/* } */ + +#define N 512 +#define M 512 +u8 test_buff[N]; +void test_nor_fs(void) +{ + u16 i; + u32 index; + u32 filenum; + r_printf(">>>[test]:gogogogoogogoogo\n"); + /* filenum = init_recfs(); */ + /* hook_norflash_open(); */ + /* r_printf(">>>[test]:index=filenum is ok? = %d\n", filenum); */ + /* init_nor_fs(&recfs, NOR_FS_S_SECTOR, NOR_FS_E_SECTOR, 12); */ + /* r_printf("recfs_scan\n"); */ + /* recfs_scan(&recfs); */ + r_printf("recfs.index.sector= %d\n", recfs.index.sector); + r_printf("pfs.index.sector\n"); + r_printf("create_recfile\n"); + + index = create_recfile(&recfs, &recfile); + + + r_printf("index = %d\n", index); + r_printf("index\n"); + r_printf("recfs.index.sector = %d\n", recfs.index.sector); + r_printf("recfile.index.sector = %d\n", recfile.index.sector); + r_printf("pfs.index.sector\n"); + /* for (i = 0; i < N; i++) { */ + /* test_buff[i] = i; */ + /* } */ + + void *test_buf = malloc(N); + for (i = 1; i < 20; i++) { + /* for (int j=0; j< N; j++) */ + /* { */ + /* test_buf[j] = i; */ + /* #<{(| test_buf += j; |)}># */ + /* #<{(| test_buf = &i; |)}># */ + /* } */ + memset(test_buf, i, N); + y_printf(">>>[test]:test_buf_len = %d\n", strlen(test_buf)); + recf_write(&recfile, test_buf, N); + } + y_printf("recf_write\n"); + /* recf_write(&recfile, test_buff, N); */ + + /* y_printf(">>>[test]:1111recf_read\n"); */ + /* recf_read(&recfile, test_buff, N); */ + /* put_buf(test_buff, N); */ + + y_printf("close_recfile\n"); + close_recfile(&recfile); + + + y_printf("recfile.len = %d\n", recfile.len); + y_printf("recfile.index.index =%d\n", recfile.index.index); + y_printf("recfile.index.sector = %d\n", recfile.index.sector); + y_printf("recfs.index.sector = %d\n", recfs.index.sector); + /* y_printf("pfs.index.sector\n"); */ + + index = open_recfile(index, &recfs, &recfile); + /* memset(test_buff, 0, sizeof(test_buff)); */ + r_printf(">>>[test]:recf_read\n"); + + void *test_buf2 = malloc(M); + for (i = 1; i < 20; i++) { + memset(test_buf, 0x0, N); + memset(test_buf2, 0x0, M); + recf_read(&recfile, test_buf2, M); + put_buf(test_buf2, M); + printf("\n\n"); + } + /* recf_read(&recfile, test_buff, N); */ + /* put_buf(test_buff, N); */ + free(test_buf); + free(test_buf2); + + while (1) { + wdt_clear(); + }; +} + +#endif + diff --git a/apps/common/fat_nor/phone_rec_fs.c b/apps/common/fat_nor/phone_rec_fs.c new file mode 100644 index 0000000..e634376 --- /dev/null +++ b/apps/common/fat_nor/phone_rec_fs.c @@ -0,0 +1,1264 @@ +/***********************************Jieli tech************************************************ + File : phone_rec_fs.c + By : phewlee + Email: lifuyong@zh-jieli.com + date : 2020-6-4 +********************************************************************************************/ +#include "spi/nor_fs.h" +#include "os/os_api.h" +#include "asm/crc16.h" +/* #include */ +#include "stdlib.h" +#include "fs/fs.h" +/* #include "jlfat/ff_opr.h" */ +#include "system/includes.h" +#include "fs/sdfile.h" +#include "boot.h" + + +//文件头 +/* typedef struct __PHONE_RECFILEHEAD { */ +/* u16 crc; */ +/* u8 head_len; */ +/* u8 reserv[5]; */ +/* u8 priv_data[16]; */ +/* u32 file_len; */ +/* u32 index; */ +/* } PHONE_RECFILEHEAD, *PPHONE_RECFILEHEAD __attribute__((aligned(4))); */ + +#define PHONE_RECFILEHEAD SDFILE_FILE_HEAD + +int phone_offset_addr = 0; +int max_rec_len = 0; +static int sdfile_rec_index = 0; + + + +#define NO_DEBUG_EN + +#ifdef NO_DEBUG_EN +#undef r_printf +#undef y_printf +#define r_printf(...) +#define y_printf(...) +#endif + +typedef struct U16BIT_IN_PHONEFS { + u8 b0 : 1; + u8 b1 : 1; + u8 b2 : 1; + u8 b3 : 1; + u8 b4 : 1; + u8 b5 : 1; + u8 b6 : 1; + u8 b7 : 1; + u8 b8 : 1; + u8 b9 : 1; + u8 b10 : 1; + u8 b11 : 1; + u8 b12 : 1; + u8 b13 : 1; + u8 b14 : 1; + u8 b15 : 1; +} U16BIT_IN_PHONEFS; + +typedef union UBIT16_IN_PHONEFS { + U16BIT_IN_PHONEFS bits; + u16 val; +} UBIT16_IN_PHONEFS; + +static UBIT16_IN_PHONEFS cd_phone; + +static u16 do16_in_phonefs(void) +{ + UBIT16_IN_PHONEFS ufcc, urp; + u8 f_xdat; + u8 f_datin; + ufcc.bits = urp.bits = cd_phone.bits; + f_datin = 0x10; + f_xdat = f_datin ^ urp.bits.b15; + + ufcc.val = urp.val << 1; + ufcc.bits.b12 = urp.bits.b11 ^ f_xdat; + ufcc.bits.b5 = urp.bits.b4 ^ f_xdat; + ufcc.bits.b0 = f_xdat; + + urp.bits = ufcc.bits; + cd_phone.bits = ufcc.bits; + return ufcc.val & 0x00ff; +} + +static void doe_in_phonefs(u16 k, void *pBuf, u32 lenIn, u32 addr) +{ + u8 *p = (u8 *)pBuf; + + if (addr) { + k = (addr >> 2) ^ k; + } + cd_phone.val = k; + *p++ ^= k; + while (--lenIn) { + *p++ ^= do16_in_phonefs(); + } +} + + + +u8 phonefs_mutex_dis = 0; +OS_MUTEX phonefs_mutex; ///<互斥信号量 +void phonefs_mutex_init(void) ///<信号量初始化 +{ + if (phonefs_mutex_dis) { + return; + } + static u8 init = 0; + if (init) { + return; + } + init = 1; + os_mutex_create(&phonefs_mutex); +} +void phonefs_mutex_enter(void) ///<申请信号量 +{ + if (phonefs_mutex_dis) { + return; + } + phonefs_mutex_init(); + os_mutex_pend(&phonefs_mutex, 0); +} +void phonefs_mutex_exit(void) ///<释放信号量 +{ + if (phonefs_mutex_dis) { + return; + } + os_mutex_post(&phonefs_mutex); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 提供给录音文件系统的物理读函数 + @param addr:读取的地址,字节单位。 + @param len:读取的长度,字节单位。 + @param buf:读取的目标BUFF。 + @return u16:读取的长度 + @author liujie + @note u8 phone_recfs_read(u32 addr,u8 *buf,u16 len) +*/ +/*----------------------------------------------------------------------------*/ +u16 phone_recfs_read(RECFILESYSTEM *pfs, u32 addr, u8 *buf, u16 len) +{ + putchar('r'); + phonefs_mutex_enter(); + pfs->read(buf, addr, len); + phonefs_mutex_exit(); + return len; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提供给录音文件系统的物理写函数 + @param addr:要写入设备的地址,字节单位。 + @param len:需要写入的长度,字节单位。 + @param buf:数据来源BUFF。 + @return u16:写入的长度 + @author liujie + @note u16 phone_recfs_wirte(u32 addr,u8 *buf,u16 len) +*/ +/*----------------------------------------------------------------------------*/ +u16 phone_recfs_wirte(RECFILESYSTEM *pfs, u32 addr, u8 *buf, u16 len) +{ + putchar('w'); + phonefs_mutex_enter(); + pfs->write(buf, addr, len); + phonefs_mutex_exit(); + return len; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 提供给录音文件系统的物理写函数(对齐) + @param pfs:文件系统句柄 + @param addr:要写入设备的地址,字节单位。 + @param len:需要写入的长度,字节单位。 + @param buf:数据来源BUFF。 + @return u16:写入的长度 + @author liujie + @note u16 phone_recfs_wirte_align(RECFILESYSTEM *pfs, u32 addr,u8 *buf,u16 len) +*/ +/*----------------------------------------------------------------------------*/ +u16 phone_recfs_wirte_align(RECFILESYSTEM *pfs, u32 addr, u8 *buf, u16 len) +{ + u32 align_addr = addr % FLASH_PAGE_SIZE; + u16 rlen = FLASH_PAGE_SIZE - align_addr; + u16 total_len = len; + u8 *tmpbuf = pfs->buf; + + if (len == 90) { + align_addr = 0; + } + + addr -= align_addr; + /* u32 addr2 = addr; */ + + if (align_addr) { + memset(tmpbuf, 0xff, FLASH_PAGE_SIZE); + if (rlen > len) { + rlen = len; + } + memcpy(tmpbuf + align_addr, buf, rlen); + putchar('C'); + phone_recfs_wirte(pfs, addr, tmpbuf, FLASH_PAGE_SIZE); + memset(tmpbuf, 0, FLASH_PAGE_SIZE); + len -= rlen; + buf += rlen; + addr += FLASH_PAGE_SIZE; + } + + while (len >= FLASH_PAGE_SIZE) { + putchar('A'); + memset(tmpbuf, 0xff, FLASH_PAGE_SIZE); + memcpy(tmpbuf, buf, FLASH_PAGE_SIZE); + phone_recfs_wirte(pfs, addr, tmpbuf, FLASH_PAGE_SIZE); + len -= FLASH_PAGE_SIZE; + buf += FLASH_PAGE_SIZE; + addr += FLASH_PAGE_SIZE; + } + + if (len) { + putchar('B'); + memset(tmpbuf, 0xff, FLASH_PAGE_SIZE); + memcpy(tmpbuf, buf, len); + /* phone_recfs_wirte(pfs, addr, tmpbuf, FLASH_PAGE_SIZE); */ + /* put_buf(tmpbuf,len); */ + phone_recfs_wirte(pfs, addr, tmpbuf, len); + } + + return total_len; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提供给录音文件系统的物理擦除函数 + @param pfs:要写入设备的地址,字节单位。 + @param start_sector:需要擦除的第一个扇区。 + @param end_sector:需要擦除的最后一个扇区。 + @return u16:擦除的扇区数目 + @author liujie + @note u16 phone_rec_erase_sector(RECFILESYSTEM *pfs,u16 start_sector,u16 end_sector) +*/ +/*----------------------------------------------------------------------------*/ +u16 phone_rec_erase_sector(RECFILESYSTEM *pfs, u16 start_sector, u16 end_sector) +{ +// u8 sr; + + if ((start_sector < pfs->first_sector) || (start_sector > pfs->last_sector)) { + return 0 ; + } + if ((end_sector < pfs->first_sector) || (end_sector > pfs->last_sector)) { + return 0 ; + } + u16 sector_cnt = 0; + /* r_printf(">>>[test]:start_sector = %d, end_sector =%d\n", start_sector , end_sector); */ + while (1) { + + phonefs_mutex_enter(); + pfs->eraser(((u32)start_sector << pfs->sector_size) + phone_offset_addr); + phonefs_mutex_exit(); + sector_cnt++; + if (start_sector == end_sector) { + break; + } + start_sector++; + if (start_sector > pfs->last_sector) { + start_sector = pfs->first_sector; + } + } + //return len;//返回擦除的sector数目 + return sector_cnt; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 录音文件seek函数 + @param pfile:文件句柄 + @param type:seek的格式 + @param offsize:seek的偏移量。 + @return u8:返回值 + @author liujie + @note u8 phone_recf_seek (REC_FILE *pfile, u8 type, u32 offsize) +*/ +/*----------------------------------------------------------------------------*/ +u8 phone_recf_seek(REC_FILE *pfile, u8 type, int offsize) +{ + u32 file_len; + if (NULL == pfile) { + return 0; + } + y_printf(">>>[test]:pfile->len = %d,type = %d, offsize = %d\n", pfile->len, type, offsize); + file_len = pfile->len;//(u32)pfile->index.sector << pfile->pfs->sector_size; + if (NOR_FS_SEEK_SET == type) { + if (abs(offsize) >= file_len) { + return REC_FILE_END; + } + pfile->rw_p = offsize + sizeof(PHONE_RECFILEHEAD); + } else { // if(NOR_FS_SEEK_CUR == type) + offsize += pfile->rw_p; + if (offsize >= file_len) { + return REC_FILE_END; + } + pfile->rw_p += offsize; + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 录音文件读函数 + @param pfile:文件句柄 + @param buff:数据BUFF + @param btr:需要读取的数据长度,字节单位 + @return u16:读取回来的长度 + @author liujie + @note u16 phone_recf_read(REC_FILE _xdata *pfile ,u8 _xdata *buff , u16 btr) +*/ +/*----------------------------------------------------------------------------*/ +u16 phone_recf_read(REC_FILE *pfile, u8 *buff, u16 btr) +{ + u32 file_len, addr; + u16 read_len = btr; + u16 len, len0; + u32 max_addr, min_addr; + max_addr = phone_offset_addr + ((u32)(pfile->pfs->last_sector + 1) << pfile->pfs->sector_size) ; + min_addr = phone_offset_addr + ((u32)(pfile->pfs->first_sector) << pfile->pfs->sector_size) ; + file_len = (u32)pfile->len; + if ((u32)(btr + pfile->rw_p) >= file_len) { + if (pfile->rw_p >= file_len) { + return 0; + } + read_len = file_len - pfile->rw_p; + } + /* if (pfile->rw_p){ */ + /* addr = pfile->rw_p + ((u32)pfile->index.sector << pfile->pfs->sector_size) + 16; */ + /* }else */ + addr = pfile->rw_p + ((u32)pfile->index.sector << pfile->pfs->sector_size); + addr += phone_offset_addr; + + + len0 = read_len; + /* y_printf(">>>[test]r_addr = %d,max_addr =%d, min_addr=%d, pfile->rw_p =%d\n",addr, max_addr, min_addr, pfile->rw_p); */ + /* y_printf(">>>[test]:r_len0 = %d,btr = %d, file_len = %d\n",len0, btr, file_len); */ + while (len0) { + if (addr >= max_addr) { + addr = addr - max_addr + min_addr; + } + if ((addr + len0) > max_addr) { + len = max_addr - addr; + } else { + len = len0; + } + /* y_printf(">>>[test]2222r_addr = %d,max_addr =%d, min_addr=%d, pfile->rw_p =%d\n",addr, max_addr, min_addr, pfile->rw_p); */ + phone_recfs_read(pfile->pfs, addr, buff, len); + /* y_printf(">>>[test]:2222r_len0 = %d\n",len0); */ + pfile->rw_p += len; + len0 -= len; + buff += len; + addr += len; + } + return read_len; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 录音文件写函数 + @param pfile:文件句柄 + @param buff:数据BUFF + @param btr:需要写入的数据长度,字节单位 + @return u16:写入的长度 + @author liujie + @note u16 phone_recf_write(REC_FILE *pfile,u8 *buff,u16 btw) +*/ +/*----------------------------------------------------------------------------*/ +u16 phone_recf_write(REC_FILE *pfile, u8 *buff, u16 btw) +{ + u32 addr; + u32 max_addr, min_addr; + u16 sector; + u16 len0 = 0; + u16 len = 0;; + max_addr = phone_offset_addr + ((u32)(pfile->pfs->last_sector + 1) << pfile->pfs->sector_size) ; + min_addr = phone_offset_addr + ((u32)(pfile->pfs->first_sector) << pfile->pfs->sector_size) ; + addr = pfile->rw_p + ((u32)pfile->index.sector << pfile->pfs->sector_size); + addr += phone_offset_addr; + /* y_printf(">>>[test]:addr = %d,max_addr =%d, min_addr=%d, pfile->rw_p =%d\n",addr, max_addr, min_addr, pfile->rw_p); */ + //pfile->len + while (1) { + if ((pfile->rw_p + btw) > pfile->len) { + //获取更多的空间; + sector = (pfile->len + (1L << pfile->pfs->sector_size) - 1) >> pfile->pfs->sector_size; + sector += pfile->index.sector; + if (sector > pfile->pfs->last_sector) { + sector = sector - pfile->pfs->last_sector + pfile->pfs->first_sector - 1; + } + if (pfile->index.sector != sector) { + /* r_printf(">>>[test]:goto erase\n"); */ + phone_rec_erase_sector(pfile->pfs, sector, sector); + /* r_printf(">>>[test]:exit erase\n"); */ + pfile->len = pfile->len + (1L << pfile->pfs->sector_size); + } else { + /* y_printf(">>>[test]:not erase, sector = %d\n", sector); */ + break; + } + + } else { + break; + } + } + if ((pfile->rw_p + btw) > pfile->len) { + len = pfile->len - pfile->rw_p ; + y_printf(">>>[test]:len = %d, pfile->len = %d,pfile->rw_p =%d \n", len, pfile->len, pfile->rw_p); + } else { + len = btw; + } + len0 = len; + + while (len0) { + if (addr >= max_addr) { + addr = addr - max_addr + min_addr; + /* r_printf(">>>[test]:write the end, goto first addr write\n"); */ + } + + if ((addr + len0) > max_addr) { + btw = max_addr - addr; + } else { + btw = len0; + } + /* y_printf(">>>[test]:btw = %d\n", btw); */ + phone_recfs_wirte_align(pfile->pfs, addr, buff, btw); + /* y_printf(">>>[test]:len0 = %d\n",len0); */ + addr += btw; + buff += btw; + len0 -= btw; + + } + + pfile->rw_p += len; + if (pfile->rw_p > pfile->w_len) { + pfile->w_len = pfile->rw_p; + } + return len; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 清除索引 + @param pfs:文件系统句柄 + @return void + @author liujie + @note void phone_recfs_idx_clear(RECFILESYSTEM *pfs) +*/ +/*----------------------------------------------------------------------------*/ +void phone_recfs_idx_clear(RECFILESYSTEM *pfs) +{ + PHONE_RECFILEHEAD file_h; + u32 addr; + u16 curr_sector; + + curr_sector = pfs->first_sector; + memset(&file_h, 0, sizeof(PHONE_RECFILEHEAD)); + + while (curr_sector <= pfs->last_sector) { + addr = (u32)curr_sector << pfs->sector_size; + addr += phone_offset_addr; + phone_recfs_wirte_align(pfs, addr, (u8 *)(&file_h), sizeof(PHONE_RECFILEHEAD)); + + curr_sector++; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief delete a rec_file + @param pfs:文件系统句柄 + @return void + @author phew +*/ +/*----------------------------------------------------------------------------*/ +void phone_recfs_clear_file(REC_FILE *pfile) +{ + PHONE_RECFILEHEAD file_h; + u32 addr; + u16 curr_sector; + + curr_sector = pfile->index.sector; + memset(&file_h, 0, sizeof(PHONE_RECFILEHEAD)); + addr = (u32)curr_sector << pfile->pfs->sector_size; + addr += phone_offset_addr; + phone_recfs_wirte_align(pfile->pfs, addr, (u8 *)(&file_h), sizeof(PHONE_RECFILEHEAD)); + +} + +/*----------------------------------------------------------------------------*/ +/**@brief 扫描文件系统 + @param pfs:文件系统句柄 + @return u32:总文件数 + @author liujie + @note u32 phone_recfs_scan(RECFILESYSTEM *pfs) +*/ +/*----------------------------------------------------------------------------*/ +/*扫描出最少的文件*/ +u32 phone_recfs_scan(RECFILESYSTEM *pfs) +{ + PHONE_RECFILEHEAD file_h __attribute__((aligned(4))); + RECF_INDEX_INFO max_index; + //RECF_INDEX_INFO min_index; + u32 addr; + u32 total_len; + u16 crc; + u16 file_cnt = 0; + u16 curr_sector = pfs->first_sector; + pfs->total_file = 0; + max_index.index = 0; + max_index.sector = pfs->first_sector; + total_len = (u32)((u32)pfs->last_sector + 1 - (u32)pfs->first_sector) << pfs->sector_size; + while (1) { + addr = (u32)curr_sector << pfs->sector_size; + addr += phone_offset_addr; + /* r_printf(">>>[test]:addr=0x%x\n", addr); */ + phone_recfs_read(pfs, addr, (u8 *)(&file_h), sizeof(PHONE_RECFILEHEAD)); + /* put_buf(&file_h , 16); */ + crc = CRC16(&file_h.data_crc, sizeof(PHONE_RECFILEHEAD) - 2); + /* y_printf(">>>[test]:crc = 0x%x, file_h.len = %d, file_h.index = %d\n", crc, file_h.len, file_h.index); */ + if ((0 != crc) && (crc == file_h.head_crc) && (file_h.len <= total_len)) { + if (file_h.index >= max_index.index) { + max_index.index = file_h.index; + max_index.sector = curr_sector; + } + + /* + if(file_h.index <= pfs->index.index) + { + min_index.index = file_h.index; + min_index.sector = curr_sector; + } + */ + r_printf(">>>[test]:addr=%d\n", addr); + file_cnt++; + if (0 != file_h.len) { + curr_sector += file_h.len >> pfs->sector_size; + if (file_h.len % (1L << pfs->sector_size)) { + curr_sector++; + } + } else { + curr_sector++; + } + + } else { + curr_sector++; + } + if (curr_sector > pfs->last_sector) { + //curr_sector = pfs->first_sector; + break; + } + } + + if (max_index.index < 0) { + //清空整个MEM() + y_printf(">>>[test]:goto clear index.sector\n"); + phone_recfs_idx_clear(pfs); + pfs->total_file = 0; + pfs->index.index = 0; + pfs->index.sector = pfs->first_sector; + } else { + pfs->index.index = max_index.index; + pfs->index.sector = max_index.sector; + /* y_printf(">>>[test]:recfs_scan pfs->index.sector = %d, pfs->index.index = %d\n", pfs->index.sector, pfs->index.index); */ + pfs->total_file = file_cnt; + /* y_printf(">>>[test]:recfs_scan file_cnt = %d\n", file_cnt); */ + } + + return file_cnt; +} +/*----------------------------------------------------------------------------*/ +/**@brief 检查指定扇区是否存爱文件 + @param pfs:文件系统的句柄 + @param pfile_h:文件头指针 + @param sector:需要分析的扇区 + @return u16:下一个有效扇区 + @author liujie + @note u16 phone_check_head(RECFILESYSTEM *pfs,PHONE_RECFILEHEAD *pfile_h,u16 sector) +*/ +/*----------------------------------------------------------------------------*/ +u16 phone_check_head(RECFILESYSTEM *pfs, PHONE_RECFILEHEAD *pfile_h, u16 sector) +{ + //RECFILEHEAD file_h; + u32 addr; + u32 total_len; + addr = sector; + addr = addr << pfs->sector_size; + addr += phone_offset_addr; + + total_len = (u32)((u32)pfs->last_sector + 1 - (u32)pfs->first_sector) << pfs->sector_size; + y_printf(">>>[test]: check head addr = %d\n", addr); + phone_recfs_read(pfs, addr, (u8 *)pfile_h, sizeof(PHONE_RECFILEHEAD)); + if ((CRC16(&pfile_h->data_crc, sizeof(PHONE_RECFILEHEAD) - 2) == pfile_h->head_crc) + && (pfile_h->len <= total_len) + ) { + r_printf(">>>[test]:AAAAAAAAAAA\n"); + sector = sector + (pfile_h->len >> pfs->sector_size); + r_printf(">>>[test]:sector = %d\n", sector); + if (pfile_h->len % (1L << pfs->sector_size)) { + r_printf(">>>[test]:BBBBBBBBBBB\n"); + sector++; + } else { + } + /* + if(sector > pfs->last_sector) + { + sector -= pfs->last_sector; + } + */ + } else { + } + return sector; +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief 建立一个文件 + @param pfs:文件系统的句柄 + @param pfile:文件的句柄 + @return u32:建立文件索引 + @author liujie + @note u32 phone_create_recfile(RECFILESYSTEM *pfs,REC_FILE *pfile) +*/ +/*----------------------------------------------------------------------------*/ +u32 phone_create_recfile(RECFILESYSTEM *pfs, REC_FILE *pfile) +{ + PHONE_RECFILEHEAD file_h; + u16 sector, sec0; + u16 sec_len; + + memset((u8 *)pfile, 0, sizeof(REC_FILE)); + pfile->pfs = pfs; + sector = pfs->index.sector; + /* y_printf(">>>[test]:create pfs->index.sector = %d\n", pfs->index.sector); */ + sec0 = phone_check_head(pfs, &file_h, sector); + if (sector != sec0) { + if (sec0 > pfs->last_sector) { + sec0 = sec0 - pfs->last_sector + pfs->first_sector - 1; + } + sector = sec0; + } + pfile->index.index = pfs->index.index + 1; + pfile->index.sector = sec0; + sec_len = phone_rec_erase_sector(pfs, sector, sec0); + /* y_printf(">>>[test]:sec_len = %d\n",sec_len); */ + pfile->len = (u32)sec_len << pfs->sector_size; + pfile->w_len = sizeof(PHONE_RECFILEHEAD); + pfile->rw_p = sizeof(PHONE_RECFILEHEAD); + pfile->addr = pfile->rw_p + (pfile->index.sector << pfile->pfs->sector_size) + phone_offset_addr; + /* y_printf(">>>[test]:rw_p = %d\n", pfile->rw_p); */ + return pfile->index.index; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭一个文件 + @param pfile:文件的句柄 + @return u32:建立文件索引 + @author liujie + @note u32 phone_close_recfile(REC_FILE *pfile) +*/ +/*----------------------------------------------------------------------------*/ +u32 phone_close_recfile(REC_FILE *pfile) +{ + PHONE_RECFILEHEAD file_h; + + memset(&file_h, 0xff, sizeof(PHONE_RECFILEHEAD)); + //file_h->crc; + pfile->w_len = pfile->rw_p; + + pfile->len = pfile->w_len; + pfile->rw_p = 0;//sizeof(PHONE_RECFILEHEAD); + file_h.len = pfile->w_len; + file_h.data_crc = sizeof(PHONE_RECFILEHEAD); + file_h.index = pfile->index.index; + file_h.addr = pfile->addr; + memcpy(file_h.name, pfile->priv_data, NORFS_DATA_LEN); + + file_h.head_crc = CRC16(&file_h.data_crc, sizeof(PHONE_RECFILEHEAD) - 2); + r_printf(">>>[test]:pfile->index.sector = %d\n", pfile->index.sector); + + //memset(&file_h,0,sizeof(RECFILEHEAD)); + //recfs_read((u32)pfile->index.sector<pfs->sector_size,(u8 *)&file_h,sizeof(RECFILEHEAD)); + + phone_recf_write(pfile, (u8 *)&file_h, sizeof(PHONE_RECFILEHEAD)); + /* put_buf(&file_h , 16); */ + pfile->pfs->index.index = pfile->index.index; + pfile->pfs->index.sector = pfile->index.sector; + + //memset(&file_h,0,sizeof(RECFILEHEAD)); + //recfs_read((u32)pfile->index.sector<pfs->sector_size,(u8 *)&file_h,sizeof(RECFILEHEAD)); + + /* r_printf(">>>[test]:file_h.len = %d\n", file_h.len); */ + return file_h.len; +} + +void phone_recf_save_sr(REC_FILE *pfile, u16 sr) +{ + if (pfile) { + pfile->sr = sr; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按照索引号,搜索一个文件 + @param index:索引号 + @param pfile:文件的句柄 + @return u32:找到文件的索引 + @author liujie + @note u32 phone_revf_index_scan(u32 index,REC_FILE *pfile) +*/ +/*----------------------------------------------------------------------------*/ +u32 phone_revf_index_scan(u32 index, REC_FILE *pfile) +{ + PHONE_RECFILEHEAD file_h; + RECFILESYSTEM *pfs; + u32 addr; + u32 total_len; + u16 curr_sector, crc; + + pfs = pfile->pfs; + curr_sector = pfs->index.sector; + total_len = (u32)((u32)pfs->last_sector + 1 - (u32)pfs->first_sector) << pfs->sector_size; + r_printf(">>>[test]:pfile->pfs->index.sector = %d, total_len = %d\n", pfile->pfs->index.sector, total_len); + + while (1) { + addr = (u32)curr_sector << pfs->sector_size; + addr += phone_offset_addr; + r_printf(">>>[test]:offset_addr = 0x%x, addr = 0x%x\n", phone_offset_addr, addr); + + phone_recfs_read(pfs, addr, (u8 *)(&file_h), sizeof(PHONE_RECFILEHEAD)); + /* put_buf(&file_h , 16); */ + crc = CRC16(&file_h.data_crc, sizeof(PHONE_RECFILEHEAD) - 2); + y_printf(">>>[test]:crc = 0x%x, file_h.len = %d, file_h.index = %d\n", crc, file_h.len, file_h.index); + if ((0 != crc) && (crc == file_h.head_crc) && (file_h.len <= total_len)) { + if (file_h.index == index) { + r_printf(">>>[test]:go in AAAAAA\n"); + pfile->index.index = index; + pfile->index.sector = curr_sector; + pfile->len = file_h.len; + pfile->w_len = file_h.len; + pfile->rw_p = sizeof(PHONE_RECFILEHEAD); + pfile->addr = file_h.addr; + /* pfile->sr = (u16)(((u16)file_h.reserv[1] << 8) | file_h.reserv[0]);//利用了保留区 */ + memcpy(pfile->priv_data, file_h.name, NORFS_DATA_LEN); + return index; + } else { + if (0 == file_h.len) { + curr_sector++; + } + curr_sector = curr_sector + (file_h.len >> pfs->sector_size); + if (file_h.len % (1L << pfs->sector_size)) { + curr_sector++; + } + } + } else { + curr_sector++; + } + + if (curr_sector > pfs->last_sector) { + curr_sector = pfs->first_sector; + } + /* r_printf(">>>[test]:pfile->index.sector = %d, curr_sector = %d\n", pfile->index.sector, curr_sector); */ + if (pfs->index.sector == curr_sector) { + break; + } + + } + return index - 1; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按照索引号打开一个文件 + @param index:索引号 + @param pfs:文件系统的句柄 + @param pfile:文件的句柄 + @return u32:找到文件的索引 + @author liujie + @note u32 phone_open_recfile(u32 index,RECFILESYSTEM *pfs,REC_FILE *pfile) +*/ +/*----------------------------------------------------------------------------*/ +u32 phone_open_recfile(u32 index, RECFILESYSTEM *pfs, REC_FILE *pfile) +{ + memset((u8 *)pfile, 0, sizeof(REC_FILE)); + pfile->pfs = pfs; + pfile->rw_p = sizeof(PHONE_RECFILEHEAD); + return phone_revf_index_scan(index, pfile); +} + + +u32 decode_data_by_user_key_in_sdfile(u16 key, u8 *buff, u16 size, u32 dec_addr, u8 dec_len) +{ + u16 key_addr; + u16 r_len; + + while (size) { + r_len = (size > dec_len) ? dec_len : size; + key_addr = (dec_addr >> 2)^key; + doe_in_phonefs(key_addr, buff, r_len, 0); + buff += r_len; + dec_addr += r_len; + size -= r_len; + } + + return dec_addr; +} + +static u16 get_chip_id_in_phonefs() +{ + return boot_info.chip_id; +} + +static void head_addr_get(char *name) +{ + extern u32 boot_info_get_sfc_base_addr(void); + u32 start_addr = boot_info_get_sfc_base_addr(); + u32 offset = 0; + struct sdfile_file_head head = {0}; + u16 local_flash_key = get_chip_id_in_phonefs(); + while (1) { + extern int norflash_origin_read(u8 * buf, u32 offset, u32 len); + norflash_origin_read((u8 *)&head, start_addr, sizeof(head)); + decode_data_by_user_key_in_sdfile(local_flash_key, (u8 *)&head, sizeof(head), offset, sizeof(head)); + if (head.head_crc != CRC16((u8 *)&head.data_crc, sizeof(head) - sizeof(head.head_crc))) { + y_printf("\n >>>[test]:func = %s,line= %d\n", __FUNCTION__, __LINE__); + return; + } + if (0 == memcmp(head.name, name, strlen(name))) { + break; + } + offset += sizeof(head); + start_addr += sizeof(head); + } + + { + extern int phone_offset_addr; + extern int max_rec_len; + phone_offset_addr = head.addr; + max_rec_len = head.len; + } + r_printf(">>>[test]:######### start_addr = 0x%x, len = 0x%x\n", head.addr, head.len); +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief 初始化文件系统信息 + @param pfs:文件系统的句柄 + @param sector_start:起始扇区 + @param sector_end:结束扇区 + @param sector_size:扇区大小(1L<first_sector = sector_start; + pfs->last_sector = sector_end; + pfs->sector_size = sector_size; +} + + +RECFILESYSTEM phone_recfs; +REC_FILE phone_recfile; +int phone_max_rec_capacity = 256 * 1024; +int set_rec_capacity(int capacity) //需要先设置容量。 +{ + + r_printf(">>>[test]:goto set_rec_capacity\n"); + head_addr_get("REC"); + + ASSERT(capacity <= max_rec_len, "capacity must smaller than max_rec_len!!!!!!! "); + phone_max_rec_capacity = capacity; + return phone_max_rec_capacity; +} +#define FS_SECTOR_S (4*1024L) +#define FS_S_SECTOR (1) +#define FS_E_SECTOR (phone_max_rec_capacity/FS_SECTOR_S-1) + +/////////////////////////////SDFILE_REC_FUNCTION//////////////////////////////////////// +/* extern u32 hook_sdfile_rec_read(u8 *buf, u32 addr, u32 len); */ +/* extern u32 hook_sdfile_rec_write(u8 *buf, u32 addr, u32 len); */ +/* extern u32 hook_sdfile_rec_erase(u32 addr); */ +extern int norflash_read(struct device *device, void *buf, u32 len, u32 offset); +extern int norflash_write(struct device *device, void *buf, u32 len, u32 offset); +extern int norflash_erase(u32 cmd, u32 addr); + +s32 hook_sdfile_rec_read(u8 *buf, u32 addr, u32 len) +{ + return norflash_read(NULL, (void *)buf, len, addr); +} + +s32 hook_sdfile_rec_write(u8 *buf, u32 addr, u32 len) +{ + return norflash_write(NULL, (void *)buf, len, addr); +} + +void hook_sdfile_rec_erase(u32 addr) +{ + norflash_erase(IOCTL_ERASE_SECTOR, addr); +} + + + +u32 phone_init_recfs(void) +{ + memset(&phone_recfs, 0, sizeof(RECFILESYSTEM)); + phone_recfs.eraser = hook_sdfile_rec_erase; + phone_recfs.read = hook_sdfile_rec_read; + phone_recfs.write = hook_sdfile_rec_write; + return true; +} + +u32 sdfile_rec_init(void) +{ + phone_init_recfs(); + phone_init_nor_fs(&phone_recfs, FS_S_SECTOR, FS_E_SECTOR, 12); + phone_recfs_scan(&phone_recfs); +#if (VFS_ENABLE == 1) + if (mount(NULL, "mnt/rec_sdfile", "rec_sdfile", 0, NULL)) { + r_printf("sdfile_rec mount succ"); + } else { + r_printf("sdfile_rec mount failed!!!"); + } +#endif /* #if (VFS_ENABLE == 1) */ + y_printf(">>>[test]:sdfile_rec_init\n"); + sdfile_rec_index = phone_recfs.index.index; + return phone_recfs.index.index; +} + +u32 sdfile_rec_createfile(void) +{ + int index; + y_printf(">>>[test]:goto create\n"); + phone_recfs_idx_clear(&phone_recfs); + index = phone_create_recfile(&phone_recfs, &phone_recfile); + return index; + +} + +u32 sdfile_rec_write(void *buff, u32 len) +{ + u16 w_len; + w_len = phone_recf_write(&phone_recfile, buff, len); + /* put_buf(buff, len); */ + return w_len; +} + +u32 sdfile_rec_read(void *buff, u32 len) +{ + u16 r_len; + if (len > 512) { + log_e("len > 512!!!!!!!!!!"); + return -1; + } + /* r_printf(">>>[test]:goto nor_fs read\n"); */ + if (((u32)buff % 4) != 0) { + void *tmp_buf = malloc(512); + r_len = phone_recf_read(&phone_recfile, tmp_buf, len); + memcpy(buff, tmp_buf, len); + free(tmp_buf); + /* put_buf(buff, len); */ + return r_len; + } + r_len = phone_recf_read(&phone_recfile, buff, len); + /* put_buf(buff, len); */ + return r_len; +} + +u32 sdfile_rec_open(u32 index) +{ + int reg; + reg = phone_open_recfile(index, &phone_recfs, &phone_recfile); + return reg; +} + +u32 sdfile_rec_close(void) +{ + int reg; + r_printf(">>>[test]:goto nor_fs close\n"); + reg = phone_close_recfile(&phone_recfile); + return reg; +} + +u32 sdfile_rec_seek(int offsize, int type) +{ + int reg; + /* r_printf(">>>[test]:goto nor_fs seek\n"); */ + reg = phone_recf_seek(&phone_recfile, (u8) type, offsize); + return reg; +} + +u32 sdfile_rec_flen(void) +{ + return phone_recfile.len; +} + +void sdfile_rec_get_priv_info(u8 *info) +{ + memcpy(info, &phone_recfile.priv_data, 16); +} + +void sdfile_rec_set_priv_info(u8 *info) //用于设置数据格式和电话信息. +{ + memcpy(&phone_recfile.priv_data, info, 16); +} + +u16 sdfile_rec_get_sr(void) +{ + return phone_recfile.sr; +} + +void sdfile_rec_set_sr(u16 sr) +{ + phone_recfile.sr = sr; +} + +void rec_clear_norfs_fileindex(void) +{ + phone_recfs_idx_clear(&phone_recfs); +} + +u32 rec_delete_rec_file(u32 index) +{ + int num; + num = phone_open_recfile(index, &phone_recfs, &phone_recfile); + if (num != index) { + log_e("open error"); + return -1; + } + phone_recfs_clear_file(&phone_recfile); + return 0; +} + +u32 flashinsize_rec_get_capacity(void) +{ + return phone_max_rec_capacity; +} + +u32 flashinsize_rec_get_index(void) +{ + return sdfile_rec_index; +} + +#if (VFS_ENABLE == 1) +int sdfile_rec_scan_ex() +{ + phone_recfs_scan(&phone_recfs); + return phone_recfs.index.index; +} + +int recfile_insizeflash_set_index(u8 file_sel, u32 index) +{ + y_printf(">>>[test]:goto recfile_insizeflash_set_index\n"); + phone_recfs_scan(&phone_recfs); + switch (file_sel) { + case FSEL_NEXT_FILE: + r_printf(">>>[test]:flash FSEL_NEXT_FILE\n"); + sdfile_rec_index++; + if (sdfile_rec_index > phone_recfs.index.index) { + log_w("play on the end, goto first play!!!!!!!!!"); + sdfile_rec_index = 1; + /* music_flash_file_set_index(FSEL_CURR_FILE, 1); */ + } + break; + case FSEL_PREV_FILE: + r_printf(">>>[test]:flash FSEL_PREV_FILE\n"); + sdfile_rec_index--; + if (sdfile_rec_index <= 0) { + log_e("index <= 0 err!!!, play first"); + sdfile_rec_index = 1; + /* music_flash_file_set_index(FSEL_CURR_FILE, 1); */ + } + break; + case FSEL_CURR_FILE: + r_printf(">>>[test]:flash FSEL_CURR_FILE\n"); + if (index <= (phone_recfs.index.index - phone_recfs.total_file)) { + sdfile_rec_index = (phone_recfs.index.index - phone_recfs.total_file) + 1; + } else if (index && (index <= phone_recfs.index.index)) { + sdfile_rec_index = index; + } else { + log_e("error!!!!!!! no file"); + return 1; + } + break; + } + if (sdfile_rec_index <= (phone_recfs.index.index - phone_recfs.total_file)) { + sdfile_rec_index = (phone_recfs.index.index - phone_recfs.total_file) + 1; + } + return 0; +} + + +u32 _sdfile_rec_init(void) +{ + return sdfile_rec_init(); +} + +static int get_ext_name(char *path, char *ext) +{ + int len = strlen(path); + char *name = (char *)path; + while (len--) { + if (*name++ == '.') { + break; + } + } + if (len <= 0) { + name = path + (strlen(path) - 3); + } + memcpy(ext, name, 3); + ext[3] = 0; + return 1; +} + +static int get_filename_by_path(char *filename, char *path) +{ + int len = strlen(path); + char *name = (char *)path; + name = path + len; + for (int i = len; i >= 0; i--) { + if (*name-- == '/') { + break; + } + if ((len - i) > 15) { + r_printf(">>>[test]:i= %d,len = %d\n", i, len); + log_w("filename is too long!!!!!!!!"); + break; + } + } + + memcpy(filename, name + 2, 15); + filename[15] = 0; + return 1; + +} + +static int sdfile_first_flag = 1; +static int _sdfile_rec_open(FILE *_file, const char *path, const char *mode) +{ + int index; + int reg; + y_printf(">>>[test]:nor_fs_open\n"); + + if (mode[0] == 'w') { + y_printf(">>>[test]:goto create\n"); + char ext[4] = {0}; + char filename[16] = {0}; + get_ext_name((char *)path, (char *)ext); + if (memcmp(ext, "WAV", 3) == 0 || memcmp(ext, "wav", 3) == 0) { + sdfile_first_flag = 1; + } else { + sdfile_first_flag = 0; + } + + index = sdfile_rec_createfile(); + get_filename_by_path((char *)filename, (char *) path); + sdfile_rec_set_priv_info((u8 *)filename); + r_printf(">>>[test]:path = %s, ext = %s, filename = %s\n", path, ext, filename); + + sdfile_rec_index = index; + return 0; + } else if (mode[0] == 'r') { + y_printf(">>>[test]: open_recfile nor_fs_hdl->index= %d\n", sdfile_rec_index); + if (sdfile_rec_index) { + index = sdfile_rec_index; + } else { + log_e("error!!!!!!!!!"); + index = 0; + return 1; + } + reg = sdfile_rec_open(index); + return 0; + } + return 0; + +} + +static int _sdfile_rec_write(FILE *_file, void *buff, u32 len) +{ + if (sdfile_first_flag == 1) { + memset(buff, 0xff, 90); + sdfile_first_flag = 0; + } + return sdfile_rec_write(buff, len); +} +static int _sdfile_rec_read(FILE *_file, void *buff, u32 len) +{ + return sdfile_rec_read(buff, len); +} +static int _sdfile_rec_close(FILE *_file) +{ + return sdfile_rec_close(); +} +static int _sdfile_rec_seek(FILE *_file, int offsize, int type) +{ + return sdfile_rec_seek(offsize, type); +} +static int _sdfile_rec_flen(FILE *_file) +{ + return sdfile_rec_flen(); +} +static int _sdfile_rec_fpos(FILE *_file) +{ + return phone_recfile.rw_p; +} +static int _sdfile_rec_mount(struct imount *mt, int cache_num) +{ + y_printf("\n >>>[test]:func = %s,line= %d\n", __FUNCTION__, __LINE__); + struct vfs_partition *app_part = &mt->part; + + app_part->offset = 0 + phone_offset_addr; + app_part->dir[0] = 'C'; + app_part->dir[1] = '\0'; + + mt->part_num = 1; + + return 0; + +} + +REGISTER_VFS_OPERATIONS(inside_nor_fs_vfs_ops) = { + .fs_type = "rec_sdfile", + .mount = _sdfile_rec_mount, + .unmount = NULL, + .format = NULL, + .fopen = _sdfile_rec_open, + .fwrite = _sdfile_rec_write, + .fread = _sdfile_rec_read, + .fseek = _sdfile_rec_seek, + .flen = _sdfile_rec_flen, + .fpos = _sdfile_rec_fpos, + .fclose = _sdfile_rec_close, + .fscan = NULL, + .fscan_release = NULL, + .fsel = NULL, + .fdelete = NULL, + .fget_name = NULL, + .frename = NULL, + .fget_free_space = NULL, + .fget_attr = NULL, + .fset_attr = NULL, + .fget_attrs = NULL, + .fset_vol = NULL, + .fmove = NULL, + .ioctl = NULL, +}; + +int sdfile_rec_ops_init(void) +{ + return 0; +} + +#endif + + diff --git a/apps/common/fat_nor/virfat_flash.c b/apps/common/fat_nor/virfat_flash.c new file mode 100644 index 0000000..29210e6 --- /dev/null +++ b/apps/common/fat_nor/virfat_flash.c @@ -0,0 +1,532 @@ +#include "system/includes.h" +/* #include "jlfat/tff.h" */ +#include "app_config.h" +#include "fs/virfat_flash.h" +#include "res/resfile.h" +/* #include "fs/fs.h" */ + +#define FLASH_8M_BELOW 1 + +#if TCFG_VIRFAT_FLASH_ENABLE +void fat_copy(void *pDest, void *pSrc, u32 copyLen) +{ + while (copyLen--) { + ((u8 *)pDest)[copyLen] = ((u8 *)pSrc)[copyLen]; + } +} + +static u16 ld_word(u8 *p) +{ + return (u16)p[1] << 8 | p[0]; +} + +static u32 ld_dword(u8 *p) +{ + return (u32)p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0]; +} + +//fat 备份4Kfat_table和4K目录项,保留扇区扩大8K ,8M +#if FLASH_8M_BELOW +static const unsigned char bpb_data[512] = { + 0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x08, 0x18, 0x00, + 0x01, 0x80, 0x00, 0x00, 0x40, 0xF8, 0x08, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x29, 0xEE, 0x8D, 0xF2, 0x2C, 0x4E, 0x4F, 0x20, 0x4E, 0x41, + 0x4D, 0x45, 0x20, 0x20, 0x20, 0x20, 0x46, 0x41, 0x54, 0x31, 0x36, 0x20, 0x20, 0x20, 0x33, 0xC9, + 0x8E, 0xD1, 0xBC, 0xF0, 0x7B, 0x8E, 0xD9, 0xB8, 0x00, 0x20, 0x8E, 0xC0, 0xFC, 0xBD, 0x00, 0x7C, + 0x38, 0x4E, 0x24, 0x7D, 0x24, 0x8B, 0xC1, 0x99, 0xE8, 0x3C, 0x01, 0x72, 0x1C, 0x83, 0xEB, 0x3A, + 0x66, 0xA1, 0x1C, 0x7C, 0x26, 0x66, 0x3B, 0x07, 0x26, 0x8A, 0x57, 0xFC, 0x75, 0x06, 0x80, 0xCA, + 0x02, 0x88, 0x56, 0x02, 0x80, 0xC3, 0x10, 0x73, 0xEB, 0x33, 0xC9, 0x8A, 0x46, 0x10, 0x98, 0xF7, + 0x66, 0x16, 0x03, 0x46, 0x1C, 0x13, 0x56, 0x1E, 0x03, 0x46, 0x0E, 0x13, 0xD1, 0x8B, 0x76, 0x11, + 0x60, 0x89, 0x46, 0xFC, 0x89, 0x56, 0xFE, 0xB8, 0x20, 0x00, 0xF7, 0xE6, 0x8B, 0x5E, 0x0B, 0x03, + 0xC3, 0x48, 0xF7, 0xF3, 0x01, 0x46, 0xFC, 0x11, 0x4E, 0xFE, 0x61, 0xBF, 0x00, 0x00, 0xE8, 0xE6, + 0x00, 0x72, 0x39, 0x26, 0x38, 0x2D, 0x74, 0x17, 0x60, 0xB1, 0x0B, 0xBE, 0xA1, 0x7D, 0xF3, 0xA6, + 0x61, 0x74, 0x32, 0x4E, 0x74, 0x09, 0x83, 0xC7, 0x20, 0x3B, 0xFB, 0x72, 0xE6, 0xEB, 0xDC, 0xA0, + 0xFB, 0x7D, 0xB4, 0x7D, 0x8B, 0xF0, 0xAC, 0x98, 0x40, 0x74, 0x0C, 0x48, 0x74, 0x13, 0xB4, 0x0E, + 0xBB, 0x07, 0x00, 0xCD, 0x10, 0xEB, 0xEF, 0xA0, 0xFD, 0x7D, 0xEB, 0xE6, 0xA0, 0xFC, 0x7D, 0xEB, + 0xE1, 0xCD, 0x16, 0xCD, 0x19, 0x26, 0x8B, 0x55, 0x1A, 0x52, 0xB0, 0x01, 0xBB, 0x00, 0x00, 0xE8, + 0x3B, 0x00, 0x72, 0xE8, 0x5B, 0x8A, 0x56, 0x24, 0xBE, 0x0B, 0x7C, 0x8B, 0xFC, 0xC7, 0x46, 0xF0, + 0x3D, 0x7D, 0xC7, 0x46, 0xF4, 0x29, 0x7D, 0x8C, 0xD9, 0x89, 0x4E, 0xF2, 0x89, 0x4E, 0xF6, 0xC6, + 0x06, 0x96, 0x7D, 0xCB, 0xEA, 0x03, 0x00, 0x00, 0x20, 0x0F, 0xB6, 0xC8, 0x66, 0x8B, 0x46, 0xF8, + 0x66, 0x03, 0x46, 0x1C, 0x66, 0x8B, 0xD0, 0x66, 0xC1, 0xEA, 0x10, 0xEB, 0x5E, 0x0F, 0xB6, 0xC8, + 0x4A, 0x4A, 0x8A, 0x46, 0x0D, 0x32, 0xE4, 0xF7, 0xE2, 0x03, 0x46, 0xFC, 0x13, 0x56, 0xFE, 0xEB, + 0x4A, 0x52, 0x50, 0x06, 0x53, 0x6A, 0x01, 0x6A, 0x10, 0x91, 0x8B, 0x46, 0x18, 0x96, 0x92, 0x33, + 0xD2, 0xF7, 0xF6, 0x91, 0xF7, 0xF6, 0x42, 0x87, 0xCA, 0xF7, 0x76, 0x1A, 0x8A, 0xF2, 0x8A, 0xE8, + 0xC0, 0xCC, 0x02, 0x0A, 0xCC, 0xB8, 0x01, 0x02, 0x80, 0x7E, 0x02, 0x0E, 0x75, 0x04, 0xB4, 0x42, + 0x8B, 0xF4, 0x8A, 0x56, 0x24, 0xCD, 0x13, 0x61, 0x61, 0x72, 0x0B, 0x40, 0x75, 0x01, 0x42, 0x03, + 0x5E, 0x0B, 0x49, 0x75, 0x06, 0xF8, 0xC3, 0x41, 0xBB, 0x00, 0x00, 0x60, 0x66, 0x6A, 0x00, 0xEB, + 0xB0, 0x42, 0x4F, 0x4F, 0x54, 0x4D, 0x47, 0x52, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x52, 0x65, + 0x6D, 0x6F, 0x76, 0x65, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x73, 0x20, 0x6F, 0x72, 0x20, 0x6F, 0x74, + 0x68, 0x65, 0x72, 0x20, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x2E, 0xFF, 0x0D, 0x0A, 0x44, 0x69, 0x73, + 0x6B, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0xFF, 0x0D, 0x0A, 0x50, 0x72, 0x65, 0x73, 0x73, 0x20, + 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x74, 0x6F, 0x20, 0x72, 0x65, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xCB, 0xD8, 0x55, 0xAA +}; +#else +//fat 备份12Kfat_table和8K目录项,保留扇区扩大20K ,32M +static const unsigned char bpb_data[512] = { + 0xEB, 0x3C, 0x90, 0x4D, 0x53, 0x44, 0x4F, 0x53, 0x35, 0x2E, 0x30, 0x00, 0x02, 0x08, 0x30, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x00, 0xF8, 0x18, 0x00, 0x3F, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x80, 0x00, 0x29, 0xEE, 0x8D, 0xF2, 0x2C, 0x4E, 0x4F, 0x20, 0x4E, 0x41, + 0x4D, 0x45, 0x20, 0x20, 0x20, 0x20, 0x46, 0x41, 0x54, 0x31, 0x36, 0x20, 0x20, 0x20, 0x33, 0xC9, + 0x8E, 0xD1, 0xBC, 0xF0, 0x7B, 0x8E, 0xD9, 0xB8, 0x00, 0x20, 0x8E, 0xC0, 0xFC, 0xBD, 0x00, 0x7C, + 0x38, 0x4E, 0x24, 0x7D, 0x24, 0x8B, 0xC1, 0x99, 0xE8, 0x3C, 0x01, 0x72, 0x1C, 0x83, 0xEB, 0x3A, + 0x66, 0xA1, 0x1C, 0x7C, 0x26, 0x66, 0x3B, 0x07, 0x26, 0x8A, 0x57, 0xFC, 0x75, 0x06, 0x80, 0xCA, + 0x02, 0x88, 0x56, 0x02, 0x80, 0xC3, 0x10, 0x73, 0xEB, 0x33, 0xC9, 0x8A, 0x46, 0x10, 0x98, 0xF7, + 0x66, 0x16, 0x03, 0x46, 0x1C, 0x13, 0x56, 0x1E, 0x03, 0x46, 0x0E, 0x13, 0xD1, 0x8B, 0x76, 0x11, + 0x60, 0x89, 0x46, 0xFC, 0x89, 0x56, 0xFE, 0xB8, 0x20, 0x00, 0xF7, 0xE6, 0x8B, 0x5E, 0x0B, 0x03, + 0xC3, 0x48, 0xF7, 0xF3, 0x01, 0x46, 0xFC, 0x11, 0x4E, 0xFE, 0x61, 0xBF, 0x00, 0x00, 0xE8, 0xE6, + 0x00, 0x72, 0x39, 0x26, 0x38, 0x2D, 0x74, 0x17, 0x60, 0xB1, 0x0B, 0xBE, 0xA1, 0x7D, 0xF3, 0xA6, + 0x61, 0x74, 0x32, 0x4E, 0x74, 0x09, 0x83, 0xC7, 0x20, 0x3B, 0xFB, 0x72, 0xE6, 0xEB, 0xDC, 0xA0, + 0xFB, 0x7D, 0xB4, 0x7D, 0x8B, 0xF0, 0xAC, 0x98, 0x40, 0x74, 0x0C, 0x48, 0x74, 0x13, 0xB4, 0x0E, + 0xBB, 0x07, 0x00, 0xCD, 0x10, 0xEB, 0xEF, 0xA0, 0xFD, 0x7D, 0xEB, 0xE6, 0xA0, 0xFC, 0x7D, 0xEB, + 0xE1, 0xCD, 0x16, 0xCD, 0x19, 0x26, 0x8B, 0x55, 0x1A, 0x52, 0xB0, 0x01, 0xBB, 0x00, 0x00, 0xE8, + 0x3B, 0x00, 0x72, 0xE8, 0x5B, 0x8A, 0x56, 0x24, 0xBE, 0x0B, 0x7C, 0x8B, 0xFC, 0xC7, 0x46, 0xF0, + 0x3D, 0x7D, 0xC7, 0x46, 0xF4, 0x29, 0x7D, 0x8C, 0xD9, 0x89, 0x4E, 0xF2, 0x89, 0x4E, 0xF6, 0xC6, + 0x06, 0x96, 0x7D, 0xCB, 0xEA, 0x03, 0x00, 0x00, 0x20, 0x0F, 0xB6, 0xC8, 0x66, 0x8B, 0x46, 0xF8, + 0x66, 0x03, 0x46, 0x1C, 0x66, 0x8B, 0xD0, 0x66, 0xC1, 0xEA, 0x10, 0xEB, 0x5E, 0x0F, 0xB6, 0xC8, + 0x4A, 0x4A, 0x8A, 0x46, 0x0D, 0x32, 0xE4, 0xF7, 0xE2, 0x03, 0x46, 0xFC, 0x13, 0x56, 0xFE, 0xEB, + 0x4A, 0x52, 0x50, 0x06, 0x53, 0x6A, 0x01, 0x6A, 0x10, 0x91, 0x8B, 0x46, 0x18, 0x96, 0x92, 0x33, + 0xD2, 0xF7, 0xF6, 0x91, 0xF7, 0xF6, 0x42, 0x87, 0xCA, 0xF7, 0x76, 0x1A, 0x8A, 0xF2, 0x8A, 0xE8, + 0xC0, 0xCC, 0x02, 0x0A, 0xCC, 0xB8, 0x01, 0x02, 0x80, 0x7E, 0x02, 0x0E, 0x75, 0x04, 0xB4, 0x42, + 0x8B, 0xF4, 0x8A, 0x56, 0x24, 0xCD, 0x13, 0x61, 0x61, 0x72, 0x0B, 0x40, 0x75, 0x01, 0x42, 0x03, + 0x5E, 0x0B, 0x49, 0x75, 0x06, 0xF8, 0xC3, 0x41, 0xBB, 0x00, 0x00, 0x60, 0x66, 0x6A, 0x00, 0xEB, + 0xB0, 0x42, 0x4F, 0x4F, 0x54, 0x4D, 0x47, 0x52, 0x20, 0x20, 0x20, 0x20, 0x0D, 0x0A, 0x52, 0x65, + 0x6D, 0x6F, 0x76, 0x65, 0x20, 0x64, 0x69, 0x73, 0x6B, 0x73, 0x20, 0x6F, 0x72, 0x20, 0x6F, 0x74, + 0x68, 0x65, 0x72, 0x20, 0x6D, 0x65, 0x64, 0x69, 0x61, 0x2E, 0xFF, 0x0D, 0x0A, 0x44, 0x69, 0x73, + 0x6B, 0x20, 0x65, 0x72, 0x72, 0x6F, 0x72, 0xFF, 0x0D, 0x0A, 0x50, 0x72, 0x65, 0x73, 0x73, 0x20, + 0x61, 0x6E, 0x79, 0x20, 0x6B, 0x65, 0x79, 0x20, 0x74, 0x6F, 0x20, 0x72, 0x65, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x0D, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAC, 0xCB, 0xD8, 0x55, 0xAA +}; +#endif + +static virfat_flash_t virfat_flash; +static u8 curr_file = 0xff; +volatile char vir_file_type = 0; +u32 change_flag = 0; +static void *fd; + + + +static u32 get_first_one(u32 n) +{ + u32 pos = 0; + for (pos = 0; pos < 32; pos++) { + if (n & BIT(pos)) { + return pos; + } + } + return 0xff; + +} + +static bool virfat_flash_mount(virfat_flash_t *disk_handler, u8 *buf) +{ + u32 fatsize; + u32 maxclust; + u32 sects_fat; + u32 n_rootdir; + + /*计算FAT表大小*/ + fatsize = ld_word(&buf[BPB_FATSz16]); /* Number of sectors per FAT */ + if (!fatsize) { + fatsize = ld_dword(&buf[BPB_FATSz32]); + } + + disk_handler->fatsize = fatsize * 512; //fat表大小 byte. + disk_handler->fatbase = ld_word(&buf[BPB_RsvdSecCnt]); /* FAT start sector (lba) */ + /* disk_handler->fatbase2 = disk_handler->fatbase + fatsize; */ + + fatsize *= buf[BPB_NumFATs]; + + disk_handler->csize = get_first_one(buf[BPB_SecPerClus]); /* Number of sectors per cluster */ + + n_rootdir = ld_word(&buf[BPB_RootEntCnt]); /* Nmuber of root directory entries */ + + disk_handler->database = (disk_handler->fatbase + fatsize + n_rootdir / 16); /* Data start sector (lba) */ + + + /*计算总容量*/ + disk_handler->capacity = ld_word(&buf[BPB_TotSec16]); /* Number of sectors on the file system */ + if (!disk_handler->capacity) { + disk_handler->capacity = ld_dword(&buf[BPB_TotSec32]); + } + /* r_printf(">>>[test]:cap = 0x%x, csize = %d\n",disk_handler->capacity, disk_handler->csize); */ + maxclust = (disk_handler->capacity - ld_word(&buf[BPB_RsvdSecCnt]) - fatsize - + n_rootdir / 16) >> disk_handler->csize; + disk_handler->max_clust = maxclust + 2; + /* r_printf(">>>[test]:maxclust = %d\n", maxclust); */ + + disk_handler->fs_type = (maxclust >= MIN_FAT32) ? FS_FAT32 : ((maxclust >= MIN_FAT16) ? FS_FAT16 : FS_FAT12); + /* r_printf(">>>[test]:fs_type = 0x%x\n", disk_handler->fs_type); */ + + /* Root directory start cluster */ + if (disk_handler->fs_type == FS_FAT32) { + disk_handler->dirbase = disk_handler->database; + disk_handler->database += 1 << disk_handler->csize; + } else { + disk_handler->dirbase = disk_handler->fatbase + fatsize; + } + + disk_handler->clustSize = disk_handler->csize + 9; + + return TRUE; +} + +static void vir_read_reserved_area(u8 *buf, u32 len) +{ + memset(buf, 0, len); +} + + +static void vir_read_BPB(u8 *buf, u32 offset, u32 len) +{ + /* u8 bpb_jl_head[] = "JLBT_DISK"; */ + + /* memset(buf, 0, 512); */ + memcpy(buf, bpb_data + offset, len); + + /* memcpy(buf + sizeof(bpb_data), bpb_jl_head, sizeof(bpb_jl_head)); */ + + /* buf[510] = 0x55; */ + /* buf[511] = 0xAA; */ +} + +static u32 virfat_write(void *buf, u32 addr, u32 len) +{ + u32 wlen; + static u32 clen = 4096; + if ((clen % 4096) == 0) { + dev_ioctl(fd, IOCTL_ERASE_SECTOR, addr); + clen = 0; + } + wlen = dev_bulk_write(fd, buf, addr, len); + clen += len; + return wlen; +} + +AT_VOLATILE_RAM_CODE +static u32 virfat_flash_read(void *buf, u32 addr_sec, u32 len) +{ + /* y_printf("[r:%d],,", addr_sec); */ + u32 real_addrsec = 0; + u32 rlen; + if (addr_sec == 0) { + vir_read_BPB(buf, 0, 512); + y_printf("fatbase:%d \n", virfat_flash.fatbase); + y_printf("dirbase:%d \n", virfat_flash.dirbase); + y_printf("database:%d \n", virfat_flash.database); + return len; + } else if (addr_sec < 4096 / 512) { + vir_read_reserved_area(buf, len); + return len; + } else { + real_addrsec = addr_sec - 4096 / 512; + } + /* r_printf(">>>[test]:real-add= %d\n",real_addrsec); */ + + /* rlen = dev_bulk_read(fd, buf, real_addrsec * 512, len); */ + rlen = _norflash_read_watch(buf, real_addrsec * 512, len, 1); + /* if (rlen != len) { */ + /* log_e("read error!!!!!!!!!!!!!"); */ + /* } */ + /* return rlen; */ + return len; +} + + +static u32 virfat_flash_write(void *buf, u32 addr_sec, u32 len) +{ + /* r_printf("[w:%d],,", addr_sec); */ + u8 *buf_temp = (u8 *)malloc(4096); + u32 wlen = 0; + u32 real_addrsec = 0; + if (addr_sec == 0) { + return len; + } else if (addr_sec < 4096 / 512) { + return len; + } else if (addr_sec < virfat_flash.fatbase) { + real_addrsec = addr_sec - 4096 / 512 + 0; // 0为flash里面保留区域(备份fat表和目录项)实际位置。 + } else if (addr_sec < virfat_flash.dirbase) { + real_addrsec = addr_sec - 4096 / 512; + /* real_addrsec = addr_sec - virfat_flash.fatbase + 8 * 1024 * UNIT / 512; // 8KxUNIT为flash里面fat表实际位置。 */ + int real_fatbase = virfat_flash.fatbase * 512 - 4096; + dev_bulk_read(fd, buf_temp, real_fatbase, 4096); + dev_ioctl(fd, IOCTL_ERASE_SECTOR, real_fatbase); + memcpy(buf_temp + (addr_sec - virfat_flash.fatbase) * 512, buf, len); + wlen = dev_bulk_write(fd, buf_temp, real_fatbase, 4096); + len = 4096; + } else if (addr_sec < virfat_flash.database) { + real_addrsec = addr_sec - 4096 / 512; + int real_dirbase = virfat_flash.dirbase * 512 - 4096; + /* real_addrsec = addr_sec - virfat_flash.dirbase + 12 * 1024 * UNIT / 512; // 12KxUNIT为flash里面目录项实际位置。 */ + dev_bulk_read(fd, buf_temp, real_dirbase, 4096); + dev_ioctl(fd, IOCTL_ERASE_SECTOR, real_dirbase); + memcpy(buf_temp + (addr_sec - virfat_flash.dirbase) * 512, buf, len); + wlen = dev_bulk_write(fd, buf_temp, real_dirbase, 4096); + len = 4096; + } else { + real_addrsec = addr_sec - 4096 / 512; + /* real_addrsec = addr_sec - virfat_flash.database + 16 * 1024 * UNIT / 512; // 16KxUNIT为flash里面数据区实际位置。 */ + /* wlen = virfat_write(buf, real_addrsec * 512, len); */ + wlen = dev_bulk_write(fd, buf, real_addrsec * 512, len); + } + free(buf_temp); + buf_temp = NULL; + if (wlen != len) { + r_printf(">>>[test]:wlen = %d, len = %d\n", wlen, len); + log_e("write error!!!!!!!!!!!!!"); + } + return wlen; +} + +AT_VOLATILE_RAM_CODE +u32 virfat_flash_read_watch(void *buf, u32 addr_sec, u32 len) +{ + /* y_printf("[r:%d],,", addr_sec); */ + u32 real_addrsec = 0; + u32 rlen; + /* if (addr_sec == 0) { */ + if (addr_sec < 512) { + vir_read_BPB(buf, addr_sec, len); + y_printf("fatbase:%d \n", virfat_flash.fatbase); + y_printf("dirbase:%d \n", virfat_flash.dirbase); + y_printf("database:%d \n", virfat_flash.database); + return len; + } else if (addr_sec < 4096) { + vir_read_reserved_area(buf, len); + return len; + } else { + real_addrsec = addr_sec - 4096 ; + } + /* r_printf(">>>[test]:real-add= %d\n",real_addrsec); */ + rlen = _norflash_read_watch(buf, real_addrsec, len, 1); + /* rlen = dev_bulk_read(fd, buf, real_addrsec, len); */ + if (rlen == 0) { + return len; + } + return rlen; +} + +u32 virfat_flash_write_watch(void *buf, u32 addr_sec, u32 len) +{ + u32 wlen; + u32 real_addrsec = 0; + if (addr_sec == 0) { + return len; + } else if (addr_sec < 4096) { + return len; + } else { + real_addrsec = addr_sec - 4096; + } + wlen = dev_bulk_write(fd, buf, real_addrsec, len); + if (wlen != len) { + r_printf(">>>[test]:wlen = %d, len = %d\n", wlen, len); + log_e("write error!!!!!!!!!!!!!"); + } + return wlen; +} + +u32 virfat_flash_erase_watch(int cmd, u32 arg) +{ + if (arg == 0) { + return 0; + } else if (arg < 4096) { + return 0; + } else { + arg = arg - 4096; + } + return dev_ioctl(fd, cmd, arg); +} +u32 virfat_flash_erase(int cmd, u32 arg) +{ + return dev_ioctl(fd, cmd, arg); +} + +u32 virfat_flash_capacity() //fat上容量 +{ + return virfat_flash.capacity * 512; +} + +u32 virfat_flash_get_real_capacity() //获取实际flash容量 +{ + u32 capacity; + dev_ioctl(fd, IOCTL_GET_CAPACITY, (u32)&capacity); + return capacity; +} + +#define BUF_LEN 4096 +void virfat_flash_get_dirinfo(void *file_buf, u32 *file_num) +{ + u32 cnt = 0; + u8 *buf = malloc(BUF_LEN); + u8 name_buf[12] = {0}; + u32 dir_len = (virfat_flash.database - virfat_flash.dirbase) * 512; + for (int k = 0; k < dir_len; k += BUF_LEN) { + virfat_flash_read_watch(buf, virfat_flash.dirbase * 512 + k, BUF_LEN); + for (int i = 0; i < BUF_LEN; i += 32) { + memset(name_buf, 0, 12); + memcpy(name_buf, buf + i, 12); + if (name_buf[0] == 0xE5) { + continue; + } + if ((name_buf[0] != 0) && (name_buf[1] != 0)) { + if (file_buf) { + memcpy(file_buf + cnt * 12, name_buf, 12); + } + cnt++; + /* r_printf(">>>[test]:name = %s\n", name_buf); */ + } else { + /* y_printf("\n >>>[test]:func = %s,line= %d\n",__FUNCTION__, __LINE__); */ + break; + } + } + } + *file_num = cnt; + free(buf); + +} + +static u32 virfat_flash_available() +{ + return 1; +} + + +u8 virfat_flash_init(void *buf_512) +{ + vir_read_BPB(buf_512, 0, 512); + + virfat_flash_mount(&virfat_flash, buf_512); + + + /* y_printf("fatbase:%d \n", virfat_flash.fatbase); */ + /* y_printf("dirbase:%d \n", virfat_flash.dirbase); */ + /* y_printf("database:%d \n", virfat_flash.database); */ + /* y_printf("clustSize:%d \n", virfat_flash.clustSize); */ + + return 0; +} +//////////////////////////////////////////////////////////////////////////////////////////////// +////////////////////////////device api////////////////////////////////////////////////////////// + +static struct device virfat_flash_dev; +static int flash_virfat_init(const struct dev_node *node, void *arg) +{ + u8 buf[512] = {0}; + memcpy(&virfat_flash.re_devname, arg, strlen(arg)); + /* r_printf(">>>[test]:init name = %s\n", virfat_flash.re_devname); */ + virfat_flash_init(buf); + return 0; +} + +static int flash_virfat_open(const char *name, struct device **device, void *arg) +{ + /* y_printf(">>>[test]:dev_name = %s\n", virfat_flash.re_devname); */ + fd = dev_open((const char *)&virfat_flash.re_devname, arg); + *device = &virfat_flash_dev; + return 0; +} +#if 0 +AT_VOLATILE_RAM_CODE +int flash_virfat_read(struct device *device, void *buf, u32 len, u32 addr) +{ + /* y_printf(">>>[test]:r;addr = %d ,len = %d\n", addr, len); */ + virfat_flash_read_watch(buf, addr, len); + return len; +} +#else +AT_VOLATILE_RAM_CODE +int flash_virfat_read(struct device *device, void *buf, u32 len, u32 addr) +{ + /* y_printf(">>>[test]:r;addr = %d ,len = %d\n", addr, len); */ + void *_buf = buf; + u32 _len = len; + u32 _lba = addr; + while (_len) { + virfat_flash_read(_buf, _lba, 512); + //printf_buf(_buf, 512); + _len -= 1; + _lba += 1; + _buf += 512; + } + return len; + + /* return virfat_flash_read(buf, addr, len); */ +} +#endif +static int flash_virfat_write(struct device *device, void *buf, u32 len, u32 addr) +{ + + /* r_printf(">>>[test]:w;addr = %d ,len = %d\n", addr, len); */ + /* return virfat_flash_write(buf, addr, len); */ + void *_buf = buf; + u32 _len = len; + u32 _lba = addr; + while (_len) { + virfat_flash_write(_buf, _lba, 512); + //printf_buf(_buf, 512); + _len -= 1; + _lba += 1; + _buf += 512; + } + return len; + +} + +static bool flash_virfat_online(const struct dev_node *node) +{ + return 1; +} + +static int flash_virfat_close(struct device *device) +{ + dev_close(device); + return 0; +} +static int flash_virfat_ioctrl(struct device *device, u32 cmd, u32 arg) +{ + int err = 0; + switch (cmd) { + case IOCTL_GET_STATUS: + *(u32 *)arg = 1; + break; + case IOCTL_GET_ID: + dev_ioctl(device, IOCTL_GET_ID, arg); + /* *((u32 *)arg) = 0x12345678; */ + break; + case IOCTL_GET_CAPACITY: + *((u32 *)arg) = virfat_flash_capacity(); + break; + case IOCTL_GET_BLOCK_SIZE: + *((u32 *)arg) = 512; + break; + case IOCTL_ERASE_SECTOR: + /* y_printf(">>>[test]:in flash_vir eraser addr = %d\n", arg); */ + err = virfat_flash_erase(cmd, arg); + break; + case IOCTL_FLUSH: + break; + case IOCTL_CMD_RESUME: + break; + case IOCTL_CMD_SUSPEND: + break; + case IOCTL_SET_ASYNC_MODE: + break; + default: + err = -EINVAL; + break; + } + return err; +} + +const struct device_operations virfat_flash_dev_ops = { + .init = flash_virfat_init, + .online = flash_virfat_online, + .open = flash_virfat_open, + .read = flash_virfat_read, + .write = flash_virfat_write, + .ioctl = flash_virfat_ioctrl, + .close = flash_virfat_close, +}; + +#endif diff --git a/apps/common/file_operate/file_api.c b/apps/common/file_operate/file_api.c new file mode 100644 index 0000000..541d8bf --- /dev/null +++ b/apps/common/file_operate/file_api.c @@ -0,0 +1,175 @@ + +#if 0 +#include "app_config.h" +#include "system/includes.h" +#include "system/os/os_cpu.h" +#include "file_operate/file_bs_deal.h" + +// folder : /xxxxxx +// filename : xxxx0000.yyy +FILE *file_api_auto_create_file(const char *path, const char *folder, const char *filename, u32 *file_index) +{ + int ret; + u32 last_num = (u32) - 1; + u32 total_num = 0; + u32 err_cnt = 0; + FILE *pfil = NULL; + char *create_file_name = NULL; + char *file_num_str; + char *ext; + +#if TCFG_NOR_FS_ENABLE + extern int nor_fs_index; + extern int recfs_scan_ex(); + nor_fs_index = recfs_scan_ex(); + last_num = nor_fs_index + 1; + create_file_name = zalloc(strlen(path) + strlen(folder) + strlen(filename) + 3); + if (!create_file_name) { + log_w("malloc err"); + return NULL; + } + strcat(create_file_name, path); + strcat(create_file_name, folder + 1); + strcat(create_file_name, "/"); + strcat(create_file_name, filename); + + file_num_str = strrchr(create_file_name, '.') - 4; + + if (last_num > 9999) { + last_num = 0; + } + file_num_str[0] = last_num / 1000 + '0'; + file_num_str[1] = last_num % 1000 / 100 + '0'; + file_num_str[2] = last_num % 100 / 10 + '0'; + file_num_str[3] = last_num % 10 + '0'; + log_i("createfile:%s ", create_file_name); + if (file_index) { + *file_index = last_num; + } + + pfil = fopen(create_file_name, "w+"); + + if (create_file_name) { + free(create_file_name); + } + return pfil; +#endif + + ext = strrchr(filename, '.'); + if (!ext) { + log_w("ext err"); + return NULL; + } + ext++; + ret = fget_encfolder_info(path, folder, ext, &last_num, &total_num); + if (ret) { + log_w("fget_encfolder_info err"); + return NULL; + } + log_i("foler:%s, total:%d, last:%d ", folder, total_num, last_num); + last_num ++; + if ((last_num >= 9999) && (total_num >= 9999)) { + log_w("file num err"); + return NULL; + } + if (total_num == 0) { + log_i("make dir"); + fmk_dir(path, folder, 0); + } + + create_file_name = zalloc(strlen(path) + strlen(folder) + strlen(filename) + 3); + if (!create_file_name) { + log_w("malloc err"); + return NULL; + } + strcat(create_file_name, path); + strcat(create_file_name, folder + 1); + strcat(create_file_name, "/"); + strcat(create_file_name, filename); + + file_num_str = strrchr(create_file_name, '.') - 4; + +_get_file: + if (last_num > 9999) { + last_num = 0; + } + file_num_str[0] = last_num / 1000 + '0'; + file_num_str[1] = last_num % 1000 / 100 + '0'; + file_num_str[2] = last_num % 100 / 10 + '0'; + file_num_str[3] = last_num % 10 + '0'; + log_i("createfile:%s ", create_file_name); + if (file_index) { + *file_index = last_num; + } + + pfil = fopen(create_file_name, "r"); + if (pfil) { + log_i("file already exists "); + fclose(pfil); + pfil = NULL; + err_cnt ++; + if (err_cnt >= 9999) { + log_w("err cnt "); + goto _exit; + } + last_num ++; + goto _get_file; + } else { + pfil = fopen(create_file_name, "w+"); + } + +_exit: + if (create_file_name) { + free(create_file_name); + } + return pfil; +} + +#if 0 +void file_create_test(void) +{ + struct storage_dev *dev = storage_dev_last(); + printf("%s,%d ", __func__, __LINE__); + if (!dev) { + printf("%s,%d ", __func__, __LINE__); + return ; + } + printf("%s,%d ", __func__, __LINE__); + printf("devname:%s, pa:%s, fs:%s ", dev->dev_name, dev->storage_path, dev->fs_type); + /* void *fmnt = mount(dev->dev_name, dev->storage_path, dev->fs_type, 3, NULL); */ + /* if (!fmnt) { */ + /* printf("%s,%d ", __func__, __LINE__); */ + /* return ; */ + /* } */ + FILE *pfil = file_api_auto_create_file(dev->root_path, "/JL_REC", "AC690000.MP3", NULL); + if (pfil) { + u8 str[] = "This is a test string."; + u8 buf[10]; + int i; + int len; + int addr; + for (i = 0; i < 100; i++) { + len = fwrite(pfil, str, sizeof(str)); + if (len != sizeof(str)) { + log_i("write file ERR!"); + } + } + len = flen(pfil); + addr = fpos(pfil); + log_i("fl:%d, addr:%d ", len, addr); + + fseek(pfil, 0, SEEK_SET); + len = fread(pfil, buf, sizeof(buf)); + if (len != sizeof(buf)) { + log_i("read file ERR!"); + } + put_buf(buf, sizeof(buf)); + + fseek(pfil, addr, SEEK_SET); + fclose(pfil); + } + /* unmount(dev->storage_path); */ +} +#endif + +#endif diff --git a/apps/common/file_operate/file_bs_deal.c b/apps/common/file_operate/file_bs_deal.c new file mode 100644 index 0000000..f3bdf1a --- /dev/null +++ b/apps/common/file_operate/file_bs_deal.c @@ -0,0 +1,488 @@ +/* + ********************************************************************************************************* + * AC51 + * fs browser select + * CODE + * + * (c) Copyright 2015-2016, ZHUHAI JIELI + * All Rights Reserved + * + * File : * + * By : jamin.li + * DATE : 2015-10-15 build this file + ********************************************************************************************************* + */ + +#include "file_bs_deal.h" +#include "uart.h" +#include "dev_manager.h" + +#define FILE_BS_OPT_DBG +#ifdef FILE_BS_OPT_DBG + +#define file_bs_puts puts +#define file_bs_printf printf + +#else +#define file_bs_puts(...) +#define file_bs_printf(...) + +#endif + +/* + ********************************************************************************************************* + * + * Description: 在指定数据中,搜索key(byte)的位置 + * + * Arguments : buf - 指定数据起始地址, buf_len-长度, key-搜索的key, + * find_type -搜索方向:0-从前往后搜索,1-从后往前搜索 + * + * Returns : key的位置 + * + * Note: + ********************************************************************************************************* + */ +//查找byte的位置 +static int find_byte_pos(u8 *buf, u16 buf_len, u8 key, u8 find_type) +{ + u8 *data = buf; + + if (0 == find_type) { + //从前往后找 + while (buf_len > 0) { + if (*data == key) { + return (int)(data - buf); + } + data++; + buf_len--; + } + } else { + //从后往前找 + data += (buf_len - 1); + while (buf_len > 0) { + if (*data == key) { + return (int)(data - buf); + } + data--; + buf_len--; + } + } + return -1; +} + + +/* + ********************************************************************************************************* + * + * Description: 转化路径格式 + * + * Arguments : + * + * Returns : 0-为成功,其他值 失败 + * + * Note: + ********************************************************************************************************* + */ +int file_comm_change_file_path(char *dest, char *src) +{ + u8 start_flag = 0, space_flag, val; + + while (1) { + val = *src; + if (val == '\0') { + *dest = '\0'; + break; + } + switch (val) { + case '/': + if (start_flag != 0) { + space_flag = 0; + } + start_flag++; + *dest = val; + break; + + case ' ': + space_flag = 1; + break; + + default: + if (space_flag != 0) { + *dest = '.'; + dest++; + space_flag = 0; + } + *dest = val; + break; + } + + dest++; + src++; + } + + return 0; +} + +/* + ********************************************************************************************************* + * + * Description: 修正从fs取等的长名 + * + * Arguments : str,len + * + * Returns : 字节长度(不包含结束符) + * + * Note: 过滤0xffff值,自动填入结束符 + ********************************************************************************************************* + */ +int file_comm_long_name_fix(u8 *str, u16 len) +{ + u8 *src = str; + while (len > 1) { + if ((*str == 0xff) && (*(str + 1) == 0xff)) { + break; + } + + if ((*str == 0x0) && (*(str + 1) == 0x0)) { + break; + } + + str += 2; + len -= 2; + } + *str = 0x00; + *(str + 1) = 0x00; + return (int)(str - src); +} + +/* + ********************************************************************************************************* + * + * Description: 转换8+3名字显示 + * + * Arguments : dest,src + * + * Returns : 转换后名字的长度(不包含结束符) + * + * Note: 转换后自动填入结束符 + ********************************************************************************************************* + */ +int file_comm_display_83name(u8 *dest, u8 *src) +{ + u8 offset; + + for (offset = 8; offset > 0; offset--) { + if (src[offset - 1] != 0x20) { + break; + } + } + + memcpy(dest, src, offset); + + if (src[8] != 0x20) { + dest[offset++] = '.'; + memcpy(dest + offset, src + 8, 3); + offset += 3; + } + + dest[offset++] = '\0'; + + return offset; //name 's len +} + +/* + ********************************************************************************************************* + * + * Description: 获取显示的文件夹或文件名字 + * + * Arguments :tpath,disp_file_name,disp_dir_name + * + * Returns : + * + * Note: 转换后 lfn_cnt 为0为短名,lfn_cnt不为0 则是长名 + ********************************************************************************************************* + */ +void file_comm_change_display_name(char *tpath, LONG_FILE_NAME *disp_file_name, LONG_FILE_NAME *disp_dir_name) +{ + u16 len; + int pos; + + //取文件名字显示 + + if (disp_file_name != NULL) { + if (disp_file_name->lfn_cnt != 0) { + //long name + file_bs_puts("file long name \n"); + //printf_buf(disp_file_name->lfn, 16); + disp_file_name->lfn_cnt = file_comm_long_name_fix((void *)disp_file_name->lfn, disp_file_name->lfn_cnt); //增加结束符 + } else { + //short name + file_bs_puts("file short name\n"); + len = strlen((void *)tpath); //增加结束符 + pos = find_byte_pos((void *)tpath, len, 0x2f, 1); // + if (pos == -1) { + strcpy(disp_file_name->lfn, "----"); + } else { + memcpy((void *)&disp_file_name->lfn[32], tpath + pos + 1, 11); + file_comm_display_83name((void *)disp_file_name->lfn, (void *)&disp_file_name->lfn[32]); + } + + disp_file_name->lfn_cnt = 0; + } + + //printf_buf(disp_file_name->lfn, 32); + + } + + + //取文件夹名字显示 + if (disp_dir_name != NULL) { + if (disp_dir_name->lfn_cnt != 0) { + //long name + file_bs_puts("folder long name \n"); + //printf_buf(disp_dir_name->lfn, 16); + disp_dir_name->lfn_cnt = file_comm_long_name_fix((void *)&disp_dir_name->lfn, disp_dir_name->lfn_cnt); //增加结束符 + } else { + //short name + file_bs_puts("folder short name \n"); + len = strlen((void *)tpath); //增加结束符 + pos = find_byte_pos((void *)tpath, len, 0x2f, 1); // + + if (pos != -1) { + pos = find_byte_pos((void *)tpath, pos, 0x2f, 1); // + } + + if (pos == -1) { + strcpy(disp_dir_name->lfn, "ROOT"); + } else { + memcpy(&disp_dir_name->lfn[32], tpath + pos + 1, 11); + file_comm_display_83name((void *)disp_dir_name->lfn, (void *)&disp_dir_name->lfn[32]); + } + disp_dir_name->lfn_cnt = 0; + } + + //printf_buf(disp_dir_name->lfn, 32); + } +} +/* + ********************************************************************************************************* + * + * Description: 打开文件浏览器 + * + * Arguments : fil_bs + * + * Returns : dir的总数 + * + * Note: + ********************************************************************************************************* + */ +//返回根目录dir总数 +u32 file_bs_open_handle(FILE_BS_DEAL *fil_bs, u8 *ext_name) +{ + u32 total_dir; + + if (fil_bs == NULL) { + puts("*open hdl is null\n"); + return 0; + } + + file_bs_puts("open bs hdl\n"); + file_bs_printf("bs_mapi:0x%x\n", (int)fil_bs); + + if (ext_name == NULL) { + ext_name = "MP3";//"WAVWMAMP3FLA"; + } + + printf("fil_bs->dev = %x\n", fil_bs->dev); + printf("%s, %s, %s, %d\n]", dev_manager_get_root_path(fil_bs->dev), dev_manager_get_logo(fil_bs->dev), __FUNCTION__, __LINE__); + fset_ext_type(dev_manager_get_root_path(fil_bs->dev), ext_name); + printf("%s, %d\n]", __FUNCTION__, __LINE__); + + total_dir = fopen_dir_info(dev_manager_get_root_path(fil_bs->dev), &fil_bs->file, 0); + printf("%s, %d\n]", __FUNCTION__, __LINE__); + if (fil_bs->file == 0) { + file_bs_puts("open bs fail\n"); + return 0; + } + file_bs_printf("open bs hdl_out,root_dir = 0x%x\n", total_dir); + return total_dir; +} + +/* + ********************************************************************************************************* + * + * Description: 关闭文件浏览器 + * + * Arguments : fil_bs + * + * Returns : + * + * Note: + ********************************************************************************************************* + */ +void file_bs_close_handle(FILE_BS_DEAL *fil_bs) +{ + file_bs_puts("close bs hdl\n"); + if (fil_bs->file) { + fclose(fil_bs->file); + fil_bs->file = NULL; + } + file_bs_puts("close bs hdl_out\n"); +} + +/* + ********************************************************************************************************* + * + * Description: 进入文件夹目录 + * + * Arguments : fil_bs,dir_info + * + * Returns : dir的总数 + * + * Note: + ********************************************************************************************************* + */ +u32 file_bs_entern_dir(FILE_BS_DEAL *fil_bs, FS_DIR_INFO *dir_info) +{ + u32 total_dir; + file_bs_printf("bs_enter dir\n"); + total_dir = fenter_dir_info(fil_bs->file, dir_info); //使用open获得的file,无需重新申请。 + file_bs_printf("bs_enter_out,t = 0x%x\n", total_dir); + return total_dir; +} + +/* + ********************************************************************************************************* + * + * Description: 返回上传目录 + * + * Arguments : fil_bs + * + * Returns : dir的总数 + * + * Note: + ********************************************************************************************************* + */ +u32 file_bs_exit_dir(FILE_BS_DEAL *fil_bs) +{ + u32 total_dir; + file_bs_printf("bs_exit dir\n"); + total_dir = fexit_dir_info(fil_bs->file);// + file_bs_printf("bs_exit_out,total = 0x%x\n", total_dir); + return total_dir; +} + +/* + ********************************************************************************************************* + * + * Description: 获取指定位置的dir信息 + * + * Arguments : fil_bs,buf--被填入的buf,start_sn -获取的其实位置(从1开始),get_cnt--获取dir的个数 + * + * Returns : 真正获取到的dir总数 + * + * Note: + ********************************************************************************************************* + */ +u32 file_bs_get_dir_info(FILE_BS_DEAL *fil_bs, FS_DIR_INFO *buf, u16 start_sn, u16 get_cnt) +{ + u32 real_dir; + /* file_bs_printf("bs_get dir_info\n"); */ + real_dir = fget_dir_info(fil_bs->file, start_sn, get_cnt, buf); + /* file_bs_printf("bs_get_out,t = 0x%x\n", real_dir); */ + return real_dir; +} + + +////////////////////////////////////////////////////////////////////////// +// test + +#if 0 + +#define BS_GET_DIR_NUM 3 +void file_bs_test(void) +{ + printf("\n\n\n\n %s,%d, ", __func__, __LINE__); + FS_DIR_INFO *dir_buf = zalloc(sizeof(FS_DIR_INFO) * BS_GET_DIR_NUM); + FILE_BS_DEAL *fil_bs = zalloc(sizeof(FILE_BS_DEAL)); + if (!fil_bs || !dir_buf) { + printf("%s,%d, ", __func__, __LINE__); + printf("malloc err"); + while (1); + } + fil_bs->dev = storage_dev_last(); + if (!fil_bs->dev) { + printf("%s,%d, ", __func__, __LINE__); + printf("have no dev"); + while (1); + } + + /* void *fmnt = mount(fil_bs->dev->dev_name, fil_bs->dev->storage_path, fil_bs->dev->fs_type, 3, NULL); */ + /* if (!fmnt) { */ + /* printf("%s,%d, ", __func__, __LINE__); */ + /* printf("mount err"); */ + /* while(1); */ + /* } */ + + int i, j, cnt, total; + file_bs_open_handle(fil_bs, "MP3");//open完后需要close + /* printf("\n root dir num: %d ", total); */ + /* if (!total) { */ + /* printf("%s,%d, ", __func__, __LINE__); */ + /* printf("total dir is zero"); */ + /* goto __exit; */ + /* } */ + + total = file_bs_entern_dir(fil_bs, dir_buf); + /* printf("\n %s,%d, ", __func__, __LINE__); */ + /* printf("dir num: %d ", total); */ + if (!total) { + printf("%s,%d, ", __func__, __LINE__); + printf("total dir is zero"); + goto __exit; + } + + u8 flag = 0; + for (i = 1; i <= total; i += BS_GET_DIR_NUM) { +__again: + cnt = file_bs_get_dir_info(fil_bs, dir_buf, i, BS_GET_DIR_NUM); + /* printf("\n cnt:%d ", cnt); */ + for (j = 0; j < cnt; j++) { + /* printf("j:%d, dirtype:%d, fntype:%d, sclust:0x%x ", i + j, dir_buf[j].dir_type, dir_buf[j].fn_type, dir_buf[j].sclust); */ + if (dir_buf[j].dir_type == BS_DIR_TYPE_FORLDER) { + if (flag < 2) { + flag ++; + if (flag == 2) { + int sub_i, sub_j, sub_cnt, sub_total; + sub_total = file_bs_entern_dir(fil_bs, &dir_buf[j]); + /* printf("\n %s,%d, ", __func__, __LINE__); */ + /* printf("dir num: %d ", sub_total); */ + if (sub_total) { + for (sub_i = 1; sub_i <= sub_total; sub_i += BS_GET_DIR_NUM) { + sub_cnt = file_bs_get_dir_info(fil_bs, dir_buf, sub_i, BS_GET_DIR_NUM); + /* printf("sub_cnt:%d ", sub_cnt); */ + for (sub_j = 0; sub_j < sub_cnt; sub_j++) { + /* printf("sub_j:%d, dirtype:%d, fntype:%d, sclust:0x%x ", sub_i + sub_j, dir_buf[sub_j].dir_type, dir_buf[sub_j].fn_type, dir_buf[sub_j].sclust); */ + } + } + } + file_bs_exit_dir(fil_bs); + goto __again; + } + } + } + } + } + +__exit: + /* printf("\n %s,%d, \n ", __func__, __LINE__); */ + + file_bs_close_handle(fil_bs); + + /* unmount(fil_bs->dev->storage_path); */ + + free(dir_buf); + free(fil_bs); +} +#endif + diff --git a/apps/common/file_operate/file_bs_deal.h b/apps/common/file_operate/file_bs_deal.h new file mode 100644 index 0000000..373e703 --- /dev/null +++ b/apps/common/file_operate/file_bs_deal.h @@ -0,0 +1,47 @@ +/* + ********************************************************************************************************* + * AC46 + * fs browser select + * CODE + * + * (c) Copyright 2015-2016, ZHUHAI JIELI + * All Rights Reserved + * + * File : * + * By : jamin.li + * DATE : 2015-10-15 build this file + ********************************************************************************************************* + */ + +#ifndef _FILE_BS_DEAL_H_ +#define _FILE_BS_DEAL_H_ + +#include "fs/fs.h" +#include "storage_dev/storage_dev.h" + +#define BS_DIR_TYPE_FORLDER 0 +#define BS_DIR_TYPE_FILE 1 + +#define BS_FNAME_TYPE_SHORT 0 +#define BS_FNAME_TYPE_LONG 1 + +typedef struct _FILE_BS_DEAL_ { + struct __dev *dev; + FILE *file; +} FILE_BS_DEAL; + + +extern int file_comm_change_file_path(char *dest, char *src); +extern int file_comm_long_name_fix(u8 *str, u16 len); +extern int file_comm_display_83name(u8 *dest, u8 *src); + +extern u32 file_bs_open_handle(FILE_BS_DEAL *fil_bs, u8 *ext_name); +extern void file_bs_close_handle(FILE_BS_DEAL *fil_bs); +extern u32 file_bs_entern_dir(FILE_BS_DEAL *fil_bs, FS_DIR_INFO *dir_info); +extern u32 file_bs_exit_dir(FILE_BS_DEAL *fil_bs); +extern u32 file_bs_get_dir_info(FILE_BS_DEAL *fil_bs, FS_DIR_INFO *buf, u16 start_sn, u16 get_cnt); + +extern void file_comm_change_display_name(char *tpath, LONG_FILE_NAME *disp_file_name, LONG_FILE_NAME *disp_dir_name); + +#endif/*_FILE_BS_DEAL_H_*/ + diff --git a/apps/common/file_operate/file_manager.c b/apps/common/file_operate/file_manager.c new file mode 100644 index 0000000..651b90b --- /dev/null +++ b/apps/common/file_operate/file_manager.c @@ -0,0 +1,153 @@ +#include "file_manager.h" +#include "app_config.h" + +#define MODE_FIX 0 +#if MODE_FIX +static int file_manager_mode_deal(struct vfscan *fs, int sel_mode, int *arg) +{ + + int err; + int fnum = 0; + int file_start = 1; + int file_end = fs->file_number; + + if (file_end == 0) { + return -ENOENT; + } + struct ffolder folder = {0}; + fget_folder(fs, &folder); + /* if ((scan->cycle_mode == FCYCLE_FOLDER) && (scan->ff_api.fileTotalInDir) */ + /* && ((scan->ff_api.fileTotalOutDir + scan->ff_api.fileTotalInDir) <= scan->ff_api.totalFileNumber) */ + /* ) { */ + + if ((fs->cycle_mode == FCYCLE_FOLDER) && (folder.fileTotal) + && ((folder.fileStart + folder.fileTotal - 1) <= file_end) + ) { + file_start = folder.fileStart; + file_end = folder.fileStart + folder.fileTotal - 1; + } + switch (sel_mode) { + case FSEL_LAST_FILE: + fnum = fs->file_number; + break; + case FSEL_FIRST_FILE: + fnum = 1; + break; + case FSEL_AUTO_FILE: + /* if (scan->ff_api.fileNumber == 0) { */ + /* return -EINVAL; */ + /* } */ + if (fs->cycle_mode == FCYCLE_ONE) { + /* fnum = scan->ff_api.fileNumber; */ + fnum = fs->file_counter; + break; + } + case FSEL_NEXT_FILE: + /* if (scan->ff_api.fileNumber == 0) { */ + /* return -EINVAL; */ + /* } */ + if (fs->cycle_mode == FCYCLE_RANDOM) { + fnum = rand32() % (file_end - file_start + 1) + file_start; + if (fnum == fs->file_counter) { + fnum = fs->file_counter + 1; + } + } else { + fnum = fs->file_counter + 1; + } + /* if (fnum > scan->last_file_number) { */ + if (fnum > fs->file_number) { + if (fs->cycle_mode == FCYCLE_LIST) { + return -ENOENT; + } else if (fs->cycle_mode == FCYCLE_FOLDER) { + fnum = file_start; + } else { + fnum = 1; + } + } + if (fnum > file_end) { + fnum = file_start; + } else if (fnum < file_start) { + fnum = file_end; + } + break; + case FSEL_PREV_FILE: + /* if (scan->ff_api.fileNumber == 0) { */ + /* return -EINVAL; */ + /* } */ + if (fs->cycle_mode == FCYCLE_RANDOM) { + fnum = rand32() % (file_end - file_start + 1) + file_start; + if (fnum == fs->file_counter) { + fnum = fs->file_counter + 1; + } + } else { + fnum = fs->file_counter - 1; + } + /* if ((scan->ff_api.fileNumber | BIT(15)) != scan->cur_file_number) { */ + /* fnum -= scan->last_file_number - scan->ff_api.totalFileNumber; */ + /* } */ + /* scan->last_file_number = scan->ff_api.totalFileNumber; */ + if (fs->cycle_mode == FCYCLE_LIST) { + break; + } + if (fnum > file_end) { + fnum = file_start; + } else if (fnum < file_start) { + fnum = file_end; + } + break; + + case FSEL_NEXT_FOLDER_FILE: + /* fnum = scan->ff_api.fileTotalOutDir + scan->ff_api.fileTotalInDir + 1; */ + fnum = folder.fileStart + folder.fileTotal; + if (fnum > fs->file_number) { + fnum = 1; + } + break; + case FSEL_PREV_FOLDER_FILE: + /* if ((scan->ff_api.fileTotalOutDir + 1) > 1) { */ + if (folder.fileStart > 1) { + fnum = folder.fileStart - 1; + } else { + fnum = fs->file_number; + } + break; + default: + return -EINVAL; + } + + if ((sel_mode != FSEL_NEXT_FOLDER_FILE) && (sel_mode != FSEL_PREV_FOLDER_FILE)) { + if (fnum < file_start) { + fnum = file_start; + } else if (fnum > file_end) { + fnum = file_end; + } + } + *arg = fnum; + return 0; +} +#endif + +FILE *file_manager_select(struct __dev *dev, struct vfscan *fs, int sel_mode, int arg, struct __scan_callback *callback) +{ + FILE *_file = NULL; + //clock_add_set(SCAN_DISK_CLK); + if (callback && callback->enter) { + callback->enter(dev);//扫描前处理, 可以在注册的回调里提高系统时钟等处理 + } +#if MODE_FIX + if ((sel_mode != FSEL_BY_SCLUST) && (sel_mode != FSEL_BY_PATH)) { + if (file_manager_mode_deal(fs, sel_mode, &arg)) { + return NULL; + } + sel_mode = FSEL_BY_NUMBER; + } +#endif + _file = fselect(fs, sel_mode, arg); + //clock_remove_set(SCAN_DISK_CLK); + if (callback && callback->exit) { + callback->exit(dev);//扫描后处理, 可以在注册的回调里还原到enter前的状态 + } + return _file; +} + + diff --git a/apps/common/file_operate/file_manager.h b/apps/common/file_operate/file_manager.h new file mode 100644 index 0000000..0f6a3c6 --- /dev/null +++ b/apps/common/file_operate/file_manager.h @@ -0,0 +1,11 @@ +#ifndef __FILE_MANAGER_H__ +#define __FILE_MANAGER_H__ + +#include "system/includes.h" +#include "typedef.h" +#include "system/fs/fs.h" +#include "dev_manager.h" + +FILE *file_manager_select(struct __dev *dev, struct vfscan *fs, int sel_mode, int arg, struct __scan_callback *callback); + +#endif// __FILE_MANAGER_H__ diff --git a/apps/common/iap/iAP_des.c b/apps/common/iap/iAP_des.c new file mode 100644 index 0000000..e66806f --- /dev/null +++ b/apps/common/iap/iAP_des.c @@ -0,0 +1,48 @@ + +#include "apple_dock/iAP.h" +#include "apple_dock/iAP2.h" +#include "apple_dock/iAP_device.h" +/* #include "apple_dock/descriptor_iap.h" */ + +#include "app_config.h" + +#if TCFG_USB_APPLE_DOCK_EN + +#define ID_INFORMATION 0x1D01L + +const u8 iAP2_message_name[] = { + GET_U16L(SW16(START_OF_MESSAGE)), GET_U16H(SW16(START_OF_MESSAGE)), + 0x00, 0x00, + GET_U16L(SW16(ID_INFORMATION)), GET_U16H(SW16(ID_INFORMATION)), + + //Name--can alter + 0x00, 4 + IAP2_ACCESSORY_NAME_LEN, 0x00, 0x00, IAP2_ACCESSORY_NAME, + //ModelIdentifier(模式描述符)--can alter + 0x00, 4 + IAP2_ACCESSORY_MODEL_IDENTIFIER_LEN, 0x00, 0x01, IAP2_ACCESSORY_MODEL_IDENTIFIER, + //Manufacturer(制造商)--can alter + 0x00, 4 + IAP2_ACCESSORY_MANUFACTURER_LEN, 0x00, 0x02, IAP2_ACCESSORY_MANUFACTURER, + //SerialNumber(序列号)--can alter + 0x00, 4 + IAP2_ACCESSORY_SERIALNUMBER_LEN, 0x00, 0x03, IAP2_ACCESSORY_SERIALNUMBER, + //FirmwareVersion(固件版本)--can alter + 0x00, 4 + IAP2_ACCESSORY_FIRMWARE_VER_LEN, 0x00, 0x04, IAP2_ACCESSORY_FIRMWARE_VER, + //HardwareVersion(硬件版本)--can alter + 0x00, 4 + IAP2_ACCESSORY_HARDWARE_VER_LEN, 0x00, 0x05, IAP2_ACCESSORY_HARDWARE_VER, +}; + +const u32 iAP2_str_tab[] = { + (u32)iAP2_message_name, sizeof(iAP2_message_name), +}; + +#if 0 +const IAP_USB_DEVICE_STRING IAP_USB_string_set[] = { + {(u8 *)IAP_sDeviceDescriptor, sizeof(IAP_sDeviceDescriptor)}, + {(u8 *)IAP_sConfigDescriptor, sizeof(IAP_sConfigDescriptor)}, + {(u8 *)IAP_iManufacturer, sizeof(IAP_iManufacturer)}, + {(u8 *)IAP_iProduct, sizeof(IAP_iProduct)}, + {(u8 *)IAP_iSerialNumber, sizeof(IAP_iSerialNumber)}, +}; +#endif + +#endif /* TCFG_USB_APPLE_DOCK_EN */ + + diff --git a/apps/common/iap/iAP_device.c b/apps/common/iap/iAP_device.c new file mode 100644 index 0000000..1b56cca --- /dev/null +++ b/apps/common/iap/iAP_device.c @@ -0,0 +1,144 @@ +/*************************************************************/ +/** @file: iAP.c + @brief: 苹果iAP 协议 + @details: + @author: Bingquan Cai + @date: 2013-10-11,09:34 + @note: +*/ +/*************************************************************/ +#include "apple_dock/iAP.h" +#include "apple_dock/iAP2.h" +#include "apple_dock/iAP_device.h" +#include "apple_dock/iAP_iic.h" +/* #include "usb_global_var.h" */ +/* #include "usb_driver.h" */ +/* #include "usb_slave_scsi.h" */ +#include "app_config.h" +#include "init.h" + +#if TCFG_USB_APPLE_DOCK_EN + +static void *iap_usb_hdl = NULL; + +#if USB_MALLOC_ENABLE +#else +static u8 USB_IAP_SEND_BUF[0x400] SEC(.mass_storage) __attribute__((aligned(4))); +static u8 USB_IAP_RECV_BUF[0x200] SEC(.mass_storage) __attribute__((aligned(4))); +#endif + +extern u8 MCU_SRAMToUSB_app(void *hdl, u8 *pBuf, u16 uCount); +extern u8 MCU_USBToSRAM_app(void *hdl, u8 *pBuf, u16 uCount); + + +static void iAP_ZLP(void) +{ + delay(50000); +} + +static u8 iAP_bulk_in_process(void) +{ + //iAP_printf_buf(iAP_var_pTxBuf, iAP_var_wLength); + return MCU_SRAMToUSB_app(iap_usb_hdl, iAP_var_pTxBuf, iAP_var_wLength); +} + +static u8 iAP_bulk_out_process(void) +{ + u8 len; + + len = MCU_USBToSRAM_app(iap_usb_hdl, iAP_var_pRxBuf, 0x200); + iAP_var_wLength = len; + /* iAP_printf_buf(iAP_var_pRxBuf, len); */ + return len; +} + +u8 iAP_transport(u8 type) +{ + u8 res = TRUE; + if (type & BIT(IAP_TRANSPORT_ZLP)) { + iAP_ZLP(); + } + if (type & BIT(IAP_TRANSPORT_IN)) { + res = iAP_bulk_in_process(); + } + if (type & BIT(IAP_TRANSPORT_OUT)) { + u8 len = iAP_bulk_out_process(); + if (type & BIT(IAP_TRANSPORT_OUT_LEN)) { + return len; + } + } + return res; +} + + +u8 apple_mfi_link(void *hdl) +{ + u8 res; + + if (MFI_CHIP_OFFLINE == chip_online_status) { + iAP_deg_str("mfi chip offline\n"); + return NO_MFI_CHIP; + } + if (MFI_PROCESS_READY != mfi_pass_status) { + return mfi_pass_status; + } + + iap_usb_hdl = hdl; + + //Reset session Tx & Rx buffer +#if USB_MALLOC_ENABLE + if (iAP_var_pTxBuf == NULL) { + iAP_var_pTxBuf = malloc(0x400); + } + if (iAP_var_pRxBuf == NULL) { + iAP_var_pRxBuf = malloc(0x200); + } +#else + iAP_var_pTxBuf = USB_IAP_SEND_BUF; + iAP_var_pRxBuf = USB_IAP_RECV_BUF; +#endif + + memset(iAP_var_pTxBuf, 0, 0x400); + memset(iAP_var_pRxBuf, 0, 0x200); + + /*Detect iAP support protocol type*/ + if (IAP2_VERSIONS == iAP_support()) { + iAP_deg_str("iAP2 support!\n"); + /* iAP_deg_str("iap2"); */ + /* os_time_dly(2); */ + res = iAP2_link() + IAP2_LINK_ERR; + if (IAP2_LINK_SUCC == res) { + mfi_pass_status = MFI_PROCESS_PASS; + } + return res; + } + + return IAP2_LINK_ERR; +} + +void apple_mfi_unlink(void) +{ +#if USB_MALLOC_ENABLE + local_irq_disable(); + if (iAP_var_pTxBuf) { + free(iAP_var_pTxBuf); + iAP_var_pTxBuf = NULL; + } + if (iAP_var_pRxBuf) { + free(iAP_var_pRxBuf); + iAP_var_pRxBuf = NULL; + } + local_irq_enable(); +#endif +} + +static int apple_dock_init(void) +{ + apple_link_init(); + apple_mfi_chip_online_check_api(); + return 0; +} +early_initcall(apple_dock_init); + +#endif /* TCFG_USB_APPLE_DOCK_EN */ + diff --git a/apps/common/iap/iAP_iic.c b/apps/common/iap/iAP_iic.c new file mode 100644 index 0000000..07d8a1f --- /dev/null +++ b/apps/common/iap/iAP_iic.c @@ -0,0 +1,228 @@ +#include "apple_dock/iAP_iic.h" +#include "apple_dock/iAP.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "app_config.h" + +#if TCFG_USB_APPLE_DOCK_EN + +#if 0 +static hw_iic_dev iic = 0; +#define iic_init() hw_iic_init(iic) +#define iic_uninit() hw_iic_uninit(iic) +#define iic_start() hw_iic_start(iic) +#define iic_stop() hw_iic_stop(iic) +#define iic_sendbyte(byte) hw_iic_tx_byte(iic, byte) +#define iic_revbyte(ack) hw_iic_rx_byte(iic, ack) +#else +static soft_iic_dev iic = 0; +#define iic_init() soft_iic_init(iic) +#define iic_uninit() soft_iic_uninit(iic) +#define iic_start() soft_iic_start(iic) +#define iic_stop() soft_iic_stop(iic) +#define iic_sendbyte(byte) soft_iic_tx_byte(iic, byte) +#define iic_revbyte(ack) soft_iic_rx_byte(iic, ack) +#endif + + + +#define IIC_START_BIT BIT(0) +#define IIC_STOP_BIT BIT(1) +#define IIC_ACK_BIT BIT(2) + +u8 iic_wbyte(u8 st, u8 dat) +{ + bool ack_var = 0; + if (st & IIC_START_BIT) { + iic_start(); + } + ack_var = iic_sendbyte(dat); + if (st & IIC_STOP_BIT) { + iic_stop(); + } + /* printf("a=%d,",ack_var); */ + /* return ack_var ? 1 : 0; */ + return ack_var ? 0 : 1; +} + +u8 iic_rbyte(u8 st) +{ + u8 iic_dat = 0; + if (st & IIC_START_BIT) { + iic_start(); + } + /* iic_dat = iic_revbyte(st & IIC_ACK_BIT); */ + iic_dat = iic_revbyte(!(st & IIC_ACK_BIT)); + if (st & IIC_STOP_BIT) { + iic_stop(); + } + /* printf("d=0x%x,",iic_dat); */ + return iic_dat; +} + +static void iic_start_addr(u8 addr) +{ + u8 cnt = 0xff; + while (--cnt) { + if (iic_wbyte(IIC_START_BIT, addr)) { + delay(200); + continue; + } else { + break; + } + } +} + + +void iAP_iic_write(u8 iic_addr, u8 iic_dat) +{ + /* iic_write_byte(WRITE_ADDR, iic_addr, iic_dat); */ + iic_start_addr(WRITE_ADDR); //Send the I2C write address of the CP + iic_wbyte(0, iic_addr); // + iic_wbyte(IIC_STOP_BIT, iic_dat); // +} + +void iAP_iic_writen(u8 iic_addr, u8 *iic_dat, u8 len) +{ + /* iic_write_buf(WRITE_ADDR, iic_addr, iic_dat, len); */ + iic_start_addr(WRITE_ADDR); //Send the I2C write address of the CP + iic_wbyte(0, iic_addr); // + + //deg_string("\niic_dat="); + for (; len > 1; len--) { + //iap_put_u8hex(*iic_dat); + iic_wbyte(0, *iic_dat++); //写数据 + } + iic_wbyte(IIC_STOP_BIT, *iic_dat); //写数据 +} + +u8 iAP_iic_read(u8 iic_addr) +{ + /* return iic_read_byte(WRITE_ADDR, READ_ADDR, iic_addr); */ + u8 iic_dat; + + iic_start_addr(WRITE_ADDR); //Send the I2C write address of the CP + iic_wbyte(IIC_STOP_BIT, iic_addr); // + iic_start_addr(READ_ADDR); //Send the I2C read address of the CP + iic_dat = iic_rbyte(IIC_STOP_BIT | IIC_ACK_BIT); // + return iic_dat; +} + +void iAP_iic_readn(u8 iic_addr, u8 *iic_dat, u8 len) +{ + /* iic_read_buf(WRITE_ADDR, READ_ADDR, iic_addr, iic_dat, len); */ + iic_start_addr(WRITE_ADDR); //Send the I2C write address of the CP + iic_wbyte(IIC_STOP_BIT, iic_addr); // + iic_start_addr(READ_ADDR); //Send the I2C read address of the CP + + /* delay8(20); */ + + for (; len > 1; len--) { + *iic_dat++ = iic_rbyte(0); // + } + *iic_dat = iic_rbyte(IIC_STOP_BIT | IIC_ACK_BIT); // + +#if (IAP_CRACK_CHIP==IAP_CRACK_CP30) + if (iic_addr == CHALLENGE_DATA_LENGTH) { + *iic_dat = 32; + } +#endif +} + + +//Authentication Coprocessor 2.0C register map +#define VALUE_DEVICE_VERSION 0x05 +#define VALUE_FIRMWARE_VERSION 0x01 +#define VALUE_AUTHENTICATION_PROTOCOL_MAJOR_VERSION 0x02 +#define VALUE_AUTHENTICATION_PROTOCOL_MINOR_VERSION 0x00 +#define VALUE_DEVICE_IDL 0x0000 +#define VALUE_DEVICE_IDH 0x0002 + +#define DEVICE_ID_SIZE 4 + +u8 iap_iic_id[4]; +const u8 iap_iic_chip_id[4] = { +#if (IAP_CRACK_CHIP==IAP_CRACK_CP30) + 0x00, 0x00, 0x03, 0x00 +#else + 0x00, 0x00, 0x02, 0x00 +#endif +}; + +u8 apple_mfi_chip_online_check_api(void) +{ + iic_init(); + os_time_dly(2); + + chip_online_status = MFI_CHIP_OFFLINE; + +#if 0 + if (VALUE_DEVICE_VERSION != iAP_iic_read(ADDR_DEVICE_VERSION)) { + return MFI_DV_ERROR; + } + if (VALUE_FIRMWARE_VERSION != iAP_iic_read(ADDR_FIRMWARE_VERSION)) { + return MFI_FV_ERROR; + } + if (VALUE_AUTHENTICATION_PROTOCOL_MAJOR_VERSION != iAP_iic_read(ADDR_AUTHENTICATION_PROTOCOL_MAJOR_VERSION)) { + return MFI_AP_MAJOR_V_ERROR; + } + if (VALUE_AUTHENTICATION_PROTOCOL_MINOR_VERSION != iAP_iic_read(ADDR_AUTHENTICATION_PROTOCOL_MINOR_VERSION)) { + return MFI_AP_MINOR_V_ERROR; + } +#endif +#if 0 + u16 id_l, id_h; + my_memset(iap_iic_id, 0, sizeof(iap_iic_id)); + iAP_iic_readn(ADDR_DEVICE_ID, (u8 *)(iap_iic_id), DEVICE_ID_SIZE); + /* id = SW32(id); */ + + id_l = iap_iic_id[1]; + id_l = (id_l << 8) | iap_iic_id[0]; + id_h = iap_iic_id[3]; + id_h = (id_h << 8) | iap_iic_id[2]; + + iAP_put_u16hex(id_l); + iAP_put_u16hex(id_h); + + if ((VALUE_DEVICE_IDL != id_l) || (VALUE_DEVICE_IDH != id_h)) { + /* iAP_deg_puts("-err-"); */ + return MFI_DEVICE_ID_ERROR; + } else { + /* iAP_deg_puts("-ok-"); */ + /* iAP_printf_buf((u8 *)id, 4); */ + } +#else +__gain: + memset(iap_iic_id, 0, sizeof(iap_iic_id)); + iAP_iic_readn(ADDR_DEVICE_ID, (u8 *)(iap_iic_id), DEVICE_ID_SIZE); + /* id = SW32(id); */ + + printf("-iap id \n"); + put_buf(iap_iic_id, sizeof(iap_iic_id)); + put_buf((u8 *)iap_iic_chip_id, sizeof(iap_iic_chip_id)); + printf("cmp=0x%x \n", memcmp(iap_iic_id, (u8 *)iap_iic_chip_id, 4)); + /* if ((iap_iic_id[0] != 0x00) */ + /* || (iap_iic_id[1] != 0x00) */ + /* || (iap_iic_id[2] != 0x02) */ + /* || (iap_iic_id[3] != 0x00) */ + /* ) { */ + if (memcmp(iap_iic_id, (u8 *)iap_iic_chip_id, 4)) { + /* iAP_deg_puts("-err-"); */ + printf("--err \n"); + os_time_dly(1); + /* goto __gain; */ + return MFI_DEVICE_ID_ERROR; + } else { + printf("--ok \n"); + /* iAP_deg_puts("-ok-"); */ + /* iAP_printf_buf((u8 *)id, 4); */ + } +#endif + + chip_online_status = MFI_CHIP_ONLINE; + + return MFI_CHIP_ONLINE; +} + +#endif /* TCFG_USB_APPLE_DOCK_EN */ + diff --git a/apps/common/include/bt_common.h b/apps/common/include/bt_common.h new file mode 100644 index 0000000..c61f08d --- /dev/null +++ b/apps/common/include/bt_common.h @@ -0,0 +1,88 @@ +// binary representation +// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) + +#ifndef _BT_COMMON_H +#define _BT_COMMON_H +#include +#include "app_config.h" + +#ifdef APP_PRIVATE_PROFILE_CFG +#include "lib_profile_cfg.h" +#else +#include "bt_profile_cfg.h" +#endif + +enum { + ST_BIT_INQUIRY = 0, + ST_BIT_PAGE_SCAN, + ST_BIT_BLE_ADV, + ST_BIT_SPP_CONN, + ST_BIT_BLE_CONN, + ST_BIT_WEIXIN_CONN, +}; + +enum { + BLE_PRIV_MSG_PAIR_CONFIRM = 0xF0, + BLE_PRIV_PAIR_ENCRYPTION_CHANGE, +};//ble_state_e + + +// #define SYS_BT_EVENT_FORM_COMMON (('C' << 24) | ('M' << 16) | ('M' << 8) | '\0') +enum { + COMMON_EVENT_EDR_REMOTE_TYPE = 1, + COMMON_EVENT_BLE_REMOTE_TYPE, +}; + +extern const int config_le_hci_connection_num;//支持同时连接个数 +extern const int config_le_sm_support_enable; //是否支持加密配对 +extern const int config_le_gatt_server_num; //支持server角色个数 +extern const int config_le_gatt_client_num; //支持client角色个数 + +extern uint16_t little_endian_read_16(const uint8_t *buffer, int pos); +extern uint32_t little_endian_read_24(const uint8_t *buffer, int pos); +extern uint32_t little_endian_read_32(const uint8_t *buffer, int pos); +extern void swapX(const uint8_t *src, uint8_t *dst, int len); + +extern void little_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value); +extern void little_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value); +extern void big_endian_store_16(uint8_t *buffer, uint16_t pos, uint16_t value); +extern void big_endian_store_32(uint8_t *buffer, uint16_t pos, uint32_t value); + +//common api +extern void bt_ble_init(void); +extern void bt_ble_exit(void); +extern void bt_ble_adv_enable(u8 enable); +extern void ble_app_disconnect(void); +extern void ble_module_enable(u8 en); +extern const u8 *bt_get_mac_addr(); +extern void lib_make_ble_address(u8 *ble_address, u8 *edr_address); +extern void user_spp_data_handler(u8 packet_type, u16 ch, u8 *packet, u16 size); +extern void bt_get_vm_mac_addr(u8 *addr); +extern void set_remote_test_flag(u8 own_remote_test); +extern void bredr_power_get(void); +extern void bredr_power_put(void); +extern void radio_set_eninv(int v); +extern void transport_spp_init(void); +extern const char *bt_get_local_name(); +extern void wdt_clear(void); +extern u8 ble_update_get_ready_jump_flag(void); +extern void reset_PK_cb_register(void (*reset_pk)(u32 *)); +extern void att_server_flow_enable(u8 enable); +extern void le_device_db_init(void); +extern bool get_remote_test_flag(); +extern void transport_spp_disconnect(void); +extern int transport_spp_flow_enable(u8 en); +extern void transport_spp_flow_cfg(void); +/* +参数 bt_tx_power 挡位: 功率 dbm ,超过等级默认为最高档 +BD29: rang(0~8) {-18.3, -14.6, -12.1, -8.5, -6.0, -4.1, -1.1, +1.1, +4.0, +6.1} +BD19: rang(0~10) {-17.6, -14.0, -11.5, -9.6, -6.6, -4.4, -0.79, -1.12, +3.8, +5.65, +8.04} +BR23: rang(0~9) {-15.7, -12.5, -10.0, -6.6, -4.4, -2.5, -0.1, +2.1, +4.6, +6.4} +BR25: rang(0~9) {-15.7, -12.5, -10.0, -6.6, -4.4, -2.5, -0.1, +2.1, +4.6, +6.4} +BR30: rang(0~8) {-17.48, -11.46, -7.96, -3.59, -0.79, +1.12, +3.8, +6.5, +8.44} +BR34: rang(0~10) {-17.6, -14.0, -11.5, -9.6, -6.6, -4.4, -1.8, 0, +2.1, +4, +6.3} +*/ +//初始化配置蓝牙发射功率最大值范围,解析详见 btcontroller_modules.h +void bt_max_pwr_set(u8 pwr, u8 pg_pwr, u8 iq_pwr, u8 ble_pwr); + +#endif diff --git a/apps/common/include/nandflash.h b/apps/common/include/nandflash.h new file mode 100644 index 0000000..7b66a6a --- /dev/null +++ b/apps/common/include/nandflash.h @@ -0,0 +1,69 @@ +#ifndef _NANDFLASH_H +#define _NANDFLASH_H + +#include "device/device.h" +#include "ioctl_cmds.h" +#include "asm/spi.h" +#include "printf.h" +#include "gpio.h" +#include "device_drive.h" +#include "malloc.h" + + +#define GD_WRITE_ENABLE 0x06 +#define GD_WRITE_DISABLE 0x04 +#define GD_BLOCK_ERASE 0xD8 +#define GD_READ_ID 0x9F +/*for features*/ +#define GD_GET_FEATURES 0x0F +#define GD_SET_FEATURES 0x1F +//> 4) +#define ITEM_TYPE(x) ((x & 0x0c) >> 2) +#define ITEM_SIZE(x) (x & 0x03) + +// keyboard usage page +#define KEYBOARD_USAGE_PAGE 0x07 +#define NO_USAGE_PAGE 0 + +// item type +#define SHORT_ITEM_STRUCT_SIZE 1 +#define SHORT_ITEM_MAX_DATA_SIZE sizeof(u32) + +#endif // #define __STANDARD_HID_H__ diff --git a/apps/common/include/update_tws.h b/apps/common/include/update_tws.h new file mode 100644 index 0000000..fabca8a --- /dev/null +++ b/apps/common/include/update_tws.h @@ -0,0 +1,92 @@ +#ifndef _RCSP_ADV_TWS_OTA_H +#define _RCSP_ADV_TWS_OTA_H + +#include "app_config.h" + +#if (OTA_TWS_SAME_TIME_ENABLE && (RCSP_ADV_EN )) + +#define SYS_BT_OTA_EVENT_TYPE_STATUS (('O' << 24) | ('T' << 16) | ('A' << 8) | '\0') + +#include "system/event.h" +#include "update_loader_download.h" + +typedef int sint32_t; + +enum { + OTA_OVER = 0, + OTA_INIT, + OTA_START, + OTA_VERIFY_ING, + OTA_VERIFY_END, + OTA_SUCC, +}; + +enum { + OTA_SINGLE_EARPHONE, + OTA_TWS, +}; + +enum { + OTA_START_UPDATE = 0, + OTA_START_UPDATE_READY, + OTA_START_VERIFY, + OTA_UPDATE_OVER, + OTA_UPDATE_ERR, + OTA_UPDATE_SUCC, +}; + +enum { + OTA_TYPE_SET = 0, + OTA_TYPE_GET, + OTA_STATUS_SET, + OTA_STATUS_GET, + OTA_REMOTE_STATUS_SET, + OTA_REMOTE_STATUS_GET, + OTA_RESULT_SET, + OTA_RESULT_GET, +}; + + +enum { + OTA_STOP_APP_DISCONNECT, + OTA_STOP_LINK_DISCONNECT, + OTA_STOP_UPDATE_OVER_SUCC, + OTA_STOP_UPDATE_OVER_ERR, + OTA_STOP_PHONE, +}; + +enum { + SYNC_CMD_START_UPDATE, + SYNC_CMD_START_VERIFY, + SYNC_CMD_UPDATE_OVER, + SYNC_CMD_UPDATE_ERR, +}; + +int tws_ota_init(void); +int tws_ota_close(void); + +int tws_ota_open(struct __tws_ota_para *para); +void tws_ota_stop(u8 reason); + +u16 tws_ota_enter_verify(void *priv); +u16 tws_ota_exit_verify(u8 *res, u8 *up_flg); +u16 tws_ota_updata_boot_info_over(void *priv); + +int tws_ota_err_callback(u8 reason); + +int tws_ota_data_send_m_to_s(u8 *buf, u16 len); +int tws_ota_sync_cmd(int reason); +void tws_ota_app_event_deal(u8 evevt); +u8 dual_bank_update_burn_boot_info_callback(u8 ret); +int bt_ota_event_handler(struct bt_event *bt); +void tws_ota_event_post(u32 type, u8 event); + +u8 tws_ota_control(int type, ...); + +void tws_ota_send_data_to_sibling(u8 opcode, u8 *data, u8 len); +int tws_ota_get_data_from_sibling(u8 opcode, u8 *data, u8 len); + +#endif //(OTA_TWS_SAME_TIME_ENABLE && RCSP_ADV_EN) + +#endif //_RCSP_ADV_TWS_OTA_H + diff --git a/apps/common/key/adkey.c b/apps/common/key/adkey.c new file mode 100644 index 0000000..a9c69ca --- /dev/null +++ b/apps/common/key/adkey.c @@ -0,0 +1,157 @@ +#include "key_driver.h" +#include "adkey.h" +#include "gpio.h" +#include "system/event.h" +#include "app_config.h" + + +#if TCFG_ADKEY_ENABLE + +static const struct adkey_platform_data *__this = NULL; + +u8 ad_get_key_value(void); +//按键驱动扫描参数列表 +struct key_driver_para adkey_scan_para = { + .scan_time = 10, //按键扫描频率, 单位: ms + .last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY; + .filter_time = 2, //按键消抖延时; + .long_time = 75, //按键判定长按数量 + .hold_time = (75 + 15), //按键判定HOLD数量 + .click_delay_time = 20, //按键被抬起后等待连击延时数量 + .key_type = KEY_DRIVER_TYPE_AD, + .get_value = ad_get_key_value, +}; +u8 ad_get_key_value(void) +{ + u8 i; + u16 ad_data; + + if (!__this->enable) { + return NO_KEY; + } + + /* ad_data = adc_get_voltage(__this->ad_channel); */ + ad_data = adc_get_value(__this->ad_channel); + /* printf("ad_value = %d \n", ad_data); */ + for (i = 0; i < ADKEY_MAX_NUM; i++) { + if ((ad_data <= __this->ad_value[i]) && (__this->ad_value[i] < 0x3ffL)) { + return __this->key_value[i]; + } + } + return NO_KEY; +} + +int adkey_init(const struct adkey_platform_data *adkey_data) +{ + __this = adkey_data; + if (!__this) { + return -EINVAL; + } + + if (!__this->enable) { + return KEY_NOT_SUPPORT; + } + adc_add_sample_ch(__this->ad_channel); //注意:初始化AD_KEY之前,先初始化ADC +#if (TCFG_ADKEY_LED_IO_REUSE || TCFG_ADKEY_IR_IO_REUSE || TCFG_ADKEY_LED_SPI_IO_REUSE) +#else + gpio_set_die(__this->adkey_pin, 0); + gpio_set_direction(__this->adkey_pin, 1); + gpio_set_pull_down(__this->adkey_pin, 0); + if (__this->extern_up_en) { + gpio_set_pull_up(__this->adkey_pin, 0); + } else { + gpio_set_pull_up(__this->adkey_pin, 1); + } +#endif + + return 0; +} + +#if (TCFG_ADKEY_LED_IO_REUSE || TCFG_ADKEY_IR_IO_REUSE || TCFG_ADKEY_LED_SPI_IO_REUSE) + +#if TCFG_ADKEY_IR_IO_REUSE +static u8 ir_io_sus = 0; +extern u8 ir_io_suspend(void); +extern u8 ir_io_resume(void); +#endif +#if TCFG_ADKEY_LED_IO_REUSE +static u8 led_io_sus = 0; +extern u8 led_io_suspend(void); +extern u8 led_io_resume(void); +#endif +#if TCFG_ADKEY_LED_SPI_IO_REUSE +static u8 led_spi_sus = 0; +extern u8 led_spi_suspend(void); +extern u8 led_spi_resume(void); +#endif +u8 adc_io_reuse_enter(u32 ch) +{ + if (ch == __this->ad_channel) { +#if TCFG_ADKEY_IR_IO_REUSE + if (ir_io_suspend()) { + return 1; + } else { + ir_io_sus = 1; + } +#endif +#if TCFG_ADKEY_LED_IO_REUSE + if (led_io_suspend()) { + return 1; + } else { + led_io_sus = 1; + } +#endif +#if TCFG_ADKEY_LED_SPI_IO_REUSE + if (led_spi_suspend()) { + return 1; + } else { + led_spi_sus = 1; + } +#endif + gpio_set_die(__this->adkey_pin, 0); + gpio_set_direction(__this->adkey_pin, 1); + gpio_set_pull_down(__this->adkey_pin, 0); + if (__this->extern_up_en) { + gpio_set_pull_up(__this->adkey_pin, 0); + } else { + gpio_set_pull_up(__this->adkey_pin, 1); + } + } + return 0; +} + +u8 adc_io_reuse_exit(u32 ch) +{ + if (ch == __this->ad_channel) { +#if TCFG_ADKEY_IR_IO_REUSE + if (ir_io_sus) { + ir_io_sus = 0; + ir_io_resume(); + } +#endif +#if TCFG_ADKEY_LED_IO_REUSE + if (led_io_sus) { + led_io_sus = 0; + led_io_resume(); + } +#endif +#if TCFG_ADKEY_LED_SPI_IO_REUSE + if (led_spi_sus) { + led_spi_sus = 0; + led_spi_resume(); + } +#endif + } + return 0; +} + +#endif + + + +#endif /* #if TCFG_ADKEY_ENABLE */ + + + + + diff --git a/apps/common/key/adkey_rtcvdd.c b/apps/common/key/adkey_rtcvdd.c new file mode 100644 index 0000000..cff4872 --- /dev/null +++ b/apps/common/key/adkey_rtcvdd.c @@ -0,0 +1,253 @@ +#include "includes.h" +#include "key_driver.h" +#include "adkey.h" +#include "gpio.h" +#include "system/event.h" +#include "app_config.h" +#include "asm/power/p33.h" + +#if TCFG_ADKEY_RTCVDD_ENABLE + +#define ADKEY_RTCVDD_DEBUG 1 +#if ADKEY_RTCVDD_DEBUG +#define adkey_rtcvdd_debug(fmt, ...) printf("[ADKEY_RTCVDD] "fmt, ##__VA_ARGS__) +#else +#define adkey_rtcvdd_debug(fmt, ...) +#endif + +#define ADC_KEY_NUMBER 10 + +#define FULL_ADC 0x3ffL + +#define ADC_FULL(x) (x) +#define ADC_VOLTAGE(x,y,z) ((x*y) / (y + z)) //x当前满幅电压,y分压电阻,z上拉电阻 +#define ADC_ZERRO(x) (0) + +u16 ad_rtcvdd_key_table[ADC_KEY_NUMBER + 1] = {0}; + +#define FULL_AD_VOLTAGE 0x3FFF + +volatile u8 adkey_lock_cnt = 0; +static u8 rtcvdd_cnt = 10; +static u8 rtcvdd_full_cnt = 0xff; +u16 rtcvdd_full_value = FULL_AD_VOLTAGE; +u16 max_value = 0; +u16 min_value = 0xffff; +u32 total_value = 0; +static u8 check_rtcvdd_cnt = 0; + +static const struct adkey_rtcvdd_platform_data *__this = NULL; + + +u8 adkey_rtcvdd_get_key_value(void); +//按键驱动扫描参数列表 +struct key_driver_para adkey_rtcvdd_scan_para = { + .scan_time = 10, //按键扫描频率, 单位: ms + .last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY; + .filter_time = 2, //按键消抖延时; + .long_time = 75, //按键判定长按数量 + .hold_time = (75 + 15), //按键判定HOLD数量 + .click_delay_time = 20, //按键被抬起后等待连击延时数量 + .key_type = KEY_DRIVER_TYPE_RTCVDD_AD, + .get_value = adkey_rtcvdd_get_key_value, +}; + +static void set_rtcvdd_table(u16 adc_rtcvdd) +{ + u8 i; + u32 extern_up_res_value = __this->extern_up_res_value; + + if (extern_up_res_value == 0) { //使用内部上拉 + extern_up_res_value = 100; + } + + for (i = 0; i < __this->adkey_num; i++) { + if (i == (__this->adkey_num - 1)) { + ad_rtcvdd_key_table[i] = (ADC_VOLTAGE(adc_rtcvdd, __this->res_value[i], extern_up_res_value) + ADC_FULL(adc_rtcvdd)) / 2; + //adkey_rtcvdd_debug("recvdd = %d, res_value[%d] = %d", adc_rtcvdd, i, __this->res_value[i]); + } else { + ad_rtcvdd_key_table[i] = (ADC_VOLTAGE(adc_rtcvdd, __this->res_value[i], extern_up_res_value) + ADC_VOLTAGE(adc_rtcvdd, __this->res_value[i + 1], extern_up_res_value)) / 2; + //adkey_rtcvdd_debug("res_value[%d] = %d, res_value[%d] = %d", i, __this->res_value[i], i + 1, __this->res_value[i+1]); + } + } +} + +static void SET_ADKEY_LOCK_CNT(u8 cnt) +{ + CPU_SR_ALLOC(); + OS_ENTER_CRITICAL(); + + adkey_lock_cnt = cnt; + + OS_EXIT_CRITICAL(); +} + +static u8 GET_ADKEY_LOCK_CNT(void) +{ + u8 val; + CPU_SR_ALLOC(); + OS_ENTER_CRITICAL(); + + val = adkey_lock_cnt; + + OS_EXIT_CRITICAL(); + return val; +} + +static void POST_ADKEY_LOCK_CNT(void) +{ + CPU_SR_ALLOC(); + OS_ENTER_CRITICAL(); + + adkey_lock_cnt --; + + OS_EXIT_CRITICAL(); +} + +/*----------------------------------------------------------------------------*/ +/**@brief ad按键初始化 + @param void + @param void + @return void + @note void ad_key0_init(void) +*/ +/*----------------------------------------------------------------------------*/ +int adkey_rtcvdd_init(const struct adkey_rtcvdd_platform_data *adkey_data) +{ + adkey_rtcvdd_debug("ad key init\n"); + + __this = adkey_data; + if (!__this) { + return -EINVAL; + } + + if (__this->extern_up_res_value == 0) { //使用内部上拉 + gpio_set_pull_up(__this->adkey_pin, 1); + } else { + gpio_set_pull_up(__this->adkey_pin, 0); + } + gpio_set_direction(__this->adkey_pin, 1); + gpio_set_pull_down(__this->adkey_pin, 0); + gpio_set_die(__this->adkey_pin, 0); + + adc_add_sample_ch(__this->ad_channel); //注意:初始化AD_KEY之前,先初始化ADC + adc_add_sample_ch(AD_CH_RTCVDD); + + set_rtcvdd_table(FULL_ADC); + + return 0; +} + + +/*把cnt个值里的最大值和最小值去掉,求剩余cnt-2个数的平均值*/ +static u16 rtcvdd_full_vaule_update(u16 value) +{ + u16 full_value = FULL_ADC; + if (rtcvdd_full_cnt == 0xff) { + rtcvdd_full_cnt = 0; + SET_ADKEY_LOCK_CNT(50); + return value; //first time + } else { + rtcvdd_full_cnt ++; + if (value > max_value) { + max_value = value; + } + if (value < min_value) { + min_value = value; + } + total_value += value; + + if (rtcvdd_full_cnt > 10 - 1) { //算10个数 + full_value = (total_value - max_value - min_value) / (rtcvdd_full_cnt - 2); + rtcvdd_full_cnt = 0; + max_value = 0; + min_value = 0xffff; + total_value = 0; + } else { + return rtcvdd_full_value; + } + } + return full_value; +} + +u8 get_rtcvdd_level(void) +{ + u8 level = GET_RTCVDD_VOL(); + return level; +} + +void set_rtcvdd_level(u8 level) +{ + if (level > 7 || level < 0) { + return; + } + RTCVDD_VOL_SEL(level); +} +/*检测到RTCVDD 比 VDDIO 高的时候自动把RTCVDD降一档*/ +static u8 rtcvdd_auto_match_vddio_lev(u32 rtcvdd_value) +{ + u8 rtcvdd_lev = 0; + if (rtcvdd_value >= FULL_ADC) { //trim rtcvdd < vddio + if (rtcvdd_cnt > 10) { + rtcvdd_cnt = 0; + rtcvdd_lev = get_rtcvdd_level(); + if (rtcvdd_lev < 8) { + rtcvdd_lev++; //降一档 + /* rtcvdd_lev--; //降一档 */ + set_rtcvdd_level(rtcvdd_lev); + SET_ADKEY_LOCK_CNT(50); + return 1; + } + } else { + rtcvdd_cnt ++; + } + } else { + rtcvdd_cnt = 0; + rtcvdd_full_value = rtcvdd_full_vaule_update(rtcvdd_value); + } + return 0; +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief 获取ad按键值 + @param void + @param void + @return key_number + @note tu8 adkey_rtcvdd_get_key_value(void) +*/ +/*----------------------------------------------------------------------------*/ +u8 adkey_rtcvdd_get_key_value(void) +{ + u8 key_number, i; + u32 ad_value; + u16 rtcvdd_value = 0; + + rtcvdd_value = 2 * adc_get_value(AD_CH_RTCVDD); + ad_value = adc_get_value(__this->ad_channel); + + /* printf("rtcvdd_value = %d, ad_value = %d", rtcvdd_value, ad_value); */ + if (rtcvdd_auto_match_vddio_lev(rtcvdd_value)) { + return NO_KEY; + } + + if (GET_ADKEY_LOCK_CNT()) { + POST_ADKEY_LOCK_CNT(); + return NO_KEY; + } + + set_rtcvdd_table(rtcvdd_full_value); + + for (i = 0; i < __this->adkey_num; i++) { + if (ad_value <= ad_rtcvdd_key_table[i] && (ad_rtcvdd_key_table[i] < 0x3FFL)) { + return __this->key_value[i]; + } + } + + return NO_KEY; +} + + +#endif /* #if TCFG_ADKEY_RTCVDD_ENABLE */ + diff --git a/apps/common/key/ctmu_touch_key.c b/apps/common/key/ctmu_touch_key.c new file mode 100644 index 0000000..80344d3 --- /dev/null +++ b/apps/common/key/ctmu_touch_key.c @@ -0,0 +1,61 @@ +#include "key_driver.h" +#include "app_config.h" + + + +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" + +#define LOG_TAG_CONST CTMU +#define LOG_TAG "[ctmu]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +/* =========== 触摸键使用说明 ============= */ +//1. 使用ctmu模块作计数; + +static const struct ctmu_touch_key_platform_data *__this = NULL; + +static u8 ctmu_touch_key_get_value(void); +//按键驱动扫描参数列表 +struct key_driver_para ctmu_touch_key_scan_para = { + .scan_time = 10, //按键扫描频率, 单位: ms + .last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY; + .filter_time = 2, //按键消抖延时; + .long_time = 55, //按键判定长按数量 + .hold_time = (55 + 15), //按键判定HOLD数量 + .click_delay_time = 40, //按键被抬起后等待连击延时数量 + .key_type = KEY_DRIVER_TYPE_CTMU_TOUCH, + .get_value = ctmu_touch_key_get_value, +}; + + + +static u8 ctmu_touch_key_get_value(void) +{ + u8 key = get_ctmu_value(); + + if (key != NO_KEY) { + log_debug("key = %d %x", key, __this->port_list[key].key_value); + return __this->port_list[key].key_value; + } + + return NO_KEY; +} + + +int ctmu_touch_key_init(const struct ctmu_touch_key_platform_data *ctmu_touch_key_data) +{ + __this = ctmu_touch_key_data; + log_info("ctmu touch_key_init >>>> "); + + return ctmu_init((void *)ctmu_touch_key_data); +} + + +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + diff --git a/apps/common/key/iokey.c b/apps/common/key/iokey.c new file mode 100644 index 0000000..baca950 --- /dev/null +++ b/apps/common/key/iokey.c @@ -0,0 +1,277 @@ +#include "key_driver.h" +#include "iokey.h" +#include "gpio.h" +#include "system/event.h" +#include "app_config.h" +#include "asm/clock.h" + +#if TCFG_IOKEY_ENABLE + +static const struct iokey_platform_data *__this = NULL; + +u8 io_get_key_value(void); + +#if MOUSE_KEY_SCAN_MODE +struct key_driver_para iokey_scan_para = { + .scan_time = 5, //按键扫描频率, 单位: ms + .last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY; + .filter_time = 2, //按键消抖延时; + .long_time = 5, //按键判定长按数量 + .hold_time = (5 + 0), //按键判定HOLD数量 + .click_delay_time = 20, //按键被抬起后等待连击延时数量 + .key_type = KEY_DRIVER_TYPE_IO, + .get_value = io_get_key_value, +}; +#else +//按键驱动扫描参数列表 +struct key_driver_para iokey_scan_para = { + .scan_time = 10, //按键扫描频率, 单位: ms + .last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY; + .filter_time = 4, //按键消抖延时; + .long_time = 75, //按键判定长按数量 + .hold_time = (75 + 15), //按键判定HOLD数量 + .click_delay_time = 20, //按键被抬起后等待连击延时数量 + .key_type = KEY_DRIVER_TYPE_IO, + .get_value = io_get_key_value, +}; +#endif + +#define MARK_BIT_VALUE(b, v) do {if ((v & (~BIT(7))) < 7) b |= BIT(v & (~BIT(7)));} while(0) + +static void key_io_pull_down_input(u8 key_io) +{ + gpio_direction_input(key_io); + gpio_set_pull_down(key_io, 1); + gpio_set_pull_up(key_io, 0); + gpio_set_die(key_io, 1); +} + + +static void key_io_pull_up_input(u8 key_io) +{ + gpio_direction_input(key_io); + gpio_set_pull_down(key_io, 0); + gpio_set_pull_up(key_io, 1); + gpio_set_die(key_io, 1); +} + +static void key_io_output_high(u8 key_io) +{ + gpio_set_pull_down(key_io, 0); + gpio_set_pull_up(key_io, 0); + gpio_direction_output(key_io, 1); +} + +static void key_io_output_low(u8 key_io) +{ + gpio_set_pull_down(key_io, 0); + gpio_set_pull_up(key_io, 0); + gpio_direction_output(key_io, 0); +} + +static int get_io_key_value(u8 key_io) +{ + return gpio_read(key_io); +} + + +static void key_io_reset(void) +{ + int i; + + for (i = 0; i < __this->num; i++) { + switch (__this->port[i].connect_way) { + case ONE_PORT_TO_HIGH: + key_io_pull_down_input(__this->port[i].key_type.one_io.port); + break; + + case ONE_PORT_TO_LOW: +#if (TCFG_IO_MULTIPLEX_WITH_SD == ENABLE) + if (TCFG_MULTIPLEX_PORT != __this->port[i].key_type.one_io.port) { + key_io_pull_up_input(__this->port[i].key_type.one_io.port); + } +#else + + key_io_pull_up_input(__this->port[i].key_type.one_io.port); +#endif + break; + + case DOUBLE_PORT_TO_IO: + break; + + default: + ASSERT(0, "IO KEY CONNECT ERR!!!"); + break; + } + } +} + + +#if MULT_KEY_ENABLE +extern const struct key_remap_data iokey_remap_data; +static u8 iokey_value_remap(u8 bit_mark) +{ + for (int i = 0; i < iokey_remap_data.remap_num; i++) { + if (iokey_remap_data.table[i].bit_value == bit_mark) { + return iokey_remap_data.table[i].remap_value; + } + } + + return NO_KEY; +} +#endif + + +#if TCFG_IO_MULTIPLEX_WITH_SD == ENABLE +static u8 mult_key_value = 1; +static void udelay(u32 usec) +{ + JL_TIMER0->CON = BIT(14); + JL_TIMER0->CNT = 0; + JL_TIMER0->PRD = clk_get("lsb") / 1000000L * usec; + JL_TIMER0->CON = BIT(0); //lsb clk + while ((JL_TIMER0->CON & BIT(15)) == 0); + JL_TIMER0->CON = BIT(14); +} +extern u8 sd_io_suspend(u8 sdx, u8 sd_io); +extern u8 sd_io_resume(u8 sdx, u8 sd_io); +void sd_mult_io_detect(void *arg) +{ + static u32 cnt = 0; + if (sd_io_suspend(1, 1) == 0) { + gpio_set_direction(TCFG_MULTIPLEX_PORT, 0); + gpio_write(TCFG_MULTIPLEX_PORT, 0); + udelay(10); + gpio_set_die(TCFG_MULTIPLEX_PORT, 1); + gpio_set_pull_down(TCFG_MULTIPLEX_PORT, 0); + gpio_set_pull_up(TCFG_MULTIPLEX_PORT, 1); + gpio_set_direction(TCFG_MULTIPLEX_PORT, 1); + udelay(10); + mult_key_value = gpio_read(TCFG_MULTIPLEX_PORT); + sd_io_resume(1, 1); + } +} +#endif + +__attribute__((weak)) u8 iokey_filter_hook(u8 io_state) +{ + return 0; +} + +u8 io_get_key_value(void) +{ + int i; + + u8 press_value = 0; + u8 read_value = 0; + u8 read_io; + u8 write_io; + u8 connect_way; + u8 ret_value = NO_KEY; + u8 bit_mark = 0; + + if (!__this->enable) { + return NO_KEY; + } + + //先扫描单IO接按键方式 + for (i = 0; i < __this->num; i++) { + connect_way = __this->port[i].connect_way; + + if (connect_way == ONE_PORT_TO_HIGH) { + press_value = 1; + } else if (connect_way == ONE_PORT_TO_LOW) { + press_value = 0; + } else { + continue; + } + + read_io = __this->port[i].key_type.one_io.port; + +#if (TCFG_IO_MULTIPLEX_WITH_SD == ENABLE) + if (read_io == TCFG_MULTIPLEX_PORT) { + read_value = mult_key_value; + } else { + read_value = get_io_key_value(read_io); + } +#else + read_value = get_io_key_value(read_io); +#endif + if (iokey_filter_hook(read_value)) { +#ifdef TCFG_IOKEY_TIME_REDEFINE + extern struct key_driver_para iokey_scan_user_para; + iokey_scan_user_para.filter_cnt = 0; + iokey_scan_user_para.press_cnt = 0; + iokey_scan_user_para.click_cnt = 0; + iokey_scan_user_para.click_delay_cnt = 0; + iokey_scan_user_para.last_key = NO_KEY; +#else + iokey_scan_para.filter_cnt = 0; + iokey_scan_para.press_cnt = 0; + iokey_scan_para.click_cnt = 0; + iokey_scan_para.click_delay_cnt = 0; + iokey_scan_para.last_key = NO_KEY; +#endif + return NO_KEY; + } + if (read_value == press_value) { + ret_value = __this->port[i].key_value; +#if MULT_KEY_ENABLE + MARK_BIT_VALUE(bit_mark, ret_value); //标记被按下的按键 +#else + goto _iokey_get_value_end; +#endif + } + } + + //再扫描两个IO接按键方式, in_port: 上拉输入, out_port: 输出低 + for (i = 0; i < __this->num; i++) { + connect_way = __this->port[i].connect_way; + if (connect_way == DOUBLE_PORT_TO_IO) {//标准双io + press_value = 0; + read_io = __this->port[i].key_type.two_io.in_port; + key_io_output_low(__this->port[i].key_type.two_io.out_port); //输出低 + key_io_pull_up_input(read_io); //上拉 + read_value = get_io_key_value(read_io); + key_io_reset(); //按键初始化为单IO检测状态 + if (read_value == press_value) { + ret_value = __this->port[i].key_value; +#if MULT_KEY_ENABLE + MARK_BIT_VALUE(bit_mark, ret_value); //标记被按下的按键 +#else + goto _iokey_get_value_end; +#endif + } + } + } + +#if MULT_KEY_ENABLE + bit_mark = iokey_value_remap(bit_mark); //组合按键重新映射按键值 + ret_value = (bit_mark != NO_KEY) ? bit_mark : ret_value; +#endif + +_iokey_get_value_end: + return ret_value; +} + + + +int iokey_init(const struct iokey_platform_data *iokey_data) +{ + int i; + + __this = iokey_data; + if (__this == NULL) { + return -EINVAL; + } + if (!__this->enable) { + return KEY_NOT_SUPPORT; + } + + key_io_reset(); + + return 0; +} + +#endif /* #if TCFG_IOKEY_ENABLE */ + diff --git a/apps/common/key/irkey.c b/apps/common/key/irkey.c new file mode 100644 index 0000000..887dcd1 --- /dev/null +++ b/apps/common/key/irkey.c @@ -0,0 +1,78 @@ +#include "key_driver.h" +#include "irkey.h" +#include "gpio.h" +#include "asm/irflt.h" +#include "app_config.h" + +#if TCFG_IRKEY_ENABLE + +u8 ir_get_key_value(void); +//按键驱动扫描参数列表 +struct key_driver_para irkey_scan_para = { + .scan_time = 10, //按键扫描频率, 单位: ms + .last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY; + .filter_time = 2, //按键消抖延时; + .long_time = 75, //按键判定长按数量 + .hold_time = (75 + 15), //按键判定HOLD数量 + .click_delay_time = 20, //按键被抬起后等待连击延时数量 + .key_type = KEY_DRIVER_TYPE_IR, + .get_value = ir_get_key_value, +}; + + + +const u8 IRTabFF00[] = { + NKEY_00, NKEY_01, NKEY_02, NKEY_03, NKEY_04, NKEY_05, NKEY_06, IR_06, IR_15, IR_08, NKEY_0A, NKEY_0B, IR_12, IR_11, NKEY_0E, NKEY_0F, + NKEY_10, NKEY_11, NKEY_12, NKEY_13, NKEY_14, IR_07, IR_09, NKEY_17, IR_13, IR_10, NKEY_1A, NKEY_1B, IR_16, NKEY_1D, NKEY_1E, NKEY_1F, + NKEY_20, NKEY_21, NKEY_22, NKEY_23, NKEY_24, NKEY_25, NKEY_26, NKEY_27, NKEY_28, NKEY_29, NKEY_2A, NKEY_2B, NKEY_2C, NKEY_2D, NKEY_2E, NKEY_2F, + NKEY_30, NKEY_31, NKEY_32, NKEY_33, NKEY_34, NKEY_35, NKEY_36, NKEY_37, NKEY_38, NKEY_39, NKEY_3A, NKEY_3B, NKEY_3C, NKEY_3D, NKEY_3E, NKEY_3F, + IR_04, NKEY_41, IR_18, IR_05, IR_03, IR_00, IR_01, IR_02, NKEY_48, NKEY_49, IR_20, NKEY_4B, NKEY_4C, NKEY_4D, NKEY_4E, NKEY_4F, + NKEY_50, NKEY_51, IR_19, NKEY_53, NKEY_54, NKEY_55, NKEY_56, NKEY_57, NKEY_58, NKEY_59, IR_17, NKEY_5B, NKEY_5C, NKEY_5D, IR_14, NKEY_5F, +}; + + +/*----------------------------------------------------------------------------*/ +/**@brief 获取ir按键值 + @param void + @param void + @return void + @note void get_irkey_value(void) +*/ +/*----------------------------------------------------------------------------*/ +u8 ir_get_key_value(void) +{ + u8 tkey = 0xff; + tkey = get_irflt_value(); + if (tkey == 0xff) { + return tkey; + } + tkey = IRTabFF00[tkey]; + return tkey; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief ir按键初始化 + @param void + @param void + @return void + @note void ir_key_init(void) +*/ +/*----------------------------------------------------------------------------*/ +int irkey_init(const struct irkey_platform_data *irkey_data) +{ + printf("irkey_init "); + + ir_input_io_sel(irkey_data->port); + + ir_output_timer_sel(); + + irflt_config(); + + ir_timeout_set(); + + return 0; +} + +#endif + diff --git a/apps/common/key/key_driver.c b/apps/common/key/key_driver.c new file mode 100644 index 0000000..5d4fb6f --- /dev/null +++ b/apps/common/key/key_driver.c @@ -0,0 +1,330 @@ +#include "device/key_driver.h" +#include "system/event.h" +#include "system/init.h" +#include "iokey.h" +#include "adkey.h" +#include "slidekey.h" +#include "irkey.h" +#include "touch_key.h" +#include "system/timer.h" +#include "asm/power_interface.h" +#include "app_config.h" +#include "rdec_key.h" +#if TCFG_KEY_TONE_EN +#include "tone_player.h" +#endif + +#if(TCFG_IRSENSOR_ENABLE == 1) +#include "irSensor/ir_manage.h" +#endif + +#define LOG_TAG_CONST KEY +#define LOG_TAG "[KEY]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +//#define LOG_DUMP_ENABLE +//#define LOG_CLI_ENABLE +#include "debug.h" + +#define KEY_EVENT_CLICK_ONLY_SUPPORT 1 //是否支持某些按键只响应单击事件 + + +#if TCFG_SPI_LCD_ENABLE +#ifndef ALL_KEY_EVENT_CLICK_ONLY +#define ALL_KEY_EVENT_CLICK_ONLY 1 //是否全部按键只响应单击事件 +#endif +#else +#ifndef ALL_KEY_EVENT_CLICK_ONLY +#define ALL_KEY_EVENT_CLICK_ONLY 0 //是否全部按键只响应单击事件 +#endif +#endif + +static volatile u8 is_key_active = 0; + + +extern u32 timer_get_ms(void); + +//=======================================================// +// 按键值重新映射函数: +// 用户可以实现该函数把一些按键值重新映射, 可用于组合键的键值重新映射 +//=======================================================// +int __attribute__((weak)) key_event_remap(struct sys_event *e) +{ + return true; +} + +//=======================================================// +// 按键扫描函数: 扫描所有注册的按键驱动 +//=======================================================// +static void key_driver_scan(void *_scan_para) +{ + struct key_driver_para *scan_para = (struct key_driver_para *)_scan_para; + + u8 key_event = 0; + u8 cur_key_value = NO_KEY; + u8 key_value = 0; + struct sys_event e; + static u8 poweron_cnt = 0; + + //为了滤掉adkey与mic连在一起时电容充放电导致的开机按键误判,一般用于type-c耳机 + /* if (poweron_cnt <= 250) { */ + /* poweron_cnt++; */ + /* return; */ + /* } */ + + cur_key_value = scan_para->get_value(); + /* if (cur_key_value != NO_KEY) { */ + /* printf(">>>cur_key_value: %d\n", cur_key_value); */ + /* } */ + + if (cur_key_value != NO_KEY) { + is_key_active = 35; //35*10Ms + } else if (is_key_active) { + is_key_active --; + } +//===== 按键消抖处理 + if (cur_key_value != scan_para->filter_value && scan_para->filter_time) { //当前按键值与上一次按键值如果不相等, 重新消抖处理, 注意filter_time != 0; + scan_para->filter_cnt = 0; //消抖次数清0, 重新开始消抖 + scan_para->filter_value = cur_key_value; //记录上一次的按键值 + return; //第一次检测, 返回不做处理 + } //当前按键值与上一次按键值相等, filter_cnt开始累加; + if (scan_para->filter_cnt < scan_para->filter_time) { + scan_para->filter_cnt++; + return; + } + //为了滤掉adkey与mic连在一起时电容充放电导致的按键误判,一般用于type-c耳机 + /* if ((cur_key_value != scan_para->last_key) && (scan_para->last_key != NO_KEY) && (cur_key_value != NO_KEY)) { */ + /* return; */ + /* } */ +//===== 按键消抖结束, 开始判断按键类型(单击, 双击, 长按, 多击, HOLD, (长按/HOLD)抬起) + if (cur_key_value != scan_para->last_key) { + if (cur_key_value == NO_KEY) { //cur_key = NO_KEY; last_key = valid_key -> 按键被抬起 + +#if MOUSE_KEY_SCAN_MODE + /* if (scan_para->press_cnt >= scan_para->long_time) { //长按/HOLD状态之后被按键抬起; */ + key_event = KEY_EVENT_UP; + key_value = scan_para->last_key; + goto _notify; //发送抬起消息 + /* } */ +#else + if (scan_para->press_cnt >= scan_para->long_time) { //长按/HOLD状态之后被按键抬起; + key_event = KEY_EVENT_UP; + key_value = scan_para->last_key; + goto _notify; //发送抬起消息 + } +#endif + + scan_para->click_delay_cnt = 1; //按键等待下次连击延时开始 + } else { //cur_key = valid_key, last_key = NO_KEY -> 按键被按下 + scan_para->press_cnt = 1; //用于判断long和hold事件的计数器重新开始计时; + if (cur_key_value != scan_para->notify_value) { //第一次单击/连击时按下的是不同按键, 单击次数重新开始计数 + scan_para->click_cnt = 1; + scan_para->notify_value = cur_key_value; + } else { + scan_para->click_cnt++; //单击次数累加 + } + } + goto _scan_end; //返回, 等待延时时间到 + } else { //cur_key = last_key -> 没有按键按下/按键长按(HOLD) + if (cur_key_value == NO_KEY) { //last_key = NO_KEY; cur_key = NO_KEY -> 没有按键按下 + if (scan_para->click_cnt > 0) { //有按键需要消息需要处理 + +#if ALL_KEY_EVENT_CLICK_ONLY//彩屏方案支持单击 + key_event = KEY_EVENT_CLICK; //单击 + key_value = scan_para->notify_value; + goto _notify; + +#endif + +#if KEY_EVENT_CLICK_ONLY_SUPPORT //是否支持某些按键只响应单击事件 + if (scan_para->notify_value & BIT(7)) { //BIT(7)按键特殊处理标志, 只发送单击事件, 也可以用于其它扩展 + key_event = KEY_EVENT_CLICK; //单击 + key_value = scan_para->notify_value; + goto _notify; + } +#endif + if (scan_para->click_delay_cnt > scan_para->click_delay_time) { //按键被抬起后延时到 + //TODO: 在此可以添加任意多击事件 + if (scan_para->click_cnt >= 5) { + key_event = KEY_EVENT_FIRTH_CLICK; //五击 + } else if (scan_para->click_cnt >= 4) { + key_event = KEY_EVENT_FOURTH_CLICK; //4击 + } else if (scan_para->click_cnt >= 3) { + key_event = KEY_EVENT_TRIPLE_CLICK; //三击 + } else if (scan_para->click_cnt >= 2) { + key_event = KEY_EVENT_DOUBLE_CLICK; //双击 + } else { + key_event = KEY_EVENT_CLICK; //单击 + } + key_value = scan_para->notify_value; + goto _notify; + } else { //按键抬起后等待下次延时时间未到 + scan_para->click_delay_cnt++; + goto _scan_end; //按键抬起后延时时间未到, 返回 + } + } else { + goto _scan_end; //没有按键需要处理 + } + } else { //last_key = valid_key; cur_key = valid_key, press_cnt累加用于判断long和hold + scan_para->press_cnt++; + if (scan_para->press_cnt == scan_para->long_time) { + key_event = KEY_EVENT_LONG; + } else if (scan_para->press_cnt == scan_para->hold_time) { + key_event = KEY_EVENT_HOLD; + scan_para->press_cnt = scan_para->long_time; + } else { + goto _scan_end; //press_cnt没到长按和HOLD次数, 返回 + } + //press_cnt没到长按和HOLD次数, 发消息 + key_value = cur_key_value; + goto _notify; + } + } + +_notify: +#if TCFG_IRSENSOR_ENABLE + if (get_irSensor_event() == IR_SENSOR_EVENT_FAR) { //未佩戴的耳机不响应按键 + return; + } +#endif + key_value &= ~BIT(7); //BIT(7) 用作按键特殊处理的标志 + e.type = SYS_KEY_EVENT; + e.u.key.init = 1; + e.u.key.type = scan_para->key_type;//区分按键类型 + e.u.key.event = key_event; + e.u.key.value = key_value; + e.u.key.tmr = timer_get_ms(); + + + scan_para->click_cnt = 0; //单击次数清0 + scan_para->notify_value = NO_KEY; + + e.arg = (void *)DEVICE_EVENT_FROM_KEY; + /* printf("key_value: 0x%x, event: %d\n", key_value, key_event); */ + if (key_event_remap(&e)) { + sys_event_notify(&e); +#if TCFG_KEY_TONE_EN + audio_key_tone_play(); +#endif + } +_scan_end: + scan_para->last_key = cur_key_value; + return; +} + + +//wakeup callback +void key_active_set(u8 port) +{ + is_key_active = 35; //35*10Ms +} + +//=======================================================// +// 按键初始化函数: 初始化所有注册的按键驱动 +//=======================================================// +int key_driver_init(void) +{ + int err; + +#if TCFG_IOKEY_ENABLE + extern const struct iokey_platform_data iokey_data; + extern struct key_driver_para iokey_scan_para; + err = iokey_init(&iokey_data); +#ifdef TCFG_IOKEY_TIME_REDEFINE + extern struct key_driver_para iokey_scan_user_para; + if (err == 0) { + sys_s_hi_timer_add((void *)&iokey_scan_user_para, key_driver_scan, iokey_scan_user_para.scan_time); //注册按键扫描定时器 + } +#else + if (err == 0) { + sys_s_hi_timer_add((void *)&iokey_scan_para, key_driver_scan, iokey_scan_para.scan_time); //注册按键扫描定时器 + } +#endif +#endif + +#if TCFG_ADKEY_ENABLE + extern const struct adkey_platform_data adkey_data; + extern struct key_driver_para adkey_scan_para; + err = adkey_init(&adkey_data); + if (err == 0) { + + sys_s_hi_timer_add((void *)&adkey_scan_para, key_driver_scan, adkey_scan_para.scan_time); //注册按键扫描定时器 + } +#endif + +#if TCFG_IRKEY_ENABLE + extern const struct irkey_platform_data irkey_data; + extern struct key_driver_para irkey_scan_para; + err = irkey_init(&irkey_data); + if (err == 0) { + sys_s_hi_timer_add((void *)&irkey_scan_para, key_driver_scan, irkey_scan_para.scan_time); //注册按键扫描定时器 + } +#endif + +#if TCFG_TOUCH_KEY_ENABLE + extern const struct touch_key_platform_data touch_key_data; + extern struct key_driver_para touch_key_scan_para; + err = touch_key_init(&touch_key_data); + if (err == 0) { + sys_s_hi_timer_add((void *)&touch_key_scan_para, key_driver_scan, touch_key_scan_para.scan_time); //注册按键扫描定时器 + } +#endif + +#if TCFG_ADKEY_RTCVDD_ENABLE + extern const struct adkey_rtcvdd_platform_data adkey_rtcvdd_data; + extern struct key_driver_para adkey_rtcvdd_scan_para; + err = adkey_rtcvdd_init(&adkey_rtcvdd_data); + if (err == 0) { + sys_s_hi_timer_add((void *)&adkey_rtcvdd_scan_para, key_driver_scan, adkey_rtcvdd_scan_para.scan_time); //注册按键扫描定时器 + } +#endif + +#if TCFG_RDEC_KEY_ENABLE + extern const struct rdec_platform_data rdec_key_data; + extern struct key_driver_para rdec_key_scan_para; + err = rdec_key_init(&rdec_key_data); + if (err == 0) { + sys_s_hi_timer_add((void *)&rdec_key_scan_para, key_driver_scan, rdec_key_scan_para.scan_time); //注册按键扫描定时器 + } +#endif + +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" + extern const struct ctmu_touch_key_platform_data ctmu_touch_key_data; + extern struct key_driver_para ctmu_touch_key_scan_para; + extern int ctmu_touch_key_init(const struct ctmu_touch_key_platform_data * ctmu_touch_key_data); + err = ctmu_touch_key_init(&ctmu_touch_key_data); + if (err == 0) { + sys_s_hi_timer_add((void *)&ctmu_touch_key_scan_para, key_driver_scan, ctmu_touch_key_scan_para.scan_time); //注册按键扫描定时器 + } +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +#if TCFG_SLIDE_KEY_ENABLE + extern const struct slidekey_platform_data slidekey_data; + extern int slidekey_init(const struct slidekey_platform_data * slidekey_data); + err = slidekey_init(&slidekey_data); + if (err == 0) { + } +#endif//TCFG_SLIDE_KEY_ENABLE + +#if TCFG_6083_ADKEY_ENABLE + extern int adkey_init_6083(); + err = adkey_init_6083(); + if (err == 0) { + } +#endif + return 0; +} + +static u8 key_idle_query(void) +{ + return !is_key_active; +} +#if !TCFG_LP_TOUCH_KEY_ENABLE +REGISTER_LP_TARGET(key_lp_target) = { + .name = "key", + .is_idle = key_idle_query, +}; +#endif /* #if !TCFG_LP_TOUCH_KEY_ENABLE */ + diff --git a/apps/common/key/rdec_key.c b/apps/common/key/rdec_key.c new file mode 100644 index 0000000..28dd0df --- /dev/null +++ b/apps/common/key/rdec_key.c @@ -0,0 +1,61 @@ +#include "key_driver.h" +#include "gpio.h" +#include "system/event.h" +#include "app_config.h" +#include "audio_config.h" +#include "rdec_key.h" + +#if TCFG_RDEC_KEY_ENABLE + +static const struct rdec_platform_data *__this = NULL; + +u8 rdec_get_key_value(void); + +struct key_driver_para rdec_key_scan_para = { + .scan_time = 10, //按键扫描频率, 单位: ms + .last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY; + .filter_time = 0, //按键消抖延时; + .long_time = 75, //按键判定长按数量 + .hold_time = (75 + 15), //按键判定HOLD数量 + .click_delay_time = 0, //按键被抬起后等待连击延时数量 + .key_type = KEY_DRIVER_TYPE_RDEC, + .get_value = rdec_get_key_value, +}; +extern s8 get_rdec_rdat(int i); + +extern u32 timer_get_ms(void); +u8 rdec_get_key_value(void) +{ + int i; + s8 rdec_data; + u8 key_value = 0; + if (!__this->enable) { + return NO_KEY; + } + for (i = 0; i < 3; i++) { + rdec_data = get_rdec_rdat(i); + if (rdec_data < 0) { + key_value = __this->rdec[i].key_value0; + return key_value; + } else if (rdec_data > 0) { + key_value = __this->rdec[i].key_value1; + return key_value; + } + } + return NO_KEY; +} +int rdec_key_init(const struct rdec_platform_data *rdec_key_data) +{ + __this = rdec_key_data; + if (!__this) { + return -EINVAL; + } + if (!__this->enable) { + return KEY_NOT_SUPPORT; + } + printf("rdec_key_init >>>> "); + return rdec_init(rdec_key_data); +} + +#endif /* #if TCFG_RDEC_KEY_ENABLE */ + diff --git a/apps/common/key/slidekey.c b/apps/common/key/slidekey.c new file mode 100644 index 0000000..cb5d8ca --- /dev/null +++ b/apps/common/key/slidekey.c @@ -0,0 +1,108 @@ +#include "key_driver.h" +#include "slidekey.h" +#include "gpio.h" +#include "system/event.h" +#include "system/includes.h" +#include "app_config.h" +#include "asm/clock.h" +#include "app_action.h" + +#if (TCFG_SLIDE_KEY_ENABLE) + +#define SLIDEKEY_FLIT_CNT_MAX 3 +#define SLIDEKEY_MAX_CH 10 +#define SLIDEKEY_SCAN_TIME 50 + +struct slide_key { + u16 old_ad[SLIDEKEY_MAX_CH]; + u16 flit_cnt[SLIDEKEY_MAX_CH]; + const struct slidekey_platform_data *parm; +}; + +static struct slide_key key; +#define __this (&key) + +static void slide_key_scan(void *p) +{ + u8 i = 0; + u16 ad_value_cur = 0; + u16 offset; + u16 distance = 0; + + if (!__this->parm->enable) { + return ; + } + + for (i = 0; i < __this->parm->num; i++) { + ad_value_cur = (u16)adc_get_value(__this->parm->port[i].ad_channel); + + //printf("nl = %d,nd = %d\n",slide_now_level[i],adc_get_value(__this->parm->port[i].ad_channel)); + if (ad_value_cur > __this->old_ad[i]) { + offset = ad_value_cur - __this->old_ad[i]; + } else { + offset = __this->old_ad[i] - ad_value_cur; + } + u16 level = (u16)(__this->parm->port[i].level); + distance = 1023 / (level + 1); + if (offset > distance / 2) { + __this->flit_cnt[i]++; + if (__this->flit_cnt[i] >= SLIDEKEY_FLIT_CNT_MAX) { + __this->flit_cnt[i] = 0; + __this->old_ad[i] = ad_value_cur; + u16 cur_level = ad_value_cur / distance; + if (cur_level > level) { + cur_level = level; + } + //y_printf("key\n"); + app_task_put_key_msg(__this->parm->port[i].msg, cur_level); + } + } else { + __this->flit_cnt[i] = 0; + } + } +} + + +void slidekey_update(void) +{ + local_irq_disable(); + for (int i = 0; i < SLIDEKEY_MAX_CH; i++) { + __this->old_ad[i] = (u16) - 1; //设置重置,可实现手动更新一次, 更新通过消息通知 + __this->flit_cnt[i] = 0; + } + local_irq_enable(); +} + + +int slidekey_init(const struct slidekey_platform_data *slidekey_data) +{ + u8 i = 0; + //memset(__this, 0x0, sizeof(struct slide_key)); + for (i = 0; i < SLIDEKEY_MAX_CH; i++) { + __this->old_ad[i] = (u16) - 1; //设置初值, 防止第一次没有变化, 没有发出单位变化 + __this->flit_cnt[i] = 0; + } + __this->parm = slidekey_data; + if (__this->parm == NULL) { + return -EINVAL; + } + for (i = 0; i < __this->parm->num; i++) { + adc_add_sample_ch(__this->parm->port[i].ad_channel); + + gpio_set_die(__this->parm->port[i].io, 0); + gpio_set_direction(__this->parm->port[i].io, 1); + gpio_set_pull_down(__this->parm->port[i].io, 0); + if (__this->parm->port[i].io_up_en) { + gpio_set_pull_up(__this->parm->port[i].io, 1); + } else { + gpio_set_pull_up(__this->parm->port[i].io, 0); + } + } + + sys_s_hi_timer_add(NULL, slide_key_scan, SLIDEKEY_SCAN_TIME); //注册按键扫描定时器 + return 0; +} + + +#endif /* #if TCFG_SLIDE_KEY_ENABLE */ + diff --git a/apps/common/key/touch_key.c b/apps/common/key/touch_key.c new file mode 100644 index 0000000..e71762e --- /dev/null +++ b/apps/common/key/touch_key.c @@ -0,0 +1,62 @@ +#include "touch_key.h" +#include "key_driver.h" +#include "app_config.h" + + +#if TCFG_TOUCH_KEY_ENABLE + + +/* =========== 触摸键使用说明 ============= */ +//1. 使用plcnt模块作计数; +//2. 配置参数时, 在配置好时钟后, 需要调试no_touch_cnt和touch_cnt的值; + +static const struct touch_key_platform_data *__this = NULL; + +//按键驱动扫描参数列表 +struct key_driver_para touch_key_scan_para = { + .scan_time = 10, //按键扫描频率, 单位: ms + .last_key = NO_KEY, //上一次get_value按键值, 初始化为NO_KEY; + .filter_time = 1, //按键消抖延时; + .long_time = 75, //按键判定长按数量 + .hold_time = (75 + 15), //按键判定HOLD数量 + .click_delay_time = 20, //按键被抬起后等待连击延时数量 + .key_type = KEY_DRIVER_TYPE_TOUCH, + .get_value = touch_key_get_value, +}; + +#define TOUCH_KEY_DEBUG 0 + +#if TOUCH_KEY_DEBUG +#define touch_key_debug(fmt, ...) printf("[TOUCH] "fmt, ##__VA_ARGS__) +#else +#define touch_key_debug(fmt, ...) +#endif + + +u8 touch_key_get_value(void) +{ + u8 key = get_plcnt_value(); + + if (key != NO_KEY) { + touch_key_debug("key = %d", key); + return __this->port_list[key].key_value; + } + + return NO_KEY; +} + + +int touch_key_init(const struct touch_key_platform_data *touch_key_data) +{ + __this = touch_key_data; + printf("touch_key_init >>>> "); + + return plcnt_init((void *)touch_key_data); +} + + +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + + + + diff --git a/apps/common/music/breakpoint.c b/apps/common/music/breakpoint.c new file mode 100644 index 0000000..494331c --- /dev/null +++ b/apps/common/music/breakpoint.c @@ -0,0 +1,83 @@ +#include "breakpoint.h" +#include "app_config.h" +#include "vm.h" +#include "system/syscfg_id.h" + +#if (defined(TCFG_DEC_APE_ENABLE) && (TCFG_DEC_APE_ENABLE)) +#define BREAKPOINT_DATA_LEN (2036 + 4) +#elif (defined(TCFG_DEC_FLAC_ENABLE) && (TCFG_DEC_FLAC_ENABLE)) +#define BREAKPOINT_DATA_LEN 688 +#elif (TCFG_DEC_M4A_ENABLE || TCFG_DEC_ALAC_ENABLE) +#define BREAKPOINT_DATA_LEN 536 +#endif + +#ifndef BREAKPOINT_DATA_LEN +#define BREAKPOINT_DATA_LEN 32 +#endif + +#define BREAKPOINT_VAILD_SIZE(p) ((p)->dbp.len + ((u32)(p)->dbp.data - (u32)(p))) + +struct __breakpoint *breakpoint_handle_creat(void) +{ + struct __breakpoint *bp = (struct __breakpoint *)zalloc(sizeof(struct __breakpoint) + BREAKPOINT_DATA_LEN); + bp->dbp.data_len = BREAKPOINT_DATA_LEN; + return bp; +} + +void breakpoint_handle_destroy(struct __breakpoint **bp) +{ + if (bp && *bp) { + free(*bp); + *bp = NULL; + } +} + +bool breakpoint_vm_read(struct __breakpoint *bp, char *logo) +{ + if (bp == NULL || logo == NULL) { + return false; + } + u16 vm_id; + if (!strcmp(logo, "sd0")) { + vm_id = CFG_SD0_BREAKPOINT0; + } else if (!strcmp(logo, "sd1")) { + vm_id = CFG_SD1_BREAKPOINT0; + } else if (!strcmp(logo, "udisk0")) { + vm_id = CFG_USB_BREAKPOINT0; + } else { + return false; + } + int rlen = vm_api_read_mult(vm_id, vm_id + 10, bp, sizeof(struct __breakpoint) + BREAKPOINT_DATA_LEN); + if (rlen == 0) { + memset(bp, 0, sizeof(struct __breakpoint) + BREAKPOINT_DATA_LEN); + bp->dbp.data_len = BREAKPOINT_DATA_LEN; + return false; + } else { + } + return true; +} + +void breakpoint_vm_write(struct __breakpoint *bp, char *logo) +{ + if (bp == NULL || logo == NULL) { + return ; + } + u16 vm_id; + if (!strcmp(logo, "sd0")) { + vm_id = CFG_SD0_BREAKPOINT0; + } else if (!strcmp(logo, "sd1")) { + vm_id = CFG_SD1_BREAKPOINT0; + } else if (!strcmp(logo, "udisk0")) { + vm_id = CFG_USB_BREAKPOINT0; + } else { + return ; + } + printf("%s %s ok\n", logo, __FUNCTION__); + vm_api_write_mult(vm_id, vm_id + 10, bp, BREAKPOINT_VAILD_SIZE(bp), 2); +} + + + + + + diff --git a/apps/common/music/breakpoint.h b/apps/common/music/breakpoint.h new file mode 100644 index 0000000..573d834 --- /dev/null +++ b/apps/common/music/breakpoint.h @@ -0,0 +1,14 @@ +#ifndef __BREAKPOINT_H__ +#define __BREAKPOINT_H__ + +#include "system/includes.h" +#include "media/audio_decoder.h" +#include "music/music_player.h" + +struct __breakpoint *breakpoint_handle_creat(void); +void breakpoint_handle_destroy(struct __breakpoint **bp); +bool breakpoint_vm_read(struct __breakpoint *bp, char *logo); +void breakpoint_vm_write(struct __breakpoint *bp, char *logo); + +#endif//__BREAKPOINT_H__ + diff --git a/apps/common/music/general_player.c b/apps/common/music/general_player.c new file mode 100644 index 0000000..9f4674d --- /dev/null +++ b/apps/common/music/general_player.c @@ -0,0 +1,272 @@ +#include "app_config.h" +#include "key_event_deal.h" +#include "audio_enc.h" +#include "general_player.h" +#include "dev_manager.h" +#include "bt/bt.h" +#include "common/dev_status.h" +#include "app_task.h" +#include "app_msg.h" +#include "media/audio_decoder.h" +#include "file_operate/file_manager.h" +#include "audio_dec/audio_dec_file.h" +///播放参数,文件扫描时用,文件后缀等 +static const char scan_parm[] = "-t" +#if (TCFG_DEC_MP3_ENABLE) + "MP1MP2MP3" +#endif +#if (TCFG_DEC_WMA_ENABLE) + "WMA" +#endif +#if ( TCFG_DEC_WAV_ENABLE || TCFG_DEC_DTS_ENABLE) + "WAVDTS" +#endif +#if (TCFG_DEC_FLAC_ENABLE) + "FLA" +#endif +#if (TCFG_DEC_APE_ENABLE) + "APE" +#endif +#if (TCFG_DEC_M4A_ENABLE) + "M4AAAC" +#endif +#if (TCFG_DEC_M4A_ENABLE || TCFG_DEC_ALAC_ENABLE) + "MP4" +#endif +#if (TCFG_DEC_AMR_ENABLE) + "AMR" +#endif +#if (TCFG_DEC_DECRYPT_ENABLE) + "SMP" +#endif +#if (TCFG_DEC_MIDI_ENABLE) + "MID" +#endif + " -sn -r" + ; + +struct __general_player { + struct __dev *dev; + struct vfscan *fsn; + FILE *file; + struct __scan_callback *scan_cb; + u8 scandisk_break; +}; + +static struct __general_player *general_player = NULL; +#define __this general_player + +int general_player_init(struct __scan_callback *scan_cb) +{ + printf("the general_player init\n"); + __this = zalloc(sizeof(struct __general_player)); + if (__this == NULL) { + return -1; + } else { + __this->scan_cb = scan_cb; + return 0; + } +} + +void general_player_exit() +{ + if (__this) { + general_player_stop(1); + free(__this); + __this = NULL; + } +} + +void general_player_stop(u8 fsn_release) +{ + if (__this == NULL) { + return ; + } + ///停止解码 + file_dec_close(); + if (__this->file) { + fclose(__this->file); + __this->file = NULL; + } + if (fsn_release && __this->fsn) { + ///根据播放情景, 通过设定flag决定是否需要释放fscan, 释放后需要重新扫盘!!! + dev_manager_scan_disk_release(__this->fsn); + __this->fsn = NULL; + } +} + + +//可以添加播放回调函数 +static int general_player_decode_start(FILE *file) +{ + int ret = 0; + + if (file) { + ///get file short name + u8 file_name[12 + 1] = {0}; //8.3+\0 + fget_name(file, file_name, sizeof(file_name)); + log_i("\n"); + log_i("file name: %s\n", file_name); + log_i("\n"); + } + ret = file_dec_create(NULL, NULL); + if (ret) { + return GENERAL_PLAYER_ERR_NO_RAM; + } + ret = file_dec_open(file, NULL); + if (ret) { + return GENERAL_PLAYER_ERR_DECODE_FAIL; + } + return GENERAL_PLAYER_SUCC; +} + +static const char *general_player_get_phy_dev(int *len) +{ + if (__this) { + char *logo = dev_manager_get_logo(__this->dev); + if (logo) { + char *str = strstr(logo, "_rec"); + if (str) { + ///录音设备,切换到音乐设备播放 + if (len) { + *len = strlen(logo) - strlen(str); + } + } else { + if (len) { + *len = strlen(logo); + } + } + return logo; + } + } + if (len) { + *len = 0; + } + return NULL; +} + +int general_player_scandisk_break(void) +{ + ///注意: + ///需要break fsn的事件, 请在这里拦截, + ///需要结合MUSIC_PLAYER_ERR_FSCAN错误,做相应的处理 + int msg[32] = {0}; + struct sys_event *event = NULL; + char *logo = NULL; + char *evt_logo = NULL; + app_task_get_msg(msg, ARRAY_SIZE(msg), 0); + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + event = (struct sys_event *)(&msg[1]); + switch (event->type) { + case SYS_DEVICE_EVENT: + switch ((u32)event->arg) { + case DRIVER_EVENT_FROM_SD0: + case DRIVER_EVENT_FROM_SD1: + case DRIVER_EVENT_FROM_SD2: + evt_logo = (char *)event->u.dev.value; + case DEVICE_EVENT_FROM_OTG: + if ((u32)event->arg == DEVICE_EVENT_FROM_OTG) { + evt_logo = (char *)"udisk0"; + } + ///设备上下线底层推出的设备逻辑盘符是跟跟音乐设备一致的(音乐/录音设备, 详细看接口注释) + int str_len = 0; + logo = general_player_get_phy_dev(&str_len); + //logo = dev_manager_get_logo(__this->dev); + ///响应设备插拔打断 + if (event->u.dev.event == DEVICE_EVENT_OUT) { + log_i("__func__ = %s logo=%s evt_logo=%s %d\n", __FUNCTION__, logo, evt_logo, str_len); + if (logo && (0 == memcmp(logo, evt_logo, str_len))) { + ///相同的设备才响应 + __this->scandisk_break = 1; + } + } else { + ///响应新设备上线 + __this->scandisk_break = 1; + } + if (__this->scandisk_break == 0) { + log_i("__func__ = %s DEVICE_EVENT_OUT TODO\n", __FUNCTION__); + dev_status_event_filter(event); + log_i("__func__ = %s DEVICE_EVENT_OUT OK\n", __FUNCTION__); + } + break; + } + break; + case SYS_BT_EVENT: + if (bt_background_event_handler_filter(event)) { + __this->scandisk_break = 1; + } + break; + case SYS_KEY_EVENT: + switch (event->u.key.event) { + case KEY_CHANGE_MODE: + ///响应切换模式事件 + __this->scandisk_break = 1; + break; + } + break; + } + break; + } + if (__this->scandisk_break) { + ///查询到需要打断的事件, 返回1, 并且重新推送一次该事件,跑主循环处理流程 + printf("\n--func=%s, line=%d\n", __FUNCTION__, __LINE__); + sys_event_notify(event); + printf("scandisk_break!!!!!!\n"); + return 1; + } else { + return 0; + } +} + +int general_play_by_sculst(char *logo, u32 sclust) +{ + int ret = 0; + if (logo == NULL) { + return GENERAL_PLAYER_ERR_PARM; + } + char *cur_logo = dev_manager_get_logo(__this->dev); + if (cur_logo == NULL || strcmp(cur_logo, logo) != 0) { + if (cur_logo != NULL) { + general_player_stop(1); + } + __this->dev = dev_manager_find_spec(logo, 1); + if (!__this->dev) { + return GENERAL_PLAYER_ERR_DEV_NOFOUND; + } + __this->fsn = dev_manager_scan_disk(__this->dev, NULL, scan_parm, 0, __this->scan_cb); + if (!__this->fsn) { + return GENERAL_PLAYER_ERR_FSCAN; + } + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_BY_SCLUST, sclust, __this->scan_cb); + if (!__this->file) { + return GENERAL_PLAYER_ERR_FILE_NOFOUND; + } + ret = general_player_decode_start(__this->file); + if (ret != GENERAL_PLAYER_SUCC) { + return ret; + } + } else { + general_player_stop(0); + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_BY_SCLUST, sclust, __this->scan_cb); + if (!__this->file) { + return GENERAL_PLAYER_ERR_FILE_NOFOUND; + } + ret = general_player_decode_start(__this->file); + if (ret != GENERAL_PLAYER_SUCC) { + return ret; + } + } + return GENERAL_PLAYER_ERR_NULL; +} + +void general_player_test() +{ + int tmp = general_player_init(NULL); + if (!tmp) { + printf("the init succ\n"); + general_play_by_sculst((char *)"sd0", 6); + } else { + printf("the init fail\n"); + } +} diff --git a/apps/common/music/general_player.h b/apps/common/music/general_player.h new file mode 100644 index 0000000..c7164ee --- /dev/null +++ b/apps/common/music/general_player.h @@ -0,0 +1,28 @@ +#ifndef __GENERAL_PLAYER_H__ +#define __GENERAL_PLAYER_H__ + +#include "system/app_core.h" +#include "system/includes.h" +#include "system/event.h" +#include "dev_manager.h" + +///解码错误码表 +enum { + GENERAL_PLAYER_ERR_NULL = 0x0, ///没有错误, 不需要做任何 + GENERAL_PLAYER_SUCC = 0x1, ///播放成功, 可以做相关显示、断点记忆等处理 + GENERAL_PLAYER_ERR_PARM, ///参数错误 + GENERAL_PLAYER_ERR_DECODE_FAIL, ///解码器启动失败错误 + GENERAL_PLAYER_ERR_NO_RAM, ///没有ram空间错误 + GENERAL_PLAYER_ERR_DEV_NOFOUND, ///没有找到指定设备 + GENERAL_PLAYER_ERR_DEV_OFFLINE, ///设备不在线错误 + GENERAL_PLAYER_ERR_FSCAN, ///设备扫描失败 + GENERAL_PLAYER_ERR_FILE_NOFOUND, ///没有找到文件 +}; + +int general_player_init(struct __scan_callback *scan_cb); +void general_player_stop(u8 fsn_release); +int general_play_by_sculst(char *logo, u32 sclust); +void general_player_exit(); +void general_player_test(); +int general_player_scandisk_break(void); +#endif diff --git a/apps/common/music/music_decrypt.c b/apps/common/music/music_decrypt.c new file mode 100644 index 0000000..fe15cf3 --- /dev/null +++ b/apps/common/music/music_decrypt.c @@ -0,0 +1,184 @@ + +#include "system/app_core.h" +#include "system/includes.h" +#include "app_config.h" +#include "music/music_decrypt.h" +#include "system/fs/fs.h" + +#if (TCFG_DEC_DECRYPT_ENABLE) + +#define LOG_TAG_CONST APP_MUSIC +#define LOG_TAG "[APP_MUSIC_CIPHER]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +/*----------------------------------------------------------------------------*/ +/**@brief 解密读使能开关 + @param u8 ctl + @return 无 + @note void cipher_ctl(u8 ctl) + */ +/*----------------------------------------------------------------------------*/ +static void cipher_ctl(CIPHER *pcipher, u8 ctl) +{ + pcipher->cipher_enable = ctl; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 解密读文件数据的回调函数,用于底层的物理读 + @param void* buf, u32 lba + @return 无 + @note void cryptanalysis_buff(void* buf, u32 faddr, u32 len) + */ +/*----------------------------------------------------------------------------*/ +#define ALIN_SIZE 4 +void cryptanalysis_buff(CIPHER *pcipher, void *buf, u32 faddr, u32 len) +{ + u32 i; + u8 j; + u8 head_rem;// + u8 tail_rem;// + u32 len_ali; + + u8 *buf_1b_ali; + u8 *cipher_code; + + cipher_code = (u8 *)&pcipher->cipher_code; + + if (!pcipher->cipher_enable) { + return; + } + /* log_info("----faddr = %d \n",faddr); */ + /* put_buf(buf,len); */ + /* log_info("buf_addr = %d \n", buf); */ + + head_rem = ALIN_SIZE - (faddr % ALIN_SIZE); + if (head_rem == ALIN_SIZE) { + head_rem = 0; + } + if (head_rem > len) { + head_rem = len; + } + + if (len - head_rem) { + tail_rem = (faddr + len) % ALIN_SIZE; + } else { + tail_rem = 0; + } + /* log_info("head_rem = %d tail_rem = %d \n", head_rem, tail_rem); */ + /* log_info("deal_head_buf\n"); */ + buf_1b_ali = buf; + j = 3; + for (i = head_rem; i > 0; i--) { + buf_1b_ali[i - 1] ^= cipher_code[j--]; + /* log_info("i = %d \n", i - 1); */ + /* log_info("buf_1b_ali[i] = %x \n", buf_1b_ali[i - 1]); */ + } + /* log_info("\n\n-----------TEST_HEAD-----------------"); */ + /* put_buf(buf_1b_ali, head_rem); */ + /* log_info("deal_main_buf\n"); */ + buf_1b_ali = buf; + buf_1b_ali = (u8 *)(buf_1b_ali + head_rem); + len_ali = len - head_rem - tail_rem; + /* log_info("len_ali = %d \n", len_ali); */ + /* log_info("buf_1b_ali = %d \n", buf_1b_ali); */ + for (i = 0; i < (len_ali / 4); i++) { + buf_1b_ali[0 + i * 4] ^= cipher_code[0]; + buf_1b_ali[1 + i * 4] ^= cipher_code[1]; + buf_1b_ali[2 + i * 4] ^= cipher_code[2]; + buf_1b_ali[3 + i * 4] ^= cipher_code[3]; + } + /* log_info("\n\n-----------TEST_MAIN-----------------"); */ + /* put_buf(buf_1b_ali, len_ali); */ + + /* log_info("deal_tail_buf\n"); */ + buf_1b_ali = buf; + buf_1b_ali += len - tail_rem; + j = 0; + for (i = 0 ; i < tail_rem; i++) { + buf_1b_ali[i] ^= cipher_code[j++]; + } + /* log_info("\n\n-----------TEST_TAIL-----------------"); */ + /* put_buf(buf_1b_ali, tail_rem); */ + + /* log_info("\n\n-----------TEST-----------------"); */ + /* put_buf(buf,len); */ +} + +/*----------------------------------------------------------------------------*/ +/**@brief 解密判断 + @param void *file:当前解码文件的句柄 + @return 无 + @note void cipher_check_decode_file(void *file) + */ +/*----------------------------------------------------------------------------*/ +void cipher_check_decode_file(CIPHER *pcipher, void *file) +{ + int rlen; + u8 name[128]; + memset(name, 0, sizeof(name)); + rlen = fget_name(file, name, sizeof(name)); + /* log_info("rlen:%d \n", rlen); */ + /* put_buf(name, sizeof(name)); */ + u8 *ext_name = strrchr(name, '.'); + if (ext_name == NULL) { + // 可能是83结构文件名 + int name_len = strlen(name); + if (name_len > 3) { + rlen = name_len - 4; + goto __check_ext; + } + } + while (rlen--) { + if ((name[rlen] >= 'a') && (name[rlen] <= 'z')) { + name[rlen] = name[rlen] - 'a' + 'A'; + } + if (name[rlen] != '.') { + continue; + } +__check_ext: + /* log_info("file exname : %s \n", &name[rlen+1]); */ + /* log_info("rlen:%d \n", rlen); */ + /* put_buf(name, sizeof(name)); */ + if (((name[rlen + 1] == 'S') && (name[rlen + 2] == 'M') && (name[rlen + 3] == 'P')) // assci + || ((name[rlen + 2] == 'S') && (name[rlen + 4] == 'M') && (name[rlen + 6] == 'P')) // unicode + ) { + log_info("\n----It's a SMP FILE---\n"); + cipher_ctl(pcipher, 1); + } + return; + } + cipher_ctl(pcipher, 0); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 解密读初始化 + @param 无 + @return 无 + @note void cipher_init(u32 key) + */ +/*----------------------------------------------------------------------------*/ +void cipher_init(CIPHER *pcipher, u32 key) +{ + pcipher->cipher_code = key; + cipher_ctl(pcipher, 0); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 解密读初关闭 + @param 无 + @return 无 + @note void cipher_close(void) + */ +/*----------------------------------------------------------------------------*/ +void cipher_close(CIPHER *pcipher) +{ + cipher_ctl(pcipher, 0); +} + +#endif + diff --git a/apps/common/music/music_decrypt.h b/apps/common/music/music_decrypt.h new file mode 100644 index 0000000..852031d --- /dev/null +++ b/apps/common/music/music_decrypt.h @@ -0,0 +1,19 @@ +#ifndef __MUSIC_DECRYPT_H__ +#define __MUSIC_DECRYPT_H__ + +#include "typedef.h" + +typedef struct _CIPHER { + u32 cipher_code; ///>解密key + u8 cipher_enable; ///>解密读使能 +} CIPHER; + +void cryptanalysis_buff(CIPHER *pcipher, void *buf, u32 faddr, u32 len); + +void cipher_check_decode_file(CIPHER *pcipher, void *file); + +void cipher_init(CIPHER *pcipher, u32 key); +void cipher_close(CIPHER *pcipher); + + +#endif //__MUSIC_DECRYPT_H__ diff --git a/apps/common/music/music_id3.c b/apps/common/music/music_id3.c new file mode 100644 index 0000000..8db56f8 --- /dev/null +++ b/apps/common/music/music_id3.c @@ -0,0 +1,298 @@ +#include "system/app_core.h" +#include "system/includes.h" +#include "app_config.h" +#include "music/music_id3.h" +#include "system/fs/fs.h" + +#if ((TCFG_DEC_ID3_V1_ENABLE) || (TCFG_DEC_ID3_V2_ENABLE)) + +#define LOG_TAG_CONST APP_MUSIC +#define LOG_TAG "[APP_MUSIC_ID3]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#define ID3_ANALYSIS_EN 1 // ID3解析 + +struct id3_v1_hdl { + char header[3]; // TAG + char title[30]; // 标题 + char artist[30]; // 作者 + char album[30]; // 专辑 + char year[4]; // 出品年代 + char comment[30]; // 备注 + char genre; // 类型 +}; + +struct id3_v2_hdl { + char header[3]; // ID3 + char ver; // 版本号 + char revision; // 副版本号 + char flag; // 标志 + u8 size[4]; // 标签大小,不包括标签头的10个字节 +}; + +struct id3_v2_frame { + char frameID[4]; // 帧标识 + u8 size[4]; // 帧大小,不包括帧头10个字节,不小于1 + char flags[2]; // 标志 +}; + +#define ID3_SIZEOF_ALIN(var,al) ((((var)+(al)-1)/(al))*(al)) +#define ID3_V1_HEADER_SIZE (128) // sizeof(struct id3_v1_hdl) +#define ID3_V2_HEADER_SIZE (10) // sizeof(struct id3_v2_hdl) +#define ID3_V2_HEADER_SIZE_MAX (1024 * 2) + +#define ID3_V2_FRAME_SIZE (10) // sizeof(struct id3_v2_frame) + +static u8 id3_v1_match(u8 *buf) +{ + if (buf[0] == 'T' && buf[1] == 'A' && buf[2] == 'G') { + return true; + } else { + return false; + } +} + +static u8 id3_v2_match(u8 *buf) +{ + //put_buf(buf, 16); + if ((buf[0] == 'I') + && (buf[1] == 'D') + && (buf[2] == '3') + && (buf[3] != 0xff) + && (buf[4] != 0xff) + && ((buf[6] & 0x80) == 0) + && ((buf[7] & 0x80) == 0) + && ((buf[8] & 0x80) == 0) + && ((buf[9] & 0x80) == 0)) { + return true; + } else { + return false; + } +} + +static u32 id3v2_get_tag_len(u8 *buf) +{ + u32 len = (((u32)buf[6] & 0x7f) << 21) + + (((u32)buf[7] & 0x7f) << 14) + + (((u32)buf[8] & 0x7f) << 7) + + (buf[9] & 0x7f) + + ID3_V2_HEADER_SIZE; + + if (buf[5] & 0x10) { + len += ID3_V2_HEADER_SIZE; + } + + log_info("----id3v2_len%d---\n", len); + return len; +} + +#if ID3_ANALYSIS_EN + +static void id3_v1_analysis(MP3_ID3_OBJ *obj) +{ + struct id3_v1_hdl *hdl = (struct id3_v1_hdl *)obj->id3_buf; + /* log_info("header:%s \n", hdl->header); */ + log_info("title:%s \n", hdl->title); + log_info("artist:%s \n", hdl->artist); + log_info("album:%s \n", hdl->album); + log_info("year:%s \n", hdl->year); + log_info("comment:%s \n", hdl->comment); + log_info("genre:%d \n", hdl->genre); +} + +static const u8 ID3_V2_FRAME_ID[][4] = { + "TIT2", // 标题 + "TPE1", // 作者 + "TALB", // 专辑 + "TYER", // 年代 + "TCON", // 类型 + "COMM", // 备注 +}; + +static void id3_v2_analysis(void *file, void *buf) +{ +#define FRAME_DAT_MAX 512 + u8 *frame_dat = malloc(FRAME_DAT_MAX); + u8 frame_hdl[ID3_V2_FRAME_SIZE]; + u32 frame_len; + struct id3_v2_hdl *hdl = (struct id3_v2_hdl *)buf; + /* log_info("header:%s \n", hdl->header); */ + + if (!frame_dat) { + return ; + } + + u32 addr = ID3_V2_HEADER_SIZE; + u32 addr_end = id3v2_get_tag_len(buf) + ID3_V2_HEADER_SIZE; + log_info("frame total len:0x%x ", addr_end); + while (addr < addr_end) { + fseek(file, addr, SEEK_SET); + fread(file, frame_hdl, ID3_V2_FRAME_SIZE); + + int idx; + struct id3_v2_frame *frame = (struct id3_v2_frame *)frame_hdl; + frame_len = (((u32)frame->size[0]) << 24) + (((u32)frame->size[1]) << 16) + (((u32)frame->size[2]) << 8) + (u32)frame->size[3]; + + log_info_hexdump(frame, ID3_V2_FRAME_SIZE); + log_info("frame ID:%s ", frame->frameID); + log_info("frame len:0x%x ", frame_len); + log_info("addr :0x%x ", addr); + + if (!frame_len) { + break; + } + if (frame_len <= FRAME_DAT_MAX) { + memset(frame_dat, 0, FRAME_DAT_MAX); + fread(file, frame_dat, frame_len); + } + + for (idx = 0; idx < sizeof(ID3_V2_FRAME_ID) / 4; idx++) { + if (!memcmp(frame->frameID, ID3_V2_FRAME_ID[idx], 4)) { + log_info("find frameID \n"); + break; + } + } + if (frame_len <= FRAME_DAT_MAX) { + log_info("frame dat:%s, \n", frame_dat); + log_info_hexdump(frame_dat, frame_len); + } + addr += ID3_V2_FRAME_SIZE + frame_len; + } + + free(frame_dat); +} +#endif + +void id3_obj_post(MP3_ID3_OBJ **obj) +{ + if (obj == NULL || (*obj) == NULL) { + return ; + } + free(*obj); + *obj = NULL; +} + +MP3_ID3_OBJ *id3_v1_obj_get(void *file) +{ + if (file == NULL) { + return NULL; + } + + MP3_ID3_OBJ *obj = NULL; + u8 *need_buf = NULL; + u32 need_buf_size; + u32 cur_fptr = fpos(file); + u32 file_len = flen(file); + + need_buf_size = ID3_SIZEOF_ALIN(sizeof(MP3_ID3_OBJ), 4) + + ID3_SIZEOF_ALIN(ID3_V1_HEADER_SIZE, 4); + need_buf = (u8 *)zalloc(need_buf_size); + if (need_buf == NULL) { + log_error("malloc err !!\n"); + return NULL; + } + + obj = (MP3_ID3_OBJ *)need_buf; + obj->id3_buf = (u8 *)(need_buf + ID3_SIZEOF_ALIN(sizeof(MP3_ID3_OBJ), 4)); + obj->id3_len = ID3_V1_HEADER_SIZE; + + fseek(file, (file_len - ID3_V1_HEADER_SIZE), SEEK_SET); + fread(file, obj->id3_buf, ID3_V1_HEADER_SIZE); + + if (id3_v1_match(obj->id3_buf) == true) { + log_info("find id3 v1 !!\n"); + put_buf(obj->id3_buf, obj->id3_len); + } else { + goto __id3_v1_err; + } + +#if ID3_ANALYSIS_EN + id3_v1_analysis(obj); +#else + + fseek(file, cur_fptr, SEEK_SET); + + return obj; +#endif + +__id3_v1_err: + fseek(file, cur_fptr, SEEK_SET); + + if (need_buf) { + free(need_buf); + } + return NULL; +} + + +MP3_ID3_OBJ *id3_v2_obj_get(void *file) +{ + if (file == NULL) { + return NULL; + } + MP3_ID3_OBJ *obj = NULL; + u8 *need_buf = NULL; + u32 need_buf_size; + u8 tmp_buf[ID3_V2_HEADER_SIZE]; + u32 cur_fptr = fpos(file); + + fseek(file, 0, SEEK_SET); + fread(file, tmp_buf, ID3_V2_HEADER_SIZE); + + if (id3_v2_match(tmp_buf) == true) { + log_info("find id3 v2 !!\n"); + +#if ID3_ANALYSIS_EN + id3_v2_analysis(file, (MP3_ID3_OBJ *)tmp_buf); +#else + + u32 tag_len = id3v2_get_tag_len(tmp_buf); + + if (tag_len > (ID3_V2_HEADER_SIZE_MAX)) { + log_error("id3 v2 info is too big!!\n", tag_len); + goto __id3_v2_err; + } + + need_buf_size = ID3_SIZEOF_ALIN(sizeof(MP3_ID3_OBJ), 4) + + ID3_SIZEOF_ALIN(tag_len, 4); + + need_buf = (u8 *)zalloc(need_buf_size); + if (need_buf == NULL) { + log_error("no space for id3 v2 %d\n", tag_len); + goto __id3_v2_err; + } + + obj = (MP3_ID3_OBJ *)need_buf; + obj->id3_buf = (u8 *)(need_buf + ID3_SIZEOF_ALIN(sizeof(MP3_ID3_OBJ), 4)); + obj->id3_len = tag_len; + + fseek(file, 0, SEEK_SET); + fread(file, obj->id3_buf, obj->id3_len); + + log_info("id3_v2 size = %d\n", obj->id3_len); + put_buf(obj->id3_buf, obj->id3_len); +#endif + + } else { + goto __id3_v2_err; + } + fseek(file, cur_fptr, SEEK_SET); + + return obj; + +__id3_v2_err: + fseek(file, cur_fptr, SEEK_SET); + + if (need_buf) { + free(need_buf); + } + return NULL; +} + +#endif + diff --git a/apps/common/music/music_id3.h b/apps/common/music/music_id3.h new file mode 100644 index 0000000..87bb1c6 --- /dev/null +++ b/apps/common/music/music_id3.h @@ -0,0 +1,15 @@ +#ifndef __MUSIC_ID3_H__ +#define __MUSIC_ID3_H__ +#include "typedef.h" + +typedef struct __MP3_ID3_OBJ { + u8 *id3_buf; + u32 id3_len; +} MP3_ID3_OBJ; + +void id3_obj_post(MP3_ID3_OBJ **obj); +MP3_ID3_OBJ *id3_v1_obj_get(void *file); +MP3_ID3_OBJ *id3_v2_obj_get(void *file); + +#endif// __MUSIC_ID3_H__ + diff --git a/apps/common/music/music_player.c b/apps/common/music/music_player.c new file mode 100644 index 0000000..0cf2e52 --- /dev/null +++ b/apps/common/music/music_player.c @@ -0,0 +1,1515 @@ +#include "music/music_player.h" +#include "key_event_deal.h" +#include "app_config.h" +#include "audio_enc.h" +#include "app_main.h" +#include "vm.h" +#include "bt_emitter.h" + +#define LOG_TAG_CONST APP_MUSIC +#define LOG_TAG "[APP_MUSIC]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + + +#define MUSIC_PLAYER_CYCLE_ALL_DEV_EN 1//FCYCLE_ALL循环模式是否使能所有设备循环 +#define MUSIC_PLAYER_PLAY_FOLDER_PREV_FIRST_FILE_EN 0//切换上一个文件夹,1:播放文件夹的第一首, 0:最后一首 + + +///music player总控制句柄 +struct __music_player { + struct __dev *dev;//当前播放设备节点 + struct vfscan *fsn;//设备扫描句柄 + FILE *file;//当前播放文件句柄 + FILE *lrc_file;//当前播放文件句柄 + void *priv;//music回调函数,私有参数 + struct __player_parm parm;//回调及参数配置 +}; + +static struct __music_player *music_player = NULL; +#define __this music_player + +static volatile u16 magic_cnt = 0; + +///播放参数,文件扫描时用,文件后缀等 +static const char scan_parm[] = "-t" +#if (TCFG_DEC_MP3_ENABLE) + "MP1MP2MP3" +#endif +#if (TCFG_DEC_WMA_ENABLE) + "WMA" +#endif +#if ( TCFG_DEC_WAV_ENABLE || TCFG_DEC_DTS_ENABLE) + "WAVDTS" +#endif +#if (TCFG_DEC_FLAC_ENABLE) + "FLA" +#endif +#if (TCFG_DEC_APE_ENABLE) + "APE" +#endif +#if (TCFG_DEC_M4A_ENABLE) + "M4AAAC" +#endif +#if (TCFG_DEC_M4A_ENABLE || TCFG_DEC_ALAC_ENABLE) + "MP4" +#endif +#if (TCFG_DEC_AMR_ENABLE) + "AMR" +#endif +#if (TCFG_DEC_DECRYPT_ENABLE) + "SMP" +#endif +#if (TCFG_DEC_MIDI_ENABLE) + "MID" +#endif + " -sn -r" +#if (TCFG_RECORD_FOLDER_DEV_ENABLE) + " -m" + REC_FOLDER_NAME +#endif + ; + +static volatile u8 save_mode_cnt = 0; +static volatile u16 save_mode_timer = 0; +//*----------------------------------------------------------------------------*/ +/**@brief music_player循环模式处理接口 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void music_player_mode_save_do(void *priv) +{ + local_irq_disable(); + if (++save_mode_cnt >= 5) { + if (save_mode_timer) { + sys_timer_del(save_mode_timer); + } + save_mode_timer = 0; + save_mode_cnt = 0; + local_irq_enable(); + syscfg_write(CFG_MUSIC_MODE, &app_var.cycle_mode, 1); + return; + } + local_irq_enable(); +} + +//*----------------------------------------------------------------------------*/ +/**@brief music_player释放接口 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void music_player_destroy(void) +{ + if (__this) { + music_player_stop(1); + free(__this); + __this = NULL; + } +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player创建接口 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +bool music_player_creat(void *priv, struct __player_parm *parm) +{ + __this = zalloc(sizeof(struct __music_player)); + if (__this == NULL) { + return false; + } + + __this->priv = priv; + memcpy(&__this->parm, parm, sizeof(struct __player_parm)); + ASSERT(__this->parm.cb, "music_player parm error!!\n"); + ASSERT(__this->parm.scan_cb, "music_player parm error 1 !!\n"); + return true; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player播放结束处理 + @param parm:结束参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_end_deal(int parm) +{ + int err = 0; + u8 event = (u8)parm; + u8 read_err = (u8)(parm >> 8); + u16 magic = (u16)(parm >> 16); + switch (event) { + ///文件播放结束, 包括正常播放结束和读文件错误导致的结束, 如拔掉设备产生的错误结束 + case AUDIO_DEC_EVENT_END: + log_i("AUDIO_DEC_EVENT_END\n"); + if (read_err) { + log_e("read err, magic err = %d, %d\n", magic, magic_cnt); + if (magic == magic_cnt - 1) { + if (read_err == 1) { + err = MUSIC_PLAYER_ERR_FILE_READ;///文件读错误 + } else { + err = MUSIC_PLAYER_ERR_DEV_READ;///设备读错误 + } + } else { + err = MUSIC_PLAYER_ERR_NULL;///序号已经对不上了, 不处理 + } + + } else { + ///正常结束,自动下一曲 +#if (MUSIC_PLAYER_CYCLE_ALL_DEV_EN) + u32 cur_file = music_player_get_file_cur(); + if ((music_player_get_record_play_status() == false) + && (app_var.cycle_mode == FCYCLE_ALL) + && (cur_file >= music_player_get_file_total()) + && (dev_manager_get_total(1) > 1)) { + char *logo = music_player_get_dev_flit("_rec", 1); + if (logo) { + err = music_player_play_first_file(logo); + break; + } + } +#endif/*MUSIC_PLAYER_CYCLE_ALL_DEV_EN*/ + err = music_player_play_auto_next(); + } + break; + ///解码器产生的错误, 文件损坏等 + case AUDIO_DEC_EVENT_ERR: + log_i("AUDIO_DEC_EVENT_ERR\n"); + err = music_player_play_auto_next();///文件播放过程出现的错误, 自动下一曲 + break; + default: + break; + } + return err; +} + +//*----------------------------------------------------------------------------*/ +/**@brief music_player解码错误处理 + @param event:err事件 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_decode_err_deal(int event) +{ + int err = 0; + switch (event) { + case AUDIO_DEC_EVENT_ERR: + ///解码启动错误, 这里将错误码转换为music_player错误类型 + err = MUSIC_PLAYER_ERR_DECODE_FAIL; + break; + default: + break; + } + return err; +} + +//*----------------------------------------------------------------------------*/ +/**@brief music_player播放结束事件回调 + @param + @return + @note 非api层接口 +*/ +/*----------------------------------------------------------------------------*/ +static void music_player_decode_event_callback(void *priv, int argc, int *argv) +{ + u8 event = (u8)argv[0]; + if (event == AUDIO_DEC_EVENT_END) { + u8 read_err = (u8)argv[1]; + u16 magic = (u16)priv; + log_i("AUDIO_DEC_EVENT_END\n"); + int parm = event | (read_err << 8) | (magic << 16); + if (__this->parm.cb && __this->parm.cb->end) { + __this->parm.cb->end(__this->priv, parm); + } + } else if (event == AUDIO_DEC_EVENT_START) { + log_i("AUDIO_DEC_EVENT_START\n"); + if (__this->parm.cb && __this->parm.cb->start) { + __this->parm.cb->start(__this->priv, 0); + } + } else if (event == AUDIO_DEC_EVENT_ERR) { + log_i("AUDIO_DEC_EVENT_ERR\n"); + if (__this->parm.cb && __this->parm.cb->err) { + __this->parm.cb->err(__this->priv, AUDIO_DEC_EVENT_ERR); + } + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief music_player解码器启动接口 + @param + file: + 文件句柄 + dbp: + 断点信息 + @return music_player 错误码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_decode_start(FILE *file, struct audio_dec_breakpoint *dbp) +{ + if (file) { + ///get file short name + u8 file_name[12 + 1] = {0}; //8.3+\0 + fget_name(music_player_get_file_hdl(), file_name, sizeof(file_name)); + log_i("\n"); + log_i("file name: %s\n", file_name); + log_i("\n"); + } + int ret; + ret = file_dec_create((void *)magic_cnt, music_player_decode_event_callback); + if (ret) { + return MUSIC_PLAYER_ERR_NO_RAM; + } + magic_cnt ++; + ret = file_dec_open(file, dbp); + if (ret) { + return MUSIC_PLAYER_ERR_DECODE_FAIL; + } + + //if (__this->parm.cb && __this->parm.cb->start) { + // __this->parm.cb->start(__this->priv, 0); + //} + + return MUSIC_PLAYER_SUCC; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取当前播放设备断点信息 + @param + bp: + 断点缓存,外部调用提供 + flag: + 1:需要获取歌曲断点信息及文件信息, 0:只获取文件信息 + @return 成功与否 + @note +*/ +/*----------------------------------------------------------------------------*/ +bool music_player_get_playing_breakpoint(struct __breakpoint *bp, u8 flag) +{ + if (__this == NULL || bp == NULL) { + return false; + } + if (dev_manager_online_check(__this->dev, 1)) { + if (file_dec_is_play() == true || file_dec_is_pause() == true) { + if (__this->file) { + if (flag) { + ///获取断点解码信息 + int ret = file_dec_get_breakpoint(&bp->dbp); + if (ret) { + ///获取断点解码信息错误 + log_e("file_dec_get_breakpoint err !!\n"); + } + } + ///获取断点文件信息 + struct vfs_attr attr = {0}; + fget_attrs(__this->file, &attr); + bp->sclust = attr.sclust; + bp->fsize = attr.fsize; + log_i("get playing breakpoint ok\n"); + return true; + } + } + } + return false; + +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取当前播放设备文件总数 + @param + @return 文件总数 + @note +*/ +/*----------------------------------------------------------------------------*/ +u16 music_player_get_file_total(void) +{ + if (__this && __this->fsn) { + return __this->fsn->file_number; + } + return 0; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取当前播放文件序号 + @param + @return 当前文件序号 + @note +*/ +/*----------------------------------------------------------------------------*/ +u16 music_player_get_file_cur(void) +{ + if (__this && __this->fsn) { + return __this->fsn->file_counter; + } + return 0; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取当前播放文件所在文件夹的文件总数 + @param + @return 文件总数 + @note +*/ +/*----------------------------------------------------------------------------*/ +u16 music_player_get_fileindir_number(void) +{ + if (__this && __this->fsn) { + return __this->fsn->fileTotalInDir; + } + return 0; + +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取当前播放文件所在文件夹 + @param + @return 当前文件夹序号 + @note +*/ +/*----------------------------------------------------------------------------*/ +u16 music_player_get_dir_cur(void) +{ + if (__this && __this->fsn) { + return __this->fsn->musicdir_counter; + } + return 0; + +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取文件夹总数 + @param + @return 文件夹总数 + @note +*/ +/*----------------------------------------------------------------------------*/ +u16 music_player_get_dir_total(void) +{ + if (__this && __this->fsn) { + return __this->fsn->dir_totalnumber; + } + return 0; + +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取文件句柄 + @param + @return 文件句柄 + @note 需要注意文件句柄的生命周期 +*/ +/*----------------------------------------------------------------------------*/ +FILE *music_player_get_file_hdl(void) +{ + if (__this && __this->file) { + return __this->file; + } + return NULL; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取文件簇号 + @param + @return 文件簇号, -1:无效 + @note +*/ +/*----------------------------------------------------------------------------*/ +u32 music_player_get_file_sclust(void) +{ + if (__this && __this->file) { + + struct vfs_attr tmp_attr = {0}; + fget_attrs(__this->file, &tmp_attr); + return tmp_attr.sclust; + } + return (u32) - 1; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取当前播放设备盘符 + @param + @return 设备盘符 + @note +*/ +/*----------------------------------------------------------------------------*/ +char *music_player_get_dev_cur(void) +{ + if (__this) { + return dev_manager_get_logo(__this->dev); + } + return NULL; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取当前播放设备下一个设备 + @param + @return 设备盘符 + @note +*/ +/*----------------------------------------------------------------------------*/ +char *music_player_get_dev_next(u8 auto_next) +{ + if (__this) { + if (auto_next) { + return dev_manager_get_logo(dev_manager_find_next(__this->dev, 1)); + } else { + //跳过录音设备 + struct __dev *next = dev_manager_find_next(__this->dev, 1); + if (next) { + char *logo = dev_manager_get_logo(next); + if (logo) { + char *str = strstr(logo, "_rec"); + if (str) { + char *cur_phy_logo = dev_manager_get_phy_logo(__this->dev); + char *next_phy_logo = dev_manager_get_phy_logo(next); + if (cur_phy_logo && next_phy_logo && strcmp(cur_phy_logo, next_phy_logo) == 0) { + //是同一个物理设备的录音设别, 跳过 + next = dev_manager_find_next(next, 1); + if (next != __this->dev) { + logo = dev_manager_get_logo(next); + return logo; + } else { + //没有其他设备了(只有录音文件夹设备及本身) + return NULL; + } + } + } + return logo; + } + } + } + } + return NULL; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取当前播放设备上一个设备 + @param + @return 设备盘符 + @note +*/ +/*----------------------------------------------------------------------------*/ +char *music_player_get_dev_prev(void) +{ + if (__this) { + return dev_manager_get_logo(dev_manager_find_prev(__this->dev, 1)); + } + return NULL; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取当前播放状态 + @param + @return 返回值如: + FILE_DEC_STATUS_STOP,//解码停止 + FILE_DEC_STATUS_PLAY,//正在解码 + FILE_DEC_STATUS_PAUSE,//解码暂停 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_get_play_status(void) +{ + int status = file_dec_get_status(); + if (status == FILE_DEC_STATUS_WAIT_PAUSE || status == FILE_DEC_STATUS_PAUSE || status == FILE_DEC_STATUS_PAUSE_SUCCESS) { + return FILE_DEC_STATUS_PAUSE; + } else if (status == FILE_DEC_STATUS_WAIT_PLAY || status == FILE_DEC_STATUS_PLAY) { + return FILE_DEC_STATUS_PLAY; + } else { + return FILE_DEC_STATUS_STOP; + } +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取当前播放歌曲时间 + @param + @return 当前播放时间 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_get_dec_cur_time(void) +{ + if (__this) { + return file_dec_get_cur_time(); + } + return 0; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取当前播放歌曲总时间 + @param + @return 当前播放总时间 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_get_dec_total_time(void) +{ + if (__this) { + return file_dec_get_total_time(); + } + return 0; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取当前播放循环模式 + @param + @return 当前播放循环模式 + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 music_player_get_repeat_mode(void) +{ + return app_var.cycle_mode; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取当前播放对应的music设备 + @param + @return 设备盘符 + @note 播放录音区分时,可以通过该接口判断当前播放的音乐设备是什么以便做录音区分判断 +*/ +/*----------------------------------------------------------------------------*/ +char *music_player_get_cur_music_dev(void) +{ + if (__this) { + char music_dev_logo[16] = {0}; + char *logo = dev_manager_get_logo(__this->dev); + if (logo) { + char *str = strstr(logo, "_rec"); + if (str) { + ///录音设备,切换到音乐设备播放 + strncpy(music_dev_logo, logo, strlen(logo) - strlen(str)); + logo = dev_manager_get_logo(dev_manager_find_spec(music_dev_logo, 1)); + } + } + return logo; + } + return NULL; +} + +const char *music_player_get_phy_dev(int *len) +{ + if (__this) { + char *logo = dev_manager_get_logo(__this->dev); + if (logo) { + char *str = strstr(logo, "_rec"); + if (str) { + ///录音设备,切换到音乐设备播放 + if (len) { + *len = strlen(logo) - strlen(str); + } + } else { + if (len) { + *len = strlen(logo); + } + } + return logo; + } + } + if (len) { + *len = 0; + } + return NULL; +} + + + +//*----------------------------------------------------------------------------*/ +/**@brief music_player获取当前录音区分播放状态 + @param + @return true:录音文件夹播放, false:非录音文件夹播放 + @note 播放录音区分时,可以通过该接口判断当前播放的是录音文件夹还是非录音文件夹 +*/ +/*----------------------------------------------------------------------------*/ +bool music_player_get_record_play_status(void) +{ + if (__this) { + char *logo = dev_manager_get_logo(__this->dev); + if (logo) { + char *str = strstr(logo, "_rec"); + if (str) { + return true; + } + } + } + return false; +} + +//*----------------------------------------------------------------------------*/ +/**@brief music_player从设备列表里面往前或往后找设备,并且过滤掉指定字符串的设备 + @param + flit:过滤字符串, 查找设备时发现设备logo包含这个字符串的会被过滤 + direct:查找方向, 1:往后, 0:往前 + @return 查找到符合条件的设备逻辑盘符, 找不到返回NULL + @note +*/ +/*----------------------------------------------------------------------------*/ +char *music_player_get_dev_flit(char *flit, u8 direct) +{ + if (__this) { + u32 counter = 0; + struct __dev *dev = __this->dev; + u32 dev_total = dev_manager_get_total(1); + if (dev_manager_online_check(__this->dev, 1) == 1) { + if (dev_total > 1) { + while (1) { + if (direct) { + dev = dev_manager_find_next(dev, 1); + } else { + dev = dev_manager_find_prev(dev, 1); + } + if (dev) { + char *logo = dev_manager_get_logo(dev); + if (flit) { + char *str = strstr(logo, flit); + if (!str) { + return logo; + } + counter++; + if (counter >= (dev_total - 1)) { + break; + } + } else { + return logo; + } + } + } + } + } + } + return NULL; +} + +//*----------------------------------------------------------------------------*/ +/**@brief music_player播放/暂停 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_pp(void) +{ + if (__this) { + file_dec_pp(); + } + return MUSIC_PLAYER_ERR_NULL; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player解码停止 + @param + fsn_release: + 1:释放扫盘句柄 + 0:不释放扫盘句柄 + @return + @note 如果释放了扫盘句柄,需要重新扫盘,否则播放失败 +*/ +/*----------------------------------------------------------------------------*/ +void music_player_stop(u8 fsn_release) +{ + if (__this == NULL) { + return ; + } + +#if (defined(TCFG_LRC_LYRICS_ENABLE) && (TCFG_LRC_LYRICS_ENABLE)) + extern void lrc_set_analysis_flag(u8 flag); + lrc_set_analysis_flag(0); +#endif + ///停止解码 + file_dec_close(); + if (__this->file) { + fclose(__this->file); + __this->file = NULL; + } + + if (__this->lrc_file) { + fclose(__this->lrc_file); + __this->lrc_file = NULL; + } + + if (fsn_release && __this->fsn) { + ///根据播放情景, 通过设定flag决定是否需要释放fscan, 释放后需要重新扫盘!!! + dev_manager_scan_disk_release(__this->fsn); + __this->fsn = NULL; + } + //检查整理VM + vm_check_all(0); +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player快进 + @param step:快进步进 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void music_player_ff(int step) +{ + if (__this) { + file_dec_FF(step); + } +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player快退 + @param step:快退步进 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void music_player_fr(int step) +{ + if (__this) { + file_dec_FR(step); + } +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player设置播放循环模式 + @param mode:循环模式 + FCYCLE_ALL + FCYCLE_ONE + FCYCLE_FOLDER + FCYCLE_RANDOM + @return 循环模式 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_set_repeat_mode(u8 mode) +{ + if (__this) { + if (mode >= FCYCLE_MAX) { + return -1; + } + app_var.cycle_mode = mode; + if (__this->fsn) { + __this->fsn->cycle_mode = mode; + log_i("cycle_mode = %d\n", mode); + local_irq_disable(); + save_mode_cnt = 0; + if (save_mode_timer == 0) { + save_mode_timer = sys_timer_add(NULL, music_player_mode_save_do, 1000); + } + local_irq_enable(); + return mode; + } + } + return -1; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player切换循环模式 + @param + @return 循环模式 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_change_repeat_mode(void) +{ + if (__this) { + app_var.cycle_mode++; + if (app_var.cycle_mode >= FCYCLE_MAX) { + app_var.cycle_mode = FCYCLE_ALL; + } + return music_player_set_repeat_mode(app_var.cycle_mode); + } + return -1; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player删除当前播放文件,并播放下一曲 + @param + @return 播放错误码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_delete_playing_file(void) +{ + if (__this && __this->file) { + ///获取当前播放文件序号, 文件删除之后, 播放下一曲 + int err = 0; + int cur_file = music_player_get_file_cur(); + char *cur_dev = music_player_get_dev_cur(); + file_dec_close(); + err = fdelete(__this->file); + if (err) { + log_info("[%s, %d] fail!!, replay cur file\n", __FUNCTION__, __LINE__); + } else { + log_info("[%s, %d] ok, play next file\n", __FUNCTION__, __LINE__); + __this->file = NULL; + __this->dev = NULL;//目的重新扫盘, 更新文件总数 + return music_player_play_by_number(cur_dev, cur_file); + } + } + return MUSIC_PLAYER_ERR_NULL; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player播放上一曲 + @param + @return 播放错误码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_play_prev_cycle_single_dev(void) +{ + ///close player first + music_player_stop(0); + ///check dev, 检查设备是否有掉线 + if (dev_manager_online_check(__this->dev, 1) == 0) { + return MUSIC_PLAYER_ERR_DEV_OFFLINE; + } + ///不需要重新找设备、扫盘 + if (__this->fsn == NULL) { + return MUSIC_PLAYER_ERR_FSCAN; + } + ///get file + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_PREV_FILE, 0, __this->parm.scan_cb);///选择上一曲 + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + ///start decoder + int err = music_player_decode_start(__this->file, 0); + if (err == MUSIC_PLAYER_SUCC) { + ///选定新设备播放成功后,需要激活当前设备 + dev_manager_set_active(__this->dev); + log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); + } + return err; +} + +int music_player_play_prev(void) +{ + int err; +#if (MUSIC_PLAYER_CYCLE_ALL_DEV_EN) + u32 cur_file = music_player_get_file_cur(); + if ((music_player_get_record_play_status() == false) + && (app_var.cycle_mode == FCYCLE_ALL) + && (cur_file == 1) + && (dev_manager_get_total(1) > 1)) { + char *logo = music_player_get_dev_flit("_rec", 0); + err = music_player_play_last_file(logo); + return err; + } +#endif/*MUSIC_PLAYER_CYCLE_ALL_DEV_EN*/ + err = music_player_play_prev_cycle_single_dev(); + return err; +} + +//*----------------------------------------------------------------------------*/ +/**@brief music_player播放下一曲 + @param + @return 播放错误码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_play_next_cycle_single_dev(void) +{ + ///close player first + music_player_stop(0); + ///check dev, 检查设备是否有掉线 + if (dev_manager_online_check(__this->dev, 1) == 0) { + return MUSIC_PLAYER_ERR_DEV_OFFLINE; + } + ///不需要重新找设备、扫盘 + if (__this->fsn == NULL) { + return MUSIC_PLAYER_ERR_FSCAN; + } + ///get file + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_NEXT_FILE, 0, __this->parm.scan_cb);///选择下一曲 + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + ///start decoder + int err = music_player_decode_start(__this->file, 0); + if (err == MUSIC_PLAYER_SUCC) { + ///选定新设备播放成功后,需要激活当前设备 + dev_manager_set_active(__this->dev); + log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); + } + return err; +} + +int music_player_play_next(void) +{ + int err; +#if (MUSIC_PLAYER_CYCLE_ALL_DEV_EN) + u32 cur_file = music_player_get_file_cur(); + if ((music_player_get_record_play_status() == false) + && (app_var.cycle_mode == FCYCLE_ALL) + && (cur_file >= music_player_get_file_total()) + && (dev_manager_get_total(1) > 1)) { + char *logo = music_player_get_dev_flit("_rec", 1); + err = music_player_play_first_file(logo); + return err; + } +#endif/*MUSIC_PLAYER_CYCLE_ALL_DEV_EN*/ + err = music_player_play_next_cycle_single_dev(); + return err; +} + +//*----------------------------------------------------------------------------*/ +/**@brief music_player播放第一曲 + @param + @return 播放错误码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_play_first_file(char *logo) +{ + if (logo == NULL) { + music_player_stop(0); + if (dev_manager_online_check(__this->dev, 1) == 0) { + return MUSIC_PLAYER_ERR_DEV_OFFLINE; + } + ///没有指定设备不需要找设备, 不需要扫描 + } else { + music_player_stop(1); + __this->dev = dev_manager_find_spec(logo, 1); + if (__this->dev == NULL) { + return MUSIC_PLAYER_ERR_DEV_NOFOUND; + } + __this->fsn = dev_manager_scan_disk(__this->dev, NULL, scan_parm, app_var.cycle_mode, __this->parm.scan_cb); + } + if (__this->fsn == NULL) { + return MUSIC_PLAYER_ERR_FSCAN; + } + ///get file + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_FIRST_FILE, 0, __this->parm.scan_cb); + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + ///start decoder + int err = music_player_decode_start(__this->file, 0); + if (err == MUSIC_PLAYER_SUCC) { + ///选定新设备播放成功后,需要激活当前设备 + dev_manager_set_active(__this->dev); + log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); + } + return err; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player播放最后一曲 + @param + @return 播放错误码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_play_last_file(char *logo) +{ + if (logo == NULL) { + music_player_stop(0); + if (dev_manager_online_check(__this->dev, 1) == 0) { + return MUSIC_PLAYER_ERR_DEV_OFFLINE; + } + ///没有指定设备不需要找设备, 不需要扫描 + } else { + music_player_stop(1); + __this->dev = dev_manager_find_spec(logo, 1); + if (__this->dev == NULL) { + return MUSIC_PLAYER_ERR_DEV_NOFOUND; + } + __this->fsn = dev_manager_scan_disk(__this->dev, NULL, scan_parm, app_var.cycle_mode, __this->parm.scan_cb); + } + if (__this->fsn == NULL) { + return MUSIC_PLAYER_ERR_FSCAN; + } + ///get file + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_LAST_FILE, 0, __this->parm.scan_cb); + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + ///start decoder + int err = music_player_decode_start(__this->file, 0); + if (err == MUSIC_PLAYER_SUCC) { + ///选定新设备播放成功后,需要激活当前设备 + dev_manager_set_active(__this->dev); + log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); + } + return err; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player自动播放下一曲 + @param + @return 播放错误码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_play_auto_next(void) +{ + ///close player first + music_player_stop(0); + ///get dev, 检查设备是否有掉线 + if (dev_manager_online_check(__this->dev, 1) == 0) { + return MUSIC_PLAYER_ERR_DEV_OFFLINE; + } + ///不需要重新找设备、扫盘 + if (__this->fsn == NULL) { + return MUSIC_PLAYER_ERR_FSCAN; + } + ///get file + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_AUTO_FILE, 0, __this->parm.scan_cb);///选择自动下一曲 + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + ///start decoder + int err = music_player_decode_start(__this->file, 0); + if (err == MUSIC_PLAYER_SUCC) { + ///选定新设备播放成功后,需要激活当前设备 + dev_manager_set_active(__this->dev); + log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); + } + return err; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player上一个文件夹 + @param + @return 播放错误码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_play_folder_prev(void) +{ + ///close player first + music_player_stop(0); + ///get dev, 检查设备是否有掉线 + if (dev_manager_online_check(__this->dev, 1) == 0) { + return MUSIC_PLAYER_ERR_DEV_OFFLINE; + } + ///不需要重新找设备、扫盘 + if (__this->fsn == NULL) { + return MUSIC_PLAYER_ERR_FSCAN; + } + ///get file + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_PREV_FOLDER_FILE, 0, __this->parm.scan_cb);///选择播放上一个文件夹 + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } +#if (MUSIC_PLAYER_PLAY_FOLDER_PREV_FIRST_FILE_EN) + struct ffolder folder_info = {0}; + if (fget_folder(__this->fsn, &folder_info)) { + log_e("folder info err!!\n"); + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + + //先关掉文件 + fclose(__this->file); + //播放文件夹第一首 + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_BY_NUMBER, folder_info.fileStart, __this->parm.scan_cb); + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } +#endif + ///start decoder + int err = music_player_decode_start(__this->file, 0); + if (err == MUSIC_PLAYER_SUCC) { + ///选定新设备播放成功后,需要激活当前设备 + dev_manager_set_active(__this->dev); + log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); + } + return err; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player下一个文件夹 + @param + @return 播放错误码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_play_folder_next(void) +{ + ///close player first + music_player_stop(0); + ///get dev, 检查设备是否有掉线 + if (dev_manager_online_check(__this->dev, 1) == 0) { + return MUSIC_PLAYER_ERR_DEV_OFFLINE; + } + ///不需要重新找设备、扫盘 + if (__this->fsn == NULL) { + return MUSIC_PLAYER_ERR_FSCAN; + } + ///get file + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_NEXT_FOLDER_FILE, 0, __this->parm.scan_cb);///选择播放上一个文件夹 + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + ///start decoder + int err = music_player_decode_start(__this->file, 0); + if (err == MUSIC_PLAYER_SUCC) { + ///选定新设备播放成功后,需要激活当前设备 + dev_manager_set_active(__this->dev); + log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); + } + return err; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player上一个设备 + @param bp:断点信息 + @return 播放错误码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_play_devcie_prev(struct __breakpoint *bp) +{ + ///close player first + music_player_stop(1); + ///get dev + __this->dev = dev_manager_find_prev(__this->dev, 1); + if (__this->dev == NULL) { + return MUSIC_PLAYER_ERR_DEV_NOFOUND; + } + ///get fscan + __this->fsn = dev_manager_scan_disk(__this->dev, NULL, (const char *)scan_parm, app_var.cycle_mode, __this->parm.scan_cb); + if (__this->fsn == NULL) { + return MUSIC_PLAYER_ERR_FSCAN; + } + int err = 0; + if (bp) { + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_BY_SCLUST, bp->sclust, __this->parm.scan_cb);//根据文件簇号查找断点文件 + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + err = music_player_decode_start(__this->file, &(bp->dbp)); + } else { + /* __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_LAST_FILE, 0, __this->parm.scan_cb); */ + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_FIRST_FILE, 0, __this->parm.scan_cb); + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + err = music_player_decode_start(__this->file, 0); + } + if (err == MUSIC_PLAYER_SUCC) { + ///选定新设备播放成功后,需要激活当前设备 + dev_manager_set_active(__this->dev); + log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); + } + return err; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player下一个设备 + @param bp:断点信息 + @return 播放错误码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_play_devcie_next(struct __breakpoint *bp) +{ + ///close player first + music_player_stop(1); + ///get dev + __this->dev = dev_manager_find_next(__this->dev, 1); + if (__this->dev == NULL) { + return MUSIC_PLAYER_ERR_DEV_NOFOUND; + } + ///get fscan + __this->fsn = dev_manager_scan_disk(__this->dev, NULL, scan_parm, app_var.cycle_mode, __this->parm.scan_cb); + if (__this->fsn == NULL) { + return MUSIC_PLAYER_ERR_FSCAN; + } + int err = 0; + if (bp) { + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_BY_SCLUST, bp->sclust, __this->parm.scan_cb);//根据文件簇号查找断点文件 + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + err = music_player_decode_start(__this->file, &(bp->dbp)); + } else { + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_FIRST_FILE, 0, __this->parm.scan_cb);//选择第一个文件播放 + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + err = music_player_decode_start(__this->file, 0); + } + if (err == MUSIC_PLAYER_SUCC) { + ///选定新设备播放成功后,需要激活当前设备 + dev_manager_set_active(__this->dev); + log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); + } + return err; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player断点播放指定设备 + @param + logo:逻辑盘符,如:sd0/sd1/udisk0 + bp:断点信息 + @return 播放错误码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_play_by_breakpoint(char *logo, struct __breakpoint *bp) +{ + u32 bp_flag = 1; + if (bp == NULL) { + return music_player_play_first_file(logo); + //return MUSIC_PLAYER_ERR_PARM; + } + if (logo == NULL) { + music_player_stop(0); + if (dev_manager_online_check(__this->dev, 1) == 0) { + return MUSIC_PLAYER_ERR_DEV_OFFLINE; + } + ///没有指定设备不需要找设备, 不需要扫描 + } else { + music_player_stop(1); + __this->dev = dev_manager_find_spec(logo, 1); + if (__this->dev == NULL) { + return MUSIC_PLAYER_ERR_DEV_NOFOUND; + } + bp_flag = 0; + set_bp_info(bp->sclust, bp->fsize, &bp_flag); //断点若有效把bp_flag置1,注意后面要用put_bp_info释放资源 + __this->fsn = dev_manager_scan_disk(__this->dev, NULL, scan_parm, app_var.cycle_mode, __this->parm.scan_cb); + } + if (__this->fsn == NULL) { + put_bp_info(); + return MUSIC_PLAYER_ERR_FSCAN; + } + if (!bp_flag) { //断点无效 + put_bp_info(); + return MUSIC_PLAYER_ERR_PARM; + } + ///get file + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_BY_SCLUST, bp->sclust, __this->parm.scan_cb);//根据文件簇号查找断点文件 + put_bp_info(); + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + + struct vfs_attr attr = {0}; + fget_attrs(__this->file, &attr); + if (bp->fsize != attr.fsize) { + return MUSIC_PLAYER_ERR_PARM; + } + + ///start decoder + int err = music_player_decode_start(__this->file, &(bp->dbp)); + if (err == MUSIC_PLAYER_SUCC) { + ///选定新设备播放成功后,需要激活当前设备 + dev_manager_set_active(__this->dev); + log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); + } + return err; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player序号播放指定设备 + @param + logo:逻辑盘符,如:sd0/sd1/udisk0 + number:指定播放序号 + @return 播放错误码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_play_by_number(char *logo, u32 number) +{ + char *cur_logo = dev_manager_get_logo(__this->dev); + if (logo == NULL || (cur_logo && logo && (0 == strcmp(logo, cur_logo)))) { + music_player_stop(0); + if (dev_manager_online_check(__this->dev, 1) == 0) { + return MUSIC_PLAYER_ERR_DEV_OFFLINE; + } + ///没有指定设备不需要找设备, 不需要扫描 + } else { + music_player_stop(1); + __this->dev = dev_manager_find_spec(logo, 1); + if (__this->dev == NULL) { + return MUSIC_PLAYER_ERR_DEV_NOFOUND; + } + __this->fsn = dev_manager_scan_disk(__this->dev, NULL, scan_parm, app_var.cycle_mode, __this->parm.scan_cb); + } + + if (__this->fsn == NULL) { + return MUSIC_PLAYER_ERR_FSCAN; + } + ///get file + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_BY_NUMBER, number, __this->parm.scan_cb); + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + ///start decoder + int err = music_player_decode_start(__this->file, 0); + if (err == MUSIC_PLAYER_SUCC) { + ///选定新设备播放成功后,需要激活当前设备 + dev_manager_set_active(__this->dev); + log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); + } + return err; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player簇号播放指定设备 + @param + logo:逻辑盘符,如:sd0/sd1/udisk0 + sclust:指定播放簇号 + @return 播放错误码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_play_by_sclust(char *logo, u32 sclust) +{ + char *cur_logo = dev_manager_get_logo(__this->dev); + if (logo == NULL || (cur_logo && logo && (0 == strcmp(logo, cur_logo)))) { + music_player_stop(0); + if (dev_manager_online_check(__this->dev, 1) == 0) { + return MUSIC_PLAYER_ERR_DEV_OFFLINE; + } + ///没有指定设备不需要找设备, 不需要扫描 + } else { + music_player_stop(1); + __this->dev = dev_manager_find_spec(logo, 1); + if (__this->dev == NULL) { + return MUSIC_PLAYER_ERR_DEV_NOFOUND; + } + __this->fsn = dev_manager_scan_disk(__this->dev, NULL, scan_parm, app_var.cycle_mode, __this->parm.scan_cb); + } + if (__this->fsn == NULL) { + return MUSIC_PLAYER_ERR_FSCAN; + } + ///get file + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_BY_SCLUST, sclust, __this->parm.scan_cb);//根据簇号查找文件 + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + ///start decoder + int err = music_player_decode_start(__this->file, 0); + if (err == MUSIC_PLAYER_SUCC) { + ///选定新设备播放成功后,需要激活当前设备 + dev_manager_set_active(__this->dev); + log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); + } + return err; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player路径播放指定设备 + @param + logo:逻辑盘符,如:sd0/sd1/udisk0, 设置为NULL,为默认当前播放设备 + path:指定播放路径 + @return 播放错误码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_player_play_by_path(char *logo, const char *path) +{ + if (path == NULL) { + return MUSIC_PLAYER_ERR_POINT; + } + if (logo == NULL) { + music_player_stop(0); + if (dev_manager_online_check(__this->dev, 1) == 0) { + return MUSIC_PLAYER_ERR_DEV_OFFLINE; + } + ///没有指定设备不需要找设备, 不需要扫描 + } else { + music_player_stop(1); + __this->dev = dev_manager_find_spec(logo, 1); + if (__this->dev == NULL) { + return MUSIC_PLAYER_ERR_DEV_NOFOUND; + } + __this->fsn = dev_manager_scan_disk(__this->dev, NULL, scan_parm, app_var.cycle_mode, __this->parm.scan_cb); + } + if (__this->fsn == NULL) { + return MUSIC_PLAYER_ERR_FSCAN; + } + ///get file + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_BY_PATH, (int)path, __this->parm.scan_cb);//根据簇号查找文件 + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + ///start decoder + int err = music_player_decode_start(__this->file, 0); + if (err == MUSIC_PLAYER_SUCC) { + ///选定新设备播放成功后,需要激活当前设备 + dev_manager_set_active(__this->dev); + log_i("[%s %d] ok\n", __FUNCTION__, __LINE__); + } + return err; +} +//*----------------------------------------------------------------------------*/ +/**@brief music_player录音区分切换播放 + @param + logo:逻辑盘符,如:sd0/sd1/udisk0, 设置为NULL,为默认当前播放设备 + bp:断点信息 + @return 播放错误码 + @note 通过指定设备盘符,接口内部通过解析盘符是否"_rec" + 来确定是切换到录音播放设备还是非录音播放设备 +*/ +/*----------------------------------------------------------------------------*/ +int music_player_play_record_folder(char *logo, struct __breakpoint *bp) +{ + int err = MUSIC_PLAYER_ERR_NULL; +#if (TCFG_RECORD_FOLDER_DEV_ENABLE) + char rec_dev_logo[16] = {0}; + char music_dev_logo[16] = {0}; + u8 rec_play = 0; + struct __dev *dev; + if (logo == NULL) { + logo = dev_manager_get_logo(__this->dev); + if (logo == NULL) { + return MUSIC_PLAYER_ERR_RECORD_DEV; + } + } + + ///判断是否是录音设备 + char *str = strstr(logo, "_rec"); + if (str == NULL) { + ///是非录音设备,切换到录音设备播放 + sprintf(rec_dev_logo, "%s%s", logo, "_rec"); + dev = dev_manager_find_spec(rec_dev_logo, 1); + logo = rec_dev_logo; + rec_play = 1; + } else { + ///录音设备,切换到音乐设备播放 + strncpy(music_dev_logo, logo, strlen(logo) - strlen(str)); + log_i("music_dev_logo = %s, logo = %s, str = %s, len = %d\n", music_dev_logo, logo, str, strlen(logo) - strlen(str)); + dev = dev_manager_find_spec(music_dev_logo, 1); + logo = music_dev_logo; + rec_play = 0; + } + if (dev == NULL) { + return MUSIC_PLAYER_ERR_RECORD_DEV; + } + + ///需要扫盘 + struct vfscan *fsn = dev_manager_scan_disk(dev, NULL, scan_parm, app_var.cycle_mode, __this->parm.scan_cb); + if (fsn == NULL) { + dev_manager_set_valid(dev, 0); + return MUSIC_PLAYER_ERR_RECORD_DEV; + } else { + music_player_stop(1); + __this->dev = dev; + __this->fsn = fsn; + } + ///get file + if (bp) { + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_BY_SCLUST, bp->sclust, __this->parm.scan_cb); + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + ///start decoder + err = music_player_decode_start(__this->file, &bp->dbp); + } else { + __this->file = file_manager_select(__this->dev, __this->fsn, FSEL_FIRST_FILE, 0, __this->parm.scan_cb);//播放录音文件夹第一个文件 + if (__this->file == NULL) { + return MUSIC_PLAYER_ERR_FILE_NOFOUND; + } + ///start decoder + err = music_player_decode_start(__this->file, 0);//录音文件夹不支持断点播放 + } + if (err == MUSIC_PLAYER_SUCC) { + ///选定新设备播放成功后,需要激活当前设备 + dev_manager_set_active(__this->dev); + log_i("[%s %d] %s devcie play ok\n", __FUNCTION__, __LINE__, logo); + } +#endif//TCFG_RECORD_FOLDER_DEV_ENABLE + return err; +} + + +int music_player_lrc_analy_start() +{ +#if (defined(TCFG_LRC_LYRICS_ENABLE) && (TCFG_LRC_LYRICS_ENABLE)) + extern bool lrc_analysis_api(FILE * file, FILE **newFile); + extern void lrc_set_analysis_flag(u8 flag); + log_i("lrc analys..."); + + if (__this && __this->file) { + if (lrc_analysis_api(__this->file, &(__this->lrc_file))) { + lrc_set_analysis_flag(1); + return 0; + } else { + lrc_set_analysis_flag(0); + return -1; + } + } + +#endif + return -1; +} + + + + diff --git a/apps/common/music/music_player.h b/apps/common/music/music_player.h new file mode 100644 index 0000000..129374a --- /dev/null +++ b/apps/common/music/music_player.h @@ -0,0 +1,148 @@ +#ifndef __MUSIC_PLAYER_H__ +#define __MUSIC_PLAYER_H__ + +#include "system/app_core.h" +#include "system/includes.h" +#include "server/server_core.h" +#include "media/audio_decoder.h" +#include "dev_manager/dev_manager.h" +#include "file_operate/file_manager.h" +#include "audio_dec/audio_dec_file.h" + +///解码错误码表 +enum { + MUSIC_PLAYER_ERR_NULL = 0x0, ///没有错误, 不需要做任何 + MUSIC_PLAYER_SUCC = 0x1, ///播放成功, 可以做相关显示、断点记忆等处理 + MUSIC_PLAYER_ERR_PARM, ///参数错误 + MUSIC_PLAYER_ERR_POINT, ///参数指针错误 + MUSIC_PLAYER_ERR_NO_RAM, ///没有ram空间错误 + MUSIC_PLAYER_ERR_DECODE_FAIL, ///解码器启动失败错误 + MUSIC_PLAYER_ERR_DEV_NOFOUND, ///没有找到指定设备 + MUSIC_PLAYER_ERR_DEV_OFFLINE, ///设备不在线错误 + MUSIC_PLAYER_ERR_DEV_READ, ///设备读错误 + MUSIC_PLAYER_ERR_FSCAN, ///设备扫描失败 + MUSIC_PLAYER_ERR_FILE_NOFOUND, ///没有找到文件 + MUSIC_PLAYER_ERR_RECORD_DEV, ///录音文件夹操作错误 + MUSIC_PLAYER_ERR_FILE_READ, ///文件读错误 +}; + +///断点信息结构体 +struct __breakpoint { + ///文件信息 + u32 fsize; + u32 sclust; + ///解码信息 + struct audio_dec_breakpoint dbp; +}; + +///回调接口结构体 +struct __player_cb { + ///解码成功回调 + void (*start)(void *priv, int parm); + ///解码结束回调 + void (*end)(void *priv, int parm); + ///解码错误回调 + void (*err)(void *priv, int parm); +}; + +///参数设置结构体 +struct __player_parm { + const struct __player_cb *cb; + ///其他扩展 + const struct __scan_callback *scan_cb;//扫盘打断回调 +}; + +//music_player创建接口 +bool music_player_creat(void *priv, struct __player_parm *parm); +//music_player释放接口 +void music_player_destroy(void); +//music_player播放结束处理 +int music_player_end_deal(int parm); +//music_player播放器解码错误处理 +int music_player_decode_err_deal(int event); +//music_player解码器启动接口 +int music_player_decode_start(FILE *file, struct audio_dec_breakpoint *dbp); +//music_player获取当前播放设备断点信息 +bool music_player_get_playing_breakpoint(struct __breakpoint *bp, u8 flag); +//music_player获取当前播放设备文件总数 +u16 music_player_get_file_total(void); +//music_player获取当前播放文件序号 +u16 music_player_get_file_cur(void); +//music_player获取当前播放文件所在文件夹的文件总数 +u16 music_player_get_fileindir_number(void); +//music_player获取当前播放文件所在文件夹 +u16 music_player_get_dir_cur(void); +//music_player获取文件夹总数 +u16 music_player_get_dir_total(void); +//music_player获取当前文件句柄 +FILE *music_player_get_file_hdl(void); +//music_player获取当前文件簇号 +u32 music_player_get_file_sclust(void); +//music_player获取现在的使用设备 +char *music_player_get_dev_cur(void); +//music_player获取当前播放对应的music设备 +char *music_player_get_cur_music_dev(void); +//music_player获取当前播放设备下一个设备 +char *music_player_get_dev_next(u8 auto_next); +//music_player获取当前播放设备上一个设备 +char *music_player_get_dev_prev(void); +//music_player获取当前播放状态 +int music_player_get_play_status(void); +//music_player获取当前播放歌曲时间 +int music_player_get_dec_cur_time(void); +//music_player获取当前播放歌曲总时间 +int music_player_get_dec_total_time(void); +//music_player获取当前播放循环模式 +u8 music_player_get_repeat_mode(void); +//music_player获取当前录音区分播放状态 +bool music_player_get_record_play_status(void); +//music_player从设备列表里面往前或往后找设备,并且过滤掉指定字符串的设备 +char *music_player_get_dev_flit(char *flit, u8 direct); +//music_player播放/暂停 +int music_player_pp(void); +//music_player快进 +void music_player_ff(int step); +//music_player快退 +void music_player_fr(int step); +//music_player设置播放循环模式 +int music_player_set_repeat_mode(u8 mode); +//music_player切换循环模式 +int music_player_change_repeat_mode(void); +//music_player解码停止 +void music_player_stop(u8 fsn_release); +//music_player删除当前播放文件,并播放下一曲 +int music_player_delete_playing_file(void); +//music_player播放上一曲 +int music_player_play_prev(void); +//music_player播放下一曲 +int music_player_play_next(void); +//music_player播放第一曲 +int music_player_play_first_file(char *logo); +//music_player播放最后一曲 +int music_player_play_last_file(char *logo); +//music_player自动播放下一曲 +int music_player_play_auto_next(void); +//music_player上一个文件夹 +int music_player_play_folder_prev(void); +//music_player下一个文件夹 +int music_player_play_folder_next(void); +//music_player上一个设备 +int music_player_play_devcie_prev(struct __breakpoint *bp); +//music_player下一个设备 +int music_player_play_devcie_next(struct __breakpoint *bp); +//music_player断点播放指定设备 +int music_player_play_by_breakpoint(char *logo, struct __breakpoint *pb); +//music_player序号播放指定设备 +int music_player_play_by_number(char *logo, u32 number); +//music_player簇号播放指定设备 +int music_player_play_by_sclust(char *logo, u32 sclust); +//music_player路径播放指定设备 +int music_player_play_by_path(char *logo, const char *path); +//music_player录音区分切换播放 +int music_player_play_record_folder(char *logo, struct __breakpoint *bp); +//获取当前设备的物理设备 +const char *music_player_get_phy_dev(int *len); +//歌词分析 +int music_player_lrc_analy_start(); +#endif//__MUSIC_PLAYER_H__ + diff --git a/apps/common/rec_nor/nor_interface.c b/apps/common/rec_nor/nor_interface.c new file mode 100644 index 0000000..4737c03 --- /dev/null +++ b/apps/common/rec_nor/nor_interface.c @@ -0,0 +1,333 @@ +#include "nor_interface.h" +#include "nor_rec_fs.h" + +#define NO_DEBUG_EN + +#ifdef NO_DEBUG_EN +#undef r_printf +#undef y_printf +#define r_printf(...) +#define y_printf(...) +#endif + +#define NOR_FS_SECTOR_S (4*1024L) +#define NOR_FS_S_SECTOR (1) +#define NOR_FS_E_SECTOR (NOR_FS_SECTOR_S-1) + +#define RECFILEHEAD SDFILE_FILE_HEAD + +struct nor_fs_rec { + NOR_RECFILESYSTEM recfs; + NOR_REC_FILE recfile; + u32 nor_fs_index; + int first_flag; + int is_read_only; +}; + +static int rec_norflash_spirec_read(void *device, u8 *buf, u32 addr, u32 len) +{ + return dev_bulk_read(device, buf, addr, len); +} + +static int rec_norflash_spirec_write(void *device, u8 *buf, u32 addr, u32 len) +{ + return dev_bulk_write(device, buf, addr, len); +} + +static void rec_norflash_spirec_eraser(void *device, u32 addr) +{ + dev_ioctl(device, IOCTL_ERASE_SECTOR, addr); +} + +static int rec_norflash_get_capacity(void *device) +{ + int capacity; + dev_ioctl(device, IOCTL_GET_CAPACITY, (u32)&capacity); + return capacity; +} + +static int rec_norflash_get_part_info(void *device, u32 *s_addr, u32 *size) +{ + u32 buf[2] = {0}; + buf[0] = (u32)s_addr; + buf[1] = (u32)size; + int reg = dev_ioctl(device, IOCTL_GET_PART_INFO, (u32)buf); + if (reg) { + log_e("get part info err!!!!!!!!"); + } + return reg; +} + +static int get_ext_name(char *path, char *ext) +{ + int len = strlen(path); + char *name = (char *)path; + while (len--) { + if (*name++ == '.') { + break; + } + } + if (len <= 0) { + name = path + (strlen(path) - 3); + } + memcpy(ext, name, 3); + ext[3] = 0; + return 1; +} + +static void add_path_index(const char *path, u32 index) +{ + int last_num = -1; + char *file_num_str; + + last_num = index ; + file_num_str = strrchr(path, '.') - 4; + if (last_num > 9999) { + last_num = 0; + } + file_num_str[0] = last_num / 1000 + '0'; + file_num_str[1] = last_num % 1000 / 100 + '0'; + file_num_str[2] = last_num % 100 / 10 + '0'; + file_num_str[3] = last_num % 10 + '0'; +} + +static u32 recfs_init(struct __NOR_RECFILESYSTEM *recfs) +{ + recfs->eraser = rec_norflash_spirec_eraser; + recfs->read = rec_norflash_spirec_read; + recfs->write = rec_norflash_spirec_write; + + return true; +} + +static int nor_fs_mount(struct imount *mt, int cache_num) +{ + int part_capacity = 0; + y_printf("\n >>>[test]:func = %s,line= %d\n", __FUNCTION__, __LINE__); + struct nor_fs_rec *rec_fs_file = zalloc(sizeof(struct nor_fs_rec)); + struct vfs_partition *app_part = &mt->part; + app_part->private_data = rec_fs_file; + rec_fs_file->recfs.device = mt->dev.fd; + rec_fs_file->is_read_only = 0; + + part_capacity = rec_norflash_get_capacity(rec_fs_file->recfs.device); + r_printf(">>>[test]:capacity = 0x%x\n", part_capacity); + + recfs_init(&rec_fs_file->recfs); + nor_pfs_init(&rec_fs_file->recfs, NOR_FS_S_SECTOR, part_capacity / NOR_FS_E_SECTOR, 12); + rec_pfs_scan(&rec_fs_file->recfs); + rec_fs_file->nor_fs_index = rec_fs_file->recfs.index.index; + + app_part->offset = 0; + app_part->dir[0] = 'C'; + app_part->dir[1] = '\0'; + + return 0; +} + +static int nor_fs_open(FILE *_file, const char *path, const char *mode) +{ + int index; + int reg; + y_printf("\n>>>[test]:nor_fs_open\n"); + struct imount *mt = _file->mt; + struct nor_fs_rec *private_data = (struct nor_fs_rec *)mt->part.private_data; + + if (mode[0] == 'w') { + y_printf(">>>[test]:goto create\n"); + char ext[4] = {0}; + char filename[16] = {0}; + get_ext_name((char *)path, (char *)ext); + if (memcmp(ext, "WAV", 3) == 0 || memcmp(ext, "wav", 3) == 0) { + private_data->first_flag = 1; + } else { + private_data->first_flag = 0; + } + + index = create_nor_recfile(&private_data->recfs, &private_data->recfile); + private_data->nor_fs_index = index; + r_printf(">>>[test]: create_recfile index= %d\n", index); + add_path_index(path, index); + printf(">>>[test]: create_recfile path= %s\n", path); + return 0; + } else if (mode[0] == 'r') { + y_printf(">>>[test]: nor_fs_open private_data->index= %d\n", private_data->nor_fs_index); + if (private_data->nor_fs_index) { + index = private_data->nor_fs_index; + } else { + log_e("error!!!!!!!!!"); + index = 0; + private_data->nor_fs_index = 0; + return 1; + } + add_path_index(path, index); + printf(">>>[test]: nor_fs_open read path= %s\n", path); + reg = open_nor_recfile(index, &private_data->recfs, &private_data->recfile); + private_data->is_read_only = 1; + return 0; + } + return 0; +} + +static int nor_fs_write(FILE *_file, void *buff, u32 len) +{ + u16 w_len; + struct imount *mt = _file->mt; + struct nor_fs_rec *private_data = (struct nor_fs_rec *)mt->part.private_data; + if (private_data->first_flag == 1) { + memset(buff, 0xff, 90); + private_data->first_flag = 0; + } + w_len = recfile_write(&private_data->recfile, buff, len); + return w_len; +} + +static int nor_fs_read(FILE *_file, void *buff, u32 len) +{ + u16 r_len; + struct imount *mt = _file->mt; + struct nor_fs_rec *private_data = (struct nor_fs_rec *)mt->part.private_data; + y_printf(">>>[test]:goto nor_fs read\n"); + if (((u32)buff % 4) != 0) { + void *tmp_buf = malloc(512); + r_len = recfile_read(&private_data->recfile, tmp_buf, len); + memcpy(buff, tmp_buf, len); + free(tmp_buf); + return r_len; + } + r_len = recfile_read(&private_data->recfile, buff, len); + return r_len; +} + +static int nor_fs_close(FILE *_file) +{ + int reg; + struct imount *mt = _file->mt; + struct nor_fs_rec *private_data = (struct nor_fs_rec *)mt->part.private_data; + y_printf(">>>[test]:goto nor_fs close\n"); + if (private_data->is_read_only) { + private_data->recfile.pfs->index.index = private_data->recfile.index.index; + private_data->recfile.pfs->index.sector = private_data->recfile.index.sector; + private_data->is_read_only = 0; + return private_data->recfile.w_len; + } + reg = close_nor_recfile(&private_data->recfile); + return reg; +} + +static int nor_fs_seek(FILE *_file, int offsize, int type) +{ + int reg; + struct imount *mt = _file->mt; + struct nor_fs_rec *private_data = (struct nor_fs_rec *)mt->part.private_data; + y_printf(">>>[test]:goto nor_fs seek\n"); + reg = recfile_seek(&private_data->recfile, (u8) type, offsize); + return reg; +} + +static int nor_fs_flen(FILE *_file) +{ + RECFILEHEAD file_h; + struct imount *mt = _file->mt; + struct nor_fs_rec *private_data = (struct nor_fs_rec *)mt->part.private_data; + y_printf(">>>[test]:goto nor_fs_flen\n"); + r_printf(">>>[test]:pfile->len = %d\n", private_data->recfile.len); + return private_data->recfile.len; +} + +static int nor_fs_fpos(FILE *_file) +{ + RECFILEHEAD file_h; + struct imount *mt = _file->mt; + struct nor_fs_rec *private_data = (struct nor_fs_rec *)mt->part.private_data; + r_printf(">>>[test]:pfile->fpos(rw_p) = %d\n", private_data->recfile.rw_p); + return private_data->recfile.rw_p; +} + +static int nor_fs_unmount(struct imount *mt) +{ + int reg; + struct nor_fs_rec *private_data = (struct nor_fs_rec *)mt->part.private_data; + y_printf(">>>[test]:goto nor_fs unmount\n"); + free(private_data); + return 0; +} + +int get_rec_capacity(FILE *_file) +{ + int part_capacity = 0; + struct imount *mt = _file->mt; + struct nor_fs_rec *private_data = (struct nor_fs_rec *)mt->part.private_data; + part_capacity = rec_norflash_get_capacity(private_data->recfs.device); + return part_capacity; +} + +static int nor_fs_fget_attrs(FILE *_file, struct vfs_attr *attr) +{ + struct imount *mt = _file->mt; + struct nor_fs_rec *private_data = (struct nor_fs_rec *)mt->part.private_data; + attr->fsize = private_data->recfile.len; + attr->sclust = private_data->recfile.addr; + + return 0; +} + + +static int nor_fs_delete(FILE *_file) +{ + struct imount *mt = _file->mt; + struct nor_fs_rec *private_data = (struct nor_fs_rec *)mt->part.private_data; + recpfs_clear(&private_data->recfile); + return 0; +} + + +REGISTER_VFS_OPERATIONS(nor_rec_fs_vfs_ops) = { + .fs_type = "rec_fs", + .mount = nor_fs_mount, + .unmount = nor_fs_unmount, + .format = NULL, + .fopen = nor_fs_open, + .fwrite = nor_fs_write, + .fread = nor_fs_read, + .fseek = nor_fs_seek, + .flen = nor_fs_flen, + .fpos = nor_fs_fpos, + .fclose = nor_fs_close, + .fscan = NULL, + .fscan_release = NULL, + .fsel = nor_fs_delete, + .fdelete = NULL, + .fget_name = NULL, + .frename = NULL, + .fget_free_space = NULL, + .fget_attr = NULL, + .fset_attr = NULL, + .fget_attrs = nor_fs_fget_attrs, + .fset_vol = NULL, + .fmove = NULL, + .ioctl = NULL, +}; + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void clear_norfs_allfile(struct imount *mt) +{ + struct nor_fs_rec *private_data = (struct nor_fs_rec *)mt->part.private_data; + recfile_idx_clear(&private_data->recfs); + private_data->recfs.total_file = 0; + private_data->recfs.index.index = 0; + private_data->recfs.index.sector = private_data->recfs.first_sector; +} + +void nor_get_data_info(FILE *_file, u32 *s_addr, u32 *part_size) +{ + struct imount *mt = _file->mt; + struct nor_fs_rec *private_data = (struct nor_fs_rec *)mt->part.private_data; + u32 start_addr, size; + rec_norflash_get_part_info(private_data->recfs.device, &start_addr, &size); + *s_addr = start_addr + private_data->recfile.addr; + *part_size = size; +} + + diff --git a/apps/common/rec_nor/nor_interface.h b/apps/common/rec_nor/nor_interface.h new file mode 100644 index 0000000..b526949 --- /dev/null +++ b/apps/common/rec_nor/nor_interface.h @@ -0,0 +1,45 @@ +#ifndef _NOR_INTERFACE_H_ +#define _NOR_INTERFACE_H_ + +#include "typedef.h" +#include "system/includes.h" +#define NORFS_DATA_LEN 16 +#define FLASH_PAGE_SIZE 256 + +//文件索引 +typedef struct __NOR_RECF_INDEX_INFO { + u16 index; //文件索引号 + u16 sector; //文件所在扇区 +} NOR_RECF_INDEX_INFO; + +//文件系统句柄 +typedef struct __NOR_RECFILESYSTEM { + NOR_RECF_INDEX_INFO index; + u8 buf[FLASH_PAGE_SIZE]; + u16 total_file; + u16 first_sector; + u16 last_sector; + u8 sector_size; + void *device; + void (*eraser)(void *device, u32 address); + s32(*read)(void *device, u8 *buf, u32 addr, u32 len); + s32(*write)(void *device, u8 *buf, u32 addr, u32 len); +} NOR_RECFILESYSTEM, *NOR_PRECFILESYSTEM ; + +//文件句柄 +typedef struct __NOR_REC_FILE { + NOR_RECF_INDEX_INFO index; + NOR_RECFILESYSTEM *pfs; + u32 addr; + char priv_data[NORFS_DATA_LEN]; + u32 len; + u32 w_len; + u32 rw_p; + u16 sr; +} NOR_REC_FILE; + +int get_rec_capacity(FILE *_file); +void clear_norfs_allfile(struct imount *mt); +void nor_get_data_info(FILE *_file, u32 *s_addr, u32 *part_size); + +#endif diff --git a/apps/common/rec_nor/nor_rec_fs.c b/apps/common/rec_nor/nor_rec_fs.c new file mode 100644 index 0000000..8f0d750 --- /dev/null +++ b/apps/common/rec_nor/nor_rec_fs.c @@ -0,0 +1,660 @@ +#include "os/os_api.h" +#include "asm/crc16.h" +#include "stdlib.h" +#include "fs/fs.h" +#include "system/includes.h" +#include "nor_interface.h" +#include "nor_rec_fs.h" + +#define RECFILEHEAD SDFILE_FILE_HEAD + +#define NO_DEBUG_EN +#ifdef NO_DEBUG_EN +#undef r_printf +#undef y_printf +#define r_printf(...) +#define y_printf(...) +#endif + +OS_MUTEX recfs_mutex; ///<互斥信号量 +void recfs_mutex_init(void) ///<信号量初始化 +{ + static u8 init = 0; + if (init) { + return; + } + init = 1; + os_mutex_create(&recfs_mutex); +} +void recfs_mutex_enter(void) ///<申请信号量 +{ + recfs_mutex_init(); + os_mutex_pend(&recfs_mutex, 0); +} +void recfs_mutex_exit(void) ///<释放信号量 +{ + os_mutex_post(&recfs_mutex); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提供给录音文件系统的物理读函数 + @param addr:读取的地址,字节单位。 + @param len:读取的长度,字节单位。 + @param buf:读取的目标BUFF。 + @return u16:读取的长度 + @author liujie + @note u8 recpfs_read(u32 addr,u8 *buf,u16 len) +*/ +/*----------------------------------------------------------------------------*/ +u16 recpfs_read(NOR_RECFILESYSTEM *pfs, u32 addr, u8 *buf, u16 len) +{ + putchar('r'); + recfs_mutex_enter(); + pfs->read(pfs->device, buf, addr, len); + recfs_mutex_exit(); + return len; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提供给录音文件系统的物理写函数 + @param addr:要写入设备的地址,字节单位。 + @param len:需要写入的长度,字节单位。 + @param buf:数据来源BUFF。 + @return u16:写入的长度 + @author liujie + @note u16 recpfs_write(u32 addr,u8 *buf,u16 len) +*/ +/*----------------------------------------------------------------------------*/ +u16 recpfs_write(NOR_RECFILESYSTEM *pfs, u32 addr, u8 *buf, u16 len) +{ + putchar('w'); + recfs_mutex_enter(); + pfs->write(pfs->device, buf, addr, len); + recfs_mutex_exit(); + return len; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 提供给录音文件系统的物理写函数(对齐) + @param pfs:文件系统句柄 + @param addr:要写入设备的地址,字节单位。 + @param len:需要写入的长度,字节单位。 + @param buf:数据来源BUFF。 + @return u16:写入的长度 + @author liujie + @note u16 recpfs_write_align(NOR_RECFILESYSTEM *pfs, u32 addr,u8 *buf,u16 len) +*/ +/*----------------------------------------------------------------------------*/ +u16 recpfs_write_align(NOR_RECFILESYSTEM *pfs, u32 addr, u8 *buf, u16 len) +{ + u32 align_addr = addr % FLASH_PAGE_SIZE; + u16 rlen = FLASH_PAGE_SIZE - align_addr; + u16 total_len = len; + u8 *tmpbuf = pfs->buf; + + if (len == 90) { + align_addr = 0; + } + + addr -= align_addr; + + if (align_addr) { + memset(tmpbuf, 0xff, FLASH_PAGE_SIZE); + if (rlen > len) { + rlen = len; + } + memcpy(tmpbuf + align_addr, buf, rlen); + putchar('C'); + recpfs_write(pfs, addr, tmpbuf, FLASH_PAGE_SIZE); + memset(tmpbuf, 0, FLASH_PAGE_SIZE); + len -= rlen; + buf += rlen; + addr += FLASH_PAGE_SIZE; + } + + while (len >= FLASH_PAGE_SIZE) { + putchar('A'); + memset(tmpbuf, 0xff, FLASH_PAGE_SIZE); + memcpy(tmpbuf, buf, FLASH_PAGE_SIZE); + recpfs_write(pfs, addr, tmpbuf, FLASH_PAGE_SIZE); + len -= FLASH_PAGE_SIZE; + buf += FLASH_PAGE_SIZE; + addr += FLASH_PAGE_SIZE; + } + + if (len) { + putchar('B'); + memset(tmpbuf, 0xff, FLASH_PAGE_SIZE); + memcpy(tmpbuf, buf, len); + recpfs_write(pfs, addr, tmpbuf, len); + } + return total_len; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提供给录音文件系统的物理擦除函数 + @param pfs:要写入设备的地址,字节单位。 + @param start_sector:需要擦除的第一个扇区。 + @param end_sector:需要擦除的最后一个扇区。 + @return u16:擦除的扇区数目 + @author liujie + @note u16 recpfs_erase_sector(NOR_RECFILESYSTEM *pfs,u16 start_sector,u16 end_sector) +*/ +/*----------------------------------------------------------------------------*/ +u16 recpfs_erase_sector(NOR_RECFILESYSTEM *pfs, u16 start_sector, u16 end_sector) +{ + if ((start_sector < pfs->first_sector) || (start_sector > pfs->last_sector)) { + return 0 ; + } + if ((end_sector < pfs->first_sector) || (end_sector > pfs->last_sector)) { + return 0 ; + } + u16 sector_cnt = 0; + /* r_printf(">>>[test]:start_sector = %d, end_sector =%d\n", start_sector , end_sector); */ + while (1) { + recfs_mutex_enter(); + pfs->eraser(pfs->device, ((u32)start_sector << pfs->sector_size)); + recfs_mutex_exit(); + sector_cnt++; + if (start_sector == end_sector) { + break; + } + start_sector++; + if (start_sector > pfs->last_sector) { + start_sector = pfs->first_sector; + } + } + return sector_cnt; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 录音文件seek函数 + @param pfile:文件句柄 + @param type:seek的格式 + @param offsize:seek的偏移量。 + @return u8:返回值 + @author liujie + @note u8 recfile_seek (REC_FILE *pfile, u8 type, u32 offsize) +*/ +/*----------------------------------------------------------------------------*/ +u8 recfile_seek(NOR_REC_FILE *pfile, u8 type, int offsize) +{ + u32 file_len; + if (NULL == pfile) { + return 0; + } + /* y_printf(">>>[test]:pfile->len = %d,type = %d, offsize = %d\n",pfile->len, type, offsize); */ + file_len = pfile->len;//(u32)pfile->index.sector << pfile->pfs->sector_size; + if (NOR_FS_SEEK_SET == type) { + if (abs(offsize) >= file_len) { + return REC_FILE_END; + } + pfile->rw_p = offsize + sizeof(RECFILEHEAD); + } else { + offsize += pfile->rw_p; + if (offsize >= file_len) { + return REC_FILE_END; + } + pfile->rw_p += offsize; + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 录音文件读函数 + @param pfile:文件句柄 + @param buff:数据BUFF + @param btr:需要读取的数据长度,字节单位 + @return u16:读取回来的长度 + @author liujie + @note u16 recfile_read(REC_FILE _xdata *pfile ,u8 _xdata *buff , u16 btr) +*/ +/*----------------------------------------------------------------------------*/ +u16 recfile_read(NOR_REC_FILE *pfile, u8 *buff, u16 btr) +{ + u32 file_len, addr; + u16 read_len = btr; + u16 len, len0; + u32 max_addr, min_addr; + max_addr = ((u32)(pfile->pfs->last_sector + 1) << pfile->pfs->sector_size) ; + min_addr = ((u32)(pfile->pfs->first_sector) << pfile->pfs->sector_size) ; + file_len = (u32)pfile->len; + if ((u32)(btr + pfile->rw_p) >= file_len) { + if (pfile->rw_p >= file_len) { + return 0; + } + read_len = file_len - pfile->rw_p; + } + addr = pfile->rw_p + ((u32)pfile->index.sector << pfile->pfs->sector_size); + len0 = read_len; + /* y_printf(">>>[test]:r_addr = %d,max_addr =%d, min_addr=%d, pfile->rw_p =%d\n", addr, max_addr, min_addr, pfile->rw_p); */ + //y_printf(">>>[test]:r_len0 = %d,btr = %d, file_len = %d\n",len0, btr, file_len); + while (len0) { + if (addr >= max_addr) { + addr = addr - max_addr + min_addr; + } + if ((addr + len0) > max_addr) { + len = max_addr - addr; + } else { + len = len0; + } + /* y_printf(">>>[test]2222r_addr = %d,max_addr =%d, min_addr=%d, pfile->rw_p =%d\n",addr, max_addr, min_addr, pfile->rw_p); */ + recpfs_read(pfile->pfs, addr, buff, len); + pfile->rw_p += len; + len0 -= len; + buff += len; + addr += len; + } + return read_len; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 录音文件写函数 + @param pfile:文件句柄 + @param buff:数据BUFF + @param btr:需要写入的数据长度,字节单位 + @return u16:写入的长度 + @author liujie + @note u16 recf_write(NOR_REC_FILE *pfile,u8 *buff,u16 btw) +*/ +/*----------------------------------------------------------------------------*/ +u16 recfile_write(NOR_REC_FILE *pfile, u8 *buff, u16 btw) +{ + u32 addr; + u32 max_addr, min_addr; + u16 sector; + u16 len0 = 0; + u16 len = 0;; + max_addr = ((u32)(pfile->pfs->last_sector + 1) << pfile->pfs->sector_size) ; + min_addr = ((u32)(pfile->pfs->first_sector) << pfile->pfs->sector_size) ; + addr = pfile->rw_p + ((u32)pfile->index.sector << pfile->pfs->sector_size); + /* y_printf(">>>[test]:addr = %d,max_addr =%d, min_addr=%d, pfile->rw_p =%d\n",addr, max_addr, min_addr, pfile->rw_p); */ + /*printf(">>>[test]:addr =0x%x,max_addr =0x%x, min_addr=0x%x,offset_addr=0x%x, pfile->rw_p =0x%x\n",addr, max_addr, min_addr, offset_addr,pfile->rw_p);*/ + while (1) { + if ((pfile->rw_p + btw) > pfile->len) { + //获取更多的空间; + sector = (pfile->len + (1L << pfile->pfs->sector_size) - 1) >> pfile->pfs->sector_size; + sector += pfile->index.sector; + if (sector > pfile->pfs->last_sector) { + sector = sector - pfile->pfs->last_sector + pfile->pfs->first_sector - 1; + } + if (pfile->index.sector != sector) { + /* r_printf(">>>[test]:goto erase\n"); */ + recpfs_erase_sector(pfile->pfs, sector, sector); + /* r_printf(">>>[test]:exit erase\n"); */ + pfile->len = pfile->len + (1L << pfile->pfs->sector_size); + } else { + /* y_printf(">>>[test]:not erase, sector = %d\n", sector); */ + break; + } + + } else { + break; + } + } + if ((pfile->rw_p + btw) > pfile->len) { + len = pfile->len - pfile->rw_p ; + y_printf(">>>[test]:len = %d, pfile->len = %d,pfile->rw_p =%d \n", len, pfile->len, pfile->rw_p); + } else { + len = btw; + } + len0 = len; + + while (len0) { + if (addr >= max_addr) { + addr = addr - max_addr + min_addr; + /* r_printf(">>>[test]:write the end, goto first addr write\n"); */ + } + + if ((addr + len0) > max_addr) { + btw = max_addr - addr; + } else { + btw = len0; + } + /* y_printf(">>>[test]:btw = %d\n", btw); */ + recpfs_write_align(pfile->pfs, addr, buff, btw); + /* y_printf(">>>[test]:len0 = %d\n",len0); */ + addr += btw; + buff += btw; + len0 -= btw; + } + pfile->rw_p += len; + if (pfile->rw_p > pfile->w_len) { + pfile->w_len = pfile->rw_p; + } + return len; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 清除索引 + @param pfs:文件系统句柄 + @return void + @author liujie + @note void recfile_idx_clear(NOR_RECFILESYSTEM *pfs) +*/ +/*----------------------------------------------------------------------------*/ +void recfile_idx_clear(NOR_RECFILESYSTEM *pfs) +{ + RECFILEHEAD file_h; + u32 addr; + u16 curr_sector; + + curr_sector = pfs->first_sector; + memset(&file_h, 0, sizeof(RECFILEHEAD)); + + while (curr_sector <= pfs->last_sector) { + addr = (u32)curr_sector << pfs->sector_size; + recpfs_write_align(pfs, addr, (u8 *)(&file_h), sizeof(RECFILEHEAD)); + curr_sector++; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief delete a rec_file + @param pfs:文件系统句柄 + @return void + @author phew +*/ +/*----------------------------------------------------------------------------*/ +void recpfs_clear(NOR_REC_FILE *pfile) +{ + RECFILEHEAD file_h; + u32 addr; + u16 curr_sector; + + curr_sector = pfile->index.sector; + memset(&file_h, 0, sizeof(RECFILEHEAD)); + addr = (u32)curr_sector << pfile->pfs->sector_size; + recpfs_write_align(pfile->pfs, addr, (u8 *)(&file_h), sizeof(RECFILEHEAD)); + +} + +/*----------------------------------------------------------------------------*/ +/**@brief 扫描文件系统 + @param pfs:文件系统句柄 + @return u32:总文件数 + @author liujie + @note u32 recfs_scan(NOR_RECFILESYSTEM *pfs) +*/ +/*----------------------------------------------------------------------------*/ +/*扫描出最少的文件*/ +u32 rec_pfs_scan(NOR_RECFILESYSTEM *pfs) +{ + RECFILEHEAD file_h __attribute__((aligned(4))); + NOR_RECF_INDEX_INFO max_index; + u32 addr; + u32 total_len; + u16 crc; + u16 file_cnt = 0; + u16 curr_sector = pfs->first_sector; + pfs->total_file = 0; + max_index.index = 0; + max_index.sector = pfs->first_sector; + total_len = (u32)((u32)pfs->last_sector + 1 - (u32)pfs->first_sector) << pfs->sector_size; + while (1) { + addr = (u32)curr_sector << pfs->sector_size; + /* r_printf(">>>[test]:addr=0x%x\n", addr); */ + recpfs_read(pfs, addr, (u8 *)(&file_h), sizeof(RECFILEHEAD)); + crc = CRC16(&file_h.data_crc, sizeof(RECFILEHEAD) - 2); + /* y_printf(">>>[test]:crc = 0x%x, file_h.len = %d, file_h.index = %d\n", crc, file_h.len, file_h.index); */ + if ((0 != crc) && (crc == file_h.head_crc) && (file_h.len <= total_len)) { + if (file_h.index >= max_index.index) { + max_index.index = file_h.index; + max_index.sector = curr_sector; + } + r_printf(">>>[test]:addr=%d\n", addr); + file_cnt++; + if (0 != file_h.len) { + curr_sector += file_h.len >> pfs->sector_size; + if (file_h.len % (1L << pfs->sector_size)) { + curr_sector++; + } + } else { + curr_sector++; + } + + } else { + curr_sector++; + } + if (curr_sector > pfs->last_sector) { + //curr_sector = pfs->first_sector; + break; + } + } + + if (max_index.index < 0) { + //清空整个MEM() + y_printf(">>>[test]:goto clear index.sector\n"); + recfile_idx_clear(pfs); + pfs->total_file = 0; + pfs->index.index = 0; + pfs->index.sector = pfs->first_sector; + } else { + pfs->index.index = max_index.index; + pfs->index.sector = max_index.sector; + /* y_printf(">>>[test]:recfs_scan pfs->index.sector = %d, pfs->index.index = %d\n", pfs->index.sector, pfs->index.index); */ + pfs->total_file = file_cnt; + /* y_printf(">>>[test]:recfs_scan file_cnt = %d\n", file_cnt); */ + } + + return file_cnt; +} +/*----------------------------------------------------------------------------*/ +/**@brief 检查指定扇区是否存爱文件 + @param pfs:文件系统的句柄 + @param pfile_h:文件头指针 + @param sector:需要分析的扇区 + @return u16:下一个有效扇区 + @author liujie + @note u16 check_head(NOR_RECFILESYSTEM *pfs,RECFILEHEAD *pfile_h,u16 sector) +*/ +/*----------------------------------------------------------------------------*/ +u16 nor_check_head(NOR_RECFILESYSTEM *pfs, RECFILEHEAD *pfile_h, u16 sector) +{ + u32 addr; + u32 total_len; + addr = sector; + addr = addr << pfs->sector_size; + + total_len = (u32)((u32)pfs->last_sector + 1 - (u32)pfs->first_sector) << pfs->sector_size; + y_printf(">>>[test]: check head addr = %d\n", addr); + recpfs_read(pfs, addr, (u8 *)pfile_h, sizeof(RECFILEHEAD)); + if ((CRC16(&pfile_h->data_crc, sizeof(RECFILEHEAD) - 2) == pfile_h->head_crc) + && (pfile_h->len <= total_len) + ) { + r_printf(">>>[test]:AAAAAAAAAAA\n"); + sector = sector + (pfile_h->len >> pfs->sector_size); + r_printf(">>>[test]:sector = %d\n", sector); + if (pfile_h->len % (1L << pfs->sector_size)) { + r_printf(">>>[test]:BBBBBBBBBBB\n"); + sector++; + } else { + } + } else { + } + return sector; +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief 建立一个文件 + @param pfs:文件系统的句柄 + @param pfile:文件的句柄 + @return u32:建立文件索引 + @author liujie + @note u32 create_nor_recfile(NOR_RECFILESYSTEM *pfs,NOR_REC_FILE *pfile) +*/ +/*----------------------------------------------------------------------------*/ +u32 create_nor_recfile(NOR_RECFILESYSTEM *pfs, NOR_REC_FILE *pfile) +{ + RECFILEHEAD file_h; + u16 sector, sec0; + u16 sec_len; + + memset((u8 *)pfile, 0, sizeof(NOR_REC_FILE)); + pfile->pfs = pfs; + sector = pfs->index.sector; + /* y_printf(">>>[test]:create pfs->index.sector = %d\n", pfs->index.sector); */ + sec0 = nor_check_head(pfs, &file_h, sector); + if (sector != sec0) { + if (sec0 > pfs->last_sector) { + sec0 = sec0 - pfs->last_sector + pfs->first_sector - 1; + } + sector = sec0; + } + pfile->index.index = pfs->index.index + 1; + pfile->index.sector = sec0; + sec_len = recpfs_erase_sector(pfs, sector, sec0); + /* y_printf(">>>[test]:sec_len = %d\n",sec_len); */ + pfile->len = (u32)sec_len << pfs->sector_size; + pfile->w_len = sizeof(RECFILEHEAD); + pfile->rw_p = sizeof(RECFILEHEAD); + pfile->addr = pfile->rw_p + (pfile->index.sector << pfile->pfs->sector_size) ; + /* y_printf(">>>[test]:rw_p = %d\n", pfile->rw_p); */ + return pfile->index.index; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭一个文件 + @param pfile:文件的句柄 + @return u32:建立文件索引 + @author liujie + @note u32 close_nor_recfile(NOR_REC_FILE *pfile) +*/ +/*----------------------------------------------------------------------------*/ +u32 close_nor_recfile(NOR_REC_FILE *pfile) +{ + RECFILEHEAD file_h; + + memset(&file_h, 0xff, sizeof(RECFILEHEAD)); + pfile->w_len = pfile->rw_p; + pfile->len = pfile->w_len; + pfile->rw_p = 0;//sizeof(RECFILEHEAD); + file_h.len = pfile->w_len; + file_h.index = pfile->index.index; + file_h.addr = pfile->addr; + memcpy(file_h.name, pfile->priv_data, NORFS_DATA_LEN); + r_printf(">>>[test]:file_h.priv_data = %s, len = %d\n", file_h.name, NORFS_DATA_LEN); + + file_h.head_crc = CRC16(&file_h.data_crc, sizeof(RECFILEHEAD) - 2); + r_printf(">>>[test]:pfile->index.sector = %d\n", pfile->index.sector); + + recfile_write(pfile, (u8 *)&file_h, sizeof(RECFILEHEAD)); + pfile->pfs->index.index = pfile->index.index; + pfile->pfs->index.sector = pfile->index.sector; + + /* r_printf(">>>[test]:file_h.len = %d\n", file_h.len); */ + return file_h.len; +} + +void recfile_save_sr(NOR_REC_FILE *pfile, u16 sr) +{ + if (pfile) { + pfile->sr = sr; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按照索引号,搜索一个文件 + @param index:索引号 + @param pfile:文件的句柄 + @return u32:找到文件的索引 + @author liujie + @note u32 recfile_index_scan(u32 index,NOR_REC_FILE *pfile) +*/ +/*----------------------------------------------------------------------------*/ +u32 recfile_index_scan(u32 index, NOR_REC_FILE *pfile) +{ + RECFILEHEAD file_h; + NOR_RECFILESYSTEM *pfs; + u32 addr; + u32 total_len; + u16 curr_sector, crc; + + pfs = pfile->pfs; + curr_sector = pfs->index.sector; + total_len = (u32)((u32)pfs->last_sector + 1 - (u32)pfs->first_sector) << pfs->sector_size; + /* r_printf(">>>[test]:pfile->pfs->index.sector = %d, total_len = %d\n", pfile->pfs->index.sector, total_len); */ + while (1) { + addr = (u32)curr_sector << pfs->sector_size; + /* r_printf(">>>[test]:offset_addr = 0x%x, addr = 0x%x\n", offset_addr, addr); */ + /* } */ + recpfs_read(pfs, addr, (u8 *)(&file_h), sizeof(RECFILEHEAD)); + crc = CRC16(&file_h.data_crc, sizeof(RECFILEHEAD) - 2); + /* y_printf(">>>[test]:crc = 0x%x, file_h.len = %d, file_h.index = %d\n", crc, file_h.len, file_h.index); */ + if ((0 != crc) && (crc == file_h.head_crc) && (file_h.len <= total_len)) { + if (file_h.index == index) { + printf(">>>[test]:go in AAAAAA\n"); + pfile->index.index = index; + pfile->index.sector = curr_sector; + pfile->len = file_h.len; + pfile->w_len = file_h.len; + pfile->rw_p = sizeof(RECFILEHEAD); + pfile->addr = file_h.addr; + memcpy(pfile->priv_data, file_h.name, NORFS_DATA_LEN); + return index; + } else { + if (0 == file_h.len) { + curr_sector++; + } + curr_sector = curr_sector + (file_h.len >> pfs->sector_size); + if (file_h.len % (1L << pfs->sector_size)) { + curr_sector++; + } + } + } else { + curr_sector++; + } + + if (curr_sector > pfs->last_sector) { + curr_sector = pfs->first_sector; + } + /* r_printf(">>>[test]:pfile->index.sector = %d, curr_sector = %d\n", pfile->index.sector, curr_sector); */ + if (pfs->index.sector == curr_sector) { + break; + } + } + return index - 1; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按照索引号打开一个文件 + @param index:索引号 + @param pfs:文件系统的句柄 + @param pfile:文件的句柄 + @return u32:找到文件的索引 + @author liujie + @note u32 open_nor_recfile(u32 index,NOR_RECFILESYSTEM *pfs,NOR_REC_FILE *pfile) +*/ +/*----------------------------------------------------------------------------*/ +u32 open_nor_recfile(u32 index, NOR_RECFILESYSTEM *pfs, NOR_REC_FILE *pfile) +{ + memset((u8 *)pfile, 0, sizeof(NOR_REC_FILE)); + pfile->pfs = pfs; + pfile->rw_p = sizeof(RECFILEHEAD); + return recfile_index_scan(index, pfile); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 初始化文件系统信息 + @param pfs:文件系统的句柄 + @param sector_start:起始扇区 + @param sector_end:结束扇区 + @param sector_size:扇区大小(1L<first_sector = sector_start; + pfs->last_sector = sector_end; + pfs->sector_size = sector_size; +} + diff --git a/apps/common/rec_nor/nor_rec_fs.h b/apps/common/rec_nor/nor_rec_fs.h new file mode 100644 index 0000000..1907f15 --- /dev/null +++ b/apps/common/rec_nor/nor_rec_fs.h @@ -0,0 +1,31 @@ +#ifndef _NOR_REC_FS_H_ +#define _NOR_REC_FS_H_ + +#define REC_FILE_END 0xFE + +enum { + NOR_FS_SEEK_SET = 0, + NOR_FS_SEEK_CUR = 0x01 +}; + +u16 recpfs_read(NOR_RECFILESYSTEM *pfs, u32 addr, u8 *buf, u16 len); +u16 recpfs_write(NOR_RECFILESYSTEM *pfs, u32 addr, u8 *buf, u16 len); +u16 recpfs_write_align(NOR_RECFILESYSTEM *pfs, u32 addr, u8 *buf, u16 len); +u16 recpfs_erase_sector(NOR_RECFILESYSTEM *pfs, u16 start_sector, u16 end_sector); +u8 recfile_seek(NOR_REC_FILE *pfile, u8 type, int offsize); +u16 recfile_read(NOR_REC_FILE *pfile, u8 *buff, u16 btr); +u16 recfile_write(NOR_REC_FILE *pfile, u8 *buff, u16 btw); +void recfile_idx_clear(NOR_RECFILESYSTEM *pfs); +void recpfs_clear(NOR_REC_FILE *pfile); +u32 rec_pfs_scan(NOR_RECFILESYSTEM *pfs); +u32 create_nor_recfile(NOR_RECFILESYSTEM *pfs, NOR_REC_FILE *pfile); +u32 close_nor_recfile(NOR_REC_FILE *pfile); +u32 recfile_index_scan(u32 index, NOR_REC_FILE *pfile); +u32 open_nor_recfile(u32 index, NOR_RECFILESYSTEM *pfs, NOR_REC_FILE *pfile); +void nor_pfs_init(NOR_RECFILESYSTEM *pfs, u16 sector_start, u16 sector_end, u8 sector_size); + + + + + +#endif diff --git a/apps/common/storage_dev/storage_dev.h b/apps/common/storage_dev/storage_dev.h new file mode 100644 index 0000000..98564f2 --- /dev/null +++ b/apps/common/storage_dev/storage_dev.h @@ -0,0 +1,64 @@ +#ifndef _STORAGE_DEV_H_ +#define _STORAGE_DEV_H_ + +#include "typedef.h" + +struct storage_dev { + char *logo; + char *dev_name; + char *storage_path; + char *root_path; + char *fs_type; + void *priv; + u32 *counter; +}; + +enum { + STORAGE_DEV_OK = 0, + STORAGE_DEV_ALREADY = (('S' << 24) | ('G' << 16) | ('\0' << 8) | '\0'), + STORAGE_DEV_IS_NOT_STORAGE, + STORAGE_DEV_NO_FIND, + STORAGE_DEV_EMPTY, + STORAGE_DEV_FULL, + STORAGE_DEV_CALLBACK, + STORAGE_DEV_FAT_MOUNT_FAIL, +}; + +int storage_dev_add(void *logo); +int storage_dev_del(void *logo); +int storage_dev_total(void); + +struct storage_dev *storage_dev_check(void *logo); +struct storage_dev *storage_dev_frist(void); +struct storage_dev *storage_dev_last(void); +struct storage_dev *storage_dev_last_active(void); +struct storage_dev *storage_dev_next(struct storage_dev *cur); +struct storage_dev *storage_dev_prev(struct storage_dev *cur); +struct storage_dev *storage_dev_last_active(void); +struct storage_dev *storage_dev_find_by_index(u16 index);//根据号码获取设备 +void storage_dev_active_mark(void *logo); + + +// return 0-ok +typedef int (* storage_callback)(struct storage_dev *); + +int storage_dev_add_ex(void *logo, storage_callback cb); +int storage_dev_del_ex(void *logo, storage_callback cb); +int storage_dev_total_ex(storage_callback cb); + +struct storage_dev *storage_dev_check_ex(void *logo, storage_callback cb); +struct storage_dev *storage_dev_frist_ex(storage_callback cb); +struct storage_dev *storage_dev_last_ex(storage_callback cb); +struct storage_dev *storage_dev_next_ex(struct storage_dev *cur, storage_callback cb); +struct storage_dev *storage_dev_prev_ex(struct storage_dev *cur, storage_callback cb); +struct storage_dev *storage_dev_last_active_ex(storage_callback cb); + + +#define REGISTER_STORAGE_DEVICE(node) \ + const struct storage_dev node sec(.storage_device) + +#define REGISTER_STORAGE_DEVICES(node) \ + const struct storage_dev node[] sec(.storage_device) + +#endif + diff --git a/apps/common/third_party_profile/common/3th_profile_api.c b/apps/common/third_party_profile/common/3th_profile_api.c new file mode 100644 index 0000000..fa55e93 --- /dev/null +++ b/apps/common/third_party_profile/common/3th_profile_api.c @@ -0,0 +1,115 @@ +#include +#include +#include + +#include "typedef.h" +#include "3th_profile_api.h" +#include "bt_tws.h" +#include "key_event_deal.h" +#include "system/timer.h" +#include "bt_common.h" +#include "btstack/avctp_user.h" +#include "os/os_api.h" + +#if BT_FOR_APP_EN + +#if (OTA_TWS_SAME_TIME_ENABLE && RCSP_ADV_EN && USER_APP_EN) +#include "rcsp_adv_tws_ota.h" +#endif + +#if (OTA_TWS_SAME_TIME_ENABLE && SMART_BOX_EN) +#include "smartbox_update_tws.h" +#else +#include "update_tws.h" +#endif + +static u8 mic_data_type = SOURCE_TYPE; +static u8 connect_type = TYPE_NULL; +static u8 tws_ble_type = TYPE_NULL; + +void mic_set_data_source(u8 data_type) +{ + mic_data_type = data_type; +} + +u8 mic_get_data_source(void) +{ + return mic_data_type; +} + +u8 get_ble_connect_type(void) +{ + return tws_ble_type; +} + +void set_ble_connect_type(u8 type) +{ + tws_ble_type = type; +} + +u8 get_app_connect_type(void) +{ + return connect_type; +} + +void set_app_connect_type(u8 type) +{ + connect_type = type; +} + + +#if TCFG_USER_TWS_ENABLE + +int tws_data_to_sibling_send(u8 opcode, u8 *data, u8 len) +{ + u8 send_data[len + 2]; + printf(">>>>>>>>>>send data to sibling \n"); + send_data[0] = opcode; + send_data[1] = len; + memcpy(send_data + 2, data, len); + + return tws_api_send_data_to_sibling(send_data, sizeof(send_data), TWS_FUNC_ID_AI_SYNC); +} + +static void __ai_tws_rx_from_sibling(u8 *data) +{ + u8 opcode = data[0]; + u8 len = data[1]; + u8 *rx_data = data + 2; + +#if (OTA_TWS_SAME_TIME_ENABLE && (RCSP_BTMATE_EN || RCSP_ADV_EN || SMART_BOX_EN)) + tws_ota_get_data_from_sibling(opcode, rx_data, len); +#endif + + free(data); +} + +static void ai_tws_rx_from_sibling(void *_data, u16 len, bool rx) +{ + int err = 0; + if (rx) { + printf(">>>%s \n", __func__); + printf("len :%d\n", len); + put_buf(_data, len); + u8 *rx_data = malloc(len); + memcpy(rx_data, _data, len); + + int msg[4]; + msg[0] = (int)__ai_tws_rx_from_sibling; + msg[1] = 1; + msg[2] = (int)rx_data; + err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg); + if (err) { + printf("tws rx post fail\n"); + } + } +} + +//发送给对耳 +REGISTER_TWS_FUNC_STUB(app_vol_sync_stub) = { + .func_id = TWS_FUNC_ID_AI_SYNC, + .func = ai_tws_rx_from_sibling, +}; + +#endif +#endif diff --git a/apps/common/third_party_profile/common/3th_profile_api.h b/apps/common/third_party_profile/common/3th_profile_api.h new file mode 100644 index 0000000..f02c1c3 --- /dev/null +++ b/apps/common/third_party_profile/common/3th_profile_api.h @@ -0,0 +1,41 @@ + + +#ifndef _3TH_PROFILE_API_H +#define _3TH_PROFILE_API_H + +#include +#include +#include "le_common.h" + +enum { + TWS_AI_CONN_STA = 0, + TWS_AI_DISCONN_STA, + TWS_AI_SPEECH_START, + TWS_AI_SPEECH_STOP, +}; + + +#define TYPE_NULL 0 +#define TYPE_BLE 1 +#define TYPE_SPP 2 + +#define TYPE_MASTER_BLE 3 +#define TYPE_SLAVE_BLE 4 + +#define TYPE_MASTER_SPP 5 +#define TYPE_SLAVE_SPP 6 + +#define SOURCE_TYPE 0 +#define SINK_TYPE_MASTER 1 +#define SINK_TYPE_SLAVE 2 + +void set_app_connect_type(u8 type); +u8 get_app_connect_type(void); +u8 get_ble_connect_type(void); +void set_ble_connect_type(u8 type); +void mic_set_data_source(u8 data_type); +u8 mic_get_data_source(void); + +int tws_data_to_sibling_send(u8 opcode, u8 *data, u8 len); //发送数据给对耳 + +#endif diff --git a/apps/common/third_party_profile/common/custom_cfg.c b/apps/common/third_party_profile/common/custom_cfg.c new file mode 100644 index 0000000..469649c --- /dev/null +++ b/apps/common/third_party_profile/common/custom_cfg.c @@ -0,0 +1,1412 @@ +#include "board_config.h" +#include "custom_cfg.h" +#include "app_config.h" + +#if RCSP_BTMATE_EN +#include "rcsp_user_update.h" +#include "rcsp_bluetooth.h" +#elif RCSP_ADV_EN +#include "rcsp_adv_user_update.h" +#include "rcsp_adv_bluetooth.h" +#elif SMART_BOX_EN +#include "smartbox_adv_bluetooth.h" +#endif + +#if AI_APP_PROTOCOL +#include "app_protocol_api.h" +#endif + +#if RCSP_ADV_EN || RCSP_BTMATE_EN || SMART_BOX_EN || APP_PROTOCOL_READ_CFG_EN +#include "app_config.h" +#include "fs.h" +//#include "crc_api.h" +//#include "syd_file.h" +#include "uart.h" +#include + +#if 0 +#pragma code_seg(".custom_cfg_code") +#pragma bss_seg(".custom_cfg_bss") +#pragma const_seg(".custom_cfg_const") +#endif + +#define CFG_DEBUG_TAG "-[CFG]:" +//#define RES_CUSTOM_CFG_FILE "/config.***" +#define RES_CUSTOM_CFG_FILE SDFILE_RES_ROOT_PATH"config.dat" + +//配置:VM的接口采用692X还是693X +#define VM_API_AC692X 0 +#define VM_API_AC693X 1 +#define USE_VM_API_SEL VM_API_AC693X + +//配置:是否在总是擦除EXIF区域然后重写,还是只有在EXIF信息有变化时才擦除 +#define ALWAYS_ERASE_EXIF_AREA 0 +#define ONLY_DIFF_ERASE_EXIF_AREA 1 +#define EXIF_ERASE_CONFIG ALWAYS_ERASE_EXIF_AREA + +//配置:文件操作接口是用692X还是693X +#define SDFILE_API_AC692X 0 +#define SDFILE_API_AC693X 1 +#define USE_FS_API_SEL SDFILE_API_AC693X + + +#define CUSTOM_CFG_DEBUG_EN 1 +#if CUSTOM_CFG_DEBUG_EN +#define cfg_puts puts +#define cfg_printf printf +#define cfg_printf_buf put_buf +#else +#define cfg_puts(...) +#define cfg_printf(...) +#define cfg_printf_buf(...) +#endif + +typedef struct _exif_info_t { + u32 addr; + u32 len; +} exif_info_t; + +static exif_info_t exif_info; + +#define MEMBER_OFFSET_OF_STRUCT(type, member) ((u32)&(((type *)0)->member)) +#define MEMBER_SIZE_OF_STRUCT(type,member) ((u16)sizeof(((type *)0)->member)) + +typedef struct _adv_data_t { + u16 crc; + u16 len; + u8 data[31]; +} adv_data_cfg_t; + +typedef struct _ble_name_t { + u16 crc; + u16 len; + u8 data[31 - 2]; +} ble_name_t; + +typedef struct _bt_name_t { + u16 crc; + u16 len; + u8 data[31]; +} bt_name_t; + +typedef struct _bt_pin_code_t { + u16 crc; + u16 len; + char data[4]; +} bt_pin_code_t; + +typedef struct _ver_info_cfg_t { + u16 crc; + u16 len; + update_file_id_t data; +} ver_info_cfg_t; + +typedef struct _reset_io_info_cfg_t { + u16 crc; + u16 len; + u8 data; +} reset_io_info_cfg_t; + +typedef struct _polit_lamp_io_info_cfg_t { + u16 crc; + u16 len; + u8 data[4]; +} pilot_lamp_io_info_cfg_t; + +typedef struct _link_key_info_cfg_t { + u16 crc; + u16 len; + update_file_link_key_t data; +} link_key_info_cfg_t; + +typedef struct _last_device_connect_linkkey_cfg_t { + u16 crc; + u16 len; + u8 data[16]; +} last_device_connect_linkkey_cfg_t; + +typedef struct LOW_POWER_VOLTAGE { + u16 crc; + u16 len; + u8 data[2]; +} low_power_voltage_t; + +typedef struct _bt_addr_cfg_t { + u16 crc; + u16 len; + u8 data[6]; +} bt_addr_cfg_t; + +typedef struct _gatt_profile_cfg_t { + u16 crc; + u16 len; + u8 data[512 + 256]; +} gatt_profile_cfg_t; + +typedef struct _power_io_on_off_cfg_t { + u16 crc; + u16 len; + u8 data[6]; +} power_io_on_off_cfg_t; + +#if VER_INFO_EXT_COUNT +typedef struct _ver_info_ext_cfg_t { + u16 crc; + u16 len; + u8 data[VER_INFO_EXT_MAX_LEN]; +} ver_info_ext_cfg_t; +#endif + +typedef struct _read_write_uuid_cfg_t { + u16 crc; + u16 len; + u8 data[4]; +} read_write_uuid_cfg_t; + +typedef struct _common_cfg_t { + u16 crc; + u16 len; + u8 data[0]; +} common_cfg_t; + +typedef struct _pid_vid_cfg_t { + u16 crc; + u16 len; + u8 data[4]; +} pid_vid_cfg_t; + +typedef struct _authkey_cfg_t { + u16 crc; + u16 len; + u8 data[32]; +} authkey_cfg_t; + +typedef struct _project_code_cfg_t { + u16 crc; + u16 len; + u8 data[32]; +} project_code_cfg_t; + +typedef struct _md5_cfg_t { + u16 crc; + u16 len; + u8 data[32]; +} md5_cfg_t; + +typedef struct _sdk_type_cfg_t { + u16 crc; + u16 len; + u8 data; +} sdk_type_cfg_t; + +typedef struct _ex_cfg_t { + adv_data_cfg_t adv_data_cfg; + adv_data_cfg_t scan_rsp_cfg; + ble_name_t ble_name_cfg; + bt_name_t bt_name_cfg; + bt_pin_code_t pin_code_cfg; + ver_info_cfg_t ver_info_cfg; + low_power_voltage_t low_power_voltage_cfg; + bt_addr_cfg_t edr_addr_cfg; + bt_addr_cfg_t ble_addr_cfg; + gatt_profile_cfg_t gatt_profile_cfg; + reset_io_info_cfg_t reset_io_info_cfg; + pilot_lamp_io_info_cfg_t pilot_lamp_io_info_cfg; + link_key_info_cfg_t link_key_info_cfg; + power_io_on_off_cfg_t power_io_on_off_cfg; + last_device_connect_linkkey_cfg_t last_device_connect_linkkey_cfg; + read_write_uuid_cfg_t ble_read_write_uuid_cfg; +#if VER_INFO_EXT_COUNT + ver_info_ext_cfg_t ver_info_authkey_cfg; + ver_info_ext_cfg_t ver_info_procode_cfg; +#endif + pid_vid_cfg_t pid_vid_cfg; + md5_cfg_t md5_cfg; + sdk_type_cfg_t sdk_type_cfg; +} ex_cfg_t; + +typedef union _ex_cfg_item_u { + adv_data_cfg_t adv_data_cfg; + adv_data_cfg_t scan_rsp_cfg; + ble_name_t ble_name_cfg; + bt_name_t bt_name_cfg; + bt_pin_code_t pin_code_cfg; + ver_info_cfg_t ver_info_cfg; + low_power_voltage_t low_power_voltage_cfg; + bt_addr_cfg_t edr_addr_cfg; + bt_addr_cfg_t ble_addr_cfg; + gatt_profile_cfg_t gatt_profile_cfg; + reset_io_info_cfg_t reset_io_info_cfg; + pilot_lamp_io_info_cfg_t pilot_lamp_io_info_cfg; + link_key_info_cfg_t link_key_info_cfg; + power_io_on_off_cfg_t power_io_on_off_cfg; + last_device_connect_linkkey_cfg_t last_device_connect_linkkey_cfg; + read_write_uuid_cfg_t ble_read_write_uuid_cfg; +#if VER_INFO_EXT_COUNT + ver_info_ext_cfg_t ver_info_authkey_cfg; + ver_info_ext_cfg_t ver_info_procode_cfg; +#endif + common_cfg_t common_cfg; + pid_vid_cfg_t pid_vid_cfg; + md5_cfg_t md5_cfg; + sdk_type_cfg_t sdk_type_cfg; +} ex_cfg_item_u; + +typedef struct _cfg_item_head_t { + u16 index; + u16 type; + u32 addr; + u32 len; + u16 crc; + u16 rfu; + u8 name[16]; +} cfg_item_head_t; + +typedef struct _cfg_head_t { + u8 flag[4]; + u16 self_crc; + u16 item_head_crc; + u32 len; + u16 item_count; + u16 rfu; + u8 name[16]; +} cfg_head_t; + +typedef enum _cfg_err_type_t { + CFG_ERR_NONE = 0, + CFG_ERR_FILE_INDEX_ERR, + CFG_ERR_FILE_SEEK_ERR, + CFG_ERR_FILE_READ_ERR, + CFG_ERR_ITEM_LEN_OVER, + CFG_ERR_ITEM_NO_FOUND, +} cfg_err_type_t; + +typedef struct _cfg_item_description { + u8 *item_name; + u8 *item_data; + u16 item_len; + u16 *real_len; +} cfg_item_description_t; + +typedef struct _update_file_id_cfg { + u16 len; + update_file_id_t data; +} update_file_id_cfg_t; + +static update_file_id_cfg_t update_id_cfg = { + .len = 0, +}; + +typedef struct _update_file_reset_io_cfg { + u16 len; + update_file_reset_io_t data; +} update_file_reset_io_cfg_t; + +static update_file_reset_io_cfg_t update_reset_io_cfg = { + .len = 0, +}; + +typedef struct _update_file_pilot_lamp_io_cfg { + u16 len; + update_file_pilot_lamp_io_t data; +} update_file_pilot_lamp_io_cfg_t; + +static update_file_pilot_lamp_io_cfg_t update_pilot_lamp_io_cfg = { + .len = 0, +}; + +typedef struct _update_file_link_key_cfg { + u16 len; + update_file_link_key_t data; +} update_file_link_key_cfg_t; + +static update_file_link_key_cfg_t update_link_cfg = { + .len = 0, +}; + +typedef struct _update_file_power_io_on_off_cfg { + u16 len; + u8 data[16]; +} update_file_power_io_on_off_cfg_t; + +static update_file_power_io_on_off_cfg_t update_power_io_on_off_cfg = { + .len = 0, +}; + +#if VER_INFO_EXT_COUNT +typedef struct _update_file_ver_info_ext_cfg { + u16 len; + u8 data[VER_INFO_EXT_COUNT * (VER_INFO_EXT_MAX_LEN + 1)]; // authkey + , + procode + '\0' +} update_file_ver_info_ext_cfg_t; + +static update_file_ver_info_ext_cfg_t update_file_ver_info_ext_cfg = { + .len = 0, +}; +#endif + +static const cfg_item_description_t cfg_item_description[] = { + [0] = { + (u8 *)"ver_info", (u8 *) &update_id_cfg.data, sizeof(update_id_cfg.data), &update_id_cfg.len + }, + [1] = { + (u8 *)"reset_io", (u8 *) &update_reset_io_cfg.data, sizeof(update_reset_io_cfg.data), &update_reset_io_cfg.len + }, + [2] = { + (u8 *)"pilot_lamp_io", (u8 *) &update_pilot_lamp_io_cfg.data, sizeof(update_pilot_lamp_io_cfg.data), &update_pilot_lamp_io_cfg.len + }, + [3] = { + (u8 *)"link_key", (u8 *) &update_link_cfg.data, sizeof(update_link_cfg.data), &update_link_cfg.len + }, + [4] = { + (u8 *)"power_io", (u8 *) &update_power_io_on_off_cfg.data, sizeof(update_power_io_on_off_cfg.data), &update_power_io_on_off_cfg.len + }, +#if VER_INFO_EXT_COUNT + [5] = { + (u8 *)"ver_info_ext", (u8 *) &update_file_ver_info_ext_cfg.data, sizeof(update_file_ver_info_ext_cfg.data), &update_file_ver_info_ext_cfg.len + }, +#endif +}; + +typedef enum _FLASH_ERASER { + CHIP_ERASER, + BLOCK_ERASER, + SECTOR_ERASER, +} FLASH_ERASER; +#if (USE_VM_API_SEL == VM_API_AC692X) +#include "flash_api.h" +#elif (USE_VM_API_SEL == VM_API_AC693X) +extern bool sfc_erase(FLASH_ERASER cmd, u32 addr); +extern u32 sfc_write(const u8 *buf, u32 addr, u32 len); +extern u32 sfc_read(u8 *buf, u32 addr, u32 len); +static void vm_read_by_addr(u8 *buf, u32 addr, u32 len) +{ + sfc_read(buf, addr, len); +} + +static u32 vm_write_by_addr(u8 *buf, u32 addr, u32 len) +{ + return sfc_write(buf, addr, len); +} + +#endif + + + +extern u32 fs_open_file_bypath_offest(void *dev_hdl, void *buf, u16 len, char *path, u32 offset); + +u32 get_cfg_data_connect_by_name(u8 *name, u8 *data, u16 len, u16 *real_len) +{ + cfg_item_head_t cfg_item_head; + cfg_head_t cfg_head; + u32 err = CFG_ERR_NONE; + u32 r_len; + u16 i; + *real_len = 0; + u32 offset = 0; + +#if (USE_FS_API_SEL == SDFILE_API_AC692X) + DEV_HANDLE dev = cache; + u32 file_err; + file_err = fs_open_file_bypath_offest(dev, &cfg_head, sizeof(cfg_head_t), RES_CUSTOM_CFG_FILE, offset); + if (0 == file_err) { + err = CFG_ERR_FILE_READ_ERR; + goto _ERR_RET; + } +#elif (USE_FS_API_SEL == SDFILE_API_AC693X) + FILE *fp = NULL; + fp = fopen(RES_CUSTOM_CFG_FILE, "r"); + if (!fp) { + cfg_puts("file open fail"); + err = CFG_ERR_FILE_READ_ERR; + goto _ERR_RET; + } + r_len = fread(fp, (void *)&cfg_head, sizeof(cfg_head_t)); + if (r_len != sizeof(cfg_head_t)) { + cfg_puts("file read cfg head fail\n"); + err = CFG_ERR_FILE_READ_ERR; + goto _ERR_RET; + } +#endif + + offset += sizeof(cfg_head_t); + cfg_printf("read file req_len:%x ret_len:%x\n", sizeof(cfg_head_t), cfg_head.len); + cfg_puts("cfg_head:\n"); + cfg_printf_buf((u8 *)&cfg_head, sizeof(cfg_head_t)); + + for (i = 0; i < cfg_head.item_count; i++) { +#if (USE_FS_API_SEL == SDFILE_API_AC692X) + file_err = fs_open_file_bypath_offest(dev, &cfg_item_head, sizeof(cfg_item_head_t), RES_CUSTOM_CFG_FILE, offset); +#elif (USE_FS_API_SEL == SDFILE_API_AC693X) + fseek(fp, SEEK_SET, offset); + r_len = fread(fp, (void *)&cfg_item_head, sizeof(cfg_item_head_t)); + if (r_len != sizeof(cfg_item_head_t)) { + cfg_puts("file read cfg item head fail\n"); + err = CFG_ERR_FILE_READ_ERR; + goto _ERR_RET; + } +#endif + offset += sizeof(cfg_item_head_t); + if (0 == memcmp(cfg_item_head.name, name, strlen((const char *)name))) { + cfg_printf("find item %d name:%s\n", i, cfg_item_head.name); + cfg_printf_buf((u8 *)&cfg_item_head, sizeof(cfg_item_head_t)); + offset = cfg_item_head.addr; + if (len < cfg_item_head.len) { + err = CFG_ERR_ITEM_LEN_OVER; + break; + } + *real_len = cfg_item_head.len; +#if (USE_FS_API_SEL == SDFILE_API_AC692X) + fs_open_file_bypath_offest(dev, data, cfg_item_head.len, RES_CUSTOM_CFG_FILE, offset); +#elif (USE_FS_API_SEL == SDFILE_API_AC693X) + fseek(fp, offset, SEEK_SET); + r_len = fread(fp, data, cfg_item_head.len); + if (r_len != cfg_item_head.len) { + cfg_puts("read cfg item content fail\n"); + err = CFG_ERR_FILE_READ_ERR; + goto _ERR_RET; + } +#endif + break; + } + } + + if (i == cfg_head.item_count) { + err = CFG_ERR_ITEM_NO_FOUND; + } + +_ERR_RET: + return err; +} + +void ex_cfg_read_flash_by_addr(u8 *buf, u32 addr, u32 len) +{ + vm_read_by_addr(buf, exif_info.addr + addr, len); +} + +extern u16 CRC16(const void *ptr, u32 len); +static u16 crc16(u8 *buf, u16 len) +{ + return CRC16(buf, len); +} + +typedef struct _cfg_item_attr_t { + u16 item_len; + u16 data_len; + u16 member_offset; +} cfg_item_attr_t; + +static const cfg_item_attr_t cfg_item_attr_tab[] = { + [CFG_ITEM_ADV_IND] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, adv_data_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, adv_data_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, adv_data_cfg), + }, + [CFG_ITEM_SCAN_RSP] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, scan_rsp_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, scan_rsp_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, scan_rsp_cfg), + }, + [CFG_ITEM_BLE_NAME] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, ble_name_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, ble_name_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, ble_name_cfg), + }, + [CFG_ITEM_BT_NAME] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, bt_name_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, bt_name_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, bt_name_cfg), + }, + [CFG_ITEM_PIN_CODE] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, pin_code_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, pin_code_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, pin_code_cfg), + }, + [CFG_ITEM_VER_INFO] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, ver_info_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, ver_info_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, ver_info_cfg), + }, + [CFG_ITEM_LOW_POWER_VOLTAGE] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, low_power_voltage_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, low_power_voltage_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, low_power_voltage_cfg), + }, + [CFG_ITEM_EDR_ADDR] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, edr_addr_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, edr_addr_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, edr_addr_cfg), + }, + [CFG_ITEM_BLE_ADDR] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, ble_addr_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, ble_addr_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, ble_addr_cfg), + }, + [CFG_ITEM_GATT_PROFILE] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, gatt_profile_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, gatt_profile_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, gatt_profile_cfg), + }, + [CFG_ITEM_RESET_IO_INFO] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, reset_io_info_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, reset_io_info_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, reset_io_info_cfg), + }, + [CFG_ITEM_PILOT_LAMP_IO_INFO] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, pilot_lamp_io_info_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, pilot_lamp_io_info_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, pilot_lamp_io_info_cfg), + }, + [CFG_ITEM_LINK_KEY_INFO] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, link_key_info_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, link_key_info_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, link_key_info_cfg), + }, + [CFG_ITEM_POWER_IO_ON_OFF] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, power_io_on_off_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, power_io_on_off_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, power_io_on_off_cfg), + }, + [CFG_ITEM_LAST_DEVICE_LINK_KEY_INFO] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, last_device_connect_linkkey_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, last_device_connect_linkkey_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, last_device_connect_linkkey_cfg), + }, + [CFG_ITEM_BLE_READ_WRITE_UUID_INFO] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, ble_read_write_uuid_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, ble_read_write_uuid_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, ble_read_write_uuid_cfg), + }, +#if VER_INFO_EXT_COUNT + [CFG_ITEM_VER_INFO_AUTHKEY] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, ver_info_authkey_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, ver_info_authkey_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, ver_info_authkey_cfg), + }, + [CFG_ITEM_VER_INFO_PROCODE] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, ver_info_procode_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, ver_info_procode_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, ver_info_procode_cfg), + }, +#endif + [CFG_ITEM_PVID] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, pid_vid_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, pid_vid_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, pid_vid_cfg), + }, + [CFG_ITEM_MD5] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, md5_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, md5_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, md5_cfg), + }, + [CFG_ITEM_SDK_TYPE] = { + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, sdk_type_cfg), + MEMBER_SIZE_OF_STRUCT(ex_cfg_t, sdk_type_cfg.data), + MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, sdk_type_cfg), + } +}; + +static u32 custom_cfg_item_change_check(u8 type, u8 *new_data, u16 new_data_len, u8 *write_flag) +{ + ex_cfg_item_u item_u; + u16 item_len = 0; + ex_cfg_t *p_ex_cfg = NULL; + u32 item_offset = 0; + u32 exif_addr = exif_info.addr; + + u32 err = 0; + + if (type > sizeof(cfg_item_attr_tab) / sizeof(cfg_item_attr_tab[0])) { + err = -2; + goto _ERR_RET; + } + + u32 data_len = cfg_item_attr_tab[type].data_len; + + if (item_len < new_data_len) { + err = -1; + goto _ERR_RET; + } + + item_len = cfg_item_attr_tab[type].item_len; + item_offset = cfg_item_attr_tab[type].member_offset; + + vm_read_by_addr((u8 *)&item_u.common_cfg, exif_addr + item_offset, item_len); + + if ((item_u.common_cfg.len == new_data_len) && \ + (0 == memcmp((u8 *)&item_u.common_cfg.data, new_data, new_data_len))) { + *write_flag = 0; + } else { + *write_flag = 1; + } + +#if 0 + switch (type) { + case CFG_ITEM_ADV_IND: + item_len = sizeof(p_ex_cfg->adv_data_cfg.data); + if (item_len < new_data_len) { + err = -1; + goto _ERR_RET; + } + item_offset = MEMBER_OFFSET_OF_STRUCT(ex_cfg_t, adv_data_cfg); + vm_read_by_addr((u8 *)&item_u.adv_data_cfg, exif_addr + item_offset, sizeof(adv_data_cfg_t)); + if ((item_u.adv_data_cfg.len == new_data_len) && \ + (0 == memcmp((u8 *)&item_u.adv_data_cfg.data, new_data, new_data_len))) { + *write_flag = 0; + } else { + *write_flag = 1; + } + break; + case CFG + } +#endif + _ERR_RET: + return err; +} +static u32 custom_cfg_item_write(u8 type, u8 *data, u16 data_len) +{ + ex_cfg_item_u item_u; + u16 item_len = 0; + ex_cfg_t *p_ex_cfg = NULL; + u32 item_offset = 0; + u32 exif_addr = exif_info.addr; + + u32 err = 0; + + if (type > sizeof(cfg_item_attr_tab) / sizeof(cfg_item_attr_tab[0])) { + err = -2; + goto _ERR_RET; + } + + u32 item_data_len = cfg_item_attr_tab[type].data_len; + + if (item_data_len < data_len) { + err = -1; + goto _ERR_RET; + } + + item_len = cfg_item_attr_tab[type].item_len; + item_offset = cfg_item_attr_tab[type].member_offset; + + vm_read_by_addr((u8 *)&item_u.common_cfg, exif_addr + item_offset, item_len); + if ((0xffff != item_u.common_cfg.crc) && \ + (0xffff != item_u.common_cfg.len)) { + err = -3; + goto _ERR_RET; + } +#if 0 + vm_read_by_addr((u8 *)&item_u.common_cfg, exif_addr + item_offset, item_len); + + if ((item_u.common_cfg.len == new_data_len) && \ + (0 == memcmp((u8 *)&item_u.common_cfg.data, new_data, new_data_len))) { + *write_flag = 0; + } else { + *write_flag = 1; + } +#else + memset((u8 *)&item_u.common_cfg.data, 0x00, item_data_len); + memcpy((u8 *)&item_u.common_cfg.data, data, data_len); + item_u.common_cfg.len = data_len; + item_u.common_cfg.crc = crc16((u8 *)&item_u.common_cfg.data, data_len); + + vm_write_by_addr((u8 *)&item_u.common_cfg, exif_addr + item_offset, item_len); +#endif + +_ERR_RET: + cfg_printf(">>>write item:%x err:%x\n", type, err); + return err; +} + +static u32 custom_cfg_fill(ex_cfg_t *user_ex_cfg, u8 *data, u16 data_len, u8 type, u8 *write_flag) +{ + u16 len = 0; + switch (type) { + case CFG_ITEM_ADV_IND: + len = sizeof(user_ex_cfg->adv_data_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->adv_data_cfg.data, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->adv_data_cfg.data, data, len); + user_ex_cfg->adv_data_cfg.len = len; + user_ex_cfg->adv_data_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->adv_data_cfg.data, data, len); + user_ex_cfg->adv_data_cfg.len = len; + user_ex_cfg->adv_data_cfg.crc = crc16(data, len); + } + break; + case CFG_ITEM_SCAN_RSP: + len = sizeof(user_ex_cfg->scan_rsp_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->scan_rsp_cfg.data, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->scan_rsp_cfg.data, data, len); + user_ex_cfg->scan_rsp_cfg.len = len; + user_ex_cfg->scan_rsp_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->scan_rsp_cfg.data, data, len); + user_ex_cfg->scan_rsp_cfg.len = len; + user_ex_cfg->scan_rsp_cfg.crc = crc16(data, len); + } + break; + case CFG_ITEM_BLE_NAME: + len = sizeof(user_ex_cfg->ble_name_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->ble_name_cfg.data, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->ble_name_cfg.data, data, len); + user_ex_cfg->ble_name_cfg.len = len; + user_ex_cfg->ble_name_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->ble_name_cfg.data, data, len); + user_ex_cfg->ble_name_cfg.len = len; + user_ex_cfg->ble_name_cfg.crc = crc16(data, len); + } + break; + case CFG_ITEM_BT_NAME: + len = sizeof(user_ex_cfg->bt_name_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->bt_name_cfg.data, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->bt_name_cfg.data, data, len); + user_ex_cfg->bt_name_cfg.len = len; + user_ex_cfg->bt_name_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->bt_name_cfg.data, data, len); + user_ex_cfg->bt_name_cfg.len = len; + user_ex_cfg->bt_name_cfg.crc = crc16(data, len); + } + break; + case CFG_ITEM_PIN_CODE: + len = sizeof(user_ex_cfg->pin_code_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->pin_code_cfg.data, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->pin_code_cfg.data, data, len); + user_ex_cfg->pin_code_cfg.len = len; + user_ex_cfg->pin_code_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->pin_code_cfg.data, data, len); + user_ex_cfg->pin_code_cfg.len = len; + user_ex_cfg->pin_code_cfg.crc = crc16(data, len); + } + break; + case CFG_ITEM_VER_INFO: + len = sizeof(user_ex_cfg->ver_info_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp((u8 *)&user_ex_cfg->ver_info_cfg.data, data, len)) { + *write_flag = 1; + memcpy((u8 *)&user_ex_cfg->ver_info_cfg.data, data, len); + user_ex_cfg->ver_info_cfg.len = len; + user_ex_cfg->ver_info_cfg.crc = crc16(data, len); + } + } else { + memcpy((u8 *)&user_ex_cfg->ver_info_cfg.data, data, len); + user_ex_cfg->ver_info_cfg.len = len; + user_ex_cfg->ver_info_cfg.crc = crc16(data, len); + } + break; + case CFG_ITEM_RESET_IO_INFO: + len = sizeof(user_ex_cfg->reset_io_info_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp((u8 *)&user_ex_cfg->reset_io_info_cfg.data, data, len)) { + *write_flag = 1; + memcpy((u8 *)&user_ex_cfg->reset_io_info_cfg.data, data, len); + user_ex_cfg->reset_io_info_cfg.len = len; + user_ex_cfg->reset_io_info_cfg.crc = crc16(data, len); + } + } else { + memcpy((u8 *)&user_ex_cfg->reset_io_info_cfg.data, data, len); + user_ex_cfg->reset_io_info_cfg.len = len; + user_ex_cfg->reset_io_info_cfg.crc = crc16(data, len); + } + break; + case CFG_ITEM_PILOT_LAMP_IO_INFO: + len = sizeof(user_ex_cfg->pilot_lamp_io_info_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->pilot_lamp_io_info_cfg.data, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->pilot_lamp_io_info_cfg.data, data, len); + user_ex_cfg->pilot_lamp_io_info_cfg.len = len; + user_ex_cfg->pilot_lamp_io_info_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->pilot_lamp_io_info_cfg.data, data, len); + user_ex_cfg->pilot_lamp_io_info_cfg.len = len; + user_ex_cfg->pilot_lamp_io_info_cfg.crc = crc16(data, len); + } + break; + case CFG_ITEM_POWER_IO_ON_OFF: + len = sizeof(user_ex_cfg->power_io_on_off_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->power_io_on_off_cfg.data, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->power_io_on_off_cfg.data, data, len); + user_ex_cfg->power_io_on_off_cfg.len = len; + user_ex_cfg->power_io_on_off_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->power_io_on_off_cfg.data, data, len); + user_ex_cfg->power_io_on_off_cfg.len = len; + user_ex_cfg->power_io_on_off_cfg.crc = crc16(data, len); + } + break; + case CFG_ITEM_LINK_KEY_INFO: + len = sizeof(user_ex_cfg->link_key_info_cfg.data.link_key); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->link_key_info_cfg.data.link_key, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->link_key_info_cfg.data.link_key, data, len); + user_ex_cfg->link_key_info_cfg.len = len; + user_ex_cfg->link_key_info_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->link_key_info_cfg.data.link_key, data, len); + user_ex_cfg->link_key_info_cfg.len = len; + user_ex_cfg->link_key_info_cfg.crc = crc16(data, len); + } + break; + case CFG_ITEM_LAST_DEVICE_LINK_KEY_INFO: + len = sizeof(user_ex_cfg->last_device_connect_linkkey_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->last_device_connect_linkkey_cfg.data, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->last_device_connect_linkkey_cfg.data, data, len); + user_ex_cfg->last_device_connect_linkkey_cfg.len = len; + user_ex_cfg->last_device_connect_linkkey_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->last_device_connect_linkkey_cfg.data, data, len); + user_ex_cfg->last_device_connect_linkkey_cfg.len = len; + user_ex_cfg->last_device_connect_linkkey_cfg.crc = crc16(data, len); + } + break; + case CFG_ITEM_LOW_POWER_VOLTAGE: + len = sizeof(user_ex_cfg->low_power_voltage_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->low_power_voltage_cfg.data, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->low_power_voltage_cfg.data, data, len); + user_ex_cfg->low_power_voltage_cfg.len = len; + user_ex_cfg->low_power_voltage_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->low_power_voltage_cfg.data, data, len); + user_ex_cfg->low_power_voltage_cfg.len = len; + user_ex_cfg->low_power_voltage_cfg.crc = crc16(data, len); + } + break; + case CFG_ITEM_EDR_ADDR: + len = sizeof(user_ex_cfg->edr_addr_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->edr_addr_cfg.data, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->edr_addr_cfg.data, data, len); + user_ex_cfg->edr_addr_cfg.len = len; + user_ex_cfg->edr_addr_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->edr_addr_cfg.data, data, len); + user_ex_cfg->edr_addr_cfg.len = len; + user_ex_cfg->edr_addr_cfg.crc = crc16(data, len); + } + break; + case CFG_ITEM_BLE_ADDR: + len = sizeof(user_ex_cfg->ble_addr_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->ble_addr_cfg.data, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->ble_addr_cfg.data, data, len); + user_ex_cfg->ble_addr_cfg.len = len; + user_ex_cfg->ble_addr_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->ble_addr_cfg.data, data, len); + user_ex_cfg->ble_addr_cfg.len = len; + user_ex_cfg->ble_addr_cfg.crc = crc16(data, len); + } + break; + case CFG_ITEM_GATT_PROFILE: + len = sizeof(user_ex_cfg->gatt_profile_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->gatt_profile_cfg.data, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->gatt_profile_cfg.data, data, len); + user_ex_cfg->gatt_profile_cfg.len = len; + user_ex_cfg->gatt_profile_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->gatt_profile_cfg.data, data, len); + user_ex_cfg->gatt_profile_cfg.len = len; + user_ex_cfg->gatt_profile_cfg.crc = crc16(data, len); + } + break; +#if VER_INFO_EXT_COUNT + case CFG_ITEM_VER_INFO_AUTHKEY: + len = sizeof(user_ex_cfg->ver_info_authkey_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->ver_info_authkey_cfg.data, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->ver_info_authkey_cfg.data, data, len); + user_ex_cfg->ver_info_authkey_cfg.len = len; + user_ex_cfg->ver_info_authkey_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->ver_info_authkey_cfg.data, data, len); + user_ex_cfg->ver_info_authkey_cfg.len = len; + user_ex_cfg->ver_info_authkey_cfg.crc = crc16(data, len); + } + break; + case CFG_ITEM_VER_INFO_PROCODE: + len = sizeof(user_ex_cfg->ver_info_procode_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->ver_info_procode_cfg.data, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->ver_info_procode_cfg.data, data, len); + user_ex_cfg->ver_info_procode_cfg.len = len; + user_ex_cfg->ver_info_procode_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->ver_info_procode_cfg.data, data, len); + user_ex_cfg->ver_info_procode_cfg.len = len; + user_ex_cfg->ver_info_procode_cfg.crc = crc16(data, len); + } + break; +#endif + case CFG_ITEM_BLE_READ_WRITE_UUID_INFO: + len = sizeof(user_ex_cfg->ble_read_write_uuid_cfg.data); + len = len > data_len ? data_len : len; + if (!(*write_flag)) { + if (memcmp(user_ex_cfg->ble_read_write_uuid_cfg.data, data, len)) { + *write_flag = 1; + memcpy(user_ex_cfg->ble_read_write_uuid_cfg.data, data, len); + user_ex_cfg->ble_read_write_uuid_cfg.len = len; + user_ex_cfg->ble_read_write_uuid_cfg.crc = crc16(data, len); + } + } else { + memcpy(user_ex_cfg->ble_read_write_uuid_cfg.data, data, len); + user_ex_cfg->ble_read_write_uuid_cfg.len = len; + user_ex_cfg->ble_read_write_uuid_cfg.crc = crc16(data, len); + } + break; + } + return 0; +} +#if VER_INFO_EXT_COUNT +static u32 fill_authkey_procode(ex_cfg_t *user_ex_cfg, u8 *item_data, u16 item_len, u8 *write_flag) +{ + if (!item_len) { + return 0; + } + u16 i = 0; + u16 index = 0; + u8 type = CFG_ITEM_VER_INFO_AUTHKEY; + u8 separator = ','; + for (; i < item_len && type < CFG_ITEM_VER_INFO_AUTHKEY + VER_INFO_EXT_COUNT; i++) { + if (separator == item_data[i]) { + custom_cfg_item_write(type, item_data + index, i - index); + index = i + 1; + type++; + } else if (i == item_len - 1) { + custom_cfg_item_write(type, item_data + index, item_len - index); + } + } + return 0; +} +#endif + +static u32 custom_cfg_file_fill(ex_cfg_t *user_ex_cfg, u8 *write_flag) +{ + u32 err; + u16 i; + u8 *item_data; + u8 *item_name; + u16 item_len; + for (i = 0 ; i < sizeof(cfg_item_description) / sizeof(cfg_item_description[0]); i++) { + err = get_cfg_data_connect_by_name(cfg_item_description[i].item_name, \ + cfg_item_description[i].item_data, \ + cfg_item_description[i].item_len, \ + cfg_item_description[i].real_len); + if (CFG_ERR_NONE != err) { + cfg_printf("cfg_item:%d read error:%x\n", i, err); + } else { + cfg_printf("cfg_name %s\n cfg_len%x\n", cfg_item_description[i].item_name, *(cfg_item_description[i].real_len)); + cfg_printf_buf((u8 *)cfg_item_description[i].item_data, *(cfg_item_description[i].real_len)); + } + if (cfg_item_description[i].real_len != 0) { + item_name = cfg_item_description[i].item_name; + item_data = cfg_item_description[i].item_data; + item_len = *cfg_item_description[i].real_len; + if (0 == strcmp((const char *)item_name, "ver_info")) { + custom_cfg_item_write(CFG_ITEM_VER_INFO, item_data, item_len); + } else if (0 == strcmp((const char *)item_name, "reset_io")) { + custom_cfg_item_write(CFG_ITEM_RESET_IO_INFO, item_data, item_len); + } else if (0 == strcmp((const char *)item_name, "pilot_lamp_io")) { + custom_cfg_item_write(CFG_ITEM_PILOT_LAMP_IO_INFO, item_data, item_len); + } else if (0 == strcmp((const char *)item_name, "link_key")) { + custom_cfg_item_write(CFG_ITEM_LINK_KEY_INFO, item_data, item_len); + } else if (0 == strcmp((const char *)item_name, "power_io")) { + custom_cfg_item_write(CFG_ITEM_POWER_IO_ON_OFF, item_data, item_len); + } else if (0 == strcmp((const char *)item_name, "ver_info_ext")) { +#if VER_INFO_EXT_COUNT + custom_cfg_item_write(CFG_ITEM_VER_INFO, item_data, item_len); +#endif + } + } + } + return err; +} + + + +extern int ble_at_get_address(u8 *addr); +//extern char *hook_get_host_name(void); +extern const char *bt_get_local_name(); +extern const u8 *bt_get_mac_addr(); +//extern char *hook_get_pin_code(void); +extern const char *bt_get_pin_code(); +//extern void hook_get_mac_addr(u8 *btaddr); +extern u8 *ble_get_scan_rsp_ptr(u8 *len); +extern u8 *ble_get_adv_data_ptr(u8 *len); +extern int le_controller_get_mac(void *addr); +extern u8 *ble_get_gatt_profile_data(u16 *len); +extern const char *bt_get_local_name(); +extern u8 *get_last_device_connect_linkkey(u16 *len); + +static u32 ex_cfg_fill_content(ex_cfg_t *user_ex_cfg, u8 *write_flag) +{ + custom_cfg_file_fill(NULL, write_flag); + + //CFG_ITEM_BT_NAME + u8 *host_name = (u8 *)bt_get_local_name(); + u16 host_name_len = strlen(bt_get_local_name()); + custom_cfg_item_write(CFG_ITEM_BT_NAME, host_name, host_name_len); + + //CFG_ITEM_EDR_ADDR + u8 addr[6]; + //hook_get_mac_addr(addr); + custom_cfg_item_write(CFG_ITEM_EDR_ADDR, bt_get_mac_addr(), sizeof(addr)); + + //CFG_ITEM_PIN_CODE +#if (0 == BT_CONNECTION_VERIFY) + u8 pin_code[] = {BT_CONNECTION_VERIFY, VER_INFO_EXT_COUNT, 0, 0}; + u16 pin_code_len = sizeof(pin_code); +#else + u8 *pin_code = (u8 *)bt_get_pin_code(); + u16 pin_code_len = strlen(bt_get_pin_code()); +#endif + custom_cfg_item_write(CFG_ITEM_PIN_CODE, pin_code, pin_code_len); + + //CFG_ITEM_BLE_ADDR + le_controller_get_mac(addr); + custom_cfg_item_write(CFG_ITEM_BLE_ADDR, addr, sizeof(addr)); + + //CFG_ITEM_BLE_NAME + host_name = bt_get_local_name(); + host_name_len = strlen(bt_get_local_name()); + custom_cfg_item_write(CFG_ITEM_BLE_NAME, host_name, host_name_len); + + //CFG_ITEM_SCAN_RSP + u16 len; + u8 *item_data = ble_get_scan_rsp_ptr(&len); + custom_cfg_item_write(CFG_ITEM_SCAN_RSP, item_data, len); + + //CFG_ITEM_ADV_IND + item_data = ble_get_adv_data_ptr(&len); + custom_cfg_item_write(CFG_ITEM_ADV_IND, item_data, len); + + //CFG_ITEM_GATT_PROFILE + item_data = ble_get_gatt_profile_data(&len); + custom_cfg_item_write(CFG_ITEM_GATT_PROFILE, item_data, len); + + + //CFG_ITEM_LAST_DEVICE_LINK_KEY_INFO + item_data = get_last_device_connect_linkkey(&len); + put_buf(item_data, len); + custom_cfg_item_write(CFG_ITEM_LAST_DEVICE_LINK_KEY_INFO, item_data, len); + +#if VER_INFO_EXT_COUNT + u8 authkey_len = 0; + u8 *local_authkey_data = NULL; + get_authkey_procode_from_cfg_file(&local_authkey_data, &authkey_len, GET_AUTH_KEY_FROM_EX_CFG); + custom_cfg_item_write(CFG_ITEM_VER_INFO_AUTHKEY, local_authkey_data, authkey_len); + + u8 procode_len = 0; + u8 *local_procode_data = NULL; + get_authkey_procode_from_cfg_file(&local_procode_data, &procode_len, GET_PRO_CODE_FROM_EX_CFG); + + custom_cfg_item_write(CFG_ITEM_VER_INFO_PROCODE, local_procode_data, procode_len); +#endif + + u16 pvid[2] = {0}; + pvid[0] = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG); + pvid[1] = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG); + + custom_cfg_item_write(CFG_ITEM_PVID, pvid, sizeof(pvid)); + + u8 md5[32] = {0}; + FILE *fp = NULL; +#define RES_MD5_FILE SDFILE_RES_ROOT_PATH"md5.bin" + fp = fopen(RES_MD5_FILE, "r"); + if (fp) { + fread(fp, (void *)md5, 32); + fclose(fp); + } + custom_cfg_item_write(CFG_ITEM_MD5, md5, sizeof(md5)); + u8 sdk_type = 0; +#if RCSP_ADV_EN || RCSP_BTMATE_EN + sdk_type = RCSP_SDK_TYPE; +#endif + custom_cfg_item_write(CFG_ITEM_SDK_TYPE, &sdk_type, sizeof(sdk_type)); + return 0; +} + +#define TEMP_BUF_LEN 0x20 +static void ex_cfg_write_to_flash(ex_cfg_t *user_ex_cfg) +{ + u32 exif_addr = exif_info.addr; + u32 exif_len = exif_info.len; + u8 empty_flag = 1; + u8 temp_buf[TEMP_BUF_LEN]; + u16 i; + + cfg_printf("exif_addr : 0x%x, exif_len : %d\n", exif_addr, exif_len); + + if (sizeof(ex_cfg_t) > exif_len) { + cfg_printf("-EX_CFG_TOO_LONG:%x\n", sizeof(ex_cfg_t)); + return ; + } + + u16 total_len = sizeof(ex_cfg_t); + u16 read_len = sizeof(temp_buf); + + while (total_len) { + u16 len = total_len > read_len ? read_len : total_len; + vm_read_by_addr(temp_buf, exif_addr, len); + + for (i = 0; i < sizeof(temp_buf); i++) { + if (temp_buf[i] != 0xff) { + empty_flag = 0; + } + } + total_len -= len; + exif_addr += len; + } + + if (empty_flag) { + cfg_puts("EX_CFG_AREA EMPTY\n"); + } else { + cfg_puts("EX_CFG_HAD_DATA\n"); + return; + } + vm_write_by_addr((u8 *)user_ex_cfg, exif_addr, sizeof(ex_cfg_t)); +} + +#define PRINT_EX_CFG_INFO 0 +static void print_user_ex_cfg_info(ex_cfg_t *user_ex_cfg); +#define EXIF_CFG_PATH SDFILE_APP_ROOT_PATH"exif" +__attribute__((noinline)) +static void ex_cfg_get_addr_and_len(u32 *addr, u32 *len) +{ + FILE *fp = fopen(EXIF_CFG_PATH, "r"); + if (fp) { + cfg_printf("open %s succ", EXIF_CFG_PATH); + struct vfs_attr attr = {0}; + fget_attrs(fp, &attr); + + extern u32 sdfile_cpu_addr2flash_addr(u32 offset); + *addr = sdfile_cpu_addr2flash_addr(attr.sclust); + *len = attr.fsize; + } else { + + cfg_printf("open %s fail", EXIF_CFG_PATH); + *addr = 0; + *len = 0; + } + + cfg_printf(">>>exif addr:%x len:%x\n", *addr, *len); +} + +u32 ex_cfg_get_start_addr(void) +{ + u32 start_addr; + FILE *fp = fopen(EXIF_CFG_PATH, "r"); + if (fp) { + cfg_printf("open %s succ", EXIF_CFG_PATH); + struct vfs_attr attr = {0}; + fget_attrs(fp, &attr); + + extern u32 sdfile_cpu_addr2flash_addr(u32 offset); + start_addr = sdfile_cpu_addr2flash_addr(attr.sclust); + } else { + + cfg_printf("open %s fail", EXIF_CFG_PATH); + start_addr = 0; + } + + return start_addr; +} + +#define SECOTR_SIZE (4*1024L) +u32 ex_cfg_fill_content_api(void) +{ + ex_cfg_get_addr_and_len(&exif_info.addr, &exif_info.len); + + if (exif_info.addr) { + //ex_cfg_read_flash_by_addr((u8 *)&user_ex_cfg, 0, sizeof(ex_cfg_t)); +#if (EXIF_ERASE_CONFIG == ALWAYS_ERASE_EXIF_AREA) + if (exif_info.len < SECOTR_SIZE) { + puts("exif len less SECOTR_SiZE\n"); + while (1); + } + + sfc_erase(SECTOR_ERASER, exif_info.addr); +#else +#error "To do ..." +#endif + + ex_cfg_fill_content(NULL, NULL); + } + + return exif_info.addr; +} +u32 ex_cfg_fill_content_api_test(void) +{ + return 0; +} + + +static void print_user_ex_cfg_info(ex_cfg_t *user_ex_cfg) +{ +#if PRINT_EX_CFG_INFO + puts("adv_data_cfg:\n"); + printf_buf(user_ex_cfg->adv_data_cfg.data, user_ex_cfg->adv_data_cfg.len); + puts("scan_rsp_cfg:\n"); + printf_buf(user_ex_cfg->scan_rsp_cfg.data, user_ex_cfg->scan_rsp_cfg.len); + puts("ble_name_cfg:\n"); + printf_buf(user_ex_cfg->ble_name_cfg.data, user_ex_cfg->ble_name_cfg.len); + puts("ble_addr_cfg:\n"); + printf_buf(user_ex_cfg->ble_addr_cfg.data, user_ex_cfg->ble_addr_cfg.len); + puts("bt_name_cfg:\n"); + printf_buf(user_ex_cfg->bt_name_cfg.data, user_ex_cfg->bt_name_cfg.len); + puts("pin_code_cfg:\n"); + printf_buf((u8 *)user_ex_cfg->pin_code_cfg.data, user_ex_cfg->pin_code_cfg.len); + puts("ver_info_cfg:\n"); + printf_buf((u8 *)&user_ex_cfg->ver_info_cfg.data, user_ex_cfg->ver_info_cfg.len); + puts("reset_io_info_cfg:\n"); + printf_buf((u8 *)&user_ex_cfg->reset_io_info_cfg.data, user_ex_cfg->reset_io_info_cfg.len); + puts("pilot_lamp_io_info_cfg:\n"); + printf_buf(user_ex_cfg->pilot_lamp_io_info_cfg.data, user_ex_cfg->pilot_lamp_io_info_cfg.len); + puts("power_io_on_off_cfg:\n"); + printf_buf(user_ex_cfg->power_io_on_off_cfg.data, user_ex_cfg->power_io_on_off_cfg.len); + puts("link_key_info_cfg:\n"); + printf_buf(user_ex_cfg->link_key_info_cfg.data.link_key, user_ex_cfg->link_key_info_cfg.len); + puts("last_device_connect_linkkey_cfg:\n"); + printf_buf(user_ex_cfg->last_device_connect_linkkey_cfg.data, user_ex_cfg->last_device_connect_linkkey_cfg.len); + puts("ver_info_authkey_cfg:\n"); + printf("len is %x\n", user_ex_cfg->ver_info_authkey_cfg.len); + if (0xffff != user_ex_cfg->ver_info_authkey_cfg.len) { + printf_buf(user_ex_cfg->ver_info_authkey_cfg.data, user_ex_cfg->ver_info_authkey_cfg.len); + } + puts("ver_info_procode_cfg:\n"); + printf("len is %x\n", user_ex_cfg->ver_info_procode_cfg.len); + if (0xffff != user_ex_cfg->ver_info_procode_cfg.len) { + printf_buf(user_ex_cfg->ver_info_procode_cfg.data, user_ex_cfg->ver_info_procode_cfg.len); + } + puts("ble_read_write_uuid_cfg:\n"); + printf("len is %x\n", user_ex_cfg->ble_read_write_uuid_cfg.len); + if (0xffff != user_ex_cfg->ble_read_write_uuid_cfg.len) { + printf_buf(user_ex_cfg->ble_read_write_uuid_cfg.data, user_ex_cfg->ble_read_write_uuid_cfg.len); + } + puts("-------------------------\n"); + puts("new_ex_cfg_info:\n"); + printf_buf((u8 *)user_ex_cfg, sizeof(ex_cfg_t)); +#endif +} + +void ex_cfg_data_load(void) +{ + ex_cfg_t user_ex_cfg; + u32 exif_addr = exif_info.addr; + vm_read_by_addr((u8 *)&user_ex_cfg, exif_addr, sizeof(ex_cfg_t)); + cfg_puts("user_ex_cfg:\n"); + cfg_printf_buf((u8 *)&user_ex_cfg, sizeof(ex_cfg_t)); +} + +u16 get_vid_pid_ver_from_cfg_file(u8 type) +{ + u8 *item_name = cfg_item_description[0].item_name; + u8 *item_data = cfg_item_description[0].item_data; + u16 item_len = cfg_item_description[0].item_len; + u16 *real_len = cfg_item_description[0].real_len; + if (!(*real_len)) { + get_cfg_data_connect_by_name(item_name, item_data, item_len, real_len); + } + switch (type) { + case GET_VID_FROM_EX_CFG: + return ((u16)item_data[0] << 8 | (u16)item_data[1]); + case GET_PID_FROM_EX_CFG: + return ((u16)item_data[2] << 8 | (u16)item_data[3]); + case GET_VER_FROM_EX_CFG: + return ((u16)item_data[4] << 8 | (u16)item_data[5]); + } + + return ((u16) - 1); +} + +#if VER_INFO_EXT_COUNT +u32 get_authkey_procode_from_cfg_file(u8 *data[], u8 *len, u8 type) +{ + u8 *item_name = cfg_item_description[5].item_name; + u8 *item_data = cfg_item_description[5].item_data; + u16 item_len = cfg_item_description[5].item_len; + u16 *real_len = cfg_item_description[5].real_len; + if (!(*real_len)) { + get_cfg_data_connect_by_name(item_name, item_data, item_len, real_len); + } + u8 offset = (u8) - 1; + u8 index = 0; + u8 separator = ','; + while (item_data[++offset]) { + if (separator == item_data[offset]) { + if (type - GET_AUTH_KEY_FROM_EX_CFG) { + index = offset; + type --; + } else { + break; + } + } + } + if (!item_data[offset]) { + index ++; + } + *data = item_data + index; + *len = offset - index; + return 0; +} +#endif + +#endif + + diff --git a/apps/common/third_party_profile/common/custom_cfg.h b/apps/common/third_party_profile/common/custom_cfg.h new file mode 100644 index 0000000..a02e145 --- /dev/null +++ b/apps/common/third_party_profile/common/custom_cfg.h @@ -0,0 +1,108 @@ +#ifndef _CUSTOM_CFG_H_ +#define _CUSTOM_CFG_H_ + +#include "typedef.h" +//#include "hw_cpu.h" +#include +#include "app_config.h" + +#define BT_CONNECTION_VERIFY 0 // 0是校验,1是不校验 + +#if (JL_EARPHONE_APP_EN && RCSP_UPDATE_EN) +#define VER_INFO_EXT_COUNT 2 //2 +#else +#define VER_INFO_EXT_COUNT 0 //2 +#endif +#define VER_INFO_EXT_MAX_LEN 24 + +enum { + CFG_ITEM_ADV_IND = 0, + CFG_ITEM_SCAN_RSP, + CFG_ITEM_BLE_NAME, + CFG_ITEM_BT_ADDR, + + CFG_ITEM_BT_NAME = 4, + CFG_ITEM_PIN_CODE, + CFG_ITEM_VER_INFO, + CFG_ITEM_LOW_POWER_VOLTAGE, + + CFG_ITEM_EDR_ADDR = 8, + CFG_ITEM_BLE_ADDR, + CFG_ITEM_GATT_PROFILE, + CFG_ITEM_RESET_IO_INFO, + + CFG_ITEM_PILOT_LAMP_IO_INFO = 12, + CFG_ITEM_LINK_KEY_INFO, + CFG_ITEM_POWER_IO_ON_OFF, + CFG_ITEM_LAST_DEVICE_LINK_KEY_INFO, + + CFG_ITEM_BLE_READ_WRITE_UUID_INFO = 16, +#if VER_INFO_EXT_COUNT + CFG_ITEM_VER_INFO_AUTHKEY, + CFG_ITEM_VER_INFO_PROCODE, +#endif + CFG_ITEM_PVID, //供loader使用 + CFG_ITEM_MD5, + CFG_ITEM_SDK_TYPE, +}; + +enum { + EX_CFG_ERR_NONE = 0, + EX_CFG_INDEX_ERR, + EX_CFG_LEN_ERR, +}; + +enum { + GET_VID_FROM_EX_CFG = 0, + GET_PID_FROM_EX_CFG, + GET_VER_FROM_EX_CFG, +#if VER_INFO_EXT_COUNT + GET_AUTH_KEY_FROM_EX_CFG, + GET_PRO_CODE_FROM_EX_CFG, +#endif +}; + +typedef struct _update_file_id { + u8 vid[2]; + u8 pid[2]; + u8 ver[2]; + u8 len[4]; + u8 reserve[4]; + u8 crc[2]; +} update_file_id_t; + +typedef struct _update_file_ext_id { + update_file_id_t update_file_id_info; +#if VER_INFO_EXT_COUNT + u8 ext[VER_INFO_EXT_COUNT * (VER_INFO_EXT_MAX_LEN * 2)]; +#endif +} update_file_ext_id_t; + +typedef struct _update_file_reset_io { + u8 io_num; + u8 resever[15]; +} update_file_reset_io_t; + +typedef struct _update_file_pilot_lamp_io { + u8 pilot_lamp_io[16]; +} update_file_pilot_lamp_io_t; + +typedef struct _update_file_link_key { + u8 link_key[16]; +} update_file_link_key_t; + +//u32 custom_cfg_file_init(void); +//void ex_cfg_write_to_flash(void); +//u32 ex_cfg_fill_content_api(u8 cfg_index, u8 *data, u16 len); +u32 ex_cfg_fill_content_api(void); +u16 get_vid_pid_ver_from_cfg_file(u8 type); +#if VER_INFO_EXT_COUNT +u32 get_authkey_procode_from_cfg_file(u8 *data[], u8 *len, u8 type); +#endif + +#if RCSP_UPDATE_EN +extern int rcsp_update_msg[10]; +#endif + +#endif + diff --git a/apps/common/third_party_profile/common/mic_rec.c b/apps/common/third_party_profile/common/mic_rec.c new file mode 100644 index 0000000..8d8d8e0 --- /dev/null +++ b/apps/common/third_party_profile/common/mic_rec.c @@ -0,0 +1,391 @@ +/***************************************************************** +>file name : mic_rec.c +>author : lichao +>create time : Wed 26 Jun 2019 04:31:50 PM CST +*****************************************************************/ +#include "system/includes.h" +#include "media/includes.h" +#include "app_config.h" +#include "audio_config.h" +#include "classic/tws_local_media_sync.h" +#include "3th_profile_api.h" +#include "classic/tws_api.h" +#include "btstack/avctp_user.h" +#include "bt_tws.h" + +#if (BT_MIC_EN) + +#define LOG_TAG "[MIC_REC]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +#define LOG_CLI_ENABLE +#include "debug.h" + +enum { + STANDARD_OPUS = 0 << 6, + KUGOU_OPUS = 1 << 6, +}; + +enum { + ENC_OPUS_16KBPS = 0, + ENC_OPUS_32KBPS = 1, + ENC_OPUS_64KBPS = 2, +}; + +typedef struct __ai_encode_info { + const u8 *info; + u32 enc_type; + u8 opus_type; + u16(*sender)(u8 *buf, u16 len); +} _ai_encode_info; + +struct __speech_buf_ctl { + cbuffer_t cbuffer; + volatile u8 speech_init_flg; + u16 cbuf_size; + u8 *speech_cbuf; +}; + +struct __mic_rec_t { + struct __speech_buf_ctl buf_ctl; + struct __ai_encode_info ai_enc_info; + u8 ai_mic_busy_flg; + u8 init_ok; + u16 frame_num; + u16 frame_size; + OS_MUTEX mutex_ai_mic; +}; +static struct __mic_rec_t mic_rec; +#define __this (&mic_rec) + +extern void bt_sniff_ready_clean(void); +bool get_tws_sibling_connect_state(void); +int a2dp_tws_dec_suspend(void *p); +void a2dp_tws_dec_resume(void); +int audio_mic_enc_open(int (*mic_output)(void *priv, void *buf, int len), u32 code_type, u8 ai_type); +int audio_mic_enc_close(); +static void ai_mic_tws_stop_opus(); + +static void speech_cbuf_init(void) +{ + __this->buf_ctl.speech_init_flg = 1; + + ASSERT(__this->buf_ctl.speech_cbuf == NULL, "speech_cbuf is err\n"); + __this->buf_ctl.speech_cbuf = malloc(__this->buf_ctl.cbuf_size); + ASSERT(__this->buf_ctl.speech_cbuf, "speech_cbuf is not ok\n"); + + cbuf_init(&(__this->buf_ctl.cbuffer), __this->buf_ctl.speech_cbuf, __this->buf_ctl.cbuf_size); +} + +static void speech_cbuf_exit(void) +{ + __this->buf_ctl.speech_init_flg = 0; + cbuf_clear(&(__this->buf_ctl.cbuffer)); + + free(__this->buf_ctl.speech_cbuf); + __this->buf_ctl.speech_cbuf = NULL; +} + +static u16 speech_data_send(u8 *buf, u16 len, u16(*send_data)(u8 *buf, u16 len)) +{ + u16 res = 0; + u16 send_len = __this->frame_num * len; + u8 temp_buf[send_len]; + + if (__this->buf_ctl.speech_init_flg == 0) { + return 0; + } + + if (cbuf_write(&(__this->buf_ctl.cbuffer), buf, len) != len) { + res = (u16)(-1); + } + + /* printf("cl %d\n",cbuf_get_data_size(&(__this->buf_ctl.cbuffer))); */ + + while (cbuf_get_data_size(&(__this->buf_ctl.cbuffer)) >= send_len) { + cbuf_read_alloc_len(&(__this->buf_ctl.cbuffer), temp_buf, send_len); + if (send_data) { + if (!send_data(temp_buf, send_len)) { + putchar('S'); + cbuf_read_alloc_len_updata(&(__this->buf_ctl.cbuffer), send_len); + } else { + putchar('E'); + break; + } + } + } + + return res; +} + +#if TCFG_USER_TWS_ENABLE +#if 0 +void tws_api_local_media_sync_rx_handler_notify() +{ + u8 *tws_buf = NULL; + int len = 0; + + if (mic_get_data_source() == SINK_TYPE_SLAVE) { + if (dma_tws_mic_pool) { + tws_buf = tws_api_local_media_trans_pop(&len); + /* log_info("sf %d %0x\n",len, tws_buf); */ + if (tws_buf) { + tws_api_local_media_trans_free(tws_buf); + } + } + } +} + +static u16 tws_data_send_slave_to_master(u8 *buf, u16 len) +{ + u8 *tws_buf = NULL; + + if (dma_tws_mic_pool == 0) { + return -1; + } + + tws_buf = tws_api_local_media_trans_alloc(len); + if (tws_buf == NULL) { + return -1; + } + /* log_info("sd %0x %d\n",tws_buf,len); */ + memcpy(tws_buf, buf, len); + /* printf("tdlen\n"); */ + /* put_buf(tws_buf,len); */ + tws_api_local_media_trans_push(tws_buf, len); + return 0; + +} +#endif + +enum { + //send to sibling + TWS_AI_A2DP_DROP_FRAME_CTL_V2 = 0, + + //tws sync deal + TWS_AI_MIC_RESUME_A2DP = 0x80, +}; + +static int mic_rec_tws_send_cmd(u8 cmd) +{ + return tws_api_send_data_to_sibling(&cmd, sizeof(cmd), 0x3890AB12); +} + +static void __mic_rec_tws_rx_cb_deal(int cmd) +{ + switch (cmd) { //tws sync deal + case TWS_AI_A2DP_DROP_FRAME_CTL_V2: + a2dp_tws_dec_suspend(NULL); + break; + case TWS_AI_MIC_RESUME_A2DP: + ai_mic_tws_stop_opus(); + break; + } +} + +static void mic_rec_tws_rx_data(void *_data, u16 len, bool rx) +{ + int msg[4]; + int err = 0; + u8 *data = (u8 *)_data; + + printf(">>>%s \n", __func__); + printf("len :%d\n", len); + put_buf(_data, len); + + if (!rx && data[0] < TWS_AI_MIC_RESUME_A2DP) { //not need deal + return; + } + + msg[0] = (int)__mic_rec_tws_rx_cb_deal; + msg[1] = 1; + msg[2] = *data; + err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg); + if (err) { + printf("tws rx post fail\n"); + } +} + +REGISTER_TWS_FUNC_STUB(mic_rec_sync_stub) = { + .func_id = 0x3890AB12, + .func = mic_rec_tws_rx_data, +}; +#endif + +u16 ai_mic_get_frame_size() +{ + return __this->frame_size; +} + +static int rec_enc_output(void *priv, void *buf, int len) +{ + bt_sniff_ready_clean(); + + u8 *send_buf = (u8 *)buf; + int send_len = len; + + //printf("len:%d\n", len); + __this->frame_size = len; + if (speech_data_send(send_buf, send_len, __this->ai_enc_info.sender) == (u16)(-1)) { + log_info("opus data miss !!! line:%d \n", __LINE__); + } + + return 0; +} + + +_WEAK_ int a2dp_tws_dec_suspend(void *p) +{ + return 0; +} + + +_WEAK_ void a2dp_tws_dec_resume(void) +{ +} + +_WEAK_ void bt_sniff_ready_clean(void) +{ +} + +_WEAK_ void mic_rec_clock_set(void) +{ +} + +_WEAK_ void mic_rec_clock_recover(void) +{ +} + +int ai_mic_rec_start(void) +{ + if (0 == __this->init_ok) { + printf("init err\n"); + return -1; + } + os_mutex_pend(&__this->mutex_ai_mic, 0); + + if (__this->ai_mic_busy_flg) { + os_mutex_post(&__this->mutex_ai_mic); + return -1; + } + + user_send_cmd_prepare(USER_CTRL_ALL_SNIFF_EXIT, 0, NULL); + +#if TCFG_USER_TWS_ENABLE + if (get_tws_sibling_connect_state() && (tws_api_get_role() == TWS_ROLE_MASTER)) { + mic_rec_tws_send_cmd(TWS_AI_A2DP_DROP_FRAME_CTL_V2); + } +#endif + + int err = a2dp_tws_dec_suspend(NULL); + if (err == 0) { + printf("opus init \n"); + + mic_rec_clock_set(); + + speech_cbuf_init(); + + printf("%s \n", __this->ai_enc_info.info); + audio_mic_enc_open(rec_enc_output, __this->ai_enc_info.enc_type, __this->ai_enc_info.opus_type); + __this->ai_mic_busy_flg = 1; + } + + os_mutex_post(&__this->mutex_ai_mic); + + return 0; +} + +int ai_mic_is_busy(void) +{ + return __this->ai_mic_busy_flg; +} + +static void ai_mic_tws_stop_opus() +{ + if (__this->ai_mic_busy_flg == 0) { + a2dp_tws_dec_resume(); + } +} + +static int ai_mic_resume_a2dp(void) +{ + int err = 0; + int msg[8]; + msg[0] = (int)ai_mic_tws_stop_opus; + msg[1] = 1; + msg[2] = 0; + + while (1) { + err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg); + if (err != OS_Q_FULL) { + break; + } + os_time_dly(2); + } + + return err; +} + +int ai_mic_rec_close(void) +{ + os_mutex_pend(&__this->mutex_ai_mic, 0); + + if (__this->ai_mic_busy_flg) { + printf(">>>>opus close: %d, %s\n", cpu_in_irq(), os_current_task()); + audio_mic_enc_close(); + + speech_cbuf_exit(); + + mic_rec_clock_recover(); + + __this->ai_mic_busy_flg = 0; + } + + os_mutex_post(&__this->mutex_ai_mic); + +#if TCFG_USER_TWS_ENABLE + if ((tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED)) { + if (tws_api_get_role() == TWS_ROLE_MASTER) { + mic_rec_tws_send_cmd(TWS_AI_MIC_RESUME_A2DP); + } + } else { + /*a2dp_tws_dec_resume();*/ + ai_mic_resume_a2dp(); + } +#else + ai_mic_resume_a2dp(); + /*a2dp_tws_dec_resume();*/ +#endif + + return 0; +} + +static int ai_mic_mutex_init(void) +{ + os_mutex_create(&__this->mutex_ai_mic); + return 0; +} +late_initcall(ai_mic_mutex_init); + +int mic_rec_pram_init(/* const char **name, */u32 enc_type, u8 opus_type, u16(*speech_send)(u8 *buf, u16 len), u16 frame_num, u16 cbuf_size) +{ + /* __this->ai_enc_info.info = name; */ + __this->init_ok = 0; + if (enc_type == AUDIO_CODING_OPUS && !TCFG_ENC_OPUS_ENABLE) { + printf("please enable opus deceder"); + return -1; + } else if (enc_type == AUDIO_CODING_SPEEX && !TCFG_ENC_SPEEX_ENABLE) { + printf("please enable speex deceder"); + return -1; + } + __this->ai_enc_info.enc_type = enc_type; + __this->ai_enc_info.opus_type = opus_type; + __this->ai_enc_info.sender = speech_send; + __this->frame_num = frame_num; + __this->buf_ctl.cbuf_size = cbuf_size; + __this->init_ok = 1; + return 0; +} +#endif + diff --git a/apps/common/third_party_profile/interface/app_protocol_api.c b/apps/common/third_party_profile/interface/app_protocol_api.c new file mode 100644 index 0000000..32c9121 --- /dev/null +++ b/apps/common/third_party_profile/interface/app_protocol_api.c @@ -0,0 +1,1202 @@ +#include +#include +#include + +#include "system/timer.h" +#include "system/task.h" +#include "app_protocol_api.h" +#include "btstack/avctp_user.h" +#include "syscfg_id.h" +#include "system/includes.h" +#include "bt_tws.h" +#include "app_protocol_ota.h" +#include "btstack/third_party/app_protocol_libs_api.h" +#include "audio_config.h" +#include "app_task.h" + +#if AI_APP_PROTOCOL +static int app_protocol_demo_init(int match_id); +static int app_protocol_ama_init(int match_id); +static int app_protocol_gma_init(int match_id); +static int app_protocol_dma_init(int match_id); +static int app_protocol_tme_init(int match_id); +static int app_protocol_mma_init(int match_id); + +#if 1 +#define APP_PROTOCOL_LOG printf +#define APP_PROTOCOL_DUMP put_buf +#else +#define APP_PROTOCOL_LOG(...) +#define APP_PROTOCOL_DUMP(...) +#endif + +typedef struct { + // linked list - assert: first field + void *offset_item; + // data is contained in same memory + u32 service_record_handle; + u8 *service_record; +} app_protocal_item_t; +#define AI_RECORD_REGISTER(handler) \ + const app_protocal_item_t handler sec(.sdp_record_item) + +struct app_protocol_info_t { + /*配置类接口*/ + void (*set_product_id)(u32 pid); + void (*set_vendor_id)(u32 vid); + void (*set_local_version)(u32 vid); + void (*set_special_info_group)(void *addr); + void (*set_tws_sibling_mac)(void *mac); +}; + +struct app_ctrl_operation_t { + int(*protocol_init)(); + int(*protocol_exit)(); + int(*adv_enable)(int enable); + int(*ibeacon_adv)(int sw); + int(*regist_wakeup_send)(void *priv, void *cbk); + int(*regist_recieve_cbk)(void *priv, void *cbk); + int(*latency_enable)(void *priv, u32 enable); + int(*send_data)(void *priv, void *buf, u16 len); + int(*send_voice_data)(void *buf, u16 len); + int(*disconnect)(void *addr); + int(*tws_receive_sync_data)(u8 *data, int len); + int(*get_auth_state)(void); + int(*start_voice_recognition)(int st); + int(*update_tws_state_to_lib)(int sta); +}; +struct callback_register_t { + void(*message_handler_regedit)(int (*handler)(int id, int opcode, u8 *data, u32 len)); + void(*check_some_status_register)(int (*handler)(int state_flag)); + void(*check_tws_role_is_master_register)(bool (*handler)(void)); + void(*tx_resume)(void (*handler)(void)); + void(*rx_resume)(void (*handler)(void)); + void(*get_battery)(bool (*handler)(u8 battery_type, u8 *value)); +}; +typedef struct app_protocol { + int handler_id; + int (*loop)(void); + int (*tx_loop)(void); + int (*special_message)(int id, int opcode, u8 *data, u32 len); + struct app_protocol_info_t *settings; + struct app_ctrl_operation_t *app_ctrl; + struct callback_register_t *callback; +} app_protocol_interface_t; + +#define MAX_NUMBER_RUN 2 +struct app_protocol_task { + app_protocol_interface_t app_p[MAX_NUMBER_RUN]; + u16 tick_timer; + u8 running_protocol_number: 3; + u8 run_flag: 1; + u8 first_init_flag: 1; + u8 reserve: 3; +}; +struct app_protocol_task g_app; +#define __this (&g_app) +static app_protocol_interface_t *current_run_app = NULL; + +#define list_for_each_app_protocol(p) \ + for (p = __this->app_p; p < __this->app_p + MAX_NUMBER_RUN; p++) + + +static app_protocol_interface_t *get_interface_for_id(u32 id) +{ + app_protocol_interface_t *app; + list_for_each_app_protocol(app) { + if (id == app->handler_id) { + return app; + } + } + return NULL; +} +static int free_interface_for_id(u32 id) +{ + app_protocol_interface_t *app; + list_for_each_app_protocol(app) { + if (id == app->handler_id) { + app->handler_id = 0; + app->loop = NULL; + app->tx_loop = NULL; + app->settings = NULL; + app->app_ctrl = NULL; + app->callback = NULL; + return 1; + } + } + return 0; +} +static app_protocol_interface_t *get_empty_interface() +{ + app_protocol_interface_t *app; + list_for_each_app_protocol(app) { + if (0 == app->handler_id) { + return app; + } + } + return NULL; +} + +/**获取当前协议*/ +u32 app_protocol_get_cur_handle_id() +{ + if (current_run_app) { + return current_run_app->handler_id; + } + return 0; +} + +/*设置产品的PID*/ +void app_protocol_set_product_id(u32 handler_id, u32 pid) +{ + app_protocol_interface_t *app = get_interface_for_id(handler_id); + if (app && app->settings) { + if (app->settings->set_product_id) { + app->settings->set_product_id(pid); + } + } +} +/*设置产品的VID*/ +void app_protocol_set_vendor_id(u32 handler_id, u32 vid) +{ + app_protocol_interface_t *app = get_interface_for_id(handler_id); + if (app && app->settings) { + if (app->settings->set_vendor_id) { + app->settings->set_vendor_id(vid); + } + } +} + +/*设置产品的version*/ +void app_protocol_set_local_version(u32 handler_id, u32 version) +{ + app_protocol_interface_t *app = get_interface_for_id(handler_id); + if (app && app->settings) { + if (app->settings->set_local_version) { + app->settings->set_local_version(version); + } + } +} + +/*配置协议更多信息,例如GMA的三元组地址*/ +void app_protocol_set_info_group(u32 handler_id, void *addr) +{ + app_protocol_interface_t *app = get_interface_for_id(handler_id); + if (app && app->settings) { + if (app->settings->set_special_info_group) { + app->settings->set_special_info_group(addr); + } + } +} +/*配置TWS的地址,app协议用于配置广播包或者命令告知app*/ +void app_protocol_set_tws_sibling_mac(u8 *mac) +{ + app_protocol_interface_t *app; + list_for_each_app_protocol(app) { + if (app->settings) { + if (app->settings->set_tws_sibling_mac) { + app->settings->set_tws_sibling_mac(mac); + } + } + } +} + +void app_protocol_ibeacon_switch(int sw) +{ + app_protocol_interface_t *app; + list_for_each_app_protocol(app) { + if (app->app_ctrl) { + if (app->app_ctrl->ibeacon_adv) { + app->app_ctrl->ibeacon_adv(sw); + } + } + } +} +void app_protocol_ble_adv_switch(int sw) +{ + app_protocol_interface_t *app; + list_for_each_app_protocol(app) { + if (app->app_ctrl) { + if (app->app_ctrl->adv_enable) { + app->app_ctrl->adv_enable(sw); + } + } + } +} +void app_protocol_disconnect(void *addr) +{ + app_protocol_interface_t *app; + list_for_each_app_protocol(app) { + if (app->app_ctrl) { + if (app->app_ctrl->disconnect) { + app->app_ctrl->disconnect(addr); + } + } + } +} +void app_protocol_get_tws_data_for_lib(u8 *data, u32 len) +{ + app_protocol_interface_t *app; + list_for_each_app_protocol(app) { + if (app->app_ctrl) { + if (app->app_ctrl->tws_receive_sync_data) { + app->app_ctrl->tws_receive_sync_data(data, len); + } + } + } +} +void app_protocal_update_tws_state_to_lib(int state) +{ + app_protocol_interface_t *app; + list_for_each_app_protocol(app) { + if (app->app_ctrl) { + if (app->app_ctrl->update_tws_state_to_lib) { + app->app_ctrl->update_tws_state_to_lib(state); + } + } + } +} +__attribute__((weak)) +bool is_tws_master_role() +{ +#if TCFG_USER_TWS_ENABLE + return (tws_api_get_role() == TWS_ROLE_MASTER); +#endif + return 1; +} + +static int app_get_tws_side() +{ + // CHECK_STATUS_TWS_SIDE: /*0是单耳,1是左耳,2是右耳*/ +#if TCFG_USER_TWS_ENABLE + if (tws_api_get_local_channel() == 'R') { + return 2; + } else if (tws_api_get_local_channel() == 'L') { + return 1; + } +#endif + return 0; +} +int app_protocol_check_status(int status_flag) +{ + switch (status_flag) { + case CHECK_STATUS_TWS_MASTER: + return is_tws_master_role(); + case CHECK_STATUS_TWS_SLAVE: + return !is_tws_master_role(); + case CHECK_STATUS_TWS_PAIR_STA: /*1是tws已经配对了,0是未配对*/ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + return true; + } else { + return false; + } +#endif + return 0; + case CHECK_STATUS_TWS_SIDE: /*0是单耳,1是左耳,2是右耳*/ + return app_get_tws_side(); + } + return 0; +} +__attribute__((weak)) +bool app_protocol_get_battery(u8 type, u8 *value) +{ + for (int i = 0; i < APP_PROTOCOL_BAT_T_MAX; i++) { + if (type & BIT(i)) { + value[i] = app_protocal_get_bat_by_type(i); + } + } + return 0; +} +static void set_mic_rec_param(int id) +{ + switch (id) { + case TME_HANDLER_ID: + mic_rec_pram_init(AUDIO_CODING_OPUS, 1 << 6, app_protocol_send_voice_data, 4, 1024); //TME每4帧加一个头,每帧长度46 + break; + case GMA_HANDLER_ID: + mic_rec_pram_init(AUDIO_CODING_OPUS, 0, app_protocol_send_voice_data, 4, 1024); + break; + case MMA_HANDLER_ID: + mic_rec_pram_init(AUDIO_CODING_SPEEX, 0, app_protocol_send_voice_data, 5, 1024); //小米每5帧加一个头,每帧长度42 + break; + default: + mic_rec_pram_init(AUDIO_CODING_OPUS, 0, app_protocol_send_voice_data, 4, 1024); + break; + + } +} +static int app_protocol_message_handler(int id, int opcode, u8 *data, u32 len) +{ + static app_protocol_interface_t *message_app = NULL; + APP_PROTOCOL_LOG("\napp_protocol_message_handler opcode = %d\n", opcode); + int ret = 0; + switch (opcode) { + case APP_PROTOCOL_CONNECTED_SPP: + case APP_PROTOCOL_CONNECTED_BLE: + //连接上断开消息的 + app_protocol_post_bt_event(AI_EVENT_APP_CONNECT, NULL); + /* void bt_check_exit_sniff(); */ + /* bt_check_exit_sniff(); */ + user_send_cmd_prepare(USER_CTRL_ALL_SNIFF_EXIT, 0, NULL); + current_run_app = get_interface_for_id(id); +#if APP_PROTOCOL_SPEECH_EN + set_mic_rec_param(id); +#endif + printf("APP_PROTOCOL_CONNECT\n"); + break; + case APP_PROTOCOL_DISCONNECT: + app_protocol_post_bt_event(AI_EVENT_APP_DISCONNECT, NULL); + app_protocol_ota_interrupt_by_disconnect(id); + current_run_app = NULL; + printf("APP_PROTOCOL_disconnect\n"); + if (app_protocol_update_success_flag()) { + cpu_reset(); + } + break; + case APP_PROTOCOL_AUTH_PASS: + break; + case APP_PROTOCOL_SPEECH_ENCODER_TYPE: + break; +#if APP_PROTOCOL_SPEECH_EN + case APP_PROTOCOL_SPEECH_START: + APP_PROTOCOL_LOG("app_protocol_speech_start by app\n"); +#if TCFG_BLUETOOTH_BACK_MODE + if (app_get_curr_task() != APP_BT_TASK) { + app_task_switch_to(APP_BT_TASK); + } +#endif + ret = app_protocol_start_speech_by_app(1); + break; + case APP_PROTOCOL_SPEECH_STOP: + ret = app_protocol_stop_speech_by_app(); + break; +#endif + case APP_PROTOCOL_SET_VOLUME: + app_protocol_set_volume(data[0]); + break; + case APP_PROTOCOL_GET_VOLUME: + data[0] = app_audio_get_volume(APP_AUDIO_STATE_MUSIC); + break; + case APP_PROTOCOL_LIB_TWS_DATA_SYNC: + app_protocol_tws_send_to_sibling(APP_PROTOCOL_TWS_FOR_LIB, data, len); + break; + default: + ret = app_protocol_ota_message_handler(id, opcode, data, len); + break; + } + message_app = get_interface_for_id(id); + + if (message_app) { + if (message_app->special_message) { + message_app->special_message(id, opcode, data, len); + } + } + return ret; +} + +static void app_protocol_resume(void) +{ + if (__this->run_flag == 0) { + return ; + } + os_taskq_post_type(APP_PROTOCOL_TASK_NAME, APP_PROTOCOL_RX_DATA_EVENT, 0, NULL); +} +static void app_protocol_send_resume(void) +{ + if (__this->run_flag == 0) { + return ; + } + os_taskq_post_type(APP_PROTOCOL_TASK_NAME, APP_PROTOCOL_TX_DATA_EVENT, 0, NULL); +} +static void app_protocol_tick_resume(void) +{ + app_protocol_resume();///500ms resume for send retry +} +static void app_protocol_loop_process(void *parm) +{ + int msg[8]; + int ret; + app_protocol_interface_t *app = NULL; + __this->tick_timer = sys_timer_add(NULL, app_protocol_tick_resume, 1000); + __this->run_flag = 1; + APP_PROTOCOL_LOG("app_protocol_loop_process\n"); + while (1) { + ret = os_taskq_pend("taskq", msg, ARRAY_SIZE(msg)); + if (ret != OS_TASKQ) { + continue; + } + switch (msg[0]) { + case APP_PROTOCOL_RX_DATA_EVENT: + list_for_each_app_protocol(app) { + if (app->handler_id) { + if (app->loop) { + app->loop(); + } + } + } + break; + case APP_PROTOCOL_TX_DATA_EVENT: + list_for_each_app_protocol(app) { + if (app->handler_id) { + if (app->tx_loop) { + app->tx_loop(); + } + } + } + break; + case APP_PROTOCOL_TASK_EXIT: + os_sem_post((OS_SEM *)msg[1]); + os_time_dly(10000); + break; + default: + APP_PROTOCOL_LOG("err app protocal msg\n"); + break; + } + } +} +//可以动态加载选择某个APP协议 +void app_protocol_init(int handler_id) +{ + APP_PROTOCOL_LOG("app_protocol_init\n"); + //如果是第二次调用这个函数,就只起注册协议的作用,不需要重新建立任务 + if (__this->running_protocol_number < MAX_NUMBER_RUN) { +#if APP_PROTOCOL_DEMO_CODE + if (app_protocol_demo_init(handler_id)) { + __this->running_protocol_number++; + } +#endif +#if APP_PROTOCOL_AMA_CODE + if (app_protocol_ama_init(handler_id)) { + __this->running_protocol_number++; + } +#endif +#if APP_PROTOCOL_GMA_CODE + if (app_protocol_gma_init(handler_id)) { + __this->running_protocol_number++; + } +#endif +#if APP_PROTOCOL_DMA_CODE + if (app_protocol_dma_init(handler_id)) { + __this->running_protocol_number++; + } +#endif +#if APP_PROTOCOL_MMA_CODE + if (app_protocol_mma_init(handler_id)) { + __this->running_protocol_number++; + } +#endif + +#if APP_PROTOCOL_TME_CODE + if (app_protocol_tme_init(handler_id)) { + __this->running_protocol_number++; + } +#endif + } + if ((__this->running_protocol_number > 0) && __this->first_init_flag == 0) { + APP_PROTOCOL_LOG("app_protocol_task create\n"); + __this->first_init_flag = 1; + task_create(app_protocol_loop_process, NULL, APP_PROTOCOL_TASK_NAME); + } +} +void app_protocol_all_init() +{ + app_protocol_init(DEMO_HANDLER_ID); + app_protocol_init(DMA_HANDLER_ID); + app_protocol_init(MMA_HANDLER_ID); + app_protocol_init(GMA_HANDLER_ID); + app_protocol_init(TME_HANDLER_ID); +} +/*为了适应以前的参数格式,自定义了一个函数发消息*/ +int app_protocol_post_msg(const char *name, int argc, ...) +{ + int ret = 0; + int argv[8]; + APP_PROTOCOL_LOG("mm_task_post_msg\n"); + va_list argptr; + ASSERT(argc < 8); + va_start(argptr, argc); + for (int i = 0; i < argc; i++) { + argv[i] = va_arg(argptr, int); + } + va_end(argptr); + if (argc == 1) { + ret = os_taskq_post_type(name, argv[0], 0, NULL); + } else { + ret = os_taskq_post_type(name, argv[0], argc - 1, &argv[1]); + } + return ret; +} +void app_protocol_exit(int handler_id) +{ + //handler_id为0时退出所有,有具体handler值是退出一个 + OS_SEM sem; + app_protocol_interface_t *app; + if (handler_id == 0) { + list_for_each_app_protocol(app) { + if (app->handler_id) { + if (app->app_ctrl) { + if (app->app_ctrl->protocol_exit) { + app->app_ctrl->protocol_exit(); + } + } + if (free_interface_for_id(app->handler_id)) { + __this->running_protocol_number--; + } + } + } + } else { + app = get_interface_for_id(handler_id); + if (app) { + if (app->app_ctrl) { + if (app->app_ctrl->protocol_exit) { + app->app_ctrl->protocol_exit(); + + + } + } + if (free_interface_for_id(handler_id)) { + __this->running_protocol_number--; + } + } + } + APP_PROTOCOL_LOG("app_protocol_exit\n"); + if (__this->run_flag && (!__this->running_protocol_number)) { + __this->run_flag = 0; + if (__this->tick_timer) { + sys_timer_del(__this->tick_timer); + __this->tick_timer = 0; + } + os_sem_create(&sem, 0); + os_taskq_post_type(APP_PROTOCOL_TASK_NAME, APP_PROTOCOL_TASK_EXIT, 1, (int *)&sem); + os_sem_pend(&sem, 0); + + task_kill(APP_PROTOCOL_TASK_NAME); + __this->first_init_flag = 0; + + APP_PROTOCOL_LOG("app_protocol_delete task\n"); + } +} + +int app_protocol_send_voice_data(uint8_t *voice_buf, uint16_t voice_len) +{ + int error = 0; + app_protocol_interface_t *app = current_run_app; + if (app) { + if (app->app_ctrl) { + if (app->app_ctrl->send_voice_data) { + error = app->app_ctrl->send_voice_data(voice_buf, voice_len); + } + } + return error; + } + return -1; +} +int app_protocol_check_connect_success() +{ + int flag = 0; + app_protocol_interface_t *app = current_run_app; + if (app) { + if (app->app_ctrl) { + //一般认为只有真正加密完才能说连接完成 + if (app->app_ctrl->get_auth_state) { + flag = app->app_ctrl->get_auth_state(); + } + } + } + return flag; +} +static int app_protocol_start_voice_recognition(int state) +{ + int flag = 0; + app_protocol_interface_t *app = current_run_app; + if (!app) { + //做案子的时候百度有时候没连接也有状态更新到蓝牙库 + app = get_interface_for_id(DMA_HANDLER_ID); + } + if (app) { + if (app->app_ctrl) { + //一般认为只有真正加密完才能说连接完成 + if (app->app_ctrl->start_voice_recognition) { + flag = app->app_ctrl->start_voice_recognition(state); + } + } + } + return flag; +} +int app_protocol_start_speech_cmd() +{ + return app_protocol_start_voice_recognition(1); +} +int app_protocol_stop_speech_cmd() +{ + return app_protocol_start_voice_recognition(0); +} +int app_protocol_left_start_speech_cmd() +{ + printf("left click"); + return app_protocol_start_voice_recognition(2); +} +int app_protocol_right_start_speech_cmd() +{ + printf("right click"); + return app_protocol_start_voice_recognition(3); +} + +void app_protocol_common_init(app_protocol_interface_t *app) +{ +#if USER_SUPPORT_PROFILE_SPP + extern void user_spp_data_handler(u8 packet_type, u16 ch, u8 * packet, u16 size); + spp_data_deal_handle_register(user_spp_data_handler); +#endif +#if TCFG_USER_TWS_ENABLE + tws_api_auto_role_switch_disable(); +#endif + if (app->callback) { + if (app->callback->message_handler_regedit) { + app->callback->message_handler_regedit(app_protocol_message_handler); + } + if (app->callback->check_tws_role_is_master_register) { + app->callback->check_tws_role_is_master_register(is_tws_master_role); + } + if (app->callback->check_some_status_register) { + app->callback->check_some_status_register(app_protocol_check_status); + } + + if (app->callback->tx_resume) { + app->callback->tx_resume(app_protocol_send_resume); + } + if (app->callback->rx_resume) { + app->callback->rx_resume(app_protocol_resume); + } + if (app->callback->get_battery) { + app->callback->get_battery(app_protocol_get_battery); + } + } + if (app->app_ctrl) { + if (app->app_ctrl->protocol_init) { + app->app_ctrl->protocol_init(); + } + } + +} +//**对接具体协议的接口**// +#if APP_PROTOCOL_DEMO_CODE +extern int demo_process(); +extern int demo_all_init(void); +extern int demo_all_exit(void); +static const struct app_ctrl_operation_t demo_ctrl = { + .protocol_init = demo_all_init, + .protocol_exit = demo_all_exit, +}; +static int app_protocol_demo_init(int match_id) +{ + if (DEMO_HANDLER_ID != match_id) { + return 0; + } + APP_PROTOCOL_LOG("app_protocol_demo_init\n"); + app_protocol_interface_t *app = get_interface_for_id(DEMO_HANDLER_ID); + if (app) { + APP_PROTOCOL_LOG("DEMO_HANDLER_ID init again\n"); + } else { + app = get_empty_interface(); + if (app) { + app->handler_id = DEMO_HANDLER_ID; + app->loop = demo_process; + app->settings = NULL; + app->app_ctrl = &demo_ctrl; + app->callback = NULL; + app_protocol_common_init(app); + APP_PROTOCOL_LOG("DEMO_HANDLER_ID init OK\n"); + return 1; + } else { + APP_PROTOCOL_LOG("not support more app protocal\n"); + } + } + return 0; +} +#endif +#if APP_PROTOCOL_AMA_CODE +static int ama_run_loop(void) +{ + APP_PROTOCOL_LOG("ama_run_loop\n"); + return 0; +} +static int app_protocol_ama_init(int match_id) +{ + if (AMA_HANDLER_ID != match_id) { + return 0; + } + APP_PROTOCOL_LOG("app_protocol_ama_init\n"); + app_protocol_interface_t *app = get_interface_for_id(AMA_HANDLER_ID); + if (app) { + APP_PROTOCOL_LOG("AMA_HANDLER_ID init again\n"); + } else { + app = get_empty_interface(); + if (app) { + app->handler_id = AMA_HANDLER_ID; + app->loop = ama_run_loop; + app->settings = NULL; + app->app_ctrl = NULL; + app->callback = NULL; + APP_PROTOCOL_LOG("AMA_HANDLER_ID init OK\n"); + return 1; + } else { + APP_PROTOCOL_LOG("not support more app protocal\n"); + } + } + return 0; +} +#endif +#if APP_PROTOCOL_GMA_CODE +#if TCFG_USER_TWS_ENABLE//GMA_TWS_SUPPORTED +u8 gma_tws_support = 1; +#endif +extern const char *gma_tone_tab[]; +extern struct app_protocol_private_handle_t gma_private_handle; +extern const u8 sdp_gma_spp_service_data[]; +AI_RECORD_REGISTER(gma_record_item) = { + .service_record = (u8 *)sdp_gma_spp_service_data, + .service_record_handle = 0x00010035, +}; +static const struct callback_register_t gma_callback = { + .message_handler_regedit = gma_message_callback_register, + .check_tws_role_is_master_register = gma_is_tws_master_callback_register, + .tx_resume = gma_tx_resume_register, + .rx_resume = gma_rx_resume_register, + .get_battery = gma_get_battery_callback_register, +}; +static const struct app_ctrl_operation_t gma_ctrl = { + .protocol_init = gma_all_init, + .protocol_exit = gma_all_exit, + .send_voice_data = gma_opus_voice_mic_send, + .get_auth_state = gma_connect_success, + .start_voice_recognition = gma_start_voice_recognition, + .adv_enable = gma_ble_adv_enable, + .ibeacon_adv = gma_ble_ibeacon_adv, + .disconnect = gma_disconnect, +}; +static const struct app_protocol_info_t gma_settings = { + .set_special_info_group = gma_set_active_ali_para, + .set_tws_sibling_mac = gma_set_sibling_mac_para, +}; + +#define GMA_MAIN_NUMBER 0X00 +#define GMA_SECONDARY_NUMBER 0X00 +#define GMA_REVISION_NUMBER 0X01 + +int app_protocol_gma_get_version(void) +{ + return (GMA_MAIN_NUMBER << 16 | GMA_SECONDARY_NUMBER << 8 | GMA_REVISION_NUMBER); +} + +/* + *code crc16 + * */ +static unsigned short wCRCin = 0xFFFF; +static unsigned short wCPoly = 0x1021; + +static unsigned short CRC16_CCITT_FALSE(u16 init_crc, unsigned char *data, unsigned int datalen) +{ + + while (datalen--) { + wCRCin ^= *(data++) << 8; + for (int i = 0; i < 8; i++) { + if (wCRCin & 0x8000) { + wCRCin = (wCRCin << 1) ^ wCPoly; + } else { + wCRCin = wCRCin << 1; + } + } + } + return (wCRCin); + +} + +static void CRC16_CCITT_FALSE_INIT(void) +{ + wCRCin = 0xFFFF; + wCPoly = 0x1021; +} + +static int CRC16_CODE_RESULT(int calc_crc) +{ + return 0; +} + +static int app_protocol_gma_init(int match_id) +{ + if (GMA_HANDLER_ID != match_id) { + return 0; + } + APP_PROTOCOL_LOG("app_protocol_gma_init\n"); + app_protocol_interface_t *app = get_interface_for_id(GMA_HANDLER_ID); + if (app) { + APP_PROTOCOL_LOG("GMA_HANDLER_ID init again\n"); + } else { + app = get_empty_interface(); + if (app) { + app->handler_id = GMA_HANDLER_ID; + app->loop = gma_rx_loop; + app->tx_loop = tm_data_send_process_thread; + app->settings = &gma_settings; + app->app_ctrl = &gma_ctrl; + app->callback = &gma_callback; + gma_prev_init(); + app_protocol_tone_register(gma_tone_tab); + app_protocol_handle_register(&gma_private_handle); + app_protocol_common_init(app); + app_protocol_ota_api api = { + .ota_request_data = gma_ota_requset_next_packet, + .ota_report_result = gma_replay_ota_result, + .ota_crc_init_hdl = CRC16_CCITT_FALSE_INIT, + .ota_crc_calc_hdl = CRC16_CCITT_FALSE, + }; + app_protocol_ota_init(&api, 0); + /* app_protocol_data_api_register(gma_ota_requset_next_packet, gma_replay_ota_result); */ + /* app_protocol_ota_crc_handler_register( CRC16_CCITT_FALSE_INIT, CRC16_CCITT_FALSE); */ + APP_PROTOCOL_LOG("GMA_HANDLER_ID init OK\n"); + return 1; + } else { + APP_PROTOCOL_LOG("not support more app protocal\n"); + } + } + return 0; +} +#endif + +#if APP_PROTOCOL_DMA_CODE +//u8 dma_tws_support = 1; +extern const char *dma_notice_tab[]; +extern const u8 sdp_dueros_spp_service_data[]; +extern const u8 sdp_dueros_ota_service_data[]; +AI_RECORD_REGISTER(dma_record_item) = { + .service_record = (u8 *)sdp_dueros_spp_service_data, + .service_record_handle = 0x00010036, +}; +AI_RECORD_REGISTER(dma_ota_record_item) = { + .service_record = (u8 *)sdp_dueros_ota_service_data, + .service_record_handle = 0x00010037, +}; + +static const struct callback_register_t dma_callback = { + .message_handler_regedit = dma_message_callback_register, + .check_some_status_register = dma_check_status_callback_register, + .tx_resume = dma_tx_resume_register, + .rx_resume = dma_rx_resume_register, + .get_battery = dma_get_battery_callback_register, +}; + +static const struct app_ctrl_operation_t dma_ctrl = { + .protocol_init = dma_all_init, + .protocol_exit = dma_all_exit, + .adv_enable = dma_ble_adv_enable, + .send_voice_data = dma_speech_data_send, + .get_auth_state = dma_pair_state, + .start_voice_recognition = dma_start_voice_recognition, + .disconnect = dma_disconnect, + .update_tws_state_to_lib = dma_update_tws_state_to_lib, + .tws_receive_sync_data = dma_tws_data_deal, + /*.send_voice_data = dma_opus_voice_mic_send, + .adv_enable = dma_ble_adv_enable,*/ +}; +static const struct app_protocol_info_t dma_settings = { + .set_product_id = dma_set_pid, + .set_special_info_group = dma_set_product_id_key, + +}; +static int dueros_special_message(int id, int opcode, u8 *data, u32 len) +{ + int ret = 0; + switch (opcode) { + case APP_PROTOCOL_DMA_SAVE_RAND: + APP_PROTOCOL_LOG("APP_PROTOCOL_DMA_SAVE_RAND"); + //APP_PROTOCOL_DUMP(data, len); + ret = syscfg_write(VM_DMA_RAND, data, len); + //app_protocol_tws_send_to_sibling(DMA_TWS_ALL_INFO_SYNC, data, len); + break; + case APP_PROTOCOL_DMA_READ_RAND: + APP_PROTOCOL_LOG("APP_PROTOCOL_DMA_READ_RAND"); + ret = syscfg_read(VM_DMA_RAND, data, len); + //APP_PROTOCOL_DUMP(data, len); + break; + case APP_PROTOCOL_DMA_SAVE_OTA_INFO: + APP_PROTOCOL_LOG("APP_PROTOCOL_DMA_SAVE_OTA_INFO"); + APP_PROTOCOL_DUMP(data, len); + //不支持断点续传 + //ret = syscfg_write(VM_TME_AUTH_COOKIE, data, len); + //app_protocol_tws_send_to_sibling(DMA_TWS_OTA_INFO_SYNC, data, len); + break; + case APP_PROTOCOL_DMA_READ_OTA_INFO: + APP_PROTOCOL_LOG("APP_PROTOCOL_DMA_READ_OTA_INFO"); + //ret = syscfg_read(VM_TME_AUTH_COOKIE, data, len); + //不支持断点续传 + memset(data, 0, len); + APP_PROTOCOL_DUMP(data, len); + break; + case APP_PROTOCOL_DMA_TTS_TYPE: + printf("app_protocol_dma_tone_play %d\n", data[0]); + //app_protocol_dma_tone_play(data[0], 1); + break; + } + return ret; +} +static int app_protocol_dma_init(int match_id) +{ + if (DMA_HANDLER_ID != match_id) { + return 0; + } + APP_PROTOCOL_LOG("app_protocol_dma_init\n"); + app_protocol_interface_t *app = get_interface_for_id(DMA_HANDLER_ID); + if (app) { + APP_PROTOCOL_LOG("DMA_HANDLER_ID init again\n"); + } else { + app = get_empty_interface(); + if (app) { + app->handler_id = DMA_HANDLER_ID; + app->loop = dueros_process; + app->tx_loop = dueros_send_process; + app->special_message = dueros_special_message; + app->settings = &dma_settings; + app->app_ctrl = &dma_ctrl; + app->callback = &dma_callback; + app_protocol_tone_register(dma_notice_tab); + dueros_dma_manufacturer_info_init(); + app_protocol_common_init(app); + APP_PROTOCOL_LOG("DMA_HANDLER_ID init OK\n"); + return 1; + } else { + APP_PROTOCOL_LOG("not support more app protocal\n"); + } + } + return 0; +} +#endif + +#if APP_PROTOCOL_TME_CODE +extern const char *tme_notice_tab[APP_RROTOCOL_TONE_MAX]; +extern const u8 sdp_tme_service_data[]; +extern struct app_protocol_private_handle_t tme_private_handle; +AI_RECORD_REGISTER(tme_record_item) = { + .service_record = (u8 *)sdp_tme_service_data, + .service_record_handle = 0x00010037, +}; + +static const struct callback_register_t tme_callback = { + .message_handler_regedit = tme_message_callback_register, + .check_tws_role_is_master_register = tme_is_tws_master_callback_register, + .tx_resume = tme_tx_resume_register, + .rx_resume = tme_rx_resume_register, + .get_battery = tme_get_battery_callback_register, +}; +static const struct app_ctrl_operation_t tme_ctrl = { + .protocol_init = tme_all_init, + .protocol_exit = tme_all_exit, + .adv_enable = tme_ble_adv_enable, + .send_voice_data = tme_send_voice_data, + .get_auth_state = tme_connect_success, + .start_voice_recognition = tme_start_voice_recognition, + .disconnect = tme_protocol_disconnect, +// .ibeacon_adv = gma_ble_ibeacon_adv, +// int(*regist_wakeup_send)(void *priv, void *cbk); +// int(*regist_recieve_cbk)(void *priv, void *cbk); +// int(*latency_enable)(void *priv, u32 enable); +// int(*send_data)(void *priv, void *buf, u16 len); +}; +static const struct app_protocol_info_t tme_settings = { + .set_special_info_group = tme_set_configuration_info, + .set_product_id = tme_set_pid, + .set_vendor_id = tme_set_bid, + //.set_tws_sibling_mac = gma_set_sibling_mac_para, + //void (*set_left_battery)(u8 bat); +}; + +#define TME_VERSION {0x00,0x10}//版本号 +static const char version[] = TME_VERSION; + +int app_protocol_tme_get_version(void) +{ + return (version[0] << 8) | version[1]; +} + + +static int app_protocol_tme_init(int match_id) +{ + if (TME_HANDLER_ID != match_id) { + return 0; + } + APP_PROTOCOL_LOG("app_protocol_tme_init\n"); + app_protocol_interface_t *app = get_interface_for_id(TME_HANDLER_ID); + if (app) { + APP_PROTOCOL_LOG("TME_HANDLER_ID init again\n"); + } else { + app = get_empty_interface(); + if (app) { + app->handler_id = TME_HANDLER_ID; + app->loop = TME_protocol_process; + app->tx_loop = TME_send_packet_process; + app->settings = &tme_settings; + app->app_ctrl = &tme_ctrl; + app->callback = &tme_callback; + app_protocol_tone_register(tme_notice_tab); + app_protocol_handle_register(&tme_private_handle); + + app_protocol_ota_api api = { + .ota_request_data = TME_request_ota_data, + .ota_report_result = NULL, + .ota_crc_init_hdl = NULL, + .ota_crc_calc_hdl = NULL, + .ota_notify_file_size = TME_notify_file_size, + }; + app_protocol_ota_init(&api, 0); + + app_protocol_common_init(app); + APP_PROTOCOL_LOG("TME_HANDLER_ID init OK\n"); + return 1; + } else { + APP_PROTOCOL_LOG("not support more app protocal\n"); + } + } + return 0; +} +#endif + +#if APP_PROTOCOL_MMA_CODE +extern void mma_prev_init(); +extern const char *mma_notice_tab[APP_RROTOCOL_TONE_MAX]; +extern struct app_protocol_private_handle_t mma_private_handle; + +static const struct callback_register_t mma_callback = { + .message_handler_regedit = mma_message_callback_register, + .check_tws_role_is_master_register = mma_is_tws_master_callback_register, + .tx_resume = mma_tx_resume_register, + .rx_resume = mma_rx_resume_register, + .get_battery = mma_get_battery_callback_register, +}; + +static const struct app_ctrl_operation_t mma_ctrl = { + + .protocol_init = mma_all_init, + .protocol_exit = mma_all_exit, + .adv_enable = mma_ble_adv_enable, + .send_voice_data = XM_speech_data_send, + .get_auth_state = XM_protocal_auth_pass, + .start_voice_recognition = mma_start_voice_recognition, + .disconnect = mma_disconnect, + .tws_receive_sync_data = mma_tws_data_deal, +}; +static const struct app_protocol_info_t mma_settings = { + .set_product_id = mma_set_product_id, + .set_vendor_id = mma_set_verdor_id, + .set_local_version = mma_set_local_version, +}; +int mma_special_message(int id, int opcode, u8 *data, u32 len) +{ + int ret = 0; + switch (opcode) { + case APP_PROTOCOL_MMA_SAVE_INFO: + APP_PROTOCOL_LOG("APP_PROTOCOL_MMA_SAVE_"); + APP_PROTOCOL_DUMP(data, len); + ret = syscfg_write(VM_DMA_RAND, data, len); + break; + case APP_PROTOCOL_MMA_READ_INFO: + APP_PROTOCOL_LOG("APP_PROTOCOL_mMA_READ_"); + ret = syscfg_read(VM_DMA_RAND, data, len); + APP_PROTOCOL_DUMP(data, len); + break; + case APP_PROTOCOL_MMA_SAVE_ADV_COUNTER: + syscfg_write(VM_TME_AUTH_COOKIE, data, len); + break; + case APP_PROTOCOL_MMA_READ_ADV_COUNTER: + syscfg_read(VM_TME_AUTH_COOKIE, data, len); + break; + } + return ret; +} +static int app_protocol_mma_init(int match_id) +{ + if (MMA_HANDLER_ID != match_id) { + return 0; + } + APP_PROTOCOL_LOG("app_protocol_mma_init\n"); + app_protocol_interface_t *app = get_interface_for_id(MMA_HANDLER_ID); + if (app) { + APP_PROTOCOL_LOG("MMA_HANDLER_ID init again\n"); + } else { + app = get_empty_interface(); + if (app) { + app->handler_id = MMA_HANDLER_ID; + app->loop = mma_protocol_loop_process; + /*app->tx_loop = ;*/ + app->special_message = mma_special_message; + app->settings = &mma_settings; + app->app_ctrl = &mma_ctrl; + app->callback = &mma_callback; + app_protocol_tone_register(mma_notice_tab); + + app_protocol_ota_api api = { + .ota_request_data = mma_request_ota_data, + .ota_report_result = mma_report_ota_status, + .ota_crc_init_hdl = NULL, + .ota_crc_calc_hdl = NULL, + .ota_notify_file_size = mma_notify_file_size, + }; + app_protocol_ota_init(&api, 1); //mma需要等待APP来进行复位 + mma_prev_init(); + app_protocol_handle_register(&mma_private_handle); + app_protocol_common_init(app); + APP_PROTOCOL_LOG("mMA_HANDLER_ID init OK\n"); + return 1; + } else { + APP_PROTOCOL_LOG("not support more app protocal\n"); + } + } + return 0; +} +#endif + +int app_protocol_get_version_by_id(int id) +{ +#if APP_PROTOCOL_GMA_CODE + if (id == GMA_HANDLER_ID) { + return app_protocol_gma_get_version(); + } +#endif +#if APP_PROTOCOL_TME_CODE + if (id == TME_HANDLER_ID) { + return app_protocol_tme_get_version(); + } +#endif + return 0; +} + +/* int app_protocol_reply_frame_check_result(int result){ */ +/* if( app_protocol_get_cur_handle_id() == GMA_HANDLER_ID){ */ +/* gma_replay_ota_result(result); */ +/* } */ +/* return 0; */ +/* } */ + +//编译问题加几个空的 +_WEAK_ void bt_ble_init(void) +{ +} +_WEAK_ void bt_ble_exit(void) +{ + APP_PROTOCOL_LOG("bt_ble_exit"); + app_protocol_disconnect(0); +} + +_WEAK_ void bt_ble_adv_enable(void) +{ +} + +#else +void app_protocol_init(int handler_id) +{ +} +void app_protocol_exit(int handler_id) +{ +} +#endif + diff --git a/apps/common/third_party_profile/interface/app_protocol_api.h b/apps/common/third_party_profile/interface/app_protocol_api.h new file mode 100644 index 0000000..fc4483a --- /dev/null +++ b/apps/common/third_party_profile/interface/app_protocol_api.h @@ -0,0 +1,82 @@ + + +#ifndef _3TH_PROTOCOL_API_H +#define _3TH_PROTOCOL_API_H + +#include +#include +#include "typedef.h" +#include "os/os_api.h" +#include "btstack/third_party/app_protocol_event.h" +#include "app_protocol_common.h" + +#define APP_PROTOCOL_TASK_NAME "app_proto" + +//定义这几个宏仅仅用于编译优化代码量。需要那个选哪个,flash够大,可以全部都打开的。 +//不要在板级头文件重复定义。 +#define APP_PROTOCOL_DEMO_CODE 0 +#define APP_PROTOCOL_GMA_CODE 0 +#define APP_PROTOCOL_AMA_CODE 0 +#define APP_PROTOCOL_DMA_CODE 0 +#define APP_PROTOCOL_TME_CODE 0 +#define APP_PROTOCOL_MMA_CODE 0 + +#define APP_PROTOCOL_SPEECH_EN 0 //语音助手功能,若无此功能则关掉 +#define APP_PROTOCOL_READ_CFG_EN 0 //从custom.dat中读取配置信息,若无此功能则关掉 + +#define DEMO_HANDLER_ID 0x300 /*作为一个使用的例子,同时也可作为客户自己添加协议的ID*/ +#define GMA_HANDLER_ID 0x400 /*阿里天猫协议接口ID*/ +#define MMA_HANDLER_ID 0x500 /*小米MMA协议接口ID*/ +#define DMA_HANDLER_ID 0x600 /*百度DMA协议接口ID*/ +#define TME_HANDLER_ID 0x700 /*腾讯酷狗TME协议接口ID*/ +#define AMA_HANDLER_ID 0x800 /*亚马逊的AMA协议接口ID*/ + +//app os task message +enum { + //Q_USER =0x400000 + APP_PROTOCOL_RX_DATA_EVENT = (Q_USER + 100), + APP_PROTOCOL_TX_DATA_EVENT, + APP_PROTOCOL_TASK_EXIT, +}; + +//参数配置类接口(在库外面的文件common区) +//配置在init之前的参数接口 +void app_protocol_set_product_id(u32 handler_id, u32 pid); +void app_protocol_set_vendor_id(u32 handler_id, u32 vid); +void app_protocol_set_local_version(u32 handler_id, u32 version); +void app_protocol_set_info_group(u32 handler_id, void *addr); //如配置三元组 +void app_protocol_tws_role_check_register(u8(*handler)(void)); /*注册获取tws状态的函数接口*/ +void app_protocol_set_tws_sibling_mac(u8 *mac); + + +//公共类函数接口 +/*这个接口主要是建立一个线程,注册一些协议需要用的公共接口,比如resume,message_handler等函数。建立了线程之后,初始化*/ +void app_protocol_all_init(); +void app_protocol_init(int handler_id); +/*主要是删除线程操作,在删除完之后再释放APP协议栈的资源*/ +void app_protocol_exit(int handler_id); +/*开始语音识别功能*/ +int app_protocol_start_speech_cmd(); +/*手动停止语音识别功能*/ +int app_protocol_stop_speech_cmd(); +int app_protocol_left_start_speech_cmd(); +int app_protocol_right_start_speech_cmd(); +void app_protocol_update_battery(u8 main, u8 left, u8 right, u8 box); +void app_protocol_ble_adv_switch(int sw); +void app_protocol_ibeacon_switch(int sw); +void app_protocol_disconnect(void *addr); +void app_protocol_get_tws_data_for_lib(u8 *data, u32 len); +/*发送mic相应编码后的数据*/ +int app_protocol_send_voice_data(uint8_t *voice_buf, uint16_t voice_len); +/*获取有没有链路连接完成状态*/ +int app_protocol_check_connect_success(); +bool is_tws_master_role(); + +u32 app_protocol_get_cur_handle_id(); + +int app_protocol_get_version_by_id(int id); + +int app_protocol_reply_frame_check_result(int result); +void app_protocal_update_tws_state_to_lib(int state); + +#endif diff --git a/apps/common/third_party_profile/interface/app_protocol_common.c b/apps/common/third_party_profile/interface/app_protocol_common.c new file mode 100644 index 0000000..3bdd212 --- /dev/null +++ b/apps/common/third_party_profile/interface/app_protocol_common.c @@ -0,0 +1,769 @@ +#include "app_protocol_api.h" +#include "app_protocol_common.h" +#include "system/includes.h" +#include "app_config.h" +#include "audio_config.h" +#include "app_chargestore.h" +#include "app_power_manage.h" +#include "asm/charge.h" +#include "bt_tws.h" +#include "btstack/avctp_user.h" +#include "3th_profile_api.h" +#include "bt_common.h" +#include "tone_player.h" +#include "app_main.h" +#include "key_event_deal.h" + +#if AI_APP_PROTOCOL + +#if 1 +#define APP_PROTOCOL_LOG printf +#define APP_PROTOCOL_DUMP put_buf +#else +#define APP_PROTOCOL_LOG(...) +#define APP_PROTOCOL_DUMP(...) +#endif + +__attribute__((weak)) +void app_protocol_tone_play(int index, int tws_sync) +{ + +} +static const char **app_tone_table = NULL; +static struct app_protocol_private_handle_t *private_handle; + +extern u8 get_remote_dev_company(void); +#define REMOTE_DEV_ANDROID 1 +#define REMOTE_DEV_IOS 2 +bool is_ios_system(void) +{ + APP_PROTOCOL_LOG("remote_dev_company :%d \n", get_remote_dev_company()); + return (get_remote_dev_company() == REMOTE_DEV_IOS); +} + +void app_protocol_tone_register(const char **tone_table) +{ + app_tone_table = tone_table; +} + +const char *app_protocol_get_tone(int index) +{ + if (app_tone_table) { + return app_tone_table[index]; + } + return NULL; +} + +void app_protocol_handle_register(struct app_protocol_private_handle_t *hd) +{ + private_handle = hd; +} + +struct app_protocol_private_handle_t *app_protocol_get_handle() +{ + return private_handle; +} + +//协议私有同步消息处理函数 +void app_protocol_tws_sync_private_deal(int cmd, int value) +{ + if (private_handle && private_handle->tws_sync_func) { + private_handle->tws_sync_func(cmd, value); + } +} + +//协议私有收到对耳数据处理函数 +void app_protocol_tws_rx_data_private_deal(u16 opcode, u8 *data, u16 len) +{ + if (private_handle && private_handle->tws_rx_from_siblling) { + private_handle->tws_rx_from_siblling(opcode, data, len); + } +} + +int app_protocol_sys_event_private_deal(struct sys_event *event) +{ + if (private_handle && private_handle->sys_event_handler) { + return private_handle->sys_event_handler(event); + } + return 0; +} + +#if APP_PROTOCOL_SPEECH_EN +#define APP_PROTOCOL_MIC_TIMEOUT 8000 //mic使用超时时间,0不限时 + +static u16 mic_timer = 0; +static u16 tone_after_exit_sniff_timer = 0; +static u8 exit_sniff_cnt = 0; +void __app_protocol_speech_stop(void) +{ + if (ai_mic_is_busy()) { + if (mic_timer) { + sys_timeout_del(mic_timer); + mic_timer = 0; + } + APP_PROTOCOL_LOG("app_protocol_speech_stop\n"); + + ai_mic_rec_close(); + app_protocol_stop_speech_cmd(); + } +} + +static void app_protocol_speech_timeout(void *priv) +{ + APP_PROTOCOL_LOG(" speech timeout !!! \n"); + __app_protocol_speech_stop(); +} + +static int app_protocol_speech_start_check() +{ + if (BT_STATUS_TAKEING_PHONE == get_bt_connect_status()) { + APP_PROTOCOL_LOG("phone ing...\n"); + return -1; + } + if (ai_mic_is_busy()) { + APP_PROTOCOL_LOG("mic activing...\n"); + return -1; + } + return 0; +} + +int __app_protocol_speech_start(void) +{ + if (!app_protocol_speech_start_check() && ai_mic_rec_start() == 0) { +#if APP_PROTOCOL_MIC_TIMEOUT + mic_timer = sys_timeout_add(NULL, app_protocol_speech_timeout, APP_PROTOCOL_MIC_TIMEOUT); +#endif + return 0; + } + APP_PROTOCOL_LOG("speech start fail\n"); + return -1; +} + +int app_protocol_start_speech_by_app(u8 tone_en) +{ + if (app_protocol_speech_start_check()) { + return -1; + } + if (app_var.siri_stu) { + APP_PROTOCOL_LOG("siri activing...\n"); + return -1; + } + if (tone_en) { + app_protocol_tone_play(APP_RROTOCOL_TONE_SPEECH_APP_START, 1); + } else { + app_protocol_post_bt_event(AI_EVENT_SPEECH_START, NULL); + } + return 0; +} + +int app_protocol_stop_speech_by_app() +{ + app_protocol_post_bt_event(AI_EVENT_SPEECH_STOP, NULL); + return 0; +} + +static void speech_tone_play_after_exit_sniff() +{ + tone_after_exit_sniff_timer = 0; + if (bt_is_sniff_close() && exit_sniff_cnt < 13) { + exit_sniff_cnt++; + tone_after_exit_sniff_timer = sys_timeout_add(NULL, speech_tone_play_after_exit_sniff, 100); + return; + } + exit_sniff_cnt = 0; + if (!app_protocol_speech_start_check()) { + app_protocol_tone_play(APP_RROTOCOL_TONE_SPEECH_KEY_START, 1); + } +} + +int app_protocol_start_speech_by_key(struct sys_event *event) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status() && !is_tws_master_role()) { + APP_PROTOCOL_LOG("tws slave, return\n"); + return 0; + } +#endif + + user_send_cmd_prepare(USER_CTRL_HFP_GET_SIRI_STATUS, 0, NULL); + if (app_protocol_speech_start_check()) { + return -1; + } + + if (app_protocol_check_connect_success() && (get_curr_channel_state()&A2DP_CH)) { + printf("no connect\n"); + } else { + if (get_curr_channel_state()&A2DP_CH) { + //<协议未连接, 但是A2DP已连接, 点击唤醒键, 提示TTS【请打开小度APP】 + if (is_ios_system()) { + APP_PROTOCOL_LOG("ble adv ibeaconn"); + app_protocol_ibeacon_switch(1); + } else { + user_send_cmd_prepare(USER_CTRL_HFP_GET_SIRI_OPEN, 0, NULL); + } + app_protocol_tone_play(APP_PROTOCOL_TONE_DISCONNECTED_ALL, 1); + } else { + //<蓝牙完全关闭状态, 用户按唤醒键, 提示TTS【蓝牙未连接, 请用手机蓝牙和我连接吧】 + app_protocol_tone_play(APP_RROTOCOL_TONE_OPEN_APP, 1); + } + APP_PROTOCOL_LOG("A2dp or protocol no connect err!!!\n"); + return -1; + } + + +#if 1//等退出sniff后再播提示音 + if (bt_is_sniff_close()) { + user_send_cmd_prepare(USER_CTRL_ALL_SNIFF_EXIT, 0, NULL); + if (tone_after_exit_sniff_timer == 0) { + tone_after_exit_sniff_timer = sys_timeout_add(NULL, speech_tone_play_after_exit_sniff, 100); + } + return 0; + } + exit_sniff_cnt = 0; +#endif + + app_protocol_tone_play(APP_RROTOCOL_TONE_SPEECH_KEY_START, 1); + return 0; +} + +int app_protocol_stop_speech_by_key(void) +{ + return 0; +} +#else +void __app_protocol_speech_stop(void) +{ +} +#endif + +void app_speech_tone_play_end_callback(void *priv, int flag) +{ + u32 index = (u32)priv; + switch (index) { +#if APP_PROTOCOL_SPEECH_EN + case APP_RROTOCOL_TONE_SPEECH_KEY_START: + APP_PROTOCOL_LOG("APP_RROTOCOL_TONE_SPEECH_KEY_START\n"); + if (app_protocol_speech_start_check()) { + break; + } + if (app_var.siri_stu) { + APP_PROTOCOL_LOG("siri activing...\n"); + break; + } + ///按键启动需要report, app启动, 直接启动语音即可 + if (is_tws_master_role() && !app_protocol_start_speech_cmd()) {//从转发mic数据给主机或主机上报完成开启mic + APP_PROTOCOL_LOG("app_protocol_mic_status_report success\n"); + app_protocol_post_bt_event(AI_EVENT_SPEECH_START, NULL); + } + break; + case APP_RROTOCOL_TONE_SPEECH_APP_START: + APP_PROTOCOL_LOG("APP_RROTOCOL_TONE_SPEECH_APP_START\n"); + if (app_protocol_speech_start_check()) { + break; + } + if (app_var.siri_stu) { + APP_PROTOCOL_LOG("siri activing...\n"); + break; + } + if (is_tws_master_role()) { + app_protocol_post_bt_event(AI_EVENT_SPEECH_START, NULL); + } + break; +#endif + default: + break; + } +} + +int app_protocol_set_volume(u8 vol) +{ + u8 vol_l = (vol * get_max_sys_vol()) / 0x64; + u8 vol_r = (vol * get_max_sys_vol()) / 0x64; + + app_audio_set_volume(APP_AUDIO_STATE_MUSIC, APP_AUDIO_STATE_MUSIC, vol_r); + return 0; +} +__attribute__((weak)) +bool vbat_is_low_power(void) +{ + return 0; +} +u8 app_protocal_get_bat_by_type(u8 type) +{ + u8 value = 0; + extern u8 get_tws_sibling_bat_persent(void); + u8 sibling_val = get_tws_sibling_bat_persent(); +#if TCFG_CHARGESTORE_ENABLE + if (sibling_val == 0xff) { + sibling_val = chargestore_get_sibling_power_level(); + } +#endif + switch (type) { + case APP_PROTOCOL_BAT_T_CHARGE_FLAG: + value = get_charge_online_flag(); + break; + case APP_PROTOCOL_BAT_T_MAIN: + value = get_vbat_percent(); + break; +#if TCFG_CHARGESTORE_ENABLE + case APP_PROTOCOL_BAT_T_BOX: + value = chargestore_get_power_level(); + break; +#endif + case APP_PROTOCOL_BAT_T_TWS_LEFT: + value = (tws_api_get_local_channel() == 'L') ? get_vbat_percent() : sibling_val; + break; + case APP_PROTOCOL_BAT_T_TWS_RIGHT: + value = (tws_api_get_local_channel() == 'R') ? get_vbat_percent() : sibling_val; + break; + case APP_PROTOCOL_BAT_T_TWS_SIBLING: + value = sibling_val; + break; + case APP_PROTOCOL_BAT_T_LOW_POWER: + value = vbat_is_low_power(); + break; + default: + break; + } + if (value == 0xff) { //获取不到电量返回0 + value = 0; + } + return value; +} + +u32 read_cfg_file(void *buf, u16 len, char *path) +{ + FILE *fp = fopen(path, "r"); + int rlen; + + if (!fp) { + //printf("read_cfg_file:fopen err!\n"); + return FALSE; + } + + rlen = fread(fp, buf, len); + if (rlen <= 0) { + //printf("read_cfg_file:fread err!\n"); + return FALSE; + } + + fclose(fp); + + return TRUE; +} + +#define LIC_PAGE_OFFSET 80 +#define FORCE_TO_ERASE 1 + +typedef enum _FLASH_ERASER { + CHIP_ERASER = 0, + BLOCK_ERASER, + SECTOR_ERASER, + PAGE_ERASER, +} FLASH_ERASER; + +typedef struct __flash_of_lic_para_head { + s16 crc; + u16 string_len; + const u8 para_string[]; +} __attribute__((packed)) _flash_of_lic_para_head; + +static bool license_para_head_check(u8 *para) +{ + _flash_of_lic_para_head *head; + + //fill head + head = (_flash_of_lic_para_head *)para; + + ///crc check + u8 *crc_data = (u8 *)(para + sizeof(((_flash_of_lic_para_head *)0)->crc)); + u32 crc_len = sizeof(_flash_of_lic_para_head) - sizeof(((_flash_of_lic_para_head *)0)->crc)/*head crc*/ + (head->string_len)/*content crc,include end character '\0'*/; + s16 crc_sum = 0; + + crc_sum = CRC16(crc_data, crc_len); + + if (crc_sum != head->crc) { + printf("license crc error !!! %x %x \n", (u32)crc_sum, (u32)head->crc); + return false; + } + + return true; +} + +//获取三元组信息的头指针 +const u8 *app_protocal_get_license_ptr(void) +{ + u32 flash_capacity = sdfile_get_disk_capacity(); + u32 flash_addr = flash_capacity - 256 + LIC_PAGE_OFFSET; + u8 *lic_ptr = NULL; + _flash_of_lic_para_head *head; + + printf("flash capacity:%x \n", flash_capacity); + lic_ptr = (u8 *)sdfile_flash_addr2cpu_addr(flash_addr); + + //head length check + head = (_flash_of_lic_para_head *)lic_ptr; + if (head->string_len >= 0xff) { + printf("license length error !!! \n"); + return NULL; + } + + ////crc check + if (license_para_head_check(lic_ptr) == (false)) { + printf("license head check fail\n"); + return NULL; + } + + //put_buf(lic_ptr, 128); + + lic_ptr += sizeof(_flash_of_lic_para_head); + return lic_ptr; +} + +extern bool sfc_erase(int cmd, u32 addr); +extern u32 sfc_write(const u8 *buf, u32 addr, u32 len); +//将三元组信息保存到flash里面 +int app_protocol_license2flash(const u8 *data, u16 len) +{ + _flash_of_lic_para_head header; + u8 buffer[256]; + u32 flash_capacity = sdfile_get_disk_capacity(); + u32 sector = flash_capacity - 4 * 1024; + u32 page_addr = flash_capacity - 256; + u8 *auif_ptr = (u8 *)sdfile_flash_addr2cpu_addr(page_addr); + +#if (!FORCE_TO_ERASE) + APP_PROTOCOL_LOG("not supported flash erase !!! \n"); + return (-1); +#endif + + ///save last 256 byte + /* memset(buffer, 0xff, sizeof(buffer)); */ + memcpy(buffer, auif_ptr, sizeof(buffer)); + auif_ptr += LIC_PAGE_OFFSET; + + header.string_len = len; + ///length + memcpy(&buffer[LIC_PAGE_OFFSET + sizeof(header.crc)], &(header.string_len), sizeof(header.string_len)); + ///context + memcpy(&buffer[LIC_PAGE_OFFSET + sizeof(header)], data, len); + ///crc + header.crc = CRC16(&buffer[LIC_PAGE_OFFSET + sizeof(header.crc)], sizeof(header.string_len) + header.string_len); + memcpy(&buffer[LIC_PAGE_OFFSET], &(header.crc), sizeof(header.crc)); + + ///check if need update data to flash,erease license erea if there are some informations in license erea + if (!memcmp(auif_ptr, buffer + LIC_PAGE_OFFSET, len + sizeof(_flash_of_lic_para_head))) { + APP_PROTOCOL_LOG("flash information the same with license\n"); + return 0; + } + + APP_PROTOCOL_LOG("erase license sector \n"); + sfc_erase(SECTOR_ERASER, sector); + + APP_PROTOCOL_LOG("write license to flash \n"); + sfc_write(buffer, page_addr, 256); + + return 0; +} + +int app_protocol_tws_send_to_sibling(u16 opcode, u8 *data, u16 len) +{ + u8 send_data[len + 4]; + printf("app protocol send data to sibling \n"); + send_data[0] = opcode & 0xff; + send_data[1] = opcode >> 8; + send_data[2] = len & 0xff; + send_data[3] = len >> 8; + memcpy(send_data + 4, data, len); + + return tws_api_send_data_to_sibling(send_data, sizeof(send_data), APP_PROTOCOL_TWS_SEND_ID); +} + +static void __tws_rx_from_sibling(u8 *data) +{ + u16 opcode = (data[1] << 8) | data[0]; + u16 len = (data[3] << 8) | data[2]; + u8 *rx_data = data + 4; + + switch (opcode) { + case APP_PROTOCOL_TWS_FOR_LIB: + APP_PROTOCOL_LOG("APP_PROTOCOL_TWS_FOR_LIB"); + app_protocol_get_tws_data_for_lib(rx_data, len); + break; + } + app_protocol_tws_rx_data_private_deal(opcode, rx_data, len); + + free(data); +} + +static void app_protocol_rx_from_sibling(void *_data, u16 len, bool rx) +{ + int err = 0; + if (rx) { + printf(">>>%s \n", __func__); + printf("len :%d\n", len); + put_buf(_data, len); + u8 *rx_data = malloc(len); + memcpy(rx_data, _data, len); + + int msg[4]; + msg[0] = (int)__tws_rx_from_sibling; + msg[1] = 1; + msg[2] = (int)rx_data; + err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg); + if (err) { + printf("tws rx post fail\n"); + } + } +} + + +//发送给对耳 +REGISTER_TWS_FUNC_STUB(app_vol_sync_stub) = { + .func_id = APP_PROTOCOL_TWS_SEND_ID, + .func = app_protocol_rx_from_sibling, +}; + +//对耳同步执行 +int app_protocol_tws_sync_send(int cmd, int value) +{ + int data[2]; + data[0] = cmd; + data[1] = value; + return tws_api_send_data_to_slave(data, sizeof(data), APP_PROTOCOL_TWS_SYNC_ID); +} + +void app_protocol_tws_sync_deal(int cmd, int value) +{ + switch (cmd) { + case APP_PROTOCOL_SYNC_TONE: + printf("APP_PROTOCOL_SYNC_TONE:%d\n", value); + app_protocol_tone_play(value, 0); + break; + } + app_protocol_tws_sync_private_deal(cmd, value); +} + +static void app_protocol_tws_sync_rx(void *data, u16 len, bool rx) +{ + int err = 0; + int *arg = (int *)data; + int msg[8]; + + msg[0] = (int)app_protocol_tws_sync_deal; + msg[1] = len / sizeof(int); + msg[2] = arg[0]; //cmd + msg[3] = arg[1]; //value + + err = os_taskq_post_type("app_core", Q_CALLBACK, 2 + len / sizeof(int), msg); + if (err) { + printf("tws sync post fail\n"); + } +} + +REGISTER_TWS_FUNC_STUB(app_protocol_sync) = { + .func_id = APP_PROTOCOL_TWS_SYNC_ID, + .func = app_protocol_tws_sync_rx, +}; + +//在app_core任务里面进行处理 +int app_protocol_post_app_core_callback(int callback, void *priv) +{ + int msg[8]; + msg[0] = callback; + msg[1] = 1; + msg[2] = (int)priv; + return os_taskq_post_type("app_core", Q_CALLBACK, 3, msg); +} + +void app_protocol_post_bt_event(u8 event, void *priv) +{ + struct sys_event e; + + memset(&e, 0, sizeof(e)); + e.type = SYS_BT_EVENT; + e.arg = (void *)SYS_BT_AI_EVENT_TYPE_STATUS; + e.u.bt.event = event; + e.u.bt.value = (int)priv; + sys_event_notify(&e); +} + + +static int app_protocol_bt_status_event_handler(struct bt_event *bt) +{ + switch (bt->event) { + case BT_STATUS_INIT_OK: + app_protocol_all_init(); + break; + case BT_STATUS_SECOND_CONNECTED: + case BT_STATUS_FIRST_CONNECTED: + if (app_protocol_check_connect_success()) { + app_protocol_tone_play(APP_PROTOCOL_TONE_CONNECTED_ALL_FINISH, 1); + } else { + app_protocol_tone_play(APP_PROTOCOL_TONE_CONNECTED_NEED_OPEN_APP, 1); + } + break; + case BT_STATUS_FIRST_DISCONNECT: + case BT_STATUS_SECOND_DISCONNECT: + app_protocol_tone_play(APP_PROTOCOL_TONE_DISCONNECTED, 1); + app_protocal_update_tws_state_to_lib(USER_NOTIFY_STATE_MOBILE_DISCONNECTED); + break; + case BT_STATUS_PHONE_INCOME: + case BT_STATUS_PHONE_OUT: + case BT_STATUS_PHONE_ACTIVE: + __app_protocol_speech_stop(); + app_protocol_ble_adv_switch(0); + break; + case BT_STATUS_PHONE_HANGUP: + app_protocol_ble_adv_switch(1); + break; + + case BT_STATUS_PHONE_MANUFACTURER: + if (!app_protocol_check_connect_success()) { + if (is_ios_system()) { + app_protocol_ibeacon_switch(1); + } + + if (get_call_status() != BT_CALL_HANGUP) { + app_protocol_ble_adv_switch(0); + } + } + break; + case BT_STATUS_VOICE_RECOGNITION: + if ((app_var.siri_stu == 1) || (app_var.siri_stu == 2)) { + __app_protocol_speech_stop(); + app_protocol_ble_adv_switch(0); + } else if (app_var.siri_stu == 0) { + app_protocol_ble_adv_switch(1); + } + break; + case BT_STATUS_CONN_A2DP_CH: + app_protocal_update_tws_state_to_lib(USER_NOTIFY_STATE_MOBILE_CONNECTED); + break; + } + return 0; +} + +static void app_protocol_bt_tws_event_handler(struct bt_event *bt) +{ + int role = bt->args[0]; + int phone_link_connection = bt->args[1]; + int reason = bt->args[2]; + + switch (bt->event) { + case TWS_EVENT_CONNECTED: + if (!is_tws_master_role()) { + app_protocol_disconnect(NULL); + app_protocol_ble_adv_switch(0); + } else { +#if APP_PROTOCOL_SPEECH_EN + if (ai_mic_is_busy()) { //mic在解码过程中,从机连接成功,挂起音频 + //ai_mic_tws_sync_suspend(); + } +#endif + } + app_protocal_update_tws_state_to_lib(USER_NOTIFY_STATE_TWS_CONNECT); + break; + case TWS_EVENT_CONNECTION_DETACH: + if (!app_protocol_check_connect_success()) { //APP未连接,开启广播 + if (0 == get_esco_coder_busy_flag()) { + //esco在用的时候开广播会影响质量 + app_protocol_ble_adv_switch(1); + } + } +#if APP_PROTOCOL_SPEECH_EN + if (!ai_mic_is_busy()) { + __app_protocol_speech_stop(); //对耳断开时没启动mic,停止语音 + } +#endif + app_protocal_update_tws_state_to_lib(USER_NOTIFY_STATE_BATTERY_LEVEL_UPDATE); //主动上报电量 + app_protocal_update_tws_state_to_lib(USER_NOTIFY_STATE_TWS_DISCONNECT); + break; + case TWS_EVENT_ROLE_SWITCH: + app_protocal_update_tws_state_to_lib(USER_NOTIFY_STATE_ROLE_SWITCH_FINISH); + app_protocol_disconnect(NULL); + if (role == TWS_ROLE_MASTER && (0 == get_esco_coder_busy_flag())) { + app_protocol_ble_adv_switch(1); + } else { + app_protocol_ble_adv_switch(0); + } + break; + } +} + +static int app_protocol_bt_ai_event_handler(struct bt_event *bt) +{ + switch (bt->event) { +#if APP_PROTOCOL_SPEECH_EN + case AI_EVENT_SPEECH_START: + APP_PROTOCOL_LOG("AI_EVENT_SPEECH_START"); + __app_protocol_speech_start(); + break; + case AI_EVENT_SPEECH_STOP: + APP_PROTOCOL_LOG("AI_EVENT_SPEECH_STOP"); + __app_protocol_speech_stop(); + break; +#endif + case AI_EVENT_APP_CONNECT: + APP_PROTOCOL_LOG("AI_EVENT_APP_CONNECT"); + if (get_curr_channel_state()&A2DP_CH) { + app_protocol_tone_play(APP_PROTOCOL_TONE_CONNECTED_ALL_FINISH, 1); + } else { + app_protocol_tone_play(APP_PROTOCOL_TONE_PROTOCOL_CONNECTED, 1); + } + break; + case AI_EVENT_APP_DISCONNECT: + APP_PROTOCOL_LOG("AI_EVENT_APP_DISCONNECT"); + __app_protocol_speech_stop(); + break; + } + return 0; +} + +int app_protocol_sys_event_handler(struct sys_event *event) +{ + switch (event->type) { + case SYS_BT_EVENT: + if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) { + app_protocol_bt_status_event_handler(&event->u.bt); + } +#if TCFG_USER_TWS_ENABLE + else if (((u32)event->arg == SYS_BT_EVENT_FROM_TWS)) { + app_protocol_bt_tws_event_handler(&event->u.bt); + } +#endif + else if (((u32)event->arg == SYS_BT_AI_EVENT_TYPE_STATUS)) { + app_protocol_bt_ai_event_handler(&event->u.bt); + } + break; + + case SYS_KEY_EVENT: + app_protocol_key_event_handler(event); + break; + } + app_protocol_sys_event_private_deal(event); + + return 0; +} +void tell_lib_start_role_switch() +{ + app_protocol_ble_adv_switch(0); + if (is_tws_master_role()) { + printf("master dev will role switch\n"); + app_protocal_update_tws_state_to_lib(USER_NOTIFY_STATE_ROLE_SWITCH_START); + /* os_time_dly(10); */ + } +} +#else +int app_protocol_sys_event_handler(struct sys_event *event) +{ + return 0; +} +void tell_lib_start_role_switch() +{ + +} + +#endif + + diff --git a/apps/common/third_party_profile/interface/app_protocol_common.h b/apps/common/third_party_profile/interface/app_protocol_common.h new file mode 100644 index 0000000..1618bac --- /dev/null +++ b/apps/common/third_party_profile/interface/app_protocol_common.h @@ -0,0 +1,108 @@ + + +#ifndef _3TH_PROTOCOL_COMMON_H +#define _3TH_PROTOCOL_COMMON_H + +#include +#include +#include "typedef.h" +#include "tone_player.h" +#include "audio_base.h" +#include "system/event.h" + +#ifndef TONE_RES_ROOT_PATH +#if TCFG_NOR_FS && (TCFG_VIRFAT_FLASH_ENABLE == 0) +#define NOR_FLASH_RES_ROOT_PATH "storage/res_nor/C/" +#define TONE_RES_ROOT_PATH NOR_FLASH_RES_ROOT_PATH //内置flash提示音根路径 +#else +#define TONE_RES_ROOT_PATH SDFILE_RES_ROOT_PATH //内置flash提示音根路径 +#endif//TCFG_NOR_FS +#endif + +#define APP_PROTOCOL_TWS_SYNC_ID 0xFFFF321A +#define APP_PROTOCOL_TWS_SEND_ID 0xFFFF321B + +enum { + APP_PROTOCOL_TONE_CONNECTED_ALL_FINISH = 0,//所有连接完成【已连接,你可以按AI键来和我进行对话】 ok + APP_PROTOCOL_TONE_PROTOCOL_CONNECTED,//APP已连接,经典蓝牙未连接【请在手机上完成蓝牙配对】 con + APP_PROTOCOL_TONE_CONNECTED_NEED_OPEN_APP,//经典蓝牙已连接,app未连接【已配对,请打开app进行连接】 btcon + APP_PROTOCOL_TONE_DISCONNECTED,//经典蓝牙已断开【蓝牙已断开,请在手机上完成蓝牙配对】 dis + APP_PROTOCOL_TONE_DISCONNECTED_ALL,//经典蓝牙和【蓝牙未连接,请用手机蓝牙和我连接吧】alldis + APP_RROTOCOL_TONE_OPEN_APP,//经典蓝牙已连接,APP未连接【请打开APP】 app + APP_RROTOCOL_TONE_SPEECH_APP_START,//手机APP启动语音助手 + APP_RROTOCOL_TONE_SPEECH_KEY_START,//按键启动语音助手 + APP_RROTOCOL_TONE_MAX,//提示音最大数量 +}; + +//发送给对耳的消息,格式为:opcode len data +enum { + APP_PROTOCOL_TWS_FOR_LIB = 0, + + GMA_TWS_CMD_SYNC_LIC, +}; + +//对耳同步的命令,格式为cmd value +enum { + APP_PROTOCOL_SYNC_TONE = 0, +}; + +//发送到系统事件处理的事件 +enum { + AI_EVENT_SPEECH_START = 0, + AI_EVENT_SPEECH_STOP, + AI_EVENT_APP_CONNECT, + AI_EVENT_APP_DISCONNECT, +}; + +struct app_protocol_private_handle_t { + void (*tws_rx_from_siblling)(u16 opcode, u8 *data, u16 len); //收到对耳数据的处理接口 + void (*tws_sync_func)(int cmd, int value); //对耳同步执行的接口 + int (*sys_event_handler)(struct sys_event *event); //系统事件 +}; + +//提示音注册和播放 +void app_protocol_tone_register(const char **tone_table); +const char *app_protocol_get_tone(int index); +void app_protocol_tone_play(int index, int tws_sync); +void app_speech_tone_play_end_callback(void *priv, int flag); //提示音播放完毕回调函数 + + +extern int ai_mic_is_busy(void); //mic正在被使用 +extern int ai_mic_rec_start(void); //启动mic和编码模块 +extern int ai_mic_rec_close(void); //停止mic和编码模块 +extern bool bt_is_sniff_close(void); + +//语音识别接口 +int mic_rec_pram_init(/* const char **name, */u32 enc_type, u8 opus_type, u16(*speech_send)(u8 *buf, u16 len), u16 frame_num, u16 cbuf_size); +int __app_protocol_speech_start(void); +void __app_protocol_speech_stop(void); +int app_protocol_start_speech_by_app(u8 tone_en); //APP启动 +int app_protocol_stop_speech_by_app(); //APP停止 +int app_protocol_start_speech_by_key(struct sys_event *event); //按键启动 +int app_protocol_stop_speech_by_key(void); //按键停止 + + +//协议获取和设置一些设备信息接口 +int app_protocol_set_volume(u8 vol); +u8 app_protocal_get_bat_by_type(u8 type); +u32 read_cfg_file(void *buf, u16 len, char *path); +const u8 *app_protocal_get_license_ptr(void); //获取三元组信息的头指针 +int app_protocol_license2flash(const u8 *data, u16 len); //将三元组信息保存到flash里面 + +//事件处理函数指针列表注册和接口 +void app_protocol_handle_register(struct app_protocol_private_handle_t *hd); +struct app_protocol_private_handle_t *app_protocol_get_handle(); +void app_protocol_tws_sync_private_deal(int cmd, int value); //对耳同步事件私有协议处理函数 +void app_protocol_tws_rx_data_private_deal(u16 opcode, u8 *data, u16 len); //私有协议处理来自对耳的数据函数 +int app_protocol_sys_event_private_deal(struct sys_event *event); //私有协议处理系统事件函数 + +void app_protocol_post_bt_event(u8 event, void *priv); //发送到系统事件处理 +int app_protocol_post_app_core_callback(int callback, void *priv); //放到app_core中处理 +int app_protocol_tws_send_to_sibling(u16 opcode, u8 *data, u16 len); //发送命令数据给对耳 +int app_protocol_tws_sync_send(int cmd, int value); //对耳同步执行命令 + +int app_protocol_key_event_handler(struct sys_event *event); //按键事件处理函数 +int app_protocol_sys_event_handler(struct sys_event *event); //系统事件处理函数 + +#endif + diff --git a/apps/common/third_party_profile/interface/app_protocol_dma.c b/apps/common/third_party_profile/interface/app_protocol_dma.c new file mode 100644 index 0000000..af33dac --- /dev/null +++ b/apps/common/third_party_profile/interface/app_protocol_dma.c @@ -0,0 +1,150 @@ +#include +#include +#include + +#include "app_protocol_api.h" +#include "system/includes.h" +#include "vm.h" +#include "audio_config.h" +#include "app_power_manage.h" +#include "user_cfg.h" +#if APP_PROTOCOL_DMA_CODE + +#if 1 +#define APP_DMA_LOG printf +#define APP_DMA_DUMP put_buf +#else +#define APP_DMA_LOG(...) +#define APP_DMA_DUMP(...) +#endif + +//*********************************************************************************// +// DMA认证信息 // +//*********************************************************************************// +//调试阶段:DMA_PRODUCT_INFO_TEST宏可以开启调试 +//生产阶段:DMA_PRODUCT_INFO_TEST宏需关闭 +#define DMA_PRODUCT_INFO_TEST 0 + +#if DMA_PRODUCT_INFO_TEST +static const char *dma_product_id = "abcdeYghv0fy6HFexl6bTIZU123Z4n6H"; +static const char *dma_triad_id = "A254BcBb000E00D200A0C0E3"; +static const char *dma_secret = "bab8d7e0dc616630"; +#endif +static const char *dma_product_key = "rcPXDpFbBOxXaDL9GZ8qLTWq7Yz8rWFm"; + +#define DMA_PRODUCT_ID_LEN 65 +#define DMA_PRODUCT_KEY_LEN 65 +#define DMA_TRIAD_ID_LEN 32 +#define DMA_SECRET_LEN 32 + +#define DMA_LEGAL_CHAR(c) ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) + +static u16 dma_get_one_info(const u8 *in, u8 *out) +{ + int read_len = 0; + const u8 *p = in; + + while (DMA_LEGAL_CHAR(*p) && *p != ',') { //read Product ID + *out++ = *p++; + read_len++; + } + return read_len; +} + +u8 read_dma_product_info_from_flash(u8 *read_buf, u16 buflen) +{ + u8 *rp = read_buf; + const u8 *dma_ptr = (u8 *)app_protocal_get_license_ptr(); + + if (dma_ptr == NULL) { + return FALSE; + } + + if (dma_get_one_info(dma_ptr, rp) != 32) { + return FALSE; + } + dma_ptr += 33; + + rp = read_buf + DMA_PRODUCT_ID_LEN; + memcpy(rp, dma_product_key, strlen(dma_product_key)); + + rp = read_buf + DMA_PRODUCT_ID_LEN + DMA_PRODUCT_KEY_LEN; + if (dma_get_one_info(dma_ptr, rp) != 24) { + return FALSE; + } + dma_ptr += 25; + + rp = read_buf + DMA_PRODUCT_ID_LEN + DMA_PRODUCT_KEY_LEN + DMA_TRIAD_ID_LEN; + if (dma_get_one_info(dma_ptr, rp) != 16) { + return FALSE; + } + + return TRUE; +} +__attribute__((weak)) +void bt_update_testbox_addr(u8 *addr) +{ + +} +void dueros_dma_manufacturer_info_init() +{ + u8 read_buf[DMA_PRODUCT_ID_LEN + DMA_PRODUCT_KEY_LEN + DMA_TRIAD_ID_LEN + DMA_SECRET_LEN + 1] = {0}; + bool ret = FALSE; + + APP_DMA_LOG("dueros_dma_manufacturer_info_init\n"); + +#if DMA_PRODUCT_INFO_TEST + memcpy(read_buf, dma_product_id, strlen(dma_product_id)); + memcpy(read_buf + DMA_PRODUCT_ID_LEN, dma_product_key, strlen(dma_product_key)); + memcpy(read_buf + DMA_PRODUCT_ID_LEN + DMA_PRODUCT_KEY_LEN, dma_triad_id, strlen(dma_triad_id)); + memcpy(read_buf + DMA_PRODUCT_ID_LEN + DMA_PRODUCT_KEY_LEN + DMA_TRIAD_ID_LEN, dma_secret, strlen(dma_secret)); + ret = TRUE; +#else + ret = read_dma_product_info_from_flash(read_buf, sizeof(read_buf)); +#endif + + if (ret == TRUE) { + APP_DMA_LOG("read license success\n"); + APP_DMA_LOG("product id: %s\n", read_buf); + APP_DMA_LOG("product key: %s\n", read_buf + DMA_PRODUCT_ID_LEN); + APP_DMA_LOG("triad id: %s\n", read_buf + DMA_PRODUCT_ID_LEN + DMA_PRODUCT_KEY_LEN); + APP_DMA_LOG("secret: %s\n", read_buf + DMA_PRODUCT_ID_LEN + DMA_PRODUCT_KEY_LEN + DMA_TRIAD_ID_LEN); + app_protocol_set_info_group(DMA_HANDLER_ID, read_buf); + } else { + app_protocol_set_info_group(DMA_HANDLER_ID, NULL); + } +//调试阶段:可以开启if 1调试 +//生产阶段:烧写器固定MAC地址 连接小度APP后与MAC地址绑定,因此下面代码需用if 0屏蔽掉 +#if 0 + u8 mac[] = {0xF4, 0x43, 0x8D, 0x29, 0x17, 0x02}; + u8 ble_mac[6]; + void bt_update_mac_addr(u8 * addr); + void lmp_hci_write_local_address(const u8 * addr); + void bt_update_testbox_addr(u8 * addr); + extern int le_controller_set_mac(void *addr); + //extern void lib_make_ble_address(u8 * ble_address, u8 * edr_address); + bt_update_mac_addr(mac); + lmp_hci_write_local_address(mac); + bt_update_testbox_addr(mac); + //lib_make_ble_address(ble_mac, mac); + le_controller_set_mac(mac); //修改BLE地址 + APP_DMA_DUMP(mac, 6); + APP_DMA_DUMP(ble_mac, 6); +#endif +} + +//*********************************************************************************// +// DMA提示音 // +//*********************************************************************************// +const char *dma_notice_tab[APP_RROTOCOL_TONE_MAX] = { + [APP_PROTOCOL_TONE_CONNECTED_ALL_FINISH] = TONE_RES_ROOT_PATH"tone/xd_ok.*",//所有连接完成【已连接,你可以按AI键来和我进行对话】 + [APP_PROTOCOL_TONE_PROTOCOL_CONNECTED] = TONE_RES_ROOT_PATH"tone/xd_con.*",//小度APP已连接,经典蓝牙未连接【请在手机上完成蓝牙配对】 + [APP_PROTOCOL_TONE_CONNECTED_NEED_OPEN_APP] = TONE_RES_ROOT_PATH"tone/xd_btcon.*",//经典蓝牙已连接,小度app未连接【已配对,请打开小度app进行连接】 + [APP_PROTOCOL_TONE_DISCONNECTED] = TONE_RES_ROOT_PATH"tone/xd_dis.*",//经典蓝牙已断开【蓝牙已断开,请在手机上完成蓝牙配对】 + [APP_PROTOCOL_TONE_DISCONNECTED_ALL] = TONE_RES_ROOT_PATH"tone/xd_alldis.*",//经典蓝牙和小度都断开了【蓝牙未连接,请用手机蓝牙和我连接吧】 + [APP_RROTOCOL_TONE_SPEECH_APP_START] = TONE_NORMAL, + [APP_RROTOCOL_TONE_SPEECH_KEY_START] = TONE_NORMAL, +}; + +#endif + diff --git a/apps/common/third_party_profile/interface/app_protocol_gma.c b/apps/common/third_party_profile/interface/app_protocol_gma.c new file mode 100644 index 0000000..a4fd614 --- /dev/null +++ b/apps/common/third_party_profile/interface/app_protocol_gma.c @@ -0,0 +1,557 @@ +#include +#include +#include + +#include "app_protocol_api.h" +#include "system/includes.h" +#include "vm.h" +#include "audio_config.h" +#include "app_power_manage.h" +#include "user_cfg.h" + +#if APP_PROTOCOL_GMA_CODE + +#if 1 +#define APP_GMA_LOG printf +#define APP_GMA_DUMP put_buf +#else +#define APP_GMA_LOG(...) +#define APP_GMA_DUMP(...) +#endif + +//*********************************************************************************// +// GMA认证信息 // +//*********************************************************************************// + +#define GMA_GMA_FROM_FLASH 0 +#define GMA_GMA_FROM_FILE 1 + +#define GMA_GMA_SOURCH GMA_GMA_FROM_FLASH + + +extern int le_controller_set_mac(void *addr); +extern void lmp_hci_write_local_address(const u8 *addr); +extern void lmp_hci_read_local_address(u8 *addr); +extern void bt_update_testbox_addr(u8 *addr); + +typedef struct { + uint8_t mac[6]; + uint32_t pid; + uint8_t secret[16]; +} ali_para_s; + +static ali_para_s ali_para; +static ali_para_s *active_ali_para = NULL; + +///mac reverse +void gma_mac_addr_reverse_get(uint8_t *buf) +{ + memcpy(buf, (const void *)active_ali_para->mac, 6); +} + +#define LEGAL_PID_NUM(cha) (cha>='0' && cha<='9') +#define LEGAL_MAC_NUM(cha) ((cha>='0'&&cha<='9') || (cha>='a'&&cha<='f') || (cha>='A'&&cha<='F') || (cha==':')) +#define LEGAL_SECRET_NUM(cha) ((cha>='0'&&cha<='9') || (cha>='a'&&cha<='f') || (cha>='A'&&cha<='F')) + +#define USELESS_CHAR ':' +#define GMA_ALI_PARA_END_CHAR ',' +#define GMA_ALI_PARA_MAC_CHAR_NUMS (sizeof(((ali_para_s *)0)->mac)) +#define GMA_ALI_PARA_PID_CHAR_NUMS 4//(sizeof(((ali_para_s *)0)->pid)) +#define GMA_ALI_PARA_SECRET_CHAR_NUMS (sizeof(((ali_para_s *)0)->secret)) + +static u8 gma_ali_para_char2num(u8 cha) +{ + u8 num = 0; + + if (cha >= '0' && cha <= '9') { + num = cha - '0'; + } else if (cha >= 'a' && cha <= 'f') { + num = cha - 'a' + 10; + } else if (cha >= 'A' && cha <= 'F') { + num = cha - 'A' + 10; + } + + return num; +} + +static int gma_license_set(ali_para_s *ali_para) +{ + const u8 *gma_ptr = (u8 *)app_protocal_get_license_ptr(); + + if (gma_ptr == NULL) { + return -1; + } + + ///license fill + //pid + memcpy((u8 *) & (ali_para->pid), gma_ptr, sizeof(ali_para->pid)); + gma_ptr += sizeof(ali_para->pid); + APP_GMA_LOG("gma pid:%d \n", ali_para->pid); + //secret + memcpy((u8 *)(ali_para->secret), gma_ptr, sizeof(ali_para->secret)); + gma_ptr += sizeof(ali_para->secret); + APP_GMA_LOG("gma secret:"); + APP_GMA_DUMP(ali_para->secret, sizeof(ali_para->secret)); + //mac + memcpy((u8 *)(ali_para->mac), gma_ptr, sizeof(ali_para->mac)); + gma_ptr += sizeof(ali_para->mac); + { + //mac reverse + u8 mac_backup_buf[6]; + memcpy(mac_backup_buf, ali_para->mac, 6); + int i; + for (i = 0; i < 6; i++) { + ali_para->mac[i] = (mac_backup_buf)[5 - i]; + } + } + APP_GMA_LOG("gma mac:"); + APP_GMA_DUMP(ali_para->mac, sizeof(ali_para->mac)); + + return 0; +} + +#if GMA_GMA_SOURCH == GMA_GMA_FROM_FILE + +#define ALI_PARA_ACTIVE_NUM 1 + +static const char *ali_para_string[] = { + "jl_auif", + //Product ID,Device Secret,Mac,Md5 + //此处可以用户自行填写从阿里申请的三元组信息 + " ", +}; + +static bool gma_ali_para_info_fill(const u8 *para, ali_para_s *ali_para) +{ + const u8 *para_string = para; + u8 highbit_en = 0; + uint32_t pid = 0; + uint32_t char_nums = 0; + uint8_t *secret = ali_para->secret; + uint8_t *mac = ali_para->mac; + + while (*para_string && *para_string != GMA_ALI_PARA_END_CHAR) { + if (!LEGAL_PID_NUM(*para_string)) { + /* APP_GMA_LOG("pid illegal character !!! \n"); */ + para_string++; + continue; + } + + ///check pid character numbers legal scope + char_nums++; + if (char_nums > GMA_ALI_PARA_PID_CHAR_NUMS) { + APP_GMA_LOG("pid character numbers overflow !!! \n"); + return false; + } + + pid *= 10; + pid += gma_ali_para_char2num(*para_string); + para_string++; + } + + ///check pid character numbers legal scope + if (char_nums != GMA_ALI_PARA_PID_CHAR_NUMS) { + APP_GMA_LOG("pid character numbers error:%d !!! \n", char_nums); + return false; + } + + APP_GMA_LOG(">>pid:%d \n", pid); + ali_para->pid = pid; + + para_string++; + char_nums = 0; + memset(ali_para->secret, 0x00, sizeof(ali_para->secret)); + while (*para_string != GMA_ALI_PARA_END_CHAR) { + if (!LEGAL_SECRET_NUM(*para_string)) { + APP_GMA_LOG("secret illegal character !!! \n"); + para_string++; + continue; + } + + ///assignment secret + if (!highbit_en) { + *secret += gma_ali_para_char2num(*para_string); + highbit_en ^= 1; + } else { + ///check secret character numbers legal scope + char_nums++; + if (char_nums > GMA_ALI_PARA_SECRET_CHAR_NUMS) { + APP_GMA_LOG("secret character number overflow !!! \n"); + return false; + } + + *secret <<= 4; + *secret++ += gma_ali_para_char2num(*para_string); + highbit_en ^= 1; + } + + para_string++; + } + + ///check secret character numbers legal scope + if (char_nums != GMA_ALI_PARA_SECRET_CHAR_NUMS) { + APP_GMA_LOG("secret character number error !!! :%d \n", char_nums); + return false; + } + + ///print secret + APP_GMA_LOG(">>ali_para secret: "); + for (int i = 0; i < sizeof(ali_para->secret) / sizeof(ali_para->secret[0]); i++) { + APP_GMA_LOG("%x ", ali_para->secret[i]); + } + + memset(ali_para->mac, 0x00, sizeof(ali_para->mac)); + para_string++; + highbit_en = 0; + char_nums = 0; + while (*para_string != GMA_ALI_PARA_END_CHAR) { + //if legal character + if (!LEGAL_MAC_NUM(*para_string)) { + APP_GMA_LOG("mac illegal character !!! \n"); + para_string++; + continue; +// return false; + } + + if (*para_string == USELESS_CHAR) { + para_string++; + continue; + } + + ///assignment mac + if (!highbit_en) { + *mac += gma_ali_para_char2num(*para_string); + highbit_en ^= 1; + } else { + //check mac character numbers legal scope + char_nums++; + if (char_nums > GMA_ALI_PARA_MAC_CHAR_NUMS) { + APP_GMA_LOG("mac character numbers overflow !!! \n"); + return false; + } + + *mac <<= 4; + *mac++ += gma_ali_para_char2num(*para_string); + highbit_en ^= 1; + } + + para_string++; + } + + //check mac character numbers legal scope + if (char_nums != GMA_ALI_PARA_MAC_CHAR_NUMS) { + APP_GMA_LOG("mac character numbers error !!! \n"); + return false; + } + + ///mac reverse + for (int i = 0, tmp_mac = 0, array_size = (sizeof(ali_para->mac) / sizeof(ali_para->mac[0])); \ + i < (sizeof(ali_para->mac) / sizeof(ali_para->mac[0]) / 2); i++) { + tmp_mac = ali_para->mac[i]; + ali_para->mac[i] = ali_para->mac[array_size - 1 - i]; + ali_para->mac[array_size - 1 - i] = tmp_mac; + } + + ///print secret + APP_GMA_LOG(">>ali_para mac: "); + for (int i = 0; i < sizeof(ali_para->mac) / sizeof(ali_para->mac[0]); i++) { + APP_GMA_LOG("%x ", ali_para->mac[i]); + } + return true; +} + +static int gma_license2flash(const ali_para_s *ali_para) +{ + int i; + u8 mac[6]; + u8 rdata[sizeof(ali_para_s)]; + + for (i = 0; i < sizeof(mac); i++) { + mac[i] = ali_para->mac[5 - i]; + } + memcpy(rdata, &ali_para->pid, sizeof(ali_para->pid)); + memcpy(rdata + sizeof(ali_para->pid), ali_para->secret, sizeof(ali_para->secret)); + memcpy(rdata + sizeof(ali_para->pid) + sizeof(ali_para->secret), mac, sizeof(mac)); + + return app_protocol_license2flash(rdata, sizeof(rdata)); +} + +#endif + + +#if TCFG_USER_TWS_ENABLE +#include "bt_tws.h" +static ali_para_s ali_para_remote; //对耳的三元组 + +//VM_GMA_MAC 对耳的地址 +//VM_GMA_ALI_PARA 对耳的三元组 + +static int gma_strcmp(const u8 *ptr1, const u8 *ptr2, u8 len) +{ + while (len--) { + if (*ptr1 != *ptr2) { + return (*ptr1 - *ptr2); + } + + ptr1++; + ptr2++; + } + + return 0; +} + +///mac reverse +u8 *gma_sibling_mac_get() //获取地址较小的那个 +{ + ali_para_s *sibling_ali_para = NULL;//&ali_para; + if (active_ali_para == &ali_para) { + printf("ali_para active \n"); + sibling_ali_para = &ali_para_remote; + } + + if (active_ali_para == &ali_para_remote) { + printf("ali_para active \n"); + sibling_ali_para = &ali_para; + } + + return (sibling_ali_para ? sibling_ali_para->mac : NULL); +} + +int gma_select_ali_para_by_common_mac() +{ + u8 ret = 0; + u8 mac[6]; + u8 mac_buf_tmp[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + ret = syscfg_read(CFG_TWS_COMMON_ADDR, mac, 6); + if (ret != 6 || !memcmp(mac, mac_buf_tmp, 6)) { + printf("tws no conn\n"); + return -1; + } + APP_GMA_LOG("active mac:"); + APP_GMA_DUMP(mac, 6); + ///select para + ali_para_s ali_para_temp; + syscfg_read(VM_GMA_ALI_PARA, (u8 *) &ali_para_temp, sizeof(ali_para_s)); + if (ali_para_temp.pid == ali_para.pid) { + memcpy(&ali_para_remote, &ali_para_temp, sizeof(ali_para_s)); + APP_GMA_LOG("remote mac:"); + APP_GMA_DUMP(ali_para_remote.mac, 6); + APP_GMA_LOG("remote pid:%d \n", ali_para_remote.pid); + APP_GMA_LOG("remote secret:"); + APP_GMA_DUMP(ali_para_remote.secret, sizeof(ali_para_remote.secret)); + if (gma_strcmp(mac, ali_para_remote.mac, 6) == 0) { + APP_GMA_LOG("used remote para \n"); + active_ali_para = &ali_para_remote; + return 0; + } else if (gma_strcmp(mac, ali_para.mac, 6) == 0) { + APP_GMA_LOG("used local para \n"); + active_ali_para = &ali_para; + return 0; + } else { + APP_GMA_LOG("MAC ERROR !!!!!!!!!!!!!!!!\n"); + return -1; + } + } else { + APP_GMA_LOG("no remote mac \n"); + } + return -1; +} + +void gma_slave_sync_remote_addr(u8 *buf) +{ + u8 common_addr[6]; + ///remote ali_para fill + memcpy(&ali_para_remote, buf, sizeof(ali_para_remote)); + syscfg_write(VM_GMA_MAC, ali_para_remote.mac, 6); + + ///write ali para to vm + syscfg_write(VM_GMA_ALI_PARA, (u8 *)&ali_para_remote, sizeof(ali_para_remote)); + + tws_api_get_local_addr(common_addr); + if (memcmp(active_ali_para->mac, common_addr, 6)) { //common地址发生变化 + APP_GMA_LOG("gma addr change"); + ///used slave address + active_ali_para = &ali_para_remote; + app_protocol_set_tws_sibling_mac(ali_para.mac); + app_protocol_set_info_group(GMA_HANDLER_ID, active_ali_para); //设置三元组 + //断开APP接口 + if (is_tws_master_role()) { + APP_GMA_LOG("gma need reconn app"); + app_protocol_disconnect(NULL); + app_protocol_ble_adv_switch(0); + le_controller_set_mac(active_ali_para->mac); + app_protocol_ble_adv_switch(1); + } + } +} + +#ifdef CONFIG_NEW_BREDR_ENABLE +void tws_host_get_common_addr(u8 *remote_addr, u8 *common_addr, char channel) +#else +void tws_host_get_common_addr(u8 *local_addr, u8 *remote_addr, u8 *common_addr, char channel) +#endif +{ + APP_GMA_LOG(">>>>>>>>>tws_host_get_common_addr ch:%c \n", channel); + + u8 mac_buf[6]; + gma_mac_addr_reverse_get(mac_buf); + APP_GMA_LOG(">>>local mac: "); + APP_GMA_DUMP(mac_buf, 6); + ///used the bigger one as host bt mac + if (gma_strcmp(mac_buf, (const u8 *)remote_addr, 6) < 0) { + ///used slave mac addr;remote_addr from slave addr reverse + memcpy(common_addr, remote_addr, 6); + } else { + ///used master mac addr + gma_mac_addr_reverse_get(common_addr); + } + APP_GMA_LOG("common_addr: "); + APP_GMA_DUMP((const u8 *)common_addr, 6); + APP_GMA_LOG("remote_addr: "); + APP_GMA_DUMP((const u8 *)remote_addr, 6); +} + +void gma_kick_license_to_sibling(void) +{ + APP_GMA_LOG("send license info to sibling\n"); + app_protocol_tws_send_to_sibling(GMA_TWS_CMD_SYNC_LIC, (u8 *) & (ali_para), sizeof(ali_para));; +} + +void gma_tws_remove_paired(void) +{ + ali_para_s ali_para_temp; + memset(&ali_para_temp, 0xff, sizeof(ali_para_s)); + syscfg_write(VM_GMA_ALI_PARA, (u8 *)&ali_para_temp, sizeof(ali_para_s)); + + active_ali_para = &ali_para; + app_protocol_set_tws_sibling_mac(ali_para_temp.mac); + app_protocol_set_info_group(GMA_HANDLER_ID, active_ali_para); //设置三元组 + + app_protocol_disconnect(NULL); + app_protocol_ble_adv_switch(0); + le_controller_set_mac(active_ali_para->mac); + app_protocol_ble_adv_switch(1); +} + +#endif + +__attribute__((weak)) +void bt_update_testbox_addr(u8 *addr) +{ + +} +int gma_prev_init(void) +{ + int err = 0; + /* ali_para_s ali_para; */ +#if GMA_GMA_SOURCH == GMA_GMA_FROM_FLASH + err = gma_license_set(&ali_para); +#elif GMA_GMA_SOURCH == GMA_GMA_FROM_FILE + u8 *ali_str = ali_para_string[ALI_PARA_ACTIVE_NUM]; + u8 ali_license[128] = {0}; + + //check if exist flash file + if (read_cfg_file(ali_license, sizeof(ali_license), SDFILE_RES_ROOT_PATH"license.txt") == TRUE) { + ali_str = ali_license; + } + APP_GMA_LOG("ali_str:%s\n", ali_str); + if (gma_ali_para_info_fill((const u8 *)ali_str, &ali_para) == false) { + APP_GMA_LOG("array context not good \n"); +///read license from flash + err = gma_license_set(&ali_para); + } +///write license to flash + if (!err) { + /* gma_license2flash(&ali_para); */ + } +#endif + if (!err) { + active_ali_para = &ali_para; +#if TCFG_USER_TWS_ENABLE + if (!gma_select_ali_para_by_common_mac()) { + app_protocol_set_tws_sibling_mac(gma_sibling_mac_get()); + } +#endif + app_protocol_set_info_group(GMA_HANDLER_ID, active_ali_para); //设置三元组 + bt_update_mac_addr(active_ali_para->mac); + lmp_hci_write_local_address(active_ali_para->mac); + app_protocol_ble_adv_switch(0); + le_controller_set_mac(active_ali_para->mac); //修改BLE地址 + bt_update_testbox_addr(ali_para.mac); + } + return err; +} + + +//*********************************************************************************// +// GMA 提示音 // +//*********************************************************************************// +const char *gma_tone_tab[APP_RROTOCOL_TONE_MAX] = { + [APP_RROTOCOL_TONE_SPEECH_KEY_START] = TONE_NORMAL, +}; + +//*********************************************************************************// +// DMA私有消息处理 // +//*********************************************************************************// +#if TCFG_USER_TWS_ENABLE +void gma_rx_tws_data_deal(u16 opcode, u8 *data, u16 len) +{ + switch (opcode) { + case GMA_TWS_CMD_SYNC_LIC: + printf(">>> TWS_AI_GMA_START_SYNC_LIC \n"); + gma_slave_sync_remote_addr(data); + break; + } +} + +static void gma_bt_tws_event_handler(struct bt_event *bt) +{ + int role = bt->args[0]; + int phone_link_connection = bt->args[1]; + int reason = bt->args[2]; + + switch (bt->event) { + case TWS_EVENT_CONNECTED: + gma_kick_license_to_sibling(); + break; + case TWS_EVENT_REMOVE_PAIRS: + gma_tws_remove_paired(); + break; + } +} +#endif + +static int gma_bt_status_event_handler(struct bt_event *bt) +{ + return 0; +} + +int gma_sys_event_deal(struct sys_event *event) +{ + switch (event->type) { + case SYS_BT_EVENT: + if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) { + gma_bt_status_event_handler(&event->u.bt); + } +#if TCFG_USER_TWS_ENABLE + else if (((u32)event->arg == SYS_BT_EVENT_FROM_TWS)) { + gma_bt_tws_event_handler(&event->u.bt); + } +#endif + break; + + } + + return 0; + +} + +struct app_protocol_private_handle_t gma_private_handle = { +#if TCFG_USER_TWS_ENABLE + .tws_rx_from_siblling = gma_rx_tws_data_deal, +#endif + /* .tws_sync_func = ; */ + .sys_event_handler = gma_sys_event_deal, +}; +#endif + diff --git a/apps/common/third_party_profile/interface/app_protocol_mma.c b/apps/common/third_party_profile/interface/app_protocol_mma.c new file mode 100644 index 0000000..8b9cc99 --- /dev/null +++ b/apps/common/third_party_profile/interface/app_protocol_mma.c @@ -0,0 +1,146 @@ +#include +#include +#include + +#include "app_protocol_api.h" +#include "system/includes.h" +#include "audio_config.h" +#include "app_power_manage.h" +#include "user_cfg.h" +#include "bt_tws.h" +#include "custom_cfg.h" + +#if APP_PROTOCOL_MMA_CODE + +#if 1 +#define APP_MMA_LOG printf +#define APP_MMA_DUMP put_buf +#else +#define APP_MMA_LOG(...) +#define APP_MMA_DUMP(...) +#endif +//*********************************************************************************// +// MMA初始化 // +//*********************************************************************************// + +void mma_prev_init() +{ + u16 pid = 0x210c; + u16 vid = 0x05d6; + u16 ver = 0x1100; +#if APP_PROTOCOL_READ_CFG_EN + vid = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG); + pid = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG); + ver = get_vid_pid_ver_from_cfg_file(GET_VER_FROM_EX_CFG); +#endif + APP_MMA_LOG("mma pid:%x, vid:%x, ver:%x\n", pid, vid, ver); + app_protocol_set_vendor_id(MMA_HANDLER_ID, vid); + app_protocol_set_product_id(MMA_HANDLER_ID, pid); + app_protocol_set_local_version(MMA_HANDLER_ID, ver); +} + +//*********************************************************************************// +// MMA提示音 // +//*********************************************************************************// +const char *mma_notice_tab[APP_RROTOCOL_TONE_MAX] = { + [APP_RROTOCOL_TONE_SPEECH_KEY_START] = TONE_NORMAL, +}; + +//*********************************************************************************// +// MMA私有消息处理 // +//*********************************************************************************// + +#if 1 +extern int le_controller_get_mac(void *addr); + +#ifdef CONFIG_NEW_BREDR_ENABLE +void tws_host_get_common_addr(u8 *remote_addr, u8 *common_addr, char channel) +#else +void tws_host_get_common_addr(u8 *local_addr, u8 *remote_addr, u8 *common_addr, char channel) +#endif +{ + APP_MMA_LOG(">>>>>>>>>tws_host_get_common_addr ch:%c \n", channel); + + if (channel == 'L') { + memcpy(common_addr, bt_get_mac_addr(), 6); + } else { + memcpy(common_addr, remote_addr, 6); + } + APP_MMA_LOG(">>>local mac: "); + APP_MMA_DUMP(bt_get_mac_addr(), 6); + APP_MMA_LOG("remote_addr: "); + APP_MMA_DUMP((const u8 *)remote_addr, 6); + APP_MMA_LOG("common_addr: "); + APP_MMA_DUMP((const u8 *)common_addr, 6); +} + +static void mma_tws_get_data_analysis(u16 cmd, u8 *data, u16 len) +{ +} + +static void mma_update_ble_addr() +{ + u8 ble_old_addr[6]; + u8 ble_new_addr[6]; + u8 comm_addr[6]; + tws_api_get_local_addr(comm_addr); + le_controller_get_mac(ble_old_addr); + void ble_update_address_tws_paired(u8 * comm_addr); + ble_update_address_tws_paired(comm_addr); + le_controller_get_mac(ble_new_addr); + if (is_tws_master_role() && memcmp(ble_old_addr, ble_new_addr, 6)) { + app_protocol_disconnect(NULL); + app_protocol_ble_adv_switch(0); + app_protocol_ble_adv_switch(1); + } +} + +static void mma_bt_tws_event_handler(struct bt_event *bt) +{ + int role = bt->args[0]; + int phone_link_connection = bt->args[1]; + int reason = bt->args[2]; + + switch (bt->event) { + case TWS_EVENT_CONNECTED: + mma_update_ble_addr(); + break; + case TWS_EVENT_REMOVE_PAIRS: + mma_update_ble_addr(); + break; + } +} + + +static int mma_bt_status_event_handler(struct bt_event *bt) +{ + return 0; +} + +int mma_sys_event_deal(struct sys_event *event) +{ + switch (event->type) { + case SYS_BT_EVENT: + if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) { + mma_bt_status_event_handler(&event->u.bt); + } +#if TCFG_USER_TWS_ENABLE + else if (((u32)event->arg == SYS_BT_EVENT_FROM_TWS)) { + mma_bt_tws_event_handler(&event->u.bt); + } +#endif + break; + + } + + return 0; + +} + +struct app_protocol_private_handle_t mma_private_handle = { + /* .tws_rx_from_siblling = mma_tws_get_data_analysis, */ + .sys_event_handler = mma_sys_event_deal, +}; +#endif +#endif + diff --git a/apps/common/third_party_profile/interface/app_protocol_ota.c b/apps/common/third_party_profile/interface/app_protocol_ota.c new file mode 100644 index 0000000..b4db72f --- /dev/null +++ b/apps/common/third_party_profile/interface/app_protocol_ota.c @@ -0,0 +1,527 @@ +#include "app_config.h" + +#if AI_APP_PROTOCOL +#include "app_protocol_ota.h" +#include "app_protocol_api.h" +#include "fs.h" +#include "os/os_error.h" +#include "update_loader_download.h" +#include "dual_bank_updata_api.h" +#include "update.h" +#include "timer.h" +#include "debug.h" + +#define LOG_TAG_CONST APP_OTA +#define LOG_TAG "[APP_OTA]" + + +int clk_set(const char *name, int clk); +update_op_tws_api_t *get_tws_update_api(void); +void tws_sync_update_crc_handler_register(void (*crc_init_hdl)(void), u32(*crc_calc_hdl)(u32 init_crc, u8 *data, u32 len)); + +#define APP_UPDATE_FAILED 0 +#define APP_UPDATE_SUCC 1 + +#define APP_CHECK_CRC_SUCC 0 +#define APP_CHECK_CRC_FAILED 1 + +typedef struct _app_protocol_ota_param_t { + u32 state; + u32 read_len; + u32 need_rx_len; + u8 *read_buf; + void (*resume_hdl)(void *priv); + int (*sleep_hdl)(void *priv); + app_protocol_ota_api ota_api; + u32 file_offset; + u8 seek_type; + u8 update_result; + u8 sync_update_first_packet; + u8 ota_cancle_flag; + u8 wait_app_reboot; + OS_SEM ota_sem; +} app_protocol_ota_param_t; + +static app_protocol_ota_param_t app_protocol_ota_param; +static update_op_tws_api_t *app_protocol_update_tws_api = NULL; + +#define __this (&app_protocol_ota_param) + +enum { + BT_SEEK_SET = 0x01, + BT_SEEK_CUR = 0x02, + BT_SEEK_TYPE_UPDATE_LEN = 0x10, +}; + +typedef enum { + UPDATA_START = 0x00, + UPDATA_REV_DATA, + UPDATA_STOP, +} UPDATA_BIT_FLAG; + +#define RETRY_TIMES 3 + +const app_protocol_ota_type_map ota_type_map[] = { + {.protocol_id = GMA_HANDLER_ID, .ota_type = PASSIVE_OTA}, + {.protocol_id = MMA_HANDLER_ID, .ota_type = INITIATIVE_OTA}, + {.protocol_id = DMA_HANDLER_ID, .ota_type = NO_SUPPORT_OTA}, + {.protocol_id = TME_HANDLER_ID, .ota_type = INITIATIVE_OTA}, + {.protocol_id = AMA_HANDLER_ID, .ota_type = NO_SUPPORT_OTA}, +}; + +//根据protocol_id获取协议升级类型 +u8 check_ota_type_by_protocol_id(int id) +{ + u8 i = 0; + for (; i < sizeof(ota_type_map) / sizeof(app_protocol_ota_type_map); i++) { + if (id == ota_type_map[i].protocol_id) { + return ota_type_map[i].ota_type; + } + } + return NO_SUPPORT_OTA; +} + +static void initiative_ota_resume_hdl_register(void (*resume_hdl)(void *priv), int (*sleep_hdl)(void *priv)) +{ + __this->resume_hdl = resume_hdl; + __this->sleep_hdl = sleep_hdl; +} + +void app_protocol_ota_init(app_protocol_ota_api *api, u8 need_wait_app_reboot) +{ + memcpy(&(__this->ota_api), api, sizeof(app_protocol_ota_api)); + __this->wait_app_reboot = need_wait_app_reboot; +#if OTA_TWS_SAME_TIME_ENABLE + tws_sync_update_crc_handler_register(__this->ota_api.ota_crc_init_hdl, __this->ota_api.ota_crc_calc_hdl); + g_printf("crc_init_hdl:0x%x crc_calc_hdl:0x%x\n", __this->ota_api.ota_crc_init_hdl, __this->ota_api.ota_crc_calc_hdl); +#endif +} + + +void initiative_ota_init(void (*resume_hdl)(void *priv), int (*sleep_hdl)(void *priv)) +{ + os_sem_create(&(__this->ota_sem), 0); + initiative_ota_resume_hdl_register(resume_hdl, sleep_hdl); +} + +u16 initiative_ota_f_open(void) +{ + log_info(">>>initiative_ota_f_open\n"); + __this->file_offset = 0; + __this->seek_type = BT_SEEK_SET; + return 1; +} + +void initiative_ota_handle(u8 state, void *buf, int len) +{ + /* log_info("R"); */ + if (state != __this->state) { + log_info(">>>initiative state err\n"); + return; + } + + switch (state) { + case UPDATA_REV_DATA: + if (__this->read_buf) { + memcpy(__this->read_buf, buf, len); + __this->read_len = len; + __this->state = 0; + } + break; + + case UPDATA_STOP: + __this->state = 0; + break; + } + + if (__this->resume_hdl) { + __this->resume_hdl(NULL); + } +} + +u16 initiative_ota_f_read(void *fp, u8 *buff, u16 len) +{ + u8 retry_cnt = 0; + + __this->need_rx_len = len; + __this->state = UPDATA_REV_DATA; + __this->read_len = 0; + __this->read_buf = buff; + +__RETRY: + if (app_protocol_get_cur_handle_id() == 0) { //如果已经断开连接直接返回-1 */ + return -1; + } + + if (__this->ota_cancle_flag) { + return -1; + } + + if (__this->ota_api.ota_request_data == NULL) { + return -1; + } + + printf("initiative_ota_read\n"); + __this->ota_api.ota_request_data(fp, __this->file_offset, len); + + while (!((0 == __this->state) && (__this->read_len == len))) { + if (__this->sleep_hdl && app_protocol_get_cur_handle_id()) { + __this->sleep_hdl(NULL); + } else { + len = -1; + break; + } + + if (!((0 == __this->state) && (__this->read_len == len))) { + if (retry_cnt++ > RETRY_TIMES) { + len = (u16) - 1; + break; + } else { + goto __RETRY; + } + } + } + + if ((u16) - 1 != len) { + __this->file_offset += len; + } + + return len; +} + +int initiative_ota_f_seek(void *fp, u8 type, u32 offset) +{ + if (type == SEEK_SET) { + __this->file_offset = offset; + __this->seek_type = BT_SEEK_SET; + } else if (type == SEEK_CUR) { + __this->file_offset += offset; + __this->seek_type = BT_SEEK_CUR; + } + + return 0;//FR_OK; +} + +static u16 initiative_ota_f_stop(u8 err) +{ + //err = update_result_handle(err); + __this->state = UPDATA_STOP; + log_info(">>>initiative_ota_stop:%x err:0x%x\n", __this->state, err); + + if (__this->ota_cancle_flag) { + return -1; + } + + if (__this->ota_api.ota_request_data) { + __this->ota_api.ota_request_data(NULL, 0, 0); + } + + while (!(0 == __this->state)) { + if (__this->sleep_hdl) { // && get_rcsp_connect_status()) { + if (__this->sleep_hdl(NULL) == OS_TIMEOUT) { + break; + } + } else { + break; + } + } + + if (__this->ota_api.ota_report_result) { + __this->ota_api.ota_report_result(err); + } + + return 1; +} + +static int initiative_ota_notify_update_content_size(void *priv, u32 size) +{ + int err; + u8 data[4]; + /* WRITE_BIG_U32(data, size); */ + /* user_change_ble_conn_param(0); */ + log_info("send content_size:%x\n", size); + if (__this->ota_api.ota_notify_file_size) { + __this->ota_api.ota_notify_file_size(size); + } + /* err = JL_CMD_send(JL_OPCODE_NOTIFY_UPDATE_CONENT_SIZE, data, sizeof(data), JL_NEED_RESPOND); */ + + return err; +} + +const update_op_api_t initiative_update_op = { + .ch_init = initiative_ota_init, + .f_open = initiative_ota_f_open, + .f_read = initiative_ota_f_read, + .f_seek = initiative_ota_f_seek, + .f_stop = initiative_ota_f_stop, + .notify_update_content_size = initiative_ota_notify_update_content_size, +}; + +void app_protocol_ota_update_success_reset(void *priv) +{ + cpu_reset(); +} + +static void initiative_ota_state_cbk(int type, u32 state, void *priv) +{ + update_ret_code_t *ret_code = (update_ret_code_t *)priv; + if (ret_code) { + log_info("state:%x err:%x\n", ret_code->stu, ret_code->err_code); + } + switch (state) { + case UPDATE_CH_EXIT: + if (UPDATE_DUAL_BANK_IS_SUPPORT()) { + if ((0 == ret_code->stu) && (0 == ret_code->err_code)) { + /* set_jl_update_flag(1); */ + log_info(">>>initiative update succ\n"); + update_result_set(UPDATA_SUCC); + __this->update_result = APP_UPDATE_SUCC; +#if !OTA_TWS_SAME_TIME_ENABLE + sys_timeout_add(NULL, app_protocol_ota_update_success_reset, 2000); //延时一段时间再reset保证命令已经发送 +#endif + } else { + log_info(">>>initiative update failed\n"); + update_result_set(UPDATA_DEV_ERR); + __this->update_result = APP_UPDATE_FAILED; + } + } else { + if ((0 == ret_code->stu) && (0 == ret_code->err_code)) { + __this->update_result = APP_UPDATE_SUCC; + /* set_jl_update_flag(1); */ + } + } + os_sem_post(&(__this->ota_sem)); + break; + } +} + +//被动升级请求下一帧数据 +int passive_ota_write_callback(void *priv) +{ + if (__this->ota_api.ota_request_data) { + __this->ota_api.ota_request_data(NULL, 0, 0); + } + return 0; +} + + +int passive_ota_set_boot_info_callback(int ret) +{ + if (__this->ota_api.ota_report_result) { + __this->ota_api.ota_report_result(ret); + } + + if (ret == 0) { //0表示boot info写成功 +#if OTA_TWS_SAME_TIME_ENABLE + if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_result_hdl && !__this->wait_app_reboot) { + app_protocol_update_tws_api->tws_ota_result_hdl(0); + } +#else + sys_timeout_add(NULL, app_protocol_ota_update_success_reset, 2000); //延时一段时间再reset保证命令已经发送 +#endif + __this->update_result = APP_UPDATE_SUCC; + } else { + dual_bank_passive_update_exit(NULL); +#if OTA_TWS_SAME_TIME_ENABLE + if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_err) { + app_protocol_update_tws_api->tws_ota_err(0); + } + __this->update_result = APP_UPDATE_FAILED; +#endif + } + return 0; +} + +int passive_ota_crc_result_call_back(int crc_res) +{ + if (crc_res) { //校验成功 + log_info("crc check succ, write boot_info\n"); + u8 update_boot_info_flag, verify_err; +#if OTA_TWS_SAME_TIME_ENABLE + if (app_protocol_update_tws_api && app_protocol_update_tws_api->exit_verify_hdl) { + if (app_protocol_update_tws_api->exit_verify_hdl(&verify_err, &update_boot_info_flag)) { + dual_bank_update_burn_boot_info((int (*)(int))passive_ota_set_boot_info_callback); + } else { //从机写boot_info失败 + if (__this->ota_api.ota_report_result) { + __this->ota_api.ota_report_result(APP_CHECK_CRC_FAILED); + } + if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_err) { //通知从机升级失败 + app_protocol_update_tws_api->tws_ota_err(0); + } + __this->update_result = APP_UPDATE_FAILED; + } + } else +#endif + { + dual_bank_update_burn_boot_info((int (*)(int))passive_ota_set_boot_info_callback); + } + } else { //校验失败 + if (__this->ota_api.ota_report_result) { + __this->ota_api.ota_report_result(APP_CHECK_CRC_FAILED); + } +#if OTA_TWS_SAME_TIME_ENABLE + if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_err) { //通知从机升级失败 + app_protocol_update_tws_api->tws_ota_err(0); + } +#endif + __this->update_result = APP_UPDATE_FAILED; + //app_protocol_reply_frame_check_result(crc_res); + dual_bank_passive_update_exit(NULL); + } + return 0; +} + +int app_protocol_ota_interrupt_by_disconnect(int id) +{ + if (check_ota_type_by_protocol_id(id) == INITIATIVE_OTA) { + + } else { +#if OTA_TWS_SAME_TIME_ENABLE + if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_err) { + app_protocol_update_tws_api->tws_ota_err(0); + } +#endif + dual_bank_passive_update_exit(NULL); + } + return 0; +} + +int app_protocol_update_success_flag(void) +{ + return __this->update_result; +} + +int app_protocol_ota_message_handler(int id, int opcode, u8 *data, u32 len) +{ + int err_code = UPDATE_RESULT_ERR_NONE; + int ret = 0; + switch (opcode) { + case APP_PROTOCOL_OTA_CHECK: + log_info("APP_PROTOCOL_OTA_CHECK\n"); + ota_frame_info *frame_info = data; + dual_bank_passive_update_init(frame_info->frame_crc, frame_info->frame_size, frame_info->max_pkt_len, NULL); + ret = dual_bank_update_allow_check(frame_info->frame_size); + if (ret) { + err_code = UPDATE_RESULT_RESOURCE_LIMIT; + dual_bank_passive_update_exit(NULL); + } else { //for tws sync update init +#if OTA_TWS_SAME_TIME_ENABLE + app_protocol_update_tws_api = get_tws_update_api(); + struct __tws_ota_para tws_update_para; + tws_update_para.fm_size = frame_info->frame_size; + tws_update_para.fm_crc16 = frame_info->frame_crc; + tws_update_para.max_pkt_len = frame_info->max_pkt_len; + if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_start) { + if (app_protocol_update_tws_api->tws_ota_start(&tws_update_para)) { + err_code = UPDATE_RESULT_OTA_TWS_START_ERR; + dual_bank_passive_update_exit(NULL); + } + } + __this->sync_update_first_packet = 1; +#endif + } + break; + + case APP_PROTOCOL_OTA_BEGIN: + update_mode_info_t info = { + .type = BLE_APP_UPDATA, + .state_cbk = initiative_ota_state_cbk, + .p_op_api = &initiative_update_op, + .task_en = 1, + }; + __this->ota_cancle_flag = 0; + app_active_update_task_init(&info); + break; + + case APP_PROTOCOL_OTA_TRANS_DATA: + log_info("APP_PROTOCOL_OTA_TRANS_DATA\n"); + if (check_ota_type_by_protocol_id(id) == INITIATIVE_OTA) { + initiative_ota_handle(UPDATA_REV_DATA, data, len); + } else { +#if OTA_TWS_SAME_TIME_ENABLE + if (!__this->sync_update_first_packet) { //第一次传输不需要pend + if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_data_send_pend) { + if (app_protocol_update_tws_api->tws_ota_data_send_pend()) { + log_info(" UPDATE_ERR_WAIT_TWS_RESPONSE_TIMEOUT\n"); + err_code = UPDATE_RESULT_OTA_TWS_NO_RSP; + break; + } + } + } + __this->sync_update_first_packet = 0; +#endif + dual_bank_update_write(data, len, passive_ota_write_callback); +#if OTA_TWS_SAME_TIME_ENABLE + if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_data_send) { + app_protocol_update_tws_api->tws_ota_data_send(data, len); + } +#endif + } + break; + + case APP_PROTOCOL_OTA_GET_APP_VERSION: + u32 fm_version = app_protocol_get_version_by_id(id); + break; + + case APP_PROTOCOL_OTA_CHECK_CRC: + if (check_ota_type_by_protocol_id(id) == INITIATIVE_OTA) { + os_sem_pend(&(__this->ota_sem), 0); + err_code = __this->update_result; + } else { + clk_set("sys", 120 * 1000000L); //提升主频加快CRC校验速度 +#if OTA_TWS_SAME_TIME_ENABLE + if (app_protocol_update_tws_api && app_protocol_update_tws_api->tws_ota_data_send_pend) { //pend 最后一包数据 + if (app_protocol_update_tws_api->tws_ota_data_send_pend()) { + log_info(" UPDATE_ERR_WAIT_TWS_RESPONSE_TIMEOUT\n"); + err_code = UPDATE_RESULT_OTA_TWS_NO_RSP; + break; + } + } + + if (app_protocol_update_tws_api && app_protocol_update_tws_api->enter_verfiy_hdl) { + if (app_protocol_update_tws_api->enter_verfiy_hdl(NULL)) { //从机校验CRC + log_info("update enter verify err\n"); + if (__this->ota_api.ota_report_result) { + __this->ota_api.ota_report_result(APP_CHECK_CRC_FAILED); + } + } else { + log_info("update enter verify succ\n"); + dual_bank_update_verify(__this->ota_api.ota_crc_init_hdl, __this->ota_api.ota_crc_calc_hdl, passive_ota_crc_result_call_back); + } + } else +#endif + { + dual_bank_update_verify(__this->ota_api.ota_crc_init_hdl, __this->ota_api.ota_crc_calc_hdl, passive_ota_crc_result_call_back); + } + } + break; + + case APP_PROTOCOL_OTA_CANCLE: + __this->ota_cancle_flag = 1; + break; + + case APP_PROTOCOL_OTA_REBOOT: + __this->state = 0; + /* #if OTA_TWS_SAME_TIME_ENABLE //同步升级在update lib里进行重启 */ + /* g_printf("APP_PROTOCOL_OTA_REBOOT!!!\n"); */ + /* #else */ + /* cpu_reset(); */ + /* #endif */ + break; + + case APP_PROTOCOL_OTA_PERCENT: + + break; + case APP_PROTOCOL_OTA_END: + + break; + case APP_PROTOCOL_OTA_SUCCESS: + + break; + case APP_PROTOCOL_OTA_FAIL: + + break; + } + return err_code; +} +#endif diff --git a/apps/common/third_party_profile/interface/app_protocol_ota.h b/apps/common/third_party_profile/interface/app_protocol_ota.h new file mode 100644 index 0000000..83ac38b --- /dev/null +++ b/apps/common/third_party_profile/interface/app_protocol_ota.h @@ -0,0 +1,28 @@ +#ifndef __APP_PROTOCOL_OTA_H__ +#define __APP_PROTOCOL_OTA_H__ + +#include "typedef.h" + +#define NO_SUPPORT_OTA 0xff +#define INITIATIVE_OTA 0x01 +#define PASSIVE_OTA 0x02 + +typedef struct app_protocol_ota_type_map_t { + u32 protocol_id; + u8 ota_type; +} app_protocol_ota_type_map; + +typedef struct app_protocol_ota_api_t { + u32(*ota_request_data)(void *priv, u32 offset, u16 len); + u32(*ota_report_result)(u8 result); + void (*ota_notify_file_size)(u32 file_size); + void (*ota_crc_init_hdl)(void); + u16(*ota_crc_calc_hdl)(u16 init_crc, u8 *data, u32 len); +} app_protocol_ota_api; + +int app_protocol_ota_message_handler(int id, int opcode, u8 *data, u32 len); +void app_protocol_ota_init(app_protocol_ota_api *api, u8 need_wait_app_reboot); +int app_protocol_ota_interrupt_by_disconnect(int id); +int app_protocol_update_success_flag(void); + +#endif //__APP_PROTOCOL_OTA_H__ diff --git a/apps/common/third_party_profile/interface/app_protocol_tme.c b/apps/common/third_party_profile/interface/app_protocol_tme.c new file mode 100644 index 0000000..7b83e0d --- /dev/null +++ b/apps/common/third_party_profile/interface/app_protocol_tme.c @@ -0,0 +1,126 @@ +#include +#include +#include + +#include "app_protocol_api.h" +#include "system/includes.h" +#include "audio_config.h" +#include "app_power_manage.h" +#include "user_cfg.h" +#include "btstack/avctp_user.h" +#include "bt_tws.h" + +#if APP_PROTOCOL_TME_CODE + +extern void TME_set_edr_connected(u8 flag); + +//*********************************************************************************// +// TME认证信息 // +//*********************************************************************************// + +//*********************************************************************************// +// TME提示音 // +//*********************************************************************************// +const char *tme_notice_tab[APP_RROTOCOL_TONE_MAX] = { + [APP_RROTOCOL_TONE_SPEECH_KEY_START] = TONE_NORMAL, +}; + +//*********************************************************************************// +// TME弱函数实现 // +//*********************************************************************************// + +//*********************************************************************************// +// TME私有消息处理 // +//*********************************************************************************// +#if 1 +extern int le_controller_set_mac(void *addr); +extern int le_controller_get_mac(void *addr); + +#if TCFG_USER_TWS_ENABLE +static void tme_tws_rx_from_sibling(u16 cmd, u8 *data, u16 len) +{ +#if TCFG_USER_TWS_ENABLE + switch (cmd) { + } +#endif +} + +static void tme_update_ble_addr() +{ + u8 ble_old_addr[6]; + u8 ble_new_addr[6]; + u8 comm_addr[6]; + + printf("%s\n", __func__); + + tws_api_get_local_addr(comm_addr); + le_controller_get_mac(ble_old_addr); + lib_make_ble_address(ble_new_addr, comm_addr); + le_controller_set_mac(ble_new_addr); //地址发生变化,更新地址 + if (is_tws_master_role() && memcmp(ble_old_addr, ble_new_addr, 6)) { + app_protocol_disconnect(NULL); + app_protocol_ble_adv_switch(0); + app_protocol_ble_adv_switch(1); + } +} + +static void tme_bt_tws_event_handler(struct bt_event *bt) +{ + int role = bt->args[0]; + int phone_link_connection = bt->args[1]; + int reason = bt->args[2]; + + switch (bt->event) { + case TWS_EVENT_CONNECTED: + tme_update_ble_addr(); + if (BT_STATUS_WAITINT_CONN != get_bt_connect_status()) { + TME_set_edr_connected(1); + } + break; + case TWS_EVENT_REMOVE_PAIRS: + tme_update_ble_addr(); + break; + } + +} +#endif + +static int tme_bt_status_event_handler(struct bt_event *bt) +{ + switch (bt->event) { + case BT_STATUS_SECOND_CONNECTED: + case BT_STATUS_FIRST_CONNECTED: + TME_set_edr_connected(1); //连接过经典蓝牙标志 + break; + } + return 0; +} + +int tme_sys_event_deal(struct sys_event *event) +{ + switch (event->type) { + case SYS_BT_EVENT: + if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) { + tme_bt_status_event_handler(&event->u.bt); + } +#if TCFG_USER_TWS_ENABLE + else if (((u32)event->arg == SYS_BT_EVENT_FROM_TWS)) { + tme_bt_tws_event_handler(&event->u.bt); + } +#endif + break; + + } + + return 0; + +} + +struct app_protocol_private_handle_t tme_private_handle = { + /* .tws_rx_from_siblling = tme_tws_rx_from_sibling, */ + .sys_event_handler = tme_sys_event_deal, +}; +#endif + +#endif + diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_bt_name_setting.c b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_bt_name_setting.c new file mode 100644 index 0000000..59278ba --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_bt_name_setting.c @@ -0,0 +1,67 @@ +#include "app_config.h" +#include "user_cfg.h" +#include "syscfg_id.h" +#include "user_cfg_id.h" +#include "le_rcsp_adv_module.h" + +#include "adv_bt_name_setting.h" +#include "adv_setting_common.h" +#include "rcsp_adv_tws_sync.h" +#include "rcsp_adv_opt.h" + +#if (RCSP_ADV_EN) +#if RCSP_ADV_NAME_SET_ENABLE +extern int get_bt_tws_connect_status(); + +void adv_edr_name_change_now(void) +{ + extern BT_CONFIG bt_cfg; + extern const char *bt_get_local_name(); + extern void lmp_hci_write_local_name(const char *name); + memcpy(bt_cfg.edr_name, _s_info.edr_name, LOCAL_NAME_LEN); + lmp_hci_write_local_name(bt_get_local_name()); +} + +void set_bt_name_setting(u8 *bt_name_setting) +{ + memcpy(_s_info.edr_name, bt_name_setting, 32); +} + +void get_bt_name_setting(u8 *bt_name_setting) +{ + memcpy(bt_name_setting, _s_info.edr_name, 32); +} + +// 1、写入VM +static void update_bt_name_vm_value(u8 *bt_name_setting) +{ + syscfg_write(CFG_BT_NAME, bt_name_setting, 32); +} +// 2、同步对端 +static void bt_name_sync(u8 *bt_name_setting) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_adv_setting(BIT(ATTR_TYPE_EDR_NAME)); + } +#endif +} + +void deal_bt_name_setting(u8 *bt_name_setting, u8 write_vm, u8 tws_sync) +{ + u8 bt_name[32] = {0}; + if (!bt_name_setting) { + get_bt_name_setting(bt_name); + } else { + memcpy(bt_name, bt_name_setting, 32); + } + if (write_vm) { + update_bt_name_vm_value(bt_name); + } + if (tws_sync) { + bt_name_sync(bt_name); + } +} +#endif + +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_bt_name_setting.h b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_bt_name_setting.h new file mode 100644 index 0000000..00318f7 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_bt_name_setting.h @@ -0,0 +1,12 @@ +#ifndef __ADV_BT_NAME_SETTING_H__ +#define __ADV_BT_NAME_SETTING_H__ + +#include "le_rcsp_adv_module.h" + +#if RCSP_ADV_NAME_SET_ENABLE + +void set_bt_name_setting(u8 *bt_name_setting); +void get_bt_name_setting(u8 *bt_name_setting); + +#endif +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_eq_setting.h b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_eq_setting.h new file mode 100644 index 0000000..f7075fb --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_eq_setting.h @@ -0,0 +1,20 @@ +#ifndef __ADV_EQ_SETTING_H__ +#define __ADV_EQ_SETTING_H__ + +#include "le_rcsp_adv_module.h" + +#if RCSP_ADV_EQ_SET_ENABLE + +struct _EQ_INFO { + u8 mode; + s8 gain_val[10]; +}; + +void set_eq_setting(u8 *eq_setting); +void get_eq_setting(u8 *eq_setting); +void deal_eq_setting(u8 *eq_setting, u8 write_vm, u8 tws_sync); +u8 app_get_eq_info(u8 *get_eq_info); +u8 app_get_eq_all_info(u8 *get_eq_info); + +#endif +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_high_low_vol.h b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_high_low_vol.h new file mode 100644 index 0000000..58a0329 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_high_low_vol.h @@ -0,0 +1,18 @@ +#ifndef __ADV_HIGH_LOW_VOL__ +#define __ADV_HIGH_LOW_VOL__ + +#include "le_rcsp_adv_module.h" + +#if RCSP_ADV_HIGH_LOW_SET + +struct _HIGL_LOW_VOL { + int low_vol; + int high_vol; +}; + +void get_high_low_vol_info(u8 *vol_gain_param); +void set_high_low_vol_info(u8 *vol_gain_param); +void deal_high_low_vol(u8 *vol_gain_data, u8 write_vm, u8 tws_sync); + +#endif +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_key_setting.c b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_key_setting.c new file mode 100644 index 0000000..d0a32d9 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_key_setting.c @@ -0,0 +1,214 @@ +#include "app_config.h" +#include "syscfg_id.h" +#include "user_cfg_id.h" +#include "key_event_deal.h" +#include "le_rcsp_adv_module.h" + +#include "adv_key_setting.h" +#include "adv_setting_common.h" +#include "rcsp_adv_tws_sync.h" +#include "rcsp_adv_opt.h" + +#if (RCSP_ADV_EN) +#if RCSP_ADV_KEY_SET_ENABLE + +extern int get_bt_tws_connect_status(); +static u8 rcsp_adv_key_event_flag = 0x0; +static void enable_adv_key_event(void) +{ + rcsp_adv_key_event_flag = 1; +} + +static u8 get_adv_key_event_status(void) +{ + return rcsp_adv_key_event_flag; +} + +static void disable_adv_key_event(void) +{ + rcsp_adv_key_event_flag = 0; +} + +void set_key_setting(u8 *key_setting_info) +{ + _s_info.key_setting[3 * 0 + 2] = key_setting_info[0]; + _s_info.key_setting[3 * 2 + 2] = key_setting_info[1]; + _s_info.key_setting[3 * 1 + 2] = key_setting_info[2]; + _s_info.key_setting[3 * 3 + 2] = key_setting_info[3]; +} + +void get_key_setting(u8 *key_setting_info) +{ + key_setting_info[0] = _s_info.key_setting[3 * 0 + 2]; + key_setting_info[1] = _s_info.key_setting[3 * 2 + 2]; + key_setting_info[2] = _s_info.key_setting[3 * 1 + 2]; + key_setting_info[3] = _s_info.key_setting[3 * 3 + 2]; +} + +static void update_key_setting_vm_value(u8 *key_setting_info) +{ + syscfg_write(CFG_RCSP_ADV_KEY_SETTING, key_setting_info, 4); +} + +static void key_setting_sync(u8 *key_setting_info) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_adv_setting(BIT(ATTR_TYPE_KEY_SETTING)); + } +#endif +} + +void deal_key_setting(u8 *key_setting_info, u8 write_vm, u8 tws_sync) +{ + u8 key_setting[4]; + if (!key_setting_info) { + get_key_setting(key_setting); + } else { + memcpy(key_setting, key_setting_info, 4); + } + // 1、写入VM + if (write_vm) { + update_key_setting_vm_value(key_setting); + } + // 2、同步对端 + if (tws_sync) { + key_setting_sync(key_setting); + } + // 3、更新状态 + enable_adv_key_event(); +} + +#define ADV_POWER_ON_OFF 0 +enum ADV_KEY_TYPE { + ADV_KEY_TYPE_NULL = 0x0, +#if ADV_POWER_ON_OFF + ADV_KEY_TYPE_POWER_ON, + ADV_KEY_TYPE_POWER_OFF, +#endif + ADV_KEY_TYPE_PREV = 0x3, + ADV_KEY_TYPE_NEXT, + ADV_KEY_TYPE_PP, + ADV_KEY_TYPE_ANSWER_CALL, + ADV_KEY_TYPE_HANG_UP, + ADV_KEY_TYPE_CALL_BACK, + ADV_KEY_TYPE_INC_VOICE, + ADV_KEY_TYPE_DESC_VOICE, + ADV_KEY_TYPE_TAKE_PHOTO, +}; + +static u8 get_adv_key_opt(u8 key_action, u8 channel) +{ + u8 opt; + for (opt = 0; opt < sizeof(_s_info.key_setting); opt += 3) { + if (_s_info.key_setting[opt] == channel && + _s_info.key_setting[opt + 1] == key_action) { + break; + } + } + if (sizeof(_s_info.key_setting) == opt) { + return -1; + } + + switch (_s_info.key_setting[opt + 2]) { + case ADV_KEY_TYPE_NULL: + //opt = KEY_NULL; + opt = ADV_KEY_TYPE_NULL; + break; +#if ADV_POWER_ON_OFF + case ADV_KEY_TYPE_POWER_ON: + opt = KEY_POWER_ON; + break; + case ADV_KEY_TYPE_POWER_OFF: + opt = KEY_RCSP_POWEROFF; + break; +#endif + case ADV_KEY_TYPE_PREV: + opt = KEY_MUSIC_PREV; + break; + case ADV_KEY_TYPE_NEXT: + opt = KEY_MUSIC_NEXT; + break; + case ADV_KEY_TYPE_PP: + opt = KEY_MUSIC_PP; + break; + case ADV_KEY_TYPE_ANSWER_CALL: + opt = KEY_CALL_ANSWER; + break; + case ADV_KEY_TYPE_HANG_UP: + opt = KEY_CALL_HANG_UP; + break; + case ADV_KEY_TYPE_CALL_BACK: + opt = KEY_CALL_LAST_NO; + break; + case ADV_KEY_TYPE_INC_VOICE: + opt = KEY_VOL_UP; + break; + case ADV_KEY_TYPE_DESC_VOICE: + opt = KEY_VOL_DOWN; + break; + case ADV_KEY_TYPE_TAKE_PHOTO: + opt = KEY_HID_CONTROL; + break; + } + return opt; +} + +void set_key_event_by_rcsp_info(struct sys_event *event, u8 *key_event) +{ + if (0 == get_adv_key_event_status()) { + return; + } + + u8 key_action = 0; + struct key_event *key = &event->u.key; + switch (key->event) { + case 0: + // 单击 + key_action = 0x1; + break; + case 4: + // 双击 + key_action = 0x2; + break; + default: + return; + } + +#if (TCFG_CHARGESTORE_ENABLE && TCFG_USER_TWS_ENABLE) + u8 channel = tws_api_get_local_channel(); + + if (get_bt_tws_connect_status()) { + channel = tws_api_get_local_channel(); + } +#else + u8 channel = 'U'; +#endif + + switch (channel) { + case 'U': + case 'L': + channel = (u32) event->arg == KEY_EVENT_FROM_TWS ? 2 : 1; + break; + case 'R': + channel = (u32) event->arg == KEY_EVENT_FROM_TWS ? 1 : 2; + break; + default: + return; + } + + key_action = get_adv_key_opt(key_action, channel); + if ((u8) - 1 != key_action) { + *key_event = key_action ? key_action : KEY_NULL; + } +} +#else + + +void set_key_event_by_rcsp_info(struct sys_event *event, u8 *key_event) +{ + return; +} + +#endif +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_key_setting.h b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_key_setting.h new file mode 100644 index 0000000..9be79b3 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_key_setting.h @@ -0,0 +1,13 @@ +#ifndef __ADV_KEY_SETTING_H__ +#define __ADV_KEY_SETTING_H__ + + +#include "le_rcsp_adv_module.h" + +#if RCSP_ADV_KEY_SET_ENABLE + +void set_key_setting(u8 *key_setting_info); +void get_key_setting(u8 *key_setting_info); + +#endif +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_led_setting.c b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_led_setting.c new file mode 100644 index 0000000..34e8969 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_led_setting.c @@ -0,0 +1,145 @@ +#include "app_config.h" +#include "syscfg_id.h" +#include "user_cfg_id.h" +#include "asm/pwm_led.h" +#include "user_cfg.h" +#include "ui_manage.h" +#include "le_rcsp_adv_module.h" + +#include "adv_led_setting.h" +#include "adv_setting_common.h" +#include "rcsp_adv_tws_sync.h" +#include "rcsp_adv_opt.h" + +#if (RCSP_ADV_EN) +#if RCSP_ADV_LED_SET_ENABLE + +enum ADV_LED_TYPE { + ADV_LED_TYPE_ALL_OFF = 0x0, + ADV_LED_TYPE_RED_ON, + ADV_LED_TYPE_BLUE_ON, + ADV_LED_TYPE_RAD_BREATHE, + ADV_LED_TYPE_BLUE_BREATHE, + ADV_LED_TYPE_FAST_FLASH, + ADV_LED_TYPE_SLOW_FLASH, +}; + +extern STATUS *get_led_config(void); +extern int get_bt_tws_connect_status(); + + +__attribute__((weak)) +u8 adv_get_led_status(void) +{ + return 1; +} + +static u8 adv_led_value_conversion(u8 adv_led_opt) +{ + u8 conversion_value = adv_led_opt; + switch (adv_led_opt) { + case ADV_LED_TYPE_ALL_OFF: + conversion_value = PWM_LED_ALL_OFF; + break; + case ADV_LED_TYPE_RED_ON: + conversion_value = PWM_LED1_ON; + break; + case ADV_LED_TYPE_BLUE_ON: + conversion_value = PWM_LED0_ON; + break; + case ADV_LED_TYPE_RAD_BREATHE: + conversion_value = PWM_LED1_BREATHE; + break; + case ADV_LED_TYPE_BLUE_BREATHE: + conversion_value = PWM_LED0_BREATHE; + break; + case ADV_LED_TYPE_FAST_FLASH: + conversion_value = PWM_LED0_LED1_FAST_FLASH; + break; + case ADV_LED_TYPE_SLOW_FLASH: + conversion_value = PWM_LED0_LED1_SLOW_FLASH; + break; + } + return conversion_value; +} + +void set_led_setting(u8 *led_setting_info) +{ + _s_info.led_status[2 * 0 + 1] = led_setting_info[0]; + _s_info.led_status[2 * 1 + 1] = led_setting_info[1]; + _s_info.led_status[2 * 2 + 1] = led_setting_info[2]; +} + +void get_led_setting(u8 *led_setting_info) +{ + led_setting_info[0] = _s_info.led_status[2 * 0 + 1]; + led_setting_info[1] = _s_info.led_status[2 * 1 + 1]; + led_setting_info[2] = _s_info.led_status[2 * 2 + 1]; +} + +// 1、写入VM +static void update_led_setting_vm_value(u8 *led_setting_info) +{ + syscfg_write(CFG_RCSP_ADV_LED_SETTING, led_setting_info, 3); +} +// 2、同步对端 +static void led_setting_sync(u8 *led_setting_info) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_adv_setting(BIT(ATTR_TYPE_LED_SETTING)); + } +#endif +} +// 3、更新状态 +void update_led_setting_state(void) +{ + u8 led_setting_info[3]; + get_led_setting(led_setting_info); + + // 直接修改led表 + STATUS *p_led = get_led_config(); + // 未配对 + p_led->bt_init_ok = adv_led_value_conversion(led_setting_info[0]); + p_led->bt_disconnect = adv_led_value_conversion(led_setting_info[0]); + // 未连接 + p_led->tws_connect_ok = adv_led_value_conversion(led_setting_info[1]); + // 连接 + p_led->bt_connect_ok = adv_led_value_conversion(led_setting_info[2]); + + switch (adv_get_led_status()) { + case STATUS_BT_INIT_OK: + case STATUS_BT_DISCONN: + ui_update_status(STATUS_BT_INIT_OK); + break; + case STATUS_BT_TWS_CONN: + ui_update_status(STATUS_BT_TWS_CONN); + break; + case STATUS_PHONE_ACTIV: + case STATUS_PHONE_OUT: + case STATUS_PHONE_INCOME: + case STATUS_BT_CONN: + ui_update_status(STATUS_BT_CONN); + break; + } +} + +void deal_led_setting(u8 *led_setting_info, u8 write_vm, u8 tws_sync) +{ + u8 led_setting[3]; + if (!led_setting_info) { + get_led_setting(led_setting); + } else { + memcpy(led_setting, led_setting_info, 3); + } + if (write_vm) { + update_led_setting_vm_value(led_setting); + } + if (tws_sync) { + led_setting_sync(led_setting); + } + update_led_setting_state(); +} + +#endif +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_led_setting.h b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_led_setting.h new file mode 100644 index 0000000..9b9b7bf --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_led_setting.h @@ -0,0 +1,13 @@ +#ifndef __ADV_LED_SETTING_H__ +#define __ADV_LED_SETTING_H__ + + +#include "le_rcsp_adv_module.h" + +#if RCSP_ADV_LED_SET_ENABLE + +void set_led_setting(u8 *led_setting_info); +void get_led_setting(u8 *led_setting_info); + +#endif +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_mic_setting.c b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_mic_setting.c new file mode 100644 index 0000000..7d13cef --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_mic_setting.c @@ -0,0 +1,155 @@ +#include "app_config.h" +#include "syscfg_id.h" +#include "user_cfg_id.h" +#include "le_rcsp_adv_module.h" + +#include "adv_mic_setting.h" +#include "adv_setting_common.h" +#include "rcsp_adv_tws_sync.h" +#include "rcsp_adv_opt.h" + +#if (RCSP_ADV_EN) +#if RCSP_ADV_MIC_SET_ENABLE + +extern void test_esco_role_switch(u8 flag); +extern void tws_conn_switch_role(); +extern int get_bt_tws_connect_status(); +static void mic_setting_info_deal(u8 mic_info_data) +{ +#if TCFG_USER_TWS_ENABLE + u8 channel = tws_api_get_local_channel(); + printf("%s, %d\n", __FUNCTION__, channel); + + if (tws_api_get_role() == TWS_ROLE_MASTER) { + printf("-----master-----\n"); + } else { + printf("-----role-----\n"); + } + switch (mic_info_data) { + case 0x01: + if (get_bt_tws_connect_status()) { + printf("-------auto--------\n"); + tws_api_auto_role_switch_enable(); + } + break; + case 0x02: + if (get_bt_tws_connect_status()) { + if (channel != 'L') { + printf("-------!L--------\n"); + tws_api_auto_role_switch_disable(); + tws_conn_switch_role(); + } + } + break; + case 0x03: + if (get_bt_tws_connect_status()) { + if (channel != 'R') { + printf("-------!R--------\n"); + tws_api_auto_role_switch_disable(); + tws_conn_switch_role(); + } + } + break; + default: + break; + } +#endif +} + +void set_mic_setting(u8 mic_setting_info) +{ + _s_info.mic_mode = mic_setting_info; +} + +u8 get_mic_setting(void) +{ + return _s_info.mic_mode; +} + +static void update_mic_setting_vm_value(u8 mic_setting_info) +{ + syscfg_write(CFG_RCSP_ADV_MIC_SETTING, &mic_setting_info, 1); +} + +static void adv_mic_setting_sync(u8 mic_setting_info) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_adv_setting(BIT(ATTR_TYPE_MIC_SETTING)); + } +#endif +} + +void deal_mic_setting(u8 mic_setting_info, u8 write_vm, u8 tws_sync) +{ + if (!mic_setting_info) { + mic_setting_info = get_mic_setting(); + } else { + set_mic_setting(mic_setting_info); + } + if (write_vm) { + update_mic_setting_vm_value(mic_setting_info); + } + if (tws_sync) { + adv_mic_setting_sync(mic_setting_info); + } + mic_setting_info_deal(mic_setting_info); +} + + +//通话时,固定mic的位置,mode--esco state +void rcsp_user_mic_fixed_deal(u8 mode) +{ + u8 channel = tws_api_get_local_channel(); + + if (!get_bt_tws_connect_status()) { + return; + } + + if (mode == 0) { + test_esco_role_switch(0); + return; + } + + if ((tws_api_get_role() == TWS_ROLE_MASTER) + && (tws_api_get_tws_state() | TWS_STA_ESCO_OPEN)) { + + switch (get_mic_setting()) { + case 0x02: + if (get_bt_tws_connect_status()) { + if (channel != 'L') { + printf("mic_sw_l\n"); + test_esco_role_switch(1); + } + } + break; + + case 0x03: + if (get_bt_tws_connect_status()) { + if (channel != 'R') { + printf("mic_sw_r\n"); + test_esco_role_switch(1); + + } + } + + break; + + default: + printf("mic_sw_auto\n"); + test_esco_role_switch(0); + break; + } + } +} + +#else + +void rcsp_user_mic_fixed_deal(u8 mode) +{ + return; +} + +#endif + +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_mic_setting.h b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_mic_setting.h new file mode 100644 index 0000000..6cef962 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_mic_setting.h @@ -0,0 +1,15 @@ +#ifndef __ADV_MIC_SETTING_H__ +#define __ADV_MIC_SETTING_H__ + + +#include "le_rcsp_adv_module.h" + +#if RCSP_ADV_MIC_SET_ENABLE + +void set_mic_setting(u8 mic_setting_info); +u8 get_mic_setting(void); +#endif + +void rcsp_user_mic_fixed_deal(u8 mode); + +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_setting_common.h b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_setting_common.h new file mode 100644 index 0000000..fb93712 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_setting_common.h @@ -0,0 +1,30 @@ +#ifndef __ADV_SETTING_COMMON_H__ +#define __ADV_SETTING_COMMON_H__ + +#include "typedef.h" +#include "event.h" + +#if RCSP_ADV_EN +struct t_s_info { + u8 edr_name[32]; + u8 key_setting[12]; + u8 led_status[6]; + u8 mic_mode; + u8 work_mode; + u8 eq_mode_info[11]; +}; +extern struct t_s_info _s_info; + +void deal_time_stamp_setting(u32 time_stamp, u8 write_vm, u8 tws_sync); +void deal_bt_name_setting(u8 *bt_name_setting, u8 write_vm, u8 tws_sync); +void deal_key_setting(u8 *key_setting_info, u8 write_vm, u8 tws_sync); +void deal_led_setting(u8 *led_setting_info, u8 write_vm, u8 tws_sync); +void deal_mic_setting(u8 mic_setting_info, u8 write_vm, u8 tws_sync); +void deal_work_setting(u8 work_setting_info, u8 write_vm, u8 tws_sync, u8 poweron); + +void adv_setting_init(void); +void update_adv_setting(u16 type); +void update_info_from_adv_vm_info(void); +void modify_bt_name_and_reset(u32 msec); +#endif +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_time_stamp_setting.c b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_time_stamp_setting.c new file mode 100644 index 0000000..ea62253 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_time_stamp_setting.c @@ -0,0 +1,87 @@ +#include "app_config.h" +#include "syscfg_id.h" +#include "user_cfg_id.h" +#include "rcsp_adv_bluetooth.h" +#include "JL_rcsp_protocol.h" +#include "le_rcsp_adv_module.h" + +#include "adv_time_stamp_setting.h" +#include "adv_setting_common.h" +#include "rcsp_adv_tws_sync.h" +#include "rcsp_adv_opt.h" + +#if (RCSP_ADV_EN) +extern int get_bt_tws_connect_status(); +static u32 adv_time_stamp = 0; +u32 get_adv_time_stamp(void) +{ + return adv_time_stamp; +} + +void set_adv_time_stamp(u32 time_stamp) +{ + adv_time_stamp = time_stamp; +} + +void sync_setting_by_time_stamp(void) +{ + tws_api_send_data_to_sibling((u8 *)&adv_time_stamp, sizeof(adv_time_stamp), TWS_FUNC_ID_TIME_STAMP_SYNC); +} + +void deal_sibling_time_stamp_setting_switch(void *data, u16 len) +{ + u32 time_stamp = *((u32 *)data); + if (adv_time_stamp > time_stamp) { + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_ADV_SETTING_SYNC, NULL, 0); + } +} + +void deal_adv_setting_gain_time_stamp(void) +{ +#if TCFG_USER_TWS_ENABLE + extern u8 adv_info_device_request(u8 * buf, u16 len); + static u8 tws_pair = 0; + u8 buf = 2; + u8 ret = 0; + if (get_bt_tws_connect_status()) { + tws_pair = 1; + } else { + if (tws_pair) { + tws_pair = 0; + ret = adv_info_device_request(&buf, sizeof(buf)); + } + } +#endif +} + +// 1、写入VM +static void update_time_stamp_vm_value(u32 time_stamp) +{ + syscfg_write(CFG_RCSP_ADV_TIME_STAMP, (u8 *)&time_stamp, 4); +} +// 2、同步对端 +static void adv_time_stamp_sync(u32 time_stamp) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_adv_setting(BIT(ATTR_TYPE_TIME_STAMP)); + } +#endif +} + +void deal_time_stamp_setting(u32 time_stamp, u8 write_vm, u8 tws_sync) +{ + if (!time_stamp) { + time_stamp = get_adv_time_stamp(); + } else { + set_adv_time_stamp(time_stamp); + } + if (write_vm) { + update_time_stamp_vm_value(time_stamp); + } + if (tws_sync) { + adv_time_stamp_sync(time_stamp); + } +} + +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_time_stamp_setting.h b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_time_stamp_setting.h new file mode 100644 index 0000000..9a04ba2 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_time_stamp_setting.h @@ -0,0 +1,10 @@ +#ifndef __ADV_TIME_STAMP_SETTING_H__ +#define __ADV_TIME_STAMP_SETTING_H__ + +void set_adv_time_stamp(u32 time_stamp); +u32 get_adv_time_stamp(void); +void deal_sibling_time_stamp_setting_switch(void *data, u16 len); +extern void sync_setting_by_time_stamp(void); +void deal_adv_setting_gain_time_stamp(void); + +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_work_setting.c b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_work_setting.c new file mode 100644 index 0000000..eee300c --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_work_setting.c @@ -0,0 +1,104 @@ +#include "app_config.h" +#include "syscfg_id.h" +#include "user_cfg_id.h" +#include "le_rcsp_adv_module.h" + +#include "adv_work_setting.h" +#include "adv_setting_common.h" +#include "rcsp_adv_tws_sync.h" +#include "rcsp_adv_opt.h" +#include "os/os_api.h" +#include "btstack/avctp_user.h" + +#if (RCSP_ADV_EN) +#if RCSP_ADV_WORK_SET_ENABLE + +extern int get_bt_tws_connect_status(); +extern void bt_set_low_latency_mode(int enable); +void set_work_setting(u8 work_setting_info) +{ + _s_info.work_mode = work_setting_info; +} + +u8 get_work_setting(void) +{ + return _s_info.work_mode; +} + +static void adv_work_setting_vm_value(u8 work_setting_info) +{ + /* syscfg_write(CFG_RCSP_ADV_WORK_SETTING, &work_setting_info, 1); */ +} + +static void adv_work_setting_sync(u8 work_setting_info) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_adv_setting(BIT(ATTR_TYPE_WORK_MODE)); + } +#endif +} + +static void __rcsp_work_set_call(void) +{ + //r_f_printf("__rcsp_work_set_call\n"); + if (1 == _s_info.work_mode) { + bt_set_low_latency_mode(0); + } else if (2 == _s_info.work_mode) { + bt_set_low_latency_mode(1); + } +} + +static void rcsp_work_set_deal(void) +{ + int err; + int msg[3]; + msg[0] = (int) __rcsp_work_set_call; + msg[1] = 1; + msg[2] = 0; + + err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg); + //r_printf("err %x\n",err); + + +} + +static void update_work_setting_state(void) +{ + //r_f_printf("set deal\n"); + rcsp_work_set_deal(); +} + +void deal_work_setting(u8 work_setting_info, u8 write_vm, u8 tws_sync, u8 poweron) +{ + if (poweron) { + __rcsp_work_set_call(); + } else { + if (0 == work_setting_info) { + work_setting_info = get_work_setting(); + } else { + set_work_setting(work_setting_info); + } + if (write_vm) { + adv_work_setting_vm_value(work_setting_info); + } + if (tws_sync) { + adv_work_setting_sync(work_setting_info); + } + update_work_setting_state(); + } +} + + +int ble_vendor_is_slow_state(void) +{ + if ((BT_STATUS_PLAYING_MUSIC == get_bt_connect_status()) && (2 == _s_info.work_mode)) { + return 1; + } else { + return 0; + } +} + + +#endif +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_work_setting.h b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_work_setting.h new file mode 100644 index 0000000..3054d8c --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_work_setting.h @@ -0,0 +1,13 @@ +#ifndef __ADV_WORK_SETTING_H__ +#define __ADV_WORK_SETTING_H__ + + +#include "le_rcsp_adv_module.h" + +#if RCSP_ADV_WORK_SET_ENABLE + +void set_work_setting(u8 work_setting_info); +u8 get_work_setting(void); + +#endif +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_bluetooth.h b/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_bluetooth.h new file mode 100644 index 0000000..5ba9c6f --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_bluetooth.h @@ -0,0 +1,119 @@ +#ifndef __JL_BLUETOOTH_ADV_H__ +#define __JL_BLUETOOTH_ADV_H__ + +#include "app_config.h" +#include "typedef.h" +#include "system/event.h" + +#include "le_common.h" +#include "ble_user.h" +#include "spp_user.h" +#if (RCSP_ADV_EN) +void rcsp_init(); +void rcsp_dev_select(u8 type); +void function_change_inform(void); + +bool common_msg_deal(u32 param, void *priv); +bool ble_msg_deal(u32 param); +bool music_msg_deal(u32 param, void *priv); +bool linein_msg_deal(u32 param); +bool rtc_msg_deal(u32 param); + +void rcsp_exit(void); +u8 rcsp_get_asr_status(void); + +enum { + RCSP_BLE, + RCSP_SPP, +}; + + +enum { + ANDROID, + APPLE_IOS, +}; + +struct JL_AI_VAR { + ble_state_e JL_ble_status; + struct ble_server_operation_t *rcsp_ble; + u8 JL_spp_status; + struct spp_operation_t *rcsp_spp; + volatile u8 speech_state; + u32 feature_mask; + u8 device_type; + u8 phone_platform; + void (*start_speech)(void); + void (*stop_speech)(void); + u8 err_report; + volatile u8 file_browse_lock_flag; + u32 return_msg; + u8 spec_mode; + struct __rcsp_user_var *rcsp_user; + volatile u8 rcsp_run_flag; + u8 ffr_mode; + u16 ffr_time; + volatile u8 wait_asr_end; +}; + +struct _SPEECH_OVER_DEAL { + u8 last_task; + u8 status; +}; + +extern struct JL_AI_VAR jl_ai_var; +extern struct _SPEECH_OVER_DEAL speech_deal_val; + + +#define DEVICE_EVENT_FROM_RCSP (('R' << 24) | ('C' << 16) | ('S' << 8) | 'P') + +enum RCSP_MSG_T { + MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET, + MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE, + MSG_JL_LOADER_DOWNLOAD_START, + MSG_JL_UPDATE_START, + MSG_JL_ENTER_UPDATE_MODE, + MSG_JL_DEV_DISCONNECT, + MSG_JL_BLE_UPDATE_START, + MSG_JL_SPP_UPDATE_START, + MSG_JL_ADV_SETTING_SYNC, + MSG_JL_ADV_SETTING_UPDATE, + MSG_JL_UPDATE_EQ, + MSG_JL_UPDATE_SEQ, + MSG_JL_SWITCH_DEVICE, + MSG_JL_UPDATE_PLAYER_TIME, + MSG_JL_UPDATE_PLAYER_STATE, + MSG_JL_UPDATE_MUSIC_INFO, + MSG_JL_UPDATE_MUSIC_PLAYER_TIME_TEMER, + MSG_JL_UPDAET_ADV_STATE_INFO, + MSG_JL_REBOOT_DEV, + MSG_JL_FIND_DEVICE_RESUME, + MSG_JL_FIND_DEVICE_STOP, + MSG_JL_PLAYER_STATE_CHANGE, + MSG_JL_AVRCP_CH_SYNC_MUSIC_INFO, +}; + +void JL_rcsp_event_to_user(u32 type, u8 event, u8 *msg, u8 size); +int JL_rcsp_event_handler(struct rcsp_event *rcsp); +void rcsp_tws_auth_sync_deal(void); +extern u8 JL_get_cur_bt_channel_sel(void); + +#define SDK_TYPE_AC690X 0x0 +#define SDK_TYPE_AC692X 0x1 +#define SDK_TYPE_AC693X 0x2 +#define SDK_TYPE_AC695X 0x3 +#define SDK_TYPE_AC697X 0x4 + +#if (defined CONFIG_CPU_BR21) +#define RCSP_SDK_TYPE SDK_TYPE_AC692X +#elif (defined CONFIG_CPU_BR22) +#define RCSP_SDK_TYPE SDK_TYPE_AC693X +#elif (defined CONFIG_CPU_BR23) +#define RCSP_SDK_TYPE SDK_TYPE_AC695X +#elif (defined CONFIG_CPU_BR30) +#define RCSP_SDK_TYPE SDK_TYPE_AC697X +#else +#define RCSP_SDK_TYPE SDK_TYPE_AC693X +#endif + +#endif +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_opt.c b/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_opt.c new file mode 100644 index 0000000..01137c4 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_opt.c @@ -0,0 +1,419 @@ +#include "app_config.h" +#include "syscfg_id.h" +#include "user_cfg_id.h" +#include "le_rcsp_adv_module.h" +#include "rcsp_adv_bluetooth.h" + +#include "rcsp_adv_opt.h" +#include "adv_setting_common.h" +#include "rcsp_adv_tws_sync.h" +#include "adv_time_stamp_setting.h" +#include "adv_bt_name_setting.h" +#include "adv_key_setting.h" +#include "adv_led_setting.h" +#include "adv_mic_setting.h" +#include "adv_work_setting.h" +#include "adv_eq_setting.h" +#include "adv_high_low_vol.h" +#include "bt_tws.h" +#include "btstack/avctp_user.h" + +#if (RCSP_ADV_EN) +static u16 adv_setting_event_flag = (u16) - 1; +static void set_adv_setting_event_flag(u16 flag) +{ + adv_setting_event_flag = flag; +} + +static u16 get_adv_setting_event_flag(void) +{ + return adv_setting_event_flag; +} + +static u8 deal_adv_setting_string_item(u8 *des, u8 *src, u8 src_len, u8 type) +{ + des[0] = type; + memcpy(des + 1, src, src_len); + return src_len + sizeof(type); +} + +void update_info_from_adv_vm_info(void) +{ + if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_TIME_STAMP)) { + deal_time_stamp_setting(0, 1, 0); + } + +#if RCSP_ADV_NAME_SET_ENABLE + if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_EDR_NAME)) { + deal_bt_name_setting(NULL, 1, 0); + } +#endif + +#if RCSP_ADV_KEY_SET_ENABLE + if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_KEY_SETTING)) { + deal_key_setting(NULL, 1, 0); + } +#endif + +#if RCSP_ADV_LED_SET_ENABLE + if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_LED_SETTING)) { + deal_led_setting(NULL, 1, 0); + } +#endif + +#if RCSP_ADV_MIC_SET_ENABLE + if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_MIC_SETTING)) { + deal_mic_setting(0, 1, 0); + } +#endif + +#if RCSP_ADV_WORK_SET_ENABLE + if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_WORK_MODE)) { + deal_work_setting(0, 1, 0, 0); + } +#endif + +#if RCSP_ADV_EQ_SET_ENABLE + if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_EQ_SETTING)) { + deal_eq_setting(0, 1, 0); + } +#endif + +#if RCSP_ADV_HIGH_LOW_SET + if (get_adv_setting_event_flag() & BIT(ATTR_TYPE_HIGH_LOW_VOL)) { + deal_high_low_vol(NULL, 1, 0); + } +#endif + + set_adv_setting_event_flag(0); +} + +static u8 adv_read_data_from_vm(u8 syscfg_id, u8 *buf, u8 buf_len) +{ + int len = 0; + u8 i = 0; + + + len = syscfg_read(syscfg_id, buf, buf_len); + + if (len > 0) { + for (i = 0; i < buf_len; i++) { + if (buf[i] != 0xff) { + return (buf_len == len); + } + } + } + + return 0; +} + +void adv_setting_init(void) +{ + u32 time_stamp = 0; + if (adv_read_data_from_vm(CFG_RCSP_ADV_TIME_STAMP, (u8 *)&time_stamp, sizeof(time_stamp))) { + set_adv_time_stamp(time_stamp); + //deal_time_stamp_setting(0, 0, 0); + } + +#if RCSP_ADV_NAME_SET_ENABLE + u8 bt_name_info[32] = {0}; + if (adv_read_data_from_vm(CFG_BT_NAME, bt_name_info, sizeof(bt_name_info))) { + set_bt_name_setting(bt_name_info); + //deal_bt_name_setting(NULL, 0, 0); + } +#endif + +#if RCSP_ADV_KEY_SET_ENABLE + u8 key_setting_info[4] = {0}; + if (adv_read_data_from_vm(CFG_RCSP_ADV_KEY_SETTING, key_setting_info, sizeof(key_setting_info))) { + set_key_setting(key_setting_info); + deal_key_setting(NULL, 0, 0); + } +#endif + +#if RCSP_ADV_LED_SET_ENABLE + u8 led_setting_info[3] = {0}; + if (adv_read_data_from_vm(CFG_RCSP_ADV_LED_SETTING, led_setting_info, sizeof(led_setting_info))) { + set_led_setting(led_setting_info); + deal_led_setting(NULL, 0, 0); + } +#endif + +#if RCSP_ADV_MIC_SET_ENABLE + u8 mic_setting_info = 0; + if (adv_read_data_from_vm(CFG_RCSP_ADV_MIC_SETTING, &mic_setting_info, sizeof(mic_setting_info))) { + set_mic_setting(mic_setting_info); + deal_mic_setting(0, 0, 0); + } +#endif + +#if RCSP_ADV_WORK_SET_ENABLE + u8 work_setting_info = 0; + if (adv_read_data_from_vm(CFG_RCSP_ADV_WORK_SETTING, &work_setting_info, sizeof(work_setting_info))) { + set_work_setting(work_setting_info); + deal_work_setting(0, 0, 0, 1); + } +#endif + +#if RCSP_ADV_EQ_SET_ENABLE + u8 eq_setting_vm_info[11] = {0}; + u8 eq_setting_info[10] = {0}; + u8 eq_setting_mode = 0; + u8 i; + if (adv_read_data_from_vm(CFG_RCSP_ADV_EQ_DATA_SETTING, eq_setting_info, sizeof(eq_setting_info))) { + if (adv_read_data_from_vm(CFG_RCSP_ADV_EQ_MODE_SETTING, &eq_setting_mode, sizeof(eq_setting_mode))) { + eq_setting_vm_info[0] = eq_setting_mode; + memcpy(eq_setting_vm_info + 1, eq_setting_info, sizeof(eq_setting_info)); + set_eq_setting(eq_setting_vm_info); + deal_eq_setting(NULL, 0, 0); + } + } +#endif + +#if RCSP_ADV_HIGH_LOW_SET + u8 high_low_vol_setting[8] = {0}; + if (adv_read_data_from_vm(CFG_RCSP_ADV_HIGH_LOW_VOL, high_low_vol_setting, sizeof(high_low_vol_setting))) { + set_high_low_vol_info(high_low_vol_setting); + deal_high_low_vol(NULL, 0, 0); + } +#endif +} + +// type : 0 ~ 8 +// mode : 0 - 从vm读出并更新全局变量数据 // 1 - 同步 +void update_adv_setting(u16 type) +{ + u8 offset = 1; + // total_len time name key led mic work eq vol + u8 adv_setting_to_sync[1 + (4 + 1) + (32 + 1) + (4 + 1) + (3 + 1) + (1 + 1) + (1 + 1) + (11 + 1) + (8 + 1)] = {0}; + memset(adv_setting_to_sync, 0, sizeof(adv_setting_to_sync)); + + if (type & BIT(ATTR_TYPE_TIME_STAMP)) { + u32 time_stamp = get_adv_time_stamp(); + offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, (u8 *)&time_stamp, sizeof(time_stamp), ATTR_TYPE_TIME_STAMP); + } + +#if RCSP_ADV_NAME_SET_ENABLE + if (type & BIT(ATTR_TYPE_EDR_NAME)) { + u8 bt_name_info[32] = {0}; + get_bt_name_setting(bt_name_info); + offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, bt_name_info, sizeof(bt_name_info), ATTR_TYPE_EDR_NAME); + } +#endif + +#if RCSP_ADV_KEY_SET_ENABLE + if (type & BIT(ATTR_TYPE_KEY_SETTING)) { + u8 key_setting_info[4] = {0}; + get_key_setting(key_setting_info); + offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, key_setting_info, sizeof(key_setting_info), ATTR_TYPE_KEY_SETTING); + } +#endif + +#if RCSP_ADV_LED_SET_ENABLE + if (type & BIT(ATTR_TYPE_LED_SETTING)) { + u8 led_setting_info[3] = {0}; + get_led_setting(led_setting_info); + offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, led_setting_info, sizeof(led_setting_info), ATTR_TYPE_LED_SETTING); + } +#endif + +#if RCSP_ADV_MIC_SET_ENABLE + if (type & BIT(ATTR_TYPE_MIC_SETTING)) { + u8 mic_setting_info = get_mic_setting(); + offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, &mic_setting_info, sizeof(mic_setting_info), ATTR_TYPE_MIC_SETTING); + } +#endif + +#if RCSP_ADV_WORK_SET_ENABLE + if (type & BIT(ATTR_TYPE_WORK_MODE)) { + u8 work_setting_info = get_work_setting(); + offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, &work_setting_info, sizeof(work_setting_info), ATTR_TYPE_WORK_MODE); + } +#endif + +#if RCSP_ADV_EQ_SET_ENABLE + if (type & BIT(ATTR_TYPE_EQ_SETTING)) { + u8 eq_setting_info[11]; + get_eq_setting(eq_setting_info); + offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, eq_setting_info, sizeof(eq_setting_info), ATTR_TYPE_EQ_SETTING); + } +#endif + +#if RCSP_ADV_HIGH_LOW_SET + if (type & BIT(ATTR_TYPE_HIGH_LOW_VOL)) { + u8 high_low_vol[8]; + get_high_low_vol_info(high_low_vol); + offset += deal_adv_setting_string_item(adv_setting_to_sync + offset, high_low_vol, sizeof(high_low_vol), ATTR_TYPE_HIGH_LOW_VOL); + } +#endif + + if (offset > 1) { + adv_setting_to_sync[0] = offset; + if (type == ((u16) - 1)) { + tws_api_send_data_to_sibling(adv_setting_to_sync, sizeof(adv_setting_to_sync), TWS_FUNC_ID_ADV_SETTING_SYNC); +#if RCSP_ADV_LED_SET_ENABLE + tws_api_sync_call_by_uuid('T', SYNC_CMD_APP_RESET_LED_UI, 300); +#endif + } else { + if (tws_api_get_role() == TWS_ROLE_MASTER) { + tws_api_send_data_to_sibling(adv_setting_to_sync, sizeof(adv_setting_to_sync), TWS_FUNC_ID_ADV_SETTING_SYNC); +#if RCSP_ADV_LED_SET_ENABLE + tws_api_sync_call_by_uuid('T', SYNC_CMD_APP_RESET_LED_UI, 300); +#endif + } + } + } +} + +void deal_sibling_setting(u8 *buf) +{ + u8 type; + u8 len = buf[0]; + u8 offset = 1; + u8 *data; + u32 time_stamp = 0; + set_adv_setting_event_flag(0); + while (offset < len) { + type = buf[offset++]; + data = buf + offset; + switch (type) { +#if RCSP_ADV_NAME_SET_ENABLE + case ATTR_TYPE_EDR_NAME: + set_bt_name_setting(data); + offset += 32; + break; +#endif +#if RCSP_ADV_KEY_SET_ENABLE + case ATTR_TYPE_KEY_SETTING : + set_key_setting(data); + offset += 4; + break; +#endif +#if RCSP_ADV_LED_SET_ENABLE + case ATTR_TYPE_LED_SETTING : + set_led_setting(data); + offset += 3; + break; +#endif +#if RCSP_ADV_MIC_SET_ENABLE + case ATTR_TYPE_MIC_SETTING : + set_mic_setting(*data); + offset += 1; + break; +#endif +#if RCSP_ADV_WORK_SET_ENABLE + case ATTR_TYPE_WORK_MODE : + set_work_setting(*data); + offset += 1; + break; +#endif +#if RCSP_ADV_EQ_SET_ENABLE + case ATTR_TYPE_EQ_SETTING : + /* g_printf("tws eq setting\n"); */ + set_eq_setting(data); + offset += 11; + break; +#endif +#if RCSP_ADV_HIGH_LOW_SET + case ATTR_TYPE_HIGH_LOW_VOL: + set_high_low_vol_info(data); + offset += 8; + break; +#endif + case ATTR_TYPE_TIME_STAMP: + time_stamp = (data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24));//*((u32 *)data); + + set_adv_time_stamp(time_stamp); + offset += 4; + break; + default: + return; + } + set_adv_setting_event_flag(get_adv_setting_event_flag() | BIT(type)); + } + // 发送事件 + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_ADV_SETTING_UPDATE, NULL, 0); +} + +#if (0) +static void adv_reset_data_to_vm(u8 syscfg_id, u8 *buf, u8 buf_len) +{ + u8 res = 0; + res = syscfg_write(syscfg_id, buf, buf_len); +} + +u8 rcsp_setting_info_reset() //恢复默认的APP设置 +{ + printf("%s", __func__); + + u32 time_stamp = 0xffffffff; + adv_reset_data_to_vm(CFG_RCSP_ADV_TIME_STAMP, (u8 *)&time_stamp, sizeof(time_stamp)); + + /* #if RCSP_ADV_NAME_SET_ENABLE */ + /* u8 bt_name_info[32] = {0}; */ + /* memset(bt_name_info,0xff,32); */ + /* adv_reset_data_to_vm(CFG_BT_NAME, bt_name_info, sizeof(bt_name_info)); */ + /* #endif */ + +#if RCSP_ADV_KEY_SET_ENABLE + u8 key_setting_info[4] = {0}; + memset(key_setting_info, 0xff, 4); + adv_reset_data_to_vm(CFG_RCSP_ADV_KEY_SETTING, key_setting_info, sizeof(key_setting_info)); +#endif + +#if RCSP_ADV_LED_SET_ENABLE + u8 led_setting_info[3] = {0}; + memset(led_setting_info, 0xff, 3); + adv_reset_data_to_vm(CFG_RCSP_ADV_LED_SETTING, led_setting_info, sizeof(led_setting_info)); +#endif + +#if RCSP_ADV_MIC_SET_ENABLE + u8 mic_setting_info = 0xff; + adv_reset_data_to_vm(CFG_RCSP_ADV_MIC_SETTING, &mic_setting_info, sizeof(mic_setting_info)); +#endif + +#if RCSP_ADV_WORK_SET_ENABLE + u8 work_setting_info = 0xff; + adv_reset_data_to_vm(CFG_RCSP_ADV_WORK_SETTING, &work_setting_info, sizeof(work_setting_info)); +#endif + +#if RCSP_ADV_EQ_SET_ENABLE + u8 eq_setting_info[10] = {0}; + u8 eq_setting_mode = 0xff; + memset(eq_setting_info, 0xff, 10); + adv_reset_data_to_vm(CFG_RCSP_ADV_EQ_DATA_SETTING, &eq_setting_info, sizeof(eq_setting_info)); + adv_reset_data_to_vm(CFG_RCSP_ADV_EQ_MODE_SETTING, &eq_setting_mode, sizeof(eq_setting_mode)); +#endif + return 0; +} + +u8 remap_app_chargestore_data_deal(u8 *buf, u8 len) +{ + u8 send_buf[30]; + u8 ret = 0; + send_buf[0] = buf[0]; +//#define CMD_GET_NAME 0xc1 + switch (buf[0]) { + case 0x08: + //printf("\n\n\n\n\n\n---------------reset store sys\n"); + ret = 1 ; + + void bt_tws_remove_pairs(); + bt_tws_remove_pairs(); + extern u8 rcsp_setting_info_reset(); + rcsp_setting_info_reset(); + user_send_cmd_prepare(USER_CTRL_DEL_ALL_REMOTE_INFO, 0, NULL); + os_time_dly(60); + cpu_reset(); + + break; + + default: + break; + } + return ret; +} +#endif + + +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_opt.h b/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_opt.h new file mode 100644 index 0000000..f8a9a72 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_opt.h @@ -0,0 +1,6 @@ +#ifndef __RCSP_ADV_OPT_H__ +#define __RCSP_ADV_OPT_H__ + +void deal_sibling_setting(u8 *buf); + +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_tws_sync.c b/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_tws_sync.c new file mode 100644 index 0000000..3ec2dff --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_tws_sync.c @@ -0,0 +1,105 @@ +#include "app_config.h" +#include "rcsp_adv_tws_sync.h" +#include "adv_setting_common.h" +#include "rcsp_adv_opt.h" +#include "adv_time_stamp_setting.h" +#include "rcsp_adv_bluetooth.h" +#include "bt_tws.h" + +#if (RCSP_ADV_EN && TCFG_USER_TWS_ENABLE) +static void adv_sync_tws_func_t(void *data, u16 len, bool rx) +{ + if (rx) { + deal_sibling_setting((u8 *)data); + } +} + +REGISTER_TWS_FUNC_STUB(adv_tws_sync) = { + .func_id = TWS_FUNC_ID_ADV_SETTING_SYNC, + .func = adv_sync_tws_func_t, +}; + +static void adv_sync_time_stamp_func_t(void *data, u16 len, bool rx) +{ + if (rx) { + deal_sibling_time_stamp_setting_switch(data, len); + } +} + +REGISTER_TWS_FUNC_STUB(adv_time_stamp_sync) = { + .func_id = TWS_FUNC_ID_TIME_STAMP_SYNC, + .func = adv_sync_time_stamp_func_t, +}; + +#define TWS_FUNC_ID_ADV_RESET_SYNC \ + (((u8)('R' + 'C' + 'S' + 'P') << (3 * 8)) | \ + ((u8)('A' + 'D' + 'V') << (2 * 8)) | \ + ((u8)('R' + 'E' + 'S' + 'E' + 'T') << (1 * 8)) | \ + ((u8)('S' + 'Y' + 'N' + 'C') << (0 * 8))) + +static void adv_sync_reset_sync_func_t(int args) +{ + extern void cpu_reset(); + cpu_reset(); +} + +TWS_SYNC_CALL_REGISTER(adv_reset_sync) = { + .uuid = TWS_FUNC_ID_ADV_RESET_SYNC, + .func = adv_sync_reset_sync_func_t, +}; + +void modify_bt_name_and_reset(u32 msec) +{ + tws_api_sync_call_by_uuid(TWS_FUNC_ID_ADV_RESET_SYNC, 0, msec); +} + +#define TWS_FUNC_ID_ADV_FIND_DEV_SYNC \ + (((u8)('A' + 'D' + 'V') << (3 * 8)) | \ + ((u8)('F' + 'I' + 'N' + 'D') << (2 * 8)) | \ + ((u8)('D' + 'E' + 'V') << (1 * 8)) | \ + ((u8)('S' + 'Y' + 'N' + 'C') << (0 * 8))) + +static void adv_find_dev_sync_func_t(int args) +{ + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_FIND_DEVICE_RESUME, &args, sizeof(args)); +} + +TWS_SYNC_CALL_REGISTER(adv_find_dev_sync) = { + .uuid = TWS_FUNC_ID_ADV_FIND_DEV_SYNC, + .func = adv_find_dev_sync_func_t, +}; + +void find_device_sync(u8 *param, u32 msec) +{ + int priv = 0; + if (TWS_ROLE_MASTER == tws_api_get_role()) { + memcpy(&priv, param, 3); + tws_api_sync_call_by_uuid(TWS_FUNC_ID_ADV_FIND_DEV_SYNC, priv, msec); + } +} + +#define TWS_FUNC_ID_ADV_FIND_DEV_STOP_TIMER_SYNC \ + (((u8)('F' + 'I' + 'N' + 'D') << (3 * 8)) | \ + ((u8)('D' + 'E' + 'V') << (2 * 8)) | \ + ((u8)('S' + 'T' + 'O' + 'P') << (1 * 8)) | \ + ((u8)('S' + 'Y' + 'N' + 'C') << (0 * 8))) + +static void adv_find_dev_stop_sync_timer_func_t(int args) +{ + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_FIND_DEVICE_STOP, &args, sizeof(args)); +} + +TWS_SYNC_CALL_REGISTER(adv_find_dev_stop_sync) = { + .uuid = TWS_FUNC_ID_ADV_FIND_DEV_STOP_TIMER_SYNC, + .func = adv_find_dev_stop_sync_timer_func_t, +}; + +void find_devic_stop_timer(u8 *param, u32 msec) +{ + int priv = 0; + if (TWS_ROLE_MASTER == tws_api_get_role()) { + memcpy(&priv, param, 3); + tws_api_sync_call_by_uuid(TWS_FUNC_ID_ADV_FIND_DEV_STOP_TIMER_SYNC, priv, msec); + } +} +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_tws_sync.h b/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_tws_sync.h new file mode 100644 index 0000000..4b2e1a9 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_tws_sync.h @@ -0,0 +1,13 @@ +#ifndef __RCSP_ADV_TWS_SYNC_H__ +#define __RCSP_ADV_TWS_SYNC_H__ + +#include "classic/tws_api.h" + +#define TWS_FUNC_ID_ADV_SETTING_SYNC \ + TWS_FUNC_ID('R', 'C', 'S', 'P') +#define TWS_FUNC_ID_TIME_STAMP_SYNC \ + TWS_FUNC_ID('R' + 'C' + 'S' + 'P', \ + 'A' + 'D' + 'V', \ + 'T' + 'I' + 'M' + 'E', \ + 'S' + 'T' + 'A' + 'M' + 'P') +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.h b/apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.h new file mode 100644 index 0000000..34fd367 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/bt_trans_data/le_rcsp_adv_module.h @@ -0,0 +1,161 @@ +// binary representation +// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) + +#ifndef _LE_SERVER_MODULE_H +#define _LE_SERVER_MODULE_H + +#include +#include "bt_common.h" +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV_RCSP) +// +// gatt profile include file, generated by jieli gatt_inc_generator.exe +// +static const uint8_t profile_data[] = { + ////////////////////////////////////////////////////// + // + // 0x0001 PRIMARY_SERVICE 1800 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x18, + + /* CHARACTERISTIC, 2a00, READ | WRITE | DYNAMIC, */ + // 0x0002 CHARACTERISTIC 2a00 READ | WRITE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x0a, 0x03, 0x00, 0x00, 0x2a, + // 0x0003 VALUE 2a00 READ | WRITE | DYNAMIC + 0x08, 0x00, 0x0a, 0x01, 0x03, 0x00, 0x00, 0x2a, + + ////////////////////////////////////////////////////// + // + // 0x0004 PRIMARY_SERVICE ae00 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x28, 0x00, 0xae, + + /* CHARACTERISTIC, ae01, WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x0040 CHARACTERISTIC ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x81, 0x00, 0x03, 0x28, 0x04, 0x82, 0x00, 0x01, 0xae, + // 0x0041 VALUE ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x08, 0x00, 0x04, 0x01, 0x82, 0x00, 0x01, 0xae, + + /* CHARACTERISTIC, ae02, NOTIFY, */ + // 0x0042 CHARACTERISTIC ae02 NOTIFY + 0x0d, 0x00, 0x02, 0x00, 0x83, 0x00, 0x03, 0x28, 0x10, 0x84, 0x00, 0x02, 0xae, + // 0x0043 VALUE ae02 NOTIFY + 0x08, 0x00, 0x10, 0x00, 0x84, 0x00, 0x02, 0xae, + // 0x0044 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x85, 0x00, 0x02, 0x29, 0x00, 0x00, + ////////////////////////////////////////////////////// + // + // 0x0014 PRIMARY_SERVICE 1812 + // + ////////////////////////////////////////////////////// + // 0x0a, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x28, 0x12, 0x18, + +#if 0// authentication + // + 10, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x28, 0x0A, 0x18, //primary service declaration + 13, 0x00, 0x02, 0x00, 0x1B, 0x00, 0x03, 0x28, 0x02, 0x1C, 0x00, 0x50, 0x2A, //characteristic declaration + 15, 0x00, 0x02, 0x04, 0x1C, 0x00, 0x50, 0x2A, 0x02, 0x8A, 0x24, 0x66, 0x82, 0x34, 0x36, //PnP ID +#endif + + // END + 0x00, 0x00, +}; +// +// characteristics <--> handles +// +#define ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE 0x0003 +#define ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE 0x0082 +#define ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE 0x0084 +#define ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE 0x0085 + +// #define ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE 0x0006 +// #define ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE 0x0008 +// #define ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE 0x0009 +// #define ATT_CHARACTERISTIC_ae03_01_VALUE_HANDLE 0x000b +// #define ATT_CHARACTERISTIC_ae04_01_VALUE_HANDLE 0x000d +// #define ATT_CHARACTERISTIC_ae04_01_CLIENT_CONFIGURATION_HANDLE 0x000e +// #define ATT_CHARACTERISTIC_ae05_01_VALUE_HANDLE 0x0010 +// #define ATT_CHARACTERISTIC_ae05_01_CLIENT_CONFIGURATION_HANDLE 0x0011 +// #define ATT_CHARACTERISTIC_ae10_01_VALUE_HANDLE 0x0013 + + + + +#define JL_OPCODE_SET_ADV 0xC0 +#define JL_OPCODE_GET_ADV 0xC1 +#define JL_OPCODE_ADV_DEVICE_NOTIFY 0xC2 +#define JL_OPCODE_ADV_NOTIFY_SETTING 0xC3 +#define JL_OPCODE_ADV_DEVICE_REQUEST 0xC4 + +#define ATTR_TYPE_BAT_VALUE (0) +#define ATTR_TYPE_EDR_NAME (1) +#define ATTR_TYPE_KEY_SETTING (2) +#define ATTR_TYPE_LED_SETTING (3) +#define ATTR_TYPE_MIC_SETTING (4) +#define ATTR_TYPE_WORK_MODE (5) +#define ATTR_TYPE_PRODUCT_MESSAGE (6) +#define ATTR_TYPE_TIME_STAMP (7) +#define ATTR_TYPE_EQ_SETTING (8) +#define ATTR_TYPE_HIGH_LOW_VOL (9) + +//rcsp功能模块使能 +#define RCSP_ADV_NAME_SET_ENABLE 1 +#define RCSP_ADV_KEY_SET_ENABLE 1 +#define RCSP_ADV_LED_SET_ENABLE 1 +#define RCSP_ADV_MIC_SET_ENABLE 1 +#define RCSP_ADV_WORK_SET_ENABLE 1 +#if (JL_EARPHONE_APP_EN) +#define RCSP_ADV_EQ_SET_ENABLE 1 +#define RCSP_ADV_MUSIC_INFO_ENABLE 1 +#define RCSP_ADV_HIGH_LOW_SET 1 +#define RCSP_ADV_FIND_DEVICE_ENABLE 1 +#else +#define RCSP_ADV_EQ_SET_ENABLE 0 +#define RCSP_ADV_MUSIC_INFO_ENABLE 0 +#define RCSP_ADV_HIGH_LOW_SET 0 +#define RCSP_ADV_FIND_DEVICE_ENABLE 0 +#endif +#define RCSP_ADV_PRODUCT_MSG_ENABLE 1 + +enum { + BT_ADV_ENABLE, + BT_ADV_DISABLE, + BT_ADV_SET_EDR_CON_FLAG, + BT_ADV_SET_BAT_CHARGE_L, + BT_ADV_SET_BAT_CHARGE_R, + BT_ADV_SET_BAT_CHARGE_C, + BT_ADV_SET_BAT_PERCENT_L, + BT_ADV_SET_BAT_PERCENT_R, + BT_ADV_SET_BAT_PERCENT_C, + BT_ADV_SET_NOTIFY_EN, +}; + +// BT_ADV_SET_EDR_CON_FLAG +#define SECNE_DISMISS (0x00) +#define SECNE_UNCONNECTED (0x01) +#define SECNE_CONNECTED (0x02) +#define SECNE_CONNECTING (0x03) +#define SECNE_CONNECTINLESS (0x04) + +#define TWS_FUNC_ID_SEQ_RAND_SYNC (('S' << (3 * 8)) | ('E' << (2 * 8)) | ('Q' << (1 * 8)) | ('\0')) + +enum { + TWS_ADV_SEQ_CHANGE = 0, + TWS_VERSON_INFO, + TWS_UPDATE_INFO, +}; + +extern int bt_ble_adv_ioctl(u32 cmd, u32 priv, u8 mode); +extern void bt_adv_seq_change(void); +void ble_app_disconnect(void); +void bt_ble_rcsp_adv_enable(void); +void bt_ble_rcsp_adv_disable(void); +u8 get_ble_adv_notify(void); +void set_ble_adv_notify(u8 en); +u8 get_connect_flag(void); +void set_connect_flag(u8 value); +void ble_module_enable(u8 en); + +#endif +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/btcrypt.h b/apps/common/third_party_profile/jieli/JL_rcsp/btcrypt.h new file mode 100644 index 0000000..33b62f5 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/btcrypt.h @@ -0,0 +1,42 @@ +#ifndef TOMCRYPT_H_ +#define TOMCRYPT_H_ +// #include +#include + + +#define HARDWARE_METHOD 0 + +#ifndef WIN32 +// #include "hw_cpu.h" +#undef HARDWARE_METHOD +#define HARDWARE_METHOD 1 +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +/* +@param [in] pt[*1] The plaintext +@param ptlen The length of the plaintext(octets) range: 1~32 +@param [in] key[*1] The key for encrypt +@param keylen[*1] The length of the key(octets) range: 1~32 +@param [out] mac[*1] output : The Message Authentication Code 16 bytes. +*/ +extern void btcon_hash(unsigned char *pt, int ptlen, unsigned char *key, int keylen, unsigned char *mac); + +#if HARDWARE_METHOD +extern int yf_aes_start_enc(unsigned char key[16], unsigned char plaintext[16], unsigned char encrypt[16]); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* TOMCRYPT_H_ */ + + +/* $Source$ */ +/* $Revision$ */ +/* $Date$ */ diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_bluetooth.h b/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_bluetooth.h new file mode 100644 index 0000000..915a6f9 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_bluetooth.h @@ -0,0 +1,98 @@ +#ifndef __JL_BLUETOOTH_H__ +#define __JL_BLUETOOTH_H__ + +#include "typedef.h" +#include "le_common.h" +#include "spp_user.h" +#include "system/event.h" +#include "rcsp_msg.h" +#include "ble_user.h" +#if RCSP_BTMATE_EN +void rcsp_init(); +void rcsp_dev_select(u8 type); +void function_change_inform(void); + +bool common_msg_deal(u32 param, void *priv); +bool ble_msg_deal(u32 param); +bool music_msg_deal(u32 param, void *priv); +bool linein_msg_deal(u32 param); +bool rtc_msg_deal(u32 param); + +void rcsp_exit(void); +u8 rcsp_get_asr_status(void); + +// enum { +// RCSP_BLE, +// RCSP_SPP, +// }; + + +enum { + ANDROID, + APPLE_IOS, +}; + +struct JL_AI_VAR { + ble_state_e JL_ble_status; + struct ble_server_operation_t *rcsp_ble; + u8 JL_spp_status; + struct spp_operation_t *rcsp_spp; + volatile u8 speech_state; + u32 feature_mask; + u8 device_type; + u8 phone_platform; + void (*start_speech)(void); + void (*stop_speech)(void); + u8 err_report; + volatile u8 file_browse_lock_flag; + u32 return_msg; + u8 spec_mode; + struct __rcsp_user_var *rcsp_user; + volatile u8 rcsp_run_flag; + u8 ffr_mode; + u16 ffr_time; + u16 rcsp_timer_hdl; + volatile u8 wait_asr_end; +}; + +struct _SPEECH_OVER_DEAL { + u8 last_task; + u8 status; +}; + +extern struct JL_AI_VAR jl_ai_var; +extern struct _SPEECH_OVER_DEAL speech_deal_val; + +enum RCSP_MSG_T { + MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET = RCSP_MSG_END, + MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE, + MSG_JL_LOADER_DOWNLOAD_START, + MSG_JL_UPDATE_START, + MSG_JL_ENTER_UPDATE_MODE, + MSG_JL_DEV_DISCONNECT, + MSG_JL_BLE_UPDATE_START, + MSG_JL_SPP_UPDATE_START, +}; + +bool rcsp_msg_post(RCSP_MSG msg, int argc, ...); + +#define SDK_TYPE_AC690X 0x0 +#define SDK_TYPE_AC692X 0x1 +#define SDK_TYPE_AC693X 0x2 +#define SDK_TYPE_AC695X 0x3 +#define SDK_TYPE_AC697X 0x4 + +#if (defined CONFIG_CPU_BR21) +#define RCSP_SDK_TYPE SDK_TYPE_AC692X +#elif (defined CONFIG_CPU_BR22) +#define RCSP_SDK_TYPE SDK_TYPE_AC693X +#elif (defined CONFIG_CPU_BR23) +#define RCSP_SDK_TYPE SDK_TYPE_AC695X +#elif (defined CONFIG_CPU_BR30) +#define RCSP_SDK_TYPE SDK_TYPE_AC697X +#else +#define RCSP_SDK_TYPE SDK_TYPE_AC693X +#endif +#endif + +#endif diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_msg.h b/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_msg.h new file mode 100644 index 0000000..59e1012 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_msg.h @@ -0,0 +1,13 @@ +#ifndef __RCSP_MSG_H__ +#define __RCSP_MSG_H__ + +typedef enum __RCSP_MSG { + RCSP_MSG_UPDATE_EQ = 0, + RCSP_MSG_SET_FMTX_POINT, + RCSP_MSG_BS_END, + RCSP_MSG_BT_SCAN, + RCSP_MSG_END, +} RCSP_MSG; + +#endif//__RCSP_MSG_H__ + diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata/rcsp_adv_user_update.c b/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata/rcsp_adv_user_update.c new file mode 100644 index 0000000..4350709 --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata/rcsp_adv_user_update.c @@ -0,0 +1,518 @@ +#include "app_config.h" +#include "rcsp_adv_user_update.h" +#if RCSP_UPDATE_EN +#include "uart.h" +#include "system/timer.h" +#include "update.h" +#include "custom_cfg.h" +#include "btstack/avctp_user.h" +#include "JL_rcsp_packet.h" +#include "JL_rcsp_protocol.h" +#include "rcsp_adv_bluetooth.h" +#include "le_rcsp_adv_module.h" +#include "update_loader_download.h" +#include "classic/tws_api.h" +#include "syscfg_id.h" + +#if (RCSP_ADV_EN) + +#define RCSP_DEBUG_EN + +#ifdef RCSP_DEBUG_EN +#define rcsp_putchar(x) putchar(x) +#define rcsp_printf printf +#define rcsp_printf_buf(x,len) printf_buf(x,len) +#else +#define rcsp_putchar(...) +#define rcsp_printf(...) +#define rcsp_printf_buf(...) +#endif + +#define DEV_UPDATE_FILE_INFO_OFFEST 0x00//0x40 +#define DEV_UPDATE_FILE_INFO_LEN 0x00//(0x10 + VER_INFO_EXT_COUNT * (VER_INFO_EXT_MAX_LEN + 1)) + +typedef enum { + UPDATA_START = 0x00, + UPDATA_REV_DATA, + UPDATA_STOP, +} UPDATA_BIT_FLAG; + +#if 0 +static update_file_id_t update_file_id_info = { + .ver[0] = 0xff, + .ver[1] = 0xff, +}; +#else +static update_file_ext_id_t update_file_id_info = { + .update_file_id_info.ver[0] = 0xff, + .update_file_id_info.ver[1] = 0xff, +}; +#endif + +extern const int support_dual_bank_update_en; +extern void JL_ble_disconnect(void); +extern void updata_parm_set(UPDATA_TYPE up_type, void *priv, u32 len); +extern u8 check_le_pakcet_sent_finish_flag(void); + +static u8 update_flag = 0; +static u8 tws_need_update = 0; //标志耳机是否需要强制升级 +static u8 tws_need_role_switch = 0; //用于tws连接之后版本号不匹配进行role_switch,低版本号的作为主机进行强制升级 +static u8 disconnect_flag = 0; +u8 get_jl_update_flag(void) +{ + printf("get_update_flag:%x\n", update_flag); + return update_flag; +} + +void set_jl_update_flag(u8 flag) +{ + update_flag = flag; + printf("update_flag:%x\n", update_flag); +} + +typedef struct _update_mode_t { + u8 opcode; + u8 opcode_sn; + +} update_mode_t; + +static update_mode_t update_record_info; + +void JL_controller_save_curr_cmd_para(u8 OpCode, u8 OpCode_SN) +{ + update_record_info.opcode = OpCode; + update_record_info.opcode_sn = OpCode_SN; +} + +void JL_controller_get_curr_cmd_para(u8 *OpCode, u8 *OpCode_SN) +{ + *OpCode = update_record_info.opcode; + *OpCode_SN = update_record_info.opcode_sn; +} + +static void (*fw_update_block_handle)(u8 state, u8 *buf, u16 len) = NULL; +void register_receive_fw_update_block_handle(void (*handle)(u8 state, u8 *buf, u16 len)) +{ + fw_update_block_handle = handle; +} + +static u16 ble_discon_timeout; +static void ble_discon_timeout_handle(void *priv) +{ + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_START, NULL, 0); +} + +void JL_rcsp_update_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + u8 msg[4]; + rcsp_printf("%s\n", __FUNCTION__); + switch (OpCode) { + case JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET: + if (0 == len) { + msg[0] = OpCode; + msg[1] = OpCode_SN; + rcsp_printf("JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET\n"); + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, + MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET, + msg, + 2); + } else { + rcsp_printf("JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET ERR\n"); + } + break; + case JL_OPCODE_INQUIRE_DEVICE_IF_CAN_UPDATE: + rcsp_printf("JL_OPCODE_INQUIRE_DEVICE_IF_CAN_UPDATE:%x %x\n", len, data[0]); + if (len) { + extern void set_curr_update_type(u8 type); + set_curr_update_type(data[0]); + msg[0] = OpCode; + msg[1] = OpCode_SN; + msg[2] = 0x00; + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, + MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE, + msg, + 3); + } + break; + case JL_OPCODE_EXIT_UPDATE_MODE: + rcsp_printf("JL_OPCODE_EXIT_UPDATE_MODE\n"); + break; + case JL_OPCODE_ENTER_UPDATE_MODE: + rcsp_printf("JL_OPCODE_ENTER_UPDATE_MODE\n"); + msg[0] = OpCode; + msg[1] = OpCode_SN; + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, + MSG_JL_ENTER_UPDATE_MODE, + msg, + 2); + break; + case JL_OPCODE_SEND_FW_UPDATE_BLOCK: + rcsp_printf("JL_OPCODE_SEND_FW_UPDATE_BLOCK\n"); + break; + case JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS: + rcsp_printf("JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS\n"); + JL_controller_save_curr_cmd_para(OpCode, OpCode_SN); + if (fw_update_block_handle) { + fw_update_block_handle(UPDATA_STOP, NULL, 0); + } + break; + /* case JL_OPCODE_SET_DEVICE_REBOOT: */ + /* rcsp_printf("JL_OPCODE_SET_DEVICE_REBOOT\n"); */ + /* if (support_dual_bank_update_en) { */ + /* cpu_reset(); */ + /* } */ + /* break; */ + default: + break; + } +} + +static void JL_rcsp_resp_dev_update_file_info_offest(u8 OpCode, u8 OpCode_SN) +{ + u8 data[4 + 2]; + u16 update_file_info_offset = DEV_UPDATE_FILE_INFO_OFFEST; + u16 update_file_info_len = DEV_UPDATE_FILE_INFO_LEN; + WRITE_BIG_U32(data + 0, update_file_info_offset); + WRITE_BIG_U16(data + 4, update_file_info_len); + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, sizeof(data)); +} + +static void JL_resp_inquire_device_if_can_update(u8 OpCode, u8 OpCode_SN, u8 update_sta) +{ + u8 data[1]; + data[0] = update_sta; + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, sizeof(data)); +} + +enum { + UPDATE_FLAG_OK, + UPDATE_FLAG_LOW_POWER, + UPDATE_FLAG_FW_INFO_ERR, + UPDATE_FLAG_FW_INFO_CONSISTENT, + UPDATE_FLAG_TWS_DISCONNECT, +}; + +static u8 judge_remote_version_can_update(void) +{ + //extern u16 ex_cfg_get_local_version_info(void); + u16 remote_file_ver = READ_BIG_U16(update_file_id_info.update_file_id_info.ver); + //u16 local_ver = ex_cfg_get_local_version_info(); + u16 local_ver = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG); + +#if (0 == VER_INFO_EXT_COUNT) + //extern u16 ex_cfg_get_local_pid_info(void); + //extern u16 ex_cfg_get_local_vid_info(void); + + //u16 local_pid = ex_cfg_get_local_pid_info(); + //u16 local_vid = ex_cfg_get_local_vid_info(); + u16 local_pid = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG); + u16 local_vid = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG); + + u16 remote_file_pid = READ_BIG_U16(update_file_id_info.update_file_id_info.pid); + u16 remote_file_vid = READ_BIG_U16(update_file_id_info.update_file_id_info.vid); + + if (remote_file_ver > local_ver || remote_file_pid != local_pid || remote_file_vid != local_vid) { + return UPDATE_FLAG_FW_INFO_ERR; + } +#else + //extern u32 ex_cfg_get_local_authkey_info(u8 * authkey_data[], u8 * authkey_len); + //extern u32 ex_cfg_get_local_procode_info(u8 * procode_data[], u8 * procode_len); + + u8 authkey_len = 0; + u8 *local_authkey_data = NULL; + get_authkey_procode_from_cfg_file(&local_authkey_data, &authkey_len, GET_AUTH_KEY_FROM_EX_CFG); + + u8 procode_len = 0; + u8 *local_procode_data = NULL; + get_authkey_procode_from_cfg_file(&local_procode_data, &procode_len, GET_PRO_CODE_FROM_EX_CFG); + + //ex_cfg_get_local_authkey_info(&local_authkey_data, &authkey_len); + //ex_cfg_get_local_procode_info(&local_procode_data, &procode_len); + + u8 *remote_authkey_data = update_file_id_info.ext; + u8 *remote_procode_data = update_file_id_info.ext + authkey_len + 1; + + if (remote_file_ver < local_ver + || 0 != memcmp(remote_authkey_data, local_authkey_data, authkey_len) + || 0 != memcmp(remote_procode_data, local_procode_data, procode_len)) { + return UPDATE_FLAG_FW_INFO_ERR; + } +#endif + + if (remote_file_ver == local_ver) { + rcsp_printf("remote_file_ver is %x, local_ver is %x, remote_file_ver is similar to local_ver\n", remote_file_ver, local_ver); + return UPDATE_FLAG_FW_INFO_CONSISTENT; + } + + return UPDATE_FLAG_OK; +} + +static bool check_edr_is_disconnct(void) +{ + if (get_curr_channel_state()) { + return TRUE; + } else { + return FALSE; + } +} + +static bool check_ble_all_packet_sent(void) +{ + if (check_le_pakcet_sent_finish_flag()) { + return TRUE; + } else { + return FALSE; + } +} + + +static u32 rcsp_update_data_read(void *priv, u32 offset_addr, u16 len) +{ + u32 err; + u8 data[4 + 2]; + WRITE_BIG_U32(data, offset_addr); + WRITE_BIG_U16(data + 4, len); + err = JL_CMD_send(JL_OPCODE_SEND_FW_UPDATE_BLOCK, data, sizeof(data), JL_NEED_RESPOND); + + return err; +} + +static JL_ERR JL_controller_resp_get_dev_refresh_fw_status(u8 OpCode, u8 OpCode_SN, u8 result) +{ + JL_ERR send_err = JL_ERR_NONE; + u8 data[1]; + + data[0] = result; //0:sucess 1:fail; + + send_err = JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, sizeof(data)); + + return send_err; +} + +u32 rcsp_update_status_response(void *priv, u8 status) +{ + u8 OpCode; + u8 OpCode_SN; + + JL_ERR send_err = JL_ERR_NONE; + + JL_controller_get_curr_cmd_para(&OpCode, &OpCode_SN); + + //log_info("get cmd para:%x %x\n", OpCode, OpCode_SN); + + if (JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS == OpCode) { + send_err = JL_controller_resp_get_dev_refresh_fw_status(OpCode, OpCode_SN, status); + } + + return send_err; +} + + + +void JL_rcsp_update_cmd_receive_resp(void *priv, u8 OpCode, u8 status, u8 *data, u16 len) +{ + switch (OpCode) { + case JL_OPCODE_SEND_FW_UPDATE_BLOCK: + if (fw_update_block_handle) { + fw_update_block_handle(UPDATA_REV_DATA, data, len); + } + break; + default: + break; + } +} + +static void rcsp_loader_download_result_handle(void *priv, u8 type, u8 cmd) +{ + if (UPDATE_LOADER_OK == cmd) { + //JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP,MSG_JL_UPDATE_START,NULL,0); + set_jl_update_flag(1); + if (support_dual_bank_update_en) { + rcsp_printf(">>>rcsp update succ\n"); + update_result_set(UPDATA_SUCC); + } + } else { + rcsp_printf(">>>update loader err\n"); + /* #if OTA_TWS_SAME_TIME_ENABLE */ + /* if((tws_ota_control(OTA_TYPE_GET) == OTA_TWS)) { */ + /* tws_ota_stop(OTA_STOP_UPDATE_OVER_ERR); */ + /* } */ + /* #endif */ + //rcsp_db_update_fail_deal(); + } +} + +extern void register_receive_fw_update_block_handle(void (*handle)(u8 state, u8 *buf, u16 len)); +extern void rcsp_update_data_api_register(u32(*data_send_hdl)(void *priv, u32 offset, u16 len), u32(*send_update_handl)(void *priv, u8 state)); +extern void rcsp_update_handle(void *buf, int len); +extern void bt_set_low_latency_mode(int enable); +extern void bt_adv_seq_change(void); +extern int bt_tws_poweroff(); +extern void bt_wait_phone_connect_control(u8 enable); +extern int tws_api_get_role(void); +extern void tws_cancle_all_noconn(); +extern void bt_ble_rcsp_adv_disable(void); +extern void ble_module_enable(u8 en); +extern void bt_ble_rcsp_adv_enable(void); + +u8 rcsp_get_update_flag(void) +{ + return tws_need_update; +} + +void rcsp_set_update_flag(u8 flag) +{ + tws_need_update = flag; +} + +u8 rcsp_update_get_role_switch(void) +{ + return tws_need_role_switch; +} + +void rcsp_update_set_role_switch(u8 sw) +{ + tws_need_role_switch = sw; +} + +void update_slave_adv_reopen(void) +{ + r_printf("slave reopen adv...\n"); + ble_module_enable(1); + bt_ble_rcsp_adv_enable(); +} + +void JL_rcsp_msg_deal(void *hdl, u8 event, u8 *msg) +{ + u16 remote_file_version; + u8 can_update_flag = UPDATE_FLAG_FW_INFO_ERR; + + switch (event) { + case MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET: + rcsp_printf("MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET\n"); + + /* extern void linein_mutex_stop(void *priv); */ + /* linein_mutex_stop(NULL); */ + /* extern void linein_mute(u8 mute); */ + /* linein_mute(1); */ + + JL_rcsp_resp_dev_update_file_info_offest((u8)msg[0], (u8)msg[1]); + break; + + case MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE: + rcsp_printf("MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE\n"); +#if 0 + remote_file_version = READ_BIG_U16(update_file_id_info.update_file_id_info.ver); + rcsp_printf("remote_file_ver:V%d.%d.%d.%d\n", + (remote_file_version & 0xf000) >> 12, + (remote_file_version & 0x0f00) >> 8, + (remote_file_version & 0x00f0) >> 4, + (remote_file_version & 0x000f)); + + if (0 == remote_file_version) { + can_update_flag = UPDATE_FLAG_OK; + } else { + can_update_flag = judge_remote_version_can_update(); + } + + if (UPDATE_FLAG_OK == can_update_flag) { + set_jl_update_flag(1); + } +#else +#if OTA_TWS_SAME_TIME_ENABLE + int get_bt_tws_connect_status(); + if (get_bt_tws_connect_status() || (!support_dual_bank_update_en)) { //单备份返回成功 + can_update_flag = UPDATE_FLAG_OK; + } else { + can_update_flag = UPDATE_FLAG_TWS_DISCONNECT; + } +#else + can_update_flag = UPDATE_FLAG_OK; +#endif //endif OTA_TWS_SAME_TIME_ENABLE +#endif + //todo;judge voltage + JL_resp_inquire_device_if_can_update((u8)msg[0], (u8)msg[1], can_update_flag); + + if (0 == support_dual_bank_update_en) { + if (!tws_api_get_role()) { + g_printf("tws master start update...\n"); + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_LOADER_DOWNLOAD_START, NULL, 0); + } else { + tws_need_update = 1; //置上该标志位APP重新连接的时候强制进入升级 + bt_ble_rcsp_adv_disable(); + ble_module_enable(0); //关闭广播防止从机被手机误回连 + r_printf("slave close adv...\n"); + sys_timeout_add(NULL, update_slave_adv_reopen, 1000 * 60); //延迟一分钟再开广播 + syscfg_write(VM_UPDATE_FLAG, &tws_need_update, sizeof(tws_need_update)); + } + if (RCSP_SPP == JL_get_cur_bt_channel_sel()) { + tws_api_detach(TWS_DETACH_BY_LOCAL); //单备份升级断开tws + tws_cancle_all_noconn(); + } else { //BLE主机需要通知从机进入了升级 + u8 data = TWS_UPDATE_INFO; + tws_api_send_data_to_sibling(&data, sizeof(data), TWS_FUNC_ID_SEQ_RAND_SYNC); + } + } + + break; + + case MSG_JL_DEV_DISCONNECT: + if (check_ble_all_packet_sent()) { + rcsp_printf("MSG_JL_DEV_DISCONNECT\n"); + JL_ble_disconnect(); + if (check_edr_is_disconnct()) { + puts("-need discon edr\n"); + user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL); + } + ble_discon_timeout = sys_timeout_add(NULL, ble_discon_timeout_handle, 1000); + } else { + rcsp_printf("W"); + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_DEV_DISCONNECT, NULL, 0); + } + break; + + case MSG_JL_LOADER_DOWNLOAD_START: + rcsp_update_data_api_register(rcsp_update_data_read, rcsp_update_status_response); + register_receive_fw_update_block_handle(rcsp_update_handle); + if (RCSP_BLE == get_curr_device_type()) { + rcsp_update_loader_download_init(BLE_APP_UPDATA, rcsp_loader_download_result_handle); + } else if (RCSP_SPP == get_curr_device_type()) { + rcsp_update_loader_download_init(SPP_APP_UPDATA, rcsp_loader_download_result_handle); + } + break; + + case MSG_JL_UPDATE_START: + if (check_edr_is_disconnct()) { + rcsp_printf("b"); + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_START, NULL, 0); + break; + } + + if (RCSP_BLE == get_curr_device_type()) { + rcsp_printf("BLE_APP_UPDATE\n"); + update_mode_api(BLE_APP_UPDATA); + } else { + rcsp_printf("SPP_APP_UPDATA\n"); + update_mode_api(SPP_APP_UPDATA); + } + break; + + case MSG_JL_ENTER_UPDATE_MODE: + rcsp_printf("MSG_JL_ENTER_UPDATE_MODE:%x %x\n", msg[0], msg[1]); + bt_set_low_latency_mode(0); + if (support_dual_bank_update_en && !tws_api_get_role()) { + u8 status = 0; + JL_CMD_response_send(msg[0], JL_PRO_STATUS_SUCCESS, msg[1], &status, 1); + rcsp_update_data_api_register(rcsp_update_data_read, rcsp_update_status_response); + register_receive_fw_update_block_handle(rcsp_update_handle); + rcsp_update_loader_download_init(DUAL_BANK_UPDATA, rcsp_loader_download_result_handle); + } + break; + + default: + break; + } +} +#endif +#endif + diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata/rcsp_adv_user_update.h b/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata/rcsp_adv_user_update.h new file mode 100644 index 0000000..79a53fc --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata/rcsp_adv_user_update.h @@ -0,0 +1,27 @@ +#ifndef _RCSP_ADV_USER_UPDATE_H_ +#define _RCSP_ADV_USER_UPDATE_H_ + +//#include "rcsp_protocol.h" +//#include "rcsp_packet.h" +#include "typedef.h" + +#define JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET 0xe1 +#define JL_OPCODE_INQUIRE_DEVICE_IF_CAN_UPDATE 0xe2 +#define JL_OPCODE_ENTER_UPDATE_MODE 0xe3 +#define JL_OPCODE_EXIT_UPDATE_MODE 0xe4 +#define JL_OPCODE_SEND_FW_UPDATE_BLOCK 0xe5 +#define JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS 0xe6 +#define JL_OPCODE_SET_DEVICE_REBOOT 0xe7 +#define JL_OPCODE_NOTIFY_UPDATE_CONENT_SIZE 0xe8 + + +void JL_rcsp_update_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len); +void JL_rcsp_update_cmd_receive_resp(void *priv, u8 OpCode, u8 status, u8 *data, u16 len); +void JL_rcsp_msg_deal(void *hdl, u8 event, u8 *msg); +u8 get_jl_update_flag(void); +void set_jl_update_flag(u8 flag); +u8 get_curr_device_type(void); +void update_slave_adv_reopen(void); + +#endif + diff --git a/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata/rcsp_user_update.h b/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata/rcsp_user_update.h new file mode 100644 index 0000000..fd4eabc --- /dev/null +++ b/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata/rcsp_user_update.h @@ -0,0 +1,25 @@ +#ifndef _RCSP_USER_UPDATE_H_ +#define _RCSP_USER_UPDATE_H_ + +//#include "rcsp_protocol.h" +//#include "rcsp_packet.h" +#include "typedef.h" + + +#define JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET 0xe1 +#define JL_OPCODE_INQUIRE_DEVICE_IF_CAN_UPDATE 0xe2 +#define JL_OPCODE_ENTER_UPDATE_MODE 0xe3 +#define JL_OPCODE_EXIT_UPDATE_MODE 0xe4 +#define JL_OPCODE_SEND_FW_UPDATE_BLOCK 0xe5 +#define JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS 0xe6 +#define JL_OPCODE_SET_DEVICE_REBOOT 0xe7 +#define JL_OPCODE_NOTIFY_UPDATE_CONENT_SIZE 0xe8 + +void JL_rcsp_update_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len); +void JL_rcsp_update_cmd_receive_resp(void *priv, u8 OpCode, u8 status, u8 *data, u16 len); +u8 get_jl_update_flag(void); +void set_jl_update_flag(u8 flag); +u8 get_curr_device_type(void); + +#endif + diff --git a/apps/common/third_party_profile/jieli/hid_user.c b/apps/common/third_party_profile/jieli/hid_user.c new file mode 100644 index 0000000..9e52143 --- /dev/null +++ b/apps/common/third_party_profile/jieli/hid_user.c @@ -0,0 +1,533 @@ + +#include "app_config.h" +#include "app_action.h" + +#include "system/includes.h" +#include "spp_user.h" +#include "string.h" +#include "circular_buf.h" +#include "spp_trans_data.h" +#include "bt_common.h" +#include "btstack/avctp_user.h" +#include "circular_buf.h" + +#include "hid_user.h" +#include "standard_hid.h" +#if (USER_SUPPORT_PROFILE_HID ==1) + +#define log_info printf + +#define HID_CHANGE_DESCRIPTOR 0 +#define TEST_USER_HID_EN 0 + +#define HID_DATA 0xA0 /*Device&host*/ +#define HID_DATC 0xB0 /*Device&host DEPRECATED*/ + +/*DATA*/ +#define DATA_OTHER 0x00 +#define DATA_INPUT 0x01 +#define DATA_OUTPUT 0x02 +#define DATA_FEATURE 0x03 + +static u8 *report_map; +static u16 report_map_size; +#define HID_REPORT_MAP_DATA report_map +#define HID_REPORT_MAP_SIZE report_map_size + +/* #define MOUSE_REPORT_TYPE 0xA1 */ +/* #define MOUSE_REPORT_ID 1 */ + +static void (*user_hid_send_wakeup)(void) = NULL; +static u16 hid_channel; +static u8 hid_run = 0; +static volatile u8 is_hid_active = 0; +static volatile u8 hid_s_step = 0; +/* static int hid_timer_id = 0; */ +int hid_timer_id = 0; + + +int edr_hid_timer_handle = 0; + +#define HID_SEND_MAX_SIZE (16) //描述符数据包的长度 +/* static u8 edr_hid_one_packet[HID_SEND_MAX_SIZE]; */ +/* static volatile u16 edr_send_packet_len = 0; */ +static volatile u8 bt_send_busy = 0; +void (*user_led_status_callback)(u8 *buffer, u16 size) = NULL; + +#define HID_TMP_BUFSIZE (64*2) +#define cbuf_get_space(a) (a)->total_len +static cbuffer_t user_send_cbuf; +static u8 hid_tmp_buffer[HID_TMP_BUFSIZE]; + +extern void hid_diy_regiest_callback(void *cb, void *interrupt_cb); +extern void hid_sdp_init(const u8 *hid_descriptor, u16 size); +extern uint16_t little_endian_read_16(const uint8_t *buffer, int pos); + +extern void put_buf(const u8 *buf, int len); +void edr_hid_data_send(u8 report_id, u8 *data, u16 len); + +/* typedef struct { */ +/* u8 report_type; */ +/* u8 report_id; */ +/* u8 button; */ +/* s8 x; */ +/* s8 y; */ +/* } hid_ctl_info_t; */ + +typedef struct { + u8 report_type; + u8 report_id; + u8 data[HID_SEND_MAX_SIZE - 2]; +} hid_data_info_t; + +//----------------------------------------------------- +static void edr_bt_evnet_post(u32 arg_type, u8 priv_event, u8 *args, u32 value) +{ + struct sys_event e; + e.type = SYS_BT_EVENT; + e.arg = (void *)arg_type; + e.u.bt.event = priv_event; + if (args) { + memcpy(e.u.bt.args, args, 7); + } + e.u.bt.value = value; + sys_event_notify(&e); +} + +/* enum { */ +/* REMOTE_DEV_UNKNOWN = 0, */ +/* REMOTE_DEV_ANDROID , */ +/* REMOTE_DEV_IOS , */ +/* }; */ +//参考识别手机系统 +void sdp_callback_remote_type(u8 remote_type) +{ + log_info("edr_hid:remote_type= %d\n", remote_type); + edr_bt_evnet_post(SYS_BT_EVENT_FORM_COMMON, COMMON_EVENT_EDR_REMOTE_TYPE, NULL, remote_type); + //to do +} + +//----------------------------------------------------- +static u16 user_data_read_sub(u8 *buf, u16 buf_size) +{ + u16 ret_len; + if (0 == cbuf_get_data_size(&user_send_cbuf)) { + return 0; + } + + OS_ENTER_CRITICAL(); + cbuf_read(&user_send_cbuf, &ret_len, 2); + if (ret_len && ret_len <= buf_size) { + cbuf_read(&user_send_cbuf, buf, ret_len); + } + OS_EXIT_CRITICAL(); + + return ret_len; +} + +static void user_data_try_send(void) +{ + u16 send_len; + + if (bt_send_busy) { + return; + } + bt_send_busy = 1;//hold + + u8 tmp_send_buf[HID_SEND_MAX_SIZE]; + + send_len = user_data_read_sub(tmp_send_buf, HID_SEND_MAX_SIZE); + + if (send_len) { + if (user_hid_send_data(tmp_send_buf, send_len)) { + bt_send_busy = 0; + } + } else { + //not send + bt_send_busy = 0; + } +} + + +static u32 user_data_write_sub(u8 *data, u16 len) +{ + u16 wlen = 0; + + u16 buf_space = cbuf_get_space(&user_send_cbuf) - cbuf_get_data_size(&user_send_cbuf); + if (len + 2 > buf_space) { + return 0; + } + + OS_ENTER_CRITICAL(); + wlen = cbuf_write(&user_send_cbuf, &len, 2); + wlen += cbuf_write(&user_send_cbuf, data, len); + OS_EXIT_CRITICAL(); + + user_data_try_send(); + return wlen; +} + + +//----------------------------------------------------- +void user_hid_set_icon(u32 class_type) +{ + __change_hci_class_type(class_type);// +} + +void user_hid_set_ReportMap(u8 *map, u16 size) +{ + report_map = map; + report_map_size = size; + + if (hid_run) { +#if !HID_CHANGE_DESCRIPTOR + hid_sdp_init(HID_REPORT_MAP_DATA, HID_REPORT_MAP_SIZE); +#endif + } + +} + + + +/* const hid_ctl_info_t test_key[5] = { */ +/* {0xA1, 1, 0, 0, 0}, */ +/* {0xA1, 1, 0, 100, 0}, */ +/* {0xA1, 1, 0, -100, 0}, */ +/* }; */ + +/* static void test_hid_send_step(void) */ +/* { */ +/* static u8 xy_step = 0; */ +/* u8 send_len = 5; */ +/* if (!hid_s_step) { */ +/* return; */ +/* } */ + +/* xy_step = !xy_step; */ + +/* if (xy_step) { */ +/* hid_s_step = 1; */ +/* } else { */ +/* hid_s_step = 2; */ +/* } */ + +/* if (0 == user_hid_send_data((u8 *)&test_key[hid_s_step], send_len)) { */ +/* hid_s_step = 0; */ +/* } */ +/* } */ + +static void user_hid_timer_handler(void *para) +{ + /* static u8 count = 0; */ + + if (!hid_channel) { + return; + } + + /* if (++count > 5) { */ + /* count = 0; */ + /* hid_s_step = 1; */ + /* test_hid_send_step(); */ + /* } */ + + /* hid_key_send(CONSUMER_PLAY_PAUSE); */ +} + +static u8 user_hid_idle_query(void) +{ + return !is_hid_active; +} + +REGISTER_LP_TARGET(hid_user_target) = { + .name = "hid_user", + .is_idle = user_hid_idle_query, +}; + + +static void user_hid_send_ok_callback(void) +{ + /* putchar('K'); */ + bt_send_busy = 0; + + if (user_hid_send_wakeup) { + user_hid_send_wakeup(); + } + + user_data_try_send(); + + /* test_hid_send_step(); */ +} + +void user_hid_regiser_wakeup_send(void *cbk) +{ + user_hid_send_wakeup = cbk; +} + +void user_hid_disconnect(void) +{ + if (hid_channel) { + user_send_cmd_prepare(USER_CTRL_HID_DISCONNECT, 0, NULL); + } +} + + +int user_hid_send_data(u8 *buf, u32 len) +{ + int ret; + hid_s_param_t s_par; + if (!hid_channel) { + return -1; + } + + s_par.chl_id = hid_channel; + s_par.data_len = len; + s_par.data_ptr = buf; + + ret = user_send_cmd_prepare(USER_CTRL_HID_SEND_DATA, sizeof(hid_s_param_t), (u8 *)&s_par); + + if (ret) { + log_info("hid send fail!!! %d\n", ret); + } + return ret; +} + +static void user_hid_msg_handler(u32 msg, u8 *packet, u32 packet_size) +{ + u16 tmp_chl; + switch (msg) { + case 1: + hid_channel = little_endian_read_16(packet, 2); //inter_channel + bt_send_busy = 0; + log_info("hid connect ########################,%d\n", hid_channel); + cbuf_init(&user_send_cbuf, hid_tmp_buffer, HID_TMP_BUFSIZE); + break; + + case 2: + log_info("hid disconnect ########################\n"); + hid_channel = 0; + cbuf_init(&user_send_cbuf, hid_tmp_buffer, HID_TMP_BUFSIZE); + break; + + case 3: + if (hid_channel == little_endian_read_16(packet, 0)) { + user_hid_send_ok_callback(); + } + break; + + default: + break; + } +} + +void user_hid_init(void (*user_hid_interrupt_handler)(u8 *packet, u16 size)) +{ + log_info("%s\n", __FUNCTION__); + hid_channel = 0; + hid_diy_regiest_callback(user_hid_msg_handler, user_hid_interrupt_handler); + +#if !HID_CHANGE_DESCRIPTOR + hid_sdp_init(HID_REPORT_MAP_DATA, HID_REPORT_MAP_SIZE); +#endif +#if TEST_USER_HID_EN + hid_timer_id = sys_s_hi_timer_add((void *)0, user_hid_timer_handler, 5000); +#endif + + cbuf_init(&user_send_cbuf, hid_tmp_buffer, HID_TMP_BUFSIZE); + hid_run = 1; +} + +void user_hid_exit(void) +{ + log_info("%s\n", __FUNCTION__); + if (hid_timer_id) { + user_hid_disconnect(); + sys_s_hi_timer_del(hid_timer_id); + hid_timer_id = 0; + } + + if (edr_hid_timer_handle) { + sys_s_hi_timer_del(edr_hid_timer_handle); + edr_hid_timer_handle = 0; + } + + hid_run = 0; +} + +void user_hid_enable(u8 en) +{ + log_info("%s:%d\n", __FUNCTION__, en); + + if (en) { + ; + } else { + user_hid_disconnect(); + } +} + +void edr_hid_data_send(u8 report_id, u8 *data, u16 len) +{ + if (!hid_channel) { + return; + } + + if (len > HID_SEND_MAX_SIZE - 2) { + log_info("buffer limitp!!!\n"); + return; + } + + putchar('@'); + hid_data_info_t data_info; + data_info.report_type = HID_DATA | DATA_INPUT; + data_info.report_id = report_id; + memcpy(data_info.data, data, len); + + if (!user_data_write_sub((u8 *)&data_info, 2 + len)) { + log_info("hid buffer full!!!\n"); + return; + } + +} + +void edr_hid_key_deal_test(u16 key_msg) +{ + edr_hid_data_send(1, (u8 *)&key_msg, 2); + + if (key_msg) { + key_msg = 0; + edr_hid_data_send(1, (u8 *)&key_msg, 2); + } +} + + +int edr_hid_is_connected(void) +{ + return hid_channel; +} + +extern u32 lmp_private_get_tx_remain_buffer(); +int edr_hid_tx_buff_is_ok(void) +{ + if (lmp_private_get_tx_remain_buffer() < 0x300) { + putchar('b'); + return 0; + } + return 1; +} + +#if HID_CHANGE_DESCRIPTOR +const u8 use_hid_descriptor[] = { + 0x05, 0x01, + 0x09, 0x02, + 0xA1, 0x01, + 0x85, 0x01, + 0x05, 0x09, + 0x19, 0x01, + 0x29, 0x03, + 0x15, 0x00, + 0x25, 0x01, + 0x95, 0x03, + 0x75, 0x01, + 0x81, 0x02, + 0x75, 0x05, + 0x95, 0x01, + 0x81, 0x03, + 0x05, 0x01, + 0x09, 0x01, + 0xA1, 0x00, + 0x09, 0x30, + 0x09, 0x31, + 0x16, 0x00, 0xD8, + 0x26, 0x00, 0x28, + 0x75, 0x10, + 0x95, 0x02, + 0x81, 0x06, + 0xC0, + 0xC0, + + 0x05, 0x0C, + 0x09, 0x01, + 0xA1, 0x01, + 0x85, 0x02, + 0x15, 0x00, + 0x25, 0x01, + 0x09, 0x34, + 0x09, 0x40, + 0x0A, 0x23, 0x02, + 0x0A, 0x24, 0x02, + 0x09, 0xE9, + 0x09, 0xEA, + 0x09, 0xB0, + 0x09, 0xB1, + 0x09, 0xB3, + 0x09, 0xB4, + 0x09, 0xB5, + 0x09, 0xB6, + 0x09, 0xB7, + 0x09, 0xCD, + 0x75, 0x01, + 0x95, 0x0E, + 0x81, 0x22, + 0x75, 0x01, + 0x95, 0x02, + 0x81, 0x02, + 0xC0 +}; + +struct user_hid_consumer_cmd { + //Bluetooth HID Protocol Message Header Octet + u8 HIDP_Hdr; + //Bluetooth HID Boot Reports + u8 report_id; + u8 button; +} _GNU_PACKED_; +static struct user_hid_consumer_cmd u_consumer = { + .HIDP_Hdr = 0xA1, + .report_id = 0x02, + .button = 0, +}; +// consumer key +#define CONSUMER_MENU 0x01 +#define CONSUMER_MENU_ESCAPE 0x02 +#define CONSUMER_AC_HOME 0x04 +void hid_consumer_send_test(u8 menu) +{ + if (menu == 1) { + u_consumer.button = CONSUMER_MENU; + } + if (menu == 2) { + u_consumer.button = CONSUMER_MENU_ESCAPE; + } + if (menu == 3) { + u_consumer.button = CONSUMER_AC_HOME; + } + put_buf((u8 *)&u_consumer, sizeof(u_consumer)); + user_data_write_sub((u8 *)&u_consumer, sizeof(u_consumer)); + u_consumer.button = 0x00; + user_data_write_sub((u8 *)&u_consumer, sizeof(u_consumer)); +} + +u8 sdp_make_hid_service_data[0x200]; +static void user_hid_sdp_init(const u8 *hid_descriptor, u16 size) +{ + int real_size; + real_size = sdp_create_diy_hid_service(sdp_make_hid_service_data, sizeof(sdp_make_hid_service_data), hid_descriptor, size); + printf("dy_hid_service(%d):", real_size); +} +void user_hid_descriptor_init(void) +{ + + //__change_hci_class_type(0x240418); /*需要更换手机显示图标的可以自己改成以前的值*/ + user_hid_init(); + user_hid_sdp_init(use_hid_descriptor, sizeof(use_hid_descriptor)); +} + +//用户修改成自定义的描述符说明 +//1、在void bredr_handle_register();中调用user_hid_descriptor_init; +//2、user_hid_sdp_init换成自己的表 +//3、文件上方HID_CHANGE_DESCRIPTOR定义为1 +//4、在bt_profile_config.c文件中extern sdp_make_hid_service_data数组, +// 把sdp_hid_service_data替换为sdp_make_hid_service_data. +//5、把const u8 hid_conn_depend_on_dev_company的值置0; +#endif + +#endif diff --git a/apps/common/third_party_profile/jieli/hid_user.h b/apps/common/third_party_profile/jieli/hid_user.h new file mode 100644 index 0000000..3cedc5a --- /dev/null +++ b/apps/common/third_party_profile/jieli/hid_user.h @@ -0,0 +1,21 @@ +#ifndef __HID_USER_H__ +#define __HID_USER_H__ + +#include "typedef.h" +#include "bt_common.h" + +enum { + HID_USER_ERR_NONE = 0x0, + HID_USER_ERR_DONE, + HID_USER_ERR_SEND_FAIL, +}; + +void user_hid_init(void (*user_hid_interrupt_handler)(u8 *packet, u16 size)); +void user_hid_exit(void); +void user_hid_enable(u8 en); +int user_hid_send_data(u8 *buf, u32 len); +void user_hid_disconnect(void); +void user_hid_set_icon(u32 class_type); +void user_hid_set_ReportMap(u8 *map, u16 size); + +#endif//__SPP_USER_H__ diff --git a/apps/common/third_party_profile/jieli/le_client_demo.c b/apps/common/third_party_profile/jieli/le_client_demo.c new file mode 100644 index 0000000..7042dce --- /dev/null +++ b/apps/common/third_party_profile/jieli/le_client_demo.c @@ -0,0 +1,1559 @@ +/********************************************************************************************* + * Filename : le_server_module.c + + * Description : + + * Author : + + * Email : zh-jieli.com + + * Last modifiled : 2017-01-17 11:14 + + * Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved. +*********************************************************************************************/ + +// ***************************************************************************** +/* EXAMPLE_START(le_counter): LE Peripheral - Heartbeat Counter over GATT + * + * @text All newer operating systems provide GATT Client functionality. + * The LE Counter examples demonstrates how to specify a minimal GATT Database + * with a custom GATT Service and a custom Characteristic that sends periodic + * notifications. + */ +// ***************************************************************************** + +#include "system/app_core.h" +#include "system/includes.h" + +#include "app_config.h" +#include "app_action.h" + +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "user_cfg.h" +#include "vm.h" +#include "btcontroller_modules.h" +#include "bt_common.h" + +#include "le_client_demo.h" +#include "le_common.h" +#include "ble_user.h" +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_CLIENT) + +#define SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN 1 +#define SHOW_RX_DATA_RATE 0 +#define EXT_ADV_MODE_EN 0 + +#if 1 +#define log_info printf +#define log_info_hexdump put_buf +#else +#define log_info(...) +#define log_info_hexdump(...) +#endif + +//------ +#define ATT_LOCAL_PAYLOAD_SIZE (64*2) //note: need >= 20 +#define ATT_SEND_CBUF_SIZE (512) //note: need >= 20,缓存大小,可修改 +#define ATT_RAM_BUFSIZE (ATT_CTRL_BLOCK_SIZE + ATT_LOCAL_PAYLOAD_SIZE + ATT_SEND_CBUF_SIZE) //note: +static u8 att_ram_buffer[ATT_RAM_BUFSIZE] __attribute__((aligned(4))); + +#define SEARCH_PROFILE_BUFSIZE (512) //note: +static u8 search_ram_buffer[SEARCH_PROFILE_BUFSIZE] __attribute__((aligned(4))); +#define scan_buffer search_ram_buffer +//--------------- +//搜索类型 +#define SET_SCAN_TYPE SCAN_ACTIVE +//搜索 周期大小 +#define SET_SCAN_INTERVAL 48 //(unit:0.625ms) +//搜索 窗口大小 +#define SET_SCAN_WINDOW 16 //(unit:0.625ms) + +//连接周期 +#define SET_CONN_INTERVAL 24 //(unit:1.25ms) +//连接latency +#define SET_CONN_LATENCY 0 //(unit:conn_interval) +//连接超时 +#define SET_CONN_TIMEOUT 400 //(unit:10ms) +//---------------------------------------------------------------------------- +static u8 scan_ctrl_en; +static u8 ble_work_state = 0; +static void (*app_recieve_callback)(void *priv, void *buf, u16 len) = NULL; +static void (*app_ble_state_callback)(void *priv, ble_state_e state) = NULL; +static void (*ble_resume_send_wakeup)(void) = NULL; +static u32 channel_priv; + +static hci_con_handle_t con_handle; + +#define BLE_VM_HEAD_TAG (0xB95C) +#define BLE_VM_TAIL_TAG (0x5CB9) +struct pair_info_t { + u16 head_tag; + u8 pair_flag; + u8 peer_address_info[7]; + u16 tail_tag; +}; +static struct pair_info_t conn_pair_info; +static u8 pair_bond_enable = 0; + +//------------------------------------------------------------------------------- +typedef struct { + uint16_t read_handle; + uint16_t read_long_handle; + uint16_t write_handle; + uint16_t write_no_respond; + uint16_t notify_handle; + uint16_t indicate_handle; +} target_hdl_t; + +//记录handle 使用 +static target_hdl_t target_handle; +static opt_handle_t opt_handle_table[OPT_HANDLE_MAX]; +static u8 opt_handle_used_cnt; +static u8 force_seach_onoff = 0; +static s8 force_seach_rssi = -127; + +static void bt_ble_create_connection(u8 *conn_addr, u8 addr_type); +static int bt_ble_scan_enable(void *priv, u32 en); +static int client_write_send(void *priv, u8 *data, u16 len); +static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type); +//--------------------------------------------------------------------------- +#if 1//default +//指定搜索uuid +//指定搜索uuid +static const target_uuid_t default_search_uuid_table[] = { + + // for uuid16 + // PRIMARY_SERVICE, ae30 + // CHARACTERISTIC, ae01, WRITE_WITHOUT_RESPONSE | DYNAMIC, + // CHARACTERISTIC, ae02, NOTIFY, + + { + .services_uuid16 = 0xae30, + .characteristic_uuid16 = 0xae01, + .opt_type = ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, + }, + + { + .services_uuid16 = 0xae30, + .characteristic_uuid16 = 0xae02, + .opt_type = ATT_PROPERTY_NOTIFY, + }, + + //for uuid128,sample + // PRIMARY_SERVICE, 0000F530-1212-EFDE-1523-785FEABCD123 + // CHARACTERISTIC, 0000F531-1212-EFDE-1523-785FEABCD123, NOTIFY, + // CHARACTERISTIC, 0000F532-1212-EFDE-1523-785FEABCD123, WRITE_WITHOUT_RESPONSE | DYNAMIC, + /* + { + .services_uuid16 = 0, + .services_uuid128 = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23} , + .characteristic_uuid16 = 0, + .characteristic_uuid128 = {0x00,0x00,0xF5,0x31 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}, + .opt_type = ATT_PROPERTY_NOTIFY, + }, + + { + .services_uuid16 = 0, + .services_uuid128 = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23} , + .characteristic_uuid16 = 0, + .characteristic_uuid128 = {0x00,0x00,0xF5,0x32 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}, + .opt_type = ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, + }, + */ + +}; + + +static void default_report_data_deal(att_data_report_t *report_data, target_uuid_t *search_uuid) +{ + log_info("report_data:%02x,%02x,%d,len(%d)", report_data->packet_type, + report_data->value_handle, report_data->value_offset, report_data->blob_length); + + log_info_hexdump(report_data->blob, report_data->blob_length); + + switch (report_data->packet_type) { + case GATT_EVENT_NOTIFICATION: //notify + break; + case GATT_EVENT_INDICATION://indicate + case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT://read + break; + case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT://read long + break; + + default: + break; + } +} + +static const u8 test_remoter_name1[] = "AC637N_MX(BLE)";// +/* static const u8 test_remoter_name2[] = "AC630N_HID567(BLE)";// */ +static u16 default_client_write_handle; +static u16 test_client_timer = 0; + +static const client_match_cfg_t match_dev01 = { + .create_conn_mode = BIT(CLI_CREAT_BY_NAME), + .compare_data_len = sizeof(test_remoter_name1) - 1, //去结束符 + .compare_data = test_remoter_name1, + .bonding_flag = 0, +}; + +/* static const client_match_cfg_t match_dev02 = { */ +/* .create_conn_mode = BIT(CLI_CREAT_BY_NAME), */ +/* .compare_data_len = sizeof(test_remoter_name2) - 1, //去结束符 */ +/* .compare_data = test_remoter_name2, */ +/* .bonding_flag = 1, */ +/* }; */ + +static void default_test_write(void) +{ + static u32 count = 0; + count++; + int ret = client_operation_send(default_client_write_handle, &count, 16, ATT_OP_WRITE_WITHOUT_RESPOND); + log_info("test_write:%x", ret); +} + +static void default_event_callback(le_client_event_e event, u8 *packet, int size) +{ + switch (event) { + case CLI_EVENT_MATCH_DEV: { + client_match_cfg_t *match_dev = packet; + log_info("match_name:%s\n", match_dev->compare_data); + } + break; + + case CLI_EVENT_MATCH_UUID: { + opt_handle_t *opt_hdl = packet; + if (opt_hdl->search_uuid == &default_search_uuid_table[0]) { + default_client_write_handle = opt_hdl->value_handle; + log_info("match_uuid22\n"); + } + } + break; + + case CLI_EVENT_SEARCH_PROFILE_COMPLETE: + log_info("CLI_EVENT_SEARCH_PROFILE_COMPLETE\n"); + if ((!test_client_timer) && default_client_write_handle) { + log_info("test timer_add\n"); + test_client_timer = sys_timer_add(0, default_test_write, 500); + } + break; + + case CLI_EVENT_CONNECTED: + break; + + case CLI_EVENT_DISCONNECT: + if (test_client_timer) { + sys_timeout_del(test_client_timer); + test_client_timer = 0; + } + default_client_write_handle = 0; + break; + + default: + break; + } +} + + +static const client_conn_cfg_t client_conn_config_default = { + .match_dev_cfg[0] = &match_dev01, + .match_dev_cfg[1] = NULL, + .match_dev_cfg[2] = NULL, + /* .match_dev_cfg[1] = &match_dev02, */ + .report_data_callback = default_report_data_deal, + .search_uuid_cnt = (sizeof(default_search_uuid_table) / sizeof(target_uuid_t)), + .search_uuid_table = default_search_uuid_table, + .security_en = 0, + .event_callback = default_event_callback, +}; + +#endif + +//--------------------------------------------------------------------------- +static client_conn_cfg_t *client_config = (void *) &client_conn_config_default ; +//---------------------------------------------------------------------------- + + +static const struct conn_update_param_t connection_param_table[] = { + {16, 24, 0, 600},//11 + {12, 28, 0, 600},//3.7 + {8, 20, 0, 600}, + {50, 60, 0, 600}, +}; + +static u8 send_param_index = 3; + +static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode); +static int client_create_cannel_api(void); +//---------------------------------------------------------------------------- + +static void client_event_report(le_client_event_e event, u8 *packet, int size) +{ + if (client_config->event_callback) { + client_config->event_callback(event, packet, size); + } +} + +static bool check_device_is_match(u8 info_type, u8 *data, int size) +{ + int i; + u8 conn_mode = BIT(info_type); + client_match_cfg_t *cfg; + + /* log_info_hexdump(data,size); */ + + for (i = 0; i < CLIENT_MATCH_CONN_MAX; i++) { + cfg = client_config->match_dev_cfg[i]; + if (cfg == NULL) { + continue; + } + /* log_info("cfg = %08x\n",cfg); */ + /* log_info_hexdump(cfg,sizeof(client_match_cfg_t)); */ + if (cfg->create_conn_mode == conn_mode && size == cfg->compare_data_len) { + log_info("match check\n"); + /* log_info_hexdump(data, size); */ + /* log_info_hexdump(cfg->compare_data, size); */ + if (0 == memcmp(data, cfg->compare_data, cfg->compare_data_len)) { + log_info("match ok\n"); + pair_bond_enable = cfg->bonding_flag; + client_event_report(CLI_EVENT_MATCH_DEV, cfg, sizeof(client_match_cfg_t)); + return true; + } + } + } + return false; +} + +static void conn_pair_vm_do(struct pair_info_t *info, u8 rw_flag) +{ + /* return; */ + + int ret; + int vm_len = sizeof(struct pair_info_t); + + log_info("-conn_pair_info vm_do:%d\n", rw_flag); + if (rw_flag == 0) { + ret = syscfg_read(CFG_BLE_MODE_INFO, (u8 *)info, vm_len); + if (!ret) { + log_info("-null--\n"); + } + if ((BLE_VM_HEAD_TAG == info->head_tag) && (BLE_VM_TAIL_TAG == info->tail_tag)) { + log_info("-exist--\n"); + log_info_hexdump((u8 *)info, vm_len); + } else { + memset(info, 0, vm_len); + info->head_tag = BLE_VM_HEAD_TAG; + info->tail_tag = BLE_VM_TAIL_TAG; + } + } else { + syscfg_write(CFG_BLE_MODE_INFO, (u8 *)info, vm_len); + } +} + +void client_clear_bonding_info(void) +{ + log_info("client_clear_bonding_info\n"); + conn_pair_vm_do(&conn_pair_info, 0); + if (conn_pair_info.pair_flag) { + //del pair bond + memset(&conn_pair_info, 0, sizeof(struct pair_info_t)); + conn_pair_vm_do(&conn_pair_info, 1); + } +} + +//------------------------------------------------------------ +static void set_ble_work_state(ble_state_e state) +{ + if (state != ble_work_state) { + log_info("ble_client_work_st:%x->%x\n", ble_work_state, state); + ble_work_state = state; + if (app_ble_state_callback) { + app_ble_state_callback((void *)channel_priv, state); + } + } +} +//------------------------------------------------------------ +static ble_state_e get_ble_work_state(void) +{ + return ble_work_state; +} + +//------------------------------------------------------------------------------- +static void check_target_uuid_match(search_result_t *result_info) +{ + u32 i; + target_uuid_t *t_uuid; + + for (i = 0; i < client_config->search_uuid_cnt; i++) { + t_uuid = &client_config->search_uuid_table[i]; + if (result_info->services.uuid16) { + if (result_info->services.uuid16 != t_uuid->services_uuid16) { + /* log_info("b1"); */ + continue; + } + } else { + if (memcmp(result_info->services.uuid128, t_uuid->services_uuid128, 16)) { + /* log_info("b2"); */ + continue; + } + } + + if (result_info->characteristic.uuid16) { + if (result_info->characteristic.uuid16 != t_uuid->characteristic_uuid16) { + /* log_info("b3"); */ + /* log_info("%d: %04x--%04x",result_info->characteristic.uuid16,t_uuid->characteristic_uuid16); */ + continue; + } + } else { + if (memcmp(result_info->characteristic.uuid128, t_uuid->characteristic_uuid128, 16)) { + /* log_info("b4"); */ + continue; + } + } + + break;//match one + } + + if (i >= client_config->search_uuid_cnt) { + return; + } + + if (opt_handle_used_cnt >= OPT_HANDLE_MAX) { + log_info("opt_handle is full!!!\n"); + return; + } + + if ((t_uuid->opt_type & result_info->characteristic.properties) != t_uuid->opt_type) { + log_info("properties not match!!!\n"); + return; + } + + log_info("match one uuid\n"); + + opt_handle_t *opt_get = &opt_handle_table[opt_handle_used_cnt++]; + opt_get->value_handle = result_info->characteristic.value_handle; + opt_get->search_uuid = t_uuid; + + switch (t_uuid->opt_type) { + case ATT_PROPERTY_READ: + target_handle.read_handle = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_WRITE_WITHOUT_RESPONSE: + target_handle.write_no_respond = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_WRITE: + target_handle.write_handle = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_NOTIFY: + target_handle.notify_handle = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_INDICATE: + target_handle.indicate_handle = result_info->characteristic.value_handle; + break; + + default: + break; + } + + client_event_report(CLI_EVENT_MATCH_UUID, opt_get, sizeof(opt_handle_t)); + +} + +//操作handle,完成 write ccc +static void do_operate_search_handle(void) +{ + u16 tmp_16; + u16 i, cur_opt_type; + opt_handle_t *opt_hdl_pt; + + log_info("opt_handle_used_cnt= %d\n", opt_handle_used_cnt); + + log_info("find target_handle:"); + log_info_hexdump(&target_handle, sizeof(target_hdl_t)); + + if (0 == opt_handle_used_cnt) { + goto opt_end; + } + + /* test_send_conn_update();//for test */ + + for (i = 0; i < opt_handle_used_cnt; i++) { + opt_hdl_pt = &opt_handle_table[i]; + cur_opt_type = opt_hdl_pt->search_uuid->opt_type; + switch ((u8)cur_opt_type) { + case ATT_PROPERTY_READ: + if (1) { + tmp_16 = 0x55A2;//fixed + log_info("read_long:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle, (u8 *)&tmp_16, 2, ATT_OP_READ_LONG); + } else { + tmp_16 = 0x55A1;//fixed + log_info("read:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle, (u8 *)&tmp_16, 2, ATT_OP_READ); + } + break; + + case ATT_PROPERTY_NOTIFY: + tmp_16 = 0x01;//fixed + log_info("write_ntf_ccc:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle + 1, &tmp_16, 2, ATT_OP_WRITE); + break; + + case ATT_PROPERTY_INDICATE: + tmp_16 = 0x02;//fixed + log_info("write_ind_ccc:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle + 1, &tmp_16, 2, ATT_OP_WRITE); + break; + + default: + break; + } + } + +opt_end: + set_ble_work_state(BLE_ST_SEARCH_COMPLETE); + +} + +//协议栈内部调用 +//return: 0--accept,1--reject +int l2cap_connection_update_request_just(u8 *packet) +{ + log_info("slave request conn_update:\n-interval_min= %d,\n-interval_max= %d,\n-latency= %d,\n-timeout= %d\n", + little_endian_read_16(packet, 0), little_endian_read_16(packet, 2), + little_endian_read_16(packet, 4), little_endian_read_16(packet, 6)); + return 0; + /* return 1; */ +} + +//协议栈内部调用 +void user_client_report_search_result(search_result_t *result_info) +{ + if (result_info == (void *) - 1) { + log_info("client_report_search_result finish!!!\n"); + do_operate_search_handle(); + client_event_report(CLI_EVENT_SEARCH_PROFILE_COMPLETE, 0, 0); + return; + } + + log_info("\n*** services, uuid16:%04x,index=%d ***\n", result_info->services.uuid16, result_info->service_index); + log_info("{charactc, uuid16:%04x,index=%d,handle:%04x~%04x,value_handle=%04x}\n", + result_info->characteristic.uuid16, result_info->characteristic_index, + result_info->characteristic.start_handle, result_info->characteristic.end_handle, + result_info->characteristic.value_handle + ); + + if (!result_info->services.uuid16) { + log_info("######services_uuid128:"); + log_info_hexdump(result_info->services.uuid128, 16); + } + + if (!result_info->characteristic.uuid16) { + log_info("######charact_uuid128:"); + log_info_hexdump(result_info->characteristic.uuid128, 16); + } + + check_target_uuid_match(result_info); +} + +#if SHOW_RX_DATA_RATE + +static u32 client_timer_handle = 0; +static u32 test_data_count; +static void client_timer_handler(void) +{ + if (!con_handle) { + test_data_count = 0; + return; + } + log_info("peer_rssi = %d\n", ble_vendor_get_peer_rssi(con_handle)); + + if (test_data_count) { + /* log_info("\n-ble_data_rate: %d bps-\n", test_data_count * 8); */ + log_info("\n%d bytes receive: %d.%02d KB/s \n", test_data_count, test_data_count / 1000, test_data_count % 1000); + test_data_count = 0; + } +} + +static void client_timer_start(void) +{ + client_timer_handle = sys_timer_add(NULL, client_timer_handler, 1000); +} + +#endif /* SHOW_RX_DATA_RATE */ + +static target_uuid_t *get_match_handle_target(u16 handle) +{ + for (int i = 0; i < opt_handle_used_cnt; i++) { + if (opt_handle_table[i].value_handle == handle) { + return opt_handle_table[i].search_uuid; + } + } + return NULL; +} + +//协议栈内部调用 +void user_client_report_data_callback(att_data_report_t *report_data) +{ + /* log_info("\n-report_data:type %02x,handle %04x,offset %d,len %d:",report_data->packet_type, */ + /* report_data->value_handle,report_data->value_offset,report_data->blob_length); */ + /* log_info_hexdump(report_data->blob,report_data->blob_length); */ + +#if SHOW_RX_DATA_RATE + test_data_count += report_data->blob_length; +#endif /* SHOW_RX_DATA_RATE */ + + target_uuid_t *search_uuid = get_match_handle_target(report_data->value_handle); + + if (client_config->report_data_callback) { + client_config->report_data_callback(report_data, search_uuid); + return; + } + + switch (report_data->packet_type) { + case GATT_EVENT_NOTIFICATION://notify +// log_info("\n-notify_rx(%d):",report_data->blob_length); + case GATT_EVENT_INDICATION://indicate + case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT://read + case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT://read long + break; + default: + break; + } +} + +// PRIMARY_SERVICE,AE30 +/* static const u16 test_services_uuid16 = 0xae30; */ + +// PRIMARY_SERVICE, 0000F530-1212-EFDE-1523-785FEABCD123 +/* static const u8 test_services_uuid128[16] = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}; */ + +static void client_search_profile_start(void) +{ + opt_handle_used_cnt = 0; + memset(&target_handle, 0, sizeof(target_hdl_t)); + user_client_init(con_handle, search_ram_buffer, SEARCH_PROFILE_BUFSIZE); + if (client_config->search_uuid_cnt) { + ble_op_search_profile_all(); + } else { + user_client_set_search_complete(); + } +} + +//------------------------------------------------------------ +static bool resolve_adv_report(u8 *adv_address, u8 data_length, u8 *data, s8 rssi) +{ + u8 i, lenght, ad_type; + u8 *adv_data_pt; + u8 find_remoter = 0; + /* u8 tmp_addr[6]; */ + u32 tmp32; + + if (check_device_is_match(CLI_CREAT_BY_ADDRESS, adv_address, 6)) { + find_remoter = 1; + } + + adv_data_pt = data; + for (i = 0; i < data_length;) { + if (*adv_data_pt == 0) { + /* log_info("analyze end\n"); */ + break; + } + + lenght = *adv_data_pt++; + ad_type = *adv_data_pt++; + i += (lenght + 1); + + switch (ad_type) { + case HCI_EIR_DATATYPE_FLAGS: + /* log_info("flags:%02x\n",adv_data_pt[0]); */ + break; + + case HCI_EIR_DATATYPE_MORE_16BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_COMPLETE_16BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_MORE_32BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_COMPLETE_32BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_MORE_128BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_COMPLETE_128BIT_SERVICE_UUIDS: + /* log_info("service uuid:"); */ + /* log_info_hexdump(adv_data_pt, lenght - 1); */ + break; + + case HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME: + case HCI_EIR_DATATYPE_SHORTENED_LOCAL_NAME: + tmp32 = adv_data_pt[lenght - 1]; + adv_data_pt[lenght - 1] = 0;; + log_info("remoter_name: %s,rssi:%d\n", adv_data_pt, rssi); + log_info_hexdump(adv_address, 6); + adv_data_pt[lenght - 1] = tmp32; + //------- +#if SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN +#define TEST_BOX_BLE_NAME "JLBT_TESTBOX" +#define TEST_BOX_BLE_NAME_LEN 0xc + if (0 == memcmp(adv_data_pt, TEST_BOX_BLE_NAME, TEST_BOX_BLE_NAME_LEN)) { + find_remoter = 1; + break; + } +#endif + /* log_info("target name:%s", client_config->compare_data); */ + if (check_device_is_match(CLI_CREAT_BY_NAME, adv_data_pt, lenght - 1)) { + find_remoter = 1; + log_info("catch name ok\n"); + } + break; + + case HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA: + if (check_device_is_match(CLI_CREAT_BY_TAG, adv_data_pt, lenght - 1)) { + log_info("get_tag_string!\n"); + find_remoter = 1; + } + break; + + case HCI_EIR_DATATYPE_APPEARANCE_DATA: + /* log_info("get_class_type:%04x\n",little_endian_read_16(adv_data_pt,0)); */ + break; + + default: + /* log_info("unknow ad_type:"); */ + break; + } + + if (find_remoter) { + log_info_hexdump(adv_data_pt, lenght - 1); + } + adv_data_pt += (lenght - 1); + } + + return find_remoter; +} + +static void client_report_adv_data(adv_report_t *report_pt, u16 len) +{ + bool find_remoter; + + /* log_info("event_type,addr_type: %x,%x; ",report_pt->event_type,report_pt->address_type); */ + /* log_info_hexdump(report_pt->address,6); */ + + /* log_info("adv_data_display:"); */ + /* log_info_hexdump(report_pt->data,report_pt->length); */ + +// log_info("rssi:%d\n",report_pt->rssi); + + find_remoter = resolve_adv_report(report_pt->address, report_pt->length, report_pt->data, report_pt->rssi); + + if (find_remoter) { + if (force_seach_onoff && force_seach_rssi > report_pt->rssi) { + log_info("match but rssi fail!!!:%d,%d\n", force_seach_rssi, report_pt->rssi); + return; + } + + log_info("rssi:%d\n", report_pt->rssi); + log_info("\n*********create_connection***********\n"); + log_info("***remote type %d,addr:", report_pt->address_type); + log_info_hexdump(report_pt->address, 6); + bt_ble_scan_enable(0, 0); + client_create_connect_api(report_pt->address, report_pt->address_type, 0); + log_info("*create_finish\n"); + } +} + +#if EXT_ADV_MODE_EN + +#define GET_STRUCT_MEMBER_OFFSET(type, member) \ + (u32)&(((struct type*)0)->member) + +struct __ext_adv_report_event { + u8 Subevent_Code; + u8 Num_Reports; + u16 Event_Type; + u8 Address_Type; + u8 Address[6]; + u8 Primary_PHY; + u8 Secondary_PHY; + u8 Advertising_SID; + u8 Tx_Power; + u8 RSSI; + u16 Periodic_Advertising_Interval; + u8 Direct_Address_Type; + u8 Direct_Address[6]; + u8 Data_Length; + u8 Data[0]; +} _GNU_PACKED_; + +static void client_report_ext_adv_data(u8 *report_pt, u16 len) +{ + bool find_remoter; + u8 address_type = report_pt[GET_STRUCT_MEMBER_OFFSET(__ext_adv_report_event, Address_Type)]; + u8 address[6]; + + /* log_info("--func=%s", __FUNCTION__); */ + /* log_info_hexdump(report_pt, len); */ + + memcpy(address, &report_pt[GET_STRUCT_MEMBER_OFFSET(__ext_adv_report_event, Address)], 6); + + find_remoter = resolve_adv_report(\ + address, \ + report_pt[GET_STRUCT_MEMBER_OFFSET(__ext_adv_report_event, Data_Length)], \ + &report_pt[GET_STRUCT_MEMBER_OFFSET(__ext_adv_report_event, Data)], 0 \ + ); + + if (find_remoter) { + if (force_seach_onoff && force_seach_rssi > report_pt->rssi) { + log_info("match but rssi fail!!!:%d,%d\n", force_seach_rssi, report_pt->rssi); + return; + } + + log_info("\n*********ext create_connection***********\n"); + log_info("***remote type %d, addr:", address_type); + log_info_hexdump(address, 6); + bt_ble_scan_enable(0, 0); + client_create_connect_api(address, address_type, 0); + log_info("*create_finish\n"); + } +} + +struct __ext_init { + u8 Initiating_Filter_Policy; + u8 Own_Address_Type; + u8 Peer_Address_Type; + u8 Peer_Address[6]; + u8 Initiating_PHYs; + u16 Scan_Interval; + u16 Scan_Window; + u16 Conn_Interval_Min; + u16 Conn_Interval_Max; + u16 Conn_Latency; + u16 Supervision_Timeout; + u16 Minimum_CE_Length; + u16 Maximum_CE_Length; +} _GNU_PACKED_; + +static void client_ext_create_connection(u8 *conn_addr, u8 addr_type) +{ + struct __ext_init *create_conn_par = scan_buffer; + + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + log_info("already create conn!!!\n"); + return; + } + + memset(create_conn_par, 0, sizeof(*create_conn_par)); + create_conn_par->Conn_Interval_Min = SET_CONN_INTERVAL; + create_conn_par->Conn_Interval_Max = SET_CONN_INTERVAL; + create_conn_par->Conn_Latency = SET_CONN_LATENCY; + create_conn_par->Supervision_Timeout = SET_CONN_TIMEOUT; + create_conn_par->Peer_Address_Type = addr_type; + create_conn_par->Initiating_PHYs = INIT_SET_1M_PHY; + memcpy(create_conn_par->Peer_Address, conn_addr, 6); + + set_ble_work_state(BLE_ST_CREATE_CONN); + + log_info_hexdump(create_conn_par, sizeof(*create_conn_par)); + + ble_op_ext_create_conn(create_conn_par, sizeof(*create_conn_par)); +} + +#endif /* EXT_ADV_MODE_EN */ + +static void client_create_connection(u8 *conn_addr, u8 addr_type) +{ + struct create_conn_param_t *create_conn_par = scan_buffer; + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + log_info("already create conn!!!\n"); + return; + } + create_conn_par->conn_interval = SET_CONN_INTERVAL; + create_conn_par->conn_latency = SET_CONN_LATENCY; + create_conn_par->supervision_timeout = SET_CONN_TIMEOUT; + memcpy(create_conn_par->peer_address, conn_addr, 6); + create_conn_par->peer_address_type = addr_type; + + set_ble_work_state(BLE_ST_CREATE_CONN); + log_info_hexdump(create_conn_par, sizeof(struct create_conn_param_t)); + ble_op_create_connection(create_conn_par); +} + +static void bt_ble_create_connection(u8 *conn_addr, u8 addr_type) +{ +#if EXT_ADV_MODE_EN + client_ext_create_connection(conn_addr, addr_type); +#else + client_create_connection(conn_addr, addr_type); +#endif /* EXT_ADV_MODE_EN */ +} + +static void client_create_connection_cannel(void) +{ + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + set_ble_work_state(BLE_ST_SEND_CREATE_CONN_CANNEL); + ble_op_create_connection_cancel(); + } +} + +static int client_disconnect(void *priv) +{ + if (con_handle) { + if (BLE_ST_SEND_DISCONN != get_ble_work_state()) { + log_info(">>>ble send disconnect\n"); + set_ble_work_state(BLE_ST_SEND_DISCONN); + ble_op_disconnect(con_handle); + } else { + log_info(">>>ble wait disconnect...\n"); + } + return APP_BLE_NO_ERROR; + } else { + return APP_BLE_OPERATION_ERROR; + } +} + +static void connection_update_complete_success(u8 *packet) +{ + int con_handle, conn_interval, conn_latency, conn_timeout; + + conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet); + conn_latency = hci_subevent_le_connection_update_complete_get_conn_latency(packet); + conn_timeout = hci_subevent_le_connection_update_complete_get_supervision_timeout(packet); + + log_info("conn_interval = %d\n", conn_interval); + log_info("conn_latency = %d\n", conn_latency); + log_info("conn_timeout = %d\n", conn_timeout); +} + + +static void cbk_sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + sm_just_event_t *event = (void *)packet; + u32 tmp32; + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + case SM_EVENT_JUST_WORKS_REQUEST: + sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); + log_info("Just Works Confirmed.\n"); + break; + case SM_EVENT_PASSKEY_DISPLAY_NUMBER: + log_info_hexdump(packet, size); + memcpy(&tmp32, event->data, 4); + log_info("Passkey display: %06u.\n", tmp32); + break; + } + break; + } +} + +static void can_send_now_wakeup(void) +{ + putchar('E'); + if (ble_resume_send_wakeup) { + ble_resume_send_wakeup(); + } +} + +const char *const phy_result[] = { + "None", + "1M", + "2M", + "Coded", +}; + +static void set_connection_data_length(u16 tx_octets, u16 tx_time) +{ + if (con_handle) { + ble_op_set_data_length(con_handle, tx_octets, tx_time); + } +} + +static void set_connection_data_phy(u8 tx_phy, u8 rx_phy) +{ + if (0 == con_handle) { + return; + } + + u8 all_phys = 0; + u16 phy_options = 0; + + ble_op_set_ext_phy(con_handle, all_phys, tx_phy, rx_phy, phy_options); +} + +static void client_profile_start(u16 con_handle) +{ + ble_op_att_send_init(con_handle, att_ram_buffer, ATT_RAM_BUFSIZE, ATT_LOCAL_PAYLOAD_SIZE); + set_ble_work_state(BLE_ST_CONNECT); + + if (0 == client_config->security_en) { + client_search_profile_start(); + } +} + +/* LISTING_START(packetHandler): Packet Handler */ +static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + int mtu; + u32 tmp; + u8 status; + + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + + /* case DAEMON_EVENT_HCI_PACKET_SENT: */ + /* break; */ + case ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE: + log_info("ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE\n"); + case ATT_EVENT_CAN_SEND_NOW: + can_send_now_wakeup(); + break; + + case HCI_EVENT_LE_META: + switch (hci_event_le_meta_get_subevent_code(packet)) { + + case HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE: + status = hci_subevent_le_enhanced_connection_complete_get_status(packet); + if (status) { + log_info("LE_MASTER CREATE CONNECTION FAIL!!! %0x\n", status); + set_ble_work_state(BLE_ST_DISCONN); + break; + } + con_handle = hci_subevent_le_enhanced_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE : 0x%0x\n", con_handle); + log_info("conn_interval = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_interval(packet)); + log_info("conn_latency = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_latency(packet)); + log_info("conn_timeout = %d\n", hci_subevent_le_enhanced_connection_complete_get_supervision_timeout(packet)); + client_profile_start(con_handle); + break; + + case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: + if (packet[3]) { + log_info("LE_MASTER CREATE CONNECTION FAIL!!! %0x\n", packet[3]); + set_ble_work_state(BLE_ST_DISCONN); + break; + } + con_handle = hci_subevent_le_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_CONNECTION_COMPLETE : %0x\n", con_handle); + connection_update_complete_success(packet + 8); + client_profile_start(con_handle); + client_event_report(CLI_EVENT_CONNECTED, packet, size); + + if (pair_bond_enable) { + conn_pair_info.pair_flag = 1; + memcpy(&conn_pair_info.peer_address_info, &packet[7], 7); + conn_pair_vm_do(&conn_pair_info, 1); + pair_bond_enable = 0; + } + break; + + case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: + connection_update_complete_success(packet); + break; + + case HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE: + log_info("APP HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE"); + break; + + case HCI_SUBEVENT_LE_PHY_UPDATE_COMPLETE: + log_info("APP HCI_SUBEVENT_LE_PHY_UPDATE %s\n", hci_event_le_meta_get_phy_update_complete_status(packet) ? "Fail" : "Succ"); + log_info("Tx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_tx_phy(packet)]); + log_info("Rx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_rx_phy(packet)]); + break; + +#if EXT_ADV_MODE_EN + case HCI_SUBEVENT_LE_EXTENDED_ADVERTISING_REPORT: + /* log_info("APP HCI_SUBEVENT_LE_EXTENDED_ADVERTISING_REPORT"); */ + /* log_info_hexdump(packet, size); */ + client_report_ext_adv_data(&packet[2], packet[1]); + break; +#endif /* EXT_ADV_MODE_EN */ + } + break; + + case HCI_EVENT_DISCONNECTION_COMPLETE: + log_info("HCI_EVENT_DISCONNECTION_COMPLETE: %0x\n", packet[5]); + con_handle = 0; + ble_op_att_send_init(con_handle, 0, 0, 0); + set_ble_work_state(BLE_ST_DISCONN); + client_event_report(CLI_EVENT_DISCONNECT, packet, size); + + //auto to do + if (conn_pair_info.pair_flag) { + client_create_connect_api(0, 0, 1); + } else { + bt_ble_scan_enable(0, 1); + } + break; + + case ATT_EVENT_MTU_EXCHANGE_COMPLETE: + mtu = att_event_mtu_exchange_complete_get_MTU(packet) - 3; + log_info("ATT MTU = %u\n", mtu); + ble_op_att_set_send_mtu(mtu); + break; + + case HCI_EVENT_VENDOR_REMOTE_TEST: + log_info("--- HCI_EVENT_VENDOR_REMOTE_TEST\n"); + break; + + case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE: + tmp = little_endian_read_16(packet, 4); + log_info("-update_rsp: %02x\n", tmp); + break; + + case GAP_EVENT_ADVERTISING_REPORT: + /* putchar('@'); */ + client_report_adv_data((void *)&packet[2], packet[1]); + break; + + case HCI_EVENT_ENCRYPTION_CHANGE: + log_info("HCI_EVENT_ENCRYPTION_CHANGE= %d\n", packet[2]); + if (client_config->security_en) { + client_search_profile_start(); + } + break; + } + break; + } +} + + +static int get_buffer_vaild_len(void *priv) +{ + u32 vaild_len = 0; + ble_op_att_get_remain(&vaild_len); + return vaild_len; +} + +static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type) +{ + int ret = APP_BLE_NO_ERROR; + if (!con_handle) { + return APP_BLE_OPERATION_ERROR; + } + + if (!handle) { + log_info("handle is null\n"); + return APP_BLE_OPERATION_ERROR; + } + + + if (get_buffer_vaild_len(0) < len) { + log_info("opt_buff_full!!!\n"); + return APP_BLE_BUFF_FULL; + } + + ret = ble_op_att_send_data(handle, data, len, att_op_type); + if (ret == BLE_BUFFER_FULL) { + ret = APP_BLE_BUFF_FULL; + } + return ret; +} + + +//----------------------------------------------- +static int client_write_send(void *priv, u8 *data, u16 len) +{ + return client_operation_send(target_handle.write_handle, data, len, ATT_OP_WRITE); +} + +static int client_write_without_respond_send(void *priv, u8 *data, u16 len) +{ + return client_operation_send(target_handle.write_no_respond, data, len, ATT_OP_WRITE_WITHOUT_RESPOND); +} + +static int client_read_value_send(void *priv) +{ + u16 tmp_flag = 0x55A1; + return client_operation_send(target_handle.read_handle, (u8 *)&tmp_flag, 2, ATT_OP_READ); +} + +static int client_read_long_value_send(void *priv) +{ + u16 tmp_flag = 0x55A2; + return client_operation_send(target_handle.read_handle, (u8 *)&tmp_flag, 2, ATT_OP_READ_LONG); +} + +#if EXT_ADV_MODE_EN + +struct __ext_scan_param { + u8 Own_Address_Type; + u8 Scanning_Filter_Policy; + u8 Scanning_PHYs; + u8 Scan_Type; + u16 Scan_Interval; + u16 Scan_Window; +} _GNU_PACKED_; + +struct __ext_scan_enable { + u8 Enable; + u8 Filter_Duplicates; + u16 Duration; + u16 Period; +} _GNU_PACKED_; + +const struct __ext_scan_param ext_scan_param = { + .Own_Address_Type = 0, + .Scanning_Filter_Policy = 0, + .Scanning_PHYs = SCAN_SET_1M_PHY, + .Scan_Type = SET_SCAN_TYPE, + .Scan_Interval = SET_SCAN_INTERVAL, + .Scan_Window = SET_SCAN_WINDOW, +}; + +const struct __ext_scan_enable ext_scan_enable = { + .Enable = 1, + .Filter_Duplicates = 0, + .Duration = 0, + .Period = 0, +}; + +const struct __ext_scan_enable ext_scan_disable = { + .Enable = 0, + .Filter_Duplicates = 0, + .Duration = 0, + .Period = 0, +}; + +#endif /* EXT_ADV_MODE_EN */ + +//扫描数设置 +static void scanning_setup_init(void) +{ + ble_op_set_scan_param(SET_SCAN_TYPE, SET_SCAN_INTERVAL, SET_SCAN_WINDOW); +} + +static int bt_ble_scan_enable(void *priv, u32 en) +{ + ble_state_e next_state, cur_state; + + if (!scan_ctrl_en) { + return APP_BLE_OPERATION_ERROR; + } + + if (en) { + next_state = BLE_ST_SCAN; + } else { + next_state = BLE_ST_IDLE; + } + + cur_state = get_ble_work_state(); + switch (cur_state) { + case BLE_ST_SCAN: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + case BLE_ST_CONNECT_FAIL: + case BLE_ST_SEND_CREATE_CONN_CANNEL: + break; + default: + return APP_BLE_OPERATION_ERROR; + break; + } + + if (cur_state == next_state) { + return APP_BLE_NO_ERROR; + } + + + log_info("scan_en:%d\n", en); + set_ble_work_state(next_state); + +#if EXT_ADV_MODE_EN + if (en) { + ble_op_set_ext_scan_param(&ext_scan_param, sizeof(ext_scan_param)); + ble_op_ext_scan_enable(&ext_scan_enable, sizeof(ext_scan_enable)); + } else { + ble_op_ext_scan_enable(&ext_scan_disable, sizeof(ext_scan_disable)); + } +#else + if (en) { + scanning_setup_init(); + } + ble_op_scan_enable2(en, 0); +#endif /* EXT_ADV_MODE_EN */ + + return APP_BLE_NO_ERROR; +} + +static int client_regiest_wakeup_send(void *priv, void *cbk) +{ + /* att_regist_wakeup_send(cbk); */ + return APP_BLE_NO_ERROR; +} + +static int client_regiest_recieve_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_recieve_callback = cbk; + return APP_BLE_NO_ERROR; +} + +static int client_regiest_state_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_ble_state_callback = cbk; + return APP_BLE_NO_ERROR; +} + +//该接口重新配置搜索的配置项 +static int client_init_config(void *priv, const client_conn_cfg_t *cfg) +{ + log_info("client_init_config\n"); + client_config = cfg;//reset config + return APP_BLE_NO_ERROR; +} + +//可配置进入强制搜索方式连接,更加信号强度过滤设备 +static int client_force_search(u8 onoff, s8 rssi) +{ + force_seach_rssi = rssi; + if (force_seach_onoff != onoff) { + + force_seach_onoff = onoff; + //强制搜索前后,关创建监听 + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + client_create_connection_cannel(); + } + } + return 0; +} + +static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode) +{ + u8 cur_state = get_ble_work_state(); + + switch (cur_state) { + case BLE_ST_SCAN: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + case BLE_ST_CONNECT_FAIL: + case BLE_ST_SEND_CREATE_CONN_CANNEL: + break; + default: + return APP_BLE_OPERATION_ERROR; + break; + } + + if (cur_state == BLE_ST_SCAN) { + log_info("stop scan\n"); + bt_ble_scan_enable(0, 0); + } + + //pair mode + if (mode == 1) { + if (conn_pair_info.pair_flag) { + if (conn_pair_info.pair_flag) { + //有配对,跳过搜索,直接创建init_creat + log_info("pair to creat!\n"); + log_info_hexdump(conn_pair_info.peer_address_info, 7); + bt_ble_create_connection(&conn_pair_info.peer_address_info[1], conn_pair_info.peer_address_info[0]); + return 0; + } + + } else { + log_info("no pair to creat!\n"); + return APP_BLE_OPERATION_ERROR; + } + } else { + log_info("addr to creat!\n"); + log_info_hexdump(addr, 7); + bt_ble_create_connection(addr, addr_type); + } + return 0; +} + +static int client_create_cannel_api(void) +{ + if (get_ble_work_state() == BLE_ST_CREATE_CONN) { + client_create_connection_cannel(); + return 0; + } + return 1; +} + +static const struct ble_client_operation_t client_operation = { + .scan_enable = bt_ble_scan_enable, + .disconnect = client_disconnect, + .get_buffer_vaild = get_buffer_vaild_len, + .write_data = (void *)client_write_without_respond_send, + .read_do = (void *)client_read_value_send, + .regist_wakeup_send = client_regiest_wakeup_send, + .regist_recieve_cbk = client_regiest_recieve_cbk, + .regist_state_cbk = client_regiest_state_cbk, + .init_config = client_init_config, + .opt_comm_send = client_operation_send, + .set_force_search = client_force_search, + .create_connect = client_create_connect_api, + .create_connect_cannel = client_create_cannel_api, + .get_work_state = get_ble_work_state, +}; + +struct ble_client_operation_t *ble_get_client_operation_table(void) +{ + return &client_operation; +} + +#define PASSKEY_ENTER_ENABLE 0 //输入passkey使能,可修改passkey +//重设passkey回调函数,在这里可以重新设置passkey +//passkey为6个数字组成,十万位、万位。。。。个位 各表示一个数字 高位不够为0 +static void reset_passkey_cb(u32 *key) +{ +#if 1 + u32 newkey = rand32();//获取随机数 + + newkey &= 0xfffff; + if (newkey > 999999) { + newkey = newkey - 999999; //不能大于999999 + } + *key = newkey; //小于或等于六位数 + log_info("set new_key= %06u\n", *key); +#else + *key = 123456; //for debug +#endif +} + + +//协议栈内部调用 +void ble_sm_setup_init(io_capability_t io_type, u8 auth_req, uint8_t min_key_size, u8 security_en) +{ + //setup SM: Display only + sm_init(); + sm_set_io_capabilities(io_type); + sm_set_authentication_requirements(auth_req); + sm_set_encryption_key_size_range(min_key_size, 16); + sm_set_request_security(security_en); + sm_event_callback_set(&cbk_sm_packet_handler); + + if (io_type == IO_CAPABILITY_DISPLAY_ONLY) { + reset_PK_cb_register(reset_passkey_cb); + } +} + + +//协议栈内部调用 +void ble_profile_init(void) +{ + log_info("ble profile init\n"); + le_device_db_init(); + ble_stack_gatt_role(1); + +#if PASSKEY_ENTER_ENABLE + ble_sm_setup_init(IO_CAPABILITY_DISPLAY_ONLY, SM_AUTHREQ_MITM_PROTECTION | SM_AUTHREQ_BONDING, 7, client_config->security_en); +#else + ble_sm_setup_init(IO_CAPABILITY_NO_INPUT_NO_OUTPUT, SM_AUTHREQ_BONDING, 7, client_config->security_en); +#endif + + /* setup ATT client */ + gatt_client_init(); + gatt_client_register_packet_handler(cbk_packet_handler); + + // register for HCI events + hci_event_callback_set(&cbk_packet_handler); + le_l2cap_register_packet_handler(&cbk_packet_handler); +} + + +static void device_bonding_init(void) +{ + int i; + int cfg_bonding = 0; + client_match_cfg_t *cfg; + for (i = 0; i < CLIENT_MATCH_CONN_MAX; i++) { + cfg = client_config->match_dev_cfg[i]; + if (cfg == NULL) { + continue; + } + if (cfg->bonding_flag) { + cfg_bonding = 1; + } + } + if (!cfg_bonding) { + client_clear_bonding_info(); + } +} + +static u8 client_idle_query(void) +{ + return 0; +} + +REGISTER_LP_TARGET(client_user_target) = { + .name = "client_user_demo", + .is_idle = client_idle_query, +}; + + + + +void bt_ble_init(void) +{ + log_info("***** ble_init******\n"); + set_ble_work_state(BLE_ST_INIT_OK); + conn_pair_vm_do(&conn_pair_info, 0); + device_bonding_init(); + ble_module_enable(1); + +#if SHOW_RX_DATA_RATE + client_timer_start(); +#endif /* SHOW_RX_DATA_RATE */ +} + +void bt_ble_exit(void) +{ + log_info("***** ble_exit******\n"); +} + +//统一接口,关闭模块 +void bt_ble_adv_enable(u8 enable) +{ + ble_module_enable(enable); +} + +//模块开关 +void ble_module_enable(u8 en) +{ + log_info("mode_en:%d\n", en); + if (en) { + scan_ctrl_en = 1; + bt_ble_scan_enable(0, 1); + } else { + if (con_handle) { + scan_ctrl_en = 0; + client_disconnect(NULL); + } else { + bt_ble_scan_enable(0, 0); + scan_ctrl_en = 0; + } + } + +} + +void client_send_conn_param_update(void) +{ + struct conn_update_param_t *param = (void *)&connection_param_table[send_param_index];//for test + log_info("client update param:-%d-%d-%d-%d-\n", param->interval_min, param->interval_max, param->latency, param->timeout); + if (con_handle) { + ble_op_conn_param_update(con_handle, param); + } +} + +/* static void test_send_conn_update(void) */ +/* { */ +/* client_send_conn_param_update(); */ +/* send_param_index++; */ +/* send_param_index &= 3; */ +/* sys_timeout_add(0,test_send_conn_update,10000); */ +/* } */ + + +//---------------------------------------------------------------------------------- + + + +#endif + + diff --git a/apps/common/third_party_profile/jieli/le_client_demo.h b/apps/common/third_party_profile/jieli/le_client_demo.h new file mode 100644 index 0000000..3176829 --- /dev/null +++ b/apps/common/third_party_profile/jieli/le_client_demo.h @@ -0,0 +1,81 @@ +// binary representation +// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) +#ifndef _LE_CLIENT_DEMO_H +#define _LE_CLIENT_DEMO_H + +#include + +//搜索匹配连接方式 +typedef enum { + CLI_CREAT_BY_ADDRESS = 0,//指定地址创建连接 + CLI_CREAT_BY_NAME,//指定设备名称创建连接 + CLI_CREAT_BY_TAG,//匹配厂家标识创建连接 +} cli_creat_mode_e; + +//主机事件 +typedef enum { + CLI_EVENT_MATCH_DEV = 1,//搜索到匹配的设备 + CLI_EVENT_CONNECTED, //设备连接成功 + CLI_EVENT_DISCONNECT,//设备连接断开 + CLI_EVENT_MATCH_UUID,//搜索到匹配的UUID + CLI_EVENT_SEARCH_PROFILE_COMPLETE, //搜索profile服务结束 +} le_client_event_e; + + +typedef struct { + //服务16bit uuid,非0 代表uuid16格式,0--代表是uuid128格式,services_uuid128 + u16 services_uuid16; + //服务16bit uuid,非0 代表uuid16格式,0--代表是uuid128格式,characteristic_uuid128 + u16 characteristic_uuid16; + u8 services_uuid128[16]; + u8 characteristic_uuid128[16]; + u16 opt_type; //属性 + u8 read_long_enable: 1; //en + u8 read_report_reference: 1; //en + u8 res_bits: 6; // +} target_uuid_t; + +//搜索操作记录的 handle +#define OPT_HANDLE_MAX 16 +typedef struct { + //匹配的UUID + target_uuid_t *search_uuid; + //可操作的handle + u16 value_handle; +} opt_handle_t; + +//最大匹配的设备个数 +#define CLIENT_MATCH_CONN_MAX 3 + +typedef struct { + u8 create_conn_mode; //cli_creat_mode_e + u8 bonding_flag; //连接过后会绑定,默认快连,不搜索设备 + u8 compare_data_len; //匹配信息长度 + const u8 *compare_data;//匹配信息,若是地址内容,由高到低位 +} client_match_cfg_t; + + +typedef struct { + //搜索匹配信息 + const client_match_cfg_t *match_dev_cfg[CLIENT_MATCH_CONN_MAX]; + //加密保定配置 0 or 1 + u8 security_en; + //搜索服务的个数 + u8 search_uuid_cnt; // <= OPT_HANDLE_MAX + //搜索服务 + const target_uuid_t *search_uuid_table; + //回调处理接收到的 notify or indicate 数据 + void (*report_data_callback)(att_data_report_t *data_report, target_uuid_t *search_uuid); + //主机一些事件回调处理 + void (*event_callback)(le_client_event_e event, u8 *packet, int size); +} client_conn_cfg_t; + +//清除绑定配对信息 +void client_clear_bonding_info(void); +void client_send_conn_param_update(void); +void ble_module_enable(u8 en); +struct ble_client_operation_t *ble_get_client_operation_table(void); +void bt_ble_init(void); +void bt_ble_adv_enable(u8 enable); + +#endif diff --git a/apps/common/third_party_profile/jieli/le_common.h b/apps/common/third_party_profile/jieli/le_common.h new file mode 100644 index 0000000..cef97c3 --- /dev/null +++ b/apps/common/third_party_profile/jieli/le_common.h @@ -0,0 +1,192 @@ +/********************************************************************************************* + * Filename : le_counter.h + + * Description : + + * Author : Bingquan + + * Email : bingquan_cai@zh-jieli.com + + * Last modifiled : 2017-01-17 15:17 + + * Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved. +*********************************************************************************************/ + +#ifndef __LE_COMMON_H_ +#define __LE_COMMON_H_ + +#include "typedef.h" +#include +#include "btstack/bluetooth.h" + +//-------------------------------------------- + +#define ADV_SET_1M_PHY 1 +#define ADV_SET_2M_PHY 2 +#define ADV_SET_CODED_PHY 3 + +#define SCAN_SET_1M_PHY BIT(0) +#define SCAN_SET_2M_PHY BIT(1) +#define SCAN_SET_CODED_PHY BIT(2) + +#define INIT_SET_1M_PHY BIT(0) +#define INIT_SET_2M_PHY BIT(1) +#define INIT_SET_CODED_PHY BIT(2) + +#define CONN_SET_1M_PHY BIT(0) +#define CONN_SET_2M_PHY BIT(1) +#define CONN_SET_CODED_PHY BIT(2) + +#define CONN_SET_PHY_OPTIONS_NONE 0 +#define CONN_SET_PHY_OPTIONS_S2 1 +#define CONN_SET_PHY_OPTIONS_S8 2 + +struct conn_param_t { + u16 interval; + u16 latency; + u16 timeout; +}; + +// #define NOTIFY_TYPE 1 +// #define INDICATION_TYPE 2 +// Minimum/default MTU + +#define ATT_CTRL_BLOCK_SIZE (188) //note: fixed,libs use +#define ADV_SCAN_MS(_ms) ((_ms) * 8 / 5) + +enum { + ADV_IND = 0, + ADV_DIRECT_IND, + ADV_SCAN_IND, + ADV_NONCONN_IND, +}; + +#define ADV_CHANNEL_37 BIT(0) +#define ADV_CHANNEL_38 BIT(1) +#define ADV_CHANNEL_39 BIT(2) +#define ADV_CHANNEL_ALL (ADV_CHANNEL_37 | ADV_CHANNEL_38 | ADV_CHANNEL_39) + +enum { + SCAN_PASSIVE = 0, + SCAN_ACTIVE, +}; + +#define FLAGS_LIMITED_DISCOVERABLE_MODE BIT(0) +#define FLAGS_GENERAL_DISCOVERABLE_MODE BIT(1) +#define FLAGS_EDR_NOT_SUPPORTED BIT(2) +#define FLAGS_LE_AND_EDR_SAME_CONTROLLER BIT(3) +#define FLAGS_LE_AND_EDR_SAME_HOST BIT(4) + + +typedef enum { + HCI_EIR_DATATYPE_FLAGS = 0x01, + HCI_EIR_DATATYPE_MORE_16BIT_SERVICE_UUIDS = 0x02, + HCI_EIR_DATATYPE_COMPLETE_16BIT_SERVICE_UUIDS = 0x03, + HCI_EIR_DATATYPE_MORE_32BIT_SERVICE_UUIDS = 0x04, + HCI_EIR_DATATYPE_COMPLETE_32BIT_SERVICE_UUIDS = 0x05, + HCI_EIR_DATATYPE_MORE_128BIT_SERVICE_UUIDS = 0x06, + HCI_EIR_DATATYPE_COMPLETE_128BIT_SERVICE_UUIDS = 0x07, + HCI_EIR_DATATYPE_SHORTENED_LOCAL_NAME = 0x08, + HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME = 0x09, + HCI_EIR_DATATYPE_TX_POWER_LEVEL = 0x0A, + HCI_EIR_DATATYPE_CLASS_OF_DEVICE = 0x0D, + HCI_EIR_DATATYPE_SIMPLE_PAIRING_HASH_C = 0x0E, + HCI_EIR_DATATYPE_SIMPLE_PAIRING_RANDOMIZER_R = 0x0F, + HCI_EIR_DATATYPE_SECURITY_MANAGER_TK_VALUE = 0x10, + HCI_EIR_DATATYPE_SECURITY_MANAGER_OOB_FLAGS = 0x11, + HCI_EIR_DATATYPE_SLAVE_CONNECTION_INTERVAL_RANGE = 0x12, + HCI_EIR_DATATYPE_16BIT_SERVICE_SOLICITATION_UUIDS = 0x14, + HCI_EIR_DATATYPE_128BIT_SERVICE_SOLICITATION_UUIDS = 0x15, + HCI_EIR_DATATYPE_SERVICE_DATA = 0x16, + HCI_EIR_DATATYPE_APPEARANCE_DATA = 0x19, + HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF +} HCI_EIR_datatype_t; + + +//按(长度 + 类型 + 内容)这样的格,组合填入广播包数据 +static inline u8 make_eir_packet_data(u8 *buf, u16 offset, u8 data_type, u8 *data, u8 data_len) +{ + if (ADV_RSP_PACKET_MAX - offset < data_len + 2) { + return offset + data_len + 2; + } + + buf[0] = data_len + 1; + buf[1] = data_type; + memcpy(buf + 2, data, data_len); + return data_len + 2; +} + +//按(长度 + 类型 + 内容)这样的格,组合填入广播包数据 +static inline u8 make_eir_packet_val(u8 *buf, u16 offset, u8 data_type, u32 val, u8 val_size) +{ + if (ADV_RSP_PACKET_MAX - offset < val_size + 2) { + return offset + val_size + 2; + } + + buf[0] = val_size + 1; + buf[1] = data_type; + memcpy(buf + 2, &val, val_size); + return val_size + 2; +} + +#define BLE_APPEARANCE_UNKNOWN 0 /**< Unknown. */ +#define BLE_APPEARANCE_GENERIC_PHONE 64 /* Generic Phone. */ +#define BLE_APPEARANCE_GENERIC_COMPUTER 128 /* Generic Computer. */ +#define BLE_APPEARANCE_GENERIC_WATCH 192 /* Generic Watch. */ +#define BLE_APPEARANCE_WATCH_SPORTS_WATCH 193 /* Watch: Sports Watch. */ +#define BLE_APPEARANCE_GENERIC_CLOCK 256 /* Generic Clock. */ +#define BLE_APPEARANCE_GENERIC_DISPLAY 320 /* Generic Display. */ +#define BLE_APPEARANCE_GENERIC_REMOTE_CONTROL 384 /* Generic Remote Control. */ +#define BLE_APPEARANCE_GENERIC_EYE_GLASSES 448 /* Generic Eye-glasses. */ +#define BLE_APPEARANCE_GENERIC_TAG 512 /* Generic Tag. */ +#define BLE_APPEARANCE_GENERIC_KEYRING 576 /* Generic Keyring. */ +#define BLE_APPEARANCE_GENERIC_MEDIA_PLAYER 640 /* Generic Media Player. */ +#define BLE_APPEARANCE_GENERIC_BARCODE_SCANNER 704 /* Generic Barcode Scanner. */ +#define BLE_APPEARANCE_GENERIC_THERMOMETER 768 /* Generic Thermometer. */ +#define BLE_APPEARANCE_THERMOMETER_EAR 769 /* Thermometer: Ear. */ +#define BLE_APPEARANCE_GENERIC_HEART_RATE_SENSOR 832 /* Generic Heart rate Sensor. */ +#define BLE_APPEARANCE_HEART_RATE_SENSOR_HEART_RATE_BELT 833 /* Heart Rate Sensor: Heart Rate Belt. */ +#define BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE 896 /* Generic Blood Pressure. */ +#define BLE_APPEARANCE_BLOOD_PRESSURE_ARM 897 /* Blood Pressure: Arm. */ +#define BLE_APPEARANCE_BLOOD_PRESSURE_WRIST 898 /* Blood Pressure: Wrist. */ +#define BLE_APPEARANCE_GENERIC_HID 960 /* Human Interface Device (HID). */ +#define BLE_APPEARANCE_HID_KEYBOARD 961 /* Keyboard (HID Subtype). */ +#define BLE_APPEARANCE_HID_MOUSE 962 /* Mouse (HID Subtype). */ +#define BLE_APPEARANCE_HID_JOYSTICK 963 /* Joystick (HID Subtype). */ +#define BLE_APPEARANCE_HID_GAMEPAD 964 /* Gamepad (HID Subtype). */ +#define BLE_APPEARANCE_HID_DIGITIZERSUBTYPE 965 /* Digitizer Tablet (HID Subtype). */ +#define BLE_APPEARANCE_HID_CARD_READER 966 /* Card Reader (HID Subtype). */ +#define BLE_APPEARANCE_HID_DIGITAL_PEN 967 /* Digital Pen (HID Subtype). */ +#define BLE_APPEARANCE_HID_BARCODE 968 /* Barcode Scanner (HID Subtype). */ +#define BLE_APPEARANCE_GENERIC_GLUCOSE_METER 1024 /* Generic Glucose Meter. */ +#define BLE_APPEARANCE_GENERIC_RUNNING_WALKING_SENSOR 1088 /* Generic Running Walking Sensor. */ +#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_IN_SHOE 1089 /* Running Walking Sensor: In-Shoe. */ +#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_SHOE 1090 /* Running Walking Sensor: On-Shoe. */ +#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_HIP 1091 /* Running Walking Sensor: On-Hip. */ +#define BLE_APPEARANCE_GENERIC_CYCLING 1152 /* Generic Cycling. */ +#define BLE_APPEARANCE_CYCLING_CYCLING_COMPUTER 1153 /* Cycling: Cycling Computer. */ +#define BLE_APPEARANCE_CYCLING_SPEED_SENSOR 1154 /* Cycling: Speed Sensor. */ +#define BLE_APPEARANCE_CYCLING_CADENCE_SENSOR 1155 /* Cycling: Cadence Sensor. */ +#define BLE_APPEARANCE_CYCLING_POWER_SENSOR 1156 /* Cycling: Power Sensor. */ +#define BLE_APPEARANCE_CYCLING_SPEED_CADENCE_SENSOR 1157 /* Cycling: Speed and Cadence Sensor. */ +#define BLE_APPEARANCE_GENERIC_PULSE_OXIMETER 3136 /* Generic Pulse Oximeter. */ +#define BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP 3137 /* Fingertip (Pulse Oximeter subtype). */ +#define BLE_APPEARANCE_PULSE_OXIMETER_WRIST_WORN 3138 /* Wrist Worn(Pulse Oximeter subtype). */ +#define BLE_APPEARANCE_GENERIC_WEIGHT_SCALE 3200 /* Generic Weight Scale. */ +#define BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS_ACT 5184 /* Generic Outdoor Sports Activity. */ +#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_DISP 5185 /* Location Display Device (Outdoor Sports Activity subtype). */ +#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_DISP 5186 /* Location and Navigation Display Device (Outdoor Sports Activity subtype). */ +#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_POD 5187 /* Location Pod (Outdoor Sports Activity subtype). */ +#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_POD 5188 /* Location and Navigation Pod (Outdoor Sports Activity subtype). */ + +extern void bt_ble_init(void); +extern void bt_ble_exit(void); +extern void le_hogp_set_icon(u16 class_type); +extern void le_hogp_set_ReportMap(u8 *map, u16 size); +extern void ble_module_enable(u8 en); + +extern void le_l2cap_register_packet_handler(void (*handler)(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)); + +#endif + + diff --git a/apps/common/third_party_profile/jieli/multi_demo/le_multi_client.c b/apps/common/third_party_profile/jieli/multi_demo/le_multi_client.c new file mode 100644 index 0000000..26b08df --- /dev/null +++ b/apps/common/third_party_profile/jieli/multi_demo/le_multi_client.c @@ -0,0 +1,1613 @@ +/********************************************************************************************* + * Filename : le_multi_client.c + + * Description : + + * Author : + + * Email : zh-jieli.com + + * Last modifiled : 2017-01-17 11:14 + + * Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved. +*********************************************************************************************/ + +// ***************************************************************************** +/* EXAMPLE_START(le_counter): LE Peripheral - Heartbeat Counter over GATT + * + * @text All newer operating systems provide GATT Client functionality. + * The LE Counter examples demonstrates how to specify a minimal GATT Database + * with a custom GATT Service and a custom Characteristic that sends periodic + * notifications. + */ +// ***************************************************************************** + +#include "system/app_core.h" +#include "system/includes.h" + +#include "app_config.h" +#include "app_action.h" + +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "user_cfg.h" +#include "vm.h" +#include "btcontroller_modules.h" +#include "bt_common.h" + +#include "le_client_demo.h" +#include "le_common.h" +#include "ble_user.h" +#include "le_multi_common.h" + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_MULTI && SUPPORT_MAX_CLIENT) + +#define SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN 1 +#define SHOW_RX_DATA_RATE 0 +#define EXT_ADV_MODE_EN 0 + +#if LE_DEBUG_PRINT_EN +#define log_info(x, ...) printf("[LE-MUL-CLIENT]" x " ", ## __VA_ARGS__) +#define log_info_hexdump put_buf +#else +#define log_info(...) +#define log_info_hexdump(...) +#endif + +//--------------- +#define SEARCH_PROFILE_BUFSIZE (512) //note: +static u8 search_ram_buffer[SEARCH_PROFILE_BUFSIZE] __attribute__((aligned(4))); +#define scan_buffer search_ram_buffer + +//--------------- +#define BASE_INTERVAL_MIN (6)//最小的interval +#if(SUPPORT_MAX_CLIENT > 2) +#define BASE_INTERVAL_VALUE (BASE_INTERVAL_MIN*4) +#else +#define BASE_INTERVAL_VALUE (BASE_INTERVAL_MIN) +#endif + +//--------------- +//搜索类型 +#define SET_SCAN_TYPE SCAN_ACTIVE +//搜索 周期大小 +#define SET_SCAN_INTERVAL ADV_SCAN_MS(10) // unit: ms +//搜索 窗口大小 +#define SET_SCAN_WINDOW ADV_SCAN_MS(10) // unit: ms + +//连接周期 +#define SET_CONN_INTERVAL (BASE_INTERVAL_MIN*8) //(unit:1.25ms) +//连接latency +#define SET_CONN_LATENCY 0 //(unit:conn_interval) +//连接超时 +#define SET_CONN_TIMEOUT 400 //(unit:10ms) +//---------------------------------------------------------------------------- +static u8 scan_ctrl_en; +static u8 ble_work_state[SUPPORT_MAX_CLIENT]; +static void (*app_recieve_callback)(void *priv, void *buf, u16 len) = NULL; +static void (*app_ble_state_callback)(void *priv, ble_state_e state) = NULL; +static void (*ble_resume_send_wakeup)(void) = NULL; +static u32 channel_priv; + +static s8 cur_dev_cid; // 当前操作的多机id + +#define BLE_VM_HEAD_TAG (0xB95C) +#define BLE_VM_TAIL_TAG (0x5CB9) +struct pair_info_t { + u16 head_tag; + u8 pair_flag: 2; + u8 match_dev_id: 6; + u8 peer_address_info[7]; + u16 tail_tag; +}; +static struct pair_info_t conn_pair_info; +static u8 pair_bond_enable = 0; +static u8 match_dev_id = 0; +static struct pair_info_t conn_pair_info_table[SUPPORT_MAX_CLIENT]; +//------------------------------------------------------------------------------- +typedef struct { + uint16_t read_handle; + uint16_t read_long_handle; + uint16_t write_handle; + uint16_t write_no_respond; + uint16_t notify_handle; + uint16_t indicate_handle; +} target_hdl_t; + +//记录handle 使用 +static target_hdl_t target_handle[SUPPORT_MAX_CLIENT]; +static opt_handle_t opt_handle_table[OPT_HANDLE_MAX]; +static u8 opt_handle_used_cnt; +static u8 force_seach_onoff = 0; +static s8 force_seach_rssi = -127; +static u8 is_mode_active = 1; + +static void bt_ble_create_connection(u8 *conn_addr, u8 addr_type); +static int bt_ble_scan_enable(void *priv, u32 en); +static int client_write_send(void *priv, u8 *data, u16 len); +static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type); +int ble_enable_new_dev_scan(void); +//--------------------------------------------------------------------------- +static client_conn_cfg_t *client_config = NULL; +//---------------------------------------------------------------------------- + +static const struct conn_update_param_t connection_param_table[] = { + {16, 24, 0, 600},//11 + {12, 28, 0, 600},//3.7 + {8, 20, 0, 600}, + {50, 60, 0, 600}, +}; + +static u8 send_param_index = 3; + +static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode); +static int client_create_cannel_api(void); +//---------------------------------------------------------------------------- + +static void client_event_report(le_client_event_e event, u8 *packet, int size) +{ + if (client_config->event_callback) { + client_config->event_callback(event, packet, size); + } +} + +static bool check_device_is_match(u8 info_type, u8 *data, int size) +{ + int i; + u8 conn_mode = BIT(info_type); + client_match_cfg_t *cfg; + + /* log_info_hexdump(data,size); */ + + for (i = 0; i < CLIENT_MATCH_CONN_MAX; i++) { + cfg = client_config->match_dev_cfg[i]; + if (cfg == NULL) { + continue; + } + /* log_info("cfg = %08x\n",cfg); */ + /* log_info_hexdump(cfg,sizeof(client_match_cfg_t)); */ + if (cfg->create_conn_mode == conn_mode && size == cfg->compare_data_len) { + log_info("match check\n"); + /* log_info_hexdump(data, size); */ + /* log_info_hexdump(cfg->compare_data, size); */ + if (0 == memcmp(data, cfg->compare_data, cfg->compare_data_len)) { + log_info("match ok:%d\n", cfg->bonding_flag); + pair_bond_enable = cfg->bonding_flag; + match_dev_id = i; + client_event_report(CLI_EVENT_MATCH_DEV, cfg, sizeof(client_match_cfg_t)); + return true; + } + } + } + return false; +} + +static void conn_pair_vm_do(struct pair_info_t *info, u8 rw_flag) +{ + /* return; */ + int ret; + int unit_len = sizeof(struct pair_info_t); + int i; + + log_info("-conn_pair_info vm_do:%d\n", rw_flag); + + if (rw_flag == 0) { + if (unit_len * SUPPORT_MAX_CLIENT != syscfg_read(CFG_BLE_MODE_INFO, (u8 *)conn_pair_info_table, unit_len * SUPPORT_MAX_CLIENT)) { + log_info("-table null--\n"); + memset(conn_pair_info_table, 0, sizeof(conn_pair_info_table)); + } + + for (i = 0; i < SUPPORT_MAX_CLIENT; i++) { + if (conn_pair_info_table[i].head_tag != BLE_VM_HEAD_TAG + || conn_pair_info_table[i].tail_tag != BLE_VM_TAIL_TAG) { + //invail pair + memset(&conn_pair_info_table[i], 0, unit_len); + } + } + + if (info) { + memcpy(info, &conn_pair_info_table[0], unit_len); + } + } else { + int fill_index = -1; + + if (!info) { + log_info("-table clean--\n"); + memset(conn_pair_info_table, 0, sizeof(conn_pair_info_table)); + } else { + for (i = 0; i < SUPPORT_MAX_CLIENT; i++) { + if (0 == memcmp(info, &conn_pair_info_table[i], unit_len)) { + return; + } + } + + r_printf("===============write new dev\n"); + put_buf(conn_pair_info_table, unit_len * SUPPORT_MAX_CLIENT); + put_buf(info, unit_len); + log_info("find table\n"); + + for (i = 0; i < SUPPORT_MAX_CLIENT; i++) { + //先找空的填入 + if (conn_pair_info_table[i].pair_flag == 0) { + fill_index = i; + break; + } + } + + if (SUPPORT_MAX_CLIENT == i) { + for (i = 0; i < SUPPORT_MAX_CLIENT; i++) { + //先覆盖相同条件的 + if (conn_pair_info_table[i].match_dev_id == info->match_dev_id) { + log_info("replace match_dev_id= %d\n", info->match_dev_id); + fill_index = i; + break; + } + } + } + + if (fill_index == -1) { + for (i = SUPPORT_MAX_CLIENT - 1; i > 0; i--) { + //覆盖旧的 + memcpy(&conn_pair_info_table[i], &conn_pair_info_table[i - 1], unit_len); + } + fill_index = 0; + } + + memcpy(&conn_pair_info_table[fill_index], info, unit_len); + conn_pair_info_table[fill_index].head_tag = BLE_VM_HEAD_TAG; + conn_pair_info_table[fill_index].tail_tag = BLE_VM_TAIL_TAG; + } + syscfg_write(CFG_BLE_MODE_INFO, (u8 *)conn_pair_info_table, unit_len * SUPPORT_MAX_CLIENT); + } + put_buf(conn_pair_info_table, unit_len * SUPPORT_MAX_CLIENT); +} + +void client_clear_bonding_info(void) +{ + log_info("client_clear_bonding_info\n"); + //del pair bond + memset(&conn_pair_info, 0, sizeof(struct pair_info_t)); + conn_pair_info.head_tag = BLE_VM_HEAD_TAG; + conn_pair_info.tail_tag = BLE_VM_TAIL_TAG; + conn_pair_vm_do(NULL, 1); +} + +//------------------------------------------------------------ +static void set_ble_work_state(u8 cid, ble_state_e state) +{ + if (state != ble_work_state[cid]) { + log_info("ble_client_work_st[%d]:%x->%x\n", cid, ble_work_state[cid], state); + ble_work_state[cid] = state; + if (app_ble_state_callback) { + app_ble_state_callback((void *)channel_priv, state); + } + } +} +//------------------------------------------------------------ +static ble_state_e get_ble_work_state(u8 cid) +{ + return ble_work_state[cid]; +} + +//------------------------------------------------------------------------------- +static void check_target_uuid_match(search_result_t *result_info) +{ + u32 i; + target_uuid_t *t_uuid; + + for (i = 0; i < client_config->search_uuid_cnt; i++) { + t_uuid = &client_config->search_uuid_table[i]; + if (result_info->services.uuid16) { + if (result_info->services.uuid16 != t_uuid->services_uuid16) { + /* log_info("b1"); */ + continue; + } + } else { + if (memcmp(result_info->services.uuid128, t_uuid->services_uuid128, 16)) { + /* log_info("b2"); */ + continue; + } + } + + if (result_info->characteristic.uuid16) { + if (result_info->characteristic.uuid16 != t_uuid->characteristic_uuid16) { + /* log_info("b3"); */ + /* log_info("%d: %04x--%04x",result_info->characteristic.uuid16,t_uuid->characteristic_uuid16); */ + continue; + } + } else { + if (memcmp(result_info->characteristic.uuid128, t_uuid->characteristic_uuid128, 16)) { + /* log_info("b4"); */ + continue; + } + } + + break;//match one + } + + if (i >= client_config->search_uuid_cnt) { + return; + } + + if (opt_handle_used_cnt >= OPT_HANDLE_MAX) { + log_info("opt_handle is full!!!\n"); + return; + } + + if ((t_uuid->opt_type & result_info->characteristic.properties) != t_uuid->opt_type) { + log_info("properties not match!!!\n"); + return; + } + + log_info("match one uuid\n"); + + opt_handle_t *opt_get = &opt_handle_table[opt_handle_used_cnt++]; + opt_get->value_handle = result_info->characteristic.value_handle; + opt_get->search_uuid = t_uuid; + + switch (t_uuid->opt_type) { + case ATT_PROPERTY_READ: + target_handle[cur_dev_cid].read_handle = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_WRITE_WITHOUT_RESPONSE: + target_handle[cur_dev_cid].write_no_respond = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_WRITE: + target_handle[cur_dev_cid].write_handle = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_NOTIFY: + target_handle[cur_dev_cid].notify_handle = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_INDICATE: + target_handle[cur_dev_cid].indicate_handle = result_info->characteristic.value_handle; + break; + + default: + break; + } + + client_event_report(CLI_EVENT_MATCH_UUID, opt_get, sizeof(opt_handle_t)); + +} + +//操作handle,完成 write ccc +static void do_operate_search_handle(void) +{ + u16 tmp_16; + u16 i, cur_opt_type; + opt_handle_t *opt_hdl_pt; + + log_info("opt_handle_used_cnt= %d\n", opt_handle_used_cnt); + + log_info("find target_handle:"); + log_info_hexdump(&target_handle[cur_dev_cid], sizeof(target_hdl_t)); + + if (0 == opt_handle_used_cnt) { + goto opt_end; + } + + /* test_send_conn_update();//for test */ + + for (i = 0; i < opt_handle_used_cnt; i++) { + opt_hdl_pt = &opt_handle_table[i]; + log_info("do opt:service_uuid16:%04x,charactc_uuid16:%04x\n", opt_hdl_pt->search_uuid->services_uuid16, opt_hdl_pt->search_uuid->characteristic_uuid16); + cur_opt_type = opt_hdl_pt->search_uuid->opt_type; + switch ((u8)cur_opt_type) { + case ATT_PROPERTY_READ: + if (opt_hdl_pt->search_uuid->read_long_enable) { + tmp_16 = 0x55A2;//fixed + log_info("read_long:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle, (u8 *)&tmp_16, 2, ATT_OP_READ_LONG); + } else { + tmp_16 = 0x55A1;//fixed + log_info("read:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle, (u8 *)&tmp_16, 2, ATT_OP_READ); + } + break; + + case ATT_PROPERTY_NOTIFY: + tmp_16 = 0x01;//fixed + log_info("write_ntf_ccc:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle + 1, &tmp_16, 2, ATT_OP_WRITE); + if (opt_hdl_pt->search_uuid->read_report_reference) { + tmp_16 = 0x55A1;//fixed + log_info("read_report_reference:%04x\n", opt_hdl_pt->value_handle + 2); + client_operation_send(opt_hdl_pt->value_handle + 2, (u8 *)&tmp_16, 2, ATT_OP_READ); + } + break; + + case ATT_PROPERTY_INDICATE: + tmp_16 = 0x02;//fixed + log_info("write_ind_ccc:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle + 1, &tmp_16, 2, ATT_OP_WRITE); + break; + + default: + break; + } + } + +opt_end: + set_ble_work_state(cur_dev_cid, BLE_ST_SEARCH_COMPLETE); + +} + +//协议栈内部调用 +//return: 0--accept,1--reject +int l2cap_connection_update_request_just(u8 *packet, hci_con_handle_t handle) +{ + log_info("slave request conn_update:\n-conn_handle= %04x\n-interval_min= %d,\n-interval_max= %d,\n-latency= %d,\n-timeout= %d\n", + handle, + little_endian_read_16(packet, 0), little_endian_read_16(packet, 2), + little_endian_read_16(packet, 4), little_endian_read_16(packet, 6)); + +#if (SUPPORT_MAX_CLIENT > 1) + u16 cfg_interval = BASE_INTERVAL_VALUE; + u16 max_interval = little_endian_read_16(packet, 2); + while (max_interval >= (cfg_interval + BASE_INTERVAL_VALUE)) { + cfg_interval += BASE_INTERVAL_VALUE; + } + little_endian_store_16(packet, 0, cfg_interval); + little_endian_store_16(packet, 2, cfg_interval); + r_printf("conn_handle:%04x,confirm_interval:%d", handle, cfg_interval); + log_info("conn_handle:%04x,confirm_interval:%d\n", handle, cfg_interval); +#endif + + //change param + /* little_endian_store_16(packet, 4,0);//disable latency */ + /* little_endian_store_16(packet, 6,400);//change timeout */ + return 0; + /* return 1; */ +} + +//协议栈内部调用 +void user_client_report_search_result(search_result_t *result_info) +{ + if (result_info == (void *) - 1) { + log_info("client_report_search_result finish!!!\n"); + do_operate_search_handle(); + client_event_report(CLI_EVENT_SEARCH_PROFILE_COMPLETE, 0, 0); + + //搜索完profile,尝试开新设备scan + ble_enable_new_dev_scan(); + return; + } + + log_info("\n*** services, uuid16:%04x,index=%d ***\n", result_info->services.uuid16, result_info->service_index); + log_info("{charactc, uuid16:%04x,index=%d,handle:%04x~%04x,value_handle=%04x}\n", + result_info->characteristic.uuid16, result_info->characteristic_index, + result_info->characteristic.start_handle, result_info->characteristic.end_handle, + result_info->characteristic.value_handle + ); + + if (!result_info->services.uuid16) { + log_info("######services_uuid128:"); + log_info_hexdump(result_info->services.uuid128, 16); + } + + if (!result_info->characteristic.uuid16) { + log_info("######charact_uuid128:"); + log_info_hexdump(result_info->characteristic.uuid128, 16); + } + + check_target_uuid_match(result_info); +} + +#if SHOW_RX_DATA_RATE + +static u32 client_timer_handle = 0; +static u32 test_data_count; +static void client_timer_handler(void) +{ + if (!client_con_handle[cur_dev_cid]) { + test_data_count = 0; + return; + } + log_info("peer_rssi = %d\n", ble_vendor_get_peer_rssi(client_con_handle[cur_dev_cid])); + + if (test_data_count) { + /* log_info("\n-ble_data_rate: %d bps-\n", test_data_count * 8); */ + log_info("\n%d bytes receive: %d.%02d KB/s \n", test_data_count, test_data_count / 1000, test_data_count % 1000); + test_data_count = 0; + } +} + +static void client_timer_start(void) +{ + client_timer_handle = sys_timer_add(NULL, client_timer_handler, 1000); +} + +#endif /* SHOW_RX_DATA_RATE */ + +static target_uuid_t *get_match_handle_target(u16 handle) +{ + for (int i = 0; i < opt_handle_used_cnt; i++) { + if (opt_handle_table[i].value_handle == handle) { + return opt_handle_table[i].search_uuid; + } + } + return NULL; +} + +//协议栈内部调用 +void user_client_report_data_callback(att_data_report_t *report_data) +{ + /* log_info("\n-report_data:type %02x,handle %04x,offset %d,len %d:",report_data->packet_type, */ + /* report_data->value_handle,report_data->value_offset,report_data->blob_length); */ + /* log_info_hexdump(report_data->blob,report_data->blob_length); */ + + if (-1 == mul_get_dev_index(report_data->conn_handle, MULTI_ROLE_CLIENT)) { + log_info("unknown_handle:%04x\n", report_data->conn_handle); + log_info_hexdump(report_data->blob, report_data->blob_length); + return; + } + +#if SHOW_RX_DATA_RATE + test_data_count += report_data->blob_length; +#endif /* SHOW_RX_DATA_RATE */ + + target_uuid_t *search_uuid = get_match_handle_target(report_data->value_handle); + + if (client_config->report_data_callback) { + client_config->report_data_callback(report_data, search_uuid); + return; + } + + switch (report_data->packet_type) { + case GATT_EVENT_NOTIFICATION://notify +// log_info("\n-notify_rx(%d):",report_data->blob_length); + case GATT_EVENT_INDICATION://indicate + case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT://read + case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT://read long + break; + default: + break; + } +} + +// PRIMARY_SERVICE,AE30 +/* static const u16 test_services_uuid16 = 0xae30; */ + +// PRIMARY_SERVICE, 0000F530-1212-EFDE-1523-785FEABCD123 +/* static const u8 test_services_uuid128[16] = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}; */ + +static void client_search_profile_start(void) +{ + opt_handle_used_cnt = 0; + memset(&target_handle[cur_dev_cid], 0, sizeof(target_hdl_t)); + user_client_init(client_con_handle[cur_dev_cid], search_ram_buffer, SEARCH_PROFILE_BUFSIZE); + if (client_config->search_uuid_cnt) { + log_info("start search_profile_all:%04x\n", client_con_handle[cur_dev_cid]); + ble_op_search_profile_all(); + } else { + log_info("skip search_profile:%04x\n\n", client_con_handle[cur_dev_cid]); + user_client_set_search_complete(); + } +} + +//------------------------------------------------------------ +static bool resolve_adv_report(u8 *adv_address, u8 data_length, u8 *data, s8 rssi) +{ + u8 i, lenght, ad_type; + u8 *adv_data_pt; + u8 find_remoter = 0; + /* u8 tmp_addr[6]; */ + u32 tmp32; + + if (check_device_is_match(CLI_CREAT_BY_ADDRESS, adv_address, 6)) { + find_remoter = 1; + } + + adv_data_pt = data; + for (i = 0; i < data_length;) { + if (*adv_data_pt == 0) { + /* log_info("analyze end\n"); */ + break; + } + + lenght = *adv_data_pt++; + ad_type = *adv_data_pt++; + i += (lenght + 1); + + switch (ad_type) { + case HCI_EIR_DATATYPE_FLAGS: + /* log_info("flags:%02x\n",adv_data_pt[0]); */ + break; + + case HCI_EIR_DATATYPE_MORE_16BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_COMPLETE_16BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_MORE_32BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_COMPLETE_32BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_MORE_128BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_COMPLETE_128BIT_SERVICE_UUIDS: + /* log_info("service uuid:"); */ + /* log_info_hexdump(adv_data_pt, lenght - 1); */ + break; + + case HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME: + case HCI_EIR_DATATYPE_SHORTENED_LOCAL_NAME: + tmp32 = adv_data_pt[lenght - 1]; + adv_data_pt[lenght - 1] = 0;; + log_info("ble remoter_name: %s,rssi:%d\n", adv_data_pt, rssi); + /* log_info_hexdump(adv_address, 6); */ + adv_data_pt[lenght - 1] = tmp32; + //------- +#if SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN +#define TEST_BOX_BLE_NAME "JLBT_TESTBOX" +#define TEST_BOX_BLE_NAME_LEN 0xc + if (0 == memcmp(adv_data_pt, TEST_BOX_BLE_NAME, TEST_BOX_BLE_NAME_LEN)) { + find_remoter = 1; + break; + } +#endif + /* log_info("target name:%s", client_config->compare_data); */ + if (check_device_is_match(CLI_CREAT_BY_NAME, adv_data_pt, lenght - 1)) { + find_remoter = 1; + log_info("catch name ok\n"); + } + break; + + case HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA: + if (check_device_is_match(CLI_CREAT_BY_TAG, adv_data_pt, lenght - 1)) { + log_info("get_tag_string!\n"); + find_remoter = 1; + } + break; + + case HCI_EIR_DATATYPE_APPEARANCE_DATA: + /* log_info("get_class_type:%04x\n",little_endian_read_16(adv_data_pt,0)); */ + break; + + default: + /* log_info("unknow ad_type:"); */ + break; + } + + if (find_remoter) { + log_info_hexdump(adv_data_pt, lenght - 1); + } + adv_data_pt += (lenght - 1); + } + + return find_remoter; +} + +static void client_report_adv_data(adv_report_t *report_pt, u16 len) +{ + bool find_tag = 0; + int i; + /* log_info("event_type,addr_type: %x,%x; ",report_pt->event_type,report_pt->address_type); */ + /* log_info_hexdump(report_pt->address,6); */ + + /* log_info("adv_data_display:"); */ + /* log_info_hexdump(report_pt->data,report_pt->length); */ + +// log_info("rssi:%d\n",report_pt->rssi); + + for (i = 0; i < SUPPORT_MAX_CLIENT; i++) { + if (conn_pair_info_table[i].pair_flag) { + /* log_info("check paired dev\n"); */ + /* put_buf(report_pt->address, 6); */ + /* put_buf(&conn_pair_info_table[i].peer_address_info[1], 6); */ + if (report_pt->event_type == conn_pair_info_table[i].peer_address_info[0] + && 0 == memcmp(report_pt->address, &conn_pair_info_table[i].peer_address_info[1], 6)) { + find_tag = 1; + log_info("find paired dev to connect\n"); + put_buf(conn_pair_info_table[i].peer_address_info, 7); + } + } + } + + if (!find_tag) { + find_tag = resolve_adv_report(report_pt->address, report_pt->length, report_pt->data, report_pt->rssi); + } + + if (find_tag) { + if (force_seach_onoff && force_seach_rssi > report_pt->rssi) { + log_info("match but rssi fail!!!:%d,%d\n", force_seach_rssi, report_pt->rssi); + return; + } + + log_info("rssi:%d\n", report_pt->rssi); + log_info("\n*********create_connection***********\n"); + log_info("***remote type %d,addr:", report_pt->address_type); + log_info_hexdump(report_pt->address, 6); + bt_ble_scan_enable(0, 0); + client_create_connect_api(report_pt->address, report_pt->address_type, 0); + log_info("*create_finish\n"); + } +} + +#if EXT_ADV_MODE_EN + +#define GET_STRUCT_MEMBER_OFFSET(type, member) \ + (u32)&(((struct type*)0)->member) + +struct __ext_adv_report_event { + u8 Subevent_Code; + u8 Num_Reports; + u16 Event_Type; + u8 Address_Type; + u8 Address[6]; + u8 Primary_PHY; + u8 Secondary_PHY; + u8 Advertising_SID; + u8 Tx_Power; + u8 RSSI; + u16 Periodic_Advertising_Interval; + u8 Direct_Address_Type; + u8 Direct_Address[6]; + u8 Data_Length; + u8 Data[0]; +} _GNU_PACKED_; + +static void client_report_ext_adv_data(u8 *report_pt, u16 len) +{ + bool find_remoter; + u8 address_type = report_pt[GET_STRUCT_MEMBER_OFFSET(__ext_adv_report_event, Address_Type)]; + u8 address[6]; + + /* log_info("--func=%s", __FUNCTION__); */ + /* log_info_hexdump(report_pt, len); */ + + memcpy(address, &report_pt[GET_STRUCT_MEMBER_OFFSET(__ext_adv_report_event, Address)], 6); + + find_remoter = resolve_adv_report(\ + address, \ + report_pt[GET_STRUCT_MEMBER_OFFSET(__ext_adv_report_event, Data_Length)], \ + &report_pt[GET_STRUCT_MEMBER_OFFSET(__ext_adv_report_event, Data)], 0 \ + ); + + if (find_remoter) { + if (force_seach_onoff && force_seach_rssi > report_pt->rssi) { + log_info("match but rssi fail!!!:%d,%d\n", force_seach_rssi, report_pt->rssi); + return; + } + + log_info("\n*********ext create_connection***********\n"); + log_info("***remote type %d, addr:", address_type); + log_info_hexdump(address, 6); + bt_ble_scan_enable(0, 0); + client_create_connect_api(address, address_type, 0); + log_info("*create_finish\n"); + } +} + +struct __ext_init { + u8 Initiating_Filter_Policy; + u8 Own_Address_Type; + u8 Peer_Address_Type; + u8 Peer_Address[6]; + u8 Initiating_PHYs; + u16 Scan_Interval; + u16 Scan_Window; + u16 Conn_Interval_Min; + u16 Conn_Interval_Max; + u16 Conn_Latency; + u16 Supervision_Timeout; + u16 Minimum_CE_Length; + u16 Maximum_CE_Length; +} _GNU_PACKED_; + +static void client_ext_create_connection(u8 *conn_addr, u8 addr_type) +{ + struct __ext_init *create_conn_par = scan_buffer; + + if (get_ble_work_state(cur_dev_cid) == BLE_ST_CREATE_CONN) { + log_info("already ext_create conn:%d!!!\n", cur_dev_cid); + return; + } + + memset(create_conn_par, 0, sizeof(*create_conn_par)); + create_conn_par->Conn_Interval_Min = SET_CONN_INTERVAL; + create_conn_par->Conn_Interval_Max = SET_CONN_INTERVAL; + create_conn_par->Conn_Latency = SET_CONN_LATENCY; + create_conn_par->Supervision_Timeout = SET_CONN_TIMEOUT; + create_conn_par->Peer_Address_Type = addr_type; + create_conn_par->Initiating_PHYs = INIT_SET_1M_PHY; + memcpy(create_conn_par->Peer_Address, conn_addr, 6); + + set_ble_work_state(cur_dev_cid, BLE_ST_CREATE_CONN); + + log_info_hexdump(create_conn_par, sizeof(*create_conn_par)); + + ble_op_ext_create_conn(create_conn_par, sizeof(*create_conn_par)); +} + +#endif /* EXT_ADV_MODE_EN */ + +static void client_create_connection(u8 *conn_addr, u8 addr_type) +{ + struct create_conn_param_t *create_conn_par = scan_buffer; + if (get_ble_work_state(cur_dev_cid) == BLE_ST_CREATE_CONN) { + log_info("already create conn:%d!!!\n", cur_dev_cid); + return; + } + create_conn_par->conn_interval = SET_CONN_INTERVAL; + create_conn_par->conn_latency = SET_CONN_LATENCY; + create_conn_par->supervision_timeout = SET_CONN_TIMEOUT; + memcpy(create_conn_par->peer_address, conn_addr, 6); + create_conn_par->peer_address_type = addr_type; + + set_ble_work_state(cur_dev_cid, BLE_ST_CREATE_CONN); + log_info_hexdump(create_conn_par, sizeof(struct create_conn_param_t)); + ble_op_create_connection(create_conn_par); +} + +static void bt_ble_create_connection(u8 *conn_addr, u8 addr_type) +{ +#if EXT_ADV_MODE_EN + client_ext_create_connection(conn_addr, addr_type); +#else + client_create_connection(conn_addr, addr_type); +#endif /* EXT_ADV_MODE_EN */ +} + +static void client_create_connection_cannel(void) +{ + if (get_ble_work_state(cur_dev_cid) == BLE_ST_CREATE_CONN) { + set_ble_work_state(cur_dev_cid, BLE_ST_SEND_CREATE_CONN_CANNEL); + ble_op_create_connection_cancel(); + } +} + +static int client_disconnect(void *priv) +{ + u8 cid = (u8) priv; + + if (cid >= SUPPORT_MAX_CLIENT) { + return APP_BLE_OPERATION_ERROR; + } + + if (client_con_handle[cid]) { + if (BLE_ST_SEND_DISCONN != get_ble_work_state(cid)) { + log_info(">>>ble(%d) send disconnect\n", cid); + set_ble_work_state(cid, BLE_ST_SEND_DISCONN); + ble_op_disconnect(client_con_handle[cid]); + } else { + log_info(">>>ble(%d) wait disconnect...\n", cid); + } + return APP_BLE_NO_ERROR; + } else { + return APP_BLE_OPERATION_ERROR; + } +} + +void ble_multi_client_disconnect(void) +{ + u8 i; + int count; + + for (u8 i = 0; i < SUPPORT_MAX_CLIENT; i++) { + count = 150; + if (client_con_handle[i]) { + client_disconnect((void *)i); + while (count-- && client_con_handle[i]) { + os_time_dly(1); + putchar('w'); + } + } + } +} + +static void connection_update_complete_success(u16 conn_handle, u8 *packet) +{ + int conn_interval, conn_latency, conn_timeout; + + conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet); + conn_latency = hci_subevent_le_connection_update_complete_get_conn_latency(packet); + conn_timeout = hci_subevent_le_connection_update_complete_get_supervision_timeout(packet); + + log_info("conn_handle = %04x\n", conn_handle); + log_info("conn_interval = %d\n", conn_interval); + log_info("conn_latency = %d\n", conn_latency); + log_info("conn_timeout = %d\n", conn_timeout); +} + +static void can_send_now_wakeup(void) +{ + putchar('E'); + if (ble_resume_send_wakeup) { + ble_resume_send_wakeup(); + } +} + +static const char *const phy_result[] = { + "None", + "1M", + "2M", + "Coded", +}; + +static void set_connection_data_length(u16 tx_octets, u16 tx_time) +{ + if (client_con_handle[cur_dev_cid]) { + ble_op_set_data_length(client_con_handle[cur_dev_cid], tx_octets, tx_time); + } +} + +static void set_connection_data_phy(u8 tx_phy, u8 rx_phy) +{ + if (0 == client_con_handle[cur_dev_cid]) { + return; + } + + u8 all_phys = 0; + u16 phy_options = 0; + + ble_op_set_ext_phy(client_con_handle[cur_dev_cid], all_phys, tx_phy, rx_phy, phy_options); +} + +static void client_profile_start(u16 conn_handle) +{ + set_ble_work_state(cur_dev_cid, BLE_ST_CONNECT); + + if (0 == client_config->security_en) { + client_search_profile_start(); + } +} + +//尝试开新设备scan +int ble_enable_new_dev_scan(void) +{ + log_info("%s\n", __FUNCTION__); + + if (!client_con_handle[cur_dev_cid]) { + log_info("dev_doing\n"); + return -1; + } + + s8 tmp_cid = mul_get_idle_dev_index(MULTI_ROLE_CLIENT); + if (tmp_cid < 0) { + log_info("no idle dev to do!!!\n"); + return -2; + } + + log_info("new_dev_scan\n"); + cur_dev_cid = tmp_cid; + set_ble_work_state(cur_dev_cid, BLE_ST_IDLE); + bt_ble_scan_enable(0, 1); + return 0; +} + + +/* LISTING_START(packetHandler): Packet Handler */ +void client_cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + int mtu; + u32 tmp; + u8 status; + + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + + /* case DAEMON_EVENT_HCI_PACKET_SENT: */ + /* break; */ + case ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE: + log_info("ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE\n"); + case ATT_EVENT_CAN_SEND_NOW: + can_send_now_wakeup(); + break; + + case HCI_EVENT_LE_META: + switch (hci_event_le_meta_get_subevent_code(packet)) { + + case HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE: { + if (1 == hci_subevent_le_connection_complete_get_role(packet)) { + //connect is slave + break; + } + + status = hci_subevent_le_enhanced_connection_complete_get_status(packet); + if (status) { + log_info("LE_MASTER CREATE CONNECTION FAIL!!! %0x\n", status); + set_ble_work_state(cur_dev_cid, BLE_ST_DISCONN); + break; + } + u16 tmp_handle1 = hci_subevent_le_enhanced_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE : 0x%0x\n", tmp_handle1); + s8 tmp_dev_cid1 = mul_get_idle_dev_index(MULTI_ROLE_CLIENT); + + if (tmp_dev_cid1 < 0) { + log_info("dev_cid full!!!\n"); + ble_op_disconnect(tmp_handle1); + break; + } + + cur_dev_cid = tmp_dev_cid1; + client_con_handle[cur_dev_cid] = tmp_handle1; + ble_op_multi_att_send_conn_handle(client_con_handle[cur_dev_cid], cur_dev_cid, MULTI_ROLE_CLIENT); + + log_info("conn_interval = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_interval(packet)); + log_info("conn_latency = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_latency(packet)); + log_info("conn_timeout = %d\n", hci_subevent_le_enhanced_connection_complete_get_supervision_timeout(packet)); + client_profile_start(client_con_handle[cur_dev_cid]); + } + break; + + case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: { + if (1 == hci_subevent_le_connection_complete_get_role(packet)) { + //connect is slave + break; + } + + if (packet[3]) { + log_info("LE_MASTER CREATE CONNECTION FAIL!!! %0x\n", packet[3]); + set_ble_work_state(cur_dev_cid, BLE_ST_DISCONN); + //auto to do + bt_ble_scan_enable(0, 1); + break; + } + + u16 tmp_handle = hci_subevent_le_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_CONNECTION_COMPLETE: %0x\n", tmp_handle); + s8 tmp_dev_cid = mul_get_idle_dev_index(MULTI_ROLE_CLIENT); + + if (tmp_dev_cid < 0) { + log_info("dev_cid full!!!\n"); + ble_op_disconnect(tmp_handle); + break; + } + + cur_dev_cid = tmp_dev_cid; + client_con_handle[cur_dev_cid] = tmp_handle; + ble_op_multi_att_send_conn_handle(client_con_handle[cur_dev_cid], cur_dev_cid, MULTI_ROLE_CLIENT); + + connection_update_complete_success(tmp_handle, packet + 8); + client_profile_start(client_con_handle[cur_dev_cid]); + client_event_report(CLI_EVENT_CONNECTED, packet, size); + + if (pair_bond_enable) { + log_info("bond remoter\n"); + conn_pair_info.pair_flag = 1; + conn_pair_info.match_dev_id = match_dev_id; + memcpy(&conn_pair_info.peer_address_info, &packet[7], 7); + conn_pair_vm_do(&conn_pair_info, 1); + pair_bond_enable = 0; + } + } + break; + + case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: { + u16 tmp_handle = little_endian_read_16(packet, 4); + if (mul_get_dev_index(tmp_handle, MULTI_ROLE_CLIENT) >= 0) { + connection_update_complete_success(tmp_handle, packet); + } + } + break; + + case HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE: + log_info("APP HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE"); + break; + + case HCI_SUBEVENT_LE_PHY_UPDATE_COMPLETE: + log_info("APP HCI_SUBEVENT_LE_PHY_UPDATE %s\n", hci_event_le_meta_get_phy_update_complete_status(packet) ? "Fail" : "Succ"); + log_info("Tx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_tx_phy(packet)]); + log_info("Rx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_rx_phy(packet)]); + break; + +#if EXT_ADV_MODE_EN + case HCI_SUBEVENT_LE_EXTENDED_ADVERTISING_REPORT: + /* log_info("APP HCI_SUBEVENT_LE_EXTENDED_ADVERTISING_REPORT"); */ + /* log_info_hexdump(packet, size); */ + if (BLE_ST_SCAN == get_ble_work_state(cur_dev_cid)) { + client_report_ext_adv_data(&packet[2], packet[1]); + } else { + log_info("drop ext_adv_report!!!\n"); + } + break; +#endif /* EXT_ADV_MODE_EN */ + } + break; + + case HCI_EVENT_DISCONNECTION_COMPLETE: + log_info("HCI_EVENT_DISCONNECTION_COMPLETE: %0x\n", packet[5]); + + u16 tmp_handle = little_endian_read_16(packet, 3); + s8 tmp_index = mul_get_dev_index(tmp_handle, MULTI_ROLE_CLIENT); + if (tmp_index < 0) { + log_info("unknown_handle:%04x\n", tmp_handle); + break; + } + + client_con_handle[tmp_index] = 0; + set_ble_work_state(tmp_index, BLE_ST_DISCONN); + client_event_report(CLI_EVENT_DISCONNECT, packet, size); + ble_op_multi_att_send_conn_handle(0, tmp_index, MULTI_ROLE_CLIENT); + + if (0 == client_con_handle[cur_dev_cid]) { + //判断当前设备是否正在scan 或者 creat + if (BLE_ST_SCAN == get_ble_work_state(cur_dev_cid) || BLE_ST_CREATE_CONN == get_ble_work_state(cur_dev_cid)) { + //直接退出,不做别的操作 + break; + } + } + + //配设备开scan + cur_dev_cid = tmp_index; + + //auto to do + if (0) { //(conn_pair_info.pair_flag && SUPPORT_MAX_CLIENT < 2) { + client_create_connect_api(0, 0, 1); + } else { + bt_ble_scan_enable(0, 1); + } + break; + + case ATT_EVENT_MTU_EXCHANGE_COMPLETE: { + u16 tmp_handle = little_endian_read_16(packet, 2); + s8 tmp_cid = mul_get_dev_index(tmp_handle, MULTI_ROLE_CLIENT); + if (tmp_cid != -1) { + mtu = att_event_mtu_exchange_complete_get_MTU(packet) - 3; + log_info("ATT MTU = %u\n", mtu); + ble_op_multi_att_set_send_mtu(tmp_handle, mtu); + /* set_connection_data_length(251, 2120); */ + } + } + break; + + case HCI_EVENT_VENDOR_REMOTE_TEST: + log_info("--- HCI_EVENT_VENDOR_REMOTE_TEST\n"); + break; + + case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE: { + u16 tmp_handle = little_endian_read_16(packet, 2); + s8 tmp_cid = mul_get_dev_index(tmp_handle, MULTI_ROLE_CLIENT); + if (tmp_cid != -1) { + tmp = little_endian_read_16(packet, 4); + log_info("-update_rsp:%04x, %02x\n", tmp_handle, tmp); + } + } + break; + + case GAP_EVENT_ADVERTISING_REPORT: + /* putchar('@'); */ + if (BLE_ST_SCAN == get_ble_work_state(cur_dev_cid)) { + client_report_adv_data((void *)&packet[2], packet[1]); + } else { + log_info("drop adv_report!!!\n"); + } + break; + + case HCI_EVENT_ENCRYPTION_CHANGE: { + u16 tmp_handle = little_endian_read_16(packet, 3); + s8 tmp_cid = mul_get_dev_index(tmp_handle, MULTI_ROLE_CLIENT); + if (tmp_cid != -1) { + log_info("HCI_EVENT_ENCRYPTION_CHANGE= %d\n", packet[2]); + if (client_config->security_en) { + client_search_profile_start(); + } + } + } + break; + } + break; + } +} + + +static int get_buffer_vaild_len(void *priv) +{ + u32 vaild_len = 0; + ble_op_multi_att_get_remain(client_con_handle[cur_dev_cid], &vaild_len); + return vaild_len; +} + +static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type) +{ + int ret = APP_BLE_NO_ERROR; + if (!client_con_handle[cur_dev_cid]) { + return APP_BLE_OPERATION_ERROR; + } + + if (!handle) { + log_info("handle is null\n"); + return APP_BLE_OPERATION_ERROR; + } + + if (get_buffer_vaild_len(0) < len) { + log_info("opt_buff_full!!!\n"); + return APP_BLE_BUFF_FULL; + } + + ret = ble_op_multi_att_send_data(client_con_handle[cur_dev_cid], handle, data, len, att_op_type); + if (ret == BLE_BUFFER_FULL) { + ret = APP_BLE_BUFF_FULL; + } + return ret; +} + + +static int client_operation_send_ext(u16 conn_handle, u16 handle, u8 *data, u16 len, u8 att_op_type) +{ + int ret = APP_BLE_NO_ERROR; + if (!conn_handle) { + return APP_BLE_OPERATION_ERROR; + } + + ret = ble_op_multi_att_send_data(conn_handle, handle, data, len, att_op_type); + if (ret == BLE_BUFFER_FULL) { + ret = APP_BLE_BUFF_FULL; + } + return ret; +} +//----------------------------------------------- +static int client_write_send(void *priv, u8 *data, u16 len) +{ + return client_operation_send(target_handle[cur_dev_cid].write_handle, data, len, ATT_OP_WRITE); +} + +static int client_write_without_respond_send(void *priv, u8 *data, u16 len) +{ + return client_operation_send(target_handle[cur_dev_cid].write_no_respond, data, len, ATT_OP_WRITE_WITHOUT_RESPOND); +} + +static int client_read_value_send(void *priv) +{ + u16 tmp_flag = 0x55A1; + return client_operation_send(target_handle[cur_dev_cid].read_handle, (u8 *)&tmp_flag, 2, ATT_OP_READ); +} + +static int client_read_long_value_send(void *priv) +{ + u16 tmp_flag = 0x55A2; + return client_operation_send(target_handle[cur_dev_cid].read_handle, (u8 *)&tmp_flag, 2, ATT_OP_READ_LONG); +} + +#if EXT_ADV_MODE_EN + +struct __ext_scan_param { + u8 Own_Address_Type; + u8 Scanning_Filter_Policy; + u8 Scanning_PHYs; + u8 Scan_Type; + u16 Scan_Interval; + u16 Scan_Window; +} _GNU_PACKED_; + +struct __ext_scan_enable { + u8 Enable; + u8 Filter_Duplicates; + u16 Duration; + u16 Period; +} _GNU_PACKED_; + +const struct __ext_scan_param ext_scan_param = { + .Own_Address_Type = 0, + .Scanning_Filter_Policy = 0, + .Scanning_PHYs = SCAN_SET_1M_PHY, + .Scan_Type = SET_SCAN_TYPE, + .Scan_Interval = SET_SCAN_INTERVAL, + .Scan_Window = SET_SCAN_WINDOW, +}; + +const struct __ext_scan_enable ext_scan_enable = { + .Enable = 1, + .Filter_Duplicates = 0, + .Duration = 0, + .Period = 0, +}; + +const struct __ext_scan_enable ext_scan_disable = { + .Enable = 0, + .Filter_Duplicates = 0, + .Duration = 0, + .Period = 0, +}; + +#endif /* EXT_ADV_MODE_EN */ + +//扫描数设置 +static void scanning_setup_init(void) +{ + ble_op_set_scan_param(SET_SCAN_TYPE, SET_SCAN_INTERVAL, SET_SCAN_WINDOW); +} + +static int bt_ble_scan_enable(void *priv, u32 en) +{ + ble_state_e next_state, cur_state; + + if (!scan_ctrl_en) { + return APP_BLE_OPERATION_ERROR; + } + + if (en) { + next_state = BLE_ST_SCAN; + } else { + next_state = BLE_ST_IDLE; + } + + cur_state = get_ble_work_state(cur_dev_cid); + switch (cur_state) { + case BLE_ST_SCAN: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + case BLE_ST_CONNECT_FAIL: + case BLE_ST_SEND_CREATE_CONN_CANNEL: + break; + default: + return APP_BLE_OPERATION_ERROR; + break; + } + + if (cur_state == next_state) { + return APP_BLE_NO_ERROR; + } + + + log_info("scan_en:%d\n", en); + set_ble_work_state(cur_dev_cid, next_state); + +#if EXT_ADV_MODE_EN + if (en) { + ble_op_set_ext_scan_param(&ext_scan_param, sizeof(ext_scan_param)); + ble_op_ext_scan_enable(&ext_scan_enable, sizeof(ext_scan_enable)); + } else { + ble_op_ext_scan_enable(&ext_scan_disable, sizeof(ext_scan_disable)); + } +#else + if (en) { + scanning_setup_init(); + } + ble_op_scan_enable2(en, 0); +#endif /* EXT_ADV_MODE_EN */ + + return APP_BLE_NO_ERROR; +} + +static int client_regiest_wakeup_send(void *priv, void *cbk) +{ + /* att_regist_wakeup_send(cbk); */ + return APP_BLE_NO_ERROR; +} + +static int client_regiest_recieve_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_recieve_callback = cbk; + return APP_BLE_NO_ERROR; +} + +static int client_regiest_state_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_ble_state_callback = cbk; + return APP_BLE_NO_ERROR; +} + +//该接口重新配置搜索的配置项 +static int client_init_config(void *priv, const client_conn_cfg_t *cfg) +{ + log_info("client_init_config\n"); + client_config = cfg;//reset config + return APP_BLE_NO_ERROR; +} + +//可配置进入强制搜索方式连接,更加信号强度过滤设备 +static int client_force_search(u8 onoff, s8 rssi) +{ + force_seach_rssi = rssi; + if (force_seach_onoff != onoff) { + + force_seach_onoff = onoff; + //强制搜索前后,关创建监听 + if (get_ble_work_state(cur_dev_cid) == BLE_ST_CREATE_CONN) { + client_create_connection_cannel(); + } + } + return 0; +} + +static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode) +{ + u8 cur_state = get_ble_work_state(cur_dev_cid); + + switch (cur_state) { + case BLE_ST_SCAN: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + case BLE_ST_CONNECT_FAIL: + case BLE_ST_SEND_CREATE_CONN_CANNEL: + break; + default: + return APP_BLE_OPERATION_ERROR; + break; + } + + if (cur_state == BLE_ST_SCAN) { + log_info("stop scan\n"); + bt_ble_scan_enable(0, 0); + } + + //pair mode + if (mode == 1) { + if (conn_pair_info.pair_flag) { + if (conn_pair_info.pair_flag) { + //有配对,跳过搜索,直接创建init_creat + log_info("pair to creat!\n"); + log_info_hexdump(conn_pair_info.peer_address_info, 7); + bt_ble_create_connection(&conn_pair_info.peer_address_info[1], conn_pair_info.peer_address_info[0]); + return 0; + } + + } else { + log_info("no pair to creat!\n"); + return APP_BLE_OPERATION_ERROR; + } + } else { + log_info("addr to creat!\n"); + log_info_hexdump(addr, 7); + bt_ble_create_connection(addr, addr_type); + } + return 0; +} + +static int client_create_cannel_api(void) +{ + if (get_ble_work_state(cur_dev_cid) == BLE_ST_CREATE_CONN) { + client_create_connection_cannel(); + return 0; + } + return 1; +} + +static ble_state_e get_ble_work_state_api(void) +{ + return get_ble_work_state(cur_dev_cid); +} + +static const struct ble_client_operation_t client_operation = { + .scan_enable = bt_ble_scan_enable, + .disconnect = client_disconnect, + .get_buffer_vaild = get_buffer_vaild_len, + .write_data = (void *)client_write_without_respond_send, + .read_do = (void *)client_read_value_send, + .regist_wakeup_send = client_regiest_wakeup_send, + .regist_recieve_cbk = client_regiest_recieve_cbk, + .regist_state_cbk = client_regiest_state_cbk, + .init_config = client_init_config, + .opt_comm_send = client_operation_send, + .set_force_search = client_force_search, + .create_connect = client_create_connect_api, + .create_connect_cannel = client_create_cannel_api, + .get_work_state = get_ble_work_state_api, + .opt_comm_send_ext = client_operation_send_ext, +}; + +struct ble_client_operation_t *ble_get_client_operation_table(void) +{ + return &client_operation; +} + +static void device_bonding_init(void) +{ + int i; + int cfg_bonding = 0; + client_match_cfg_t *cfg; + for (i = 0; i < CLIENT_MATCH_CONN_MAX; i++) { + cfg = client_config->match_dev_cfg[i]; + if (cfg == NULL) { + continue; + } + if (cfg->bonding_flag) { + cfg_bonding = 1; + } + } + if (!cfg_bonding) { + client_clear_bonding_info(); + } +} + +static u8 multi_client_idle_query(void) +{ + return !is_mode_active; +} + +REGISTER_LP_TARGET(multi_client_target) = { + .name = "multi_client", + .is_idle = multi_client_idle_query, +}; + +//模块开关 +void ble_client_module_enable(u8 en) +{ + log_info("mode_en:%d\n", en); + + if (en) { + scan_ctrl_en = 1; + bt_ble_scan_enable(0, 1); + } else { + scan_ctrl_en = 0; + bt_ble_scan_enable(0, 0); + ble_multi_client_disconnect(); + } +} + +void client_profile_init(void) +{ + log_info("%s\n", __FUNCTION__); + + //setup GATT client + gatt_client_init(); + gatt_client_register_packet_handler(client_cbk_packet_handler); + memset(&conn_pair_info, 0, sizeof(struct pair_info_t)); + memset(conn_pair_info_table, 0, sizeof(conn_pair_info_table)); + conn_pair_info.head_tag = BLE_VM_HEAD_TAG; + conn_pair_info.tail_tag = BLE_VM_TAIL_TAG; + +} + + + +void bt_multi_client_init(void) +{ + log_info("%s\n", __FUNCTION__); + + ASSERT(client_config != NULL, "%s\n", "client's config not init\n"); + + cur_dev_cid = 0; + memset(&ble_work_state, BLE_ST_INIT_OK, SUPPORT_MAX_CLIENT); + memset(&client_con_handle, 0, SUPPORT_MAX_CLIENT << 1); + + set_ble_work_state(cur_dev_cid, BLE_ST_INIT_OK); + conn_pair_vm_do(&conn_pair_info, 0); + device_bonding_init(); + ble_client_module_enable(1); + +#if SHOW_RX_DATA_RATE + client_timer_start(); +#endif /* SHOW_RX_DATA_RATE */ +} + +void bt_multi_client_exit(void) +{ + log_info("%s\n", __FUNCTION__); + ble_client_module_enable(0); +} + +//主机请求更新连接参数 +void client_send_conn_param_update(void) +{ + struct conn_update_param_t *param = (void *)&connection_param_table[send_param_index];//for test + log_info("client update param:-%d-%d-%d-%d-\n", param->interval_min, param->interval_max, param->latency, param->timeout); + if (client_con_handle[cur_dev_cid]) { + ble_op_conn_param_update(client_con_handle[cur_dev_cid], param); + } +} + +/* static void test_send_conn_update(void) */ +/* { */ +/* client_send_conn_param_update(); */ +/* send_param_index++; */ +/* send_param_index &= 3; */ +/* sys_timeout_add(0,test_send_conn_update,10000); */ +/* } */ + +//切换已连接多机 +int le_multi_client_switch_connect_cid(u8 cid) +{ + if (cid < SUPPORT_MAX_CLIENT && client_con_handle[cid]) { + cur_dev_cid = cid; + return 0; + } else { + log_info("cid not exist!!!\n"); + return -1; + } +} + +//---------------------------------------------------------------------------------- + + + +#endif + + diff --git a/apps/common/third_party_profile/jieli/multi_demo/le_multi_common.c b/apps/common/third_party_profile/jieli/multi_demo/le_multi_common.c new file mode 100644 index 0000000..4b33302 --- /dev/null +++ b/apps/common/third_party_profile/jieli/multi_demo/le_multi_common.c @@ -0,0 +1,414 @@ +/********************************************************************************************* + * Filename : le_server_module.c + + * Description : + + * Author : + + * Email : zh-jieli.com + + * Last modifiled : 2017-01-17 11:14 + + * Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved. +*********************************************************************************************/ + +// ***************************************************************************** +/* EXAMPLE_START(le_counter): LE Peripheral - Heartbeat Counter over GATT + * + * @text All newer operating systems provide GATT Client functionality. + * The LE Counter examples demonstrates how to specify a minimal GATT Database + * with a custom GATT Service and a custom Characteristic that sends periodic + * notifications. + */ +// ***************************************************************************** +#include "system/app_core.h" +#include "system/includes.h" + +#include "app_config.h" +#include "app_action.h" + +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "user_cfg.h" +#include "vm.h" +#include "btcontroller_modules.h" +#include "bt_common.h" +#include "3th_profile_api.h" + +#include "le_common.h" + +#include "rcsp_bluetooth.h" +#include "JL_rcsp_api.h" +#include "custom_cfg.h" +#include "btstack/btstack_event.h" +#include "le_multi_common.h" + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_MULTI) + +#if LE_DEBUG_PRINT_EN +/* extern void printf_buf(u8 *buf, u32 len); */ +//#define log_info r_printf +#define log_info(x, ...) printf("[LE-MUL-COMM]" x " ", ## __VA_ARGS__) +#define log_info_hexdump put_buf + +#else +#define log_info(...) +#define log_info_hexdump(...) +#endif + +//---------------------------------------------------------------------------------------- +#define MULTI_ATT_MTU_SIZE (512) //ATT MTU的值 + +//ATT发送的包长, note: 20 <= need >= MTU +#define MULTI_ATT_LOCAL_PAYLOAD_SIZE (MULTI_ATT_MTU_SIZE) // +//ATT缓存的buffer大小, note: need >= 20,可修改 +#define MULTI_ATT_SEND_CBUF_SIZE (512*3) // + +//共配置的RAM +#define MULTI_ATT_RAM_BUFSIZE (ATT_CTRL_BLOCK_SIZE + MULTI_ATT_LOCAL_PAYLOAD_SIZE + MULTI_ATT_SEND_CBUF_SIZE) //note: +static u8 multi_att_ram_buffer[MULTI_ATT_RAM_BUFSIZE] __attribute__((aligned(4))); + +u16 server_con_handle[SUPPORT_MAX_SERVER]; +u16 client_con_handle[SUPPORT_MAX_CLIENT]; + +extern const int config_btctler_le_hw_nums; +extern const int config_btctler_le_rx_nums; +extern const int config_btctler_le_acl_total_nums; +extern const int config_le_sm_support_enable; +extern const int config_btctler_le_master_multilink; + +extern void sm_set_master_request_pair(int enable); +//---------------------------------------------------------------------------------------- +s8 mul_get_dev_index(u16 handle, u8 role) +{ + s8 i; + u16 *group_handle; + u8 count; + + if (!role) { + group_handle = server_con_handle; + count = SUPPORT_MAX_SERVER; + } else { + group_handle = client_con_handle; + count = SUPPORT_MAX_CLIENT; + } + + for (i = 0; i < count; i++) { + if (handle == group_handle[i]) { + return i; + } + } + return -1; +} + +s8 mul_get_idle_dev_index(u8 role) +{ + s8 i; + u16 *group_handle; + u8 count; + + if (!role) { + group_handle = server_con_handle; + count = SUPPORT_MAX_SERVER; + } else { + group_handle = client_con_handle; + count = SUPPORT_MAX_CLIENT; + } + + for (i = 0; i < count; i++) { + if (0 == group_handle[i]) { + return i; + } + } + return -1; +} + + +s8 mul_del_dev_index(u16 handle, u8 role) +{ + s8 i; + u16 *group_handle; + u8 count; + + if (!role) { + group_handle = server_con_handle; + count = SUPPORT_MAX_SERVER; + } else { + group_handle = client_con_handle; + count = SUPPORT_MAX_CLIENT; + } + + + for (i = 0; i < count; i++) { + if (handle == group_handle[i]) { + group_handle[i] = 0; + return i; + } + } + return -1; +} + +bool mul_dev_have_connected(u8 role) +{ + s8 i; + u16 *group_handle; + u8 count; + + if (!role) { + group_handle = server_con_handle; + count = SUPPORT_MAX_SERVER; + } else { + group_handle = client_con_handle; + count = SUPPORT_MAX_CLIENT; + } + + for (i = 0; i < count; i++) { + if (group_handle[i]) { + return true; + } + } + return false; +} + +u16 mul_dev_get_conn_handle(u8 index, u8 role) +{ + u16 *group_handle; + u8 count; + + if (!role) { + group_handle = server_con_handle; + count = SUPPORT_MAX_SERVER; + } else { + group_handle = client_con_handle; + count = SUPPORT_MAX_CLIENT; + } + + if (index < count) { + return group_handle[index]; + } else { + return 0; + } +} + + +void cbk_sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + sm_just_event_t *event = (void *)packet; + u32 tmp32; + log_info("%s\n", __FUNCTION__); + + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + case SM_EVENT_JUST_WORKS_REQUEST: + sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); + log_info("Just Works Confirmed.\n"); + break; + case SM_EVENT_PASSKEY_DISPLAY_NUMBER: + log_info_hexdump(packet, size); + memcpy(&tmp32, event->data, 4); + log_info("Passkey display: %06u.\n", tmp32); + break; + } + break; + } +} + +/* LISTING_START(packetHandler): Packet Handler */ +static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ +#if SUPPORT_MAX_SERVER + trans_cbk_packet_handler(packet_type, channel, packet, size); +#endif + +#if SUPPORT_MAX_CLIENT + client_cbk_packet_handler(packet_type, channel, packet, size); +#endif +} + +#define PASSKEY_ENTER_ENABLE 0 //输入passkey使能,可修改passkey +//重设passkey回调函数,在这里可以重新设置passkey +//passkey为6个数字组成,十万位、万位。。。。个位 各表示一个数字 高位不够为0 +static void reset_passkey_cb(u32 *key) +{ +#if 1 + u32 newkey = rand32();//获取随机数 + + newkey &= 0xfffff; + if (newkey > 999999) { + newkey = newkey - 999999; //不能大于999999 + } + *key = newkey; //小于或等于六位数 + log_info("set new_key= %06u\n", *key); +#else + *key = 123456; //for debug +#endif +} + +void ble_sm_setup_init(io_capability_t io_type, u8 auth_req, uint8_t min_key_size, u8 security_en) +{ + //setup SM: Display only + log_info("%s\n", __FUNCTION__); + sm_init(); + sm_set_io_capabilities(io_type); + sm_set_authentication_requirements(auth_req); + sm_set_encryption_key_size_range(min_key_size, 16); + sm_set_request_security(security_en); + sm_set_master_request_pair(security_en); + sm_event_callback_set(&cbk_sm_packet_handler); + + if (io_type == IO_CAPABILITY_DISPLAY_ONLY) { + reset_PK_cb_register(reset_passkey_cb); + } +} + +void ble_profile_init(void) +{ + log_info("%s\n", __FUNCTION__); + +#if SUPPORT_MAX_SERVER && SUPPORT_MAX_CLIENT + ble_stack_gatt_role(2); +#elif SUPPORT_MAX_CLIENT + ble_stack_gatt_role(1); +#else + ble_stack_gatt_role(0); +#endif + + ble_vendor_set_default_att_mtu(MULTI_ATT_MTU_SIZE); + + if (config_le_sm_support_enable) { + le_device_db_init(); +#if PASSKEY_ENTER_ENABLE + ble_sm_setup_init(IO_CAPABILITY_DISPLAY_ONLY, SM_AUTHREQ_MITM_PROTECTION, 7, TCFG_BLE_SECURITY_EN); +#else + ble_sm_setup_init(IO_CAPABILITY_NO_INPUT_NO_OUTPUT, SM_AUTHREQ_BONDING, 7, TCFG_BLE_SECURITY_EN); +#endif + } + +#if SUPPORT_MAX_SERVER + server_profile_init(); +#endif + +#if SUPPORT_MAX_CLIENT + client_profile_init(); +#endif + + // register for HCI events + hci_event_callback_set(&cbk_packet_handler); + /* ble_l2cap_register_packet_handler(packet_cbk); */ + /* sm_event_packet_handler_register(packet_cbk); */ + le_l2cap_register_packet_handler(&cbk_packet_handler); + + ble_op_multi_att_send_init(multi_att_ram_buffer, MULTI_ATT_SEND_CBUF_SIZE, MULTI_ATT_LOCAL_PAYLOAD_SIZE); +} + +//统一接口,关闭模块 +void ble_module_enable(u8 en) +{ + log_info("mode_en:%d\n", en); + +#if SUPPORT_MAX_SERVER + ble_trans_module_enable(en); +#endif + +#if SUPPORT_MAX_CLIENT + ble_client_module_enable(en); +#endif + +} + +void ble_app_disconnect(void) +{ +#if SUPPORT_MAX_SERVER + ble_multi_trans_disconnect(); +#endif + +#if SUPPORT_MAX_CLIENT + ble_multi_client_disconnect(); +#endif + + +} + +//--------------------------------------------- +void bt_ble_init(void) +{ + int error_reset = 0; + log_info("%s,%d\n", __FUNCTION__, __LINE__); + log_info("ble_file: %s", __FILE__); + + //确认配置是否ok + if (config_le_gatt_server_num + config_le_gatt_client_num > config_btctler_le_hw_nums) { + log_info("config_btctler_le_hw_nums not enough!!!\n"); + error_reset = 1; + } + + if (config_btctler_le_rx_nums < config_btctler_le_hw_nums * 3) { + log_info("config_btctler_le_rx_nums not enough!!!\n"); + error_reset = 1; + } + + if (config_btctler_le_acl_total_nums < config_btctler_le_hw_nums * 3) { + log_info("config_btctler_le_acl_total_nums not enough!!!\n"); + error_reset = 1; + } + + if (config_le_hci_connection_num > config_btctler_le_hw_nums) { + log_info("config_btctler_le_hw_nums not enough!!!\n"); + error_reset = 1; + } + + if (config_le_hci_connection_num && (config_le_gatt_server_num + config_le_gatt_client_num) > config_le_hci_connection_num) { + log_info("config_le_hci_connection_num not enough!!!\n"); + error_reset = 1; + } + + if (config_le_hci_connection_num && att_send_check_multi_dev(config_le_gatt_server_num, config_le_gatt_client_num)) { + log_info("no support more device!!!\n"); + error_reset = 1; + } + + if (SUPPORT_MAX_SERVER > config_le_gatt_server_num) { + log_info("config_le_gatt_server_num not enough!!!\n"); + error_reset = 1; + } + + if (SUPPORT_MAX_CLIENT > config_le_gatt_client_num) { + log_info("config_le_gatt_client_num not enough!!!\n"); + error_reset = 1; + } + + if (error_reset) { + printf("======error config!!!\n"); + ASSERT(0); + while (1); + } + +#if SUPPORT_MAX_SERVER + bt_multi_trans_init(); +#endif + +#if SUPPORT_MAX_CLIENT + bt_multi_client_init(); + if (config_btctler_le_master_multilink) { + //ble_vendor_set_hold_prio(0, 1); + } +#endif +} + +void bt_ble_exit(void) +{ + log_info("%s\n", __FUNCTION__); + +#if SUPPORT_MAX_SERVER + bt_multi_trans_exit(); +#endif + +#if SUPPORT_MAX_CLIENT + bt_multi_client_exit(); +#endif +} + +#endif + + diff --git a/apps/common/third_party_profile/jieli/multi_demo/le_multi_common.h b/apps/common/third_party_profile/jieli/multi_demo/le_multi_common.h new file mode 100644 index 0000000..8d2810a --- /dev/null +++ b/apps/common/third_party_profile/jieli/multi_demo/le_multi_common.h @@ -0,0 +1,49 @@ +// binary representation +// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) + +#ifndef _LE_MUTIL_COMMON_H +#define _LE_MUTIL_COMMON_H + +#include +#include "app_config.h" + +#if TRANS_MULTI_BLE_EN + +#define MULTI_ROLE_CLIENT 1 +#define MULTI_ROLE_SERVER 0 + +#define MULTI_ROLE_MASTER 1 +#define MULTI_ROLE_SLAVE 0 + +//--------------------------------- +#define SUPPORT_MAX_SERVER TRANS_MULTI_BLE_SLAVE_NUMS +#define SUPPORT_MAX_CLIENT TRANS_MULTI_BLE_MASTER_NUMS +//--------------------------------- +//---------------------------------------------------------------------------------------- +extern u16 server_con_handle[]; +extern u16 client_con_handle[]; + + +s8 mul_get_dev_index(u16 handle, u8 role); +s8 mul_get_idle_dev_index(u8 role); +s8 mul_del_dev_index(u16 handle, u8 role); +bool mul_dev_have_connected(u8 role); +u16 mul_dev_get_conn_handle(u8 index, u8 role); + +void bt_multi_trans_init(void); +void bt_multi_trans_exit(void); +void bt_multi_client_init(void); +void bt_multi_client_exit(void); +void trans_cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); +void client_cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); + +void client_profile_init(void); +void server_profile_init(void); +void ble_trans_module_enable(u8 en); +void ble_client_module_enable(u8 en); +void ble_multi_trans_disconnect(void); +void ble_multi_client_disconnect(void); + +#endif + +#endif diff --git a/apps/common/third_party_profile/jieli/multi_demo/le_multi_trans.c b/apps/common/third_party_profile/jieli/multi_demo/le_multi_trans.c new file mode 100644 index 0000000..88c076d --- /dev/null +++ b/apps/common/third_party_profile/jieli/multi_demo/le_multi_trans.c @@ -0,0 +1,1346 @@ +/********************************************************************************************* + * Filename : le_server_module.c + + * Description : + + * Author : + + * Email : zh-jieli.com + + * Last modifiled : 2017-01-17 11:14 + + * Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved. +*********************************************************************************************/ + +// ***************************************************************************** +/* EXAMPLE_START(le_counter): LE Peripheral - Heartbeat Counter over GATT + * + * @text All newer operating systems provide GATT Client functionality. + * The LE Counter examples demonstrates how to specify a minimal GATT Database + * with a custom GATT Service and a custom Characteristic that sends periodic + * notifications. + */ +// ***************************************************************************** +#include "system/app_core.h" +#include "system/includes.h" + +#include "app_config.h" +#include "app_action.h" + +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "user_cfg.h" +#include "vm.h" +#include "btcontroller_modules.h" +#include "bt_common.h" +#include "3th_profile_api.h" + +#include "le_common.h" + +#include "rcsp_bluetooth.h" +#include "JL_rcsp_api.h" +#include "custom_cfg.h" +#include "btstack/btstack_event.h" +#include "le_multi_common.h" + +#define MUTIL_ROLE_IS_SERVER 1 +#include "le_multi_trans.h" + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_MULTI && SUPPORT_MAX_SERVER) +//TRANS ANCS +#define TRANS_ANCS_EN 0 //for ios ancs function + +#define TEST_SEND_DATA_RATE 0 //测试上行发送数据 +#define TEST_SEND_HANDLE_VAL ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE +/* #define TEST_SEND_HANDLE_VAL ATT_CHARACTERISTIC_ae05_01_VALUE_HANDLE */ +#define EXT_ADV_MODE_EN 0 +#define TEST_AUDIO_DATA_UPLOAD 0 //测试文件上传 + +#if LE_DEBUG_PRINT_EN +/* extern void printf_buf(u8 *buf, u32 len); */ +//#define log_info y_printf +#define log_info(x, ...) printf("[LE-MUL-TRANS]" x " ", ## __VA_ARGS__) +#define log_info_hexdump put_buf + +#else +#define log_info(...) +#define log_info_hexdump(...) +#endif + +//---------------------------------------------------------------------------------------- + +#if TEST_SEND_DATA_RATE +static u32 test_data_count; +static u32 server_timer_handle = 0; +static u8 test_data_start; +#endif + +//--------------- +// 广播周期 (unit:0.625ms) +#define ADV_INTERVAL_MIN (160*1) +//--------------- +#define HOLD_LATENCY_CNT_MIN (3) //(0~0xffff) +#define HOLD_LATENCY_CNT_MAX (15) //(0~0xffff) +#define HOLD_LATENCY_CNT_ALL (0xffff) +//--------------- +//加密设置 +/* static const uint8_t sm_min_key_size = 7; */ + +//连接参数更新请求设置 +//是否使能参数请求更新,0--disable, 1--enable +static const uint8_t connection_update_enable = 1; ///0--disable, 1--enable +//当前请求的参数表index +static uint8_t connection_update_cnt[SUPPORT_MAX_SERVER]; // + +//参数表 +static const struct conn_update_param_t connection_param_table[] = { + {16, 24, 10, 600},//11 + {12, 28, 10, 600},//3.7 + {8, 20, 10, 600}, + /* {12, 28, 4, 600},//3.7 */ + /* {12, 24, 30, 600},//3.05 */ +}; + +//共可用的参数组数 +#define CONN_PARAM_TABLE_CNT (sizeof(connection_param_table)/sizeof(struct conn_update_param_t)) + +#define EIR_TAG_STRING 0xd6, 0x05, 0x08, 0x00, 'J', 'L', 'A', 'I', 'S', 'D','K' +static const char user_tag_string[] = {EIR_TAG_STRING}; + +static u8 adv_data_len; +static u8 adv_data[ADV_RSP_PACKET_MAX];//max is 31 +static u8 scan_rsp_data_len; +static u8 scan_rsp_data[ADV_RSP_PACKET_MAX];//max is 31 + +static char gap_device_name[BT_NAME_LEN_MAX] = "jl_ble_test"; +static u8 gap_device_name_len = 0; //名字长度,不包含结束符 +static u8 ble_work_state[SUPPORT_MAX_SERVER]; //ble 状态变化 +static u8 adv_ctrl_en; //广播控制 +static u8 test_read_write_buf[4]; + +static void (*app_recieve_callback)(void *priv, void *buf, u16 len) = NULL; +static void (*app_ble_state_callback)(void *priv, ble_state_e state) = NULL; +static void (*ble_resume_send_wakeup)(void) = NULL; +static u32 channel_priv; + +static s8 cur_dev_cid; // 当前操作的多机id +//------------------------------------------------------ +static int app_send_user_data_check(u16 len); +static int app_send_user_data_do(void *priv, u8 *data, u16 len); +static int app_send_user_data(u16 conn_handle, u16 handle, u8 *data, u16 len, u8 handle_type); +//广播参数设置 +static void advertisements_setup_init(); +static int set_adv_enable(void *priv, u32 en); +static int get_buffer_vaild_len(void *priv); +extern const char *bt_get_local_name(); +extern void clr_wdt(void); +extern void sys_auto_shut_down_disable(void); +extern void sys_auto_shut_down_enable(void); +extern u8 get_total_connect_dev(void); +int ble_enable_new_dev_adv(void); +//------------------------------------------------------ +//for ANCS +#if TRANS_ANCS_EN +#define ANCS_SUBEVENT_CLIENT_NOTIFICATION (0xF1) +void ancs_client_init(void); +void ancs_client_register_callback(btstack_packet_handler_t callback); +const char *ancs_client_attribute_name_for_id(int id); +void ancs_set_notification_buffer(u8 *buffer, u16 buffer_size); + +//ancs info buffer +#define ANCS_INFO_BUFFER_SIZE (1024) +static u8 ancs_info_buffer[ANCS_INFO_BUFFER_SIZE]; +#endif + +//------------------------------------------------------ +#if TEST_AUDIO_DATA_UPLOAD +static const u8 test_audio_data_file[1024] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9 +}; + +#define AUDIO_ONE_PACKET_LEN (128) +static void test_send_audio_data(int init_flag) +{ + static u32 send_pt = 0; + static u32 start_flag = 0; + + if (!server_con_handle[cur_dev_cid]) { + return; + } + + if (init_flag) { + log_info("audio send init\n"); + send_pt = 0; + start_flag = 1; + } + + if (!start_flag) { + return; + } + + u32 file_size = sizeof(test_audio_data_file); + u8 *file_ptr = test_audio_data_file; + + if (send_pt >= file_size) { + log_info("audio send Complete\n"); + start_flag = 0; + return; + } + + u32 send_len = file_size - send_pt; + if (send_len > AUDIO_ONE_PACKET_LEN) { + send_len = AUDIO_ONE_PACKET_LEN; + } + + while (1) { + if (app_send_user_data_check(send_len)) { + log_info("audio send %08x\n", send_pt); + if (app_send_user_data(server_con_handle[cur_dev_cid], ATT_CHARACTERISTIC_ae3c_01_VALUE_HANDLE, &file_ptr[send_pt], send_len, ATT_OP_AUTO_READ_CCC)) { + log_info("audio send fail!\n"); + break; + } else { + send_pt += send_len; + } + } else { + break; + } + } +} +#endif + + +static void send_request_connect_parameter(u8 table_index, u8 cid) +{ + struct conn_update_param_t *param = (void *)&connection_param_table[table_index];//static ram + + if (server_con_handle[cid]) { + log_info("update_request:%04x----%d-%d-%d-%d-\n", server_con_handle[cid], param->interval_min, param->interval_max, param->latency, param->timeout); + ble_op_conn_param_request(server_con_handle[cid], param); + } +} + +static void check_connetion_updata_deal(u8 cid) +{ + if (connection_update_enable) { + if (connection_update_cnt[cid] < CONN_PARAM_TABLE_CNT) { + send_request_connect_parameter(connection_update_cnt[cid], cid); + } + } +} + +static void connection_update_complete_success(u16 conn_handle, u8 *packet) +{ + int conn_interval, conn_latency, conn_timeout; + + conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet); + conn_latency = hci_subevent_le_connection_update_complete_get_conn_latency(packet); + conn_timeout = hci_subevent_le_connection_update_complete_get_supervision_timeout(packet); + + log_info("conn_handle = %04x\n", conn_handle); + log_info("conn_interval = %d\n", conn_interval); + log_info("conn_latency = %d\n", conn_latency); + log_info("conn_timeout = %d\n", conn_timeout); +} + + +static void set_ble_work_state(u8 cid, ble_state_e state) +{ + if (state != ble_work_state[cid]) { + log_info("ble_work_st[%d]:%x->%x\n", cid, ble_work_state[cid], state); + ble_work_state[cid] = state; + if (app_ble_state_callback) { + app_ble_state_callback((void *)channel_priv, state); + } + } +} + +static ble_state_e get_ble_work_state(u8 cid) +{ + return ble_work_state[cid]; +} + +#if TEST_SEND_DATA_RATE +static void server_timer_handler(void) +{ + if (!server_con_handle[cur_dev_cid]) { + test_data_count = 0; + test_data_start = 0; + return; + } + + log_info("peer_rssi = %d\n", ble_vendor_get_peer_rssi(server_con_handle[cur_dev_cid])); + + if (test_data_count) { + log_info("\n%d bytes send: %d.%02d KB/s \n", test_data_count, test_data_count / 1000, test_data_count % 1000); + test_data_count = 0; + } +} + +static void server_timer_start(void) +{ + if (server_timer_handle) { + return; + } + + server_timer_handle = sys_timer_add(NULL, server_timer_handler, 1000); +} + +static void server_timer_stop(void) +{ + if (server_timer_handle) { + sys_timeout_del(server_timer_handle); + server_timer_handle = 0; + } +} + +void test_data_send_packet(void) +{ + u32 vaild_len = get_buffer_vaild_len(0);//获取发送buffer可写入的数据 + if (!test_data_start) { + return; + } + + if (vaild_len) { + if (!app_send_user_data(server_con_handle[cur_dev_cid], TEST_SEND_HANDLE_VAL, (void *)&test_data_count, vaild_len, ATT_OP_AUTO_READ_CCC)) { + test_data_count += vaild_len; + } + } + clr_wdt(); +} +#endif + + +static void can_send_now_wakeup(void) +{ + /* putchar('E'); */ + if (ble_resume_send_wakeup) { + ble_resume_send_wakeup(); + } + +#if TEST_SEND_DATA_RATE + test_data_send_packet(); +#endif + +#if TEST_AUDIO_DATA_UPLOAD + test_send_audio_data(0); +#endif + +} + +static void ble_auto_shut_down_enable(u8 enable) +{ +#if TCFG_AUTO_SHUT_DOWN_TIME + if (enable) { + if (get_total_connect_dev() == 0) { //已经没有设备连接 + sys_auto_shut_down_enable(); + } + } else { + sys_auto_shut_down_disable(); + } +#endif +} + +static const char *const phy_result[] = { + "None", + "1M", + "2M", + "Coded", +}; + +static void set_connection_data_length(u16 tx_octets, u16 tx_time) +{ + if (server_con_handle[cur_dev_cid]) { + ble_op_set_data_length(server_con_handle[cur_dev_cid], tx_octets, tx_time); + } +} + +static void set_connection_data_phy(u8 tx_phy, u8 rx_phy) +{ + if (0 == server_con_handle[cur_dev_cid]) { + return; + } + + u8 all_phys = 0; + u16 phy_options = CONN_SET_PHY_OPTIONS_S8; + ble_op_set_ext_phy(server_con_handle[cur_dev_cid], all_phys, tx_phy, rx_phy, phy_options); +} + +static void server_profile_start(u16 conn_handle) +{ +#if BT_FOR_APP_EN + set_app_connect_type(TYPE_BLE); +#endif + + set_ble_work_state(cur_dev_cid, BLE_ST_CONNECT); + ble_auto_shut_down_enable(0); + + /* set_connection_data_phy(CONN_SET_CODED_PHY, CONN_SET_CODED_PHY); */ +} + +_WEAK_ +u8 ble_update_get_ready_jump_flag(void) +{ + return 0; +} + +//尝试开新设备广播 +int ble_enable_new_dev_adv(void) +{ + log_info("%s\n", __FUNCTION__); + + if (!server_con_handle[cur_dev_cid]) { + log_info("dev_doing\n"); + return -1; + } + + s8 tmp_cid = mul_get_idle_dev_index(MULTI_ROLE_SERVER); + if (tmp_cid < 0) { + log_info("no idle dev to do!!!\n"); + return -2; + } + + log_info("new_dev_adv\n"); + cur_dev_cid = tmp_cid; + set_ble_work_state(cur_dev_cid, BLE_ST_IDLE); + bt_ble_adv_enable(1); + return 0; +} + +/* + * @section Packet Handler + * + * @text The packet handler is used to: + * - stop the counter after a disconnect + * - send a notification when the requested ATT_EVENT_CAN_SEND_NOW is received + */ +/* LISTING_START(packetHandler): Packet Handler */ +void trans_cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + int mtu; + u32 tmp; + u8 status; + const char *attribute_name; + + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + + /* case DAEMON_EVENT_HCI_PACKET_SENT: */ + /* break; */ + case ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE: + log_info("ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE\n"); + case ATT_EVENT_CAN_SEND_NOW: + can_send_now_wakeup(); + break; + + case HCI_EVENT_LE_META: + switch (hci_event_le_meta_get_subevent_code(packet)) { + case HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE: { + status = hci_subevent_le_enhanced_connection_complete_get_status(packet); + if (status) { + log_info("LE_SLAVE CONNECTION FAIL!!! %0x\n", status); + set_ble_work_state(cur_dev_cid, BLE_ST_DISCONN); + break; + } + + u16 tmp_handle1 = hci_subevent_le_enhanced_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE : %0x\n", tmp_handle1); + + s8 tmp_dev_cid1 = mul_get_idle_dev_index(MULTI_ROLE_SERVER); + if (tmp_dev_cid1 < 0) { + log_info("dev_cid full!!!\n"); + ble_op_disconnect(tmp_handle1); + break; + } + + cur_dev_cid = tmp_dev_cid1; + server_con_handle[cur_dev_cid] = tmp_handle1; + connection_update_cnt[cur_dev_cid] = 0; + ble_op_multi_att_send_conn_handle(server_con_handle[cur_dev_cid], cur_dev_cid, MULTI_ROLE_SERVER); + + log_info("conn_interval = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_interval(packet)); + log_info("conn_latency = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_latency(packet)); + log_info("conn_timeout = %d\n", hci_subevent_le_enhanced_connection_complete_get_supervision_timeout(packet)); + server_profile_start(server_con_handle[cur_dev_cid]); + } + break; + + case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: { + if (0 == hci_subevent_le_connection_complete_get_role(packet)) { + //connect is master + break; + } + + if (packet[3]) { + log_info("LE_SLAVE CONNECTION FAIL!!! %0x\n", packet[3]); + set_ble_work_state(cur_dev_cid, BLE_ST_DISCONN); + bt_ble_adv_enable(1); + break; + } + + u16 tmp_handle = hci_subevent_le_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_CONNECTION_COMPLETE: %0x\n", tmp_handle); + + s8 tmp_dev_cid = mul_get_idle_dev_index(MULTI_ROLE_SERVER); + + if (tmp_dev_cid < 0) { + log_info("dev_cid full!!!\n"); + ble_op_disconnect(tmp_handle); + break; + } + + cur_dev_cid = tmp_dev_cid; + server_con_handle[cur_dev_cid] = tmp_handle; + connection_update_cnt[cur_dev_cid] = 0; + ble_op_multi_att_send_conn_handle(server_con_handle[cur_dev_cid], cur_dev_cid, MULTI_ROLE_SERVER); + + connection_update_complete_success(tmp_handle, packet + 8); + server_profile_start(server_con_handle[cur_dev_cid]); + +#if RCSP_BTMATE_EN +#if (defined(BT_CONNECTION_VERIFY) && (0 == BT_CONNECTION_VERIFY)) + JL_rcsp_auth_reset(); +#endif + //rcsp_dev_select(RCSP_BLE); + rcsp_init(); +#endif + log_info("ble remote rssi= %d\n", ble_vendor_get_peer_rssi(server_con_handle[cur_dev_cid])); + } + break; + + case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: { + u16 tmp_handle = little_endian_read_16(packet, 4); + if (mul_get_dev_index(tmp_handle, MULTI_ROLE_SERVER) >= 0) { + connection_update_complete_success(tmp_handle, packet); + } + } + break; + + case HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE: + log_info("APP HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE\n"); + /* set_connection_data_phy(CONN_SET_CODED_PHY, CONN_SET_CODED_PHY); */ + break; + + case HCI_SUBEVENT_LE_PHY_UPDATE_COMPLETE: + log_info("APP HCI_SUBEVENT_LE_PHY_UPDATE %s\n", hci_event_le_meta_get_phy_update_complete_status(packet) ? "Fail" : "Succ"); + log_info("Tx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_tx_phy(packet)]); + log_info("Rx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_rx_phy(packet)]); + break; + } + break; + + case HCI_EVENT_DISCONNECTION_COMPLETE: + u16 tmp_handle = little_endian_read_16(packet, 3); + s8 tmp_index = mul_get_dev_index(tmp_handle, MULTI_ROLE_SERVER); + if (tmp_index < 0) { + log_info("unknown_handle:%04x\n", tmp_handle); + break; + } + + log_info("HCI_EVENT_DISCONNECTION_COMPLETE: %0x\n", packet[5]); + server_con_handle[tmp_index] = 0; + set_ble_work_state(tmp_index, BLE_ST_DISCONN); + ble_op_multi_att_send_conn_handle(0, tmp_index, MULTI_ROLE_SERVER); + + if (0 == server_con_handle[cur_dev_cid]) { + //判断当前设备是否正在ADV + if (BLE_ST_ADV == get_ble_work_state(cur_dev_cid)) { + //直接退出,不做别的操作 + break; + } + } + + +#if RCSP_BTMATE_EN + rcsp_exit(); +#endif + + //配设备开scan + cur_dev_cid = tmp_index; + + if (!ble_update_get_ready_jump_flag()) { + bt_ble_adv_enable(1); + } + +#if BT_FOR_APP_EN + set_app_connect_type(TYPE_NULL); +#endif + ble_auto_shut_down_enable(1); + break; + + case ATT_EVENT_MTU_EXCHANGE_COMPLETE: { + u16 tmp_handle = little_endian_read_16(packet, 2); + s8 tmp_cid = mul_get_dev_index(tmp_handle, MULTI_ROLE_SERVER); + if (tmp_cid != -1) { + mtu = att_event_mtu_exchange_complete_get_MTU(packet) - 3; + log_info("ATT MTU = %u\n", mtu); + ble_op_multi_att_set_send_mtu(tmp_handle, mtu); + /* set_connection_data_length(251, 2120); */ + } + } + break; + + case HCI_EVENT_VENDOR_REMOTE_TEST: + log_info("--- HCI_EVENT_VENDOR_REMOTE_TEST\n"); + break; + + case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE: { + u16 tmp_handle = little_endian_read_16(packet, 2); + s8 tmp_cid = mul_get_dev_index(tmp_handle, MULTI_ROLE_SERVER); + if (tmp_cid != -1) { + tmp = little_endian_read_16(packet, 4); + log_info("-update_rsp:%04x, %02x\n", tmp_handle, tmp); + if (tmp) { + connection_update_cnt[tmp_cid]++; + log_info("remoter reject!!!\n"); + check_connetion_updata_deal(tmp_cid); + } else { + connection_update_cnt[tmp_cid] = CONN_PARAM_TABLE_CNT; + } + + } + } + break; + + case HCI_EVENT_ENCRYPTION_CHANGE: { + u16 tmp_handle = little_endian_read_16(packet, 3); + s8 tmp_cid = mul_get_dev_index(tmp_handle, MULTI_ROLE_SERVER); + if (tmp_cid != -1) { + log_info("HCI_EVENT_ENCRYPTION_CHANGE= %d\n", packet[2]); + } + } + break; + +#if TRANS_ANCS_EN + case HCI_EVENT_ANCS_META: + switch (hci_event_ancs_meta_get_subevent_code(packet)) { + case ANCS_SUBEVENT_CLIENT_NOTIFICATION: + printf("ANCS_SUBEVENT_CLIENT_NOTIFICATION \n"); + attribute_name = ancs_client_attribute_name_for_id(ancs_subevent_client_notification_get_attribute_id(packet)); + if (!attribute_name) { + printf("ancs unknow attribute_id :%d \n", ancs_subevent_client_notification_get_attribute_id(packet)); + break; + } else { + u16 attribute_strlen = little_endian_read_16(packet, 7); + u8 *attribute_str = (void *)little_endian_read_32(packet, 9); + printf("Notification: %s - %s \n", attribute_name, attribute_str); + } + break; + default: + break; + } + + break; +#endif + + } + break; + } +} + + +/* LISTING_END */ + +/* + * @section ATT Read + * + * @text The ATT Server handles all reads to constant data. For dynamic data like the custom characteristic, the registered + * att_read_callback is called. To handle long characteristics and long reads, the att_read_callback is first called + * with buffer == NULL, to request the total value length. Then it will be called again requesting a chunk of the value. + * See Listing attRead. + */ + +/* LISTING_START(attRead): ATT Read */ + +// ATT Client Read Callback for Dynamic Data +// - if buffer == NULL, don't copy data, just return size of value +// - if buffer != NULL, copy data and return number bytes copied +// @param offset defines start of attribute value +static uint16_t att_read_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t offset, uint8_t *buffer, uint16_t buffer_size) +{ + + uint16_t att_value_len = 0; + uint16_t handle = att_handle; + + log_info("read_callback,conn_handle =%04x, handle=%04x,buffer=%08x\n", connection_handle, handle, (u32)buffer); + + switch (handle) { + case ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE: + att_value_len = gap_device_name_len; + + if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) { + break; + } + + if (buffer) { + memcpy(buffer, &gap_device_name[offset], buffer_size); + att_value_len = buffer_size; + log_info("\n------read gap_name: %s \n", gap_device_name); + } + break; + + case ATT_CHARACTERISTIC_ae10_01_VALUE_HANDLE: + att_value_len = sizeof(test_read_write_buf); + if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) { + break; + } + + if (buffer) { + memcpy(buffer, &test_read_write_buf[offset], buffer_size); + att_value_len = buffer_size; + } + break; + + case ATT_CHARACTERISTIC_ae04_01_CLIENT_CONFIGURATION_HANDLE: + case ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE: + case ATT_CHARACTERISTIC_ae05_01_CLIENT_CONFIGURATION_HANDLE: + case ATT_CHARACTERISTIC_ae3c_01_CLIENT_CONFIGURATION_HANDLE: + if (buffer) { + buffer[0] = att_get_ccc_config(handle); + buffer[1] = 0; + } + att_value_len = 2; + break; + + default: + break; + } + + log_info("att_value_len= %d\n", att_value_len); + return att_value_len; + +} + + +/* LISTING_END */ +/* + * @section ATT Write + * + * @text The only valid ATT write in this example is to the Client Characteristic Configuration, which configures notification + * and indication. If the ATT handle matches the client configuration handle, the new configuration value is stored and used + * in the heartbeat handler to decide if a new value should be sent. See Listing attWrite. + */ + +/* LISTING_START(attWrite): ATT Write */ +static int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size) +{ + int result = 0; + u16 tmp16; + + u16 handle = att_handle; + + log_info("write_callback,conn_handle =%04x, handle =%04x,size =%d\n", connection_handle, handle, buffer_size); + + switch (handle) { + + case ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE: + break; + + case ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE: +#if TEST_SEND_DATA_RATE + if (buffer[0]) { + server_timer_start(); + } else { + server_timer_stop(); + test_data_start = 0; + } +#endif + case ATT_CHARACTERISTIC_ae04_01_CLIENT_CONFIGURATION_HANDLE: + case ATT_CHARACTERISTIC_ae05_01_CLIENT_CONFIGURATION_HANDLE: + case ATT_CHARACTERISTIC_ae3c_01_CLIENT_CONFIGURATION_HANDLE: + set_ble_work_state(cur_dev_cid, BLE_ST_NOTIFY_IDICATE); + check_connetion_updata_deal(cur_dev_cid); + log_info("\n------write ccc:%04x,%02x\n", handle, buffer[0]); + att_set_ccc_config(handle, buffer[0]); + +#if TEST_SEND_DATA_RATE + test_data_start = 1;//start + if (buffer[0]) { + test_data_send_packet(); + } +#endif + //被使能通知后,尝试开新设备广播 + ble_enable_new_dev_adv(); + break; + + case ATT_CHARACTERISTIC_ae10_01_VALUE_HANDLE: + tmp16 = sizeof(test_read_write_buf); + if ((offset >= tmp16) || (offset + buffer_size) > tmp16) { + break; + } + memcpy(&test_read_write_buf[offset], buffer, buffer_size); + break; + + case ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE: + printf("\n-ae01_rx(%d):", buffer_size); + put_buf(buffer, buffer_size); + + //收发测试,自动发送收到的数据;for test + if (app_send_user_data_check(buffer_size)) { + app_send_user_data(connection_handle, ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE, buffer, buffer_size, ATT_OP_AUTO_READ_CCC); + } + +#if TEST_SEND_DATA_RATE + if ((buffer[0] == 'A') && (buffer[1] == 'F')) { + test_data_start = 1;//start + } else if ((buffer[0] == 'A') && (buffer[1] == 'A')) { + test_data_start = 0;//stop + } +#endif + break; + + case ATT_CHARACTERISTIC_ae03_01_VALUE_HANDLE: + printf("\n-ae_rx(%d):", buffer_size); + put_buf(buffer, buffer_size); + + //收发测试,自动发送收到的数据;for test + if (app_send_user_data_check(buffer_size)) { + app_send_user_data(connection_handle, ATT_CHARACTERISTIC_ae05_01_VALUE_HANDLE, buffer, buffer_size, ATT_OP_AUTO_READ_CCC); + } + break; + +#if RCSP_BTMATE_EN + case ATT_CHARACTERISTIC_ae02_02_CLIENT_CONFIGURATION_HANDLE: + ble_op_latency_skip(server_con_handle[cur_dev_cid], HOLD_LATENCY_CNT_ALL); // + set_ble_work_state(cur_dev_cid, BLE_ST_NOTIFY_IDICATE); +#endif + /* if ((cur_conn_latency == 0) */ + /* && (connection_update_cnt == CONN_PARAM_TABLE_CNT) */ + /* && (Peripheral_Preferred_Connection_Parameters[0].latency != 0)) { */ + /* connection_update_cnt = 0; */ + /* } */ + check_connetion_updata_deal(cur_dev_cid); + log_info("\n------write ccc:%04x,%02x\n", handle, buffer[0]); + att_set_ccc_config(handle, buffer[0]); + break; + +#if RCSP_BTMATE_EN + case ATT_CHARACTERISTIC_ae01_02_VALUE_HANDLE: + printf("rcsp_read:%x\n", buffer_size); + if (app_recieve_callback) { + app_recieve_callback(0, buffer, buffer_size); + } + break; +#endif + + case ATT_CHARACTERISTIC_ae3b_01_VALUE_HANDLE: + printf("\n-ae3b_rx(%d):", buffer_size); + put_buf(buffer, buffer_size); + +#if TEST_AUDIO_DATA_UPLOAD + if (0 == memcmp(buffer, "start", 5)) { + test_send_audio_data(1); + } +#endif + break; + + default: + break; + } + + return 0; +} + +static int app_send_user_data(u16 conn_handle, u16 handle, u8 *data, u16 len, u8 handle_type) +{ + u32 ret = APP_BLE_NO_ERROR; + + if (!conn_handle) { + return APP_BLE_OPERATION_ERROR; + } + + if (!att_get_ccc_config(handle + 1)) { + log_info("fail,no write ccc!!!,%04x\n", handle + 1); + return APP_BLE_NO_WRITE_CCC; + } + + ret = ble_op_multi_att_send_data(conn_handle, handle, data, len, handle_type); + + if (ret == BLE_BUFFER_FULL) { + ret = APP_BLE_BUFF_FULL; + } + + if (ret) { + log_info("app_send_fail:%d !!!\n", ret); + } + return ret; +} + +//------------------------------------------------------ +static int make_set_adv_data(void) +{ + u8 offset = 0; + u8 *buf = adv_data; + + + /* offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_FLAGS, 0x18, 1); */ + /* offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_FLAGS, 0x1A, 1); */ + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_FLAGS, 0x06, 1); + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_16BIT_SERVICE_UUIDS, 0xAF30, 2); + + if (offset > ADV_RSP_PACKET_MAX) { + puts("***adv_data overflow!!!!!!\n"); + return -1; + } + log_info("adv_data(%d):", offset); + log_info_hexdump(buf, offset); + adv_data_len = offset; + ble_op_set_adv_data(offset, buf); + return 0; +} + +static int make_set_rsp_data(void) +{ + u8 offset = 0; + u8 *buf = scan_rsp_data; + +#if RCSP_BTMATE_EN + u8 tag_len = sizeof(user_tag_string); + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA, (void *)user_tag_string, tag_len); +#endif + + u8 name_len = gap_device_name_len; + u8 vaild_len = ADV_RSP_PACKET_MAX - (offset + 2); + if (name_len > vaild_len) { + name_len = vaild_len; + } + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME, (void *)gap_device_name, name_len); + + if (offset > ADV_RSP_PACKET_MAX) { + puts("***rsp_data overflow!!!!!!\n"); + return -1; + } + + log_info("rsp_data(%d):", offset); + log_info_hexdump(buf, offset); + scan_rsp_data_len = offset; + ble_op_set_rsp_data(offset, buf); + return 0; +} + +//广播参数设置 +static void advertisements_setup_init() +{ + uint8_t adv_type = ADV_IND; + uint8_t adv_channel = ADV_CHANNEL_ALL; + int ret = 0; + + ble_op_set_adv_param(ADV_INTERVAL_MIN, adv_type, adv_channel); + + ret |= make_set_adv_data(); + ret |= make_set_rsp_data(); + + if (ret) { + puts("advertisements_setup_init fail !!!!!!\n"); + return; + } + +} + + +#if EXT_ADV_MODE_EN + +#define EXT_ADV_NAME 'J', 'L', '_', 'E', 'X', 'T', '_', 'A', 'D', 'V' +/* #define EXT_ADV_NAME "JL_EXT_ADV" */ +#define BYTE_LEN(x...) sizeof((u8 []) {x}) +#define EXT_ADV_DATA \ + 0x02, 0x01, 0x06, \ + 0x03, 0x02, 0xF0, 0xFF, \ + BYTE_LEN(EXT_ADV_NAME) + 1, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, EXT_ADV_NAME + +struct ext_advertising_param { + u8 Advertising_Handle; + u16 Advertising_Event_Properties; + u8 Primary_Advertising_Interval_Min[3]; + u8 Primary_Advertising_Interval_Max[3]; + u8 Primary_Advertising_Channel_Map; + u8 Own_Address_Type; + u8 Peer_Address_Type; + u8 Peer_Address[6]; + u8 Advertising_Filter_Policy; + u8 Advertising_Tx_Power; + u8 Primary_Advertising_PHY; + u8 Secondary_Advertising_Max_Skip; + u8 Secondary_Advertising_PHY; + u8 Advertising_SID; + u8 Scan_Request_Notification_Enable; +} _GNU_PACKED_; + +struct ext_advertising_data { + u8 Advertising_Handle; + u8 Operation; + u8 Fragment_Preference; + u8 Advertising_Data_Length; + u8 Advertising_Data[BYTE_LEN(EXT_ADV_DATA)]; +} _GNU_PACKED_; + +struct ext_advertising_enable { + u8 Enable; + u8 Number_of_Sets; + u8 Advertising_Handle; + u16 Duration; + u8 Max_Extended_Advertising_Events; +} _GNU_PACKED_; + +const struct ext_advertising_param ext_adv_param = { + .Advertising_Handle = 0, + .Advertising_Event_Properties = 1, + .Primary_Advertising_Interval_Min = {30, 0, 0}, + .Primary_Advertising_Interval_Max = {30, 0, 0}, + .Primary_Advertising_Channel_Map = 7, + .Primary_Advertising_PHY = ADV_SET_1M_PHY, + .Secondary_Advertising_PHY = ADV_SET_1M_PHY, +}; + +const struct ext_advertising_data ext_adv_data = { + .Advertising_Handle = 0, + .Operation = 3, + .Fragment_Preference = 0, + .Advertising_Data_Length = BYTE_LEN(EXT_ADV_DATA), + .Advertising_Data = EXT_ADV_DATA, +}; + +const struct ext_advertising_enable ext_adv_enable = { + .Enable = 1, + .Number_of_Sets = 1, + .Advertising_Handle = 0, + .Duration = 0, + .Max_Extended_Advertising_Events = 0, +}; + +const struct ext_advertising_enable ext_adv_disable = { + .Enable = 0, + .Number_of_Sets = 1, + .Advertising_Handle = 0, + .Duration = 0, + .Max_Extended_Advertising_Events = 0, +}; + +#endif /* EXT_ADV_MODE_EN */ + +static int set_adv_enable(void *priv, u32 en) +{ + ble_state_e next_state, cur_state; + + if (!adv_ctrl_en) { + return APP_BLE_OPERATION_ERROR; + } + + if (server_con_handle[cur_dev_cid]) { + return APP_BLE_OPERATION_ERROR; + } + + if (en) { + next_state = BLE_ST_ADV; + } else { + next_state = BLE_ST_IDLE; + } + + cur_state = get_ble_work_state(cur_dev_cid); + switch (cur_state) { + case BLE_ST_ADV: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + break; + default: + return APP_BLE_OPERATION_ERROR; + break; + } + + if (cur_state == next_state) { + return APP_BLE_NO_ERROR; + } + log_info("adv_en:%d\n", en); + set_ble_work_state(cur_dev_cid, next_state); + +#if EXT_ADV_MODE_EN + if (en) { + ble_op_set_ext_adv_param(&ext_adv_param, sizeof(ext_adv_param)); + + log_info_hexdump(&ext_adv_data, sizeof(ext_adv_data)); + ble_op_set_ext_adv_data(&ext_adv_data, sizeof(ext_adv_data)); + + ble_op_set_ext_adv_enable(&ext_adv_enable, sizeof(ext_adv_enable)); + } else { + ble_op_set_ext_adv_enable(&ext_adv_disable, sizeof(ext_adv_disable)); + } +#else + if (en) { + advertisements_setup_init(); + } + ble_op_adv_enable(en); +#endif /* EXT_ADV_MODE_EN */ + + return APP_BLE_NO_ERROR; +} + + +static int trans_disconnect(void *priv) +{ + u8 cid = (u8) priv; + + if (cid >= SUPPORT_MAX_SERVER) { + return APP_BLE_OPERATION_ERROR; + } + + if (server_con_handle[cid]) { + if (BLE_ST_SEND_DISCONN != get_ble_work_state(cid)) { + log_info(">>>ble(%d) send disconnect\n", cid); + set_ble_work_state(cid, BLE_ST_SEND_DISCONN); + ble_op_disconnect(server_con_handle[cid]); + } else { + log_info(">>>ble(%d) wait disconnect...\n", cid); + } + return APP_BLE_NO_ERROR; + } else { + return APP_BLE_OPERATION_ERROR; + } +} + + +static int get_buffer_vaild_len(void *priv) +{ + u32 vaild_len = 0; + ble_op_multi_att_get_remain(server_con_handle[cur_dev_cid], &vaild_len); + return vaild_len; +} + +static int app_send_user_data_do(void *priv, u8 *data, u16 len) +{ +#if PRINT_DMA_DATA_EN + if (len < 128) { + log_info("-le_tx(%d):"); + log_info_hexdump(data, len); + } else { + putchar('L'); + } +#endif + return app_send_user_data(server_con_handle[cur_dev_cid], ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE, data, len, ATT_OP_AUTO_READ_CCC); +} + +static int app_send_user_data_check(u16 len) +{ + u32 buf_space = get_buffer_vaild_len(0); + if (len <= buf_space) { + return 1; + } + return 0; +} + + +static int regiest_wakeup_send(void *priv, void *cbk) +{ + ble_resume_send_wakeup = cbk; + return APP_BLE_NO_ERROR; +} + +static int regiest_recieve_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_recieve_callback = cbk; + return APP_BLE_NO_ERROR; +} + +static int regiest_state_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_ble_state_callback = cbk; + return APP_BLE_NO_ERROR; +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + +u8 *ble_get_scan_rsp_ptr(u16 *len) +{ + if (len) { + *len = scan_rsp_data_len; + } + return scan_rsp_data; +} + +u8 *ble_get_adv_data_ptr(u16 *len) +{ + if (len) { + *len = adv_data_len; + } + return adv_data; +} + +u8 *ble_get_gatt_profile_data(u16 *len) +{ + *len = sizeof(profile_data); + return (u8 *)profile_data; +} + + +void bt_ble_adv_enable(u8 enable) +{ + set_adv_enable(0, enable); +} + +u16 bt_ble_is_connected(void) +{ + return server_con_handle[cur_dev_cid]; +} + +void ble_trans_module_enable(u8 en) +{ + log_info("mode_en:%d\n", en); + if (en) { + adv_ctrl_en = 1; + bt_ble_adv_enable(1); + } else { + adv_ctrl_en = 0; + bt_ble_adv_enable(0); + ble_multi_trans_disconnect(); + } +} + +void server_profile_init(void) +{ + log_info("%s\n", __FUNCTION__); + + /* setup ATT server */ + att_server_init(profile_data, att_read_callback, att_write_callback); + att_server_register_packet_handler(trans_cbk_packet_handler); + +#if TRANS_ANCS_EN + //setup ANCS clent + ancs_client_init(); + ancs_set_notification_buffer(ancs_info_buffer, sizeof(ancs_info_buffer)); + ancs_client_register_callback(&trans_cbk_packet_handler); +#endif + +} + + + +static const char ble_ext_name[] = "(BLE)"; + +void bt_multi_trans_init(void) +{ + log_info("%s\n", __FUNCTION__); + char *name_p; + u8 ext_name_len = sizeof(ble_ext_name) - 1; + + name_p = bt_get_local_name(); + gap_device_name_len = strlen(name_p); + if (gap_device_name_len > BT_NAME_LEN_MAX - ext_name_len) { + gap_device_name_len = BT_NAME_LEN_MAX - ext_name_len; + } + + //增加后缀,区分名字 + memcpy(gap_device_name, name_p, gap_device_name_len); + memcpy(&gap_device_name[gap_device_name_len], "(BLE)", ext_name_len); + gap_device_name_len += ext_name_len; + + log_info("ble name(%d): %s \n", gap_device_name_len, gap_device_name); + + cur_dev_cid = 0; + memset(&ble_work_state, BLE_ST_INIT_OK, SUPPORT_MAX_SERVER); + memset(&server_con_handle, 0, SUPPORT_MAX_SERVER << 1); + + set_ble_work_state(cur_dev_cid, BLE_ST_INIT_OK); + ble_trans_module_enable(1); + +#if TEST_SEND_DATA_RATE + server_timer_start(); +#endif +} + +void bt_multi_trans_exit(void) +{ + log_info("%s\n", __FUNCTION__); + + ble_trans_module_enable(0); + +#if TEST_SEND_DATA_RATE + server_timer_stop(); +#endif + +} + +void ble_multi_trans_disconnect(void) +{ + u8 i; + int count; + + for (u8 i = 0; i < SUPPORT_MAX_SERVER; i++) { + count = 150; + if (server_con_handle[i]) { + trans_disconnect((void *)i); + while (count-- && server_con_handle[i]) { + os_time_dly(1); + putchar('w'); + } + } + } +} + +#if RCSP_BTMATE_EN +static int rcsp_send_user_data_do(void *priv, u8 *data, u16 len) +{ + log_info("rcsp_tx:%x\n", len); +#if PRINT_DMA_DATA_EN + if (len < 128) { + log_info("-dma_tx(%d):"); + log_info_hexdump(data, len); + } else { + putchar('L'); + } +#endif + return app_send_user_data(server_con_handle[cur_dev_cid], ATT_CHARACTERISTIC_ae02_02_VALUE_HANDLE, data, len, ATT_OP_AUTO_READ_CCC); +} +#endif + +#if RCSP_BTMATE_EN +static const struct ble_server_operation_t mi_ble_operation = { + .adv_enable = set_adv_enable, + .disconnect = trans_disconnect, + .get_buffer_vaild = get_buffer_vaild_len, + .send_data = (void *)rcsp_send_user_data_do, + .regist_wakeup_send = regiest_wakeup_send, + .regist_recieve_cbk = regiest_recieve_cbk, + .regist_state_cbk = regiest_state_cbk, +}; +#else +static const struct ble_server_operation_t mi_ble_operation = { + .adv_enable = set_adv_enable, + .disconnect = trans_disconnect, + .get_buffer_vaild = get_buffer_vaild_len, + .send_data = (void *)app_send_user_data_do, + .regist_wakeup_send = regiest_wakeup_send, + .regist_recieve_cbk = regiest_recieve_cbk, + .regist_state_cbk = regiest_state_cbk, +}; +#endif + +void ble_get_server_operation_table(struct ble_server_operation_t **interface_pt) +{ + *interface_pt = (void *)&mi_ble_operation; +} + +void ble_server_send_test_key_num(u8 key_num) +{ + ; +} + +//切换已连接多机 +int le_multi_server_switch_connect_cid(u8 cid) +{ + if (cid < SUPPORT_MAX_SERVER && server_con_handle[cid]) { + cur_dev_cid = cid; + return 0; + } else { + log_info("cid not exist!!!\n"); + return -1; + } +} + + +#endif + + diff --git a/apps/common/third_party_profile/jieli/multi_demo/le_multi_trans.h b/apps/common/third_party_profile/jieli/multi_demo/le_multi_trans.h new file mode 100644 index 0000000..bcf912f --- /dev/null +++ b/apps/common/third_party_profile/jieli/multi_demo/le_multi_trans.h @@ -0,0 +1,195 @@ +// binary representation +// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) + +#ifndef _LE_MUTIL_TRANS_H +#define _LE_MUTIL_TRANS_H + +#include +#include "app_config.h" + +//---------------------------------------------------------------------------------------------------------- +// +// gatt profile include file, generated by jieli gatt_inc_generator.exe +// + +#if MUTIL_ROLE_IS_SERVER + +static const uint8_t profile_data[] = { + ////////////////////////////////////////////////////// + // + // 0x0001 PRIMARY_SERVICE 1800 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x18, + + /* CHARACTERISTIC, 2a00, READ | WRITE | DYNAMIC, */ + // 0x0002 CHARACTERISTIC 2a00 READ | WRITE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x0a, 0x03, 0x00, 0x00, 0x2a, + // 0x0003 VALUE 2a00 READ | WRITE | DYNAMIC + 0x08, 0x00, 0x0a, 0x01, 0x03, 0x00, 0x00, 0x2a, + + ////////////////////////////////////////////////////// + // + // 0x0004 PRIMARY_SERVICE ae30 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x28, 0x30, 0xae, + + /* CHARACTERISTIC, ae01, WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x0005 CHARACTERISTIC ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x05, 0x00, 0x03, 0x28, 0x04, 0x06, 0x00, 0x01, 0xae, + // 0x0006 VALUE ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x08, 0x00, 0x04, 0x01, 0x06, 0x00, 0x01, 0xae, + + /* CHARACTERISTIC, ae02, NOTIFY, */ + // 0x0007 CHARACTERISTIC ae02 NOTIFY + 0x0d, 0x00, 0x02, 0x00, 0x07, 0x00, 0x03, 0x28, 0x10, 0x08, 0x00, 0x02, 0xae, + // 0x0008 VALUE ae02 NOTIFY + 0x08, 0x00, 0x10, 0x00, 0x08, 0x00, 0x02, 0xae, + // 0x0009 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x09, 0x00, 0x02, 0x29, 0x00, 0x00, + + /* CHARACTERISTIC, ae03, WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x000a CHARACTERISTIC ae03 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x03, 0x28, 0x04, 0x0b, 0x00, 0x03, 0xae, + // 0x000b VALUE ae03 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x08, 0x00, 0x04, 0x01, 0x0b, 0x00, 0x03, 0xae, + + /* CHARACTERISTIC, ae04, NOTIFY, */ + // 0x000c CHARACTERISTIC ae04 NOTIFY + 0x0d, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x03, 0x28, 0x10, 0x0d, 0x00, 0x04, 0xae, + // 0x000d VALUE ae04 NOTIFY + 0x08, 0x00, 0x10, 0x00, 0x0d, 0x00, 0x04, 0xae, + // 0x000e CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x0e, 0x00, 0x02, 0x29, 0x00, 0x00, + + /* CHARACTERISTIC, ae05, INDICATE, */ + // 0x000f CHARACTERISTIC ae05 INDICATE + 0x0d, 0x00, 0x02, 0x00, 0x0f, 0x00, 0x03, 0x28, 0x20, 0x10, 0x00, 0x05, 0xae, + // 0x0010 VALUE ae05 INDICATE + 0x08, 0x00, 0x20, 0x00, 0x10, 0x00, 0x05, 0xae, + // 0x0011 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x11, 0x00, 0x02, 0x29, 0x00, 0x00, + + /* CHARACTERISTIC, ae10, READ | WRITE | DYNAMIC, */ + // 0x0012 CHARACTERISTIC ae10 READ | WRITE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x12, 0x00, 0x03, 0x28, 0x0a, 0x13, 0x00, 0x10, 0xae, + // 0x0013 VALUE ae10 READ | WRITE | DYNAMIC + 0x08, 0x00, 0x0a, 0x01, 0x13, 0x00, 0x10, 0xae, + + +#if 0 + //for uuid128,sample + // PRIMARY_SERVICE, 0000F530-1212-EFDE-1523-785FEABCD123 + // CHARACTERISTIC, 0000F531-1212-EFDE-1523-785FEABCD123, NOTIFY, + // CHARACTERISTIC, 0000F532-1212-EFDE-1523-785FEABCD123, WRITE_WITHOUT_RESPONSE | DYNAMIC, + + ////////////////////////////////////////////////////// + // + // 0x0014 PRIMARY_SERVICE 0000F530-1212-EFDE-1523-785FEABCD123 + // + ////////////////////////////////////////////////////// + 0x18, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x28, 0x23, 0xd1, 0xbc, 0xea, 0x5f, 0x78, 0x23, 0x15, 0xde, 0xef, 0x12, 0x12, 0x30, 0xf5, 0x00, 0x00, + + /* CHARACTERISTIC, 0000F531-1212-EFDE-1523-785FEABCD123, NOTIFY, */ + // 0x0015 CHARACTERISTIC 0000F531-1212-EFDE-1523-785FEABCD123 NOTIFY + 0x1b, 0x00, 0x02, 0x00, 0x15, 0x00, 0x03, 0x28, 0x10, 0x16, 0x00, 0x23, 0xd1, 0xbc, 0xea, 0x5f, 0x78, 0x23, 0x15, 0xde, 0xef, 0x12, 0x12, 0x31, 0xf5, 0x00, 0x00, + // 0x0016 VALUE 0000F531-1212-EFDE-1523-785FEABCD123 NOTIFY + 0x16, 0x00, 0x10, 0x02, 0x16, 0x00, 0x23, 0xd1, 0xbc, 0xea, 0x5f, 0x78, 0x23, 0x15, 0xde, 0xef, 0x12, 0x12, 0x31, 0xf5, 0x00, 0x00, + // 0x0017 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x17, 0x00, 0x02, 0x29, 0x00, 0x00, + + /* CHARACTERISTIC, 0000F532-1212-EFDE-1523-785FEABCD123, WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x0018 CHARACTERISTIC 0000F532-1212-EFDE-1523-785FEABCD123 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x1b, 0x00, 0x02, 0x00, 0x18, 0x00, 0x03, 0x28, 0x04, 0x19, 0x00, 0x23, 0xd1, 0xbc, 0xea, 0x5f, 0x78, 0x23, 0x15, 0xde, 0xef, 0x12, 0x12, 0x32, 0xf5, 0x00, 0x00, + // 0x0019 VALUE 0000F532-1212-EFDE-1523-785FEABCD123 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x16, 0x00, 0x04, 0x03, 0x19, 0x00, 0x23, 0xd1, 0xbc, 0xea, 0x5f, 0x78, 0x23, 0x15, 0xde, 0xef, 0x12, 0x12, 0x32, 0xf5, 0x00, 0x00, +#endif + + ////////////////////////////////////////////////////// + // + // 0x0014 PRIMARY_SERVICE 1812 + // + ////////////////////////////////////////////////////// + // 0x0a, 0x00, 0x02, 0x00, 0x34, 0x00, 0x00, 0x28, 0x12, 0x18,//ios app can't disconn + +#if 0// authentication + // + 10, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x28, 0x0A, 0x18, //primary service declaration + 13, 0x00, 0x02, 0x00, 0x1B, 0x00, 0x03, 0x28, 0x02, 0x1C, 0x00, 0x50, 0x2A, //characteristic declaration + 15, 0x00, 0x02, 0x04, 0x1C, 0x00, 0x50, 0x2A, 0x02, 0x8A, 0x24, 0x66, 0x82, 0x34, 0x36, //PnP ID +#endif + + ////////////////////////////////////////////////////// + // + // 0x0040 PRIMARY_SERVICE ae3a + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x40, 0x00, 0x00, 0x28, 0x3a, 0xae, + + /* CHARACTERISTIC, ae3b, WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x0041 CHARACTERISTIC ae3b WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x41, 0x00, 0x03, 0x28, 0x04, 0x42, 0x00, 0x3b, 0xae, + // 0x0042 VALUE ae3b WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x08, 0x00, 0x04, 0x01, 0x42, 0x00, 0x3b, 0xae, + + /* CHARACTERISTIC, ae3c, NOTIFY, */ + // 0x0043 CHARACTERISTIC ae3c NOTIFY + 0x0d, 0x00, 0x02, 0x00, 0x43, 0x00, 0x03, 0x28, 0x10, 0x44, 0x00, 0x3c, 0xae, + // 0x0044 VALUE ae3c NOTIFY + 0x08, 0x00, 0x10, 0x00, 0x44, 0x00, 0x3c, 0xae, + // 0x0045 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x45, 0x00, 0x02, 0x29, 0x00, 0x00, + +#if RCSP_BTMATE_EN + ////////////////////////////////////////////////////// + // + // 0x0004 PRIMARY_SERVICE ae00 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x28, 0x00, 0xae, + + /* CHARACTERISTIC, ae01, WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x0040 CHARACTERISTIC ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x81, 0x00, 0x03, 0x28, 0x04, 0x82, 0x00, 0x01, 0xae, + // 0x0041 VALUE ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x08, 0x00, 0x04, 0x01, 0x82, 0x00, 0x01, 0xae, + + /* CHARACTERISTIC, ae02, NOTIFY, */ + // 0x0042 CHARACTERISTIC ae02 NOTIFY + 0x0d, 0x00, 0x02, 0x00, 0x83, 0x00, 0x03, 0x28, 0x10, 0x84, 0x00, 0x02, 0xae, + // 0x0043 VALUE ae02 NOTIFY + 0x08, 0x00, 0x10, 0x00, 0x84, 0x00, 0x02, 0xae, + // 0x0044 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x85, 0x00, 0x02, 0x29, 0x00, 0x00, +#endif + // END + 0x00, 0x00, +}; +// +// characteristics <--> handles +// +#if RCSP_BTMATE_EN +#define ATT_CHARACTERISTIC_ae01_02_VALUE_HANDLE 0x0082 +#define ATT_CHARACTERISTIC_ae02_02_VALUE_HANDLE 0x0084 +#define ATT_CHARACTERISTIC_ae02_02_CLIENT_CONFIGURATION_HANDLE 0x0085 +#endif + +#define ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE 0x0003 +#define ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE 0x0006 +#define ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE 0x0008 +#define ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE 0x0009 +#define ATT_CHARACTERISTIC_ae03_01_VALUE_HANDLE 0x000b +#define ATT_CHARACTERISTIC_ae04_01_VALUE_HANDLE 0x000d +#define ATT_CHARACTERISTIC_ae04_01_CLIENT_CONFIGURATION_HANDLE 0x000e +#define ATT_CHARACTERISTIC_ae05_01_VALUE_HANDLE 0x0010 +#define ATT_CHARACTERISTIC_ae05_01_CLIENT_CONFIGURATION_HANDLE 0x0011 +#define ATT_CHARACTERISTIC_ae10_01_VALUE_HANDLE 0x0013 + +#define ATT_CHARACTERISTIC_ae3b_01_VALUE_HANDLE 0x0042 +#define ATT_CHARACTERISTIC_ae3c_01_VALUE_HANDLE 0x0044 +#define ATT_CHARACTERISTIC_ae3c_01_CLIENT_CONFIGURATION_HANDLE 0x0045 + +#endif + +#endif diff --git a/apps/common/third_party_profile/jieli/online_db/online_db_deal.c b/apps/common/third_party_profile/jieli/online_db/online_db_deal.c new file mode 100644 index 0000000..a4e0395 --- /dev/null +++ b/apps/common/third_party_profile/jieli/online_db/online_db_deal.c @@ -0,0 +1,700 @@ +#include "app_config.h" +#include "app_action.h" +#include "system/includes.h" +#include "string.h" +#include "online_db_deal.h" +#include "circular_buf.h" +#include "bt_common.h" + +#if APP_ONLINE_DEBUG + +#define LOG_TAG_CONST ONLINE_DB +#define LOG_TAG "[ONLINE_DB]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#if (TCFG_AUDIO_DATA_EXPORT_ENABLE && (TCFG_AUDIO_DATA_EXPORT_ENABLE == AUDIO_DATA_EXPORT_USE_SPP)) +#define DB_MEM_BUF_LEN (768 * 15) +#else +#define DB_MEM_BUF_LEN (768) +#endif +#define DB_ONE_PACKET_LEN (256) + + +#define DB_TIMER_SET (200) //unit:ms +#define DB_PAYLOAD_MAXSIZE (253) +#define DB_TMP_PACKET_LEN (660) +#define DB_PRINT_BUFF_LEN (128) + +#define DB_PRINT_DATA_EN 0//是否上报串口打印数据,某些场景就导致死机,不建议使用 +#define DB_PRINT_DELAY_TYPE 0//0-timeout check,1-time check + +#define cbuf_get_space(a) (a)->total_len + +enum { + DB_EVT_MSG_NULL = 0, + DB_EVT_MSG_SEND, +}; + +enum { + DB_TO_TYPE_PRINT = 0, +}; + +struct db_head_t { + u8 length; + u8 type; + u8 seq; + u8 data[0]; +} _GNU_PACKED_; + +struct db_online_info_t { + u16 db_timer; + u8 active; + u8 seq; + int db_cb_api_table[DB_PKT_TYPE_MAX]; + int (*send_api)(u8 *packet, u16 size); + cbuffer_t send_cbuf; + u8 db_mem_buffer[DB_MEM_BUF_LEN]; + u8 tmp_send_buf[DB_TMP_PACKET_LEN]; + u16 tmp_data_len; + u8 tmp_recieve_buf[DB_ONE_PACKET_LEN]; + u16 tmp_recieve_len; + u8 print_buffer[DB_PRINT_BUFF_LEN * 2]; + volatile u8 *print_buf_prt; + volatile u16 print_count; +}; + +static volatile u8 db_send_busy = 0; +static volatile u8 db_timeout_type = 0; +static volatile u16 print_record_count = 0; + +static struct db_online_info_t online_global_info; +#define __this (&online_global_info) + +//----------------------------------------------------- +extern void register_putbyte_hook(int (*hook_call)(char a)); +static void db_data_try_send(void); +static void db_data_send_msg(int evt_msg); +static void db_print_test_function(void); +static void db_timeout_handle(int type); +//----------------------------------------------------- +//获取cbuff 数据 +static u16 db_data_read_sub(u8 *buf, u16 buf_size) +{ + u16 ret_len; + if (0 == cbuf_get_data_size(&__this->send_cbuf)) { + return 0; + } + + OS_ENTER_CRITICAL(); + if (cbuf_get_data_size(&__this->send_cbuf)) {//check again + cbuf_read(&__this->send_cbuf, &ret_len, 2); + if (ret_len && ret_len <= buf_size) { + cbuf_read(&__this->send_cbuf, buf, ret_len); + } + } + OS_EXIT_CRITICAL(); + + return ret_len; +} + +//尝试发送cbuff 数据 +static void db_data_try_send(void) +{ + u16 send_len; + + if (db_send_busy) { + return; + } + db_send_busy = 1;//hold + + if (__this->tmp_data_len) { + /* log_info("send_tmp_data = %d",__this->tmp_data_len); */ + if (__this->send_api) { + if (__this->send_api(__this->tmp_send_buf, __this->tmp_data_len)) { + db_send_busy = 0;//fail + return; + } + __this->tmp_data_len = 0; + } + } + + send_len = db_data_read_sub(__this->tmp_send_buf, DB_TMP_PACKET_LEN); + + if (send_len > DB_TMP_PACKET_LEN) { + printf("err:send_len= %d\n", send_len); + ASSERT(0); + } + + if (send_len) { + /* log_info("send_buf_data = %d",send_len); */ + if (__this->send_api(__this->tmp_send_buf, send_len)) { + __this->tmp_data_len = send_len; + db_send_busy = 0;//fail + } + } else { + //not send + db_send_busy = 0; + } +} + +//写入数据到cbuff +static u32 db_data_write_sub(u8 *head, u8 head_size, u8 *data, u16 len) +{ + u16 wlen = 0; + u16 total_len = 0; + + if (!__this->active) { + /* log_error("not active!"); */ + return 0; + } + + if (len > DB_ONE_PACKET_LEN) { + ASSERT(0); + } + + total_len = head_size + len; + + OS_ENTER_CRITICAL(); + u16 buf_space = cbuf_get_space(&__this->send_cbuf) - cbuf_get_data_size(&__this->send_cbuf); + if (total_len + 2 > buf_space) { + /* log_error("cbuf full!"); */ + OS_EXIT_CRITICAL(); + return 0; + } + + wlen = cbuf_write(&__this->send_cbuf, &total_len, 2); + if (head_size) { + wlen += cbuf_write(&__this->send_cbuf, head, head_size); + } + if (len) { + wlen += cbuf_write(&__this->send_cbuf, data, len); + } + OS_EXIT_CRITICAL(); + + /* db_data_try_send(); */ + if (!db_send_busy) { + db_data_send_msg(DB_EVT_MSG_SEND); + } + return wlen; +} + +//处理协议栈来数,分发到已注册模块解析处理 +static void db_packet_handle(u8 *packet, u8 size) +{ + struct db_head_t *db_ptr = (void *)packet; + int ret = -1; + + if (db_ptr->length == 0) { + log_error("len=0"); + return; + } + + + //判读是否需要缓存组包 + if (__this->tmp_recieve_len) { + if (__this->tmp_recieve_len + size > DB_ONE_PACKET_LEN) { + log_error("rx_len_err:%d", __this->tmp_recieve_len + size); + __this->tmp_recieve_len = 0; + return; + } + + memcpy(&__this->tmp_recieve_buf[__this->tmp_recieve_len], packet, size); + __this->tmp_recieve_len += size; + if (__this->tmp_recieve_len < db_ptr->length) { + /* putchar('<'); */ + return; + } + + db_ptr = (void *)&__this->tmp_recieve_buf; + packet = (void *)&__this->tmp_recieve_buf; + size = __this->tmp_recieve_len; + __this->tmp_recieve_len = 0; + /* putchar('>'); */ + } else { + if (size < db_ptr->length) { + __this->tmp_recieve_len = size; + memcpy(&__this->tmp_recieve_buf, packet, size); + /* putchar('<'); */ + return; + } + } + + if (db_ptr->type == 0 || db_ptr->type >= DB_PKT_TYPE_MAX) { + log_error("type_err"); + return; + } + + + /* int (*db_parse_data)(u8 *packet,u8 size,u8 *ext_data,ext_size); */ + int (*db_parse_data)(u8 * packet, u8 size, u8 * ext_data, u16 ext_size) = (void *)(__this->db_cb_api_table[db_ptr->type]); + + if (db_parse_data) { + /* log_info("db_parse_data,%08x",db_parse_data); */ + + log_info("rx_data(%d):", size); + log_info_hexdump((void *)db_ptr, size); + + u8 *tmp_buf_pt = malloc(DB_ONE_PACKET_LEN); + if (!tmp_buf_pt) { + log_error("malloc faill,drop data!!!"); + return; + } + + size -= 3; + //整理对齐 + memcpy(tmp_buf_pt, db_ptr->data, size); + db_parse_data(tmp_buf_pt, size, &db_ptr->type, 2); + free(tmp_buf_pt); + } +} + + +//打印数据推送处理,需要临界保护 +static void db_print_send_deal(void) +{ + static volatile u8 send_flag = 0; + u16 tmp_len = 0; + u8 *tmp_buf; + + if (send_flag) { + __this->print_count = 0;//drop data + return; + } + + //乒乓buffer + OS_ENTER_CRITICAL(); + send_flag = 1; + if (__this->print_count) { //check again + tmp_len = __this->print_count; + tmp_buf = __this->print_buf_prt; + if (__this->print_buf_prt == __this->print_buffer) { + __this->print_buf_prt = &__this->print_buffer[DB_PRINT_BUFF_LEN]; + } else { + __this->print_buf_prt = __this->print_buffer; + } + __this->print_count = 0; + } + OS_EXIT_CRITICAL(); + if (tmp_len) { + app_online_db_send(DB_PKT_TYPE_PRINT, tmp_buf, tmp_len); + } + send_flag = 0; + +} + +//截取串口打印数据处理 +static int db_hook_put_byte(char a) +{ + static volatile repeat_cnt = 0; + int ret = 0; //0--keep uart,1--not uart + + if (repeat_cnt) { + return ret; + } + repeat_cnt = 1; + + if (__this->print_count > (DB_PRINT_BUFF_LEN - 4)) { + db_print_send_deal(); + } + __this->print_buf_prt[__this->print_count++] = (u8)a; + repeat_cnt = 0; + +#if(0 == DB_PRINT_DELAY_TYPE) + if (0 == (db_timeout_type & BIT(DB_TO_TYPE_PRINT))) { + db_timeout_type |= BIT(DB_TO_TYPE_PRINT); + print_record_count = __this->print_count; + sys_timeout_add(DB_TO_TYPE_PRINT, db_timeout_handle, DB_TIMER_SET); + } +#endif + + return ret; +} + +#if(1 == DB_PRINT_DELAY_TYPE) +//定义检测打印数据是否需要超时推送到上位机 +static void db_print_timer_handle(void) +{ + if (__this->print_count) { + if (print_record_count == __this->print_count) { //第二次检查相同才输出打印 + db_print_send_deal(); + } else { + print_record_count = __this->print_count; + } + } + +} +#endif + +//检测打印数据是否需要超时推送到上位机 +static void db_timeout_handle(int type) +{ +#if(0 == DB_PRINT_DELAY_TYPE) + if (!__this->active) { + return; + } + + /* putchar('&'); */ + if (type == DB_TO_TYPE_PRINT) { + if (__this->print_count) { //第二次检查相同才输出打印 + if (print_record_count == __this->print_count) { //第二次检查相同才输出打印 + db_timeout_type &= (~BIT(DB_TO_TYPE_PRINT)); + db_print_send_deal(); + } else { + print_record_count = __this->print_count; + sys_timeout_add(DB_TO_TYPE_PRINT, db_timeout_handle, DB_TIMER_SET); + } + } else { + db_timeout_type &= (~BIT(DB_TO_TYPE_PRINT)); + } + } +#endif +} + +/* static u8 test_buffer_data22[512]; */ +/* static void db_test_send_data(void) */ +/* { */ +/* app_online_db_send_more(0, test_buffer_data22, 512); */ +/* } */ + +//上位机连上初始化 +static void db_init(db_com_e conn_type) +{ + cbuf_init(&__this->send_cbuf, __this->db_mem_buffer, DB_MEM_BUF_LEN); + +#if(1 == DB_PRINT_DELAY_TYPE) + __this->db_timer = sys_timer_add(NULL, db_print_timer_handle, DB_TIMER_SET); +#endif + + __this->print_count = 0; + __this->print_buf_prt = __this->print_buffer; + __this->tmp_data_len = 0; + __this->tmp_recieve_len = 0; + db_send_busy = 0; + +#if DB_PRINT_DATA_EN + register_putbyte_hook(db_hook_put_byte); +#endif + + __this->active = conn_type; + //db_print_test_function(); + + /* for (int i = 0; i < 512; i++) { */ + /* test_buffer_data22[i] = i; */ + /* } */ + /* sys_timer_add(0, db_test_send_data, 200); */ + /* printf_buf(test_buffer_data22, 512); */ +} + +//上位断开,退出 +void db_exit(void) +{ + __this->active = DB_COM_TYPE_NULL; + +#if(1 == DB_PRINT_DELAY_TYPE) + if (__this->db_timer) { + sys_timer_del(__this->db_timer); + __this->db_timer = 0; + } +#endif + +#if DB_PRINT_DATA_EN + register_putbyte_hook(NULL); +#endif + + OS_ENTER_CRITICAL(); + cbuf_clear(&__this->send_cbuf); + OS_EXIT_CRITICAL(); +} + + +//注册协议栈发送接口 +static void db_register_send_data(void *send_api_call) +{ + __this->send_api = send_api_call; +} + +//协议栈发送完成,唤醒 +static void db_wakeup_send_data(void *send_api_call) +{ + db_send_busy = 0;// + db_data_try_send(); +} + +static void db_data_send_msg(int evt_msg) +{ + struct sys_event e; + e.type = SYS_DEVICE_EVENT; + e.arg = (void *)DEVICE_EVENT_ONLINE_DATA; + e.u.dev.event = 0; + e.u.dev.value = evt_msg; + sys_event_notify(&e); +} + +struct db_online_api_t de_online_api_table = { + .init = db_init, + .exit = db_exit, + .packet_handle = db_packet_handle, + .register_send_data = db_register_send_data, + .send_wake_up = db_wakeup_send_data, +}; + +//获取接口列表 +struct db_online_api_t *app_online_get_api_table(void) +{ + return &de_online_api_table; +} + +//注册模块解析函数 +void app_online_db_register_handle(db_pkt_e type, int (*db_parse_data)(u8 *packet, u8 size, u8 *ext_data, u16 ext_size)) +{ + if (type == 0 || type >= DB_PKT_TYPE_MAX) { + log_error("reg_type_err"); + return; + } + log_info("register_handle %d,%08x", type, db_parse_data); + __this->db_cb_api_table[type] = (int)db_parse_data; +} + +//获取可发送数据的长度 +int app_online_get_buf_remain(db_pkt_e type) +{ + if (!__this->active) { + return 0; + } + + int w_len = 0; + int head_size = 3; + int buf_space = cbuf_get_space(&__this->send_cbuf) - cbuf_get_data_size(&__this->send_cbuf); + int pack_size = head_size + DB_PAYLOAD_MAXSIZE; + + if (buf_space <= head_size) { + w_len = 0; + } else if (buf_space < pack_size) { + w_len = buf_space - head_size; + } else { + w_len = (buf_space / pack_size) * DB_PAYLOAD_MAXSIZE; + buf_space = buf_space % pack_size; + if (buf_space > head_size) { + w_len += (buf_space - head_size); + } + } + return w_len; +} + +//发送包,发送 +int app_online_db_send(db_pkt_e type, u8 *packet, u8 size) +{ + struct db_head_t db_ptr; + db_ptr.length = size + 2; + db_ptr.type = type; + db_ptr.seq = __this->seq++; + u8 head_size = 3; + + if (!__this->active) { + return -1; + } + + if (!size) { + log_error("size err!!!"); + return -2; + } + +#if 0// + head_size = 0;//不发送头 +#endif + + log_info("tx_data(%d):,type=%d", size, type); + log_info_hexdump(packet, size); + + if (!db_data_write_sub(&db_ptr, head_size, packet, size)) { + log_error("full fail,%d,%d", type, size); + return -3; + } + return 0; +} + +//发送包,发送 +int app_online_db_send_more(db_pkt_e type, u8 *packet, u16 size) +{ + struct db_head_t db_ptr; + u8 head_size = 3; + + if (!__this->active) { + return -1; + } + + if (!size || size > 650) { + log_error("overflow!!!%d,%d", type, size); + return -2; + } + + log_info("tx_more_data(%d):,type=%d", size, type); + log_info_hexdump(packet, size); + + u16 need_buff_size = ((size / DB_PAYLOAD_MAXSIZE) * (DB_PAYLOAD_MAXSIZE + head_size)); + u16 remain_size = size % DB_PAYLOAD_MAXSIZE; + + if (remain_size) { + need_buff_size += (remain_size + head_size); + } + + OS_ENTER_CRITICAL(); + if (need_buff_size + 2 > app_online_get_buf_remain(type)) { + OS_EXIT_CRITICAL(); + log_error("more full!!!"); + return -3; + } + + u16 payload_size; + db_ptr.type = type; + cbuf_write(&__this->send_cbuf, &need_buff_size, 2); + + while (size) { + if (size > DB_PAYLOAD_MAXSIZE) { + payload_size = DB_PAYLOAD_MAXSIZE; + } else { + payload_size = size; + } + size -= payload_size; + db_ptr.length = payload_size + 2; + db_ptr.seq = __this->seq++; + cbuf_write(&__this->send_cbuf, &db_ptr, head_size); + cbuf_write(&__this->send_cbuf, packet, payload_size); + packet += payload_size; + } + OS_EXIT_CRITICAL(); + + db_data_try_send(); + /* if (!db_send_busy) { */ + /* db_data_send_msg(DB_EVT_MSG_SEND); */ + /* } */ + return 0; +} + + +//应答包,发送 +int app_online_db_ack(u8 seq, u8 *packet, u8 size) +{ + struct db_head_t db_ptr; + db_ptr.length = size + 2; + db_ptr.type = DB_PKT_TYPE_ACK; + db_ptr.seq = seq; + + if (!__this->active) { + return -1; + } + + log_info("tx_ack(%d):,seq=%d", size, seq); + log_info_hexdump(packet, size); + + if (!db_data_write_sub(&db_ptr, 3, packet, size)) { + log_error("send fail2,%d,%d", seq, size); + return -1; + } + return 0; +} + + + +void app_online_event_handle(int evt_value) +{ + if (evt_value == DB_EVT_MSG_SEND) { + /* putchar('@'); */ + db_data_try_send(); + } +} + +void app_online_putchar(char a) +{ + db_hook_put_byte(a); +} + +void app_online_puts(char *str) +{ + while (*str != 0) { + db_hook_put_byte(*str++); + } +} + +static void app_online_put_u4hex(unsigned char dat) +{ + dat = 0xf & dat; + if (dat > 9) { + app_online_putchar(dat - 10 + 'A'); + } else { + app_online_putchar(dat + '0'); + } +} + + +void app_online_put_u16hex(u16 dat) +{ + app_online_putchar('0'); + app_online_putchar('x'); + + app_online_put_u4hex(dat >> 12); + app_online_put_u4hex(dat >> 8); + app_online_put_u4hex(dat >> 4); + app_online_put_u4hex(dat); + + app_online_putchar(' '); +} + +void app_online_put_u8hex(u8 dat) +{ + app_online_put_u4hex(dat >> 4); + app_online_put_u4hex(dat); + app_online_putchar(' '); +} + +void app_online_put_u32hex(u32 dat) +{ + app_online_putchar('0'); + app_online_putchar('x'); + + app_online_put_u4hex(dat >> 28); + app_online_put_u4hex(dat >> 24); + app_online_put_u4hex(dat >> 20); + app_online_put_u4hex(dat >> 16); + app_online_put_u4hex(dat >> 12); + app_online_put_u4hex(dat >> 8); + app_online_put_u4hex(dat >> 4); + app_online_put_u4hex(dat); + + app_online_putchar(' '); +} + +void app_online_put_buf(u8 *buf, u16 len) +{ + for (int i = 0; i < len; i++) { + if ((i % 16) == 0) { + app_online_putchar('\n') ; + } + app_online_put_u8hex(buf[i]) ; + } + app_online_putchar('\n') ; +} + +static const u8 test_buffer_data[8] = {1, 2, 3, 4, 5, 6, 7, 8, 9}; +static void db_print_test_function(void) +{ + app_online_puts("print test start\n"); + app_online_putchar('@'); + app_online_put_u8hex(0x78); + app_online_put_u16hex(0x1234); + app_online_put_u32hex(0x33445566); + app_online_put_buf(test_buffer_data, 32); + app_online_puts("print test end\n"); +} + + + +#endif + + + diff --git a/apps/common/third_party_profile/jieli/online_db/online_db_deal.h b/apps/common/third_party_profile/jieli/online_db/online_db_deal.h new file mode 100644 index 0000000..2dfcd67 --- /dev/null +++ b/apps/common/third_party_profile/jieli/online_db/online_db_deal.h @@ -0,0 +1,99 @@ +#ifndef __ONLINE_DB_DEAL_H__ +#define __ONLINE_DB_DEAL_H__ +#include "typedef.h" + +typedef enum { + DB_PKT_TYPE_ACK = 0, + DB_PKT_TYPE_PRINT, + DB_PKT_TYPE_EQ = 5, + DB_PKT_TYPE_ANC = 7, + DB_PKT_TYPE_AEC = 8, + DB_PKT_TYPE_EXPORT = 0x9, + DB_PKT_TYPE_TOUCH = 0xA, + DB_PKT_TYPE_DMS = 0xB, + DB_PKT_TYPE_DAT_CH0 = 0x10, + DB_PKT_TYPE_DAT_CH1, + DB_PKT_TYPE_DAT_CH2, + DB_PKT_TYPE_MAX, +} db_pkt_e; + +typedef enum { + DB_COM_TYPE_NULL = 0, + DB_COM_TYPE_SPP, + DB_COM_TYPE_BLE, +} db_com_e; + +struct db_online_api_t { + void (*init)(db_com_e conn_type); + void (*exit)(void); + void (*register_send_data)(void *send_api); + void (*send_wake_up)(void); + int (*packet_handle)(u8 *packet, u16 size); +}; + +/* + @funtion 获取可写入缓存的数据长度 + @param [in] type + @return 可写入的长度 + */ +int app_online_get_buf_remain(db_pkt_e type); + +/* + @funtion 大数据包发送,超过253,会拆包,蓝牙一次发多包 + @param [in] type + @param [in] packet 数据地址 + @param [in] size 数据长度, range:1~512 + @return 0 sucess,others fail + */ +int app_online_db_send_more(db_pkt_e type, u8 *packet, u16 size); + + +/* + @funtion 数据包发送 + @param [in] type + @param [in] packet 数据地址 + @param [in] size 数据长度, range:1~253 + @return 0 sucess,others fail + */ +int app_online_db_send(db_pkt_e type, u8 *packet, u8 size); + +/* + @funtion 应答包发送 + @param [in] seq 应答对应接收包数据的seq值 + @param [in] packet 数据地址 + @param [in] size 数据长度, range:1~253 + @return 0 sucess,others fail + */ +int app_online_db_ack(u8 seq, u8 *packet, u8 size); + +/* + @funtion 注册接收数据包类型的处理函数 + @param [in] type + @param [in] db_parse_datap, funtion to callback + + int (*db_parse_data)(u8 *packet, u8 size, u8 *ext_data, u16 ext_size) + @param [in] packet 数据地址 + @param [in] size 数据长度, range:1~253 + @param [in] ext_data ,协议层head的起始地址,db_head_t + @param [in] ext_size ,数据 0~2 + @return 0 sucess,others fail + + */ +void app_online_db_register_handle(db_pkt_e type, int (*db_parse_data)(u8 *packet, u8 size, u8 *ext_data, u16 ext_size)); + +/* + @funtion get api funtion + @return api_funtion point. + */ +struct db_online_api_t *app_online_get_api_table(void); + + +//debug printf,提供简单打印接口 +void app_online_putchar(char a); +void app_online_puts(char *str); +void app_online_put_u8hex(u8 dat); +void app_online_put_u16hex(u16 dat); +void app_online_put_u32hex(u32 dat); +void app_online_put_buf(u8 *buf, u16 len); + +#endif// diff --git a/apps/common/third_party_profile/jieli/online_db/spp_online_db.c b/apps/common/third_party_profile/jieli/online_db/spp_online_db.c new file mode 100644 index 0000000..d887945 --- /dev/null +++ b/apps/common/third_party_profile/jieli/online_db/spp_online_db.c @@ -0,0 +1,99 @@ + +#include "app_config.h" +#include "app_action.h" + +#include "system/includes.h" +#include "spp_user.h" +#include "string.h" +#include "circular_buf.h" +#include "bt_common.h" +#include "online_db_deal.h" +#include "spp_online_db.h" + +#if 1 +extern void printf_buf(u8 *buf, u32 len); +#define log_info printf +#define log_info_hexdump printf_buf +#else +#define log_info(...) +#define log_info_hexdump(...) +#endif + +#if APP_ONLINE_DEBUG + +static struct db_online_api_t *db_api; +static struct spp_operation_t *spp_api = NULL; +static u8 spp_state; + +int online_spp_send_data(u8 *data, u16 len) +{ + if (spp_api) { + /* log_info("spp_api_tx(%d) \n", len); */ + /* log_info_hexdump(data, len); */ + return spp_api->send_data(NULL, data, len); + } + return SPP_USER_ERR_SEND_FAIL; +} + +int online_spp_send_data_check(u16 len) +{ + if (spp_api) { + if (spp_api->busy_state()) { + return 0; + } + } + return 1; +} + +static void online_spp_state_cbk(u8 state) +{ + spp_state = state; + switch (state) { + case SPP_USER_ST_CONNECT: + log_info("SPP_USER_ST_CONNECT ~~~\n"); + db_api->init(DB_COM_TYPE_SPP); + db_api->register_send_data(online_spp_send_data); + break; + + case SPP_USER_ST_DISCONN: + log_info("SPP_USER_ST_DISCONN ~~~\n"); + db_api->exit(); + break; + + default: + break; + } + +} + +static void online_spp_send_wakeup(void) +{ + /* putchar('W'); */ + db_api->send_wake_up(); +} + +static void online_spp_recieve_cbk(void *priv, u8 *buf, u16 len) +{ + log_info("spp_api_rx(%d) \n", len); + /* log_info_hexdump(buf, len); */ + + db_api->packet_handle(buf, len); + + //loop send data for test + /* if (online_spp_send_data_check(len)) { */ + /* online_spp_send_data(buf, len); */ + /* } */ +} + +void online_spp_init(void) +{ + spp_state = 0; + spp_get_operation_table(&spp_api); + spp_api->regist_recieve_cbk(0, online_spp_recieve_cbk); + spp_api->regist_state_cbk(0, online_spp_state_cbk); + spp_api->regist_wakeup_send(NULL, online_spp_send_wakeup); + db_api = app_online_get_api_table(); +} + +#endif + diff --git a/apps/common/third_party_profile/jieli/online_db/spp_online_db.h b/apps/common/third_party_profile/jieli/online_db/spp_online_db.h new file mode 100644 index 0000000..42bde6d --- /dev/null +++ b/apps/common/third_party_profile/jieli/online_db/spp_online_db.h @@ -0,0 +1,8 @@ +#ifndef __SPP_ONLINE_DB_H__ +#define __SPP_ONLINE_DB_H__ + +#include "typedef.h" +#include "bt_common.h" + + +#endif// diff --git a/apps/common/third_party_profile/jieli/trans_data_demo/le_trans_data.c b/apps/common/third_party_profile/jieli/trans_data_demo/le_trans_data.c new file mode 100644 index 0000000..d7b504d --- /dev/null +++ b/apps/common/third_party_profile/jieli/trans_data_demo/le_trans_data.c @@ -0,0 +1,1315 @@ +/********************************************************************************************* + * Filename : le_server_module.c + + * Description : + + * Author : + + * Email : zh-jieli.com + + * Last modifiled : 2017-01-17 11:14 + + * Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved. +*********************************************************************************************/ + +// ***************************************************************************** +/* EXAMPLE_START(le_counter): LE Peripheral - Heartbeat Counter over GATT + * + * @text All newer operating systems provide GATT Client functionality. + * The LE Counter examples demonstrates how to specify a minimal GATT Database + * with a custom GATT Service and a custom Characteristic that sends periodic + * notifications. + */ +// ***************************************************************************** +#include "system/app_core.h" +#include "system/includes.h" + +#include "app_config.h" +#include "app_action.h" + +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "user_cfg.h" +#include "vm.h" +#include "btcontroller_modules.h" +#include "bt_common.h" +#include "3th_profile_api.h" + +#include "le_trans_data.h" +#include "le_common.h" + +#include "rcsp_bluetooth.h" +#include "JL_rcsp_api.h" +#include "custom_cfg.h" + + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_TRANS_DATA) + +//TRANS ANCS +#define TRANS_ANCS_EN 0 +#if TRANS_ANCS_EN +#include "btstack/btstack_event.h" +#endif + +#define TEST_SEND_DATA_RATE 0 //测试上行发送数据 +#define TEST_SEND_HANDLE_VAL ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE +/* #define TEST_SEND_HANDLE_VAL ATT_CHARACTERISTIC_ae05_01_VALUE_HANDLE */ +#define EXT_ADV_MODE_EN 0 + +#define TEST_AUDIO_DATA_UPLOAD 0 //测试文件上传 + + +#if 1 +extern void printf_buf(u8 *buf, u32 len); +#define log_info printf +#define log_info_hexdump printf_buf +#else +#define log_info(...) +#define log_info_hexdump(...) +#endif + + +/* #define LOG_TAG_CONST BT_BLE */ +/* #define LOG_TAG "[LE_S_DEMO]" */ +/* #define LOG_ERROR_ENABLE */ +/* #define LOG_DEBUG_ENABLE */ +/* #define LOG_INFO_ENABLE */ +/* #define LOG_DUMP_ENABLE */ +/* #define LOG_CLI_ENABLE */ +/* #include "debug.h" */ + +//------ +//ATT发送的包长, note: 20 <=need >= MTU +#define ATT_LOCAL_PAYLOAD_SIZE (200) // +//ATT缓存的buffer大小, note: need >= 20,可修改 +#define ATT_SEND_CBUF_SIZE (512) // + +//共配置的RAM +#define ATT_RAM_BUFSIZE (ATT_CTRL_BLOCK_SIZE + ATT_LOCAL_PAYLOAD_SIZE + ATT_SEND_CBUF_SIZE) //note: +static u8 att_ram_buffer[ATT_RAM_BUFSIZE] __attribute__((aligned(4))); +//--------------- + +#if TEST_SEND_DATA_RATE +static u32 test_data_count; +static u32 server_timer_handle = 0; +static u8 test_data_start; +#endif + +//--------------- +// 广播周期 (unit:0.625ms) +#define ADV_INTERVAL_MIN (160*5) + +#define HOLD_LATENCY_CNT_MIN (3) //(0~0xffff) +#define HOLD_LATENCY_CNT_MAX (15) //(0~0xffff) +#define HOLD_LATENCY_CNT_ALL (0xffff) + +static volatile hci_con_handle_t con_handle; + +//加密设置 +static const uint8_t sm_min_key_size = 7; + +//连接参数更新请求设置 +//是否使能参数请求更新,0--disable, 1--enable +static const uint8_t connection_update_enable = 1; ///0--disable, 1--enable +//当前请求的参数表index +static uint8_t connection_update_cnt = 0; // + +//参数表 +static const struct conn_update_param_t connection_param_table[] = { + {16, 24, 10, 600},//11 + {12, 28, 10, 600},//3.7 + {8, 20, 10, 600}, + /* {12, 28, 4, 600},//3.7 */ + /* {12, 24, 30, 600},//3.05 */ +}; + +//共可用的参数组数 +#define CONN_PARAM_TABLE_CNT (sizeof(connection_param_table)/sizeof(struct conn_update_param_t)) + +#if (ATT_RAM_BUFSIZE < 64) +#error "adv_data & rsp_data buffer error!!!!!!!!!!!!" +#endif + +//用户可配对的,这是样机跟客户开发的app配对的秘钥 +/* const u8 link_key_data[16] = {0x06, 0x77, 0x5f, 0x87, 0x91, 0x8d, 0xd4, 0x23, 0x00, 0x5d, 0xf1, 0xd8, 0xcf, 0x0c, 0x14, 0x2b}; */ +#define EIR_TAG_STRING 0xd6, 0x05, 0x08, 0x00, 'J', 'L', 'A', 'I', 'S', 'D','K' +static const char user_tag_string[] = {EIR_TAG_STRING}; + +static u8 adv_data_len; +static u8 adv_data[ADV_RSP_PACKET_MAX];//max is 31 +static u8 scan_rsp_data_len; +static u8 scan_rsp_data[ADV_RSP_PACKET_MAX];//max is 31 + +/* #define adv_data &att_ram_buffer[0] */ +/* #define scan_rsp_data &att_ram_buffer[32] */ + +static char gap_device_name[BT_NAME_LEN_MAX] = "jl_ble_test"; +static u8 gap_device_name_len = 0; //名字长度,不包含结束符 +static u8 ble_work_state = 0; //ble 状态变化 +static u8 adv_ctrl_en; //广播控制 + +static u8 test_read_write_buf[4]; + +static void (*app_recieve_callback)(void *priv, void *buf, u16 len) = NULL; +static void (*app_ble_state_callback)(void *priv, ble_state_e state) = NULL; +static void (*ble_resume_send_wakeup)(void) = NULL; +static u32 channel_priv; + +static int app_send_user_data_check(u16 len); +static int app_send_user_data_do(void *priv, u8 *data, u16 len); +static int app_send_user_data(u16 handle, u8 *data, u16 len, u8 handle_type); + +// Complete Local Name 默认的蓝牙名字 + +//------------------------------------------------------ +//广播参数设置 +static void advertisements_setup_init(); +static int set_adv_enable(void *priv, u32 en); +static int get_buffer_vaild_len(void *priv); +extern const char *bt_get_local_name(); +extern void clr_wdt(void); +extern void sys_auto_shut_down_disable(void); +extern void sys_auto_shut_down_enable(void); +extern u8 get_total_connect_dev(void); + +//------------------------------------------------------ +//NACS +#if TRANS_ANCS_EN +#define ANCS_SUBEVENT_CLIENT_NOTIFICATION 0xF1 +void ancs_client_init(void); +void ancs_client_register_callback(btstack_packet_handler_t callback); +const char *ancs_client_attribute_name_for_id(int id); +void ancs_set_notification_buffer(u8 *buffer, u16 buffer_size); + +//ancs info buffer +#define ANCS_INFO_BUFFER_SIZE (1024) +static u8 ancs_info_buffer[ANCS_INFO_BUFFER_SIZE]; +#endif + +//------------------------------------------------------ +#if TEST_AUDIO_DATA_UPLOAD +static const u8 test_audio_data_file[1024] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9 +}; + +#define AUDIO_ONE_PACKET_LEN 128 +static void test_send_audio_data(int init_flag) +{ + static u32 send_pt = 0; + static u32 start_flag = 0; + + if (!con_handle) { + return; + } + + if (init_flag) { + log_info("audio send init\n"); + send_pt = 0; + start_flag = 1; + } + + if (!start_flag) { + return; + } + + u32 file_size = sizeof(test_audio_data_file); + u8 *file_ptr = test_audio_data_file; + + if (send_pt >= file_size) { + log_info("audio send Complete\n"); + start_flag = 0; + return; + } + + u32 send_len = file_size - send_pt; + if (send_len > AUDIO_ONE_PACKET_LEN) { + send_len = AUDIO_ONE_PACKET_LEN; + } + + while (1) { + if (app_send_user_data_check(send_len)) { + log_info("audio send %08x\n", send_pt); + if (app_send_user_data(ATT_CHARACTERISTIC_ae3c_01_VALUE_HANDLE, &file_ptr[send_pt], send_len, ATT_OP_AUTO_READ_CCC)) { + log_info("audio send fail!\n"); + break; + } else { + send_pt += send_len; + } + } else { + break; + } + } +} + +#endif + + +static void send_request_connect_parameter(u8 table_index) +{ + struct conn_update_param_t *param = (void *)&connection_param_table[table_index];//static ram + + log_info("update_request:-%d-%d-%d-%d-\n", param->interval_min, param->interval_max, param->latency, param->timeout); + if (con_handle) { + ble_op_conn_param_request(con_handle, param); + } +} + +static void check_connetion_updata_deal(void) +{ + if (connection_update_enable) { + if (connection_update_cnt < CONN_PARAM_TABLE_CNT) { + send_request_connect_parameter(connection_update_cnt); + } + } +} + +static void connection_update_complete_success(u8 *packet) +{ + int con_handle, conn_interval, conn_latency, conn_timeout; + + con_handle = hci_subevent_le_connection_update_complete_get_connection_handle(packet); + conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet); + conn_latency = hci_subevent_le_connection_update_complete_get_conn_latency(packet); + conn_timeout = hci_subevent_le_connection_update_complete_get_supervision_timeout(packet); + + log_info("conn_interval = %d\n", conn_interval); + log_info("conn_latency = %d\n", conn_latency); + log_info("conn_timeout = %d\n", conn_timeout); +} + + +static void set_ble_work_state(ble_state_e state) +{ + if (state != ble_work_state) { + log_info("ble_work_st:%x->%x\n", ble_work_state, state); + ble_work_state = state; + if (app_ble_state_callback) { + app_ble_state_callback((void *)channel_priv, state); + } + } +} + +static ble_state_e get_ble_work_state(void) +{ + return ble_work_state; +} + +static void cbk_sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + sm_just_event_t *event = (void *)packet; + u32 tmp32; + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + case SM_EVENT_JUST_WORKS_REQUEST: + sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); + log_info("Just Works Confirmed.\n"); + break; + case SM_EVENT_PASSKEY_DISPLAY_NUMBER: + log_info_hexdump(packet, size); + memcpy(&tmp32, event->data, 4); + log_info("Passkey display: %06u.\n", tmp32); + break; + } + break; + } +} + + +#if TEST_SEND_DATA_RATE +static void server_timer_handler(void) +{ + if (!con_handle) { + test_data_count = 0; + test_data_start = 0; + return; + } + + log_info("peer_rssi = %d\n", ble_vendor_get_peer_rssi(con_handle)); + + if (test_data_count) { + log_info("\n%d bytes send: %d.%02d KB/s \n", test_data_count, test_data_count / 1000, test_data_count % 1000); + test_data_count = 0; + } +} + +static void server_timer_start(void) +{ + if (server_timer_handle) { + return; + } + + server_timer_handle = sys_timer_add(NULL, server_timer_handler, 1000); +} + +static void server_timer_stop(void) +{ + if (server_timer_handle) { + sys_timeout_del(server_timer_handle); + server_timer_handle = 0; + } +} + +void test_data_send_packet(void) +{ + u32 vaild_len = get_buffer_vaild_len(0);//获取发送buffer可写入的数据 + if (!test_data_start) { + return; + } + + if (vaild_len) { + if (!app_send_user_data(TEST_SEND_HANDLE_VAL, (void *)&test_data_count, vaild_len, ATT_OP_AUTO_READ_CCC)) { + test_data_count += vaild_len; + } + } + clr_wdt(); +} +#endif + + +static void can_send_now_wakeup(void) +{ + /* putchar('E'); */ + if (ble_resume_send_wakeup) { + ble_resume_send_wakeup(); + } + +#if TEST_SEND_DATA_RATE + test_data_send_packet(); +#endif + +#if TEST_AUDIO_DATA_UPLOAD + test_send_audio_data(0); +#endif + +} + +static void ble_auto_shut_down_enable(u8 enable) +{ +#if TCFG_AUTO_SHUT_DOWN_TIME + if (enable) { + if (get_total_connect_dev() == 0) { //已经没有设备连接 + sys_auto_shut_down_enable(); + } + } else { + sys_auto_shut_down_disable(); + } +#endif +} + +const char *const phy_result[] = { + "None", + "1M", + "2M", + "Coded", +}; + +static void set_connection_data_length(u16 tx_octets, u16 tx_time) +{ + if (con_handle) { + ble_op_set_data_length(con_handle, tx_octets, tx_time); + } +} + +static void set_connection_data_phy(u8 tx_phy, u8 rx_phy) +{ + if (0 == con_handle) { + return; + } + + u8 all_phys = 0; + u16 phy_options = CONN_SET_PHY_OPTIONS_S8; + + ble_op_set_ext_phy(con_handle, all_phys, tx_phy, rx_phy, phy_options); +} + +static void server_profile_start(u16 con_handle) +{ +#if BT_FOR_APP_EN + set_app_connect_type(TYPE_BLE); +#endif + ble_op_att_send_init(con_handle, att_ram_buffer, ATT_RAM_BUFSIZE, ATT_LOCAL_PAYLOAD_SIZE); + set_ble_work_state(BLE_ST_CONNECT); + ble_auto_shut_down_enable(0); + + /* set_connection_data_phy(CONN_SET_CODED_PHY, CONN_SET_CODED_PHY); */ +} + +_WEAK_ +u8 ble_update_get_ready_jump_flag(void) +{ + return 0; +} +/* + * @section Packet Handler + * + * @text The packet handler is used to: + * - stop the counter after a disconnect + * - send a notification when the requested ATT_EVENT_CAN_SEND_NOW is received + */ + +/* LISTING_START(packetHandler): Packet Handler */ +static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + int mtu; + u32 tmp; + u8 status; + const char *attribute_name; + + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + + /* case DAEMON_EVENT_HCI_PACKET_SENT: */ + /* break; */ + case ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE: + log_info("ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE\n"); + case ATT_EVENT_CAN_SEND_NOW: + can_send_now_wakeup(); + break; + + case HCI_EVENT_LE_META: + switch (hci_event_le_meta_get_subevent_code(packet)) { + case HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE: + status = hci_subevent_le_enhanced_connection_complete_get_status(packet); + if (status) { + log_info("LE_SLAVE CONNECTION FAIL!!! %0x\n", status); + set_ble_work_state(BLE_ST_DISCONN); + break; + } + con_handle = hci_subevent_le_enhanced_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE : %0x\n", con_handle); + log_info("conn_interval = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_interval(packet)); + log_info("conn_latency = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_latency(packet)); + log_info("conn_timeout = %d\n", hci_subevent_le_enhanced_connection_complete_get_supervision_timeout(packet)); + server_profile_start(con_handle); + break; + + case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: + con_handle = hci_subevent_le_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_CONNECTION_COMPLETE: %0x\n", con_handle); + connection_update_complete_success(packet + 8); + server_profile_start(con_handle); +#if RCSP_BTMATE_EN +#if (defined(BT_CONNECTION_VERIFY) && (0 == BT_CONNECTION_VERIFY)) + JL_rcsp_auth_reset(); +#endif + //rcsp_dev_select(RCSP_BLE); + rcsp_init(); +#endif + break; + + case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: + connection_update_complete_success(packet); + break; + + case HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE: + log_info("APP HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE\n"); + /* set_connection_data_phy(CONN_SET_CODED_PHY, CONN_SET_CODED_PHY); */ + break; + + case HCI_SUBEVENT_LE_PHY_UPDATE_COMPLETE: + log_info("APP HCI_SUBEVENT_LE_PHY_UPDATE %s\n", hci_event_le_meta_get_phy_update_complete_status(packet) ? "Fail" : "Succ"); + log_info("Tx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_tx_phy(packet)]); + log_info("Rx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_rx_phy(packet)]); + break; + } + break; + + case HCI_EVENT_DISCONNECTION_COMPLETE: + log_info("HCI_EVENT_DISCONNECTION_COMPLETE: %0x\n", packet[5]); +#if RCSP_BTMATE_EN + rcsp_exit(); +#endif + con_handle = 0; + ble_op_att_send_init(con_handle, 0, 0, 0); + set_ble_work_state(BLE_ST_DISCONN); + + if (!ble_update_get_ready_jump_flag()) { + bt_ble_adv_enable(1); + } + connection_update_cnt = 0; +#if BT_FOR_APP_EN + set_app_connect_type(TYPE_NULL); +#endif + ble_auto_shut_down_enable(1); + break; + + case ATT_EVENT_MTU_EXCHANGE_COMPLETE: + mtu = att_event_mtu_exchange_complete_get_MTU(packet) - 3; + log_info("ATT MTU = %u\n", mtu); + ble_op_att_set_send_mtu(mtu); + /* set_connection_data_length(251, 2120); */ + break; + + case HCI_EVENT_VENDOR_REMOTE_TEST: + log_info("--- HCI_EVENT_VENDOR_REMOTE_TEST\n"); + break; + + case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE: + tmp = little_endian_read_16(packet, 4); + log_info("-update_rsp: %02x\n", tmp); + if (tmp) { + connection_update_cnt++; + log_info("remoter reject!!!\n"); + check_connetion_updata_deal(); + } else { + connection_update_cnt = CONN_PARAM_TABLE_CNT; + } + break; + + case HCI_EVENT_ENCRYPTION_CHANGE: + log_info("HCI_EVENT_ENCRYPTION_CHANGE= %d\n", packet[2]); + break; + +#if TRANS_ANCS_EN + case HCI_EVENT_ANCS_META: + switch (hci_event_ancs_meta_get_subevent_code(packet)) { + case ANCS_SUBEVENT_CLIENT_NOTIFICATION: + printf("ANCS_SUBEVENT_CLIENT_NOTIFICATION \n"); + attribute_name = ancs_client_attribute_name_for_id(ancs_subevent_client_notification_get_attribute_id(packet)); + if (!attribute_name) { + printf("ancs unknow attribute_id :%d \n", ancs_subevent_client_notification_get_attribute_id(packet)); + break; + } else { + u16 attribute_strlen = little_endian_read_16(packet, 7); + u8 *attribute_str = (void *)little_endian_read_32(packet, 9); + printf("Notification: %s - %s \n", attribute_name, attribute_str); + } + break; + default: + break; + } + + break; +#endif + + } + break; + } +} + + +/* LISTING_END */ + +/* + * @section ATT Read + * + * @text The ATT Server handles all reads to constant data. For dynamic data like the custom characteristic, the registered + * att_read_callback is called. To handle long characteristics and long reads, the att_read_callback is first called + * with buffer == NULL, to request the total value length. Then it will be called again requesting a chunk of the value. + * See Listing attRead. + */ + +/* LISTING_START(attRead): ATT Read */ + +// ATT Client Read Callback for Dynamic Data +// - if buffer == NULL, don't copy data, just return size of value +// - if buffer != NULL, copy data and return number bytes copied +// @param offset defines start of attribute value +static uint16_t att_read_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t offset, uint8_t *buffer, uint16_t buffer_size) +{ + + uint16_t att_value_len = 0; + uint16_t handle = att_handle; + + log_info("read_callback, handle= 0x%04x,buffer= %08x\n", handle, (u32)buffer); + + switch (handle) { + case ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE: + att_value_len = gap_device_name_len; + + if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) { + break; + } + + if (buffer) { + memcpy(buffer, &gap_device_name[offset], buffer_size); + att_value_len = buffer_size; + log_info("\n------read gap_name: %s \n", gap_device_name); + } + break; + + case ATT_CHARACTERISTIC_ae10_01_VALUE_HANDLE: + att_value_len = sizeof(test_read_write_buf); + if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) { + break; + } + + if (buffer) { + memcpy(buffer, &test_read_write_buf[offset], buffer_size); + att_value_len = buffer_size; + } + break; + + case ATT_CHARACTERISTIC_ae04_01_CLIENT_CONFIGURATION_HANDLE: + case ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE: + case ATT_CHARACTERISTIC_ae05_01_CLIENT_CONFIGURATION_HANDLE: + case ATT_CHARACTERISTIC_ae3c_01_CLIENT_CONFIGURATION_HANDLE: + if (buffer) { + buffer[0] = att_get_ccc_config(handle); + buffer[1] = 0; + } + att_value_len = 2; + break; + + default: + break; + } + + log_info("att_value_len= %d\n", att_value_len); + return att_value_len; + +} + + +/* LISTING_END */ +/* + * @section ATT Write + * + * @text The only valid ATT write in this example is to the Client Characteristic Configuration, which configures notification + * and indication. If the ATT handle matches the client configuration handle, the new configuration value is stored and used + * in the heartbeat handler to decide if a new value should be sent. See Listing attWrite. + */ + +/* LISTING_START(attWrite): ATT Write */ +static int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size) +{ + int result = 0; + u16 tmp16; + + u16 handle = att_handle; + + log_info("write_callback, handle= 0x%04x,size = %d\n", handle, buffer_size); + + switch (handle) { + + case ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE: + break; + + case ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE: +#if TEST_SEND_DATA_RATE + if (buffer[0]) { + server_timer_start(); + } else { + server_timer_stop(); + test_data_start = 0; + } +#endif + case ATT_CHARACTERISTIC_ae04_01_CLIENT_CONFIGURATION_HANDLE: + case ATT_CHARACTERISTIC_ae05_01_CLIENT_CONFIGURATION_HANDLE: + case ATT_CHARACTERISTIC_ae3c_01_CLIENT_CONFIGURATION_HANDLE: + set_ble_work_state(BLE_ST_NOTIFY_IDICATE); + check_connetion_updata_deal(); + log_info("\n------write ccc:%04x,%02x\n", handle, buffer[0]); + att_set_ccc_config(handle, buffer[0]); + +#if TEST_SEND_DATA_RATE + test_data_start = 1;//start + if (buffer[0]) { + test_data_send_packet(); + } +#endif + break; + + case ATT_CHARACTERISTIC_ae10_01_VALUE_HANDLE: + tmp16 = sizeof(test_read_write_buf); + if ((offset >= tmp16) || (offset + buffer_size) > tmp16) { + break; + } + memcpy(&test_read_write_buf[offset], buffer, buffer_size); + break; + + case ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE: + printf("\n-ae01_rx(%d):", buffer_size); + printf_buf(buffer, buffer_size); + + //收发测试,自动发送收到的数据;for test + if (app_send_user_data_check(buffer_size)) { + app_send_user_data(ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE, buffer, buffer_size, ATT_OP_AUTO_READ_CCC); + } + +#if TEST_SEND_DATA_RATE + if ((buffer[0] == 'A') && (buffer[1] == 'F')) { + test_data_start = 1;//start + } else if ((buffer[0] == 'A') && (buffer[1] == 'A')) { + test_data_start = 0;//stop + } +#endif + break; + + case ATT_CHARACTERISTIC_ae03_01_VALUE_HANDLE: + printf("\n-ae_rx(%d):", buffer_size); + printf_buf(buffer, buffer_size); + + //收发测试,自动发送收到的数据;for test + if (app_send_user_data_check(buffer_size)) { + app_send_user_data(ATT_CHARACTERISTIC_ae05_01_VALUE_HANDLE, buffer, buffer_size, ATT_OP_AUTO_READ_CCC); + } + break; + +#if RCSP_BTMATE_EN + case ATT_CHARACTERISTIC_ae02_02_CLIENT_CONFIGURATION_HANDLE: + ble_op_latency_skip(con_handle, HOLD_LATENCY_CNT_ALL); // + set_ble_work_state(BLE_ST_NOTIFY_IDICATE); +#endif + /* if ((cur_conn_latency == 0) */ + /* && (connection_update_cnt == CONN_PARAM_TABLE_CNT) */ + /* && (Peripheral_Preferred_Connection_Parameters[0].latency != 0)) { */ + /* connection_update_cnt = 0; */ + /* } */ + check_connetion_updata_deal(); + log_info("\n------write ccc:%04x,%02x\n", handle, buffer[0]); + att_set_ccc_config(handle, buffer[0]); + break; +#if RCSP_BTMATE_EN + case ATT_CHARACTERISTIC_ae01_02_VALUE_HANDLE: + printf("rcsp_read:%x\n", buffer_size); + if (app_recieve_callback) { + app_recieve_callback(0, buffer, buffer_size); + } + break; +#endif + + case ATT_CHARACTERISTIC_ae3b_01_VALUE_HANDLE: + printf("\n-ae3b_rx(%d):", buffer_size); + printf_buf(buffer, buffer_size); + +#if TEST_AUDIO_DATA_UPLOAD + if (0 == memcmp(buffer, "start", 5)) { + test_send_audio_data(1); + } +#endif + break; + + default: + break; + } + + return 0; +} + +static int app_send_user_data(u16 handle, u8 *data, u16 len, u8 handle_type) +{ + u32 ret = APP_BLE_NO_ERROR; + + if (!con_handle) { + return APP_BLE_OPERATION_ERROR; + } + + if (!att_get_ccc_config(handle + 1)) { + log_info("fail,no write ccc!!!,%04x\n", handle + 1); + return APP_BLE_NO_WRITE_CCC; + } + + ret = ble_op_att_send_data(handle, data, len, handle_type); + if (ret == BLE_BUFFER_FULL) { + ret = APP_BLE_BUFF_FULL; + } + + if (ret) { + log_info("app_send_fail:%d !!!!!!\n", ret); + } + return ret; +} + +//------------------------------------------------------ +static int make_set_adv_data(void) +{ + u8 offset = 0; + u8 *buf = adv_data; + + + /* offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_FLAGS, 0x18, 1); */ + /* offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_FLAGS, 0x1A, 1); */ + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_FLAGS, 0x06, 1); + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_16BIT_SERVICE_UUIDS, 0xAF30, 2); + + if (offset > ADV_RSP_PACKET_MAX) { + puts("***adv_data overflow!!!!!!\n"); + return -1; + } + log_info("adv_data(%d):", offset); + log_info_hexdump(buf, offset); + adv_data_len = offset; + ble_op_set_adv_data(offset, buf); + return 0; +} + +static int make_set_rsp_data(void) +{ + u8 offset = 0; + u8 *buf = scan_rsp_data; + +#if RCSP_BTMATE_EN + u8 tag_len = sizeof(user_tag_string); + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA, (void *)user_tag_string, tag_len); +#endif + + u8 name_len = gap_device_name_len; + u8 vaild_len = ADV_RSP_PACKET_MAX - (offset + 2); + if (name_len > vaild_len) { + name_len = vaild_len; + } + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME, (void *)gap_device_name, name_len); + + if (offset > ADV_RSP_PACKET_MAX) { + puts("***rsp_data overflow!!!!!!\n"); + return -1; + } + + log_info("rsp_data(%d):", offset); + log_info_hexdump(buf, offset); + scan_rsp_data_len = offset; + ble_op_set_rsp_data(offset, buf); + return 0; +} + +//广播参数设置 +static void advertisements_setup_init() +{ + uint8_t adv_type = ADV_IND; + uint8_t adv_channel = ADV_CHANNEL_ALL; + int ret = 0; + + ble_op_set_adv_param(ADV_INTERVAL_MIN, adv_type, adv_channel); + + ret |= make_set_adv_data(); + ret |= make_set_rsp_data(); + + if (ret) { + puts("advertisements_setup_init fail !!!!!!\n"); + return; + } + +} + +#define PASSKEY_ENTER_ENABLE 0 //输入passkey使能,可修改passkey +//重设passkey回调函数,在这里可以重新设置passkey +//passkey为6个数字组成,十万位、万位。。。。个位 各表示一个数字 高位不够为0 +static void reset_passkey_cb(u32 *key) +{ +#if 1 + u32 newkey = rand32();//获取随机数 + + newkey &= 0xfffff; + if (newkey > 999999) { + newkey = newkey - 999999; //不能大于999999 + } + *key = newkey; //小于或等于六位数 + printf("set new_key= %06u\n", *key); +#else + *key = 123456; //for debug +#endif +} + +void ble_sm_setup_init(io_capability_t io_type, u8 auth_req, uint8_t min_key_size, u8 security_en) +{ + //setup SM: Display only + sm_init(); + sm_set_io_capabilities(io_type); + sm_set_authentication_requirements(auth_req); + sm_set_encryption_key_size_range(min_key_size, 16); + sm_set_request_security(security_en); + sm_event_callback_set(&cbk_sm_packet_handler); + + if (io_type == IO_CAPABILITY_DISPLAY_ONLY) { + reset_PK_cb_register(reset_passkey_cb); + } +} + + +void ble_profile_init(void) +{ + printf("ble profile init\n"); + le_device_db_init(); + +#if PASSKEY_ENTER_ENABLE + ble_sm_setup_init(IO_CAPABILITY_DISPLAY_ONLY, SM_AUTHREQ_MITM_PROTECTION, 7, TCFG_BLE_SECURITY_EN); +#else + ble_sm_setup_init(IO_CAPABILITY_NO_INPUT_NO_OUTPUT, SM_AUTHREQ_BONDING, 7, TCFG_BLE_SECURITY_EN); +#endif + + /* setup ATT server */ + att_server_init(profile_data, att_read_callback, att_write_callback); + att_server_register_packet_handler(cbk_packet_handler); + /* gatt_client_register_packet_handler(packet_cbk); */ + + // register for HCI events + hci_event_callback_set(&cbk_packet_handler); + /* ble_l2cap_register_packet_handler(packet_cbk); */ + /* sm_event_packet_handler_register(packet_cbk); */ + le_l2cap_register_packet_handler(&cbk_packet_handler); + +#if TRANS_ANCS_EN + //setup GATT client + gatt_client_init(); + + //setup ANCS clent + ancs_client_init(); + ancs_set_notification_buffer(ancs_info_buffer, sizeof(ancs_info_buffer)); + ancs_client_register_callback(&cbk_packet_handler); +#endif + +} + +#if EXT_ADV_MODE_EN + + +#define EXT_ADV_NAME 'J', 'L', '_', 'E', 'X', 'T', '_', 'A', 'D', 'V' +/* #define EXT_ADV_NAME "JL_EXT_ADV" */ +#define BYTE_LEN(x...) sizeof((u8 []) {x}) +#define EXT_ADV_DATA \ + 0x02, 0x01, 0x06, \ + 0x03, 0x02, 0xF0, 0xFF, \ + BYTE_LEN(EXT_ADV_NAME) + 1, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, EXT_ADV_NAME + +struct ext_advertising_param { + u8 Advertising_Handle; + u16 Advertising_Event_Properties; + u8 Primary_Advertising_Interval_Min[3]; + u8 Primary_Advertising_Interval_Max[3]; + u8 Primary_Advertising_Channel_Map; + u8 Own_Address_Type; + u8 Peer_Address_Type; + u8 Peer_Address[6]; + u8 Advertising_Filter_Policy; + u8 Advertising_Tx_Power; + u8 Primary_Advertising_PHY; + u8 Secondary_Advertising_Max_Skip; + u8 Secondary_Advertising_PHY; + u8 Advertising_SID; + u8 Scan_Request_Notification_Enable; +} _GNU_PACKED_; + +struct ext_advertising_data { + u8 Advertising_Handle; + u8 Operation; + u8 Fragment_Preference; + u8 Advertising_Data_Length; + u8 Advertising_Data[BYTE_LEN(EXT_ADV_DATA)]; +} _GNU_PACKED_; + +struct ext_advertising_enable { + u8 Enable; + u8 Number_of_Sets; + u8 Advertising_Handle; + u16 Duration; + u8 Max_Extended_Advertising_Events; +} _GNU_PACKED_; + +const struct ext_advertising_param ext_adv_param = { + .Advertising_Handle = 0, + .Advertising_Event_Properties = 1, + .Primary_Advertising_Interval_Min = {30, 0, 0}, + .Primary_Advertising_Interval_Max = {30, 0, 0}, + .Primary_Advertising_Channel_Map = 7, + .Primary_Advertising_PHY = ADV_SET_1M_PHY, + .Secondary_Advertising_PHY = ADV_SET_1M_PHY, +}; + +const struct ext_advertising_data ext_adv_data = { + .Advertising_Handle = 0, + .Operation = 3, + .Fragment_Preference = 0, + .Advertising_Data_Length = BYTE_LEN(EXT_ADV_DATA), + .Advertising_Data = EXT_ADV_DATA, +}; + +const struct ext_advertising_enable ext_adv_enable = { + .Enable = 1, + .Number_of_Sets = 1, + .Advertising_Handle = 0, + .Duration = 0, + .Max_Extended_Advertising_Events = 0, +}; + +const struct ext_advertising_enable ext_adv_disable = { + .Enable = 0, + .Number_of_Sets = 1, + .Advertising_Handle = 0, + .Duration = 0, + .Max_Extended_Advertising_Events = 0, +}; + +#endif /* EXT_ADV_MODE_EN */ + +static int set_adv_enable(void *priv, u32 en) +{ + ble_state_e next_state, cur_state; + + if (!adv_ctrl_en) { + return APP_BLE_OPERATION_ERROR; + } + + if (con_handle) { + return APP_BLE_OPERATION_ERROR; + } + + if (en) { + next_state = BLE_ST_ADV; + } else { + next_state = BLE_ST_IDLE; + } + + cur_state = get_ble_work_state(); + switch (cur_state) { + case BLE_ST_ADV: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + break; + default: + return APP_BLE_OPERATION_ERROR; + break; + } + + if (cur_state == next_state) { + return APP_BLE_NO_ERROR; + } + log_info("adv_en:%d\n", en); + set_ble_work_state(next_state); + +#if EXT_ADV_MODE_EN + if (en) { + ble_op_set_ext_adv_param(&ext_adv_param, sizeof(ext_adv_param)); + + log_info_hexdump(&ext_adv_data, sizeof(ext_adv_data)); + ble_op_set_ext_adv_data(&ext_adv_data, sizeof(ext_adv_data)); + + ble_op_set_ext_adv_enable(&ext_adv_enable, sizeof(ext_adv_enable)); + } else { + ble_op_set_ext_adv_enable(&ext_adv_disable, sizeof(ext_adv_disable)); + } +#else + if (en) { + advertisements_setup_init(); + } + ble_op_adv_enable(en); +#endif /* EXT_ADV_MODE_EN */ + + return APP_BLE_NO_ERROR; +} + +static int ble_disconnect(void *priv) +{ + if (con_handle) { + if (BLE_ST_SEND_DISCONN != get_ble_work_state()) { + log_info(">>>ble send disconnect\n"); + set_ble_work_state(BLE_ST_SEND_DISCONN); + ble_op_disconnect(con_handle); + } else { + log_info(">>>ble wait disconnect...\n"); + } + return APP_BLE_NO_ERROR; + } else { + return APP_BLE_OPERATION_ERROR; + } +} + + +static int get_buffer_vaild_len(void *priv) +{ + u32 vaild_len = 0; + ble_op_att_get_remain(&vaild_len); + return vaild_len; +} + +static int app_send_user_data_do(void *priv, u8 *data, u16 len) +{ +#if PRINT_DMA_DATA_EN + if (len < 128) { + log_info("-le_tx(%d):"); + log_info_hexdump(data, len); + } else { + putchar('L'); + } +#endif + return app_send_user_data(ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE, data, len, ATT_OP_AUTO_READ_CCC); +} + +static int app_send_user_data_check(u16 len) +{ + u32 buf_space = get_buffer_vaild_len(0); + if (len <= buf_space) { + return 1; + } + return 0; +} + + +static int regiest_wakeup_send(void *priv, void *cbk) +{ + ble_resume_send_wakeup = cbk; + return APP_BLE_NO_ERROR; +} + +static int regiest_recieve_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_recieve_callback = cbk; + return APP_BLE_NO_ERROR; +} + +static int regiest_state_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_ble_state_callback = cbk; + return APP_BLE_NO_ERROR; +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + + +u8 *ble_get_scan_rsp_ptr(u16 *len) +{ + if (len) { + *len = scan_rsp_data_len; + } + return scan_rsp_data; +} + +u8 *ble_get_adv_data_ptr(u16 *len) +{ + if (len) { + *len = adv_data_len; + } + return adv_data; +} + +u8 *ble_get_gatt_profile_data(u16 *len) +{ + *len = sizeof(profile_data); + return (u8 *)profile_data; +} + + +void bt_ble_adv_enable(u8 enable) +{ + set_adv_enable(0, enable); +} + +u16 bt_ble_is_connected(void) +{ + return con_handle; +} + +void ble_module_enable(u8 en) +{ + log_info("mode_en:%d\n", en); + if (en) { + adv_ctrl_en = 1; + bt_ble_adv_enable(1); + } else { + if (con_handle) { + adv_ctrl_en = 0; + ble_disconnect(NULL); + } else { + bt_ble_adv_enable(0); + adv_ctrl_en = 0; + } + } +} + +static const char ble_ext_name[] = "(BLE)"; + +void bt_ble_init(void) +{ + log_info("***** ble_init******\n"); + char *name_p; + u8 ext_name_len = sizeof(ble_ext_name) - 1; + + name_p = bt_get_local_name(); + gap_device_name_len = strlen(name_p); + if (gap_device_name_len > BT_NAME_LEN_MAX - ext_name_len) { + gap_device_name_len = BT_NAME_LEN_MAX - ext_name_len; + } + + //增加后缀,区分名字 + memcpy(gap_device_name, name_p, gap_device_name_len); + memcpy(&gap_device_name[gap_device_name_len], "(BLE)", ext_name_len); + gap_device_name_len += ext_name_len; + + log_info("ble name(%d): %s \n", gap_device_name_len, gap_device_name); + + set_ble_work_state(BLE_ST_INIT_OK); + ble_module_enable(1); + +#if TEST_SEND_DATA_RATE + server_timer_start(); +#endif +} + +void bt_ble_exit(void) +{ + log_info("***** ble_exit******\n"); + + ble_module_enable(0); + +#if TEST_SEND_DATA_RATE + server_timer_stop(); +#endif + +} + + +void ble_app_disconnect(void) +{ + ble_disconnect(NULL); +} + +#if RCSP_BTMATE_EN +static int rcsp_send_user_data_do(void *priv, u8 *data, u16 len) +{ + log_info("rcsp_tx:%x\n", len); +#if PRINT_DMA_DATA_EN + if (len < 128) { + log_info("-dma_tx(%d):"); + log_info_hexdump(data, len); + } else { + putchar('L'); + } +#endif + return app_send_user_data(ATT_CHARACTERISTIC_ae02_02_VALUE_HANDLE, data, len, ATT_OP_AUTO_READ_CCC); +} +#endif + +#if RCSP_BTMATE_EN +static const struct ble_server_operation_t mi_ble_operation = { + .adv_enable = set_adv_enable, + .disconnect = ble_disconnect, + .get_buffer_vaild = get_buffer_vaild_len, + .send_data = (void *)rcsp_send_user_data_do, + .regist_wakeup_send = regiest_wakeup_send, + .regist_recieve_cbk = regiest_recieve_cbk, + .regist_state_cbk = regiest_state_cbk, +}; +#else +static const struct ble_server_operation_t mi_ble_operation = { + .adv_enable = set_adv_enable, + .disconnect = ble_disconnect, + .get_buffer_vaild = get_buffer_vaild_len, + .send_data = (void *)app_send_user_data_do, + .regist_wakeup_send = regiest_wakeup_send, + .regist_recieve_cbk = regiest_recieve_cbk, + .regist_state_cbk = regiest_state_cbk, +}; +#endif + +void ble_get_server_operation_table(struct ble_server_operation_t **interface_pt) +{ + *interface_pt = (void *)&mi_ble_operation; +} + +void ble_server_send_test_key_num(u8 key_num) +{ + ; +} + +#endif + + diff --git a/apps/common/third_party_profile/jieli/trans_data_demo/le_trans_data.h b/apps/common/third_party_profile/jieli/trans_data_demo/le_trans_data.h new file mode 100644 index 0000000..355152a --- /dev/null +++ b/apps/common/third_party_profile/jieli/trans_data_demo/le_trans_data.h @@ -0,0 +1,189 @@ +// binary representation +// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) + +#ifndef _LE_TRANS_DATA_H +#define _LE_TRANS_DATA_H + +#include +#include "app_config.h" +// +// gatt profile include file, generated by jieli gatt_inc_generator.exe +// + +static const uint8_t profile_data[] = { + ////////////////////////////////////////////////////// + // + // 0x0001 PRIMARY_SERVICE 1800 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x18, + + /* CHARACTERISTIC, 2a00, READ | WRITE | DYNAMIC, */ + // 0x0002 CHARACTERISTIC 2a00 READ | WRITE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x0a, 0x03, 0x00, 0x00, 0x2a, + // 0x0003 VALUE 2a00 READ | WRITE | DYNAMIC + 0x08, 0x00, 0x0a, 0x01, 0x03, 0x00, 0x00, 0x2a, + + ////////////////////////////////////////////////////// + // + // 0x0004 PRIMARY_SERVICE ae30 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x28, 0x30, 0xae, + + /* CHARACTERISTIC, ae01, WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x0005 CHARACTERISTIC ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x05, 0x00, 0x03, 0x28, 0x04, 0x06, 0x00, 0x01, 0xae, + // 0x0006 VALUE ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x08, 0x00, 0x04, 0x01, 0x06, 0x00, 0x01, 0xae, + + /* CHARACTERISTIC, ae02, NOTIFY, */ + // 0x0007 CHARACTERISTIC ae02 NOTIFY + 0x0d, 0x00, 0x02, 0x00, 0x07, 0x00, 0x03, 0x28, 0x10, 0x08, 0x00, 0x02, 0xae, + // 0x0008 VALUE ae02 NOTIFY + 0x08, 0x00, 0x10, 0x00, 0x08, 0x00, 0x02, 0xae, + // 0x0009 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x09, 0x00, 0x02, 0x29, 0x00, 0x00, + + /* CHARACTERISTIC, ae03, WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x000a CHARACTERISTIC ae03 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x03, 0x28, 0x04, 0x0b, 0x00, 0x03, 0xae, + // 0x000b VALUE ae03 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x08, 0x00, 0x04, 0x01, 0x0b, 0x00, 0x03, 0xae, + + /* CHARACTERISTIC, ae04, NOTIFY, */ + // 0x000c CHARACTERISTIC ae04 NOTIFY + 0x0d, 0x00, 0x02, 0x00, 0x0c, 0x00, 0x03, 0x28, 0x10, 0x0d, 0x00, 0x04, 0xae, + // 0x000d VALUE ae04 NOTIFY + 0x08, 0x00, 0x10, 0x00, 0x0d, 0x00, 0x04, 0xae, + // 0x000e CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x0e, 0x00, 0x02, 0x29, 0x00, 0x00, + + /* CHARACTERISTIC, ae05, INDICATE, */ + // 0x000f CHARACTERISTIC ae05 INDICATE + 0x0d, 0x00, 0x02, 0x00, 0x0f, 0x00, 0x03, 0x28, 0x20, 0x10, 0x00, 0x05, 0xae, + // 0x0010 VALUE ae05 INDICATE + 0x08, 0x00, 0x20, 0x00, 0x10, 0x00, 0x05, 0xae, + // 0x0011 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x11, 0x00, 0x02, 0x29, 0x00, 0x00, + + /* CHARACTERISTIC, ae10, READ | WRITE | DYNAMIC, */ + // 0x0012 CHARACTERISTIC ae10 READ | WRITE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x12, 0x00, 0x03, 0x28, 0x0a, 0x13, 0x00, 0x10, 0xae, + // 0x0013 VALUE ae10 READ | WRITE | DYNAMIC + 0x08, 0x00, 0x0a, 0x01, 0x13, 0x00, 0x10, 0xae, + + +#if 0 + //for uuid128,sample + // PRIMARY_SERVICE, 0000F530-1212-EFDE-1523-785FEABCD123 + // CHARACTERISTIC, 0000F531-1212-EFDE-1523-785FEABCD123, NOTIFY, + // CHARACTERISTIC, 0000F532-1212-EFDE-1523-785FEABCD123, WRITE_WITHOUT_RESPONSE | DYNAMIC, + + ////////////////////////////////////////////////////// + // + // 0x0014 PRIMARY_SERVICE 0000F530-1212-EFDE-1523-785FEABCD123 + // + ////////////////////////////////////////////////////// + 0x18, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x28, 0x23, 0xd1, 0xbc, 0xea, 0x5f, 0x78, 0x23, 0x15, 0xde, 0xef, 0x12, 0x12, 0x30, 0xf5, 0x00, 0x00, + + /* CHARACTERISTIC, 0000F531-1212-EFDE-1523-785FEABCD123, NOTIFY, */ + // 0x0015 CHARACTERISTIC 0000F531-1212-EFDE-1523-785FEABCD123 NOTIFY + 0x1b, 0x00, 0x02, 0x00, 0x15, 0x00, 0x03, 0x28, 0x10, 0x16, 0x00, 0x23, 0xd1, 0xbc, 0xea, 0x5f, 0x78, 0x23, 0x15, 0xde, 0xef, 0x12, 0x12, 0x31, 0xf5, 0x00, 0x00, + // 0x0016 VALUE 0000F531-1212-EFDE-1523-785FEABCD123 NOTIFY + 0x16, 0x00, 0x10, 0x02, 0x16, 0x00, 0x23, 0xd1, 0xbc, 0xea, 0x5f, 0x78, 0x23, 0x15, 0xde, 0xef, 0x12, 0x12, 0x31, 0xf5, 0x00, 0x00, + // 0x0017 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x17, 0x00, 0x02, 0x29, 0x00, 0x00, + + /* CHARACTERISTIC, 0000F532-1212-EFDE-1523-785FEABCD123, WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x0018 CHARACTERISTIC 0000F532-1212-EFDE-1523-785FEABCD123 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x1b, 0x00, 0x02, 0x00, 0x18, 0x00, 0x03, 0x28, 0x04, 0x19, 0x00, 0x23, 0xd1, 0xbc, 0xea, 0x5f, 0x78, 0x23, 0x15, 0xde, 0xef, 0x12, 0x12, 0x32, 0xf5, 0x00, 0x00, + // 0x0019 VALUE 0000F532-1212-EFDE-1523-785FEABCD123 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x16, 0x00, 0x04, 0x03, 0x19, 0x00, 0x23, 0xd1, 0xbc, 0xea, 0x5f, 0x78, 0x23, 0x15, 0xde, 0xef, 0x12, 0x12, 0x32, 0xf5, 0x00, 0x00, +#endif + + ////////////////////////////////////////////////////// + // + // 0x0014 PRIMARY_SERVICE 1812 + // + ////////////////////////////////////////////////////// + // 0x0a, 0x00, 0x02, 0x00, 0x34, 0x00, 0x00, 0x28, 0x12, 0x18,//ios app can't disconn + +#if 0// authentication + // + 10, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x28, 0x0A, 0x18, //primary service declaration + 13, 0x00, 0x02, 0x00, 0x1B, 0x00, 0x03, 0x28, 0x02, 0x1C, 0x00, 0x50, 0x2A, //characteristic declaration + 15, 0x00, 0x02, 0x04, 0x1C, 0x00, 0x50, 0x2A, 0x02, 0x8A, 0x24, 0x66, 0x82, 0x34, 0x36, //PnP ID +#endif + + ////////////////////////////////////////////////////// + // + // 0x0040 PRIMARY_SERVICE ae3a + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x40, 0x00, 0x00, 0x28, 0x3a, 0xae, + + /* CHARACTERISTIC, ae3b, WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x0041 CHARACTERISTIC ae3b WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x41, 0x00, 0x03, 0x28, 0x04, 0x42, 0x00, 0x3b, 0xae, + // 0x0042 VALUE ae3b WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x08, 0x00, 0x04, 0x01, 0x42, 0x00, 0x3b, 0xae, + + /* CHARACTERISTIC, ae3c, NOTIFY, */ + // 0x0043 CHARACTERISTIC ae3c NOTIFY + 0x0d, 0x00, 0x02, 0x00, 0x43, 0x00, 0x03, 0x28, 0x10, 0x44, 0x00, 0x3c, 0xae, + // 0x0044 VALUE ae3c NOTIFY + 0x08, 0x00, 0x10, 0x00, 0x44, 0x00, 0x3c, 0xae, + // 0x0045 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x45, 0x00, 0x02, 0x29, 0x00, 0x00, + +#if RCSP_BTMATE_EN + ////////////////////////////////////////////////////// + // + // 0x0004 PRIMARY_SERVICE ae00 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x28, 0x00, 0xae, + + /* CHARACTERISTIC, ae01, WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x0040 CHARACTERISTIC ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x81, 0x00, 0x03, 0x28, 0x04, 0x82, 0x00, 0x01, 0xae, + // 0x0041 VALUE ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x08, 0x00, 0x04, 0x01, 0x82, 0x00, 0x01, 0xae, + + /* CHARACTERISTIC, ae02, NOTIFY, */ + // 0x0042 CHARACTERISTIC ae02 NOTIFY + 0x0d, 0x00, 0x02, 0x00, 0x83, 0x00, 0x03, 0x28, 0x10, 0x84, 0x00, 0x02, 0xae, + // 0x0043 VALUE ae02 NOTIFY + 0x08, 0x00, 0x10, 0x00, 0x84, 0x00, 0x02, 0xae, + // 0x0044 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x85, 0x00, 0x02, 0x29, 0x00, 0x00, +#endif + // END + 0x00, 0x00, +}; +// +// characteristics <--> handles +// +#if RCSP_BTMATE_EN +#define ATT_CHARACTERISTIC_ae01_02_VALUE_HANDLE 0x0082 +#define ATT_CHARACTERISTIC_ae02_02_VALUE_HANDLE 0x0084 +#define ATT_CHARACTERISTIC_ae02_02_CLIENT_CONFIGURATION_HANDLE 0x0085 +#endif + +#define ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE 0x0003 +#define ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE 0x0006 +#define ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE 0x0008 +#define ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE 0x0009 +#define ATT_CHARACTERISTIC_ae03_01_VALUE_HANDLE 0x000b +#define ATT_CHARACTERISTIC_ae04_01_VALUE_HANDLE 0x000d +#define ATT_CHARACTERISTIC_ae04_01_CLIENT_CONFIGURATION_HANDLE 0x000e +#define ATT_CHARACTERISTIC_ae05_01_VALUE_HANDLE 0x0010 +#define ATT_CHARACTERISTIC_ae05_01_CLIENT_CONFIGURATION_HANDLE 0x0011 +#define ATT_CHARACTERISTIC_ae10_01_VALUE_HANDLE 0x0013 + +#define ATT_CHARACTERISTIC_ae3b_01_VALUE_HANDLE 0x0042 +#define ATT_CHARACTERISTIC_ae3c_01_VALUE_HANDLE 0x0044 +#define ATT_CHARACTERISTIC_ae3c_01_CLIENT_CONFIGURATION_HANDLE 0x0045 + +#endif diff --git a/apps/common/third_party_profile/jieli/trans_data_demo/spp_trans_data.c b/apps/common/third_party_profile/jieli/trans_data_demo/spp_trans_data.c new file mode 100644 index 0000000..02e5b4c --- /dev/null +++ b/apps/common/third_party_profile/jieli/trans_data_demo/spp_trans_data.c @@ -0,0 +1,200 @@ + +#include "app_config.h" +#include "app_action.h" + +#include "system/includes.h" +#include "spp_user.h" +#include "string.h" +#include "circular_buf.h" +#include "spp_trans_data.h" +#include "bt_common.h" +#include "btstack/avctp_user.h" + +#if 1 +extern void printf_buf(u8 *buf, u32 len); +#define log_info printf +#define log_info_hexdump printf_buf +#else +#define log_info(...) +#define log_info_hexdump(...) +#endif + +#define TEST_SPP_DATA_RATE 0 + +/* #define DEBUG_ENABLE */ +/* #include "debug_log.h" */ +#include "spp_trans_data.h" +#if TRANS_DATA_EN + +#if TEST_SPP_DATA_RATE +#define SPP_TIMER_MS (100) +static u32 test_data_count; +static u32 spp_timer_handle = 0; +static u32 spp_test_start; +#endif + +#define SPP_DATA_RECIEVT_FLOW 0//流控功能使能 + +void rfcomm_change_credits_setting(u16 init_credits, u8 base); +int rfcomm_send_cretits_by_profile(u16 rfcomm_cid, u16 credit, u8 auto_flag); + +static struct spp_operation_t *spp_api = NULL; +static u8 spp_state; +static u16 spp_channel; + +int transport_spp_send_data(u8 *data, u16 len) +{ + if (spp_api) { + log_info("spp_api_tx(%d) \n", len); + /* log_info_hexdump(data, len); */ + clear_sniff_cnt(); + return spp_api->send_data(NULL, data, len); + } + return SPP_USER_ERR_SEND_FAIL; +} + +int transport_spp_send_data_check(u16 len) +{ + if (spp_api) { + if (spp_api->busy_state()) { + return 0; + } + } + return 1; +} + +static void transport_spp_state_cbk(u8 state) +{ + spp_state = state; + switch (state) { + case SPP_USER_ST_CONNECT: + log_info("SPP_USER_ST_CONNECT ~~~\n"); + + break; + + case SPP_USER_ST_DISCONN: + log_info("SPP_USER_ST_DISCONN ~~~\n"); + spp_channel = 0; + + break; + + default: + break; + } + +} + +static void transport_spp_send_wakeup(void) +{ + putchar('W'); +} + +static void transport_spp_recieve_cbk(void *priv, u8 *buf, u16 len) +{ + spp_channel = (u16)priv; + log_info("spp_api_rx(%d) \n", len); + log_info_hexdump(buf, len); + clear_sniff_cnt(); + +#if TEST_SPP_DATA_RATE + if ((buf[0] == 'A') && (buf[1] == 'F')) { + spp_test_start = 1;//start + } else if ((buf[0] == 'A') && (buf[1] == 'A')) { + spp_test_start = 0;//stop + } +#endif + + //loop send data for test + if (transport_spp_send_data_check(len)) { + transport_spp_send_data(buf, len); + } +} + + +#if TEST_SPP_DATA_RATE + +static void test_spp_send_data(void) +{ + u16 send_len = 250; + if (transport_spp_send_data_check(send_len)) { + test_data_count += send_len; + transport_spp_send_data(&test_data_count, send_len); + } +} + +static void test_timer_handler(void) +{ + static u32 t_count = 0; + + if (SPP_USER_ST_CONNECT != spp_state) { + test_data_count = 0; + spp_test_start = 0; + return; + } + + if (spp_test_start) { + test_spp_send_data(); + } + + if (++t_count < (1000 / SPP_TIMER_MS)) { + return; + } + t_count = 0; + + if (test_data_count) { + log_info("\n-spp_data_rate: %d bps-\n", test_data_count * 8); + test_data_count = 0; + } +} +#endif + + +void transport_spp_init(void) +{ + log_info("transport_spp_init\n"); +#if (USER_SUPPORT_PROFILE_SPP==1) + spp_state = 0; + spp_get_operation_table(&spp_api); + spp_api->regist_recieve_cbk(0, transport_spp_recieve_cbk); + spp_api->regist_state_cbk(0, transport_spp_state_cbk); + spp_api->regist_wakeup_send(NULL, transport_spp_send_wakeup); +#endif + +#if TEST_SPP_DATA_RATE + spp_timer_handle = sys_timer_add(NULL, test_timer_handler, SPP_TIMER_MS); +#endif + +} + +void transport_spp_disconnect(void) +{ + if (SPP_USER_ST_CONNECT == spp_state) { + log_info("transport_spp_disconnect\n"); + user_send_cmd_prepare(USER_CTRL_SPP_DISCONNECT, 0, NULL); + } +} + +void transport_spp_flow_cfg(void) +{ +#if SPP_DATA_RECIEVT_FLOW + rfcomm_change_credits_setting(1, 1); +#endif +} + +//流控使能 EN: 1 or 0 +int transport_spp_flow_enable(u8 en) +{ + int ret = -1; + +#if SPP_DATA_RECIEVT_FLOW + if (spp_channel) { + ret = rfcomm_send_cretits_by_profile(spp_channel, 1, !en); + } +#endif + + log_info("transport_spp_flow_enable:%02x,%d,%d\n", spp_channel, en, ret); + return ret; +} + +#endif + diff --git a/apps/common/third_party_profile/jieli/trans_data_demo/spp_trans_data.h b/apps/common/third_party_profile/jieli/trans_data_demo/spp_trans_data.h new file mode 100644 index 0000000..a27dc9d --- /dev/null +++ b/apps/common/third_party_profile/jieli/trans_data_demo/spp_trans_data.h @@ -0,0 +1,9 @@ +#ifndef __SPP_TRANS_DATA_H__ +#define __SPP_TRANS_DATA_H__ + +#include "typedef.h" +#include "bt_common.h" + +void transport_spp_init(void); + +#endif//__RCSP_SPP_USER_H__ diff --git a/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_client.c b/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_client.c new file mode 100644 index 0000000..96cb288 --- /dev/null +++ b/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_client.c @@ -0,0 +1,1614 @@ +/********************************************************************************************* + * Filename : le_multi_client.c + + * Description : + + * Author : + + * Email : zh-jieli.com + + * Last modifiled : 2017-01-17 11:14 + + * Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved. +*********************************************************************************************/ + +// ***************************************************************************** +/* EXAMPLE_START(le_counter): LE Peripheral - Heartbeat Counter over GATT + * + * @text All newer operating systems provide GATT Client functionality. + * The LE Counter examples demonstrates how to specify a minimal GATT Database + * with a custom GATT Service and a custom Characteristic that sends periodic + * notifications. + */ +// ***************************************************************************** + +#include "system/app_core.h" +#include "system/includes.h" + +#include "app_config.h" +#include "app_action.h" + +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "user_cfg.h" +#include "vm.h" +#include "btcontroller_modules.h" +#include "bt_common.h" + +#include "le_client_demo.h" +#include "le_common.h" +#include "ble_user.h" +#include "tuya_le_multi_common.h" + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_TUYA_MULTI&& SUPPORT_MAX_CLIENT) + +#define SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN 1 +#define SHOW_RX_DATA_RATE 0 +#define EXT_ADV_MODE_EN 0 + +#if LE_DEBUG_PRINT_EN +#define log_info(x, ...) printf("[LE-MUL-CLIENT]" x " ", ## __VA_ARGS__) +#define log_info_hexdump put_buf +#else +#define log_info(...) +#define log_info_hexdump(...) +#endif + +//--------------- +#define SEARCH_PROFILE_BUFSIZE (512) //note: +static u8 search_ram_buffer[SEARCH_PROFILE_BUFSIZE] __attribute__((aligned(4))); +#define scan_buffer search_ram_buffer + +//--------------- +#define BASE_INTERVAL_MIN (6)//最小的interval +#if(SUPPORT_MAX_CLIENT > 2) +#define BASE_INTERVAL_VALUE (BASE_INTERVAL_MIN*4) +#else +#define BASE_INTERVAL_VALUE (BASE_INTERVAL_MIN) +#endif + +//--------------- +//搜索类型 +#define SET_SCAN_TYPE SCAN_ACTIVE +//搜索 周期大小 +#define SET_SCAN_INTERVAL ADV_SCAN_MS(10) // unit: ms +//搜索 窗口大小 +#define SET_SCAN_WINDOW ADV_SCAN_MS(10) // unit: ms + +//连接周期 +#define SET_CONN_INTERVAL (BASE_INTERVAL_MIN*8) //(unit:1.25ms) +//连接latency +#define SET_CONN_LATENCY 0 //(unit:conn_interval) +//连接超时 +#define SET_CONN_TIMEOUT 400 //(unit:10ms) +//---------------------------------------------------------------------------- +static u8 scan_ctrl_en; +static u8 ble_work_state[SUPPORT_MAX_CLIENT]; +static void (*app_recieve_callback)(void *priv, void *buf, u16 len) = NULL; +static void (*app_ble_state_callback)(void *priv, ble_state_e state) = NULL; +static void (*ble_resume_send_wakeup)(void) = NULL; +static u32 channel_priv; + +static s8 cur_dev_cid; // 当前操作的多机id + +#define BLE_VM_HEAD_TAG (0xB95C) +#define BLE_VM_TAIL_TAG (0x5CB9) +struct pair_info_t { + u16 head_tag; + u8 pair_flag: 2; + u8 match_dev_id: 6; + u8 peer_address_info[7]; + u16 tail_tag; +}; +static struct pair_info_t conn_pair_info; +static u8 pair_bond_enable = 0; +static u8 match_dev_id = 0; +static struct pair_info_t conn_pair_info_table[SUPPORT_MAX_CLIENT]; +//------------------------------------------------------------------------------- +typedef struct { + uint16_t read_handle; + uint16_t read_long_handle; + uint16_t write_handle; + uint16_t write_no_respond; + uint16_t notify_handle; + uint16_t indicate_handle; +} target_hdl_t; + +//记录handle 使用 +static target_hdl_t target_handle[SUPPORT_MAX_CLIENT]; +static opt_handle_t opt_handle_table[OPT_HANDLE_MAX]; +static u8 opt_handle_used_cnt; +static u8 force_seach_onoff = 0; +static s8 force_seach_rssi = -127; +static u8 is_mode_active = 1; + +static void bt_ble_create_connection(u8 *conn_addr, u8 addr_type); +static int bt_ble_scan_enable(void *priv, u32 en); +static int client_write_send(void *priv, u8 *data, u16 len); +static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type); +int ble_enable_new_dev_scan(void); +//--------------------------------------------------------------------------- +static client_conn_cfg_t *client_config = NULL; +//---------------------------------------------------------------------------- + +static const struct conn_update_param_t connection_param_table[] = { + {16, 24, 0, 600},//11 + {12, 28, 0, 600},//3.7 + {8, 20, 0, 600}, + {50, 60, 0, 600}, +}; + +static u8 send_param_index = 3; + +static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode); +static int client_create_cannel_api(void); +//---------------------------------------------------------------------------- + +static void client_event_report(le_client_event_e event, u8 *packet, int size) +{ + if (client_config->event_callback) { + client_config->event_callback(event, packet, size); + } +} + +static bool check_device_is_match(u8 info_type, u8 *data, int size) +{ + int i; + u8 conn_mode = BIT(info_type); + client_match_cfg_t *cfg; + + /* log_info_hexdump(data,size); */ + + for (i = 0; i < CLIENT_MATCH_CONN_MAX; i++) { + cfg = client_config->match_dev_cfg[i]; + if (cfg == NULL) { + continue; + } + /* log_info("cfg = %08x\n",cfg); */ + /* log_info_hexdump(cfg,sizeof(client_match_cfg_t)); */ + if (cfg->create_conn_mode == conn_mode && size == cfg->compare_data_len) { + log_info("match check\n"); + /* log_info_hexdump(data, size); */ + /* log_info_hexdump(cfg->compare_data, size); */ + if (0 == memcmp(data, cfg->compare_data, cfg->compare_data_len)) { + log_info("match ok:%d\n", cfg->bonding_flag); + pair_bond_enable = cfg->bonding_flag; + match_dev_id = i; + client_event_report(CLI_EVENT_MATCH_DEV, cfg, sizeof(client_match_cfg_t)); + return true; + } + } + } + return false; +} + +static void conn_pair_vm_do(struct pair_info_t *info, u8 rw_flag) +{ + /* return; */ + int ret; + int unit_len = sizeof(struct pair_info_t); + int i; + + log_info("-conn_pair_info vm_do:%d\n", rw_flag); + + if (rw_flag == 0) { + if (unit_len * SUPPORT_MAX_CLIENT != syscfg_read(CFG_BLE_MODE_INFO, (u8 *)conn_pair_info_table, unit_len * SUPPORT_MAX_CLIENT)) { + log_info("-table null--\n"); + memset(conn_pair_info_table, 0, sizeof(conn_pair_info_table)); + } + + for (i = 0; i < SUPPORT_MAX_CLIENT; i++) { + if (conn_pair_info_table[i].head_tag != BLE_VM_HEAD_TAG + || conn_pair_info_table[i].tail_tag != BLE_VM_TAIL_TAG) { + //invail pair + memset(&conn_pair_info_table[i], 0, unit_len); + } + } + + if (info) { + memcpy(info, &conn_pair_info_table[0], unit_len); + } + } else { + int fill_index = -1; + + if (!info) { + log_info("-table clean--\n"); + memset(conn_pair_info_table, 0, sizeof(conn_pair_info_table)); + } else { + for (i = 0; i < SUPPORT_MAX_CLIENT; i++) { + if (0 == memcmp(info, &conn_pair_info_table[i], unit_len)) { + return; + } + } + + r_printf("===============write new dev\n"); + put_buf(conn_pair_info_table, unit_len * SUPPORT_MAX_CLIENT); + put_buf(info, unit_len); + log_info("find table\n"); + + for (i = 0; i < SUPPORT_MAX_CLIENT; i++) { + //先找空的填入 + if (conn_pair_info_table[i].pair_flag == 0) { + fill_index = i; + break; + } + } + + if (SUPPORT_MAX_CLIENT == i) { + for (i = 0; i < SUPPORT_MAX_CLIENT; i++) { + //先覆盖相同条件的 + if (conn_pair_info_table[i].match_dev_id == info->match_dev_id) { + log_info("replace match_dev_id= %d\n", info->match_dev_id); + fill_index = i; + break; + } + } + } + + if (fill_index == -1) { + for (i = SUPPORT_MAX_CLIENT - 1; i > 0; i--) { + //覆盖旧的 + memcpy(&conn_pair_info_table[i], &conn_pair_info_table[i - 1], unit_len); + } + fill_index = 0; + } + + memcpy(&conn_pair_info_table[fill_index], info, unit_len); + conn_pair_info_table[fill_index].head_tag = BLE_VM_HEAD_TAG; + conn_pair_info_table[fill_index].tail_tag = BLE_VM_TAIL_TAG; + } + syscfg_write(CFG_BLE_MODE_INFO, (u8 *)conn_pair_info_table, unit_len * SUPPORT_MAX_CLIENT); + } + put_buf(conn_pair_info_table, unit_len * SUPPORT_MAX_CLIENT); +} + +void client_clear_bonding_info(void) +{ + log_info("client_clear_bonding_info\n"); + //del pair bond + memset(&conn_pair_info, 0, sizeof(struct pair_info_t)); + conn_pair_info.head_tag = BLE_VM_HEAD_TAG; + conn_pair_info.tail_tag = BLE_VM_TAIL_TAG; + conn_pair_vm_do(NULL, 1); +} + +//------------------------------------------------------------ +static void set_ble_work_state(u8 cid, ble_state_e state) +{ + if (state != ble_work_state[cid]) { + log_info("ble_client_work_st[%d]:%x->%x\n", cid, ble_work_state[cid], state); + ble_work_state[cid] = state; + if (app_ble_state_callback) { + app_ble_state_callback((void *)channel_priv, state); + } + } +} +//------------------------------------------------------------ +static ble_state_e get_ble_work_state(u8 cid) +{ + return ble_work_state[cid]; +} + +//------------------------------------------------------------------------------- +static void check_target_uuid_match(search_result_t *result_info) +{ + u32 i; + target_uuid_t *t_uuid; + + for (i = 0; i < client_config->search_uuid_cnt; i++) { + t_uuid = &client_config->search_uuid_table[i]; + if (result_info->services.uuid16) { + if (result_info->services.uuid16 != t_uuid->services_uuid16) { + /* log_info("b1"); */ + continue; + } + } else { + if (memcmp(result_info->services.uuid128, t_uuid->services_uuid128, 16)) { + /* log_info("b2"); */ + continue; + } + } + + if (result_info->characteristic.uuid16) { + if (result_info->characteristic.uuid16 != t_uuid->characteristic_uuid16) { + /* log_info("b3"); */ + /* log_info("%d: %04x--%04x",result_info->characteristic.uuid16,t_uuid->characteristic_uuid16); */ + continue; + } + } else { + if (memcmp(result_info->characteristic.uuid128, t_uuid->characteristic_uuid128, 16)) { + /* log_info("b4"); */ + continue; + } + } + + break;//match one + } + + if (i >= client_config->search_uuid_cnt) { + return; + } + + if (opt_handle_used_cnt >= OPT_HANDLE_MAX) { + log_info("opt_handle is full!!!\n"); + return; + } + + if ((t_uuid->opt_type & result_info->characteristic.properties) != t_uuid->opt_type) { + log_info("properties not match!!!\n"); + return; + } + + log_info("match one uuid\n"); + + opt_handle_t *opt_get = &opt_handle_table[opt_handle_used_cnt++]; + opt_get->value_handle = result_info->characteristic.value_handle; + opt_get->search_uuid = t_uuid; + + switch (t_uuid->opt_type) { + case ATT_PROPERTY_READ: + target_handle[cur_dev_cid].read_handle = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_WRITE_WITHOUT_RESPONSE: + target_handle[cur_dev_cid].write_no_respond = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_WRITE: + target_handle[cur_dev_cid].write_handle = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_NOTIFY: + target_handle[cur_dev_cid].notify_handle = result_info->characteristic.value_handle; + break; + + case ATT_PROPERTY_INDICATE: + target_handle[cur_dev_cid].indicate_handle = result_info->characteristic.value_handle; + break; + + default: + break; + } + + client_event_report(CLI_EVENT_MATCH_UUID, opt_get, sizeof(opt_handle_t)); + +} + +//操作handle,完成 write ccc +static void do_operate_search_handle(void) +{ + u16 tmp_16; + u16 i, cur_opt_type; + opt_handle_t *opt_hdl_pt; + + log_info("opt_handle_used_cnt= %d\n", opt_handle_used_cnt); + + log_info("find target_handle:"); + log_info_hexdump(&target_handle[cur_dev_cid], sizeof(target_hdl_t)); + + if (0 == opt_handle_used_cnt) { + goto opt_end; + } + + /* test_send_conn_update();//for test */ + + for (i = 0; i < opt_handle_used_cnt; i++) { + opt_hdl_pt = &opt_handle_table[i]; + log_info("do opt:service_uuid16:%04x,charactc_uuid16:%04x\n", opt_hdl_pt->search_uuid->services_uuid16, opt_hdl_pt->search_uuid->characteristic_uuid16); + cur_opt_type = opt_hdl_pt->search_uuid->opt_type; + switch ((u8)cur_opt_type) { + case ATT_PROPERTY_READ: + if (opt_hdl_pt->search_uuid->read_long_enable) { + tmp_16 = 0x55A2;//fixed + log_info("read_long:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle, (u8 *)&tmp_16, 2, ATT_OP_READ_LONG); + } else { + tmp_16 = 0x55A1;//fixed + log_info("read:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle, (u8 *)&tmp_16, 2, ATT_OP_READ); + } + break; + + case ATT_PROPERTY_NOTIFY: + tmp_16 = 0x01;//fixed + log_info("write_ntf_ccc:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle + 1, &tmp_16, 2, ATT_OP_WRITE); + if (opt_hdl_pt->search_uuid->read_report_reference) { + tmp_16 = 0x55A1;//fixed + log_info("read_report_reference:%04x\n", opt_hdl_pt->value_handle + 2); + client_operation_send(opt_hdl_pt->value_handle + 2, (u8 *)&tmp_16, 2, ATT_OP_READ); + } + break; + + case ATT_PROPERTY_INDICATE: + tmp_16 = 0x02;//fixed + log_info("write_ind_ccc:%04x\n", opt_hdl_pt->value_handle); + client_operation_send(opt_hdl_pt->value_handle + 1, &tmp_16, 2, ATT_OP_WRITE); + break; + + default: + break; + } + } + +opt_end: + set_ble_work_state(cur_dev_cid, BLE_ST_SEARCH_COMPLETE); + +} + +//协议栈内部调用 +//return: 0--accept,1--reject +int l2cap_connection_update_request_just(u8 *packet, hci_con_handle_t handle) +{ + log_info("slave request conn_update:\n-conn_handle= %04x\n-interval_min= %d,\n-interval_max= %d,\n-latency= %d,\n-timeout= %d\n", + handle, + little_endian_read_16(packet, 0), little_endian_read_16(packet, 2), + little_endian_read_16(packet, 4), little_endian_read_16(packet, 6)); + +#if (SUPPORT_MAX_CLIENT > 1) + u16 cfg_interval = BASE_INTERVAL_VALUE; + u16 max_interval = little_endian_read_16(packet, 2); + while (max_interval >= (cfg_interval + BASE_INTERVAL_VALUE)) { + cfg_interval += BASE_INTERVAL_VALUE; + } + little_endian_store_16(packet, 0, cfg_interval); + little_endian_store_16(packet, 2, cfg_interval); + r_printf("conn_handle:%04x,confirm_interval:%d", handle, cfg_interval); + log_info("conn_handle:%04x,confirm_interval:%d\n", handle, cfg_interval); +#endif + + //change param + /* little_endian_store_16(packet, 4,0);//disable latency */ + /* little_endian_store_16(packet, 6,400);//change timeout */ + return 0; + /* return 1; */ +} + +//协议栈内部调用 +void user_client_report_search_result(search_result_t *result_info) +{ + if (result_info == (void *) - 1) { + log_info("client_report_search_result finish!!!\n"); + do_operate_search_handle(); + client_event_report(CLI_EVENT_SEARCH_PROFILE_COMPLETE, 0, 0); + + //搜索完profile,尝试开新设备scan + ble_enable_new_dev_scan(); + return; + } + + log_info("\n*** services, uuid16:%04x,index=%d ***\n", result_info->services.uuid16, result_info->service_index); + log_info("{charactc, uuid16:%04x,index=%d,handle:%04x~%04x,value_handle=%04x}\n", + result_info->characteristic.uuid16, result_info->characteristic_index, + result_info->characteristic.start_handle, result_info->characteristic.end_handle, + result_info->characteristic.value_handle + ); + + if (!result_info->services.uuid16) { + log_info("######services_uuid128:"); + log_info_hexdump(result_info->services.uuid128, 16); + } + + if (!result_info->characteristic.uuid16) { + log_info("######charact_uuid128:"); + log_info_hexdump(result_info->characteristic.uuid128, 16); + } + + check_target_uuid_match(result_info); +} + +#if SHOW_RX_DATA_RATE + +static u32 client_timer_handle = 0; +static u32 test_data_count; +static void client_timer_handler(void) +{ + if (!client_con_handle[cur_dev_cid]) { + test_data_count = 0; + return; + } + log_info("peer_rssi = %d\n", ble_vendor_get_peer_rssi(client_con_handle[cur_dev_cid])); + + if (test_data_count) { + /* log_info("\n-ble_data_rate: %d bps-\n", test_data_count * 8); */ + log_info("\n%d bytes receive: %d.%02d KB/s \n", test_data_count, test_data_count / 1000, test_data_count % 1000); + test_data_count = 0; + } +} + +static void client_timer_start(void) +{ + client_timer_handle = sys_timer_add(NULL, client_timer_handler, 1000); +} + +#endif /* SHOW_RX_DATA_RATE */ + +static target_uuid_t *get_match_handle_target(u16 handle) +{ + for (int i = 0; i < opt_handle_used_cnt; i++) { + if (opt_handle_table[i].value_handle == handle) { + return opt_handle_table[i].search_uuid; + } + } + return NULL; +} + +//协议栈内部调用 +void user_client_report_data_callback(att_data_report_t *report_data) +{ + /* log_info("\n-report_data:type %02x,handle %04x,offset %d,len %d:",report_data->packet_type, */ + /* report_data->value_handle,report_data->value_offset,report_data->blob_length); */ + /* log_info_hexdump(report_data->blob,report_data->blob_length); */ + + if (-1 == mul_get_dev_index(report_data->conn_handle, MULTI_ROLE_CLIENT)) { + log_info("unknown_handle:%04x\n", report_data->conn_handle); + log_info_hexdump(report_data->blob, report_data->blob_length); + return; + } + +#if SHOW_RX_DATA_RATE + test_data_count += report_data->blob_length; +#endif /* SHOW_RX_DATA_RATE */ + + target_uuid_t *search_uuid = get_match_handle_target(report_data->value_handle); + + if (client_config->report_data_callback) { + client_config->report_data_callback(report_data, search_uuid); + return; + } + + switch (report_data->packet_type) { + case GATT_EVENT_NOTIFICATION://notify +// log_info("\n-notify_rx(%d):",report_data->blob_length); + case GATT_EVENT_INDICATION://indicate + case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT://read + case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT://read long + break; + default: + break; + } +} + +// PRIMARY_SERVICE,AE30 +/* static const u16 test_services_uuid16 = 0xae30; */ + +// PRIMARY_SERVICE, 0000F530-1212-EFDE-1523-785FEABCD123 +/* static const u8 test_services_uuid128[16] = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}; */ + +static void client_search_profile_start(void) +{ + opt_handle_used_cnt = 0; + memset(&target_handle[cur_dev_cid], 0, sizeof(target_hdl_t)); + user_client_init(client_con_handle[cur_dev_cid], search_ram_buffer, SEARCH_PROFILE_BUFSIZE); + if (client_config->search_uuid_cnt) { + log_info("start search_profile_all:%04x\n", client_con_handle[cur_dev_cid]); + ble_op_search_profile_all(); + } else { + log_info("skip search_profile:%04x\n\n", client_con_handle[cur_dev_cid]); + user_client_set_search_complete(); + } +} + +//------------------------------------------------------------ +static bool resolve_adv_report(u8 *adv_address, u8 data_length, u8 *data, s8 rssi) +{ + putchar('&'); + u8 i, lenght, ad_type; + u8 *adv_data_pt; + u8 find_remoter = 0; + /* u8 tmp_addr[6]; */ + u32 tmp32; + + if (check_device_is_match(CLI_CREAT_BY_ADDRESS, adv_address, 6)) { + find_remoter = 1; + } + + adv_data_pt = data; + for (i = 0; i < data_length;) { + if (*adv_data_pt == 0) { + /* log_info("analyze end\n"); */ + break; + } + + lenght = *adv_data_pt++; + ad_type = *adv_data_pt++; + i += (lenght + 1); + + switch (ad_type) { + case HCI_EIR_DATATYPE_FLAGS: + /* log_info("flags:%02x\n",adv_data_pt[0]); */ + break; + + case HCI_EIR_DATATYPE_MORE_16BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_COMPLETE_16BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_MORE_32BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_COMPLETE_32BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_MORE_128BIT_SERVICE_UUIDS: + case HCI_EIR_DATATYPE_COMPLETE_128BIT_SERVICE_UUIDS: + /* log_info("service uuid:"); */ + /* log_info_hexdump(adv_data_pt, lenght - 1); */ + break; + + case HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME: + case HCI_EIR_DATATYPE_SHORTENED_LOCAL_NAME: + tmp32 = adv_data_pt[lenght - 1]; + adv_data_pt[lenght - 1] = 0;; + log_info("ble remoter_name: %s,rssi:%d\n", adv_data_pt, rssi); + /* log_info_hexdump(adv_address, 6); */ + adv_data_pt[lenght - 1] = tmp32; + //------- +#if SUPPORT_TEST_BOX_BLE_MASTER_TEST_EN +#define TEST_BOX_BLE_NAME "JLBT_TESTBOX" +#define TEST_BOX_BLE_NAME_LEN 0xc + if (0 == memcmp(adv_data_pt, TEST_BOX_BLE_NAME, TEST_BOX_BLE_NAME_LEN)) { + find_remoter = 1; + break; + } +#endif + /* log_info("target name:%s", client_config->compare_data); */ + if (check_device_is_match(CLI_CREAT_BY_NAME, adv_data_pt, lenght - 1)) { + find_remoter = 1; + log_info("catch name ok\n"); + } + break; + + case HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA: + if (check_device_is_match(CLI_CREAT_BY_TAG, adv_data_pt, lenght - 1)) { + log_info("get_tag_string!\n"); + find_remoter = 1; + } + break; + + case HCI_EIR_DATATYPE_APPEARANCE_DATA: + /* log_info("get_class_type:%04x\n",little_endian_read_16(adv_data_pt,0)); */ + break; + + default: + /* log_info("unknow ad_type:"); */ + break; + } + + if (find_remoter) { + log_info_hexdump(adv_data_pt, lenght - 1); + } + adv_data_pt += (lenght - 1); + } + + return find_remoter; +} + +static void client_report_adv_data(adv_report_t *report_pt, u16 len) +{ + bool find_tag = 0; + int i; + /* log_info("event_type,addr_type: %x,%x; ",report_pt->event_type,report_pt->address_type); */ + /* log_info_hexdump(report_pt->address,6); */ + + /* log_info("adv_data_display:"); */ + /* log_info_hexdump(report_pt->data,report_pt->length); */ + +// log_info("rssi:%d\n",report_pt->rssi); + + for (i = 0; i < SUPPORT_MAX_CLIENT; i++) { + if (conn_pair_info_table[i].pair_flag) { + /* log_info("check paired dev\n"); */ + /* put_buf(report_pt->address, 6); */ + /* put_buf(&conn_pair_info_table[i].peer_address_info[1], 6); */ + if (report_pt->event_type == conn_pair_info_table[i].peer_address_info[0] + && 0 == memcmp(report_pt->address, &conn_pair_info_table[i].peer_address_info[1], 6)) { + find_tag = 1; + log_info("find paired dev to connect\n"); + put_buf(conn_pair_info_table[i].peer_address_info, 7); + } + } + } + + if (!find_tag) { + find_tag = resolve_adv_report(report_pt->address, report_pt->length, report_pt->data, report_pt->rssi); + } + + if (find_tag) { + if (force_seach_onoff && force_seach_rssi > report_pt->rssi) { + log_info("match but rssi fail!!!:%d,%d\n", force_seach_rssi, report_pt->rssi); + return; + } + + log_info("rssi:%d\n", report_pt->rssi); + log_info("\n*********create_connection***********\n"); + log_info("***remote type %d,addr:", report_pt->address_type); + log_info_hexdump(report_pt->address, 6); + bt_ble_scan_enable(0, 0); + client_create_connect_api(report_pt->address, report_pt->address_type, 0); + log_info("*create_finish\n"); + } +} + +#if EXT_ADV_MODE_EN + +#define GET_STRUCT_MEMBER_OFFSET(type, member) \ + (u32)&(((struct type*)0)->member) + +struct __ext_adv_report_event { + u8 Subevent_Code; + u8 Num_Reports; + u16 Event_Type; + u8 Address_Type; + u8 Address[6]; + u8 Primary_PHY; + u8 Secondary_PHY; + u8 Advertising_SID; + u8 Tx_Power; + u8 RSSI; + u16 Periodic_Advertising_Interval; + u8 Direct_Address_Type; + u8 Direct_Address[6]; + u8 Data_Length; + u8 Data[0]; +} _GNU_PACKED_; + +static void client_report_ext_adv_data(u8 *report_pt, u16 len) +{ + bool find_remoter; + u8 address_type = report_pt[GET_STRUCT_MEMBER_OFFSET(__ext_adv_report_event, Address_Type)]; + u8 address[6]; + + /* log_info("--func=%s", __FUNCTION__); */ + /* log_info_hexdump(report_pt, len); */ + + memcpy(address, &report_pt[GET_STRUCT_MEMBER_OFFSET(__ext_adv_report_event, Address)], 6); + + find_remoter = resolve_adv_report(\ + address, \ + report_pt[GET_STRUCT_MEMBER_OFFSET(__ext_adv_report_event, Data_Length)], \ + &report_pt[GET_STRUCT_MEMBER_OFFSET(__ext_adv_report_event, Data)], 0 \ + ); + + if (find_remoter) { + if (force_seach_onoff && force_seach_rssi > report_pt->rssi) { + log_info("match but rssi fail!!!:%d,%d\n", force_seach_rssi, report_pt->rssi); + return; + } + + log_info("\n*********ext create_connection***********\n"); + log_info("***remote type %d, addr:", address_type); + log_info_hexdump(address, 6); + bt_ble_scan_enable(0, 0); + client_create_connect_api(address, address_type, 0); + log_info("*create_finish\n"); + } +} + +struct __ext_init { + u8 Initiating_Filter_Policy; + u8 Own_Address_Type; + u8 Peer_Address_Type; + u8 Peer_Address[6]; + u8 Initiating_PHYs; + u16 Scan_Interval; + u16 Scan_Window; + u16 Conn_Interval_Min; + u16 Conn_Interval_Max; + u16 Conn_Latency; + u16 Supervision_Timeout; + u16 Minimum_CE_Length; + u16 Maximum_CE_Length; +} _GNU_PACKED_; + +static void client_ext_create_connection(u8 *conn_addr, u8 addr_type) +{ + struct __ext_init *create_conn_par = scan_buffer; + + if (get_ble_work_state(cur_dev_cid) == BLE_ST_CREATE_CONN) { + log_info("already ext_create conn:%d!!!\n", cur_dev_cid); + return; + } + + memset(create_conn_par, 0, sizeof(*create_conn_par)); + create_conn_par->Conn_Interval_Min = SET_CONN_INTERVAL; + create_conn_par->Conn_Interval_Max = SET_CONN_INTERVAL; + create_conn_par->Conn_Latency = SET_CONN_LATENCY; + create_conn_par->Supervision_Timeout = SET_CONN_TIMEOUT; + create_conn_par->Peer_Address_Type = addr_type; + create_conn_par->Initiating_PHYs = INIT_SET_1M_PHY; + memcpy(create_conn_par->Peer_Address, conn_addr, 6); + + set_ble_work_state(cur_dev_cid, BLE_ST_CREATE_CONN); + + log_info_hexdump(create_conn_par, sizeof(*create_conn_par)); + + ble_op_ext_create_conn(create_conn_par, sizeof(*create_conn_par)); +} + +#endif /* EXT_ADV_MODE_EN */ + +static void client_create_connection(u8 *conn_addr, u8 addr_type) +{ + struct create_conn_param_t *create_conn_par = scan_buffer; + if (get_ble_work_state(cur_dev_cid) == BLE_ST_CREATE_CONN) { + log_info("already create conn:%d!!!\n", cur_dev_cid); + return; + } + create_conn_par->conn_interval = SET_CONN_INTERVAL; + create_conn_par->conn_latency = SET_CONN_LATENCY; + create_conn_par->supervision_timeout = SET_CONN_TIMEOUT; + memcpy(create_conn_par->peer_address, conn_addr, 6); + create_conn_par->peer_address_type = addr_type; + + set_ble_work_state(cur_dev_cid, BLE_ST_CREATE_CONN); + log_info_hexdump(create_conn_par, sizeof(struct create_conn_param_t)); + ble_op_create_connection(create_conn_par); +} + +static void bt_ble_create_connection(u8 *conn_addr, u8 addr_type) +{ +#if EXT_ADV_MODE_EN + client_ext_create_connection(conn_addr, addr_type); +#else + client_create_connection(conn_addr, addr_type); +#endif /* EXT_ADV_MODE_EN */ +} + +static void client_create_connection_cannel(void) +{ + if (get_ble_work_state(cur_dev_cid) == BLE_ST_CREATE_CONN) { + set_ble_work_state(cur_dev_cid, BLE_ST_SEND_CREATE_CONN_CANNEL); + ble_op_create_connection_cancel(); + } +} + +static int client_disconnect(void *priv) +{ + u8 cid = (u8) priv; + + if (cid >= SUPPORT_MAX_CLIENT) { + return APP_BLE_OPERATION_ERROR; + } + + if (client_con_handle[cid]) { + if (BLE_ST_SEND_DISCONN != get_ble_work_state(cid)) { + log_info(">>>ble(%d) send disconnect\n", cid); + set_ble_work_state(cid, BLE_ST_SEND_DISCONN); + ble_op_disconnect(client_con_handle[cid]); + } else { + log_info(">>>ble(%d) wait disconnect...\n", cid); + } + return APP_BLE_NO_ERROR; + } else { + return APP_BLE_OPERATION_ERROR; + } +} + +void ble_multi_client_disconnect(void) +{ + u8 i; + int count; + + for (u8 i = 0; i < SUPPORT_MAX_CLIENT; i++) { + count = 150; + if (client_con_handle[i]) { + client_disconnect((void *)i); + while (count-- && client_con_handle[i]) { + os_time_dly(1); + putchar('w'); + } + } + } +} + +static void connection_update_complete_success(u16 conn_handle, u8 *packet) +{ + int conn_interval, conn_latency, conn_timeout; + + conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet); + conn_latency = hci_subevent_le_connection_update_complete_get_conn_latency(packet); + conn_timeout = hci_subevent_le_connection_update_complete_get_supervision_timeout(packet); + + log_info("conn_handle = %04x\n", conn_handle); + log_info("conn_interval = %d\n", conn_interval); + log_info("conn_latency = %d\n", conn_latency); + log_info("conn_timeout = %d\n", conn_timeout); +} + +static void can_send_now_wakeup(void) +{ + putchar('E'); + if (ble_resume_send_wakeup) { + ble_resume_send_wakeup(); + } +} + +static const char *const phy_result[] = { + "None", + "1M", + "2M", + "Coded", +}; + +static void set_connection_data_length(u16 tx_octets, u16 tx_time) +{ + if (client_con_handle[cur_dev_cid]) { + ble_op_set_data_length(client_con_handle[cur_dev_cid], tx_octets, tx_time); + } +} + +static void set_connection_data_phy(u8 tx_phy, u8 rx_phy) +{ + if (0 == client_con_handle[cur_dev_cid]) { + return; + } + + u8 all_phys = 0; + u16 phy_options = 0; + + ble_op_set_ext_phy(client_con_handle[cur_dev_cid], all_phys, tx_phy, rx_phy, phy_options); +} + +static void client_profile_start(u16 conn_handle) +{ + set_ble_work_state(cur_dev_cid, BLE_ST_CONNECT); + + if (0 == client_config->security_en) { + client_search_profile_start(); + } +} + +//尝试开新设备scan +int ble_enable_new_dev_scan(void) +{ + log_info("%s\n", __FUNCTION__); + + if (!client_con_handle[cur_dev_cid]) { + log_info("dev_doing\n"); + return -1; + } + + s8 tmp_cid = mul_get_idle_dev_index(MULTI_ROLE_CLIENT); + if (tmp_cid < 0) { + log_info("no idle dev to do!!!\n"); + return -2; + } + + log_info("new_dev_scan\n"); + cur_dev_cid = tmp_cid; + set_ble_work_state(cur_dev_cid, BLE_ST_IDLE); + bt_ble_scan_enable(0, 1); + return 0; +} + + +/* LISTING_START(packetHandler): Packet Handler */ +void client_cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + int mtu; + u32 tmp; + u8 status; + + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + + /* case DAEMON_EVENT_HCI_PACKET_SENT: */ + /* break; */ + case ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE: + log_info("ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE\n"); + case ATT_EVENT_CAN_SEND_NOW: + can_send_now_wakeup(); + break; + + case HCI_EVENT_LE_META: + switch (hci_event_le_meta_get_subevent_code(packet)) { + + case HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE: { + if (1 == hci_subevent_le_connection_complete_get_role(packet)) { + //connect is slave + break; + } + + status = hci_subevent_le_enhanced_connection_complete_get_status(packet); + if (status) { + log_info("LE_MASTER CREATE CONNECTION FAIL!!! %0x\n", status); + set_ble_work_state(cur_dev_cid, BLE_ST_DISCONN); + break; + } + u16 tmp_handle1 = hci_subevent_le_enhanced_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE : 0x%0x\n", tmp_handle1); + s8 tmp_dev_cid1 = mul_get_idle_dev_index(MULTI_ROLE_CLIENT); + + if (tmp_dev_cid1 < 0) { + log_info("dev_cid full!!!\n"); + ble_op_disconnect(tmp_handle1); + break; + } + + cur_dev_cid = tmp_dev_cid1; + client_con_handle[cur_dev_cid] = tmp_handle1; + ble_op_multi_att_send_conn_handle(client_con_handle[cur_dev_cid], cur_dev_cid, MULTI_ROLE_CLIENT); + + log_info("conn_interval = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_interval(packet)); + log_info("conn_latency = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_latency(packet)); + log_info("conn_timeout = %d\n", hci_subevent_le_enhanced_connection_complete_get_supervision_timeout(packet)); + client_profile_start(client_con_handle[cur_dev_cid]); + } + break; + + case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: { + if (1 == hci_subevent_le_connection_complete_get_role(packet)) { + //connect is slave + break; + } + + if (packet[3]) { + log_info("LE_MASTER CREATE CONNECTION FAIL!!! %0x\n", packet[3]); + set_ble_work_state(cur_dev_cid, BLE_ST_DISCONN); + //auto to do + bt_ble_scan_enable(0, 1); + break; + } + + u16 tmp_handle = hci_subevent_le_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_CONNECTION_COMPLETE: %0x\n", tmp_handle); + s8 tmp_dev_cid = mul_get_idle_dev_index(MULTI_ROLE_CLIENT); + + if (tmp_dev_cid < 0) { + log_info("dev_cid full!!!\n"); + ble_op_disconnect(tmp_handle); + break; + } + + cur_dev_cid = tmp_dev_cid; + client_con_handle[cur_dev_cid] = tmp_handle; + ble_op_multi_att_send_conn_handle(client_con_handle[cur_dev_cid], cur_dev_cid, MULTI_ROLE_CLIENT); + + connection_update_complete_success(tmp_handle, packet + 8); + client_profile_start(client_con_handle[cur_dev_cid]); + client_event_report(CLI_EVENT_CONNECTED, packet, size); + + if (pair_bond_enable) { + log_info("bond remoter\n"); + conn_pair_info.pair_flag = 1; + conn_pair_info.match_dev_id = match_dev_id; + memcpy(&conn_pair_info.peer_address_info, &packet[7], 7); + conn_pair_vm_do(&conn_pair_info, 1); + pair_bond_enable = 0; + } + } + break; + + case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: { + u16 tmp_handle = little_endian_read_16(packet, 4); + if (mul_get_dev_index(tmp_handle, MULTI_ROLE_CLIENT) >= 0) { + connection_update_complete_success(tmp_handle, packet); + } + } + break; + + case HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE: + log_info("APP HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE"); + break; + + case HCI_SUBEVENT_LE_PHY_UPDATE_COMPLETE: + log_info("APP HCI_SUBEVENT_LE_PHY_UPDATE %s\n", hci_event_le_meta_get_phy_update_complete_status(packet) ? "Fail" : "Succ"); + log_info("Tx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_tx_phy(packet)]); + log_info("Rx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_rx_phy(packet)]); + break; + +#if EXT_ADV_MODE_EN + case HCI_SUBEVENT_LE_EXTENDED_ADVERTISING_REPORT: + /* log_info("APP HCI_SUBEVENT_LE_EXTENDED_ADVERTISING_REPORT"); */ + /* log_info_hexdump(packet, size); */ + if (BLE_ST_SCAN == get_ble_work_state(cur_dev_cid)) { + client_report_ext_adv_data(&packet[2], packet[1]); + } else { + log_info("drop ext_adv_report!!!\n"); + } + break; +#endif /* EXT_ADV_MODE_EN */ + } + break; + + case HCI_EVENT_DISCONNECTION_COMPLETE: + log_info("HCI_EVENT_DISCONNECTION_COMPLETE: %0x\n", packet[5]); + + u16 tmp_handle = little_endian_read_16(packet, 3); + s8 tmp_index = mul_get_dev_index(tmp_handle, MULTI_ROLE_CLIENT); + if (tmp_index < 0) { + log_info("unknown_handle:%04x\n", tmp_handle); + break; + } + + client_con_handle[tmp_index] = 0; + set_ble_work_state(tmp_index, BLE_ST_DISCONN); + client_event_report(CLI_EVENT_DISCONNECT, packet, size); + ble_op_multi_att_send_conn_handle(0, tmp_index, MULTI_ROLE_CLIENT); + + if (0 == client_con_handle[cur_dev_cid]) { + //判断当前设备是否正在scan 或者 creat + if (BLE_ST_SCAN == get_ble_work_state(cur_dev_cid) || BLE_ST_CREATE_CONN == get_ble_work_state(cur_dev_cid)) { + //直接退出,不做别的操作 + break; + } + } + + //配设备开scan + cur_dev_cid = tmp_index; + + //auto to do + if (0) { //(conn_pair_info.pair_flag && SUPPORT_MAX_CLIENT < 2) { + client_create_connect_api(0, 0, 1); + } else { + bt_ble_scan_enable(0, 1); + } + break; + + case ATT_EVENT_MTU_EXCHANGE_COMPLETE: { + u16 tmp_handle = little_endian_read_16(packet, 2); + s8 tmp_cid = mul_get_dev_index(tmp_handle, MULTI_ROLE_CLIENT); + if (tmp_cid != -1) { + mtu = att_event_mtu_exchange_complete_get_MTU(packet) - 3; + log_info("ATT MTU = %u\n", mtu); + ble_op_multi_att_set_send_mtu(tmp_handle, mtu); + /* set_connection_data_length(251, 2120); */ + } + } + break; + + case HCI_EVENT_VENDOR_REMOTE_TEST: + log_info("--- HCI_EVENT_VENDOR_REMOTE_TEST\n"); + break; + + case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE: { + u16 tmp_handle = little_endian_read_16(packet, 2); + s8 tmp_cid = mul_get_dev_index(tmp_handle, MULTI_ROLE_CLIENT); + if (tmp_cid != -1) { + tmp = little_endian_read_16(packet, 4); + log_info("-update_rsp:%04x, %02x\n", tmp_handle, tmp); + } + } + break; + + case GAP_EVENT_ADVERTISING_REPORT: + /* putchar('@'); */ + if (BLE_ST_SCAN == get_ble_work_state(cur_dev_cid)) { + client_report_adv_data((void *)&packet[2], packet[1]); + } else { + log_info("drop adv_report!!!\n"); + } + break; + + case HCI_EVENT_ENCRYPTION_CHANGE: { + u16 tmp_handle = little_endian_read_16(packet, 3); + s8 tmp_cid = mul_get_dev_index(tmp_handle, MULTI_ROLE_CLIENT); + if (tmp_cid != -1) { + log_info("HCI_EVENT_ENCRYPTION_CHANGE= %d\n", packet[2]); + if (client_config->security_en) { + client_search_profile_start(); + } + } + } + break; + } + break; + } +} + + +static int get_buffer_vaild_len(void *priv) +{ + u32 vaild_len = 0; + ble_op_multi_att_get_remain(client_con_handle[cur_dev_cid], &vaild_len); + return vaild_len; +} + +static int client_operation_send(u16 handle, u8 *data, u16 len, u8 att_op_type) +{ + int ret = APP_BLE_NO_ERROR; + if (!client_con_handle[cur_dev_cid]) { + return APP_BLE_OPERATION_ERROR; + } + + if (!handle) { + log_info("handle is null\n"); + return APP_BLE_OPERATION_ERROR; + } + + if (get_buffer_vaild_len(0) < len) { + log_info("opt_buff_full!!!\n"); + return APP_BLE_BUFF_FULL; + } + + ret = ble_op_multi_att_send_data(client_con_handle[cur_dev_cid], handle, data, len, att_op_type); + if (ret == BLE_BUFFER_FULL) { + ret = APP_BLE_BUFF_FULL; + } + return ret; +} + + +static int client_operation_send_ext(u16 conn_handle, u16 handle, u8 *data, u16 len, u8 att_op_type) +{ + int ret = APP_BLE_NO_ERROR; + if (!conn_handle) { + return APP_BLE_OPERATION_ERROR; + } + + ret = ble_op_multi_att_send_data(conn_handle, handle, data, len, att_op_type); + if (ret == BLE_BUFFER_FULL) { + ret = APP_BLE_BUFF_FULL; + } + return ret; +} +//----------------------------------------------- +static int client_write_send(void *priv, u8 *data, u16 len) +{ + return client_operation_send(target_handle[cur_dev_cid].write_handle, data, len, ATT_OP_WRITE); +} + +static int client_write_without_respond_send(void *priv, u8 *data, u16 len) +{ + return client_operation_send(target_handle[cur_dev_cid].write_no_respond, data, len, ATT_OP_WRITE_WITHOUT_RESPOND); +} + +static int client_read_value_send(void *priv) +{ + u16 tmp_flag = 0x55A1; + return client_operation_send(target_handle[cur_dev_cid].read_handle, (u8 *)&tmp_flag, 2, ATT_OP_READ); +} + +static int client_read_long_value_send(void *priv) +{ + u16 tmp_flag = 0x55A2; + return client_operation_send(target_handle[cur_dev_cid].read_handle, (u8 *)&tmp_flag, 2, ATT_OP_READ_LONG); +} + +#if EXT_ADV_MODE_EN + +struct __ext_scan_param { + u8 Own_Address_Type; + u8 Scanning_Filter_Policy; + u8 Scanning_PHYs; + u8 Scan_Type; + u16 Scan_Interval; + u16 Scan_Window; +} _GNU_PACKED_; + +struct __ext_scan_enable { + u8 Enable; + u8 Filter_Duplicates; + u16 Duration; + u16 Period; +} _GNU_PACKED_; + +const struct __ext_scan_param ext_scan_param = { + .Own_Address_Type = 0, + .Scanning_Filter_Policy = 0, + .Scanning_PHYs = SCAN_SET_1M_PHY, + .Scan_Type = SET_SCAN_TYPE, + .Scan_Interval = SET_SCAN_INTERVAL, + .Scan_Window = SET_SCAN_WINDOW, +}; + +const struct __ext_scan_enable ext_scan_enable = { + .Enable = 1, + .Filter_Duplicates = 0, + .Duration = 0, + .Period = 0, +}; + +const struct __ext_scan_enable ext_scan_disable = { + .Enable = 0, + .Filter_Duplicates = 0, + .Duration = 0, + .Period = 0, +}; + +#endif /* EXT_ADV_MODE_EN */ + +//扫描数设置 +static void scanning_setup_init(void) +{ + ble_op_set_scan_param(SET_SCAN_TYPE, SET_SCAN_INTERVAL, SET_SCAN_WINDOW); +} + +static int bt_ble_scan_enable(void *priv, u32 en) +{ + ble_state_e next_state, cur_state; + + if (!scan_ctrl_en) { + return APP_BLE_OPERATION_ERROR; + } + + if (en) { + next_state = BLE_ST_SCAN; + } else { + next_state = BLE_ST_IDLE; + } + + cur_state = get_ble_work_state(cur_dev_cid); + switch (cur_state) { + case BLE_ST_SCAN: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + case BLE_ST_CONNECT_FAIL: + case BLE_ST_SEND_CREATE_CONN_CANNEL: + break; + default: + return APP_BLE_OPERATION_ERROR; + break; + } + + if (cur_state == next_state) { + return APP_BLE_NO_ERROR; + } + + + log_info("scan_en:%d\n", en); + set_ble_work_state(cur_dev_cid, next_state); + +#if EXT_ADV_MODE_EN + if (en) { + ble_op_set_ext_scan_param(&ext_scan_param, sizeof(ext_scan_param)); + ble_op_ext_scan_enable(&ext_scan_enable, sizeof(ext_scan_enable)); + } else { + ble_op_ext_scan_enable(&ext_scan_disable, sizeof(ext_scan_disable)); + } +#else + if (en) { + scanning_setup_init(); + } + ble_op_scan_enable2(en, 0); +#endif /* EXT_ADV_MODE_EN */ + + return APP_BLE_NO_ERROR; +} + +static int client_regiest_wakeup_send(void *priv, void *cbk) +{ + /* att_regist_wakeup_send(cbk); */ + return APP_BLE_NO_ERROR; +} + +static int client_regiest_recieve_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_recieve_callback = cbk; + return APP_BLE_NO_ERROR; +} + +static int client_regiest_state_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_ble_state_callback = cbk; + return APP_BLE_NO_ERROR; +} + +//该接口重新配置搜索的配置项 +static int client_init_config(void *priv, const client_conn_cfg_t *cfg) +{ + log_info("client_init_config\n"); + client_config = cfg;//reset config + return APP_BLE_NO_ERROR; +} + +//可配置进入强制搜索方式连接,更加信号强度过滤设备 +static int client_force_search(u8 onoff, s8 rssi) +{ + force_seach_rssi = rssi; + if (force_seach_onoff != onoff) { + + force_seach_onoff = onoff; + //强制搜索前后,关创建监听 + if (get_ble_work_state(cur_dev_cid) == BLE_ST_CREATE_CONN) { + client_create_connection_cannel(); + } + } + return 0; +} + +static int client_create_connect_api(u8 *addr, u8 addr_type, u8 mode) +{ + u8 cur_state = get_ble_work_state(cur_dev_cid); + + switch (cur_state) { + case BLE_ST_SCAN: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + case BLE_ST_CONNECT_FAIL: + case BLE_ST_SEND_CREATE_CONN_CANNEL: + break; + default: + return APP_BLE_OPERATION_ERROR; + break; + } + + if (cur_state == BLE_ST_SCAN) { + log_info("stop scan\n"); + bt_ble_scan_enable(0, 0); + } + + //pair mode + if (mode == 1) { + if (conn_pair_info.pair_flag) { + if (conn_pair_info.pair_flag) { + //有配对,跳过搜索,直接创建init_creat + log_info("pair to creat!\n"); + log_info_hexdump(conn_pair_info.peer_address_info, 7); + bt_ble_create_connection(&conn_pair_info.peer_address_info[1], conn_pair_info.peer_address_info[0]); + return 0; + } + + } else { + log_info("no pair to creat!\n"); + return APP_BLE_OPERATION_ERROR; + } + } else { + log_info("addr to creat!\n"); + log_info_hexdump(addr, 7); + bt_ble_create_connection(addr, addr_type); + } + return 0; +} + +static int client_create_cannel_api(void) +{ + if (get_ble_work_state(cur_dev_cid) == BLE_ST_CREATE_CONN) { + client_create_connection_cannel(); + return 0; + } + return 1; +} + +static ble_state_e get_ble_work_state_api(void) +{ + return get_ble_work_state(cur_dev_cid); +} + +static const struct ble_client_operation_t client_operation = { + .scan_enable = bt_ble_scan_enable, + .disconnect = client_disconnect, + .get_buffer_vaild = get_buffer_vaild_len, + .write_data = (void *)client_write_without_respond_send, + .read_do = (void *)client_read_value_send, + .regist_wakeup_send = client_regiest_wakeup_send, + .regist_recieve_cbk = client_regiest_recieve_cbk, + .regist_state_cbk = client_regiest_state_cbk, + .init_config = client_init_config, + .opt_comm_send = client_operation_send, + .set_force_search = client_force_search, + .create_connect = client_create_connect_api, + .create_connect_cannel = client_create_cannel_api, + .get_work_state = get_ble_work_state_api, + .opt_comm_send_ext = client_operation_send_ext, +}; + +struct ble_client_operation_t *ble_get_client_operation_table(void) +{ + return &client_operation; +} + +static void device_bonding_init(void) +{ + int i; + int cfg_bonding = 0; + client_match_cfg_t *cfg; + for (i = 0; i < CLIENT_MATCH_CONN_MAX; i++) { + cfg = client_config->match_dev_cfg[i]; + if (cfg == NULL) { + continue; + } + if (cfg->bonding_flag) { + cfg_bonding = 1; + } + } + if (!cfg_bonding) { + client_clear_bonding_info(); + } +} + +static u8 multi_client_idle_query(void) +{ + return !is_mode_active; +} + +REGISTER_LP_TARGET(multi_client_target) = { + .name = "multi_client", + .is_idle = multi_client_idle_query, +}; + +//模块开关 +void ble_client_module_enable(u8 en) +{ + log_info("mode_en:%d\n", en); + + if (en) { + scan_ctrl_en = 1; + bt_ble_scan_enable(0, 1); + } else { + scan_ctrl_en = 0; + bt_ble_scan_enable(0, 0); + ble_multi_client_disconnect(); + } +} + +void client_profile_init(void) +{ + log_info("%s\n", __FUNCTION__); + + //setup GATT client + gatt_client_init(); + gatt_client_register_packet_handler(client_cbk_packet_handler); + memset(&conn_pair_info, 0, sizeof(struct pair_info_t)); + memset(conn_pair_info_table, 0, sizeof(conn_pair_info_table)); + conn_pair_info.head_tag = BLE_VM_HEAD_TAG; + conn_pair_info.tail_tag = BLE_VM_TAIL_TAG; + +} + + + +void bt_multi_client_init(void) +{ + log_info("%s\n", __FUNCTION__); + + ASSERT(client_config != NULL, "%s\n", "client's config not init\n"); + + cur_dev_cid = 0; + memset(&ble_work_state, BLE_ST_INIT_OK, SUPPORT_MAX_CLIENT); + memset(&client_con_handle, 0, SUPPORT_MAX_CLIENT << 1); + + set_ble_work_state(cur_dev_cid, BLE_ST_INIT_OK); + conn_pair_vm_do(&conn_pair_info, 0); + device_bonding_init(); + ble_client_module_enable(1); + +#if SHOW_RX_DATA_RATE + client_timer_start(); +#endif /* SHOW_RX_DATA_RATE */ +} + +void bt_multi_client_exit(void) +{ + log_info("%s\n", __FUNCTION__); + ble_client_module_enable(0); +} + +//主机请求更新连接参数 +void client_send_conn_param_update(void) +{ + struct conn_update_param_t *param = (void *)&connection_param_table[send_param_index];//for test + log_info("client update param:-%d-%d-%d-%d-\n", param->interval_min, param->interval_max, param->latency, param->timeout); + if (client_con_handle[cur_dev_cid]) { + ble_op_conn_param_update(client_con_handle[cur_dev_cid], param); + } +} + +/* static void test_send_conn_update(void) */ +/* { */ +/* client_send_conn_param_update(); */ +/* send_param_index++; */ +/* send_param_index &= 3; */ +/* sys_timeout_add(0,test_send_conn_update,10000); */ +/* } */ + +//切换已连接多机 +int le_multi_client_switch_connect_cid(u8 cid) +{ + if (cid < SUPPORT_MAX_CLIENT && client_con_handle[cid]) { + cur_dev_cid = cid; + return 0; + } else { + log_info("cid not exist!!!\n"); + return -1; + } +} + +//---------------------------------------------------------------------------------- + + + +#endif + + diff --git a/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_common.c b/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_common.c new file mode 100644 index 0000000..55f0186 --- /dev/null +++ b/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_common.c @@ -0,0 +1,414 @@ +/********************************************************************************************* + * Filename : le_server_module.c + + * Description : + + * Author : + + * Email : zh-jieli.com + + * Last modifiled : 2017-01-17 11:14 + + * Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved. +*********************************************************************************************/ + +// ***************************************************************************** +/* EXAMPLE_START(le_counter): LE Peripheral - Heartbeat Counter over GATT + * + * @text All newer operating systems provide GATT Client functionality. + * The LE Counter examples demonstrates how to specify a minimal GATT Database + * with a custom GATT Service and a custom Characteristic that sends periodic + * notifications. + */ +// ***************************************************************************** +#include "system/app_core.h" +#include "system/includes.h" + +#include "app_config.h" +#include "app_action.h" + +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "user_cfg.h" +#include "vm.h" +#include "btcontroller_modules.h" +#include "bt_common.h" +#include "3th_profile_api.h" + +#include "le_common.h" + +#include "rcsp_bluetooth.h" +#include "JL_rcsp_api.h" +#include "custom_cfg.h" +#include "btstack/btstack_event.h" +#include "tuya_le_multi_common.h" + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_TUYA_MULTI) + +#if LE_DEBUG_PRINT_EN +/* extern void printf_buf(u8 *buf, u32 len); */ +//#define log_info r_printf +#define log_info(x, ...) printf("[LE-MUL-COMM]" x " ", ## __VA_ARGS__) +#define log_info_hexdump put_buf + +#else +#define log_info(...) +#define log_info_hexdump(...) +#endif + +//---------------------------------------------------------------------------------------- +#define MULTI_ATT_MTU_SIZE (512) //ATT MTU的值 + +//ATT发送的包长, note: 20 <= need >= MTU +#define MULTI_ATT_LOCAL_PAYLOAD_SIZE (MULTI_ATT_MTU_SIZE) // +//ATT缓存的buffer大小, note: need >= 20,可修改 +#define MULTI_ATT_SEND_CBUF_SIZE (512*3) // + +//共配置的RAM +#define MULTI_ATT_RAM_BUFSIZE (ATT_CTRL_BLOCK_SIZE + MULTI_ATT_LOCAL_PAYLOAD_SIZE + MULTI_ATT_SEND_CBUF_SIZE) //note: +static u8 multi_att_ram_buffer[MULTI_ATT_RAM_BUFSIZE] __attribute__((aligned(4))); + +u16 server_con_handle[SUPPORT_MAX_SERVER]; +u16 client_con_handle[SUPPORT_MAX_CLIENT]; + +extern const int config_btctler_le_hw_nums; +extern const int config_btctler_le_rx_nums; +extern const int config_btctler_le_acl_total_nums; +extern const int config_le_sm_support_enable; +extern const int config_btctler_le_master_multilink; + +extern void sm_set_master_request_pair(int enable); +//---------------------------------------------------------------------------------------- +s8 mul_get_dev_index(u16 handle, u8 role) +{ + s8 i; + u16 *group_handle; + u8 count; + + if (!role) { + group_handle = server_con_handle; + count = SUPPORT_MAX_SERVER; + } else { + group_handle = client_con_handle; + count = SUPPORT_MAX_CLIENT; + } + + for (i = 0; i < count; i++) { + if (handle == group_handle[i]) { + return i; + } + } + return -1; +} + +s8 mul_get_idle_dev_index(u8 role) +{ + s8 i; + u16 *group_handle; + u8 count; + + if (!role) { + group_handle = server_con_handle; + count = SUPPORT_MAX_SERVER; + } else { + group_handle = client_con_handle; + count = SUPPORT_MAX_CLIENT; + } + + for (i = 0; i < count; i++) { + if (0 == group_handle[i]) { + return i; + } + } + return -1; +} + + +s8 mul_del_dev_index(u16 handle, u8 role) +{ + s8 i; + u16 *group_handle; + u8 count; + + if (!role) { + group_handle = server_con_handle; + count = SUPPORT_MAX_SERVER; + } else { + group_handle = client_con_handle; + count = SUPPORT_MAX_CLIENT; + } + + + for (i = 0; i < count; i++) { + if (handle == group_handle[i]) { + group_handle[i] = 0; + return i; + } + } + return -1; +} + +bool mul_dev_have_connected(u8 role) +{ + s8 i; + u16 *group_handle; + u8 count; + + if (!role) { + group_handle = server_con_handle; + count = SUPPORT_MAX_SERVER; + } else { + group_handle = client_con_handle; + count = SUPPORT_MAX_CLIENT; + } + + for (i = 0; i < count; i++) { + if (group_handle[i]) { + return true; + } + } + return false; +} + +u16 mul_dev_get_conn_handle(u8 index, u8 role) +{ + u16 *group_handle; + u8 count; + + if (!role) { + group_handle = server_con_handle; + count = SUPPORT_MAX_SERVER; + } else { + group_handle = client_con_handle; + count = SUPPORT_MAX_CLIENT; + } + + if (index < count) { + return group_handle[index]; + } else { + return 0; + } +} + + +void cbk_sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + sm_just_event_t *event = (void *)packet; + u32 tmp32; + log_info("%s\n", __FUNCTION__); + + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + case SM_EVENT_JUST_WORKS_REQUEST: + sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); + log_info("Just Works Confirmed.\n"); + break; + case SM_EVENT_PASSKEY_DISPLAY_NUMBER: + log_info_hexdump(packet, size); + memcpy(&tmp32, event->data, 4); + log_info("Passkey display: %06u.\n", tmp32); + break; + } + break; + } +} + +/* LISTING_START(packetHandler): Packet Handler */ +static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ +#if SUPPORT_MAX_SERVER + trans_cbk_packet_handler(packet_type, channel, packet, size); +#endif + +#if SUPPORT_MAX_CLIENT + client_cbk_packet_handler(packet_type, channel, packet, size); +#endif +} + +#define PASSKEY_ENTER_ENABLE 0 //输入passkey使能,可修改passkey +//重设passkey回调函数,在这里可以重新设置passkey +//passkey为6个数字组成,十万位、万位。。。。个位 各表示一个数字 高位不够为0 +static void reset_passkey_cb(u32 *key) +{ +#if 1 + u32 newkey = rand32();//获取随机数 + + newkey &= 0xfffff; + if (newkey > 999999) { + newkey = newkey - 999999; //不能大于999999 + } + *key = newkey; //小于或等于六位数 + log_info("set new_key= %06u\n", *key); +#else + *key = 123456; //for debug +#endif +} + +void ble_sm_setup_init(io_capability_t io_type, u8 auth_req, uint8_t min_key_size, u8 security_en) +{ + //setup SM: Display only + log_info("%s\n", __FUNCTION__); + sm_init(); + sm_set_io_capabilities(io_type); + sm_set_authentication_requirements(auth_req); + sm_set_encryption_key_size_range(min_key_size, 16); + sm_set_request_security(security_en); + sm_set_master_request_pair(security_en); + sm_event_callback_set(&cbk_sm_packet_handler); + + if (io_type == IO_CAPABILITY_DISPLAY_ONLY) { + reset_PK_cb_register(reset_passkey_cb); + } +} + +void ble_profile_init(void) +{ + log_info("%s\n", __FUNCTION__); + +#if SUPPORT_MAX_SERVER && SUPPORT_MAX_CLIENT + ble_stack_gatt_role(2); +#elif SUPPORT_MAX_CLIENT + ble_stack_gatt_role(1); +#else + ble_stack_gatt_role(0); +#endif + + ble_vendor_set_default_att_mtu(MULTI_ATT_MTU_SIZE); + + if (config_le_sm_support_enable) { + le_device_db_init(); +#if PASSKEY_ENTER_ENABLE + ble_sm_setup_init(IO_CAPABILITY_DISPLAY_ONLY, SM_AUTHREQ_MITM_PROTECTION, 7, TCFG_BLE_SECURITY_EN); +#else + ble_sm_setup_init(IO_CAPABILITY_NO_INPUT_NO_OUTPUT, SM_AUTHREQ_BONDING, 7, TCFG_BLE_SECURITY_EN); +#endif + } + +#if SUPPORT_MAX_SERVER + server_profile_init(); +#endif + +#if SUPPORT_MAX_CLIENT + client_profile_init(); +#endif + + // register for HCI events + hci_event_callback_set(&cbk_packet_handler); + /* ble_l2cap_register_packet_handler(packet_cbk); */ + /* sm_event_packet_handler_register(packet_cbk); */ + le_l2cap_register_packet_handler(&cbk_packet_handler); + + ble_op_multi_att_send_init(multi_att_ram_buffer, MULTI_ATT_SEND_CBUF_SIZE, MULTI_ATT_LOCAL_PAYLOAD_SIZE); +} + +//统一接口,关闭模块 +void ble_module_enable(u8 en) +{ + log_info("mode_en:%d\n", en); + +#if SUPPORT_MAX_SERVER + ble_trans_module_enable(en); +#endif + +#if SUPPORT_MAX_CLIENT + ble_client_module_enable(en); +#endif + +} + +void ble_app_disconnect(void) +{ +#if SUPPORT_MAX_SERVER + ble_multi_trans_disconnect(); +#endif + +#if SUPPORT_MAX_CLIENT + ble_multi_client_disconnect(); +#endif + + +} + +//--------------------------------------------- +void bt_ble_init(void) +{ + int error_reset = 0; + log_info("%s,%d\n", __FUNCTION__, __LINE__); + log_info("ble_file: %s", __FILE__); + + //确认配置是否ok + if (config_le_gatt_server_num + config_le_gatt_client_num > config_btctler_le_hw_nums) { + log_info("config_btctler_le_hw_nums not enough!!!\n"); + error_reset = 1; + } + + if (config_btctler_le_rx_nums < config_btctler_le_hw_nums * 3) { + log_info("config_btctler_le_rx_nums not enough!!!\n"); + error_reset = 1; + } + + if (config_btctler_le_acl_total_nums < config_btctler_le_hw_nums * 3) { + log_info("config_btctler_le_acl_total_nums not enough!!!\n"); + error_reset = 1; + } + + if (config_le_hci_connection_num > config_btctler_le_hw_nums) { + log_info("config_btctler_le_hw_nums not enough!!!\n"); + error_reset = 1; + } + + if (config_le_hci_connection_num && (config_le_gatt_server_num + config_le_gatt_client_num) > config_le_hci_connection_num) { + log_info("config_le_hci_connection_num not enough!!!\n"); + error_reset = 1; + } + + if (config_le_hci_connection_num && att_send_check_multi_dev(config_le_gatt_server_num, config_le_gatt_client_num)) { + log_info("no support more device!!!\n"); + error_reset = 1; + } + + if (SUPPORT_MAX_SERVER > config_le_gatt_server_num) { + log_info("config_le_gatt_server_num not enough!!!\n"); + error_reset = 1; + } + + if (SUPPORT_MAX_CLIENT > config_le_gatt_client_num) { + log_info("config_le_gatt_client_num not enough!!!\n"); + error_reset = 1; + } + + if (error_reset) { + printf("======error config!!!\n"); + ASSERT(0); + while (1); + } + +#if SUPPORT_MAX_SERVER + bt_multi_trans_init(); +#endif + +#if SUPPORT_MAX_CLIENT + bt_multi_client_init(); + if (config_btctler_le_master_multilink) { + //ble_vendor_set_hold_prio(0, 1); + } +#endif +} + +void bt_ble_exit(void) +{ + log_info("%s\n", __FUNCTION__); + +#if SUPPORT_MAX_SERVER + bt_multi_trans_exit(); +#endif + +#if SUPPORT_MAX_CLIENT + bt_multi_client_exit(); +#endif +} + +#endif + + diff --git a/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_common.h b/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_common.h new file mode 100644 index 0000000..1fef9db --- /dev/null +++ b/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_common.h @@ -0,0 +1,49 @@ +// binary representation +// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) + +#ifndef _LE_MUTIL_COMMON_H +#define _LE_MUTIL_COMMON_H + +#include +#include "app_config.h" + +#if TUYA_MULTI_BLE_EN + +#define MULTI_ROLE_CLIENT 1 +#define MULTI_ROLE_SERVER 0 + +#define MULTI_ROLE_MASTER 1 +#define MULTI_ROLE_SLAVE 0 + +//--------------------------------- +#define SUPPORT_MAX_SERVER TRANS_MULTI_BLE_SLAVE_NUMS +#define SUPPORT_MAX_CLIENT TRANS_MULTI_BLE_MASTER_NUMS +//--------------------------------- +//---------------------------------------------------------------------------------------- +extern u16 server_con_handle[]; +extern u16 client_con_handle[]; + + +s8 mul_get_dev_index(u16 handle, u8 role); +s8 mul_get_idle_dev_index(u8 role); +s8 mul_del_dev_index(u16 handle, u8 role); +bool mul_dev_have_connected(u8 role); +u16 mul_dev_get_conn_handle(u8 index, u8 role); + +void bt_multi_trans_init(void); +void bt_multi_trans_exit(void); +void bt_multi_client_init(void); +void bt_multi_client_exit(void); +void trans_cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); +void client_cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); + +void client_profile_init(void); +void server_profile_init(void); +void ble_trans_module_enable(u8 en); +void ble_client_module_enable(u8 en); +void ble_multi_trans_disconnect(void); +void ble_multi_client_disconnect(void); + +#endif + +#endif diff --git a/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_trans.c b/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_trans.c new file mode 100644 index 0000000..c6c7483 --- /dev/null +++ b/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_trans.c @@ -0,0 +1,1121 @@ +/********************************************************************************************* + * Filename : le_server_module.c + + * Description : + + * Author : + + * Email : zh-jieli.com + + * Last modifiled : 2017-01-17 11:14 + + * Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved. +*********************************************************************************************/ + +// ***************************************************************************** +/* EXAMPLE_START(le_counter): LE Peripheral - Heartbeat Counter over GATT + * + * @text All newer operating systems provide GATT Client functionality. + * The LE Counter examples demonstrates how to specify a minimal GATT Database + * with a custom GATT Service and a custom Characteristic that sends periodic + * notifications. + */ +// ***************************************************************************** +#include "system/app_core.h" +#include "system/includes.h" + +#include "app_config.h" +#include "app_action.h" + +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "user_cfg.h" +#include "vm.h" +#include "btcontroller_modules.h" +#include "bt_common.h" +#include "3th_profile_api.h" + +#include "le_common.h" + +#include "rcsp_bluetooth.h" +#include "JL_rcsp_api.h" +#include "custom_cfg.h" +#include "btstack/btstack_event.h" +#include "tuya_le_multi_common.h" + +#define MUTIL_ROLE_IS_SERVER 1 +#include "tuya_le_multi_trans.h" + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_TUYA_MULTI&& SUPPORT_MAX_SERVER) + +//TRANS ANCS +#define TRANS_ANCS_EN 0 +#if TRANS_ANCS_EN +#include "btstack/btstack_event.h" +#endif + +#define TEST_SEND_HANDLE_VAL ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE +/* #define TEST_SEND_HANDLE_VAL ATT_CHARACTERISTIC_ae05_01_VALUE_HANDLE */ +#define EXT_ADV_MODE_EN 0 + +#define TEST_AUDIO_DATA_UPLOAD 0 //测试文件上传 + +#if 1//LE_DEBUG_PRINT_EN +extern void printf_buf(u8 *buf, u32 len); +/* #define log_info printf */ +#define log_info(x, ...) printf("[tuya_demo]" x " ", ## __VA_ARGS__) +#define log_info_hexdump printf_buf +#else +#define log_info(...) +#define log_info_hexdump(...) +#endif + + +/* #define LOG_TAG_CONST BT_BLE */ +/* #define LOG_TAG "[LE_S_DEMO]" */ +/* #define LOG_ERROR_ENABLE */ +/* #define LOG_DEBUG_ENABLE */ +/* #define LOG_INFO_ENABLE */ +/* #define LOG_DUMP_ENABLE */ +/* #define LOG_CLI_ENABLE */ +/* #include "debug.h" */ + +//------ +//ATT发送的包长, note: 20 <=need >= MTU + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x04) +#define ATT_LOCAL_MTU_SIZE (246) // +//ATT缓存的buffer大小, note: need >= 20,可修改 +#define ATT_SEND_CBUF_SIZE (246) // +#else +#define ATT_LOCAL_MTU_SIZE (23) // +//ATT缓存的buffer大小, note: need >= 20,可修改 +#define ATT_SEND_CBUF_SIZE (246) // +#endif + +//共配置的RAM +#define ATT_RAM_BUFSIZE (ATT_CTRL_BLOCK_SIZE + ATT_LOCAL_MTU_SIZE + ATT_SEND_CBUF_SIZE) //note: +static u8 att_ram_buffer[ATT_RAM_BUFSIZE] __attribute__((aligned(4))); +//--------------- + +/* + 打开流控使能后,确定使能接口 att_server_flow_enable 被调用 + 然后使用过程 通过接口 att_server_flow_hold 来控制流控开关 + 注意:流控只能控制对方使用带响应READ/WRITE等命令方式 + 例如:ATT_WRITE_REQUEST = 0x12 + */ +#define ATT_DATA_RECIEVT_FLOW 0//流控功能使能 + +//--------------- +// 广播周期 (unit:0.625ms) +#define ADV_INTERVAL_MIN (160*5) + +#define HOLD_LATENCY_CNT_MIN (3) //(0~0xffff) +#define HOLD_LATENCY_CNT_MAX (15) //(0~0xffff) +#define HOLD_LATENCY_CNT_ALL (0xffff) + +static volatile hci_con_handle_t con_handle; + +//加密设置 +/* static const uint8_t sm_min_key_size = 7; */ + +//连接参数更新请求设置 +//是否使能参数请求更新,0--disable, 1--enable +static const uint8_t connection_update_enable = 1; ///0--disable, 1--enable +//当前请求的参数表index +static uint8_t connection_update_cnt = 0; // + +//参数表 +static const struct conn_update_param_t connection_param_table[] = { + {16, 24, 10, 600},//11 + {12, 28, 10, 600},//3.7 + {8, 20, 10, 600}, + /* {12, 28, 4, 600},//3.7 */ + /* {12, 24, 30, 600},//3.05 */ +}; + +//共可用的参数组数 +#define CONN_PARAM_TABLE_CNT (sizeof(connection_param_table)/sizeof(struct conn_update_param_t)) + +#if (ATT_RAM_BUFSIZE < 64) +#error "adv_data & rsp_data buffer error!!!!!!!!!!!!" +#endif + +//用户可配对的,这是样机跟客户开发的app配对的秘钥 +/* const u8 link_key_data[16] = {0x06, 0x77, 0x5f, 0x87, 0x91, 0x8d, 0xd4, 0x23, 0x00, 0x5d, 0xf1, 0xd8, 0xcf, 0x0c, 0x14, 0x2b}; */ +#define EIR_TAG_STRING 0xd6, 0x05, 0x08, 0x00, 'J', 'L', 'A', 'I', 'S', 'D','K' +static const char user_tag_string[] = {EIR_TAG_STRING}; + +static u8 adv_data_len; +static u8 adv_data[ADV_RSP_PACKET_MAX];//max is 31 +static u8 scan_rsp_data_len; +static u8 scan_rsp_data[ADV_RSP_PACKET_MAX];//max is 31 + +/* #define adv_data &att_ram_buffer[0] */ +/* #define scan_rsp_data &att_ram_buffer[32] */ + +static char gap_device_name[BT_NAME_LEN_MAX] = "jl_ble_test"; +static u8 gap_device_name_len = 0; //名字长度,不包含结束符 +static u8 ble_work_state = 0; //ble 状态变化 +static u8 adv_ctrl_en; //广播控制 + +static u8 test_read_write_buf[4]; + +static void (*app_recieve_callback)(void *priv, void *buf, u16 len) = NULL; +static void (*app_ble_state_callback)(void *priv, ble_state_e state) = NULL; +static void (*ble_resume_send_wakeup)(void) = NULL; +static u32 channel_priv; + +static int app_send_user_data_check(u16 len); +int tuya_app_send_user_data_do(void *priv, u8 *data, u16 len); +static int app_send_user_data(u16 handle, u8 *data, u16 len, u8 handle_type); + +// Complete Local Name 默认的蓝牙名字 + +//------------------------------------------------------ +//广播参数设置 +static void advertisements_setup_init(); +static int set_adv_enable(void *priv, u32 en); +static int get_buffer_vaild_len(void *priv); +extern const char *bt_get_local_name(); +extern void clr_wdt(void); +extern void sys_auto_shut_down_disable(void); +extern void sys_auto_shut_down_enable(void); +extern u8 get_total_connect_dev(void); +extern u8 JL_tuya_ble_gatt_receive_data(u8 *p_data, u16 len); + +//------------------------------------------------------ +//NACS +#if TRANS_ANCS_EN +#define ANCS_SUBEVENT_CLIENT_NOTIFICATION 0xF1 +void ancs_client_init(void); +void ancs_client_register_callback(btstack_packet_handler_t callback); +const char *ancs_client_attribute_name_for_id(int id); +void ancs_set_notification_buffer(u8 *buffer, u16 buffer_size); + +//ancs info buffer +#define ANCS_INFO_BUFFER_SIZE (1024) +static u8 ancs_info_buffer[ANCS_INFO_BUFFER_SIZE]; +#endif + +static void send_request_connect_parameter(u8 table_index) +{ + struct conn_update_param_t *param = (void *)&connection_param_table[table_index];//static ram + + log_info("update_request:-%d-%d-%d-%d-\n", param->interval_min, param->interval_max, param->latency, param->timeout); + if (con_handle) { + ble_op_conn_param_request(con_handle, param); + } +} + +static void check_connetion_updata_deal(void) +{ + if (connection_update_enable) { + if (connection_update_cnt < CONN_PARAM_TABLE_CNT) { + send_request_connect_parameter(connection_update_cnt); + } + } +} + +static void connection_update_complete_success(u8 *packet) +{ + int con_handle, conn_interval, conn_latency, conn_timeout; + + con_handle = hci_subevent_le_connection_update_complete_get_connection_handle(packet); + conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet); + conn_latency = hci_subevent_le_connection_update_complete_get_conn_latency(packet); + conn_timeout = hci_subevent_le_connection_update_complete_get_supervision_timeout(packet); + + log_info("conn_interval = %d\n", conn_interval); + log_info("conn_latency = %d\n", conn_latency); + log_info("conn_timeout = %d\n", conn_timeout); +} + + +static void set_ble_work_state(ble_state_e state) +{ + if (state != ble_work_state) { + log_info("ble_work_st:%x->%x\n", ble_work_state, state); + ble_work_state = state; + if (app_ble_state_callback) { + app_ble_state_callback((void *)channel_priv, state); + } + } +} + +static ble_state_e get_ble_work_state(void) +{ + return ble_work_state; +} + +static void cbk_sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + sm_just_event_t *event = (void *)packet; + u32 tmp32; + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + case SM_EVENT_JUST_WORKS_REQUEST: + sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); + log_info("Just Works Confirmed.\n"); + break; + case SM_EVENT_PASSKEY_DISPLAY_NUMBER: + log_info_hexdump(packet, size); + memcpy(&tmp32, event->data, 4); + log_info("Passkey display: %06u.\n", tmp32); + break; + } + break; + } +} + + +static void can_send_now_wakeup(void) +{ + /* putchar('E'); */ + if (ble_resume_send_wakeup) { + ble_resume_send_wakeup(); + } +} + +static void ble_auto_shut_down_enable(u8 enable) +{ +#if TCFG_AUTO_SHUT_DOWN_TIME + if (enable) { + if (get_total_connect_dev() == 0) { //已经没有设备连接 + sys_auto_shut_down_enable(); + } + } else { + sys_auto_shut_down_disable(); + } +#endif +} + +const char *const phy_result[] = { + "None", + "1M", + "2M", + "Coded", +}; + +static void set_connection_data_length(u16 tx_octets, u16 tx_time) +{ + if (con_handle) { + ble_op_set_data_length(con_handle, tx_octets, tx_time); + } +} + +static void set_connection_data_phy(u8 tx_phy, u8 rx_phy) +{ + if (0 == con_handle) { + return; + } + + u8 all_phys = 0; + u16 phy_options = CONN_SET_PHY_OPTIONS_S8; + + ble_op_set_ext_phy(con_handle, all_phys, tx_phy, rx_phy, phy_options); +} + +static void server_profile_start(u16 con_handle) +{ +#if BT_FOR_APP_EN + set_app_connect_type(TYPE_BLE); +#endif + ble_op_att_send_init(con_handle, att_ram_buffer, ATT_RAM_BUFSIZE, ATT_LOCAL_MTU_SIZE); + set_ble_work_state(BLE_ST_CONNECT); + ble_auto_shut_down_enable(0); + + /* set_connection_data_phy(CONN_SET_CODED_PHY, CONN_SET_CODED_PHY); */ +} + +_WEAK_ +u8 ble_update_get_ready_jump_flag(void) +{ + return 0; +} +/* + * @section Packet Handler + * + * @text The packet handler is used to: + * - stop the counter after a disconnect + * - send a notification when the requested ATT_EVENT_CAN_SEND_NOW is received + */ + +/* LISTING_START(packetHandler): Packet Handler */ +static void trans_cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + int mtu; + u32 tmp; + u8 status; + const char *attribute_name; + + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + + /* case DAEMON_EVENT_HCI_PACKET_SENT: */ + /* break; */ + case ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE: + log_info("ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE\n"); + case ATT_EVENT_CAN_SEND_NOW: + can_send_now_wakeup(); + break; + + case HCI_EVENT_LE_META: + switch (hci_event_le_meta_get_subevent_code(packet)) { + case HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE: + status = hci_subevent_le_enhanced_connection_complete_get_status(packet); + if (status) { + log_info("LE_SLAVE CONNECTION FAIL!!! %0x\n", status); + set_ble_work_state(BLE_ST_DISCONN); + break; + } + con_handle = hci_subevent_le_enhanced_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE : %0x\n", con_handle); + log_info("conn_interval = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_interval(packet)); + log_info("conn_latency = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_latency(packet)); + log_info("conn_timeout = %d\n", hci_subevent_le_enhanced_connection_complete_get_supervision_timeout(packet)); + server_profile_start(con_handle); + break; + + case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: + con_handle = hci_subevent_le_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_CONNECTION_COMPLETE: %0x\n", con_handle); + connection_update_complete_success(packet + 8); + server_profile_start(con_handle); + log_info("ble remote rssi= %d\n", ble_vendor_get_peer_rssi(con_handle)); + log_info("tuya_ble_connection_handler\n"); + tuya_ble_connected_handler(); + + break; + + case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: + printf("HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE"); + connection_update_complete_success(packet); + break; + + case HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE: + log_info("APP HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE\n"); + /* set_connection_data_phy(CONN_SET_CODED_PHY, CONN_SET_CODED_PHY); */ + break; + + case HCI_SUBEVENT_LE_PHY_UPDATE_COMPLETE: + log_info("APP HCI_SUBEVENT_LE_PHY_UPDATE %s\n", hci_event_le_meta_get_phy_update_complete_status(packet) ? "Fail" : "Succ"); + log_info("Tx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_tx_phy(packet)]); + log_info("Rx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_rx_phy(packet)]); + break; + } + break; + + case HCI_EVENT_DISCONNECTION_COMPLETE: + log_info("HCI_EVENT_DISCONNECTION_COMPLETE: %0x\n", packet[5]); + con_handle = 0; + ble_op_att_send_init(con_handle, 0, 0, 0); + set_ble_work_state(BLE_ST_DISCONN); + + + connection_update_cnt = 0; +#if BT_FOR_APP_EN + set_app_connect_type(TYPE_NULL); +#endif + ble_auto_shut_down_enable(1); + log_info("tuya_ble_disconnection_handler\n"); + tuya_ble_disconnected_handler(); + + extern void tuya_ble_adv_change(void); + tuya_ble_adv_change(); + break; + + case ATT_EVENT_MTU_EXCHANGE_COMPLETE: + mtu = att_event_mtu_exchange_complete_get_MTU(packet) - 3; + log_info("ATT MTU = %u\n", mtu); + ble_op_att_set_send_mtu(mtu); + /* set_connection_data_length(251, 2120); */ + break; + + case HCI_EVENT_VENDOR_REMOTE_TEST: + log_info("--- HCI_EVENT_VENDOR_REMOTE_TEST\n"); + break; + + case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE: + tmp = little_endian_read_16(packet, 4); + log_info("-update_rsp: %02x\n", tmp); + if (tmp) { + connection_update_cnt++; + log_info("remoter reject!!!\n"); + check_connetion_updata_deal(); + } else { + connection_update_cnt = CONN_PARAM_TABLE_CNT; + } + break; + + case HCI_EVENT_ENCRYPTION_CHANGE: + log_info("HCI_EVENT_ENCRYPTION_CHANGE= %d\n", packet[2]); + break; + +#if TRANS_ANCS_EN + case HCI_EVENT_ANCS_META: + switch (hci_event_ancs_meta_get_subevent_code(packet)) { + case ANCS_SUBEVENT_CLIENT_NOTIFICATION: + printf("ANCS_SUBEVENT_CLIENT_NOTIFICATION \n"); + attribute_name = ancs_client_attribute_name_for_id(ancs_subevent_client_notification_get_attribute_id(packet)); + if (!attribute_name) { + printf("ancs unknow attribute_id :%d \n", ancs_subevent_client_notification_get_attribute_id(packet)); + break; + } else { + u16 attribute_strlen = little_endian_read_16(packet, 7); + u8 *attribute_str = (void *)little_endian_read_32(packet, 9); + printf("Notification: %s - %s \n", attribute_name, attribute_str); + } + break; + default: + break; + } + + break; +#endif + + } + break; + } +} + + +/* LISTING_END */ + +/* + * @section ATT Read + * + * @text The ATT Server handles all reads to constant data. For dynamic data like the custom characteristic, the registered + * att_read_callback is called. To handle long characteristics and long reads, the att_read_callback is first called + * with buffer == NULL, to request the total value length. Then it will be called again requesting a chunk of the value. + * See Listing attRead. + */ + +/* LISTING_END */ +/* + * @section ATT Write + * + * @text The only valid ATT write in this example is to the Client Characteristic Configuration, which configures notification + * and indication. If the ATT handle matches the client configuration handle, the new configuration value is stored and used + * in the heartbeat handler to decide if a new value should be sent. See Listing attWrite. + */ + +/* LISTING_START(attWrite): ATT Write */ +static int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size) +{ + int result = 0; + u16 tmp16; + u8 *tmp_buf = NULL; + u16 handle = att_handle; + + //log_info("write_callback, handle= 0x%04x,size = %d\n", handle, buffer_size); + //put_buf(buffer, buffer_size); + + switch (handle) { +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x03) + case ATT_CHARACTERISTIC_2b10_01_CLIENT_CONFIGURATION_HANDLE: + set_ble_work_state(BLE_ST_NOTIFY_IDICATE); + check_connetion_updata_deal(); + printf("\n------write ccc:%04x,%02x\n", handle, buffer[0]); + att_set_ccc_config(handle, buffer[0]); + break; + + case ATT_CHARACTERISTIC_2b11_01_VALUE_HANDLE: + printf("TUYA msg receive, handle = 0x%x, size = %d\n", handle, buffer_size); + //put_buf(buffer, buffer_size); + JL_tuya_ble_gatt_receive_data(buffer, buffer_size); + break; +#endif + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x04) + case ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_CLIENT_CONFIGURATION_HANDLE: + set_ble_work_state(BLE_ST_NOTIFY_IDICATE); + check_connetion_updata_deal(); + printf("\n------write ccc:%04x,%02x\n", handle, buffer[0]); + att_set_ccc_config(handle, buffer[0]); + break; + + case ATT_CHARACTERISTIC_00000001_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE: + printf("\nTUYA msg receive, handle = 0x%x, size = %d\n", handle, buffer_size); + //put_buf(buffer, buffer_size); + JL_tuya_ble_gatt_receive_data(buffer, buffer_size); + break; + + case ATT_CHARACTERISTIC_00000003_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE: + printf("\nTUYA read msg, handle = 0x%x, size = %d\n", handle, buffer_size); + put_buf(buffer, buffer_size); + break; + +#endif + + default: + printf("\n\nunknow handle:%d\n\n", handle); + break; + } + + return 0; +} + +static int app_send_user_data(u16 handle, u8 *data, u16 len, u8 handle_type) +{ + u32 ret = APP_BLE_NO_ERROR; + + if (!con_handle) { + return APP_BLE_OPERATION_ERROR; + } + + if (!att_get_ccc_config(handle + 1)) { + log_info("fail,no write ccc!!!,%04x\n", handle + 1); + return APP_BLE_NO_WRITE_CCC; + } + + ret = ble_op_att_send_data(handle, data, len, handle_type); + if (ret == BLE_BUFFER_FULL) { + ret = APP_BLE_BUFF_FULL; + } + + if (ret) { + log_info("app_send_fail:%d !!!!!!\n", ret); + } + return ret; +} + +//------------------------------------------------------ +static int make_set_adv_data(void) +{ + u8 offset = 0; + u8 *buf = adv_data; + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x03) + u8 service_data[11] = {0x01, 0xA2, 0x00, 0x65, 0x36, 0x6A, 0x6C, 0x6C, 0x70, 0x79, 0x37}; + + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_FLAGS, 0x06, 1); + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_MORE_16BIT_SERVICE_UUIDS, 0xA201, 2); + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_SERVICE_DATA, (void *)service_data, 11); +#endif + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x04) + u8 service_data[22] = {0x50, 0XFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_FLAGS, 0x06, 1); + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_MORE_16BIT_SERVICE_UUIDS, 0x50FD, 2); + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_SERVICE_DATA, (void *)service_data, 22); +#endif + + if (offset > ADV_RSP_PACKET_MAX) { + puts("***adv_data overflow!!!!!!\n"); + return -1; + } + log_info("adv_data(%d):", offset); + log_info_hexdump(buf, offset); + adv_data_len = offset; + ble_op_set_adv_data(offset, buf); + return 0; +} + +static int make_set_rsp_data(void) +{ + u8 offset = 0; + u8 *buf = scan_rsp_data; + + u8 name_len = gap_device_name_len; + u8 vaild_len = ADV_RSP_PACKET_MAX - (offset + 2); + if (name_len > vaild_len) { + name_len = vaild_len; + } + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x03) + u8 ble_specific_data[24] = {0xD0, 0x07, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x38, 0xD1, 0x4B, 0xE7, 0xF3, 0x61, 0xB8, 0xB3, 0xFA, 0x4E, 0x8C, 0x70, 0xD5, 0xEB, 0x25, 0x7E}; + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME, 0x5954, 2); + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA, (void *)ble_specific_data, 24); +#endif + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x04) + u8 ble_specific_data[22] = {0xD0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME, 0x5954, 2); + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA, (void *)ble_specific_data, 24); +#endif + + + if (offset > ADV_RSP_PACKET_MAX) { + puts("***rsp_data overflow!!!!!!\n"); + return -1; + } + + log_info("rsp_data(%d):", offset); + log_info_hexdump(buf, offset); + scan_rsp_data_len = offset; + ble_op_set_rsp_data(offset, buf); + return 0; +} + +//广播参数设置 +static void advertisements_setup_init() +{ + uint8_t adv_type = ADV_IND; + uint8_t adv_channel = ADV_CHANNEL_ALL; + int ret = 0; + + ble_op_set_adv_param(ADV_INTERVAL_MIN, adv_type, adv_channel); + + ret |= make_set_adv_data(); + ret |= make_set_rsp_data(); + + if (ret) { + puts("advertisements_setup_init fail !!!!!!\n"); + return; + } + +} + +#define PASSKEY_ENTER_ENABLE 0 //输入passkey使能,可修改passkey +//重设passkey回调函数,在这里可以重新设置passkey +//passkey为6个数字组成,十万位、万位。。。。个位 各表示一个数字 高位不够为0 +static void reset_passkey_cb(u32 *key) +{ +#if 1 + u32 newkey = rand32();//获取随机数 + + newkey &= 0xfffff; + if (newkey > 999999) { + newkey = newkey - 999999; //不能大于999999 + } + *key = newkey; //小于或等于六位数 + printf("set new_key= %06u\n", *key); +#else + *key = 123456; //for debug +#endif +} + +void server_profile_init(void) +{ + printf("TUYA ble profile init\n"); + le_device_db_init(); + +#if PASSKEY_ENTER_ENABLE + ble_sm_setup_init(IO_CAPABILITY_DISPLAY_ONLY, SM_AUTHREQ_MITM_PROTECTION, 7, TCFG_BLE_SECURITY_EN); +#else + /* ble_sm_setup_init(IO_CAPABILITY_NO_INPUT_NO_OUTPUT, SM_AUTHREQ_BONDING, 7, TCFG_BLE_SECURITY_EN); */ + ble_sm_setup_init(IO_CAPABILITY_NO_INPUT_NO_OUTPUT, SM_AUTHREQ_BONDING, 7, 0); +#endif + + /* setup ATT server */ + att_server_init(profile_data, NULL, att_write_callback); + att_server_register_packet_handler(trans_cbk_packet_handler); + /* gatt_client_register_packet_handler(packet_cbk); */ + + // register for HCI events + hci_event_callback_set(&trans_cbk_packet_handler); + /* ble_l2cap_register_packet_handler(packet_cbk); */ + /* sm_event_packet_handler_register(packet_cbk); */ + le_l2cap_register_packet_handler(&trans_cbk_packet_handler); + +#if TRANS_ANCS_EN + //setup GATT client + gatt_client_init(); + + //setup ANCS clent + ancs_client_init(); + ancs_set_notification_buffer(ancs_info_buffer, sizeof(ancs_info_buffer)); + ancs_client_register_callback(&cbk_packet_handler); +#endif + + extern u16 ble_vendor_set_default_att_mtu(u16 mtu_size); + ble_vendor_set_default_att_mtu(ATT_LOCAL_MTU_SIZE); +} + +#if EXT_ADV_MODE_EN + + +#define EXT_ADV_NAME 'J', 'L', '_', 'E', 'X', 'T', '_', 'A', 'D', 'V' +/* #define EXT_ADV_NAME "JL_EXT_ADV" */ +#define BYTE_LEN(x...) sizeof((u8 []) {x}) +#define EXT_ADV_DATA \ + 0x02, 0x01, 0x06, \ + 0x03, 0x02, 0xF0, 0xFF, \ + BYTE_LEN(EXT_ADV_NAME) + 1, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, EXT_ADV_NAME + +struct ext_advertising_param { + u8 Advertising_Handle; + u16 Advertising_Event_Properties; + u8 Primary_Advertising_Interval_Min[3]; + u8 Primary_Advertising_Interval_Max[3]; + u8 Primary_Advertising_Channel_Map; + u8 Own_Address_Type; + u8 Peer_Address_Type; + u8 Peer_Address[6]; + u8 Advertising_Filter_Policy; + u8 Advertising_Tx_Power; + u8 Primary_Advertising_PHY; + u8 Secondary_Advertising_Max_Skip; + u8 Secondary_Advertising_PHY; + u8 Advertising_SID; + u8 Scan_Request_Notification_Enable; +} _GNU_PACKED_; + +struct ext_advertising_data { + u8 Advertising_Handle; + u8 Operation; + u8 Fragment_Preference; + u8 Advertising_Data_Length; + u8 Advertising_Data[BYTE_LEN(EXT_ADV_DATA)]; +} _GNU_PACKED_; + +struct ext_advertising_enable { + u8 Enable; + u8 Number_of_Sets; + u8 Advertising_Handle; + u16 Duration; + u8 Max_Extended_Advertising_Events; +} _GNU_PACKED_; + +const struct ext_advertising_param ext_adv_param = { + .Advertising_Handle = 0, + .Advertising_Event_Properties = 1, + .Primary_Advertising_Interval_Min = {30, 0, 0}, + .Primary_Advertising_Interval_Max = {30, 0, 0}, + .Primary_Advertising_Channel_Map = 7, + .Primary_Advertising_PHY = ADV_SET_1M_PHY, + .Secondary_Advertising_PHY = ADV_SET_1M_PHY, +}; + +const struct ext_advertising_data ext_adv_data = { + .Advertising_Handle = 0, + .Operation = 3, + .Fragment_Preference = 0, + .Advertising_Data_Length = BYTE_LEN(EXT_ADV_DATA), + .Advertising_Data = EXT_ADV_DATA, +}; + +const struct ext_advertising_enable ext_adv_enable = { + .Enable = 1, + .Number_of_Sets = 1, + .Advertising_Handle = 0, + .Duration = 0, + .Max_Extended_Advertising_Events = 0, +}; + +const struct ext_advertising_enable ext_adv_disable = { + .Enable = 0, + .Number_of_Sets = 1, + .Advertising_Handle = 0, + .Duration = 0, + .Max_Extended_Advertising_Events = 0, +}; + +#endif /* EXT_ADV_MODE_EN */ + +void tuya_set_adv_enable() +{ + if (con_handle) { + printf("connect is exist return\n"); + return; + } + + if (!adv_ctrl_en) { + printf("!adv_ctrl_en return\n"); + return; + } + ble_op_adv_enable(1); +} + +static int set_adv_enable(void *priv, u32 en) +{ + ble_state_e next_state, cur_state; + + if (!adv_ctrl_en) { + return APP_BLE_OPERATION_ERROR; + } + + if (con_handle) { + return APP_BLE_OPERATION_ERROR; + } + + if (en) { + next_state = BLE_ST_ADV; + } else { + next_state = BLE_ST_IDLE; + } + + cur_state = get_ble_work_state(); + switch (cur_state) { + case BLE_ST_ADV: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + break; + default: + return APP_BLE_OPERATION_ERROR; + break; + } + + if (cur_state == next_state) { + return APP_BLE_NO_ERROR; + } + log_info("adv_en:%d\n", en); + set_ble_work_state(next_state); + +#if EXT_ADV_MODE_EN + if (en) { + ble_op_set_ext_adv_param(&ext_adv_param, sizeof(ext_adv_param)); + + log_info_hexdump(&ext_adv_data, sizeof(ext_adv_data)); + ble_op_set_ext_adv_data(&ext_adv_data, sizeof(ext_adv_data)); + + ble_op_set_ext_adv_enable(&ext_adv_enable, sizeof(ext_adv_enable)); + } else { + ble_op_set_ext_adv_enable(&ext_adv_disable, sizeof(ext_adv_disable)); + } +#else + if (en) { + advertisements_setup_init(); + } + ble_op_adv_enable(en); +#endif /* EXT_ADV_MODE_EN */ + + return APP_BLE_NO_ERROR; +} + +static int ble_trans_disconnect(void *priv) +{ + if (con_handle) { + if (BLE_ST_SEND_DISCONN != get_ble_work_state()) { + log_info(">>>tuya ble send disconnect\n"); + set_ble_work_state(BLE_ST_SEND_DISCONN); + ble_op_disconnect(con_handle); + } else { + log_info(">>>tuya ble wait disconnect...\n"); + } + return APP_BLE_NO_ERROR; + } else { + return APP_BLE_OPERATION_ERROR; + } +} + + +static int get_buffer_vaild_len(void *priv) +{ + u32 vaild_len = 0; + ble_op_att_get_remain(&vaild_len); + return vaild_len; +} + +int tuya_app_send_user_data_do(void *priv, u8 *data, u16 len) +{ +#if PRINT_DMA_DATA_EN + if (len < 128) { + log_info("-le_tx(%d):"); + log_info_hexdump(data, len); + } else { + putchar('L'); + } +#endif + att_set_ccc_config(ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE + 1, ATT_OP_NOTIFY); + return app_send_user_data(ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE, data, len, ATT_OP_AUTO_READ_CCC); + + return 0; + //return app_send_user_data(ATT_CHARACTERISTIC_2b10_01_VALUE_HANDLE, data, len, ATT_OP_AUTO_READ_CCC); +} + +static int app_send_user_data_check(u16 len) +{ + u32 buf_space = get_buffer_vaild_len(0); + if (len <= buf_space) { + return 1; + } + return 0; +} + + +static int regiest_wakeup_send(void *priv, void *cbk) +{ + ble_resume_send_wakeup = cbk; + return APP_BLE_NO_ERROR; +} + +static int regiest_recieve_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_recieve_callback = cbk; + return APP_BLE_NO_ERROR; +} + +static int regiest_state_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_ble_state_callback = cbk; + return APP_BLE_NO_ERROR; +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + + +u8 *ble_get_scan_rsp_ptr(u16 *len) +{ + if (len) { + *len = scan_rsp_data_len; + } + return scan_rsp_data; +} + +u8 *ble_get_adv_data_ptr(u16 *len) +{ + if (len) { + *len = adv_data_len; + } + return adv_data; +} + +u8 *ble_get_gatt_profile_data(u16 *len) +{ + *len = sizeof(profile_data); + return (u8 *)profile_data; +} + + +void bt_ble_adv_enable(u8 enable) +{ + set_adv_enable(0, enable); +} + +u16 bt_ble_is_connected(void) +{ + return con_handle; +} + +void ble_trans_module_enable(u8 en) +{ + if (en) { + adv_ctrl_en = 1; + bt_ble_adv_enable(1); + } else { + if (con_handle) { + adv_ctrl_en = 0; + ble_trans_disconnect(NULL); + } else { + bt_ble_adv_enable(0); + adv_ctrl_en = 0; + } + } +} + + +//流控使能 EN: 1-停止收数 or 0-继续收数 +int ble_trans_flow_enable(u8 en) +{ + int ret = -1; +#if ATT_DATA_RECIEVT_FLOW + if (con_handle) { + att_server_flow_hold(con_handle, en); + ret = 0; + } +#endif + log_info("ble_trans_flow_enable:%d,%d\n", en, ret); + return ret; +} + +//for test +static void timer_trans_flow_test(void) +{ + static u8 sw = 0; + if (con_handle) { + sw = !sw; + ble_trans_flow_enable(sw); + } +} + +static const char ble_ext_name[] = "(BLE)"; +int tuya_app_send_user_data(u8 *data, u16 len) +{ + int ret = 0; + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x03) + att_set_ccc_config(ATT_CHARACTERISTIC_2b10_01_VALUE_HANDLE + 1, ATT_OP_NOTIFY); + ret = app_send_user_data(ATT_CHARACTERISTIC_2b10_01_VALUE_HANDLE, data, len, ATT_OP_NOTIFY); +#endif +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x04) + att_set_ccc_config(ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE + 1, ATT_OP_NOTIFY); + ret = app_send_user_data(ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE, data, len, ATT_OP_NOTIFY); +#endif + printf("tuya_send_user_data: %d, len = %d\n", ret, len); + put_buf(data, len); + return ret ; +} + +void bt_multi_trans_init(void) +{ + log_info("***** ble_init******\n"); + char *name_p; + +#if DOUBLE_BT_SAME_NAME + u8 ext_name_len = 0; +#else + u8 ext_name_len = sizeof(ble_ext_name) - 1; +#endif + + name_p = bt_get_local_name(); + gap_device_name_len = strlen(name_p); + if (gap_device_name_len > BT_NAME_LEN_MAX - ext_name_len) { + gap_device_name_len = BT_NAME_LEN_MAX - ext_name_len; + } + + memcpy(gap_device_name, name_p, gap_device_name_len); + +#if DOUBLE_BT_SAME_NAME == 0 + //增加后缀,区分名字 + memcpy(&gap_device_name[gap_device_name_len], "(BLE)", ext_name_len); + gap_device_name_len += ext_name_len; +#endif + + log_info("ble name(%d): %s \n", gap_device_name_len, gap_device_name); + +#if ATT_DATA_RECIEVT_FLOW + log_info("att_server_flow_enable\n"); + att_server_flow_enable(1); + /* sys_timer_add(0, timer_trans_flow_test, 3000); */ +#endif + + set_ble_work_state(BLE_ST_INIT_OK); + ble_module_enable(1); + + extern void tuya_ble_app_init(); + tuya_ble_app_init(); +} + +void bt_multi_trans_exit(void) +{ + log_info("***** bt_multi_trans_exit******\n"); + + ble_module_enable(0); +} + +static const struct ble_server_operation_t mi_ble_operation = { + .adv_enable = set_adv_enable, + .disconnect = ble_trans_disconnect, + .get_buffer_vaild = get_buffer_vaild_len, + .send_data = (void *)tuya_app_send_user_data_do, + .regist_wakeup_send = regiest_wakeup_send, + .regist_recieve_cbk = regiest_recieve_cbk, + .regist_state_cbk = regiest_state_cbk, +}; + +void ble_get_server_operation_table(struct ble_server_operation_t **interface_pt) +{ + *interface_pt = (void *)&mi_ble_operation; +} + +void ble_server_send_test_key_num(u8 key_num) +{ + ; +} + + +#endif + + diff --git a/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_trans.h b/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_trans.h new file mode 100644 index 0000000..7d085e7 --- /dev/null +++ b/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_trans.h @@ -0,0 +1,126 @@ +// binary representation +// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) + +#ifndef _TUYA_DEMO_H +#define _TUYA_DEMO_H + +#include +#include "app_config.h" +#include "tuya_ble_internal_config.h" + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_TUYA_MULTI) +#if MUTIL_ROLE_IS_SERVER +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x03) +// +// gatt profile include file, generated by jieli gatt_inc_generator.exe +// + +const uint8_t profile_data[] = { + ////////////////////////////////////////////////////// + // + // 0x0001 PRIMARY_SERVICE 1800 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x18, + + /* CHARACTERISTIC, 2a00, READ | DYNAMIC, */ + // 0x0002 CHARACTERISTIC 2a00 READ | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x03, 0x00, 0x00, 0x2a, + // 0x0003 VALUE 2a00 READ | DYNAMIC + 0x08, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x2a, + + ////////////////////////////////////////////////////// + // + // 0x0004 PRIMARY_SERVICE 1910 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x28, 0x10, 0x19, + + /* CHARACTERISTIC, 2b10, NOTIFY | DYNAMIC, */ + // 0x0005 CHARACTERISTIC 2b10 NOTIFY | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x05, 0x00, 0x03, 0x28, 0x10, 0x06, 0x00, 0x10, 0x2b, + // 0x0006 VALUE 2b10 NOTIFY | DYNAMIC + 0x08, 0x00, 0x10, 0x01, 0x06, 0x00, 0x10, 0x2b, + // 0x0007 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x07, 0x00, 0x02, 0x29, 0x00, 0x00, + + /* CHARACTERISTIC, 2b11, WRITE | WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x0008 CHARACTERISTIC 2b11 WRITE | WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x08, 0x00, 0x03, 0x28, 0x0c, 0x09, 0x00, 0x11, 0x2b, + // 0x0009 VALUE 2b11 WRITE | WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x08, 0x00, 0x0c, 0x01, 0x09, 0x00, 0x11, 0x2b, + + // END + 0x00, 0x00, +}; +// +// characteristics <--> handles +// +#define ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE 0x0003 +#define ATT_CHARACTERISTIC_2b10_01_VALUE_HANDLE 0x0006 +#define ATT_CHARACTERISTIC_2b10_01_CLIENT_CONFIGURATION_HANDLE 0x0007 +#define ATT_CHARACTERISTIC_2b11_01_VALUE_HANDLE 0x0009 +#endif + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x04) +// +// gatt profile include file, generated by jieli gatt_inc_generator.exe +// + +const uint8_t profile_data[] = { + ////////////////////////////////////////////////////// + // + // 0x0001 PRIMARY_SERVICE 1800 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x18, + + /* CHARACTERISTIC, 2a00, READ | DYNAMIC, */ + // 0x0002 CHARACTERISTIC 2a00 READ | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x03, 0x00, 0x00, 0x2a, + // 0x0003 VALUE 2a00 READ | DYNAMIC + 0x08, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x2a, + + ////////////////////////////////////////////////////// + // + // 0x0004 PRIMARY_SERVICE FD50 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x28, 0x50, 0xfd, + + /* CHARACTERISTIC, 00000001-0000-1001-8001-00805F9B07D0, WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x0005 CHARACTERISTIC 00000001-0000-1001-8001-00805F9B07D0 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x1b, 0x00, 0x02, 0x00, 0x05, 0x00, 0x03, 0x28, 0x04, 0x06, 0x00, 0xd0, 0x07, 0x9b, 0x5f, 0x80, 0x00, 0x01, 0x80, 0x01, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + // 0x0006 VALUE 00000001-0000-1001-8001-00805F9B07D0 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x16, 0x00, 0x04, 0x03, 0x06, 0x00, 0xd0, 0x07, 0x9b, 0x5f, 0x80, 0x00, 0x01, 0x80, 0x01, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + + /* CHARACTERISTIC, 00000002-0000-1001-8001-00805F9B07D0, NOTIFY | DYNAMIC, */ + // 0x0007 CHARACTERISTIC 00000002-0000-1001-8001-00805F9B07D0 NOTIFY | DYNAMIC + 0x1b, 0x00, 0x02, 0x00, 0x07, 0x00, 0x03, 0x28, 0x10, 0x08, 0x00, 0xd0, 0x07, 0x9b, 0x5f, 0x80, 0x00, 0x01, 0x80, 0x01, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + // 0x0008 VALUE 00000002-0000-1001-8001-00805F9B07D0 NOTIFY | DYNAMIC + 0x16, 0x00, 0x10, 0x03, 0x08, 0x00, 0xd0, 0x07, 0x9b, 0x5f, 0x80, 0x00, 0x01, 0x80, 0x01, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + // 0x0009 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x09, 0x00, 0x02, 0x29, 0x00, 0x00, + + /* CHARACTERISTIC, 00000003-0000-1001-8001-00805F9B07D0, READ | DYNAMIC, */ + // 0x000a CHARACTERISTIC 00000003-0000-1001-8001-00805F9B07D0 READ | DYNAMIC + 0x1b, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x03, 0x28, 0x02, 0x0b, 0x00, 0xd0, 0x07, 0x9b, 0x5f, 0x80, 0x00, 0x01, 0x80, 0x01, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + // 0x000b VALUE 00000003-0000-1001-8001-00805F9B07D0 READ | DYNAMIC + 0x16, 0x00, 0x02, 0x03, 0x0b, 0x00, 0xd0, 0x07, 0x9b, 0x5f, 0x80, 0x00, 0x01, 0x80, 0x01, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + + // END + 0x00, 0x00, +}; +// +// characteristics <--> handles +// +#define ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE 0x0003 +#define ATT_CHARACTERISTIC_00000001_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE 0x0006 +#define ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE 0x0008 +#define ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_CLIENT_CONFIGURATION_HANDLE 0x0009 +#define ATT_CHARACTERISTIC_00000003_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE 0x000b +#endif + +#endif +#endif +#endif diff --git a/apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ble_app_demo.c b/apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ble_app_demo.c new file mode 100644 index 0000000..efe2e7f --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ble_app_demo.c @@ -0,0 +1,262 @@ +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" +#include "tuya_ble_heap.h" +#include "tuya_ble_mem.h" +#include "tuya_ble_api.h" +#include "tuya_ble_port.h" +#include "tuya_ble_main.h" +#include "tuya_ble_secure.h" +#include "tuya_ble_data_handler.h" +#include "tuya_ble_storage.h" +#include "tuya_ble_sdk_version.h" +#include "tuya_ble_utils.h" +#include "tuya_ble_event.h" +#include "tuya_ble_app_demo.h" +//#include "tuya_ble_demo_version.h" +#include "tuya_ble_log.h" +#include "tuya_ota.h" +#include "system/generic/printf.h" + +#include "log.h" +#include "system/includes.h" +//#include "ota.h" + +tuya_ble_device_param_t device_param = {0}; + +#define LED_PIN IO_PORTA_01 +static bool tuya_led_state = 0; +static const char device_id_test[] = "tuya58253f7c8ed1"; +static const char auth_key_test[] = "I9ikbTKVMhfvEDgARBCtFbAWUpZIRdyv"; +static const uint8_t mac_test[6] = {0xDC, 0x23, 0x4D, 0x65, 0xB0, 0x66}; //The actual MAC address is : 66:55:44:33:22:11 + + +#define APP_CUSTOM_EVENT_1 1 +#define APP_CUSTOM_EVENT_2 2 +#define APP_CUSTOM_EVENT_3 3 +#define APP_CUSTOM_EVENT_4 4 +#define APP_CUSTOM_EVENT_5 5 + +static uint8_t dp_data_array[255 + 3]; +static uint16_t dp_data_len = 0; + +typedef struct { + uint8_t data[50]; +} custom_data_type_t; + +void custom_data_process(int32_t evt_id, void *data) +{ + custom_data_type_t *event_1_data; + TUYA_APP_LOG_DEBUG("custom event id = %d", evt_id); + switch (evt_id) { + case APP_CUSTOM_EVENT_1: + event_1_data = (custom_data_type_t *)data; + TUYA_APP_LOG_HEXDUMP_DEBUG("received APP_CUSTOM_EVENT_1 data:", event_1_data->data, 50); + break; + case APP_CUSTOM_EVENT_2: + break; + case APP_CUSTOM_EVENT_3: + break; + case APP_CUSTOM_EVENT_4: + break; + case APP_CUSTOM_EVENT_5: + break; + default: + break; + + } +} + +custom_data_type_t custom_data; + +void custom_evt_1_send_test(uint8_t data) +{ + tuya_ble_custom_evt_t event; + + for (uint8_t i = 0; i < 50; i++) { + custom_data.data[i] = data; + } + event.evt_id = APP_CUSTOM_EVENT_1; + event.custom_event_handler = (void *)custom_data_process; + event.data = &custom_data; + tuya_ble_custom_event_send(event); +} + +static uint16_t sn = 0; +static uint32_t time_stamp = 1587795793; + +void tuya_data_init() +{ + struct { + uint8_t id; + uint8_t type; + uint16_t len; + uint8_t data; + } p_dp_data; + + p_dp_data.id = 1; + p_dp_data.type = 1; + p_dp_data.len = 0x0100; + p_dp_data.data = tuya_led_state; + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x03) + tuya_ble_dp_data_report(&p_dp_data, 5); //1 +#endif +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x04) + tuya_ble_dp_data_send(sn, DP_SEND_TYPE_ACTIVE, DP_SEND_FOR_CLOUD_PANEL, DP_SEND_WITH_RESPONSE, &p_dp_data, 5); +#endif +} + +void tuya_data_parse(tuya_ble_cb_evt_param_t *event) +{ + uint8_t *buf = event->dp_received_data.p_data; + uint32_t sn = event->dp_received_data.sn; + put_buf(buf, event->dp_received_data.data_len); + struct { + uint8_t id; + uint8_t type; + uint16_t len; + uint8_t data; + } p_dp_data; + + p_dp_data.id = buf[0]; + p_dp_data.type = buf[1]; + p_dp_data.len = 0x0100; + p_dp_data.data = buf[4]; + + printf("\n\n<-------------- tuya_data_parse -------------->"); + printf("sn = %d, id = %d, type = %d, len = %d, data = %d", sn, p_dp_data.id, p_dp_data.type, p_dp_data.len, p_dp_data.data); + + + switch (buf[0]) { + case 1: + printf("tuya switch control, onoff set to: %d\n", p_dp_data.data); + tuya_led_state = p_dp_data.data; + gpio_direction_output(LED_PIN, tuya_led_state); + break; + //case 2: + //printf("tuya mode control, mode set to: %d\n", buf[3]); + //break; + default: + printf("unknow control msg len = %d, data:", buf[2]); + break; + } +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x03) + tuya_ble_dp_data_report(&p_dp_data, 5); //1 +#endif +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x04) + tuya_ble_dp_data_send(sn, DP_SEND_TYPE_ACTIVE, DP_SEND_FOR_CLOUD_PANEL, DP_SEND_WITH_RESPONSE, &p_dp_data, 5); +#endif + +} + +static void tuya_cb_handler(tuya_ble_cb_evt_param_t *event) +{ + int16_t result = 0; + printf("tuya cb_handler event->evt=0x%x\n", event->evt); + switch (event->evt) { + case TUYA_BLE_CB_EVT_CONNECTE_STATUS: + TUYA_APP_LOG_INFO("received tuya ble conncet status update event,current connect status = %d", event->connect_status); + break; + case TUYA_BLE_CB_EVT_DP_DATA_RECEIVED: + tuya_data_parse(event); + break; + case TUYA_BLE_CB_EVT_DP_DATA_REPORT_RESPONSE: + TUYA_APP_LOG_INFO("received dp data report response result code =%d", event->dp_response_data.status); + + break; + case TUYA_BLE_CB_EVT_DP_DATA_WTTH_TIME_REPORT_RESPONSE: + TUYA_APP_LOG_INFO("received dp data report response result code =%d", event->dp_response_data.status); + break; + case TUYA_BLE_CB_EVT_DP_DATA_WITH_FLAG_REPORT_RESPONSE: + TUYA_APP_LOG_INFO("received dp data with flag report response sn = %d , flag = %d , result code =%d", event->dp_with_flag_response_data.sn, event->dp_with_flag_response_data.mode + , event->dp_with_flag_response_data.status); + + break; + case TUYA_BLE_CB_EVT_DP_DATA_WITH_FLAG_AND_TIME_REPORT_RESPONSE: + TUYA_APP_LOG_INFO("received dp data with flag and time report response sn = %d , flag = %d , result code =%d", event->dp_with_flag_and_time_response_data.sn, + event->dp_with_flag_and_time_response_data.mode, event->dp_with_flag_and_time_response_data.status); + + break; + case TUYA_BLE_CB_EVT_UNBOUND: + + TUYA_APP_LOG_INFO("received unbound req"); + + break; + case TUYA_BLE_CB_EVT_ANOMALY_UNBOUND: + + TUYA_APP_LOG_INFO("received anomaly unbound req"); + + break; + case TUYA_BLE_CB_EVT_DEVICE_RESET: + + TUYA_APP_LOG_INFO("received device reset req"); + + break; + case TUYA_BLE_CB_EVT_DP_QUERY: + TUYA_APP_LOG_INFO("received TUYA_BLE_CB_EVT_DP_QUERY event"); + if (dp_data_len > 0) { +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x03) + tuya_ble_dp_data_report(dp_data_array, dp_data_len); +#endif +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x04) + tuya_ble_dp_data_send(sn, DP_SEND_TYPE_ACTIVE, DP_SEND_FOR_CLOUD_PANEL, DP_SEND_WITH_RESPONSE, dp_data_array, dp_data_len); +#endif + } + break; + case TUYA_BLE_CB_EVT_OTA_DATA: + tuya_ota_proc(event->ota_data.type, event->ota_data.p_data, event->ota_data.data_len); + break; + case TUYA_BLE_CB_EVT_NETWORK_INFO: + TUYA_APP_LOG_INFO("received net info : %s", event->network_data.p_data); + tuya_ble_net_config_response(result); + break; + case TUYA_BLE_CB_EVT_WIFI_SSID: + + break; + case TUYA_BLE_CB_EVT_TIME_STAMP: + TUYA_APP_LOG_INFO("received unix timestamp : %s ,time_zone : %d", event->timestamp_data.timestamp_string, event->timestamp_data.time_zone); + tuya_data_init(); + break; + case TUYA_BLE_CB_EVT_TIME_NORMAL: + + break; + case TUYA_BLE_CB_EVT_DATA_PASSTHROUGH: + TUYA_APP_LOG_HEXDUMP_DEBUG("received ble passthrough data :", event->ble_passthrough_data.p_data, event->ble_passthrough_data.data_len); + tuya_ble_data_passthrough(event->ble_passthrough_data.p_data, event->ble_passthrough_data.data_len); + break; + default: + TUYA_APP_LOG_WARNING("app_tuya_cb_queue msg: unknown event type 0x%04x", event->evt); + break; + } + tuya_ble_inter_event_response(event); +} + + +void tuya_ble_app_init(void) +{ + device_param.device_id_len = 16; //If use the license stored by the SDK,initialized to 0, Otherwise 16 or 20. + + int ret = 0; + device_param.use_ext_license_key = 1; + if (device_param.device_id_len == 16) { + memcpy(device_param.auth_key, (void *)auth_key_test, AUTH_KEY_LEN); + memcpy(device_param.device_id, (void *)device_id_test, DEVICE_ID_LEN); + memcpy(device_param.mac_addr.addr, mac_test, 6); + device_param.mac_addr.addr_type = TUYA_BLE_ADDRESS_TYPE_RANDOM; + } + device_param.p_type = TUYA_BLE_PRODUCT_ID_TYPE_PID; + device_param.product_id_len = 8; + memcpy(device_param.product_id, APP_PRODUCT_ID, 8); + device_param.firmware_version = TY_APP_VER_NUM; + device_param.hardware_version = TY_HARD_VER_NUM; + printf("HJY:12345\n"); + tuya_ble_sdk_init(&device_param); + ret = tuya_ble_callback_queue_register(tuya_cb_handler); + y_printf("tuya_ble_callback_queue_register,ret=%d\n", ret); + + //tuya_ota_init(); + + //TUYA_APP_LOG_INFO("demo project version : "TUYA_BLE_DEMO_VERSION_STR); + TUYA_APP_LOG_INFO("app version : "TY_APP_VER_STR); + +} diff --git a/apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ble_app_demo.h b/apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ble_app_demo.h new file mode 100644 index 0000000..2eef02c --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ble_app_demo.h @@ -0,0 +1,48 @@ +#ifndef TUYA_BLE_APP_DEMO_H_ +#define TUYA_BLE_APP_DEMO_H_ + + +#ifdef __cplusplus +extern "C" { +#endif + + + +#define APP_PRODUCT_ID "xqhyt364" + +#define APP_BUILD_FIRMNAME "tuya_ble_sdk_app_demo_nrf52832" + +//固件版本 +#define TY_APP_VER_NUM 0x0100 +#define TY_APP_VER_STR "1.0" + +//硬件版本 +#define TY_HARD_VER_NUM 0x0100 +#define TY_HARD_VER_STR "1.0" + + +/* +typedef enum { + white, + colour, + scene, + music, +} tuya_light_mode; +*/ + + +void tuya_ble_app_init(void); + + +#ifdef __cplusplus +} +#endif + +#endif // + + + + + + + diff --git a/apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ota.c b/apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ota.c new file mode 100644 index 0000000..726ae7f --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ota.c @@ -0,0 +1,206 @@ +#include "tuya_ota.h" +#include "tuya_ble_type.h" +#include "tuya_ble_app_demo.h" +#include "dual_bank_updata_api.h" +#include "timer.h" +#include "asm/clock.h" + +tuya_ble_status_t tuya_ble_ota_response(tuya_ble_ota_response_t *p_data); + +#define OTA_WRITE_FLASH_SIZE (2048) + +typedef struct { + u32 file_size; + u32 recv_len; + u32 file_crc; + u16 tuya_ota_packet_num; + u8 buff[OTA_WRITE_FLASH_SIZE]; + u32 buff_size; +} tuya_ota_t; + +tuya_ota_t tuya_ota; + +__attribute__((weak)) +u8 tuya_start_ota_check(void) +{ + return 0; +} + +void tuya_ota_reset(void *priv) +{ + cpu_reset(); +} + +int tuya_ota_boot_info_cb(int err) +{ + sys_timeout_add(NULL, tuya_ota_reset, 2000); + return 0; +} + +int tuya_ota_file_end_response(void *priv) +{ + tuya_ble_ota_response_t response; + tuya_ota_end_response_t ota_end_response; + ota_end_response.reserve = 0; + + int old_sys_clk = clk_get("sys"); + + clk_set("sys", 120 * 1000000L); //提升系统时钟提高校验速度 + if (dual_bank_update_verify_without_crc() == 0) { + printf("UPDATE SUCCESS"); + ota_end_response.state = 0; + dual_bank_update_burn_boot_info(tuya_ota_boot_info_cb); + } else { + printf("UPDATE FAILURE"); + ota_end_response.state = 2; + } + clk_set("sys", old_sys_clk); //恢复时钟 + response.type = TUYA_BLE_OTA_END; + response.p_data = &ota_end_response; + response.data_len = 2; + return tuya_ble_ota_response(&response); +} + +int tuya_ota_data_response() +{ + tuya_ble_ota_response_t response; + tuya_ota_data_response_t ota_data_response; + response.type = TUYA_BLE_OTA_DATA; + ota_data_response.reserve = 0; + ota_data_response.state = TUYA_OTA_DATA_SUCC; + response.p_data = &ota_data_response; + response.data_len = 2; + tuya_ble_ota_response(&response); + return 0; +} + +int tuya_update_write_cb(void *priv) +{ + tuya_ota_data_response(); + return 0; +} + +void tuya_ota_proc(u16 type, u8 *recv_data, u32 recv_len) +{ + tuya_ble_ota_response_t response; + static bool first_packet_come = 0; + static u32 current_file_size = 0; + + switch (type) { + case TUYA_BLE_OTA_REQ: + printf("TUYA_BLE_OTA_REQ\n"); + dual_bank_passive_update_exit(NULL); //tuya APP退到后台会中断发数,重新开始REQ要退出上一次的任务 + tuya_ota_req_response_t ota_req_response; + ota_req_response.flag = tuya_start_ota_check(); + ota_req_response.ota_version = 3; + ota_req_response.reserve = 0; + ota_req_response.frame_version = TY_APP_VER_NUM; + ota_req_response.max_pkt_len = OTA_MAX_DATA_LEN; + first_packet_come = 0; + current_file_size = 0; + response.p_data = &ota_req_response; + response.data_len = 9; + memset(&tuya_ota, 0, sizeof(tuya_ota)); + break; + case TUYA_BLE_OTA_FILE_INFO: + printf("TUYA_BLE_OTA_FILE_INFO\n"); + tuya_ota_file_info_response_t ota_file_info_response; + ota_file_info_response.reserve = 0; + tuya_ota.file_size = READ_BIG_U32(recv_data + 29); + uint32_t file_version = READ_BIG_U32(recv_data + 9); + printf("TUYA_BLE_OTA_FILE_INFO file_size%d file_version%d", tuya_ota.file_size, file_version); + dual_bank_passive_update_init(0, tuya_ota.file_size, OTA_WRITE_FLASH_SIZE, NULL); + if (dual_bank_update_allow_check(tuya_ota.file_size) != 0) { + dual_bank_passive_update_exit(NULL); + ota_file_info_response.state = TUYA_OTA_STATE_FILE_SIZE_TOO_LARGE; + } else if (file_version <= TY_APP_VER_NUM) { + dual_bank_passive_update_exit(NULL); + ota_file_info_response.state = TUYA_OTA_STATE_VER_LOW; + } else { + ota_file_info_response.state = TUYA_OTA_STATE_NORMAL; + } + response.p_data = &ota_file_info_response; + response.data_len = 26; + break; + case TUYA_BLE_OTA_FILE_OFFSET_REQ: + printf("TUYA_BLE_OTA_FILE_OFFSET_REQ\n"); + uint8_t data[5] = {0}; + response.type = TUYA_BLE_OTA_FILE_OFFSET_REQ; + u32 offset_addr = READ_BIG_U32(recv_data + 1); + data[1] = (u8)(offset_addr >> 24); + data[2] = (u8)(offset_addr >> 16); + data[3] = (u8)(offset_addr >> 8); + data[4] = (u8)(offset_addr >> 0); + printf("offset_addr = 0x%x", offset_addr); + response.data_len = 5; + response.p_data = data; + tuya_ble_ota_response(&response); + return; + /* tuya_ota_file_offset_response_t ota_file_offset_response; */ + /* ota_file_offset_response.reserve = 0; */ + /* ota_file_offset_response.offset = recv_data[1] << 24 | recv_data[2] << 16 | recv_data[3] << 8 | recv_data[4]; */ + /* printf("offset:%d\n", ota_file_offset_response.offset); */ + /* response.p_data = &ota_file_offset_response; */ + /* response.data_len = 2; */ + break; + case TUYA_BLE_OTA_DATA: + printf("TUYA_BLE_OTA_DATA\n"); + tuya_ota_data_response_t ota_data_response; + ota_data_response.reserve = 0; + u16 remote_packet_num = (recv_data[1] << 8) + recv_data[2]; + u32 cur_frame_size = (recv_data[3] << 8) + recv_data[4]; + + if (remote_packet_num == 0 && first_packet_come == 1) { + printf("OTA ERROR packet num error, num = %d", remote_packet_num); + ota_data_response.state = TUYA_OTA_DATA_PKT_NUM_ERR; + response.p_data = &ota_data_response; + response.data_len = 2; + response.type = TUYA_BLE_OTA_DATA; + tuya_ble_ota_response(&response); + + return; + } + + current_file_size += cur_frame_size; + printf("OTA DATA info:"); + put_buf(recv_data, 7); + printf("file_size:%d remote_packet_num:%d, last_packet_num = %d, frame_size:%d\n", current_file_size, remote_packet_num, tuya_ota.tuya_ota_packet_num, recv_len - 7); + + first_packet_come = 1; + + if (remote_packet_num && remote_packet_num != tuya_ota.tuya_ota_packet_num + 1) { + printf("OTA ERROR packet num error"); + ota_data_response.state = TUYA_OTA_DATA_PKT_NUM_ERR; + response.p_data = &ota_data_response; + response.data_len = 2; + tuya_ble_ota_response(&response); + //dual_bank_passive_update_exit(NULL); + return; + } else { + tuya_ota.recv_len += recv_len - 7; + memcpy(tuya_ota.buff + tuya_ota.buff_size, recv_data + 7, recv_len - 7); + tuya_ota.buff_size += recv_len - 7; + if (tuya_ota.buff_size >= OTA_WRITE_FLASH_SIZE) { + dual_bank_update_write(tuya_ota.buff, OTA_WRITE_FLASH_SIZE, tuya_update_write_cb); + tuya_ota.buff_size -= OTA_WRITE_FLASH_SIZE; + } else { + tuya_ota_data_response(); + tuya_ota.tuya_ota_packet_num = remote_packet_num; + return; + } + } + tuya_ota.tuya_ota_packet_num = remote_packet_num; + break; + case TUYA_BLE_OTA_END: + printf("TUYA_BLE_OTA_END\n"); + if (tuya_ota.buff_size != 0) { //把剩余的数据写入flash + dual_bank_update_write(tuya_ota.buff, tuya_ota.buff_size, tuya_ota_file_end_response); + } else { + tuya_ota_file_end_response(NULL); + } + break; + } + response.type = type; + tuya_ble_ota_response(&response); +} + diff --git a/apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ota.h b/apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ota.h new file mode 100644 index 0000000..7247570 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ota.h @@ -0,0 +1,58 @@ +#ifndef __TUYA_OTA_H__ +#define __TUYA_OTA_H__ + +#include "typedef.h" + +#define OTA_MAX_DATA_LEN 128 + +enum { + TUYA_OTA_STATE_NORMAL = 0, + TUYA_OTA_STATE_PID_NO_MATCH, + TUYA_OTA_STATE_VER_LOW, + TUYA_OTA_STATE_FILE_SIZE_TOO_LARGE, +}; + +enum { + TUYA_OTA_DATA_SUCC = 0, + TUYA_OTA_DATA_PKT_NUM_ERR, + TUYA_OTA_DATA_LEN_ERR, + TUYA_OTA_DATA_CRC_FAILED, + TUYA_OTA_DATA_OTHER_ERR, +}; + +#define READ_BIG_U32(a) ((*((u8*)(a)) <<24) + (*((u8*)(a)+1)<<16) + (*((u8*)(a)+2)<<8) + *((u8*)(a)+3)) + +typedef struct tuya_ota_req_response { + u8 flag; + u8 ota_version; + u8 reserve; + u32 frame_version; + u16 max_pkt_len; +} tuya_ota_req_response_t; + +typedef struct tuya_ota_file_info_response { + u8 reserve; + u8 state; + u32 store_file_len; //用于断点续传,目前不支持 + u32 store_crc; + u8 md5[16]; //目前不使用 +} tuya_ota_file_info_response_t; + +typedef struct tuya_ota_file_offset_response { + u8 reserve; + u32 offset; +} tuya_ota_file_offset_response_t; + +typedef struct tuya_ota_data_response { + u8 reserve; + u8 state; +} tuya_ota_data_response_t; + +typedef struct tuya_ota_end_response { + u8 reserve; + u8 state; +} tuya_ota_end_response_t; + +void tuya_ota_proc(u16 type, u8 *recv_data, u32 recv_len); + +#endif diff --git a/apps/common/third_party_profile/tuya_protocol/app/product_test/tuya_ble_app_production_test.c b/apps/common/third_party_profile/tuya_protocol/app/product_test/tuya_ble_app_production_test.c new file mode 100644 index 0000000..657b5b0 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/app/product_test/tuya_ble_app_production_test.c @@ -0,0 +1,1386 @@ +/** + * \file tuya_ble_app_production_test.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" +#include "tuya_ble_heap.h" +#include "tuya_ble_mem.h" +#include "tuya_ble_api.h" +#include "tuya_ble_port.h" +#include "tuya_ble_main.h" +#include "tuya_ble_internal_config.h" +#include "tuya_ble_data_handler.h" +#include "tuya_ble_mutli_tsf_protocol.h" +#include "tuya_ble_utils.h" +#include "tuya_ble_secure.h" +#include "tuya_ble_main.h" +#include "tuya_ble_storage.h" +#include "tuya_ble_app_production_test.h" +#include "tuya_ble_log.h" +#include "tuya_ble_api.h" +#include "tuya_ble_utils.h" + + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE == TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) +#include "tuya_ecc.h" +#if (TUYA_BLE_INCLUDE_CJSON_COMPONENTS != 0) +#include "cJSON.h" +#endif +#endif + +#if defined(CUSTOMIZED_TUYA_BLE_APP_PRODUCT_TEST_HEADER_FILE) +#include CUSTOMIZED_TUYA_BLE_APP_PRODUCT_TEST_HEADER_FILE +#endif + + +#if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE&&TUYA_BLE_DEVICE_AUTH_DATA_STORE) + +static uint8_t tuya_ble_production_test_flag = 0; + +static uint8_t tuya_ble_production_test_with_ble_flag = 0; + +#define tuya_ble_prod_monitor_timeout_ms 60000 //60s + +tuya_ble_timer_t tuya_ble_xTimer_prod_monitor; + + +void tuya_ble_internal_production_test_with_ble_flag_clear(void) +{ + tuya_ble_production_test_with_ble_flag = 0; +} + + +uint8_t tuya_ble_internal_production_test_with_ble_flag_get(void) +{ + return tuya_ble_production_test_with_ble_flag; +} + + +static void tuya_ble_vtimer_prod_monitor_callback(tuya_ble_timer_t pxTimer) +{ + tuya_ble_device_delay_ms(1000); + tuya_ble_device_reset(); + +} + +static void tuya_ble_prod_monitor_timer_init(void) +{ + if (tuya_ble_timer_create(&tuya_ble_xTimer_prod_monitor, tuya_ble_prod_monitor_timeout_ms, TUYA_BLE_TIMER_SINGLE_SHOT, tuya_ble_vtimer_prod_monitor_callback) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("tuya_ble_xTimer_prod_monitor creat failed"); + } + +} + + +static void tuya_ble_prod_monitor_timer_start(void) +{ + if (tuya_ble_timer_start(tuya_ble_xTimer_prod_monitor) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("tuya_ble_xTimer_prod_monitor start failed"); + } + +} + +static void tuya_ble_prod_monitor_timer_stop(void) +{ + + if (tuya_ble_timer_stop(tuya_ble_xTimer_prod_monitor) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("tuya_ble_xTimer_prod_monitor stop failed"); + } + +} + + +static uint32_t tuya_ble_uart_prod_send(uint8_t type, uint8_t *pdata, uint8_t len) +{ + uint8_t uart_send_len = 7 + len; + uint8_t *uart_send_buffer = NULL; + + uart_send_buffer = (uint8_t *)tuya_ble_malloc(uart_send_len); + if (uart_send_buffer != NULL) { + uart_send_buffer[0] = 0x66; + uart_send_buffer[1] = 0xAA; + uart_send_buffer[2] = 0x00; + uart_send_buffer[3] = type; + uart_send_buffer[4] = 0; + uart_send_buffer[5] = len; + memcpy(uart_send_buffer + 6, pdata, len); + uart_send_buffer[6 + len] = tuya_ble_check_sum(uart_send_buffer, 6 + len); + tuya_ble_common_uart_send_data(uart_send_buffer, 7 + len); + tuya_ble_free(uart_send_buffer); + } else { + TUYA_BLE_LOG_ERROR("uart prod send buffer malloc failed."); + return 1; + } + + return 0; +} + + +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_prod_updata_mac(uint8_t *mac) +{ + return TUYA_BLE_SUCCESS; +} + +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_prod_beacon_scan_start(void) +{ + return TUYA_BLE_SUCCESS; +} + +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_prod_beacon_scan_stop(void) +{ + return TUYA_BLE_SUCCESS; +} + +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_prod_beacon_get_rssi_avg(int8_t *rssi) +{ + *rssi = -20; + return TUYA_BLE_SUCCESS; +} + + +static void tuya_ble_auc_enter(uint8_t *para, uint16_t len) +{ + uint8_t buf[1]; + + /* if dev is binding, can't entry ftm mode */ + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + TUYA_BLE_LOG_DEBUG("AUC ENTER, BUT DEV IS BINDING"); + + tuya_ble_device_delay_ms(200); + tuya_ble_device_reset(); + return; + } + + TUYA_BLE_LOG_DEBUG("AUC ENTER!"); + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE == TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) + buf[0] = (TUYA_BLE_AUC_FINGERPRINT_VER << TUYA_BLE_AUC_FW_FINGERPRINT_POS) | \ + (TUYA_BLE_AUC_WRITE_PID << TUYA_BLE_AUC_WRITE_PID_POS) | + (TUYA_BLE_AUC_WRITE_DEV_CERT << TUYA_BLE_AUC_WRITE_DEV_CERT_POS); +#else + buf[0] = (TUYA_BLE_AUC_FINGERPRINT_VER << TUYA_BLE_AUC_FW_FINGERPRINT_POS) | \ + (TUYA_BLE_AUC_WRITE_PID << TUYA_BLE_AUC_WRITE_PID_POS); +#endif + + if (tuya_ble_production_test_flag == 1) { + //tuya_ble_stop_scan(); + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_ENTER, buf, 1); + return; + } + tuya_ble_prod_monitor_timer_init(); + + tuya_ble_prod_monitor_timer_start(); + + tuya_ble_prod_beacon_scan_start(); + + tuya_ble_production_test_flag = 1; + + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_ENTER, buf, 1); +} + + +static void tuya_ble_auc_query_hid(uint8_t *para, uint16_t len) +{ + if (tuya_ble_production_test_flag != 1) { + return; + } + + TUYA_BLE_LOG_DEBUG("AUC QUERY HID!"); + char buf[70] = "{\"ret\":true,\"hid\":\"\"}"; + + + if (tuya_ble_buffer_value_is_all_x(tuya_ble_current_para.auth_settings.h_id, H_ID_LEN, 0xFF)) { + buf[19] = '\"'; + buf[20] = '}'; + } else if (tuya_ble_buffer_value_is_all_x(tuya_ble_current_para.auth_settings.h_id, H_ID_LEN, 0)) { + buf[19] = '\"'; + buf[20] = '}'; + } else { + memcpy(&buf[19], tuya_ble_current_para.auth_settings.h_id, H_ID_LEN); + buf[38] = '\"'; + buf[39] = '}'; + } + + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_QUERY_HID, (uint8_t *)buf, strlen(buf)); + + TUYA_BLE_LOG_HEXDUMP_DEBUG("AUC QUERY HID response data : ", (uint8_t *)buf, strlen(buf)); +} + + + +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_prod_gpio_test(void) +{ + return TUYA_BLE_SUCCESS; +} + + +static void tuya_ble_auc_gpio_test(uint8_t *para, uint16_t len) +{ + char ture_buf[] = "{\"ret\":true}"; + char false_buf[] = "{\"ret\":false}"; + if (tuya_ble_production_test_flag != 1) { + return; + } + + TUYA_BLE_LOG_DEBUG("AUC GPIO TEST!"); + + if (tuya_ble_prod_gpio_test() == TUYA_BLE_SUCCESS) { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_GPIO_TEST, (uint8_t *)ture_buf, strlen(ture_buf)); + TUYA_BLE_LOG_DEBUG("AUC GPIO TEST successed!"); + } else { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_GPIO_TEST, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("AUC GPIO TEST failed!"); + } + +} + + +static void tuya_ble_prod_asciitohex(uint8_t *ascbuf, uint8_t len, uint8_t *hexbuf) +{ + uint8_t i = 0, j = 0; + + for (j = 0; j < (len / 2); j++) { + if ((ascbuf[i] >= 0x30) && (ascbuf[i] <= 0x39)) { + hexbuf[j] = ((ascbuf[i] - 0x30) << 4); + } else if ((ascbuf[i] >= 65) && (ascbuf[i] <= 70)) { + hexbuf[j] = ((ascbuf[i] - 55) << 4); + } else if ((ascbuf[i] >= 97) && (ascbuf[i] <= 102)) { + hexbuf[j] = ((ascbuf[i] - 87) << 4); + } + i++; + if ((ascbuf[i] >= 0x30) && (ascbuf[i] <= 0x39)) { + hexbuf[j] |= (ascbuf[i] - 0x30); + } else if ((ascbuf[i] >= 65) && (ascbuf[i] <= 70)) { + hexbuf[j] |= (ascbuf[i] - 55); + } else if ((ascbuf[i] >= 97) && (ascbuf[i] <= 102)) { + hexbuf[j] |= (ascbuf[i] - 87); + } + i++; + + } + +} + +static void tuya_ble_auc_write_auth_info(uint8_t *para, uint16_t len) +{ + uint8_t mac_temp[6]; + uint8_t mac_char[13]; + uint8_t pid_len = 0, i = 0, pid_pos = 0; + char true_buf[] = "{\"ret\":true}"; + char false_buf[] = "{\"ret\":false}"; + + if (tuya_ble_production_test_flag != 1) { + return; + } + + TUYA_BLE_LOG_DEBUG("AUC WRITE AUTH INFO!"); + + /* + { + "auzkey":"xxxx", //"6":"32", 7 + 6+4 + "uuid":"xxxx", //"4":"16", 7 +6+32+6 + 4+4 + "mac":"xxxxxx", //"3":"12", + "prod_test":"xxxx" //"9":"4/5" + "pid":"abcdefgh" //if any + } + */ + + if (len < 100) { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_AUTH_INFO, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("AUC_CMD_WRITE_AUTH_INFO error ,since Invalid length!"); + return; + } + +#if ( TUYA_BLE_PROD_SUPPORT_OEM_TYPE == TUYA_BLE_PROD_OEM_TYPE_0_5 ) + if ((memcmp(¶[2], "auzkey", 6) != 0) || (memcmp(¶[46], "uuid", 4) != 0) || (memcmp(¶[72], "mac", 3) != 0) || ((memcmp(¶[110], "pid\":\"", 6) != 0) && (memcmp(¶[111], "pid\":\"", 6) != 0))) { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_AUTH_INFO, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("AUC_CMD_WRITE_AUTH_INFO error ,since Invalid paras"); + return; + } + + i = para[115] == '\"' ? 116 : 117; + pid_pos = i; + pid_len = 0; + while ((para[i] != '\"') && (pid_len <= 20)) { + i++; + pid_len++; + } + if (pid_len > 20) { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_AUTH_INFO, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("AUC_CMD_WRITE_AUTH_INFO error ,because pid len > 20 ."); + return; + } + + memcpy(mac_char, ¶[78], 12); + tuya_ble_prod_asciitohex(mac_char, 12, mac_temp); + + if (tuya_ble_storage_write_auth_key_device_id_mac(¶[11], AUTH_KEY_LEN, ¶[53], DEVICE_ID_LEN, mac_temp, MAC_LEN, mac_char, MAC_LEN * 2, ¶[pid_pos], pid_len) == TUYA_BLE_SUCCESS) { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_AUTH_INFO, (uint8_t *)true_buf, strlen(true_buf)); + TUYA_BLE_LOG_DEBUG("AUC WRITE AUTH INFO successed!"); + } else { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_AUTH_INFO, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("AUC_CMD_WRITE_AUTH_INFO failed!"); + } +#else + if ((memcmp(¶[2], "auzkey", 6) != 0) || (memcmp(¶[46], "uuid", 4) != 0) || (memcmp(¶[72], "mac", 3) != 0)) { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_AUTH_INFO, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("AUC_CMD_WRITE_AUTH_INFO error ,since Invalid paras"); + return; + } + + memcpy(mac_char, ¶[78], 12); + tuya_ble_prod_asciitohex(mac_char, 12, mac_temp); + + if (tuya_ble_storage_write_auth_key_device_id_mac(¶[11], AUTH_KEY_LEN, ¶[53], DEVICE_ID_LEN, mac_temp, MAC_LEN, mac_char, MAC_LEN * 2, NULL, 0) == TUYA_BLE_SUCCESS) { + tuya_ble_prod_updata_mac(mac_temp); + + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_AUTH_INFO, (uint8_t *)true_buf, strlen(true_buf)); + TUYA_BLE_LOG_DEBUG("AUC WRITE AUTH INFO successed!"); + } else { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_AUTH_INFO, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("AUC_CMD_WRITE_AUTH_INFO failed!"); + } +#endif +} + + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE == TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) +volatile uint32_t comm_cfg_total_len = 0; +volatile uint32_t comm_cfg_cur_rcv_len = 0; +uint8_t *p_comm_cfg = NULL; + + +#if ( TUYA_BLE_INCLUDE_CJSON_COMPONENTS != 0 ) +static void tuya_ble_auc_write_comm_cfg(uint8_t *para, uint16_t len) +{ + char reply_buf[64] = {0}; + uint16_t reply_buf_len = 0; + bool reply_ret = false; + + if (tuya_ble_production_test_flag != 1) { + return; + } + + TUYA_BLE_LOG_DEBUG("AUC WRITE COMM CFG INFO!"); + + cJSON *root = NULL, *item = NULL; + int type; + char *key = NULL; + char *value = NULL; + uint32_t offset, crc32, calc_crc32; + + unsigned char pstr[len + 1]; + memset(pstr, 0x00, len + 1); + memcpy(pstr, para, len); + + root = cJSON_Parse((char *)pstr); + if (!root) { + TUYA_BLE_LOG_ERROR("cJSON error : [%s]\n", cJSON_GetErrorPtr()); + goto EXIT_ERR; + } + + // type + item = cJSON_GetObjectItem(root, "type"); + if (NULL == item) { + goto EXIT_ERR; + } + type = item->valueint; + + // key + item = cJSON_GetObjectItem(root, "key"); + if (NULL == item) { + goto EXIT_ERR; + } + key = item->valuestring; + + if ((memcmp(key, "deviceCertificate", strlen("deviceCertificate")) != 0) && \ + (memcmp(key, "privateKey", strlen("privateKey")) != 0)) { + TUYA_BLE_LOG_ERROR("WRITE COMM CFG, but key unknow."); + goto EXIT_ERR; + } + + /* process different types, 1->size 2->value 3->crc32 */ + if (type == 1) { + // size + item = cJSON_GetObjectItem(root, "size"); + if (NULL == item) { + goto EXIT_ERR; + } + + comm_cfg_total_len = item->valueint; + comm_cfg_cur_rcv_len = 0; + + p_comm_cfg = (uint8_t *)tuya_ble_malloc(comm_cfg_total_len + 16); + if (p_comm_cfg == NULL) { + TUYA_BLE_LOG_ERROR("WRITE COMM CFG, malloc failed."); + } else { + reply_ret = true; + } + } else if (type == 2) { + // value + offset + item = cJSON_GetObjectItem(root, "value"); + if (NULL == item) { + goto EXIT_ERR; + } + value = item->valuestring; + + item = cJSON_GetObjectItem(root, "offset"); + if (NULL == item) { + goto EXIT_ERR; + } + offset = item->valueint; + + memcpy(&p_comm_cfg[offset], value, strlen(value)); + TUYA_BLE_LOG_DEBUG("WRITE COMM CFG offset=[%d] value_size=[%d]", offset, strlen(value)); + TUYA_BLE_LOG_HEXDUMP_DEBUG("value", (uint8_t *)value, strlen(value)); + + comm_cfg_cur_rcv_len += strlen(value); + reply_ret = true; + } else if (type == 3) { + // crc32 + if (comm_cfg_cur_rcv_len != comm_cfg_total_len) { + TUYA_BLE_LOG_DEBUG("WRITE COMM CFG size err, recv=[%d] total=[%d]", comm_cfg_cur_rcv_len, comm_cfg_total_len); + goto EXIT_ERR; + } + + item = cJSON_GetObjectItem(root, "crc32"); + if (NULL == item) { + goto EXIT_ERR; + } + crc32 = (uint32_t)item->valueint; + + calc_crc32 = tuya_ble_crc32_compute(p_comm_cfg, comm_cfg_total_len, NULL); + if (crc32 != calc_crc32) { + TUYA_BLE_LOG_DEBUG("WRITE COMM CFG crc32 err, calc=[%d] crc32=[%d]", calc_crc32, crc32); + } else { + TUYA_BLE_LOG_DEBUG("---------WRITE COMM CFG write context success---------"); + TUYA_BLE_LOG_DEBUG("context size = [%d]", comm_cfg_total_len); + TUYA_BLE_LOG_DEBUG("context crc32 = [%d]", crc32); + TUYA_BLE_LOG_HEXDUMP_DEBUG("context ", p_comm_cfg, comm_cfg_total_len); + reply_ret = true; + + /* write to security chip */ + if (memcmp(key, "deviceCertificate", strlen("deviceCertificate")) == 0) { + if (tuya_ble_storage_private_data(PRIVATE_DATA_DEV_CERT, p_comm_cfg, comm_cfg_total_len) != TUYA_BLE_SUCCESS) { + reply_ret = false; + } + } else if (memcmp(key, "privateKey", strlen("privateKey")) == 0) { + uint8_t private_key[64] = {0}; + uint16_t private_key_len; + + if (tuya_ble_ecc_key_pem2hex((char *)p_comm_cfg, private_key, &private_key_len) == 0) { + TUYA_BLE_LOG_DEBUG("tuya ble ecc key pem2hex failed"); + reply_ret = false; + } else { + TUYA_BLE_LOG_HEXDUMP_DEBUG("private key raw", private_key, private_key_len); + + if (tuya_ble_storage_private_data(PRIVATE_DATA_ECC_KEY, private_key, private_key_len) != TUYA_BLE_SUCCESS) { + reply_ret = false; + } + } + } + + if (p_comm_cfg != NULL) { + tuya_ble_free(p_comm_cfg); + } + } + } else { + TUYA_BLE_LOG_ERROR("WRITE COMM CFG type err. [%d]", type); + } + +EXIT_ERR: + if (reply_ret) { + reply_buf_len = sprintf((char *)reply_buf, "{\"ret\":true,\"key\":\"%s\"}", key); + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_COMM_CFG, (uint8_t *)reply_buf, reply_buf_len); + + TUYA_BLE_LOG_DEBUG("AUC WRITE COMM CFG responsed successed."); + } else { + reply_buf_len = sprintf((char *)reply_buf, "{\"ret\":false,\"key\":\"%s\"}", key); + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_COMM_CFG, (uint8_t *)reply_buf, reply_buf_len); + + TUYA_BLE_LOG_DEBUG("AUC WRITE COMM CFG failed!"); + + if (p_comm_cfg != NULL) { + tuya_ble_free(p_comm_cfg); + } + } + + if (NULL != root) { + cJSON_Delete(root); + } +} +#else +static void tuya_ble_auc_write_comm_cfg(uint8_t *para, uint16_t len) +{ + char reply_buf[64] = {0}; + uint16_t reply_buf_len = 0; + bool reply_ret = false; + + if (tuya_ble_production_test_flag != 1) { + return; + } + + TUYA_BLE_LOG_DEBUG("AUC WRITE COMM CFG INFO!"); + + int i; + int type, size, offset, crc32; + char key[64] = {0}; + uint8_t symbol_colon_index[32] = {0}; + uint8_t symbol_comma_index[32] = {0}; + uint8_t symbol_colon_cnt, symbol_comma_cnt; + uint16_t start_pos, end_pos, cut_len; + uint32_t calc_crc32; + + symbol_colon_cnt = tuya_ble_search_symbol_index((char *)para, len, ':', symbol_colon_index); + symbol_comma_cnt = tuya_ble_search_symbol_index((char *)para, len, ',', symbol_comma_index); + if (symbol_colon_cnt == 0 || symbol_comma_cnt == 0) { + goto EXIT_ERR; + } + + TUYA_BLE_LOG_DEBUG("symbol->: cnt=[%d]", symbol_colon_cnt); + TUYA_BLE_LOG_HEXDUMP_DEBUG("symbol : list index", symbol_colon_index, symbol_colon_cnt); + + TUYA_BLE_LOG_DEBUG("symbol->, cnt=[%d]", symbol_comma_cnt); + TUYA_BLE_LOG_HEXDUMP_DEBUG("symbol , list index", symbol_comma_index, symbol_comma_cnt); + + // type + start_pos = symbol_colon_index[0] + 1; + type = para[start_pos] - '0'; + TUYA_BLE_LOG_DEBUG("parse type ->[%d]", type); + + // key + start_pos = symbol_colon_index[1] + 2; + end_pos = symbol_comma_index[1] - 2; + cut_len = (end_pos - start_pos + 1); + memcpy(key, ¶[start_pos], cut_len); + key[cut_len] = '\0'; + TUYA_BLE_LOG_DEBUG("parse key ->[%s]", key); + + if ((memcmp(key, "deviceCertificate", strlen("deviceCertificate")) != 0) && \ + (memcmp(key, "privateKey", strlen("privateKey")) != 0)) { + TUYA_BLE_LOG_ERROR("WRITE COMM CFG, but key unknow."); + goto EXIT_ERR; + } + + /* process different types, 1->size 2->value 3->crc32 */ + if (type == 1) { + /* + { + "type":1, + "key":"xxxx", + "size":xxx + } + */ + + // size + start_pos = symbol_colon_index[2] + 1; + end_pos = len - 2; + cut_len = (end_pos - start_pos + 1); + size = tuya_ble_ascii_to_int((char *)¶[start_pos], cut_len); + TUYA_BLE_LOG_DEBUG("parse size ->[%d]", size); + + comm_cfg_total_len = size; + comm_cfg_cur_rcv_len = 0; + + p_comm_cfg = (uint8_t *)tuya_ble_malloc(comm_cfg_total_len + 16); + if (p_comm_cfg == NULL) { + TUYA_BLE_LOG_ERROR("WRITE COMM CFG, malloc failed."); + } else { + reply_ret = true; + } + } else if (type == 2) { + /* + { + "type":2, + "key":"xxxx", + "value":"xxxx", + "offset":xxxx + } + */ + + // offset + start_pos = symbol_colon_index[3] + 1; + end_pos = len - 2; + cut_len = (end_pos - start_pos + 1); + offset = tuya_ble_ascii_to_int((char *)¶[start_pos], cut_len); + TUYA_BLE_LOG_DEBUG("parse offset ->[%d]", offset); + + // value + start_pos = symbol_colon_index[2] + 2; + end_pos = symbol_comma_index[2] - 2; + cut_len = (end_pos - start_pos + 1); + + // replace tab character "\r"->'\r' "\n"->'\n' + uint8_t *p_value = NULL; + uint16_t buf_i = 0; + p_value = (uint8_t *)tuya_ble_malloc(cut_len); + + for (i = start_pos; i <= end_pos; i++) { + if ((para[i] == '\\') && (para[i + 1] == 'r')) { + p_value[buf_i++] = '\r'; + + i += 1; + cut_len -= 1; + TUYA_BLE_LOG_DEBUG("find r "); + } else if ((para[i] == '\\') && (para[i + 1] == 'n')) { + p_value[buf_i++] = '\n'; + + i += 1; + cut_len -= 1; + TUYA_BLE_LOG_DEBUG("find n "); + } else { + p_value[buf_i++] = para[i]; + } + } + + memcpy(&p_comm_cfg[offset], p_value, cut_len); + tuya_ble_free(p_value); + TUYA_BLE_LOG_DEBUG("WRITE COMM CFG offset=[%d] value_size=[%d]", offset, cut_len); + + comm_cfg_cur_rcv_len += cut_len; + reply_ret = true; + } else if (type == 3) { + /* + { + "type":3, + "key":"xxxx", + "crc32":xxxx + } + */ + + if (comm_cfg_cur_rcv_len != comm_cfg_total_len) { + TUYA_BLE_LOG_DEBUG("WRITE COMM CFG size err, recv=[%d] total=[%d]", comm_cfg_cur_rcv_len, comm_cfg_total_len); + goto EXIT_ERR; + } + + // crc32 + start_pos = symbol_colon_index[2] + 1; + end_pos = len - 2; + cut_len = (end_pos - start_pos + 1); + crc32 = tuya_ble_ascii_to_int((char *)¶[start_pos], cut_len); + TUYA_BLE_LOG_DEBUG("parse crc32 ->[%d]", crc32); + + calc_crc32 = tuya_ble_crc32_compute(p_comm_cfg, comm_cfg_total_len, NULL); + if (crc32 != calc_crc32) { + TUYA_BLE_LOG_DEBUG("WRITE COMM CFG crc32 err, calc=[%d] crc32=[%d]", calc_crc32, crc32); + } else { + TUYA_BLE_LOG_DEBUG("---------WRITE COMM CFG write context success---------"); + TUYA_BLE_LOG_DEBUG("context size = [%d]", comm_cfg_total_len); + TUYA_BLE_LOG_DEBUG("context crc32 = [%d]", crc32); + TUYA_BLE_LOG_HEXDUMP_DEBUG("context ", p_comm_cfg, comm_cfg_total_len); + reply_ret = true; + + /* write to security chip */ + if (memcmp(key, "deviceCertificate", strlen("deviceCertificate")) == 0) { + if (tuya_ble_storage_private_data(PRIVATE_DATA_DEV_CERT, p_comm_cfg, comm_cfg_total_len) != TUYA_BLE_SUCCESS) { + reply_ret = false; + } + } else if (memcmp(key, "privateKey", strlen("privateKey")) == 0) { + uint8_t private_key[64] = {0}; + uint16_t private_key_len; + + if (tuya_ble_ecc_key_pem2hex((char *)p_comm_cfg, private_key, &private_key_len) == 0) { + TUYA_BLE_LOG_DEBUG("tuya ble ecc key pem2hex failed"); + reply_ret = false; + } else { + TUYA_BLE_LOG_HEXDUMP_DEBUG("private key raw", private_key, private_key_len); + + if (tuya_ble_storage_private_data(PRIVATE_DATA_ECC_KEY, private_key, private_key_len) != TUYA_BLE_SUCCESS) { + reply_ret = false; + } + } + } + + if (p_comm_cfg != NULL) { + tuya_ble_free(p_comm_cfg); + } + } + } else { + TUYA_BLE_LOG_ERROR("WRITE COMM CFG type err. [%d]", type); + } + +EXIT_ERR: + if (reply_ret) { + reply_buf_len = sprintf((char *)reply_buf, "{\"ret\":true,\"key\":\"%s\"}", key); + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_COMM_CFG, (uint8_t *)reply_buf, reply_buf_len); + + TUYA_BLE_LOG_DEBUG("AUC WRITE COMM CFG responsed successed."); + } else { + reply_buf_len = sprintf((char *)reply_buf, "{\"ret\":false,\"key\":\"%s\"}", key); + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_COMM_CFG, (uint8_t *)reply_buf, reply_buf_len); + + TUYA_BLE_LOG_DEBUG("AUC WRITE COMM CFG failed!"); + + if (p_comm_cfg != NULL) { + tuya_ble_free(p_comm_cfg); + } + } +} +#endif // ( TUYA_BLE_INCLUDE_CJSON_COMPONENTS != 0 ) +#endif // ( TUYA_BLE_SECURE_CONNECTION_TYPE == TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION ) + + +static void tuya_ble_auc_query_info(uint8_t *para, uint16_t len) +{ + + uint8_t i = 0; + uint8_t mac_temp[13]; + uint8_t *alloc_buf = NULL; + + if (tuya_ble_production_test_flag != 1) { + return; + } + + TUYA_BLE_LOG_DEBUG("AUC QUERY INFO!"); + + alloc_buf = (uint8_t *)tuya_ble_malloc(256); + + if (alloc_buf) { + memset(alloc_buf, 0, 256); + } else { + TUYA_BLE_LOG_ERROR("AUC QUERY INFO alloc buf malloc failed."); + return; + } + + alloc_buf[i++] = '{'; + alloc_buf[i++] = '\"'; + memcpy(&alloc_buf[i], "ret", 3); + i += 3; + alloc_buf[i++] = '\"'; + + alloc_buf[i++] = ':'; + memcpy(&alloc_buf[i], "true", 4); + i += 4; + + alloc_buf[i++] = ','; + alloc_buf[i++] = '\"'; + memcpy(&alloc_buf[i], "auzKey", 6); + i += 6; + alloc_buf[i++] = '\"'; + alloc_buf[i++] = ':'; + alloc_buf[i++] = '\"'; + memcpy(&alloc_buf[i], tuya_ble_current_para.auth_settings.auth_key, AUTH_KEY_LEN); + i += AUTH_KEY_LEN; + + alloc_buf[i++] = '\"'; + + alloc_buf[i++] = ','; + alloc_buf[i++] = '\"'; + memcpy(&alloc_buf[i], "hid", 3); + i += 3; + alloc_buf[i++] = '\"'; + alloc_buf[i++] = ':'; + alloc_buf[i++] = '\"'; + memcpy(&alloc_buf[i], tuya_ble_current_para.auth_settings.h_id, H_ID_LEN); + i += 19; + alloc_buf[i++] = '\"'; + + alloc_buf[i++] = ','; + alloc_buf[i++] = '\"'; + memcpy(&alloc_buf[i], "uuid", 4); + i += 4; + alloc_buf[i++] = '\"'; + alloc_buf[i++] = ':'; + alloc_buf[i++] = '\"'; + memcpy(&alloc_buf[i], tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN); + i += DEVICE_ID_LEN; + alloc_buf[i++] = '\"'; + + alloc_buf[i++] = ','; + alloc_buf[i++] = '\"'; + memcpy(&alloc_buf[i], "mac", 3); + i += 3; + alloc_buf[i++] = '\"'; + alloc_buf[i++] = ':'; + alloc_buf[i++] = '\"'; + + memcpy(&alloc_buf[i], tuya_ble_current_para.auth_settings.mac_string, MAC_LEN * 2); + i += MAC_LEN * 2; + alloc_buf[i++] = '\"'; + + alloc_buf[i++] = ','; + alloc_buf[i++] = '\"'; + memcpy(&alloc_buf[i], "firmName", 8); + i += 8; + alloc_buf[i++] = '\"'; + alloc_buf[i++] = ':'; + alloc_buf[i++] = '\"'; + memcpy(&alloc_buf[i], TUYA_BLE_APP_BUILD_FIRMNAME_STRING, strlen(TUYA_BLE_APP_BUILD_FIRMNAME_STRING)); + i += strlen(TUYA_BLE_APP_BUILD_FIRMNAME_STRING); + alloc_buf[i++] = '\"'; + + alloc_buf[i++] = ','; + alloc_buf[i++] = '\"'; + memcpy(&alloc_buf[i], "firmVer", 7); + i += 7; + alloc_buf[i++] = '\"'; + alloc_buf[i++] = ':'; + alloc_buf[i++] = '\"'; + memcpy(&alloc_buf[i], TUYA_BLE_APP_VERSION_STRING, strlen(TUYA_BLE_APP_VERSION_STRING)); + i += strlen(TUYA_BLE_APP_VERSION_STRING); + alloc_buf[i++] = '\"'; + + alloc_buf[i++] = ','; + alloc_buf[i++] = '\"'; + memcpy(&alloc_buf[i], "prod_test", 9); + i += 9; + alloc_buf[i++] = '\"'; + alloc_buf[i++] = ':'; + + memcpy(&alloc_buf[i], "false", 5); + i += 5; + + alloc_buf[i++] = '}'; + + alloc_buf[i++] = 0; + + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_QUERY_INFO, (uint8_t *)alloc_buf, i - 1); + + TUYA_BLE_LOG_DEBUG("AUC_CMD_QUERY_INFO RESPONSE!"); + + tuya_ble_free(alloc_buf); +} + + +static void tuya_ble_auc_reset(uint8_t *para, uint16_t len) +{ + uint8_t buf[1] = {0x00}; + + if (tuya_ble_production_test_flag != 1) { + return; + } + TUYA_BLE_LOG_DEBUG("auc RESET!"); + + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_RESET, buf, sizeof(buf)); + + tuya_ble_device_delay_ms(1000); + + tuya_ble_device_reset(); + +} + + +static void tuya_ble_auc_write_hid(uint8_t *para, uint16_t len) +{ + uint8_t hid[19]; + char true_buf[] = "{\"ret\":true}"; + char false_buf[] = "{\"ret\":false}"; + + if (tuya_ble_production_test_flag != 1) { + return; + } + + TUYA_BLE_LOG_DEBUG("AUC WRITE AUTH HID!"); + + if (len < 27) { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_HID, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("WRITE AUTH HID para length error!"); + return; + } + + if (memcmp(¶[2], "hid", 3) != 0) { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_HID, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("WRITE AUTH HID para error!"); + return; + } + + memcpy(hid, ¶[8], H_ID_LEN); + + if (tuya_ble_storage_write_hid(hid, H_ID_LEN) == TUYA_BLE_SUCCESS) { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_HID, (uint8_t *)true_buf, strlen(true_buf)); + TUYA_BLE_LOG_DEBUG("WRITE AUTH HID successed."); + } else { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_HID, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("WRITE AUTH HID failed."); + } + + + +} + + +static void tuya_ble_auc_query_fingerprint(uint8_t *para, uint16_t len) +{ + int32_t length = 0; + uint8_t *alloc_buf = NULL; + + if (tuya_ble_production_test_flag != 1) { + return; + } + + TUYA_BLE_LOG_DEBUG("AUC QUERY FINGERPRINT!"); + + alloc_buf = (uint8_t *)tuya_ble_malloc(256); + + if (alloc_buf) { + memset(alloc_buf, 0, 256); + } else { + TUYA_BLE_LOG_ERROR("AUC QUERY INFO alloc buf malloc failed."); + return; + } + + length = sprintf((char *)alloc_buf, "{\"ret\":true,\"firmName\":\"%s\",\"firmVer\":\"%s\"}", TUYA_BLE_APP_BUILD_FIRMNAME_STRING, TUYA_BLE_APP_VERSION_STRING); + + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_QUERY_FINGERPRINT, alloc_buf, length); + + tuya_ble_free(alloc_buf); + + TUYA_BLE_LOG_DEBUG("AUC_CMD_QUERY_FINGERPRINT responsed."); + +} + + + + +static void tuya_ble_auc_rssi_test(uint8_t *para, uint16_t len) +{ + uint8_t length = 0; + int8_t rssi = 0; + static const char false_buf[] = "{\"ret\":false}"; + char true_buf[30]; + + if (tuya_ble_production_test_flag != 1) { + return; + } + + TUYA_BLE_LOG_DEBUG("AUC RSSI TEST!"); + + memset(true_buf, 0, sizeof(true_buf)); + + tuya_ble_prod_beacon_scan_stop(); + + if (tuya_ble_prod_beacon_get_rssi_avg(&rssi) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("auc get rssi failed."); + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_RSSI_TEST, (uint8_t *)false_buf, strlen(false_buf)); + } else { + length = sprintf((char *)true_buf, "{\"ret\":true,\"rssi\":\"%d\"}", rssi); + TUYA_BLE_LOG_DEBUG("auc get rssi = %d", rssi); + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_RSSI_TEST, (uint8_t *)true_buf, length); + } +} + + +static void tuya_ble_auc_read_mac(uint8_t *para, uint16_t len) +{ + (void)(para); + (void)(len); + + int32_t length = 0; + uint8_t buf[64]; + uint8_t mac_addr_str[12 + 1]; + + if (tuya_ble_production_test_flag != 1) { + return; + } + + TUYA_BLE_LOG_DEBUG("AUC READ MAC ADDR!"); + + // MAC string format: DC 23 xx xx xx xx + memcpy(mac_addr_str, tuya_ble_current_para.auth_settings.mac_string, MAC_LEN * 2); + mac_addr_str[12] = '\0'; + + int swap_len = MAC_LEN * 2; + char temp[2]; + + for (int i = 0; i < swap_len / 2; i += 2) { + temp[0] = mac_addr_str[i]; + temp[1] = mac_addr_str[i + 1]; + + mac_addr_str[i] = mac_addr_str[swap_len - 2 - i]; + mac_addr_str[i + 1] = mac_addr_str[swap_len - 1 - i]; + + mac_addr_str[swap_len - 2 - i] = temp[0]; + mac_addr_str[swap_len - 1 - i] = temp[1]; + } + + length = sprintf((void *)buf, "{\"ret\":true,\"mac\":\"%s\"}", mac_addr_str); + + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_READ_MAC, buf, length); + + TUYA_BLE_LOG_DEBUG("AUC_CMD_READ_MAC responsed."); +} + + +static void tuya_ble_auc_exit(uint8_t *para, uint16_t len) +{ + (void)(para); + (void)(len); + + if (tuya_ble_production_test_flag != 1) { + return; + } + + TUYA_BLE_LOG_DEBUG("AUC EXIT!"); + + char buf[] = "{\"ret\":true}"; + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_EXIT, (uint8_t *)buf, strlen(buf)); + + tuya_ble_device_delay_ms(1000); + tuya_ble_device_reset(); +} + + +#if ( TUYA_BLE_PROD_SUPPORT_OEM_TYPE == TUYA_BLE_PROD_OEM_TYPE_0_5 ) + +typedef struct { + bool need_subpkg; /**< whether need subpkg received. */ + + uint8_t file_type; /**< file type. 0x09-OEM file 0x10-homekit atoken. */ + uint32_t total_nums; /**< subpkg total numbers. */ + uint32_t file_crc32; /**< file crc32 value. */ + uint32_t rcv_file_len; /**< currently received file length. */ + uint8_t *p_file_data; /**< the point of received file data. */ +} write_subpkg_info_t; + +static write_subpkg_info_t write_subpkg_info = { + .need_subpkg = false, + + .file_type = 0, + .total_nums = 0, + .file_crc32 = 0, + .rcv_file_len = 0, + .p_file_data = NULL, +}; + + +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_prod_storage_oem_info(uint8_t *para, uint16_t len) +{ + return TUYA_BLE_SUCCESS; +} + + +static void tuya_ble_auc_write_oem_info(uint8_t *para, uint16_t len) +{ + char true_buf[] = "{\"ret\":true}"; + char false_buf[] = "{\"ret\":false}"; + + if (tuya_ble_production_test_flag != 1) { + return; + } + + TUYA_BLE_LOG_DEBUG("AUC WRITE OEM INFO!"); + + if (len == 0) { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_OEM_INFO, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("WRITE OEM INFO para length error!"); + return; + } + + if ((write_subpkg_info.need_subpkg == false) && (write_subpkg_info.total_nums == 0)) { // need not subpkg + if (para[0] != '{' || para[len - 1] != '}') { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_OEM_INFO, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("WRITE OEM INFO failed."); + return; + } + + if (tuya_ble_prod_storage_oem_info(para, len) == TUYA_BLE_SUCCESS) { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_OEM_INFO, (uint8_t *)true_buf, strlen(true_buf)); + TUYA_BLE_LOG_DEBUG("WRITE OEM INFO successed."); + } else { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_OEM_INFO, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("WRITE OEM INFO failed."); + } + } else { + uint16_t cur_subpkg = (para[0] << 8) + para[1]; + if (cur_subpkg < write_subpkg_info.total_nums) { + memcpy(write_subpkg_info.p_file_data + write_subpkg_info.rcv_file_len, para + 2, len - 2); + write_subpkg_info.rcv_file_len += len - 2; + + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_OEM_INFO, (uint8_t *)true_buf, strlen(true_buf)); + TUYA_BLE_LOG_DEBUG("WRITE OEM INFO subpkg successed."); + } else { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_OEM_INFO, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("WRITE OEM INFO subpkg failed."); + } + } +} + + +static void tuya_ble_auc_write_subpkg_start(uint8_t *para, uint16_t len) +{ + char true_buf[] = "{\"ret\":true}"; + char false_buf[] = "{\"ret\":false}"; + + uint8_t cmd; + int packageNum, crc32; + uint8_t symbol_colon_index[8] = {0}; + uint8_t symbol_comma_index[8] = {0}; + uint8_t symbol_colon_cnt, symbol_comma_cnt; + uint16_t start_pos, end_pos, cut_len; + + symbol_colon_cnt = tuya_ble_search_symbol_index((char *)para, len, ':', symbol_colon_index); + symbol_comma_cnt = tuya_ble_search_symbol_index((char *)para, len, ',', symbol_comma_index); + + /* check json filed */ + if ((symbol_colon_cnt == 0 || symbol_comma_cnt == 0) || \ + (memcmp(¶[2], "cmd", strlen("cmd")) != 0) || \ + (memcmp(¶[symbol_comma_index[0] + 2], "packageNum", strlen("packageNum")) != 0) || \ + (memcmp(¶[symbol_comma_index[1] + 2], "crc32", strlen("crc32")) != 0)) { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_SUBPKG_START, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("AUC WRITE SUBPKG START format err failed."); + return; + } + + /* cmd */ + start_pos = symbol_colon_index[0] + 2; + end_pos = symbol_comma_index[0] - 2; + cut_len = (end_pos - start_pos + 1); + tuya_ble_hexstr2hex((uint8_t *)¶[start_pos], cut_len, &cmd); + TUYA_BLE_LOG_DEBUG("parse cmd ->[0x%02x]", cmd); + + /* packageNum */ + start_pos = symbol_colon_index[1] + 1; + end_pos = symbol_comma_index[1] - 1; + cut_len = (end_pos - start_pos + 1); + packageNum = tuya_ble_ascii_to_int((char *)¶[start_pos], cut_len); + TUYA_BLE_LOG_DEBUG("parse packageNum ->[%d]", packageNum); + + /* crc32 */ + start_pos = symbol_colon_index[2] + 1; + end_pos = len - 2; + cut_len = (end_pos - start_pos + 1); + crc32 = tuya_ble_ascii_to_int((char *)¶[start_pos], cut_len); + TUYA_BLE_LOG_DEBUG("parse crc32 ->[%d]", crc32); + + write_subpkg_info.need_subpkg = true; + write_subpkg_info.file_type = cmd; //!< "09"-oem ocnfig data "10"-homekit atoken data. format: hexstring + write_subpkg_info.total_nums = packageNum; + write_subpkg_info.file_crc32 = crc32; + + write_subpkg_info.p_file_data = (uint8_t *)tuya_ble_malloc(240 * write_subpkg_info.total_nums); + if (write_subpkg_info.p_file_data == NULL) { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_SUBPKG_START, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_ERROR("AUC WRITE SUBPKG START alloc buf malloc failed."); + return; + } + + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_SUBPKG_START, (uint8_t *)true_buf, strlen(true_buf)); + TUYA_BLE_LOG_DEBUG("AUC WRITE SUBPKG START successed."); +} + + +static void tuya_ble_auc_write_subpkg_end(uint8_t *para, uint16_t len) +{ + char true_buf[] = "{\"ret\":true}"; + char false_buf[] = "{\"ret\":false}"; + uint32_t calc_crc32; + + /* check received file whether correct */ + calc_crc32 = tuya_ble_crc32_compute(write_subpkg_info.p_file_data, write_subpkg_info.rcv_file_len, NULL); + if (calc_crc32 != write_subpkg_info.file_crc32) { + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_SUBPKG_END, (uint8_t *)false_buf, strlen(false_buf)); + TUYA_BLE_LOG_DEBUG("AUC WRITE SUBPKG END crc32 check failed."); + } else { + if (write_subpkg_info.file_type == 0x09) { + /* oem config data */ + tuya_ble_prod_storage_oem_info(write_subpkg_info.p_file_data, write_subpkg_info.rcv_file_len); + } else if (write_subpkg_info.file_type == 0x10) { + /* homekit atoken data */ + // TODO .. + } + + tuya_ble_uart_prod_send(TUYA_BLE_AUC_CMD_WRITE_SUBPKG_END, (uint8_t *)true_buf, strlen(true_buf)); + TUYA_BLE_LOG_DEBUG("AUC WRITE SUBPKG END successed."); + } + + /* Clear progress vars, and free p_file_data*/ + write_subpkg_info.need_subpkg = false; + write_subpkg_info.file_crc32 = 0; + write_subpkg_info.total_nums = 0; + write_subpkg_info.file_type = 0; + write_subpkg_info.rcv_file_len = 0; + + tuya_ble_free(write_subpkg_info.p_file_data); +} +#endif + + + +__TUYA_BLE_WEAK void tuya_ble_custom_app_production_test_process(uint8_t channel, uint8_t *p_in_data, uint16_t in_len) +{ + uint16_t sub_cmd = 0; + uint8_t *data_buffer = NULL; + uint16_t data_len = ((p_in_data[4] << 8) + p_in_data[5]); + + if ((p_in_data[6] != 3) || (data_len < 3)) { + return; + } + + sub_cmd = (p_in_data[7] << 8) + p_in_data[8]; + data_len -= 3; + if (data_len > 0) { + data_buffer = p_in_data + 9; + } + + switch (sub_cmd) { + + + default: + break; + }; + + +} + + +__TUYA_BLE_WEAK void tuya_ble_app_sdk_test_process(uint8_t channel, uint8_t *p_in_data, uint16_t in_len) +{ + uint16_t sub_cmd = 0; + uint8_t *data_buffer = NULL; + uint16_t data_len = ((p_in_data[4] << 8) + p_in_data[5]); + + if ((p_in_data[6] != 3) || (data_len < 3)) { + return; + } + + sub_cmd = (p_in_data[7] << 8) + p_in_data[8]; + data_len -= 3; + if (data_len > 0) { + data_buffer = p_in_data + 9; + } + + switch (sub_cmd) { + + + default: + break; + }; + + +} + + + +extern void tuya_ble_connect_monitor_timer_stop(void); +void tuya_ble_app_production_test_process(uint8_t channel, uint8_t *p_in_data, uint16_t in_len) +{ + uint8_t cmd = p_in_data[3]; + uint16_t data_len = (p_in_data[4] << 8) + p_in_data[5]; + uint8_t *data_buffer = p_in_data + 6; + /* + if(tuya_ble_current_para.sys_settings.factory_test_flag==0) // + { + TUYA_BLE_LOG_WARNING("The production interface is closed!"); + return; + } + */ + if ((channel != 0) && (cmd != TUYA_BLE_AUC_CMD_EXTEND)) { + TUYA_BLE_LOG_ERROR("The authorization instructions are not supported in non-serial channels!"); + return; + } + if ((channel == 1) && (cmd == TUYA_BLE_AUC_CMD_EXTEND)) { + if (tuya_ble_production_test_with_ble_flag == 0) { + tuya_ble_production_test_with_ble_flag = 1; + if (tuya_ble_connect_status_get() != BONDING_CONN) { + tuya_ble_connect_monitor_timer_stop(); + } + } + + } + switch (cmd) { + case TUYA_BLE_AUC_CMD_EXTEND: + tuya_ble_custom_app_production_test_process(channel, p_in_data, in_len); + break; + case TUYA_BLE_SDK_TEST_CMD_EXTEND: + tuya_ble_app_sdk_test_process(channel, p_in_data, in_len); + break; + case TUYA_BLE_AUC_CMD_ENTER: + tuya_ble_auc_enter(data_buffer, data_len); + break; + case TUYA_BLE_AUC_CMD_QUERY_HID: + tuya_ble_auc_query_hid(data_buffer, data_len); + break; + case TUYA_BLE_AUC_CMD_GPIO_TEST: + tuya_ble_auc_gpio_test(data_buffer, data_len); + break; + case TUYA_BLE_AUC_CMD_WRITE_AUTH_INFO: + tuya_ble_auc_write_auth_info(data_buffer, data_len); + break; + case TUYA_BLE_AUC_CMD_QUERY_INFO: + tuya_ble_auc_query_info(data_buffer, data_len); + break; + case TUYA_BLE_AUC_CMD_RESET: + tuya_ble_auc_reset(data_buffer, data_len); + break; + case TUYA_BLE_AUC_CMD_QUERY_FINGERPRINT: + tuya_ble_auc_query_fingerprint(data_buffer, data_len); + break; + case TUYA_BLE_AUC_CMD_WRITE_HID: + tuya_ble_auc_write_hid(data_buffer, data_len); + break; + case TUYA_BLE_AUC_CMD_RSSI_TEST: + tuya_ble_auc_rssi_test(data_buffer, data_len); + break; + case TUYA_BLE_AUC_CMD_READ_MAC: + tuya_ble_auc_read_mac(data_buffer, data_len); + break; + + case TUYA_BLE_AUC_CMD_EXIT: + tuya_ble_auc_exit(data_buffer, data_len); + break; + +#if ( TUYA_BLE_PROD_SUPPORT_OEM_TYPE == TUYA_BLE_PROD_OEM_TYPE_0_5 ) + case TUYA_BLE_AUC_CMD_WRITE_OEM_INFO: + tuya_ble_auc_write_oem_info(data_buffer, data_len); + break; + case TUYA_BLE_AUC_CMD_WRITE_SUBPKG_START: + tuya_ble_auc_write_subpkg_start(data_buffer, data_len); + break; + case TUYA_BLE_AUC_CMD_WRITE_SUBPKG_END: + tuya_ble_auc_write_subpkg_end(data_buffer, data_len); + break; +#endif + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE == TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) + case TUYA_BLE_AUC_CMD_WRITE_COMM_CFG: + tuya_ble_auc_write_comm_cfg(data_buffer, data_len); + break; +#endif + + default: + break; + }; + + +} + +#else + +void tuya_ble_app_production_test_process(uint8_t channel, uint8_t *p_in_data, uint16_t in_len) +{ + uint8_t cmd = p_in_data[3]; + uint16_t data_len = (p_in_data[4] << 8) + p_in_data[5]; + uint8_t *data_buffer = p_in_data + 6; + switch (cmd) { + default: + break; + }; + + +} + +#endif + + + diff --git a/apps/common/third_party_profile/tuya_protocol/app/product_test/tuya_ble_app_production_test.h b/apps/common/third_party_profile/tuya_protocol/app/product_test/tuya_ble_app_production_test.h new file mode 100644 index 0000000..98ff56e --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/app/product_test/tuya_ble_app_production_test.h @@ -0,0 +1,100 @@ +/** + * \file tuya_ble_app_production_test.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#ifndef _TUYA_BLE_APP_PRODUCTION_TEST_H_ +#define _TUYA_BLE_APP_PRODUCTION_TEST_H_ + +#include +#include "tuya_ble_internal_config.h" + + + +#ifdef __cplusplus +extern "C" { +#endif + +#define TUYA_BLE_AUC_CMD_ENTER 0x00 +#define TUYA_BLE_AUC_CMD_QUERY_HID 0x01 +#define TUYA_BLE_AUC_CMD_GPIO_TEST 0x02 +#define TUYA_BLE_AUC_CMD_WRITE_AUTH_INFO 0x03 +#define TUYA_BLE_AUC_CMD_QUERY_INFO 0x04 +#define TUYA_BLE_AUC_CMD_RESET 0x05 +#define TUYA_BLE_AUC_CMD_QUERY_FINGERPRINT 0x06 +#define TUYA_BLE_AUC_CMD_WRITE_HID 0x07 +#define TUYA_BLE_AUC_CMD_RSSI_TEST 0x08 +#define TUYA_BLE_AUC_CMD_WRITE_OEM_INFO 0x09 +#define TUYA_BLE_AUC_CMD_WRITE_SUBPKG_START 0x0C +#define TUYA_BLE_AUC_CMD_WRITE_SUBPKG_END 0x0D +#define TUYA_BLE_AUC_CMD_WRITE_COMM_CFG 0x12 // ADD +#define TUYA_BLE_AUC_CMD_READ_MAC 0x13 +#define TUYA_BLE_AUC_CMD_EXIT 0x14 + +#define TUYA_BLE_AUC_CMD_EXTEND 0xF0 +#define TUYA_BLE_SDK_TEST_CMD_EXTEND 0xF2 + + +#define TUYA_BLE_AUC_FINGERPRINT_VER 1 + +#if ( TUYA_BLE_PROD_SUPPORT_OEM_TYPE == TUYA_BLE_PROD_OEM_TYPE_0_5 ) +#define TUYA_BLE_AUC_WRITE_PID 1 +#else +#define TUYA_BLE_AUC_WRITE_PID 0 +#endif + +#define TUYA_BLE_AUC_WRITE_DEV_CERT 1 + +enum { + TUYA_BLE_AUC_FW_FINGERPRINT_POS = 0, + TUYA_BLE_AUC_WRITE_PID_POS = 1, + TUYA_BLE_AUC_WRITE_DEV_CERT_POS = 5, +}; + + +/*channel: 0-uart ,1 - ble.*/ +void tuya_ble_app_production_test_process(uint8_t channel, uint8_t *p_in_data, uint16_t in_len); + + +#if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE&&TUYA_BLE_DEVICE_AUTH_DATA_STORE) + +tuya_ble_status_t tuya_ble_prod_beacon_scan_start(void); + +tuya_ble_status_t tuya_ble_prod_beacon_scan_stop(void); + +tuya_ble_status_t tuya_ble_prod_beacon_get_rssi_avg(int8_t *rssi); + +tuya_ble_status_t tuya_ble_prod_gpio_test(void); + +void tuya_ble_internal_production_test_with_ble_flag_clear(void); + +uint8_t tuya_ble_internal_production_test_with_ble_flag_get(void); + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // _TUYA_BLE_APP_PRODUCTION_TEST_H_ + diff --git a/apps/common/third_party_profile/tuya_protocol/app/uart_common/tuya_ble_app_uart_common_handler.c b/apps/common/third_party_profile/tuya_protocol/app/uart_common/tuya_ble_app_uart_common_handler.c new file mode 100644 index 0000000..08d1925 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/app/uart_common/tuya_ble_app_uart_common_handler.c @@ -0,0 +1,813 @@ +/** + * \file tuya_ble_app_uart_common_handler.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" +#include "tuya_ble_heap.h" +#include "tuya_ble_mem.h" +#include "tuya_ble_api.h" +#include "tuya_ble_port.h" +#include "tuya_ble_main.h" +#include "tuya_ble_internal_config.h" +#include "tuya_ble_data_handler.h" +#include "tuya_ble_mutli_tsf_protocol.h" +#include "tuya_ble_utils.h" +#include "tuya_ble_secure.h" +#include "tuya_ble_main.h" +#include "tuya_ble_storage.h" +#include "tuya_ble_app_uart_common_handler.h" +#include "tuya_ble_log.h" + + +#define TUYA_BLE_OTA_MCU_TEST 0 + +#define TUYA_BLE_UART_COMMON_MCU_OTA_DATA_LENGTH_MAX 200 + +#define TUYA_BLE_OTA_MCU_TYPE 1 + + +#define TUYA_BLE_UART_COMMON_MCU_OTA_REQUEST 0xEA +#define TUYA_BLE_UART_COMMON_MCU_OTA_FILE_INFO 0xEB +#define TUYA_BLE_UART_COMMON_MCU_OTA_FILE_OFFSET 0xEC +#define TUYA_BLE_UART_COMMON_MCU_OTA_DATA 0xED +#define TUYA_BLE_UART_COMMON_MCU_OTA_END 0xEE + + +#if (!TUYA_BLE_OTA_MCU_TEST) + + +void tuya_ble_uart_common_mcu_ota_data_from_ble_handler(uint16_t cmd, uint8_t *recv_data, uint32_t recv_len) +{ + static uint8_t uart_data_temp[42]; + uint8_t *uart_data_buffer = NULL; + uint8_t uart_data_len = 0; + + if (cmd == FRM_OTA_DATA_REQ) { + uart_data_buffer = (uint8_t *)tuya_ble_malloc(recv_len + 7); + if (uart_data_buffer == NULL) { + TUYA_BLE_LOG_ERROR("uart_data_buffer malloc failed."); + return; + } + + } else { + uart_data_buffer = uart_data_temp; + } + + uart_data_buffer[0] = 0x55; + uart_data_buffer[1] = 0xAA; + uart_data_buffer[2] = 0x00; + switch (cmd) { + case FRM_OTA_START_REQ: + uart_data_buffer[3] = TUYA_BLE_UART_COMMON_MCU_OTA_REQUEST; + uart_data_buffer[4] = 0; + uart_data_buffer[5] = 2; + uart_data_buffer[6] = TUYA_BLE_UART_COMMON_MCU_OTA_DATA_LENGTH_MAX >> 8; + uart_data_buffer[7] = (uint8_t)TUYA_BLE_UART_COMMON_MCU_OTA_DATA_LENGTH_MAX; + uart_data_len = 8; + break; + case FRM_OTA_FILE_INFOR_REQ: + uart_data_buffer[3] = TUYA_BLE_UART_COMMON_MCU_OTA_FILE_INFO; + uart_data_buffer[4] = 0; + uart_data_buffer[5] = 35; + memcpy(uart_data_buffer + 6, recv_data, 8); + uart_data_buffer[14] = recv_data[9]; + uart_data_buffer[15] = recv_data[10]; + uart_data_buffer[16] = recv_data[11]; + memcpy(&uart_data_buffer[17], recv_data + 12, 24); + uart_data_len = 41; + break; + case FRM_OTA_FILE_OFFSET_REQ: + uart_data_buffer[3] = TUYA_BLE_UART_COMMON_MCU_OTA_FILE_OFFSET; + uart_data_buffer[4] = 0; + uart_data_buffer[5] = 4; + memcpy(uart_data_buffer + 6, recv_data, 4); + uart_data_len = 10; + break; + case FRM_OTA_DATA_REQ: + uart_data_buffer[3] = TUYA_BLE_UART_COMMON_MCU_OTA_DATA; + uart_data_buffer[4] = 0; + uart_data_buffer[5] = recv_len; + memcpy(uart_data_buffer + 6, recv_data, recv_len); + uart_data_len = 6 + recv_len; + break; + case FRM_OTA_END_REQ: + uart_data_buffer[3] = TUYA_BLE_UART_COMMON_MCU_OTA_END; + uart_data_buffer[4] = 0; + uart_data_buffer[5] = 0; + uart_data_len = 6; + break; + default: + break; + } + + uart_data_buffer[uart_data_len] = tuya_ble_check_sum(uart_data_buffer, uart_data_len); + + tuya_ble_common_uart_send_data(uart_data_buffer, uart_data_len + 1); + + TUYA_BLE_LOG_HEXDUMP_DEBUG("mcu ota uart send data : ", uart_data_buffer, uart_data_len + 1); + + if (cmd == FRM_OTA_DATA_REQ) { + tuya_ble_free(uart_data_buffer); + } + +} + + + +static void tuya_ble_uart_common_mcu_ota_data_from_uart_handler(uint8_t cmd, uint8_t *data_buffer, uint16_t data_len) +{ + static uint8_t ble_data_buffer[30]; + static uint8_t ble_data_len = 0; + uint16_t ble_cmd = 0; + tuya_ble_connect_status_t currnet_connect_status; + + memset(ble_data_buffer, 0, sizeof(ble_data_buffer)); + ble_data_len = 0; + switch (cmd) { + case TUYA_BLE_UART_COMMON_MCU_OTA_REQUEST: + ble_data_buffer[0] = data_buffer[0]; + ble_data_buffer[1] = 3; + ble_data_buffer[2] = TUYA_BLE_OTA_MCU_TYPE; + ble_data_buffer[3] = 0; + memcpy(&ble_data_buffer[4], data_buffer + 1, 5); + ble_data_len = 9; + ble_cmd = FRM_OTA_START_RESP; + break; + case TUYA_BLE_UART_COMMON_MCU_OTA_FILE_INFO: + ble_data_buffer[0] = TUYA_BLE_OTA_MCU_TYPE; + memcpy(&ble_data_buffer[1], data_buffer, 25); + ble_data_len = 26; + ble_cmd = FRM_OTA_FILE_INFOR_RESP; + break; + case TUYA_BLE_UART_COMMON_MCU_OTA_FILE_OFFSET: + ble_data_buffer[0] = TUYA_BLE_OTA_MCU_TYPE; + memcpy(&ble_data_buffer[1], data_buffer, 4); + ble_data_len = 5; + ble_cmd = FRM_OTA_FILE_OFFSET_RESP; + break; + case TUYA_BLE_UART_COMMON_MCU_OTA_DATA: + ble_data_buffer[0] = TUYA_BLE_OTA_MCU_TYPE; + ble_data_buffer[1] = data_buffer[0]; + ble_data_len = 2; + ble_cmd = FRM_OTA_DATA_RESP; + break; + case TUYA_BLE_UART_COMMON_MCU_OTA_END: + ble_data_buffer[0] = TUYA_BLE_OTA_MCU_TYPE; + ble_data_buffer[1] = data_buffer[0]; + ble_data_len = 2; + ble_cmd = FRM_OTA_END_RESP; + break; + default: + break; + }; + + currnet_connect_status = tuya_ble_connect_status_get(); + + if (currnet_connect_status != BONDING_CONN) { + TUYA_BLE_LOG_ERROR("tuya_ble_uart_common_mcu_ota_process FAILED."); + return; + } + + if (ble_data_len > 0) { + tuya_ble_commData_send(ble_cmd, 0, ble_data_buffer, ble_data_len, ENCRYPTION_MODE_SESSION_KEY); + } + +} + + +__TUYA_BLE_WEAK void tuya_ble_custom_app_uart_common_process(uint8_t *p_in_data, uint16_t in_len) +{ + uint8_t cmd = p_in_data[3]; + uint16_t data_len = (p_in_data[4] << 8) + p_in_data[5]; + uint8_t *data_buffer = p_in_data + 6; + + switch (cmd) { + + default: + break; + }; + +} + + + +void tuya_ble_uart_common_process(uint8_t *p_in_data, uint16_t in_len) +{ + uint8_t cmd = p_in_data[3]; + uint16_t data_len = (p_in_data[4] << 8) + p_in_data[5]; + uint8_t *data_buffer = p_in_data + 6; + + switch (cmd) { + case TUYA_BLE_UART_COMMON_MCU_OTA_REQUEST: + case TUYA_BLE_UART_COMMON_MCU_OTA_FILE_INFO: + case TUYA_BLE_UART_COMMON_MCU_OTA_FILE_OFFSET: + case TUYA_BLE_UART_COMMON_MCU_OTA_DATA: + case TUYA_BLE_UART_COMMON_MCU_OTA_END: + tuya_ble_uart_common_mcu_ota_data_from_uart_handler(cmd, data_buffer, data_len); + break; + default: + tuya_ble_custom_app_uart_common_process(p_in_data, in_len); + break; + }; + +} + + +#else + + +tuya_ble_timer_t tuya_ble_xtimer_heartbeat ; + +static uint32_t tuya_ble_heartbeat_timeout_ms = 1000; + +static uint8_t heartbeat_uart_buffer[10]; + +static uint8_t mcu_info_get = 0; + + +static void tuya_ble_common_uart_protocol_send(uint8_t cmd, uint8_t *pdata, uint8_t len) +{ + static uint8_t alloc_buf[256]; + + uint8_t i = 0; + alloc_buf[0 + 1] = 0x55; + alloc_buf[1 + 1] = 0xaa; + alloc_buf[2 + 1] = 0x00; + alloc_buf[3 + 1] = cmd; + alloc_buf[4 + 1] = 0; + alloc_buf[5 + 1] = len; + + memcpy(alloc_buf + 6 + 1, pdata, len); + alloc_buf[7 + len] = tuya_ble_check_sum(alloc_buf + 1, 6 + len); + + tuya_ble_common_uart_send_data(alloc_buf + 1, 7 + len); +} + + +static void tuya_ble_vtimer_heartbeat_callback(tuya_ble_timer_t timer) +{ + heartbeat_uart_buffer[0] = 0x55; + heartbeat_uart_buffer[1] = 0xAA; + heartbeat_uart_buffer[2] = 0x00; + heartbeat_uart_buffer[3] = 0x00; + heartbeat_uart_buffer[4] = 0x00; + heartbeat_uart_buffer[5] = 0x00; + heartbeat_uart_buffer[6] = 0xFF; + + tuya_ble_common_uart_send_data(heartbeat_uart_buffer, 7); + +} + + +static void tuya_ble_heartbeat_timer_create(void) +{ + if (tuya_ble_timer_create(&tuya_ble_xtimer_heartbeat, tuya_ble_heartbeat_timeout_ms, TUYA_BLE_TIMER_REPEATED, tuya_ble_vtimer_heartbeat_callback) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("tuya_ble_xtimer_heartbeat creat failed"); + } + +} + + +static void tuya_ble_heartbeat_timer_start(void) +{ + if (tuya_ble_timer_start(tuya_ble_xtimer_heartbeat) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("tuya_ble_xtimer_heartbeat start failed"); + } + +} + +static void tuya_ble_heartbeat_timer_restart(uint32_t ms) +{ + if (tuya_ble_timer_restart(tuya_ble_xtimer_heartbeat, ms) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("tuya_ble_xtimer_heartbeat restart failed"); + } + +} + + +static void tuya_ble_heartbeat_timer_stop(void) +{ + + if (tuya_ble_timer_stop(tuya_ble_xtimer_heartbeat) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("tuya_ble_xtimer_heartbeat stop failed"); + } + +} + + +static void tuya_ble_heartbeat_timer_delete(void) +{ + + if (tuya_ble_timer_delete(tuya_ble_xtimer_heartbeat) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("tuya_ble_xtimer_heartbeat delete failed"); + } + +} + + + + +static void tuya_ble_ota_data_process_test(uint8_t *p_data, uint16_t p_data_len); + +void tuya_ble_uart_common_mcu_ota_data_from_ble_handler(uint16_t cmd, uint8_t *recv_data, uint32_t recv_len) +{ + static uint8_t uart_data_temp[42]; + uint8_t uart_cmd = 0xFF; + uint8_t *uart_data_buffer = NULL; + uint8_t uart_data_len = 0; + + if (cmd == FRM_OTA_DATA_REQ) { + uart_data_buffer = (uint8_t *)tuya_ble_malloc(recv_len + 7); + if (uart_data_buffer == NULL) { + TUYA_BLE_LOG_ERROR("uart_data_buffer malloc failed.\n"); + return; + } + + } else { + uart_data_buffer = uart_data_temp; + } + + uart_data_buffer[0] = 0x55; + uart_data_buffer[1] = 0xAA; + uart_data_buffer[2] = 0x00; + switch (cmd) { + case FRM_OTA_START_REQ: + uart_data_buffer[3] = TUYA_BLE_UART_COMMON_MCU_OTA_REQUEST; + uart_data_buffer[4] = 0; + uart_data_buffer[5] = 2; + uart_data_buffer[6] = TUYA_BLE_UART_COMMON_MCU_OTA_DATA_LENGTH_MAX >> 8; + uart_data_buffer[7] = (uint8_t)TUYA_BLE_UART_COMMON_MCU_OTA_DATA_LENGTH_MAX; + uart_data_len = 8; + break; + case FRM_OTA_FILE_INFOR_REQ: + uart_data_buffer[3] = TUYA_BLE_UART_COMMON_MCU_OTA_FILE_INFO; + uart_data_buffer[4] = 0; + uart_data_buffer[5] = 35; + memcpy(uart_data_buffer + 6, recv_data, 8); + uart_data_buffer[14] = recv_data[9]; + uart_data_buffer[15] = recv_data[10]; + uart_data_buffer[16] = recv_data[11]; + memcpy(&uart_data_buffer[17], recv_data + 12, 24); + uart_data_len = 41; + break; + case FRM_OTA_FILE_OFFSET_REQ: + uart_data_buffer[3] = TUYA_BLE_UART_COMMON_MCU_OTA_FILE_OFFSET; + uart_data_buffer[4] = 0; + uart_data_buffer[5] = 4; + memcpy(uart_data_buffer + 6, recv_data, 4); + uart_data_len = 10; + break; + case FRM_OTA_DATA_REQ: + uart_data_buffer[3] = TUYA_BLE_UART_COMMON_MCU_OTA_DATA; + uart_data_buffer[4] = 0; + uart_data_buffer[5] = recv_len; + memcpy(uart_data_buffer + 6, recv_data, recv_len); + uart_data_len = 6 + recv_len; + break; + case FRM_OTA_END_REQ: + uart_data_buffer[3] = TUYA_BLE_UART_COMMON_MCU_OTA_END; + uart_data_buffer[4] = 0; + uart_data_buffer[5] = 0; + uart_data_len = 6; + break; + default: + break; + } + + uart_data_buffer[uart_data_len] = tuya_ble_check_sum(uart_data_buffer, uart_data_len); + + tuya_ble_common_uart_send_data(uart_data_buffer, uart_data_len + 1); + + TUYA_BLE_LOG_HEXDUMP_DEBUG("mcu ota uart send data : ", uart_data_buffer, uart_data_len + 1); + + if (cmd == FRM_OTA_DATA_REQ) { + tuya_ble_free(uart_data_buffer); + } + +} + + + +static void tuya_ble_uart_common_mcu_ota_data_from_uart_handler(uint8_t cmd, uint8_t *data_buffer, uint16_t data_len) +{ + static uint8_t ble_data_buffer[30]; + static uint8_t ble_data_len = 0; + uint16_t ble_cmd = 0; + tuya_ble_connect_status_t currnet_connect_status; + + memset(ble_data_buffer, 0, sizeof(ble_data_buffer)); + ble_data_len = 0; + switch (cmd) { + case TUYA_BLE_UART_COMMON_MCU_OTA_REQUEST: + ble_data_buffer[0] = data_buffer[0]; + ble_data_buffer[1] = 3; + ble_data_buffer[2] = TUYA_BLE_OTA_MCU_TYPE; + ble_data_buffer[3] = 0; + memcpy(&ble_data_buffer[4], data_buffer + 1, 5); + ble_data_len = 9; + ble_cmd = FRM_OTA_START_RESP; + break; + case TUYA_BLE_UART_COMMON_MCU_OTA_FILE_INFO: + ble_data_buffer[0] = TUYA_BLE_OTA_MCU_TYPE; + memcpy(&ble_data_buffer[1], data_buffer, 25); + ble_data_len = 26; + ble_cmd = FRM_OTA_FILE_INFOR_RESP; + break; + case TUYA_BLE_UART_COMMON_MCU_OTA_FILE_OFFSET: + ble_data_buffer[0] = TUYA_BLE_OTA_MCU_TYPE; + memcpy(&ble_data_buffer[1], data_buffer, 4); + ble_data_len = 5; + ble_cmd = FRM_OTA_FILE_OFFSET_RESP; + break; + case TUYA_BLE_UART_COMMON_MCU_OTA_DATA: + ble_data_buffer[0] = TUYA_BLE_OTA_MCU_TYPE; + ble_data_buffer[1] = data_buffer[0]; + ble_data_len = 2; + ble_cmd = FRM_OTA_DATA_RESP; + break; + case TUYA_BLE_UART_COMMON_MCU_OTA_END: + ble_data_buffer[0] = TUYA_BLE_OTA_MCU_TYPE; + ble_data_buffer[1] = data_buffer[0]; + ble_data_len = 2; + ble_cmd = FRM_OTA_END_RESP; + break; + default: + break; + }; + + currnet_connect_status = tuya_ble_connect_status_get(); + + if (currnet_connect_status != BONDING_CONN) { + TUYA_BLE_LOG_ERROR("tuya_ble_uart_common_mcu_ota_process FAILED."); + return; + } + + if (ble_data_len > 0) { + tuya_ble_commData_send(ble_cmd, 0, ble_data_buffer, ble_data_len, ENCRYPTION_MODE_SESSION_KEY); + } + +} + + +void tuya_ble_uart_common_send_current_ble_state(void) +{ + uint8_t ble_work_state = 0; + tuya_ble_connect_status_t ble_state; + + ble_state = tuya_ble_connect_status_get(); + + if ((ble_state == UNBONDING_UNCONN) || (ble_state == UNBONDING_UNCONN) || (ble_state == UNBONDING_UNCONN)) { + ble_work_state = 1; + } else if ((ble_state == BONDING_UNCONN) || (ble_state == BONDING_UNAUTH_CONN)) { + ble_work_state = 2; + } else if (ble_state == BONDING_CONN) { + ble_work_state = 3; + } else { + ble_work_state = 0; + } + + tuya_ble_common_uart_protocol_send(TUYA_BLE_UART_COMMON_REPORT_WORK_STATE_TYPE, (uint8_t *)&ble_work_state, 1); + +} + + +void tuya_ble_uart_common_process(uint8_t *p_in_data, uint16_t in_len) +{ + uint8_t cmd = p_in_data[3]; + uint16_t data_len = (p_in_data[4] << 8) + p_in_data[5]; + uint8_t *data_buffer = p_in_data + 6; + uint32_t mcu_firmware_version = 0, mcu_hardware_version = 0; + switch (cmd) { + case TUYA_BLE_UART_COMMON_HEART_MSG_TYPE: + if ((mcu_info_get == 0) || (data_buffer[0] == 0)) { + mcu_info_get = 1; + tuya_ble_common_uart_protocol_send(TUYA_BLE_UART_COMMON_SEARCH_PID_TYPE, NULL, 0); + } + + break; + + case TUYA_BLE_UART_COMMON_SEARCH_PID_TYPE: + if (memcmp(tuya_ble_current_para.pid, data_buffer, 8) != 0) { + TUYA_BLE_LOG_HEXDUMP_DEBUG("PID change to : ", data_buffer, 16); + tuya_ble_device_update_product_id(TUYA_BLE_PRODUCT_ID_TYPE_PID, 8, data_buffer); + + } + + tuya_ble_heartbeat_timer_restart(10000); + tuya_ble_common_uart_protocol_send(TUYA_BLE_UART_COMMON_CK_MCU_TYPE, NULL, 0); + tuya_ble_common_uart_protocol_send(TUYA_BLE_UART_COMMON_QUERY_MCU_VERSION, NULL, 0); + + break; + + case TUYA_BLE_UART_COMMON_CK_MCU_TYPE: + + tuya_ble_uart_common_send_current_ble_state(); + + break; + + case TUYA_BLE_UART_COMMON_QUERY_MCU_VERSION: + mcu_firmware_version = (data_buffer[0] << 16) | (data_buffer[1] << 8) | (data_buffer[2]); + mcu_hardware_version = (data_buffer[3] << 16) | (data_buffer[4] << 8) | (data_buffer[5]); + TUYA_BLE_LOG_DEBUG("reveived mcu_firmware_version : 0x%04x mcu_hardware_version : 0x%04x", mcu_firmware_version, mcu_hardware_version); + tuya_ble_device_update_mcu_version(mcu_firmware_version, mcu_hardware_version); + + break; + + case TUYA_BLE_UART_COMMON_MCU_SEND_VERSION: + mcu_firmware_version = (data_buffer[0] << 16) | (data_buffer[1] << 8) | (data_buffer[2]); + mcu_hardware_version = (data_buffer[3] << 16) | (data_buffer[4] << 8) | (data_buffer[5]); + TUYA_BLE_LOG_DEBUG("reveived mcu_firmware_version : 0x%04x mcu_hardware_version : 0x%04x", mcu_firmware_version, mcu_hardware_version); + tuya_ble_device_update_mcu_version(mcu_firmware_version, mcu_hardware_version); + break; + + case TUYA_BLE_UART_COMMON_REPORT_WORK_STATE_TYPE: + + break; + case TUYA_BLE_UART_COMMON_RESET_TYPE: + + break; + case TUYA_BLE_UART_COMMON_SEND_CMD_TYPE: + + break; + case TUYA_BLE_UART_COMMON_SEND_STATUS_TYPE: + + break; + case TUYA_BLE_UART_COMMON_QUERY_STATUS: + + break; + case TUYA_BLE_UART_COMMON_SEND_STORAGE_TYPE: + + break; + case TUYA_BLE_UART_COMMON_SEND_TIME_SYNC_TYPE: + + break; + case TUYA_BLE_UART_COMMON_MODIFY_ADV_INTERVAL: + + break; + case TUYA_BLE_UART_COMMON_TURNOFF_SYSTEM_TIME: + + break; + case TUYA_BLE_UART_COMMON_ENANBLE_LOWER_POWER: + + break; + case TUYA_BLE_UART_COMMON_SEND_ONE_TIME_PASSWORD_TOKEN: + + break; + case TUYA_BLE_UART_COMMON_ACTIVE_DISCONNECT: + + break; + case TUYA_BLE_UART_COMMON_BLE_OTA_STATUS: + + break; + + case TUYA_BLE_UART_COMMON_MCU_OTA_REQUEST: + case TUYA_BLE_UART_COMMON_MCU_OTA_FILE_INFO: + case TUYA_BLE_UART_COMMON_MCU_OTA_FILE_OFFSET: + case TUYA_BLE_UART_COMMON_MCU_OTA_DATA: + case TUYA_BLE_UART_COMMON_MCU_OTA_END: + tuya_ble_uart_common_mcu_ota_data_from_uart_handler(cmd, data_buffer, data_len); + break; + default: + break; + }; + +} + +static uint8_t mcu_ota_flag = 0; + +#define MCU_OTA_MAX_DATA_SIZE 200 + +#define CURRENT_MCU_FIRMWARE_VERSION 0x010000 + +#define SUPPORT_MCU_OTA_FILE_MAX_LENGTH 102400 + +typedef struct { + uint32_t file_version; + uint8_t file_md5[16]; + uint32_t file_length; + uint32_t file_crc32; +} mcu_ota_file_info_data_t; + +static mcu_ota_file_info_data_t mcu_ota_file_data = {0}; + +static uint16_t current_package = 0; +static uint16_t last_package = 0; + +static uint32_t current_image_crc_last; +static uint32_t current_image_write_offset; + +static void mcu_ota_current_para_init(void) +{ + current_package = 0; + last_package = 0; + mcu_ota_flag = 0; + current_image_crc_last = 0; + current_image_write_offset = 0; +} + +void mcu_ota_test_init(void) +{ + mcu_ota_current_para_init(); + tuya_ble_heartbeat_timer_create(); + tuya_ble_heartbeat_timer_start(); +} + +void mcu_ota_test_para_init_connect(void) +{ + mcu_ota_current_para_init(); +} + + +static void tuya_ble_ota_data_process_test(uint8_t *p_data, uint16_t p_data_len) +{ + uint16_t len = 0; + uint16_t crc16_rev, crc16_temp; + static uint8_t ota_data_response_buffer[40]; + uint8_t ota_data_response_len; + uint8_t cmd = p_data[3]; + uint16_t ota_data_len = (p_data[4] << 8) + p_data[5]; + uint8_t *ota_data_buffer = p_data + 6; + memset(ota_data_response_buffer, 0, sizeof(ota_data_response_buffer)); + ota_data_response_buffer[0] = 0x55; + ota_data_response_buffer[1] = 0xaa; + ota_data_response_buffer[2] = 0x00; + switch (cmd) { + case TUYA_BLE_UART_COMMON_MCU_OTA_REQUEST: + ota_data_response_buffer[3] = TUYA_BLE_UART_COMMON_MCU_OTA_REQUEST; + ota_data_response_buffer[4] = 0; + ota_data_response_buffer[5] = 6; + if (mcu_ota_flag == 0) { + mcu_ota_current_para_init(); + ota_data_response_buffer[6] = 0; + ota_data_response_buffer[7] = ((uint32_t)CURRENT_MCU_FIRMWARE_VERSION >> 16); + ota_data_response_buffer[8] = ((uint32_t)CURRENT_MCU_FIRMWARE_VERSION >> 8); + ota_data_response_buffer[9] = ((uint32_t)CURRENT_MCU_FIRMWARE_VERSION); + ota_data_response_buffer[10] = ((uint16_t)MCU_OTA_MAX_DATA_SIZE >> 8); + ota_data_response_buffer[11] = ((uint16_t)MCU_OTA_MAX_DATA_SIZE); + mcu_ota_flag = 1; + memset(&mcu_ota_file_data, 0, sizeof(mcu_ota_file_data)); + } else { + ota_data_response_buffer[6] = 1; + mcu_ota_flag = 0; + } + ota_data_response_len = 12; + + break; + + case TUYA_BLE_UART_COMMON_MCU_OTA_FILE_INFO: + ota_data_response_buffer[3] = TUYA_BLE_UART_COMMON_MCU_OTA_FILE_INFO; + ota_data_response_buffer[4] = 0; + ota_data_response_buffer[5] = 25; + if (mcu_ota_flag != 1) { + ota_data_response_buffer[6] = 4; + mcu_ota_flag = 0; + } else { + if (memcmp(ota_data_buffer, tuya_ble_current_para.pid, 8)) { + ota_data_response_buffer[6] = 1; + mcu_ota_flag = 0; + } else { + mcu_ota_file_data.file_version = (ota_data_buffer[8] << 16) + (ota_data_buffer[9] << 8) + ota_data_buffer[10]; + memcpy(mcu_ota_file_data.file_md5, ota_data_buffer + 11, 16); + mcu_ota_file_data.file_length = (ota_data_buffer[27] << 24) + (ota_data_buffer[28] << 16) + (ota_data_buffer[29] << 8) + ota_data_buffer[30]; + mcu_ota_file_data.file_crc32 = (ota_data_buffer[31] << 24) + (ota_data_buffer[32] << 16) + (ota_data_buffer[33] << 8) + ota_data_buffer[34]; + + if (mcu_ota_file_data.file_version <= CURRENT_MCU_FIRMWARE_VERSION) { + ota_data_response_buffer[6] = 2; + mcu_ota_flag = 0; + } else if (mcu_ota_file_data.file_length > SUPPORT_MCU_OTA_FILE_MAX_LENGTH) { + ota_data_response_buffer[6] = 3; + mcu_ota_flag = 0; + } else { + ota_data_response_buffer[6] = 0; + mcu_ota_flag = 2; + + } + + + } + } + ota_data_response_len = 31; + + break; + case TUYA_BLE_UART_COMMON_MCU_OTA_FILE_OFFSET: + ota_data_response_buffer[3] = TUYA_BLE_UART_COMMON_MCU_OTA_FILE_OFFSET; + ota_data_response_buffer[4] = 0; + ota_data_response_buffer[5] = 4; + if (mcu_ota_flag == 2) { + memset(&ota_data_response_buffer[6], 0, 4); + mcu_ota_flag = 3; + ota_data_response_len = 10; + } else { + mcu_ota_flag = 0; + ota_data_response_len = 0; + } + + break; + + case TUYA_BLE_UART_COMMON_MCU_OTA_DATA: + ota_data_response_buffer[3] = TUYA_BLE_UART_COMMON_MCU_OTA_DATA; + ota_data_response_buffer[4] = 0; + ota_data_response_buffer[5] = 1; + + if ((mcu_ota_flag == 3) || (mcu_ota_flag == 4)) { + current_package = (ota_data_buffer[0] << 8) | ota_data_buffer[1]; + len = (ota_data_buffer[2] << 8) | ota_data_buffer[3]; + + if ((current_package != (last_package + 1)) && (current_package != 0)) { + TUYA_BLE_LOG_ERROR("mcu ota received package number error.received package number : %d", current_package); + ota_data_response_buffer[6] = 1; + } else if ((len > MCU_OTA_MAX_DATA_SIZE) || ((len + 6) != (p_data_len - 7))) { + TUYA_BLE_LOG_ERROR("mcu ota received package data length error : len = %d,p_data_len = %d", len, p_data_len); + ota_data_response_buffer[6] = 2; + } else { + crc16_temp = (ota_data_buffer[4] << 8) | ota_data_buffer[5]; + crc16_rev = tuya_ble_crc16_compute(&ota_data_buffer[6], len, NULL); + if (crc16_temp != crc16_rev) { + TUYA_BLE_LOG_ERROR("mcu ota received package data crc16 error,crc_16_cal = 0x%04x ; crc16_rev = 0x%04x", crc16_temp, crc16_rev); + ota_data_response_buffer[6] = 3; + } + + } + + + if (ota_data_response_buffer[6] == 0) { + current_image_crc_last = tuya_ble_crc32_compute(&ota_data_buffer[6], len, ¤t_image_crc_last); + current_image_write_offset += len; + mcu_ota_flag = 4; + last_package = current_package; + } else { + mcu_ota_flag = 0; + mcu_ota_current_para_init(); + } + ota_data_response_len = 7; + + } else { + mcu_ota_flag = 0; + ota_data_response_len = 0; + } + + break; + + case TUYA_BLE_UART_COMMON_MCU_OTA_END: + ota_data_response_buffer[3] = TUYA_BLE_UART_COMMON_MCU_OTA_END; + ota_data_response_buffer[4] = 0; + ota_data_response_buffer[5] = 1; + if (mcu_ota_flag != 0) { + if (mcu_ota_file_data.file_length != current_image_write_offset) { + ota_data_response_buffer[6] = 1; + } else if (mcu_ota_file_data.file_crc32 != current_image_crc_last) { + ota_data_response_buffer[6] = 2; + } else { + ota_data_response_buffer[6] = 0; + mcu_ota_flag = 0; + TUYA_BLE_LOG_DEBUG("mcu ota test succeed."); + } + ota_data_response_len = 7; + } else { + mcu_ota_flag = 0; + ota_data_response_len = 0; + } + + + break; + + default: + + break; + }; + + if (ota_data_response_len > 0) { + ota_data_response_buffer[ota_data_response_len] = tuya_ble_check_sum(ota_data_response_buffer, ota_data_response_len); + ota_data_response_len++; + tuya_ble_common_uart_send_full_instruction_received(ota_data_response_buffer, ota_data_response_len); + } + +} + +#endif + + + + + diff --git a/apps/common/third_party_profile/tuya_protocol/app/uart_common/tuya_ble_app_uart_common_handler.h b/apps/common/third_party_profile/tuya_protocol/app/uart_common/tuya_ble_app_uart_common_handler.h new file mode 100644 index 0000000..c26846e --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/app/uart_common/tuya_ble_app_uart_common_handler.h @@ -0,0 +1,53 @@ +/** + * \file tuya_ble_app_uart_common_handler.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#ifndef _TUYA_BLE_APP_UART_COMMON_HANDLER_H_ +#define _TUYA_BLE_APP_UART_COMMON_HANDLER_H_ + +#include +#include "tuya_ble_internal_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Function for transmit ble data from peer devices to tuya sdk. + * + * @note This function must be called from where the ble data is received. + *. + * */ + +void tuya_ble_uart_common_process(uint8_t *p_in_data, uint16_t in_len); + +void tuya_ble_uart_common_mcu_ota_data_from_ble_handler(uint16_t cmd, uint8_t *recv_data, uint32_t recv_len); + + +#ifdef __cplusplus +} +#endif + +#endif // _TUYA_BLE_APP_UART_COMMON_HANDLER_H_ + diff --git a/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/aes.c b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/aes.c new file mode 100644 index 0000000..be039a8 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/aes.c @@ -0,0 +1,2285 @@ +/* + * FIPS-197 compliant AES implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ + +#include "aes.h" + + +#if defined(MBEDTLS_AES_C) + +#include + + +//#include "mbedtls/platform.h" +//#include "mbedtls/platform_util.h" +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif +#if defined(MBEDTLS_AESNI_C) +#include "mbedtls/aesni.h" +#endif + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_printf //printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_AES_ALT) + + +/* Internal macros meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 ) +#define MBEDTLS_INTERNAL_VALIDATE( cond ) do { } while( 0 ) + +/* Parameter validation macros based on platform_util.h */ +#define AES_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_AES_BAD_INPUT_DATA ) +#define AES_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +#if defined(MBEDTLS_PADLOCK_C) && \ + ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) ) +static int aes_padlock_ace = -1; +#endif + +#if defined(MBEDTLS_AES_ROM_TABLES) +/* + * Forward S-box + */ +static const unsigned char FSb[256] = { + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +/* + * Forward tables + */ +#define FT \ +\ + V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ + V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ + V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ + V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ + V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ + V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ + V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ + V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ + V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ + V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ + V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ + V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ + V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ + V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ + V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ + V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ + V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ + V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ + V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ + V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ + V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ + V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ + V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ + V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ + V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ + V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ + V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ + V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ + V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ + V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ + V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ + V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ + V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ + V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ + V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ + V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ + V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ + V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ + V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ + V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ + V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ + V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ + V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ + V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ + V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ + V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ + V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ + V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ + V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ + V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ + V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ + V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ + V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ + V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ + V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ + V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ + V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ + V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ + V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ + V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ + V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ + V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ + V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ + V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t FT0[256] = { FT }; +#undef V + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t FT3[256] = { FT }; +#undef V + +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +#undef FT + +/* + * Reverse S-box + */ +static const unsigned char RSb[256] = { + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +/* + * Reverse tables + */ +#define RT \ +\ + V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ + V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ + V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ + V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ + V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ + V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ + V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ + V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ + V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ + V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ + V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ + V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ + V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ + V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ + V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ + V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ + V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ + V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ + V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ + V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ + V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ + V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ + V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ + V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ + V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ + V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ + V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ + V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ + V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ + V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ + V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ + V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ + V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ + V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ + V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ + V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ + V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ + V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ + V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ + V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ + V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ + V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ + V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ + V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ + V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ + V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ + V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ + V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ + V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ + V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ + V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ + V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ + V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ + V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ + V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ + V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ + V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ + V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ + V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ + V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ + V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ + V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ + V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ + V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t RT0[256] = { RT }; +#undef V + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t RT3[256] = { RT }; +#undef V + +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +#undef RT + +/* + * Round constants + */ +static const uint32_t RCON[10] = { + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 +}; + +#else /* MBEDTLS_AES_ROM_TABLES */ + +/* + * Forward S-box & tables + */ +static unsigned char FSb[256]; +static uint32_t FT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) +static uint32_t FT1[256]; +static uint32_t FT2[256]; +static uint32_t FT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +/* + * Reverse S-box & tables + */ +static unsigned char RSb[256]; +static uint32_t RT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) +static uint32_t RT1[256]; +static uint32_t RT2[256]; +static uint32_t RT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +/* + * Round constants + */ +static uint32_t RCON[10]; + +/* + * Tables generation code + */ +#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) +#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) +#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) + +static int aes_init_done = 0; + +static void aes_gen_tables(void) +{ + int i, x, y, z; + int pow[256]; + int log[256]; + + /* + * compute pow and log tables over GF(2^8) + */ + for (i = 0, x = 1; i < 256; i++) { + pow[i] = x; + log[x] = i; + x = (x ^ XTIME(x)) & 0xFF; + } + + /* + * calculate the round constants + */ + for (i = 0, x = 1; i < 10; i++) { + RCON[i] = (uint32_t) x; + x = XTIME(x) & 0xFF; + } + + /* + * generate the forward and reverse S-boxes + */ + FSb[0x00] = 0x63; + RSb[0x63] = 0x00; + + for (i = 1; i < 256; i++) { + x = pow[255 - log[i]]; + + y = x; + y = ((y << 1) | (y >> 7)) & 0xFF; + x ^= y; + y = ((y << 1) | (y >> 7)) & 0xFF; + x ^= y; + y = ((y << 1) | (y >> 7)) & 0xFF; + x ^= y; + y = ((y << 1) | (y >> 7)) & 0xFF; + x ^= y ^ 0x63; + + FSb[i] = (unsigned char) x; + RSb[x] = (unsigned char) i; + } + + /* + * generate the forward and reverse tables + */ + for (i = 0; i < 256; i++) { + x = FSb[i]; + y = XTIME(x) & 0xFF; + z = (y ^ x) & 0xFF; + + FT0[i] = ((uint32_t) y) ^ + ((uint32_t) x << 8) ^ + ((uint32_t) x << 16) ^ + ((uint32_t) z << 24); + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + FT1[i] = ROTL8(FT0[i]); + FT2[i] = ROTL8(FT1[i]); + FT3[i] = ROTL8(FT2[i]); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + + x = RSb[i]; + + RT0[i] = ((uint32_t) MUL(0x0E, x)) ^ + ((uint32_t) MUL(0x09, x) << 8) ^ + ((uint32_t) MUL(0x0D, x) << 16) ^ + ((uint32_t) MUL(0x0B, x) << 24); + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + RT1[i] = ROTL8(RT0[i]); + RT2[i] = ROTL8(RT1[i]); + RT3[i] = ROTL8(RT2[i]); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + } +} + +#undef ROTL8 + +#endif /* MBEDTLS_AES_ROM_TABLES */ + +#if defined(MBEDTLS_AES_FEWER_TABLES) + +#define ROTL8(x) ( (uint32_t)( ( x ) << 8 ) + (uint32_t)( ( x ) >> 24 ) ) +#define ROTL16(x) ( (uint32_t)( ( x ) << 16 ) + (uint32_t)( ( x ) >> 16 ) ) +#define ROTL24(x) ( (uint32_t)( ( x ) << 24 ) + (uint32_t)( ( x ) >> 8 ) ) + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) ROTL8( RT0[idx] ) +#define AES_RT2(idx) ROTL16( RT0[idx] ) +#define AES_RT3(idx) ROTL24( RT0[idx] ) + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) ROTL8( FT0[idx] ) +#define AES_FT2(idx) ROTL16( FT0[idx] ) +#define AES_FT3(idx) ROTL24( FT0[idx] ) + +#else /* MBEDTLS_AES_FEWER_TABLES */ + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) RT1[idx] +#define AES_RT2(idx) RT2[idx] +#define AES_RT3(idx) RT3[idx] + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) FT1[idx] +#define AES_FT2(idx) FT2[idx] +#define AES_FT3(idx) FT3[idx] + +#endif /* MBEDTLS_AES_FEWER_TABLES */ + +static void *(* const volatile memset_func)(void *, int, size_t) = memset; + +static void mbedtls_platform_zeroize(void *buf, size_t len) +{ + memset_func(buf, 0, len); +} + +void mbedtls_aes_init(mbedtls_aes_context *ctx) +{ + AES_VALIDATE(ctx != NULL); + + memset(ctx, 0, sizeof(mbedtls_aes_context)); +} + +void mbedtls_aes_free(mbedtls_aes_context *ctx) +{ + if (ctx == NULL) { + return; + } + + mbedtls_platform_zeroize(ctx, sizeof(mbedtls_aes_context)); +} + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +void mbedtls_aes_xts_init(mbedtls_aes_xts_context *ctx) +{ + AES_VALIDATE(ctx != NULL); + + mbedtls_aes_init(&ctx->crypt); + mbedtls_aes_init(&ctx->tweak); +} + +void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx) +{ + if (ctx == NULL) { + return; + } + + mbedtls_aes_free(&ctx->crypt); + mbedtls_aes_free(&ctx->tweak); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/* + * AES key schedule (encryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) +int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits) +{ + unsigned int i; + uint32_t *RK; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(key != NULL); + + switch (keybits) { + case 128: + ctx->nr = 10; + break; + case 192: + ctx->nr = 12; + break; + case 256: + ctx->nr = 14; + break; + default : + return (MBEDTLS_ERR_AES_INVALID_KEY_LENGTH); + } + +#if !defined(MBEDTLS_AES_ROM_TABLES) + if (aes_init_done == 0) { + aes_gen_tables(); + aes_init_done = 1; + } +#endif + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if (aes_padlock_ace == -1) { + aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE); + } + + if (aes_padlock_ace) { + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16(ctx->buf); + } else +#endif + ctx->rk = RK = ctx->buf; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { + return (mbedtls_aesni_setkey_enc((unsigned char *) ctx->rk, key, keybits)); + } +#endif + + for (i = 0; i < (keybits >> 5); i++) { + GET_UINT32_LE(RK[i], key, i << 2); + } + + switch (ctx->nr) { + case 10: + + for (i = 0; i < 10; i++, RK += 4) { + RK[4] = RK[0] ^ RCON[i] ^ + ((uint32_t) FSb[(RK[3] >> 8) & 0xFF ]) ^ + ((uint32_t) FSb[(RK[3] >> 16) & 0xFF ] << 8) ^ + ((uint32_t) FSb[(RK[3] >> 24) & 0xFF ] << 16) ^ + ((uint32_t) FSb[(RK[3]) & 0xFF ] << 24); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 12: + + for (i = 0; i < 8; i++, RK += 6) { + RK[6] = RK[0] ^ RCON[i] ^ + ((uint32_t) FSb[(RK[5] >> 8) & 0xFF ]) ^ + ((uint32_t) FSb[(RK[5] >> 16) & 0xFF ] << 8) ^ + ((uint32_t) FSb[(RK[5] >> 24) & 0xFF ] << 16) ^ + ((uint32_t) FSb[(RK[5]) & 0xFF ] << 24); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 14: + + for (i = 0; i < 7; i++, RK += 8) { + RK[8] = RK[0] ^ RCON[i] ^ + ((uint32_t) FSb[(RK[7] >> 8) & 0xFF ]) ^ + ((uint32_t) FSb[(RK[7] >> 16) & 0xFF ] << 8) ^ + ((uint32_t) FSb[(RK[7] >> 24) & 0xFF ] << 16) ^ + ((uint32_t) FSb[(RK[7]) & 0xFF ] << 24); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ((uint32_t) FSb[(RK[11]) & 0xFF ]) ^ + ((uint32_t) FSb[(RK[11] >> 8) & 0xFF ] << 8) ^ + ((uint32_t) FSb[(RK[11] >> 16) & 0xFF ] << 16) ^ + ((uint32_t) FSb[(RK[11] >> 24) & 0xFF ] << 24); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + } + + return (0); +} +#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ + +/* + * AES key schedule (decryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) +int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits) +{ + int i, j, ret; + mbedtls_aes_context cty; + uint32_t *RK; + uint32_t *SK; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(key != NULL); + + mbedtls_aes_init(&cty); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if (aes_padlock_ace == -1) { + aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE); + } + + if (aes_padlock_ace) { + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16(ctx->buf); + } else +#endif + ctx->rk = RK = ctx->buf; + + /* Also checks keybits */ + if ((ret = mbedtls_aes_setkey_enc(&cty, key, keybits)) != 0) { + goto exit; + } + + ctx->nr = cty.nr; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { + mbedtls_aesni_inverse_key((unsigned char *) ctx->rk, + (const unsigned char *) cty.rk, ctx->nr); + goto exit; + } +#endif + + SK = cty.rk + cty.nr * 4; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for (i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8) { + for (j = 0; j < 4; j++, SK++) { + *RK++ = AES_RT0(FSb[(*SK) & 0xFF ]) ^ + AES_RT1(FSb[(*SK >> 8) & 0xFF ]) ^ + AES_RT2(FSb[(*SK >> 16) & 0xFF ]) ^ + AES_RT3(FSb[(*SK >> 24) & 0xFF ]); + } + } + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_aes_free(&cty); + + return (ret); +} + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int mbedtls_aes_xts_decode_keys(const unsigned char *key, + unsigned int keybits, + const unsigned char **key1, + unsigned int *key1bits, + const unsigned char **key2, + unsigned int *key2bits) +{ + const unsigned int half_keybits = keybits / 2; + const unsigned int half_keybytes = half_keybits / 8; + + switch (keybits) { + case 256: + break; + case 512: + break; + default : + return (MBEDTLS_ERR_AES_INVALID_KEY_LENGTH); + } + + *key1bits = half_keybits; + *key2bits = half_keybits; + *key1 = &key[0]; + *key2 = &key[half_keybytes]; + + return 0; +} + +int mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(key != NULL); + + ret = mbedtls_aes_xts_decode_keys(key, keybits, &key1, &key1bits, + &key2, &key2bits); + if (ret != 0) { + return (ret); + } + + /* Set the tweak key. Always set tweak key for the encryption mode. */ + ret = mbedtls_aes_setkey_enc(&ctx->tweak, key2, key2bits); + if (ret != 0) { + return (ret); + } + + /* Set crypt key for encryption. */ + return mbedtls_aes_setkey_enc(&ctx->crypt, key1, key1bits); +} + +int mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(key != NULL); + + ret = mbedtls_aes_xts_decode_keys(key, keybits, &key1, &key1bits, + &key2, &key2bits); + if (ret != 0) { + return (ret); + } + + /* Set the tweak key. Always set tweak key for encryption. */ + ret = mbedtls_aes_setkey_enc(&ctx->tweak, key2, key2bits); + if (ret != 0) { + return (ret); + } + + /* Set crypt key for decryption. */ + return mbedtls_aes_setkey_dec(&ctx->crypt, key1, key1bits); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ AES_FT0( ( Y0 ) & 0xFF ) ^ \ + AES_FT1( ( Y1 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y2 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y3 >> 24 ) & 0xFF ); \ + \ + X1 = *RK++ ^ AES_FT0( ( Y1 ) & 0xFF ) ^ \ + AES_FT1( ( Y2 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y3 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y0 >> 24 ) & 0xFF ); \ + \ + X2 = *RK++ ^ AES_FT0( ( Y2 ) & 0xFF ) ^ \ + AES_FT1( ( Y3 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y0 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y1 >> 24 ) & 0xFF ); \ + \ + X3 = *RK++ ^ AES_FT0( ( Y3 ) & 0xFF ) ^ \ + AES_FT1( ( Y0 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y1 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y2 >> 24 ) & 0xFF ); \ +} + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ AES_RT0( ( Y0 ) & 0xFF ) ^ \ + AES_RT1( ( Y3 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y2 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y1 >> 24 ) & 0xFF ); \ + \ + X1 = *RK++ ^ AES_RT0( ( Y1 ) & 0xFF ) ^ \ + AES_RT1( ( Y0 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y3 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y2 >> 24 ) & 0xFF ); \ + \ + X2 = *RK++ ^ AES_RT0( ( Y2 ) & 0xFF ) ^ \ + AES_RT1( ( Y1 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y0 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y3 >> 24 ) & 0xFF ); \ + \ + X3 = *RK++ ^ AES_RT0( ( Y3 ) & 0xFF ) ^ \ + AES_RT1( ( Y2 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y1 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y0 >> 24 ) & 0xFF ); \ +} + +/* + * AES-ECB block encryption + */ +#if !defined(MBEDTLS_AES_ENCRYPT_ALT) +int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) +{ + int i; + uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->rk; + + GET_UINT32_LE(X0, input, 0); + X0 ^= *RK++; + GET_UINT32_LE(X1, input, 4); + X1 ^= *RK++; + GET_UINT32_LE(X2, input, 8); + X2 ^= *RK++; + GET_UINT32_LE(X3, input, 12); + X3 ^= *RK++; + + for (i = (ctx->nr >> 1) - 1; i > 0; i--) { + AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); + AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); + } + + AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); + + X0 = *RK++ ^ \ + ((uint32_t) FSb[(Y0) & 0xFF ]) ^ + ((uint32_t) FSb[(Y1 >> 8) & 0xFF ] << 8) ^ + ((uint32_t) FSb[(Y2 >> 16) & 0xFF ] << 16) ^ + ((uint32_t) FSb[(Y3 >> 24) & 0xFF ] << 24); + + X1 = *RK++ ^ \ + ((uint32_t) FSb[(Y1) & 0xFF ]) ^ + ((uint32_t) FSb[(Y2 >> 8) & 0xFF ] << 8) ^ + ((uint32_t) FSb[(Y3 >> 16) & 0xFF ] << 16) ^ + ((uint32_t) FSb[(Y0 >> 24) & 0xFF ] << 24); + + X2 = *RK++ ^ \ + ((uint32_t) FSb[(Y2) & 0xFF ]) ^ + ((uint32_t) FSb[(Y3 >> 8) & 0xFF ] << 8) ^ + ((uint32_t) FSb[(Y0 >> 16) & 0xFF ] << 16) ^ + ((uint32_t) FSb[(Y1 >> 24) & 0xFF ] << 24); + + X3 = *RK++ ^ \ + ((uint32_t) FSb[(Y3) & 0xFF ]) ^ + ((uint32_t) FSb[(Y0 >> 8) & 0xFF ] << 8) ^ + ((uint32_t) FSb[(Y1 >> 16) & 0xFF ] << 16) ^ + ((uint32_t) FSb[(Y2 >> 24) & 0xFF ] << 24); + + PUT_UINT32_LE(X0, output, 0); + PUT_UINT32_LE(X1, output, 4); + PUT_UINT32_LE(X2, output, 8); + PUT_UINT32_LE(X3, output, 12); + + return (0); +} +#endif /* !MBEDTLS_AES_ENCRYPT_ALT */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_encrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) +{ + mbedtls_internal_aes_encrypt(ctx, input, output); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block decryption + */ +#if !defined(MBEDTLS_AES_DECRYPT_ALT) +int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) +{ + int i; + uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->rk; + + GET_UINT32_LE(X0, input, 0); + X0 ^= *RK++; + GET_UINT32_LE(X1, input, 4); + X1 ^= *RK++; + GET_UINT32_LE(X2, input, 8); + X2 ^= *RK++; + GET_UINT32_LE(X3, input, 12); + X3 ^= *RK++; + + for (i = (ctx->nr >> 1) - 1; i > 0; i--) { + AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); + AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); + } + + AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); + + X0 = *RK++ ^ \ + ((uint32_t) RSb[(Y0) & 0xFF ]) ^ + ((uint32_t) RSb[(Y3 >> 8) & 0xFF ] << 8) ^ + ((uint32_t) RSb[(Y2 >> 16) & 0xFF ] << 16) ^ + ((uint32_t) RSb[(Y1 >> 24) & 0xFF ] << 24); + + X1 = *RK++ ^ \ + ((uint32_t) RSb[(Y1) & 0xFF ]) ^ + ((uint32_t) RSb[(Y0 >> 8) & 0xFF ] << 8) ^ + ((uint32_t) RSb[(Y3 >> 16) & 0xFF ] << 16) ^ + ((uint32_t) RSb[(Y2 >> 24) & 0xFF ] << 24); + + X2 = *RK++ ^ \ + ((uint32_t) RSb[(Y2) & 0xFF ]) ^ + ((uint32_t) RSb[(Y1 >> 8) & 0xFF ] << 8) ^ + ((uint32_t) RSb[(Y0 >> 16) & 0xFF ] << 16) ^ + ((uint32_t) RSb[(Y3 >> 24) & 0xFF ] << 24); + + X3 = *RK++ ^ \ + ((uint32_t) RSb[(Y3) & 0xFF ]) ^ + ((uint32_t) RSb[(Y2 >> 8) & 0xFF ] << 8) ^ + ((uint32_t) RSb[(Y1 >> 16) & 0xFF ] << 16) ^ + ((uint32_t) RSb[(Y0 >> 24) & 0xFF ] << 24); + + PUT_UINT32_LE(X0, output, 0); + PUT_UINT32_LE(X1, output, 4); + PUT_UINT32_LE(X2, output, 8); + PUT_UINT32_LE(X3, output, 12); + + return (0); +} +#endif /* !MBEDTLS_AES_DECRYPT_ALT */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_decrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) +{ + mbedtls_internal_aes_decrypt(ctx, input, output); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block encryption/decryption + */ +int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16]) +{ + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT); + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { + return (mbedtls_aesni_crypt_ecb(ctx, mode, input, output)); + } +#endif + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if (aes_padlock_ace) { + if (mbedtls_padlock_xcryptecb(ctx, mode, input, output) == 0) { + return (0); + } + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if (mode == MBEDTLS_AES_ENCRYPT) { + return (mbedtls_internal_aes_encrypt(ctx, input, output)); + } else { + return (mbedtls_internal_aes_decrypt(ctx, input, output)); + } +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * AES-CBC buffer encryption/decryption + */ +int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output) +{ + int i; + unsigned char temp[16]; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT); + AES_VALIDATE_RET(iv != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + + if (length % 16) { + return (MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH); + } + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if (aes_padlock_ace) { + if (mbedtls_padlock_xcryptcbc(ctx, mode, length, iv, input, output) == 0) { + return (0); + } + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if (mode == MBEDTLS_AES_DECRYPT) { + while (length > 0) { + memcpy(temp, input, 16); + mbedtls_aes_crypt_ecb(ctx, mode, input, output); + + for (i = 0; i < 16; i++) { + output[i] = (unsigned char)(output[i] ^ iv[i]); + } + + memcpy(iv, temp, 16); + + input += 16; + output += 16; + length -= 16; + } + } else { + while (length > 0) { + for (i = 0; i < 16; i++) { + output[i] = (unsigned char)(input[i] ^ iv[i]); + } + + mbedtls_aes_crypt_ecb(ctx, mode, output, output); + memcpy(iv, output, 16); + + input += 16; + output += 16; + length -= 16; + } + } + + return (0); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + +/* Endianess with 64 bits values */ +#ifndef GET_UINT64_LE +#define GET_UINT64_LE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \ + | ( (uint64_t) (b)[(i) + 6] << 48 ) \ + | ( (uint64_t) (b)[(i) + 5] << 40 ) \ + | ( (uint64_t) (b)[(i) + 4] << 32 ) \ + | ( (uint64_t) (b)[(i) + 3] << 24 ) \ + | ( (uint64_t) (b)[(i) + 2] << 16 ) \ + | ( (uint64_t) (b)[(i) + 1] << 8 ) \ + | ( (uint64_t) (b)[(i) ] ); \ +} +#endif + +#ifndef PUT_UINT64_LE +#define PUT_UINT64_LE(n,b,i) \ +{ \ + (b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) ] = (unsigned char) ( (n) ); \ +} +#endif + +typedef unsigned char mbedtls_be128[16]; + +/* + * GF(2^128) multiplication function + * + * This function multiplies a field element by x in the polynomial field + * representation. It uses 64-bit word operations to gain speed but compensates + * for machine endianess and hence works correctly on both big and little + * endian machines. + */ +static void mbedtls_gf128mul_x_ble(unsigned char r[16], + const unsigned char x[16]) +{ + uint64_t a, b, ra, rb; + + GET_UINT64_LE(a, x, 0); + GET_UINT64_LE(b, x, 8); + + ra = (a << 1) ^ 0x0087 >> (8 - ((b >> 63) << 3)); + rb = (a >> 63) | (b << 1); + + PUT_UINT64_LE(ra, r, 0); + PUT_UINT64_LE(rb, r, 8); +} + +/* + * AES-XTS buffer encryption/decryption + */ +int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output) +{ + int ret; + size_t blocks = length / 16; + size_t leftover = length % 16; + unsigned char tweak[16]; + unsigned char prev_tweak[16]; + unsigned char tmp[16]; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT); + AES_VALIDATE_RET(data_unit != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + + /* Data units must be at least 16 bytes long. */ + if (length < 16) { + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + } + + /* NIST SP 800-38E disallows data units larger than 2**20 blocks. */ + if (length > (1 << 20) * 16) { + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + } + + /* Compute the tweak. */ + ret = mbedtls_aes_crypt_ecb(&ctx->tweak, MBEDTLS_AES_ENCRYPT, + data_unit, tweak); + if (ret != 0) { + return (ret); + } + + while (blocks--) { + size_t i; + + if (leftover && (mode == MBEDTLS_AES_DECRYPT) && blocks == 0) { + /* We are on the last block in a decrypt operation that has + * leftover bytes, so we need to use the next tweak for this block, + * and this tweak for the lefover bytes. Save the current tweak for + * the leftovers and then update the current tweak for use on this, + * the last full block. */ + memcpy(prev_tweak, tweak, sizeof(tweak)); + mbedtls_gf128mul_x_ble(tweak, tweak); + } + + for (i = 0; i < 16; i++) { + tmp[i] = input[i] ^ tweak[i]; + } + + ret = mbedtls_aes_crypt_ecb(&ctx->crypt, mode, tmp, tmp); + if (ret != 0) { + return (ret); + } + + for (i = 0; i < 16; i++) { + output[i] = tmp[i] ^ tweak[i]; + } + + /* Update the tweak for the next block. */ + mbedtls_gf128mul_x_ble(tweak, tweak); + + output += 16; + input += 16; + } + + if (leftover) { + /* If we are on the leftover bytes in a decrypt operation, we need to + * use the previous tweak for these bytes (as saved in prev_tweak). */ + unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak; + + /* We are now on the final part of the data unit, which doesn't divide + * evenly by 16. It's time for ciphertext stealing. */ + size_t i; + unsigned char *prev_output = output - 16; + + /* Copy ciphertext bytes from the previous block to our output for each + * byte of cyphertext we won't steal. At the same time, copy the + * remainder of the input for this final round (since the loop bounds + * are the same). */ + for (i = 0; i < leftover; i++) { + output[i] = prev_output[i]; + tmp[i] = input[i] ^ t[i]; + } + + /* Copy ciphertext bytes from the previous block for input in this + * round. */ + for (; i < 16; i++) { + tmp[i] = prev_output[i] ^ t[i]; + } + + ret = mbedtls_aes_crypt_ecb(&ctx->crypt, mode, tmp, tmp); + if (ret != 0) { + return ret; + } + + /* Write the result back to the previous block, overriding the previous + * output we copied. */ + for (i = 0; i < 16; i++) { + prev_output[i] = tmp[i] ^ t[i]; + } + } + + return (0); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb128(mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output) +{ + int c; + size_t n; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT); + AES_VALIDATE_RET(iv_off != NULL); + AES_VALIDATE_RET(iv != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + + n = *iv_off; + + if (n > 15) { + return (MBEDTLS_ERR_AES_BAD_INPUT_DATA); + } + + if (mode == MBEDTLS_AES_DECRYPT) { + while (length--) { + if (n == 0) { + mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); + } + + c = *input++; + *output++ = (unsigned char)(c ^ iv[n]); + iv[n] = (unsigned char) c; + + n = (n + 1) & 0x0F; + } + } else { + while (length--) { + if (n == 0) { + mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); + } + + iv[n] = *output++ = (unsigned char)(iv[n] ^ *input++); + + n = (n + 1) & 0x0F; + } + } + + *iv_off = n; + + return (0); +} + +/* + * AES-CFB8 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb8(mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output) +{ + unsigned char c; + unsigned char ov[17]; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT); + AES_VALIDATE_RET(iv != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + while (length--) { + memcpy(ov, iv, 16); + mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); + + if (mode == MBEDTLS_AES_DECRYPT) { + ov[16] = *input; + } + + c = *output++ = (unsigned char)(iv[0] ^ *input++); + + if (mode == MBEDTLS_AES_ENCRYPT) { + ov[16] = c; + } + + memcpy(iv, ov + 1, 16); + } + + return (0); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB (Output Feedback Mode) buffer encryption/decryption + */ +int mbedtls_aes_crypt_ofb(mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output) +{ + int ret = 0; + size_t n; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(iv_off != NULL); + AES_VALIDATE_RET(iv != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + + n = *iv_off; + + if (n > 15) { + return (MBEDTLS_ERR_AES_BAD_INPUT_DATA); + } + + while (length--) { + if (n == 0) { + ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); + if (ret != 0) { + goto exit; + } + } + *output++ = *input++ ^ iv[n]; + + n = (n + 1) & 0x0F; + } + + *iv_off = n; + +exit: + return (ret); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR buffer encryption/decryption + */ +int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output) +{ + int c, i; + size_t n; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(nc_off != NULL); + AES_VALIDATE_RET(nonce_counter != NULL); + AES_VALIDATE_RET(stream_block != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + + n = *nc_off; + + if (n > 0x0F) { + return (MBEDTLS_ERR_AES_BAD_INPUT_DATA); + } + + while (length--) { + if (n == 0) { + mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block); + + for (i = 16; i > 0; i--) + if (++nonce_counter[i - 1] != 0) { + break; + } + } + c = *input++; + *output++ = (unsigned char)(c ^ stream_block[n]); + + n = (n + 1) & 0x0F; + } + + *nc_off = n; + + return (0); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#endif /* !MBEDTLS_AES_ALT */ + +#if (MBEDTLS_AES_SELF_TEST==1) +/* + * AES test vectors from: + * + * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip + */ +static const unsigned char aes_test_ecb_dec[3][16] = { + { + 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, + 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 + }, + { + 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, + 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 + }, + { + 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, + 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE + } +}; + +static const unsigned char aes_test_ecb_enc[3][16] = { + { + 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, + 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F + }, + { + 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, + 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 + }, + { + 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, + 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 + } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char aes_test_cbc_dec[3][16] = { + { + 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, + 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 + }, + { + 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, + 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B + }, + { + 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, + 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 + } +}; + +static const unsigned char aes_test_cbc_enc[3][16] = { + { + 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, + 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D + }, + { + 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, + 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 + }, + { + 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, + 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 + } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 test vectors from: + * + * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + */ +static const unsigned char aes_test_cfb128_key[3][32] = { + { + 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C + }, + { + 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B + }, + { + 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 + } +}; + +static const unsigned char aes_test_cfb128_iv[16] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_cfb128_pt[64] = { + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 +}; + +static const unsigned char aes_test_cfb128_ct[3][64] = { + { + 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, + 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, + 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, + 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, + 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, + 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 + }, + { + 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, + 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, + 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, + 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, + 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, + 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF + }, + { + 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, + 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, + 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, + 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, + 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, + 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 + } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB test vectors from: + * + * https://csrc.nist.gov/publications/detail/sp/800-38a/final + */ +static const unsigned char aes_test_ofb_key[3][32] = { + { + 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C + }, + { + 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B + }, + { + 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 + } +}; + +static const unsigned char aes_test_ofb_iv[16] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_ofb_pt[64] = { + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 +}; + +static const unsigned char aes_test_ofb_ct[3][64] = { + { + 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, + 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25, + 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, + 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc, + 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, + 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e + }, + { + 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, + 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01, + 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, + 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2, + 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, + 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a + }, + { + 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, + 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d, + 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, + 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08, + 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, + 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 + } +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc3686.html + */ + +static const unsigned char aes_test_ctr_key[3][16] = { + { + 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E + }, + { + 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 + }, + { + 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC + } +}; + +static const unsigned char aes_test_ctr_nonce_counter[3][16] = { + { + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 + }, + { + 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 + }, + { + 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 + } +}; + +static const unsigned char aes_test_ctr_pt[3][48] = { + { + 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 + }, + + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F + }, + + { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23 + } +}; + +static const unsigned char aes_test_ctr_ct[3][48] = { + { + 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, + 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 + }, + { + 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, + 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, + 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, + 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 + }, + { + 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, + 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, + 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, + 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, + 0x25, 0xB2, 0x07, 0x2F + } +}; + +static const int aes_test_ctr_len[3] = +{ 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/* + * AES-XTS test vectors from: + * + * IEEE P1619/D16 Annex B + * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf + * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf) + */ +static const unsigned char aes_test_xts_key[][32] = { + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 + }, + { + 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 + }, +}; + +static const unsigned char aes_test_xts_pt32[][32] = { + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 + }, + { + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 + }, +}; + +static const unsigned char aes_test_xts_ct32[][32] = { + { + 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec, + 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92, + 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85, + 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e + }, + { + 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e, + 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b, + 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4, + 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 + }, + { + 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, + 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, + 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, + 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 + }, +}; + +static const unsigned char aes_test_xts_data_unit[][16] = { + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, + { + 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }, +}; + +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/* + * Checkup routine + */ +int mbedtls_aes_self_test(int verbose) +{ + int ret = 0, i, j, u, mode; + unsigned int keybits; + unsigned char key[32]; + unsigned char buf[64]; + const unsigned char *aes_tests; +#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) + unsigned char iv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char prv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_OFB) + size_t offset; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS) + int len; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + mbedtls_aes_context ctx; + + memset(key, 0, 32); + mbedtls_aes_init(&ctx); + + /* + * ECB mode + */ + for (i = 0; i < 6; i++) { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if (verbose != 0) + mbedtls_printf(" AES-ECB-%3d (%s): ", keybits, + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + + memset(buf, 0, 16); + + if (mode == MBEDTLS_AES_DECRYPT) { + ret = mbedtls_aes_setkey_dec(&ctx, key, keybits); + aes_tests = aes_test_ecb_dec[u]; + } else { + ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); + aes_tests = aes_test_ecb_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { + mbedtls_printf("skipped\n"); + continue; + } else if (ret != 0) { + goto exit; + } + + for (j = 0; j < 10000; j++) { + ret = mbedtls_aes_crypt_ecb(&ctx, mode, buf, buf); + if (ret != 0) { + goto exit; + } + } + + if (memcmp(buf, aes_tests, 16) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) { + mbedtls_printf("passed\n"); + } + } + + if (verbose != 0) { + mbedtls_printf("\n"); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for (i = 0; i < 6; i++) { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if (verbose != 0) + mbedtls_printf(" AES-CBC-%3d (%s): ", keybits, + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + + memset(iv, 0, 16); + memset(prv, 0, 16); + memset(buf, 0, 16); + + if (mode == MBEDTLS_AES_DECRYPT) { + ret = mbedtls_aes_setkey_dec(&ctx, key, keybits); + aes_tests = aes_test_cbc_dec[u]; + } else { + ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); + aes_tests = aes_test_cbc_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { + mbedtls_printf("skipped\n"); + continue; + } else if (ret != 0) { + goto exit; + } + + for (j = 0; j < 10000; j++) { + if (mode == MBEDTLS_AES_ENCRYPT) { + unsigned char tmp[16]; + + memcpy(tmp, prv, 16); + memcpy(prv, buf, 16); + memcpy(buf, tmp, 16); + } + + ret = mbedtls_aes_crypt_cbc(&ctx, mode, 16, iv, buf, buf); + if (ret != 0) { + goto exit; + } + + } + + if (memcmp(buf, aes_tests, 16) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) { + mbedtls_printf("passed\n"); + } + } + + if (verbose != 0) { + mbedtls_printf("\n"); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /* + * CFB128 mode + */ + for (i = 0; i < 6; i++) { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if (verbose != 0) + mbedtls_printf(" AES-CFB128-%3d (%s): ", keybits, + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + + memcpy(iv, aes_test_cfb128_iv, 16); + memcpy(key, aes_test_cfb128_key[u], keybits / 8); + + offset = 0; + ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { + mbedtls_printf("skipped\n"); + continue; + } else if (ret != 0) { + goto exit; + } + + if (mode == MBEDTLS_AES_DECRYPT) { + memcpy(buf, aes_test_cfb128_ct[u], 64); + aes_tests = aes_test_cfb128_pt; + } else { + memcpy(buf, aes_test_cfb128_pt, 64); + aes_tests = aes_test_cfb128_ct[u]; + } + + ret = mbedtls_aes_crypt_cfb128(&ctx, mode, 64, &offset, iv, buf, buf); + if (ret != 0) { + goto exit; + } + + if (memcmp(buf, aes_tests, 64) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) { + mbedtls_printf("passed\n"); + } + } + + if (verbose != 0) { + mbedtls_printf("\n"); + } +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /* + * OFB mode + */ + for (i = 0; i < 6; i++) { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if (verbose != 0) + mbedtls_printf(" AES-OFB-%3d (%s): ", keybits, + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + + memcpy(iv, aes_test_ofb_iv, 16); + memcpy(key, aes_test_ofb_key[u], keybits / 8); + + offset = 0; + ret = mbedtls_aes_setkey_enc(&ctx, key, keybits); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if (ret == MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED && keybits == 192) { + mbedtls_printf("skipped\n"); + continue; + } else if (ret != 0) { + goto exit; + } + + if (mode == MBEDTLS_AES_DECRYPT) { + memcpy(buf, aes_test_ofb_ct[u], 64); + aes_tests = aes_test_ofb_pt; + } else { + memcpy(buf, aes_test_ofb_pt, 64); + aes_tests = aes_test_ofb_ct[u]; + } + + ret = mbedtls_aes_crypt_ofb(&ctx, 64, &offset, iv, buf, buf); + if (ret != 0) { + goto exit; + } + + if (memcmp(buf, aes_tests, 64) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) { + mbedtls_printf("passed\n"); + } + } + + if (verbose != 0) { + mbedtls_printf("\n"); + } +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for (i = 0; i < 6; i++) { + u = i >> 1; + mode = i & 1; + + if (verbose != 0) + mbedtls_printf(" AES-CTR-128 (%s): ", + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + + memcpy(nonce_counter, aes_test_ctr_nonce_counter[u], 16); + memcpy(key, aes_test_ctr_key[u], 16); + + offset = 0; + if ((ret = mbedtls_aes_setkey_enc(&ctx, key, 128)) != 0) { + goto exit; + } + + len = aes_test_ctr_len[u]; + + if (mode == MBEDTLS_AES_DECRYPT) { + memcpy(buf, aes_test_ctr_ct[u], len); + aes_tests = aes_test_ctr_pt[u]; + } else { + memcpy(buf, aes_test_ctr_pt[u], len); + aes_tests = aes_test_ctr_ct[u]; + } + + ret = mbedtls_aes_crypt_ctr(&ctx, len, &offset, nonce_counter, + stream_block, buf, buf); + if (ret != 0) { + goto exit; + } + + if (memcmp(buf, aes_tests, len) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) { + mbedtls_printf("passed\n"); + } + } + + if (verbose != 0) { + mbedtls_printf("\n"); + } +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { + static const int num_tests = + sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key); + mbedtls_aes_xts_context ctx_xts; + + /* + * XTS mode + */ + mbedtls_aes_xts_init(&ctx_xts); + + for (i = 0; i < num_tests << 1; i++) { + const unsigned char *data_unit; + u = i >> 1; + mode = i & 1; + + if (verbose != 0) + mbedtls_printf(" AES-XTS-128 (%s): ", + (mode == MBEDTLS_AES_DECRYPT) ? "dec" : "enc"); + + memset(key, 0, sizeof(key)); + memcpy(key, aes_test_xts_key[u], 32); + data_unit = aes_test_xts_data_unit[u]; + + len = sizeof(*aes_test_xts_ct32); + + if (mode == MBEDTLS_AES_DECRYPT) { + ret = mbedtls_aes_xts_setkey_dec(&ctx_xts, key, 256); + if (ret != 0) { + goto exit; + } + memcpy(buf, aes_test_xts_ct32[u], len); + aes_tests = aes_test_xts_pt32[u]; + } else { + ret = mbedtls_aes_xts_setkey_enc(&ctx_xts, key, 256); + if (ret != 0) { + goto exit; + } + memcpy(buf, aes_test_xts_pt32[u], len); + aes_tests = aes_test_xts_ct32[u]; + } + + + ret = mbedtls_aes_crypt_xts(&ctx_xts, mode, len, data_unit, + buf, buf); + if (ret != 0) { + goto exit; + } + + if (memcmp(buf, aes_tests, len) != 0) { + ret = 1; + goto exit; + } + + if (verbose != 0) { + mbedtls_printf("passed\n"); + } + } + + if (verbose != 0) { + mbedtls_printf("\n"); + } + + mbedtls_aes_xts_free(&ctx_xts); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + + ret = 0; + +exit: + if (ret != 0 && verbose != 0) { + mbedtls_printf("failed\n"); + } + + mbedtls_aes_free(&ctx); + + return (ret); +} + +#endif /* MBEDTLS_AES_SELF_TEST */ + +#endif /* MBEDTLS_AES_C */ diff --git a/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/aes.h b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/aes.h new file mode 100644 index 0000000..50d6d35 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/aes.h @@ -0,0 +1,678 @@ +/** + * \file aes.h + * + * \brief This file contains AES definitions and functions. + * + * The Advanced Encryption Standard (AES) specifies a FIPS-approved + * cryptographic algorithm that can be used to protect electronic + * data. + * + * The AES algorithm is a symmetric block cipher that can + * encrypt and decrypt information. For more information, see + * FIPS Publication 197: Advanced Encryption Standard and + * ISO/IEC 18033-2:2006: Information technology -- Security + * techniques -- Encryption algorithms -- Part 2: Asymmetric + * ciphers. + * + * The AES-XTS block mode is standardized by NIST SP 800-38E + * + * and described in detail by IEEE P1619 + * . + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_AES_H +#define MBEDTLS_AES_H + +#define MBEDTLS_AES_ROM_TABLES +//#define MBEDTLS_AES_FEWER_TABLES +#define MBEDTLS_CIPHER_MODE_CBC +//#define MBEDTLS_CIPHER_MODE_CFB +//#define MBEDTLS_PKCS1_V15 +//#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED +//#define MBEDTLS_SSL_PROTO_TLS1_1 + +/* mbed TLS modules */ +#define MBEDTLS_AES_C + + +#include +#include + +/* padlock.c and aesni.c rely on these values! */ +#define MBEDTLS_AES_ENCRYPT 1 /**< AES encryption. */ +#define MBEDTLS_AES_DECRYPT 0 /**< AES decryption. */ + +/* Error codes in range 0x0020-0x0022 */ +#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +/* Error codes in range 0x0021-0x0025 */ +#define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */ + +/* MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE is deprecated and should not be used. */ +#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */ + +/* MBEDTLS_ERR_AES_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_AES_ALT) +// Regular implementation +// + +/** + * \brief The AES context-type definition. + */ +typedef struct mbedtls_aes_context { + int nr; /*!< The number of rounds. */ + uint32_t *rk; /*!< AES round keys. */ + uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can + hold 32 extra Bytes, which can be used for + one of the following purposes: +
  • Alignment if VIA padlock is + used.
  • +
  • Simplifying key expansion in the 256-bit + case by generating an extra round key. +
*/ +} +mbedtls_aes_context; + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief The AES XTS context-type definition. + */ +typedef struct mbedtls_aes_xts_context { + mbedtls_aes_context crypt; /*!< The AES context to use for AES block + encryption or decryption. */ + mbedtls_aes_context tweak; /*!< The AES context used for tweak + computation. */ +} mbedtls_aes_xts_context; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#else /* MBEDTLS_AES_ALT */ +#include "aes_alt.h" +#endif /* MBEDTLS_AES_ALT */ + +/** + * \brief This function initializes the specified AES context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES context to initialize. This must not be \c NULL. + */ +void mbedtls_aes_init(mbedtls_aes_context *ctx); + +/** + * \brief This function releases and clears the specified AES context. + * + * \param ctx The AES context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. + */ +void mbedtls_aes_free(mbedtls_aes_context *ctx); + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function initializes the specified AES XTS context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES XTS context to initialize. This must not be \c NULL. + */ +void mbedtls_aes_xts_init(mbedtls_aes_xts_context *ctx); + +/** + * \brief This function releases and clears the specified AES XTS context. + * + * \param ctx The AES XTS context to clear. + * If this is \c NULL, this function does nothing. + * Otherwise, the context must have been at least initialized. + */ +void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function sets the encryption key. + * + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The encryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The AES context to which the key should be bound. + * It must be initialized. + * \param key The decryption key. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits); + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function prepares an XTS context for encryption and + * sets the encryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. + * \param key The encryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits); + +/** + * \brief This function prepares an XTS context for decryption and + * sets the decryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * It must be initialized. + * \param key The decryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * This must be a readable buffer of size \p keybits bits. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function performs an AES single-block encryption or + * decryption operation. + * + * It performs the operation defined in the \p mode parameter + * (encrypt or decrypt), on the input data buffer defined in + * the \p input parameter. + * + * mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or + * mbedtls_aes_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param input The buffer holding the input data. + * It must be readable and at least \c 16 Bytes long. + * \param output The buffer where the output data will be written. + * It must be writeable and at least \c 16 Bytes long. + + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ecb(mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16]); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an AES-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aes_init(), and either + * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on full blocks, that is, the input size + * must be a multiple of the AES block size of \c 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (\c 16 Bytes). + * \param iv Initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH + * on failure. + */ +int mbedtls_aes_crypt_cbc(mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function performs an AES-XTS encryption or decryption + * operation for an entire XTS data unit. + * + * AES-XTS encrypts or decrypts blocks based on their location as + * defined by a data unit number. The data unit number must be + * provided by \p data_unit. + * + * NIST SP 800-38E limits the maximum size of a data unit to 2^20 + * AES blocks. If the data unit is larger than this, this function + * returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH. + * + * \param ctx The AES XTS context to use for AES XTS operations. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of a data unit in Bytes. This can be any + * length between 16 bytes and 2^24 bytes inclusive + * (between 1 and 2^20 block cipher blocks). + * \param data_unit The address of the data unit encoded as an array of 16 + * bytes in little-endian format. For disk encryption, this + * is typically the index of the block device sector that + * contains the data. + * \param input The buffer holding the input data (which is an entire + * data unit). This function reads \p length Bytes from \p + * input. + * \param output The buffer holding the output data (which is an entire + * data unit). This function writes \p length Bytes to \p + * output. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is + * smaller than an AES block in size (16 Bytes) or if \p + * length is larger than 2^20 blocks (16 MiB). + */ +int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an AES-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aes_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_cfb128(mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output); + +/** + * \brief This function performs an AES-CFB8 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined + * in the \p input parameter. + * + * Due to the nature of CFB, you must use the same key schedule for + * both encryption and decryption operations. Therefore, you must + * use the context initialized with mbedtls_aes_setkey_enc() for + * both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT + * \param length The length of the input data. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_cfb8(mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/** + * \brief This function performs an AES-OFB (Output Feedback Mode) + * encryption or decryption operation. + * + * For OFB, you must set up the context with + * mbedtls_aes_setkey_enc(), regardless of whether you are + * performing an encryption or decryption operation. This is + * because OFB mode uses the same key schedule for encryption and + * decryption. + * + * The OFB operation is identical for encryption or decryption, + * therefore no operation mode needs to be specified. + * + * \note Upon exit, the content of iv, the Initialisation Vector, is + * updated so that you can call the same function again on the next + * block(s) of data and get the same result as if it was encrypted + * in one call. This allows a "streaming" usage, by initialising + * iv_off to 0 before the first call, and preserving its value + * between calls. + * + * For non-streaming use, the iv should be initialised on each call + * to a unique value, and iv_off set to 0 on each call. + * + * If you need to retain the contents of the initialisation vector, + * you must either save it manually or use the cipher module + * instead. + * + * \warning For the OFB mode, the initialisation vector must be unique + * every encryption operation. Reuse of an initialisation vector + * will compromise security. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ofb(mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output); + +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an AES-CTR encryption or decryption + * operation. + * + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aes_setkey_enc() + * for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that an AES block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param nc_off The offset in the current \p stream_block, for + * resuming within the current cipher stream. The + * offset pointer should be 0 at the start of a stream. + * It must point to a valid \c size_t. + * \param nonce_counter The 128-bit nonce and counter. + * It must be a readable-writeable buffer of \c 16 Bytes. + * \param stream_block The saved stream block for resuming. This is + * overwritten by the function. + * It must be a readable-writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ctr(mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/** + * \brief Internal AES block encryption function. This is only + * exposed to allow overriding it using + * \c MBEDTLS_AES_ENCRYPT_ALT. + * + * \param ctx The AES context to use for encryption. + * \param input The plaintext block. + * \param output The output (ciphertext) block. + * + * \return \c 0 on success. + */ +int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]); + +/** + * \brief Internal AES block decryption function. This is only + * exposed to allow overriding it using see + * \c MBEDTLS_AES_DECRYPT_ALT. + * + * \param ctx The AES context to use for decryption. + * \param input The ciphertext block. + * \param output The output (plaintext) block. + * + * \return \c 0 on success. + */ +int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Deprecated internal AES block encryption function + * without return value. + * + * \deprecated Superseded by mbedtls_internal_aes_encrypt() + * + * \param ctx The AES context to use for encryption. + * \param input Plaintext block. + * \param output Output (ciphertext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_encrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]); + +/** + * \brief Deprecated internal AES block decryption function + * without return value. + * + * \deprecated Superseded by mbedtls_internal_aes_decrypt() + * + * \param ctx The AES context to use for decryption. + * \param input Ciphertext block. + * \param output Output (plaintext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_decrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + + +#if (MBEDTLS_SELF_TEST==1) +/** + * \brief Checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_aes_self_test(int verbose); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ diff --git a/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/ccm.c b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/ccm.c new file mode 100644 index 0000000..8e3220b --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/ccm.c @@ -0,0 +1,391 @@ +/* + * NIST SP800-38C compliant CCM implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + */ + + +#include +#include "aes.h" +#include "ccm.h" +#include "cpu.h" + +#define CCM_ENCRYPT 0 +#define CCM_DECRYPT 1 + + +static bool aes128_ecb_encrypt(const uint8_t *key, uint8_t *input, uint16_t input_len, uint8_t *output) +{ + uint16_t length; + mbedtls_aes_context aes_ctx; + // + if (input_len % 16) { + return false; + } + + length = input_len; + + mbedtls_aes_init(&aes_ctx); + + mbedtls_aes_setkey_enc(&aes_ctx, key, 128); + + while (length > 0) { + mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, input, output); + input += 16; + output += 16; + length -= 16; + } + + mbedtls_aes_free(&aes_ctx); + + return true; +} + +static int aes_ecb_encrypt(const uint8_t *pKey, uint8_t *input, uint8_t *output) +{ + // return (int)aes128_ecb_encrypt(pKey, input, 16, output); + // AES128_ECB_encrypt(input,pKey, output); + // return 0; + // return aes128_encrypt(pKey, input, 16, output); + uint16_t length; + mbedtls_aes_context aes_ctx; + + length = 16; + + mbedtls_aes_init(&aes_ctx); + + mbedtls_aes_setkey_enc(&aes_ctx, pKey, 128); + + while (length > 0) { + mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, input, output); + input += 16; + output += 16; + length -= 16; + } + + mbedtls_aes_free(&aes_ctx); + + return 0; +} + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize(void *v, size_t n) +{ + volatile unsigned char *p = v; + while (n--) { + *p++ = 0; + } +} + +/* + * Macros for common operations. + * Results in smaller compiled code than static inline functions. + */ + +/* + * Update the CBC-MAC state in y using a block in b + * (Always using b as the source helps the compiler optimise a bit better.) + */ +#define UPDATE_CBC_MAC \ + for( i = 0; i < 16; i++ ) \ + y[i] ^= b[i]; \ + \ + if( ( ret = aes_ecb_encrypt( key, y, y) ) != 0 ) \ + return( ret ); + +/* + * Encrypt or decrypt a partial block with CTR + * Warning: using b for temporary storage! src and dst must not be b! + * This avoids allocating one more 16 bytes buffer while allowing src == dst. + */ +#define CTR_CRYPT( dst, src, len ) \ + if( ( ret = aes_ecb_encrypt( key, ctr, b) ) != 0 ) \ + return( ret ); \ + \ + for( i = 0; i < len; i++ ) \ + dst[i] = src[i] ^ b[i]; + +/* + * Authenticated encryption or decryption + */ +static int ccm_auth_crypt(int mode, const unsigned char *key, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, size_t length, + unsigned char *output, + unsigned char *tag, size_t tag_len) +{ + int ret; + unsigned char i; + unsigned char q; + size_t len_left; + unsigned char b[16]; + unsigned char y[16]; + unsigned char ctr[16]; + const unsigned char *src; + unsigned char *dst; + + /* + * Check length requirements: SP800-38C A.1 + * Additional requirement: a < 2^16 - 2^8 to simplify the code. + * 'length' checked later (when writing it to the first block) + */ + if (tag_len < 4 || tag_len > 16 || tag_len % 2 != 0) { + return (MBEDTLS_ERR_CCM_BAD_INPUT); + } + + /* Also implies q is within bounds */ + if (iv_len < 7 || iv_len > 13) { + return (MBEDTLS_ERR_CCM_BAD_INPUT); + } + + if (add_len > 0xFF00) { + return (MBEDTLS_ERR_CCM_BAD_INPUT); + } + + q = 16 - 1 - (unsigned char) iv_len; + + /* + * First block B_0: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 length + * + * With flags as (bits): + * 7 0 + * 6 add present? + * 5 .. 3 (t - 2) / 2 + * 2 .. 0 q - 1 + */ + b[0] = 0; + b[0] |= (add_len > 0) << 6; + b[0] |= ((tag_len - 2) / 2) << 3; + b[0] |= q - 1; + + memcpy(b + 1, iv, iv_len); + + for (i = 0, len_left = length; i < q; i++, len_left >>= 8) { + b[15 - i] = (unsigned char)(len_left & 0xFF); + } + + if (len_left > 0) { + return (MBEDTLS_ERR_CCM_BAD_INPUT); + } + + + /* Start CBC-MAC with first block */ + memset(y, 0, 16); + UPDATE_CBC_MAC; + + /* + * If there is additional data, update CBC-MAC with + * add_len, add, 0 (padding to a block boundary) + */ + if (add_len > 0) { + size_t use_len; + len_left = add_len; + src = add; + + memset(b, 0, 16); + b[0] = (unsigned char)((add_len >> 8) & 0xFF); + b[1] = (unsigned char)((add_len) & 0xFF); + + use_len = len_left < 16 - 2 ? len_left : 16 - 2; + memcpy(b + 2, src, use_len); + len_left -= use_len; + src += use_len; + + UPDATE_CBC_MAC; + + while (len_left > 0) { + use_len = len_left > 16 ? 16 : len_left; + + memset(b, 0, 16); + memcpy(b, src, use_len); + UPDATE_CBC_MAC; + + len_left -= use_len; + src += use_len; + } + } + + /* + * Prepare counter block for encryption: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 counter (initially 1) + * + * With flags as (bits): + * 7 .. 3 0 + * 2 .. 0 q - 1 + */ + ctr[0] = q - 1; + memcpy(ctr + 1, iv, iv_len); + memset(ctr + 1 + iv_len, 0, q); + ctr[15] = 1; + + /* + * Authenticate and {en,de}crypt the message. + * + * The only difference between encryption and decryption is + * the respective order of authentication and {en,de}cryption. + */ + len_left = length; + src = input; + dst = output; + + while (len_left > 0) { + size_t use_len = len_left > 16 ? 16 : len_left; + + if (mode == CCM_ENCRYPT) { + memset(b, 0, 16); + memcpy(b, src, use_len); + UPDATE_CBC_MAC; + } + + CTR_CRYPT(dst, src, use_len); + + if (mode == CCM_DECRYPT) { + memset(b, 0, 16); + memcpy(b, dst, use_len); + UPDATE_CBC_MAC; + } + + dst += use_len; + src += use_len; + len_left -= use_len; + + /* + * Increment counter. + * No need to check for overflow thanks to the length check above. + */ + for (i = 0; i < q; i++) + if (++ctr[15 - i] != 0) { + break; + } + } + + /* + * Authentication: reset counter and crypt/mask internal tag + */ + for (i = 0; i < q; i++) { + ctr[15 - i] = 0; + } + + CTR_CRYPT(y, y, 16); + memcpy(tag, y, tag_len); + + return (0); +} + +/* + * Authenticated encryption + */ +int aes_ccm_encrypt_and_tag(const unsigned char *key, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, size_t length, + unsigned char *output, + unsigned char *tag, size_t tag_len) +{ + return (ccm_auth_crypt(CCM_ENCRYPT, key, iv, iv_len, + add, add_len, input, length, output, tag, tag_len)); +} + +/* + * Authenticated decryption + */ +int aes_ccm_auth_decrypt(const unsigned char *key, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, size_t length, + unsigned char *output, + const unsigned char *tag, size_t tag_len) +{ + int ret; + unsigned char check_tag[16]; + unsigned char i; + int diff; + + if ((ret = ccm_auth_crypt(CCM_DECRYPT, key, + iv, iv_len, add, add_len, + input, length, output, check_tag, tag_len)) != 0) { + return (ret); + } + + /* Check tag in "constant-time" */ + for (diff = 0, i = 0; i < tag_len; i++) { + diff |= tag[i] ^ check_tag[i]; + } + + if (diff != 0) { + mbedtls_zeroize(output, length); + return (MBEDTLS_ERR_CCM_AUTH_FAILED); + } + + return (0); +} + +//#define MI_AUTOTEST + +#ifdef MI_AUTOTEST +static uint8_t k[16] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f + }; +static uint8_t nonce[13] = {0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c + }; +static uint8_t p[64] = "HELLOWORLD!@#$%^helloworld123456"; +static uint8_t c[64] = {0}; +static uint8_t d[64] = {0}; +static uint8_t mic[4] = {0}; +static uint8_t astr[4] = {1, 2, 3, 4}; + + +#define LEN 32 +void aes_ccm_test2(void) +{ + + aes_ccm_encrypt_and_tag(k, nonce, 12, astr, sizeof(astr), p, LEN, c, mic, 4); + aes_ccm_auth_decrypt(k, nonce, 12, astr, sizeof(astr), c, LEN, d, mic, 4); + + //MI_LOG_INFO("Cipher : \n"); + //MI_LOG_HEXDUMP(c, LEN); + // MI_LOG_INFO("MIC : \n"); + // MI_LOG_HEXDUMP(mic, sizeof(mic)); + + // MI_LOG_DEBUG("AES128-CCM TEST: "); + if (memcmp(d, p, LEN) == 0) { + // MI_LOG_PRINTF(" PASS \n"); + } else { + // MI_LOG_PRINTF(" FAIL \n"); + } + +} +#endif + + diff --git a/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/ccm.h b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/ccm.h new file mode 100644 index 0000000..0f04529 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/ccm.h @@ -0,0 +1,93 @@ +/** + * \file ccm.h + * + * \brief Counter with CBC-MAC (CCM) for 128-bit block ciphers + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_CCM_H +#define MBEDTLS_CCM_H + +#define MBEDTLS_ERR_CCM_BAD_INPUT -0x000D /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_CCM_AUTH_FAILED -0x000F /**< Authenticated decryption failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief CCM buffer encryption + * + * \param key key must be 16 bytes + * \param length length of the input data in bytes + * \param iv nonce (initialization vector) + * \param iv_len length of IV in bytes + * must be 2, 3, 4, 5, 6, 7 or 8 + * \param add additional data + * \param add_len length of additional data in bytes + * must be less than 2^16 - 2^8 + * \param input buffer holding the input data + * \param output buffer for holding the output data + * must be at least 'length' bytes wide + * \param tag buffer for holding the tag + * \param tag_len length of the tag to generate in bytes + * must be 4, 6, 8, 10, 14 or 16 + * + * \note The tag is written to a separate buffer. To get the tag + * concatenated with the output as in the CCM spec, use + * tag = output + length and make sure the output buffer is + * at least length + tag_len wide. + * + * \return 0 if successful + */ +int aes_ccm_encrypt_and_tag(const unsigned char *key, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, size_t length, + unsigned char *output, + unsigned char *tag, size_t tag_len); + +/** + * \brief CCM buffer authenticated decryption + * + * \param key key must be 16 bytes + * \param length length of the input data + * \param iv initialization vector + * \param iv_len length of IV + * \param add additional data + * \param add_len length of additional data + * \param input buffer holding the input data + * \param output buffer for holding the output data + * \param tag buffer holding the tag + * \param tag_len length of the tag + * + * \return 0 if successful and authenticated, + * MBEDTLS_ERR_CCM_AUTH_FAILED if tag does not match + */ +int aes_ccm_auth_decrypt(const unsigned char *key, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, size_t length, + unsigned char *output, + const unsigned char *tag, size_t tag_len); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CCM_H */ diff --git a/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/hmac.c b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/hmac.c new file mode 100644 index 0000000..11d3b0b --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/hmac.c @@ -0,0 +1,366 @@ +#include "sha1.h" +#include "sha256.h" +#include "hmac.h" + + +#define hmac_printf + + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef CEIL_DIV +#define CEIL_DIV(a, b) (((a) + (b) - 1) / (b)) +#endif + + +#define SHA1_DIGEST_SIZE 20 +#define SHA1_BLOCK_SIZE 64 + +#define SHA256_DIGEST_SIZE 32 +#define SHA256_BLOCK_SIZE 64 + + +typedef struct { + /** Digest-specific context */ + mbedtls_sha1_context *md_ctx; + + /** HMAC part of the context */ + uint8_t ipad[64]; + uint8_t opad[64]; +} hmac_sha1_context_t; + +typedef struct { + /** Digest-specific context */ + mbedtls_sha256_context *md_ctx; + + /** HMAC part of the context */ + uint8_t ipad[64]; + uint8_t opad[64]; +} hmac_sha256_context_t; + + + +void hmac_sha1_init(hmac_sha1_context_t *ctx) +{ + memset(ctx, 0, sizeof(hmac_sha1_context_t)); +} + +void hmac_sha1_free(hmac_sha1_context_t *ctx) +{ + mbedtls_sha1_free((mbedtls_sha1_context *)ctx->md_ctx); +} + + +int32_t hmac_sha1_setup(hmac_sha1_context_t *ctx, int32_t hmac) +{ + return 0; +} + +int hmac_sha1_starts(hmac_sha1_context_t *ctx, const uint8_t *key, uint32_t keylen) +{ + + uint8_t sum[SHA1_DIGEST_SIZE]; + uint32_t i; + + if (keylen > (uint32_t) SHA1_BLOCK_SIZE) { + mbedtls_sha1_starts((mbedtls_sha1_context *) ctx->md_ctx); + mbedtls_sha1_update((mbedtls_sha1_context *) ctx->md_ctx, key, keylen); + mbedtls_sha1_finish((mbedtls_sha1_context *) ctx->md_ctx, sum); + + keylen = SHA1_DIGEST_SIZE; + key = sum; + } + + + memset(ctx->ipad, 0x36, SHA1_BLOCK_SIZE); + memset(ctx->opad, 0x5C, SHA1_BLOCK_SIZE); + + for (i = 0; i < keylen; i++) { + ctx->ipad[i] = (uint8_t)(ctx->ipad[i] ^ key[i]); + ctx->opad[i] = (uint8_t)(ctx->opad[i] ^ key[i]); + } + + memset(sum, 0, sizeof(sum)); + + mbedtls_sha1_starts((mbedtls_sha1_context *) ctx->md_ctx); + mbedtls_sha1_update((mbedtls_sha1_context *) ctx->md_ctx, ctx->ipad, SHA1_BLOCK_SIZE); + + return 0; + +} + +int32_t hmac_sha1_update(hmac_sha1_context_t *ctx, const uint8_t *input, uint32_t ilen) +{ + mbedtls_sha1_update((mbedtls_sha1_context *) ctx->md_ctx, input, ilen); + return 0; +} + +int32_t hmac_sha1_finish(hmac_sha1_context_t *ctx, uint8_t *output) +{ + uint8_t tmp[SHA1_DIGEST_SIZE]; + + mbedtls_sha1_finish((mbedtls_sha1_context *) ctx->md_ctx, tmp); + mbedtls_sha1_starts((mbedtls_sha1_context *) ctx->md_ctx); + mbedtls_sha1_update((mbedtls_sha1_context *) ctx->md_ctx, ctx->opad, SHA1_BLOCK_SIZE); + mbedtls_sha1_update((mbedtls_sha1_context *) ctx->md_ctx, tmp, SHA1_DIGEST_SIZE); + mbedtls_sha1_finish((mbedtls_sha1_context *) ctx->md_ctx, output); + + return 0; +} + +int32_t hmac_sha1_reset(hmac_sha1_context_t *ctx) +{ + + mbedtls_sha1_starts((mbedtls_sha1_context *) ctx->md_ctx); + mbedtls_sha1_update((mbedtls_sha1_context *) ctx->md_ctx, ctx->ipad, SHA1_BLOCK_SIZE); + + return 0 ; +} + +int32_t hmac_sha1_crypt(const uint8_t *key, uint32_t keylen, const uint8_t *input, uint32_t ilen, uint8_t *output) +{ + hmac_sha1_context_t ctx; + mbedtls_sha1_context sha_ctx; + int32_t ret; + + hmac_sha1_init(&ctx); + memset(&sha_ctx, 0, sizeof(sha_ctx)); + ctx.md_ctx = &sha_ctx; + if ((ret = hmac_sha1_setup(&ctx, 1)) != 0) { + return (ret); + } + + hmac_sha1_starts(&ctx, key, keylen); + hmac_sha1_update(&ctx, input, ilen); + hmac_sha1_finish(&ctx, output); + + return (0); +} + +// + +void hmac_sha256_init(hmac_sha256_context_t *ctx) +{ + memset(ctx, 0, sizeof(hmac_sha256_context_t)); +} + +void hmac_sha256_free(hmac_sha256_context_t *ctx) +{ + mbedtls_sha256_free((mbedtls_sha256_context *)ctx->md_ctx); +} + + +int32_t hmac_sha256_setup(hmac_sha256_context_t *ctx, int32_t hmac) +{ + return 0; +} + +int hmac_sha256_starts(hmac_sha256_context_t *ctx, const uint8_t *key, uint32_t keylen) +{ + + uint8_t sum[SHA256_DIGEST_SIZE]; + uint32_t i; + + if (keylen > (uint32_t) SHA256_BLOCK_SIZE) { + mbedtls_sha256_starts((mbedtls_sha256_context *) ctx->md_ctx, 0); + mbedtls_sha256_update((mbedtls_sha256_context *) ctx->md_ctx, key, keylen); + mbedtls_sha256_finish((mbedtls_sha256_context *) ctx->md_ctx, sum); + + keylen = SHA256_DIGEST_SIZE; + key = sum; + } + + + memset(ctx->ipad, 0x36, SHA256_BLOCK_SIZE); + memset(ctx->opad, 0x5C, SHA256_BLOCK_SIZE); + + for (i = 0; i < keylen; i++) { + ctx->ipad[i] = (uint8_t)(ctx->ipad[i] ^ key[i]); + ctx->opad[i] = (uint8_t)(ctx->opad[i] ^ key[i]); + } + + memset(sum, 0, sizeof(sum)); + + mbedtls_sha256_starts((mbedtls_sha256_context *) ctx->md_ctx, 0); + mbedtls_sha256_update((mbedtls_sha256_context *) ctx->md_ctx, ctx->ipad, SHA256_BLOCK_SIZE); + + return 0; + +} + +int32_t hmac_sha256_update(hmac_sha256_context_t *ctx, const uint8_t *input, uint32_t ilen) +{ + mbedtls_sha256_update((mbedtls_sha256_context *) ctx->md_ctx, input, ilen); + return 0; +} + +int32_t hmac_sha256_finish(hmac_sha256_context_t *ctx, uint8_t *output) +{ + uint8_t tmp[SHA256_DIGEST_SIZE]; + + mbedtls_sha256_finish((mbedtls_sha256_context *) ctx->md_ctx, tmp); + mbedtls_sha256_starts((mbedtls_sha256_context *) ctx->md_ctx, 0); + mbedtls_sha256_update((mbedtls_sha256_context *) ctx->md_ctx, ctx->opad, SHA256_BLOCK_SIZE); + mbedtls_sha256_update((mbedtls_sha256_context *) ctx->md_ctx, tmp, SHA256_DIGEST_SIZE); + mbedtls_sha256_finish((mbedtls_sha256_context *) ctx->md_ctx, output); + + return 0; +} + +int32_t hmac_sha256_reset(hmac_sha256_context_t *ctx) +{ + + mbedtls_sha256_starts((mbedtls_sha256_context *) ctx->md_ctx, 0); + mbedtls_sha256_update((mbedtls_sha256_context *) ctx->md_ctx, ctx->ipad, SHA256_BLOCK_SIZE); + + return 0 ; +} + +int32_t hmac_sha256_crypt(const uint8_t *key, uint32_t keylen, const uint8_t *input, uint32_t ilen, uint8_t *output) +{ + hmac_sha256_context_t ctx; + mbedtls_sha256_context sha_ctx; + int32_t ret; + + hmac_sha256_init(&ctx); + memset(&sha_ctx, 0, sizeof(sha_ctx)); + ctx.md_ctx = &sha_ctx; + if ((ret = hmac_sha256_setup(&ctx, 1)) != 0) { + return (ret); + } + + hmac_sha256_starts(&ctx, key, keylen); + hmac_sha256_update(&ctx, input, ilen); + hmac_sha256_finish(&ctx, output); + + return (0); +} + +uint32_t sha256_hkdf(const uint8_t *key, uint32_t key_len, + const uint8_t *salt, uint32_t salt_len, + const uint8_t *info, uint32_t info_len, + uint8_t *out, uint32_t out_len) +{ + const uint8_t null_salt[32] = {0}; + uint8_t PRK[32]; + uint8_t T_n[32]; + uint32_t loop; + uint32_t temp_len; + + // Step 1: HKDF-Extract(salt, IKM) -> PRK + if (salt == NULL) { + hmac_sha256_crypt(null_salt, 32, key, key_len, PRK); + } else { + hmac_sha256_crypt(salt, salt_len, key, key_len, PRK); + } + + // Step 2: HKDF-Expand(PRK, info, L) -> OKM + //T(0) = empty string (zero length) + //T(1) = HMAC-Hash(PRK, T(0) | info | 0x01) + //T(2) = HMAC-Hash(PRK, T(1) | info | 0x02) + //T(3) = HMAC-Hash(PRK, T(2) | info | 0x03) + + uint8_t temp[32 + info_len + 1]; + memset(temp, 0, 32 + info_len + 1); + loop = CEIL_DIV(out_len, 32); + + for (int32_t i = 0; i < loop ; i++) { + if (i == 0) { + temp_len = 0; + } else { + memcpy(temp, T_n, 32); + temp_len = 32; + } + + memcpy(temp + temp_len, info, info_len); + temp_len += info_len; + + temp[temp_len] = i + 1; + temp_len += 1; + + hmac_sha256_crypt(PRK, 32, temp, temp_len, T_n); + + memcpy(out + 32 * i, T_n, MIN(32, out_len)); + out_len -= 32; + } + + return 0; +} + + + +/***************************************************this is for test************************************************/ +#if (HMAC_SELF_TEST == 1) + +/////////////////////////////////////////// +//Hash = SHA-256 +//IKM = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b (22 octets) +//salt = 0x000102030405060708090a0b0c (13 octets) +//info = 0xf0f1f2f3f4f5f6f7f8f9 (10 octets) +//L = 42 +// +//PRK = 0x077709362c2e32df0ddc3f0dc47bba63 +// 90b6c73bb50f9c3122ec844ad7c2b3e5 (32 octets) +//OKM = 0x3cb25f25faacd57a90434f64d0362f2a +// 2d2d0a90cf1a5a4c5db02d56ecc4c5bf +// 34007208d5b887185865 (42 octets) + +#if 0 +uint8_t salt[13] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c}; +uint8_t info[10] = {0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9}; +uint8_t key_material[22] = {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}; +#endif + + +void hkdf_test(void) +{ + uint8_t key_material[80] = {0x00, + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, + 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, + 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f + }; + + uint8_t salt[80] = {0x60, + 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 0x80, + 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, + 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, + 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf + }; + + uint8_t info[80] = {0xb0, + 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 0xc0, + 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, + 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, + 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, + 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff + }; + + uint8_t expect[82] = { + 0xb1, 0x1e, 0x39, 0x8d, 0xc8, 0x03, 0x27, 0xa1, 0xc8, 0xe7, 0xf7, 0x8c, 0x59, 0x6a, 0x49, 0x34, + 0x4f, 0x01, 0x2e, 0xda, 0x2d, 0x4e, 0xfa, 0xd8, 0xa0, 0x50, 0xcc, 0x4c, 0x19, 0xaf, 0xa9, 0x7c, + 0x59, 0x04, 0x5a, 0x99, 0xca, 0xc7, 0x82, 0x72, 0x71, 0xcb, 0x41, 0xc6, 0x5e, 0x59, 0x0e, 0x09, + 0xda, 0x32, 0x75, 0x60, 0x0c, 0x2f, 0x09, 0xb8, 0x36, 0x77, 0x93, 0xa9, 0xac, 0xa3, 0xdb, 0x71, + 0xcc, 0x30, 0xc5, 0x81, 0x79, 0xec, 0x3e, 0x87, 0xc1, 0x4c, 0x01, 0xd5, 0xc1, 0xf3, 0x43, 0x4f, + 0x1d, 0x87 + }; + uint8_t out_key[82]; + + sha256_hkdf(key_material, sizeof(key_material), salt, sizeof(salt), info, sizeof(info), out_key, 82); + + hmac_printf("SHA256-HKDF TEST: "); + if (memcmp(expect, out_key, 82) == 0) { + hmac_printf(" PASS\n"); + } else { + hmac_printf(" FAIL\n"); + } + +} + + +#endif + diff --git a/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/hmac.h b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/hmac.h new file mode 100644 index 0000000..0c483c3 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/hmac.h @@ -0,0 +1,49 @@ +#ifndef HMAC_H +#define HMAC_H + +#include +#include +#include + + +#define HMAC_SELF_TEST 0 + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * \brief Output = Generic_HMAC( hmac key, input buffer ) + * + * \param md_info message digest info + * \param key HMAC secret key + * \param keylen length of the HMAC key in bytes + * \param input buffer holding the data + * \param ilen length of the input data + * \param output Generic HMAC-result + * + * \returns 0 on success, MBEDTLS_ERR_MD_BAD_INPUT_DATA if parameter + * verification fails. + */ +int32_t hmac_sha1_crypt(const uint8_t *key, uint32_t keylen, const uint8_t *input, uint32_t ilen, uint8_t *output); + + +int32_t hmac_sha256_crypt(const uint8_t *key, uint32_t keylen, const uint8_t *input, uint32_t ilen, uint8_t *output); + + +uint32_t sha256_hkdf(const uint8_t *key, uint32_t key_len, const uint8_t *salt, uint32_t salt_len, const uint8_t *info, uint32_t info_len, + uint8_t *out, uint32_t out_len); + +#if (HMAC_SELF_TEST == 1) + +void hkdf_test(void); + +#endif /* HMAC_SELF_TEST */ + + +#ifdef __cplusplus +} +#endif + +#endif /* hmac.h */ diff --git a/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/md5.c b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/md5.c new file mode 100644 index 0000000..6e1b8de --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/md5.c @@ -0,0 +1,504 @@ +/* + * RFC 1321 compliant MD5 implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#define MBEDTLS_MD5_C + +#if defined(MBEDTLS_MD5_C) + +#include "md5.h" +#include + +#define mbedtls_printf //printf + + +#if !defined(MBEDTLS_MD5_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void mbedtls_md5_init(mbedtls_md5_context *ctx) +{ + memset(ctx, 0, sizeof(mbedtls_md5_context)); +} + +void mbedtls_md5_free(mbedtls_md5_context *ctx) +{ + if (ctx == NULL) { + return; + } + + //mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) ); + memset(ctx, 0, sizeof(mbedtls_md5_context)); +} + +void mbedtls_md5_clone(mbedtls_md5_context *dst, + const mbedtls_md5_context *src) +{ + *dst = *src; +} + +/* + * MD5 context setup + */ +int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + + return (0); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_starts(mbedtls_md5_context *ctx) +{ + mbedtls_md5_starts_ret(ctx); +} +#endif + +#if !defined(MBEDTLS_MD5_PROCESS_ALT) +int mbedtls_internal_md5_process(mbedtls_md5_context *ctx, + const unsigned char data[64]) +{ + uint32_t X[16], A, B, C, D; + + GET_UINT32_LE(X[ 0], data, 0); + GET_UINT32_LE(X[ 1], data, 4); + GET_UINT32_LE(X[ 2], data, 8); + GET_UINT32_LE(X[ 3], data, 12); + GET_UINT32_LE(X[ 4], data, 16); + GET_UINT32_LE(X[ 5], data, 20); + GET_UINT32_LE(X[ 6], data, 24); + GET_UINT32_LE(X[ 7], data, 28); + GET_UINT32_LE(X[ 8], data, 32); + GET_UINT32_LE(X[ 9], data, 36); + GET_UINT32_LE(X[10], data, 40); + GET_UINT32_LE(X[11], data, 44); + GET_UINT32_LE(X[12], data, 48); + GET_UINT32_LE(X[13], data, 52); + GET_UINT32_LE(X[14], data, 56); + GET_UINT32_LE(X[15], data, 60); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define P(a,b,c,d,k,s,t) \ +{ \ + a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) + + P(A, B, C, D, 0, 7, 0xD76AA478); + P(D, A, B, C, 1, 12, 0xE8C7B756); + P(C, D, A, B, 2, 17, 0x242070DB); + P(B, C, D, A, 3, 22, 0xC1BDCEEE); + P(A, B, C, D, 4, 7, 0xF57C0FAF); + P(D, A, B, C, 5, 12, 0x4787C62A); + P(C, D, A, B, 6, 17, 0xA8304613); + P(B, C, D, A, 7, 22, 0xFD469501); + P(A, B, C, D, 8, 7, 0x698098D8); + P(D, A, B, C, 9, 12, 0x8B44F7AF); + P(C, D, A, B, 10, 17, 0xFFFF5BB1); + P(B, C, D, A, 11, 22, 0x895CD7BE); + P(A, B, C, D, 12, 7, 0x6B901122); + P(D, A, B, C, 13, 12, 0xFD987193); + P(C, D, A, B, 14, 17, 0xA679438E); + P(B, C, D, A, 15, 22, 0x49B40821); + +#undef F + +#define F(x,y,z) (y ^ (z & (x ^ y))) + + P(A, B, C, D, 1, 5, 0xF61E2562); + P(D, A, B, C, 6, 9, 0xC040B340); + P(C, D, A, B, 11, 14, 0x265E5A51); + P(B, C, D, A, 0, 20, 0xE9B6C7AA); + P(A, B, C, D, 5, 5, 0xD62F105D); + P(D, A, B, C, 10, 9, 0x02441453); + P(C, D, A, B, 15, 14, 0xD8A1E681); + P(B, C, D, A, 4, 20, 0xE7D3FBC8); + P(A, B, C, D, 9, 5, 0x21E1CDE6); + P(D, A, B, C, 14, 9, 0xC33707D6); + P(C, D, A, B, 3, 14, 0xF4D50D87); + P(B, C, D, A, 8, 20, 0x455A14ED); + P(A, B, C, D, 13, 5, 0xA9E3E905); + P(D, A, B, C, 2, 9, 0xFCEFA3F8); + P(C, D, A, B, 7, 14, 0x676F02D9); + P(B, C, D, A, 12, 20, 0x8D2A4C8A); + +#undef F + +#define F(x,y,z) (x ^ y ^ z) + + P(A, B, C, D, 5, 4, 0xFFFA3942); + P(D, A, B, C, 8, 11, 0x8771F681); + P(C, D, A, B, 11, 16, 0x6D9D6122); + P(B, C, D, A, 14, 23, 0xFDE5380C); + P(A, B, C, D, 1, 4, 0xA4BEEA44); + P(D, A, B, C, 4, 11, 0x4BDECFA9); + P(C, D, A, B, 7, 16, 0xF6BB4B60); + P(B, C, D, A, 10, 23, 0xBEBFBC70); + P(A, B, C, D, 13, 4, 0x289B7EC6); + P(D, A, B, C, 0, 11, 0xEAA127FA); + P(C, D, A, B, 3, 16, 0xD4EF3085); + P(B, C, D, A, 6, 23, 0x04881D05); + P(A, B, C, D, 9, 4, 0xD9D4D039); + P(D, A, B, C, 12, 11, 0xE6DB99E5); + P(C, D, A, B, 15, 16, 0x1FA27CF8); + P(B, C, D, A, 2, 23, 0xC4AC5665); + +#undef F + +#define F(x,y,z) (y ^ (x | ~z)) + + P(A, B, C, D, 0, 6, 0xF4292244); + P(D, A, B, C, 7, 10, 0x432AFF97); + P(C, D, A, B, 14, 15, 0xAB9423A7); + P(B, C, D, A, 5, 21, 0xFC93A039); + P(A, B, C, D, 12, 6, 0x655B59C3); + P(D, A, B, C, 3, 10, 0x8F0CCC92); + P(C, D, A, B, 10, 15, 0xFFEFF47D); + P(B, C, D, A, 1, 21, 0x85845DD1); + P(A, B, C, D, 8, 6, 0x6FA87E4F); + P(D, A, B, C, 15, 10, 0xFE2CE6E0); + P(C, D, A, B, 6, 15, 0xA3014314); + P(B, C, D, A, 13, 21, 0x4E0811A1); + P(A, B, C, D, 4, 6, 0xF7537E82); + P(D, A, B, C, 11, 10, 0xBD3AF235); + P(C, D, A, B, 2, 15, 0x2AD7D2BB); + P(B, C, D, A, 9, 21, 0xEB86D391); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + + return (0); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_process(mbedtls_md5_context *ctx, + const unsigned char data[64]) +{ + mbedtls_internal_md5_process(ctx, data); +} +#endif +#endif /* !MBEDTLS_MD5_PROCESS_ALT */ + +/* + * MD5 process buffer + */ +int mbedtls_md5_update_ret(mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen) +{ + int ret; + size_t fill; + uint32_t left; + + if (ilen == 0) { + return (0); + } + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if (ctx->total[0] < (uint32_t) ilen) { + ctx->total[1]++; + } + + if (left && ilen >= fill) { + memcpy((void *)(ctx->buffer + left), input, fill); + if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) { + return (ret); + } + + input += fill; + ilen -= fill; + left = 0; + } + + while (ilen >= 64) { + if ((ret = mbedtls_internal_md5_process(ctx, input)) != 0) { + return (ret); + } + + input += 64; + ilen -= 64; + } + + if (ilen > 0) { + memcpy((void *)(ctx->buffer + left), input, ilen); + } + + return (0); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_update(mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen) +{ + mbedtls_md5_update_ret(ctx, input, ilen); +} +#endif + +/* + * MD5 final digest + */ +int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx, + unsigned char output[16]) +{ + int ret; + uint32_t used; + uint32_t high, low; + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if (used <= 56) { + /* Enough room for padding + length in current block */ + memset(ctx->buffer + used, 0, 56 - used); + } else { + /* We'll need an extra block */ + memset(ctx->buffer + used, 0, 64 - used); + + if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) { + return (ret); + } + + memset(ctx->buffer, 0, 56); + } + + /* + * Add message length + */ + high = (ctx->total[0] >> 29) + | (ctx->total[1] << 3); + low = (ctx->total[0] << 3); + + PUT_UINT32_LE(low, ctx->buffer, 56); + PUT_UINT32_LE(high, ctx->buffer, 60); + + if ((ret = mbedtls_internal_md5_process(ctx, ctx->buffer)) != 0) { + return (ret); + } + + /* + * Output final state + */ + PUT_UINT32_LE(ctx->state[0], output, 0); + PUT_UINT32_LE(ctx->state[1], output, 4); + PUT_UINT32_LE(ctx->state[2], output, 8); + PUT_UINT32_LE(ctx->state[3], output, 12); + + return (0); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_finish(mbedtls_md5_context *ctx, + unsigned char output[16]) +{ + mbedtls_md5_finish_ret(ctx, output); +} +#endif + +#endif /* !MBEDTLS_MD5_ALT */ + +/* + * output = MD5( input buffer ) + */ +int mbedtls_md5_ret(const unsigned char *input, + size_t ilen, + unsigned char output[16]) +{ + int ret; + mbedtls_md5_context ctx; + + mbedtls_md5_init(&ctx); + + if ((ret = mbedtls_md5_starts_ret(&ctx)) != 0) { + goto exit; + } + + if ((ret = mbedtls_md5_update_ret(&ctx, input, ilen)) != 0) { + goto exit; + } + + if ((ret = mbedtls_md5_finish_ret(&ctx, output)) != 0) { + goto exit; + } + +exit: + mbedtls_md5_free(&ctx); + + return (ret); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5(const unsigned char *input, + size_t ilen, + unsigned char output[16]) +{ + mbedtls_md5_ret(input, ilen, output); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * RFC 1321 test vectors + */ +static const unsigned char md5_test_buf[7][81] = { + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { + "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890" + } +}; + +static const size_t md5_test_buflen[7] = { + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md5_test_sum[7][16] = { + { + 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, + 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E + }, + { + 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, + 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 + }, + { + 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, + 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 + }, + { + 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, + 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 + }, + { + 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, + 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B + }, + { + 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, + 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F + }, + { + 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, + 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A + } +}; + +/* + * Checkup routine + */ +int mbedtls_md5_self_test(int verbose) +{ + int i, ret = 0; + unsigned char md5sum[16]; + + for (i = 0; i < 7; i++) { + if (verbose != 0) { + mbedtls_printf(" MD5 test #%d: ", i + 1); + } + + ret = mbedtls_md5_ret(md5_test_buf[i], md5_test_buflen[i], md5sum); + if (ret != 0) { + goto fail; + } + + if (memcmp(md5sum, md5_test_sum[i], 16) != 0) { + ret = 1; + goto fail; + } + + if (verbose != 0) { + mbedtls_printf("passed\n"); + } + } + + if (verbose != 0) { + mbedtls_printf("\n"); + } + + return (0); + +fail: + if (verbose != 0) { + mbedtls_printf("failed\n"); + } + + return (ret); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD5_C */ diff --git a/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/md5.h b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/md5.h new file mode 100644 index 0000000..6e66999 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/md5.h @@ -0,0 +1,309 @@ +/** + * \file md5.h + * + * \brief MD5 message digest algorithm (hash function) + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_MD5_H +#define MBEDTLS_MD5_H + + +#include +#include + + +//#define MBEDTLS_MD5_SELF_TEST + + +/* MBEDTLS_ERR_MD5_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_MD5_ALT) +// Regular implementation +// + +/** + * \brief MD5 context structure + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_md5_context { + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md5_context; + +#else /* MBEDTLS_MD5_ALT */ +#include "md5_alt.h" +#endif /* MBEDTLS_MD5_ALT */ + +/** + * \brief Initialize MD5 context + * + * \param ctx MD5 context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_init(mbedtls_md5_context *ctx); + +/** + * \brief Clear MD5 context + * + * \param ctx MD5 context to be cleared + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_free(mbedtls_md5_context *ctx); + +/** + * \brief Clone (the state of) an MD5 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_clone(mbedtls_md5_context *dst, + const mbedtls_md5_context *src); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_update_ret(mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx, + unsigned char output[16]); + +/** + * \brief MD5 process data block (internal use only) + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md5_process(mbedtls_md5_context *ctx, + const unsigned char data[64]); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD5 context setup + * + * \deprecated Superseded by mbedtls_md5_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_starts(mbedtls_md5_context *ctx); + +/** + * \brief MD5 process buffer + * + * \deprecated Superseded by mbedtls_md5_update_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_update(mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen); + +/** + * \brief MD5 final digest + * + * \deprecated Superseded by mbedtls_md5_finish_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_finish(mbedtls_md5_context *ctx, + unsigned char output[16]); + +/** + * \brief MD5 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md5_process() in 2.7.0 + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_process(mbedtls_md5_context *ctx, + const unsigned char data[64]); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_ret(const unsigned char *input, + size_t ilen, + unsigned char output[16]); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD5( input buffer ) + * + * \deprecated Superseded by mbedtls_md5_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5(const unsigned char *input, + size_t ilen, + unsigned char output[16]); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_self_test(int verbose); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md5.h */ diff --git a/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha1.c b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha1.c new file mode 100644 index 0000000..c3cde4a --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha1.c @@ -0,0 +1,575 @@ +/* + * FIPS-180-1 compliant SHA-1 implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +#define MBEDTLS_SHA1_C + +#if defined(MBEDTLS_SHA1_C) + +#include "sha1.h" + +#include + +#define mbedtls_printf printf + +/* Internal macros meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 ) +#define MBEDTLS_INTERNAL_VALIDATE( cond ) do { } while( 0 ) + +#define SHA1_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA ) + +#define SHA1_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA1_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +void mbedtls_sha1_init(mbedtls_sha1_context *ctx) +{ + SHA1_VALIDATE(ctx != NULL); + + memset(ctx, 0, sizeof(mbedtls_sha1_context)); +} + +void mbedtls_sha1_free(mbedtls_sha1_context *ctx) +{ + if (ctx == NULL) { + return; + } + + //mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); + memset(ctx, 0, sizeof(mbedtls_sha1_context)); +} + +void mbedtls_sha1_clone(mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src) +{ + SHA1_VALIDATE(dst != NULL); + SHA1_VALIDATE(src != NULL); + + *dst = *src; +} + +/* + * SHA-1 context setup + */ +int mbedtls_sha1_starts_ret(mbedtls_sha1_context *ctx) +{ + SHA1_VALIDATE_RET(ctx != NULL); + + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + return (0); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_starts(mbedtls_sha1_context *ctx) +{ + mbedtls_sha1_starts_ret(ctx); +} +#endif + +#if !defined(MBEDTLS_SHA1_PROCESS_ALT) +int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, + const unsigned char data[64]) +{ + uint32_t temp, W[16], A, B, C, D, E; + + SHA1_VALIDATE_RET(ctx != NULL); + SHA1_VALIDATE_RET((const unsigned char *)data != NULL); + + GET_UINT32_BE(W[ 0], data, 0); + GET_UINT32_BE(W[ 1], data, 4); + GET_UINT32_BE(W[ 2], data, 8); + GET_UINT32_BE(W[ 3], data, 12); + GET_UINT32_BE(W[ 4], data, 16); + GET_UINT32_BE(W[ 5], data, 20); + GET_UINT32_BE(W[ 6], data, 24); + GET_UINT32_BE(W[ 7], data, 28); + GET_UINT32_BE(W[ 8], data, 32); + GET_UINT32_BE(W[ 9], data, 36); + GET_UINT32_BE(W[10], data, 40); + GET_UINT32_BE(W[11], data, 44); + GET_UINT32_BE(W[12], data, 48); + GET_UINT32_BE(W[13], data, 52); + GET_UINT32_BE(W[14], data, 56); + GET_UINT32_BE(W[15], data, 60); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define R(t) \ +( \ + temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \ + W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \ + ( W[t & 0x0F] = S(temp,1) ) \ +) + +#define P(a,b,c,d,e,x) \ +{ \ + e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P(A, B, C, D, E, W[0]); + P(E, A, B, C, D, W[1]); + P(D, E, A, B, C, W[2]); + P(C, D, E, A, B, W[3]); + P(B, C, D, E, A, W[4]); + P(A, B, C, D, E, W[5]); + P(E, A, B, C, D, W[6]); + P(D, E, A, B, C, W[7]); + P(C, D, E, A, B, W[8]); + P(B, C, D, E, A, W[9]); + P(A, B, C, D, E, W[10]); + P(E, A, B, C, D, W[11]); + P(D, E, A, B, C, W[12]); + P(C, D, E, A, B, W[13]); + P(B, C, D, E, A, W[14]); + P(A, B, C, D, E, W[15]); + P(E, A, B, C, D, R(16)); + P(D, E, A, B, C, R(17)); + P(C, D, E, A, B, R(18)); + P(B, C, D, E, A, R(19)); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P(A, B, C, D, E, R(20)); + P(E, A, B, C, D, R(21)); + P(D, E, A, B, C, R(22)); + P(C, D, E, A, B, R(23)); + P(B, C, D, E, A, R(24)); + P(A, B, C, D, E, R(25)); + P(E, A, B, C, D, R(26)); + P(D, E, A, B, C, R(27)); + P(C, D, E, A, B, R(28)); + P(B, C, D, E, A, R(29)); + P(A, B, C, D, E, R(30)); + P(E, A, B, C, D, R(31)); + P(D, E, A, B, C, R(32)); + P(C, D, E, A, B, R(33)); + P(B, C, D, E, A, R(34)); + P(A, B, C, D, E, R(35)); + P(E, A, B, C, D, R(36)); + P(D, E, A, B, C, R(37)); + P(C, D, E, A, B, R(38)); + P(B, C, D, E, A, R(39)); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P(A, B, C, D, E, R(40)); + P(E, A, B, C, D, R(41)); + P(D, E, A, B, C, R(42)); + P(C, D, E, A, B, R(43)); + P(B, C, D, E, A, R(44)); + P(A, B, C, D, E, R(45)); + P(E, A, B, C, D, R(46)); + P(D, E, A, B, C, R(47)); + P(C, D, E, A, B, R(48)); + P(B, C, D, E, A, R(49)); + P(A, B, C, D, E, R(50)); + P(E, A, B, C, D, R(51)); + P(D, E, A, B, C, R(52)); + P(C, D, E, A, B, R(53)); + P(B, C, D, E, A, R(54)); + P(A, B, C, D, E, R(55)); + P(E, A, B, C, D, R(56)); + P(D, E, A, B, C, R(57)); + P(C, D, E, A, B, R(58)); + P(B, C, D, E, A, R(59)); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P(A, B, C, D, E, R(60)); + P(E, A, B, C, D, R(61)); + P(D, E, A, B, C, R(62)); + P(C, D, E, A, B, R(63)); + P(B, C, D, E, A, R(64)); + P(A, B, C, D, E, R(65)); + P(E, A, B, C, D, R(66)); + P(D, E, A, B, C, R(67)); + P(C, D, E, A, B, R(68)); + P(B, C, D, E, A, R(69)); + P(A, B, C, D, E, R(70)); + P(E, A, B, C, D, R(71)); + P(D, E, A, B, C, R(72)); + P(C, D, E, A, B, R(73)); + P(B, C, D, E, A, R(74)); + P(A, B, C, D, E, R(75)); + P(E, A, B, C, D, R(76)); + P(D, E, A, B, C, R(77)); + P(C, D, E, A, B, R(78)); + P(B, C, D, E, A, R(79)); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + + return (0); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_process(mbedtls_sha1_context *ctx, + const unsigned char data[64]) +{ + mbedtls_internal_sha1_process(ctx, data); +} +#endif +#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ + +/* + * SHA-1 process buffer + */ +int mbedtls_sha1_update_ret(mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen) +{ + int ret; + size_t fill; + uint32_t left; + + SHA1_VALIDATE_RET(ctx != NULL); + SHA1_VALIDATE_RET(ilen == 0 || input != NULL); + + if (ilen == 0) { + return (0); + } + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if (ctx->total[0] < (uint32_t) ilen) { + ctx->total[1]++; + } + + if (left && ilen >= fill) { + memcpy((void *)(ctx->buffer + left), input, fill); + + if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) { + return (ret); + } + + input += fill; + ilen -= fill; + left = 0; + } + + while (ilen >= 64) { + if ((ret = mbedtls_internal_sha1_process(ctx, input)) != 0) { + return (ret); + } + + input += 64; + ilen -= 64; + } + + if (ilen > 0) { + memcpy((void *)(ctx->buffer + left), input, ilen); + } + + return (0); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_update(mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen) +{ + mbedtls_sha1_update_ret(ctx, input, ilen); +} +#endif + +/* + * SHA-1 final digest + */ +int mbedtls_sha1_finish_ret(mbedtls_sha1_context *ctx, + unsigned char output[20]) +{ + int ret; + uint32_t used; + uint32_t high, low; + + SHA1_VALIDATE_RET(ctx != NULL); + SHA1_VALIDATE_RET((unsigned char *)output != NULL); + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if (used <= 56) { + /* Enough room for padding + length in current block */ + memset(ctx->buffer + used, 0, 56 - used); + } else { + /* We'll need an extra block */ + memset(ctx->buffer + used, 0, 64 - used); + + if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) { + return (ret); + } + + memset(ctx->buffer, 0, 56); + } + + /* + * Add message length + */ + high = (ctx->total[0] >> 29) + | (ctx->total[1] << 3); + low = (ctx->total[0] << 3); + + PUT_UINT32_BE(high, ctx->buffer, 56); + PUT_UINT32_BE(low, ctx->buffer, 60); + + if ((ret = mbedtls_internal_sha1_process(ctx, ctx->buffer)) != 0) { + return (ret); + } + + /* + * Output final state + */ + PUT_UINT32_BE(ctx->state[0], output, 0); + PUT_UINT32_BE(ctx->state[1], output, 4); + PUT_UINT32_BE(ctx->state[2], output, 8); + PUT_UINT32_BE(ctx->state[3], output, 12); + PUT_UINT32_BE(ctx->state[4], output, 16); + + return (0); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_finish(mbedtls_sha1_context *ctx, + unsigned char output[20]) +{ + mbedtls_sha1_finish_ret(ctx, output); +} +#endif + +#endif /* !MBEDTLS_SHA1_ALT */ + +/* + * output = SHA-1( input buffer ) + */ +int mbedtls_sha1_ret(const unsigned char *input, + size_t ilen, + unsigned char output[20]) +{ + int ret; + mbedtls_sha1_context ctx; + + SHA1_VALIDATE_RET(ilen == 0 || input != NULL); + SHA1_VALIDATE_RET((unsigned char *)output != NULL); + + mbedtls_sha1_init(&ctx); + + if ((ret = mbedtls_sha1_starts_ret(&ctx)) != 0) { + goto exit; + } + + if ((ret = mbedtls_sha1_update_ret(&ctx, input, ilen)) != 0) { + goto exit; + } + + if ((ret = mbedtls_sha1_finish_ret(&ctx, output)) != 0) { + goto exit; + } + +exit: + mbedtls_sha1_free(&ctx); + + return (ret); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1(const unsigned char *input, + size_t ilen, + unsigned char output[20]) +{ + mbedtls_sha1_ret(input, ilen, output); +} +#endif + +#if defined(MBEDTLS_SHA1_SELF_TEST) +/* + * FIPS-180-1 test vectors + */ +static const unsigned char sha1_test_buf[3][57] = { + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t sha1_test_buflen[3] = { + 3, 56, 1000 +}; + +static const unsigned char sha1_test_sum[3][20] = { + { + 0xA9, 0x99, 0x3E, 0x36, 0x47, 0x06, 0x81, 0x6A, 0xBA, 0x3E, + 0x25, 0x71, 0x78, 0x50, 0xC2, 0x6C, 0x9C, 0xD0, 0xD8, 0x9D + }, + { + 0x84, 0x98, 0x3E, 0x44, 0x1C, 0x3B, 0xD2, 0x6E, 0xBA, 0xAE, + 0x4A, 0xA1, 0xF9, 0x51, 0x29, 0xE5, 0xE5, 0x46, 0x70, 0xF1 + }, + { + 0x34, 0xAA, 0x97, 0x3C, 0xD4, 0xC4, 0xDA, 0xA4, 0xF6, 0x1E, + 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F + } +}; + +/* + * Checkup routine + */ +int mbedtls_sha1_self_test(int verbose) +{ + int i, j, buflen, ret = 0; + unsigned char buf[1024]; + unsigned char sha1sum[20]; + mbedtls_sha1_context ctx; + + mbedtls_sha1_init(&ctx); + + /* + * SHA-1 + */ + for (i = 0; i < 3; i++) { + if (verbose != 0) { + mbedtls_printf(" SHA-1 test #%d: ", i + 1); + } + + if ((ret = mbedtls_sha1_starts_ret(&ctx)) != 0) { + goto fail; + } + + if (i == 2) { + memset(buf, 'a', buflen = 1000); + + for (j = 0; j < 1000; j++) { + ret = mbedtls_sha1_update_ret(&ctx, buf, buflen); + if (ret != 0) { + goto fail; + } + } + } else { + ret = mbedtls_sha1_update_ret(&ctx, sha1_test_buf[i], + sha1_test_buflen[i]); + if (ret != 0) { + goto fail; + } + } + + if ((ret = mbedtls_sha1_finish_ret(&ctx, sha1sum)) != 0) { + goto fail; + } + + if (memcmp(sha1sum, sha1_test_sum[i], 20) != 0) { + ret = 1; + goto fail; + } + + if (verbose != 0) { + mbedtls_printf("passed\n"); + } + } + + if (verbose != 0) { + mbedtls_printf("\n"); + } + + goto exit; + +fail: + if (verbose != 0) { + mbedtls_printf("failed\n"); + } + +exit: + mbedtls_sha1_free(&ctx); + + return (ret); +} + +#endif /* MBEDTLS_SHA1_SELF_TEST */ + +#endif /* MBEDTLS_SHA1_C */ diff --git a/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha1.h b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha1.h new file mode 100644 index 0000000..097d6bb --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha1.h @@ -0,0 +1,347 @@ +/** + * \file sha1.h + * + * \brief This file contains SHA-1 definitions and functions. + * + * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in + * FIPS 180-4: Secure Hash Standard (SHS). + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SHA1_H +#define MBEDTLS_SHA1_H + +//#define MBEDTLS_SHA1_SELF_TEST + +#include +#include + +/* MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /**< SHA-1 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA1_BAD_INPUT_DATA -0x0073 /**< SHA-1 input data was malformed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA1_ALT) +// Regular implementation +// + +/** + * \brief The SHA-1 context structure. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_sha1_context { + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[5]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ +} +mbedtls_sha1_context; + +#else /* MBEDTLS_SHA1_ALT */ +#include "sha1_alt.h" +#endif /* MBEDTLS_SHA1_ALT */ + +/** + * \brief This function initializes a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. + * This must not be \c NULL. + * + */ +void mbedtls_sha1_init(mbedtls_sha1_context *ctx); + +/** + * \brief This function clears a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to clear. This may be \c NULL, + * in which case this function does nothing. If it is + * not \c NULL, it must point to an initialized + * SHA-1 context. + * + */ +void mbedtls_sha1_free(mbedtls_sha1_context *ctx); + +/** + * \brief This function clones the state of a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param dst The SHA-1 context to clone to. This must be initialized. + * \param src The SHA-1 context to clone from. This must be initialized. + * + */ +void mbedtls_sha1_clone(mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src); + +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. This must be initialized. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1_starts_ret(mbedtls_sha1_context *ctx); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_update_ret(mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized and + * have a hash operation started. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha1_finish_ret(mbedtls_sha1_context *ctx, + unsigned char output[20]); + +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to use. This must be initialized. + * \param data The data block being processed. This must be a + * readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, + const unsigned char data[64]); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0. + * + * \param ctx The SHA-1 context to initialize. This must be initialized. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_starts(mbedtls_sha1_context *ctx); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized and + * have a hash operation started. + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_update(mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized and + * have a hash operation started. + * \param output The SHA-1 checksum result. + * This must be a writable buffer of length \c 20 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_finish(mbedtls_sha1_context *ctx, + unsigned char output[20]); + +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0. + * + * \param ctx The SHA-1 context. This must be initialized. + * \param data The data block being processed. + * This must be a readable buffer of length \c 64 bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_process(mbedtls_sha1_context *ctx, + const unsigned char data[64]); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * \param output The SHA-1 checksum result. + * This must be a writable buffer of length \c 20 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + * + */ +int mbedtls_sha1_ret(const unsigned char *input, + size_t ilen, + unsigned char output[20]); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_ret() in 2.7.0 + * + * \param input The buffer holding the input data. + * This must be a readable buffer of length \p ilen Bytes. + * \param ilen The length of the input data \p input in Bytes. + * \param output The SHA-1 checksum result. This must be a writable + * buffer of size \c 20 Bytes. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1(const unsigned char *input, + size_t ilen, + unsigned char output[20]); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SHA1_SELF_TEST) + +/** + * \brief The SHA-1 checkup routine. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \return \c 0 on success. + * \return \c 1 on failure. + * + */ +int mbedtls_sha1_self_test(int verbose); + +#endif /* MBEDTLS_SHA1_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha1.h */ diff --git a/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha256.c b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha256.c new file mode 100644 index 0000000..8b39ad4 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha256.c @@ -0,0 +1,600 @@ +/* + * FIPS-180-2 compliant SHA-256 implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +#define MBEDTLS_SHA256_C + +#if defined(MBEDTLS_SHA256_C) + +#include "sha256.h" +#include +#include + +#define mbedtls_printf //printf + +/* Internal macros meant to be called only from within the library. */ +#define MBEDTLS_INTERNAL_VALIDATE_RET( cond, ret ) do { } while( 0 ) +#define MBEDTLS_INTERNAL_VALIDATE( cond ) do { } while( 0 ) + +#define SHA256_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA ) +#define SHA256_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +#if !defined(MBEDTLS_SHA256_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +do { \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} while( 0 ) +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +do { \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} while( 0 ) +#endif + +void mbedtls_sha256_init(mbedtls_sha256_context *ctx) +{ + SHA256_VALIDATE(ctx != NULL); + + memset(ctx, 0, sizeof(mbedtls_sha256_context)); +} + +void mbedtls_sha256_free(mbedtls_sha256_context *ctx) +{ + if (ctx == NULL) { + return; + } + + //mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); + memset(ctx, 0, sizeof(mbedtls_sha256_context)); +} + +void mbedtls_sha256_clone(mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src) +{ + SHA256_VALIDATE(dst != NULL); + SHA256_VALIDATE(src != NULL); + + *dst = *src; +} + +/* + * SHA-256 context setup + */ +int mbedtls_sha256_starts_ret(mbedtls_sha256_context *ctx, int is224) +{ + SHA256_VALIDATE_RET(ctx != NULL); + SHA256_VALIDATE_RET(is224 == 0 || is224 == 1); + + ctx->total[0] = 0; + ctx->total[1] = 0; + + if (is224 == 0) { + /* SHA-256 */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; + } else { + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; + } + + ctx->is224 = is224; + + return (0); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_starts(mbedtls_sha256_context *ctx, + int is224) +{ + mbedtls_sha256_starts_ret(ctx, is224); +} +#endif + +#if !defined(MBEDTLS_SHA256_PROCESS_ALT) +static const uint32_t K[] = { + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, +}; + +#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) +#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) + +#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) + +#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) + +#define F0(x,y,z) ((x & y) | (z & (x | y))) +#define F1(x,y,z) (z ^ (x & (y ^ z))) + +#define R(t) \ +( \ + W[t] = S1(W[t - 2]) + W[t - 7] + \ + S0(W[t - 15]) + W[t - 16] \ +) + +#define P(a,b,c,d,e,f,g,h,x,K) \ +{ \ + temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + temp2 = S2(a) + F0(a,b,c); \ + d += temp1; h = temp1 + temp2; \ +} + +int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, + const unsigned char data[64]) +{ + uint32_t temp1, temp2, W[64]; + uint32_t A[8]; + unsigned int i; + + SHA256_VALIDATE_RET(ctx != NULL); + SHA256_VALIDATE_RET((const unsigned char *)data != NULL); + + for (i = 0; i < 8; i++) { + A[i] = ctx->state[i]; + } + +#if defined(MBEDTLS_SHA256_SMALLER) + for (i = 0; i < 64; i++) { + if (i < 16) { + GET_UINT32_BE(W[i], data, 4 * i); + } else { + R(i); + } + + P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i]); + + temp1 = A[7]; + A[7] = A[6]; + A[6] = A[5]; + A[5] = A[4]; + A[4] = A[3]; + A[3] = A[2]; + A[2] = A[1]; + A[1] = A[0]; + A[0] = temp1; + } +#else /* MBEDTLS_SHA256_SMALLER */ + for (i = 0; i < 16; i++) { + GET_UINT32_BE(W[i], data, 4 * i); + } + + for (i = 0; i < 16; i += 8) { + P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i + 0], K[i + 0]); + P(A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i + 1], K[i + 1]); + P(A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i + 2], K[i + 2]); + P(A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i + 3], K[i + 3]); + P(A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i + 4], K[i + 4]); + P(A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i + 5], K[i + 5]); + P(A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i + 6], K[i + 6]); + P(A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i + 7], K[i + 7]); + } + + for (i = 16; i < 64; i += 8) { + P(A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i + 0), K[i + 0]); + P(A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i + 1), K[i + 1]); + P(A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i + 2), K[i + 2]); + P(A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i + 3), K[i + 3]); + P(A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i + 4), K[i + 4]); + P(A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i + 5), K[i + 5]); + P(A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i + 6), K[i + 6]); + P(A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i + 7), K[i + 7]); + } +#endif /* MBEDTLS_SHA256_SMALLER */ + + for (i = 0; i < 8; i++) { + ctx->state[i] += A[i]; + } + + return (0); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_process(mbedtls_sha256_context *ctx, + const unsigned char data[64]) +{ + mbedtls_internal_sha256_process(ctx, data); +} +#endif +#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ + +/* + * SHA-256 process buffer + */ +int mbedtls_sha256_update_ret(mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen) +{ + int ret; + size_t fill; + uint32_t left; + + SHA256_VALIDATE_RET(ctx != NULL); + SHA256_VALIDATE_RET(ilen == 0 || input != NULL); + + if (ilen == 0) { + return (0); + } + + left = ctx->total[0] & 0x3F; + fill = 64 - left; + + ctx->total[0] += (uint32_t) ilen; + ctx->total[0] &= 0xFFFFFFFF; + + if (ctx->total[0] < (uint32_t) ilen) { + ctx->total[1]++; + } + + if (left && ilen >= fill) { + memcpy((void *)(ctx->buffer + left), input, fill); + + if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) { + return (ret); + } + + input += fill; + ilen -= fill; + left = 0; + } + + while (ilen >= 64) { + if ((ret = mbedtls_internal_sha256_process(ctx, input)) != 0) { + return (ret); + } + + input += 64; + ilen -= 64; + } + + if (ilen > 0) { + memcpy((void *)(ctx->buffer + left), input, ilen); + } + + return (0); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_update(mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen) +{ + mbedtls_sha256_update_ret(ctx, input, ilen); +} +#endif + +/* + * SHA-256 final digest + */ +int mbedtls_sha256_finish_ret(mbedtls_sha256_context *ctx, + unsigned char output[32]) +{ + int ret; + uint32_t used; + uint32_t high, low; + + SHA256_VALIDATE_RET(ctx != NULL); + SHA256_VALIDATE_RET((unsigned char *)output != NULL); + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if (used <= 56) { + /* Enough room for padding + length in current block */ + memset(ctx->buffer + used, 0, 56 - used); + } else { + /* We'll need an extra block */ + memset(ctx->buffer + used, 0, 64 - used); + + if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) { + return (ret); + } + + memset(ctx->buffer, 0, 56); + } + + /* + * Add message length + */ + high = (ctx->total[0] >> 29) + | (ctx->total[1] << 3); + low = (ctx->total[0] << 3); + + PUT_UINT32_BE(high, ctx->buffer, 56); + PUT_UINT32_BE(low, ctx->buffer, 60); + + if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) { + return (ret); + } + + /* + * Output final state + */ + PUT_UINT32_BE(ctx->state[0], output, 0); + PUT_UINT32_BE(ctx->state[1], output, 4); + PUT_UINT32_BE(ctx->state[2], output, 8); + PUT_UINT32_BE(ctx->state[3], output, 12); + PUT_UINT32_BE(ctx->state[4], output, 16); + PUT_UINT32_BE(ctx->state[5], output, 20); + PUT_UINT32_BE(ctx->state[6], output, 24); + + if (ctx->is224 == 0) { + PUT_UINT32_BE(ctx->state[7], output, 28); + } + + return (0); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_finish(mbedtls_sha256_context *ctx, + unsigned char output[32]) +{ + mbedtls_sha256_finish_ret(ctx, output); +} +#endif + +#endif /* !MBEDTLS_SHA256_ALT */ + +/* + * output = SHA-256( input buffer ) + */ +int mbedtls_sha256_ret(const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224) +{ + int ret; + mbedtls_sha256_context ctx; + + SHA256_VALIDATE_RET(is224 == 0 || is224 == 1); + SHA256_VALIDATE_RET(ilen == 0 || input != NULL); + SHA256_VALIDATE_RET((unsigned char *)output != NULL); + + mbedtls_sha256_init(&ctx); + + if ((ret = mbedtls_sha256_starts_ret(&ctx, is224)) != 0) { + goto exit; + } + + if ((ret = mbedtls_sha256_update_ret(&ctx, input, ilen)) != 0) { + goto exit; + } + + if ((ret = mbedtls_sha256_finish_ret(&ctx, output)) != 0) { + goto exit; + } + +exit: + mbedtls_sha256_free(&ctx); + + return (ret); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256(const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224) +{ + mbedtls_sha256_ret(input, ilen, output, is224); +} +#endif + +#if defined(MBEDTLS_SHA256_SELF_TEST) + +#define mbedtls_calloc calloc +#define mbedtls_free free +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha256_test_buf[3][57] = { + { "abc" }, + { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" }, + { "" } +}; + +static const size_t sha256_test_buflen[3] = { + 3, 56, 1000 +}; + +static const unsigned char sha256_test_sum[6][32] = { + /* + * SHA-224 test vectors + */ + { + 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22, + 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3, + 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7, + 0xE3, 0x6C, 0x9D, 0xA7 + }, + { + 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC, + 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50, + 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19, + 0x52, 0x52, 0x25, 0x25 + }, + { + 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8, + 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B, + 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE, + 0x4E, 0xE7, 0xAD, 0x67 + }, + + /* + * SHA-256 test vectors + */ + { + 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA, + 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23, + 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C, + 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD + }, + { + 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8, + 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39, + 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67, + 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 + }, + { + 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92, + 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67, + 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E, + 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 + } +}; + +/* + * Checkup routine + */ +int mbedtls_sha256_self_test(int verbose) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha256sum[32]; + mbedtls_sha256_context ctx; + + buf = mbedtls_calloc(1024, sizeof(unsigned char)); + if (NULL == buf) { + if (verbose != 0) { + mbedtls_printf("Buffer allocation failed\n"); + } + + return (1); + } + + mbedtls_sha256_init(&ctx); + + for (i = 0; i < 6; i++) { + j = i % 3; + k = i < 3; + + if (verbose != 0) { + mbedtls_printf(" SHA-%d test #%d: ", 256 - k * 32, j + 1); + } + + if ((ret = mbedtls_sha256_starts_ret(&ctx, k)) != 0) { + goto fail; + } + + if (j == 2) { + memset(buf, 'a', buflen = 1000); + + for (j = 0; j < 1000; j++) { + ret = mbedtls_sha256_update_ret(&ctx, buf, buflen); + if (ret != 0) { + goto fail; + } + } + + } else { + ret = mbedtls_sha256_update_ret(&ctx, sha256_test_buf[j], + sha256_test_buflen[j]); + if (ret != 0) { + goto fail; + } + } + + if ((ret = mbedtls_sha256_finish_ret(&ctx, sha256sum)) != 0) { + goto fail; + } + + + if (memcmp(sha256sum, sha256_test_sum[i], 32 - k * 4) != 0) { + ret = 1; + goto fail; + } + + if (verbose != 0) { + mbedtls_printf("passed\n"); + } + } + + if (verbose != 0) { + mbedtls_printf("\n"); + } + + goto exit; + +fail: + if (verbose != 0) { + mbedtls_printf("failed\n"); + } + +exit: + mbedtls_sha256_free(&ctx); + mbedtls_free(buf); + + return (ret); +} + +#endif /* MBEDTLS_SHA256_SELF_TEST */ + +#endif /* MBEDTLS_SHA256_C */ diff --git a/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha256.h b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha256.h new file mode 100644 index 0000000..a71850d --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha256.h @@ -0,0 +1,292 @@ +/** + * \file sha256.h + * + * \brief This file contains SHA-224 and SHA-256 definitions and functions. + * + * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SHA256_H +#define MBEDTLS_SHA256_H + +#include +#include + +//#define MBEDTLS_SHA256_SELF_TEST + +/* MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED is deprecated and should not be used. */ +#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */ +#define MBEDTLS_ERR_SHA256_BAD_INPUT_DATA -0x0074 /**< SHA-256 input data was malformed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// + +/** + * \brief The SHA-256 context structure. + * + * The structure is used both for SHA-256 and for SHA-224 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha256_starts_ret(). + */ +typedef struct mbedtls_sha256_context { + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ + int is224; /*!< Determines which function to use: + 0: Use SHA-256, or 1: Use SHA-224. */ +} +mbedtls_sha256_context; + +#else /* MBEDTLS_SHA256_ALT */ +#include "sha256_alt.h" +#endif /* MBEDTLS_SHA256_ALT */ + +/** + * \brief This function initializes a SHA-256 context. + * + * \param ctx The SHA-256 context to initialize. This must not be \c NULL. + */ +void mbedtls_sha256_init(mbedtls_sha256_context *ctx); + +/** + * \brief This function clears a SHA-256 context. + * + * \param ctx The SHA-256 context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized SHA-256 context. + */ +void mbedtls_sha256_free(mbedtls_sha256_context *ctx); + +/** + * \brief This function clones the state of a SHA-256 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha256_clone(mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src); + +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \param ctx The context to use. This must be initialized. + * \param is224 This determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_starts_ret(mbedtls_sha256_context *ctx, int is224); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_update_ret(mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-256 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-224 or SHA-256 checksum result. + * This must be a writable buffer of length \c 32 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha256_finish_ret(mbedtls_sha256_context *ctx, + unsigned char output[32]); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must + * be a readable buffer of length \c 64 Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, + const unsigned char data[64]); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0. + * + * \param ctx The context to use. This must be initialized. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_starts(mbedtls_sha256_context *ctx, + int is224); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0. + * + * \param ctx The SHA-256 context to use. This must be + * initialized and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_update(mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0. + * + * \param ctx The SHA-256 context. This must be initialized and + * have a hash operation started. + * \param output The SHA-224 or SHA-256 checksum result. This must be + * a writable buffer of length \c 32 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_finish(mbedtls_sha256_context *ctx, + unsigned char output[32]); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0. + * + * \param ctx The SHA-256 context. This must be initialized. + * \param data The buffer holding one block of data. This must be + * a readable buffer of size \c 64 Bytes. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_process(mbedtls_sha256_context *ctx, + const unsigned char data[64]); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-224 or SHA-256 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. This must + * be a writable buffer of length \c 32 Bytes. + * \param is224 Determines which function to use. This must be + * either \c 0 for SHA-256, or \c 1 for SHA-224. + */ +int mbedtls_sha256_ret(const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function calculates the SHA-224 or SHA-256 checksum + * of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0. + * + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-224 or SHA-256 checksum result. This must be + * a writable buffer of length \c 32 Bytes. + * \param is224 Determines which function to use. This must be either + * \c 0 for SHA-256, or \c 1 for SHA-224. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256(const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +#if defined(MBEDTLS_SHA256_SELF_TEST) + +/** + * \brief The SHA-224 and SHA-256 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha256_self_test(int verbose); + +#endif /* MBEDTLS_SHA256_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha256.h */ diff --git a/apps/common/third_party_profile/tuya_protocol/port/JL_to_tuya_ble_port_peripheral.c b/apps/common/third_party_profile/tuya_protocol/port/JL_to_tuya_ble_port_peripheral.c new file mode 100644 index 0000000..e31b18c --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/port/JL_to_tuya_ble_port_peripheral.c @@ -0,0 +1,32 @@ +/** + * \file tuya_ble_port_peripheral.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +//#include "tuya_ble_port.h" +//#include "tuya_ble_type.h" + + + + + + diff --git a/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port.c b/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port.c new file mode 100644 index 0000000..10c69f5 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port.c @@ -0,0 +1,667 @@ +/** + * \file tuya_ble_port.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#include "tuya_ble_port.h" +#include "tuya_ble_type.h" + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_gap_advertising_adv_data_update(uint8_t const *p_ad_data, uint8_t ad_len) +{ + return TUYA_BLE_SUCCESS; +} +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_gap_advertising_scan_rsp_data_update(uint8_t const *p_sr_data, uint8_t sr_len) +{ + return TUYA_BLE_SUCCESS; +} + +/** + *@brief Function for update the device information characteristic value. + *@param[in] p_data The pointer to the data to be updated. + *@param[in] data_len The length of the data to be updated. + * + *@note The device information characteristic uuid : 00000003-0000-1001-8001-00805F9B07D0 + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_device_info_characteristic_value_update(uint8_t const *p_data, uint8_t data_len) +{ + return TUYA_BLE_SUCCESS; +} + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_gap_disconnect(void) +{ + return TUYA_BLE_SUCCESS; +} + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_gatt_send_data(const uint8_t *p_data, uint16_t len) +{ + return TUYA_BLE_SUCCESS; +} + + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_timer_create(void **p_timer_id, uint32_t timeout_value_ms, tuya_ble_timer_mode mode, tuya_ble_timer_handler_t timeout_handler) +{ + return TUYA_BLE_SUCCESS; +} +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_timer_delete(void *timer_id) +{ + return TUYA_BLE_SUCCESS; +} +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_timer_start(void *timer_id) +{ + return TUYA_BLE_SUCCESS; +} + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_timer_restart(void *timer_id, uint32_t timeout_value_ms) +{ + return TUYA_BLE_SUCCESS; +} + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_timer_stop(void *timer_id) +{ + return TUYA_BLE_SUCCESS; +} + + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK void tuya_ble_device_delay_ms(uint32_t ms) +{ + +} + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK void tuya_ble_device_delay_us(uint32_t us) +{ + +} + + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_rand_generator(uint8_t *p_buf, uint8_t len) +{ + return TUYA_BLE_SUCCESS; +} + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_device_reset(void) +{ + return TUYA_BLE_SUCCESS; +} + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_gap_addr_get(tuya_ble_gap_addr_t *p_addr) +{ + return TUYA_BLE_SUCCESS; +} + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_gap_addr_set(tuya_ble_gap_addr_t *p_addr) +{ + return TUYA_BLE_SUCCESS; +} + +/** +*@brief +*@param +* +*@note +* +* */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_rtc_get_timestamp(uint32_t *timestamp, int32_t *timezone) +{ + return TUYA_BLE_SUCCESS; +} + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_rtc_set_timestamp(uint32_t timestamp, int32_t timezone) +{ + return TUYA_BLE_SUCCESS; +} + + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_nv_init(void) +{ + return TUYA_BLE_SUCCESS; +} +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_nv_erase(uint32_t addr, uint32_t size) +{ + return TUYA_BLE_SUCCESS; +} +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_nv_write(uint32_t addr, const uint8_t *p_data, uint32_t size) +{ + return TUYA_BLE_SUCCESS; +} +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_nv_read(uint32_t addr, uint8_t *p_data, uint32_t size) +{ + return TUYA_BLE_SUCCESS; +} + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_common_uart_init(void) +{ + return TUYA_BLE_SUCCESS; +} + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_common_uart_send_data(const uint8_t *p_data, uint16_t len) +{ + return TUYA_BLE_SUCCESS; +} + + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_task_create(void **pp_handle, const char *p_name, void (*p_routine)(void *), void *p_param, uint16_t stack_size, uint16_t priority) +{ + return true; +} +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_task_delete(void *p_handle) +{ + return true; +} +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_task_suspend(void *p_handle) +{ + return true; +} +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_task_resume(void *p_handle) +{ + return true; +} +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_msg_queue_create(void **pp_handle, uint32_t msg_num, uint32_t msg_size) +{ + return true; +} +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_msg_queue_delete(void *p_handle) +{ + return true; +} +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_msg_queue_peek(void *p_handle, uint32_t *p_msg_num) +{ + return true; +} +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_msg_queue_send(void *p_handle, void *p_msg, uint32_t wait_ms) +{ + return true; +} +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_msg_queue_recv(void *p_handle, void *p_msg, uint32_t wait_ms) +{ + return true; +} + + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_event_queue_send_port(tuya_ble_evt_param_t *evt, uint32_t wait_ms) +{ + return true; +} + + + +/** + * @brief 128 bit AES ECB encryption on speicified plaintext and keys + * @param input specifed plain text to be encypted + * @param input_len byte length of the data to be descrypted, must be multiples of 16 + * @param key keys to encrypt the plaintext + * @param output output buffer to store encrypted data + * @return encryption results + * @retval true successful + * @retval false fail + * @note least significant octet of encrypted data corresponds to encypted[0] + */ +__TUYA_BLE_WEAK bool tuya_ble_aes128_ecb_encrypt(uint8_t *key, uint8_t *input, uint16_t input_len, uint8_t *output) +{ + return true; +} + +/** + * @brief 128 bit AES ECB decryption on speicified encrypted data and keys + * @param input specifed encypted data to be decypted + * @param input_len byte length of the data to be descrypted, must be multiples of 16 + * @param key keys to decrypt the data + * @param output output buffer to store plain data + * @return decryption results + * @retval true successful + * @retval false fail + * @note least significant octet of encrypted data corresponds to encypted[0] +*/ +__TUYA_BLE_WEAK bool tuya_ble_aes128_ecb_decrypt(uint8_t *key, uint8_t *input, uint16_t input_len, uint8_t *output) +{ + return true; +} +/** + * @brief 128 bit AES CBC encryption on speicified plaintext and keys + * @param input specifed plain text to be encypted + * @param key keys to encrypt the plaintext + * @param output output buffer to store encrypted data + * @param iv initialization vector (IV) for CBC mode + * @param input_len byte length of the data to be descrypted, must be multiples of 16 + * @return encryption results + * @retval true successful + * @retval false fail + * @note least significant octet of encrypted data corresponds to encypted[0] + */ +__TUYA_BLE_WEAK bool tuya_ble_aes128_cbc_encrypt(uint8_t *key, uint8_t *iv, uint8_t *input, uint16_t input_len, uint8_t *output) +{ + return true; +} +/** + * @brief 128 bit AES CBC descryption on speicified plaintext and keys + * @param input specifed encypted data to be decypted + * @param key keys to decrypt the data + * @param output output buffer to store plain data + * @param iv initialization vector (IV) for CBC mode + * @param input_len byte length of the data to be descrypted, must be multiples of 16 + * @return encryption results + * @retval true successful + * @retval false fail + * @note least significant octet of encrypted data corresponds to encypted[0] + */ +__TUYA_BLE_WEAK bool tuya_ble_aes128_cbc_decrypt(uint8_t *key, uint8_t *iv, uint8_t *input, uint16_t input_len, uint8_t *output) +{ + return true; +} +/** + * @brief MD5 checksum + * @param input specifed plain text to be encypted + * @param output output buffer to store md5 result data,output data len is always 16 + * @param input_len byte length of the data to be encypted + * @return encryption results + * @retval true successful + * @retval false fail + * @note + */ +__TUYA_BLE_WEAK bool tuya_ble_md5_crypt(uint8_t *input, uint16_t input_len, uint8_t *output) +{ + return true; +} + +/** + * @brief SHA256 checksum + * @param input specifed plain text to be encypted + * @param output output buffer to store sha256 result data,output data len is always 32 + * @param input_len byte length of the data to be encypted + * @return encryption results + * @retval true successful + * @retval false fail + * @note + */ +__TUYA_BLE_WEAK bool tuya_ble_sha256_crypt(const uint8_t *input, uint16_t input_len, uint8_t *output) +{ + return true; +} + +/** + *@brief storage private data, for example: token/dev cert/keys + *@param private_data_type describe private data type, see the tuay_ble_private_data_type enum define + *@param p_data storage data point + *@param data_size p_data size + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_storage_private_data(tuya_ble_private_data_type private_data_type, uint8_t *p_data, uint32_t data_size) +{ + return 0; +} + +/** + *@brief Get device certificate length + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK uint32_t tuya_ble_get_dev_crt_len(void) +{ + return 0; +} + +/** + *@brief Get device certificate data + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_get_dev_crt_der(uint8_t *p_der, uint32_t der_len) +{ + return TUYA_BLE_ERR_NOT_FOUND; +} + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_ecc_keypair_gen_secp256r1(uint8_t *public_key, uint8_t *private_key) +{ + return TUYA_BLE_ERR_INVALID_STATE; +} + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_ecc_shared_secret_compute_secp256r1(uint8_t *public_key, uint8_t *private_key, uint8_t *secret_key) +{ + return TUYA_BLE_ERR_INVALID_STATE; +} + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_ecc_sign_secp256r1(const uint8_t *p_sk, const uint8_t *p_data, uint32_t data_size, uint8_t *p_sig) +{ + return TUYA_BLE_ERR_INVALID_STATE; +} + +/** + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_ecc_verify_secp256r1(const uint8_t *p_pk, const uint8_t *p_data, uint32_t data_size, const uint8_t *p_sig) +{ + return TUYA_BLE_ERR_RESOURCES; +} + +/** + * @brief This function calculates the full generic HMAC + * on the input buffer with the provided key. + * @param key The HMAC secret key. + * @param key_len The length of the HMAC secret key in Bytes. + * @param input specifed plain text to be encypted + * @param output output buffer to store the result data + * @param input_len byte length of the data to be encypted + * @return encryption results + * @retval true successful + * @retval false fail + * @note + */ +__TUYA_BLE_WEAK bool tuya_ble_hmac_sha1_crypt(const uint8_t *key, uint32_t key_len, const uint8_t *input, uint32_t input_len, uint8_t *output) +{ + return true; +} + +/** + * @brief This function calculates the full generic HMAC + * on the input buffer with the provided key. + * @param key The HMAC secret key. + * @param key_len The length of the HMAC secret key in Bytes. + * @param input specifed plain text to be encypted + * @param output output buffer to store the result data + * @param input_len byte length of the data to be encypted + * @return encryption results + * @retval true successful + * @retval false fail + * @note + */ +__TUYA_BLE_WEAK bool tuya_ble_hmac_sha256_crypt(const uint8_t *key, uint32_t key_len, const uint8_t *input, uint32_t input_len, uint8_t *output) +{ + return true; +} + + +/** + * @brief Allocate a memory block with required size. + * + * + * @param[in] size Required memory size. + * + * @return The address of the allocated memory block. If the address is NULL, the + * memory allocation failed. + */ +__TUYA_BLE_WEAK void *tuya_ble_port_malloc(uint32_t size); + +/** + * + * @brief Free a memory block that had been allocated. + * + * @param[in] pv The address of memory block being freed. + * + * @return None. + */ +__TUYA_BLE_WEAK void tuya_ble_port_free(void *pv); + + diff --git a/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port.h b/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port.h new file mode 100644 index 0000000..8a770c2 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port.h @@ -0,0 +1,710 @@ +/** + * \file tuya_ble_port.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + + +#ifndef TUYA_BLE_PORT_H__ +#define TUYA_BLE_PORT_H__ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" +#include "tuya_ble_config.h" +#include "tuya_ble_port_peripheral.h" + +void tuya_ble_device_enter_critical(void); +void tuya_ble_device_exit_critical(void); + +#if defined(TUYA_BLE_PORT_PLATFORM_HEADER_FILE) +/** + * @file TUYA_BLE_PORT_PLATFORM_HEADER_FILE + * + * @brief Platform header file + + * @note + * Must declare or define 'tuya_ble_device_enter_critical' and 'tuya_ble_device_exit_critical' in the platform header file. + + * An example on the nrf52832 platform is as follows + + * @example + + * @code + #define TUYA_BLE_PORT_PLATFORM_HEADER_FILE "tuya_ble_port_nrf52832.h" ///disconnect) { + ble_operation->disconnect(NULL); + return TUYA_BLE_SUCCESS; + } + + return TUYA_BLE_ERR_INVALID_STATE; +} + +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_gatt_send_data(const uint8_t *p_data, uint16_t len) +{ + int ret = 0; + struct ble_server_operation_t *ble_operation = NULL; + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + ble_get_server_operation_table(&ble_operation); + if (ble_operation && ble_operation->send_data) { + ret = ble_operation->send_data(NULL, p_data, len); + TUYA_BLE_LOG_DEBUG("%d\n", ret); + return ret ? TUYA_BLE_ERR_UNKNOWN : TUYA_BLE_SUCCESS; + } + return TUYA_BLE_ERR_INVALID_STATE; +} + +struct timer_param { + tuya_ble_timer_mode mode; + tuya_ble_timer_handler_t timeout_handler; + uint32_t timeout_value_ms; +}; + +static struct timer_param ble_timer; + +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_timer_create(void **p_timer_id, uint32_t timeout_value_ms, tuya_ble_timer_mode mode, tuya_ble_timer_handler_t timeout_handler) +{ + *p_timer_id = malloc(2); + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + if (*p_timer_id) { + //我们的timer不需要create,所以这里只需要保存一下信息 + *(u16 *)(*p_timer_id) = 0; + ble_timer.mode = mode; + ble_timer.timeout_handler = timeout_handler; + ble_timer.timeout_value_ms = timeout_value_ms; + return TUYA_BLE_SUCCESS; + } + + return TUYA_BLE_ERR_NO_MEM; +} +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_timer_delete(void *timer_id) +{ + u16 id = *(u16 *)timer_id; + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + if (id) { + if (ble_timer.mode == TUYA_BLE_TIMER_SINGLE_SHOT) { + sys_timeout_del(id); + } else { + sys_timer_del(id); + } + } + free(timer_id); + return TUYA_BLE_SUCCESS; +} +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_timer_start(void *timer_id) +{ + u16 id = *(u16 *)timer_id; + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + if (id) { + if (ble_timer.mode == TUYA_BLE_TIMER_SINGLE_SHOT) { + sys_timeout_del(id); + } else { + sys_timer_del(id); + } + } + u16(*sys_timer_create)(void *priv, void (*func)(void *priv), u32 msec); + sys_timer_create = (ble_timer.mode == TUYA_BLE_TIMER_SINGLE_SHOT) ? sys_timeout_add : sys_timer_add; + *(u16 *)timer_id = sys_timer_create(NULL, ble_timer.timeout_handler, ble_timer.timeout_value_ms); + return TUYA_BLE_SUCCESS; +} + +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_timer_restart(void *timer_id, uint32_t timeout_value_ms) +{ + u16 id = *(u16 *)timer_id; + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + sys_timer_modify(id, timeout_value_ms); + sys_timer_re_run(id); + return TUYA_BLE_SUCCESS; +} + +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_timer_stop(void *timer_id) +{ + return TUYA_BLE_SUCCESS; +} + + +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK void tuya_ble_device_delay_ms(uint32_t ms) +{ + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + if (ms < 10) { + ms = 10; + } + os_time_dly(ms / 10); +} + +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK void tuya_ble_device_delay_us(uint32_t us) +{ + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + delay_us(us); +} + + +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_rand_generator(uint8_t *p_buf, uint8_t len) +{ + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + get_random_number(p_buf, len); + return TUYA_BLE_SUCCESS; +} + +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_device_reset(void) +{ + return TUYA_BLE_SUCCESS; +} + +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_gap_addr_get(tuya_ble_gap_addr_t *p_addr) +{ + u8 ret; + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + if (p_addr->addr_type == TUYA_BLE_ADDRESS_TYPE_PUBLIC) { + ret = le_controller_get_mac(p_addr->addr); + } else if (p_addr->addr_type == TUYA_BLE_ADDRESS_TYPE_RANDOM) { + ret = le_controller_get_random_mac(p_addr->addr); + } + return ret ? TUYA_BLE_ERR_NOT_FOUND : TUYA_BLE_SUCCESS; +} + +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_gap_addr_set(tuya_ble_gap_addr_t *p_addr) +{ + u8 ret; + ble_op_adv_enable(0); + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + TUYA_BLE_LOG_DEBUG("tuya_ble_gap_addr_set=%d\n", p_addr->addr_type); + TUYA_BLE_LOG_HEXDUMP_DEBUG("addr", p_addr->addr, 6); + ble_op_set_own_address_type(p_addr->addr_type); + if (p_addr->addr_type == TUYA_BLE_ADDRESS_TYPE_PUBLIC) { + ret = le_controller_set_mac(p_addr->addr); + } else if (p_addr->addr_type == TUYA_BLE_ADDRESS_TYPE_RANDOM) { + ret = le_controller_set_random_mac(p_addr->addr); + } + ble_op_adv_enable(1); + return ret ? TUYA_BLE_ERR_INVALID_ADDR : TUYA_BLE_SUCCESS; +} + +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK void tuya_ble_device_enter_critical(void) +{ + OS_ENTER_CRITICAL(); +} +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK void tuya_ble_device_exit_critical(void) +{ + OS_EXIT_CRITICAL(); +} + +/* +*@brief +*@param +* +*@note +* +* */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_rtc_get_timestamp(uint32_t *timestamp, int32_t *timezone) +{ + //目前用不到 + *timestamp = 0; + *timezone = 0; + return TUYA_BLE_SUCCESS; +} +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_rtc_set_timestamp(uint32_t timestamp, int32_t timezone) +{ + return TUYA_BLE_SUCCESS; +} + +typedef enum _FLASH_ERASER { + CHIP_ERASER, + BLOCK_ERASER,//4k + SECTOR_ERASER,//64k +} FLASH_ERASER; + + +// +extern bool sfc_erase(FLASH_ERASER cmd, u32 addr); +extern u32 sdfile_cpu_addr2flash_addr(u32 offset); + +#define USER_FILE_NAME SDFILE_APP_ROOT_PATH"USERIF" +#define NV_MODE_FILE 0 //固定放在一个指定的区域,一般情况下不会被意外擦除,flash比较大的方案建议用这个 +#define NV_MODE_VM 1 //用VM存,被意外擦除的概率比较高,比如升级的时候,flash空间不够的时候用这个 +#define TUYA_BLE_NV_MODE NV_MODE_FILE +//使用文件的的方式保存数据,需要在ini文件添加下面的配置 +/* +USERIF_ADR=AUTO; +USERIF_LEN=0x4000; +USERIF_OPT=1; +*/ + +FILE *code_fp = NULL; + +struct vfs_attr code_attr = {0}; +struct vfs_attr attr; + +typedef struct __tuya_addr_to_vfs { + u32 tuya_start_addr;//0 + u32 vfs_satrt_addr;//1 +} tuya_addr_to_vfs; + +static tuya_addr_to_vfs addr_sw; +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_nv_init(void) +{ +#if (TUYA_BLE_NV_MODE == NV_MODE_FILE) + if (code_fp) { + return TUYA_BLE_SUCCESS; + } + code_fp = fopen(USER_FILE_NAME, "r+w"); + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + if (code_fp == NULL) { + TUYA_BLE_LOG_DEBUG("file open err!!!"); + return TUYA_BLE_ERR_RESOURCES; + } + + fget_attrs(code_fp, &attr); + if (attr.fsize < 2048) { + TUYA_BLE_LOG_DEBUG("file size err!!!"); + } + addr_sw.tuya_start_addr = 0; + addr_sw.vfs_satrt_addr = attr.sclust; + TUYA_BLE_LOG_DEBUG("addr %x,%x\n", attr.sclust, addr_sw.tuya_start_addr); + TUYA_BLE_LOG_DEBUG("tuya_ble_nv_initok\n"); +#endif + + return TUYA_BLE_SUCCESS; +} +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_nv_erase(uint32_t addr, uint32_t size) +{ +#if (TUYA_BLE_NV_MODE == NV_MODE_FILE) + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + if (code_fp == NULL) { + TUYA_BLE_LOG_DEBUG("file ptr err!!!"); + return TUYA_BLE_ERR_RESOURCES; + } + u32 flash_addr = sdfile_cpu_addr2flash_addr(addr_sw.vfs_satrt_addr + addr); + sfc_erase(SECTOR_ERASER, flash_addr);// 4k +#endif + return TUYA_BLE_SUCCESS; +} +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_nv_write(uint32_t addr, const uint8_t *p_data, uint32_t size) +{ +#if (TUYA_BLE_NV_MODE == NV_MODE_FILE) + FILE *write_fp = code_fp; + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + if (code_fp == NULL) { + TUYA_BLE_LOG_DEBUG("file ptr err!!!"); + return TUYA_BLE_ERR_RESOURCES; + } + int ret = 0; + ret = fseek(write_fp, addr, SEEK_SET); + TUYA_BLE_LOG_DEBUG("fseek=%x,addr_star=%d,size=%d\n", addr, ret, size); + int r = fwrite(write_fp, p_data, size);//更新数据到自定义区,写数据前需要擦除,确保处于FF状态才能成功写入 + if (r != size) { + TUYA_BLE_LOG_DEBUG("write file error code %x", r); + } +#else + u8 index; + switch (addr) { + case TUYA_BLE_AUTH_FLASH_ADDR: + index = CFG_USER_TUYA_INFO_AUTH; + break; + case TUYA_BLE_AUTH_FLASH_BACKUP_ADDR: + index = CFG_USER_TUYA_INFO_AUTH_BK; + break; + case TUYA_BLE_SYS_FLASH_ADDR: + index = CFG_USER_TUYA_INFO_SYS; + break; + case TUYA_BLE_SYS_FLASH_BACKUP_ADDR: + index = CFG_USER_TUYA_INFO_SYS_BK; + break; + + default: + return TUYA_BLE_ERR_INVALID_ADDR; + } + if (syscfg_write(index, p_data, size) != size) { + return TUYA_BLE_ERR_INVALID_ADDR; + } +#endif + //发消息,用来给TWS同步app配对数据 + if (addr == TUYA_BLE_AUTH_FLASH_ADDR) { + if (ble_task.ble_task_name) { + os_taskq_post_msg(ble_task.ble_task_name, 1, BLE_TASK_MSG_INFO_SYNC_AUTH); + } + } else if (addr == TUYA_BLE_SYS_FLASH_ADDR) { + if (ble_task.ble_task_name) { + os_taskq_post_msg(ble_task.ble_task_name, 1, BLE_TASK_MSG_INFO_SYNC_SYS); + } + } + return TUYA_BLE_SUCCESS; +} +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_nv_read(uint32_t addr, uint8_t *p_data, uint32_t size) +{ +#if (TUYA_BLE_NV_MODE == NV_MODE_FILE) + FILE *read_fp = code_fp; + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + if (code_fp == NULL) { + TUYA_BLE_LOG_DEBUG("file ptr err!!!"); + return TUYA_BLE_ERR_RESOURCES; + } + fseek(read_fp, addr, SEEK_SET); + fread(read_fp, p_data, size);//文件模式读取自定义数据区 + TUYA_BLE_LOG_HEXDUMP_DEBUG("file read:", p_data, size); +#else + u8 index; + switch (addr) { + case TUYA_BLE_AUTH_FLASH_ADDR: + index = CFG_USER_TUYA_INFO_AUTH; + break; + case TUYA_BLE_AUTH_FLASH_BACKUP_ADDR: + index = CFG_USER_TUYA_INFO_AUTH_BK; + break; + case TUYA_BLE_SYS_FLASH_ADDR: + index = CFG_USER_TUYA_INFO_SYS; + break; + case TUYA_BLE_SYS_FLASH_BACKUP_ADDR: + index = CFG_USER_TUYA_INFO_SYS_BK; + break; + + default: + return TUYA_BLE_ERR_INVALID_ADDR; + } + syscfg_read(index, p_data, size); +#endif + return TUYA_BLE_SUCCESS; +} + +bool uart_dev_test_init_api(void); +u16 uart_dev_test_send_api(void *data, u16 len); +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_common_uart_init(void) +{ + /* bool ret = uart_dev_test_init_api(); */ + /* return ret ? TUYA_BLE_SUCCESS : TUYA_BLE_ERR_BUSY; */ + return TUYA_BLE_SUCCESS; +} + +extern tuya_ble_status_t tuya_ble_gatt_receive_data(uint8_t *p_data, uint16_t len); +u8 JL_tuya_ble_gatt_receive_data(u8 *p_data, u16 len) +{ + return tuya_ble_gatt_receive_data(p_data, len); +} +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK tuya_ble_status_t tuya_ble_common_uart_send_data(const uint8_t *p_data, uint16_t len) +{ + /* u16 wlen = uart_dev_test_send_api(p_data, len); */ + /* return wlen == len ? TUYA_BLE_SUCCESS : TUYA_BLE_ERR_BUSY; */ + return TUYA_BLE_SUCCESS; +} + + +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_task_create(void **pp_handle, const char *p_name, void (*p_routine)(void *), void *p_param, uint16_t stack_size, uint16_t priority) +{ + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + int ret = os_task_create(p_routine, p_param, priority, stack_size, 256, p_name); + if (ret == 0) { + ble_task.ble_task_name = p_name; + os_sem_create(&ble_task.ble_sem, 0); + TUYA_BLE_LOG_DEBUG("%s succ\n", __func__); + } + return ret ? false : true; +} +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_task_delete(void *p_handle) +{ + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + if (ble_task.ble_task_name) { + os_task_del(ble_task.ble_task_name); + os_sem_del(&ble_task.ble_sem, 0); + ble_task.ble_task_name = NULL; + } + return true; +} +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_task_suspend(void *p_handle) +{ + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + if (ble_task.ble_task_name) { + os_sem_pend(&ble_task.ble_sem, 0); + } + return true; +} +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_task_resume(void *p_handle) +{ + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + if (ble_task.ble_task_name) { + os_sem_set(&ble_task.ble_sem, 1); + os_sem_post(&ble_task.ble_sem); + } + return true; +} + +struct ble_msg_queue { + cbuffer_t queue_hdl; + u8 *queue; + u8 enable; + u32 msg_size; +}; + +struct ble_msg_queue ble_queue; + +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_msg_queue_create(void **pp_handle, uint32_t msg_num, uint32_t msg_size) +{ + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + memset(&ble_queue, 0x00, sizeof(ble_queue)); + ble_queue.queue = malloc(msg_size * msg_num); + if (ble_queue.queue) { + *pp_handle = (void *)ble_queue.queue; + ble_queue.msg_size = msg_size; + cbuf_init(&ble_queue.queue_hdl, ble_queue.queue, msg_size * msg_num); + ble_queue.enable = 1; + return true; + } + return false; +} +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_msg_queue_delete(void *p_handle) +{ + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + if (ble_queue.enable) { + ble_queue.enable = 0; + free(ble_queue.queue); + ble_queue.queue = NULL; + } + return true; +} +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_msg_queue_peek(void *p_handle, uint32_t *p_msg_num) +{ + return true; +} + +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_msg_queue_send(void *p_handle, void *p_msg, uint32_t wait_ms) +{ + if (ble_queue.enable) { + //TUYA_BLE_LOG_DEBUG("%s\n", __func__); + int wlen = cbuf_write(&ble_queue.queue_hdl, p_msg, ble_queue.msg_size); + os_taskq_post_msg(ble_task.ble_task_name, 2, BLE_TASK_MSG_MSG_COMES, (u32)p_handle); + } + return true; +} + +static bool tuya_ble_os_msg_queue_recv_sub_deal(void *p_msg) +{ + tuya_ble_evt_param_t *evt = (tuya_ble_evt_param_t *)p_msg; + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + bool ret = false; + switch (evt->hdr.event) { + case TUYA_BLE_EVT_DATA_PASSTHROUGH: + break; + + default: + return true; + } + + return ret; +} + +void (*tuya_cb_handler)(tuya_ble_cb_evt_param_t *event) = NULL; +void tuya_event_to_earphone(u8 msg, u8 sub_msg, u32 value); +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_os_msg_queue_recv(void *p_handle, void *p_msg, uint32_t wait_ms) +{ + int ret; + int msg[16]; + ret = os_task_pend("taskq", msg, ARRAY_SIZE(msg)); + if (ret != OS_TASKQ) { + return false; + } + if (msg[0] != Q_MSG) { + return false; + } + + //TUYA_BLE_LOG_DEBUG("tuya_ble_os_msg_queue_recv\n"); + + bool b_ret = false; + + switch (msg[1]) { + case BLE_TASK_MSG_MSG_COMES: + cbuf_read(&ble_queue.queue_hdl, p_msg, ble_queue.msg_size); + if ((u32)msg[2] == (u32)ble_queue.queue) { + b_ret = tuya_ble_os_msg_queue_recv_sub_deal(p_msg); + } else { + tuya_cb_handler = (void(*)(tuya_ble_cb_evt_param_t *))msg[2]; + tuya_cb_handler((tuya_ble_cb_evt_param_t *)p_msg); + } + break; + + case BLE_TASK_MSG_INFO_SYNC_AUTH: + //设备信息变更(比如mac变更,但是正常使用不会跑这里)要同步tws + // tuya_event_to_earphone(TUYA_BLE_TO_EARPHONE_SYNC_AUTH_MSG, 0, 0); + break; + + case BLE_TASK_MSG_INFO_SYNC_SYS: + //app配对信息变更要同步tws + //tuya_event_to_earphone(TUYA_BLE_TO_EARPHONE_SYNC_SYS_MSG, 0, 0); + break; + + default: + break; + } + + //TUYA_BLE_LOG_DEBUG("deal ret %d\n", b_ret); + + return b_ret; +} + + +/* + *@brief + *@param + * + *@note + * + * */ +__TUYA_BLE_WEAK bool tuya_ble_event_queue_send_port(tuya_ble_evt_param_t *evt, uint32_t wait_ms) +{ + TUYA_BLE_LOG_DEBUG("%s\n", __func__); + return tuya_ble_os_msg_queue_send((void *)ble_queue.queue, evt, wait_ms); +} + + + +/** + * @brief 128 bit AES ECB encryption on speicified plaintext and keys + * @param input specifed plain text to be encypted + * @param input_len byte length of the data to be descrypted, must be multiples of 16 + * @param key keys to encrypt the plaintext + * @param output output buffer to store encrypted data + * @return encryption results + * @retval true successful + * @retval false fail + * @note least significant octet of encrypted data corresponds to encypted[0] + */ +__TUYA_BLE_WEAK bool tuya_ble_aes128_ecb_encrypt(uint8_t *key, uint8_t *input, uint16_t input_len, uint8_t *output) +{ + uint16_t length; + mbedtls_aes_context aes_ctx; + // + if (input_len % 16) { + return false; + } + + length = input_len; + + mbedtls_aes_init(&aes_ctx); + + mbedtls_aes_setkey_enc(&aes_ctx, key, 128); + + while (length > 0) { + mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_ENCRYPT, input, output); + input += 16; + output += 16; + length -= 16; + } + + mbedtls_aes_free(&aes_ctx); + + return true; +} + +/** + * @brief 128 bit AES ECB decryption on speicified encrypted data and keys + * @param input specifed encypted data to be decypted + * @param input_len byte length of the data to be descrypted, must be multiples of 16 + * @param key keys to decrypt the data + * @param output output buffer to store plain data + * @return decryption results + * @retval true successful + * @retval false fail + * @note least significant octet of encrypted data corresponds to encypted[0] +*/ +__TUYA_BLE_WEAK bool tuya_ble_aes128_ecb_decrypt(uint8_t *key, uint8_t *input, uint16_t input_len, uint8_t *output) +{ + uint16_t length; + mbedtls_aes_context aes_ctx; + // + if (input_len % 16) { + return false; + } + + length = input_len; + + mbedtls_aes_init(&aes_ctx); + + mbedtls_aes_setkey_dec(&aes_ctx, key, 128); + + while (length > 0) { + mbedtls_aes_crypt_ecb(&aes_ctx, MBEDTLS_AES_DECRYPT, input, output); + input += 16; + output += 16; + length -= 16; + } + + mbedtls_aes_free(&aes_ctx); + return true; +} +/** + * @brief 128 bit AES CBC encryption on speicified plaintext and keys + * @param input specifed plain text to be encypted + * @param key keys to encrypt the plaintext + * @param output output buffer to store encrypted data + * @param iv initialization vector (IV) for CBC mode + * @param input_len byte length of the data to be descrypted, must be multiples of 16 + * @return encryption results + * @retval true successful + * @retval false fail + * @note least significant octet of encrypted data corresponds to encypted[0] + */ +__TUYA_BLE_WEAK bool tuya_ble_aes128_cbc_encrypt(uint8_t *key, uint8_t *iv, uint8_t *input, uint16_t input_len, uint8_t *output) +{ + mbedtls_aes_context aes_ctx; + + if (input_len % 16) { + return false; + } + + mbedtls_aes_init(&aes_ctx); + + mbedtls_aes_setkey_enc(&aes_ctx, key, 128); + + mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, input_len, iv, input, output); + + mbedtls_aes_free(&aes_ctx); + + return true; +} +/** + * @brief 128 bit AES CBC descryption on speicified plaintext and keys + * @param input specifed encypted data to be decypted + * @param key keys to decrypt the data + * @param output output buffer to store plain data + * @param iv initialization vector (IV) for CBC mode + * @param input_len byte length of the data to be descrypted, must be multiples of 16 + * @return encryption results + * @retval true successful + * @retval false fail + * @note least significant octet of encrypted data corresponds to encypted[0] + */ +__TUYA_BLE_WEAK bool tuya_ble_aes128_cbc_decrypt(uint8_t *key, uint8_t *iv, uint8_t *input, uint16_t input_len, uint8_t *output) +{ + mbedtls_aes_context aes_ctx; + + if (input_len % 16) { + return false; + } + + mbedtls_aes_init(&aes_ctx); + + mbedtls_aes_setkey_dec(&aes_ctx, key, 128); + + mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, input_len, iv, input, output); + + mbedtls_aes_free(&aes_ctx); + + return true; +} +/** + * @brief MD5 checksum + * @param input specifed plain text to be encypted + * @param output output buffer to store md5 result data,output data len is always 16 + * @param input_len byte length of the data to be encypted + * @return encryption results + * @retval true successful + * @retval false fail + * @note + */ +__TUYA_BLE_WEAK bool tuya_ble_md5_crypt(uint8_t *input, uint16_t input_len, uint8_t *output) +{ + mbedtls_md5_context md5_ctx; + mbedtls_md5_init(&md5_ctx); + mbedtls_md5_starts(&md5_ctx); + mbedtls_md5_update(&md5_ctx, input, input_len); + mbedtls_md5_finish(&md5_ctx, output); + mbedtls_md5_free(&md5_ctx); + return true; +} + +/** + * @brief This function calculates the full generic HMAC + * on the input buffer with the provided key. + * @param key The HMAC secret key. + * @param key_len The length of the HMAC secret key in Bytes. + * @param input specifed plain text to be encypted + * @param output output buffer to store the result data + * @param input_len byte length of the data to be encypted + * @return encryption results + * @retval true successful + * @retval false fail + * @note + */ +__TUYA_BLE_WEAK bool tuya_ble_hmac_sha1_crypt(const uint8_t *key, uint32_t key_len, const uint8_t *input, uint32_t input_len, uint8_t *output) +{ + return true; +} + +/** + * @brief This function calculates the full generic HMAC + * on the input buffer with the provided key. + * @param key The HMAC secret key. + * @param key_len The length of the HMAC secret key in Bytes. + * @param input specifed plain text to be encypted + * @param output output buffer to store the result data + * @param input_len byte length of the data to be encypted + * @return encryption results + * @retval true successful + * @retval false fail + * @note + */ +__TUYA_BLE_WEAK bool tuya_ble_hmac_sha256_crypt(const uint8_t *key, uint32_t key_len, const uint8_t *input, uint32_t input_len, uint8_t *output) +{ + return true; +} + + +/** + * \brief Allocate a memory block with required size. + * + * + * \param[in] size Required memory size. + * + * \return The address of the allocated memory block. If the address is NULL, the + * memory allocation failed. + */ +__TUYA_BLE_WEAK void *tuya_ble_port_malloc(uint32_t size) +{ + return malloc(size); +} + + + +/** + * + * \brief Free a memory block that had been allocated. + * + * \param[in] pv The address of memory block being freed. + * + * \return None. + */ +__TUYA_BLE_WEAK void tuya_ble_port_free(void *pv) +{ + return free(pv); +} + + + + + diff --git a/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port_peripheral.c b/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port_peripheral.c new file mode 100644 index 0000000..a9507b6 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port_peripheral.c @@ -0,0 +1,32 @@ +/** + * \file tuya_ble_port_peripheral.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#include "tuya_ble_port.h" +#include "tuya_ble_type.h" + + + + + + diff --git a/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port_peripheral.h b/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port_peripheral.h new file mode 100644 index 0000000..067e943 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port_peripheral.h @@ -0,0 +1,43 @@ +/** + * \file tuya_ble_port_peripheral.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + + +#ifndef TUYA_BLE_PORT_PERIPHERAL_H__ +#define TUYA_BLE_PORT_PERIPHERAL_H__ + + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" + + + + + + +#endif + + + + + diff --git a/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_stdlib.h b/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_stdlib.h new file mode 100644 index 0000000..722aabd --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_stdlib.h @@ -0,0 +1,86 @@ +/** + * \file tuya_ble_stdlib.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + + +#ifndef TUYA_BLE_STDLIB_H__ +#define TUYA_BLE_STDLIB_H__ + +/* + * If not using the standard library,please set to 0 . Then implement the library functions required by the TUYA BLE SDK in other files and declare in this file. + */ + +#define TUYA_BLE_USE_STDLIB 1 + +#if TUYA_BLE_USE_STDLIB + +#include "cpu.h" +#include +#include +#include +#include + +#else + +// +typedef unsigned char uint8_t ; +typedef signed char int8_t; + +typedef unsigned short uint16_t; +typedef signed short int16_t; + +typedef int int32_t; +typedef unsigned int uint32_t; + +typedef long long int64_t; +typedef unsigned long long uint64_t; + +#define true 1 +#define false 0 + +.......... + +void *memset(void *str, int32_t c, uint32_t n); +void *memcpy(void *str1, const void *str2, uint32_t n); +int32_t memcmp(const void *str1, const void *str2, uint32_t n); +uint32_t strlen(const char *str); +int32_t rand(void); +int64_t atoll(const char *str); + +............. + + + +#endif + + + + + + +#endif + + + + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_api.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_api.h new file mode 100644 index 0000000..03bcbc6 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_api.h @@ -0,0 +1,405 @@ +/** + * \file tuya_ble_api.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + + +#ifndef TUYA_BLE_API_H__ +#define TUYA_BLE_API_H__ + +#include "tuya_ble_type.h" +#include "tuya_ble_internal_config.h" +#include "tuya_ble_port.h" + +#if (TUYA_BLE_USE_OS==0) +/** + * @brief Function for executing all enqueued tasks. + * + * @note This function must be called from within the main loop. It will + * execute all events scheduled since the last time it was called. + * */ +void tuya_ble_main_tasks_exec(void); +#endif + +/** + * @brief Function for transmit ble data from peer devices to tuya sdk. + * + * @note This function must be called from where the ble data is received. + *. + * */ +tuya_ble_status_t tuya_ble_gatt_receive_data(uint8_t *p_data, uint16_t len); + +/** + * @brief Function for transmit uart data to tuya sdk. + * + * @note This function must be called from where the uart data is received. + *. + * */ +tuya_ble_status_t tuya_ble_common_uart_receive_data(uint8_t *p_data, uint16_t len); + +/** + * @brief Function for send the full instruction received from uart to the sdk. + * + * @param + * [in]p_data : pointer to full instruction data(Complete instruction,include0x55 or 0x66 0xaa and checksum.) + * [in]len : Number of bytes of pdata. + * + * @note If the application uses a custom uart parsing algorithm to obtain the full uart instruction,then call this function to send the full instruction. + * + * */ +tuya_ble_status_t tuya_ble_common_uart_send_full_instruction_received(uint8_t *p_data, uint16_t len); + + +/** + * @brief Function for update the device id to tuya sdk. + * + * @note the following id of the device must be update immediately when changed. + *. + * */ + +tuya_ble_status_t tuya_ble_device_update_product_id(tuya_ble_product_id_type_t type, uint8_t len, uint8_t *p_buf); + +tuya_ble_status_t tuya_ble_device_update_login_key(uint8_t *p_buf, uint8_t len); + +#if ((TUYA_BLE_PROTOCOL_VERSION_HIGN==4) && (TUYA_BLE_BEACON_KEY_ENABLE)) +tuya_ble_status_t tuya_ble_device_update_beacon_key(uint8_t *p_buf, uint8_t len); +#endif + +tuya_ble_status_t tuya_ble_device_update_bound_state(uint8_t state); + +tuya_ble_status_t tuya_ble_device_update_mcu_version(uint32_t mcu_firmware_version, uint32_t mcu_hardware_version); + +/** + * @brief Function for initialize the tuya sdk. + * + * @note appliction should call this after all platform init complete. + *. + * */ + +tuya_ble_status_t tuya_ble_sdk_init(tuya_ble_device_param_t *param_data); + + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN==4) + +/** + * @brief Function for send the dp point data. + * + * @param [in]sn: The sending sequence number of the application definition management. + * [in]type : DP_SEND_TYPE_ACTIVE- The device actively sends dp data;DP_SEND_TYPE_PASSIVE- The device passively sends dp data. For example, in order to answer the dp query command of the mobile app. Currently only applicable to WIFI+BLE combo devices. + * [in]mode : See the description in the 'tuya_ble_type.h' file for details. + * [in]ack : See the description in the 'tuya_ble_type.h' file for details. + * [in]p_dp_data : The pointer of dp data . + * [in]dp_data_len : The length of dp data . + * @note new api, The length of each dp data sent through this function must be 2 bytes. DTLD->'L' must be 2 bytes. + *. + * */ +tuya_ble_status_t tuya_ble_dp_data_send(uint32_t sn, tuya_ble_dp_data_send_type_t type, tuya_ble_dp_data_send_mode_t mode, tuya_ble_dp_data_send_ack_t ack, uint8_t *p_dp_data, uint32_t dp_data_len); + +/** + * @brief Function for send the dp data with time. + * + * @param [in]sn: The sending sequence number of the application definition management. + * [in]mode : See the description in the 'tuya_ble_type.h' file for details. + * [in]time_type : DP_TIME_TYPE_MS_STRING - Indicates that the following 'p_time_data' is a string of milliseconds that must be 13 bytes in length. + * E.g, 'p_time_data' points to the string "1600777955000"; + * DP_TIME_TYPE_UNIX_TIMESTAMP - Indicates that the following 'p_time_data' points to the four-byte unix timestamp data. + * E.g, unix timestamp is 1600777955 = 0x5F69EEE3, then 'p_time_data' is {0x5F,0x69,0xEE,0xE3} ; + * [in]p_time_data : time data pointer. + * [in]p_dp_data : The pointer of dp data . + * [in]dp_data_len : The length of dp data . + * @note new api, The length of each dp data sent through this function must be 2 bytes. DTLD->'L' must be 2 bytes. + *. The default type of this function is 'DP_SEND_TYPE_ACTIVE', and the default ack is 'DP_SEND_WITH_RESPONSE', which cannot be changed. + * */ +tuya_ble_status_t tuya_ble_dp_data_with_time_send(uint32_t sn, tuya_ble_dp_data_send_mode_t mode, tuya_ble_dp_data_send_time_type_t time_type, uint8_t *p_time_data, uint8_t *p_dp_data, uint32_t dp_data_len); + +#else + +/** + * @brief Function for report the dp point data. + * + * @note + *. + * */ + +tuya_ble_status_t tuya_ble_dp_data_report(uint8_t *p_data, uint32_t len); + +/** + * @brief Function for report the dp point data with time. + * + * @note + *. + * */ + +tuya_ble_status_t tuya_ble_dp_data_with_time_report(uint32_t timestamp, uint8_t *p_data, uint32_t len); + +/** + * @brief Function for report the dp point data with time. + * + * @note time_string: 13-byte millisecond string ,for example ,"0000000123456"; + *. + * */ + +tuya_ble_status_t tuya_ble_dp_data_with_time_ms_string_report(uint8_t *time_string, uint8_t *p_data, uint32_t len); + +/** + * @brief Function for report the dp point data with flag. + * + * @note + *. + * */ + +tuya_ble_status_t tuya_ble_dp_data_with_flag_report(uint16_t sn, tuya_ble_dp_data_send_mode_t mode, uint8_t *p_data, uint32_t len); + +/** + * @brief Function for report the dp point data with flag and time. + * + * @note + *. + * */ + +tuya_ble_status_t tuya_ble_dp_data_with_flag_and_time_report(uint16_t sn, tuya_ble_dp_data_send_mode_t mode, uint32_t timestamp, uint8_t *p_data, uint32_t len); + +/** + * @brief Function for report the dp point data with flag and time. + * + * @note time_string: 13-byte millisecond string ,for example ,"0000000123456"; + *. + * */ +tuya_ble_status_t tuya_ble_dp_data_with_flag_and_time_ms_string_report(uint16_t sn, tuya_ble_dp_data_send_mode_t mode, uint8_t *time_string, uint8_t *p_data, uint32_t len); + +#endif + +/** + * @brief Function for process the internal state of tuya sdk, application should call this in connect handler. + * + * @note + *. + * */ +void tuya_ble_connected_handler(void); + + +/** + * @brief Function for process the internal state of tuya sdk, application should call this in disconnect handler. + * + * @note + *. + * */ +void tuya_ble_disconnected_handler(void); + +#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE + +/** + *@brief Function for update the link encrypted status to sdk, application should call this function when the link layer encryption is successful. + *@note + * + * */ +void tuya_ble_link_encrypted_handler(void); + +#endif + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN >= 3) +/** + * @brief Function for process the internal state of tuya sdk, application should call this in disconnect handler. + * @param [in]on_off: 0-off ,1 - on. + * @note + *. + * */ +tuya_ble_status_t tuya_ble_adv_data_connecting_request_set(uint8_t on_off); +#endif + +/** + * @brief Function for data passthrough. + * + * @note The tuya sdk will forwards the data to the app. + *. + * */ +tuya_ble_status_t tuya_ble_data_passthrough(uint8_t *p_data, uint32_t len); + + +/** + * @brief Function for response the production test instruction asynchronous. + * + * @param [in]channel: 0-uart ,1 - ble. + * [in]pdata : pointer to production test cmd data(Complete instruction,include0x66 0xaa and checksum.) + * [in]len : Number of bytes of pdata. + * @note The tuya sdk will forwards the data to the app. + *. + * */ +tuya_ble_status_t tuya_ble_production_test_asynchronous_response(uint8_t channel, uint8_t *p_data, uint32_t len); + +/** + * @brief Function for response for the net config req. + * + * @note + *. + * */ +tuya_ble_status_t tuya_ble_net_config_response(int16_t result_code); + + +#if (!TUYA_BLE_DEVICE_REGISTER_FROM_BLE) +/** + * @brief Function for response for ubound req. + * + * @note + *. + * */ +tuya_ble_status_t tuya_ble_ubound_response(uint8_t result_code); + + +/** + * @brief Function for response for anomaly ubound req. + * + * @note + *. + * */ +tuya_ble_status_t tuya_ble_anomaly_ubound_response(uint8_t result_code); + +/** + * @brief Function for response for device reset req. + * + * @note + *. + * */ +tuya_ble_status_t tuya_ble_device_reset_response(uint8_t result_code); + +#endif + +/** + * @brief Function for get the ble connet status. + * + * @note + *. + * */ + +tuya_ble_connect_status_t tuya_ble_connect_status_get(void); + +/** + * @brief Function for notify the sdk the device has unbind. + * + * @note + *. + * */ +tuya_ble_status_t tuya_ble_device_unbind(void); + +/** + * @brief Function for notify the sdk the device has resumes factory Settings. + * + * @note When the device resumes factory Settings,shoule notify the sdk. + *. + * */ + +tuya_ble_status_t tuya_ble_device_factory_reset(void); + + +/** + * @brief Function for Request update time. + * + * @param time_type: 0-13-byte millisecond string [from cloud],1 - normal time format [from cloud] , 2 - normal time format[from app local] + * @note + *. + * */ +tuya_ble_status_t tuya_ble_time_req(uint8_t time_type); + +/** + * @brief Function for response the ota req. + * + * @note response the ota data req from call back event. + *. + * */ + +tuya_ble_status_t tuya_ble_ota_response(tuya_ble_ota_response_t *p_data); + + + +/** + * @brief Function for send custom event to main process of ble sdk. + * + * @note + *. + * */ +uint8_t tuya_ble_custom_event_send(tuya_ble_custom_evt_t evt); + + + +#if TUYA_BLE_USE_OS + +/** + * @brief Function for registe queue to receive call back evt when use os + * + * @note + * + * */ +tuya_ble_status_t tuya_ble_callback_queue_register(void *cb_queue); + +/** + * @brief Function for response the event. + * + * @note if use os,must be sure to call this function after process one event in queue. + * + * */ +tuya_ble_status_t tuya_ble_event_response(tuya_ble_cb_evt_param_t *param); + +#else + +/** + * @brief Function for registe call back functions. + * + * @note appliction should receive the message from the call back registed by this function. + * + * */ +tuya_ble_status_t tuya_ble_callback_queue_register(tuya_ble_callback_t cb); + +/** + * @brief Function for get scheduler queue size. + * + * @note If it returns 0, it means that the queue has not been initialized. + * + * */ +uint16_t tuya_ble_scheduler_queue_size_get(void); +/** + * @brief Function for get queue free space. + * + * @note + * + * */ +uint16_t tuya_ble_scheduler_queue_space_get(void); +/** + * @brief Function for get the number of current events in the queue. + * + * @note + * + * */ +uint16_t tuya_ble_scheduler_queue_events_get(void); + +#endif + +/** + * @brief Function for check if sleep is allowed. + * + * @note If it returns true, it means that sleep is allowed. + * + * */ +bool tuya_ble_sleep_allowed_check(void); + + +#endif + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_bulk_data.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_bulk_data.h new file mode 100644 index 0000000..d49a845 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_bulk_data.h @@ -0,0 +1,92 @@ +/** + * \file tuya_ble_bulkdata.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#ifndef TUYA_BLE_BULK_DATA_H_ +#define TUYA_BLE_BULK_DATA_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/********************************************************************* + * INCLUDE + */ +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" + + + +/**@brief Macro for defining bulk data transfer protocol. */ + +#define FRM_BULK_DATA_READ_INFO_REQ 0x0007 //APP->BLE +#define FRM_BULK_DATA_READ_INFO_RESP 0x0007 //BLE->APP +#define FRM_BULK_DATA_READ_DATA_REQ 0x0008 //APP->BLE +#define FRM_BULK_DATA_READ_DATA_RESP 0x0008 //BLE->APP +#define FRM_BULK_DATA_SEND_DATA 0x0009 //BLE->APP +#define FRM_BULK_DATA_ERASE_DATA_REQ 0x000A //APP->BLE +#define FRM_BULK_DATA_ERASE_DATA_RESP 0x000A //BLE->APP + + + +/**@brief Function for get the block size used for bulk data reading. + * + * + * @param[out] block size used for bulk data reading. + * @note The block size depends on the mtu value negotiated after the BLE connection is established. + * If the return value is 0, stop the current bulk data transmission. + */ +uint32_t tuya_ble_bulk_data_read_block_size_get(void); + +/**@brief Function for handling the bulk data request. + * + * + * @param[in] cmd Request command. + * @param[in] p_recv_data Pointer to the buffer with received data. + * @param[in] recv_data_len Length of received data. + */ +void tuya_ble_handle_bulk_data_req(uint16_t cmd, uint8_t *p_recv_data, uint32_t recv_data_len); + +/**@brief Function for respond to app requests. + * + * + * @param[in] p_data The pointer to the response data. + */ +tuya_ble_status_t tuya_ble_bulk_data_response(tuya_ble_bulk_data_response_t *p_data); + +/**@brief Function for handling the bulk data events. + * + * + * @param[in] p_evt Event received from the application. + */ +void tuya_ble_handle_bulk_data_evt(tuya_ble_evt_param_t *p_evt); + + + +#ifdef __cplusplus +} +#endif + +#endif //TUYA_BLE_BULKDATA_H_ + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_data_handler.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_data_handler.h new file mode 100644 index 0000000..1d4bc80 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_data_handler.h @@ -0,0 +1,194 @@ +/** + * \file tuya_ble_data_handler.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#ifndef TUYA_BLE_DATA_HANDLER_H_ +#define TUYA_BLE_DATA_HANDLER_H_ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_internal_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#define FRM_QRY_DEV_INFO_REQ 0x0000 //APP->BLE +#define FRM_QRY_DEV_INFO_RESP 0x0000 //BLE->APP +#define PAIR_REQ 0x0001 //APP->BLE +#define PAIR_RESP 0x0001 //BLE->APP +#define FRM_CMD_SEND 0x0002 //APP->BLE +#define FRM_CMD_RESP 0x0002 //BLE->APP +#define FRM_STATE_QUERY 0x0003 //APP->BLE +#define FRM_STATE_QUERY_RESP 0x0003 //BLE->APP +#define FRM_LOGIN_KEY_REQ 0x0004 //APP->BLE +#define FRM_LOGIN_KEY_RESP 0x0004 //BLE->APP +#define FRM_UNBONDING_REQ 0x0005 //APP->BLE +#define FRM_UNBONDING_RESP 0x0005 //BLE->APP +#define FRM_DEVICE_RESET 0x0006 //APP->BLE +#define FRM_DEVICE_RESET_RESP 0x0006 //BLE->APP + +#define FRM_OTA_START_REQ 0x000C //APP->BLE +#define FRM_OTA_START_RESP 0x000C //BLE->APP +#define FRM_OTA_FILE_INFOR_REQ 0x000D //APP->BLE +#define FRM_OTA_FILE_INFOR_RESP 0x000D //BLE->APP +#define FRM_OTA_FILE_OFFSET_REQ 0x000E //APP->BLE +#define FRM_OTA_FILE_OFFSET_RESP 0x000E //BLE->APP +#define FRM_OTA_DATA_REQ 0x000F //APP->BLE +#define FRM_OTA_DATA_RESP 0x000F //BLE->APP +#define FRM_OTA_END_REQ 0x0010 //APP->BLE +#define FRM_OTA_END_RESP 0x0010 //BLE->APP + +#define FRM_FACTORY_TEST_CMD 0x0012 //APP->BLE +#define FRM_FACTORY_TEST_RESP 0x0012 //BLE->APP + +#define FRM_ANOMALY_UNBONDING_REQ 0x0014 //APP->BLE +#define FRM_ANOMALY_UNBONDING_RESP 0x0014 //BLE->APP + +#define FRM_AUTHENTICATE_PHASE_1_REQ 0x0015 //APP->BLE +#define FRM_AUTHENTICATE_PHASE_1_RESP 0x0015 //BLE->APP + +#define FRM_AUTHENTICATE_PHASE_2_REQ 0x0016 //APP->BLE +#define FRM_AUTHENTICATE_PHASE_2_RESP 0x0016 //BLE->APP + +#define FRM_AUTHENTICATE_PHASE_3_REQ 0x0017 //APP->BLE +#define FRM_AUTHENTICATE_PHASE_3_RESP 0x0017 //BLE->APP + +#define FRM_ANOMALY_UNBONDING_REQ 0x0014 //APP->BLE +#define FRM_ANOMALY_UNBONDING_RESP 0x0014 //BLE->APP + + +#define FRM_NET_CONFIG_INFO_REQ 0x0021 //APP->BLE +#define FRM_NET_CONFIG_INFO_RESP 0x0021 //BLE->APP + +#define FRM_NET_CONFIG_RESPONSE_REPORT_REQ 0x0022 //APP->BLE +#define FRM_NET_CONFIG_RESPONSE_REPORT_RESP 0x0022 //BLE->APP + + +#define FRM_DATA_PASSTHROUGH_REQ 0x0023 //APP<->BLE + +#define FRM_DP_DATA_WRITE_REQ 0x0027 //APP->BLE +#define FRM_DP_DATA_WRITE_RESP 0x0027 //BLE->APP + +#define FRM_STAT_REPORT 0x8001 //BLE->APP +#define FRM_STAT_REPORT_RESP 0x8001 //APP->BLE + +#define FRM_STAT_WITH_TIME_REPORT 0x8003 //BLE->APP +#define FRM_STAT_WITH_TIME_REPORT_RESP 0x8003 //APP->BLE + +#define FRM_DATA_WITH_FLAG_REPORT 0x8004 //BLE->APP +#define FRM_DATA_WITH_FLAG_REPORT_RESP 0x8004 //APP->BLE + +#define FRM_DATA_WITH_FLAG_AND_TIME_REPORT 0x8005 //BLE->APP +#define FRM_DATA_WITH_FLAG_AND_TIME_REPORT_RESP 0x8005 //APP->BLE + +#define FRM_DP_DATA_SEND_REQ 0x8006 //BLE->APP +#define FRM_DP_DATA_SEND_RESP 0x8006 //APP->BLE + +#define FRM_DP_DATA_WITH_TIME_SEND_REQ 0x8007 //BLE->APP +#define FRM_DP_DATA_WITH_TIME_SEND_RESP 0x8007 //APP->BLE + +#define FRM_WEATHER_DATA_REQUEST 0x8017 //BLE->APP +#define FRM_WEATHER_DATA_REQUEST_RESP 0x8017 //APP->BLE + +#define FRM_WEATHER_DATA_RECEIVED 0x8018 //APP->BLE +#define FRM_WEATHER_DATA_RECEIVED_RESP 0x8018 //BLE->APP + +#define FRM_GET_UNIX_TIME_MS_REQ 0x8010 //BLE->APP +#define FRM_GET_UNIX_TIME_MS_RESP 0x8010 //APP->BLE +#define FRM_GET_UNIX_TIME_CHAR_MS_REQ 0x8011 //BLE->APP +#define FRM_GET_UNIX_TIME_CHAR_MS_RESP 0x8011 //APP->BLE +#define FRM_GET_UNIX_TIME_CHAR_DATE_REQ 0x8012 //BLE->APP +#define FRM_GET_UNIX_TIME_CHAR_DATE_RESP 0x8012 //APP->BLE + +#define FRM_GET_APP_LOCAL_TIME_REQ 0x8013 //BLE->APP +#define FRM_GET_APP_LOCAL_TIME_RESP 0x8013 //APP->BLE +#define FRM_GET_UNIX_TIME_WITH_DST_REQ 0x8014 //BLE->APP [timestamp + timezone + daylight saving time] +#define FRM_GET_UNIX_TIME_WITH_DST_RESP 0x8014 //APP->BLE [timestamp + timezone + daylight saving time] + +typedef enum { + TUYA_BLE_OTA_STATUS_NONE, + TUYA_BLE_OTA_STATUS_START, + TUYA_BLE_OTA_STATUS_FILE_INFO, + TUYA_BLE_OTA_STATUS_FILE_OFFSET, + TUYA_BLE_OTA_STATUS_FILE_DATA, + TUYA_BLE_OTA_STATUS_FILE_END, + TUYA_BLE_OTA_STATUS_MAX, +} tuya_ble_ota_status_t; + + +typedef struct { + uint32_t send_len; + uint8_t *send_data; + uint32_t encrypt_data_buf_len; + uint8_t *encrypt_data_buf; +} tuya_ble_r_air_send_packet; + + +typedef struct { + uint32_t recv_len; + uint32_t recv_len_max; + uint8_t *recv_data; + uint32_t decrypt_buf_len; + uint8_t *de_encrypt_buf; +} tuya_ble_r_air_recv_packet; + +void tuya_ble_air_recv_packet_free(void); + +void tuya_ble_set_device_version(uint32_t firmware_version, uint32_t hardware_version); + +void tuya_ble_set_external_mcu_version(uint32_t firmware_version, uint32_t hardware_version); + +uint8_t tuya_ble_commData_send(uint16_t cmd, uint32_t ack_sn, uint8_t *data, uint16_t len, uint8_t encryption_mode); + +uint8_t tuya_ble_send(uint16_t cmd, uint32_t ack_sn, uint8_t *data, uint16_t len); + +void tuya_ble_evt_process(uint16_t cmd, uint8_t *recv_data, uint32_t recv_len); + +void tuya_ble_reset_ble_sn(void); + +void tuya_ble_commonData_rx_proc(uint8_t *buf, uint16_t len); + +void tuya_ble_pair_rand_clear(void); + +uint8_t tuya_ble_pair_rand_valid_get(void); + +uint32_t tuya_ble_send_packet_data_length_get(void); + +void tuya_ble_device_unbond(void); + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE==TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) + +void tuya_ble_auth_data_reset(void); + +#endif + +#ifdef __cplusplus +} +#endif + +#endif // TUYA_BLE_COMMDATA_HANDLER_H_ + + + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_event.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_event.h new file mode 100644 index 0000000..4ab4b95 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_event.h @@ -0,0 +1,159 @@ +/** + * \file tuya_ble_event.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#ifndef TUYA_BLE_EVENT_H_ +#define TUYA_BLE_EVENT_H_ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +#if (!TUYA_BLE_USE_OS) + + +#define TUYA_BLE_EVT_MAX_NUM MAX_NUMBER_OF_TUYA_MESSAGE +#define TUYA_BLE_EVT_SIZE 52 //64 + +enum { + TUYA_BLE_EVT_SEND_SUCCESS = 0, + TUYA_BLE_EVT_SEND_NO_MEMORY = 1, + TUYA_BLE_EVT_SEND_FAIL = 2, +}; + +#define TUYA_BLE_ERROR_HANDLER(ERR_CODE) + +#define TUYA_BLE_ERROR_CHECK(ERR_CODE) + +#define TUYA_BLE_ERROR_CHECK_BOOL(BOOLEAN_VALUE) + + +#define CEIL_DIV(A, B) \ + (((A) + (B) - 1) / (B)) + +/**@brief Compute number of bytes required to hold the scheduler buffer. + * + * @param[in] EVENT_SIZE Maximum size of events to be passed through the scheduler. + * @param[in] QUEUE_SIZE Number of entries in scheduler queue (i.e. the maximum number of events + * that can be scheduled for execution). + * + * @return Required scheduler buffer size (in bytes). + */ +#define TUYA_BLE_SCHED_BUF_SIZE(EVENT_SIZE, QUEUE_SIZE) \ + ((EVENT_SIZE) * ((QUEUE_SIZE) + 1)) + + +/**@brief Macro for initializing the event scheduler. + * + * @details It will also handle dimensioning and allocation of the memory buffer required by the + * scheduler, making sure the buffer is correctly aligned. + * + * @param[in] EVENT_SIZE Maximum size of events to be passed through the scheduler. + * @param[in] QUEUE_SIZE Number of entries in scheduler queue (i.e. the maximum number of events + * that can be scheduled for execution). + * + * @note Since this macro allocates a buffer, it must only be called once (it is OK to call it + * several times as long as it is from the same location, e.g. to do a reinitialization). + */ +#define TUYA_BLE_SCHED_INIT(EVENT_SIZE, QUEUE_SIZE) \ + do \ + { \ + static uint32_t TUYA_BLE_SCHED_BUF[CEIL_DIV(TUYA_BLE_SCHED_BUF_SIZE((EVENT_SIZE), (QUEUE_SIZE)), \ + sizeof(uint32_t))]; \ + uint32_t ERR_CODE = tuya_ble_sched_init((EVENT_SIZE), (QUEUE_SIZE), TUYA_BLE_SCHED_BUF); \ + TUYA_BLE_ERROR_CHECK(ERR_CODE); \ + } while (0) + +/**@brief Function for initializing the Scheduler. + * + * @details It must be called before entering the main loop. + * + * @param[in] max_event_size Maximum size of events to be passed through the scheduler. + * @param[in] queue_size Number of entries in scheduler queue (i.e. the maximum number of + * events that can be scheduled for execution). + * @param[in] p_evt_buffer Pointer to memory buffer for holding the scheduler queue. It must + * be dimensioned using the APP_SCHED_BUFFER_SIZE() macro. The buffer + * must be aligned to a 4 byte boundary. + * + * @note Normally initialization should be done using the TUYA_SCHED_INIT() macro, as that will both + * allocate the scheduler buffer, and also align the buffer correctly. + * + * @retval NRF_SUCCESS Successful initialization. + * @retval NRF_ERROR_INVALID_PARAM Invalid parameter (buffer not aligned to a 4 byte + * boundary). + */ +//uint32_t tuya_ble_sched_init(uint16_t max_event_size, uint16_t queue_size, void * p_evt_buffer); + +/**@brief Function for executing all scheduled events. + * + * @details This function must be called from within the main loop. It will execute all events + * scheduled since the last time it was called. + */ +void tuya_sched_execute(void); + +/**@brief Function for scheduling an event. + * + * @details Puts an event into the event queue. + * + * @param[in] p_event_data Pointer to event data to be scheduled. + * @param[in] event_size Size of event data to be scheduled. + * @param[in] handler Event handler to receive the event. + * + * @return NRF_SUCCESS on success, otherwise an error code. + */ +//tuya_ble_status_t tuya_ble_sched_event_put(void const * p_event_data, uint16_t event_data_size); + + +/**@brief Function for getting the current amount of free space in the queue. + * + * @details The real amount of free space may be less if entries are being added from an interrupt. + * To get the sxact value, this function should be called from the critical section. + * + * @return Amount of free space in the queue. + */ +uint16_t tuya_ble_sched_queue_size_get(void); + +uint16_t tuya_ble_sched_queue_space_get(void); + +uint16_t tuya_ble_sched_queue_events_get(void); + +void tuya_ble_event_queue_init(void); + +tuya_ble_status_t tuya_ble_message_send(tuya_ble_evt_param_t *evt); + + +#endif + +#ifdef __cplusplus +} +#endif + +#endif // + + + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_feature_weather.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_feature_weather.h new file mode 100644 index 0000000..bc789f5 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_feature_weather.h @@ -0,0 +1,221 @@ +/** + * \file tuya_ble_feature_weather.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#ifndef TUYA_BLE_FEATURE_WEATHER_H_ +#define TUYA_BLE_FEATURE_WEATHER_H_ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" + + +/**@brief Total number of weather parameters currently supported. */ +#define SUPPORT_WEATHER_KEY_TYPE_MAX_NUMS ( 25 ) + + +/**@brief Weather key type. */ +typedef enum { + WKT_TEMP = (1 << 0), /**< temperature. */ + WKT_THIHG = (1 << 1), /**< high temperature. */ + WKT_TLOW = (1 << 2), /**< low temperature. */ + WKT_HUMIDITY = (1 << 3), /**< humidity. */ + WKT_CONDITION = (1 << 4), /**< weather condition. */ + WKT_PRESSURE = (1 << 5), /**< pressure. */ + WKT_REALFEEL = (1 << 6), /**< sendible temperature. */ + WKT_UVI = (1 << 7), /**< uvi. */ + WKT_SUNRISE = (1 << 8), /**< sunrise. */ + WKT_SUNSET = (1 << 9), /**< sunset. */ + WKT_UNIX = (1 << 10), /**< unix time, Use with sunrise and sunset. */ + WKT_LOCAL = (1 << 11), /**< local time, Use with sunrise and sunset. */ + WKT_WINDSPEED = (1 << 12), /**< wind speed. */ + WKT_WINDDIR = (1 << 13), /**< wind direction. */ + WKT_WINDLEVEL = (1 << 14), /**< wind speed scale/level. */ + WKT_AQI = (1 << 15), /**< aqi. */ + WKT_TIPS = (1 << 16), /**< tips. */ + WKT_RANK = (1 << 17), /**< Detailed AQI status and national ranking. */ + WKT_PM10 = (1 << 18), /**< pm10. */ + WKT_PM25 = (1 << 19), /**< pm2.5. */ + WKT_O3 = (1 << 20), /**< o3. */ + WKT_NO2 = (1 << 21), /**< no2. */ + WKT_CO = (1 << 22), /**< co. */ + WKT_SO2 = (1 << 23), /**< so2. */ + WKT_CONDITIONNUM = (1 << 24), /**< weather condition mapping id. */ + + WKT_COMBINE_BITMAP_MAXVAL = (1 << SUPPORT_WEATHER_KEY_TYPE_MAX_NUMS), +} tuya_ble_weather_key_type_t; + + +/**@brief Weather value type. */ +typedef enum { + WVT_INTEGER = 0, + WVT_STRING, +} tuya_ble_weather_value_type_t; + + +/**@brief Weather location type. */ +typedef enum { + WLT_PAIR_NETWORK_LOCATION = 1, /**< Pair network location. */ + WLT_APP_CURRENT_LOCATION, /**< Mobile phone current location. */ + WLT_CUSTOM_LOCATION, /**< The current sdk version unsupport. */ + + WLT_MAX, +} tuya_ble_weather_location_type_t; + + +/**@brief Weather data object structure. + * + */ +typedef struct { + uint8_t n_day; /**< which day. */ + tuya_ble_weather_key_type_t key_type; /**< weather key type. */ + tuya_ble_weather_value_type_t val_type; /**< weather value type. */ + uint8_t value_len; /**< weather value length. */ + char vaule[]; /**< weather values. */ +} tuya_ble_wd_object_t; + + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * @brief Function for request weather data. Default request current location of mobile phone + * + * @note Example1: request temperatur & humidity and two days, called: tuya_ble_feature_weather_data_request((WKT_TEMP | WKT_HUMIDITY), 2); + * Example2: request sunrise data&time and ont day, called: tuya_ble_feature_weather_data_request((WKT_SUNRISE | WKT_LOCAL), 1); + * Example3: request highest temperature and seven days, called: tuya_ble_feature_weather_data_request((WKT_THIHG), 7); + * In addition, request sunrise/sunset must be matched with WKT_UNIX/WKT_LOCAL, otherwise the received data is unix time + * + * @param[in] combine_type Request combine types. For details, see the enum of tuya_ble_weather_key_type_t + * @param[in] n_days Request forecast days, rang from [1-7]; 1-means only today, 2-means today+tomorrow ... + * + * @retval TUYA_BLE_ERR_INVALID_PARAM The provided Parameters are not valid. + * @retval TUYA_BLE_ERR_NO_MEM If no memory is available to accept the operation. + * @retval TUYA_BLE_ERR_INTERNAL If weather request message send failed. + * @retval TUYA_BLE_SUCCESS Successful. + * + * */ +extern tuya_ble_status_t tuya_ble_feature_weather_data_request(uint32_t combine_type, uint8_t n_days); + + +/** + * @brief Function for request weather data with appoint location. + * + * @param[in] location_type Request location types. For details, see the enum of tuya_ble_weather_location_type_t. + * @param[in] combine_type Request combine types. For details, see the enum of tuya_ble_weather_key_type_t + * @param[in] n_days Request forecast days, rang from [1-7]; 1-means only today, 2-means today+tomorrow ... + * + * @retval TUYA_BLE_ERR_INVALID_PARAM The provided Parameters are not valid. + * @retval TUYA_BLE_ERR_NO_MEM If no memory is available to accept the operation. + * @retval TUYA_BLE_ERR_INTERNAL If weather request message send failed. + * @retval TUYA_BLE_SUCCESS Successful. + * + * */ +extern tuya_ble_status_t tuya_ble_feature_weather_data_request_with_location(tuya_ble_weather_location_type_t location_type, uint32_t combine_type, uint8_t n_days); + +/** + * @brief Function for application parse received weather datas, In tuya_cb_handler() function + * add TUYA_BLE_CB_EVT_WEATHER_DATA_REQ_RESPONSE and TUYA_BLE_CB_EVT_WEATHER_DATA_RECEIVED callback + * event and process it. For example: + * + case TUYA_BLE_CB_EVT_WEATHER_DATA_REQ_RESPONSE: + TUYA_APP_LOG_INFO("received weather data request response result code =%d",event->weather_req_response_data.status); + break; + + case TUYA_BLE_CB_EVT_WEATHER_DATA_RECEIVED: + tuya_ble_wd_object_t *object; + uint16_t object_len = 0; + for (;;) { + object = (tuya_ble_wd_object_t *)(event->weather_received_data.p_data + object_len); + + TUYA_APP_LOG_DEBUG("recvived weather data, n_days=[%d] key=[0x%08x] val_type=[%d] val_len=[%d]", \ + object->n_day, object->key_type, object->val_type, object->value_len); + TUYA_APP_LOG_HEXDUMP_DEBUG("vaule :", (uint8_t *)object->vaule, object->value_len); + + // TODO .. YOUR JOBS + + object_len += (sizeof(tuya_ble_wd_object_t) + object->value_len); + if (object_len >= event->weather_received_data.data_len) + break; + } + break; + * */ + + +/** + * @brief Function for convert weather enum type to string + * + * @note For example input convert type=WKT_TEMP, output key "w.temp" + * + * @param[in] type Convert type + * @param[out] key The ponit of weather key string + * + * @retval TUYA_BLE_ERR_INVALID_PARAM The provided Parameters are not valid. + * @retval TUYA_BLE_ERR_NOT_FOUND No corresponding type was found. + * @retval TUYA_BLE_SUCCESS Successful. + * + * */ +extern tuya_ble_status_t tuya_ble_feature_weather_key_enum_type_to_string(tuya_ble_weather_key_type_t type, char *key); + + +/** + * @brief Function for handler weather data request event + * + * @details Internal use of tuya ble sdk + * + * @param[in] evt For details, see the struct of tuya_ble_evt_param_t + * + * */ +extern void tuya_ble_handle_weather_data_request_evt(tuya_ble_evt_param_t *evt); + + +/** + * @brief Function for handler weather data request response/ack + * + * @details Internal use of tuya ble sdk + * + * @param[in] recv_data The point of recvived response data + * @param[in] recv_len The numbers of data + * + * */ +extern void tuya_ble_handle_weather_data_request_response(uint8_t *recv_data, uint16_t recv_len); + + +/** + * @brief Function for handler weather data received + * + * @details Internal use of tuya ble sdk + * + * @param[in] recv_data The point of recvived weather data + * @param[in] recv_len The numbers of data + * + * */ +extern void tuya_ble_handle_weather_data_received(uint8_t *recv_data, uint16_t recv_len); + + +#ifdef __cplusplus +} +#endif + +#endif /* TUYA_BLE_FEATURE_WEATHER_H_ */ diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_gatt_send_queue.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_gatt_send_queue.h new file mode 100644 index 0000000..6f6b4d2 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_gatt_send_queue.h @@ -0,0 +1,49 @@ +/** + * \file tuya_ble_gatt_send_queue.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#ifndef TUYA_BLE_GATT_SEND_QUEUE_H_ +#define TUYA_BLE_GATT_SEND_QUEUE_H_ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" +#include "tuya_ble_queue.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + uint8_t *buf; + uint8_t size; +} tuya_ble_gatt_send_data_t; + +void tuya_ble_gatt_send_queue_init(void); +void tuya_ble_gatt_send_data_handle(void *evt); +tuya_ble_status_t tuya_ble_gatt_send_data_enqueue(uint8_t *p_data, uint8_t data_len); + +#ifdef __cplusplus +} +#endif + +#endif //TUYA_BLE_GATT_SEND_QUEUE_H_ diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_heap.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_heap.h new file mode 100644 index 0000000..7745a55 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_heap.h @@ -0,0 +1,114 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ + + +#ifndef TUYA_HEAP_H__ +#define TUYA_HEAP_H__ + +#include "tuya_ble_stdlib.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if (TUYA_BLE_USE_PLATFORM_MEMORY_HEAP==0) + +#define portBYTE_ALIGNMENT 4 + + + +#if portBYTE_ALIGNMENT == 32 +#define portBYTE_ALIGNMENT_MASK ( 0x001f ) +#endif + +#if portBYTE_ALIGNMENT == 16 +#define portBYTE_ALIGNMENT_MASK ( 0x000f ) +#endif + +#if portBYTE_ALIGNMENT == 8 +#define portBYTE_ALIGNMENT_MASK ( 0x0007 ) +#endif + +#if portBYTE_ALIGNMENT == 4 +#define portBYTE_ALIGNMENT_MASK ( 0x0003 ) +#endif + +#if portBYTE_ALIGNMENT == 2 +#define portBYTE_ALIGNMENT_MASK ( 0x0001 ) +#endif + +#if portBYTE_ALIGNMENT == 1 +#define portBYTE_ALIGNMENT_MASK ( 0x0000 ) +#endif + +#ifndef portBYTE_ALIGNMENT_MASK +#error "Invalid portBYTE_ALIGNMENT definition" +#endif + + +#ifndef tuyaASSERT +#define tuyaASSERT( x ) +#define tuyaASSERT_DEFINED 0 +#else +#define tuyaASSERT_DEFINED 1 +#endif + + +#ifndef tuyaCOVERAGE_TEST_MARKER +#define tuyaCOVERAGE_TEST_MARKER() +#endif + + +#ifndef tuya_traceMALLOC +#define tuya_traceMALLOC( pvAddress, uiSize ) +#endif + +#ifndef tuya_traceFREE +#define tuya_traceFREE( pvAddress, uiSize ) +#endif + + + +void *pvTuyaPortMalloc(uint32_t xWantedSize); + +void vTuyaPortFree(void *pv); + +uint32_t xTuyaPortGetFreeHeapSize(void); + +uint32_t xTuyaPortGetMinimumEverFreeHeapSize(void); + + +#endif + +#ifdef __cplusplus +} +#endif + +#endif //TUYA_HEAP_H__ + +/** @} */ diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_internal_config.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_internal_config.h new file mode 100644 index 0000000..4d800ca --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_internal_config.h @@ -0,0 +1,150 @@ +/** + * \file tuya_ble_internal_config.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + + +#ifndef TUYA_BLE_INTERNAL_CONFIG_H__ +#define TUYA_BLE_INTERNAL_CONFIG_H__ + + +#include "tuya_ble_config.h" +#include "tuya_ble_port.h" + + +#define MAX_NUMBER_OF_TUYA_MESSAGE 16 //!< tuya ble message queue size + + +//BLE Communication protocol version v4.2 +#define TUYA_BLE_PROTOCOL_VERSION_HIGN 0x04 +#define TUYA_BLE_PROTOCOL_VERSION_LOW 0x02 + +#define TUYA_BLE_DP_WRITE_CURRENT_VERSION 0 + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN>=4) + +#define TUYA_BLE_AIR_FRAME_MAX 1536 + +#define TUYA_UART_RECEIVE_MAX_DP_DATA_LEN (512+4) + +#define TUYA_UART_RECEIVE_MAX_DP_BUFFER_DATA_LEN (512+4) + +#define TUYA_BLE_RECEIVE_MAX_DP_DATA_LEN (512+4) + +#define TUYA_BLE_SEND_MAX_DP_DATA_LEN TUYA_BLE_RECEIVE_MAX_DP_DATA_LEN + +#define TUYA_BLE_SEND_MAX_DATA_LEN (((TUYA_BLE_AIR_FRAME_MAX-17)/16)*16-14) + +#define TUYA_BLE_RECEIVE_MAX_DATA_LEN TUYA_BLE_SEND_MAX_DATA_LEN + +#else + +#define TUYA_BLE_ADVANCED_ENCRYPTION_DEVICE 0 + +#define TUYA_BLE_AIR_FRAME_MAX 1024 + +#define TUYA_UART_RECEIVE_MAX_DP_DATA_LEN (255+4) +#define TUYA_UART_RECEIVE_MAX_DP_BUFFER_DATA_LEN (255+4) + +#define TUYA_BLE_RECEIVE_MAX_DP_DATA_LEN (255+3) + +#define TUYA_BLE_SEND_MAX_DP_DATA_LEN TUYA_BLE_RECEIVE_MAX_DP_DATA_LEN + +#define TUYA_BLE_REPORT_MAX_DP_DATA_LEN TUYA_BLE_RECEIVE_MAX_DP_DATA_LEN + +#define TUYA_BLE_TRANSMISSION_MAX_DATA_LEN (TUYA_BLE_AIR_FRAME_MAX-29) + +#define TUYA_BLE_SEND_MAX_DATA_LEN TUYA_BLE_TRANSMISSION_MAX_DATA_LEN + +#define TUYA_BLE_RECEIVE_MAX_DATA_LEN TUYA_BLE_SEND_MAX_DATA_LEN + +#endif + + +#define TUYA_BLE_GATT_SEND_DATA_QUEUE_SIZE (MAX_NUMBER_OF_TUYA_MESSAGE*3) + + +#if (TUYA_BLE_USE_PLATFORM_MEMORY_HEAP==0) +/** + * MACRO for memory management + */ +#define TUYA_BLE_TOTAL_HEAP_SIZE 5120 + +#if (TUYA_BLE_TOTAL_HEAP_SIZE<5120) +#define TUYA_BLE_BULK_DATA_MAX_READ_BLOCK_SIZE 512 +#else +#define TUYA_BLE_BULK_DATA_MAX_READ_BLOCK_SIZE 1024 +#endif + +#else +#define TUYA_BLE_BULK_DATA_MAX_READ_BLOCK_SIZE 512 +#endif + + +#ifndef TUYA_BLE_MAX_CALLBACKS +#define TUYA_BLE_MAX_CALLBACKS 1 +#endif + + +#define TUYA_BLE_AUTH_FLASH_ADDR (TUYA_NV_START_ADDR) +#define TUYA_BLE_AUTH_FLASH_BACKUP_ADDR (TUYA_NV_START_ADDR+TUYA_NV_ERASE_MIN_SIZE) + +#define TUYA_BLE_SYS_FLASH_ADDR (TUYA_NV_START_ADDR+TUYA_NV_ERASE_MIN_SIZE*2) +#define TUYA_BLE_SYS_FLASH_BACKUP_ADDR (TUYA_NV_START_ADDR+TUYA_NV_ERASE_MIN_SIZE*3) + + +/** + * 1 - device register from ble 0 - from others + * @note: + */ +#define TUYA_BLE_DEVICE_REGISTER_FROM_BLE (TUYA_BLE_DEVICE_COMMUNICATION_ABILITY&TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_REGISTER_FROM_BLE) + + +#define TUYA_BLE_DEVICE_AUTH_DATA_STORE TUYA_BLE_DEVICE_AUTH_SELF_MANAGEMENT + +/** + * if 1 ,tuya ble sdk authorization storage into extern medium, For example security chip + */ +#define TUYA_BLE_DEVICE_AUTH_DATA_STORE_EXT_MEDIUM 0 + + +/** + * if 1 ,used ble dongle for product test, the transmit datas will encryption + */ +#define TUYA_BLE_PROD_TEST_SUPPORT_ENCRYPTION 0 + + +/** + * if >=1, the product support oem, when execute prod test will write in pid and json config file + * + * Noticed!!! if enable the macro, need to realization 'tuya_ble_status_t tuya_ble_prod_storage_oem_info(uint8_t *para,uint16_t len)' + * function yourself at the custom_app_product_test.c + */ +#define TUYA_BLE_PROD_SUPPORT_OEM_TYPE TUYA_BLE_PROD_OEM_TYPE_NONE + + +#if (TUYA_BLE_SYS_FLASH_BACKUP_ADDR>=(TUYA_NV_AREA_SIZE+TUYA_NV_START_ADDR)) +#error "Storage Memory overflow!" +#endif + + +#endif diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_log.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_log.h new file mode 100644 index 0000000..61a80ec --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_log.h @@ -0,0 +1,142 @@ +/** + * \file tuya_ble_log.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#ifndef TUYA_BLE_LOG_H__ +#define TUYA_BLE_LOG_H__ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_internal_config.h" +#include "tuya_ble_log_internal.h" + +#if TUYA_BLE_LOG_ENABLE + + +#ifndef TUYA_BLE_LOG_LEVEL +#define TUYA_BLE_LOG_LEVEL TUYA_BLE_LOG_LEVEL_DEBUG +#endif + +#ifndef TUYA_BLE_LOG_COLORS_ENABLE +#define TUYA_BLE_LOG_COLORS_ENABLE 0 +#endif + + +#define TUYA_BLE_LOG_ERROR(...) TUYA_BLE_LOG_INTERNAL_ERROR(__VA_ARGS__) +#define TUYA_BLE_LOG_WARNING(...) TUYA_BLE_LOG_INTERNAL_WARNING( __VA_ARGS__) +#define TUYA_BLE_LOG_INFO(...) TUYA_BLE_LOG_INTERNAL_INFO( __VA_ARGS__) +#define TUYA_BLE_LOG_DEBUG(...) TUYA_BLE_LOG_INTERNAL_DEBUG( __VA_ARGS__) + +#define TUYA_BLE_LOG_HEXDUMP_ERROR(...) TUYA_BLE_LOG_INTERNAL_HEXDUMP_ERROR(__VA_ARGS__) +#define TUYA_BLE_LOG_HEXDUMP_WARNING(...) TUYA_BLE_LOG_INTERNAL_HEXDUMP_WARNING( __VA_ARGS__) +#define TUYA_BLE_LOG_HEXDUMP_INFO(...) TUYA_BLE_LOG_INTERNAL_HEXDUMP_INFO( __VA_ARGS__) +#define TUYA_BLE_LOG_HEXDUMP_DEBUG(...) TUYA_BLE_LOG_INTERNAL_HEXDUMP_DEBUG( __VA_ARGS__) + +#else + +#define TUYA_BLE_LOG_ERROR(...) +#define TUYA_BLE_LOG_WARNING(...) +#define TUYA_BLE_LOG_INFO(...) +#define TUYA_BLE_LOG_DEBUG(...) + +#define TUYA_BLE_LOG_HEXDUMP_ERROR(...) +#define TUYA_BLE_LOG_HEXDUMP_WARNING(...) +#define TUYA_BLE_LOG_HEXDUMP_INFO(...) +#define TUYA_BLE_LOG_HEXDUMP_DEBUG(...) + +#endif // + + +#if TUYA_APP_LOG_ENABLE + +#ifndef TUYA_APP_LOG_LEVEL +#define TUYA_APP_LOG_LEVEL TUYA_APP_LOG_LEVEL_DEBUG +#endif + +#ifndef TUYA_APP_LOG_COLORS_ENABLE +#define TUYA_APP_LOG_COLORS_ENABLE 0 +#endif + + +#define TUYA_APP_LOG_ERROR(...) TUYA_APP_LOG_INTERNAL_ERROR(__VA_ARGS__) +#define TUYA_APP_LOG_WARNING(...) TUYA_APP_LOG_INTERNAL_WARNING( __VA_ARGS__) +#define TUYA_APP_LOG_INFO(...) TUYA_APP_LOG_INTERNAL_INFO( __VA_ARGS__) +#define TUYA_APP_LOG_DEBUG(...) TUYA_APP_LOG_INTERNAL_DEBUG( __VA_ARGS__) + +#define TUYA_APP_LOG_HEXDUMP_ERROR(...) TUYA_APP_LOG_INTERNAL_HEXDUMP_ERROR(__VA_ARGS__) +#define TUYA_APP_LOG_HEXDUMP_WARNING(...) TUYA_APP_LOG_INTERNAL_HEXDUMP_WARNING( __VA_ARGS__) +#define TUYA_APP_LOG_HEXDUMP_INFO(...) TUYA_APP_LOG_INTERNAL_HEXDUMP_INFO( __VA_ARGS__) +#define TUYA_APP_LOG_HEXDUMP_DEBUG(...) TUYA_APP_LOG_INTERNAL_HEXDUMP_DEBUG( __VA_ARGS__) + +#else + +#define TUYA_APP_LOG_ERROR(...) +#define TUYA_APP_LOG_WARNING(...) +#define TUYA_APP_LOG_INFO(...) +#define TUYA_APP_LOG_DEBUG(...) + +#define TUYA_APP_LOG_HEXDUMP_ERROR(...) +#define TUYA_APP_LOG_HEXDUMP_WARNING(...) +#define TUYA_APP_LOG_HEXDUMP_INFO(...) +#define TUYA_APP_LOG_HEXDUMP_DEBUG(...) + +#endif // + + +#ifdef TUYA_BLE_ASSERT + +#define TUYA_BLE_ERR_HANDLER(ERR_CODE) \ + do \ + { \ + TUYA_BLE_LOG_ERROR("Error code 0x%04X <%d>. %s:%d\n", ERR_CODE, ERR_CODE, (uint32_t)__FILE__, __LINE__); \ + } while (0) + +#define TUYA_BLE_ERR_CHECK(ERR_CODE) \ + do \ + { \ + const uint32_t LOCAL_ERR_CODE = (ERR_CODE); \ + if (LOCAL_ERR_CODE != 0) \ + { \ + TUYA_BLE_ERR_HANDLER(LOCAL_ERR_CODE); \ + } \ + } while (0) + +#define TUYA_BLE_ERR_TEST(ERR_CODE, EXPECT) \ + do \ + { \ + const uint32_t LOCAL_ERR_CODE = (ERR_CODE); \ + if (LOCAL_ERR_CODE != (EXPECT)) \ + { \ + TUYA_BLE_ERR_HANDLER(LOCAL_ERR_CODE); \ + } \ + } while (0) +#else // + +#define TUYA_BLE_ERR_CHECK(ERR_CODE) + +#define TUYA_BLE_ERR_TEST(ERR_CODE, EXPECT) + +#endif // + + + +#endif // TUYA_BLE_LOG_H__ diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_log_internal.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_log_internal.h new file mode 100644 index 0000000..750d634 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_log_internal.h @@ -0,0 +1,288 @@ +/** + * \file tuya_ble_log_internal.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#ifndef TUYA_BLE_LOG_INTERNAL__H__ +#define TUYA_BLE_LOG_INTERNAL__H__ + +#include "tuya_ble_port.h" +#include "tuya_ble_internal_config.h" + + +#if !defined(TUYA_BLE_PRINTF) +#error "Not defined printf function." +#elif !defined(TUYA_BLE_HEXDUMP) +#error "Not defined hexdump function." +#endif + + +#ifndef TUYA_BLE_LOG_COLORS_ENABLE +#define TUYA_BLE_LOG_COLORS_ENABLE 0 +#endif + +#ifndef TUYA_BLE_LOG_MODULE_NAME +#define TUYA_BLE_LOG_MODULE_NAME "TUYA_BLE" +#endif + + + +#if TUYA_BLE_LOG_COLORS_ENABLE +#define TUYA_BLE_LOG_COLOR_DEFAULT "\x1B[0m" +#define TUYA_BLE_LOG_COLOR_BLACK "\x1B[1;30m" +#define TUYA_BLE_LOG_COLOR_RED "\x1B[1;31m" +#define TUYA_BLE_LOG_COLOR_GREEN "\x1B[1;32m" +#define TUYA_BLE_LOG_COLOR_YELLOW "\x1B[1;33m" +#define TUYA_BLE_LOG_COLOR_BLUE "\x1B[1;34m" +#define TUYA_BLE_LOG_COLOR_MAGENTA "\x1B[1;35m" +#define TUYA_BLE_LOG_COLOR_CYAN "\x1B[1;36m" +#define TUYA_BLE_LOG_COLOR_WHITE "\x1B[1;37m" +#else +#define TUYA_BLE_LOG_COLOR_DEFAULT +#define TUYA_BLE_LOG_COLOR_BLACK +#define TUYA_BLE_LOG_COLOR_RED +#define TUYA_BLE_LOG_COLOR_GREEN +#define TUYA_BLE_LOG_COLOR_YELLOW +#define TUYA_BLE_LOG_COLOR_BLUE +#define TUYA_BLE_LOG_COLOR_MAGENTA +#define TUYA_BLE_LOG_COLOR_CYAN +#define TUYA_BLE_LOG_COLOR_WHITE +#endif + +#define TUYA_BLE_LOG_ERROR_COLOR TUYA_BLE_LOG_COLOR_RED +#define TUYA_BLE_LOG_WARNING_COLOR TUYA_BLE_LOG_COLOR_YELLOW +#define TUYA_BLE_LOG_INFO_COLOR TUYA_BLE_LOG_COLOR_DEFAULT +#define TUYA_BLE_LOG_DEBUG_COLOR TUYA_BLE_LOG_COLOR_GREEN +#define TUYA_BLE_LOG_DEFAULT_COLOR TUYA_BLE_LOG_COLOR_DEFAULT + +#define TUYA_BLE_LOG_BREAK ": " + +//#define TUYA_BLE_LOG_CRLF "\r\n" +#define TUYA_BLE_LOG_CRLF "" + +#define TUYA_BLE_ERROR_PREFIX TUYA_BLE_LOG_ERROR_COLOR "[E] " TUYA_BLE_LOG_MODULE_NAME TUYA_BLE_LOG_BREAK +#define TUYA_BLE_WARNING_PREFIX TUYA_BLE_LOG_WARNING_COLOR "[W] " TUYA_BLE_LOG_MODULE_NAME TUYA_BLE_LOG_BREAK +#define TUYA_BLE_INFO_PREFIX TUYA_BLE_LOG_INFO_COLOR "[I] " TUYA_BLE_LOG_MODULE_NAME TUYA_BLE_LOG_BREAK +#define TUYA_BLE_DEBUG_PREFIX TUYA_BLE_LOG_DEBUG_COLOR "[D] " TUYA_BLE_LOG_MODULE_NAME TUYA_BLE_LOG_BREAK + + +#define TUYA_BLE_LOG_INTERNAL_ERROR(_fmt_, ...) \ +do { \ + if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_ERROR) \ + { \ + TUYA_BLE_PRINTF(TUYA_BLE_ERROR_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR TUYA_BLE_LOG_CRLF, ##__VA_ARGS__); \ + } \ +} while(0) + +#define TUYA_BLE_LOG_INTERNAL_WARNING(_fmt_, ...) \ +do { \ + if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_WARNING) \ + { \ + TUYA_BLE_PRINTF(TUYA_BLE_WARNING_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR TUYA_BLE_LOG_CRLF, ##__VA_ARGS__); \ + } \ +} while(0) + +#define TUYA_BLE_LOG_INTERNAL_INFO(_fmt_, ...) \ +do { \ + if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_INFO) \ + { \ + TUYA_BLE_PRINTF(TUYA_BLE_INFO_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR TUYA_BLE_LOG_CRLF, ##__VA_ARGS__); \ + } \ +} while(0) + +#define TUYA_BLE_LOG_INTERNAL_DEBUG(_fmt_, ...) \ +do { \ + if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_DEBUG) \ + { \ + TUYA_BLE_PRINTF(TUYA_BLE_DEBUG_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR TUYA_BLE_LOG_CRLF, ##__VA_ARGS__); \ + } \ +} while(0) + +#define TUYA_BLE_LOG_INTERNAL_HEXDUMP_ERROR(_fmt_, p_data, len) \ +do { \ + if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_ERROR) \ + { \ + TUYA_BLE_PRINTF(TUYA_BLE_ERROR_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_BLE_LOG_CRLF,len ); \ + TUYA_BLE_HEXDUMP(p_data, len); \ + TUYA_BLE_PRINTF(TUYA_BLE_LOG_CRLF); \ + } \ +} while(0) + +#define TUYA_BLE_LOG_INTERNAL_HEXDUMP_WARNING(_fmt_, p_data, len) \ +do { \ + if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_WARNING) \ + { \ + TUYA_BLE_PRINTF(TUYA_BLE_WARNING_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_BLE_LOG_CRLF,len); \ + TUYA_BLE_HEXDUMP(p_data, len); \ + TUYA_BLE_PRINTF(TUYA_BLE_LOG_CRLF); \ + } \ +} while(0) + +#define TUYA_BLE_LOG_INTERNAL_HEXDUMP_INFO(_fmt_, p_data, len) \ +do { \ + if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_INFO) \ + { \ + TUYA_BLE_PRINTF(TUYA_BLE_INFO_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_BLE_LOG_CRLF,len); \ + TUYA_BLE_HEXDUMP(p_data, len); \ + TUYA_BLE_PRINTF(TUYA_BLE_LOG_CRLF); \ + } \ +} while(0) + +#define TUYA_BLE_LOG_INTERNAL_HEXDUMP_DEBUG(_fmt_, p_data, len) \ +do { \ + if (TUYA_BLE_LOG_LEVEL >= TUYA_BLE_LOG_LEVEL_DEBUG) \ + { \ + TUYA_BLE_PRINTF(TUYA_BLE_DEBUG_PREFIX _fmt_ TUYA_BLE_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_BLE_LOG_CRLF,len); \ + TUYA_BLE_HEXDUMP(p_data, len); \ + TUYA_BLE_PRINTF(TUYA_BLE_LOG_CRLF); \ + } \ +} while(0) + + + +/* TUYA APP LOG */ + +#ifndef TUYA_APP_LOG_COLORS_ENABLE +#define TUYA_APP_LOG_COLORS_ENABLE 0 +#endif + +#ifndef TUYA_APP_LOG_MODULE_NAME +#define TUYA_APP_LOG_MODULE_NAME "TUYA_APP" +#endif + + + +#if TUYA_APP_LOG_COLORS_ENABLE +#define TUYA_APP_LOG_COLOR_DEFAULT "\x1B[0m" +#define TUYA_APP_LOG_COLOR_BLACK "\x1B[1;30m" +#define TUYA_APP_LOG_COLOR_RED "\x1B[1;31m" +#define TUYA_APP_LOG_COLOR_GREEN "\x1B[1;32m" +#define TUYA_APP_LOG_COLOR_YELLOW "\x1B[1;33m" +#define TUYA_APP_LOG_COLOR_BLUE "\x1B[1;34m" +#define TUYA_APP_LOG_COLOR_MAGENTA "\x1B[1;35m" +#define TUYA_APP_LOG_COLOR_CYAN "\x1B[1;36m" +#define TUYA_APP_LOG_COLOR_WHITE "\x1B[1;37m" +#else +#define TUYA_APP_LOG_COLOR_DEFAULT +#define TUYA_APP_LOG_COLOR_BLACK +#define TUYA_APP_LOG_COLOR_RED +#define TUYA_APP_LOG_COLOR_GREEN +#define TUYA_APP_LOG_COLOR_YELLOW +#define TUYA_APP_LOG_COLOR_BLUE +#define TUYA_APP_LOG_COLOR_MAGENTA +#define TUYA_APP_LOG_COLOR_CYAN +#define TUYA_APP_LOG_COLOR_WHITE +#endif + +#define TUYA_APP_LOG_ERROR_COLOR TUYA_APP_LOG_COLOR_RED +#define TUYA_APP_LOG_WARNING_COLOR TUYA_APP_LOG_COLOR_YELLOW +#define TUYA_APP_LOG_INFO_COLOR TUYA_APP_LOG_COLOR_DEFAULT +#define TUYA_APP_LOG_DEBUG_COLOR TUYA_APP_LOG_COLOR_GREEN +#define TUYA_APP_LOG_DEFAULT_COLOR TUYA_APP_LOG_COLOR_DEFAULT + +#define TUYA_APP_LOG_BREAK ": " + +//#define TUYA_APP_LOG_CRLF "\r\n" +#define TUYA_APP_LOG_CRLF "" + +#define TUYA_APP_ERROR_PREFIX TUYA_APP_LOG_ERROR_COLOR "[E] " TUYA_APP_LOG_MODULE_NAME TUYA_APP_LOG_BREAK +#define TUYA_APP_WARNING_PREFIX TUYA_APP_LOG_WARNING_COLOR "[W] " TUYA_APP_LOG_MODULE_NAME TUYA_APP_LOG_BREAK +#define TUYA_APP_INFO_PREFIX TUYA_APP_LOG_INFO_COLOR "[I] " TUYA_APP_LOG_MODULE_NAME TUYA_APP_LOG_BREAK +#define TUYA_APP_DEBUG_PREFIX TUYA_APP_LOG_DEBUG_COLOR "[D] " TUYA_APP_LOG_MODULE_NAME TUYA_APP_LOG_BREAK + + +#define TUYA_APP_LOG_INTERNAL_ERROR(_fmt_, ...) \ +do { \ + if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_ERROR) \ + { \ + TUYA_BLE_PRINTF(TUYA_APP_ERROR_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR TUYA_APP_LOG_CRLF, ##__VA_ARGS__); \ + } \ +} while(0) + +#define TUYA_APP_LOG_INTERNAL_WARNING(_fmt_, ...) \ +do { \ + if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_WARNING) \ + { \ + TUYA_BLE_PRINTF(TUYA_APP_WARNING_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR TUYA_APP_LOG_CRLF, ##__VA_ARGS__); \ + } \ +} while(0) + +#define TUYA_APP_LOG_INTERNAL_INFO(_fmt_, ...) \ +do { \ + if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_INFO) \ + { \ + TUYA_BLE_PRINTF(TUYA_APP_INFO_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR TUYA_APP_LOG_CRLF, ##__VA_ARGS__); \ + } \ +} while(0) + +#define TUYA_APP_LOG_INTERNAL_DEBUG(_fmt_, ...) \ +do { \ + if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_DEBUG) \ + { \ + TUYA_BLE_PRINTF(TUYA_APP_DEBUG_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR TUYA_APP_LOG_CRLF, ##__VA_ARGS__); \ + } \ +} while(0) + +#define TUYA_APP_LOG_INTERNAL_HEXDUMP_ERROR(_fmt_, p_data, len) \ +do { \ + if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_ERROR) \ + { \ + TUYA_BLE_PRINTF(TUYA_APP_ERROR_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_APP_LOG_CRLF,len ); \ + TUYA_BLE_HEXDUMP(p_data, len); \ + TUYA_BLE_PRINTF(TUYA_APP_LOG_CRLF); \ + } \ +} while(0) + +#define TUYA_APP_LOG_INTERNAL_HEXDUMP_WARNING(_fmt_, p_data, len) \ +do { \ + if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_WARNING) \ + { \ + TUYA_BLE_PRINTF(TUYA_APP_WARNING_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_APP_LOG_CRLF,len); \ + TUYA_BLE_HEXDUMP(p_data, len); \ + TUYA_BLE_PRINTF(TUYA_APP_LOG_CRLF); \ + } \ +} while(0) + +#define TUYA_APP_LOG_INTERNAL_HEXDUMP_INFO(_fmt_, p_data, len) \ +do { \ + if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_INFO) \ + { \ + TUYA_BLE_PRINTF(TUYA_APP_INFO_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_APP_LOG_CRLF,len); \ + TUYA_BLE_HEXDUMP(p_data, len); \ + TUYA_BLE_PRINTF(TUYA_APP_LOG_CRLF); \ + } \ +} while(0) + +#define TUYA_APP_LOG_INTERNAL_HEXDUMP_DEBUG(_fmt_, p_data, len) \ +do { \ + if (TUYA_APP_LOG_LEVEL >= TUYA_APP_LOG_LEVEL_DEBUG) \ + { \ + TUYA_BLE_PRINTF(TUYA_APP_DEBUG_PREFIX _fmt_ TUYA_APP_LOG_DEFAULT_COLOR " [len=%d] :" TUYA_APP_LOG_CRLF,len); \ + TUYA_BLE_HEXDUMP(p_data, len); \ + TUYA_BLE_PRINTF(TUYA_APP_LOG_CRLF); \ + } \ +} while(0) + + +#endif // TUYA_BLE_LOG_INTERNAL__H__ + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_main.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_main.h new file mode 100644 index 0000000..7d33775 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_main.h @@ -0,0 +1,78 @@ +/** + * \file tuya_ble_main.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + + +#ifndef TUYA_BLE_MAIN_H__ +#define TUYA_BLE_MAIN_H__ + +#include "tuya_ble_type.h" +#include "tuya_ble_internal_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +extern tuya_ble_parameters_settings_t tuya_ble_current_para; + +void tuya_ble_connect_status_set(tuya_ble_connect_status_t status); + +tuya_ble_connect_status_t tuya_ble_connect_status_get(void); + +#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE + +void tuya_ble_link_status_set(tuya_ble_link_status_t status); + +tuya_ble_link_status_t tuya_ble_link_status_get(void); + +#endif + +void tuya_ble_event_init(void); + +uint8_t tuya_ble_event_send(tuya_ble_evt_param_t *evt); + +uint8_t tuya_ble_cb_event_send(tuya_ble_cb_evt_param_t *evt); + +uint8_t tuya_ble_get_adv_connect_request_bit_status(void); + +void tuya_ble_adv_change(void); + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN >= 3) +void tuya_ble_adv_change_with_connecting_request(void); +#endif + +tuya_ble_status_t tuya_ble_inter_event_response(tuya_ble_cb_evt_param_t *param); + +void tuya_ble_connect_monitor_timer_init(void); + +void tuya_ble_connect_monitor_timer_start(void); + +void tuya_ble_connect_monitor_timer_stop(void); + +#ifdef __cplusplus +} +#endif + + +#endif + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_mem.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_mem.h new file mode 100644 index 0000000..b19c0a9 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_mem.h @@ -0,0 +1,54 @@ +/** + * \file tuya_ble_mem.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + + +#ifndef TUYA_BLE_MEM_H__ +#define TUYA_BLE_MEM_H__ + +#include "tuya_ble_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +void *tuya_ble_malloc(uint16_t size); + +tuya_ble_status_t tuya_ble_free(uint8_t *ptr); + + +#ifdef __cplusplus +} +#endif + + +#endif + + + + + + + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_mutli_tsf_protocol.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_mutli_tsf_protocol.h new file mode 100644 index 0000000..8cbc0d7 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_mutli_tsf_protocol.h @@ -0,0 +1,316 @@ +/** + * \file tuya_ble_mutli_tsf_protocol.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ +#ifndef _TUYA_BLE_MUTLI_TSF_PROTOCOL_H +#define _TUYA_BLE_MUTLI_TSF_PROTOCOL_H + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __MUTLI_TSF_PROTOCOL_GLOBALS +#define __MUTLI_TSF_PROTOCOL_EXT +#else +#define __MUTLI_TSF_PROTOCOL_EXT extern +#endif + +/*********************************************************** +*************************micro define*********************** +***********************************************************/ +#define SNGL_PKG_TRSFR_LMT TUYA_BLE_DATA_MTU_MAX // single package transfer limit + +//#define FRM_TYPE_OFFSET (0x0f << 4) +#define FRM_VERSION_OFFSET (0x0f << 4) +#define FRM_SEQ_OFFSET (0x0f << 0) + +// frame total len +typedef uint32_t frame_total_t; + +// frame subpackage num +typedef uint32_t frame_subpkg_num_t; + + +// frame sequence +typedef uint8_t frame_seq_t; + +#define FRAME_SEQ_LMT 16 + +// frame subpackage len +typedef uint16_t frame_subpkg_len_t; + +// frame package description +typedef uint8_t frm_pkg_desc_t; +#define FRM_PKG_INIT 0 // frame package init +#define FRM_PKG_FIRST 1 // frame package first +#define FRM_PKG_MIDDLE 2 // frame package middle +#define FRM_PKG_END 3 // frame package end + +// mutil tsf ret code +typedef int32_t mtp_ret; +#define MTP_OK 0 +#define MTP_INVALID_PARAM 1 +#define MTP_COM_ERROR 2 +#define MTP_TRSMITR_CONTINUE 3 +#define MTP_TRSMITR_ERROR 4 +#define MTP_MALLOC_ERR 5 + +// frame transmitter process +typedef struct { + frame_total_t total; //4 bytes, total length of data, not including header + uint8_t version; //1 byte, protocol major version number + frame_seq_t seq; //1 byte + frm_pkg_desc_t pkg_desc; //1 byte, Current packet frame type (init/first/middle/end) + frame_subpkg_num_t subpkg_num;//4 bytes, current sub-packet number + uint32_t pkg_trsmitr_cnt; // package process count ,Number of bytes sent + frame_subpkg_len_t subpkg_len;//1 byte, the data length in the current sub-packet + uint8_t subpkg[SNGL_PKG_TRSFR_LMT]; +} frm_trsmitr_proc_s; + + +// dp type description,please refer to the relevant help documents of Tuya iot platform for the usage of various types of dp points. +typedef uint8_t dp_type; +#define DT_RAW 0 +#define DT_BOOL 1 +#define DT_VALUE 2 +#define DT_INT DT_VALUE +#define DT_STRING 3 +#define DT_ENUM 4 +#define DT_BITMAP 5 +#define DT_CHAR 7 //Not currently supported +#define DT_UCHAR 8 //Not currently supported +#define DT_SHORT 9 //Not currently supported +#define DT_USHORT 10 //Not currently supported +#define DT_LMT DT_USHORT + +#define DT_VALUE_LEN 4 // int +#define DT_BOOL_LEN 1 +#define DT_ENUM_LEN 1 +#define DT_BITMAP_MAX 4 // 1/2/4 +#define DT_STR_MAX 255 +#define DT_RAW_MAX 255 +#define DT_INT_LEN DT_VALUE_LEN + +typedef struct s_klv_node { + struct s_klv_node *next; + uint8_t id; + dp_type type; + uint16_t len; + uint8_t *data; +} klv_node_s; + + +/*********************************************************** +*************************variable define******************** +***********************************************************/ + + +/*********************************************************** +*************************function define******************** +***********************************************************/ +/*********************************************************** +* Function: make_klv_list +* description: +* Input: +* Output: +* Return: +***********************************************************/ +__MUTLI_TSF_PROTOCOL_EXT \ +klv_node_s *make_klv_list(klv_node_s *list, uint8_t id, dp_type type, \ + void *data, uint16_t len); + +/*********************************************************** +* Function: free_klv_list +* description: +* Input: list +* Output: +* Return: +***********************************************************/ +__MUTLI_TSF_PROTOCOL_EXT \ +void free_klv_list(klv_node_s *list); + +/*********************************************************** +* Function: klvlist_2_data +* description: +* Input: list +* Output: data len +* Return: +* Note:data need free. +***********************************************************/ +__MUTLI_TSF_PROTOCOL_EXT \ +mtp_ret klvlist_2_data(klv_node_s *list, uint8_t **data, uint32_t *len, uint8_t type); + +/*********************************************************** +* Function: data_2_klvlist +* description: +* Input: data len +* Output: list +* Return: +* Note: list need to call free_klv_list to free. +***********************************************************/ +__MUTLI_TSF_PROTOCOL_EXT \ +mtp_ret data_2_klvlist(uint8_t *data, uint32_t len, klv_node_s **list, uint8_t type); + +/*********************************************************** +* Function: create_trsmitr_init +* description: create a transmitter and initialize +* Input: none +* Output: +* Return: transmitter handle +***********************************************************/ +__MUTLI_TSF_PROTOCOL_EXT \ +frm_trsmitr_proc_s *create_trsmitr_init(void); + +/*********************************************************** +* Function: trsmitr_init +* description: init a transmitter +* Input: transmitter handle +* Output: +* Return: +***********************************************************/ +__MUTLI_TSF_PROTOCOL_EXT \ +void trsmitr_init(frm_trsmitr_proc_s *frm_trsmitr); + +/*********************************************************** +* Function: delete_trsmitr +* description: delete transmitter +* Input: transmitter handle +* Output: +* Return: +***********************************************************/ +__MUTLI_TSF_PROTOCOL_EXT \ +void delete_trsmitr(frm_trsmitr_proc_s *frm_trsmitr); + +/*********************************************************** +* Function: get_trsmitr_frame_total_len +* description: get a transmitter total data len +* Input: transmitter handle +* Output: +* Return: frame_total_t +***********************************************************/ +__MUTLI_TSF_PROTOCOL_EXT \ +frame_total_t get_trsmitr_frame_total_len(frm_trsmitr_proc_s *frm_trsmitr); + +/*********************************************************** +* Function: get_trsmitr_frame_type +* description: +* Input: transmitter handle +* Output: +* Return: frame_type_t +***********************************************************/ +__MUTLI_TSF_PROTOCOL_EXT \ +uint8_t get_trsmitr_frame_version(frm_trsmitr_proc_s *frm_trsmitr); + +/*********************************************************** +* Function: get_trsmitr_frame_seq +* description: +* Input: transmitter handle +* Output: +* Return: frame_seq_t +***********************************************************/ +__MUTLI_TSF_PROTOCOL_EXT \ +frame_seq_t get_trsmitr_frame_seq(frm_trsmitr_proc_s *frm_trsmitr); + +/*********************************************************** +* Function: get_trsmitr_subpkg_len +* description: +* Input: transmitter handle +* Output: +* Return: frame_subpkg_len_t +***********************************************************/ +__MUTLI_TSF_PROTOCOL_EXT \ +frame_subpkg_len_t get_trsmitr_subpkg_len(frm_trsmitr_proc_s *frm_trsmitr); + +/*********************************************************** +* Function: get_trsmitr_subpkg +* description: +* Input: transmitter handle +* Output: +* Return: subpackage buf +***********************************************************/ +__MUTLI_TSF_PROTOCOL_EXT \ +uint8_t *get_trsmitr_subpkg(frm_trsmitr_proc_s *frm_trsmitr); + +/*********************************************************** +* Function: trsmitr_send_pkg_encode +* description: frm_trsmitr->transmitter handle +* type->frame type +* buf->data buf +* len->data len +* Input: +* Output: +* Return: MTP_OK->buf send up +* MTP_TRSMITR_CONTINUE->need call again to be continue +* other->error +* Note: could get from encode data len and encode data by calling method + get_trsmitr_subpkg_len() and get_trsmitr_subpkg() +***********************************************************/ +__MUTLI_TSF_PROTOCOL_EXT \ +mtp_ret trsmitr_send_pkg_encode(frm_trsmitr_proc_s *frm_trsmitr, uint8_t version, uint8_t *buf, uint32_t len); + +/*********************************************************** +* Function: trsmitr_send_pkg_encode_with_packet_length +* description: Encoding function for specifying sub-packet length +* +* +* +* Input: +* Output: +* Return: MTP_OK->buf send up +* MTP_TRSMITR_CONTINUE->need call again to be continue +* other->error +* Note: could get from encode data len and encode data by calling method + get_trsmitr_subpkg_len() and get_trsmitr_subpkg() +***********************************************************/ +__MUTLI_TSF_PROTOCOL_EXT \ +mtp_ret trsmitr_send_pkg_encode_with_packet_length(frm_trsmitr_proc_s *frm_trsmitr, uint32_t pkg_len_max, uint8_t version, uint8_t *buf, uint32_t len); + +/*********************************************************** +* Function: trsmitr_recv_pkg_decode +* description: frm_trsmitr->transmitter handle +* raw_data->raw encode data +* raw_data_len->raw encode data len +* Input: +* Output: +* Return: MTP_OK->buf receive up +* MTP_TRSMITR_CONTINUE->need call again to be continue +* other->error +* Note: could get from decode data len and decode data by calling method + get_trsmitr_subpkg_len() and get_trsmitr_subpkg() +***********************************************************/ +__MUTLI_TSF_PROTOCOL_EXT \ +mtp_ret trsmitr_recv_pkg_decode(frm_trsmitr_proc_s *frm_trsmitr, uint8_t *raw_data, uint16_t raw_data_len); + + +#ifdef __cplusplus +} +#endif + + +#endif + + + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_queue.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_queue.h new file mode 100644 index 0000000..e1679d8 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_queue.h @@ -0,0 +1,56 @@ +/** + * \file tuya_ble_queue.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#ifndef TUYA_BLE_QUEUE_H_ +#define TUYA_BLE_QUEUE_H_ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + void *buf; + volatile uint8_t size; + volatile uint8_t offset; + volatile uint8_t rd_ptr; + volatile uint8_t wr_ptr; + volatile uint8_t used; +} tuya_ble_queue_t; + +tuya_ble_status_t tuya_ble_queue_init(tuya_ble_queue_t *q, void *buf, uint8_t size, uint8_t elem_size); +tuya_ble_status_t tuya_ble_enqueue(tuya_ble_queue_t *q, void *in); +tuya_ble_status_t tuya_ble_queue_get(tuya_ble_queue_t *q, void *out); +tuya_ble_status_t tuya_ble_dequeue(tuya_ble_queue_t *q, void *out); +void tuya_ble_queue_decrease(tuya_ble_queue_t *q); +void tuya_ble_queue_flush(tuya_ble_queue_t *q); +uint8_t tuya_ble_get_queue_used(tuya_ble_queue_t *q); + +#ifdef __cplusplus +} +#endif + +#endif //TUYA_BLE_QUEUE_H_ diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_storage.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_storage.h new file mode 100644 index 0000000..a8f1278 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_storage.h @@ -0,0 +1,53 @@ +/** + * \file tuya_ble_storage.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#ifndef TUYA_BLE_STORAGE_H_ +#define TUYA_BLE_STORAGE_H_ + +#include "tuya_ble_type.h" +#include "tuya_ble_internal_config.h" + +uint32_t tuya_ble_storage_save_sys_settings(void); + +uint32_t tuya_ble_storage_save_auth_settings(void); + +uint32_t tuya_ble_storage_init(void); + + +#if (TUYA_BLE_DEVICE_AUTH_DATA_STORE) + +tuya_ble_status_t tuya_ble_storage_write_pid(tuya_ble_product_id_type_t pid_type, uint8_t pid_len, uint8_t *pid); + +tuya_ble_status_t tuya_ble_storage_write_hid(uint8_t *hid, uint8_t len); + +tuya_ble_status_t tuya_ble_storage_read_id_info(tuya_ble_factory_id_data_t *id); + +tuya_ble_status_t tuya_ble_storage_write_auth_key_device_id_mac(uint8_t *auth_key, uint8_t auth_key_len, uint8_t *device_id, uint8_t device_id_len, + uint8_t *mac, uint8_t mac_len, uint8_t *mac_string, uint8_t mac_string_len, uint8_t *pid, uint8_t pid_len); + +#endif + +#endif + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_type.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_type.h new file mode 100644 index 0000000..9fc27f9 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_type.h @@ -0,0 +1,1057 @@ +/** + * \file tuya_ble_type.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + + +#ifndef TUYA_BLE_TYPE_H__ +#define TUYA_BLE_TYPE_H__ + +#include "tuya_ble_stdlib.h" + + +#ifndef NULL +#define NULL 0 +#endif + +#if defined(__CC_ARM) +#pragma anon_unions +#elif defined(__ICCARM__) +#pragma language = extended +#elif defined(__GNUC__) +/* anonymous unions are enabled by default */ +#endif + + +#if defined ( __CC_ARM ) + +#ifndef __TUYA_BLE_ASM +#define __TUYA_BLE_ASM __asm +#endif + +#ifndef __TUYA_BLE_INLINE +#define __TUYA_BLE_INLINE __inline +#endif + +#ifndef __TUYA_BLE_WEAK +#define __TUYA_BLE_WEAK __weak +#endif + +#ifndef __TUYA_BLE_ALIGN +#define __TUYA_BLE_ALIGN(n) __align(n) +#endif + +#ifndef __TUYA_BLE_PACKED +#define __TUYA_BLE_PACKED __packed +#endif + +#define TUYA_BLE_GET_SP() __current_sp() + +#elif defined ( __ICCARM__ ) + +#ifndef __TUYA_BLE_ASM +#define __TUYA_BLE_ASM __asm +#endif + +#ifndef __TUYA_BLE_INLINE +#define __TUYA_BLE_INLINE inline +#endif + +#ifndef __TUYA_BLE_WEAK +#define __TUYA_BLE_WEAK __weak +#endif + +#ifndef __TUYA_BLE_ALIGN +#define TUYA_BLE_STRING_PRAGMA(x) _Pragma(#x) +#define __TUYA_BLE_ALIGN(n) STRING_PRAGMA(data_alignment = n) +#endif + +#ifndef __TUYA_BLE_PACKED +#define __TUYA_BLE_PACKED __packed +#endif + +#define TUYA_BLE_GET_SP() __get_SP() + +#elif defined ( __GNUC__ ) + +#ifndef __TUYA_BLE_ASM +#define __TUYA_BLE_ASM __asm +#endif + +#ifndef __TUYA_BLE_INLINE +#define __TUYA_BLE_INLINE inline +#endif + +#ifndef __TUYA_BLE_WEAK +#define __TUYA_BLE_WEAK __attribute__((weak)) +#endif + +#ifndef __TUYA_BLE_ALIGN +#define __TUYA_BLE_ALIGN(n) __attribute__((aligned(n))) +#endif + +#ifndef __TUYA_BLE_PACKED +#define __TUYA_BLE_PACKED __attribute__((packed)) +#endif + +#define TUYA_BLE_GET_SP() tuya_ble_gcc_current_sp() + +static inline unsigned int tuya_ble_gcc_current_sp(void) +{ + register unsigned sp __asm("sp"); + return sp; +} +#endif + + +#define TUYA_BLE_EVT_BASE 0x00 +#define TUYA_BLE_CB_EVT_BASE 0x40 + +#define H_ID_LEN 19 +#define TUYA_BLE_PRODUCT_ID_DEFAULT_LEN 8 +//#define PRODUCT_KEY_LEN TUYA_BLE_PRODUCT_ID_OR_KEY_LEN +#define DEVICE_ID_LEN 16 +#define DEVICE_ID_LEN_MAX 20 +#define AUTH_KEY_LEN 32 +#define LOGIN_KEY_LEN 6 +#define ECC_SECRET_KEY_LEN 32 +#define DEVICE_VIRTUAL_ID_LEN 22 +#define SECRET_KEY_LEN 16 +#define PAIR_RANDOM_LEN 6 +#define MAC_LEN 6 +#define MAC_STRING_LEN 12 +#define BEACON_KEY_LEN 16 + +#define TUYA_BLE_PRODUCT_ID_MAX_LEN 16 + +#define TUYA_BLE_ADV_LOCAL_NAME_MAX_LEN 5 + +/** @defgroup TUY_BLE_DEVICE_COMMUNICATION_ABILITY tuya ble device communication ability + * @{ + */ +#define TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_BLE 0x0000 +#define TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_REGISTER_FROM_BLE 0x0001 +#define TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_MESH 0x0002 +#define TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_WIFI_24G 0x0004 +#define TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_WIFI_5G 0x0008 +#define TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_ZIGBEE 0x0010 +#define TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_NB 0x0020 +/** End of TUY_BLE_DEVICE_COMMUNICATION_ABILITY + * @} + */ + +#define TUYA_BLE_LOG_LEVEL_ERROR 1U +#define TUYA_BLE_LOG_LEVEL_WARNING 2U +#define TUYA_BLE_LOG_LEVEL_INFO 3U +#define TUYA_BLE_LOG_LEVEL_DEBUG 4U + +#define TUYA_APP_LOG_LEVEL_ERROR 1U +#define TUYA_APP_LOG_LEVEL_WARNING 2U +#define TUYA_APP_LOG_LEVEL_INFO 3U +#define TUYA_APP_LOG_LEVEL_DEBUG 4U + +/** @defgroup TUYA_BLE_SECURE_CONNECTION_TYPE tuya ble secure connection type + * @{ + */ +#define TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY 0x00 + +#define TUYA_BLE_SECURE_CONNECTION_WITH_ECC 0x01 + +#define TUYA_BLE_SECURE_CONNECTION_WTIH_PASSTHROUGH 0x02 + +#define TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_DEVCIE_ID_20 0x03 //Discarded in agreements 4.0 and later + +#define TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION 0x04 +/** End of TUYA_BLE_SECURE_CONNECTION_TYPE + * @} + */ + +enum { + KEY_USER_DEAL_POST = 0, + KEY_USER_DEAL_POST_MSG, + KEY_USER_DEAL_POST_EVENT, + KEY_USER_DEAL_POST_2, +}; + +typedef enum { + TUYA_BLE_SUCCESS = 0x00, + TUYA_BLE_ERR_INTERNAL, + TUYA_BLE_ERR_NOT_FOUND, + TUYA_BLE_ERR_NO_EVENT, + TUYA_BLE_ERR_NO_MEM, + TUYA_BLE_ERR_INVALID_ADDR, // Invalid pointer supplied + TUYA_BLE_ERR_INVALID_PARAM, // Invalid parameter(s) supplied. + TUYA_BLE_ERR_INVALID_STATE, // Invalid state to perform operation. + TUYA_BLE_ERR_INVALID_LENGTH, + TUYA_BLE_ERR_DATA_SIZE, + TUYA_BLE_ERR_TIMEOUT, + TUYA_BLE_ERR_BUSY, + TUYA_BLE_ERR_COMMON, + TUYA_BLE_ERR_RESOURCES, + TUYA_BLE_ERR_UNKNOWN, // other ble sdk errors +} tuya_ble_status_t; + + +typedef enum { + TUYA_BLE_PRODUCT_ID_TYPE_PID, + TUYA_BLE_PRODUCT_ID_TYPE_PRODUCT_KEY, +} tuya_ble_product_id_type_t; + + +typedef enum { + TUYA_BLE_ADDRESS_TYPE_PUBLIC, // public address + TUYA_BLE_ADDRESS_TYPE_RANDOM, // random address +} tuya_ble_addr_type_t; + +typedef struct { + tuya_ble_addr_type_t addr_type; + uint8_t addr[6]; +} tuya_ble_gap_addr_t; + +typedef struct { + uint8_t use_ext_license_key; //If use the license key stored by the SDK,initialized to 0, Otherwise 1. + uint8_t device_id_len; //if ==20,Compressed into 16 + uint8_t device_id[DEVICE_ID_LEN_MAX]; + uint8_t auth_key[AUTH_KEY_LEN]; + tuya_ble_gap_addr_t mac_addr; + uint8_t mac_addr_string[MAC_STRING_LEN]; + + tuya_ble_product_id_type_t p_type; + uint8_t product_id_len; + uint8_t product_id[TUYA_BLE_PRODUCT_ID_MAX_LEN]; + uint8_t adv_local_name_len; + uint8_t adv_local_name[TUYA_BLE_ADV_LOCAL_NAME_MAX_LEN]; //Only supported when TUYA_BLE_PROTOCOL_VERSION_HIGN >= 4. + uint32_t firmware_version; //0x00010102 : v1.1.2 + uint32_t hardware_version; + + uint8_t device_vid[DEVICE_VIRTUAL_ID_LEN]; + uint8_t login_key[LOGIN_KEY_LEN]; + uint8_t beacon_key[BEACON_KEY_LEN]; + uint8_t bound_flag; + + uint8_t reserve_1; + uint8_t reserve_2; +} tuya_ble_device_param_t; + + +typedef struct { + uint16_t min_conn_interval; // Range: 0x0006 to 0x0C80, Time = N * 1.25 msec, Time Range: 7.5 msec to 4 seconds. + uint16_t max_conn_interval; // Range: 0x0006 to 0x0C80, Time = N * 1.25 msec, Time Range: 7.5 msec to 4 seconds. + uint16_t slave_latency; // Range: 0x0000 to 0x01F3 + uint16_t conn_sup_timeout; // Range: 0x000A to 0x0C80, Time = N * 10 msec, Time Range: 100 msec to 32 seconds +} tuya_ble_gap_conn_param_t; + + +typedef enum { + TUYA_BLE_EVT_MTU_DATA_RECEIVE = TUYA_BLE_EVT_BASE, + TUYA_BLE_EVT_DEVICE_INFO_UPDATE, + TUYA_BLE_EVT_DP_DATA_REPORTED, + TUYA_BLE_EVT_DP_DATA_WITH_TIME_REPORTED, + TUYA_BLE_EVT_DP_DATA_WITH_TIME_STRING_REPORTED, + TUYA_BLE_EVT_DP_DATA_WITH_FLAG_REPORTED, + TUYA_BLE_EVT_DP_DATA_WITH_FLAG_AND_TIME_REPORTED, + TUYA_BLE_EVT_DP_DATA_WITH_FLAG_AND_TIME_STRING_REPORTED, + TUYA_BLE_EVT_DP_DATA_SEND, + TUYA_BLE_EVT_DP_DATA_WITH_TIME_SEND, + TUYA_BLE_EVT_DEVICE_UNBIND, + TUYA_BLE_EVT_FACTORY_RESET, + TUYA_BLE_EVT_OTA_RESPONSE, + TUYA_BLE_EVT_BULK_DATA_RESPONSE, + TUYA_BLE_EVT_DATA_PASSTHROUGH, + TUYA_BLE_EVT_PRODUCTION_TEST_RESPONSE, + TUYA_BLE_EVT_UART_CMD, + TUYA_BLE_EVT_BLE_CMD, + TUYA_BLE_EVT_NET_CONFIG_RESPONSE, + TUYA_BLE_EVT_CUSTOM, + TUYA_BLE_EVT_CONNECT_STATUS_UPDATE, + TUYA_BLE_EVT_UNBOUND_RESPONSE, + TUYA_BLE_EVT_ANOMALY_UNBOUND_RESPONSE, + TUYA_BLE_EVT_DEVICE_RESET_RESPONSE, + TUYA_BLE_EVT_TIME_REQ, + TUYA_BLE_EVT_EXTEND_TIME_REQ, + TUYA_BLE_EVT_GATT_SEND_DATA, + TUYA_BLE_EVT_CONNECTING_REQUEST, + TUYA_BLE_EVT_WEATHER_DATA_REQ, + TUYA_BLE_EVT_LINK_STATUS_UPDATE, +} tuya_ble_evt_t; + + +/* + * dp data report mode + *@note + * */ +typedef enum { + DP_SEND_FOR_CLOUD_PANEL = 0, // The mobile app uploads the received dp data to the cloud and also sends it to the panel for display. + DP_SEND_FOR_CLOUD, // The mobile app will only upload the received dp data to the cloud. + DP_SEND_FOR_PANEL, // The mobile app will only send the received dp data to the panel display. + DP_SEND_FOR_NONE, // Neither uploaded to the cloud nor sent to the panel display. +} tuya_ble_dp_data_send_mode_t; + + +typedef enum { + DP_SEND_TYPE_ACTIVE = 0, // The device actively sends dp data. + DP_SEND_TYPE_PASSIVE, // The device passively sends dp data. For example, in order to answer the dp query command of the mobile app. Currently only applicable to WIFI+BLE combo devices. +} tuya_ble_dp_data_send_type_t; + + +typedef enum { + DP_SEND_WITH_RESPONSE = 0, // Need a mobile app to answer. + DP_SEND_WITHOUT_RESPONSE, // No need for mobile app to answer. +} tuya_ble_dp_data_send_ack_t; + + +typedef struct { + uint8_t *p_data; // Used when the length of mtu data is greater than 20. + uint8_t data[20]; // Used when the length of mtu data is less than or equal to 20, In order to improve communication efficiency in BLE4.0 devices. + uint16_t len; +} tuya_ble_mtu_data_receive_t; + + + + +typedef enum { + DEVICE_INFO_TYPE_PID, + DEVICE_INFO_TYPE_PRODUCT_KEY, + DEVICE_INFO_TYPE_LOGIN_KEY, + DEVICE_INFO_TYPE_BOUND, + DEVICE_INFO_TYPE_BEACON_KEY, +} tuya_ble_device_info_type_t; + + +typedef struct { + tuya_ble_device_info_type_t type; + uint8_t len; + uint8_t data[32]; +} tuya_ble_device_info_data_t; + + + +typedef struct { + uint8_t *p_data; + uint16_t data_len; +} tuya_ble_dp_data_reported_t; + + +typedef struct { + uint32_t timestamp; + uint8_t *p_data; + uint16_t data_len; +} tuya_ble_dp_data_with_time_reported_t; + + +typedef struct { + uint8_t time_string[13 + 1]; + uint8_t *p_data; + uint16_t data_len; +} tuya_ble_dp_data_with_time_string_reported_t; + +typedef struct { + uint16_t sn; + tuya_ble_dp_data_send_mode_t mode; + uint8_t *p_data; + uint16_t data_len; +} tuya_ble_dp_data_with_flag_reported_t; + + +typedef struct { + uint16_t sn; + tuya_ble_dp_data_send_mode_t mode; + uint32_t timestamp; + uint8_t *p_data; + uint16_t data_len; +} tuya_ble_dp_data_with_flag_and_time_reported_t; + + +typedef struct { + uint16_t sn; + tuya_ble_dp_data_send_mode_t mode; + uint8_t time_string[13 + 1]; + uint8_t *p_data; + uint16_t data_len; +} tuya_ble_dp_data_with_flag_and_time_string_reported_t; + + +typedef struct { + uint32_t sn; + tuya_ble_dp_data_send_type_t type; + tuya_ble_dp_data_send_mode_t mode; + tuya_ble_dp_data_send_ack_t ack; + uint8_t *p_data; + uint16_t data_len; +} tuya_ble_dp_data_send_data_t; + + +typedef enum { + DP_TIME_TYPE_MS_STRING = 0, + DP_TIME_TYPE_UNIX_TIMESTAMP, +} tuya_ble_dp_data_send_time_type_t; + + +typedef struct { + uint32_t sn; + tuya_ble_dp_data_send_type_t type; + tuya_ble_dp_data_send_mode_t mode; + tuya_ble_dp_data_send_ack_t ack; + tuya_ble_dp_data_send_time_type_t time_type; + uint8_t time_data[13 + 1]; + uint8_t *p_data; + uint16_t data_len; +} tuya_ble_dp_data_with_time_send_data_t; + + +typedef struct { + uint8_t reserve; +} tuya_ble_device_unbind_t; + +typedef struct { + uint8_t reserve; +} tuya_ble_factory_reset_t; + +/* + * ota data + * */ + +typedef enum { + TUYA_BLE_OTA_REQ, + TUYA_BLE_OTA_FILE_INFO, + TUYA_BLE_OTA_FILE_OFFSET_REQ, + TUYA_BLE_OTA_DATA, + TUYA_BLE_OTA_END, + TUYA_BLE_OTA_UNKONWN, +} tuya_ble_ota_data_type_t; + + +typedef struct { + tuya_ble_ota_data_type_t type; + uint16_t data_len; + uint8_t *p_data; +} tuya_ble_ota_response_t; + + +typedef enum { + TUYA_BLE_BULK_DATA_EVT_READ_INFO, + TUYA_BLE_BULK_DATA_EVT_READ_BLOCK, + TUYA_BLE_BULK_DATA_EVT_SEND_DATA, + TUYA_BLE_BULK_DATA_EVT_ERASE, + TUYA_BLE_BULK_DATA_EVT_UNKONWN, +} tuya_ble_bulk_data_evt_type_t; + + +typedef struct { + uint16_t block_number; +} tuya_ble_bulk_data_evt_read_block_req_t; + + +typedef struct { + uint16_t block_number; +} tuya_ble_bulk_data_evt_send_data_req_t; + + +typedef struct { + tuya_ble_bulk_data_evt_type_t evt; + uint8_t bulk_type; + union { + tuya_ble_bulk_data_evt_read_block_req_t block_data_req_data; + tuya_ble_bulk_data_evt_send_data_req_t send_data_req_data; + } params; +} tuya_ble_bulk_data_request_t; + + + +typedef struct { + uint8_t status; + uint8_t flag; + uint32_t bulk_data_length; + uint32_t bulk_data_crc; + uint16_t block_data_length; +} tuya_ble_bulk_data_evt_read_info_res_t; + + +typedef struct { + uint8_t status; + uint16_t block_number; + uint16_t block_data_length; + uint16_t block_data_crc16; + uint16_t max_packet_data_length; +} tuya_ble_bulk_data_evt_read_block_res_t; + + +typedef struct { + uint16_t current_block_number; + uint16_t current_block_length; + uint8_t *p_current_block_data; +} tuya_ble_bulk_data_evt_send_data_res_t; + + +typedef struct { + uint8_t status; +} tuya_ble_bulk_data_evt_erase_res_t; + + +typedef struct { + tuya_ble_bulk_data_evt_type_t evt; + uint8_t bulk_type; + union { + tuya_ble_bulk_data_evt_read_info_res_t bulk_info_res_data; + tuya_ble_bulk_data_evt_read_block_res_t block_res_data; + tuya_ble_bulk_data_evt_send_data_res_t send_res_data; + tuya_ble_bulk_data_evt_erase_res_t erase_res_data; + } params; +} tuya_ble_bulk_data_response_t; + + + +typedef struct { + uint16_t data_len; + uint8_t *p_data; +} tuya_ble_passthrough_data_t; + + +typedef struct { + uint8_t channel; + uint16_t data_len; + uint8_t *p_data; +} tuya_ble_production_test_response_data_t; + +typedef struct { + uint32_t cmd; + uint16_t data_len; + uint8_t *p_data; +} tuya_ble_uart_cmd_t; + + +typedef struct { + uint32_t cmd; + uint16_t data_len; + uint8_t *p_data; +} tuya_ble_ble_cmd_t; + +typedef struct { + int16_t result_code; +} tuya_ble_net_config_response_t; + + +typedef struct { + uint8_t cmd; +} tuya_ble_connecting_request_data_t; + + +typedef struct { + int32_t evt_id; + void *data; + void (*custom_event_handler)(int32_t evt_id, void *data); +} tuya_ble_custom_evt_t; + + +typedef enum { + TUYA_BLE_CONNECTED, + TUYA_BLE_DISCONNECTED, +} tuya_ble_connect_status_change_t; + + +typedef struct { + uint8_t result_code; +} tuya_ble_ubound_response_t; + + +typedef struct { + uint8_t result_code; +} tuya_ble_anomaly_ubound_response_t; + + +typedef struct { + uint8_t result_code; +} tuya_ble_device_reset_response_t; + +typedef struct { + // 0-13-byte millisecond string[from cloud] + // 1 - normal time format[from cloud] + // 2 - normal time format[from app local] + uint8_t time_type; +} tuya_ble_time_req_data_t; + + +typedef struct { + uint8_t n_years_dst; +} tuya_ble_extend_time_req_data_t; + + +typedef struct { + uint8_t *p_data; + uint16_t data_len; +} tuya_ble_weather_req_data_t; + + +typedef struct { + uint8_t link_app_status; +} tuya_ble_link_status_update_data_t; + + +typedef struct { + tuya_ble_evt_t event; + void (*event_handler)(void *evt); +} tuya_ble_evt_hdr_t; + + +/* + * tuya ble sdk evt parameters union + * */ +typedef struct { + tuya_ble_evt_hdr_t hdr; + union { + tuya_ble_mtu_data_receive_t mtu_data; + tuya_ble_device_info_data_t device_info_data; + tuya_ble_dp_data_reported_t reported_data; + tuya_ble_dp_data_with_time_reported_t reported_with_time_data; + tuya_ble_dp_data_with_time_string_reported_t reported_with_time_string_data; + tuya_ble_dp_data_with_flag_reported_t flag_reported_data; + tuya_ble_dp_data_with_flag_and_time_reported_t flag_reported_with_time_data; + tuya_ble_dp_data_with_flag_and_time_string_reported_t flag_reported_with_time_string_data; + tuya_ble_dp_data_send_data_t dp_send_data; + tuya_ble_dp_data_with_time_send_data_t dp_with_time_send_data; + tuya_ble_device_unbind_t device_unbind_data; + tuya_ble_factory_reset_t factory_reset_data; + tuya_ble_ota_response_t ota_response_data; + tuya_ble_bulk_data_response_t bulk_res_data; + tuya_ble_passthrough_data_t passthrough_data; + tuya_ble_production_test_response_data_t prod_test_res_data; + tuya_ble_uart_cmd_t uart_cmd_data; + tuya_ble_ble_cmd_t ble_cmd_data; + tuya_ble_net_config_response_t net_config_response_data; + tuya_ble_custom_evt_t custom_evt; + tuya_ble_connect_status_change_t connect_change_evt; + tuya_ble_ubound_response_t ubound_res_data; + tuya_ble_anomaly_ubound_response_t anomaly_ubound_res_data; + tuya_ble_device_reset_response_t device_reset_res_data; + tuya_ble_time_req_data_t time_req_data; + tuya_ble_extend_time_req_data_t extend_time_req_data; + tuya_ble_connecting_request_data_t connecting_request_data; + tuya_ble_weather_req_data_t weather_req_data; + tuya_ble_link_status_update_data_t link_update_data; + }; +} tuya_ble_evt_param_t; + + + + +/* + * tuya ble call back event type. + * */ +typedef enum { + TUYA_BLE_CB_EVT_CONNECTE_STATUS = TUYA_BLE_CB_EVT_BASE, + TUYA_BLE_CB_EVT_DP_WRITE, // old version + TUYA_BLE_CB_EVT_DP_QUERY, + TUYA_BLE_CB_EVT_DP_DATA_RECEIVED, // new version + TUYA_BLE_CB_EVT_OTA_DATA, + TUYA_BLE_CB_EVT_BULK_DATA, + TUYA_BLE_CB_EVT_NETWORK_INFO, + TUYA_BLE_CB_EVT_WIFI_SSID, + TUYA_BLE_CB_EVT_TIME_STAMP, + TUYA_BLE_CB_EVT_TIME_NORMAL, + TUYA_BLE_CB_EVT_APP_LOCAL_TIME_NORMAL, + TUYA_BLE_CB_EVT_TIME_STAMP_WITH_DST, + TUYA_BLE_CB_EVT_DATA_PASSTHROUGH, + TUYA_BLE_CB_EVT_DP_DATA_REPORT_RESPONSE, + TUYA_BLE_CB_EVT_DP_DATA_WTTH_TIME_REPORT_RESPONSE, + TUYA_BLE_CB_EVT_DP_DATA_WITH_FLAG_REPORT_RESPONSE, + TUYA_BLE_CB_EVT_DP_DATA_WITH_FLAG_AND_TIME_REPORT_RESPONSE, + TUYA_BLE_CB_EVT_DP_DATA_SEND_RESPONSE, // new version + TUYA_BLE_CB_EVT_DP_DATA_WITH_TIME_SEND_RESPONSE, // new version + TUYA_BLE_CB_EVT_UNBOUND, + TUYA_BLE_CB_EVT_ANOMALY_UNBOUND, + TUYA_BLE_CB_EVT_DEVICE_RESET, + TUYA_BLE_CB_EVT_UPDATE_LOGIN_KEY_VID, + TUYA_BLE_CB_EVT_UNBIND_RESET_RESPONSE, // Notify the application of the result of the local reset + TUYA_BLE_CB_EVT_WEATHER_DATA_REQ_RESPONSE, // received request weather data app response + TUYA_BLE_CB_EVT_WEATHER_DATA_RECEIVED, // received app sync weather data +} tuya_ble_cb_evt_t; + +/* + * current connect status + *@note + * */ +typedef enum { + UNBONDING_UNCONN = 0, + UNBONDING_CONN, + BONDING_UNCONN, + BONDING_CONN, + BONDING_UNAUTH_CONN, + UNBONDING_UNAUTH_CONN, + UNKNOW_STATUS +} tuya_ble_connect_status_t; + +/* + * current link status + *@note + * */ +typedef enum { + LINK_DISCONNECTED = 0, + LINK_CONNECTED, + LINK_ENCRYPTED, + LINK_UNKNOW_STATUS +} tuya_ble_link_status_t; + +/* + * current connect status + *@note + * */ +typedef enum { + TUYA_BLE_AUTH_STATUS_PHASE_NONE = 0, + TUYA_BLE_AUTH_STATUS_PHASE_1, + TUYA_BLE_AUTH_STATUS_PHASE_2, + TUYA_BLE_AUTH_STATUS_PHASE_3, +} tuya_ble_auth_status_t; + +/* + * dp data buffer: (Dp_id,Dp_type,Dp_len,Dp_data),(Dp_id,Dp_type,Dp_len,Dp_data),.... + * */ +typedef struct { + uint8_t *p_data; + uint16_t data_len; +} tuya_ble_dp_write_data_t; + +/* + * query dp point data,if data_len is 0,means query all dp point data,otherwise query the dp point in p_data buffer. + * */ +typedef struct { + uint8_t *p_data; + uint16_t data_len; +} tuya_ble_dp_query_data_t; + +/* +* dp data buffer(Dp_len:2): (Dp_id,Dp_type,Dp_len,Dp_data),(Dp_id,Dp_type,Dp_len,Dp_data),.... + * */ +typedef struct { + uint32_t sn; + uint8_t *p_data; + uint16_t data_len; +} tuya_ble_dp_data_received_data_t; + + +typedef struct { + tuya_ble_ota_data_type_t type; + uint16_t data_len; + uint8_t *p_data; +} tuya_ble_ota_data_t; + + + +/* + * network data,unformatted json data,for example " {"wifi_ssid":"tuya","password":"12345678","token":"xxxxxxxxxx"} " + * */ +typedef struct { + uint16_t data_len;//include '\0' + uint8_t *p_data; +} tuya_ble_network_data_t; + +/* + * wifi ssid data,unformatted json data,for example " {"wifi_ssid":"tuya","password":"12345678"} " + * */ +typedef struct { + uint16_t data_len;//include '\0' + uint8_t *p_data; +} tuya_ble_wifi_ssid_data_t; + + +/* + * uninx timestamp + * */ +typedef struct { + uint8_t timestamp_string[14]; + int16_t time_zone; //actual time zone Multiply by 100. +} tuya_ble_timestamp_data_t; + + +/* + * normal time formatted + * */ +typedef struct { + uint16_t nYear; + uint8_t nMonth; + uint8_t nDay; + uint8_t nHour; + uint8_t nMin; + uint8_t nSec; + uint8_t DayIndex; /* 0 = Sunday */ + int16_t time_zone; //actual time zone Multiply by 100. +} tuya_ble_time_noraml_data_t; + +/* + * normal time formatted + * */ +typedef struct { + uint32_t timestamp; + int16_t time_zone; /**< actual time zone Multiply by 100. */ + uint8_t n_years_dst; /**< how many years of daylight saving time. */ + uint8_t *p_data; /**< the point of dst data. */ + uint16_t data_len; /**< dst data length. */ +} tuya_ble_timestamp_with_dst_data_t; + +/* + * + * */ +typedef struct { + uint8_t status; +} tuya_ble_dp_data_report_response_t; + +/* + * + * */ +typedef struct { + uint8_t status; +} tuya_ble_dp_data_with_time_report_response_t; + +/* + * + * */ +typedef struct { + uint16_t sn; + tuya_ble_dp_data_send_mode_t mode; + uint8_t status; +} tuya_ble_dp_data_with_flag_report_response_t; + +/* + * + * */ +typedef struct { + uint16_t sn; + tuya_ble_dp_data_send_mode_t mode; + uint8_t status; +} tuya_ble_dp_data_with_flag_and_time_report_response_t; + +/* + * + * */ +typedef struct { + uint32_t sn; + tuya_ble_dp_data_send_type_t type; + tuya_ble_dp_data_send_mode_t mode; + tuya_ble_dp_data_send_ack_t ack; + uint8_t status; // 0 - succeed, 1- failed. +} tuya_ble_dp_data_send_response_data_t; + +/* + * + * */ +typedef struct { + uint32_t sn; + tuya_ble_dp_data_send_type_t type; + tuya_ble_dp_data_send_mode_t mode; + tuya_ble_dp_data_send_ack_t ack; + uint8_t status; // 0 - succeed, 1- failed. +} tuya_ble_dp_data_with_time_send_response_data_t; + + +/* + * + * */ +typedef struct { + uint8_t data; +} tuya_ble_unbound_data_t; + +/* + * + * */ +typedef struct { + uint8_t data; +} tuya_ble_anomaly_unbound_data_t; + +/* + * + * */ +typedef struct { + uint8_t data; +} tuya_ble_device_reset_data_t; + +/* + * + * */ +typedef struct { + uint8_t status; +} tuya_ble_weather_data_req_response_t; + + +/** + * weather data (key_len,key,vaule_type,value_len,value),(key_len,key,vaule_type,value_len,value),.... + * + */ +typedef struct { + uint16_t object_count; /**< weather data object counts. */ + uint8_t location; /**< location. */ + uint8_t *p_data; /**< weather data. */ + uint16_t data_len; /**< weather data length. */ +} tuya_ble_weather_data_received_data_t; + + +/* + * + * */ +typedef struct { + uint8_t login_key_len; + uint8_t vid_len; + uint8_t beacon_key_len; + uint8_t login_key[LOGIN_KEY_LEN]; + uint8_t vid[DEVICE_VIRTUAL_ID_LEN]; + uint8_t beacon_key[BEACON_KEY_LEN]; +} tuya_ble_login_key_vid_data_t; + +typedef enum { + RESET_TYPE_UNBIND, + RESET_TYPE_FACTORY_RESET, +} tuya_ble_reset_type_t; + +/* + * + * */ +typedef struct { + tuya_ble_reset_type_t type; + uint8_t status; //0-succeed,1-failed. +} tuya_ble_unbind_reset_response_data_t; + +/* + * tuya ble sdk callback parameters union + * */ +typedef struct { + tuya_ble_cb_evt_t evt; + union { + tuya_ble_connect_status_t connect_status; + tuya_ble_dp_write_data_t dp_write_data; + tuya_ble_dp_query_data_t dp_query_data; + tuya_ble_dp_data_received_data_t dp_received_data; + tuya_ble_ota_data_t ota_data; + tuya_ble_bulk_data_request_t bulk_req_data; + tuya_ble_network_data_t network_data; + tuya_ble_wifi_ssid_data_t wifi_info_data; + tuya_ble_timestamp_data_t timestamp_data; + tuya_ble_time_noraml_data_t time_normal_data; + tuya_ble_timestamp_with_dst_data_t timestamp_with_dst_data; + tuya_ble_passthrough_data_t ble_passthrough_data; + tuya_ble_dp_data_report_response_t dp_response_data; + tuya_ble_dp_data_with_time_report_response_t dp_with_time_response_data; + tuya_ble_dp_data_with_flag_report_response_t dp_with_flag_response_data; + tuya_ble_dp_data_with_flag_and_time_report_response_t dp_with_flag_and_time_response_data; + tuya_ble_dp_data_send_response_data_t dp_send_response_data; + tuya_ble_dp_data_with_time_send_response_data_t dp_with_time_send_response_data; + tuya_ble_unbound_data_t unbound_data; + tuya_ble_anomaly_unbound_data_t anomaly_unbound_data; + tuya_ble_device_reset_data_t device_reset_data; + tuya_ble_login_key_vid_data_t device_login_key_vid_data; + tuya_ble_unbind_reset_response_data_t reset_response_data; + tuya_ble_weather_data_req_response_t weather_req_response_data; + tuya_ble_weather_data_received_data_t weather_received_data; + }; +} tuya_ble_cb_evt_param_t; + + +/* TIMER related */ +typedef void *tuya_ble_timer_t; + +typedef void (*tuya_ble_timer_handler_t)(void *); + + +typedef enum { + TUYA_BLE_TIMER_SINGLE_SHOT, + TUYA_BLE_TIMER_REPEATED, +} tuya_ble_timer_mode; + + + +typedef void (*tuya_ble_callback_t)(tuya_ble_cb_evt_param_t *param); + + +typedef struct { + uint32_t crc; + uint32_t settings_version; + uint8_t h_id[H_ID_LEN]; + uint8_t device_id[DEVICE_ID_LEN]; + uint8_t mac[MAC_LEN]; + uint8_t auth_key[AUTH_KEY_LEN]; + uint8_t mac_string[MAC_LEN * 2]; + uint8_t pid_type; + uint8_t pid_len; + uint8_t factory_pid[TUYA_BLE_PRODUCT_ID_MAX_LEN]; + uint8_t res[110]; +} tuya_ble_auth_settings_t; + + +typedef struct { + uint32_t crc; + uint32_t settings_version; + tuya_ble_product_id_type_t pid_type; + uint8_t pid_len; + uint8_t common_pid[TUYA_BLE_PRODUCT_ID_MAX_LEN]; + uint8_t login_key[LOGIN_KEY_LEN]; + uint8_t ecc_secret_key[ECC_SECRET_KEY_LEN]; + uint8_t device_virtual_id[DEVICE_VIRTUAL_ID_LEN]; + uint8_t user_rand[PAIR_RANDOM_LEN]; + uint8_t bound_flag; + uint8_t factory_test_flag; + uint8_t server_cert_pub_key[64]; + uint8_t beacon_key[BEACON_KEY_LEN]; + uint8_t res[47]; +} tuya_ble_sys_settings_t; + + +typedef struct { + tuya_ble_auth_settings_t auth_settings; + tuya_ble_sys_settings_t sys_settings; + tuya_ble_product_id_type_t pid_type; + uint8_t pid_len; + uint8_t pid[TUYA_BLE_PRODUCT_ID_MAX_LEN]; + uint8_t adv_local_name_len; + uint8_t adv_local_name[TUYA_BLE_ADV_LOCAL_NAME_MAX_LEN]; +} tuya_ble_parameters_settings_t; + + +typedef struct { + tuya_ble_product_id_type_t pid_type; + uint8_t pid_len; + uint8_t pid[TUYA_BLE_PRODUCT_ID_MAX_LEN]; + uint8_t h_id[H_ID_LEN]; + uint8_t device_id[DEVICE_ID_LEN]; + uint8_t mac[MAC_LEN]; + uint8_t auth_key[AUTH_KEY_LEN]; +} tuya_ble_factory_id_data_t; + + +typedef enum { + PRIVATE_DATA_ECC_KEY = 1, + + PRIVATE_DATA_DEV_CERT = 10, + PRIVATE_DATA_TUYA_AUTH_TOKEN, +} tuya_ble_private_data_type; + + +/** @defgroup TUYA_BLE_PROD_OEM_TYPE tuya ble prod oem type + * @{ + */ +#define TUYA_BLE_PROD_OEM_TYPE_NONE ( 0 ) +#define TUYA_BLE_PROD_OEM_TYPE_0_5 ( 1 ) +#define TUYA_BLE_PROD_OEM_TYPE_1_0 ( 2 ) +#define TUYA_BLE_PROD_OEM_TYPE_1_5 ( 3 ) +#define TUYA_BLE_PROD_OEM_TYPE_2_0 ( 4 ) +/** End of TUYA_BLE_PROD_OEM_TYPE + * @} + */ + + +#endif diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_unix_time.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_unix_time.h new file mode 100644 index 0000000..d183e5d --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_unix_time.h @@ -0,0 +1,51 @@ +/** + * \file tuya_ble_unix_time.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#ifndef TUYA_BLE_UNIX_TIME_H_ +#define TUYA_BLE_UNIX_TIME_H_ + +#include "tuya_ble_stdlib.h" + +/* time struct */ +typedef struct { + uint16_t nYear; + uint8_t nMonth; + uint8_t nDay; + uint8_t nHour; + uint8_t nMin; + uint8_t nSec; + uint8_t DayIndex; /* 0 = Sunday */ +} tuya_ble_time_struct_data_t; + + +void tuya_ble_utc_sec_2_mytime(uint32_t utc_sec, tuya_ble_time_struct_data_t *result, bool daylightSaving); + +void tuya_ble_utc_sec_2_mytime_string(uint32_t utc_sec, bool daylightSaving, char *s); + +uint32_t tuya_ble_mytime_2_utc_sec(tuya_ble_time_struct_data_t *currTime, bool daylightSaving); + +#endif + + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_utils.h b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_utils.h new file mode 100644 index 0000000..db4abfc --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/include/tuya_ble_utils.h @@ -0,0 +1,123 @@ +/** + * \file tuya_ble_utils.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#ifndef TUYA_BLE_UTILS_H_ +#define TUYA_BLE_UTILS_H_ + +#include "tuya_ble_stdlib.h" + + +#define BSWAP_16(x) \ + (uint16_t)((((uint16_t)(x) & 0x00ff) << 8) | \ + (((uint16_t)(x) & 0xff00) >> 8) ) + + +#define BSWAP_32(x) \ + (uint32_t)((((uint32_t)(x) & 0xff000000) >> 24) | \ + (((uint32_t)(x) & 0x00ff0000) >> 8) | \ + (((uint32_t)(x) & 0x0000ff00) << 8) | \ + (((uint32_t)(x) & 0x000000ff) << 24)) + +int32_t tuya_ble_rand_number(int32_t min, int32_t max); + +int32_t tuya_ble_count_bits(uint32_t data); + +void tuya_ble_inverted_array(uint8_t *array, uint16_t length); + +bool tuya_ble_buffer_value_is_all_x(uint8_t *buffer, uint16_t len, uint8_t value); + +uint8_t tuya_ble_check_sum(uint8_t *pbuf, uint16_t len); + +uint8_t tuya_ble_check_num(uint8_t *buf, uint8_t num); + +void tuya_ble_hextoascii(uint8_t *hexbuf, uint8_t len, uint8_t *ascbuf); + +void tuya_ble_hextostr(uint8_t *hexbuf, uint8_t len, uint8_t *strbuf); + +void tuya_ble_asciitohex(uint8_t *ascbuf, uint8_t *hexbuf); + +uint8_t tuya_ble_char_2_ascii(uint8_t data); + +void tuya_ble_str_to_hex(uint8_t *str_buf, uint8_t str_len, uint8_t *hex_buf); + +bool tuya_ble_is_word_aligned_tuya(void const *p); + +uint16_t tuya_ble_crc16_compute(uint8_t *p_data, uint16_t size, uint16_t *p_crc); + +uint32_t tuya_ble_crc32_compute(uint8_t const *p_data, uint32_t size, uint32_t const *p_crc); + +void tuya_ble_device_id_20_to_16(uint8_t *in, uint8_t *out); + +void tuya_ble_device_id_16_to_20(uint8_t *in, uint8_t *out); + +char tuya_ble_hexstr2hex(uint8_t *hexstr, int32_t len, uint8_t *hex); + +/** + * @brief Function for search character/symbol index from input string + * + * @param + * [in]data : pointer to input data + * [in]data : Number of bytes of data + * [in]symbol : Search symbol or character, Such as ':' or ',' + * [out]index[] : Array of indexs + * + * @return The number of matched character/symbol + * + * @note + * + * */ +int32_t tuya_ble_search_symbol_index(char *data, uint16_t len, char symbol, uint8_t index[]); + +int32_t tuya_ble_ascii_to_int(char *ascii, uint16_t len); + +/** + * @brief Function for pem format ecc key to hex foramt + * + * @param + * [in]pem : pointer to pem data + * [out]key : pointer to output data, hex format ecc key + * [out]key_len: Number of bytes of key. + * + * @return 0 - failed, 1 - success + * + * @note developer could use tuya_ble_ecc_key_pem2hex_example() function to test + * + * */ +int32_t tuya_ble_ecc_key_pem2hex(const char *pem, uint8_t *key, uint16_t *key_len); + +/** + * @brief Function for extract r+s from der from ecdsa sign + * + * @param + * [in]der : pointer to der data + * [out]raw_rs : pointer to output data, the raw data[r+s] of der + * + * @return 0 - failed, 1 - success + * + * @note + * + * */ +int32_t tuya_ble_ecc_sign_secp256r1_extract_raw_from_der(const char *der, uint8_t *raw_rs); + +#endif /* TUYA_UTILS_H_ */ diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/lib/libtuya_lib.a b/apps/common/third_party_profile/tuya_protocol/sdk/lib/libtuya_lib.a new file mode 100644 index 0000000..44f8ff2 Binary files /dev/null and b/apps/common/third_party_profile/tuya_protocol/sdk/lib/libtuya_lib.a differ diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/lib/tuya_ble_event_handler.h b/apps/common/third_party_profile/tuya_protocol/sdk/lib/tuya_ble_event_handler.h new file mode 100644 index 0000000..84f0bdc --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/lib/tuya_ble_event_handler.h @@ -0,0 +1,99 @@ +/** + * \file tuya_ble_event_handler.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + + +#ifndef TUYA_BLE_EVENT_HANDLER_H__ +#define TUYA_BLE_EVENT_HANDLER_H__ + +#include "tuya_ble_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + +void tuya_ble_handle_device_info_update_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_dp_data_reported_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_dp_data_with_time_reported_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_dp_data_with_time_string_reported_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_dp_data_with_flag_reported_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_dp_data_with_flag_and_time_reported_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_dp_data_with_flag_and_time_string_reported_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_dp_data_send_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_dp_data_with_time_send_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_device_unbind_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_factory_reset_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_ota_response_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_bulk_data_evt(tuya_ble_evt_param_t *p_evt); + +void tuya_ble_handle_data_passthrough_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_data_prod_test_response_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_uart_cmd_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_ble_cmd_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_net_config_response_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_time_request_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_extend_time_request_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_unbound_response_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_anomaly_unbound_response_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_device_reset_response_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_connect_change_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_ble_data_evt(uint8_t *buf, uint16_t len); + +void tuya_ble_handle_connecting_request_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_link_update_evt(tuya_ble_evt_param_t *evt); + +void tuya_ble_handle_weather_data_request_evt(tuya_ble_evt_param_t *evt); + +#ifdef __cplusplus +} +#endif + + +#endif + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/lib/tuya_ble_secure.h b/apps/common/third_party_profile/tuya_protocol/sdk/lib/tuya_ble_secure.h new file mode 100644 index 0000000..eb9f7f1 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/lib/tuya_ble_secure.h @@ -0,0 +1,74 @@ +/** + * \file tuya_ble_secure.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#ifndef TUYA_BLE_SECURE_H_ +#define TUYA_BLE_SECURE_H_ + +#include "tuya_ble_type.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +enum { + ENCRYPTION_MODE_NONE, + ENCRYPTION_MODE_KEY_1, + ENCRYPTION_MODE_KEY_2, + ENCRYPTION_MODE_KEY_3, + ENCRYPTION_MODE_KEY_4, + ENCRYPTION_MODE_SESSION_KEY, + ENCRYPTION_MODE_ECDH_KEY, + ENCRYPTION_MODE_FTM_KEY, + ENCRYPTION_MODE_MAX, +}; + +bool tuya_ble_register_key_generate(uint8_t *output, tuya_ble_parameters_settings_t *current_para); + +uint8_t tuya_ble_encryption(uint16_t protocol_version, uint8_t encryption_mode, uint8_t *iv, uint8_t *in_buf, uint32_t in_len, uint32_t *out_len, uint8_t *out_buf, tuya_ble_parameters_settings_t *current_para_data, uint8_t *dev_rand); + +uint8_t tuya_ble_encrypt_old_with_key(uint8_t *key, uint8_t *in_buf, uint8_t in_len, uint8_t *out_buf); + +bool tuya_ble_device_id_encrypt(uint8_t *key_in, uint16_t key_len, uint8_t *input, uint16_t input_len, uint8_t *output); + +bool tuya_ble_device_id_decrypt(uint8_t *key_in, uint16_t key_len, uint8_t *input, uint16_t input_len, uint8_t *output); + +bool tuya_ble_device_id_encrypt_v4(uint8_t *key_in, uint16_t key_len, uint8_t *input, uint16_t input_len, uint8_t *output); + +uint8_t tuya_ble_decryption(uint16_t protocol_version, uint8_t const *in_buf, uint32_t in_len, uint32_t *out_len, uint8_t *out_buf, tuya_ble_parameters_settings_t *current_para_data, uint8_t *dev_rand); + +bool tuya_ble_server_cert_data_verify(const uint8_t *p_data, uint16_t data_len, const uint8_t *p_sig); + +bool tuya_ble_sig_data_verify(const uint8_t *p_pk, const uint8_t *p_data, uint16_t data_len, const uint8_t *p_sig); + +void tuya_ble_event_process(tuya_ble_evt_param_t *tuya_ble_evt); + + +#ifdef __cplusplus +} +#endif + +#endif // TUYA_BLE_SECURE_H_ + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_api.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_api.c new file mode 100644 index 0000000..a69fa16 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_api.c @@ -0,0 +1,1570 @@ +/** + * \file tuya_ble_api.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ +#include "tuya_ble_stdlib.h" +#include "tuya_ble_api.h" +#include "tuya_ble_port.h" +#include "tuya_ble_type.h" +#include "tuya_ble_main.h" +#include "tuya_ble_mem.h" +#include "tuya_ble_log.h" +#include "tuya_ble_data_handler.h" +#include "tuya_ble_internal_config.h" +#include "tuya_ble_mutli_tsf_protocol.h" +#include "tuya_ble_storage.h" +#include "tuya_ble_utils.h" +#include "tuya_ble_sdk_version.h" +#include "tuya_ble_gatt_send_queue.h" +#include "tuya_ble_event.h" +#include "tuya_ble_app_production_test.h" + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE == TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) +#include "cJSON.h" +#endif + +static uint8_t m_callback_numbers = 0; + +#if TUYA_BLE_USE_OS +extern uint32_t m_cb_queue_table[TUYA_BLE_MAX_CALLBACKS]; + +/** + * @brief Function for registe queue to receive call back evt when use os + * + * @note + * + * */ +tuya_ble_status_t tuya_ble_callback_queue_register(void *cb_queue) +{ + tuya_ble_status_t ret; + + tuya_ble_device_enter_critical(); + if (m_callback_numbers == TUYA_BLE_MAX_CALLBACKS) { + ret = TUYA_BLE_ERR_RESOURCES; + } else { + m_cb_queue_table[m_callback_numbers] = (uint32_t)cb_queue; + m_callback_numbers++; + + ret = TUYA_BLE_SUCCESS; + } + tuya_ble_device_exit_critical(); + + return ret; +} + + +/** + * @brief Function for response the event. + * + * @note if use os,must be sure to call this function after process one event in queue. + * + * */ +tuya_ble_status_t tuya_ble_event_response(tuya_ble_cb_evt_param_t *param) +{ + return tuya_ble_inter_event_response(param); +} + +#else + + +extern tuya_ble_callback_t m_cb_table[TUYA_BLE_MAX_CALLBACKS]; +/** + * @brief Function for registe call back functions. + * + * @note appliction should receive the message from the call back registed by this function. + * + * */ +tuya_ble_status_t tuya_ble_callback_queue_register(tuya_ble_callback_t cb) +{ + tuya_ble_status_t ret; + + tuya_ble_device_enter_critical(); + if (m_callback_numbers == TUYA_BLE_MAX_CALLBACKS) { + ret = TUYA_BLE_ERR_RESOURCES; + } else { + m_cb_table[m_callback_numbers] = cb; + m_callback_numbers++; + + ret = TUYA_BLE_SUCCESS; + } + tuya_ble_device_exit_critical(); + + return ret; +} + +/** + * @brief Function for get scheduler queue size. + * + * @note If it returns 0, it means that the queue has not been initialized. + * + * */ +uint16_t tuya_ble_scheduler_queue_size_get(void) +{ + return tuya_ble_sched_queue_size_get(); +} + +/** + * @brief Function for get queue free space. + * + * @note + * + * */ +uint16_t tuya_ble_scheduler_queue_space_get(void) +{ + return tuya_ble_sched_queue_space_get(); +} + +/** + * @brief Function for get the number of current events in the queue. + * + * @note + * + * */ +uint16_t tuya_ble_scheduler_queue_events_get(void) +{ + return tuya_ble_sched_queue_events_get(); +} + +#endif + +/** + * @brief Function for check if sleep is allowed. + * + * @note If it returns true, it means that sleep is allowed. + * + * */ +bool tuya_ble_sleep_allowed_check(void) +{ +#if TUYA_BLE_USE_OS + if (tuya_ble_internal_production_test_with_ble_flag_get() == 0) +#else + if ((tuya_ble_scheduler_queue_events_get() == 0) && (tuya_ble_internal_production_test_with_ble_flag_get() == 0)) +#endif + { + return true; + } else { + return false; + } +} + + +/* + *@brief + *@param + * + *@note + * + * */ +tuya_ble_status_t tuya_ble_gatt_receive_data(uint8_t *p_data, uint16_t len) +{ + tuya_ble_evt_param_t event; + + memset(&event, 0, sizeof(tuya_ble_evt_param_t)); + + event.hdr.event = TUYA_BLE_EVT_MTU_DATA_RECEIVE; + + if (len > TUYA_BLE_DATA_MTU_MAX) { + event.mtu_data.len = TUYA_BLE_DATA_MTU_MAX; + } else { + event.mtu_data.len = len; + } + if (event.mtu_data.len <= 20) { + memcpy(event.mtu_data.data, p_data, event.mtu_data.len); + } else { + event.mtu_data.p_data = (uint8_t *)tuya_ble_malloc(event.mtu_data.len); + if (event.mtu_data.p_data == NULL) { + printf("tuya_ble_gatt_receive_data error 1"); + return TUYA_BLE_ERR_NO_MEM; + } + memcpy(event.mtu_data.p_data, p_data, event.mtu_data.len); + } + + if (tuya_ble_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_event_send ble data error,data len = %d ", event.mtu_data.len); + if (event.mtu_data.p_data) { + printf("tuya_ble_gatt_receive_data error 2"); + tuya_ble_free(event.mtu_data.p_data); + } + return TUYA_BLE_ERR_INTERNAL; + } + + return TUYA_BLE_SUCCESS; +} + + +/* + *@brief Function for receive uart data. + *@param + * + *@note + * + * */ + +typedef enum { + TUYA_BLE_UART_REV_STATE_FOUND_NULL, + TUYA_BLE_UART_REV_STATE_FOUND_HEAD, + TUYA_BLE_UART_REV_STATE_FOUND_CMD, + TUYA_BLE_UART_REV_STATE_FOUND_LEN_H, + TUYA_BLE_UART_REV_STATE_FOUND_LEN_L, + TUYA_BLE_UART_REV_STATE_FOUND_DATA, + TUYA_BLE_UART_REV_STATE_UNKOWN, +} tuya_ble_uart_rev_state_type_t; + +#define UART_RX_BUFFER_MAX 300 +#define UART_RX_DATA_LEN_MAX 249 +static volatile tuya_ble_uart_rev_state_type_t current_uart_rev_state_type = TUYA_BLE_UART_REV_STATE_FOUND_NULL; +static uint8_t UART_RX_Buffer[UART_RX_BUFFER_MAX]; +static uint8_t UART_RX_Buffer_temp[3] = {0}; +static uint16_t uart_data_len = 0; +static volatile uint16_t UART_RX_Count = 0; + + +static bool tuya_ble_common_uart_data_unpack(uint8_t data) +{ + bool ret = false; + + UART_RX_Buffer_temp[0] = UART_RX_Buffer_temp[1]; + UART_RX_Buffer_temp[1] = UART_RX_Buffer_temp[2]; + UART_RX_Buffer_temp[2] = data; + + if (((UART_RX_Buffer_temp[0] == 0x55) || (UART_RX_Buffer_temp[0] == 0x66)) && (UART_RX_Buffer_temp[1] == 0xAA) && ((UART_RX_Buffer_temp[2] == 0x00) || (UART_RX_Buffer_temp[2] == 0x01))) { + memset(UART_RX_Buffer, 0, sizeof(UART_RX_Buffer)); + memcpy(UART_RX_Buffer, UART_RX_Buffer_temp, 3); + memset(UART_RX_Buffer_temp, 0, 3); + UART_RX_Count = 3; + current_uart_rev_state_type = TUYA_BLE_UART_REV_STATE_FOUND_HEAD; + uart_data_len = 0; + return ret; + } + + switch (current_uart_rev_state_type) { + case TUYA_BLE_UART_REV_STATE_FOUND_NULL: + break; + case TUYA_BLE_UART_REV_STATE_FOUND_HEAD: + UART_RX_Buffer[UART_RX_Count++] = data; + current_uart_rev_state_type = TUYA_BLE_UART_REV_STATE_FOUND_CMD; + break; + case TUYA_BLE_UART_REV_STATE_FOUND_CMD: + UART_RX_Buffer[UART_RX_Count++] = data; + current_uart_rev_state_type = TUYA_BLE_UART_REV_STATE_FOUND_LEN_H; + break; + case TUYA_BLE_UART_REV_STATE_FOUND_LEN_H: + UART_RX_Buffer[UART_RX_Count++] = data; + uart_data_len = (UART_RX_Buffer[UART_RX_Count - 2] << 8) | UART_RX_Buffer[UART_RX_Count - 1]; + if (uart_data_len > UART_RX_DATA_LEN_MAX) { + memset(UART_RX_Buffer_temp, 0, 3); + memset(UART_RX_Buffer, 0, sizeof(UART_RX_Buffer)); + UART_RX_Count = 0; + current_uart_rev_state_type = TUYA_BLE_UART_REV_STATE_FOUND_NULL; + uart_data_len = 0; + } else if (uart_data_len > 0) { + current_uart_rev_state_type = TUYA_BLE_UART_REV_STATE_FOUND_LEN_L; + } else { + current_uart_rev_state_type = TUYA_BLE_UART_REV_STATE_FOUND_DATA; + } + break; + case TUYA_BLE_UART_REV_STATE_FOUND_LEN_L: + UART_RX_Buffer[UART_RX_Count++] = data; //DATA + uart_data_len--; + if (uart_data_len == 0) { + current_uart_rev_state_type = TUYA_BLE_UART_REV_STATE_FOUND_DATA; + } + break; + case TUYA_BLE_UART_REV_STATE_FOUND_DATA: + UART_RX_Buffer[UART_RX_Count++] = data; //sum data + ret = true; + break; + default: + memset(UART_RX_Buffer_temp, 0, 3); + memset(UART_RX_Buffer, 0, sizeof(UART_RX_Buffer)); + UART_RX_Count = 0; + current_uart_rev_state_type = TUYA_BLE_UART_REV_STATE_FOUND_NULL; + uart_data_len = 0; + break; + }; + + return ret; + +} + +tuya_ble_status_t tuya_ble_common_uart_receive_data(uint8_t *p_data, uint16_t len) +{ + tuya_ble_status_t ret = TUYA_BLE_ERR_NOT_FOUND; + tuya_ble_evt_param_t event; + uint8_t *uart_evt_buffer; + uint16_t i; + + for (i = 0; i < len; i++) { + if (tuya_ble_common_uart_data_unpack(p_data[i])) { + + uart_evt_buffer = (uint8_t *)tuya_ble_malloc(UART_RX_Count); + + if (uart_evt_buffer == NULL) { + TUYA_BLE_LOG_ERROR("tuya_MemGet uart evt buffer fail."); + ret = TUYA_BLE_ERR_NO_MEM; + } else { + event.hdr.event = TUYA_BLE_EVT_UART_CMD; + + event.uart_cmd_data.data_len = UART_RX_Count; + + event.uart_cmd_data.p_data = uart_evt_buffer; + + memcpy(event.uart_cmd_data.p_data, &UART_RX_Buffer[0], event.uart_cmd_data.data_len); + + if (tuya_ble_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_event_send uart data error."); + tuya_ble_free(uart_evt_buffer); + ret = TUYA_BLE_ERR_BUSY; + } else { + ret = TUYA_BLE_SUCCESS; + } + } + memset(UART_RX_Buffer_temp, 0, 3); + memset(UART_RX_Buffer, 0, sizeof(UART_RX_Buffer)); + UART_RX_Count = 0; + current_uart_rev_state_type = TUYA_BLE_UART_REV_STATE_FOUND_NULL; + uart_data_len = 0; + + } + } + + return ret; +} + + +/** + * @brief Function for send the full instruction received from uart to the sdk. + * + * @param + * [in]p_data : pointer to full instruction data(Complete instruction,include0x55 or 0x66 0xaa and checksum.) + * [in]len : Number of bytes of pdata. + * + * @note If the application uses a custom uart parsing algorithm to obtain the full uart instruction,then call this function to send the full instruction. + * + * */ +tuya_ble_status_t tuya_ble_common_uart_send_full_instruction_received(uint8_t *p_data, uint16_t len) +{ + tuya_ble_status_t ret = TUYA_BLE_SUCCESS; + tuya_ble_evt_param_t event; + uint16_t rev_len, data_len; + uint8_t *uart_evt_buffer; + + if (len < 7) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + + if ((p_data[0] != 0x55) && (p_data[0] != 0x66)) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + + uart_evt_buffer = (uint8_t *)tuya_ble_malloc(len); + + if (uart_evt_buffer == NULL) { + TUYA_BLE_LOG_ERROR("tuya_MemGet uart evt buffer fail."); + ret = TUYA_BLE_ERR_NO_MEM; + } else { + event.hdr.event = TUYA_BLE_EVT_UART_CMD; + + event.uart_cmd_data.data_len = len; + + event.uart_cmd_data.p_data = uart_evt_buffer; + + memcpy(event.uart_cmd_data.p_data, p_data, len); + + if (tuya_ble_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_event_send uart full cmd error."); + tuya_ble_free(uart_evt_buffer); + ret = TUYA_BLE_ERR_BUSY; + } + } + + return ret; +} + + + + +/* + *@brief + *@param + * + *@note + * + * */ +tuya_ble_status_t tuya_ble_device_update_product_id(tuya_ble_product_id_type_t type, uint8_t len, uint8_t *p_buf) +{ + tuya_ble_evt_param_t event; + + if (len == 0) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + + if (len > TUYA_BLE_PRODUCT_ID_MAX_LEN) { + len = TUYA_BLE_PRODUCT_ID_MAX_LEN; + } + + event.hdr.event = TUYA_BLE_EVT_DEVICE_INFO_UPDATE; + + if (type == TUYA_BLE_PRODUCT_ID_TYPE_PID) { + event.device_info_data.type = DEVICE_INFO_TYPE_PID; + } else { + event.device_info_data.type = DEVICE_INFO_TYPE_PRODUCT_KEY; + } + + event.device_info_data.len = len; + memcpy(event.device_info_data.data, p_buf, len); + if (tuya_ble_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_event_send product id update error"); + return TUYA_BLE_ERR_INTERNAL; + } + + return TUYA_BLE_SUCCESS; +} + + +/* + *@brief + *@param + * + *@note + * + * */ +tuya_ble_status_t tuya_ble_device_update_login_key(uint8_t *p_buf, uint8_t len) +{ + tuya_ble_evt_param_t event; + + event.hdr.event = TUYA_BLE_EVT_DEVICE_INFO_UPDATE; + + event.device_info_data.type = DEVICE_INFO_TYPE_LOGIN_KEY; + + if (len < LOGIN_KEY_LEN) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + event.device_info_data.len = LOGIN_KEY_LEN; + memcpy(event.device_info_data.data, p_buf, LOGIN_KEY_LEN); + if (tuya_ble_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_event_send LOGIN KEY update error"); + return TUYA_BLE_ERR_INTERNAL; + } + + return TUYA_BLE_SUCCESS; +} +#if ((TUYA_BLE_PROTOCOL_VERSION_HIGN==4) && (TUYA_BLE_BEACON_KEY_ENABLE)) +/** + *@brief + *@param + * + *@note + * + * */ +tuya_ble_status_t tuya_ble_device_update_beacon_key(uint8_t *p_buf, uint8_t len) +{ + tuya_ble_evt_param_t event; + + event.hdr.event = TUYA_BLE_EVT_DEVICE_INFO_UPDATE; + + event.device_info_data.type = DEVICE_INFO_TYPE_BEACON_KEY; + + if (len < BEACON_KEY_LEN) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + event.device_info_data.len = BEACON_KEY_LEN; + memcpy(event.device_info_data.data, p_buf, BEACON_KEY_LEN); + if (tuya_ble_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_event_send BEACON KEY update error"); + return TUYA_BLE_ERR_INTERNAL; + } + + return TUYA_BLE_SUCCESS; +} +#endif +/* + *@brief + *@param + * + *@note + * + * */ +tuya_ble_status_t tuya_ble_device_update_mcu_version(uint32_t mcu_firmware_version, uint32_t mcu_hardware_version) +{ + tuya_ble_set_external_mcu_version(mcu_firmware_version, mcu_hardware_version); + return TUYA_BLE_SUCCESS; +} + +/* + *@brief + *@param + * + *@note + * + * */ +tuya_ble_status_t tuya_ble_device_update_bound_state(uint8_t state) +{ + tuya_ble_evt_param_t event; + + event.hdr.event = TUYA_BLE_EVT_DEVICE_INFO_UPDATE; + + event.device_info_data.type = DEVICE_INFO_TYPE_BOUND; + + if ((state != 1) && (state != 0)) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + event.device_info_data.len = 1; + event.device_info_data.data[0] = state; + if (tuya_ble_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_event_send bound state update error"); + return TUYA_BLE_ERR_INTERNAL; + } + + return TUYA_BLE_SUCCESS; +} + + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN==4) + +/* + *@brief + *@param + * + *@note + * + * */ +tuya_ble_status_t tuya_ble_dp_data_send(uint32_t sn, tuya_ble_dp_data_send_type_t type, tuya_ble_dp_data_send_mode_t mode, tuya_ble_dp_data_send_ack_t ack, uint8_t *p_dp_data, uint32_t dp_data_len) +{ + tuya_ble_evt_param_t evt; + uint8_t *ble_evt_buffer = NULL; + mtp_ret ret; + klv_node_s *list = NULL; + + if (tuya_ble_connect_status_get() != BONDING_CONN) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + if ((dp_data_len > (TUYA_BLE_SEND_MAX_DATA_LEN - 7)) || (dp_data_len == 0)) { + TUYA_BLE_LOG_ERROR("send dp data len error,data len = %d , max data len = %d", dp_data_len, TUYA_BLE_SEND_MAX_DATA_LEN - 7); + return TUYA_BLE_ERR_INVALID_LENGTH; + } + ret = data_2_klvlist(p_dp_data, dp_data_len, &list, 1); + if (MTP_OK != ret) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + free_klv_list(list); + + ble_evt_buffer = (uint8_t *)tuya_ble_malloc(dp_data_len + 7); + if (ble_evt_buffer == NULL) { + return TUYA_BLE_ERR_NO_MEM; + } else { + ble_evt_buffer[0] = TUYA_BLE_DP_WRITE_CURRENT_VERSION; + ble_evt_buffer[1] = sn >> 24; + ble_evt_buffer[2] = sn >> 16; + ble_evt_buffer[3] = sn >> 8; + ble_evt_buffer[4] = sn; + switch (type) { + case DP_SEND_TYPE_ACTIVE: + ble_evt_buffer[5] = 0; + break; + case DP_SEND_TYPE_PASSIVE: + ble_evt_buffer[5] = 1; + break; + default: + ble_evt_buffer[5] = 0; + break; + + }; + if (ack == DP_SEND_WITHOUT_RESPONSE) { + ble_evt_buffer[5] |= 0x80; + } + ble_evt_buffer[6] = mode; + memcpy(ble_evt_buffer + 7, p_dp_data, dp_data_len); + } + + evt.hdr.event = TUYA_BLE_EVT_DP_DATA_SEND; + evt.dp_send_data.sn = sn; + evt.dp_send_data.type = type; + evt.dp_send_data.mode = mode; + evt.dp_send_data.ack = ack; + evt.dp_send_data.p_data = ble_evt_buffer; + evt.dp_send_data.data_len = dp_data_len + 7; + + if (tuya_ble_event_send(&evt) != 0) { + tuya_ble_free(ble_evt_buffer); + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; +} + + +/* + *@brief + *@param + * + *@note + * + * */ +tuya_ble_status_t tuya_ble_dp_data_with_time_send(uint32_t sn, tuya_ble_dp_data_send_mode_t mode, tuya_ble_dp_data_send_time_type_t time_type, uint8_t *p_time_data, uint8_t *p_dp_data, uint32_t dp_data_len) +{ + tuya_ble_evt_param_t evt; + uint8_t *ble_evt_buffer = NULL; + mtp_ret ret; + klv_node_s *list = NULL; + uint16_t buffer_len = 0; + + if (tuya_ble_connect_status_get() != BONDING_CONN) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + if ((dp_data_len > (TUYA_BLE_SEND_MAX_DATA_LEN - 7 - 14)) || (dp_data_len == 0)) { + return TUYA_BLE_ERR_INVALID_LENGTH; + } + + ret = data_2_klvlist(p_dp_data, dp_data_len, &list, 1); + if (MTP_OK != ret) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + free_klv_list(list); + + if (time_type == DP_TIME_TYPE_UNIX_TIMESTAMP) { + buffer_len = dp_data_len + 12; + } else if (time_type == DP_TIME_TYPE_MS_STRING) { + buffer_len = dp_data_len + 21; + } else { + return TUYA_BLE_ERR_INVALID_PARAM; + } + + ble_evt_buffer = (uint8_t *)tuya_ble_malloc(buffer_len); + + if (ble_evt_buffer == NULL) { + return TUYA_BLE_ERR_NO_MEM; + } else { + ble_evt_buffer[0] = TUYA_BLE_DP_WRITE_CURRENT_VERSION; + ble_evt_buffer[1] = sn >> 24; + ble_evt_buffer[2] = sn >> 16; + ble_evt_buffer[3] = sn >> 8; + ble_evt_buffer[4] = sn; + ble_evt_buffer[5] = 0; //must 0 - WITH RESPONSE + + ble_evt_buffer[6] = mode; + ble_evt_buffer[7] = time_type; + + if (time_type == DP_TIME_TYPE_UNIX_TIMESTAMP) { + memcpy(&ble_evt_buffer[8], p_time_data, 4); + memcpy(ble_evt_buffer + 12, p_dp_data, dp_data_len); + } else { + memcpy(&ble_evt_buffer[8], p_time_data, 13); + memcpy(ble_evt_buffer + 21, p_dp_data, dp_data_len); + } + + + } + + evt.hdr.event = TUYA_BLE_EVT_DP_DATA_WITH_TIME_SEND; + evt.dp_with_time_send_data.sn = sn; + evt.dp_with_time_send_data.type = DP_SEND_TYPE_ACTIVE; + evt.dp_with_time_send_data.mode = mode; + evt.dp_with_time_send_data.ack = DP_SEND_WITH_RESPONSE; + evt.dp_with_time_send_data.p_data = ble_evt_buffer; + evt.dp_with_time_send_data.data_len = buffer_len; + + if (tuya_ble_event_send(&evt) != 0) { + tuya_ble_free(ble_evt_buffer); + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; +} + +#else +/* + *@brief + *@param + * + *@note + * + * */ +tuya_ble_status_t tuya_ble_dp_data_report(uint8_t *p_data, uint32_t len) +{ + tuya_ble_evt_param_t evt; + uint8_t *ble_evt_buffer; + mtp_ret ret; + klv_node_s *list = NULL; + + if (tuya_ble_connect_status_get() != BONDING_CONN) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + if ((len > TUYA_BLE_REPORT_MAX_DP_DATA_LEN) || (len == 0)) { + TUYA_BLE_LOG_ERROR("report dp data len error,data len = %d , max data len = %d", len, TUYA_BLE_REPORT_MAX_DP_DATA_LEN); + return TUYA_BLE_ERR_INVALID_LENGTH; + } + ret = data_2_klvlist(p_data, len, &list, 0); + if (MTP_OK != ret) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + free_klv_list(list); + + ble_evt_buffer = (uint8_t *)tuya_ble_malloc(len); + if (ble_evt_buffer == NULL) { + return TUYA_BLE_ERR_NO_MEM; + } else { + memcpy(ble_evt_buffer, p_data, len); + } + + evt.hdr.event = TUYA_BLE_EVT_DP_DATA_REPORTED; + evt.reported_data.p_data = ble_evt_buffer; + evt.reported_data.data_len = len; + + if (tuya_ble_event_send(&evt) != 0) { + tuya_ble_free(ble_evt_buffer); + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; +} + +/* + *@brief + *@param + * + *@note + * + * */ +tuya_ble_status_t tuya_ble_dp_data_with_flag_report(uint16_t sn, tuya_ble_dp_data_send_mode_t mode, uint8_t *p_data, uint32_t len) +{ + tuya_ble_evt_param_t evt; + uint8_t *ble_evt_buffer = NULL; + mtp_ret ret; + klv_node_s *list = NULL; + + if (tuya_ble_connect_status_get() != BONDING_CONN) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + if ((len > (TUYA_BLE_REPORT_MAX_DP_DATA_LEN - 3)) || (len == 0)) { + TUYA_BLE_LOG_ERROR("report flag dp data len error,data len = %d , max data len = %d", len, (TUYA_BLE_REPORT_MAX_DP_DATA_LEN - 3)); + return TUYA_BLE_ERR_INVALID_LENGTH; + } + ret = data_2_klvlist(p_data, len, &list, 0); + if (MTP_OK != ret) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + free_klv_list(list); + + ble_evt_buffer = (uint8_t *)tuya_ble_malloc(len + 3); + if (ble_evt_buffer == NULL) { + return TUYA_BLE_ERR_NO_MEM; + } else { + ble_evt_buffer[0] = sn >> 8; + ble_evt_buffer[1] = sn; + ble_evt_buffer[2] = mode; + memcpy(ble_evt_buffer + 3, p_data, len); + } + + evt.hdr.event = TUYA_BLE_EVT_DP_DATA_WITH_FLAG_REPORTED; + evt.flag_reported_data.sn = sn; + evt.flag_reported_data.mode = mode; + evt.flag_reported_data.p_data = ble_evt_buffer; + evt.flag_reported_data.data_len = len + 3; + + if (tuya_ble_event_send(&evt) != 0) { + tuya_ble_free(ble_evt_buffer); + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; +} + +/* + *@brief + *@param + * + *@note + * + * */ + +tuya_ble_status_t tuya_ble_dp_data_with_time_report(uint32_t timestamp, uint8_t *p_data, uint32_t len) +{ + tuya_ble_evt_param_t evt; + uint8_t *ble_evt_buffer; + mtp_ret ret; + klv_node_s *list = NULL; + + if (tuya_ble_connect_status_get() != BONDING_CONN) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + if ((len > TUYA_BLE_REPORT_MAX_DP_DATA_LEN) || (len == 0)) { + return TUYA_BLE_ERR_INVALID_LENGTH; + } + ret = data_2_klvlist(p_data, len, &list, 0); + if (MTP_OK != ret) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + free_klv_list(list); + ble_evt_buffer = (uint8_t *)tuya_ble_malloc(len); + if (ble_evt_buffer == NULL) { + return TUYA_BLE_ERR_NO_MEM; + } else { + memcpy(ble_evt_buffer, p_data, len); + } + + evt.hdr.event = TUYA_BLE_EVT_DP_DATA_WITH_TIME_REPORTED; + evt.reported_with_time_data.timestamp = timestamp; + evt.reported_with_time_data.p_data = ble_evt_buffer; + evt.reported_with_time_data.data_len = len; + + if (tuya_ble_event_send(&evt) != 0) { + tuya_ble_free(ble_evt_buffer); + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; +} + +/* + *@brief + *@param + * + *@note + * + * */ +tuya_ble_status_t tuya_ble_dp_data_with_flag_and_time_report(uint16_t sn, tuya_ble_dp_data_send_mode_t mode, uint32_t timestamp, uint8_t *p_data, uint32_t len) +{ + tuya_ble_evt_param_t evt; + uint8_t *ble_evt_buffer = NULL; + mtp_ret ret; + klv_node_s *list = NULL; + + if (tuya_ble_connect_status_get() != BONDING_CONN) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + if ((len > (TUYA_BLE_REPORT_MAX_DP_DATA_LEN - 8)) || (len == 0)) { + return TUYA_BLE_ERR_INVALID_LENGTH; + } + ret = data_2_klvlist(p_data, len, &list, 0); + if (MTP_OK != ret) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + free_klv_list(list); + ble_evt_buffer = (uint8_t *)tuya_ble_malloc(len); + if (ble_evt_buffer == NULL) { + return TUYA_BLE_ERR_NO_MEM; + } else { + memcpy(ble_evt_buffer, p_data, len); + } + + evt.hdr.event = TUYA_BLE_EVT_DP_DATA_WITH_FLAG_AND_TIME_REPORTED; + evt.flag_reported_with_time_data.sn = sn; + evt.flag_reported_with_time_data.mode = mode; + evt.flag_reported_with_time_data.timestamp = timestamp; + evt.flag_reported_with_time_data.p_data = ble_evt_buffer; + evt.flag_reported_with_time_data.data_len = len; + + if (tuya_ble_event_send(&evt) != 0) { + tuya_ble_free(ble_evt_buffer); + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; +} + +/* + *@brief + *@param + * + *@note time_string: 13-byte millisecond string ,for example ,"0000000123456"; + * + * */ + +tuya_ble_status_t tuya_ble_dp_data_with_time_ms_string_report(uint8_t *time_string, uint8_t *p_data, uint32_t len) +{ + tuya_ble_evt_param_t evt; + uint8_t *ble_evt_buffer; + mtp_ret ret; + klv_node_s *list = NULL; + + if (tuya_ble_connect_status_get() != BONDING_CONN) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + if ((len > TUYA_BLE_REPORT_MAX_DP_DATA_LEN) || (len == 0)) { + return TUYA_BLE_ERR_INVALID_LENGTH; + } + ret = data_2_klvlist(p_data, len, &list, 0); + if (MTP_OK != ret) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + free_klv_list(list); + ble_evt_buffer = (uint8_t *)tuya_ble_malloc(len); + if (ble_evt_buffer == NULL) { + return TUYA_BLE_ERR_NO_MEM; + } else { + memcpy(ble_evt_buffer, p_data, len); + } + + evt.hdr.event = TUYA_BLE_EVT_DP_DATA_WITH_TIME_STRING_REPORTED; + memcpy(evt.reported_with_time_string_data.time_string, time_string, 13); + evt.reported_with_time_string_data.p_data = ble_evt_buffer; + evt.reported_with_time_string_data.data_len = len; + + if (tuya_ble_event_send(&evt) != 0) { + tuya_ble_free(ble_evt_buffer); + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; +} + +/* + *@brief + *@param + * + *@note time_string: 13-byte millisecond string ,for example ,"0000000123456"; + * + * */ +tuya_ble_status_t tuya_ble_dp_data_with_flag_and_time_ms_string_report(uint16_t sn, tuya_ble_dp_data_send_mode_t mode, uint8_t *time_string, uint8_t *p_data, uint32_t len) +{ + tuya_ble_evt_param_t evt; + uint8_t *ble_evt_buffer = NULL; + mtp_ret ret; + klv_node_s *list = NULL; + + if (tuya_ble_connect_status_get() != BONDING_CONN) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + if ((len > (TUYA_BLE_REPORT_MAX_DP_DATA_LEN - 17)) || (len == 0)) { + return TUYA_BLE_ERR_INVALID_LENGTH; + } + ret = data_2_klvlist(p_data, len, &list, 0); + if (MTP_OK != ret) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + free_klv_list(list); + ble_evt_buffer = (uint8_t *)tuya_ble_malloc(len); + if (ble_evt_buffer == NULL) { + return TUYA_BLE_ERR_NO_MEM; + } else { + memcpy(ble_evt_buffer, p_data, len); + } + + evt.hdr.event = TUYA_BLE_EVT_DP_DATA_WITH_FLAG_AND_TIME_STRING_REPORTED; + evt.flag_reported_with_time_string_data.sn = sn; + evt.flag_reported_with_time_string_data.mode = mode; + memcpy(evt.flag_reported_with_time_string_data.time_string, time_string, 13); + evt.flag_reported_with_time_string_data.p_data = ble_evt_buffer; + evt.flag_reported_with_time_string_data.data_len = len; + + if (tuya_ble_event_send(&evt) != 0) { + tuya_ble_free(ble_evt_buffer); + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; +} + +#endif + +/** + * @brief Function for data passthrough. + * + * @note The tuya sdk will forwards the data to the app. + *. + * */ +tuya_ble_status_t tuya_ble_data_passthrough(uint8_t *p_data, uint32_t len) +{ + tuya_ble_evt_param_t evt; + uint8_t *ble_evt_buffer; + + if (tuya_ble_connect_status_get() != BONDING_CONN) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + if (len > TUYA_BLE_SEND_MAX_DATA_LEN) { + return TUYA_BLE_ERR_INVALID_LENGTH; + } + + ble_evt_buffer = (uint8_t *)tuya_ble_malloc(len); + if (ble_evt_buffer == NULL) { + return TUYA_BLE_ERR_NO_MEM; + } + + memcpy(ble_evt_buffer, (uint8_t *)p_data, len); + evt.hdr.event = TUYA_BLE_EVT_DATA_PASSTHROUGH; + evt.passthrough_data.p_data = ble_evt_buffer; + evt.passthrough_data.data_len = len; + + if (tuya_ble_event_send(&evt) != 0) { + tuya_ble_free(ble_evt_buffer); + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; + +} + +/** + * @brief Function for response the production test instruction asynchronous. + * + * @param [in]channel: 0-uart ,1 - ble. + * [in]p_data : pointer to production test cmd data(Complete instruction,include0x66 0xaa and checksum.) + * [in]len : Number of bytes of pdata. + * @note + *. + * */ +tuya_ble_status_t tuya_ble_production_test_asynchronous_response(uint8_t channel, uint8_t *p_data, uint32_t len) +{ + tuya_ble_evt_param_t evt; + uint8_t *ble_evt_buffer; + + if (len > TUYA_BLE_SEND_MAX_DATA_LEN) { + return TUYA_BLE_ERR_INVALID_LENGTH; + } + + ble_evt_buffer = (uint8_t *)tuya_ble_malloc(len); + if (ble_evt_buffer == NULL) { + return TUYA_BLE_ERR_NO_MEM; + } + + memcpy(ble_evt_buffer, (uint8_t *)p_data, len); + evt.hdr.event = TUYA_BLE_EVT_PRODUCTION_TEST_RESPONSE; + evt.prod_test_res_data.p_data = ble_evt_buffer; + evt.prod_test_res_data.data_len = len; + evt.prod_test_res_data.channel = channel; + + if (tuya_ble_event_send(&evt) != 0) { + tuya_ble_free(ble_evt_buffer); + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; + +} + + +/** + * @brief Function for response for the net config req. + * + * @note + *. + * */ +tuya_ble_status_t tuya_ble_net_config_response(int16_t result_code) +{ + tuya_ble_evt_param_t evt; + tuya_ble_connect_status_t status = tuya_ble_connect_status_get(); + + if ((status != BONDING_CONN) && (status != UNBONDING_CONN)) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + evt.hdr.event = TUYA_BLE_EVT_NET_CONFIG_RESPONSE; + evt.net_config_response_data.result_code = result_code; + + if (tuya_ble_event_send(&evt) != 0) { + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; + +} + +#if (!TUYA_BLE_DEVICE_REGISTER_FROM_BLE) +/** + * @brief Function for response for ubound req. + * + * @note + *. + * */ +tuya_ble_status_t tuya_ble_ubound_response(uint8_t result_code) +{ + tuya_ble_evt_param_t evt; + tuya_ble_connect_status_t status = tuya_ble_connect_status_get(); + + if (status != BONDING_CONN) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + evt.hdr.event = TUYA_BLE_EVT_UNBOUND_RESPONSE; + evt.ubound_res_data.result_code = result_code; + + if (tuya_ble_event_send(&evt) != 0) { + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; + +} + + +/** + * @brief Function for response for anomaly ubound req. + * + * @note + *. + * */ +tuya_ble_status_t tuya_ble_anomaly_ubound_response(uint8_t result_code) +{ + tuya_ble_evt_param_t evt; + tuya_ble_connect_status_t status = tuya_ble_connect_status_get(); + + if (status != BONDING_CONN) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + evt.hdr.event = TUYA_BLE_EVT_ANOMALY_UNBOUND_RESPONSE; + evt.anomaly_ubound_res_data.result_code = result_code; + + if (tuya_ble_event_send(&evt) != 0) { + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; + +} + +/** + * @brief Function for response for device reset req. + * + * @note + *. + * */ +tuya_ble_status_t tuya_ble_device_reset_response(uint8_t result_code) +{ + tuya_ble_evt_param_t evt; + tuya_ble_connect_status_t status = tuya_ble_connect_status_get(); + + if (status != BONDING_CONN) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + evt.hdr.event = TUYA_BLE_EVT_DEVICE_RESET_RESPONSE; + evt.device_reset_res_data.result_code = result_code; + + if (tuya_ble_event_send(&evt) != 0) { + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; + +} + +#endif + + +/** + *@brief + *@param + * + *@note + * + * */ + +tuya_ble_status_t tuya_ble_device_unbind(void) +{ + tuya_ble_evt_param_t event; + + event.hdr.event = TUYA_BLE_EVT_DEVICE_UNBIND; + event.device_unbind_data.reserve = 0; + + if (tuya_ble_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_event_send device unbind error"); + return TUYA_BLE_ERR_INTERNAL; + } + + return TUYA_BLE_SUCCESS; +} + +/* + *@brief + *@param + * + *@note + * + * */ + +tuya_ble_status_t tuya_ble_device_factory_reset(void) +{ + tuya_ble_evt_param_t event; + + event.hdr.event = TUYA_BLE_EVT_FACTORY_RESET; + + if (tuya_ble_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_event_send factory reset error"); + return TUYA_BLE_ERR_INTERNAL; + } + + return TUYA_BLE_SUCCESS; +} + + +/* + *@brief + *@param time_type: + * 0 -13-bytes millisecond string[from cloud] + * 1 - normal time format[from cloud] + * 2 - normal time format[from app local] + *@note + * + * */ + +tuya_ble_status_t tuya_ble_time_req(uint8_t time_type) +{ + tuya_ble_evt_param_t event; + + if (time_type > 2) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + + event.hdr.event = TUYA_BLE_EVT_TIME_REQ; + event.time_req_data.time_type = time_type; + + if (tuya_ble_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_event_send time req error"); + return TUYA_BLE_ERR_INTERNAL; + } + + return TUYA_BLE_SUCCESS; +} + +/* + *@brief + *@param + * + *@note + * + * */ + +tuya_ble_status_t tuya_ble_ota_response(tuya_ble_ota_response_t *p_data) +{ + tuya_ble_evt_param_t evt; + uint8_t *ble_evt_buffer; + + if (tuya_ble_connect_status_get() != BONDING_CONN) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + if (p_data->data_len > TUYA_BLE_SEND_MAX_DATA_LEN) { + return TUYA_BLE_ERR_INVALID_LENGTH; + } + + ble_evt_buffer = (uint8_t *)tuya_ble_malloc(p_data->data_len); + if (ble_evt_buffer == NULL) { + return TUYA_BLE_ERR_NO_MEM; + } + + memcpy(ble_evt_buffer, (uint8_t *)p_data->p_data, p_data->data_len); + evt.hdr.event = TUYA_BLE_EVT_OTA_RESPONSE; + evt.ota_response_data.type = p_data->type; + evt.ota_response_data.p_data = ble_evt_buffer; + evt.ota_response_data.data_len = p_data->data_len; + + if (tuya_ble_event_send(&evt) != 0) { + tuya_ble_free(ble_evt_buffer); + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; +} + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN >= 3) +/* + *@brief + *@param [in]on_off: 0-off ,1 - on. + * + *@note + * + * */ +tuya_ble_status_t tuya_ble_adv_data_connecting_request_set(uint8_t on_off) +{ + tuya_ble_connect_status_t currnet_connect_status; + tuya_ble_evt_param_t evt; + + if (on_off > 1) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + currnet_connect_status = tuya_ble_connect_status_get(); + if ((currnet_connect_status != BONDING_UNCONN) && (currnet_connect_status != UNBONDING_UNCONN)) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + evt.hdr.event = TUYA_BLE_EVT_CONNECTING_REQUEST; + evt.connecting_request_data.cmd = on_off; + + if (tuya_ble_event_send(&evt) != 0) { + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; + +} + +#endif + +extern tuya_ble_parameters_settings_t tuya_ble_current_para; + +/* + *@brief + *@param + * + *@note + * + * */ +void tuya_ble_connected_handler(void) +{ + tuya_ble_evt_param_t event; + + event.hdr.event = TUYA_BLE_EVT_CONNECT_STATUS_UPDATE; + event.connect_change_evt = TUYA_BLE_CONNECTED; + + if (tuya_ble_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_event_send connect handler error"); + } +} + +/* + *@brief + *@param + * + *@note + * + * */ +void tuya_ble_disconnected_handler(void) +{ + tuya_ble_evt_param_t event; + + event.hdr.event = TUYA_BLE_EVT_CONNECT_STATUS_UPDATE; + event.connect_change_evt = TUYA_BLE_DISCONNECTED; + + if (tuya_ble_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_event_send disconnect handler error"); + } +} + +#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE + +/* + *@brief + *@param + * + *@note + * + * */ +void tuya_ble_link_encrypted_handler(void) +{ + tuya_ble_evt_param_t event; + + event.hdr.event = TUYA_BLE_EVT_LINK_STATUS_UPDATE; + event.link_update_data.link_app_status = 1; + + if (tuya_ble_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_event_send link encrypted handler error"); + } +} + +#endif + +/* + *@brief + *@param + * + *@note + * + * */ +tuya_ble_status_t tuya_ble_sdk_init(tuya_ble_device_param_t *param_data) +{ + tuya_ble_cb_evt_param_t event; + uint8_t device_id_temp[16]; + uint8_t device_id_temp2[20]; + tuya_ble_gap_addr_t bt_addr; + uint8_t mac_temp[6]; + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE == TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) && \ + (TUYA_BLE_INCLUDE_CJSON_COMPONENTS != 0) + cJSON_Hooks hooks; + hooks.malloc_fn = tuya_ble_malloc; + hooks.free_fn = tuya_ble_free; + cJSON_InitHooks(&hooks); +#endif + +#if (!TUYA_BLE_DEVICE_AUTH_DATA_STORE) + if ((param_data->use_ext_license_key != 1) || ((param_data->device_id_len != 16) && (param_data->device_id_len != 20))) { + TUYA_BLE_LOG_ERROR("tuya_ble_sdk_init param_data->device_id_len error."); + return TUYA_BLE_ERR_INVALID_PARAM; + } +#endif + + if (param_data->adv_local_name_len > TUYA_BLE_ADV_LOCAL_NAME_MAX_LEN) { + TUYA_BLE_LOG_ERROR("tuya_ble_sdk_init param_data->adv_local_name_len error."); + return TUYA_BLE_ERR_INVALID_PARAM; + } + + tuya_ble_storage_init(); + + if (param_data->product_id_len > 0) { // + tuya_ble_current_para.pid_type = param_data->p_type; + + tuya_ble_current_para.pid_len = param_data->product_id_len; + + if (tuya_ble_current_para.pid_len > TUYA_BLE_PRODUCT_ID_MAX_LEN) { + tuya_ble_current_para.pid_len = TUYA_BLE_PRODUCT_ID_MAX_LEN; + } + + memcpy(tuya_ble_current_para.pid, param_data->product_id, tuya_ble_current_para.pid_len); + } else { +#if ( TUYA_BLE_PROD_SUPPORT_OEM_TYPE == TUYA_BLE_PROD_OEM_TYPE_0_5 ) + tuya_ble_current_para.pid_type = tuya_ble_current_para.auth_settings.pid_type; + tuya_ble_current_para.pid_len = tuya_ble_current_para.auth_settings.pid_len; + memcpy(tuya_ble_current_para.pid, tuya_ble_current_para.auth_settings.factory_pid, tuya_ble_current_para.pid_len); +#endif + } + + if (param_data->adv_local_name_len > 0) { // + memcpy(tuya_ble_current_para.adv_local_name, param_data->adv_local_name, param_data->adv_local_name_len); + tuya_ble_current_para.adv_local_name_len = param_data->adv_local_name_len; + } else { + memcpy(tuya_ble_current_para.adv_local_name, "TY", 2); + tuya_ble_current_para.adv_local_name_len = 2; + } + +#if (!TUYA_BLE_DEVICE_AUTH_DATA_STORE) + if (param_data->device_id_len == 20) { + TUYA_BLE_LOG_HEXDUMP_DEBUG("device_id_20 ", param_data->device_id, 20); + tuya_ble_device_id_20_to_16(param_data->device_id, device_id_temp); + TUYA_BLE_LOG_HEXDUMP_DEBUG("device_id_16 ", device_id_temp, 16); + tuya_ble_device_id_16_to_20(device_id_temp, device_id_temp2); + TUYA_BLE_LOG_HEXDUMP_DEBUG("device_id_20 ", device_id_temp2, 20); + memcpy(tuya_ble_current_para.auth_settings.device_id, device_id_temp, DEVICE_ID_LEN); + } else { + memcpy(tuya_ble_current_para.auth_settings.device_id, param_data->device_id, DEVICE_ID_LEN); + } + + memcpy(tuya_ble_current_para.auth_settings.auth_key, param_data->auth_key, AUTH_KEY_LEN); + + memcpy(tuya_ble_current_para.sys_settings.device_virtual_id, param_data->device_vid, DEVICE_VIRTUAL_ID_LEN); + + /* copy mac & mac_string into tuya_ble_current_para.auth_settings */ + tuya_ble_str_to_hex(param_data->mac_addr_string, MAC_STRING_LEN, mac_temp); + TUYA_BLE_LOG_HEXDUMP_INFO("The MAC address passed in by the application", mac_temp, 6); + tuya_ble_inverted_array(mac_temp, 6); //Convert to little endian format + memcpy(param_data->mac_addr.addr, mac_temp, MAC_LEN); + memcpy(tuya_ble_current_para.auth_settings.mac, mac_temp, MAC_LEN); + tuya_ble_hextoascii(mac_temp, MAC_LEN, tuya_ble_current_para.auth_settings.mac_string); + + tuya_ble_current_para.sys_settings.bound_flag = param_data->bound_flag; + + if (tuya_ble_current_para.sys_settings.bound_flag) { + memcpy(tuya_ble_current_para.sys_settings.login_key, param_data->login_key, LOGIN_KEY_LEN); + +#if ((TUYA_BLE_PROTOCOL_VERSION_HIGN==4) && (TUYA_BLE_BEACON_KEY_ENABLE)) + + memcpy(tuya_ble_current_para.sys_settings.beacon_key, param_data->beacon_key, BEACON_KEY_LEN); + +#endif + } + +#else + + if ((param_data->use_ext_license_key == 1) && ((param_data->device_id_len == 16) || (param_data->device_id_len == 20))) { + if (param_data->device_id_len == 20) { + TUYA_BLE_LOG_HEXDUMP_DEBUG("device_id_20 ", param_data->device_id, 20); + tuya_ble_device_id_20_to_16(param_data->device_id, device_id_temp); + TUYA_BLE_LOG_HEXDUMP_DEBUG("device_id_16 ", device_id_temp, 16); + tuya_ble_device_id_16_to_20(device_id_temp, device_id_temp2); + TUYA_BLE_LOG_HEXDUMP_DEBUG("device_id_20 ", device_id_temp2, 20); + memcpy(tuya_ble_current_para.auth_settings.device_id, device_id_temp, DEVICE_ID_LEN); + } else { + memcpy(tuya_ble_current_para.auth_settings.device_id, param_data->device_id, DEVICE_ID_LEN); + } + + memcpy(tuya_ble_current_para.auth_settings.auth_key, param_data->auth_key, AUTH_KEY_LEN); + + /* copy mac & mac_string into tuya_ble_current_para.auth_settings */ + tuya_ble_str_to_hex(param_data->mac_addr_string, MAC_STRING_LEN, mac_temp); + TUYA_BLE_LOG_HEXDUMP_INFO("The MAC address passed in by the application", mac_temp, 6); + tuya_ble_inverted_array(mac_temp, 6); //Convert to little endian format + memcpy(param_data->mac_addr.addr, mac_temp, MAC_LEN); + memcpy(tuya_ble_current_para.auth_settings.mac, mac_temp, MAC_LEN); + tuya_ble_hextoascii(mac_temp, MAC_LEN, tuya_ble_current_para.auth_settings.mac_string); + } + +#endif + + if (tuya_ble_gap_addr_get(&bt_addr) == TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_HEXDUMP_INFO("current device MAC address : ", bt_addr.addr, 6); + + if (TUYA_BLE_DEVICE_MAC_UPDATE) { + if (param_data->device_id_len == 0) { + bt_addr.addr_type = TUYA_BLE_ADDRESS_TYPE_RANDOM; + memcpy(mac_temp, tuya_ble_current_para.auth_settings.mac, 6); + } else { + bt_addr.addr_type = param_data->mac_addr.addr_type; + memcpy(mac_temp, param_data->mac_addr.addr, 6); + } + + if ((!tuya_ble_buffer_value_is_all_x(mac_temp, 6, 0)) && (memcmp(mac_temp, bt_addr.addr, 6))) { + memcpy(bt_addr.addr, mac_temp, 6); + if (tuya_ble_gap_addr_set(&bt_addr) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("GAP ADDR SET failed!"); + } else { + TUYA_BLE_LOG_INFO("GAP ADDR SET SUCCESSED!"); + if (TUYA_BLE_DEVICE_MAC_UPDATE_RESET) { + tuya_ble_device_delay_ms(500); + tuya_ble_device_reset(); + } + } + } + } + } else { + TUYA_BLE_LOG_WARNING("GAP ADDR GET failed!"); + } + + tuya_ble_set_device_version(param_data->firmware_version, param_data->hardware_version); + + tuya_ble_set_external_mcu_version(0, 0); //Initialize to 0 + + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + tuya_ble_connect_status_set(BONDING_UNCONN); + } else { + tuya_ble_connect_status_set(UNBONDING_UNCONN); + } + + tuya_ble_adv_change(); + + tuya_ble_event_init(); + + tuya_ble_gatt_send_queue_init(); + + tuya_ble_common_uart_init(); + + tuya_ble_connect_monitor_timer_init(); + + TUYA_BLE_LOG_HEXDUMP_INFO("auth settings mac", tuya_ble_current_para.auth_settings.mac, MAC_LEN); + TUYA_BLE_LOG_HEXDUMP_INFO("product_id", tuya_ble_current_para.pid, tuya_ble_current_para.pid_len); + TUYA_BLE_LOG_HEXDUMP_DEBUG("device_uuid", tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN); + TUYA_BLE_LOG_HEXDUMP_DEBUG("device_authkey", tuya_ble_current_para.auth_settings.auth_key, AUTH_KEY_LEN); + TUYA_BLE_LOG_INFO("bond_flag = %d", tuya_ble_current_para.sys_settings.bound_flag); + + TUYA_BLE_LOG_INFO("tuya ble sdk version : "TUYA_BLE_SDK_VERSION_STR); + + return TUYA_BLE_SUCCESS; +} diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_bulk_data.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_bulk_data.c new file mode 100644 index 0000000..7af8a36 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_bulk_data.c @@ -0,0 +1,278 @@ +/** + * \file tuya_ble_bulkdata.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#include "tuya_ble_bulk_data.h" +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" +#include "tuya_ble_heap.h" +#include "tuya_ble_mem.h" +#include "tuya_ble_api.h" +#include "tuya_ble_port.h" +#include "tuya_ble_main.h" +#include "tuya_ble_internal_config.h" +#include "tuya_ble_data_handler.h" +#include "tuya_ble_mutli_tsf_protocol.h" +#include "tuya_ble_utils.h" +#include "tuya_ble_secure.h" +#include "tuya_ble_main.h" +#include "tuya_ble_storage.h" +#include "tuya_ble_unix_time.h" +#include "tuya_ble_log.h" +#include "tuya_ble_gatt_send_queue.h" + + +uint32_t tuya_ble_bulk_data_read_block_size_get(void) +{ + uint32_t mtu_length = 0; + uint32_t read_block_size = 0; + + if (tuya_ble_connect_status_get() != BONDING_CONN) { + read_block_size = 0; + } else { + mtu_length = tuya_ble_send_packet_data_length_get(); + if (mtu_length < 100) { + read_block_size = 256; + } else if ((mtu_length >= 100) && (mtu_length < 150)) { + read_block_size = 512; + } else { + read_block_size = TUYA_BLE_BULK_DATA_MAX_READ_BLOCK_SIZE; + } + } + + return read_block_size; +} + + +void tuya_ble_handle_bulk_data_req(uint16_t cmd, uint8_t *p_recv_data, uint32_t recv_data_len) +{ + uint16_t data_len; + tuya_ble_cb_evt_param_t event; + uint8_t err_code = 0; + + data_len = (p_recv_data[11] << 8) + p_recv_data[12]; + + if (data_len == 0) { + return; + } else if (p_recv_data[13] != 0) { /*Currently only supports version 0*/ + return; + } else { + + } + + event.evt = TUYA_BLE_CB_EVT_BULK_DATA; + + switch (cmd) { + case FRM_BULK_DATA_READ_INFO_REQ: + event.bulk_req_data.evt = TUYA_BLE_BULK_DATA_EVT_READ_INFO; + event.bulk_req_data.bulk_type = p_recv_data[14]; + break; + + case FRM_BULK_DATA_READ_DATA_REQ: + event.bulk_req_data.evt = TUYA_BLE_BULK_DATA_EVT_READ_BLOCK; + event.bulk_req_data.bulk_type = p_recv_data[14]; + event.bulk_req_data.params.block_data_req_data.block_number = (p_recv_data[15] << 8) + p_recv_data[16]; + break; + + case FRM_BULK_DATA_ERASE_DATA_REQ: + event.bulk_req_data.evt = TUYA_BLE_BULK_DATA_EVT_ERASE; + event.bulk_req_data.bulk_type = p_recv_data[14]; + break; + + default: + err_code = 1; + break; + } + + if (err_code == 0) { + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_bulk_data_req-tuya ble send cb event failed."); + } + } +} + + +tuya_ble_status_t tuya_ble_bulk_data_response(tuya_ble_bulk_data_response_t *p_data) +{ + tuya_ble_evt_param_t evt; + + if (tuya_ble_connect_status_get() != BONDING_CONN) { + return TUYA_BLE_ERR_INVALID_STATE; + } + + if ((p_data->evt == TUYA_BLE_BULK_DATA_EVT_SEND_DATA) && (p_data->params.send_res_data.current_block_length > (TUYA_BLE_SEND_MAX_DATA_LEN - 8))) { + return TUYA_BLE_ERR_INVALID_LENGTH; + } + + evt.hdr.event = TUYA_BLE_EVT_BULK_DATA_RESPONSE; + + memcpy(&evt.bulk_res_data, p_data, sizeof(tuya_ble_bulk_data_response_t)); + + if (p_data->evt == TUYA_BLE_BULK_DATA_EVT_SEND_DATA) { + evt.bulk_res_data.params.send_res_data.p_current_block_data = NULL; + evt.bulk_res_data.params.send_res_data.p_current_block_data = (uint8_t *)tuya_ble_malloc(p_data->params.send_res_data.current_block_length); + if (evt.bulk_res_data.params.send_res_data.p_current_block_data == NULL) { + return TUYA_BLE_ERR_NO_MEM; + } + memcpy(evt.bulk_res_data.params.send_res_data.p_current_block_data, p_data->params.send_res_data.p_current_block_data, p_data->params.send_res_data.current_block_length); + } + + if (tuya_ble_event_send(&evt) != 0) { + if (p_data->evt == TUYA_BLE_BULK_DATA_EVT_SEND_DATA) { + tuya_ble_free(evt.bulk_res_data.params.send_res_data.p_current_block_data); + } + + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; +} + + +void tuya_ble_handle_bulk_data_evt(tuya_ble_evt_param_t *evt) +{ + uint16_t bulk_data_cmd = 0; + uint8_t buffer[14]; + uint8_t *p_buf = NULL; + uint16_t data_length = 0; + uint8_t encry_mode = 0; + tuya_ble_cb_evt_param_t event; + uint8_t err_code = 0; + + + if (tuya_ble_pair_rand_valid_get() == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_4; + } + + buffer[0] = 0; + buffer[1] = evt->bulk_res_data.bulk_type; + + switch (evt->bulk_res_data.evt) { + case TUYA_BLE_BULK_DATA_EVT_READ_INFO: + + bulk_data_cmd = FRM_BULK_DATA_READ_INFO_RESP; + buffer[2] = evt->bulk_res_data.params.bulk_info_res_data.status; + buffer[3] = evt->bulk_res_data.params.bulk_info_res_data.flag; + buffer[4] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_length >> 24; + buffer[5] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_length >> 16; + buffer[6] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_length >> 8; + buffer[7] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_length; + buffer[8] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_crc >> 24; + buffer[9] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_crc >> 16; + buffer[10] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_crc >> 8; + buffer[11] = evt->bulk_res_data.params.bulk_info_res_data.bulk_data_crc; + buffer[12] = evt->bulk_res_data.params.bulk_info_res_data.block_data_length >> 8; + buffer[13] = evt->bulk_res_data.params.bulk_info_res_data.block_data_length; + data_length = 14; + break; + + case TUYA_BLE_BULK_DATA_EVT_READ_BLOCK: + + bulk_data_cmd = FRM_BULK_DATA_READ_DATA_RESP; + buffer[2] = evt->bulk_res_data.params.block_res_data.status; + buffer[3] = evt->bulk_res_data.params.block_res_data.block_number >> 8; + buffer[4] = evt->bulk_res_data.params.block_res_data.block_number; + buffer[5] = evt->bulk_res_data.params.block_res_data.block_data_length >> 8; + buffer[6] = evt->bulk_res_data.params.block_res_data.block_data_length; + buffer[7] = evt->bulk_res_data.params.block_res_data.max_packet_data_length >> 8; + buffer[8] = evt->bulk_res_data.params.block_res_data.max_packet_data_length; + buffer[9] = evt->bulk_res_data.params.block_res_data.block_data_crc16 >> 8; + buffer[10] = evt->bulk_res_data.params.block_res_data.block_data_crc16; + data_length = 11; + break; + + case TUYA_BLE_BULK_DATA_EVT_SEND_DATA : + + bulk_data_cmd = FRM_BULK_DATA_SEND_DATA; + p_buf = (uint8_t *)tuya_ble_malloc(evt->bulk_res_data.params.send_res_data.current_block_length + 8); + if (p_buf) { + p_buf[0] = 0; + p_buf[1] = evt->bulk_res_data.bulk_type; + p_buf[2] = evt->bulk_res_data.params.send_res_data.current_block_number >> 8; + p_buf[3] = evt->bulk_res_data.params.send_res_data.current_block_number; + p_buf[4] = 0; + p_buf[5] = 0; + p_buf[6] = evt->bulk_res_data.params.send_res_data.current_block_length >> 8; + p_buf[7] = evt->bulk_res_data.params.send_res_data.current_block_length; + memcpy(&p_buf[8], evt->bulk_res_data.params.send_res_data.p_current_block_data, evt->bulk_res_data.params.send_res_data.current_block_length); + data_length = evt->bulk_res_data.params.send_res_data.current_block_length + 8; + } + tuya_ble_free(evt->bulk_res_data.params.send_res_data.p_current_block_data); + break; + + case TUYA_BLE_BULK_DATA_EVT_ERASE : + + bulk_data_cmd = FRM_BULK_DATA_ERASE_DATA_RESP; + buffer[2] = evt->bulk_res_data.params.erase_res_data.status; + data_length = 3; + + break; + + default: + break; + } + + if (data_length > 0) { + if (evt->bulk_res_data.evt == TUYA_BLE_BULK_DATA_EVT_READ_BLOCK) { + err_code = tuya_ble_commData_send(bulk_data_cmd, 0, buffer, data_length, encry_mode); + + if (evt->bulk_res_data.params.block_res_data.status == 0) { + event.evt = TUYA_BLE_CB_EVT_BULK_DATA; + + event.bulk_req_data.evt = TUYA_BLE_BULK_DATA_EVT_SEND_DATA; + event.bulk_req_data.bulk_type = evt->bulk_res_data.bulk_type; + + event.bulk_req_data.params.send_data_req_data.block_number = evt->bulk_res_data.params.block_res_data.block_number; + + if (!err_code) { + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_bulk_data_evt-tuya ble send cb event failed."); + } + } else { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_bulk_data_evt-response read bulk data error."); + } + } + + } else if (evt->bulk_res_data.evt == TUYA_BLE_BULK_DATA_EVT_SEND_DATA) { + err_code = tuya_ble_commData_send(bulk_data_cmd, 0, p_buf, data_length, encry_mode); + tuya_ble_free(p_buf); + } else { + tuya_ble_commData_send(bulk_data_cmd, 0, buffer, data_length, encry_mode); + } + } + +} + + + + + + + + + + + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_data_handler.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_data_handler.c new file mode 100644 index 0000000..2dc5dd9 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_data_handler.c @@ -0,0 +1,2510 @@ +/** + * \file tuya_ble_data_handler.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" +#include "tuya_ble_heap.h" +#include "tuya_ble_mem.h" +#include "tuya_ble_api.h" +#include "tuya_ble_port.h" +#include "tuya_ble_main.h" +#include "tuya_ble_internal_config.h" +#include "tuya_ble_data_handler.h" +#include "tuya_ble_mutli_tsf_protocol.h" +#include "tuya_ble_utils.h" +#include "tuya_ble_secure.h" +#include "tuya_ble_main.h" +#include "tuya_ble_storage.h" +#include "tuya_ble_unix_time.h" +#include "tuya_ble_log.h" +#include "tuya_ble_gatt_send_queue.h" +#include "tuya_ble_bulk_data.h" +#include "tuya_ble_app_production_test.h" +#include "tuya_ble_app_uart_common_handler.h" +#if (TUYA_BLE_FEATURE_WEATHER_ENABLE != 0) +#include "tuya_ble_feature_weather.h" +#endif + + +static uint32_t tuya_ble_firmware_version = 0; +static uint32_t tuya_ble_hardware_version = 0; + +static uint32_t tuya_ble_mcu_firmware_version = 0; +static uint32_t tuya_ble_mcu_hardware_version = 0; + + +static tuya_ble_r_air_recv_packet air_recv_packet; + +static frm_trsmitr_proc_s ty_trsmitr_proc; +static frm_trsmitr_proc_s ty_trsmitr_proc_send; +static uint32_t send_packet_data_len = 20; + +uint8_t tuya_ble_pair_rand[6] = {0}; +uint8_t tuya_ble_pair_rand_valid = 0; + +static uint32_t tuya_ble_receive_sn = 0; +static uint32_t tuya_ble_send_sn = 1; + + +tuya_ble_ota_status_t tuya_ble_ota_status; + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN==4) + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE==TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) + +static uint8_t dev_cert_data[1024]; +static uint8_t current_ser_cert_pub_key[64]; +static uint8_t current_dev_random_for_sign[6]; +static tuya_ble_auth_status_t current_auth_status; + +void tuya_ble_auth_data_reset(void) +{ + tuya_ble_device_enter_critical(); + current_auth_status = TUYA_BLE_AUTH_STATUS_PHASE_NONE; + memset(current_ser_cert_pub_key, 0, sizeof(current_ser_cert_pub_key)); + memset(current_dev_random_for_sign, 0, sizeof(current_dev_random_for_sign)); + tuya_ble_device_exit_critical(); +} + +#endif + +#endif + +static uint32_t get_ble_send_sn(void) +{ + uint32_t sn; + tuya_ble_device_enter_critical(); + sn = tuya_ble_send_sn++; + tuya_ble_device_exit_critical(); + return sn; +} + +static void set_ble_receive_sn(uint32_t sn) +{ + tuya_ble_device_enter_critical(); + tuya_ble_receive_sn = sn; + tuya_ble_device_exit_critical(); +} + +void tuya_ble_reset_ble_sn(void) +{ + tuya_ble_device_enter_critical(); + tuya_ble_receive_sn = 0; + tuya_ble_send_sn = 1; + tuya_ble_device_exit_critical(); +} + + +void tuya_ble_set_device_version(uint32_t firmware_version, uint32_t hardware_version) +{ + tuya_ble_firmware_version = firmware_version; + tuya_ble_hardware_version = hardware_version; +} + + +void tuya_ble_set_external_mcu_version(uint32_t firmware_version, uint32_t hardware_version) +{ + tuya_ble_device_enter_critical(); + tuya_ble_mcu_firmware_version = firmware_version; + tuya_ble_mcu_hardware_version = hardware_version; + tuya_ble_device_exit_critical(); +} + + +void tuya_ble_ota_status_set(tuya_ble_ota_status_t status) +{ + tuya_ble_ota_status = status; +} + + +tuya_ble_ota_status_t tuya_ble_ota_status_get(void) +{ + return tuya_ble_ota_status; +} + + +void tuya_ble_pair_rand_clear(void) +{ + tuya_ble_device_enter_critical(); + memset(tuya_ble_pair_rand, 0, sizeof(tuya_ble_pair_rand)); + tuya_ble_pair_rand_valid = 0; + tuya_ble_device_exit_critical(); +} + + +uint8_t tuya_ble_pair_rand_valid_get(void) +{ + return tuya_ble_pair_rand_valid; +} + + +uint32_t tuya_ble_send_packet_data_length_get(void) +{ + return send_packet_data_len; +} + + +static bool buffer_value_is_all_x(uint8_t *buffer, uint16_t len, uint8_t value) +{ + bool ret = true; + for (uint16_t i = 0; i < len; i++) { + if (buffer[i] != value) { + ret = false; + break; + } + } + return ret; +} + +void tuya_ble_air_recv_packet_free(void) +{ + if (air_recv_packet.recv_data) { + tuya_ble_free(air_recv_packet.recv_data); + air_recv_packet.recv_data = NULL; + air_recv_packet.recv_len_max = 0; + air_recv_packet.recv_len = 0; + } +} + +static uint32_t ble_data_unpack(uint8_t *buf, uint32_t len) +{ + static uint32_t offset = 0; + mtp_ret ret; + + ret = trsmitr_recv_pkg_decode(&ty_trsmitr_proc, buf, len); + if (MTP_OK != ret && MTP_TRSMITR_CONTINUE != ret) { + air_recv_packet.recv_len_max = 0; + air_recv_packet.recv_len = 0; + if (air_recv_packet.recv_data) { + tuya_ble_free(air_recv_packet.recv_data); + air_recv_packet.recv_data = NULL; + } + + return 1; + } + + if (FRM_PKG_FIRST == ty_trsmitr_proc.pkg_desc) { + if (air_recv_packet.recv_data) { + tuya_ble_free(air_recv_packet.recv_data); + air_recv_packet.recv_data = NULL; + } + air_recv_packet.recv_len_max = get_trsmitr_frame_total_len(&ty_trsmitr_proc); + if ((air_recv_packet.recv_len_max > TUYA_BLE_AIR_FRAME_MAX) || (air_recv_packet.recv_len_max == 0)) { + air_recv_packet.recv_len_max = 0; + air_recv_packet.recv_len = 0; + TUYA_BLE_LOG_ERROR("ble_data_unpack total size [%d ]error.", air_recv_packet.recv_len_max); + return 2; + } + air_recv_packet.recv_len = 0; + air_recv_packet.recv_data = tuya_ble_malloc(air_recv_packet.recv_len_max); + if (air_recv_packet.recv_data == NULL) { + TUYA_BLE_LOG_ERROR("ble_data_unpack malloc failed."); + return 2; + } + memset(air_recv_packet.recv_data, 0, air_recv_packet.recv_len_max); + offset = 0; + } + if ((offset + get_trsmitr_subpkg_len(&ty_trsmitr_proc)) <= air_recv_packet.recv_len_max) { + if (air_recv_packet.recv_data) { + memcpy(air_recv_packet.recv_data + offset, get_trsmitr_subpkg(&ty_trsmitr_proc), get_trsmitr_subpkg_len(&ty_trsmitr_proc)); + offset += get_trsmitr_subpkg_len(&ty_trsmitr_proc); + air_recv_packet.recv_len = offset; + } else { + TUYA_BLE_LOG_ERROR("ble_data_unpack error."); + air_recv_packet.recv_len_max = 0; + air_recv_packet.recv_len = 0; + return 2; + } + } else { + ret = MTP_INVALID_PARAM; + TUYA_BLE_LOG_ERROR("ble_data_unpack[] error:MTP_INVALID_PARAM"); + tuya_ble_air_recv_packet_free(); + } + + if (ret == MTP_OK) { + offset = 0; + TUYA_BLE_LOG_DEBUG("ble_data_unpack[%d]", air_recv_packet.recv_len); + + return 0; + } else { + return 2; + } +} + +static uint8_t ble_cmd_data_crc_check(uint8_t *input, uint16_t len) +{ + uint16_t data_len = 0; + uint16_t crc16 = 0xFFFF; + uint16_t crc16_cal = 0; + + data_len = (input[10] << 8) | input[11]; + + if (data_len >= TUYA_BLE_RECEIVE_MAX_DATA_LEN) { + return 1; + } + + crc16_cal = tuya_ble_crc16_compute(input, 12 + data_len, &crc16); + + TUYA_BLE_LOG_DEBUG("crc16_cal[0x%04x]", crc16_cal); + crc16 = (input[12 + data_len] << 8) | input[13 + data_len]; + TUYA_BLE_LOG_DEBUG("crc16[0x%04x]", crc16); + if (crc16 == crc16_cal) { + return 0; + } else { + return 1; + } +} + + +void tuya_ble_commonData_rx_proc(uint8_t *buf, uint16_t len) +{ + uint8_t temp; + uint32_t current_sn = 0; + uint16_t current_cmd = 0; + tuya_ble_evt_param_t evt; + uint8_t *ble_evt_buffer = NULL; + uint8_t current_encry_mode = 0; + uint16_t p_version = 0; + bool is_cmd_with_encry_mode_correct = true; + + if (ble_data_unpack(buf, len)) { + return; // + } + + if (air_recv_packet.recv_len > TUYA_BLE_AIR_FRAME_MAX) { + TUYA_BLE_LOG_ERROR("air_recv_packet.recv_len bigger than TUYA_BLE_AIR_FRAME_MAX."); + tuya_ble_air_recv_packet_free(); + return; + } + + if (ty_trsmitr_proc.version < 2) { + TUYA_BLE_LOG_ERROR("ty_ble_rx_proc version not compatibility!"); + tuya_ble_air_recv_packet_free(); + return; + } + + + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + if ((ENCRYPTION_MODE_NONE == air_recv_packet.recv_data[0]) || (ENCRYPTION_MODE_FTM_KEY == air_recv_packet.recv_data[0])) { + TUYA_BLE_LOG_ERROR("ty_ble_rx_proc data encryption mode error since bound_flag = 1."); + tuya_ble_air_recv_packet_free(); + return; + } + } + + current_encry_mode = air_recv_packet.recv_data[0]; + + TUYA_BLE_LOG_HEXDUMP_DEBUG("received encry data", (uint8_t *)air_recv_packet.recv_data, air_recv_packet.recv_len); // + + air_recv_packet.de_encrypt_buf = NULL; + + air_recv_packet.de_encrypt_buf = (uint8_t *)tuya_ble_malloc(air_recv_packet.recv_len); + + if (air_recv_packet.de_encrypt_buf == NULL) { + TUYA_BLE_LOG_ERROR("air_recv_packet.de_encrypt_buf malloc failed."); + tuya_ble_air_recv_packet_free(); + return; + } else { + p_version = (TUYA_BLE_PROTOCOL_VERSION_HIGN << 8) + TUYA_BLE_PROTOCOL_VERSION_LOW; + air_recv_packet.decrypt_buf_len = 0; + temp = tuya_ble_decryption(p_version, (uint8_t *)air_recv_packet.recv_data, air_recv_packet.recv_len, &air_recv_packet.decrypt_buf_len, + (uint8_t *)air_recv_packet.de_encrypt_buf, &tuya_ble_current_para, tuya_ble_pair_rand); + tuya_ble_air_recv_packet_free(); + } + + + if (temp != 0) { + TUYA_BLE_LOG_ERROR("ble receive data decryption error code = %d", temp); + tuya_ble_free(air_recv_packet.de_encrypt_buf); + return; + } + + TUYA_BLE_LOG_HEXDUMP_DEBUG("decryped data", (uint8_t *)air_recv_packet.de_encrypt_buf, air_recv_packet.decrypt_buf_len); + + if (ble_cmd_data_crc_check((uint8_t *)air_recv_packet.de_encrypt_buf, air_recv_packet.decrypt_buf_len) != 0) { + TUYA_BLE_LOG_ERROR("ble receive data crc check error!"); + tuya_ble_free(air_recv_packet.de_encrypt_buf); + return; + } + +#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE + + if (current_cmd == FRM_QRY_DEV_INFO_REQ) { + tuya_ble_reset_ble_sn(); + } + +#endif + + current_sn = air_recv_packet.de_encrypt_buf[0] << 24; + current_sn += air_recv_packet.de_encrypt_buf[1] << 16; + current_sn += air_recv_packet.de_encrypt_buf[2] << 8; + current_sn += air_recv_packet.de_encrypt_buf[3]; + + if (current_sn <= tuya_ble_receive_sn) { + TUYA_BLE_LOG_ERROR("ble receive SN error!"); + tuya_ble_gap_disconnect(); + tuya_ble_free(air_recv_packet.de_encrypt_buf); + return; + } else { + set_ble_receive_sn(current_sn); + } + + current_cmd = ((air_recv_packet.de_encrypt_buf[8] << 8) | air_recv_packet.de_encrypt_buf[9]); + + if (current_cmd == FRM_FACTORY_TEST_CMD) { + // Check recvived cmd with encry mode corresponding relationship +#if (TUYA_BLE_PROD_TEST_SUPPORT_ENCRYPTION != 0) + if (current_encry_mode != ENCRYPTION_MODE_FTM_KEY) { + is_cmd_with_encry_mode_correct = false; + } +#else + if (current_encry_mode != ENCRYPTION_MODE_NONE) { + is_cmd_with_encry_mode_correct = false; + } +#endif + + if (!is_cmd_with_encry_mode_correct) { + tuya_ble_free(air_recv_packet.de_encrypt_buf); + TUYA_BLE_LOG_ERROR("ble receive cmd error on prod factory test state, need encrypt!"); + return; + } + } + + if ((BONDING_CONN != tuya_ble_connect_status_get()) && (FRM_QRY_DEV_INFO_REQ != current_cmd) && (PAIR_REQ != current_cmd) + && (FRM_LOGIN_KEY_REQ != current_cmd) && (FRM_FACTORY_TEST_CMD != current_cmd) && (FRM_NET_CONFIG_INFO_REQ != current_cmd) && (FRM_ANOMALY_UNBONDING_REQ != current_cmd) + && (FRM_AUTHENTICATE_PHASE_1_REQ != current_cmd) && (FRM_AUTHENTICATE_PHASE_2_REQ != current_cmd) && (FRM_AUTHENTICATE_PHASE_3_REQ != current_cmd)) { + tuya_ble_free(air_recv_packet.de_encrypt_buf); + TUYA_BLE_LOG_ERROR("ble receive cmd error on current bond state!"); + return; + } + + + if (tuya_ble_ota_status_get() != TUYA_BLE_OTA_STATUS_NONE) { + if (!((current_cmd >= FRM_OTA_START_REQ) && (current_cmd <= FRM_OTA_END_REQ))) { + tuya_ble_free(air_recv_packet.de_encrypt_buf); + TUYA_BLE_LOG_ERROR("ble receive cmd error on ota state!"); + return; + } + } + + ble_evt_buffer = (uint8_t *)tuya_ble_malloc(air_recv_packet.decrypt_buf_len + 1); + if (ble_evt_buffer == NULL) { + TUYA_BLE_LOG_ERROR("ty_ble_rx_proc no mem."); + tuya_ble_free(air_recv_packet.de_encrypt_buf); + return; + } else { + memset(ble_evt_buffer, 0, air_recv_packet.decrypt_buf_len + 1); + } + ble_evt_buffer[0] = current_encry_mode; + memcpy(ble_evt_buffer + 1, (uint8_t *)air_recv_packet.de_encrypt_buf, air_recv_packet.decrypt_buf_len); + evt.hdr.event = TUYA_BLE_EVT_BLE_CMD; + evt.ble_cmd_data.cmd = current_cmd; + evt.ble_cmd_data.p_data = ble_evt_buffer; + evt.ble_cmd_data.data_len = air_recv_packet.decrypt_buf_len + 1; + TUYA_BLE_LOG_DEBUG("BLE EVENT SEND-CMD:0x%02x - LEN:0x%02x", current_cmd, air_recv_packet.decrypt_buf_len + 1); + + if (tuya_ble_event_send(&evt) != 0) { + TUYA_BLE_LOG_ERROR("ble event send fail!"); + tuya_ble_free(ble_evt_buffer); + } + + tuya_ble_free(air_recv_packet.de_encrypt_buf); + +} + + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN==4) + +static void tuya_ble_handle_dev_info_req(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t p_buf[112]; + uint8_t payload_len = 0; + uint32_t ack_sn = 0; + uint8_t encry_mode = 0; + uint32_t version_temp_s, version_temp_h; + tuya_ble_gap_addr_t mac_addr; + uint16_t data_len = recv_data[11] << 8 | recv_data[12]; + + if (data_len != 2) { + TUYA_BLE_LOG_ERROR("get device infor cmd error with v4,data_len = %d", data_len); + tuya_ble_gap_disconnect(); + return; + } + + memset(p_buf, 0, sizeof(p_buf)); + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + TUYA_BLE_LOG_DEBUG("get device infor-%d", tuya_ble_current_para.sys_settings.bound_flag); + + send_packet_data_len = recv_data[13] << 8 | recv_data[14]; + + if ((send_packet_data_len == 0) || (send_packet_data_len > TUYA_BLE_DATA_MTU_MAX)) { + send_packet_data_len = 20; + } + + TUYA_BLE_LOG_DEBUG("current app mtu data len = %d", send_packet_data_len); + + tuya_ble_rand_generator(tuya_ble_pair_rand, 6); + tuya_ble_pair_rand_valid = 1; + + if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE) { + version_temp_s = tuya_ble_firmware_version; + version_temp_h = tuya_ble_hardware_version; + p_buf[4] = 0x00; + } else { + version_temp_s = tuya_ble_firmware_version >> 8; + version_temp_h = tuya_ble_hardware_version >> 8; + p_buf[4] = 0x05; + } + p_buf[0] = (version_temp_s >> 8) & 0xff; + p_buf[1] = (version_temp_s & 0xff); + p_buf[2] = TUYA_BLE_PROTOCOL_VERSION_HIGN; + p_buf[3] = TUYA_BLE_PROTOCOL_VERSION_LOW; + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE==TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) + + p_buf[4] |= 0x02; + if (TUYA_BLE_ADVANCED_ENCRYPTION_AUTH_ON_CONNECT) { + p_buf[4] |= 0x08; + } + +#endif + +#if (TUYA_BLE_PROTOCOL_VERSION_LOW>=1) + + if (TUYA_BLE_BEACON_KEY_ENABLE) { + p_buf[4] |= 0x10; + } + +#endif + + p_buf[5] = tuya_ble_current_para.sys_settings.bound_flag; + memcpy(&p_buf[6], tuya_ble_pair_rand, 6); + p_buf[12] = (version_temp_h >> 8) & 0xff; + p_buf[13] = (version_temp_h & 0xff); + + tuya_ble_register_key_generate(&p_buf[14], &tuya_ble_current_para); + + p_buf[46] = (tuya_ble_firmware_version >> 16) & 0xff; + p_buf[47] = (tuya_ble_firmware_version >> 8) & 0xff; + p_buf[48] = (tuya_ble_firmware_version & 0xff); + p_buf[49] = (tuya_ble_hardware_version >> 16) & 0xff; + p_buf[50] = (tuya_ble_hardware_version >> 8) & 0xff; + p_buf[51] = (tuya_ble_hardware_version & 0xff); + + p_buf[52] = TUYA_BLE_DEVICE_COMMUNICATION_ABILITY >> 8; + p_buf[53] = TUYA_BLE_DEVICE_COMMUNICATION_ABILITY; //communication ability + + p_buf[54] = 0x00; + + memcpy(&p_buf[55], tuya_ble_current_para.sys_settings.device_virtual_id, DEVICE_VIRTUAL_ID_LEN); + + p_buf[77] = (tuya_ble_mcu_firmware_version >> 16) & 0xff; + p_buf[78] = (tuya_ble_mcu_firmware_version >> 8) & 0xff; + p_buf[79] = (tuya_ble_mcu_firmware_version & 0xff); + p_buf[80] = (tuya_ble_mcu_hardware_version >> 16) & 0xff; + p_buf[81] = (tuya_ble_mcu_hardware_version >> 8) & 0xff; + p_buf[82] = (tuya_ble_mcu_hardware_version & 0xff); + + p_buf[83] = TUYA_BLE_WIFI_DEVICE_REGISTER_MODE; + +#if (TUYA_BLE_PROTOCOL_VERSION_LOW>=2) + + memset(&p_buf[84], 0, 4); + + tuya_ble_gap_addr_get(&mac_addr); + + p_buf[88] = mac_addr.addr_type; + + memcpy(&p_buf[89], mac_addr.addr, 6); + + p_buf[95] = strlen(TUYA_BLE_APP_FIRMWARE_KEY); + + if ((p_buf[95] == 8) || (p_buf[95] == 16)) { + memcpy(&p_buf[96], TUYA_BLE_APP_FIRMWARE_KEY, p_buf[95]); + } else { + p_buf[95] = 0; + } + + payload_len = 96 + p_buf[95]; + +#else + + p_buf[84] = strlen(TUYA_BLE_APP_FIRMWARE_KEY); + + if ((p_buf[84] == 8) || (p_buf[84] == 16)) { + memcpy(&p_buf[85], TUYA_BLE_APP_FIRMWARE_KEY, p_buf[84]); + } else { + p_buf[84] = 0; + } + + payload_len = 85 + p_buf[84]; + +#endif + + encry_mode = recv_data[0]; + + if (tuya_ble_commData_send(FRM_QRY_DEV_INFO_RESP, ack_sn, p_buf, payload_len, encry_mode) == 2) { + tuya_ble_pair_rand_clear(); + } +} + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE==TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) + +static void tuya_ble_handle_authenticate_phase1(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t p_buf[7]; + uint8_t encry_mode = 0; + uint32_t ack_sn = 0; + uint8_t sig_data[64]; + uint16_t data_len = 0; + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + data_len = (recv_data[11] << 8) + recv_data[12]; + + if (((tuya_ble_current_para.sys_settings.bound_flag == 0) && (recv_data[13] == 0)) || ((tuya_ble_current_para.sys_settings.bound_flag == 1) && (recv_data[13] == 1))) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_authenticate_phase1 -> invalid state."); + tuya_ble_gap_disconnect(); + return; + } + + if ((data_len != 1 && data_len != 130) || (current_auth_status != TUYA_BLE_AUTH_STATUS_PHASE_NONE)) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_authenticate_phase1 -> invalid state or data length."); + tuya_ble_gap_disconnect(); + return; + } + + p_buf[0] = 0; + + tuya_ble_auth_data_reset(); + + if (recv_data[13] == 1) { + if (data_len == 130) { + memcpy(current_ser_cert_pub_key, recv_data + 15, 64); + memcpy(sig_data, recv_data + 79, 64); + TUYA_BLE_LOG_HEXDUMP_DEBUG("received server public key:", current_ser_cert_pub_key, sizeof(current_ser_cert_pub_key)); + TUYA_BLE_LOG_HEXDUMP_DEBUG("received server public key signature data:", sig_data, sizeof(sig_data)); + if (!tuya_ble_server_cert_data_verify(recv_data + 14, 65, sig_data)) { + p_buf[0] = 1; + TUYA_BLE_LOG_ERROR("server public key signature data verify failed."); + } else { + TUYA_BLE_LOG_DEBUG("server public key signature data verify succeed."); + } + } else { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_authenticate_phase1 -> invalid state."); + tuya_ble_gap_disconnect(); + return; + } + } else { + memcpy(current_ser_cert_pub_key, tuya_ble_current_para.sys_settings.server_cert_pub_key, 64); + TUYA_BLE_LOG_HEXDUMP_DEBUG("get server public key from tuya ble current para:", current_ser_cert_pub_key, sizeof(current_ser_cert_pub_key)); + } + + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_2; + } + + if (p_buf[0] == 0) { + tuya_ble_rand_generator(current_dev_random_for_sign, 6); + TUYA_BLE_LOG_HEXDUMP_DEBUG("device generate random:", current_dev_random_for_sign, sizeof(current_dev_random_for_sign)); + memcpy(p_buf + 1, current_dev_random_for_sign, 6); + current_auth_status = TUYA_BLE_AUTH_STATUS_PHASE_1; + tuya_ble_commData_send(FRM_AUTHENTICATE_PHASE_1_RESP, ack_sn, p_buf, 7, encry_mode); + } else { + tuya_ble_commData_send(FRM_AUTHENTICATE_PHASE_1_RESP, ack_sn, p_buf, 1, encry_mode); + TUYA_BLE_LOG_ERROR("tuya_ble_handle_authenticate_phase1 -> auth failed."); + tuya_ble_gap_disconnect(); + } + + +} + + +static void tuya_ble_handle_authenticate_phase2(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t encry_mode = 0; + uint32_t ack_sn = 0; + uint8_t sig_data[64] = {0}; + uint16_t data_len = 0; + uint32_t dev_cert_data_len = 0; + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + data_len = (recv_data[11] << 8) + recv_data[12]; + + if ((data_len != 65) || (current_auth_status != TUYA_BLE_AUTH_STATUS_PHASE_1)) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_authenticate_phase2 -> invalid state or data length."); + tuya_ble_gap_disconnect(); + return; + } + memset(dev_cert_data, 0, sizeof(dev_cert_data)); + + dev_cert_data[0] = 0; + + if (recv_data[13] == 0) { + memcpy(sig_data, recv_data + 14, 64); + TUYA_BLE_LOG_HEXDUMP_DEBUG("received signature data for device random:", sig_data, sizeof(sig_data)); + } else { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_authenticate_phase2 -> invalid data type."); + tuya_ble_gap_disconnect(); + return; + } + + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_2; + } + TUYA_BLE_LOG_HEXDUMP_DEBUG("current device random:", current_dev_random_for_sign, sizeof(current_dev_random_for_sign)); + TUYA_BLE_LOG_HEXDUMP_DEBUG("verify signature data of device random use server public key:", current_ser_cert_pub_key, sizeof(current_ser_cert_pub_key)); + if (!tuya_ble_sig_data_verify(current_ser_cert_pub_key, current_dev_random_for_sign, 6, sig_data)) { + dev_cert_data[0] = 1; + tuya_ble_commData_send(FRM_AUTHENTICATE_PHASE_2_RESP, ack_sn, dev_cert_data, 1, encry_mode); + TUYA_BLE_LOG_ERROR("tuya_ble_handle_authenticate_phase2 -> device random signature data verify failed."); + tuya_ble_gap_disconnect(); + return; + + } else { + TUYA_BLE_LOG_DEBUG("tuya_ble_handle_authenticate_phase2 -> device random signature data verify succeed."); + } + + if (tuya_ble_current_para.sys_settings.bound_flag == 0) { + dev_cert_data_len = tuya_ble_get_dev_crt_len(); + + if (dev_cert_data_len == 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_authenticate_phase2 -> get dev cert length error."); + tuya_ble_gap_disconnect(); + return; + } else { + TUYA_BLE_LOG_DEBUG("tuya_ble_handle_authenticate_phase2 -> get dev cert length = %d .", dev_cert_data_len); + dev_cert_data[0] = 0; + dev_cert_data[1] = 0; + if (tuya_ble_get_dev_crt_der(dev_cert_data + 2, dev_cert_data_len) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_authenticate_phase2 -> get dev cert data error."); + tuya_ble_gap_disconnect(); + return; + } + TUYA_BLE_LOG_HEXDUMP_DEBUG("get device cert :", dev_cert_data + 2, dev_cert_data_len); + tuya_ble_commData_send(FRM_AUTHENTICATE_PHASE_2_RESP, ack_sn, dev_cert_data, dev_cert_data_len + 2, encry_mode); + } + } else { + dev_cert_data[0] = 0; + tuya_ble_commData_send(FRM_AUTHENTICATE_PHASE_2_RESP, ack_sn, dev_cert_data, 1, encry_mode); + TUYA_BLE_LOG_DEBUG("tuya_ble_handle_authenticate_phase2 -> no need send dev cert because in bound state."); + } + + current_auth_status = TUYA_BLE_AUTH_STATUS_PHASE_2; + +} + + +static void tuya_ble_handle_authenticate_phase3(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t encry_mode = 0; + uint32_t ack_sn = 0; + uint8_t p_buf[65] = {0}; + uint16_t data_len = 0; + uint8_t random[6] = {0}; + uint8_t random_hash[32] = {0}; + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + data_len = (recv_data[11] << 8) + recv_data[12]; + + if ((data_len != 7 && data_len != 1) || (current_auth_status != TUYA_BLE_AUTH_STATUS_PHASE_2)) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_authenticate_phase3 -> invalid state or data length."); + tuya_ble_gap_disconnect(); + return; + } + + if (recv_data[13] != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_authenticate_phase3 -> dev cert verify failed."); + tuya_ble_gap_disconnect(); + return; + } else { + TUYA_BLE_LOG_HEXDUMP_DEBUG("received server random for signature :", random, 6); + memcpy(random, &recv_data[14], 6); + } + + if (tuya_ble_ecc_sign_secp256r1(NULL, random, 6, p_buf + 1) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_authenticate_phase3 -> server random sign failed."); + tuya_ble_gap_disconnect(); + return; + } else { + TUYA_BLE_LOG_HEXDUMP_DEBUG("tuya_ble_handle_authenticate_phase3 -> server random sign succeed.", p_buf + 1, 64); + } + + p_buf[0] = 0; + + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_2; + } + + tuya_ble_commData_send(FRM_AUTHENTICATE_PHASE_3_RESP, ack_sn, p_buf, 65, encry_mode); + + current_auth_status = TUYA_BLE_AUTH_STATUS_PHASE_3; + +} + +#endif + +extern void tuya_ble_connect_monitor_timer_stop(void); +static void tuya_ble_handle_pair_req(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t p_buf[1]; + uint8_t encry_mode = 0; + uint32_t ack_sn = 0; + uint16_t data_len = 0; + tuya_ble_cb_evt_param_t event; + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + data_len = (recv_data[11] << 8) + recv_data[12]; + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE==TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) + +#if (TUYA_BLE_ADVANCED_ENCRYPTION_AUTH_ON_CONNECT) + + if (current_auth_status != TUYA_BLE_AUTH_STATUS_PHASE_3) { + TUYA_BLE_LOG_ERROR("PAIR_REQ failed ,because current_auth_status error!"); //ID not match ,and disconnected. + tuya_ble_gap_disconnect(); + return; + } + +#else + + if (tuya_ble_current_para.sys_settings.bound_flag == 0) { + if (current_auth_status != TUYA_BLE_AUTH_STATUS_PHASE_3) { + TUYA_BLE_LOG_ERROR("PAIR_REQ failed ,because current_auth_status error!"); //ID not match ,and disconnected. + tuya_ble_gap_disconnect(); + return; + } + } + +#endif + +#endif + + + if (0 == memcmp(&recv_data[13], tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN)) { + tuya_ble_connect_monitor_timer_stop(); + + if (1 == tuya_ble_get_adv_connect_request_bit_status()) { + TUYA_BLE_LOG_INFO("ble adv data update,because the last broadcast data connection request flag was set!"); + tuya_ble_adv_change(); + } + + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + TUYA_BLE_LOG_INFO("PAIR_REQ already bound!"); + p_buf[0] = 2; + tuya_ble_connect_status_set(BONDING_CONN); + } else { +#if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + +#if (TUYA_BLE_PROTOCOL_VERSION_LOW>=1) + + if (TUYA_BLE_BEACON_KEY_ENABLE) { + if (data_len < 61) { + p_buf[0] = 1; + goto pair_exit; + } else { + if (recv_data[57] != BEACON_KEY_LEN) { + p_buf[0] = 1; + goto pair_exit; + } else { + memcpy(tuya_ble_current_para.sys_settings.beacon_key, recv_data + 58, BEACON_KEY_LEN); + } + } + + } + +#endif + + memcpy(tuya_ble_current_para.sys_settings.login_key, recv_data + 29, LOGIN_KEY_LEN); + memcpy(tuya_ble_current_para.sys_settings.device_virtual_id, recv_data + 29 + LOGIN_KEY_LEN, DEVICE_VIRTUAL_ID_LEN); + tuya_ble_current_para.sys_settings.bound_flag = 1; + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE==TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) + + if (!tuya_ble_buffer_value_is_all_x(current_ser_cert_pub_key, 64, 0)) { + memcpy(tuya_ble_current_para.sys_settings.server_cert_pub_key, current_ser_cert_pub_key, 64); + } else { + p_buf[0] = 1; + tuya_ble_current_para.sys_settings.bound_flag = 0; + goto pair_exit; + } + +#endif + + tuya_ble_storage_save_sys_settings(); + + tuya_ble_connect_status_set(BONDING_CONN); + + tuya_ble_adv_change(); + TUYA_BLE_LOG_INFO("PAIR_REQ ok-%d", tuya_ble_current_para.sys_settings.bound_flag); + + event.evt = TUYA_BLE_CB_EVT_UPDATE_LOGIN_KEY_VID; + event.device_login_key_vid_data.login_key_len = LOGIN_KEY_LEN; + event.device_login_key_vid_data.vid_len = DEVICE_VIRTUAL_ID_LEN; + +#if (TUYA_BLE_PROTOCOL_VERSION_LOW>=1) + if (TUYA_BLE_BEACON_KEY_ENABLE) { + event.device_login_key_vid_data.beacon_key_len = BEACON_KEY_LEN; + memcpy(event.device_login_key_vid_data.beacon_key, tuya_ble_current_para.sys_settings.beacon_key, BEACON_KEY_LEN); + } +#endif + + memcpy(event.device_login_key_vid_data.login_key, tuya_ble_current_para.sys_settings.login_key, LOGIN_KEY_LEN); + memcpy(event.device_login_key_vid_data.vid, tuya_ble_current_para.sys_settings.device_virtual_id, DEVICE_VIRTUAL_ID_LEN); + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya ble send cb event failed."); + } else { + TUYA_BLE_LOG_DEBUG("tuya ble send cb event succeed."); + } + + +#else + tuya_ble_connect_status_set(UNBONDING_CONN); +#endif + p_buf[0] = 0x00; + } + + event.evt = TUYA_BLE_CB_EVT_CONNECTE_STATUS; + event.connect_status = tuya_ble_connect_status_get(); + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya ble send cb event failed."); + } else { + TUYA_BLE_LOG_INFO("tuya ble send cb event succeed."); + } + + + } else { + TUYA_BLE_LOG_ERROR("PAIR_REQ device id not match!"); //ID not match ,and disconnected. + p_buf[0] = 0x01; + + } + + +pair_exit: + if (p_buf[0] == 0) { +#if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + encry_mode = ENCRYPTION_MODE_SESSION_KEY; +#else + encry_mode = recv_data[0]; +#endif + } else if (p_buf[0] == 1) { + encry_mode = recv_data[0]; + } else if (p_buf[0] == 2) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + + } + + tuya_ble_commData_send(PAIR_RESP, ack_sn, p_buf, 1, encry_mode); + + if (encry_mode == ENCRYPTION_MODE_SESSION_KEY) { + if (TUYA_BLE_AUTO_REQUEST_TIME_CONFIGURE == 1) { + tuya_ble_commData_send(FRM_GET_UNIX_TIME_CHAR_MS_REQ, 0, NULL, 0, encry_mode); + TUYA_BLE_LOG_INFO("send FRM_GET_UNIX_TIME_CHAR_MS_REQ cmd to app.\n"); + } else if (TUYA_BLE_AUTO_REQUEST_TIME_CONFIGURE == 2) { + tuya_ble_commData_send(FRM_GET_APP_LOCAL_TIME_REQ, 0, NULL, 0, encry_mode); + TUYA_BLE_LOG_INFO("send FRM_GET_APP_LOCAL_TIME_REQ cmd to app.\n"); + } else { + + } + } + + if (p_buf[0] == 1) { + tuya_ble_gap_disconnect(); + } + +} + + + +#endif //TUYA_BLE_PROTOCOL_VERSION_HIGN==4 + + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN==3) + +#if (TUYA_BLE_PROTOCOL_VERSION_LOW>=2) + +static void tuya_ble_handle_dev_info_req(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t p_buf[90]; + uint8_t payload_len = 0; + uint32_t ack_sn = 0; + uint8_t encry_mode = 0; + uint32_t version_temp_s, version_temp_h; + + memset(p_buf, 0, sizeof(p_buf)); + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + TUYA_BLE_LOG_DEBUG("get device infor-%d", tuya_ble_current_para.sys_settings.bound_flag); + + send_packet_data_len = 20; + + tuya_ble_rand_generator(tuya_ble_pair_rand, 6); + tuya_ble_pair_rand_valid = 1; + + if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE) { + version_temp_s = tuya_ble_firmware_version; + version_temp_h = tuya_ble_hardware_version; + p_buf[4] = 0x00; + } else { + version_temp_s = tuya_ble_firmware_version >> 8; + version_temp_h = tuya_ble_hardware_version >> 8; + p_buf[4] = 0x05; + } + p_buf[0] = (version_temp_s >> 8) & 0xff; + p_buf[1] = (version_temp_s & 0xff); + p_buf[2] = TUYA_BLE_PROTOCOL_VERSION_HIGN; + p_buf[3] = TUYA_BLE_PROTOCOL_VERSION_LOW; + if (TUYA_BLE_ADVANCED_ENCRYPTION_DEVICE == 1) { + p_buf[4] |= 0x02; + } + + p_buf[5] = tuya_ble_current_para.sys_settings.bound_flag; + memcpy(&p_buf[6], tuya_ble_pair_rand, 6); + p_buf[12] = (version_temp_h >> 8) & 0xff; + p_buf[13] = (version_temp_h & 0xff); + + tuya_ble_register_key_generate(&p_buf[14], &tuya_ble_current_para); + + p_buf[46] = (tuya_ble_firmware_version >> 16) & 0xff; + p_buf[47] = (tuya_ble_firmware_version >> 8) & 0xff; + p_buf[48] = (tuya_ble_firmware_version & 0xff); + p_buf[49] = (tuya_ble_hardware_version >> 16) & 0xff; + p_buf[50] = (tuya_ble_hardware_version >> 8) & 0xff; + p_buf[51] = (tuya_ble_hardware_version & 0xff); + + p_buf[52] = TUYA_BLE_DEVICE_COMMUNICATION_ABILITY >> 8; + p_buf[53] = TUYA_BLE_DEVICE_COMMUNICATION_ABILITY; //communication ability + + p_buf[54] = 0x00; + + memcpy(&p_buf[55], tuya_ble_current_para.sys_settings.device_virtual_id, DEVICE_VIRTUAL_ID_LEN); + + p_buf[77] = (tuya_ble_mcu_firmware_version >> 16) & 0xff; + p_buf[78] = (tuya_ble_mcu_firmware_version >> 8) & 0xff; + p_buf[79] = (tuya_ble_mcu_firmware_version & 0xff); + p_buf[80] = (tuya_ble_mcu_hardware_version >> 16) & 0xff; + p_buf[81] = (tuya_ble_mcu_hardware_version >> 8) & 0xff; + p_buf[82] = (tuya_ble_mcu_hardware_version & 0xff); + + p_buf[83] = TUYA_BLE_WIFI_DEVICE_REGISTER_MODE; + + payload_len = 84; + + encry_mode = recv_data[0]; + + if (tuya_ble_commData_send(FRM_QRY_DEV_INFO_RESP, ack_sn, p_buf, payload_len, encry_mode) == 2) { + tuya_ble_pair_rand_clear(); + } +} + +#else //version <= 3.1 TUYA_BLE_PROTOCOL_VERSION_LOW<2 + +static void tuya_ble_handle_dev_info_req(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t p_buf[90]; + uint8_t payload_len = 0; + uint32_t ack_sn = 0; + uint8_t encry_mode = 0; + uint32_t version_temp_s, version_temp_h; + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + TUYA_BLE_LOG_DEBUG("get device infor-%d", tuya_ble_current_para.sys_settings.bound_flag); + + send_packet_data_len = 20; + + tuya_ble_rand_generator(tuya_ble_pair_rand, 6); + tuya_ble_pair_rand_valid = 1; + + if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE) { + version_temp_s = tuya_ble_firmware_version; + version_temp_h = tuya_ble_hardware_version; + p_buf[4] = 0x00; + } else { + version_temp_s = tuya_ble_firmware_version >> 8; + version_temp_h = tuya_ble_hardware_version >> 8; + p_buf[4] = 0x05; + } + p_buf[0] = (version_temp_s >> 8) & 0xff; + p_buf[1] = (version_temp_s & 0xff); + p_buf[2] = TUYA_BLE_PROTOCOL_VERSION_HIGN; + p_buf[3] = TUYA_BLE_PROTOCOL_VERSION_LOW; + if (TUYA_BLE_ADVANCED_ENCRYPTION_DEVICE == 1) { + p_buf[4] |= 0x02; + } + + p_buf[5] = tuya_ble_current_para.sys_settings.bound_flag; + memcpy(&p_buf[6], tuya_ble_pair_rand, 6); + p_buf[12] = (version_temp_h >> 8) & 0xff; + p_buf[13] = (version_temp_h & 0xff); + memcpy(&p_buf[14], tuya_ble_current_para.auth_settings.auth_key, AUTH_KEY_LEN); + + p_buf[46] = (tuya_ble_firmware_version >> 16) & 0xff; + p_buf[47] = (tuya_ble_firmware_version >> 8) & 0xff; + p_buf[48] = (tuya_ble_firmware_version & 0xff); + p_buf[49] = (tuya_ble_hardware_version >> 16) & 0xff; + p_buf[50] = (tuya_ble_hardware_version >> 8) & 0xff; + p_buf[51] = (tuya_ble_hardware_version & 0xff); + + p_buf[52] = TUYA_BLE_DEVICE_COMMUNICATION_ABILITY >> 8; + p_buf[53] = TUYA_BLE_DEVICE_COMMUNICATION_ABILITY; //communication ability + + p_buf[54] = 0x00; + + memcpy(&p_buf[55], tuya_ble_current_para.sys_settings.device_virtual_id, DEVICE_VIRTUAL_ID_LEN); + + p_buf[77] = (tuya_ble_mcu_firmware_version >> 16) & 0xff; + p_buf[78] = (tuya_ble_mcu_firmware_version >> 8) & 0xff; + p_buf[79] = (tuya_ble_mcu_firmware_version & 0xff); + p_buf[80] = (tuya_ble_mcu_hardware_version >> 16) & 0xff; + p_buf[81] = (tuya_ble_mcu_hardware_version >> 8) & 0xff; + p_buf[82] = (tuya_ble_mcu_hardware_version & 0xff); + + payload_len = 83; + + encry_mode = recv_data[0]; + + if (tuya_ble_commData_send(FRM_QRY_DEV_INFO_RESP, ack_sn, p_buf, payload_len, encry_mode) == 2) { + tuya_ble_pair_rand_clear(); + } +} + +#endif + +extern void tuya_ble_connect_monitor_timer_stop(void); +static void tuya_ble_handle_pair_req(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t p_buf[1]; + uint8_t encry_mode = 0; + uint32_t ack_sn = 0; + tuya_ble_cb_evt_param_t event; + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + if (0 == memcmp(&recv_data[13], tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN)) { + tuya_ble_connect_monitor_timer_stop(); + + if (1 == tuya_ble_get_adv_connect_request_bit_status()) { + TUYA_BLE_LOG_INFO("ble adv data update,because the last broadcast data connection request flag was set!"); + tuya_ble_adv_change(); + } + + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + TUYA_BLE_LOG_INFO("PAIR_REQ already bound!"); + p_buf[0] = 2; + tuya_ble_connect_status_set(BONDING_CONN); + } else { +#if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + memcpy(tuya_ble_current_para.sys_settings.login_key, recv_data + 29, LOGIN_KEY_LEN); + memcpy(tuya_ble_current_para.sys_settings.device_virtual_id, recv_data + 29 + LOGIN_KEY_LEN, DEVICE_VIRTUAL_ID_LEN); + tuya_ble_current_para.sys_settings.bound_flag = 1; + + tuya_ble_storage_save_sys_settings(); + + tuya_ble_connect_status_set(BONDING_CONN); + + tuya_ble_adv_change(); + TUYA_BLE_LOG_INFO("PAIR_REQ ok-%d", tuya_ble_current_para.sys_settings.bound_flag); + + event.evt = TUYA_BLE_CB_EVT_UPDATE_LOGIN_KEY_VID; + event.device_login_key_vid_data.login_key_len = LOGIN_KEY_LEN; + event.device_login_key_vid_data.vid_len = DEVICE_VIRTUAL_ID_LEN; + memcpy(event.device_login_key_vid_data.login_key, tuya_ble_current_para.sys_settings.login_key, LOGIN_KEY_LEN); + memcpy(event.device_login_key_vid_data.vid, tuya_ble_current_para.sys_settings.device_virtual_id, DEVICE_VIRTUAL_ID_LEN); + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya ble send cb event failed."); + } else { + TUYA_BLE_LOG_DEBUG("tuya ble send cb event succeed."); + } + + +#else //TUYA_BLE_DEVICE_REGISTER_FROM_BLE + tuya_ble_connect_status_set(UNBONDING_CONN); +#endif + p_buf[0] = 0x00; + } + + + event.evt = TUYA_BLE_CB_EVT_CONNECTE_STATUS; + event.connect_status = tuya_ble_connect_status_get(); + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya ble send cb event failed."); + } else { + TUYA_BLE_LOG_INFO("tuya ble send cb event succeed."); + } + + + } else { + TUYA_BLE_LOG_ERROR("PAIR_REQ device id not match!"); //ID not match ,and disconnected. + p_buf[0] = 0x01; + + } + + + if (p_buf[0] == 0) { +#if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + encry_mode = ENCRYPTION_MODE_SESSION_KEY; +#else + encry_mode = recv_data[0]; +#endif + } else if (p_buf[0] == 1) { + encry_mode = recv_data[0]; + } else if (p_buf[0] == 2) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + + } + + tuya_ble_commData_send(PAIR_RESP, ack_sn, p_buf, 1, encry_mode); + + if (encry_mode == ENCRYPTION_MODE_SESSION_KEY) { + tuya_ble_commData_send(FRM_GET_UNIX_TIME_CHAR_MS_REQ, 0, NULL, 0, encry_mode); + TUYA_BLE_LOG_INFO("send FRM_GET_UNIX_TIME_CHAR_MS_REQ cmd to app.\n"); + } + + if (p_buf[0] == 1) { + tuya_ble_gap_disconnect(); + } + +} + +#endif + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN==2) + +static void tuya_ble_handle_dev_info_req(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t p_buf[70]; + uint8_t payload_len = 0; + uint32_t ack_sn = 0; + uint8_t encry_mode = 0; + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + TUYA_BLE_LOG_INFO("get device infor-%d", tuya_ble_current_para.sys_settings.bound_flag); + + send_packet_data_len = 20; + + tuya_ble_rand_generator(tuya_ble_pair_rand, 6); + tuya_ble_pair_rand_valid = 1; + + + p_buf[0] = (tuya_ble_firmware_version >> 8) & 0xff; + p_buf[1] = (tuya_ble_firmware_version & 0xff); + p_buf[2] = TUYA_BLE_PROTOCOL_VERSION_HIGN; + p_buf[3] = TUYA_BLE_PROTOCOL_VERSION_LOW; + if (TUYA_BLE_ADVANCED_ENCRYPTION_DEVICE == 1) { + p_buf[4] = 0x02; + } else { + p_buf[4] = 0x00; + } + p_buf[5] = tuya_ble_current_para.sys_settings.bound_flag; + memcpy(&p_buf[6], tuya_ble_pair_rand, 6); + p_buf[12] = (tuya_ble_hardware_version >> 8) & 0xff; + p_buf[13] = (tuya_ble_hardware_version & 0xff); + memcpy(&p_buf[14], tuya_ble_current_para.auth_settings.auth_key, AUTH_KEY_LEN); + + payload_len = 46; + + encry_mode = recv_data[0]; + + if (tuya_ble_commData_send(FRM_QRY_DEV_INFO_RESP, ack_sn, p_buf, payload_len, encry_mode) == 2) { + tuya_ble_pair_rand_clear(); + } + +} + +extern void tuya_ble_connect_monitor_timer_stop(void); +static void tuya_ble_handle_pair_req(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t p_buf[1]; + uint8_t encry_mode = 0; + uint32_t ack_sn = 0; + tuya_ble_cb_evt_param_t event; + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + if (0 == memcmp(&recv_data[13], tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN)) { + tuya_ble_connect_monitor_timer_stop(); + + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + TUYA_BLE_LOG_ERROR("PAIR_REQ already bound!"); + p_buf[0] = 2; + } else { + +#if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + + memcpy(tuya_ble_current_para.sys_settings.login_key, recv_data + 29, LOGIN_KEY_LEN); + tuya_ble_current_para.sys_settings.bound_flag = 1; + tuya_ble_storage_save_sys_settings(); + tuya_ble_adv_change(); + TUYA_BLE_LOG_INFO("PAIR_REQ ok-%d", tuya_ble_current_para.sys_settings.bound_flag); + + event.evt = TUYA_BLE_CB_EVT_UPDATE_LOGIN_KEY_VID; + event.device_login_key_vid_data.login_key_len = LOGIN_KEY_LEN; + event.device_login_key_vid_data.vid_len = 0; + memcpy(event.device_login_key_vid_data.login_key, tuya_ble_current_para.sys_settings.login_key, LOGIN_KEY_LEN); + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya ble send cb event failed."); + } else { + TUYA_BLE_LOG_DEBUG("tuya ble send cb event succeed."); + } + +#else + tuya_ble_connect_status_set(UNBONDING_CONN); +#endif + p_buf[0] = 0x00; + + } + + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + tuya_ble_connect_status_set(BONDING_CONN); + } + + event.evt = TUYA_BLE_CB_EVT_CONNECTE_STATUS; + event.connect_status = tuya_ble_connect_status_get(); + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya ble send cb event failed."); + } else { + TUYA_BLE_LOG_INFO("tuya ble send cb event succeed."); + } + + + } else { + TUYA_BLE_LOG_ERROR("PAIR_REQ device id not match!"); //ID not match ,and disconnected. + p_buf[0] = 0x01; + + } + + + if (p_buf[0] == 0) { +#if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + encry_mode = ENCRYPTION_MODE_SESSION_KEY; +#else + encry_mode = recv_data[0]; +#endif + } else if (p_buf[0] == 1) { + encry_mode = recv_data[0]; + } else if (p_buf[0] == 2) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + + } + + tuya_ble_commData_send(PAIR_RESP, ack_sn, p_buf, 1, encry_mode); + + if (encry_mode == ENCRYPTION_MODE_SESSION_KEY) { + tuya_ble_commData_send(FRM_GET_UNIX_TIME_CHAR_MS_REQ, 0, NULL, 0, encry_mode); + TUYA_BLE_LOG_INFO("send FRM_GET_UNIX_TIME_CHAR_MS_REQ cmd to app."); + } + + if (p_buf[0] == 1) { + tuya_ble_gap_disconnect(); + } + +} + +#endif + +static void tuya_ble_handle_net_config_info_req(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t p_buf[1]; + uint8_t encry_mode = 0; + uint32_t ack_sn = 0; + tuya_ble_cb_evt_param_t event; + uint16_t data_len; + + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + data_len = (recv_data[11] << 8) + recv_data[12]; + encry_mode = recv_data[0]; + + event.evt = TUYA_BLE_CB_EVT_NETWORK_INFO; + uint8_t *ble_cb_evt_buffer = (uint8_t *)tuya_ble_malloc(data_len); + if (ble_cb_evt_buffer == NULL) { + p_buf[0] = 1; + TUYA_BLE_LOG_ERROR("ble_cb_evt_buffer malloc failed."); + tuya_ble_commData_send(FRM_NET_CONFIG_INFO_RESP, ack_sn, p_buf, 1, encry_mode); + return; + } else { + memset(ble_cb_evt_buffer, 0, data_len); + memcpy(ble_cb_evt_buffer, &recv_data[13], data_len); + } + event.network_data.data_len = data_len; + event.network_data.p_data = ble_cb_evt_buffer; + + if (tuya_ble_cb_event_send(&event) != 0) { + tuya_ble_free(ble_cb_evt_buffer); + TUYA_BLE_LOG_ERROR("tuya ble send cb event failed."); + p_buf[0] = 1; + tuya_ble_commData_send(FRM_NET_CONFIG_INFO_RESP, ack_sn, p_buf, 1, encry_mode); + return; + } else { + p_buf[0] = 0; + } + + tuya_ble_commData_send(FRM_NET_CONFIG_INFO_RESP, ack_sn, p_buf, 1, encry_mode); + + +} + + +static void tuya_ble_handle_ble_passthrough_data_req(uint8_t *recv_data, uint16_t recv_len) +{ + tuya_ble_cb_evt_param_t event; + uint16_t data_len; + + data_len = (recv_data[11] << 8) + recv_data[12]; + + event.evt = TUYA_BLE_CB_EVT_DATA_PASSTHROUGH; + + uint8_t *ble_cb_evt_buffer = (uint8_t *)tuya_ble_malloc(data_len); + if (ble_cb_evt_buffer == NULL) { + TUYA_BLE_LOG_ERROR("ble_cb_evt_buffer malloc failed."); + return; + } else { + memcpy(ble_cb_evt_buffer, &recv_data[13], data_len); + } + event.ble_passthrough_data.data_len = data_len; + event.ble_passthrough_data.p_data = ble_cb_evt_buffer; + + if (tuya_ble_cb_event_send(&event) != 0) { + tuya_ble_free(ble_cb_evt_buffer); + TUYA_BLE_LOG_ERROR("tuya ble send cb event failed."); + } else { + + } + +} + + +static void tuya_ble_handle_ble_factory_test_req(uint8_t *recv_data, uint16_t recv_len) +{ + uint16_t data_len; + uint32_t ack_sn; + uint8_t sum; + uint8_t encry_mode; + + data_len = (recv_data[11] << 8) + recv_data[12]; + + if (data_len < 7) { + return; + } + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + encry_mode = recv_data[0]; + + if ((recv_data[13] == 0x66) && (recv_data[14] == 0xAA)) { + sum = tuya_ble_check_sum(&recv_data[13], data_len - 1); + if (sum == recv_data[13 + data_len - 1]) { + tuya_ble_app_production_test_process(1, &recv_data[13], data_len); + } + } + +} + + +static void tuya_ble_handle_ota_req(uint16_t cmd, uint8_t *recv_data, uint32_t recv_len) +{ + tuya_ble_cb_evt_param_t event; + uint16_t data_len; + tuya_ble_ota_data_type_t cmd_type; + + data_len = (recv_data[11] << 8) + recv_data[12]; + + if (data_len == 0) { + return; + } + + if (recv_data[13] == 1) { //extern mcu ota + tuya_ble_uart_common_mcu_ota_data_from_ble_handler(cmd, &recv_data[14], data_len - 1); + } else if (recv_data[13] == 0) { + event.evt = TUYA_BLE_CB_EVT_OTA_DATA; + + uint8_t *ble_cb_evt_buffer = (uint8_t *)tuya_ble_malloc(data_len); + if (ble_cb_evt_buffer == NULL) { + TUYA_BLE_LOG_ERROR("ble_cb_evt_buffer malloc failed."); + return; + } else { + memcpy(ble_cb_evt_buffer, &recv_data[13], data_len); + } + + switch (cmd) { + case FRM_OTA_START_REQ: + cmd_type = TUYA_BLE_OTA_REQ; + break; + case FRM_OTA_FILE_INFOR_REQ: + cmd_type = TUYA_BLE_OTA_FILE_INFO; + break; + case FRM_OTA_FILE_OFFSET_REQ: + cmd_type = TUYA_BLE_OTA_FILE_OFFSET_REQ; + break; + case FRM_OTA_DATA_REQ: + cmd_type = TUYA_BLE_OTA_DATA; + break; + case FRM_OTA_END_REQ: + cmd_type = TUYA_BLE_OTA_END; + break; + default: + cmd_type = TUYA_BLE_OTA_UNKONWN; + break; + } + + event.ota_data.type = cmd_type; + event.ota_data.data_len = data_len; + event.ota_data.p_data = ble_cb_evt_buffer; + + if (tuya_ble_cb_event_send(&event) != 0) { + tuya_ble_free(ble_cb_evt_buffer); + TUYA_BLE_LOG_ERROR("tuya_ble_handle_ota_req-tuya ble send cb event failed."); + } else { + + } + } else { + + } +} + +static char current_timems_string[14] = "000000000000"; + +static void tuya_ble_handle_unix_time_char_ms_resp(uint8_t *recv_data, uint16_t recv_len) +{ + int16_t zone_temp = 0; + uint64_t time_stamp_ms; + uint32_t time_stamp; + tuya_ble_cb_evt_param_t event; + + memset(&event, 0, sizeof(tuya_ble_cb_evt_param_t)); + + if (recv_len < 30) { + TUYA_BLE_LOG_ERROR("received unix time char cmd data length error!"); + return; + } + + if (!buffer_value_is_all_x(&recv_data[13], 13, 0)) { + memcpy(current_timems_string, &recv_data[13], 13); + zone_temp = (int16_t)((recv_data[26] << 8) | recv_data[27]); + time_stamp_ms = atoll(current_timems_string); + TUYA_BLE_LOG_INFO("received unix time_zone = %d\n", zone_temp); + time_stamp = time_stamp_ms / 1000; + if (time_stamp_ms % 1000 >= 500) { + time_stamp += 1; + } + + tuya_ble_rtc_set_timestamp(time_stamp, zone_temp); + + event.evt = TUYA_BLE_CB_EVT_TIME_STAMP; + + memcpy(event.timestamp_data.timestamp_string, current_timems_string, 13); + event.timestamp_data.time_zone = zone_temp; + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_unix_time_char_ms_resp-tuya ble send cb event failed."); + } + + } + +} + + +static void tuya_ble_handle_unix_time_date_resp(uint8_t *recv_data, uint16_t recv_len) +{ + int16_t zone_temp = 0; + uint32_t time_stamp; + tuya_ble_cb_evt_param_t event; + tuya_ble_time_struct_data_t time_temp; + + if (recv_len < 24) { + TUYA_BLE_LOG_ERROR("received unix time date cmd data length error!"); + return; + } + + memset(&event, 0, sizeof(tuya_ble_cb_evt_param_t)); + + if (!buffer_value_is_all_x(&recv_data[13], 7, 0)) { + time_temp.nYear = 2000 + recv_data[13]; + time_temp.nMonth = recv_data[14]; + time_temp.nDay = recv_data[15]; + time_temp.nHour = recv_data[16]; + time_temp.nMin = recv_data[17]; + time_temp.nSec = recv_data[18]; + time_temp.DayIndex = recv_data[19]; + + time_stamp = tuya_ble_mytime_2_utc_sec(&time_temp, false); + + zone_temp = (int16_t)((recv_data[20] << 8) | recv_data[21]); + + TUYA_BLE_LOG_INFO("received unix time_zone = %d", zone_temp); + + tuya_ble_rtc_set_timestamp(time_stamp, zone_temp); + + event.evt = TUYA_BLE_CB_EVT_TIME_NORMAL; + event.time_normal_data.nYear = recv_data[13]; + event.time_normal_data.nMonth = recv_data[14]; + event.time_normal_data.nDay = recv_data[15]; + event.time_normal_data.nHour = recv_data[16]; + event.time_normal_data.nMin = recv_data[17]; + event.time_normal_data.nSec = recv_data[18]; + event.time_normal_data.DayIndex = recv_data[19]; + event.time_normal_data.time_zone = zone_temp; + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_unix_time_date_resp-tuya ble send cb event failed."); + } + + } + +} + +static void tuya_ble_handle_app_local_time_data_resp(uint8_t *recv_data, uint16_t recv_len) +{ + int16_t zone_temp = 0; + uint32_t local_time, time_stamp; + tuya_ble_cb_evt_param_t event; + tuya_ble_time_struct_data_t time_temp; + + if (recv_len < 24) { + TUYA_BLE_LOG_ERROR("received app local time date cmd data length error!"); + return; + } + + memset(&event, 0, sizeof(tuya_ble_cb_evt_param_t)); + + if (!buffer_value_is_all_x(&recv_data[13], 7, 0)) { + time_temp.nYear = 2000 + recv_data[13]; + time_temp.nMonth = recv_data[14]; + time_temp.nDay = recv_data[15]; + time_temp.nHour = recv_data[16]; + time_temp.nMin = recv_data[17]; + time_temp.nSec = recv_data[18]; + time_temp.DayIndex = recv_data[19]; + + local_time = tuya_ble_mytime_2_utc_sec(&time_temp, false); + + zone_temp = (int16_t)((recv_data[20] << 8) | recv_data[21]); + + TUYA_BLE_LOG_INFO("received app local time_zone = %d", zone_temp); + + time_stamp = (local_time - zone_temp * 36); //!< Convert to unix timestamp + tuya_ble_rtc_set_timestamp(time_stamp, zone_temp); + + event.evt = TUYA_BLE_CB_EVT_APP_LOCAL_TIME_NORMAL; + event.time_normal_data.nYear = recv_data[13]; + event.time_normal_data.nMonth = recv_data[14]; + event.time_normal_data.nDay = recv_data[15]; + event.time_normal_data.nHour = recv_data[16]; + event.time_normal_data.nMin = recv_data[17]; + event.time_normal_data.nSec = recv_data[18]; + event.time_normal_data.DayIndex = recv_data[19]; + event.time_normal_data.time_zone = zone_temp; + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_app_local_time_date_resp-tuya ble send cb event failed."); + } + + } +} + + +static void tuya_ble_handle_unix_time_with_dst_date_resp(uint8_t *recv_data, uint16_t recv_len) +{ + int16_t zone_temp = 0; + uint32_t time_stamp; + uint8_t years_of_dst; + uint16_t dst_content_len; + tuya_ble_cb_evt_param_t event; + char current_time_string[11] = "0000000000"; + uint8_t *ble_cb_evt_buffer = NULL; + + if (recv_len < 28) { + TUYA_BLE_LOG_ERROR("received extend unix time date cmd data length error!"); + return; + } + + memset(&event, 0, sizeof(tuya_ble_cb_evt_param_t)); + + if (!buffer_value_is_all_x(&recv_data[13], 10, 0)) { + memcpy(current_time_string, &recv_data[13], 10); + time_stamp = atol(current_time_string); + + zone_temp = (int16_t)((recv_data[23] << 8) | recv_data[24]); + TUYA_BLE_LOG_INFO("received unix time_zone = %d\n", zone_temp); + + tuya_ble_rtc_set_timestamp(time_stamp, zone_temp); + + /* daylight saving time */ + years_of_dst = recv_data[25]; + dst_content_len = (years_of_dst * 20); + TUYA_BLE_LOG_INFO("received dst years= %d ", years_of_dst); + TUYA_BLE_LOG_HEXDUMP_INFO("dst data ", &recv_data[26], dst_content_len); + + if (years_of_dst > 0) { + ble_cb_evt_buffer = (uint8_t *)tuya_ble_malloc(dst_content_len); + if (ble_cb_evt_buffer == NULL) { + TUYA_BLE_LOG_ERROR("ble_cb_evt_buffer malloc failed."); + return; + } else { + memcpy(ble_cb_evt_buffer, &recv_data[26], dst_content_len); + } + } + + event.evt = TUYA_BLE_CB_EVT_TIME_STAMP_WITH_DST; + event.timestamp_with_dst_data.timestamp = time_stamp; + event.timestamp_with_dst_data.time_zone = zone_temp; + event.timestamp_with_dst_data.n_years_dst = years_of_dst; + event.timestamp_with_dst_data.p_data = ble_cb_evt_buffer; + event.timestamp_with_dst_data.data_len = dst_content_len; + + if (tuya_ble_cb_event_send(&event) != 0) { + if (years_of_dst > 0) { + tuya_ble_free(ble_cb_evt_buffer); + } + + TUYA_BLE_LOG_ERROR("tuya_ble_handle_unix_time_with_dst_resp-tuya ble send cb event failed."); + } + } +} + +static void tuya_ble_handle_dp_query_req(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t p_buf[1]; + uint16_t dp_num = 0; + uint32_t ack_sn = 0; + tuya_ble_cb_evt_param_t event; + uint8_t *ble_cb_evt_buffer = NULL; + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + dp_num = (recv_data[11] << 8) | recv_data[12]; + + p_buf[0] = 0x00; + + tuya_ble_commData_send(FRM_STATE_QUERY_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY); + + event.evt = TUYA_BLE_CB_EVT_DP_QUERY; + + if (dp_num > 0) { + ble_cb_evt_buffer = (uint8_t *)tuya_ble_malloc(dp_num); + if (ble_cb_evt_buffer == NULL) { + TUYA_BLE_LOG_ERROR("ble_cb_evt_buffer malloc failed."); + return; + } else { + memcpy(ble_cb_evt_buffer, &recv_data[13], dp_num); + } + } + event.dp_query_data.p_data = ble_cb_evt_buffer; + event.dp_query_data.data_len = dp_num; + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_query_req-tuya ble send cb event failed."); + if (dp_num > 0) { + tuya_ble_free(ble_cb_evt_buffer); + } + } else { + + } +} + + +void tuya_ble_device_unbond(void) +{ + + tuya_ble_gap_disconnect(); + memset(tuya_ble_current_para.sys_settings.login_key, 0, LOGIN_KEY_LEN); + memset(tuya_ble_current_para.sys_settings.beacon_key, 0, BEACON_KEY_LEN); + tuya_ble_current_para.sys_settings.bound_flag = 0; + tuya_ble_storage_save_sys_settings(); + tuya_ble_adv_change(); + tuya_ble_connect_status_set(UNBONDING_UNCONN); + TUYA_BLE_LOG_INFO("tuya_ble_device_unbond current bound flag = %d", tuya_ble_current_para.sys_settings.bound_flag); +} + + + +static void tuya_ble_handle_unbond_req(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t p_buf[1]; + uint8_t encry_mode = 0; + uint32_t ack_sn = 0; + tuya_ble_cb_evt_param_t event; + +#if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + + p_buf[0] = 0; + + tuya_ble_commData_send(FRM_UNBONDING_RESP, ack_sn, p_buf, 1, encry_mode); + +#if (TUYA_BLE_DEVICE_UNBIND_MODE) + tuya_ble_device_unbond(); + + event.evt = TUYA_BLE_CB_EVT_CONNECTE_STATUS; + event.connect_status = tuya_ble_connect_status_get(); + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_unbond_req-tuya ble send cb event (connect status update) failed."); + } else { + + } +#else + tuya_ble_gap_disconnect(); +#endif + +#endif + + event.evt = TUYA_BLE_CB_EVT_UNBOUND; + event.unbound_data.data = 0; + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_unbond_req-tuya ble send cb event (unbound req) failed."); + } else { + + } + +} + + +static void tuya_ble_handle_anomaly_unbond_req(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t p_buf[1]; + uint8_t encry_mode = 0; + uint32_t ack_sn = 0; + tuya_ble_cb_evt_param_t event; + +#if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + encry_mode = ENCRYPTION_MODE_KEY_1; + + p_buf[0] = 0; + + tuya_ble_commData_send(FRM_ANOMALY_UNBONDING_RESP, ack_sn, p_buf, 1, encry_mode); + tuya_ble_device_unbond(); + + event.evt = TUYA_BLE_CB_EVT_CONNECTE_STATUS; + event.connect_status = tuya_ble_connect_status_get(); + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_anomaly_unbond_req-tuya ble send cb event (connect status update) failed."); + } else { + + } + +#endif + + event.evt = TUYA_BLE_CB_EVT_ANOMALY_UNBOUND; + event.anomaly_unbound_data.data = 0; + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_anomaly_unbond_req-tuya ble send cb event (unbound req) failed."); + } else { + + } + +} + + +static void tuya_ble_handle_device_reset_req(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t p_buf[1]; + uint8_t encry_mode = 0; + uint32_t ack_sn = 0; + tuya_ble_cb_evt_param_t event; + +#if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + + p_buf[0] = 0; + + tuya_ble_commData_send(FRM_DEVICE_RESET_RESP, ack_sn, p_buf, 1, encry_mode); + +#if (TUYA_BLE_DEVICE_UNBIND_MODE) + memset(tuya_ble_current_para.sys_settings.device_virtual_id, 0, DEVICE_VIRTUAL_ID_LEN); + tuya_ble_device_unbond(); + + event.evt = TUYA_BLE_CB_EVT_CONNECTE_STATUS; + event.connect_status = tuya_ble_connect_status_get(); + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_device_reset_req-tuya ble send cb event (connect status update) failed."); + } else { + + } +#else + tuya_ble_gap_disconnect(); +#endif + +#endif + + event.evt = TUYA_BLE_CB_EVT_DEVICE_RESET; + event.device_reset_data.data = 0; + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_device_reset_req-tuya ble send cb event device reset req failed."); + } else { + + } + +} + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN==4) + +static void tuya_ble_handle_dp_data_write_req(uint8_t *recv_data, uint16_t recv_len) +{ + mtp_ret ret; + klv_node_s *list = NULL; + uint8_t p_buf[6]; + uint16_t data_len = 0; + uint32_t ack_sn = 0; + tuya_ble_cb_evt_param_t event; + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + data_len = (recv_data[11] << 8) | recv_data[12]; + + if ((data_len < 5) || (data_len > TUYA_BLE_RECEIVE_MAX_DP_DATA_LEN)) { + TUYA_BLE_LOG_ERROR("cmd dp write error,receive data len == %d", data_len); + if (data_len < 5) { + memcpy(&p_buf[0], &recv_data[13], data_len); + } else { + memcpy(&p_buf[0], &recv_data[13], 5); + } + p_buf[5] = 1; + tuya_ble_commData_send(FRM_DP_DATA_WRITE_RESP, ack_sn, p_buf, 6, ENCRYPTION_MODE_SESSION_KEY); + return; + } else if (recv_data[13] != 0) { + TUYA_BLE_LOG_ERROR("cmd dp write version not support"); + + memcpy(&p_buf[0], &recv_data[13], 5); + + p_buf[5] = 1; + tuya_ble_commData_send(FRM_DP_DATA_WRITE_RESP, ack_sn, p_buf, 6, ENCRYPTION_MODE_SESSION_KEY); + return; + } else { + + } + + TUYA_BLE_LOG_HEXDUMP_DEBUG("cmd_dp_write data : ", recv_data + 13, data_len); + memcpy(&p_buf[0], &recv_data[13], 5); + ret = data_2_klvlist(&recv_data[18], data_len - 5, &list, 1); + if (MTP_OK != ret) { + TUYA_BLE_LOG_ERROR("cmd rx fail-%d", ret); + p_buf[5] = 1; + tuya_ble_commData_send(FRM_DP_DATA_WRITE_RESP, ack_sn, p_buf, 6, ENCRYPTION_MODE_SESSION_KEY); + return; + } + + free_klv_list(list); + + event.evt = TUYA_BLE_CB_EVT_DP_DATA_RECEIVED; + + uint8_t *ble_cb_evt_buffer = (uint8_t *)tuya_ble_malloc(data_len - 5); + if (ble_cb_evt_buffer == NULL) { + TUYA_BLE_LOG_ERROR("ble_cb_evt_buffer malloc failed."); + p_buf[5] = 0x01; + tuya_ble_commData_send(FRM_DP_DATA_WRITE_RESP, ack_sn, p_buf, 6, ENCRYPTION_MODE_SESSION_KEY); + return; + } else { + memcpy(ble_cb_evt_buffer, &recv_data[18], data_len - 5); + event.dp_received_data.sn = (recv_data[14] << 24) | (recv_data[15] << 16) | (recv_data[16] << 8) | recv_data[17]; + event.dp_received_data.p_data = ble_cb_evt_buffer; + event.dp_received_data.data_len = data_len - 5; + } + + if (tuya_ble_cb_event_send(&event) != 0) { + tuya_ble_free(ble_cb_evt_buffer); + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_write_req-tuya ble send cb event failed."); + p_buf[5] = 0x01; + tuya_ble_commData_send(FRM_DP_DATA_WRITE_RESP, ack_sn, p_buf, 6, ENCRYPTION_MODE_SESSION_KEY); + } else { + p_buf[5] = 0x00; + tuya_ble_commData_send(FRM_DP_DATA_WRITE_RESP, ack_sn, p_buf, 6, ENCRYPTION_MODE_SESSION_KEY); + } + +} + +static void tuya_ble_handle_dp_data_send_response(uint8_t *recv_data, uint16_t recv_len) +{ + tuya_ble_cb_evt_param_t event; + uint16_t data_len = recv_data[11] << 8 | recv_data[12]; + + if (data_len != 8) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_send_response- invalid data len received."); + return; + } + + event.evt = TUYA_BLE_CB_EVT_DP_DATA_SEND_RESPONSE; + event.dp_send_response_data.sn = recv_data[14] << 24 | recv_data[15] << 16 | recv_data[16] << 8 | recv_data[17]; + event.dp_send_response_data.ack = ((recv_data[18] & 0x80) ? DP_SEND_WITHOUT_RESPONSE : DP_SEND_WITH_RESPONSE); + if ((recv_data[18] & 0x0F) == 1) { + event.dp_send_response_data.type = DP_SEND_TYPE_PASSIVE; + } else if ((recv_data[18] & 0x0F) == 0) { + event.dp_send_response_data.type = DP_SEND_TYPE_ACTIVE; + } else { + return; + } + + if (recv_data[19] > 3) { + return; + } + event.dp_send_response_data.mode = recv_data[19]; + event.dp_send_response_data.status = recv_data[20]; + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_send_response-tuya ble send cb event failed."); + } else { + + } +} + +static void tuya_ble_handle_dp_data_with_time_send_response(uint8_t *recv_data, uint16_t recv_len) +{ + tuya_ble_cb_evt_param_t event; + uint16_t data_len = recv_data[11] << 8 | recv_data[12]; + + if (data_len != 8) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_with_time_send_response- invalid data len received."); + return; + } + + event.evt = TUYA_BLE_CB_EVT_DP_DATA_WITH_TIME_SEND_RESPONSE; + event.dp_with_time_send_response_data.sn = recv_data[14] << 24 | recv_data[15] << 16 | recv_data[16] << 8 | recv_data[17]; + event.dp_with_time_send_response_data.ack = ((recv_data[18] & 0x80) ? DP_SEND_WITHOUT_RESPONSE : DP_SEND_WITH_RESPONSE); + if ((recv_data[18] & 0x0F) == 1) { + event.dp_with_time_send_response_data.type = DP_SEND_TYPE_PASSIVE; + } else if ((recv_data[18] & 0x0F) == 0) { + event.dp_with_time_send_response_data.type = DP_SEND_TYPE_ACTIVE; + } else { + return; + } + + if (recv_data[19] > 3) { + return; + } + event.dp_with_time_send_response_data.mode = recv_data[19]; + event.dp_with_time_send_response_data.status = recv_data[20]; + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_with_time_send_response-tuya ble send cb event failed."); + } else { + + } +} + +#else //(TUYA_BLE_PROTOCOL_VERSION_HIGN<4) + +static void tuya_ble_handle_dp_write_req(uint8_t *recv_data, uint16_t recv_len) +{ + mtp_ret ret; + klv_node_s *list = NULL; + uint8_t p_buf[1]; + uint16_t data_len = 0; + uint32_t ack_sn = 0; + tuya_ble_cb_evt_param_t event; + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + data_len = (recv_data[11] << 8) | recv_data[12]; + + if ((data_len == 0) || (data_len > TUYA_BLE_RECEIVE_MAX_DP_DATA_LEN)) { + TUYA_BLE_LOG_ERROR("cmd dp write receive data len == %d", data_len); + p_buf[0] = 0x01; + tuya_ble_commData_send(FRM_CMD_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY); + return; + } + TUYA_BLE_LOG_HEXDUMP_DEBUG("cmd_dp_write data : ", recv_data + 13, data_len); + ret = data_2_klvlist(&recv_data[13], data_len, &list, 0); + if (MTP_OK != ret) { + TUYA_BLE_LOG_ERROR("cmd rx fail-%d", ret); + p_buf[0] = 0x01; + tuya_ble_commData_send(FRM_CMD_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY); + return; + } + + free_klv_list(list); + p_buf[0] = 0x00; + + tuya_ble_commData_send(FRM_CMD_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY); + + event.evt = TUYA_BLE_CB_EVT_DP_WRITE; + + uint8_t *ble_cb_evt_buffer = (uint8_t *)tuya_ble_malloc(data_len); + if (ble_cb_evt_buffer == NULL) { + TUYA_BLE_LOG_ERROR("ble_cb_evt_buffer malloc failed."); + return; + } else { + memcpy(ble_cb_evt_buffer, &recv_data[13], data_len); + } + event.dp_write_data.p_data = ble_cb_evt_buffer; + event.dp_write_data.data_len = data_len; + + if (tuya_ble_cb_event_send(&event) != 0) { + tuya_ble_free(ble_cb_evt_buffer); + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_write_req-tuya ble send cb event failed."); + } else { + + } + +} + +static void tuya_ble_handle_dp_data_report_res(uint8_t *recv_data, uint16_t recv_len) +{ + tuya_ble_cb_evt_param_t event; + + event.evt = TUYA_BLE_CB_EVT_DP_DATA_REPORT_RESPONSE; + event.dp_response_data.status = recv_data[13]; + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_report_res-tuya ble send cb event failed."); + } else { + + } +} + +static void tuya_ble_handle_dp_data_with_time_report_res(uint8_t *recv_data, uint16_t recv_len) +{ + tuya_ble_cb_evt_param_t event; + + event.evt = TUYA_BLE_CB_EVT_DP_DATA_WTTH_TIME_REPORT_RESPONSE; + event.dp_response_data.status = recv_data[13]; + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_report_res-tuya ble send cb event failed."); + } else { + + } +} + +static void tuya_ble_handle_dp_data_with_flag_report_res(uint8_t *recv_data, uint16_t recv_len) +{ + tuya_ble_cb_evt_param_t event; + uint16_t data_len = recv_data[11] << 8 | recv_data[12]; + + if (data_len != 4) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_with_flag_report_res- invalid data len received."); + return; + } + + event.evt = TUYA_BLE_CB_EVT_DP_DATA_WITH_FLAG_REPORT_RESPONSE; + event.dp_with_flag_response_data.sn = recv_data[13] << 8 | recv_data[14]; + event.dp_with_flag_response_data.mode = recv_data[15]; + event.dp_with_flag_response_data.status = recv_data[16]; + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_with_flag_report_res-tuya ble send cb event failed."); + } else { + + } +} + +static void tuya_ble_handle_dp_data_with_flag_and_time_report_res(uint8_t *recv_data, uint16_t recv_len) +{ + tuya_ble_cb_evt_param_t event; + uint16_t data_len = recv_data[11] << 8 | recv_data[12]; + + if (data_len != 4) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_with_flag_and_time_report_res- invalid data len received."); + return; + } + + event.evt = TUYA_BLE_CB_EVT_DP_DATA_WITH_FLAG_AND_TIME_REPORT_RESPONSE; + event.dp_with_flag_and_time_response_data.sn = recv_data[13] << 8 | recv_data[14]; + event.dp_with_flag_and_time_response_data.mode = recv_data[15]; + event.dp_with_flag_and_time_response_data.status = recv_data[16]; + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_with_flag_and_time_report_res-tuya ble send cb event failed."); + } else { + + } +} + +#endif + + +void tuya_ble_evt_process(uint16_t cmd, uint8_t *recv_data, uint32_t recv_len) +{ + printf("process cmd = 0x%x", cmd); + switch (cmd) { +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN==4) + + case FRM_DP_DATA_WRITE_REQ: + tuya_ble_handle_dp_data_write_req(recv_data, recv_len); + break; + case FRM_DP_DATA_SEND_RESP: + tuya_ble_handle_dp_data_send_response(recv_data, recv_len); + break; + case FRM_DP_DATA_WITH_TIME_SEND_RESP: + tuya_ble_handle_dp_data_with_time_send_response(recv_data, recv_len); + break; + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE==TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) + + case FRM_AUTHENTICATE_PHASE_1_REQ: + tuya_ble_handle_authenticate_phase1(recv_data, recv_len); + break; + case FRM_AUTHENTICATE_PHASE_2_REQ: + tuya_ble_handle_authenticate_phase2(recv_data, recv_len); + break; + case FRM_AUTHENTICATE_PHASE_3_REQ: + tuya_ble_handle_authenticate_phase3(recv_data, recv_len); + break; + +#endif + +#if (TUYA_BLE_FEATURE_WEATHER_ENABLE != 0) + case FRM_WEATHER_DATA_REQUEST_RESP: + tuya_ble_handle_weather_data_request_response(recv_data, recv_len); + break; + case FRM_WEATHER_DATA_RECEIVED: + tuya_ble_handle_weather_data_received(recv_data, recv_len); + break; +#endif + +#else + case FRM_CMD_SEND: + tuya_ble_handle_dp_write_req(recv_data, recv_len); + break; + case FRM_STAT_REPORT_RESP: + tuya_ble_handle_dp_data_report_res(recv_data, recv_len); + break; + case FRM_DATA_WITH_FLAG_REPORT_RESP: + tuya_ble_handle_dp_data_with_flag_report_res(recv_data, recv_len); + break; + case FRM_STAT_WITH_TIME_REPORT_RESP: + tuya_ble_handle_dp_data_with_time_report_res(recv_data, recv_len); + break; + case FRM_DATA_WITH_FLAG_AND_TIME_REPORT_RESP: + tuya_ble_handle_dp_data_with_flag_and_time_report_res(recv_data, recv_len); + break; +#endif + case FRM_STATE_QUERY: + tuya_ble_handle_dp_query_req(recv_data, recv_len); + break; + case FRM_QRY_DEV_INFO_REQ: + tuya_ble_handle_dev_info_req(recv_data, recv_len); + break; + case PAIR_REQ: + tuya_ble_handle_pair_req(recv_data, recv_len); + break; + case FRM_NET_CONFIG_INFO_REQ: + tuya_ble_handle_net_config_info_req(recv_data, recv_len); + break; + case FRM_DATA_PASSTHROUGH_REQ: + tuya_ble_handle_ble_passthrough_data_req(recv_data, recv_len); + break; + case FRM_BULK_DATA_READ_INFO_REQ: + case FRM_BULK_DATA_READ_DATA_REQ: + case FRM_BULK_DATA_ERASE_DATA_REQ: + TUYA_BLE_LOG_INFO("RECEIVED BULK DATA CMD:0x%02x DATA LEN:0x%02x", cmd, recv_len); + tuya_ble_handle_bulk_data_req(cmd, recv_data, recv_len); + break; + case FRM_OTA_START_REQ: + case FRM_OTA_FILE_INFOR_REQ: + case FRM_OTA_FILE_OFFSET_REQ: + case FRM_OTA_DATA_REQ: + case FRM_OTA_END_REQ: + TUYA_BLE_LOG_INFO("RECEIVED OTA CMD:0x%02x DATA LEN:0x%02x", cmd, recv_len); + tuya_ble_handle_ota_req(cmd, recv_data, recv_len); + break; + case FRM_GET_UNIX_TIME_CHAR_MS_RESP: + tuya_ble_handle_unix_time_char_ms_resp(recv_data, recv_len); + break; + case FRM_GET_UNIX_TIME_CHAR_DATE_RESP: + tuya_ble_handle_unix_time_date_resp(recv_data, recv_len); + break; + case FRM_GET_APP_LOCAL_TIME_RESP: + tuya_ble_handle_app_local_time_data_resp(recv_data, recv_len); + break; + case FRM_GET_UNIX_TIME_WITH_DST_RESP: + tuya_ble_handle_unix_time_with_dst_date_resp(recv_data, recv_len); + break; + case FRM_UNBONDING_REQ: + TUYA_BLE_LOG_INFO("RECEIVED FRM_UNBONDING_REQ"); + tuya_ble_handle_unbond_req(recv_data, recv_len); + break; + case FRM_ANOMALY_UNBONDING_REQ: + TUYA_BLE_LOG_INFO("RECEIVED FRM_ANOMALY_UNBONDING_REQ"); + tuya_ble_handle_anomaly_unbond_req(recv_data, recv_len); + break; + case FRM_DEVICE_RESET: + TUYA_BLE_LOG_INFO("RECEIVED FRM_DEVICE_RESET_REQ"); + tuya_ble_handle_device_reset_req(recv_data, recv_len); + break; + + case FRM_FACTORY_TEST_CMD: + tuya_ble_handle_ble_factory_test_req(recv_data, recv_len); + break; + default: + TUYA_BLE_LOG_WARNING("RECEIVED UNKNOWN BLE EVT CMD-0x%04x", cmd); + break; + } +} + +uint8_t tuya_ble_commData_send(uint16_t cmd, uint32_t ack_sn, uint8_t *data, uint16_t len, uint8_t encryption_mode) +{ + mtp_ret ret; + uint16_t send_len = 0; + uint8_t *p_buf = NULL; + uint32_t err = 0; + int8_t retries_cnt = 0; + uint8_t iv[16]; + uint16_t rand_value = 0, i = 0; + uint16_t crc16 = 0; + uint16_t en_len = 0; + uint32_t out_len = 0; + uint32_t temp_len = 0; + uint32_t package_number = 0; + uint16_t p_version = 0; + tuya_ble_r_air_send_packet air_send_packet; + + memset(&air_send_packet, 0, sizeof(air_send_packet)); + + tuya_ble_connect_status_t currnet_connect_status = tuya_ble_connect_status_get(); + + if ((currnet_connect_status == BONDING_UNCONN) || (currnet_connect_status == UNBONDING_UNCONN)) { + TUYA_BLE_LOG_ERROR("tuya ble commData_send failed,because ble not in connect status."); + return 2; + } + + if ((encryption_mode >= ENCRYPTION_MODE_MAX) || (len > TUYA_BLE_SEND_MAX_DATA_LEN)) { + return 1; + } + + + if (encryption_mode != ENCRYPTION_MODE_NONE) { + for (i = 0; i < 16; i += 2) { + rand_value = rand(); + iv[i + 0] = rand_value >> 8; + iv[i + 1] = rand_value; + } + en_len = 17; + } else { + en_len = 1; + memset(iv, 0, sizeof(iv)); + } + + air_send_packet.send_len = 14 + len; + + if (air_send_packet.send_len % 16 == 0) { + temp_len = 0; + } else { + temp_len = 16 - air_send_packet.send_len % 16; + } + + temp_len += air_send_packet.send_len; + + if (temp_len > (TUYA_BLE_AIR_FRAME_MAX - en_len)) { + TUYA_BLE_LOG_ERROR("The length of the send to ble exceeds the maximum length."); + air_send_packet.send_len = 0; + return 1; + } + + air_send_packet.send_data = NULL; + + air_send_packet.send_data = (uint8_t *)tuya_ble_malloc(temp_len); //must temp_len + + if (air_send_packet.send_data == NULL) { + TUYA_BLE_LOG_ERROR("air_send_packet.send_data malloc failed return 3."); + air_send_packet.send_len = 0; + return 3; + } else { + memset(air_send_packet.send_data, 0, temp_len); + } + + + uint32_t send_sn = get_ble_send_sn(); + + air_send_packet.send_data[0] = send_sn >> 24; + air_send_packet.send_data[1] = send_sn >> 16; + air_send_packet.send_data[2] = send_sn >> 8; + air_send_packet.send_data[3] = send_sn; + + air_send_packet.send_data[4] = ack_sn >> 24; + air_send_packet.send_data[5] = ack_sn >> 16; + air_send_packet.send_data[6] = ack_sn >> 8; + air_send_packet.send_data[7] = ack_sn; + + air_send_packet.send_data[8] = cmd >> 8; + air_send_packet.send_data[9] = cmd; + + air_send_packet.send_data[10] = len >> 8; + air_send_packet.send_data[11] = len; + + memcpy(&air_send_packet.send_data[12], data, len); + + crc16 = tuya_ble_crc16_compute(air_send_packet.send_data, 12 + len, NULL); + + air_send_packet.send_data[12 + len] = crc16 >> 8; + air_send_packet.send_data[13 + len] = crc16; + + + TUYA_BLE_LOG_HEXDUMP_DEBUG("ble_commData_send plain data", (uint8_t *)air_send_packet.send_data, air_send_packet.send_len); // + + air_send_packet.encrypt_data_buf = NULL; + + air_send_packet.encrypt_data_buf = (uint8_t *)tuya_ble_malloc(temp_len + en_len); + + if (air_send_packet.encrypt_data_buf == NULL) { + TUYA_BLE_LOG_ERROR("air_send_packet.encrypt_data_buf malloc failed."); + tuya_ble_free(air_send_packet.send_data); + return 3; + } else { + air_send_packet.encrypt_data_buf_len = 0; + memset(air_send_packet.encrypt_data_buf, 0, temp_len + en_len); + } + + + air_send_packet.encrypt_data_buf[0] = encryption_mode; + + if (encryption_mode != ENCRYPTION_MODE_NONE) { + memcpy(&air_send_packet.encrypt_data_buf[1], iv, 16); + } else { + + } + + p_version = (TUYA_BLE_PROTOCOL_VERSION_HIGN << 8) + TUYA_BLE_PROTOCOL_VERSION_LOW; + if (tuya_ble_encryption(p_version, encryption_mode, iv, (uint8_t *)air_send_packet.send_data, air_send_packet.send_len, &out_len, + (uint8_t *)(air_send_packet.encrypt_data_buf + en_len), &tuya_ble_current_para, tuya_ble_pair_rand) == 0) { + if ((encryption_mode != ENCRYPTION_MODE_NONE) && (out_len != temp_len)) { + TUYA_BLE_LOG_ERROR("ble_commData_send encryed error."); + tuya_ble_free(air_send_packet.send_data); + tuya_ble_free(air_send_packet.encrypt_data_buf); + return 1; + } + + air_send_packet.encrypt_data_buf_len = en_len + out_len; + + TUYA_BLE_LOG_HEXDUMP_DEBUG("ble_commData_send encryped data", (uint8_t *)air_send_packet.encrypt_data_buf, air_send_packet.encrypt_data_buf_len); // + } else { + TUYA_BLE_LOG_ERROR("ble_commData_send encryed fail."); + tuya_ble_free(air_send_packet.send_data); + tuya_ble_free(air_send_packet.encrypt_data_buf); + return 1; + } + + tuya_ble_free(air_send_packet.send_data); + package_number = 0; + if ((send_packet_data_len == 0) || (send_packet_data_len > TUYA_BLE_DATA_MTU_MAX)) { + send_packet_data_len = 20; + } + trsmitr_init(&ty_trsmitr_proc_send); + do { + ret = trsmitr_send_pkg_encode_with_packet_length(&ty_trsmitr_proc_send, send_packet_data_len, TUYA_BLE_PROTOCOL_VERSION_HIGN, + (uint8_t *)(air_send_packet.encrypt_data_buf), air_send_packet.encrypt_data_buf_len); + if (MTP_OK != ret && MTP_TRSMITR_CONTINUE != ret) { + tuya_ble_free(air_send_packet.encrypt_data_buf); + return 1; + } + send_len = get_trsmitr_subpkg_len(&ty_trsmitr_proc_send); + p_buf = get_trsmitr_subpkg(&ty_trsmitr_proc_send); + package_number++; + tuya_ble_gatt_send_data_enqueue(p_buf, send_len); + + } while (ret == MTP_TRSMITR_CONTINUE); + + TUYA_BLE_LOG_INFO("ble_commData_send len = %d , package_number = %d , protocol version : 0x%02x , error code : 0x%02x", air_send_packet.encrypt_data_buf_len, package_number, TUYA_BLE_PROTOCOL_VERSION_HIGN, err); + + tuya_ble_free(air_send_packet.encrypt_data_buf); + + return 0; +} + + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event.c new file mode 100644 index 0000000..c7fe4a7 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event.c @@ -0,0 +1,225 @@ +/** + * \file tuya_ble_event.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" +#include "tuya_ble_heap.h" +#include "tuya_ble_mem.h" +#include "tuya_ble_api.h" +#include "tuya_ble_port.h" +#include "tuya_ble_main.h" +#include "tuya_ble_secure.h" +#include "tuya_ble_data_handler.h" +#include "tuya_ble_storage.h" +#include "tuya_ble_sdk_version.h" +#include "tuya_ble_utils.h" +#include "tuya_ble_event.h" +#include "tuya_ble_log.h" + +#if (!TUYA_BLE_USE_OS) + +static uint8_t *m_queue_event_data; /**< Array for holding the queue event data. */ +static volatile uint8_t m_queue_start_index; /**< Index of queue entry at the start of the queue. */ +static volatile uint8_t m_queue_end_index; /**< Index of queue entry at the end of the queue. */ +static uint16_t m_queue_event_size; /**< Maximum event size in queue. */ +static uint16_t m_queue_size; /**< Number of queue entries. */ + + +/**@brief Function for incrementing a queue index, and handle wrap-around. + * + * @param[in] index Old index. + * + * @return New (incremented) index. + */ +static __TUYA_BLE_INLINE uint8_t next_index(uint8_t index) +{ + return (index < m_queue_size) ? (index + 1) : 0; +} + + +static __TUYA_BLE_INLINE uint8_t tuya_sched_queue_full(void) +{ + uint8_t tmp = m_queue_start_index; + return next_index(m_queue_end_index) == tmp; +} + +/**@brief Macro for checking if a queue is full. */ +#define TUYA_BLE_SCHED_QUEUE_FULL() tuya_sched_queue_full() + + +static __TUYA_BLE_INLINE uint8_t tuya_sched_queue_empty(void) +{ + uint8_t tmp = m_queue_start_index; + return m_queue_end_index == tmp; +} + +/**@brief Macro for checking if a queue is empty. */ +#define TUYA_BLE_SCHED_QUEUE_EMPTY() tuya_sched_queue_empty() + + +uint32_t tuya_ble_sched_init(uint16_t event_size, uint16_t queue_size, void *p_event_buffer) +{ + + // Check that buffer is correctly aligned + if (!tuya_ble_is_word_aligned_tuya(p_event_buffer)) { + TUYA_BLE_LOG_ERROR("tuya_ble_sched_init error"); + return 1; + } + + // Initialize event scheduler + m_queue_event_data = &((uint8_t *)p_event_buffer)[0]; + m_queue_end_index = 0; + m_queue_start_index = 0; + m_queue_event_size = event_size; + m_queue_size = queue_size; + + return 0; +} + +uint16_t tuya_ble_sched_queue_size_get(void) +{ + return m_queue_size; +} + +uint16_t tuya_ble_sched_queue_space_get(void) +{ + uint16_t start = m_queue_start_index; + uint16_t end = m_queue_end_index; + uint16_t free_space = m_queue_size - ((end >= start) ? + (end - start) : (m_queue_size + 1 - start + end)); + return free_space; +} + + +uint16_t tuya_ble_sched_queue_events_get(void) +{ + uint16_t start = m_queue_start_index; + uint16_t end = m_queue_end_index; + uint16_t number_of_events; + if (m_queue_size == 0) { + number_of_events = 0; + } else { + number_of_events = ((end >= start) ? (end - start) : (m_queue_size + 1 - start + end)); + } + return number_of_events; +} + + +static tuya_ble_status_t tuya_ble_sched_event_put(void const *p_event_data, uint16_t event_data_size) +{ + tuya_ble_status_t err_code; + + if (event_data_size <= m_queue_event_size) { + uint16_t event_index = 0xFFFF; + + tuya_ble_device_enter_critical(); + + if (!TUYA_BLE_SCHED_QUEUE_FULL()) { + event_index = m_queue_end_index; + m_queue_end_index = next_index(m_queue_end_index); + + } + + tuya_ble_device_exit_critical(); + + if (event_index != 0xFFFF) { + // NOTE: This can be done outside the critical region since the event consumer will + // always be called from the main loop, and will thus never interrupt this code. + + if ((p_event_data != NULL) && (event_data_size > 0)) { + memcpy(&m_queue_event_data[event_index * m_queue_event_size], + p_event_data, + event_data_size); + + } else { + + } + + err_code = TUYA_BLE_SUCCESS; + } else { + err_code = TUYA_BLE_ERR_NO_MEM; + } + } else { + err_code = TUYA_BLE_ERR_INVALID_LENGTH; + } + + return err_code; +} + + +void tuya_sched_execute(void) +{ + static tuya_ble_evt_param_t tuya_ble_evt; + tuya_ble_evt_param_t *evt; + + evt = &tuya_ble_evt; + + uint8_t end_ix = m_queue_end_index; + + while (m_queue_start_index != end_ix) { //(!TUYA_BLE_SCHED_QUEUE_EMPTY()) + // Since this function is only called from the main loop, there is no + // need for a critical region here, however a special care must be taken + // regarding update of the queue start index (see the end of the loop). + uint16_t event_index = m_queue_start_index; + + void *p_event_data; + + p_event_data = &(m_queue_event_data[event_index * m_queue_event_size]); + + memcpy(evt, p_event_data, sizeof(tuya_ble_evt_param_t)); + + //TUYA_BLE_LOG_DEBUG("TUYA_RECEIVE_EVT-0x%04x,start index-0x%04x,end index-0x%04x\n",evt->hdr.event,m_queue_start_index,m_queue_end_index); + + tuya_ble_event_process(evt); + + // Event processed, now it is safe to move the queue start index, + // so the queue entry occupied by this event can be used to store + // a next one. + m_queue_start_index = next_index(m_queue_start_index); + } + +} + + + +void tuya_ble_event_queue_init(void) +{ + if ((sizeof(tuya_ble_evt_param_t)) > TUYA_BLE_EVT_SIZE) { + TUYA_BLE_LOG_ERROR("ERROR!!TUYA_BLE_EVT_SIZE is not enough!"); + return; + } + + TUYA_BLE_SCHED_INIT(TUYA_BLE_EVT_SIZE, TUYA_BLE_EVT_MAX_NUM); +} + + +tuya_ble_status_t tuya_ble_message_send(tuya_ble_evt_param_t *evt) +{ + return tuya_ble_sched_event_put(evt, m_queue_event_size); +} + + +#endif + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event_handler.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event_handler.c new file mode 100644 index 0000000..849f8d2 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event_handler.c @@ -0,0 +1,779 @@ +/** + * \file tuya_ble_event_handler.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" +#include "tuya_ble_heap.h" +#include "tuya_ble_mem.h" +#include "tuya_ble_api.h" +#include "tuya_ble_port.h" +#include "tuya_ble_main.h" +#include "tuya_ble_secure.h" +#include "tuya_ble_data_handler.h" +#include "tuya_ble_storage.h" +#include "tuya_ble_sdk_version.h" +#include "tuya_ble_event.h" +#include "tuya_ble_utils.h" +#include "tuya_ble_app_uart_common_handler.h" +#include "tuya_ble_app_production_test.h" +#include "tuya_ble_log.h" +#include "tuya_ble_event_handler.h" + + +void tuya_ble_handle_device_info_update_evt(tuya_ble_evt_param_t *evt) +{ +#if (!TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + tuya_ble_cb_evt_param_t event; + tuya_ble_connect_status_t current_connect_status; +#endif + switch (evt->device_info_data.type) { + case DEVICE_INFO_TYPE_PID: + tuya_ble_current_para.pid_type = TUYA_BLE_PRODUCT_ID_TYPE_PID; + tuya_ble_current_para.pid_len = evt->device_info_data.len; + memcpy(tuya_ble_current_para.pid, evt->device_info_data.data, tuya_ble_current_para.pid_len); + tuya_ble_adv_change(); + break; + + case DEVICE_INFO_TYPE_PRODUCT_KEY: + tuya_ble_current_para.pid_type = TUYA_BLE_PRODUCT_ID_TYPE_PRODUCT_KEY; + tuya_ble_current_para.pid_len = evt->device_info_data.len; + memcpy(tuya_ble_current_para.pid, evt->device_info_data.data, tuya_ble_current_para.pid_len); + tuya_ble_adv_change(); + break; + case DEVICE_INFO_TYPE_LOGIN_KEY: +#if (!TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + if (memcmp(tuya_ble_current_para.sys_settings.login_key, evt->device_info_data.data, LOGIN_KEY_LEN)) { + memcpy(tuya_ble_current_para.sys_settings.login_key, evt->device_info_data.data, LOGIN_KEY_LEN); + + } +#endif + break; + case DEVICE_INFO_TYPE_BOUND: + +#if (!TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + if (tuya_ble_current_para.sys_settings.bound_flag != evt->device_info_data.data[0]) { + tuya_ble_current_para.sys_settings.bound_flag = evt->device_info_data.data[0]; + + tuya_ble_adv_change(); + current_connect_status = tuya_ble_connect_status_get(); + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { //0->1 + if (current_connect_status == UNBONDING_CONN) { + tuya_ble_connect_status_set(BONDING_CONN); + } else if (current_connect_status == UNBONDING_UNAUTH_CONN) { + tuya_ble_connect_status_set(BONDING_UNAUTH_CONN); + } else if (current_connect_status == UNBONDING_UNCONN) { + tuya_ble_connect_status_set(BONDING_UNCONN); + } else { + + } + + } else { //1->0 + if (current_connect_status == BONDING_CONN) { + tuya_ble_connect_status_set(UNBONDING_CONN); + } else if (current_connect_status == BONDING_UNAUTH_CONN) { + tuya_ble_connect_status_set(UNBONDING_UNAUTH_CONN); + } else if (current_connect_status == BONDING_UNCONN) { + tuya_ble_connect_status_set(UNBONDING_UNCONN); + } else { + + } + } + + event.evt = TUYA_BLE_CB_EVT_CONNECTE_STATUS; + event.connect_status = tuya_ble_connect_status_get(); + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya ble send cb event failed."); + } else { + TUYA_BLE_LOG_ERROR("tuya ble send cb event succeed."); + } + + } +#endif + break; + default: + break; + } + +} + + +void tuya_ble_handle_dp_data_reported_evt(tuya_ble_evt_param_t *evt) +{ + uint8_t encry_mode = 0; + if (tuya_ble_pair_rand_valid_get() == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_4; + } + tuya_ble_commData_send(FRM_STAT_REPORT, 0, evt->reported_data.p_data, evt->reported_data.data_len, encry_mode); + + if (evt->reported_data.p_data) { + tuya_ble_free(evt->reported_data.p_data); + } +} + +void tuya_ble_handle_dp_data_with_flag_reported_evt(tuya_ble_evt_param_t *evt) +{ + uint8_t encry_mode = 0; + if (tuya_ble_pair_rand_valid_get() == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_4; + } + + tuya_ble_commData_send(FRM_DATA_WITH_FLAG_REPORT, 0, evt->flag_reported_data.p_data, evt->flag_reported_data.data_len, encry_mode); + + if (evt->flag_reported_data.p_data) { + tuya_ble_free(evt->flag_reported_data.p_data); + } +} + +void tuya_ble_handle_dp_data_with_time_reported_evt(tuya_ble_evt_param_t *evt) +{ + uint8_t *data_buffer = NULL; + uint16_t data_len; + uint8_t encry_mode = 0; + + data_len = 5 + evt->reported_with_time_data.data_len; + + data_buffer = (uint8_t *)tuya_ble_malloc(data_len); + if (data_buffer == NULL) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_with_time_reported_evt malloc failed."); + if (evt->reported_with_time_data.p_data) { + tuya_ble_free(evt->reported_with_time_data.p_data); + } + return; + } else { + memset(data_buffer, 0, data_len); + } + + if (tuya_ble_pair_rand_valid_get() == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_4; + } + + data_buffer[0] = 1; + data_buffer[1] = evt->reported_with_time_data.timestamp >> 24; + data_buffer[2] = evt->reported_with_time_data.timestamp >> 16; + data_buffer[3] = evt->reported_with_time_data.timestamp >> 8; + data_buffer[4] = evt->reported_with_time_data.timestamp; + + memcpy(&data_buffer[5], evt->reported_with_time_data.p_data, evt->reported_with_time_data.data_len); + + tuya_ble_commData_send(FRM_STAT_WITH_TIME_REPORT, 0, data_buffer, data_len, encry_mode); + + tuya_ble_free(data_buffer); + + if (evt->reported_with_time_data.p_data) { + tuya_ble_free(evt->reported_with_time_data.p_data); + } +} + +void tuya_ble_handle_dp_data_with_flag_and_time_reported_evt(tuya_ble_evt_param_t *evt) +{ + uint8_t *data_buffer = NULL; + uint16_t data_len; + uint8_t encry_mode = 0; + + data_len = 8 + evt->flag_reported_with_time_data.data_len; + + data_buffer = (uint8_t *)tuya_ble_malloc(data_len); + if (data_buffer == NULL) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_with_flag_and_time_reported_evt malloc failed."); + if (evt->flag_reported_with_time_data.p_data) { + tuya_ble_free(evt->flag_reported_with_time_data.p_data); + } + return; + } else { + memset(data_buffer, 0, data_len); + } + + if (tuya_ble_pair_rand_valid_get() == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_4; + } + + data_buffer[0] = evt->flag_reported_with_time_data.sn >> 8; + data_buffer[1] = evt->flag_reported_with_time_data.sn; + data_buffer[2] = evt->flag_reported_with_time_data.mode; + data_buffer[3] = 1; + data_buffer[4] = evt->flag_reported_with_time_data.timestamp >> 24; + data_buffer[5] = evt->flag_reported_with_time_data.timestamp >> 16; + data_buffer[6] = evt->flag_reported_with_time_data.timestamp >> 8; + data_buffer[7] = evt->flag_reported_with_time_data.timestamp; + + memcpy(&data_buffer[8], evt->flag_reported_with_time_data.p_data, evt->flag_reported_with_time_data.data_len); + + tuya_ble_commData_send(FRM_DATA_WITH_FLAG_AND_TIME_REPORT, 0, data_buffer, data_len, encry_mode); + + tuya_ble_free(data_buffer); + + if (evt->flag_reported_with_time_data.p_data) { + tuya_ble_free(evt->flag_reported_with_time_data.p_data); + } +} + +void tuya_ble_handle_dp_data_with_time_string_reported_evt(tuya_ble_evt_param_t *evt) +{ + uint8_t *data_buffer = NULL; + uint16_t data_len; + uint8_t encry_mode = 0; + + data_len = 14 + evt->reported_with_time_string_data.data_len; + + data_buffer = (uint8_t *)tuya_ble_malloc(data_len); + if (data_buffer == NULL) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_with_time_string_reported_evt malloc failed."); + if (evt->reported_with_time_string_data.p_data) { + tuya_ble_free(evt->reported_with_time_string_data.p_data); + } + return; + } else { + memset(data_buffer, 0, data_len); + } + + if (tuya_ble_pair_rand_valid_get() == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_4; + } + + data_buffer[0] = 0; + + memcpy(&data_buffer[1], evt->reported_with_time_string_data.time_string, 13); + + memcpy(&data_buffer[14], evt->reported_with_time_string_data.p_data, evt->reported_with_time_string_data.data_len); + + tuya_ble_commData_send(FRM_STAT_WITH_TIME_REPORT, 0, data_buffer, data_len, encry_mode); + + tuya_ble_free(data_buffer); + + if (evt->reported_with_time_string_data.p_data) { + tuya_ble_free(evt->reported_with_time_string_data.p_data); + } +} + +void tuya_ble_handle_dp_data_with_flag_and_time_string_reported_evt(tuya_ble_evt_param_t *evt) +{ + uint8_t *data_buffer = NULL; + uint16_t data_len; + uint8_t encry_mode = 0; + + data_len = 17 + evt->flag_reported_with_time_string_data.data_len; + + data_buffer = (uint8_t *)tuya_ble_malloc(data_len); + if (data_buffer == NULL) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_dp_data_with_flag_and_time_string_reported_evt malloc failed."); + if (evt->flag_reported_with_time_string_data.p_data) { + tuya_ble_free(evt->flag_reported_with_time_string_data.p_data); + } + return; + } else { + memset(data_buffer, 0, data_len); + } + + if (tuya_ble_pair_rand_valid_get() == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_4; + } + + data_buffer[0] = evt->flag_reported_with_time_string_data.sn >> 8; + data_buffer[1] = evt->flag_reported_with_time_string_data.sn; + data_buffer[2] = evt->flag_reported_with_time_string_data.mode; + data_buffer[3] = 0; + memcpy(&data_buffer[4], evt->flag_reported_with_time_string_data.time_string, 13); + + memcpy(&data_buffer[17], evt->flag_reported_with_time_string_data.p_data, evt->flag_reported_with_time_string_data.data_len); + + tuya_ble_commData_send(FRM_DATA_WITH_FLAG_AND_TIME_REPORT, 0, data_buffer, data_len, encry_mode); + + tuya_ble_free(data_buffer); + + if (evt->flag_reported_with_time_string_data.p_data) { + tuya_ble_free(evt->flag_reported_with_time_string_data.p_data); + } +} + + +void tuya_ble_handle_dp_data_send_evt(tuya_ble_evt_param_t *evt) +{ + uint8_t encry_mode = 0; + if (tuya_ble_pair_rand_valid_get() == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_4; + } + + tuya_ble_commData_send(FRM_DP_DATA_SEND_REQ, 0, evt->dp_send_data.p_data, evt->dp_send_data.data_len, encry_mode); + + if (evt->dp_send_data.p_data) { + tuya_ble_free(evt->dp_send_data.p_data); + } +} + +void tuya_ble_handle_dp_data_with_time_send_evt(tuya_ble_evt_param_t *evt) +{ + uint8_t encry_mode = 0; + + if (tuya_ble_pair_rand_valid_get() == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_4; + } + + tuya_ble_commData_send(FRM_DP_DATA_WITH_TIME_SEND_REQ, 0, evt->dp_with_time_send_data.p_data, evt->dp_with_time_send_data.data_len, encry_mode); + + if (evt->dp_with_time_send_data.p_data) { + tuya_ble_free(evt->dp_with_time_send_data.p_data); + } +} + + +void tuya_ble_handle_device_unbind_evt(tuya_ble_evt_param_t *evt) +{ + tuya_ble_cb_evt_param_t event; + + tuya_ble_device_unbond(); + + event.evt = TUYA_BLE_CB_EVT_CONNECTE_STATUS; + event.connect_status = tuya_ble_connect_status_get(); + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_factory_reset_evt-tuya ble send cb event (connect status update) failed."); + } else { + + } + + event.evt = TUYA_BLE_CB_EVT_UNBIND_RESET_RESPONSE; + event.reset_response_data.type = RESET_TYPE_UNBIND; + event.reset_response_data.status = 0; + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_device_unbind_evt-tuya ble send cb event (TUYA_BLE_CB_EVT_UNBIND_RESET_RESPONSE) failed."); + } else { + + } + +} + + +void tuya_ble_handle_factory_reset_evt(tuya_ble_evt_param_t *evt) +{ + tuya_ble_cb_evt_param_t event; + + memset(tuya_ble_current_para.sys_settings.device_virtual_id, 0, DEVICE_VIRTUAL_ID_LEN); + tuya_ble_device_unbond(); + + event.evt = TUYA_BLE_CB_EVT_CONNECTE_STATUS; + event.connect_status = tuya_ble_connect_status_get(); + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_factory_reset_evt-tuya ble send cb event (connect status update) failed."); + } else { + + } + + event.evt = TUYA_BLE_CB_EVT_UNBIND_RESET_RESPONSE; + event.reset_response_data.type = RESET_TYPE_FACTORY_RESET; + event.reset_response_data.status = 0; + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_factory_reset_evt-tuya ble send cb event (TUYA_BLE_CB_EVT_UNBIND_RESET_RESPONSE) failed."); + } else { + + } + +} + + +void tuya_ble_handle_ota_response_evt(tuya_ble_evt_param_t *evt) +{ + uint16_t ota_cmd_type = 0; + + uint8_t encry_mode = 0; + if (tuya_ble_pair_rand_valid_get() == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_4; + } + + switch (evt->ota_response_data.type) { + case TUYA_BLE_OTA_REQ: + ota_cmd_type = FRM_OTA_START_REQ; + break; + case TUYA_BLE_OTA_FILE_INFO: + ota_cmd_type = FRM_OTA_FILE_INFOR_REQ; + break; + case TUYA_BLE_OTA_FILE_OFFSET_REQ : + ota_cmd_type = FRM_OTA_FILE_OFFSET_REQ; + break; + case TUYA_BLE_OTA_DATA : + ota_cmd_type = FRM_OTA_DATA_REQ; + break; + case TUYA_BLE_OTA_END : + ota_cmd_type = FRM_OTA_END_REQ; + break; + default: + break; + } + + if (ota_cmd_type != 0) { + tuya_ble_commData_send(ota_cmd_type, 0, evt->ota_response_data.p_data, evt->ota_response_data.data_len, encry_mode); + } + + if (evt->ota_response_data.p_data) { + tuya_ble_free(evt->ota_response_data.p_data); + } +} + + +void tuya_ble_handle_data_passthrough_evt(tuya_ble_evt_param_t *evt) +{ + uint8_t encry_mode = 0; + + if (tuya_ble_current_para.sys_settings.bound_flag) { + if (tuya_ble_pair_rand_valid_get() == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_4; + } + } else { + encry_mode = ENCRYPTION_MODE_KEY_2; + } + + tuya_ble_commData_send(FRM_DATA_PASSTHROUGH_REQ, 0, evt->passthrough_data.p_data, evt->passthrough_data.data_len, encry_mode); + + if (evt->passthrough_data.p_data) { + tuya_ble_free(evt->passthrough_data.p_data); + } +} + + +void tuya_ble_handle_data_prod_test_response_evt(tuya_ble_evt_param_t *evt) +{ + uint8_t encry_mode = 0; + tuya_ble_connect_status_t connect_status; + + if (evt->prod_test_res_data.channel == 0) { + tuya_ble_common_uart_send_data(evt->prod_test_res_data.p_data, evt->prod_test_res_data.data_len); + } else if (evt->prod_test_res_data.channel == 1) { + connect_status = tuya_ble_connect_status_get(); + if (connect_status == BONDING_CONN) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { +#if (TUYA_BLE_PROD_TEST_SUPPORT_ENCRYPTION != 0) + encry_mode = ENCRYPTION_MODE_FTM_KEY; +#else + encry_mode = ENCRYPTION_MODE_NONE; +#endif + } + + tuya_ble_commData_send(FRM_FACTORY_TEST_RESP, 0, evt->prod_test_res_data.p_data, evt->prod_test_res_data.data_len, encry_mode); + } + + if (evt->prod_test_res_data.p_data) { + tuya_ble_free(evt->prod_test_res_data.p_data); + } + +} + + +void tuya_ble_handle_uart_cmd_evt(tuya_ble_evt_param_t *evt) +{ + uint8_t sum; + uint8_t *uart_send_buffer; + uint16_t uart_send_len; + + TUYA_BLE_LOG_HEXDUMP_DEBUG("received uart cmd data", (uint8_t *)evt->uart_cmd_data.p_data, evt->uart_cmd_data.data_len); // + +#if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + + if (evt->uart_cmd_data.data_len > 0) { + sum = tuya_ble_check_sum(evt->uart_cmd_data.p_data, evt->uart_cmd_data.data_len - 1); + if (sum == evt->uart_cmd_data.p_data[evt->uart_cmd_data.data_len - 1]) { + + switch (evt->uart_cmd_data.p_data[0]) { + case 0x55: + tuya_ble_uart_common_process(evt->uart_cmd_data.p_data, evt->uart_cmd_data.data_len); + break; + case 0x66: + tuya_ble_app_production_test_process(0, evt->uart_cmd_data.p_data, evt->uart_cmd_data.data_len); + break; + default: + break; + }; + + } else { + TUYA_BLE_LOG_ERROR("uart receive data check_sum error , receive sum = 0x%02x ; cal sum = 0x%02x", evt->uart_cmd_data.p_data[evt->uart_cmd_data.data_len - 1], sum); + } + } + +#endif + + if (evt->uart_cmd_data.p_data) { + tuya_ble_free(evt->uart_cmd_data.p_data); + } +} + + +void tuya_ble_handle_ble_cmd_evt(tuya_ble_evt_param_t *evt) +{ + + tuya_ble_evt_process(evt->ble_cmd_data.cmd, evt->ble_cmd_data.p_data, evt->ble_cmd_data.data_len); + if (evt->ble_cmd_data.p_data) { + tuya_ble_free(evt->ble_cmd_data.p_data); + } +} + + +void tuya_ble_handle_net_config_response_evt(tuya_ble_evt_param_t *evt) +{ + uint8_t encry_mode = 0; + uint8_t data[2]; + + if (tuya_ble_pair_rand_valid_get() == 1) { + encry_mode = ENCRYPTION_MODE_KEY_2; + } else { + encry_mode = ENCRYPTION_MODE_KEY_1; + } + + + data[0] = ((int16_t)(evt->net_config_response_data.result_code)) >> 8; + data[1] = (int16_t)(evt->net_config_response_data.result_code); + + tuya_ble_commData_send(FRM_NET_CONFIG_RESPONSE_REPORT_REQ, 0, data, 2, encry_mode); + +} + + +void tuya_ble_handle_time_request_evt(tuya_ble_evt_param_t *evt) +{ + uint8_t encry_mode = 0; + uint16_t cmd; + if (tuya_ble_pair_rand_valid_get() == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_4; + } + + if (evt->time_req_data.time_type == 0) { + cmd = FRM_GET_UNIX_TIME_CHAR_MS_REQ; + } else if (evt->time_req_data.time_type == 1) { + cmd = FRM_GET_UNIX_TIME_CHAR_DATE_REQ; + } else if (evt->time_req_data.time_type == 2) { + cmd = FRM_GET_APP_LOCAL_TIME_REQ; + } else { + return; + } + + tuya_ble_commData_send(cmd, 0, NULL, 0, encry_mode); + +} + +void tuya_ble_handle_extend_time_request_evt(tuya_ble_evt_param_t *evt) +{ + uint8_t encry_mode = 0; + uint8_t data[1]; + + if (tuya_ble_pair_rand_valid_get() == 1) { + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + } else { + encry_mode = ENCRYPTION_MODE_KEY_4; + } + + data[0] = evt->extend_time_req_data.n_years_dst; + + tuya_ble_commData_send(FRM_GET_UNIX_TIME_WITH_DST_REQ, 0, data, 1, encry_mode); +} + + +void tuya_ble_handle_unbound_response_evt(tuya_ble_evt_param_t *evt) +{ +#if (!TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + uint8_t encry_mode = 0; + uint8_t result; + + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + + result = evt->ubound_res_data.result_code; + + tuya_ble_commData_send(FRM_UNBONDING_RESP, 0, &result, 1, encry_mode); +#else + return; +#endif +} + +void tuya_ble_handle_anomaly_unbound_response_evt(tuya_ble_evt_param_t *evt) +{ +#if (!TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + + uint8_t encry_mode = 0; + uint8_t result; + + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + + result = evt->anomaly_ubound_res_data.result_code; + + tuya_ble_commData_send(FRM_ANOMALY_UNBONDING_RESP, 0, &result, 1, encry_mode); + +#else + return; +#endif + +} + +void tuya_ble_handle_device_reset_response_evt(tuya_ble_evt_param_t *evt) +{ +#if (!TUYA_BLE_DEVICE_REGISTER_FROM_BLE) + uint8_t encry_mode = 0; + uint8_t result; + + encry_mode = ENCRYPTION_MODE_SESSION_KEY; + + result = evt->device_reset_res_data.result_code; + + tuya_ble_commData_send(FRM_DEVICE_RESET_RESP, 0, &result, 1, encry_mode); +#else + return; +#endif +} + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN >= 3) +void tuya_ble_handle_connecting_request_evt(tuya_ble_evt_param_t *evt) +{ + tuya_ble_connect_status_t currnet_connect_status; + currnet_connect_status = tuya_ble_connect_status_get(); + if ((currnet_connect_status != BONDING_UNCONN) && (currnet_connect_status != UNBONDING_UNCONN)) { + return; + } + if (evt->connecting_request_data.cmd == 0) { + tuya_ble_adv_change(); + } else { + tuya_ble_adv_change_with_connecting_request(); + } + +} +#endif + +extern void tuya_ble_connect_monitor_timer_start(void); +void tuya_ble_handle_connect_change_evt(tuya_ble_evt_param_t *evt) +{ + tuya_ble_cb_evt_param_t event; + uint8_t send_cb_flag = 1; + + if (evt->connect_change_evt == TUYA_BLE_CONNECTED) { + TUYA_BLE_LOG_INFO("Connected!"); + tuya_ble_reset_ble_sn(); + if (tuya_ble_current_para.sys_settings.bound_flag != 1) { + tuya_ble_connect_status_set(UNBONDING_UNAUTH_CONN); + } else { + tuya_ble_connect_status_set(BONDING_UNAUTH_CONN); + } + + tuya_ble_connect_monitor_timer_start(); + +#if (TUYA_BLE_DEVICE_REGISTER_FROM_BLE&&TUYA_BLE_DEVICE_AUTH_DATA_STORE) + + tuya_ble_internal_production_test_with_ble_flag_clear(); + +#endif + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE==TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) + + tuya_ble_auth_data_reset(); + +#endif + +#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE + + tuya_ble_link_status_set(LINK_CONNECTED); + +#endif + + } else if (evt->connect_change_evt == TUYA_BLE_DISCONNECTED) { + TUYA_BLE_LOG_INFO("Disonnected"); + + tuya_ble_reset_ble_sn(); + + tuya_ble_pair_rand_clear(); + + tuya_ble_air_recv_packet_free(); + + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + tuya_ble_connect_status_set(BONDING_UNCONN); + } else { + tuya_ble_connect_status_set(UNBONDING_UNCONN); + } + +#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE + + tuya_ble_link_status_set(LINK_DISCONNECTED); + +#endif + + } else { + TUYA_BLE_LOG_WARNING("unknown connect_change_evt!"); + } + + if (send_cb_flag) { + event.evt = TUYA_BLE_CB_EVT_CONNECTE_STATUS; + event.connect_status = tuya_ble_connect_status_get(); + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya ble send cb event failed."); + } else { + TUYA_BLE_LOG_DEBUG("tuya ble send cb event succeed."); + } + + } + +} + + +void tuya_ble_handle_link_update_evt(tuya_ble_evt_param_t *evt) +{ +#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE + + if (evt->link_update_data.link_app_status == 1) { + tuya_ble_link_status_set(LINK_ENCRYPTED); + if (tuya_ble_connect_status_get() != BONDING_CONN) { + tuya_ble_connect_monitor_timer_stop(); + } + TUYA_BLE_LOG_DEBUG("link encrypted."); + } + +#endif +} + +void tuya_ble_handle_ble_data_evt(uint8_t *buf, uint16_t len) +{ + tuya_ble_commonData_rx_proc(buf, len); + if (len > 20) { + tuya_ble_free(buf); + } +} + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event_handler_weak.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event_handler_weak.c new file mode 100644 index 0000000..5a2cb5c --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event_handler_weak.c @@ -0,0 +1,193 @@ +/** + * \file tuya_ble_event_handler_weak.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" +#include "tuya_ble_event_handler.h" + + + +__TUYA_BLE_WEAK void tuya_ble_handle_device_info_update_evt(tuya_ble_evt_param_t *evt) +{ + +} + + +__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_reported_evt(tuya_ble_evt_param_t *evt) +{ + +} + + +__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_with_time_reported_evt(tuya_ble_evt_param_t *evt) +{ + +} + + +__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_with_time_string_reported_evt(tuya_ble_evt_param_t *evt) +{ + +} + +__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_with_flag_reported_evt(tuya_ble_evt_param_t *evt) +{ + +} + +__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_with_flag_and_time_reported_evt(tuya_ble_evt_param_t *evt) +{ + +} + +__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_with_flag_and_time_string_reported_evt(tuya_ble_evt_param_t *evt) +{ + +} + + +__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_send_evt(tuya_ble_evt_param_t *evt) +{ + +} + + +__TUYA_BLE_WEAK void tuya_ble_handle_dp_data_with_time_send_evt(tuya_ble_evt_param_t *evt) +{ + +} + + +__TUYA_BLE_WEAK void tuya_ble_handle_device_unbind_evt(tuya_ble_evt_param_t *evt) +{ + +} + + + +__TUYA_BLE_WEAK void tuya_ble_handle_factory_reset_evt(tuya_ble_evt_param_t *evt) +{ + +} + + +__TUYA_BLE_WEAK void tuya_ble_handle_ota_response_evt(tuya_ble_evt_param_t *evt) +{ + +} + +__TUYA_BLE_WEAK void tuya_ble_handle_bulk_data_evt(tuya_ble_evt_param_t *evt) +{ + +} + +__TUYA_BLE_WEAK void tuya_ble_handle_data_passthrough_evt(tuya_ble_evt_param_t *evt) +{ + +} + + +__TUYA_BLE_WEAK void tuya_ble_handle_data_prod_test_response_evt(tuya_ble_evt_param_t *evt) +{ + +} + + +__TUYA_BLE_WEAK void tuya_ble_handle_uart_cmd_evt(tuya_ble_evt_param_t *evt) +{ + +} + + +__TUYA_BLE_WEAK void tuya_ble_handle_ble_cmd_evt(tuya_ble_evt_param_t *evt) +{ + +} + + +__TUYA_BLE_WEAK void tuya_ble_handle_net_config_response_evt(tuya_ble_evt_param_t *evt) +{ + + +} + + +__TUYA_BLE_WEAK void tuya_ble_handle_time_request_evt(tuya_ble_evt_param_t *evt) +{ + + +} + + +__TUYA_BLE_WEAK void tuya_ble_handle_extend_time_request_evt(tuya_ble_evt_param_t *evt) +{ + + +} + + +__TUYA_BLE_WEAK void tuya_ble_handle_unbound_response_evt(tuya_ble_evt_param_t *evt) +{ + +} + +__TUYA_BLE_WEAK void tuya_ble_handle_anomaly_unbound_response_evt(tuya_ble_evt_param_t *evt) +{ + + +} + +__TUYA_BLE_WEAK void tuya_ble_handle_device_reset_response_evt(tuya_ble_evt_param_t *evt) +{ + +} + +__TUYA_BLE_WEAK void tuya_ble_handle_connect_change_evt(tuya_ble_evt_param_t *evt) +{ + + +} + +__TUYA_BLE_WEAK void tuya_ble_handle_connecting_request_evt(tuya_ble_evt_param_t *evt) +{ + +} + +__TUYA_BLE_WEAK void tuya_ble_handle_ble_data_evt(uint8_t *buf, uint16_t len) +{ + +} + +__TUYA_BLE_WEAK void tuya_ble_handle_link_update_evt(tuya_ble_evt_param_t *evt) +{ + +} + +__TUYA_BLE_WEAK void tuya_ble_handle_weather_data_request_evt(tuya_ble_evt_param_t *evt) +{ + +} + + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_feature_weather.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_feature_weather.c new file mode 100644 index 0000000..3c081ef --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_feature_weather.c @@ -0,0 +1,447 @@ +/** + * \file tuya_ble_feature_weather.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" +#include "tuya_ble_heap.h" +#include "tuya_ble_mem.h" +#include "tuya_ble_api.h" +#include "tuya_ble_port.h" +#include "tuya_ble_main.h" +#include "tuya_ble_internal_config.h" +#include "tuya_ble_feature_weather.h" +#include "tuya_ble_data_handler.h" +#include "tuya_ble_mutli_tsf_protocol.h" +#include "tuya_ble_utils.h" +#include "tuya_ble_secure.h" +#include "tuya_ble_main.h" +#include "tuya_ble_storage.h" +#include "tuya_ble_unix_time.h" +#include "tuya_ble_log.h" +#include "tuya_ble_gatt_send_queue.h" + +#if ( (TUYA_BLE_PROTOCOL_VERSION_HIGN==4) && (TUYA_BLE_FEATURE_WEATHER_ENABLE != 0) ) + +/**@brief Weather key string. */ +const char *weather_key[] = { + "w.temp", + "w.thigh", + "w.tlow", + "w.humidity", + "w.condition", + "w.pressure", + "w.realFeel", + "w.uvi", + "w.sunRise", + "w.sunSet", + "t.unix", + "t.local", + "w.windSpeed", + "w.windDir", + "w.windLevel", + "w.aqi", + "w.tips", + "w.rank", + "w.pm10", + "w.pm25", + "w.o3", + "w.no2", + "w.co", + "w.so2", + "w.conditionNum", + + "w.data.", //**< w.data.n, n rang from [1-7] +}; + +static tuya_ble_weather_location_type_t cur_req_weather_location_type; + +/** + * @brief Function for calculate weather key max string length + * + * @return The max string len + * + * */ +static uint16_t calc_weather_key_max_string_len(void) +{ + int i, string_array_element = sizeof(weather_key) / sizeof(weather_key[0]); + uint16_t string_len = 0, tmp; + + for (i = 0; i < string_array_element; i++) { + tmp = strlen(weather_key[i]); + if (tmp > string_len) { + string_len = tmp; + } + } + + return string_len; +} + + +/** + * @brief Function for convert weather key to enum type + * + * @note For example input key "w.temp.0", convert type=WKT_TEMP day=1 + * + * @param[in] key The ponit of input weather key string + * @param[out] type Convert type + * @param[out] day The day of weather data, rang from [1-7], 1-means today + * + * @retval TUYA_BLE_ERR_INVALID_PARAM The provided Parameters are not valid. + * @retval TUYA_BLE_ERR_NOT_FOUND No corresponding key was found. + * @retval TUYA_BLE_SUCCESS Successful. + * + * */ +static tuya_ble_status_t weather_key_string_to_enum_type(char *key, uint8_t key_str_len, tuya_ble_weather_key_type_t *type, uint8_t *day) +{ + int i, string_array_element; + + if (key == NULL) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + + string_array_element = sizeof(weather_key) / sizeof(weather_key[0]); + for (i = 0; i < string_array_element; i++) { + if ((strncmp(key, weather_key[i], strlen(weather_key[i])) == 0) && \ + (key_str_len <= (strlen(weather_key[i]) + 2))) { + if (type != NULL) { + *type = (tuya_ble_weather_key_type_t)(1 << i); + } + + if (day != NULL) { + if (key_str_len > strlen(weather_key[i])) { + /* key.n */ + *day = key[strlen(weather_key[i]) + 1] - '0' + 1; + } else { + /* only today */ + *day = 1; + } + } + + return TUYA_BLE_SUCCESS; + } + } + + return TUYA_BLE_ERR_NOT_FOUND; +} + + +tuya_ble_status_t tuya_ble_feature_weather_key_enum_type_to_string(tuya_ble_weather_key_type_t type, char *key) +{ + int bit; + + if (type >= WKT_COMBINE_BITMAP_MAXVAL || key == NULL) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + + /* Convert to actual weather key string based on type */ + for (bit = 0; bit < SUPPORT_WEATHER_KEY_TYPE_MAX_NUMS; bit++) { + if (((type >> bit) & 0x01) == 0x01) { + memcpy(key, weather_key[bit], strlen(weather_key[bit])); + return TUYA_BLE_SUCCESS; + } + } + + return TUYA_BLE_ERR_NOT_FOUND; +} + + +/** + * @brief Function for parse weather lktlv format data + * + * @param[in] recv_data The point of input data + * @param[in] recv_len The length of input data + * + * @retval TUYA_BLE_ERR_INVALID_PARAM The provided Parameters are not valid. + * @retval TUYA_BLE_SUCCESS Successful. + * + * */ +static tuya_ble_status_t weather_data_lktlv_parse(uint8_t *in, uint16_t in_len, uint8_t *out, uint16_t *out_len, uint16_t *object_nums) +{ + uint8_t key_len, value_len, n_day; + uint16_t object_len = 0; + + tuya_ble_weather_key_type_t weather_type; + tuya_ble_weather_value_type_t value_type; + tuya_ble_wd_object_t *object; + uint16_t tmp_out_len = 0, tmp_object_nums = 0; + + if (in == NULL || in_len == 0 || out == NULL || out_len == NULL || object_nums == NULL) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + + /*------------------------------------------------------------------------- + | 1byte | key_len | 1byte | 1byte | value_len | + | key_len | key | value_type | value_len | value | + ---------------------------------------------------------------------------*/ + for (;;) { + key_len = in[0 + object_len]; + value_type = in[1 + key_len + object_len]; + value_len = in[2 + key_len + object_len]; + + if (weather_key_string_to_enum_type((char *)&in[1 + object_len], key_len, &weather_type, &n_day) != TUYA_BLE_SUCCESS) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + + TUYA_BLE_LOG_DEBUG("parse weather data, n_day=[%d] type=[0x%08x] val_type=[%d] ,", n_day, weather_type, value_type); + TUYA_BLE_LOG_HEXDUMP_DEBUG("value :", &in[3 + key_len + object_len], value_len); + + /* Convert lktlv format to tuya_ble_wd_object */ + object = (tuya_ble_wd_object_t *)tuya_ble_malloc(sizeof(tuya_ble_wd_object_t) + value_len); + if (object == NULL) { + return TUYA_BLE_ERR_NO_MEM; + } + + object->n_day = n_day; + object->key_type = weather_type; + object->val_type = value_type; + object->value_len = value_len; + memcpy(&(object->vaule), &in[3 + key_len + object_len], value_len); + + memcpy(&out[tmp_out_len], object, (sizeof(tuya_ble_wd_object_t) + value_len)); + tmp_out_len += (sizeof(tuya_ble_wd_object_t) + value_len); + tuya_ble_free((uint8_t *)object); + + tmp_object_nums += 1; + object_len += (key_len + value_len + 3); + if (object_len >= in_len) { + *out_len = tmp_out_len; + *object_nums = tmp_object_nums; + break; + } + } + + TUYA_BLE_LOG_DEBUG("parse weather data finish, total count=[%d]", tmp_object_nums); + return TUYA_BLE_SUCCESS; +} + + +tuya_ble_status_t tuya_ble_feature_weather_data_request_with_location(tuya_ble_weather_location_type_t location_type, uint32_t combine_type, uint8_t n_days) +{ + tuya_ble_evt_param_t event; + uint8_t *ble_evt_buffer = NULL; + uint16_t ble_evt_buffer_len = 0; + uint16_t per_weather_key_malloc_size, weather_key_len; + int bit, count; + + if ((location_type >= WLT_MAX) || (location_type == WLT_CUSTOM_LOCATION)) { + TUYA_BLE_LOG_ERROR("request weather location type this sdk version unsupport"); + return TUYA_BLE_ERR_INVALID_PARAM; + } + + if (combine_type >= WKT_COMBINE_BITMAP_MAXVAL || n_days < 1 || n_days > 7) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + + /* Calc total bit1 counters */ + count = tuya_ble_count_bits((uint32_t)(combine_type)); + if (0 == count) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + + /* Malloc data buffer */ + count += 1; // add w.data.n + per_weather_key_malloc_size = (calc_weather_key_max_string_len() + 4); + ble_evt_buffer = (uint8_t *)tuya_ble_malloc(2 + per_weather_key_malloc_size * count); + if (ble_evt_buffer == NULL) { + return TUYA_BLE_ERR_NO_MEM; + } + + /* Fill version & location info */ + cur_req_weather_location_type = location_type; + + ble_evt_buffer[0] = 0; + ble_evt_buffer[1] = (uint8_t)(location_type); + ble_evt_buffer_len += 2; + + /* Convert to actual weather key based on type */ + for (bit = 0; bit < SUPPORT_WEATHER_KEY_TYPE_MAX_NUMS; bit++) { + if (((combine_type >> bit) & 0x01) == 0x01) { + /* Weather data format: [len + key] */ + weather_key_len = strlen(weather_key[bit]); + ble_evt_buffer[ble_evt_buffer_len] = weather_key_len; + memcpy(&ble_evt_buffer[ble_evt_buffer_len + 1], weather_key[bit], weather_key_len); + + ble_evt_buffer_len += (1 + weather_key_len); + } + } + + /* Fill request n_days */ + weather_key_len = sprintf((char *)&ble_evt_buffer[ble_evt_buffer_len + 1], "w.date.%d", n_days); + ble_evt_buffer[ble_evt_buffer_len] = weather_key_len; + ble_evt_buffer_len += (1 + weather_key_len); + + TUYA_BLE_LOG_DEBUG("request weather location=[%d] type=[0x%x], n_days=[%d]", location_type, combine_type, n_days); + TUYA_BLE_LOG_HEXDUMP_DEBUG("request weather data :", ble_evt_buffer, ble_evt_buffer_len); + + event.hdr.event = TUYA_BLE_EVT_WEATHER_DATA_REQ; + event.weather_req_data.p_data = ble_evt_buffer; + event.weather_req_data.data_len = ble_evt_buffer_len; + + if (tuya_ble_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_event_send weather req data error"); + tuya_ble_free(ble_evt_buffer); + return TUYA_BLE_ERR_NO_EVENT; + } + + return TUYA_BLE_SUCCESS; +} + + +tuya_ble_status_t tuya_ble_feature_weather_data_request(uint32_t combine_type, uint8_t n_days) +{ + return tuya_ble_feature_weather_data_request_with_location(WLT_APP_CURRENT_LOCATION, combine_type, n_days); +} + + +void tuya_ble_handle_weather_data_request_evt(tuya_ble_evt_param_t *evt) +{ + uint8_t encry_mode = 0; + + encry_mode = (tuya_ble_pair_rand_valid_get()) ? (ENCRYPTION_MODE_SESSION_KEY) : (ENCRYPTION_MODE_KEY_4); + + tuya_ble_commData_send(FRM_WEATHER_DATA_REQUEST, 0, evt->weather_req_data.p_data, evt->weather_req_data.data_len, encry_mode); + + if (evt->weather_req_data.p_data) { + tuya_ble_free(evt->weather_req_data.p_data); + } +} + + +void tuya_ble_handle_weather_data_request_response(uint8_t *recv_data, uint16_t recv_len) +{ + tuya_ble_cb_evt_param_t event; + uint16_t data_len = recv_data[11] << 8 | recv_data[12]; + + if (data_len != 1) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_weather_data_request_response- invalid data len received."); + return; + } + + event.evt = TUYA_BLE_CB_EVT_WEATHER_DATA_REQ_RESPONSE; + event.weather_req_response_data.status = recv_data[13]; + + if (tuya_ble_cb_event_send(&event) != 0) { + TUYA_BLE_LOG_ERROR("tuya_ble_handle_weather_data_request_response-tuya ble send cb event failed."); + } else { + + } +} + + +void tuya_ble_handle_weather_data_received(uint8_t *recv_data, uint16_t recv_len) +{ + uint8_t p_buf[1]; + uint16_t data_len = 0; + uint32_t ack_sn = 0; + tuya_ble_cb_evt_param_t event; + uint16_t weather_data_start_pos, weather_data_len; + uint16_t buffer_len, object_count; + + ack_sn = recv_data[1] << 24; + ack_sn += recv_data[2] << 16; + ack_sn += recv_data[3] << 8; + ack_sn += recv_data[4]; + + data_len = (recv_data[11] << 8) | recv_data[12]; + + if ((data_len < 5) || (data_len > TUYA_BLE_RECEIVE_MAX_DATA_LEN)) { + TUYA_BLE_LOG_ERROR("cmd weather data write error,receive data len == %d", data_len); + p_buf[0] = 0x01; + tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY); + return; + } else if (recv_data[13] != 0x00) { + TUYA_BLE_LOG_ERROR("cmd weather data write error, version not support"); + p_buf[0] = 0x01; + tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY); + return; + } else if ((recv_data[14] >= WLT_MAX) || (recv_data[14] == WLT_CUSTOM_LOCATION)) { + TUYA_BLE_LOG_ERROR("cmd weather data write error, location type this sdk version unsupport"); + p_buf[0] = 0x01; + tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY); + return; + } else if (recv_data[14] != cur_req_weather_location_type) { + TUYA_BLE_LOG_ERROR("cmd weather data write error, location type no correspondence"); + p_buf[0] = 0x01; + tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY); + return; + } + + TUYA_BLE_LOG_HEXDUMP_DEBUG("cmd weather data write : ", recv_data + 13, data_len); + + /* parse location info */ + weather_data_start_pos = 15; + weather_data_len = (data_len - 2); + + uint8_t *ble_cb_evt_buffer = (uint8_t *)tuya_ble_malloc(weather_data_len); + if (ble_cb_evt_buffer == NULL) { + TUYA_BLE_LOG_ERROR("ble_cb_evt_buffer malloc failed."); + p_buf[0] = 0x01; + tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY); + return; + } + + if (weather_data_lktlv_parse(&recv_data[weather_data_start_pos], weather_data_len, ble_cb_evt_buffer, &buffer_len, &object_count) != TUYA_BLE_SUCCESS) { + tuya_ble_free(ble_cb_evt_buffer); + + TUYA_BLE_LOG_ERROR("cmd weather data parse failed"); + p_buf[0] = 0x01; + tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY); + return; + } + + event.evt = TUYA_BLE_CB_EVT_WEATHER_DATA_RECEIVED; + event.weather_received_data.object_count = object_count; + event.weather_received_data.location = recv_data[14]; + event.weather_received_data.p_data = ble_cb_evt_buffer; + event.weather_received_data.data_len = buffer_len; + + if (tuya_ble_cb_event_send(&event) != 0) { + tuya_ble_free(ble_cb_evt_buffer); + TUYA_BLE_LOG_ERROR("tuya_ble_handle_weather_data_received-tuya ble send cb event failed."); + + p_buf[0] = 0x01; + tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY); + } else { + p_buf[0] = 0x00; + tuya_ble_commData_send(FRM_WEATHER_DATA_RECEIVED_RESP, ack_sn, p_buf, 1, ENCRYPTION_MODE_SESSION_KEY); + } +} + +#else + +void tuya_ble_handle_weather_data_request_evt(tuya_ble_evt_param_t *evt) +{ + +} + +void tuya_ble_handle_weather_data_request_response(uint8_t *recv_data, uint16_t recv_len) +{ + +} + +void tuya_ble_handle_weather_data_received(uint8_t *recv_data, uint16_t recv_len) +{ + +} + +#endif diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_gatt_send_queue.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_gatt_send_queue.c new file mode 100644 index 0000000..0646711 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_gatt_send_queue.c @@ -0,0 +1,125 @@ +/** + * \file tuya_ble_gatt_send_queue.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_gatt_send_queue.h" +#include "tuya_ble_type.h" +#include "tuya_ble_config.h" +#include "tuya_ble_port.h" +#include "tuya_ble_mem.h" +#include "tuya_ble_main.h" +#include "tuya_ble_log.h" + +static tuya_ble_queue_t gatt_send_queue; +static tuya_ble_gatt_send_data_t send_buf[TUYA_BLE_GATT_SEND_DATA_QUEUE_SIZE]; + +static volatile uint8_t gatt_queue_flag = 0; + +void tuya_ble_gatt_send_queue_init(void) +{ + gatt_queue_flag = 0; + tuya_ble_queue_init(&gatt_send_queue, (void *) send_buf, TUYA_BLE_GATT_SEND_DATA_QUEUE_SIZE, sizeof(tuya_ble_gatt_send_data_t)); +} + +static void tuya_ble_gatt_send_queue_free(void) +{ + tuya_ble_gatt_send_data_t data = {0}; + memset(&data, 0, sizeof(tuya_ble_gatt_send_data_t)); + while (tuya_ble_dequeue(&gatt_send_queue, &data) == TUYA_BLE_SUCCESS) { + if (data.buf) { + tuya_ble_free(data.buf); + } + memset(&data, 0, sizeof(tuya_ble_gatt_send_data_t)); + } + TUYA_BLE_LOG_DEBUG("tuya_ble_gatt_send_queue_free execute."); +} + +void tuya_ble_gatt_send_data_handle(void *evt) +{ + tuya_ble_gatt_send_data_t data = {0}; + tuya_ble_evt_param_t event; + tuya_ble_connect_status_t currnet_connect_status; + + while (tuya_ble_queue_get(&gatt_send_queue, &data) == TUYA_BLE_SUCCESS) { + currnet_connect_status = tuya_ble_connect_status_get(); + if ((currnet_connect_status == BONDING_UNCONN) || (currnet_connect_status == UNBONDING_UNCONN)) { + tuya_ble_gatt_send_queue_free(); + break; + } + + if (tuya_ble_gatt_send_data(data.buf, data.size) == TUYA_BLE_SUCCESS) { + tuya_ble_free(data.buf); + tuya_ble_queue_decrease(&gatt_send_queue); + } else { + event.hdr.event = TUYA_BLE_EVT_GATT_SEND_DATA; + event.hdr.event_handler = tuya_ble_gatt_send_data_handle; + if (tuya_ble_event_send(&event) != 0) { + tuya_ble_gatt_send_queue_free(); + TUYA_BLE_LOG_ERROR("TUYA_BLE_EVT_GATT_SEND_DATA error."); + } + + break; + + } + } + if (tuya_ble_get_queue_used(&gatt_send_queue) == 0) { + tuya_ble_queue_flush(&gatt_send_queue); + gatt_queue_flag = 0; + } + +} + + + +tuya_ble_status_t tuya_ble_gatt_send_data_enqueue(uint8_t *p_data, uint8_t data_len) +{ + tuya_ble_gatt_send_data_t data = {0}; + + data.buf = tuya_ble_malloc(data_len); + + if (data.buf) { + memcpy(data.buf, p_data, data_len); + data.size = data_len; + if (tuya_ble_enqueue(&gatt_send_queue, &data) == TUYA_BLE_SUCCESS) { + if (gatt_queue_flag == 0) { + gatt_queue_flag = 1; + tuya_ble_gatt_send_data_handle(NULL); + } + return TUYA_BLE_SUCCESS; + } else { + tuya_ble_free(data.buf); + return TUYA_BLE_ERR_NO_MEM; + } + } else { + return TUYA_BLE_ERR_NO_MEM; + } + +} + +uint32_t tuya_ble_get_gatt_send_queue_used(void) +{ + return tuya_ble_get_queue_used(&gatt_send_queue); +} + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_heap.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_heap.c new file mode 100644 index 0000000..d4c475d --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_heap.c @@ -0,0 +1,366 @@ +/* + * FreeRTOS Kernel V10.0.0 + * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. If you wish to use our Amazon + * FreeRTOS name, please do so in a fair use way that does not cause confusion. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ +#include "tuya_ble_stdlib.h" +#include "tuya_ble_heap.h" +#include "tuya_ble_port.h" +#include "tuya_ble_internal_config.h" + +#if (TUYA_BLE_USE_PLATFORM_MEMORY_HEAP==0) + +/* Block sizes must not get too small. */ +#define heapMINIMUM_BLOCK_SIZE ( ( uint32_t ) ( xHeapStructSize << 1 ) ) + +/* Assumes 8bit bytes! */ +#define heapBITS_PER_BYTE ( ( uint32_t ) 8 ) + +static uint8_t ucHeap[ TUYA_BLE_TOTAL_HEAP_SIZE ]; + + +/* Define the linked list structure. This is used to link free blocks in order +of their memory address. */ +typedef struct A_BLOCK_LINK { + struct A_BLOCK_LINK *pxNextFreeBlock; /*<< The next free block in the list. */ + uint32_t xBlockSize; /*<< The size of the free block. */ +} BlockLink_t; + +/*-----------------------------------------------------------*/ + +/* + * Inserts a block of memory that is being freed into the correct position in + * the list of free memory blocks. The block being freed will be merged with + * the block in front it and/or the block behind it if the memory blocks are + * adjacent to each other. + */ +static void prvInsertBlockIntoFreeList(BlockLink_t *pxBlockToInsert); + +/* + * Called automatically to setup the required heap structures the first time + * pvPortMalloc() is called. + */ +static void prvHeapInit(void); + +/*-----------------------------------------------------------*/ + +/* The size of the structure placed at the beginning of each allocated memory +block must by correctly byte aligned. */ +static const uint32_t xHeapStructSize = (sizeof(BlockLink_t) + ((uint32_t)(portBYTE_ALIGNMENT - 1))) & ~((uint32_t) portBYTE_ALIGNMENT_MASK); + +/* Create a couple of list links to mark the start and end of the list. */ +static BlockLink_t xStart, *pxEnd = NULL; + +/* Keeps track of the number of free bytes remaining, but says nothing about +fragmentation. */ +static uint32_t xFreeBytesRemaining = 0U; +static uint32_t xMinimumEverFreeBytesRemaining = 0U; + +/* Gets set to the top bit of an size_t type. When this bit in the xBlockSize +member of an BlockLink_t structure is set then the block belongs to the +application. When the bit is free the block is still part of the free heap +space. */ +static uint32_t xBlockAllocatedBit = 0; + +/*-----------------------------------------------------------*/ + +void *pvTuyaPortMalloc(uint32_t xWantedSize) +{ + BlockLink_t *pxBlock, *pxPreviousBlock, *pxNewBlockLink; + void *pvReturn = NULL; + + tuya_ble_device_enter_critical(); + { + /* If this is the first call to malloc then the heap will require + initialisation to setup the list of free blocks. */ + if (pxEnd == NULL) { + prvHeapInit(); + } else { + tuyaCOVERAGE_TEST_MARKER(); + } + + /* Check the requested block size is not so large that the top bit is + set. The top bit of the block size member of the BlockLink_t structure + is used to determine who owns the block - the application or the + kernel, so it must be free. */ + if ((xWantedSize & xBlockAllocatedBit) == 0) { + /* The wanted size is increased so it can contain a BlockLink_t + structure in addition to the requested amount of bytes. */ + if (xWantedSize > 0) { + xWantedSize += xHeapStructSize; + + /* Ensure that blocks are always aligned to the required number + of bytes. */ + if ((xWantedSize & portBYTE_ALIGNMENT_MASK) != 0x00) { + /* Byte alignment required. */ + xWantedSize += (portBYTE_ALIGNMENT - (xWantedSize & portBYTE_ALIGNMENT_MASK)); + tuyaASSERT((xWantedSize & portBYTE_ALIGNMENT_MASK) == 0); + } else { + tuyaCOVERAGE_TEST_MARKER(); + } + } else { + tuyaCOVERAGE_TEST_MARKER(); + } + + if ((xWantedSize > 0) && (xWantedSize <= xFreeBytesRemaining)) { + /* Traverse the list from the start (lowest address) block until + one of adequate size is found. */ + pxPreviousBlock = &xStart; + pxBlock = xStart.pxNextFreeBlock; + while ((pxBlock->xBlockSize < xWantedSize) && (pxBlock->pxNextFreeBlock != NULL)) { + pxPreviousBlock = pxBlock; + pxBlock = pxBlock->pxNextFreeBlock; + } + + /* If the end marker was reached then a block of adequate size + was not found. */ + if (pxBlock != pxEnd) { + /* Return the memory space pointed to - jumping over the + BlockLink_t structure at its start. */ + pvReturn = (void *)(((uint8_t *) pxPreviousBlock->pxNextFreeBlock) + xHeapStructSize); + + /* This block is being returned for use so must be taken out + of the list of free blocks. */ + pxPreviousBlock->pxNextFreeBlock = pxBlock->pxNextFreeBlock; + + /* If the block is larger than required it can be split into + two. */ + if ((pxBlock->xBlockSize - xWantedSize) > heapMINIMUM_BLOCK_SIZE) { + /* This block is to be split into two. Create a new + block following the number of bytes requested. The void + cast is used to prevent byte alignment warnings from the + compiler. */ + pxNewBlockLink = (void *)(((uint8_t *) pxBlock) + xWantedSize); + tuyaASSERT((((uint32_t) pxNewBlockLink) & portBYTE_ALIGNMENT_MASK) == 0); + + /* Calculate the sizes of two blocks split from the + single block. */ + pxNewBlockLink->xBlockSize = pxBlock->xBlockSize - xWantedSize; + pxBlock->xBlockSize = xWantedSize; + + /* Insert the new block into the list of free blocks. */ + prvInsertBlockIntoFreeList(pxNewBlockLink); + } else { + tuyaCOVERAGE_TEST_MARKER(); + } + + xFreeBytesRemaining -= pxBlock->xBlockSize; + + if (xFreeBytesRemaining < xMinimumEverFreeBytesRemaining) { + xMinimumEverFreeBytesRemaining = xFreeBytesRemaining; + } else { + tuyaCOVERAGE_TEST_MARKER(); + } + + /* The block is being returned - it is allocated and owned + by the application and has no "next" block. */ + pxBlock->xBlockSize |= xBlockAllocatedBit; + pxBlock->pxNextFreeBlock = NULL; + } else { + tuyaCOVERAGE_TEST_MARKER(); + } + } else { + tuyaCOVERAGE_TEST_MARKER(); + } + } else { + tuyaCOVERAGE_TEST_MARKER(); + } + + tuya_traceMALLOC(pvReturn, xWantedSize); + } + (void) tuya_ble_device_exit_critical(); + +#if( tuyaUSE_MALLOC_FAILED_HOOK == 1 ) + { + if (pvReturn == NULL) { + extern void vApplicationMallocFailedHook(void); + vApplicationMallocFailedHook(); + } else { + tuyaCOVERAGE_TEST_MARKER(); + } + } +#endif + + tuyaASSERT((((uint32_t) pvReturn) & (uint32_t) portBYTE_ALIGNMENT_MASK) == 0); + return pvReturn; +} +/*-----------------------------------------------------------*/ + +void vTuyaPortFree(void *pv) +{ + uint8_t *puc = (uint8_t *) pv; + BlockLink_t *pxLink; + + if (pv != NULL) { + /* The memory being freed will have an BlockLink_t structure immediately + before it. */ + puc -= xHeapStructSize; + + /* This casting is to keep the compiler from issuing warnings. */ + pxLink = (void *) puc; + + /* Check the block is actually allocated. */ + tuyaASSERT((pxLink->xBlockSize & xBlockAllocatedBit) != 0); + tuyaASSERT(pxLink->pxNextFreeBlock == NULL); + + if ((pxLink->xBlockSize & xBlockAllocatedBit) != 0) { + if (pxLink->pxNextFreeBlock == NULL) { + /* The block is being returned to the heap - it is no longer + allocated. */ + pxLink->xBlockSize &= ~xBlockAllocatedBit; + + tuya_ble_device_enter_critical(); + { + /* Add this block to the list of free blocks. */ + xFreeBytesRemaining += pxLink->xBlockSize; + tuya_traceFREE(pv, pxLink->xBlockSize); + prvInsertBlockIntoFreeList(((BlockLink_t *) pxLink)); + } + (void) tuya_ble_device_exit_critical(); + } else { + tuyaCOVERAGE_TEST_MARKER(); + } + } else { + tuyaCOVERAGE_TEST_MARKER(); + } + } +} +/*-----------------------------------------------------------*/ + +uint32_t xTuyaPortGetFreeHeapSize(void) +{ + return xFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +uint32_t xTuyaPortGetMinimumEverFreeHeapSize(void) +{ + return xMinimumEverFreeBytesRemaining; +} +/*-----------------------------------------------------------*/ + +void vTuyaPortInitialiseBlocks(void) +{ + /* This just exists to keep the linker quiet. */ +} +/*-----------------------------------------------------------*/ + +static void prvHeapInit(void) +{ + BlockLink_t *pxFirstFreeBlock; + uint8_t *pucAlignedHeap; + uint32_t uxAddress; + uint32_t xTotalHeapSize = TUYA_BLE_TOTAL_HEAP_SIZE; + + /* Ensure the heap starts on a correctly aligned boundary. */ + uxAddress = (uint32_t) ucHeap; + + if ((uxAddress & portBYTE_ALIGNMENT_MASK) != 0) { + uxAddress += (portBYTE_ALIGNMENT - 1); + uxAddress &= ~((uint32_t) portBYTE_ALIGNMENT_MASK); + xTotalHeapSize -= uxAddress - (uint32_t) ucHeap; + } + + pucAlignedHeap = (uint8_t *) uxAddress; + + /* xStart is used to hold a pointer to the first item in the list of free + blocks. The void cast is used to prevent compiler warnings. */ + xStart.pxNextFreeBlock = (void *) pucAlignedHeap; + xStart.xBlockSize = (uint32_t) 0; + + /* pxEnd is used to mark the end of the list of free blocks and is inserted + at the end of the heap space. */ + uxAddress = ((uint32_t) pucAlignedHeap) + xTotalHeapSize; + uxAddress -= xHeapStructSize; + uxAddress &= ~((uint32_t) portBYTE_ALIGNMENT_MASK); + pxEnd = (void *) uxAddress; + pxEnd->xBlockSize = 0; + pxEnd->pxNextFreeBlock = NULL; + + /* To start with there is a single free block that is sized to take up the + entire heap space, minus the space taken by pxEnd. */ + pxFirstFreeBlock = (void *) pucAlignedHeap; + pxFirstFreeBlock->xBlockSize = uxAddress - (uint32_t) pxFirstFreeBlock; + pxFirstFreeBlock->pxNextFreeBlock = pxEnd; + + /* Only one block exists - and it covers the entire usable heap space. */ + xMinimumEverFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; + xFreeBytesRemaining = pxFirstFreeBlock->xBlockSize; + + /* Work out the position of the top bit in a size_t variable. */ + xBlockAllocatedBit = ((uint32_t) 1) << ((sizeof(uint32_t) * heapBITS_PER_BYTE) - 1); +} +/*-----------------------------------------------------------*/ + +static void prvInsertBlockIntoFreeList(BlockLink_t *pxBlockToInsert) +{ + BlockLink_t *pxIterator; + uint8_t *puc; + + /* Iterate through the list until a block is found that has a higher address + than the block being inserted. */ + for (pxIterator = &xStart; pxIterator->pxNextFreeBlock < pxBlockToInsert; pxIterator = pxIterator->pxNextFreeBlock) { + /* Nothing to do here, just iterate to the right position. */ + } + + /* Do the block being inserted, and the block it is being inserted after + make a contiguous block of memory? */ + puc = (uint8_t *) pxIterator; + if ((puc + pxIterator->xBlockSize) == (uint8_t *) pxBlockToInsert) { + pxIterator->xBlockSize += pxBlockToInsert->xBlockSize; + pxBlockToInsert = pxIterator; + } else { + tuyaCOVERAGE_TEST_MARKER(); + } + + /* Do the block being inserted, and the block it is being inserted before + make a contiguous block of memory? */ + puc = (uint8_t *) pxBlockToInsert; + if ((puc + pxBlockToInsert->xBlockSize) == (uint8_t *) pxIterator->pxNextFreeBlock) { + if (pxIterator->pxNextFreeBlock != pxEnd) { + /* Form one big block from the two blocks. */ + pxBlockToInsert->xBlockSize += pxIterator->pxNextFreeBlock->xBlockSize; + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock->pxNextFreeBlock; + } else { + pxBlockToInsert->pxNextFreeBlock = pxEnd; + } + } else { + pxBlockToInsert->pxNextFreeBlock = pxIterator->pxNextFreeBlock; + } + + /* If the block being inserted plugged a gab, so was merged with the block + before and the block after, then it's pxNextFreeBlock pointer will have + already been set, and should not be set here as that would make it point + to itself. */ + if (pxIterator != pxBlockToInsert) { + pxIterator->pxNextFreeBlock = pxBlockToInsert; + } else { + tuyaCOVERAGE_TEST_MARKER(); + } +} + +#endif + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_main.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_main.c new file mode 100644 index 0000000..9cd1a19 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_main.c @@ -0,0 +1,910 @@ +/** + * \file tuya_ble_main.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" +#include "tuya_ble_heap.h" +#include "tuya_ble_mem.h" +#include "tuya_ble_api.h" +#include "tuya_ble_port.h" +#include "tuya_ble_main.h" +#include "tuya_ble_secure.h" +#include "tuya_ble_data_handler.h" +#include "tuya_ble_storage.h" +#include "tuya_ble_sdk_version.h" +#include "tuya_ble_event.h" +#include "tuya_ble_utils.h" +#include "tuya_ble_app_uart_common_handler.h" +#include "tuya_ble_app_production_test.h" +#include "tuya_ble_log.h" +#include "tuya_ble_internal_config.h" + +tuya_ble_parameters_settings_t tuya_ble_current_para; + + +static volatile tuya_ble_connect_status_t tuya_ble_connect_status = UNKNOW_STATUS; + +#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE +static volatile tuya_ble_link_status_t tuya_ble_link_status = LINK_UNKNOW_STATUS; +#endif + +#if TUYA_BLE_USE_OS + +uint32_t m_cb_queue_table[TUYA_BLE_MAX_CALLBACKS]; + +#else +tuya_ble_callback_t m_cb_table[TUYA_BLE_MAX_CALLBACKS]; +#endif + + +void tuya_ble_connect_status_set(tuya_ble_connect_status_t status) +{ + tuya_ble_device_enter_critical(); + tuya_ble_connect_status = status; + tuya_ble_device_exit_critical(); + +} + +tuya_ble_connect_status_t tuya_ble_connect_status_get(void) +{ + return tuya_ble_connect_status; +} + +#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE + +void tuya_ble_link_status_set(tuya_ble_link_status_t status) +{ + tuya_ble_device_enter_critical(); + tuya_ble_link_status = status; + tuya_ble_device_exit_critical(); +} + +tuya_ble_link_status_t tuya_ble_link_status_get(void) +{ + return tuya_ble_link_status; +} + +#endif + +tuya_ble_timer_t tuya_ble_xtimer_connect_monitor; + +#define tuya_ble_connect_monitor_timeout_ms 30000 + +static void tuya_ble_vtimer_conncet_monitor_callback(tuya_ble_timer_t timer) +{ + tuya_ble_connect_status_t connect_state = tuya_ble_connect_status_get(); + + if ((connect_state == UNBONDING_UNAUTH_CONN) || (connect_state == BONDING_UNAUTH_CONN)) { + TUYA_BLE_LOG_DEBUG("ble disconncet because monitor timer timeout."); + tuya_ble_gap_disconnect(); + } + +} + + +void tuya_ble_connect_monitor_timer_init(void) +{ + if (tuya_ble_timer_create(&tuya_ble_xtimer_connect_monitor, tuya_ble_connect_monitor_timeout_ms, TUYA_BLE_TIMER_SINGLE_SHOT, tuya_ble_vtimer_conncet_monitor_callback) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("tuya_ble_xtimer_connect_monitor creat failed"); + } + +} + + +void tuya_ble_connect_monitor_timer_start(void) +{ + if (tuya_ble_timer_start(tuya_ble_xtimer_connect_monitor) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("tuya_ble_xtimer_connect_monitor start failed"); + } + +} + + +void tuya_ble_connect_monitor_timer_stop(void) +{ + + if (tuya_ble_timer_stop(tuya_ble_xtimer_connect_monitor) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("tuya_ble_xtimer_connect_monitor start failed"); + } + +} + + +#if TUYA_BLE_USE_OS + +#if TUYA_BLE_SELF_BUILT_TASK +void *tuya_ble_task_handle; //!< APP Task handle +void *tuya_ble_queue_handle; //!< Event queue handle + +static void tuya_ble_main_task(void *p_param) +{ + tuya_ble_evt_param_t tuya_ble_evt; + uint32_t i = 0; + + while (true) { + if (tuya_ble_os_msg_queue_recv(tuya_ble_queue_handle, &tuya_ble_evt, 0xFFFFFFFF) == true) { + //printf("task event:%d", tuya_ble_evt.hdr.event); + tuya_ble_event_process(&tuya_ble_evt); + + } + + } + +} +#endif + +#else + +void tuya_ble_main_tasks_exec(void) +{ + tuya_sched_execute(); +} +#endif + + + + +void tuya_ble_event_init(void) +{ +#if TUYA_BLE_USE_OS + +#if TUYA_BLE_SELF_BUILT_TASK + tuya_ble_os_task_create(&tuya_ble_task_handle, "tuya", tuya_ble_main_task, 0, TUYA_BLE_TASK_STACK_SIZE, TUYA_BLE_TASK_PRIORITY); + tuya_ble_os_msg_queue_create(&tuya_ble_queue_handle, MAX_NUMBER_OF_TUYA_MESSAGE, sizeof(tuya_ble_evt_param_t)); +#endif + +#else + tuya_ble_event_queue_init(); +#endif + +#if TUYA_BLE_USE_OS + for (uint8_t i = 0; i < TUYA_BLE_MAX_CALLBACKS; i++) { + m_cb_queue_table[i] = 0; + } + +#else + for (uint8_t i = 0; i < TUYA_BLE_MAX_CALLBACKS; i++) { + m_cb_table[i] = NULL; + } +#endif + +} + + +uint8_t tuya_ble_event_send(tuya_ble_evt_param_t *evt) +{ +#if TUYA_BLE_USE_OS + +#if TUYA_BLE_SELF_BUILT_TASK + if (tuya_ble_os_msg_queue_send(tuya_ble_queue_handle, evt, 0)) { + return 0; + } else { + return 1; + } +#else + if (tuya_ble_event_queue_send_port(evt, 0)) { + return 0; + } else { + return 1; + } +#endif + +#else + if (tuya_ble_message_send(evt) == TUYA_BLE_SUCCESS) { + return 0; + } else { + return 1; + } +#endif +} + + +uint8_t tuya_ble_custom_event_send(tuya_ble_custom_evt_t evt) +{ + static tuya_ble_evt_param_t event; + uint8_t ret = 0; + +#if TUYA_BLE_USE_OS + event.hdr.event = TUYA_BLE_EVT_CUSTOM; + event.custom_evt = evt; + +#if TUYA_BLE_SELT_BUILT_TASK + if (tuya_ble_os_msg_queue_send(tuya_ble_queue_handle, &event, 0)) { + return 0; + } else { + return 1; + } +#else + if (tuya_ble_event_queue_send_port(&event, 0)) { + return 0; + } else { + return 1; + } +#endif + +#else + + event.hdr.event = TUYA_BLE_EVT_CUSTOM; + event.custom_evt = evt; + + if (tuya_ble_message_send(&event) == TUYA_BLE_SUCCESS) { + ret = 0; + } else { + ret = 1; + } + + return ret; +#endif +} + + + +tuya_ble_status_t tuya_ble_inter_event_response(tuya_ble_cb_evt_param_t *param) +{ + + switch (param->evt) { + case TUYA_BLE_CB_EVT_CONNECTE_STATUS: + break; + case TUYA_BLE_CB_EVT_DP_WRITE: + if (param->dp_write_data.p_data) { + tuya_ble_free(param->dp_write_data.p_data); + } + break; + case TUYA_BLE_CB_EVT_DP_DATA_RECEIVED: + if (param->dp_received_data.p_data) { + tuya_ble_free(param->dp_received_data.p_data); + } + break; + case TUYA_BLE_CB_EVT_DP_QUERY: + if (param->dp_query_data.p_data) { + tuya_ble_free(param->dp_query_data.p_data); + } + break; + case TUYA_BLE_CB_EVT_OTA_DATA: + if (param->ota_data.p_data) { + tuya_ble_free(param->ota_data.p_data); + } + break; + case TUYA_BLE_CB_EVT_NETWORK_INFO: + if (param->network_data.p_data) { + tuya_ble_free(param->network_data.p_data); + } + break; + case TUYA_BLE_CB_EVT_WIFI_SSID: + if (param->wifi_info_data.p_data) { + tuya_ble_free(param->wifi_info_data.p_data); + } + break; + case TUYA_BLE_CB_EVT_TIME_STAMP: + break; + case TUYA_BLE_CB_EVT_TIME_NORMAL: + break; + case TUYA_BLE_CB_EVT_APP_LOCAL_TIME_NORMAL: + break; + case TUYA_BLE_CB_EVT_TIME_STAMP_WITH_DST: + if (param->timestamp_with_dst_data.p_data) { + tuya_ble_free(param->timestamp_with_dst_data.p_data); + } + break; + case TUYA_BLE_CB_EVT_DATA_PASSTHROUGH: + + if (param->ble_passthrough_data.p_data) { + tuya_ble_free(param->ble_passthrough_data.p_data); + } + break; +#if (TUYA_BLE_FEATURE_WEATHER_ENABLE != 0) + case TUYA_BLE_CB_EVT_WEATHER_DATA_RECEIVED: + if (param->weather_received_data.p_data) { + tuya_ble_free(param->weather_received_data.p_data); + } + break; +#endif + default: + break; + } + + return TUYA_BLE_SUCCESS; +} + + + +uint8_t tuya_ble_cb_event_send(tuya_ble_cb_evt_param_t *evt) +{ +#if TUYA_BLE_USE_OS + if (m_cb_queue_table[0]) { + if (tuya_ble_os_msg_queue_send((void *)m_cb_queue_table[0], evt, 0)) { + return 0; + } else { + return 1; + } + } +#else + tuya_ble_callback_t fun; + if (m_cb_table[0]) { + fun = m_cb_table[0]; + fun(evt); + tuya_ble_inter_event_response(evt); + } +#endif + return 0; + +} + + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN==4) + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ + +#define TUYA_BLE_ADV_DATA_LEN_MAX 31 + +static const uint8_t adv_data_const[TUYA_BLE_ADV_DATA_LEN_MAX] = { + 0x02, + 0x01, + 0x06, + 0x03, + 0x02, + 0x50, 0xFD, + 0x17, + 0x16, + 0x50, 0xFD, + 0x41, 0x00, //Frame Control + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + + +#define TUYA_BLE_SCAN_RSP_DATA_LEN_MAX 31 +static const uint8_t scan_rsp_data_const[TUYA_BLE_SCAN_RSP_DATA_LEN_MAX] = { + 0x17, // length + 0xFF, + 0xD0, + 0x07, + 0x00, //Encry Mode(8) + 0x00, 0x00, //communication way bit0-mesh bit1-wifi bit2-zigbee bit3-NB + 0x00, //FLAG + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x03, //24 + 0x09, + 0x54, 0x59, +}; + +static uint8_t adv_data[TUYA_BLE_ADV_DATA_LEN_MAX]; +static uint8_t scan_rsp_data[TUYA_BLE_SCAN_RSP_DATA_LEN_MAX]; + +uint8_t tuya_ble_get_adv_connect_request_bit_status(void) +{ + return (adv_data[11] & 0x02); +} + +void tuya_ble_adv_change(void) +{ + uint8_t *aes_buf = NULL; + uint8_t *p_buf = NULL; + uint8_t adv_data_length = 0; + uint8_t scan_rsp_data_length = 0; + uint8_t aes_key[16]; + uint8_t encry_device_id[DEVICE_ID_LEN]; + + memcpy(adv_data, adv_data_const, TUYA_BLE_ADV_DATA_LEN_MAX); + memcpy(&scan_rsp_data, scan_rsp_data_const, TUYA_BLE_SCAN_RSP_DATA_LEN_MAX); + + adv_data[7] = 7 + tuya_ble_current_para.pid_len; + + adv_data[13] = tuya_ble_current_para.pid_type; + adv_data[14] = tuya_ble_current_para.pid_len; + + if (TUYA_BLE_DEVICE_SHARED) { + adv_data[11] |= 0x04 ; + } else { + adv_data[11] &= (~0x04); + } + + adv_data[11] &= (~0x02); //clear connect request bit + + + scan_rsp_data[4] = TUYA_BLE_SECURE_CONNECTION_TYPE; + + scan_rsp_data[5] = TUYA_BLE_DEVICE_COMMUNICATION_ABILITY >> 8; + scan_rsp_data[6] = TUYA_BLE_DEVICE_COMMUNICATION_ABILITY; + + if (tuya_ble_current_para.pid_len == 20) { + scan_rsp_data[7] |= 0x01 ; + } else { + scan_rsp_data[7] &= (~0x01); + } + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE==TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) + + if (TUYA_BLE_ADVANCED_ENCRYPTION_AUTH_ON_CONNECT) { + scan_rsp_data[7] |= 0x02 ; + } else { + scan_rsp_data[7] &= (~0x02); + } + +#endif + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + adv_data[11] |= 0x08 ; + // + memcpy(aes_key, tuya_ble_current_para.sys_settings.login_key, LOGIN_KEY_LEN); + memcpy(aes_key + LOGIN_KEY_LEN, tuya_ble_current_para.auth_settings.device_id, 16 - LOGIN_KEY_LEN); + + aes_buf = tuya_ble_malloc(200); + + if (aes_buf == NULL) { + TUYA_BLE_LOG_ERROR("Malloc failed for AES BUF in adv change."); + return; + } else { + memset(aes_buf, 0, 200); + } + + tuya_ble_encrypt_old_with_key(aes_key, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN, aes_buf); + + memcpy(&adv_data[15], (uint8_t *)(aes_buf + 1), tuya_ble_current_para.pid_len); + + tuya_ble_free(aes_buf); + + tuya_ble_device_id_encrypt_v4(&adv_data[11], adv_data[7] - 3, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN, encry_device_id); + + memcpy(&scan_rsp_data[8], encry_device_id, DEVICE_ID_LEN); + + } else { + adv_data[11] &= (~0x08); + + memcpy(&adv_data[15], tuya_ble_current_para.pid, tuya_ble_current_para.pid_len); + tuya_ble_device_id_encrypt_v4(&adv_data[11], adv_data[7] - 3, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN, encry_device_id); + + memcpy(&scan_rsp_data[8], encry_device_id, DEVICE_ID_LEN); + } + + if (tuya_ble_current_para.adv_local_name_len > TUYA_BLE_ADV_LOCAL_NAME_MAX_LEN) { + tuya_ble_current_para.adv_local_name_len = TUYA_BLE_ADV_LOCAL_NAME_MAX_LEN; + } + scan_rsp_data[24] = tuya_ble_current_para.adv_local_name_len + 1; + scan_rsp_data[25] = 0x09; + memcpy(&scan_rsp_data[26], tuya_ble_current_para.adv_local_name, tuya_ble_current_para.adv_local_name_len); + + TUYA_BLE_LOG_INFO("adv data changed ,current bound flag = %d", tuya_ble_current_para.sys_settings.bound_flag); + + adv_data_length = tuya_ble_current_para.pid_len + 15; + scan_rsp_data_length = tuya_ble_current_para.adv_local_name_len + 26; + + tuya_ble_gap_advertising_adv_data_update(adv_data, adv_data_length); + tuya_ble_gap_advertising_scan_rsp_data_update(scan_rsp_data, scan_rsp_data_length); + +#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE + + p_buf = tuya_ble_malloc(adv_data_length + scan_rsp_data_length + 3); + if (p_buf == NULL) { + TUYA_BLE_LOG_ERROR("Malloc failed for read buf in adv change."); + return; + } else { + memset(p_buf, 0, adv_data_length + scan_rsp_data_length + 3); + p_buf[0] = 0; + p_buf[1] = adv_data_length + scan_rsp_data_length; + memcpy(&p_buf[2], adv_data, adv_data_length); + memcpy(&p_buf[2 + adv_data_length], scan_rsp_data, scan_rsp_data_length); + } + + tuya_ble_device_info_characteristic_value_update(p_buf, (adv_data_length + scan_rsp_data_length + 3)); + + tuya_ble_free(p_buf); +#endif + +} + +void tuya_ble_adv_change_with_connecting_request(void) +{ + uint8_t *aes_buf = NULL; + uint8_t *p_buf = NULL; + uint8_t adv_data_length = 0; + uint8_t scan_rsp_data_length = 0; + uint8_t aes_key[16]; + uint8_t encry_device_id[DEVICE_ID_LEN]; + + memcpy(adv_data, adv_data_const, TUYA_BLE_ADV_DATA_LEN_MAX); + memcpy(&scan_rsp_data, scan_rsp_data_const, TUYA_BLE_SCAN_RSP_DATA_LEN_MAX); + + adv_data[7] = 7 + tuya_ble_current_para.pid_len; + + adv_data[13] = tuya_ble_current_para.pid_type; + adv_data[14] = tuya_ble_current_para.pid_len; + + if (TUYA_BLE_DEVICE_SHARED) { + adv_data[11] |= 0x04 ; + } else { + adv_data[11] &= (~0x04); + } + + adv_data[11] |= 0x02; //set connect request bit + + + scan_rsp_data[4] = TUYA_BLE_SECURE_CONNECTION_TYPE; + + scan_rsp_data[5] = TUYA_BLE_DEVICE_COMMUNICATION_ABILITY >> 8; + scan_rsp_data[6] = TUYA_BLE_DEVICE_COMMUNICATION_ABILITY; + + if (tuya_ble_current_para.pid_len == 20) { + scan_rsp_data[7] |= 0x01 ; + } else { + scan_rsp_data[7] &= (~0x01); + } + +#if (TUYA_BLE_SECURE_CONNECTION_TYPE==TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) + + if (TUYA_BLE_ADVANCED_ENCRYPTION_AUTH_ON_CONNECT) { + scan_rsp_data[7] |= 0x02 ; + } else { + scan_rsp_data[7] &= (~0x02); + } + +#endif + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + adv_data[11] |= 0x08 ; + // + memcpy(aes_key, tuya_ble_current_para.sys_settings.login_key, LOGIN_KEY_LEN); + memcpy(aes_key + LOGIN_KEY_LEN, tuya_ble_current_para.auth_settings.device_id, 16 - LOGIN_KEY_LEN); + + aes_buf = tuya_ble_malloc(200); + + if (aes_buf == NULL) { + TUYA_BLE_LOG_ERROR("Malloc failed for AES BUF in adv change with connecting request."); + return; + } else { + memset(aes_buf, 0, 200); + } + + tuya_ble_encrypt_old_with_key(aes_key, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN, aes_buf); + + memcpy(&adv_data[15], (uint8_t *)(aes_buf + 1), tuya_ble_current_para.pid_len); + + tuya_ble_free(aes_buf); + + tuya_ble_device_id_encrypt_v4(&adv_data[11], adv_data[7] - 3, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN, encry_device_id); + + memcpy(&scan_rsp_data[8], encry_device_id, DEVICE_ID_LEN); + + } else { + adv_data[11] &= (~0x08); + + memcpy(&adv_data[15], tuya_ble_current_para.pid, tuya_ble_current_para.pid_len); + tuya_ble_device_id_encrypt_v4(&adv_data[11], adv_data[7] - 3, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN, encry_device_id); + + memcpy(&scan_rsp_data[8], encry_device_id, DEVICE_ID_LEN); + } + + if (tuya_ble_current_para.adv_local_name_len > TUYA_BLE_ADV_LOCAL_NAME_MAX_LEN) { + tuya_ble_current_para.adv_local_name_len = TUYA_BLE_ADV_LOCAL_NAME_MAX_LEN; + } + scan_rsp_data[24] = tuya_ble_current_para.adv_local_name_len + 1; + scan_rsp_data[25] = 0x09; + memcpy(&scan_rsp_data[26], tuya_ble_current_para.adv_local_name, tuya_ble_current_para.adv_local_name_len); + + TUYA_BLE_LOG_INFO("adv data changed ,current bound flag = %d", tuya_ble_current_para.sys_settings.bound_flag); + + adv_data_length = tuya_ble_current_para.pid_len + 15; + scan_rsp_data_length = tuya_ble_current_para.adv_local_name_len + 26; + + tuya_ble_gap_advertising_adv_data_update(adv_data, adv_data_length); + tuya_ble_gap_advertising_scan_rsp_data_update(scan_rsp_data, scan_rsp_data_length); + +#if TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE + + p_buf = tuya_ble_malloc(adv_data_length + scan_rsp_data_length + 3); + if (p_buf == NULL) { + TUYA_BLE_LOG_ERROR("Malloc failed for read buf in adv change."); + return; + } else { + memset(p_buf, 0, adv_data_length + scan_rsp_data_length + 3); + p_buf[0] = 0; + p_buf[1] = adv_data_length + scan_rsp_data_length; + memcpy(&p_buf[2], adv_data, adv_data_length); + memcpy(&p_buf[2 + adv_data_length], scan_rsp_data, scan_rsp_data_length); + } + + tuya_ble_device_info_characteristic_value_update(p_buf, (adv_data_length + scan_rsp_data_length + 3)); + + tuya_ble_free(p_buf); + +#endif + +} + +#endif + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN==3) + +/** @brief GAP - Advertisement data (max size = 31 bytes, best kept short to conserve power) */ + +#define TUYA_BLE_ADV_DATA_LEN (12+TUYA_BLE_PRODUCT_ID_MAX_LEN) + +static const uint8_t adv_data_const[TUYA_BLE_ADV_DATA_LEN] = { + 0x02, + 0x01, + 0x06, + 0x03, + 0x02, + 0x01, 0xA2, + 0x14, + 0x16, + 0x01, 0xA2, + 0x00, //id type 00-pid 01-product key + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + + +#define TUYA_BLE_SCAN_RSP_DATA_LEN 30 +static const uint8_t scan_rsp_data_const[TUYA_BLE_SCAN_RSP_DATA_LEN] = { + 0x03, + 0x09, + 0x54, 0x59, + 0x19, // length + 0xFF, + 0xD0, + 0x07, + 0x00, //bond flag bit7 + 0x03, //protocol version + 0x01, //Encry Mode + 0x00, 0x00, //communication way bit0-mesh bit1-wifi bit2-zigbee bit3-NB + 0x00, //data type + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static uint8_t adv_data[TUYA_BLE_ADV_DATA_LEN]; +static uint8_t scan_rsp_data[TUYA_BLE_SCAN_RSP_DATA_LEN]; + +uint8_t tuya_ble_get_adv_connect_request_bit_status(void) +{ + return (scan_rsp_data[8] & 0x01); +} + +void tuya_ble_adv_change(void) +{ + uint8_t *aes_buf = NULL; + uint8_t aes_key[16]; + uint8_t encry_device_id[DEVICE_ID_LEN]; + + memcpy(adv_data, adv_data_const, TUYA_BLE_ADV_DATA_LEN); + memcpy(&scan_rsp_data, scan_rsp_data_const, TUYA_BLE_SCAN_RSP_DATA_LEN); + + adv_data[7] = 4 + tuya_ble_current_para.pid_len; + adv_data[11] = tuya_ble_current_para.pid_type; + + if (TUYA_BLE_DEVICE_SHARED) { + scan_rsp_data[8] |= 0x02 ; + } else { + scan_rsp_data[8] &= (~0x02); + } + + scan_rsp_data[8] &= (~0x01); + + scan_rsp_data[9] = TUYA_BLE_PROTOCOL_VERSION_HIGN; + + scan_rsp_data[10] = TUYA_BLE_SECURE_CONNECTION_TYPE; + + scan_rsp_data[11] = TUYA_BLE_DEVICE_COMMUNICATION_ABILITY >> 8; + scan_rsp_data[12] = TUYA_BLE_DEVICE_COMMUNICATION_ABILITY; + + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + scan_rsp_data[8] |= 0x80 ; + // + memcpy(aes_key, tuya_ble_current_para.sys_settings.login_key, LOGIN_KEY_LEN); + memcpy(aes_key + LOGIN_KEY_LEN, tuya_ble_current_para.auth_settings.device_id, 16 - LOGIN_KEY_LEN); + + aes_buf = tuya_ble_malloc(200); + + if (aes_buf == NULL) { + return; + } else { + memset(aes_buf, 0, 200); + } + + tuya_ble_encrypt_old_with_key(aes_key, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN, aes_buf); + + memcpy(&adv_data[12], (uint8_t *)(aes_buf + 1), tuya_ble_current_para.pid_len); + + tuya_ble_free(aes_buf); + + memset(aes_key, 0, sizeof(aes_key)); + memcpy(aes_key, &adv_data[12], tuya_ble_current_para.pid_len); + + tuya_ble_device_id_encrypt(aes_key, tuya_ble_current_para.pid_len, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN, encry_device_id); + + memcpy(&scan_rsp_data[14], encry_device_id, DEVICE_ID_LEN); + + } else { + scan_rsp_data[8] &= (~0x80); + + memcpy(&adv_data[12], tuya_ble_current_para.pid, tuya_ble_current_para.pid_len); + tuya_ble_device_id_encrypt(tuya_ble_current_para.pid, tuya_ble_current_para.pid_len, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN, encry_device_id); + + memcpy(&scan_rsp_data[14], encry_device_id, DEVICE_ID_LEN); + } + TUYA_BLE_LOG_INFO("adv data changed ,current bound flag = %d", tuya_ble_current_para.sys_settings.bound_flag); + tuya_ble_gap_advertising_adv_data_update(adv_data, tuya_ble_current_para.pid_len + 12); + tuya_ble_gap_advertising_scan_rsp_data_update(scan_rsp_data, sizeof(scan_rsp_data)); + +} + +void tuya_ble_adv_change_with_connecting_request(void) +{ + uint8_t *aes_buf = NULL; + uint8_t aes_key[16]; + uint8_t encry_device_id[DEVICE_ID_LEN]; + + memcpy(adv_data, adv_data_const, TUYA_BLE_ADV_DATA_LEN); + memcpy(&scan_rsp_data, scan_rsp_data_const, TUYA_BLE_SCAN_RSP_DATA_LEN); + + adv_data[7] = 4 + tuya_ble_current_para.pid_len; + adv_data[11] = tuya_ble_current_para.pid_type; + + if (TUYA_BLE_DEVICE_SHARED) { + scan_rsp_data[8] |= 0x02 ; + } else { + scan_rsp_data[8] &= (~0x02); + } + + scan_rsp_data[8] |= 0x01 ; + + scan_rsp_data[9] = TUYA_BLE_PROTOCOL_VERSION_HIGN; + + scan_rsp_data[10] = TUYA_BLE_SECURE_CONNECTION_TYPE; + + scan_rsp_data[11] = TUYA_BLE_DEVICE_COMMUNICATION_ABILITY >> 8; + scan_rsp_data[12] = TUYA_BLE_DEVICE_COMMUNICATION_ABILITY; + + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + scan_rsp_data[8] |= 0x80 ; + // + memcpy(aes_key, tuya_ble_current_para.sys_settings.login_key, LOGIN_KEY_LEN); + memcpy(aes_key + LOGIN_KEY_LEN, tuya_ble_current_para.auth_settings.device_id, 16 - LOGIN_KEY_LEN); + + aes_buf = tuya_ble_malloc(200); + + if (aes_buf == NULL) { + return; + } else { + memset(aes_buf, 0, 200); + } + + tuya_ble_encrypt_old_with_key(aes_key, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN, aes_buf); + + memcpy(&adv_data[12], (uint8_t *)(aes_buf + 1), tuya_ble_current_para.pid_len); + + tuya_ble_free(aes_buf); + + memset(aes_key, 0, sizeof(aes_key)); + memcpy(aes_key, &adv_data[12], tuya_ble_current_para.pid_len); + + tuya_ble_device_id_encrypt(aes_key, tuya_ble_current_para.pid_len, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN, encry_device_id); + + memcpy(&scan_rsp_data[14], encry_device_id, DEVICE_ID_LEN); + + } else { + scan_rsp_data[8] &= (~0x80); + + memcpy(&adv_data[12], tuya_ble_current_para.pid, tuya_ble_current_para.pid_len); + tuya_ble_device_id_encrypt(tuya_ble_current_para.pid, tuya_ble_current_para.pid_len, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN, encry_device_id); + + + memcpy(&scan_rsp_data[14], encry_device_id, DEVICE_ID_LEN); + } + TUYA_BLE_LOG_INFO("adv data changed ,current bound flag = %d", tuya_ble_current_para.sys_settings.bound_flag); + tuya_ble_gap_advertising_adv_data_update(adv_data, tuya_ble_current_para.pid_len + 12); + tuya_ble_gap_advertising_scan_rsp_data_update(scan_rsp_data, sizeof(scan_rsp_data)); + +} + +#endif + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN==2) + +#define TUYA_BLE_ADV_DATA_LEN 11 + +#define TUYA_BLE_SCAN_RSP_DATA_LEN 30 + +static const uint8_t scan_rsp_data_const[30] = { + /* Manufacturer Specific Data */ + 0x1D, /* length */ + 0xFF, + 0x59, + 0x02, + 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + + +static const uint8_t adv_data_const[11] = { + /* Flags */ + 0x02, /* length */ + 0x01, /* type="Flags" */ + 0x06, + /* Local name */ + 0x03, /* length */ + 0x09, + 'T', 'Y', + 0x03, + 0x02, + 0x01, 0xA2, +}; + +uint8_t adv_data[TUYA_BLE_ADV_DATA_LEN]; +uint8_t scan_rsp_data[TUYA_BLE_SCAN_RSP_DATA_LEN]; + +void tuya_ble_adv_change(void) +{ + uint8_t *aes_buf = NULL; + uint8_t aes_key[16]; + uint8_t encry_device_id[DEVICE_ID_LEN]; + + memcpy(adv_data, adv_data_const, TUYA_BLE_ADV_DATA_LEN); + memcpy(scan_rsp_data, scan_rsp_data_const, TUYA_BLE_SCAN_RSP_DATA_LEN); + + scan_rsp_data[4] &= (~0x70); + + if (tuya_ble_current_para.sys_settings.bound_flag == 1) { + scan_rsp_data[4] |= 0x80 ; + // + memcpy(aes_key, tuya_ble_current_para.sys_settings.login_key, LOGIN_KEY_LEN); + memcpy(aes_key + LOGIN_KEY_LEN, tuya_ble_current_para.auth_settings.device_id, 16 - LOGIN_KEY_LEN); + + aes_buf = tuya_ble_malloc(200); + + if (aes_buf == NULL) { + return; + } else { + memset(aes_buf, 0, 200); + } + + tuya_ble_encrypt_old_with_key(aes_key, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN, aes_buf); + + memcpy(&scan_rsp_data[6], (uint8_t *)(aes_buf + 1), tuya_ble_current_para.pid_len); + + tuya_ble_free(aes_buf); + + memset(aes_key, 0, sizeof(aes_key)); + memcpy(aes_key, &scan_rsp_data[6], tuya_ble_current_para.pid_len); + + tuya_ble_device_id_encrypt(aes_key, tuya_ble_current_para.pid_len, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN, encry_device_id); + + memcpy(&scan_rsp_data[14], encry_device_id, DEVICE_ID_LEN); + + } else { + scan_rsp_data[4] &= (~0x80); + memcpy(&scan_rsp_data[6], tuya_ble_current_para.pid, tuya_ble_current_para.pid_len); + tuya_ble_device_id_encrypt(tuya_ble_current_para.pid, 8, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN, encry_device_id); + + memcpy(&scan_rsp_data[14], encry_device_id, DEVICE_ID_LEN); + } + + TUYA_BLE_LOG_INFO("adv data changed ,current bound flag = %d", tuya_ble_current_para.sys_settings.bound_flag); + + tuya_ble_gap_advertising_adv_data_update(adv_data, sizeof(adv_data)); + tuya_ble_gap_advertising_scan_rsp_data_update(scan_rsp_data, sizeof(scan_rsp_data)); + +} + +#endif + + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_mem.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_mem.c new file mode 100644 index 0000000..bb4baf4 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_mem.c @@ -0,0 +1,140 @@ +/** + * \file tuya_ble_mem.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" +#include "tuya_ble_heap.h" +#include "tuya_ble_mem.h" +#include "tuya_ble_internal_config.h" + + +#if (TUYA_BLE_USE_PLATFORM_MEMORY_HEAP==0) + +/** + *@brief Allocate and clear a memory block with required size. + *@param[in] size Required memory size. + * + *@note + * + * */ +void *tuya_ble_malloc(uint16_t size) +{ + uint8_t *ptr = pvTuyaPortMalloc(size); + if (ptr) { + memset(ptr, 0x0, size); //allocate buffer need init + } + return ptr; +} + + +/** + *@brief Free a memory block that had been allocated. + *@param[in] ptr The address of memory block being freed. + * + *@note + * + * */ +tuya_ble_status_t tuya_ble_free(uint8_t *ptr) +{ + if (ptr == NULL) { + return TUYA_BLE_SUCCESS; + } + + vTuyaPortFree(ptr); + return TUYA_BLE_SUCCESS; +} + + +/** + *@brief + *@param + * + *@note + * + * */ +void *tuya_ble_calloc_n(uint32_t n, uint32_t size) +{ + void *ptr = NULL; + ptr = pvTuyaPortMalloc(n * size); + if (ptr != NULL) { + memset(ptr, 0, n * size); + } + return ptr; +} + + +/** + *@brief + *@param + * + *@note + * + * */ +void tuya_ble_free_n(void *ptr) +{ + vTuyaPortFree(ptr); +} + +#else + + +/** + *@brief Allocate and clear a memory block with required size. + *@param[in] size Required memory size. + * + *@note + * + * */ +void *tuya_ble_malloc(uint16_t size) +{ + uint8_t *ptr = tuya_ble_port_malloc(size); + if (ptr) { + memset(ptr, 0x0, size); //allocate buffer need init + } + return ptr; +} + + +/** + *@brief Free a memory block that had been allocated. + *@param[in] ptr The address of memory block being freed. + * + *@note + * + * */ +tuya_ble_status_t tuya_ble_free(uint8_t *ptr) +{ + if (ptr == NULL) { + return TUYA_BLE_SUCCESS; + } + + tuya_ble_port_free(ptr); + return TUYA_BLE_SUCCESS; +} + + +#endif + + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_mutli_tsf_protocol.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_mutli_tsf_protocol.c new file mode 100644 index 0000000..d5cf6a3 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_mutli_tsf_protocol.c @@ -0,0 +1,710 @@ +/** + * \file tuya_ble_mutli_tsf_protocol.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_type.h" +#include "tuya_ble_mem.h" +#include "tuya_ble_mutli_tsf_protocol.h" + +#define __MUTLI_TSF_PROTOCOL_GLOBALS + +/*********************************************************** +*************************micro define*********************** +***********************************************************/ +#define MTP_DEBUG 1 + +#if MTP_DEBUG +#define MTP_PR_DEBUG(_fmt_, ...) \ + printf("[mtp:dbg]%s:%d "_fmt_"\n\r", __FILE__, __LINE__, ##__VA_ARGS__) +#define MTP_PR_DEBUG_RAW(_fmt_, ...) \ + printf(_fmt_, ##__VA_ARGS__) +#else +#define MTP_PR_DEBUG(...) +#define MTP_PR_DEBUG_RAW(_fmt_, ...) +#endif + +#define MTP_PR_NOTICE(_fmt_, ...) \ + printf("[mtp:notice]%s:%d "_fmt_"\n\r", __FILE__, __LINE__, ##__VA_ARGS__) +#define MTP_PR_ERR(_fmt_, ...) \ + printf("[mtp:err]%s:%d "_fmt_"\n\r", __FILE__, __LINE__, ##__VA_ARGS__) + +#undef NULL +#define NULL (void *)0 +/*********************************************************** +*************************variable define******************** +***********************************************************/ +static frame_seq_t frame_seq = 0; + +/*********************************************************** +*************************function define******************** +***********************************************************/ +/*********************************************************** +* Function: create_trsmitr_init +* description: create a transmitter and initialize +* Input: none +* Output: +* Return: transmitter handle +***********************************************************/ +frm_trsmitr_proc_s *create_trsmitr_init(void) +{ + frm_trsmitr_proc_s *frm_trsmitr = NULL; + + frm_trsmitr = (frm_trsmitr_proc_s *)tuya_ble_malloc(sizeof(frm_trsmitr_proc_s)); + if ((void *)0 == frm_trsmitr) { + return (void *)0; + } + memset(frm_trsmitr, 0, sizeof(frm_trsmitr_proc_s)); + + return frm_trsmitr; +} + +/*********************************************************** +* Function: trsmitr_init +* description: init a transmitter +* Input: transmitter handle +* Output: +* Return: +***********************************************************/ +void trsmitr_init(frm_trsmitr_proc_s *frm_trsmitr) +{ + memset(frm_trsmitr, 0, sizeof(frm_trsmitr_proc_s)); +} + +/*********************************************************** +* Function: delete_trsmitr +* description: delete transmitter +* Input: transmitter handle +* Output: +* Return: +***********************************************************/ +void delete_trsmitr(frm_trsmitr_proc_s *frm_trsmitr) +{ + //free(frm_trsmitr); + tuya_ble_free((uint8_t *)frm_trsmitr); +} + +/*********************************************************** +* Function: get_trsmitr_frame_total_len +* description: get a transmitter total data len +* Input: transmitter handle +* Output: +* Return: frame_total_t +***********************************************************/ +frame_total_t get_trsmitr_frame_total_len(frm_trsmitr_proc_s *frm_trsmitr) +{ + return frm_trsmitr->total; +} + +/*********************************************************** +* Function: get_trsmitr_frame_version +* description: +* Input: transmitter handle +* Output: +* Return: +***********************************************************/ +uint8_t get_trsmitr_frame_version(frm_trsmitr_proc_s *frm_trsmitr) +{ + return frm_trsmitr->version; +} + +/*********************************************************** +* Function: get_trsmitr_frame_seq +* description: +* Input: transmitter handle +* Output: +* Return: frame_seq_t +***********************************************************/ +frame_seq_t get_trsmitr_frame_seq(frm_trsmitr_proc_s *frm_trsmitr) +{ + return frm_trsmitr->seq; +} + +/*********************************************************** +* Function: get_trsmitr_subpkg_len +* description: +* Input: transmitter handle +* Output: +* Return: frame_subpkg_len_t +***********************************************************/ +frame_subpkg_len_t get_trsmitr_subpkg_len(frm_trsmitr_proc_s *frm_trsmitr) +{ + return frm_trsmitr->subpkg_len; +} + +/*********************************************************** +* Function: get_trsmitr_subpkg +* description: +* Input: transmitter handle +* Output: +* Return: subpackage buf +***********************************************************/ +uint8_t *get_trsmitr_subpkg(frm_trsmitr_proc_s *frm_trsmitr) +{ + return frm_trsmitr->subpkg; +} + +static frame_seq_t get_frame_seq(void) //Because this type of data is not used temporarily, it can be used for multi-threaded calls temporarily +{ + return (frame_seq >= FRAME_SEQ_LMT) ? 0 : frame_seq++; +} + +/*********************************************************** +* Function: trsmitr_send_pkg_encode +* description: frm_trsmitr->transmitter handle +* type->frame type +* buf->data buf +* len->data len +* Input: +* Output: +* Return: MTP_OK->buf send up +* MTP_TRSMITR_CONTINUE->need call again to be continue +* other->error +* Note: could get from encode data len and encode data by calling method + get_trsmitr_subpkg_len() and get_trsmitr_subpkg() +***********************************************************/ +mtp_ret trsmitr_send_pkg_encode(frm_trsmitr_proc_s *frm_trsmitr, uint8_t version, uint8_t *buf, uint32_t len) +{ + if (((void *)0) == frm_trsmitr) { + return MTP_INVALID_PARAM; + } + + if (FRM_PKG_INIT == frm_trsmitr->pkg_desc) { + frm_trsmitr->total = len; + frm_trsmitr->version = version; + frm_trsmitr->seq = get_frame_seq(); + frm_trsmitr->subpkg_num = 0; + frm_trsmitr->pkg_trsmitr_cnt = 0; + } + + if (frm_trsmitr->subpkg_num >= 0x10000000 || len >= 0x10000000) { + return MTP_COM_ERROR; + } + + uint16_t sunpkg_offset = 0; + + // package code + // subpackage num encode + int32_t i; + uint32_t tmp = 0; + tmp = frm_trsmitr->subpkg_num; + for (i = 0; i < 4; i++) { + frm_trsmitr->subpkg[sunpkg_offset] = tmp % 0x80; + if ((tmp / 0x80)) { + frm_trsmitr->subpkg[sunpkg_offset] |= 0x80; + } + sunpkg_offset++; + tmp /= 0x80; + if (0 == tmp) { + break; + } + } + + // the first package include the frame total len + if (0 == frm_trsmitr->subpkg_num) { + // frame len encode + tmp = len; + for (i = 0; i < 4; i++) { + frm_trsmitr->subpkg[sunpkg_offset] = tmp % 0x80; + if ((tmp / 0x80)) { + frm_trsmitr->subpkg[sunpkg_offset] |= 0x80; + } + sunpkg_offset++; + tmp /= 0x80; + if (0 == tmp) { + break; + } + } + + // frame type and frame seq + frm_trsmitr->subpkg[sunpkg_offset++] = (frm_trsmitr->version << 0x04) | (frm_trsmitr->seq & 0x0f); + } + + // frame data transfer + uint16_t send_data_len = (SNGL_PKG_TRSFR_LMT - sunpkg_offset); + if ((len - frm_trsmitr->pkg_trsmitr_cnt) < send_data_len) { + send_data_len = len - frm_trsmitr->pkg_trsmitr_cnt; + } + + memcpy(&(frm_trsmitr->subpkg[sunpkg_offset]), buf + frm_trsmitr->pkg_trsmitr_cnt, send_data_len); + frm_trsmitr->subpkg_len = sunpkg_offset + send_data_len; + + frm_trsmitr->pkg_trsmitr_cnt += send_data_len; + if (0 == frm_trsmitr->subpkg_num) { + frm_trsmitr->pkg_desc = FRM_PKG_FIRST; + } else { + frm_trsmitr->pkg_desc = FRM_PKG_MIDDLE; + } + + if (frm_trsmitr->pkg_trsmitr_cnt < frm_trsmitr->total) { + frm_trsmitr->subpkg_num++; + return MTP_TRSMITR_CONTINUE; + } + + frm_trsmitr->pkg_desc = FRM_PKG_END; + return MTP_OK; +} + +/*********************************************************** +* Function: trsmitr_send_pkg_encode_with_packet_length +* description: Encoding function for specifying sub-packet length +* +* +* +* Input: +* Output: +* Return: MTP_OK->buf send up +* MTP_TRSMITR_CONTINUE->need call again to be continue +* other->error +* Note: could get from encode data len and encode data by calling method + get_trsmitr_subpkg_len() and get_trsmitr_subpkg() +***********************************************************/ +mtp_ret trsmitr_send_pkg_encode_with_packet_length(frm_trsmitr_proc_s *frm_trsmitr, uint32_t pkg_len_max, uint8_t version, uint8_t *buf, uint32_t len) +{ + if (((void *)0) == frm_trsmitr) { + return MTP_INVALID_PARAM; + } + + if ((pkg_len_max == 0) || (pkg_len_max > SNGL_PKG_TRSFR_LMT)) { + return MTP_INVALID_PARAM; + } + + if (FRM_PKG_INIT == frm_trsmitr->pkg_desc) { + frm_trsmitr->total = len; + frm_trsmitr->version = version; + frm_trsmitr->seq = get_frame_seq(); + frm_trsmitr->subpkg_num = 0; + frm_trsmitr->pkg_trsmitr_cnt = 0; + } + + if (frm_trsmitr->subpkg_num >= 0x10000000 || len >= 0x10000000) { + return MTP_COM_ERROR; + } + + uint16_t sunpkg_offset = 0; + + // package code + // subpackage num encode + int32_t i; + uint32_t tmp = 0; + tmp = frm_trsmitr->subpkg_num; + for (i = 0; i < 4; i++) { + frm_trsmitr->subpkg[sunpkg_offset] = tmp % 0x80; + if ((tmp / 0x80)) { + frm_trsmitr->subpkg[sunpkg_offset] |= 0x80; + } + sunpkg_offset++; + tmp /= 0x80; + if (0 == tmp) { + break; + } + } + + // the first package include the frame total len + if (0 == frm_trsmitr->subpkg_num) { + // frame len encode + tmp = len; + for (i = 0; i < 4; i++) { + frm_trsmitr->subpkg[sunpkg_offset] = tmp % 0x80; + if ((tmp / 0x80)) { + frm_trsmitr->subpkg[sunpkg_offset] |= 0x80; + } + sunpkg_offset++; + tmp /= 0x80; + if (0 == tmp) { + break; + } + } + + // frame type and frame seq + frm_trsmitr->subpkg[sunpkg_offset++] = (frm_trsmitr->version << 0x04) | (frm_trsmitr->seq & 0x0f); + } + + // frame data transfer + uint16_t send_data_len = (pkg_len_max - sunpkg_offset); + if ((len - frm_trsmitr->pkg_trsmitr_cnt) < send_data_len) { + send_data_len = len - frm_trsmitr->pkg_trsmitr_cnt; + } + + memcpy(&(frm_trsmitr->subpkg[sunpkg_offset]), buf + frm_trsmitr->pkg_trsmitr_cnt, send_data_len); + frm_trsmitr->subpkg_len = sunpkg_offset + send_data_len; + + frm_trsmitr->pkg_trsmitr_cnt += send_data_len; + if (0 == frm_trsmitr->subpkg_num) { + frm_trsmitr->pkg_desc = FRM_PKG_FIRST; + } else { + frm_trsmitr->pkg_desc = FRM_PKG_MIDDLE; + } + + if (frm_trsmitr->pkg_trsmitr_cnt < frm_trsmitr->total) { + frm_trsmitr->subpkg_num++; + return MTP_TRSMITR_CONTINUE; + } + + frm_trsmitr->pkg_desc = FRM_PKG_END; + return MTP_OK; +} + + + +mtp_ret trsmitr_recv_pkg_decode(frm_trsmitr_proc_s *frm_trsmitr, uint8_t *raw_data, uint16_t raw_data_len) +{ + if (NULL == raw_data || (raw_data_len > SNGL_PKG_TRSFR_LMT) || NULL == frm_trsmitr) { + return MTP_INVALID_PARAM; + } + + if (FRM_PKG_INIT == frm_trsmitr->pkg_desc) { + frm_trsmitr->total = 0; + frm_trsmitr->version = 0; + frm_trsmitr->seq = 0; + frm_trsmitr->pkg_trsmitr_cnt = 0; + } + + uint16_t sunpkg_offset = 0; + // package code + // subpackage num decode + int32_t i; + uint32_t multiplier = 1; + uint8_t digit; + frame_subpkg_num_t subpkg_num = 0; +//Package number + for (i = 0; i < 4; i++) { + digit = raw_data[sunpkg_offset++]; + subpkg_num += (digit & 0x7f) * multiplier; + multiplier *= 0x80; + + if (0 == (digit & 0x80)) { + break; + } + } + + if (0 == subpkg_num) { + frm_trsmitr->total = 0; + frm_trsmitr->version = 0; + frm_trsmitr->seq = 0; + frm_trsmitr->pkg_trsmitr_cnt = 0; + frm_trsmitr->pkg_desc = FRM_PKG_FIRST; + } else { + frm_trsmitr->pkg_desc = FRM_PKG_MIDDLE; + } + + if (frm_trsmitr->subpkg_num >= 0x10000000) { + return MTP_COM_ERROR; + } + // is receive the subpackage num valid? + if (frm_trsmitr->pkg_desc != FRM_PKG_FIRST) { + if (subpkg_num < frm_trsmitr->subpkg_num) { + return MTP_TRSMITR_ERROR; + } else if (subpkg_num == frm_trsmitr->subpkg_num) { + return MTP_TRSMITR_CONTINUE; + } + + if (subpkg_num - frm_trsmitr->subpkg_num > 1) { + return MTP_TRSMITR_ERROR; + } + } + + frm_trsmitr->subpkg_num = subpkg_num; + + if (0 == frm_trsmitr->subpkg_num) { + // frame len decode + multiplier = 1; + for (i = 0; i < 4; i++) { + digit = raw_data[sunpkg_offset++]; + frm_trsmitr->total += (digit & 0x7f) * multiplier; + multiplier *= 0x80; + + if (0 == (digit & 0x80)) { + break; + } + } + + if (frm_trsmitr->total >= 0x10000000) { + return MTP_COM_ERROR; + } + + // frame type and frame seq decode + frm_trsmitr->version = (raw_data[sunpkg_offset] & FRM_VERSION_OFFSET) >> 4; + frm_trsmitr->seq = raw_data[sunpkg_offset++] & FRM_SEQ_OFFSET; + } + + uint16_t recv_data_len = raw_data_len - sunpkg_offset; + if ((frm_trsmitr->total - frm_trsmitr->pkg_trsmitr_cnt) < recv_data_len) { + recv_data_len = frm_trsmitr->total - frm_trsmitr->pkg_trsmitr_cnt; + } + + // decode data cp to transmitter subpackage buf + memcpy(frm_trsmitr->subpkg, &raw_data[sunpkg_offset], recv_data_len); + frm_trsmitr->subpkg_len = recv_data_len; + frm_trsmitr->pkg_trsmitr_cnt += recv_data_len; + + if (frm_trsmitr->pkg_trsmitr_cnt < frm_trsmitr->total) { + return MTP_TRSMITR_CONTINUE; + } + //cannot add 'frm_trsmitr->pkg_desc = FRM_PKG_END;' here. + return MTP_OK; +} +/*********************************************************** +* Function: free_klv_list +* description: +* Input: list +* Output: +* Return: +***********************************************************/ +void free_klv_list(klv_node_s *list) +{ + if (NULL == list) { + return; + } + + klv_node_s *node = list; + klv_node_s *next_node = NULL; + + do { + next_node = node->next; + //free(node); + tuya_ble_free((uint8_t *)(node->data)); + + tuya_ble_free((uint8_t *)node); + node = next_node; + } while (node); +} + +/*********************************************************** +* Function: make_klv_list +* description: +* Input: +* Output: +* Return: +***********************************************************/ +klv_node_s *make_klv_list(klv_node_s *list, uint8_t id, dp_type type, void *p_data, uint16_t len) +{ + klv_node_s *node = NULL; + uint32_t tmp4 = 0, tmp2 = 0; + + if (NULL == p_data || type >= DT_LMT) { + return NULL; + } + + if (DT_VALUE == type && DT_VALUE_LEN != len) { + goto err_ret; + } else if (DT_BITMAP == type && len != 1 && len != 2 && len != DT_BITMAP_MAX) { + goto err_ret; + } else if (DT_BOOL == type && DT_BOOL_LEN != len) { + goto err_ret; + } else if (DT_ENUM == type && DT_ENUM_LEN != len) { + goto err_ret; + } + + + node = (klv_node_s *)tuya_ble_malloc(sizeof(klv_node_s)); + + if (NULL == node) { + goto err_ret; + } + memset(node, 0, sizeof(klv_node_s)); + if (len > 0) { + node->data = tuya_ble_malloc(len); + if (node->data == NULL) { + tuya_ble_free(node->data); + tuya_ble_free((uint8_t *)node); + goto err_ret; + } + } + node->id = id; + node->len = len; + node->type = type; + + if (DT_VALUE == type) { + // change to big-end + tmp4 = *(uint32_t *)p_data; + // unsigned char shift = 0; + node->data[0] = (tmp4 >> 24) & 0xff; + node->data[1] = (tmp4 >> 16) & 0xff; + node->data[2] = (tmp4 >> 8) & 0xff; + node->data[3] = (tmp4 >> 0) & 0xff; + } else if (DT_BITMAP == type) { + if (len == 4) { + tmp4 = *(uint32_t *)p_data; + // unsigned char shift = 0; + node->data[0] = (tmp4 >> 24) & 0xff; + node->data[1] = (tmp4 >> 16) & 0xff; + node->data[2] = (tmp4 >> 8) & 0xff; + node->data[3] = (tmp4 >> 0) & 0xff; + } else if (len == 2) { + tmp2 = *(uint16_t *)p_data; + node->data[0] = (tmp2 >> 8) & 0xff; + node->data[1] = (tmp2 >> 0) & 0xff; + } else { + node->data[0] = *(uint8_t *)p_data; + } + } else { + if (len > 0) { + memcpy((void *)node->data, (uint8_t *)p_data, len); + } + } + node->next = list; + return node; + +err_ret: + free_klv_list(list); + return NULL; +} + +/*********************************************************** +* Function: klvlist_2_data +* description: +* Input: type:0- 1 byte length,1- 2 byte length +* Output: +* Return: +***********************************************************/ +mtp_ret klvlist_2_data(klv_node_s *list, uint8_t **data, uint32_t *len, uint8_t type) +{ + if (NULL == list || NULL == data || NULL == len) { + return MTP_INVALID_PARAM; + } + + klv_node_s *node = list; + + // count data len + uint32_t mk_data_len = 0; + while (node) { + mk_data_len += sizeof(klv_node_s) + node->len - sizeof(struct s_klv_node *); + node = node->next; + } + + uint8_t *mk_data = (uint8_t *)tuya_ble_malloc(mk_data_len); + if (NULL == mk_data) { + return MTP_MALLOC_ERR; + } + + // fill data + uint32_t offset = 0; + node = list; + while (node) { + mk_data[offset++] = node->id; + mk_data[offset++] = node->type; + if (1 == type) { + mk_data[offset++] = node->len >> 8; + mk_data[offset++] = node->len; + } else { + mk_data[offset++] = node->len; + } + if (node->len > 0) { + memcpy(&mk_data[offset], node->data, node->len); + } + offset += node->len; + node = node->next; + } + *len = offset; + *data = mk_data; + + return MTP_OK; +} + +/*********************************************************** +* Function: data_2_klvlist +* description: +* Input: type: 0- 1 byte length,1- 2 byte length +* Output: +* Return: +***********************************************************/ +mtp_ret data_2_klvlist(uint8_t *data, uint32_t len, klv_node_s **list, uint8_t type) +{ + uint16_t dp_len = 0; + //The data is parsed into a list of dp points dpid+dp_tp+len+data + if (NULL == data || NULL == list) { + return MTP_INVALID_PARAM; + } + + uint32_t offset = 0; + klv_node_s *klv_list = NULL; + klv_node_s *node = NULL; + do { + // not full klv + if (type == 1) { + if ((len - offset) < 4) { + free_klv_list(klv_list); + return MTP_COM_ERROR; + } + } else { + if ((len - offset) < 3) { + free_klv_list(klv_list); + return MTP_COM_ERROR; + } + } + + node = (klv_node_s *)tuya_ble_malloc(sizeof(klv_node_s)); + if (NULL == node) { + free_klv_list(klv_list); + return MTP_MALLOC_ERR; + } + memset(node, 0, sizeof(klv_node_s)); + if (1 == type) { + dp_len = (data[2 + offset] << 8) + data[3 + offset]; + } else { + dp_len = data[2 + offset]; + } + + if (dp_len > 0) { + node->data = tuya_ble_malloc(dp_len); + if (node->data == NULL) { + tuya_ble_free(node->data); + tuya_ble_free((uint8_t *)node); + free_klv_list(klv_list); + return MTP_MALLOC_ERR; + } + } + node->id = data[offset++]; + node->type = data[offset++]; + if (1 == type) { + //offset++; + node->len = data[offset++]; + node->len = (node->len << 8) + data[offset++]; + } else { + node->len = data[offset++]; + } + if ((len - offset) < node->len) { + // is remain data len enougn? + tuya_ble_free(node->data); + tuya_ble_free((uint8_t *)node); + free_klv_list(klv_list); + return MTP_COM_ERROR; + } + if (node->len > 0) { + memcpy(node->data, &data[offset], node->len); + } + + offset += node->len; + + node->next = klv_list; + klv_list = node; + } while (offset < len); + + if (NULL == klv_list) { + return MTP_COM_ERROR; + } + *list = klv_list; + return MTP_OK; +} + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_queue.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_queue.c new file mode 100644 index 0000000..fb1b330 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_queue.c @@ -0,0 +1,100 @@ +/** + * \file tuya_ble_queue.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_queue.h" +#include "tuya_ble_type.h" + +tuya_ble_status_t tuya_ble_queue_init(tuya_ble_queue_t *q, void *buf, uint8_t queue_size, uint8_t elem_size) +{ + if (buf == NULL || q == NULL) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + + q->buf = buf; + q->size = queue_size; + q->offset = elem_size; + q->rd_ptr = 0; + q->wr_ptr = 0; + q->used = 0; + + return TUYA_BLE_SUCCESS; +} + +tuya_ble_status_t tuya_ble_enqueue(tuya_ble_queue_t *q, void *in) +{ + if (q->used >= q->size) { + return TUYA_BLE_ERR_NO_MEM; + } + + memcpy((uint8_t *)q->buf + q->wr_ptr * q->offset, in, q->offset); + q->wr_ptr = (q->wr_ptr + 1) % q->size; + q->used++; + + return TUYA_BLE_SUCCESS; +} + +tuya_ble_status_t tuya_ble_queue_get(tuya_ble_queue_t *q, void *out) +{ + if (q->used > 0) { + memcpy(out, (uint8_t *)q->buf + q->rd_ptr * q->offset, q->offset); + return TUYA_BLE_SUCCESS; + } else { + return TUYA_BLE_ERR_NOT_FOUND; + } +} + +tuya_ble_status_t tuya_ble_dequeue(tuya_ble_queue_t *q, void *out) +{ + if (q->used > 0) { + memcpy(out, (uint8_t *)q->buf + q->rd_ptr * q->offset, q->offset); + q->rd_ptr = (q->rd_ptr + 1) % q->size; + q->used--; + return TUYA_BLE_SUCCESS; + } else { + return TUYA_BLE_ERR_NOT_FOUND; + } +} + +void tuya_ble_queue_decrease(tuya_ble_queue_t *q) +{ + if (q->used > 0) { + q->rd_ptr = (q->rd_ptr + 1) % q->size; + q->used--; + } +} + + +void tuya_ble_queue_flush(tuya_ble_queue_t *q) +{ + q->rd_ptr = 0; + q->wr_ptr = 0; + q->used = 0; +} + +uint8_t tuya_ble_get_queue_used(tuya_ble_queue_t *q) +{ + return q->used; +} + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_storage.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_storage.c new file mode 100644 index 0000000..35d304d --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_storage.c @@ -0,0 +1,498 @@ +/** + * \file tuya_ble_storage.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ +#include "tuya_ble_stdlib.h" +#include "tuya_ble_api.h" +#include "tuya_ble_port.h" +#include "tuya_ble_type.h" +#include "tuya_ble_main.h" +#include "tuya_ble_mem.h" +#include "tuya_ble_data_handler.h" +#include "tuya_ble_internal_config.h" +#include "tuya_ble_mutli_tsf_protocol.h" +#include "tuya_ble_storage.h" +#include "tuya_ble_utils.h" +#include "tuya_ble_log.h" + + +typedef struct { + uint32_t crc; + uint32_t settings_version; + uint8_t h_id[H_ID_LEN]; + uint8_t device_id[DEVICE_ID_LEN]; + uint8_t mac[MAC_LEN]; + uint8_t auth_key[AUTH_KEY_LEN]; +} tuya_ble_auth_settings_old_t; + + +typedef struct { + uint32_t crc; + uint32_t settings_version; + tuya_ble_product_id_type_t pid_type; + uint8_t pid_len; + uint8_t common_pid[TUYA_BLE_PRODUCT_ID_MAX_LEN]; + uint8_t login_key[LOGIN_KEY_LEN]; + uint8_t ecc_secret_key[ECC_SECRET_KEY_LEN]; + uint8_t device_virtual_id[DEVICE_VIRTUAL_ID_LEN]; + uint8_t user_rand[PAIR_RANDOM_LEN]; + uint8_t bound_flag; +} tuya_ble_sys_settings_old_t; + + +typedef struct { + tuya_ble_auth_settings_t flash_settings_auth; + tuya_ble_auth_settings_t flash_settings_auth_backup; +} tuya_ble_storage_auth_settings_t; + +typedef struct { + tuya_ble_sys_settings_t flash_settings_sys; + tuya_ble_sys_settings_t flash_settings_sys_backup; +} tuya_ble_storage_sys_settings_t; + + +static bool buffer_value_is_all_x(uint8_t *buffer, uint16_t len, uint8_t value) +{ + bool ret = true; + for (uint16_t i = 0; i < len; i++) { + if (buffer[i] != value) { + ret = false; + break; + } + } + return ret; +} + + + +static uint32_t auth_settings_crc_get(tuya_ble_auth_settings_t const *p_settings) +{ + // The crc is calculated from the s_dfu_settings struct, except the crc itself and the init command + return tuya_ble_crc32_compute((uint8_t *)(p_settings) + 4, sizeof(tuya_ble_auth_settings_t) - 4, NULL); +} + +static bool auth_settings_crc_ok(tuya_ble_auth_settings_t const *p_settings, uint8_t *flash_update) +{ + uint32_t crc, crc_old; + if (p_settings->crc != 0xFFFFFFFF) { + // CRC is set. Content must be valid + crc = auth_settings_crc_get(p_settings); + if (crc == p_settings->crc) { + return true; + } else { + crc_old = tuya_ble_crc32_compute((uint8_t *)(p_settings) + 4, sizeof(tuya_ble_auth_settings_old_t) - 4, NULL); + if (crc_old == p_settings->crc) { + *flash_update = 1; + return true; + } + } + } + return false; +} + + +static uint32_t sys_settings_crc_get(tuya_ble_sys_settings_t const *p_settings) +{ + // The crc is calculated from the s_dfu_settings struct, except the crc itself and the init command + return tuya_ble_crc32_compute((uint8_t *)(p_settings) + 4, sizeof(tuya_ble_sys_settings_t) - 4, NULL); +} + + + +static bool sys_settings_crc_ok(tuya_ble_sys_settings_t const *p_settings, uint8_t *flash_update) +{ + uint32_t crc, crc_old; + if (p_settings->crc != 0xFFFFFFFF) { + // CRC is set. Content must be valid + crc = sys_settings_crc_get(p_settings); + if (crc == p_settings->crc) { + return true; + } else { + crc_old = tuya_ble_crc32_compute((uint8_t *)(p_settings) + 4, sizeof(tuya_ble_sys_settings_old_t) - 4, NULL); + if (crc_old == p_settings->crc) { + *flash_update = 1; + return true; + } + } + } + return false; +} + + +uint32_t tuya_ble_storage_load_settings(void) +{ + uint32_t err_code = 0; + bool settings_valid ; + bool settings_backup_valid; + uint8_t auth_settings_flag = 1; + uint8_t sys_settings_flag = 1; + uint8_t auth_settings_update = 0; + uint8_t sys_settings_update = 0; + tuya_ble_storage_auth_settings_t *p_storage_settings_auth = NULL; + tuya_ble_storage_sys_settings_t *p_storage_settings_sys = NULL; + + p_storage_settings_auth = (tuya_ble_storage_auth_settings_t *)tuya_ble_malloc(sizeof(tuya_ble_storage_auth_settings_t)); + + if (p_storage_settings_auth == NULL) { + TUYA_BLE_LOG_ERROR("p_storage_settings_auth malloc failed."); + memset(&tuya_ble_current_para.auth_settings, 0, sizeof(tuya_ble_auth_settings_t)); + auth_settings_flag = 0; + } else { + memset(p_storage_settings_auth, 0, sizeof(tuya_ble_storage_auth_settings_t)); + } + + if (auth_settings_flag == 1) { + tuya_ble_nv_read(TUYA_BLE_AUTH_FLASH_ADDR, (uint8_t *)&p_storage_settings_auth->flash_settings_auth, sizeof(tuya_ble_auth_settings_t)); + tuya_ble_nv_read(TUYA_BLE_AUTH_FLASH_BACKUP_ADDR, (uint8_t *)&p_storage_settings_auth->flash_settings_auth_backup, sizeof(tuya_ble_auth_settings_t)); + + settings_valid = auth_settings_crc_ok(&p_storage_settings_auth->flash_settings_auth, &auth_settings_update); + settings_backup_valid = auth_settings_crc_ok(&p_storage_settings_auth->flash_settings_auth_backup, &auth_settings_update); + + if (settings_valid) { + memcpy(&tuya_ble_current_para.auth_settings, &p_storage_settings_auth->flash_settings_auth, sizeof(tuya_ble_auth_settings_t)); + } else if (settings_backup_valid) { + memcpy(&tuya_ble_current_para.auth_settings, &p_storage_settings_auth->flash_settings_auth_backup, sizeof(tuya_ble_auth_settings_t)); + } else { + memset(&tuya_ble_current_para.auth_settings, 0, sizeof(tuya_ble_auth_settings_t)); + auth_settings_flag = 0; + } + if (auth_settings_update == 1) { + tuya_ble_storage_save_auth_settings(); + auth_settings_update = 0; + } + + tuya_ble_free((uint8_t *)p_storage_settings_auth); + + } + + p_storage_settings_sys = (tuya_ble_storage_sys_settings_t *)tuya_ble_malloc(sizeof(tuya_ble_storage_sys_settings_t)); + + if (p_storage_settings_sys == NULL) { + TUYA_BLE_LOG_ERROR("p_storage_settings_sys malloc failed."); + memset(&tuya_ble_current_para.sys_settings, 0, sizeof(tuya_ble_sys_settings_t)); + sys_settings_flag = 0; + } else { + memset(p_storage_settings_sys, 0, sizeof(tuya_ble_storage_sys_settings_t)); + } + + if (sys_settings_flag == 1) { + tuya_ble_nv_read(TUYA_BLE_SYS_FLASH_ADDR, (uint8_t *)&p_storage_settings_sys->flash_settings_sys, sizeof(tuya_ble_sys_settings_t)); + tuya_ble_nv_read(TUYA_BLE_SYS_FLASH_BACKUP_ADDR, (uint8_t *)&p_storage_settings_sys->flash_settings_sys_backup, sizeof(tuya_ble_sys_settings_t)); + + settings_valid = sys_settings_crc_ok(&p_storage_settings_sys->flash_settings_sys, &sys_settings_update); + settings_backup_valid = sys_settings_crc_ok(&p_storage_settings_sys->flash_settings_sys_backup, &sys_settings_update); + + if (settings_valid) { + memcpy(&tuya_ble_current_para.sys_settings, &p_storage_settings_sys->flash_settings_sys, sizeof(tuya_ble_sys_settings_t)); + } else if (settings_backup_valid) { + memcpy(&tuya_ble_current_para.sys_settings, &p_storage_settings_sys->flash_settings_sys_backup, sizeof(tuya_ble_sys_settings_t)); + } else { + memset(&tuya_ble_current_para.sys_settings, 0, sizeof(tuya_ble_sys_settings_t)); + tuya_ble_current_para.sys_settings.factory_test_flag = 0xFF; + sys_settings_flag = 0; + } + + if (sys_settings_update == 1) { + tuya_ble_current_para.sys_settings.factory_test_flag = 0xFF; + tuya_ble_storage_save_sys_settings(); + sys_settings_update = 0; + } + + tuya_ble_free((uint8_t *)p_storage_settings_sys); + + } + + tuya_ble_current_para.pid_type = tuya_ble_current_para.sys_settings.pid_type; + tuya_ble_current_para.pid_len = tuya_ble_current_para.sys_settings.pid_len; + memcpy(tuya_ble_current_para.pid, tuya_ble_current_para.sys_settings.common_pid, tuya_ble_current_para.pid_len); + + + return err_code; +} + + +uint32_t tuya_ble_storage_save_auth_settings(void) +{ + uint32_t err_code = 0; + + tuya_ble_current_para.auth_settings.crc = tuya_ble_crc32_compute((uint8_t *)&tuya_ble_current_para.auth_settings + 4, sizeof(tuya_ble_current_para.auth_settings) - 4, NULL); + + if (tuya_ble_nv_erase(TUYA_BLE_AUTH_FLASH_ADDR, TUYA_NV_ERASE_MIN_SIZE) == TUYA_BLE_SUCCESS) { + err_code = tuya_ble_nv_write(TUYA_BLE_AUTH_FLASH_ADDR, (uint8_t *)&tuya_ble_current_para.auth_settings, sizeof(tuya_ble_auth_settings_t)); + + if (err_code == TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_DEBUG("write flash_settings_auth data succeed!"); + + if (tuya_ble_nv_erase(TUYA_BLE_AUTH_FLASH_BACKUP_ADDR, TUYA_NV_ERASE_MIN_SIZE) == TUYA_BLE_SUCCESS) { + if (tuya_ble_nv_write(TUYA_BLE_AUTH_FLASH_BACKUP_ADDR, (uint8_t *)&tuya_ble_current_para.auth_settings, sizeof(tuya_ble_auth_settings_t)) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("write flash_settings_auth data backup failed!"); + err_code = 1; + } + } else { + TUYA_BLE_LOG_ERROR("erase flash_settings_auth data backup failed!"); + err_code = 1; + } + } else { + TUYA_BLE_LOG_ERROR("write flash_settings_auth data failed!"); + err_code = 1; + } + } else { + TUYA_BLE_LOG_ERROR("erase flash_settings_auth data failed!"); + err_code = 1; + } + return err_code; + +} + +uint32_t tuya_ble_storage_save_sys_settings(void) +{ + uint32_t err_code = 0; + +#if (TUYA_BLE_DEVICE_AUTH_DATA_STORE) + + tuya_ble_current_para.sys_settings.crc = tuya_ble_crc32_compute((uint8_t *)&tuya_ble_current_para.sys_settings + 4, sizeof(tuya_ble_sys_settings_t) - 4, NULL); + + if (tuya_ble_nv_erase(TUYA_BLE_SYS_FLASH_ADDR, TUYA_NV_ERASE_MIN_SIZE) == TUYA_BLE_SUCCESS) { + err_code = tuya_ble_nv_write(TUYA_BLE_SYS_FLASH_ADDR, (uint8_t *)&tuya_ble_current_para.sys_settings, sizeof(tuya_ble_sys_settings_t)); + + if (err_code == TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_INFO("write flash_settings_sys data succeed!"); + + if (tuya_ble_nv_erase(TUYA_BLE_SYS_FLASH_BACKUP_ADDR, TUYA_NV_ERASE_MIN_SIZE) == TUYA_BLE_SUCCESS) { + if (tuya_ble_nv_write(TUYA_BLE_SYS_FLASH_BACKUP_ADDR, (uint8_t *)&tuya_ble_current_para.sys_settings, sizeof(tuya_ble_sys_settings_t)) != TUYA_BLE_SUCCESS) { + TUYA_BLE_LOG_ERROR("write flash_settings_sys data backup failed!"); + err_code = 1; + } + } else { + TUYA_BLE_LOG_ERROR("erase flash_settings_sys data backup failed!"); + err_code = 1; + } + + } else { + TUYA_BLE_LOG_ERROR("write flash_settings_sys data failed!"); + err_code = 1; + } + } else { + TUYA_BLE_LOG_ERROR("erase flash_settings_sys data failed!"); + err_code = 1; + } + +#endif + + return err_code; +} + + + +uint32_t tuya_ble_storage_init(void) +{ + uint32_t err = 0; + + tuya_ble_nv_init(); + +#if (TUYA_BLE_DEVICE_AUTH_DATA_STORE) + + tuya_ble_storage_load_settings(); + +#endif + return err; +} + +#if (TUYA_BLE_DEVICE_AUTH_DATA_STORE) +/** + * @brief Function for write pid to nv + * + * @note + * + * */ +tuya_ble_status_t tuya_ble_storage_write_pid(tuya_ble_product_id_type_t pid_type, uint8_t pid_len, uint8_t *pid) +{ + tuya_ble_status_t ret = TUYA_BLE_SUCCESS; + uint8_t is_write = 0; + + if (pid_len > TUYA_BLE_PRODUCT_ID_MAX_LEN) { + return TUYA_BLE_ERR_INVALID_PARAM; + } + + if ((pid_type != tuya_ble_current_para.pid_type) || (pid_len != tuya_ble_current_para.pid_len)) { + tuya_ble_current_para.pid_type = pid_type; + tuya_ble_current_para.pid_len = pid_len; + memcpy(tuya_ble_current_para.pid, pid, pid_len); + tuya_ble_current_para.sys_settings.pid_type = pid_type; + tuya_ble_current_para.sys_settings.pid_len = pid_len; + memcpy(tuya_ble_current_para.sys_settings.common_pid, pid, pid_len); + is_write = 1; + } else if (memcmp(pid, tuya_ble_current_para.pid, pid_len) != 0) { + tuya_ble_current_para.pid_type = pid_type; + tuya_ble_current_para.pid_len = pid_len; + memcpy(tuya_ble_current_para.pid, pid, pid_len); + tuya_ble_current_para.sys_settings.pid_type = pid_type; + tuya_ble_current_para.sys_settings.pid_len = pid_len; + memcpy(tuya_ble_current_para.sys_settings.common_pid, pid, pid_len); + is_write = 1; + } else { + + } + if (is_write == 1) { + if (tuya_ble_storage_save_sys_settings()) { + ret = TUYA_BLE_ERR_BUSY; + } + } + + return ret; +} + + +/** + * @brief Function for write hid to nv + * + * @note + * + * */ +tuya_ble_status_t tuya_ble_storage_write_hid(uint8_t *hid, uint8_t len) +{ + tuya_ble_status_t ret = TUYA_BLE_SUCCESS; + + if (len != H_ID_LEN) { + ret = TUYA_BLE_ERR_INVALID_PARAM; + } else { + if (memcmp(hid, tuya_ble_current_para.auth_settings.h_id, H_ID_LEN) != 0) { + memcpy(tuya_ble_current_para.auth_settings.h_id, hid, H_ID_LEN); + if (tuya_ble_storage_save_auth_settings()) { + ret = TUYA_BLE_ERR_BUSY; + } + } + } + + return ret; +} + +/** + * @brief Function for read id parameters + * + * @note + * + * */ +tuya_ble_status_t tuya_ble_storage_read_id_info(tuya_ble_factory_id_data_t *id) +{ + tuya_ble_status_t ret = TUYA_BLE_SUCCESS; + + id->pid_type = tuya_ble_current_para.pid_type; + id->pid_len = tuya_ble_current_para.pid_len; + memcpy(id->pid, tuya_ble_current_para.pid, tuya_ble_current_para.pid_len); + + memcpy(id->h_id, tuya_ble_current_para.auth_settings.h_id, H_ID_LEN); + memcpy(id->device_id, tuya_ble_current_para.auth_settings.device_id, DEVICE_ID_LEN); + memcpy(id->mac, tuya_ble_current_para.auth_settings.mac, MAC_LEN); + memcpy(id->auth_key, tuya_ble_current_para.auth_settings.auth_key, AUTH_KEY_LEN); + + return ret; +} + + +/** + * @brief Function for write auth key/uuid/mac/pid + * + * @note If the id length is 0, the corresponding id will not be written. + * + * */ +tuya_ble_status_t tuya_ble_storage_write_auth_key_device_id_mac(uint8_t *auth_key, uint8_t auth_key_len, uint8_t *device_id, uint8_t device_id_len, + uint8_t *mac, uint8_t mac_len, uint8_t *mac_string, uint8_t mac_string_len, uint8_t *pid, uint8_t pid_len) +{ + tuya_ble_status_t ret = TUYA_BLE_SUCCESS; + uint8_t is_write = 0; + + if (((auth_key_len != AUTH_KEY_LEN) && (auth_key_len != 0)) || ((device_id_len != DEVICE_ID_LEN) && (device_id_len != 0)) || ((mac_len != MAC_LEN) && (mac_len != 0))) { + ret = TUYA_BLE_ERR_INVALID_PARAM; + } else { + if (auth_key_len == AUTH_KEY_LEN) { + if (memcmp(tuya_ble_current_para.auth_settings.auth_key, auth_key, AUTH_KEY_LEN) != 0) { + memcpy(tuya_ble_current_para.auth_settings.auth_key, auth_key, AUTH_KEY_LEN); + is_write = 1; + } + } + if (device_id_len == DEVICE_ID_LEN) { + if (memcmp(tuya_ble_current_para.auth_settings.device_id, device_id, DEVICE_ID_LEN) != 0) { + memcpy(tuya_ble_current_para.auth_settings.device_id, device_id, DEVICE_ID_LEN); + is_write = 1; + } + } + if (mac_len == MAC_LEN) { + if (memcmp(tuya_ble_current_para.auth_settings.mac, mac, MAC_LEN) != 0) { + memcpy(tuya_ble_current_para.auth_settings.mac, mac, MAC_LEN); + memcpy(tuya_ble_current_para.auth_settings.mac_string, mac_string, MAC_LEN * 2); + is_write = 1; + } + } + if (pid_len > 0) { + if ((tuya_ble_current_para.auth_settings.pid_len != pid_len) || (memcmp(tuya_ble_current_para.auth_settings.factory_pid, pid, pid_len) != 0)) { + memcpy(tuya_ble_current_para.auth_settings.factory_pid, pid, pid_len); + tuya_ble_current_para.auth_settings.pid_len = pid_len; + tuya_ble_current_para.auth_settings.pid_type = (uint8_t)TUYA_BLE_PRODUCT_ID_TYPE_PID; + is_write = 1; + } + } + + if (is_write == 1) { + +#if (!TUYA_BLE_DEVICE_AUTH_DATA_STORE_EXT_MEDIUM) + if (tuya_ble_storage_save_auth_settings()) { + ret = TUYA_BLE_ERR_BUSY; + } +#else + tuya_ble_current_para.auth_settings.crc = tuya_ble_crc32_compute((uint8_t *)&tuya_ble_current_para.auth_settings + 4, sizeof(tuya_ble_current_para.auth_settings) - 4, NULL); + + if (tuya_ble_storage_private_data(PRIVATE_DATA_TUYA_AUTH_TOKEN, (uint8_t *)&tuya_ble_current_para.auth_settings, sizeof(tuya_ble_auth_settings_t))) { + ret = TUYA_BLE_ERR_BUSY; + } +#endif // (!TUYA_BLE_DEVICE_AUTH_DATA_STORE_EXT_MEDIUM) + else { + /* force clear device_virtual_id info */ + //if(tuya_ble_current_para.sys_settings.bound_flag==1) + { + memset(tuya_ble_current_para.sys_settings.device_virtual_id, 0, DEVICE_VIRTUAL_ID_LEN); + memset(tuya_ble_current_para.sys_settings.login_key, 0, LOGIN_KEY_LEN); + tuya_ble_current_para.sys_settings.bound_flag = 0; + tuya_ble_storage_save_sys_settings(); + tuya_ble_adv_change(); + tuya_ble_connect_status_set(UNBONDING_UNCONN); + TUYA_BLE_LOG_INFO("The state has changed, current bound flag = %d", tuya_ble_current_para.sys_settings.bound_flag); + } + } + } + + } + + return ret; +} + +#endif + + + + + + + + + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_unix_time.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_unix_time.c new file mode 100644 index 0000000..80def9c --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_unix_time.c @@ -0,0 +1,284 @@ +/** + * \file tuya_ble_unix_time.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + +#include "tuya_ble_stdlib.h" +#include "tuya_ble_unix_time.h" + + + +#define UTC_BASE_YEAR 1970 +#define MONTH_PER_YEAR 12 +#define DAY_PER_YEAR 365 +#define SEC_PER_DAY 86400 +#define SEC_PER_HOUR 3600 +#define SEC_PER_MIN 60 + +/* Number of days per month */ +static const uint8_t g_day_per_mon[MONTH_PER_YEAR] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + + + +/** + * @brief Function for Determine whether it is a leap year. + * + * @return 1:leap year + * @note + *. + * */ +static uint8_t applib_dt_is_leap_year(uint16_t year) +{ + /*----------------------------------------------------------------*/ + /* Local Variables */ + /*----------------------------------------------------------------*/ + + /*----------------------------------------------------------------*/ + /* Code Body */ + /*----------------------------------------------------------------*/ + if ((year % 400) == 0) { + return 1; + } else if ((year % 100) == 0) { + return 0; + } else if ((year % 4) == 0) { + return 1; + } else { + return 0; + } +} + + +/** + * @brief Function for obtain the days of month. + * + * @return days + * @note + *. + * */ +static uint8_t applib_dt_last_day_of_mon(uint8_t month, uint16_t year) +{ + /*----------------------------------------------------------------*/ + /* Local Variables */ + /*----------------------------------------------------------------*/ + + /*----------------------------------------------------------------*/ + /* Code Body */ + /*----------------------------------------------------------------*/ + if ((month == 0) || (month > 12)) { + return g_day_per_mon[1] + applib_dt_is_leap_year(year); + } + + if (month != 2) { + return g_day_per_mon[month - 1]; + } else { + return g_day_per_mon[1] + applib_dt_is_leap_year(year); + } +} + + +/** + * @brief Function for get the corresponding week based on the given date. + * + * @return + * @note 0-Sunday 6-Saturday + *. + * */ +static uint8_t applib_dt_dayindex(uint16_t year, uint8_t month, uint8_t day) +{ + int8_t century_code, year_code, month_code, day_code; + int32_t week = 0; + + century_code = year_code = month_code = day_code = 0; + + if (month == 1 || month == 2) { + century_code = (year - 1) / 100; + year_code = (year - 1) % 100; + month_code = month + 12; + day_code = day; + } else { + century_code = year / 100; + year_code = year % 100; + month_code = month; + day_code = day; + } + + week = year_code + year_code / 4 + century_code / 4 - 2 * century_code + 26 * (month_code + 1) / 10 + day_code - 1; + week = week > 0 ? (week % 7) : ((week % 7) + 7); + + return week; +} + + +/** + * @brief Function for Get the corresponding date according to the UTC timestamp. + * + * @param[in] daylightSaving:daylight saving time + * @return + * @note + *. + * */ +void tuya_ble_utc_sec_2_mytime(uint32_t utc_sec, tuya_ble_time_struct_data_t *result, bool daylightSaving) +{ + /*----------------------------------------------------------------*/ + /* Local Variables */ + /*----------------------------------------------------------------*/ + int32_t sec, day; + uint16_t y; + uint8_t m; + uint16_t d; + // uint8_t dst; + + /*----------------------------------------------------------------*/ + /* Code Body */ + /*----------------------------------------------------------------*/ + + if (daylightSaving) { + utc_sec += SEC_PER_HOUR; + } + + /* hour, min, sec */ + /* hour */ + sec = utc_sec % SEC_PER_DAY; + result->nHour = sec / SEC_PER_HOUR; + + /* min */ + sec %= SEC_PER_HOUR; + result->nMin = sec / SEC_PER_MIN; + + /* sec */ + result->nSec = sec % SEC_PER_MIN; + + /* year, month, day */ + /* year */ + /* year */ + day = utc_sec / SEC_PER_DAY; + for (y = UTC_BASE_YEAR; day > 0; y++) { + d = (DAY_PER_YEAR + applib_dt_is_leap_year(y)); + if (day >= d) { + day -= d; + } else { + break; + } + } + + result->nYear = y; + + for (m = 1; m < MONTH_PER_YEAR; m++) { + d = applib_dt_last_day_of_mon(m, y); + if (day >= d) { + day -= d; + } else { + break; + } + } + + result->nMonth = m; + result->nDay = (uint8_t)(day + 1); + + result->DayIndex = applib_dt_dayindex(result->nYear, result->nMonth, result->nDay); +} + +/** + * @brief Function for Get the UTC timestamp according to corresponding date . + * + * @param[in] daylightSaving:daylight saving time + * @return + * @note + *. + * */ +uint32_t tuya_ble_mytime_2_utc_sec(tuya_ble_time_struct_data_t *currTime, bool daylightSaving) +{ + /*----------------------------------------------------------------*/ + /* Local Variables */ + /*----------------------------------------------------------------*/ + uint16_t i; + uint32_t no_of_days = 0; + uint32_t utc_time; + uint8_t dst = 1; + + /*----------------------------------------------------------------*/ + /* Code Body */ + /*----------------------------------------------------------------*/ + if (currTime->nYear < UTC_BASE_YEAR) { + return 0; + } + + /* year */ + for (i = UTC_BASE_YEAR; i < currTime->nYear; i++) { + no_of_days += (DAY_PER_YEAR + applib_dt_is_leap_year(i)); + } + + /* month */ + for (i = 1; i < currTime->nMonth; i++) { + no_of_days += applib_dt_last_day_of_mon((unsigned char) i, currTime->nYear); + } + + /* day */ + no_of_days += (currTime->nDay - 1); + + /* sec */ + utc_time = (unsigned int) no_of_days * SEC_PER_DAY + (unsigned int)(currTime->nHour * SEC_PER_HOUR + + currTime->nMin * SEC_PER_MIN + currTime->nSec); + + if (dst && daylightSaving) { + utc_time -= SEC_PER_HOUR; + } + + return utc_time; +} + + +void tuya_ble_utc_sec_2_mytime_string(uint32_t utc_sec, bool daylightSaving, char *s) +{ + tuya_ble_time_struct_data_t rtc_time = {0}; + uint32_t temp = 0; + + tuya_ble_utc_sec_2_mytime(utc_sec, &rtc_time, daylightSaving); + + temp = rtc_time.nYear; + s[0] = temp / 1000 + 0x30; + temp = rtc_time.nYear % 1000; + s[1] = temp / 100 + 0x30; + temp = temp % 100; + s[2] = temp / 10 + 0x30; + s[3] = temp % 10 + 0x30; + s[4] = '-'; + s[5] = rtc_time.nMonth / 10 + 0x30; + s[6] = rtc_time.nMonth % 10 + 0x30; + s[7] = '-'; + s[8] = rtc_time.nDay / 10 + 0x30; + s[9] = rtc_time.nDay % 10 + 0x30; + s[10] = ' '; + s[11] = rtc_time.nHour / 10 + 0x30; + s[12] = rtc_time.nHour % 10 + 0x30; + s[13] = ':'; + s[14] = rtc_time.nMin / 10 + 0x30; + s[15] = rtc_time.nMin % 10 + 0x30; + s[16] = ':'; + s[17] = rtc_time.nSec / 10 + 0x30; + s[18] = rtc_time.nSec % 10 + 0x30; + s[19] = '\0'; +} + + + diff --git a/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_utils.c b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_utils.c new file mode 100644 index 0000000..fc60185 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_utils.c @@ -0,0 +1,773 @@ +/** + * \file tuya_ble_utils.c + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ +#include "tuya_ble_stdlib.h" +#include "tuya_ble_utils.h" +#include "tuya_ble_port.h" +#include "tuya_ble_mem.h" + + +int32_t tuya_ble_count_bits(uint32_t data) +{ + int32_t i = 0; + int32_t cnt = 0; + + for (i = 0; i < 32; i++) { + if (data & 0x01) { + cnt++; + } + + data >>= 1; + } + + return cnt; +} + +int32_t tuya_ble_rand_number(int32_t min, int32_t max) +{ + static bool is_srand_init = false; + int32_t num; + + if (!is_srand_init) { + is_srand_init = true; + //srand(time(NULL)); + } + + num = rand() % (max - min) + min; // [min<=num<=max] + + return num; +} + +void tuya_ble_inverted_array(uint8_t *array, uint16_t length) +{ + uint8_t temp; + uint16_t i, j; + for (i = 0, j = length - 1; i < j; i++, j--) { + temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } +} + +bool tuya_ble_buffer_value_is_all_x(uint8_t *buffer, uint16_t len, uint8_t value) +{ + bool ret = true; + for (uint16_t i = 0; i < len; i++) { + if (buffer[i] != value) { + ret = false; + break; + } + } + return ret; +} + + +uint8_t tuya_ble_check_sum(uint8_t *pbuf, uint16_t len) +{ + uint32_t i = 0, ck_sum = 0; + + for (i = 0; i < len ; i++) { + ck_sum += pbuf[i]; + } + return (uint8_t)ck_sum; +} + +uint8_t tuya_ble_check_num(uint8_t *buf, uint8_t num) +{ + uint8_t i = 0; + + for (; i < buf[0]; i++) { + if (buf[i + 1] == num) { + return 1; + } + } + return 0; +} + +void tuya_ble_hextoascii(uint8_t *hexbuf, uint8_t len, uint8_t *ascbuf) +{ + uint8_t i = 0, j = 0, temp = 0; + + for (i = 0; i < len; i++) { + temp = (hexbuf[i] >> 4) & 0xf; + if (temp <= 9) { + ascbuf[j] = temp + 0x30; + } else { + ascbuf[j] = temp + 87; + } + j++; + temp = (hexbuf[i]) & 0xf; + if (temp <= 9) { + ascbuf[j] = temp + 0x30; + } else { + ascbuf[j] = temp + 87; + } + j++; + } + +} + +void tuya_ble_hextostr(uint8_t *hexbuf, uint8_t len, uint8_t *strbuf) +{ + uint8_t i = 0, j = 0, temp = 0; + + for (i = 0; i < len; i++) { + temp = (hexbuf[i] >> 4) & 0x0f; + if (temp <= 9) { + strbuf[j] = temp + 0x30; + } else { + strbuf[j] = temp + 87; + } + j++; + temp = (hexbuf[i]) & 0x0f; + if (temp <= 9) { + strbuf[j] = temp + 0x30; + } else { + strbuf[j] = temp + 87; + } + j++; + } + strbuf[j] = 0x00; +} + +void tuya_ble_asciitohex(uint8_t *ascbuf, uint8_t *hexbuf) +{ + uint8_t i = 0, j = 0; + + while (ascbuf[i]) { + j++; + if ((ascbuf[i] >= 0x30) && (ascbuf[i] <= 0x39)) { + hexbuf[j] = ((ascbuf[i] - 0x30) << 4); + } else if ((ascbuf[i] >= 65) && (ascbuf[i] <= 70)) { + hexbuf[j] = ((ascbuf[i] - 55) << 4); + } else if ((ascbuf[i] >= 97) && (ascbuf[i] <= 102)) { + hexbuf[j] = ((ascbuf[i] - 87) << 4); + } + i++; + if ((ascbuf[i] >= 0x30) && (ascbuf[i] <= 0x39)) { + hexbuf[j] |= (ascbuf[i] - 0x30); + } else if ((ascbuf[i] >= 65) && (ascbuf[i] <= 70)) { + hexbuf[j] |= (ascbuf[i] - 55); + } else if ((ascbuf[i] >= 97) && (ascbuf[i] <= 102)) { + hexbuf[j] |= (ascbuf[i] - 87); + } + i++; + } + hexbuf[0] = j; +} + + + +uint8_t tuya_ble_char_2_ascii(uint8_t data) +{ + uint8_t ret = 0xff; + + if ((data >= 48) && (data <= 57)) { + ret = data - 48; + } else if ((data >= 65) && (data <= 70)) { + ret = data - 55; + } else if ((data >= 97) && (data <= 102)) { + ret = data - 87; + } + return ret; +} + +void tuya_ble_str_to_hex(uint8_t *str_buf, uint8_t str_len, uint8_t *hex_buf) +{ + uint8_t data_tmp = 0, i = 0, j = 0; + + for (j = 0 ; j < str_len ; j++) { + data_tmp = tuya_ble_char_2_ascii(str_buf[j]); + if (data_tmp != 0xff) { + hex_buf[i] = (data_tmp << 4); + } else { + return; + } + j++; + data_tmp = tuya_ble_char_2_ascii(str_buf[j]); + if (data_tmp != 0xff) { + hex_buf[i] += data_tmp; + } else { + return; + } + i++; + } +} + +void tuya_ble_swap(int16_t *a, int16_t *b) +{ + int16_t temp; + temp = *a; + *a = *b; + *b = temp; +} + + +int32_t tuya_ble_hex2int(uint8_t mhex) +{ + switch (mhex) { + case '0': + return 0; + case '1': + return 1; + case '2': + return 2; + case '3': + return 3; + case '4': + return 4; + case '5': + return 5; + case '6': + return 6; + case '7': + return 7; + case '8': + return 8; + case '9': + return 9; + case 'a': + case 'A': + return 10; + case 'b': + case 'B': + return 11; + case 'c': + case 'C': + return 12; + case 'd': + case 'D': + return 13; + case 'e': + case 'E': + return 14; + case 'f': + case 'F': + return 15; + default: + return -1; + } +} +char tuya_ble_hexstr2int(uint8_t *hexstr, int32_t len, uint8_t *sum) +{ + *sum = 0; + int32_t value; + for (int32_t i = 0; i < len; i++) { + value = tuya_ble_hex2int(hexstr[i]); + if (value == -1) { + return 0; + } + (*sum) = (*sum) << 4; + (*sum) += value; + } + return 1; +} +char tuya_ble_hexstr2hex(uint8_t *hexstr, int32_t len, uint8_t *hex) +{ + for (uint8_t i = 0; i < len; i += 2) { + if (tuya_ble_hexstr2int(&hexstr[i], 2, &hex[i / 2]) == 0) { + return 0; + } + } + return 1; +} + + +static void swapX(const uint8_t *src, uint8_t *dst, int32_t len) +{ + int32_t i; + for (i = 0; i < len; i++) { + dst[len - 1 - i] = src[i]; + } +} + +void tuya_ble_swap24(uint8_t dst[3], const uint8_t src[3]) +{ + swapX(src, dst, 3); +} + +void tuya_ble_swap32(uint8_t dst[4], const uint8_t src[4]) +{ + swapX(src, dst, 4); +} + +void tuya_ble_swap48(uint8_t dst[7], const uint8_t src[7]) +{ + swapX(src, dst, 6); +} + +void tuya_ble_swap56(uint8_t dst[7], const uint8_t src[7]) +{ + swapX(src, dst, 7); +} + +void tuya_ble_swap64(uint8_t dst[8], const uint8_t src[8]) +{ + swapX(src, dst, 8); +} + +void tuya_ble_swap128(uint8_t dst[16], const uint8_t src[16]) +{ + swapX(src, dst, 16); +} + + + +uint16_t tuya_ble_crc16_compute(uint8_t *p_data, uint16_t size, uint16_t *p_crc) +{ + + uint16_t poly[2] = {0, 0xa001}; //0x8005 <==> 0xa001 + uint16_t crc; + int i, j; + crc = (p_crc == NULL) ? 0xFFFF : *p_crc; + + for (j = size; j > 0; j--) { + unsigned char ds = *p_data++; + + for (i = 0; i < 8; i++) { + crc = (crc >> 1) ^ poly[(crc ^ ds) & 1]; + ds = ds >> 1; + } + } + + return crc; +} + + +uint32_t tuya_ble_crc32_compute(uint8_t const *p_data, uint32_t size, uint32_t const *p_crc) +{ + uint32_t crc; + crc = (p_crc == NULL) ? 0xFFFFFFFF : ~(*p_crc); + for (uint32_t i = 0; i < size; i++) { + crc = crc ^ p_data[i]; + for (uint32_t j = 8; j > 0; j--) { + crc = (crc >> 1) ^ (0xEDB88320U & ((crc & 1) ? 0xFFFFFFFF : 0)); + } + } + return ~crc; +} + + + +/**@brief Function for checking if a pointer value is aligned to a 4 byte boundary. + * + * @param[in] p Pointer value to be checked. + * + * @return TRUE if pointer is aligned to a 4 byte boundary, FALSE otherwise. + */ +bool tuya_ble_is_word_aligned_tuya(void const *p) +{ + return (((uintptr_t)p & 0x03) == 0); +} + + + +void tuya_ble_device_id_20_to_16(uint8_t *in, uint8_t *out) +{ + uint8_t i, j; + uint8_t temp[4]; + for (i = 0; i < 5; i++) { + for (j = i * 4; j < (i * 4 + 4); j++) { + if ((in[j] >= 0x30) && (in[j] <= 0x39)) { + temp[j - i * 4] = in[j] - 0x30; + } else if ((in[j] >= 0x41) && (in[j] <= 0x5A)) { + temp[j - i * 4] = in[j] - 0x41 + 36; + } else if ((in[j] >= 0x61) && (in[j] <= 0x7A)) { + temp[j - i * 4] = in[j] - 0x61 + 10; + } else { + + } + } + + out[i * 3] = temp[0] & 0x3F; + out[i * 3] <<= 2; + out[i * 3] |= ((temp[1] >> 4) & 0x03); + + out[i * 3 + 1] = temp[1] & 0x0F; + out[i * 3 + 1] <<= 4; + out[i * 3 + 1] |= ((temp[2] >> 2) & 0x0F); + + out[i * 3 + 2] = temp[2] & 0x03; + out[i * 3 + 2] <<= 6; + out[i * 3 + 2] |= temp[3] & 0x3F; + + } + + out[15] = 0xFF; +} + +void tuya_ble_device_id_16_to_20(uint8_t *in, uint8_t *out) +{ + uint8_t i, j; + uint8_t temp[4]; + for (i = 0; i < 5; i++) { + j = i * 3; + temp[j - i * 3] = (in[j] >> 2) & 0x3F; + temp[j - i * 3 + 1] = in[j] & 0x03; + temp[j - i * 3 + 1] <<= 4; + temp[j - i * 3 + 1] |= (in[j + 1] >> 4) & 0x0F; + temp[j - i * 3 + 2] = (in[j + 1] & 0x0F) << 2; + temp[j - i * 3 + 2] |= ((in[j + 2] & 0xC0) >> 6) & 0x03; + temp[j - i * 3 + 3] = in[j + 2] & 0x3F; + + for (j = i * 4; j < (i * 4 + 4); j++) { + if ((temp[j - i * 4] >= 0) && (temp[j - i * 4] <= 9)) { + out[j] = temp[j - i * 4] + 0x30; + } else if ((temp[j - i * 4] >= 10) && (temp[j - i * 4] <= 35)) { + out[j] = temp[j - i * 4] + 87; + } else if ((temp[j - i * 4] >= 36) && (temp[j - i * 4] <= 61)) { + out[j] = temp[j - i * 4] + 29; + } else { + + } + } + + + } + +} + + +/** + * @brief Function for search character/symbol index from input string + * + * @param + * [in]data : pointer to input data + * [in]data : Number of bytes of data + * [in]symbol : Search symbol or character, Such as ':' or ',' + * [out]index[] : Array of indexs + * + * @return The number of matched character/symbol + * + * @note + * + * */ +int32_t tuya_ble_search_symbol_index(char *data, uint16_t len, char symbol, uint8_t index[]) +{ + int32_t i; + uint8_t index_buf[64] = {0}; + uint8_t symbol_cnt = 0; + + if (data == NULL || len == 0 || index == NULL) { + return symbol_cnt; + } + + for (i = 0; i < len; i++) { + if (data[i] == symbol) { + index_buf[symbol_cnt] = i; + symbol_cnt += 1; + + if (symbol_cnt >= sizeof(index_buf)) { + /* error, too many symbols */ + break; + } + } + } + + if (symbol_cnt != 0) { + memcpy(index, index_buf, symbol_cnt); + } + + return symbol_cnt; +} + + +int32_t tuya_ble_ascii_to_int(char *ascii, uint16_t len) +{ + int32_t i; + int32_t num = 0; + bool negative = false; + + if (ascii == NULL || len == 0) { + return num; + } + + if (ascii[0] == 0x2D) { + negative = true; + } else { + num *= 10; + num += ascii[0] - '0'; + } + + for (i = 1; i < len; i++) { + num *= 10; + num += ascii[i] - '0'; + } + + if (negative) { + num = -1 * num; + } + + return num; +} + + +static uint8_t base64_decode(const uint8_t *input, uint16_t inlen, uint8_t *output, uint16_t *outlen) +{ + const char *base64_tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + uint8_t reverse_tbl[256] = {0}; + int32_t off = 0; + int32_t i = 0; + + if (NULL == input) { + return 1; + } + + if (inlen == 0) { + inlen = strlen((char *)input); + } + + if (inlen == 0 || (inlen % 4 != 0)) { + return 1; + } + + for (i = 0; i < 64; i++) { + reverse_tbl[base64_tbl[i]] = i; + } + + for (i = 0; i < inlen - 4; i += 4) { + output[off++] = (reverse_tbl[input[i]] << 2) | ((reverse_tbl[input[i + 1]] >> 4) & 0xFF); + output[off++] = (reverse_tbl[input[i + 1]] << 4) | ((reverse_tbl[input[i + 2]] >> 2) & 0xFF); + output[off++] = (reverse_tbl[input[i + 2]] << 6) | ((reverse_tbl[input[i + 3]]) & 0xFF); + } + + if (input[i + 2] == '=') { + output[off++] = (reverse_tbl[input[i]] << 2) | ((reverse_tbl[input[i + 1]] >> 4) & 0xFF); + } else if (input[i + 3] == '=') { + output[off++] = (reverse_tbl[input[i]] << 2) | ((reverse_tbl[input[i + 1]] >> 4) & 0xFF); + output[off++] = (reverse_tbl[input[i + 1]] << 4) | ((reverse_tbl[input[i + 2]] >> 2) & 0xFF); + } else { + output[off++] = (reverse_tbl[input[i]] << 2) | ((reverse_tbl[input[i + 1]] >> 4) & 0xFF); + output[off++] = (reverse_tbl[input[i + 1]] << 4) | ((reverse_tbl[input[i + 2]] >> 2) & 0xFF); + output[off++] = (reverse_tbl[input[i + 2]] << 6) | ((reverse_tbl[input[i + 3]]) & 0xFF); + } + + if (NULL != outlen) { + *outlen = off; + } + + return 0; +} + +static int32_t delChar(char *s, uint16_t len, char match_char) +{ + int32_t i, j; + int32_t counter = 0; + + for (i = 0; i < len; i++) { + if (s[i] == match_char) { + counter++; + + for (j = i; j < len; j++) { + s[j] = s[j + 1]; + i--; + } + } + } + return counter; +} + + +/** + * @brief Function for pem format ecc key to hex foramt + * + * @param + * [in]pem : pointer to pem data + * [out]key : pointer to output data, hex format ecc key + * [out]key_len: Number of bytes of key. + * + * @return 0 - failed, 1 - success + * + * @note developer could use tuya_ble_ecc_key_pem2hex_example() function to test + * + * */ +int32_t tuya_ble_ecc_key_pem2hex(const char *pem, uint8_t *key, uint16_t *key_len) +{ + char buf1[256] = {0}; + char buf2[256] = {0}; + uint16_t inlen = 0; + uint16_t i, j, k = 0; + uint16_t len, len1, len2 = 0; + + if (NULL == pem) { + return 0; + } + + inlen = strlen(pem); + + if (inlen > 256) { + return 0; + } + + //head + if ((pem[0] != '-') || (pem[1] != '-') || (pem[2] != '-') || (pem[3] != '-') || (pem[4] != '-')) { + return 0; + } + + //tail + if ((pem[inlen - 1] != '-') || (pem[inlen - 2] != '-') || (pem[inlen - 3] != '-') || (pem[inlen - 4] != '-') || (pem[inlen - 5] != '-')) { + return 0; + } + + //find head end + for (i = 5; i < inlen - 5; i++) { + if (pem[i] == '-') { + if ((pem[i + 1] != '-') || (pem[i + 2] != '-') || (pem[i + 3] != '-') || (pem[i + 4] != '-')) { + return 0; + } + + len1 = i + 5; + break; + } + } + + //remove head + memcpy(buf1, pem + len1, inlen - len1); + + //find tail + for (i = 0; i < inlen - len1; i++) { + if (buf1[i] == '-') { + if ((buf1[i + 1] != '-') || (buf1[i + 2] != '-') || (buf1[i + 3] != '-') || (buf1[i + 4] != '-')) { + return 0; + } + + len2 = i; + break; + } + } + len = len2; + + //remove \n + len1 = delChar(buf1, len, '\n'); + len = len - len1; + //remove \r + len1 = delChar(buf1, len, '\r'); + len = len - len1; + + //decode + base64_decode((uint8_t *)buf1, len, (uint8_t *)buf2, (uint16_t *)&len2); + + //next is asn.1 decode + if (buf2[0] != 0x30) { //0x30 + return 0; + } + + len1 = buf2[1];//0x30 0x41 + if ((len1 + 2) != len2) { + return 0; + } + + if (buf2[2] != 0x02) { //0x30 0x41 0x20 0x01 0x00 + return 0; + } + + if (buf2[5] != 0x30) { + return 0; + } + + len1 = buf2[6]; + + if (buf2[7 + len1] != 0x04) { //0x04 + return 0; + } + +// len2 = buf2[8+len1];//0x04 0x27 + + if (buf2[9 + len1] != 0x30) { //0x30 + return 0; + } + +// len = buf2[10+len1];//0x25 + + if (buf2[11 + len1] != 0x02) { //0x02 + return 0; + } + + if (buf2[14 + len1] != 0x04) { //0x04 + return 0; + } + + *key_len = buf2[15 + len1]; + memcpy(key, &buf2[16 + len1], *key_len); + + return 1; +} + + +void tuya_ble_ecc_key_pem2hex_example(void) +{ + uint8_t key[64] = {0}; + uint16_t keylen = 0; + + char test_char[] = + "-----BEGIN PRIVATE KEY-----MEECAQAwEwYHKoZIzj0CAQYIKoZIzj0DAQcEJzAlAgEBBCBX5s0E0DJowr3ibkG41jfvjRFgaoCO7v8fU/Wq/xLlDQ==-----END PRIVATE KEY-----"; + + tuya_ble_ecc_key_pem2hex(test_char, key, &keylen); + + /* output hex format key */ + // 57 E6 CD 04 D0 32 68 C2 BD E2 6E 41 B8 D6 37 EF + // 8D 11 60 6A 80 8E EE FF 1F 53 F5 AA FF 12 E5 0D +} + + +/** + * @brief Function for extract r+s from der from ecdsa sign + * + * @param + * [in]der : pointer to der data + * [out]raw_rs : pointer to output data, the raw data[r+s] of der + * + * @return 0 - failed, 1 - success + * + * @note + * + * */ +int32_t tuya_ble_ecc_sign_secp256r1_extract_raw_from_der(const char *der, uint8_t *raw_rs) +{ + /* extract r + s from der */ + int pos = 0; + uint8_t raw[64] = {0}; + + if (der == NULL || raw_rs == NULL) { + return 0; + } + + if (der[3] != 0x20) { + memcpy(raw, &der[5], 32); + pos = 5 + 32; + } else { + memcpy(raw, &der[4], 32); + pos = 4 + 32; + } + + // 37 + if (der[pos + 1] != 0x20) { + memcpy(&raw[32], &der[pos + 3], 32); + } else { + memcpy(&raw[32], &der[pos + 2], 32); + } + + memcpy(raw_rs, raw, sizeof(raw)); + return 1; +} + diff --git a/apps/common/third_party_profile/tuya_protocol/tuya_ble_config.h b/apps/common/third_party_profile/tuya_protocol/tuya_ble_config.h new file mode 100644 index 0000000..b426d42 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/tuya_ble_config.h @@ -0,0 +1,298 @@ +/** + * \file tuya_ble_config.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + + +#ifndef TUYA_BLE_CONFIG_H__ +#define TUYA_BLE_CONFIG_H__ + + +#if defined(CUSTOMIZED_TUYA_BLE_CONFIG_FILE) +#include CUSTOMIZED_TUYA_BLE_CONFIG_FILE +#endif + + +/* + * If the application has a customized production test project(file),please define CUSTOMIZED_TUYA_BLE_APP_PRODUCT_TEST_FILE in CUSTOMIZED_TUYA_BLE_CONFIG_FILE. + */ +#ifndef CUSTOMIZED_TUYA_BLE_APP_PRODUCT_TEST_HEADER_FILE +#undef CUSTOMIZED_TUYA_BLE_APP_PRODUCT_TEST_HEADER_FILE +#endif + +/* + * If needed,please define CUSTOMIZED_TUYA_BLE_APP_UART_COMMON_FILE in CUSTOMIZED_TUYA_BLE_CONFIG_FILE. + */ +#ifndef CUSTOMIZED_TUYA_BLE_APP_UART_COMMON_HEADER_FILE +#undef CUSTOMIZED_TUYA_BLE_APP_UART_COMMON_HEADER_FILE +#endif + + +/* + * If needed,please define TUYA_BLE_PORT_PLATFORM_HEADER_FILE in CUSTOMIZED_TUYA_BLE_CONFIG_FILE. + */ +#ifndef TUYA_BLE_PORT_PLATFORM_HEADER_FILE +#undef TUYA_BLE_PORT_PLATFORM_HEADER_FILE +#endif + +/* + * If using an OS, be sure to call the tuya api functions and SDK-related queues within the same task + */ +#ifndef TUYA_BLE_USE_OS +#define TUYA_BLE_USE_OS 1 +#endif +/* + * If using an OS, tuya ble sdk will create a task autonomously to process ble event. + */ + +#if TUYA_BLE_USE_OS + +#ifndef TUYA_BLE_SELF_BUILT_TASK +#define TUYA_BLE_SELF_BUILT_TASK 1 +#endif + +#if TUYA_BLE_SELF_BUILT_TASK + +#ifndef TUYA_BLE_TASK_PRIORITY +#define TUYA_BLE_TASK_PRIORITY 1 +#endif + +#ifndef TUYA_BLE_TASK_STACK_SIZE +#define TUYA_BLE_TASK_STACK_SIZE 256 * 10 //!< Task stack size ,application do not change this default value +#endif + +#endif + +#endif +/* + * TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_BLE ble normal + * TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_REGISTER_FROM_BLE device register from ble + * TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_MESH ble mesh + * TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_WIFI_24G wifi_2.4g + * TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_WIFI_5G wifi_5g + * TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_ZIGBEE zigbee + * TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_NB nb-iot + * @note: + * for example (TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_BLE|TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_MESH|TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_WIFI_24G) + */ +//#define TUYA_BLE_DEVICE_COMMUNICATION_ABILITY (TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_BLE|TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_WIFI_24G|TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_WIFI_5G) +#ifndef TUYA_BLE_DEVICE_COMMUNICATION_ABILITY +#define TUYA_BLE_DEVICE_COMMUNICATION_ABILITY (TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_BLE|TUYA_BLE_DEVICE_COMMUNICATION_ABILITY_REGISTER_FROM_BLE) +#endif + +/* + * Whether it is a shared device. + */ +#ifndef TUYA_BLE_DEVICE_SHARED +#define TUYA_BLE_DEVICE_SHARED 0 +#endif + +/* + * If it is 1, then sdk need to perform the unbind operation,otherwise sdk do not need. + */ +#ifndef TUYA_BLE_DEVICE_UNBIND_MODE +#define TUYA_BLE_DEVICE_UNBIND_MODE 1 +#endif + +/* + * If TUYA_BLE_WIFI_DEVICE_REGISTER_MODE is 1,Mobile app must first sends instructions to query network status after sending the pairing request . + */ +#ifndef TUYA_BLE_WIFI_DEVICE_REGISTER_MODE +#define TUYA_BLE_WIFI_DEVICE_REGISTER_MODE 1 +#endif + +/* + * if 1 ,tuya ble sdk authorization self-management + */ +#ifndef TUYA_BLE_DEVICE_AUTH_SELF_MANAGEMENT +#define TUYA_BLE_DEVICE_AUTH_SELF_MANAGEMENT 1 +#endif + +/* + * TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY encrypt with auth key + * TUYA_BLE_SECURE_CONNECTION_WITH_ECC encrypt with ECDH + * TUYA_BLE_SECURE_CONNECTION_WTIH_PASSTHROUGH no encrypt + * TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION advanced encrypt(security chip ) with auth key + * @note : only choose one +*/ +#ifndef TUYA_BLE_SECURE_CONNECTION_TYPE +#define TUYA_BLE_SECURE_CONNECTION_TYPE TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY +#endif + +/* + * MACRO for advanced encryption,if 1 will perform two-way authentication on every connection,otherwise perform certification at the first registration. + */ +#if (TUYA_BLE_SECURE_CONNECTION_TYPE==TUYA_BLE_SECURE_CONNECTION_WITH_AUTH_KEY_ADVANCED_ENCRYPTION) + +#ifndef TUYA_BLE_ADVANCED_ENCRYPTION_AUTH_ON_CONNECT +#define TUYA_BLE_ADVANCED_ENCRYPTION_AUTH_ON_CONNECT 0 +#endif + +#ifndef TUYA_BLE_INCLUDE_CJSON_COMPONENTS +#define TUYA_BLE_INCLUDE_CJSON_COMPONENTS 1 +#endif + +#endif + +/* + * if 1 ,ble sdk will update mac address with with the address of the authorization information. + */ +#ifndef TUYA_BLE_DEVICE_MAC_UPDATE +#define TUYA_BLE_DEVICE_MAC_UPDATE 0 +#endif + +/* + * if 1 ,after update mac will reset. + */ +#ifndef TUYA_BLE_DEVICE_MAC_UPDATE_RESET +#define TUYA_BLE_DEVICE_MAC_UPDATE_RESET 0 +#endif + +/* + * if defined ,ble sdk use platform memory heap. + */ +#ifndef TUYA_BLE_USE_PLATFORM_MEMORY_HEAP +#define TUYA_BLE_USE_PLATFORM_MEMORY_HEAP 0 +#endif + + +/* + * if defined ,include UART module + */ +//#define TUYA_BLE_UART + + +/* + * if defined ,include product test module + */ +//#define TUYA_BLE_PRODUCTION_TEST + + +/* + * gatt mtu max sizes + */ + +#ifndef TUYA_BLE_DATA_MTU_MAX +#define TUYA_BLE_DATA_MTU_MAX 243 +#endif + +/* + * if defined ,enable sdk log output + */ + +#ifndef TUYA_BLE_LOG_ENABLE +#define TUYA_BLE_LOG_ENABLE 1 +#endif + +#ifndef TUYA_BLE_LOG_COLORS_ENABLE +#define TUYA_BLE_LOG_COLORS_ENABLE 0 +#endif + +#ifndef TUYA_BLE_LOG_LEVEL +#define TUYA_BLE_LOG_LEVEL TUYA_BLE_LOG_LEVEL_DEBUG +#endif + + +/* + * if defined ,enable app log output + */ + +#ifndef TUYA_APP_LOG_ENABLE +#define TUYA_APP_LOG_ENABLE 1 +#endif + +#ifndef TUYA_APP_LOG_COLORS_ENABLE +#define TUYA_APP_LOG_COLORS_ENABLE 0 +#endif + +#ifndef TUYA_APP_LOG_LEVEL +#define TUYA_APP_LOG_LEVEL TUYA_APP_LOG_LEVEL_DEBUG +#endif + +/* + * If it is 1, then sdk need to request beacon key from app when binding . + */ +#ifndef TUYA_BLE_BEACON_KEY_ENABLE +#define TUYA_BLE_BEACON_KEY_ENABLE 0 +#endif + +/* + * Enable the weather module. + */ +#ifndef TUYA_BLE_FEATURE_WEATHER_ENABLE +#define TUYA_BLE_FEATURE_WEATHER_ENABLE 0 +#endif + +/* + * Enable support the link layer encryption. + */ +#ifndef TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE +#define TUYA_BLE_LINK_LAYER_ENCRYPTION_SUPPORT_ENABLE 0 +#endif + +/* + * Whether to automatically perform a time request after the connection is established. + * - 0 Not request. + * - 1 Request cloud time. + * - 2 Request phone local time. + */ +#ifndef TUYA_BLE_AUTO_REQUEST_TIME_CONFIGURE +#define TUYA_BLE_AUTO_REQUEST_TIME_CONFIGURE 1 +#endif + + +//nv +/* The minimum size of flash erasure. May be a flash sector size. */ +#ifndef TUYA_NV_ERASE_MIN_SIZE +#define TUYA_NV_ERASE_MIN_SIZE (0x100) +#endif +/* the flash write granularity, unit: byte*/ +#ifndef TUYA_NV_WRITE_GRAN +#define TUYA_NV_WRITE_GRAN (4) +#endif +/* start address */ +#ifndef TUYA_NV_START_ADDR +#define TUYA_NV_START_ADDR 0 +#endif + +/* area size. */ +#ifndef TUYA_NV_AREA_SIZE +#define TUYA_NV_AREA_SIZE (4*TUYA_NV_ERASE_MIN_SIZE) +#endif + +/*MACRO for production test module*/ +#ifndef TUYA_BLE_APP_VERSION_STRING +#define TUYA_BLE_APP_VERSION_STRING "1.0" +#endif + +#ifndef TUYA_BLE_APP_BUILD_FIRMNAME_STRING +#define TUYA_BLE_APP_BUILD_FIRMNAME_STRING "tuya_ble_sdk_app_demo_xxx" +#endif + +#ifndef TUYA_BLE_APP_FIRMWARE_KEY +#define TUYA_BLE_APP_FIRMWARE_KEY "" +#endif + +#endif + + + diff --git a/apps/common/third_party_profile/tuya_protocol/tuya_ble_sdk_version.h b/apps/common/third_party_profile/tuya_protocol/tuya_ble_sdk_version.h new file mode 100644 index 0000000..a94f482 --- /dev/null +++ b/apps/common/third_party_profile/tuya_protocol/tuya_ble_sdk_version.h @@ -0,0 +1,38 @@ +/** + * \file tuya_ble_sdk_version.h + * + * \brief + */ +/* + * Copyright (C) 2014-2019, Tuya Inc., All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the 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. + * + * This file is part of tuya ble sdk + */ + + +#ifndef TUYA_BLE_SDK_VERSION_H__ +#define TUYA_BLE_SDK_VERSION_H__ + + +#define TUYA_BLE_SDK_VERSION_NUM 0x020000 +#define TUYA_BLE_SDK_VERSION_STR "2.0.0" + + +#endif + + + + diff --git a/apps/common/ui/lcd/lcd_ui_api.c b/apps/common/ui/lcd/lcd_ui_api.c new file mode 100644 index 0000000..2a7343c --- /dev/null +++ b/apps/common/ui/lcd/lcd_ui_api.c @@ -0,0 +1,684 @@ +#include "app_config.h" +#include "includes.h" +#include "ui/ui_api.h" +#include "ui/ui.h" +#include "typedef.h" + +#if (TCFG_UI_ENABLE &&TCFG_SPI_LCD_ENABLE && (!TCFG_SIMPLE_LCD_ENABLE)) + +#include "ui/ui_sys_param.h" +#include "ui/res_config.h" + +#define CURR_WINDOW_MAIN (0) + +#define UI_NO_ARG (-1) +#define UI_TASK_NAME "ui" + +enum { + UI_MSG_OTHER, + UI_MSG_KEY, + UI_MSG_TOUCH, + UI_MSG_SHOW, + UI_MSG_HIDE, + UI_TIME_TOUCH_RESUME, + UI_TIME_TOUCH_SUPEND, + UI_MSG_EXIT, +}; + + +struct ui_server_env { + u8 init: 1; + u8 key_lock : 1; + OS_SEM start_sem; + int (*touch_event_call)(void); + int touch_event_interval; + u16 timer; +}; + +int lcd_backlight_status(); +int lcd_backlight_ctrl(u8 on); +void ui_backlight_open(void); +void ui_backlight_close(void); +int lcd_sleep_ctrl(u8 enter); + +static struct ui_server_env __ui_display = {0}; + +int key_is_ui_takeover() +{ + return __ui_display.key_lock; +} + +void key_ui_takeover(u8 on) +{ + __ui_display.key_lock = !!on; +} + +static int post_ui_msg(int *msg, u8 len) +{ + int err = 0; + int count = 0; + if (!__ui_display.init) { + return -1; + } +__retry: + err = os_taskq_post_type(UI_TASK_NAME, msg[0], len - 1, &msg[1]); + + if (cpu_in_irq() || cpu_irq_disabled()) { + return err; + } + + if (err) { + if (!strcmp(os_current_task(), UI_TASK_NAME)) { + return err; + } + if (count > 20) { + return -1; + } + count++; + os_time_dly(1); + goto __retry; + } + return err; +} + + +//=================================================================================// +// @brief: 显示主页 应用于非ui线程显示主页使用 +//有针对ui线程进行处理,允许用于ui线程等同ui_show使用 +//=================================================================================// +int ui_show_main(int id) +{ + u32 rets;//, reti; + __asm__ volatile("%0 = rets":"=r"(rets)); + printf("__func__ %s %x\n", __func__, rets); + + static u32 mem_id[8] = {0}; + static OS_SEM sem;// = zalloc(sizeof(OS_SEM)); + int msg[8]; + int i; + + + if (id <= 0) { + if (mem_id[7 + id]) { + id = mem_id[7 + id]; + } else { + printf("[ui_show_main] id %d is invalid.\n", id); + return 0; + } + } + //else { + if (mem_id[7] != id) { + for (i = 1; i <= 7; i++) { + mem_id[i - 1] = mem_id[i]; + } + mem_id[7] = id; + } + //} + + printf("[ui_show_main] id = 0x%x\n", id); + + /* if (!strcmp(os_current_task(), UI_TASK_NAME)) { */ + /* ui_show(id); */ + /* return 0; */ + /* } */ + u8 need_pend = 0; + if (!(cpu_in_irq() || cpu_irq_disabled())) { + if (strcmp(os_current_task(), UI_TASK_NAME)) { + need_pend = 1; + } + } + msg[0] = UI_MSG_SHOW; + msg[1] = id; + msg[2] = 0; + + if (need_pend) { + os_sem_create(&sem, 0); + msg[2] = (int)&sem; + } + + if (!post_ui_msg(msg, 3)) { + if (need_pend) { + os_sem_pend(&sem, 0); + } + } + + + if (!lcd_backlight_status()) { + printf("backlight is close ... ui_show_main_now\n"); + ui_auto_shut_down_enable(); + ui_touch_timer_start(); + } + + + return 0; +} + + +//=================================================================================// +// @brief: 关闭主页 应用于非ui线程关闭使用 +//有针对ui线程进行处理,允许用于ui线程等同ui_hide使用 +//=================================================================================// +int ui_hide_main(int id) +{ + u32 rets;//, reti; + __asm__ volatile("%0 = rets":"=r"(rets)); + printf("__func__ %s %x\n", __func__, rets); + + + static OS_SEM sem;// = zalloc(sizeof(OS_SEM)); + int msg[8]; + + u8 need_pend = 0;; + if (!(cpu_in_irq() || cpu_irq_disabled())) { + if (strcmp(os_current_task(), UI_TASK_NAME)) { + need_pend = 1; + } + } + /* if (!strcmp(os_current_task(), UI_TASK_NAME)) { */ + /* if (CURR_WINDOW_MAIN == id) { */ + /* id = ui_get_current_window_id(); */ + /* } */ + /* ui_hide(id); */ + /* return 0; */ + /* } */ + msg[0] = UI_MSG_HIDE; + msg[1] = id; + msg[2] = 0; + + if (need_pend) { + os_sem_create(&sem, 0); + msg[2] = (int)&sem; + } + + if (!post_ui_msg(msg, 3)) { + if (need_pend) { + os_sem_pend(&sem, 0); + } + } + return 0; +} + +//=================================================================================// +// @brief: 关闭当前主页 灵活使用自动判断当前主页进行关闭 +//用户可以不用关心当前打开的主页,特别适用于一个任务使用了多个主页的场景 +//=================================================================================// +int ui_hide_curr_main() +{ + return ui_hide_main(CURR_WINDOW_MAIN); +} + + + +//=================================================================================// +// @brief: 应用往ui发送消息,ui主页需要注册回调函数关闭当前主页 +// //消息发送方法demo: UI_MSG_POST("test1:a=%4,test2:bcd=%4,test3:efgh=%4,test4:hijkl=%4", 1,2,3,4); +// 往test1、test2、test3、test4发送了字符为a、bcd、efgh、hijkl,附带变量为1、2、3、4 +// 每次可以只发一个消息,也可以不带数据例如:UI_MSG_POST("test1") +//=================================================================================// +int ui_server_msg_post(const char *msg, ...) +{ + int ret = 0; + int argv[9]; + argv[0] = UI_MSG_OTHER; + argv[1] = (int)msg; + va_list argptr; + va_start(argptr, msg); + for (int i = 2; i < 7; i++) { + argv[i] = va_arg(argptr, int); + } + va_end(argptr); + return post_ui_msg(argv, 9); +} + +//=================================================================================// +// @brief: 应用往ui发送key消息,由ui控件分配 +//=================================================================================// +int ui_key_msg_post(int key) +{ + u8 count = 0; + int msg[8]; + + if (key >= 0x80) { + return -1; + } + + msg[0] = UI_MSG_KEY; + msg[1] = key; + return post_ui_msg(msg, 2); +} + + +//=================================================================================// +// @brief: 应用往ui发送触摸消息,由ui控件分配 +//=================================================================================// +int ui_touch_msg_post(struct touch_event *event) +{ + int msg[8]; + int i = 0; + ui_auto_shut_down_modify(); + if (!lcd_backlight_status()) { + ui_backlight_open(); + return 0; + } + msg[0] = UI_MSG_TOUCH; + msg[1] = (int)NULL; + memcpy(&msg[2], event, sizeof(struct touch_event)); + return post_ui_msg(msg, sizeof(struct touch_event) / 4 + 2); +} + +//=================================================================================// +// @brief: 应用往ui发送触摸消息,由ui控件分配 +//=================================================================================// +int ui_touch_msg_post_withcallback(struct touch_event *event, void (*cb)(u8 finish)) +{ + int msg[8]; + int i = 0; + msg[0] = UI_MSG_TOUCH; + msg[1] = (int)cb; + memcpy(&msg[2], event, sizeof(struct touch_event)); + return post_ui_msg(msg, sizeof(struct touch_event) / 4 + 2); +} + + + +const char *str_substr_iter(const char *str, char delim, int *iter) +{ + const char *substr; + ASSERT(str != NULL); + substr = str + *iter; + if (*substr == '\0') { + return NULL; + } + for (str = substr; *str != '\0'; str++) { + (*iter)++; + if (*str == delim) { + break; + } + } + return substr; +} + + +static int do_msg_handler(const char *msg, va_list *pargptr, int (*handler)(const char *, u32)) +{ + int ret = 0; + int width; + int step = 0; + u32 arg = 0x5678; + int m[16]; + char *t = (char *)&m[3]; + va_list argptr = *pargptr; + + if (*msg == '\0') { + handler((const char *)' ', 0); + return 0; + } + + while (*msg && *msg != ',') { + switch (step) { + case 0: + if (*msg == ':') { + step = 1; + } + break; + case 1: + switch (*msg) { + case '%': + msg++; + if (*msg >= '0' && *msg <= '9') { + if (*msg == '1') { + arg = va_arg(argptr, int) & 0xff; + } else if (*msg == '2') { + arg = va_arg(argptr, int) & 0xffff; + } else if (*msg == '4') { + arg = va_arg(argptr, int); + } + } else if (*msg == 'p') { + arg = va_arg(argptr, int); + } + m[2] = arg; + handler((char *)&m[3], m[2]); + t = (char *)&m[3]; + step = 0; + break; + case '=': + *t = '\0'; + break; + case ' ': + break; + default: + *t++ = *msg; + break; + } + break; + } + msg++; + } + *pargptr = argptr; + return ret; +} + + +int ui_message_handler(int id, const char *msg, va_list argptr) +{ + int iter = 0; + const char *str; + const struct uimsg_handl *handler; + struct window *window = (struct window *)ui_core_get_element_by_id(id); + if (!window || !window->private_data) { + return -EINVAL; + } + handler = (const struct uimsg_handl *)window->private_data; + while ((str = str_substr_iter(msg, ',', &iter)) != NULL) { + for (; handler->msg != NULL; handler++) { + if (!memcmp(str, handler->msg, strlen(handler->msg))) { + do_msg_handler(str + strlen(handler->msg), &argptr, handler->handler); + break; + } + } + } + + return 0; +} + + + + +extern void sys_param_init(void); + +void ui_touch_timer_delete() +{ + if (!__ui_display.init) { + return; + } + +#if UI_WATCH_RES_ENABLE + local_irq_disable(); + if (!__ui_display.timer) { + local_irq_enable(); + return; + } + local_irq_enable(); +#endif + int msg[8]; + msg[0] = UI_TIME_TOUCH_SUPEND; + post_ui_msg(msg, 1); + +} + + +void ui_touch_timer_start() +{ + if (!__ui_display.init) { + return; + } + + local_irq_disable(); + if (__ui_display.timer) { + local_irq_enable(); + return; + } + local_irq_enable(); + int msg[8]; + msg[0] = UI_TIME_TOUCH_RESUME; + post_ui_msg(msg, 1); +} + +void ui_set_touch_event(int (*touch_event)(void), int interval) +{ + __ui_display.touch_event_call = touch_event; + __ui_display.touch_event_interval = interval; +} + + +void ui_auto_shut_down_enable(void); +void ui_auto_shut_down_disable(void); +static int ui_auto_shut_down_timer = 0; +void ui_backlight_open(void) +{ + + u32 rets;//, reti; + __asm__ volatile("%0 = rets":"=r"(rets)); + + if (!__ui_display.init) { + return; + } + + printf("__func__ %s %x\n", __func__, rets); + if (!lcd_backlight_status()) { + + + /* UI_MSG_POST("ui_lp_cb:exit=%4", 1); */ + /* sys_key_event_enable();//关闭按键 */ + ui_auto_shut_down_enable(); + //lcd_sleep_ctrl(0);//屏幕退出低功耗 +#if UI_WATCH_RES_ENABLE + ui_show_main(0);//恢复当前ui +#endif + ui_touch_timer_start(); + } +} + +void ui_backlight_close(void) +{ + + if (!__ui_display.init) { + return; + } + + if (lcd_backlight_status()) { + /* UI_MSG_POST("ui_lp_cb:enter=%4", 0); */ + /* sys_key_event_disable();//关闭按键 */ +#if UI_WATCH_RES_ENABLE + ui_hide_curr_main();//关闭当前页面 +#endif + ui_auto_shut_down_disable(); + ui_touch_timer_delete(); + } +} + + +void ui_auto_shut_down_enable(void) +{ +#if TCFG_UI_SHUT_DOWN_TIME + if (!__ui_display.init) { + return; + } + if (ui_auto_shut_down_timer == 0) { + ui_auto_shut_down_timer = sys_timeout_add(NULL, ui_backlight_close, TCFG_UI_SHUT_DOWN_TIME * 1000); + } +#endif +} + +void ui_auto_shut_down_disable(void) +{ +#if TCFG_UI_SHUT_DOWN_TIME + if (ui_auto_shut_down_timer) { + sys_timeout_del(ui_auto_shut_down_timer); + ui_auto_shut_down_timer = 0; + } +#endif +} + +void ui_auto_shut_down_modify(void) +{ +#if TCFG_UI_SHUT_DOWN_TIME + if (ui_auto_shut_down_timer) { + sys_timer_modify(ui_auto_shut_down_timer, TCFG_UI_SHUT_DOWN_TIME * 1000); + } +#endif +} + +static void ui_task(void *p) +{ + int msg[32]; + int ret; + struct element_key_event e = {0}; + + sys_param_init(); + /* struct ui_style style; */ + /* style.file = NULL; */ + + ui_framework_init(p); + /* ret = ui_set_style_file(&style); */ + /* if (ret) { */ + /* printf("ui task fail!\n"); */ + /* return; */ + /* } */ + __ui_display.init = 1; + os_sem_post(&(__ui_display.start_sem)); + struct touch_event *touch; + struct element_touch_event t; + + if (__ui_display.touch_event_call && __ui_display.touch_event_interval) { + __ui_display.timer = sys_timer_add((void *)NULL, __ui_display.touch_event_call, __ui_display.touch_event_interval); //注册按键扫描定时器 + } + + while (1) { + ret = os_taskq_pend(NULL, msg, ARRAY_SIZE(msg)); //500ms_reflash + if (ret != OS_TASKQ) { + continue; + } + + switch (msg[0]) { //action + case UI_MSG_EXIT: + os_sem_post((OS_SEM *)msg[1]); + os_time_dly(10000); + break; + case UI_MSG_OTHER: + ui_message_handler(ui_get_current_window_id(), (const char *)msg[1], (void *)&msg[2]); + break; + case UI_MSG_KEY: + e.value = msg[1]; + ui_event_onkey(&e); + break; + case UI_MSG_TOUCH: + touch = (struct touch_event *)&msg[2]; + t.event = touch->event; + t.pos.x = touch->x; + t.pos.y = touch->y; + /* printf("event = %d %d %d \n", t.event, t.pos.x, t.pos.y); */ + if (msg[1]) { + ((void(*)(u8))msg[1])(0); + } + ui_event_ontouch(&t); + if (msg[1]) { + ((void(*)(u8))msg[1])(1); + } + + break; + case UI_MSG_SHOW: + if (!lcd_backlight_status()) { + lcd_sleep_ctrl(0);//退出低功耗 + } + + if (msg[1] >> 24 == CTRL_TYPE_WINDOW && ui_get_current_window_id() > 0) { + printf("ui = %x show repeat.....\n", ui_get_current_window_id()); + ui_hide(ui_get_current_window_id()); + } + + ui_show(msg[1]); + if (msg[2]) { + os_sem_post((OS_SEM *)msg[2]); + } + break; + case UI_MSG_HIDE: + if (CURR_WINDOW_MAIN == msg[1]) { + ui_hide(ui_get_current_window_id()); + } else { + ui_hide(msg[1]); + } + + if (msg[2]) { + os_sem_post((OS_SEM *)msg[2]); + } + break; + case UI_TIME_TOUCH_RESUME: + lcd_backlight_ctrl(true); + if (__ui_display.timer) { + break; + } + if (__ui_display.touch_event_call && __ui_display.touch_event_interval) { + __ui_display.timer = sys_timer_add((void *)NULL, __ui_display.touch_event_call, __ui_display.touch_event_interval); //注册按键扫描定时器 + } + break; + case UI_TIME_TOUCH_SUPEND: + if (__ui_display.timer) { + sys_timer_del(__ui_display.timer); + __ui_display.timer = 0; + } + lcd_backlight_ctrl(false); + break; + default: + break; + } + } +} + + +extern int ui_file_check_valid(); +extern int ui_upgrade_file_check_valid(); + +int lcd_ui_init(void *arg) +{ + int err = 0; + + printf("open_resouece_start...\n"); + if (ui_file_check_valid()) { + printf("ui_file_check_valid fail!!!\n"); + if (ui_upgrade_file_check_valid()) { + printf("ui_upgrade_file_check_valid fail!!!\n"); + return -1; + } + } + + os_sem_create(&(__ui_display.start_sem), 0); + err = task_create(ui_task, arg, UI_TASK_NAME); + os_sem_pend(&(__ui_display.start_sem), 0); + return err; +} + +#else + +int key_is_ui_takeover() +{ + return 0; +} + +void key_ui_takeover(u8 on) +{ + +} + +int ui_key_msg_post(int key) +{ + return 0; +} + + +int ui_touch_msg_post(struct touch_event *event) +{ + return 0; +} + +int ui_touch_msg_post_withcallback(struct touch_event *event, void (*cb)(u8 finish)) +{ + return 0; +} + +void ui_touch_timer_delete() +{ + +} + +void ui_touch_timer_start() +{ + +} + +void ui_backlight_ctrl(u8 lcd_open_flag) +{ + +} +#endif + diff --git a/apps/common/ui/lcd_simple/lcd_simple_api.c b/apps/common/ui/lcd_simple/lcd_simple_api.c new file mode 100644 index 0000000..842eb99 --- /dev/null +++ b/apps/common/ui/lcd_simple/lcd_simple_api.c @@ -0,0 +1,309 @@ +#include "app_config.h" +#include "includes.h" +#include "ui/ui_api.h" +#include "ui/ui.h" +#include "typedef.h" +#include "ui/ui_simple/ui_res.h" +#include "font/font_textout.h" +#include "ui/lcd_simple/ui_mainmenu.h" + + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_UI_SIMPLE)) +#include "key_event_deal.h" +#include "app_task.h" +#include "font/language_list.h" + +extern u8 LCDBuff[8][128]; + +#define UI_TASK_NAME "ui" + + + +/* static const struct ui_dis_api *ui_dis_main[] = { */ +/* #if TCFG_APP_BT_EN */ +/* #endif */ +/* #if TCFG_APP_MUSIC_EN */ +/* #endif */ +/* #if TCFG_APP_FM_EN */ +/* #endif */ +/* #if TCFG_APP_RECORD_EN */ +/* #endif */ +/* #if TCFG_APP_LINEIN_EN */ +/* #endif */ +/* #if TCFG_APP_RTC_EN */ +/* #endif */ +/* #if TCFG_APP_PC_EN */ +/* #endif */ +/* #if TCFG_APP_SPDIF_EN */ +/* #endif */ +/* }; */ +/* */ + + +struct ui_display_env { + u8 init; + OS_SEM sem;//用来做模式初始化的信号量 + struct lcd_interface *lcd; + int main_menu;//当前主页 + int this_menu;//当前子页面 +}; + + +static struct ui_display_env __ui_display_env = {0}; + +#define __ui_display (&__ui_display_env) +#define __this (__ui_display) + +static int post_ui_msg(int *msg, u8 len) +{ + int count = 0; + int err = 0; + if (!__ui_display->init) { + return -1; + } + +__retry: + err = os_taskq_post_type(UI_TASK_NAME, msg[0], len - 1, &msg[1]); + if (cpu_in_irq() || cpu_irq_disabled()) { + return err; + } + if (err) { + + if (!strcmp(os_current_task(), UI_TASK_NAME)) { + return err; + } + + if (count > 10) { + return -1; + } + count++; + os_time_dly(1); + goto __retry; + } + return err; +} + + +// @brief: 应用往ui发送key消息,由ui控件分配 +//=================================================================================// +int ui_simple_key_msg_post(int key, int value) +{ + int msg[8]; + + /* if (key >= 0x80) { */ + /* return -1; */ + /* } */ + /* */ + msg[0] = Q_EVENT | SYS_KEY_EVENT; + msg[1] = key; + msg[2] = value; + return post_ui_msg(msg, 3); +} + + + + +void clear_lcd() +{ + if (!__this->init) { + return; + } + __this->lcd->clear_screen(0); +} + + +void draw_lcd(u8 start_page, u8 page_len) +{ + if (!__this->init) { + return; + } + __this->lcd->draw_page(&(LCDBuff[start_page][0]), start_page, page_len); +} + +void clear_lcd_area(u8 start_page, u8 end_page) +{ + if (end_page > 8) { + end_page = 8; + } + for (; start_page < end_page; start_page++) { + memset(&LCDBuff[start_page][0], 0x00, 128); + } +} + + + + + + +extern u8 app_get_curr_task(); + +extern void demo_simple_ui_mode(); + +static void ui_task_loop() +{ + while (1) { + switch (app_get_curr_task()) { + case APP_POWERON_TASK: + case APP_POWEROFF_TASK: + case APP_BT_TASK: + case APP_MUSIC_TASK: + case APP_FM_TASK: + case APP_RECORD_TASK: + case APP_LINEIN_TASK: + case APP_RTC_TASK: + case APP_PC_TASK: + case APP_SPDIF_TASK: + case APP_IDLE_TASK: + case APP_SLEEP_TASK: + case APP_SMARTBOX_ACTION_TASK: + demo_simple_ui_mode(); + break; + default: + printf(" no task \n"); + os_time_dly(100); + break; + } + } + + +} + +static void test_ui() +{ + /* ResShowPic(2,0,0); */ + /* ResShowPic(2,0,16); */ + /* ResShowMultiString(0,0,7); */ + struct font_info *info = font_open(NULL, Chinese_Simplified); + info->flags = FONT_SHOW_PIXEL;//显示 + info->text_height = 16; + info->text_width = 128;//设置显示窗口大小 + font_textout_utf8(info, "杰理科技", strlen("杰理科技"), 24, 0); + font_textout_utf8(info, "按ok按键开始", strlen("按ok按键开始"), 0, 16); + font_textout_utf8(info, "测试", strlen("测试"), 24, 32); + font_close(info); + ResShowPic(2, 0, 48); + ResShowPic(2, 110, 48); + draw_lcd(0, 8); + +} + + +static void __font_pix_copy(u8 *pix, struct rect *draw, int x, int y, + int height, int width, u8 color) +{ + + int i, j, h; + for (j = 0; j < (height + 7) / 8; j++) { /* 纵向8像素为1字节 */ + for (i = 0; i < width; i++) { + if (((i + x) >= draw->left) + && ((i + x) <= (draw->left + draw->width - 1))) { /* x在绘制区域,要绘制 */ + u8 pixel = pix[j * width + i]; + int hh = height - (j * 8); + if (hh > 8) { + hh = 8; + } + for (h = 0; h < hh; h++) { + if (((y + j * 8 + h) >= draw->top) + && ((y + j * 8 + h) <= (draw->top + draw->height - 1))) { /* y在绘制区域,要绘制 */ + u16 clr = pixel & BIT(h) ? color : !color; + if (clr) { + LCDBuff[j + (y + h) / 8][x + i] |= (BIT(h)); + } else { + LCDBuff[j + (y + h)][x + i] &= ~(BIT(h)); + } + } + } /* endof for h */ + + } + }/* endof for i */ + }/* endof for j */ +} + + + +void ui_simple_putchar(struct font_info *info, u8 *pixel, u16 width, u16 height, u16 x, u16 y) +{ + struct rect draw; + u8 color = 1; + draw.left = x; + draw.top = y; + draw.width = info->text_width; + draw.height = info->text_height; + __font_pix_copy(pixel, + (struct rect *)&draw, + (s16)x, + (s16)y, + height, + width, + color); +} + +static void half_second_tick() +{ + ui_simple_key_msg_post(MSG_HALF_SECOND, 0); + //半秒的事件 +} + +static void ui_task(void *p) +{ + __ui_display->init = 1; + + struct lcd_info info = {0}; + __this->lcd = lcd_get_hdl(); + printf("ui_task_run_Check ...\n"); + ASSERT(__this->lcd); + ASSERT(__this->lcd->init); + ASSERT(__this->lcd->get_screen_info); + ASSERT(__this->lcd->draw); + ASSERT(__this->lcd->set_draw_area); + ASSERT(__this->lcd->backlight_ctrl); + ASSERT(__this->lcd->clear_screen); + ASSERT(__this->lcd->draw_page); + + if (__this->lcd->init) { + __this->lcd->init(p); + } + + if (__this->lcd->backlight_ctrl) { + __this->lcd->backlight_ctrl(true); + } + + if (__this->lcd->get_screen_info) { + __this->lcd->get_screen_info(&info); + } + + printf("ui_platform_init :: [%d,%d,%d,%d]\n", 0, 0, info.width, info.height); + os_sem_post(&__ui_display->sem); + findtaskexist(APP_TASK_MAX_INDEX); + ResOpen("mnt/sdfile/res/menu.res"); + test_ui(); + sys_timer_add(NULL, half_second_tick, 500); //制作半秒的时机 + while (1) { + ui_task_loop(); + } +} + + + + + + +int lcd_ui_init(void *arg) +{ + int err = 0; + os_sem_create(&__ui_display->sem, 0); + err = task_create(ui_task, arg, UI_TASK_NAME); + os_sem_pend(&__ui_display->sem, 0); + return 0; +} + + + +#else + +int ui_simple_key_msg_post(int key, int value) +{ + return 0; +} + +#endif diff --git a/apps/common/ui/lcd_simple/ui.c b/apps/common/ui/lcd_simple/ui.c new file mode 100644 index 0000000..475b6e2 --- /dev/null +++ b/apps/common/ui/lcd_simple/ui.c @@ -0,0 +1,315 @@ +#include "app_config.h" +#include "includes.h" +#include "system/includes.h" +#include "fs/fs.h" +#include "ui/ui_simple/ui_res.h" +#include "ui/lcd_simple/ui.h" +#include "key_event_deal.h" + + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_UI_SIMPLE)) + +s8 MenuItemSelectOnNum; //当前屏幕活动page序号:0--(MENUITEMSUMPERSCR-1) +s8 CurrentScreenNum; //当前所处屏幕数,从0序号开始 +u8 NeedScreenSumViaItem; //菜单项目总数将占用屏幕的屏数 +u8 LaseScreenRemainMenuItem; //最后一屏只需显示的菜单项目数 + +#define LCDPAGE 8 +#define LCDCOLUMN 128 +#define SCR_WIDTH LCDCOLUMN +#define SCR_HEIGHT (LCDPAGE*8) + + + +extern u8 LCDBuff[8][128]; +extern u8 LanguageMode ; //语言模式,ID号 + +//滑动块// +u8 SetSlider(u8 start_x, u8 start_y, u8 length) +{ + start_x = start_x; + length = length; +// u8 x; +// if( (start_x>SCR_WIDTH-length+2) || (start_y>LCDPAGE) || (length>SLIDERLENGTH)) +// return false; +// +// LCDBuff[start_y][start_x]=0x3C; +// for(x=start_x+1; x SCR_WIDTH - 4) || (Start_y > LCDPAGE)) { + return false; + } + + for (x = Start_x; x < Start_x + 4; x++) { + LCDBuff[Start_y][x] = SlideBlockPixelBuf[x - Start_x]; + } + + return true; +} + +u8 SetSlideBlock1(u8 Start_x, u8 Start_y) +{ + if (ResShowPic(SLIDER_P, Start_x, Start_y * 8)) { + return true; + } else { + return false; + } +} + +u8 draw_slider(s8 currentpos, u8 slider_y_pos, u8 sliderlength) +{ + if ((currentpos > sliderlength) || (slider_y_pos > LCDPAGE) || (sliderlength > SLIDERLENGTH)) { //判断滑动条是否超出屏幕范围 + return false; + } + + if (currentpos <= 0) { //界限判断 + currentpos = 0; + } else if (currentpos > SLIDERLENGTH) { + currentpos = SLIDERLENGTH; + } + + //ClearLcdBuf_Page(slider_y_pos,1); + clear_lcd_area(slider_y_pos, slider_y_pos + 1); + SetSlider((SCR_WIDTH - sliderlength) / 2, slider_y_pos, sliderlength); + SetSlideBlock1((SCR_WIDTH - sliderlength) / 2 + currentpos, slider_y_pos); + draw_lcd(slider_y_pos, slider_y_pos + 1); + return true; +} + + + +u8 UI_Slider(FUN gslider) +{ + int msg[16] = {0}; + struct sys_event *event = NULL; + u8 currentpos; + u8 autoruntime = SLIDER_NOMOVE_TIMEEXIT; + + clear_lcd(); + currentpos = gslider(UI_SLIDER_CURR_VALUE); + draw_slider(currentpos, 5, SLIDERLENGTH); + draw_lcd(0, LCDPAGE); + + while (1) { + int ret = os_taskq_pend(NULL, msg, ARRAY_SIZE(msg)); //500ms_reflash + if (ret != OS_TASKQ) { + continue; + } + + if (msg[0] != 0) { + continue; + } + + + switch (msg[1]) { //action + case KEY_OK: + return 0x00; + + case KEY_UP: //HOLD + autoruntime = SLIDER_NOMOVE_TIMEEXIT; + clear_lcd_area(1, 4); + currentpos = gslider(UI_SLIDER_DEC); + draw_slider(currentpos, 5, SLIDERLENGTH); + draw_lcd(0, 8); + break; + + case KEY_DOWN: //HOLD + autoruntime = SLIDER_NOMOVE_TIMEEXIT; + clear_lcd_area(1, 4); + currentpos = gslider(UI_SLIDER_INC); + draw_slider(currentpos, 5, SLIDERLENGTH); + draw_lcd(0, 8); + break; + + case MSG_HALF_SECOND: + autoruntime-- ; + if (autoruntime == 0) { + return currentpos ; + //return 0xff; + } + break; + + default: + break; + } + } +} + + + +//进度条// +u8 UI_Progress(u8 currentpos, u8 progress_y_pos, u8 progresslength) +{ + u8 i; + if ((currentpos > progresslength) || (progress_y_pos > LCDPAGE) || (progresslength > 100)) { + return false; + } + memset(&LCDBuff[0][0], 0x00, sizeof(LCDBuff)); + //while(1) + { + SetProgress((SCR_WIDTH - progresslength) / 2, progress_y_pos, progresslength); + for (i = 1; i < currentpos + 1; i++) { + LCDBuff[progress_y_pos][(SCR_WIDTH - progresslength) / 2 + i] = 0xFF; + } + draw_lcd(0, LCDPAGE); + } + return true; +} + + + +u8 SetProgress(u8 start_x, u8 start_y, u8 length) +{ + u8 x; + if ((start_x > SCR_WIDTH - length + 2) || (start_y > LCDPAGE) || (length > 100)) { + return false; + } + + LCDBuff[start_y][start_x] = 0x7E; + for (x = start_x + 1; x < start_x + 1 + length + 1; x++) { + LCDBuff[start_y][x] = 0x81; + } + LCDBuff[start_y][start_x + length + 1] = 0x7E; + return true; +} + +void Scrol_String(u16 StringID) +{ + res_infor_t stringinfor; + u8 yy; + u32 sdimageaddr = 0; + static u32 ScrolOffset = 0; + //putchar(0x30+StringID); + //u16 StringID = menulist.ItemString[menulist.ActiveItemNum-1]; + + void *file = ResGetFp(); + if (!file) { + return; + } + + // if(!IsScrolString) return; + fseek(file, sizeof(res_head_t) + 2 * sizeof(res_entry_t) + BMPID_SUM * sizeof(res_infor_t) + ((StringID - 1)*LANGUAGEID_SUM + LanguageMode - 1)*sizeof(res_infor_t), SEEK_SET); + fread(file, (u8 *)&stringinfor, sizeof(res_infor_t)); + + stringinfor.dwOffset = ntohl(stringinfor.dwOffset); //res文件保存为大端模式,PC为小端模式,故加此三句,单片机下应该不加此三句 + stringinfor.wWidth = ntoh(stringinfor.wWidth); + + sdimageaddr = stringinfor.dwOffset; + + if (stringinfor.wWidth > SCR_WIDTH - MENUICONWIDTH - SCROLLBARWIDTH) { //字符串图片宽度 > 屏幕所能显示最大宽度(减去菜单Icon占用的宽度) + //需要进行滚屏处理 + for (yy = 0; yy < MENUITEMHEIGHT / 8 ; yy++) { + fseek(file, sdimageaddr + ScrolOffset, SEEK_SET); + fread(file, &LCDBuff[MenuItemSelectOnNum * 2 + yy][MENUICONWIDTH], (SCR_WIDTH - MENUICONWIDTH - SCROLLBARWIDTH)); + sdimageaddr += stringinfor.wWidth; + } + ScrolOffset += 1; + if (ScrolOffset + (SCR_WIDTH - MENUICONWIDTH - SCROLLBARWIDTH) >= stringinfor.wWidth) { + ScrolOffset = 0; + } + //TRACE("sdimageaddr: %d , ScrolOffset: %d \n", sdimageaddr, ScrolOffset ); + UI_MenuSelectOn(MenuItemSelectOnNum); + draw_lcd(0, LCDPAGE); + } +// else +// IsScrolString = false; +} + + + + + + +u8 SetScrollBar(u8 Start_x) +{ + u8 x, y; + u8 ScrollBarPixelBuf[8][6] = { 0xFC, 0x02, 0x01, 0x01, 0x02, 0xFC, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0x3F, 0x40, 0x80, 0x80, 0x40, 0x3F + }; + if (Start_x > SCR_WIDTH - 6) { //6为滚动条的象ç´ 宽度 + return false; + } + + for (x = Start_x; x < Start_x + 6; x++) { + for (y = 0; y < 8; y++) { + LCDBuff[y][x] = ScrollBarPixelBuf[y][x - Start_x]; + } + } + return true; +} + + +u8 TurnPixelReverse_Page(u8 startpage, u8 pagelen) +{ + u8 hnum, l; + + if ((startpage > 8) || (pagelen > 8)) { + return false; + } + + for (hnum = startpage; hnum < startpage + pagelen; hnum = hnum + 1) { + for (l = 0; l < SCR_WIDTH; l++) { + LCDBuff[hnum][l] = ~LCDBuff[hnum][l]; + } + } + return true; +} + +u8 TurnPixelReverse_Rect(u8 left, u8 top, u8 right, u8 bottom) +{ + //left、right取值范围:0--(SCR_WIDTH-1) ; top、bottom取值范围:0--(SCR_HEIGHT/8-1) + u8 hnum, l; + if ((left > SCR_WIDTH) || (top > SCR_HEIGHT) || (left >= right) || (top >= bottom)) { + return false; + } + + for (hnum = top; hnum < bottom + 1; hnum = hnum + 1) { + for (l = left; l < right + 1; l++) { + LCDBuff[hnum][l] = ~LCDBuff[hnum][l]; + } + } + return true; +} + +u8 ClearLcdBuf_Page(u8 startpage, u8 pagelen) +{ + u8 hnum, l; + + if ((startpage > 8) || (pagelen > 8)) { + return false; + } + + for (hnum = startpage; hnum < startpage + pagelen; hnum = hnum + 1) { + for (l = 0; l < SCR_WIDTH; l++) { + LCDBuff[hnum][l] = 0x00; + } + } + return true; +} + +#endif + + diff --git a/apps/common/ui/lcd_simple/ui_mainmenu.c b/apps/common/ui/lcd_simple/ui_mainmenu.c new file mode 100644 index 0000000..a2bcb3a --- /dev/null +++ b/apps/common/ui/lcd_simple/ui_mainmenu.c @@ -0,0 +1,254 @@ +#include "app_config.h" +#include "includes.h" +#include "system/includes.h" +#include "fs/fs.h" +#include "ui/ui_simple/ui_res.h" +#include "ui/lcd_simple/ui_mainmenu.h" +#include "ui/lcd_simple/ui.h" +#include "key_event_deal.h" +#include "app_task.h" +#include "app_msg.h" + + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_UI_SIMPLE)) + + +/* APP_POWERON_TASK = 1, */ +/* APP_POWEROFF_TASK = 2, */ +/* APP_BT_TASK = 3, */ +/* APP_MUSIC_TASK = 4, */ +/* APP_FM_TASK = 5, */ +/* APP_RECORD_TASK = 6, */ +/* APP_LINEIN_TASK = 7, */ +/* APP_RTC_TASK = 8, */ +/* APP_SLEEP_TASK = 9, */ +/* APP_IDLE_TASK = 10, */ +/* APP_PC_TASK = 11, */ +/* APP_SPDIF_TASK = 12, */ +/* APP_WATCH_UPDATE_TASK = 13, */ +/* APP_SMARTBOX_ACTION_TASK = 14, */ +/* */ +const TASKSTRUCT taskbuf[TASKTOTLE] = { + {"none", 0xffff, 0xffff, 0,},//0 + {"poweron", 0xffff, 0xffff, 0,},//1 + {"powerff", 0xffff, 0xffff, 0,},//2 + {"bt", FM, t_fm, 1,},//3 + {"music", MUSIC1, t_music, 1,},//4 + {"fm", FM, t_fm, 1,},//5 + {"record", RECORD1, t_record, 1,},//6 + {"linein", LINEIN1, alarm1, 1,},//7 + {"rtctime", TOOLP, fm_rtue, 1,},//8 + {"end", 0xffff, 0xffff, 0,},//必须 以end 结束 +}; + +u8 taskindex[TASKTOTLE] = {0xff, 0, 1, 2, 3, 4, 5, 0xff, 0xff, 6, 7}; +u8 taskshow[TASKTOTLE]; + +u8 g_taskshowsum; + +#define LCDPAGE 8 +#define LCDCOLUMN 128 +#define SCR_WIDTH LCDCOLUMN +#define SCR_HEIGHT (LCDPAGE*8) + + +extern u8 LCDBuff[LCDPAGE][LCDCOLUMN]; + +void findtaskexist(u8 tasksum) +{ + u8 i; + u8 ret; + u8 n = 0; + u8 appnumber = 0; + u16 taskexist = 0x0001; //必有 main task + u8 taskfile[16]; + + memset(&taskindex, 0xff, sizeof(taskindex)); + for (i = 1; i < tasksum; i++) { //不用检查main task 0 + if (!strcmp(taskbuf[i].taskname, "end")) { + break; + } + taskexist |= BIT(i); + if (taskbuf[i].showflag == 1) { //该task需显性显示 + taskshow[n] = i; + taskindex[i] = appnumber++; + n++; + } + } + g_taskshowsum = n; +} + +u8 Set_LeftTriangle(u8 Start_x, u8 Start_y) //左三角标 +{ + u8 x, y; + u8 LeftTrianglePixelBuf[2][3] = {0x80, 0xC0, 0xE0, + 0x00, 0x01, 0x03 + }; + + if ((Start_x > SCR_WIDTH - 3) || (Start_y > LCDPAGE)) { + return false; + } + + for (x = Start_x; x < Start_x + 3; x++) { + for (y = Start_y; y < Start_y + 2; y++) { + LCDBuff[y][x] = LeftTrianglePixelBuf[y - Start_y][x - Start_x]; + } + } + return true; +} + +u8 Set_RightTriangle(u8 Start_x, u8 Start_y) //右三角标 +{ + u8 x, y; + u8 LeftTrianglePixelBuf[2][3] = {0xE0, 0xC0, 0x80, + 0x03, 0x01, 0x00 + }; + + if ((Start_x > SCR_WIDTH - 3) || (Start_y > LCDPAGE)) { + return false; + } + + for (x = Start_x; x < Start_x + 3; x++) { + for (y = Start_y; y < Start_y + 2; y++) { + LCDBuff[y][x] = LeftTrianglePixelBuf[y - Start_y][x - Start_x]; + } + } + return true; +} +void draw_mainmenu(s8 scr_index, s8 start_task_num) +{ + u8 n; + u8 mem_start_task_num; + mem_start_task_num = start_task_num; + clear_lcd(); + for (n = 0; n < (g_taskshowsum < SCREENSHOWTASKSUM ? g_taskshowsum : SCREENSHOWTASKSUM); n++) { + if (n == scr_index) { + clear_lcd_area(0, 1); + ResShowMultiString(0, 0, taskbuf[taskshow[start_task_num]].strID); + ResShowPic(taskbuf[taskshow[start_task_num]].bmpID + 1, n * 24 + 4, 2 * 8); //选中的图标 + } else { + ResShowPic(taskbuf[taskshow[start_task_num]].bmpID + 0, n * 24 + 4, 2 * 8); //未选中的图标 + } + start_task_num++; + } + + if (mem_start_task_num != (g_taskshowsum - (g_taskshowsum < SCREENSHOWTASKSUM ? g_taskshowsum : SCREENSHOWTASKSUM))) { + Set_RightTriangle((SCR_WIDTH - 1) - 3, 3); + } + if (mem_start_task_num != 0) { + Set_LeftTriangle(0, 3); + } + draw_lcd(0, 8) ; +} + +u8 UI_mainmenu(s8 apprun) +{ + u8 need_draw = 0 ; + u8 autoruntime = AUTORUNTIMEMAX; + int msg[16] = {0}; + + s8 task_index; //任务索引号 + s8 screen_index; //当前屏幕显示高亮图标的索引号0-4 + s8 start_task_index; //当前屏幕显示的第一个任务图标的索引号 + s8 mem_task_app; //传递进来的任务号 + + mem_task_app = apprun;//6 1 + task_index = taskindex[apprun]; //5 0 +// deg_string("\n task_index init: "); +// printf_u8(task_index); + if (task_index <= (g_taskshowsum < SCREENSHOWTASKSUM ? g_taskshowsum : SCREENSHOWTASKSUM)) { + if (task_index == SCREENSHOWTASKSUM) { + screen_index = task_index - 1; + start_task_index = task_index - ((g_taskshowsum < SCREENSHOWTASKSUM ? g_taskshowsum : SCREENSHOWTASKSUM) - 1); + //task_index = task_index-1; + } else { + screen_index = task_index; + start_task_index = 0; + } + } else { + screen_index = (g_taskshowsum < SCREENSHOWTASKSUM ? g_taskshowsum : SCREENSHOWTASKSUM) - 1; //4 + start_task_index = task_index - ((g_taskshowsum < SCREENSHOWTASKSUM ? g_taskshowsum : SCREENSHOWTASKSUM) - 1); //1 + } + draw_mainmenu(screen_index, start_task_index); + while (1) { + + if (need_draw != 0) { + draw_mainmenu(screen_index, start_task_index) ; + need_draw = FALSE; + draw_lcd(0, 8) ; + autoruntime = AUTORUNTIMEMAX; + } + + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + printf("ui %s key = %d value = %x\n", __func__, msg[1], msg[2]); + switch (msg[1]) { + case KEY_OK: + return taskshow[task_index]; + case KEY_UP: + task_index--; + if (task_index < 0) { + task_index = 0; + } + + screen_index--; + if (screen_index < 0) { + start_task_index--; + if (start_task_index < 0) { + start_task_index = 0; + } + } + if (screen_index < 0) { + screen_index = 0; + } + + // deg_string("\n task_index: "); + // printf_u8(task_index); + // deg_string("\n screen_index: "); + // printf_u8(screen_index); + need_draw = TRUE; + break; + + + case KEY_DOWN: + task_index++; + if (task_index > (g_taskshowsum - 1)) { + task_index = g_taskshowsum - 1 ; + } + + screen_index++; + if (screen_index > (g_taskshowsum < SCREENSHOWTASKSUM ? g_taskshowsum : SCREENSHOWTASKSUM) - 1) { + start_task_index++; + if (start_task_index > g_taskshowsum - (g_taskshowsum < SCREENSHOWTASKSUM ? g_taskshowsum : SCREENSHOWTASKSUM)) { + start_task_index = g_taskshowsum - (g_taskshowsum < SCREENSHOWTASKSUM ? g_taskshowsum : SCREENSHOWTASKSUM); + } + } + if (screen_index > ((g_taskshowsum < SCREENSHOWTASKSUM ? g_taskshowsum : SCREENSHOWTASKSUM) - 1)) { + screen_index = (g_taskshowsum < SCREENSHOWTASKSUM ? g_taskshowsum : SCREENSHOWTASKSUM) - 1; + } + + + // deg_string("\n task_index: "); + // printf_u8(task_index); + // deg_string("\n screen_index: "); + // printf_u8(screen_index); + need_draw = TRUE; + break; + + case MSG_HALF_SECOND: + autoruntime-- ; + if (autoruntime == 0) { + //return taskshow[mem_task_app-1]; + clear_lcd(); + return 0xff; + } + break ; + + default: + break; + } + } + } +} +#endif diff --git a/apps/common/ui/led7/led7_ui_api.c b/apps/common/ui/led7/led7_ui_api.c new file mode 100644 index 0000000..27e8011 --- /dev/null +++ b/apps/common/ui/led7/led7_ui_api.c @@ -0,0 +1,447 @@ +#include "app_config.h" +#include "includes.h" +#include "ui/ui_api.h" +#include "clock_cfg.h" + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_LED7)) +#define UI_DEBUG_ENABLE +#ifdef UI_DEBUG_ENABLE +#define ui_debug(fmt, ...) printf("[UI] "fmt, ##__VA_ARGS__) +#define ui_log(fmt, ...) printf("[UI] "fmt, ##__VA_ARGS__) +#define ui_error(fmt, ...) printf("[UI error] "fmt, ##__VA_ARGS__) +#else +#define ui_debug(...) +#define ui_log(...) +#define ui_error(...) +#endif + +#define UI_NO_ARG (-1) +#define UI_TASK_NAME "ui" + + + +struct ui_display_env { + u8 init; + OS_SEM sem;//用来做模式初始化的信号量 + u16 tmp_menu_ret_cnt;//子页面显示计数 + u16 auto_reflash_time;//自动刷新计数 + u16 time_count;//计数器 + void (*timeout_cb)(int);//回调函数 + int main_menu;//当前主页 + int this_menu;//当前子页面 + LCD_API *ui_api;//显示api + const struct ui_dis_api *ui;//指向具体模式的处理函数 + void *private;//页面open时候传入的函数 +}; + +enum { + UI_MSG_REFLASH,//刷新主页 + UI_MSG_OTHER,//显示子页面 + UI_MSG_STRICK,//定时器事件 + UI_MSG_MENU_SW,//页面切换 + UI_MSG_MENU_CLOSE,//页面关闭 + UI_MSG_EXIT,//模式退出 +}; + + + + +static const struct ui_dis_api *ui_dis_main[] = { +#if TCFG_APP_BT_EN + &bt_main, +#endif +#if TCFG_APP_MUSIC_EN + &music_main, +#endif +#if TCFG_APP_FM_EN + &fm_main, +#endif +#if TCFG_APP_RECORD_EN + &record_main, +#endif +#if TCFG_APP_LINEIN_EN + &linein_main, +#endif +#if TCFG_APP_RTC_EN + &rtc_main, +#endif +#if TCFG_APP_PC_EN + &pc_main, +#endif +#if TCFG_APP_SPDIF_EN + /* &idle_main, */ +#endif + &idle_main, +}; + + + + +#define list_for_each_ui_main(c) \ + int ui_list = 0;\ + for (c = ui_dis_main[ui_list]; ui_list init) { + return -1; + } + +__retry: + err = os_taskq_post_type(UI_TASK_NAME, msg[0], len - 1, &msg[1]); + if (cpu_in_irq() || cpu_irq_disabled()) { + return err; + } + if (err) { + + if (!strcmp(os_current_task(), UI_TASK_NAME)) { + return err; + } + + if (count > 10) { + return -1; + } + count++; + os_time_dly(1); + goto __retry; + } + return err; +} +//=================================================================================// +// API 函数 +//=================================================================================// + +//=================================================================================// +// @brief: 非主界面显示 +// @input: +// 1)tmp_menu: 要显示的非主界面 +// 2)ret_time: 持续时间ms, 返回主界面 +// 3)arg: 显示参数 +// 4)子菜单被打断或者时间到了 +//=================================================================================// +void ui_set_tmp_menu(u8 app_menu, u16 ret_time, s32 arg, void (*timeout_cb)(u8 menu)) +{ + + int msg[6]; + msg[0] = UI_MSG_OTHER; + msg[1] = app_menu; + msg[2] = arg; + msg[3] = (int)((ret_time + 99) / 100); + msg[4] = (int)timeout_cb; + post_ui_msg(msg, 5); +} + +//进入app时设置一次, 设置主界面 +void ui_set_main_menu(enum ui_menu_main menu) +{ + int msg[2]; + msg[0] = UI_MSG_MENU_SW; + msg[1] = menu; + post_ui_msg(msg, 2); +} +//进入app时设置一次, 设置主界面 +void ui_close_main_menu() +{ + int msg[1]; + msg[0] = UI_MSG_MENU_CLOSE; + post_ui_msg(msg, 1); +} + + + + +//=================================================================================// +// @brief: 主界面显示刷新 +// @input: +// 1)break_in : 1:打断显示 0:不打断显示 +// 打断显示可以理解为当前正在显示临时页面并非主页,例如设置页面,打断显示可以打断当前显示,恢复主页刷新 +// 实例化函数:ui_menu_reflash_action +//=================================================================================// +void ui_menu_reflash(u8 break_in)//break_in 是否打断显示,例如显示设置过程中需要刷新新界面。是是否打断设置界面显示 +{ + int msg[2]; + msg[0] = UI_MSG_REFLASH; + msg[1] = !!break_in; + post_ui_msg(msg, 2); +} + +//=================================================================================// +// @brief: 自动刷新时间 +// @input: 自动刷新主页 +//=================================================================================// +void ui_set_auto_reflash(u32 msec)//自动刷新主页 +{ + if (__ui_display->init) { + __ui_display->auto_reflash_time = (msec + 99) / 100; + } + +} + + +//=================================================================================// +// @brief: led7 复用io 推灯 api +// // @input: +// 1)app_menu 需要显示的灯id +// 2)on 开关灯 +// 3)phase 相位,即先低电平 后高电平 或者先高电平后低电平 +// 4)高电平时间 单位2ms +// 5)周期时间 单位2ms +//=================================================================================// + +void ui_set_led(u8 app_menu, u8 on, u8 phase, u16 highlight, u16 period)// +{ +#if TCFG_UI_LED1888_ENABLE + extern void LED1888_show_led0(u32 arg); + extern void LED1888_show_led1(u32 arg); + u32 arg = 0; + arg = (!!on) << 31 | (!!phase) << 30 | highlight << 15 | (period - highlight); + + if (period >= highlight) { + if (app_menu == MENU_LED0) { + if (arg) { + LED1888_show_led0(arg); + } else { + LED1888_show_led0(0); + } + return; + } else if (app_menu == MENU_LED1) { + if (arg) { + LED1888_show_led1(arg); + } else { + LED1888_show_led1(0); + } + return; + } + + } +#endif +} + +u8 ui_get_app_menu(u8 type) +{ + if (!__ui_display->ui_api) { + return 0; + } + if (type) { + return __ui_display->main_menu; + } else { + return __ui_display->this_menu; + } + return 0; +} + + +static void ui_strick_loop() +{ + int msg[1]; + if (__ui_display->init) { + if (__ui_display->auto_reflash_time && ((++__ui_display->time_count) >= __ui_display->auto_reflash_time)) { + ui_menu_reflash(0);//自动刷新主页 + __ui_display->time_count = 0; + } + + if (__ui_display->tmp_menu_ret_cnt && ((--__ui_display->tmp_menu_ret_cnt) == 0)) { + msg[0] = UI_MSG_STRICK; + post_ui_msg(msg, 1); + } + } +} + +//=================================================================================// +// 实例化函数 +//=================================================================================// + +//=================================================================================// +//=================================================================================// +// @brief: 主界面显示实例化函数 +// api 对应 ui_menu_reflash +//=================================================================================// +static void __ui_menu_reflash_action(u8 break_in) +{ + if (break_in && (__ui_display->this_menu != MENU_MAIN)) {//如果需要打断显示,先判断当前是否主页,不是主页 + if (__ui_display->timeout_cb) {//判断是否有打断显示回调函数,有则告诉应用,当前页面已经被打断 + __ui_display->timeout_cb(__ui_display->this_menu); + __ui_display->timeout_cb = NULL; + } + } else if (__ui_display->this_menu != MENU_MAIN) {//不支持打断显示 + return ; + } + if (__ui_display->ui && __ui_display->ui->ui_main) { + __ui_display->ui->ui_main(__ui_display->ui_api, __ui_display->private); //刷新主页 + } + __ui_display->this_menu = MENU_MAIN; +} + + +//=================================================================================// +// @brief: 子界面显示实例化函数 +// api 对应 ui_set_tmp_menu +//=================================================================================// +static void __ui_user_action(int menu, u16 ret_time, u32 arg, void (*timeout_cb)(u8 menu)) +{ + int ret = false; + if (menu != __ui_display->this_menu) {//如果显示的子页面和当前不一样,则回调注册的回调函数 + if (__ui_display->timeout_cb) { + __ui_display->timeout_cb(__ui_display->this_menu); + __ui_display->timeout_cb = NULL; + } + } + __ui_display->tmp_menu_ret_cnt = ret_time; + __ui_display->timeout_cb = timeout_cb; + __ui_display->this_menu = menu; + if (__ui_display->ui && __ui_display->ui->ui_user) {//判断使用有指向的主页,有的则优先主页处理 + ret = __ui_display->ui->ui_user(__ui_display->ui_api, __ui_display->private, menu, arg); + } + if (ret != true) { + ui_common(__ui_display->ui_api, __ui_display->private, menu, arg); //公共显示 + } +} + +//=================================================================================// +// @brief: 主界面显示实例化函数 +//=================================================================================// +static void __ui_main_close_action() +{ + __ui_display->auto_reflash_time = 0;//停止自动计数 + __ui_display->tmp_menu_ret_cnt = 0; + __ui_display->time_count = 0; + + if (__ui_display->timeout_cb) {//检测回调 + __ui_display->timeout_cb(__ui_display->this_menu); + __ui_display->timeout_cb = NULL; + } + if (__ui_display->ui && __ui_display->ui->close) {//掉用关闭 + __ui_display->ui->close(__ui_display->ui_api, __ui_display->private); + __ui_display->ui = NULL; + __ui_display->private = NULL; + } + __ui_display->main_menu = 0; + __ui_display->this_menu = MENU_MAIN; +} + + + + + +//=================================================================================// +// @brief: 主界面显示实例化函数 +// api 对应 ui_set_tmp_menu +//=================================================================================// +static void __ui_main_open_action(int cur_main) +{ + const struct ui_dis_api *ui; + __ui_main_close_action(); + list_for_each_ui_main(ui) { + if (ui->ui == cur_main) { + __ui_display->ui = ui; + if (ui->open) { + __ui_display->private = ui->open((void *)__ui_display->ui_api); + } + if (ui->ui_main) { + ui->ui_main((void *)__ui_display->ui_api, __ui_display->private); + } + break; + } + } + __ui_display->main_menu = cur_main; + __ui_display->this_menu = MENU_MAIN; +} + + + + +static void __ui_strick_action() +{ + if (!__ui_display->tmp_menu_ret_cnt && __ui_display->main_menu) { + if (__ui_display->timeout_cb) { + __ui_display->timeout_cb(__ui_display->this_menu); + __ui_display->timeout_cb = NULL; + } + if (__ui_display->ui && __ui_display->ui->ui_main) { + __ui_display->ui->ui_main(__ui_display->ui_api, __ui_display->private); + } + __ui_display->this_menu = MENU_MAIN; + } +} + + +static void ui_task(void *p) +{ + int msg[32]; + int ret; + __ui_display->init = 1; + os_sem_post(&__ui_display->sem); + sys_timer_add(NULL, ui_strick_loop, 100); //500ms + while (1) { + ret = os_taskq_pend(NULL, msg, ARRAY_SIZE(msg)); //500ms_reflash + if (ret != OS_TASKQ) { + continue; + } + switch (msg[0]) { //action + case UI_MSG_EXIT: + os_sem_post((OS_SEM *)msg[1]); + os_time_dly(10000); + break; + case UI_MSG_STRICK: + __ui_strick_action(); + break; + case UI_MSG_REFLASH: + __ui_menu_reflash_action(!!msg[1]); + break; + case UI_MSG_OTHER: + __ui_user_action(msg[1], msg[3], msg[2], (void (*)(u8))msg[4]); + break; + case UI_MSG_MENU_SW: + __ui_main_open_action(msg[1]); + break; + case UI_MSG_MENU_CLOSE: + __ui_main_close_action(); + break; + + default: + break; + } + } +} + + + + + +int led7_ui_init(const struct ui_devices_cfg *ui_cfg) +{ + + int err = 0; + clock_add(DEC_UI_CLK); +#if TCFG_UI_LED1888_ENABLE + if (ui_cfg->type == LED_7) { + void *led_1888_init(const struct led7_platform_data * _data); + __ui_display->ui_api = (LCD_API *)led_1888_init(ui_cfg->private_data); + } +#endif + +#if TCFG_UI_LED7_ENABLE + void *led7_init(const struct led7_platform_data * _data); + __ui_display->ui_api = (LCD_API *)led7_init(ui_cfg->private_data); +#endif + + if (__ui_display->ui_api == NULL) { + return -ENODEV; + } + os_sem_create(&__ui_display->sem, 0); + err = task_create(ui_task, NULL, UI_TASK_NAME); + os_sem_pend(&__ui_display->sem, 0); + return 0; +} + + + +#endif /* #if TCFG_UI_ENABLE */ diff --git a/apps/common/update/norflash_ufw_update.c b/apps/common/update/norflash_ufw_update.c new file mode 100644 index 0000000..8ee1f45 --- /dev/null +++ b/apps/common/update/norflash_ufw_update.c @@ -0,0 +1,318 @@ +#include "app_config.h" +#include "typedef.h" +#include "fs.h" +#include "norflash.h" +#include "spi/nor_fs.h" +#include "rec_nor/nor_interface.h" +#include "update_loader_download.h" +#include "update.h" + +typedef struct _nor_update_info { + u32 src_file_addr; + u32 src_file_len; +} nor_update_info_parm; + +static nor_update_info_parm nor_update_info; +static void *update_fp = NULL; + +//=============================================================// +// 外挂NorFlash升级V2版本 // +/* APP NorFlash 升级模型(APP_NORFLASH_UFW_UPDATA) + ________ ________ ________ + | | | | | | + | | (1) | | (2) | | + | APP | ---------> |NorFlash| --------> | CHIP | + | | nor_update.ufw | | nor_update.ufw | | + |________| |________| |________| + +NOTE: + 关于流程(1): 该流程为从远端获取升级文件(nor_update.ufw)写到外置flash某个位置, nor_update.ufw文件在外置flash中需要保证在物理上连续存储, 注意该流程为用户在自己定义的ota中完成, 不在本文件流程中, 需要用户自己开发; + 关于流程(2): 该流程为本文件实现的升级流程, 改动较少(主要改动为跟读取外置flash的硬件相关接口), 在用户完成流程(1)后(nor_update.ufw已存在外置flash), 可随时调用norflash_update_ufw_init函数启动升级; + + */ +//============================================================// + +#define NORFLASH_UFW_UPDATE_VERIFY_ALL_FILE 1 //1: 进升级前校验用户写到外置flash的nor_update.ufw文件; 0: 不校验 + +extern const int support_norflash_ufw_update_en; + +//=========================================================// +// norflash 操作接口 +//=========================================================// + +static u32 user_remote_base_addr = 0; // +static u32 user_remote_cur_offset = 0; +static void *dev_ptr = NULL; +/*----------------------------------------------------------------------------*/ +/**@brief 获取升级文件在外flash存放位置和长度 + @param buf, 结构为nor_update_info + @return void + @note +*/ +/*----------------------------------------------------------------------------*/ +static void get_nor_update_info_param(void *buf) +{ + if (buf) { + printf("src_file_addr = 0x%x", nor_update_info.src_file_addr); //外挂flash存放flash.bin文件物理地址 + printf("src_file_len = 0x%x", nor_update_info.src_file_len); //外挂flash存放flash.bin文件物理地址 + memcpy(buf, (u8 *)&nor_update_info, sizeof(nor_update_info)); + } +} + + + +static u32 user_remote_device_get_cur_addr(void) +{ + return (user_remote_base_addr + user_remote_cur_offset); +} +/*----------------------------------------------------------------------------*/ +/**@brief 打开外置flash升级文件(初始化外置flash读接口) + @param void + @return 0: 打开错误; + 非0: 打开成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static u16 norflash_ufw_update_f_open(void) +{ + printf("%s", __func__); + + dev_ptr = dev_open("res_nor", NULL); + if (dev_ptr) { + printf("open dev succ 0x%x", dev_ptr); + } else { + printf("open dev fail"); + return 0; + } + + return 1; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 读取外置flash升级文件内容 + @param fp: NULL, 保留 + @param buff: 读取数据buf + @param len: 读取数据长度 + @return len: 读取成功 + (-1): 读取出错 + @note +*/ +/*----------------------------------------------------------------------------*/ +static u16 norflash_ufw_update_f_read(void *fp, u8 *buff, u16 len) +{ + //TODO: + int rlen = 0; + if (dev_ptr) { + wdt_clear(); + rlen = dev_bulk_read(dev_ptr, buff, user_remote_device_get_cur_addr(), len); + //printf("%s: addr = 0x%x, rlen = %d, dev_ptr = 0x%x", __func__, user_remote_device_get_cur_addr(), rlen, dev_ptr); + user_remote_cur_offset += len; + //put_buf(buff, 128); + } + + return len; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 偏移升级文件地址 + @param fp: NULL, 保留 + @param type: SEEK_SET, SEEK_CUR, SEEK_END + @param offset: 偏移长度 + @return 0: 操作成功 + 非0: 操作出错 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int norflash_ufw_update_f_seek(void *fp, u8 type, u32 offset) +{ + //TODO: + //printf("%s", __func__); + if (type == SEEK_SET) { + user_remote_cur_offset = offset; + } else { + ASSERT(0, "ONLY SUPPORT SEEK_SET"); + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭外置flash读操作 + @param err: 传入升级状态 + @return 0: 操作成功 + 非0: 操作出错 + @note +*/ +/*----------------------------------------------------------------------------*/ +static u16 norflash_ufw_update_f_stop(u8 err) +{ + //TODO: + printf("%s, err = 0x%x", __func__, err); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 通知升级文件大小 + @param priv: NULL, 保留 + @param size: 待升级文件大小 + @return 0: 操作成功 + 非0: 操作出错 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int norflash_ufw_update_notify_update_content_size(void *priv, u32 size) +{ + //TODO: + printf("%s: size: 0x%x", __func__, size); + + return 0; +} + + +static const update_op_api_t norflash_ufw_update_op_api = { + .ch_init = NULL, + .f_open = norflash_ufw_update_f_open, + .f_read = norflash_ufw_update_f_read, + .f_seek = norflash_ufw_update_f_seek, + .f_stop = norflash_ufw_update_f_stop, + .notify_update_content_size = norflash_ufw_update_notify_update_content_size, +}; + +/*----------------------------------------------------------------------------*/ +/**@brief 外置flash升级文件校验完成, 会调用该函数 + @param priv: 回调传入参数 + @param type: 升级模式 + @param cmd: 1) UPDATE_LOADER_OK 外置flash升级文件校验成功, cpu复位, 启动内置flash固件升级流程 + 2) UPDATE_LOADER_ERR 外置flash升级文件校验失败 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void norflash_ufw_update_end_callback(void *priv, int type, u8 cmd) +{ + //TODO: + printf("%s: type: 0x%x, cmd = 0x%x", __func__, type, cmd); + + if (type == USER_NORFLASH_UFW_UPDATA) { + if (cmd == UPDATE_LOADER_OK) { + printf("soft reset to update >>>"); + cpu_reset(); //复位让主控进入升级内置flash + } + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 填充升级结构体私有参数 + @param p: 升级结构体指针(UPDATA_PARM) + @return void + @note +*/ +/*----------------------------------------------------------------------------*/ +static void norflash_ufw_update_private_param_fill(UPDATA_PARM *p) +{ + get_nor_update_info_param(p->parm_priv); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 固件升级校验流程完成, cpu reset跳转升级新的固件 + @param type: 升级类型 + @return void + @note +*/ +/*----------------------------------------------------------------------------*/ +static void norflash_ufw_update_before_jump_handle(int type) +{ + printf("soft reset to update >>>"); + cpu_reset(); //复位让主控进入升级内置flash +} + +/*----------------------------------------------------------------------------*/ +/**@brief 外置norflash升级流程状态处理 + @param type: 升级类型 + @param state: 当前升级状态 + @param priv: 跟状态相关的私有参数指针 + @return void + @note +*/ +/*----------------------------------------------------------------------------*/ +static void norflash_ufw_update_state_cbk(int type, u32 state, void *priv) +{ + update_ret_code_t *ret_code = (update_ret_code_t *)priv; + + printf("state:%x err:%x\n", ret_code->stu, ret_code->err_code); + + switch (state) { + case UPDATE_CH_EXIT: + if ((0 == ret_code->stu) && (0 == ret_code->err_code)) { + //update_mode_api(BT_UPDATA); + update_mode_api_v2(USER_NORFLASH_UFW_UPDATA, + norflash_ufw_update_private_param_fill, + norflash_ufw_update_before_jump_handle); + } + + break; + + default: + break; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 通过地址读取升级文件内容 + @param buf, 读取数据缓存 + @param addr, 读取外置flash数据的地址 + @param len, 读取外置flash数据的长度 + @return u16 读取长度 + @note +*/ +/*----------------------------------------------------------------------------*/ +static u16 norflash_update_file_read(void *buf, u32 addr, u32 len) +{ + int rlen = 0; + + if (dev_ptr) { + wdt_clear(); + //printf("%s: addr = 0x%x, rlen = 0x%x", __func__, addr, len); + rlen = dev_bulk_read(dev_ptr, buf, addr, len); + //put_buf(buff, 128); + } + + return rlen; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 启动外置flash升级接口, 该接口为用户在保证将nor_update.ufw烧写到外置flash之后, 调用该接口进行内置flash升级 + @param norflash_addr: 升级文件在外置flash的物理地址 + @return void + @note +*/ +/*----------------------------------------------------------------------------*/ +//使用ufw文件格式 +void norflash_update_ufw_init(u32 norflash_addr) +{ + if (support_norflash_ufw_update_en == 0) { + return; + } + user_remote_base_addr = norflash_addr; + nor_update_info.src_file_addr = norflash_addr; + +#if NORFLASH_UFW_UPDATE_VERIFY_ALL_FILE + if (norflash_ufw_update_f_open()) { + if (update_file_verify(norflash_addr, norflash_update_file_read) != 0) { + //校验失败 + return; + } + } +#endif /* #if NORFLASH_UFW_UPDATE_VERIFY_ALL_FILE */ + + update_mode_info_t nofrflash_ufw_update_info = { + .type = USER_NORFLASH_UFW_UPDATA, + .state_cbk = norflash_ufw_update_state_cbk, + .p_op_api = &norflash_ufw_update_op_api, + .task_en = 1, + }; + + app_active_update_task_init(&nofrflash_ufw_update_info); +} + + diff --git a/apps/common/update/norflash_update.c b/apps/common/update/norflash_update.c new file mode 100644 index 0000000..0b3aca3 --- /dev/null +++ b/apps/common/update/norflash_update.c @@ -0,0 +1,105 @@ +#include "app_config.h" +#include "typedef.h" +#include "fs.h" +#include "norflash.h" +#include "spi/nor_fs.h" + +typedef struct _nor_fs_part { + u32 update_file_addr; + u32 update_area_start_addr; + u32 update_area_end_addr; +} nor_fs_parm; + +nor_fs_parm update_norfs_parm; + +#define NORFLASH_LOADER_PATH "storage/nor_fs/C/loader.bin" +static void *fd = NULL; +void register_loader_write_handler(u32(*hdl)(void *, u32)); +u16 CRC16_with_initval(const void *ptr, u32 len, u16 i_val); +u32 nor_get_absolute_addr(void); +u32 nor_get_start_addr(void); +u32 nor_get_capacity(void); + +void get_nor_update_param(void *buf) +{ + if (buf) { + printf("file_addr:0x%x start_addr:0x%x end_addr:0x%x\n", update_norfs_parm.update_file_addr, update_norfs_parm.update_area_start_addr, update_norfs_parm.update_area_end_addr); + memcpy(buf, (u8 *)&update_norfs_parm, sizeof(update_norfs_parm)); + } +} + +int norflash_f_open(u32 loader_len) +{ + fd = fopen(NORFLASH_LOADER_PATH, "w+"); + if (!fd) { + r_printf("update fopen err\n"); + return -1; + } else { + g_printf("update fopen succ\n"); + update_norfs_parm.update_file_addr = nor_get_absolute_addr(); + update_norfs_parm.update_area_start_addr = nor_get_start_addr(); + update_norfs_parm.update_area_end_addr = update_norfs_parm.update_area_start_addr + nor_get_capacity(); + if (loader_len > nor_get_capacity) { + return -2; + } + } + return 0; +} + +u32 norflash_f_write(u8 *buff, u16 len) +{ + if (fd) { + return fwrite(fd, buff, len); + } + return 0; +} + +u32 norflash_update_verify(u32 loader_len, u32 loader_crc) +{ + u32 len = loader_len; + u32 crc_temp = 0; + if (fd) { + fseek(fd, NOR_FS_SEEK_SET, 0); //偏移到文件起始 + u16 r_len; + + u8 *temp_buf = malloc(512); + if (NULL == temp_buf) { + goto _ERR_RET; + } + u16 temp_buf_len = 512; + + while (len) { + r_len = (len > temp_buf_len) ? temp_buf_len : len; + + fread(fd, temp_buf, r_len); + crc_temp = CRC16_with_initval(temp_buf, r_len, crc_temp); + + len -= r_len; + } + +_ERR_RET: + if (NULL != temp_buf) { + free(temp_buf); + } + + if (crc_temp == loader_crc) { + return 0; + } + } + return 1; +} + +void norflash_update_close() +{ + if (fd) { + fclose(fd); + } +} + +int norflash_loader_start(u32 loader_len) +{ + register_loader_write_handler(norflash_f_write); + return norflash_f_open(loader_len); +} + + diff --git a/apps/common/update/testbox_update.c b/apps/common/update/testbox_update.c new file mode 100644 index 0000000..7660282 --- /dev/null +++ b/apps/common/update/testbox_update.c @@ -0,0 +1,202 @@ + +#include "update_loader_download.h" +#include "update.h" +#include "btctrler_task.h" +#include "app_config.h" + + +#if defined(CONFIG_SPP_AND_LE_CASE_ENABLE) || defined(CONFIG_HID_CASE_ENABLE) +#include "lib_profile_cfg.h" +#else +#include "bt_profile_cfg.h" +#endif + +#if (SMART_BOX_EN) && (CONFIG_WATCH_CASE_ENABLE) +#include "smartbox/smartbox_task.h" +#endif + +#define LOG_TAG "[TEST-UPDATE]" +#define LOG_INFO_ENABLE +#define LOG_ERROR_ENABLE +#include "system/debug.h" + +extern void update_close_hw(void *filter_name); +extern void btctrler_testbox_update_msg_handle_register(void (*handle)(int)); +extern void __bt_updata_reset_bt_bredrexm_addr(void); +extern int __bt_updata_save_connection_info(void); +extern const update_op_api_t lmp_ch_update_op; +extern const update_op_api_t ble_ll_ch_update_op; + +static void testbox_bt_classic_update_private_param_fill(UPDATA_PARM *p) +{ + +} + +int clk_set(const char *name, int clk); +extern void ll_hci_destory(void); +extern void ram_protect_close(void); +static void testbox_bt_classic_update_before_jump_handle(int type) +{ + if (UPDATE_MODULE_IS_SUPPORT(UPDATE_BT_LMP_EN)) { + clk_set("sys", 24000000); +#if TCFG_USER_TWS_ENABLE || TCFG_USER_BLE_ENABLE + log_info("close ble hw\n"); + ll_hci_destory(); +#endif + update_close_hw("bredr"); + if (__bt_updata_save_connection_info()) { + log_error("bt save conn info fail!\n"); + return; + } + + ram_protect_close(); + //note:last func will not return; + __bt_updata_reset_bt_bredrexm_addr(); + } +} + +static void testbox_bt_classic_update_state_cbk(int type, u32 state, void *priv) +{ + update_ret_code_t *ret_code = (update_ret_code_t *)priv; + + switch (state) { + case UPDATE_CH_EXIT: + log_info("state:%x err:%x\n", ret_code->stu, ret_code->err_code); + if (UPDATE_DUAL_BANK_IS_SUPPORT()) { + if ((0 == ret_code->stu) && (0 == ret_code->err_code)) { + log_info("bt update succ\n"); + update_result_set(UPDATA_SUCC); + } else { + log_info("bt update fail\n"); + update_result_set(UPDATA_DEV_ERR); + } + } else { + if ((0 == ret_code->stu) && (0 == ret_code->err_code)) { + //update_mode_api(BT_UPDATA); + update_mode_api_v2(BT_UPDATA, + testbox_bt_classic_update_private_param_fill, + testbox_bt_classic_update_before_jump_handle); + } + } + break; + } +} + +static u8 ble_update_ready_jump_flag = 0; +u8 ble_update_get_ready_jump_flag(void) +{ + return ble_update_ready_jump_flag; +} + +static void testbox_ble_update_private_param_fill(UPDATA_PARM *p) +{ + u8 addr[6]; + extern int le_controller_get_mac(void *addr); + if (BT_MODULES_IS_SUPPORT(BT_MODULE_LE) && UPDATE_MODULE_IS_SUPPORT(UPDATE_BLE_TEST_EN)) { + le_controller_get_mac(addr); + memcpy(p->parm_priv, addr, 6); + puts("ble addr:\n"); + put_buf(p->parm_priv, 6); + } +} + +static void testbox_ble_update_before_jump_handle(int type) +{ + if (BT_MODULES_IS_SUPPORT(BT_MODULE_LE) && UPDATE_MODULE_IS_SUPPORT(UPDATE_BLE_TEST_EN)) { + ll_hci_destory(); + } + + cpu_reset(); +} + +extern u8 check_le_conn_disconnet_flag(void); +extern void ble_app_disconnect(void); +static void testbox_ble_update_state_cbk(int type, u32 state, void *priv) +{ + update_ret_code_t *ret_code = (update_ret_code_t *)priv; + + switch (state) { + case UPDATE_CH_EXIT: + if (UPDATE_DUAL_BANK_IS_SUPPORT()) { + if ((0 == ret_code->stu) && (0 == ret_code->err_code)) { + log_info("bt update succ\n"); + update_result_set(UPDATA_SUCC); + } else { + log_info("bt update fail\n"); + update_result_set(UPDATA_DEV_ERR); + } + } else { + if ((0 == ret_code->stu) && (0 == ret_code->err_code)) { +#if TCFG_USER_BLE_ENABLE && ((TCFG_BLE_DEMO_SELECT != DEF_BLE_DEMO_ADV) \ + && (TCFG_BLE_DEMO_SELECT != DEF_BLE_DEMO_NULL) \ + && (TCFG_BLE_DEMO_SELECT != DEF_BLE_DEMO_CLIENT)) + + ble_update_ready_jump_flag = 1; + ble_app_disconnect(); + u8 cnt = 0; + while (!check_le_conn_disconnet_flag()) { + log_info("wait discon\n"); + os_time_dly(2); + if (cnt++ > 5) { + break; + } + } + + //update_mode_api(BLE_TEST_UPDATA); + update_mode_api_v2(BLE_TEST_UPDATA, + testbox_ble_update_private_param_fill, + testbox_ble_update_before_jump_handle); +#endif + } + } + break; + } +} + +void testbox_update_msg_handle(int msg) +{ + log_info("msg:%x\n", msg); + + switch (msg) { + case MSG_BT_UPDATE_LOADER_DOWNLOAD_START: + if (UPDATE_MODULE_IS_SUPPORT(UPDATE_BT_LMP_EN)) { +#if (SMART_BOX_EN) && (CONFIG_WATCH_CASE_ENABLE) + app_smartbox_task_prepare(0, SMARTBOX_TASK_ACTION_WATCH_TRANSFER, 0); +#endif + update_mode_info_t info = { + .type = BT_UPDATA, + .state_cbk = testbox_bt_classic_update_state_cbk, + .p_op_api = &lmp_ch_update_op, + .task_en = 1, + }; + app_active_update_task_init(&info); + } + break; + + case MSG_BLE_TEST_OTA_LOADER_DOWNLOAD_START: + if (UPDATE_MODULE_IS_SUPPORT(UPDATE_BLE_TEST_EN)) { + update_mode_info_t info = { + .type = BLE_TEST_UPDATA, + .state_cbk = testbox_ble_update_state_cbk, + .p_op_api = &ble_ll_ch_update_op, + .task_en = 1, + }; + app_active_update_task_init(&info); + } + break; + +defaut: + log_error("not support update msg:%x\n", msg); + break; + } + +} + +void testbox_update_init(void) +{ + if (UPDATE_MODULE_IS_SUPPORT(UPDATE_BLE_TEST_EN) || UPDATE_MODULE_IS_SUPPORT(UPDATE_BT_LMP_EN)) { + log_info("testbox msg handle reg:%x\n", testbox_update_msg_handle); + btctrler_testbox_update_msg_handle_register(testbox_update_msg_handle); + } +} + diff --git a/apps/common/update/uart_update.c b/apps/common/update/uart_update.c new file mode 100644 index 0000000..46f1513 --- /dev/null +++ b/apps/common/update/uart_update.c @@ -0,0 +1,373 @@ +#include "app_config.h" +#if(USER_UART_UPDATE_ENABLE) && (UART_UPDATE_ROLE == UART_UPDATE_SLAVE) +#include "typedef.h" +#include "update_loader_download.h" +#include "os/os_api.h" +#include "system/task.h" +#include "update.h" +#include "gpio.h" +#include "uart_update.h" +#include "asm/uart_dev.h" +#include "asm/clock.h" + +static volatile u32 uart_to_cnt = 0; +static volatile u32 uart_file_offset = 0; +static volatile u16 rx_cnt; //收数据计数 +static void (*uart_update_resume_hdl)(void *priv) = NULL; +static int (*uart_update_sleep_hdl)(void *priv) = NULL; + +#define LOG_TAG "[UART_UPDATE]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +#define LOG_CLI_ENABLE +#include "debug.h" + +#define RETRY_TIME 4//重试n次 +#define PACKET_TIMEOUT 200//ms + +//命令 +#define CMD_UPDATE_START 0x01 +#define CMD_UPDATE_READ 0x02 +#define CMD_UPDATE_END 0x03 +#define CMD_SEND_UPDATE_LEN 0x04 +#define CMD_KEEP_ALIVE 0x05 + + +#define READ_LIT_U16(a) (*((u8*)(a)) + (*((u8*)(a)+1)<<8)) +#define READ_LIT_U32(a) (*((u8*)(a)) + (*((u8*)(a)+1)<<8) + (*((u8*)(a)+2)<<16) + (*((u8*)(a)+3)<<24)) + +#define WRITE_LIT_U16(a,src) {*((u8*)(a)+1) = (u8)(src>>8); *((u8*)(a)+0) = (u8)(src&0xff); } +#define WRITE_LIT_U32(a,src) {*((u8*)(a)+3) = (u8)((src)>>24); *((u8*)(a)+2) = (u8)(((src)>>16)&0xff);*((u8*)(a)+1) = (u8)(((src)>>8)&0xff);*((u8*)(a)+0) = (u8)((src)&0xff);} + +#define THIS_TASK_NAME "uart_update" + + +static protocal_frame_t protocal_frame __attribute__((aligned(4))); +u32 update_baudrate = 9600; //初始波特率 +static uart_update_cfg update_cfg; + +u32 uart_dev_receive_data(void *buf, u32 relen, u32 addr); +void uart_set_dir(u8 mode); +void uart_update_write(u8 *data, u32 len); +void uart_update_set_baud(u32 baudrate); +void uart_close_deal(void); +void uart_hw_init(uart_update_cfg update_cfg, void (*cb)(void *, u32)); +void uart_data_decode(u8 *buf, u16 len); +void updata_parm_set(UPDATA_TYPE up_type, void *priv, u32 len); + +enum { + SEEK_SET = 0x0, + SEEK_CUR = 0x1, + SEEK_END = 0X2, +}; + +enum { + CMD_UART_UPDATE_START = 0x1, + CMD_UART_UPDATE_READ, + CMD_UART_UPDATE_END, + CMD_UART_UPDATE_UPDATE_LEN, + CMD_UART_JEEP_ALIVE, + CMD_UART_UPDATE_READY, +}; + + +static void uart_update_hdl_register(void (*resume_hdl)(void *priv), int (*sleep_hdl)(void *priv)) +{ + uart_update_resume_hdl = resume_hdl; + uart_update_sleep_hdl = sleep_hdl; +} + +void sava_uart_update_param(void) +{ + UPDATA_UART uart_param = {.control_baud = update_baudrate, .control_io_tx = update_cfg.tx, .control_io_rx = update_cfg.rx}; + updata_parm_set(UART_UPDATA, (u8 *)&uart_param, sizeof(UPDATA_UART)); +} + +static void uart_update_callback(void *priv, u8 type, u8 cmd) +{ + if (cmd == UPDATE_LOADER_OK) { + update_mode_api(type, update_baudrate, update_cfg.tx, update_cfg.rx); + } else { + //失败将波特率设置回初始,并重置变量 + rx_cnt = 0; + update_baudrate = 9600; + uart_file_offset = 0; + uart_update_set_baud(update_baudrate); + //uart_hw_init(update_cfg, uart_data_decode); + } +} + +void uart_data_decode(u8 *buf, u16 len) +{ + u16 crc, crc0, i, ch; + /* printf("decode_len:%d\n", len); */ + /* put_buf(buf, len); */ + for (i = 0; i < len; i++) { + ch = buf[i]; +__recheck: + if (rx_cnt == 0) { + if (ch == SYNC_MARK0) { + protocal_frame.raw_data[rx_cnt++] = ch; + } + } else if (rx_cnt == 1) { + protocal_frame.raw_data[rx_cnt++] = ch; + if (ch != SYNC_MARK1) { + rx_cnt = 0; + goto __recheck; + } + } else if (rx_cnt < 4) { + protocal_frame.raw_data[rx_cnt++] = ch; + } else { + protocal_frame.raw_data[rx_cnt++] = ch; + if (rx_cnt == (protocal_frame.data.length + SYNC_SIZE)) { + rx_cnt = 0; + extern u16 CRC16(void *ptr, u32 len); + crc = CRC16(protocal_frame.raw_data, protocal_frame.data.length + SYNC_SIZE - 2); + memcpy(&crc0, &protocal_frame.raw_data[protocal_frame.data.length + SYNC_SIZE - 2], 2); + if (crc0 == crc) { + switch (protocal_frame.data.data[0]) { + case CMD_UART_UPDATE_START: + log_info("CMD_UART_UPDATE_START\n"); + os_taskq_post_msg(THIS_TASK_NAME, 1, MSG_UART_UPDATE_START_RSP); + break; + case CMD_UART_UPDATE_READ: + log_info("CMD_UART_UPDATE_READ\n"); + if (uart_update_resume_hdl) { + uart_update_resume_hdl(NULL); + } + break; + case CMD_UART_UPDATE_END: + log_info("CMD_UART_UPDATE_END\n"); + break; + case CMD_UART_UPDATE_UPDATE_LEN: + log_info("CMD_UART_UPDATE_LEN\n"); + break; + case CMD_UART_JEEP_ALIVE: + log_info("CMD_UART_KEEP_ALIVE\n"); + break; + case CMD_UART_UPDATE_READY: + log_info("CMD_UART_UPDATE_READY\n"); + os_taskq_post_msg(THIS_TASK_NAME, 1, MSG_UART_UPDATE_READY); + break; + default: + log_info("unkown cmd...\n"); + break; + } + } else { + rx_cnt = 0; + } + } + } + } +} + +static bool uart_send_packet(u8 *buf, u16 length) +{ + bool ret; + u16 crc; + u8 *buffer; + + buffer = (u8 *)&protocal_frame; + protocal_frame.data.mark0 = SYNC_MARK0; + protocal_frame.data.mark1 = SYNC_MARK1; + protocal_frame.data.length = length; + memcpy((char *)&buffer[4], buf, length); + crc = CRC16(buffer, length + SYNC_SIZE - 2); + memcpy(buffer + 4 + length, &crc, 2); + uart_set_dir(0);//设为输出 + uart_update_write((u8 *)&protocal_frame, length + SYNC_SIZE); + uart_set_dir(1); + return ret; +} + +u32 uart_dev_receive_data(void *buf, u32 relen, u32 addr) +{ + u8 i; + struct file_info file_cmd; + for (i = 0; i < RETRY_TIME; i++) { + if (i > 0) { + putchar('r'); + } + file_cmd.cmd = CMD_UPDATE_READ; + file_cmd.addr = addr; + file_cmd.len = relen; + uart_send_packet(&file_cmd, sizeof(file_cmd)); + if (uart_update_sleep_hdl) { + if (uart_update_sleep_hdl(NULL) == OS_TIMEOUT) { + continue; + } + } + memcpy(&file_cmd, protocal_frame.data.data, sizeof(file_cmd)); + if ((file_cmd.cmd != CMD_UPDATE_READ) || (file_cmd.addr != addr) || (file_cmd.len != relen)) { + continue; + } + memcpy(buf, &protocal_frame.data.data[sizeof(file_cmd)], protocal_frame.data.length - sizeof(file_cmd)); + return (protocal_frame.data.length - sizeof(file_cmd)); + } + putchar('R'); + return relen; +} + +bool uart_update_cmd(u8 cmd, u8 *buf, u32 len) +{ + u8 *pbuf, i; + //for (i = 0; i < RETRY_TIME; i++) + { + pbuf = protocal_frame.data.data; + pbuf[0] = cmd; + if (buf) { + memcpy(pbuf + 1, buf, len); + } + uart_send_packet(pbuf, len + 1); + } + return TRUE; +} + +extern const update_op_api_t uart_ch_update_op; +void uart_update_recv(u8 cmd, u8 *buf, u32 len) +{ + u32 baudrate = 9600; + switch (cmd) { + case CMD_UPDATE_START: + memcpy(&baudrate, buf, 4); + if (update_baudrate != baudrate) { + update_baudrate = baudrate; + uart_update_set_baud(baudrate); + uart_update_cmd(CMD_UPDATE_START, &update_baudrate, 4); + } else { + app_update_loader_downloader_init( //设置完波特率后开始升级 + UART_UPDATA, + uart_update_callback, + NULL, + &uart_ch_update_op); + } + break; + + case CMD_UPDATE_END: + break; + + case CMD_SEND_UPDATE_LEN: + break; + + default: + break; + } +} + + +bool uart_send_update_len(u32 update_len) +{ + u8 cmd[4]; + WRITE_LIT_U32(&cmd[0], update_len); + return uart_update_cmd(CMD_SEND_UPDATE_LEN, cmd, 4); +} + + +u16 uart_f_open(void) +{ + return 1; +} + +u16 uart_f_read(void *handle, void *buf, u32 relen) +{ + u32 len; + len = uart_dev_receive_data(buf, relen, uart_file_offset); + if (len == -1) { + log_info("uart_f_read err\n"); + return -1; + } + uart_file_offset += len; + return len; +} + +int uart_f_seek(void *fp, u8 type, u32 offset) +{ + if (type == SEEK_SET) { + uart_file_offset = offset; + } else if (type == SEEK_CUR) { + uart_file_offset += offset; + } + return 0;//FR_OK; +} + +u16 uart_f_stop(u8 err) +{ + uart_update_cmd(CMD_UPDATE_END, &err, 1); + update_baudrate = 9600; //把波特率设置回9600 + return 0; +} + + + +const update_op_api_t uart_ch_update_op = { + .ch_init = uart_update_hdl_register, + .f_open = uart_f_open, + .f_read = uart_f_read, + .f_seek = uart_f_seek, + .f_stop = uart_f_stop, +}; + +static void update_loader_download_task(void *p) +{ + int ret; + int msg[8]; + static u8 update_start = 0; + const uart_bus_t *uart_bus; + u32 uart_rxcnt = 0; + + while (1) { + ret = os_task_pend("taskq", msg, ARRAY_SIZE(msg)); + if (ret != OS_TASKQ) { + continue; + } + if (msg[0] != Q_MSG) { + continue; + } + switch (msg[1]) { + case MSG_UART_UPDATE_READY: + uart_update_cmd(CMD_UPDATE_START, NULL, 0); + break; + + case MSG_UART_UPDATE_START_RSP: //收到START_RSP 进行波特率设置设置 + log_info("MSG_UART_UPDATE_START_RSP\n"); + uart_update_recv(protocal_frame.data.data[0], &protocal_frame.data.data[1], protocal_frame.data.length - 1); + break; + + case MSG_UART_UPDATE_READ_RSP: + log_info("MSG_UART_UPDATE_READ_RSP\n"); + break; + + default: + log_info("unkown msg..............\n"); + break; + } + } +} + +void uart_update_init(uart_update_cfg *cfg) +{ + memcpy(&update_cfg, cfg, sizeof(uart_update_cfg)); + task_create(update_loader_download_task, NULL, THIS_TASK_NAME); + uart_hw_init(update_cfg, uart_data_decode); + printf(">>>%s\n", __func__); +} + + +static void clock_critical_enter(void) +{ +} + +static void clock_critical_exit(void) +{ + uart_update_set_baud(update_baudrate); +} +CLOCK_CRITICAL_HANDLE_REG(uart_update, clock_critical_enter, clock_critical_exit) + + + + + + + +#endif diff --git a/apps/common/update/uart_update_master.c b/apps/common/update/uart_update_master.c new file mode 100644 index 0000000..a35e473 --- /dev/null +++ b/apps/common/update/uart_update_master.c @@ -0,0 +1,457 @@ +#include "app_config.h" +#if(USER_UART_UPDATE_ENABLE) && (UART_UPDATE_ROLE == UART_UPDATE_MASTER) +#include "typedef.h" +#include "update_loader_download.h" +#include "os/os_api.h" +#include "system/task.h" +#include "update.h" +#include "gpio.h" +#include "uart_update.h" +#include "asm/uart_dev.h" +#include "asm/clock.h" +#include "timer.h" +#include "system/fs/fs.h" + +static volatile u32 uart_to_cnt = 0; +static volatile u32 uart_file_offset = 0; +static volatile u16 rx_cnt; //收数据计数 + +typedef struct _uart_updte_ctl_t { + OS_SEM sem; + OS_SEM rx_sem; + volatile u16 timemax; + volatile u16 timeout; + volatile u8 flag; + volatile u8 err_code; + u8 update_sta; + u8 update_percent; + u32 update_total_size; + u32 update_send_size; + u8 rx_cmd[0x30]; + u16 cmd_len; + u16 uart_timer_hdl; +} uart_update_ctl_t; + +static uart_update_ctl_t uart_update_ctl; +#define __this (&uart_update_ctl) + +#define LOG_TAG "[UART_UPDATE]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +#define LOG_CLI_ENABLE +#include "debug.h" + +#define RETRY_TIME 4//重试n次 +#define PACKET_TIMEOUT 200//ms + +#define FILE_READ_UNIT 512 // +#define UART_DEFAULT_BAUD 9600 +#define UART_UPDATE_BAUD (50*10000L) +#define TIME_TICK_UNIT (10) //unit:ms +//命令 +#define CMD_UPDATE_START 0x01 +#define CMD_UPDATE_READ 0x02 +#define CMD_UPDATE_END 0x03 +#define CMD_SEND_UPDATE_LEN 0x04 +#define CMD_KEEP_ALIVE 0x05 + + +#define READ_LIT_U16(a) (*((u8*)(a)) + (*((u8*)(a)+1)<<8)) +#define READ_LIT_U32(a) (*((u8*)(a)) + (*((u8*)(a)+1)<<8) + (*((u8*)(a)+2)<<16) + (*((u8*)(a)+3)<<24)) + +#define WRITE_LIT_U16(a,src) {*((u8*)(a)+1) = (u8)(src>>8); *((u8*)(a)+0) = (u8)(src&0xff); } +#define WRITE_LIT_U32(a,src) {*((u8*)(a)+3) = (u8)((src)>>24); *((u8*)(a)+2) = (u8)(((src)>>16)&0xff);*((u8*)(a)+1) = (u8)(((src)>>8)&0xff);*((u8*)(a)+0) = (u8)((src)&0xff);} + +#define THIS_TASK_NAME "uart_update" + + +static protocal_frame_t protocal_frame __attribute__((aligned(4))); +u32 update_baudrate = 9600; //初始波特率 +static uart_update_cfg update_cfg; +void *fd = NULL; + +u32 uart_dev_receive_data(void *buf, u32 relen, u32 addr); +void uart_set_dir(u8 mode); +void uart_update_write(u8 *data, u32 len); +void uart_update_set_baud(u32 baudrate); +void uart_close_deal(void); +void uart_hw_init(uart_update_cfg update_cfg, void (*cb)(void *, u32)); +void uart_data_decode(u8 *buf, u16 len); + +/* enum { */ +/* SEEK_SET = 0x0, */ +/* SEEK_CUR = 0x1, */ +/* SEEK_END = 0X2, */ +/* }; */ + +enum { + CMD_UART_UPDATE_START = 0x1, + CMD_UART_UPDATE_READ, + CMD_UART_UPDATE_END, + CMD_UART_UPDATE_UPDATE_LEN, + CMD_UART_JEEP_ALIVE, + CMD_UART_UPDATE_READY, +}; + +enum { + RX_DATA_READY = 0, + RX_DATA_TIMEOUT, + RX_DATA_SUCC, +}; + +void uart_data_decode(u8 *buf, u16 len) +{ + u16 crc, crc0, i, ch; + /* printf("decode_len:%d\n", len); */ + /* put_buf(buf, len); */ + for (i = 0; i < len; i++) { + ch = buf[i]; +__recheck: + if (rx_cnt == 0) { + if (ch == SYNC_MARK0) { + protocal_frame.raw_data[rx_cnt++] = ch; + } + } else if (rx_cnt == 1) { + protocal_frame.raw_data[rx_cnt++] = ch; + if (ch != SYNC_MARK1) { + rx_cnt = 0; + goto __recheck; + } + } else if (rx_cnt < 4) { + protocal_frame.raw_data[rx_cnt++] = ch; + } else { + protocal_frame.raw_data[rx_cnt++] = ch; + if (rx_cnt == (protocal_frame.data.length + SYNC_SIZE)) { + rx_cnt = 0; + extern u16 CRC16(void *ptr, u32 len); + crc = CRC16(protocal_frame.raw_data, protocal_frame.data.length + SYNC_SIZE - 2); + memcpy(&crc0, &protocal_frame.raw_data[protocal_frame.data.length + SYNC_SIZE - 2], 2); + if (crc0 == crc) { + __this->timemax = 0; + if (protocal_frame.data.length <= sizeof(__this->rx_cmd)) { + memcpy(__this->rx_cmd, &(protocal_frame.data.data), protocal_frame.data.length); + __this->flag = RX_DATA_SUCC; + os_sem_post(&__this->rx_sem); + } + } + } + } + } +} + +static bool uart_send_packet(u8 *buf, u16 length) +{ + bool ret; + u16 crc; + u8 *buffer; + + buffer = (u8 *)&protocal_frame; + protocal_frame.data.mark0 = SYNC_MARK0; + protocal_frame.data.mark1 = SYNC_MARK1; + protocal_frame.data.length = length; + memcpy((char *)&buffer[4], buf, length); + crc = CRC16(buffer, length + SYNC_SIZE - 2); + memcpy(buffer + 4 + length, &crc, 2); + uart_set_dir(0);//设为输出 + uart_update_write((u8 *)&protocal_frame, length + SYNC_SIZE); + uart_set_dir(1); + return ret; +} + +//read file by file operation handle +u32 ufw_data_read_api(u8 *buff, u32 addr, u32 size) +{ + //To do... + if (fd) { + fseek(fd, addr, SEEK_SET); + return fread(fd, buff, size); + } + return 0; +} + +//open file and get file operation handle +bool ufw_file_op_init(char *update_path) +{ + if (fd) { + fclose(fd); + } + //To do + fd = fopen(update_path, "r"); + if (!fd) { + return false; + } + return true; +} + +//close the file and release resource +void ufw_file_op_close(void) +{ + if (fd) { + fclose(fd); + fd = NULL; + } + //To do +} + +static u32 update_data_read_from_file(void *p, u32 addr, u32 len) +{ + u8 *buffer; + struct file_info *p_file_info; + u32 read_len = 0; + + if (len > FILE_READ_UNIT) { + return (u32) - 1; + } + + buffer = malloc(len + sizeof(struct file_info)); + if (buffer) { + p_file_info = (struct file_info *)buffer; + p_file_info->cmd = CMD_UART_UPDATE_READ; + p_file_info->addr = addr; + p_file_info->len = len; + read_len = ufw_data_read_api(buffer + sizeof(struct file_info), addr, len); + } else { + return (u32) - 2; + } + + uart_send_packet(buffer, len + sizeof(struct file_info)); + + if (buffer) { + free(buffer); + } + + return read_len; +} + +enum { + UPDATE_STA_NONE = 0, + UPDATE_STA_READY, + UPDATE_STA_START, + UPDATE_STA_TIMEOUT, + UPDATE_STA_LOADER_DOWNLOAD_FINISH, + UPDATE_STA_SUCC, + UPDATE_STA_FAIL, +}; + +enum { + UPDATE_ERR_NONE = 0, + UPDATE_ERR_KEY, + UPDATE_ERR_VERIFY, + + UPDATE_ERR_LOADER_DOWNLOAD_SUCC = 0x80, +}; + +static void uart_update_err_code_handle(u8 code) +{ + if (code) { + if (UPDATE_ERR_LOADER_DOWNLOAD_SUCC == code) { + __this->update_percent = 100; + __this->update_send_size = 0; + __this->update_total_size = 0; + __this->update_sta = UPDATE_STA_LOADER_DOWNLOAD_FINISH; + log_info("loader dn succ\n"); + } else { + __this->update_sta = UPDATE_STA_FAIL; + log_error("update_err:%x\n", code); + } + } else { + __this->update_percent = 100; + __this->update_sta = UPDATE_STA_SUCC; + log_info("update all succ\n"); + } +} + + +static int uart_update_wait_rev_data(timeout) +{ + u32 err; + __this->flag = RX_DATA_READY; + __this->timeout = 0; + __this->timemax = (timeout + 1) / TIME_TICK_UNIT; + + err = os_sem_pend(&__this->rx_sem, 2000); + + if (OS_NO_ERR != err) { + log_info("wait tm out\n"); + } + + __this->timemax = __this->timeout = 0; + + if (__this->flag == RX_DATA_SUCC) { + return TRUE; + } + + return FALSE; +} + +int uart_update_api_write_then_read(u8 *buf, u8 length, u8 timeout) +{ + int ret = FALSE; + + uart_send_packet(buf, length); + if (timeout) { + ret = uart_update_wait_rev_data(timeout); + } + + return ret; +} + +bool uart_update_send_update_ready(char *file_update_path) +{ + u8 ut_cmd[1]; + ut_cmd[0] = CMD_UART_UPDATE_READY; + + if (ufw_file_op_init(file_update_path)) { + __this->update_sta = UPDATE_STA_READY; + uart_send_packet(ut_cmd, sizeof(ut_cmd)); + log_info("uart_update_send_update_ready\n"); + return TRUE; + } + + return FALSE; +} + +bool get_uart_update_sta(void) +{ + return (__this->update_sta == UPDATE_STA_READY || __this->update_sta == UPDATE_STA_START) ? TRUE : FALSE; +} + +static void update_process_run(void) +{ + update_baudrate = UART_DEFAULT_BAUD; + uart_update_set_baud(update_baudrate); + + __this->update_total_size = 0; + __this->update_percent = 0; + __this->update_send_size = 0; + + u8 *pbuf = &__this->rx_cmd; + while (1) { + if (OS_NO_ERR != os_sem_pend(&__this->rx_sem, 800)) { + log_info("uart_timeout\n"); + __this->update_sta = UPDATE_STA_TIMEOUT; + update_baudrate = 9600; + uart_update_set_baud(update_baudrate); + continue; + } + + //os_time_dly(1); + + switch (pbuf[0]) { + case CMD_UPDATE_START: + log_info("CMD_UPDATE_START\n"); + __this->update_sta = UPDATE_STA_START; + update_baudrate = UART_UPDATE_BAUD; + WRITE_LIT_U32(pbuf + 1, update_baudrate); + uart_send_packet(pbuf, 1 + sizeof(u32)); + log_info("use baud:%x\n", update_baudrate); + uart_update_set_baud(update_baudrate); + break; + + case CMD_UPDATE_READ: { + u32 addr = READ_LIT_U32(&pbuf[1]); + u32 len = READ_LIT_U32(&pbuf[1 + sizeof(u32)]); + if (__this->update_total_size) { + __this->update_send_size += len; + __this->update_percent = (__this->update_send_size * 100) / __this->update_total_size; + if (__this->update_percent >= 99) { + __this->update_percent = 99; + } + log_info("send data process:%x\n", __this->update_percent); + } + log_info("CMD_UPDATE_READ\n"); + update_data_read_from_file(NULL, addr, len); + } + break; + + case CMD_UPDATE_END: + log_info("CMD_UPDATE_END\n"); + uart_update_err_code_handle(pbuf[1]); + uart_send_packet(pbuf, 1); + break; + + case CMD_SEND_UPDATE_LEN: + __this->update_total_size = READ_LIT_U32(&pbuf[1]); + __this->update_percent = 0; + __this->update_send_size = 0; + log_info("update_total_size:%x\n", __this->update_total_size); + uart_send_packet(pbuf, 1); + break; + + case CMD_KEEP_ALIVE: + uart_send_packet(pbuf, 1); + break; + + } + } +} + +static void uart_timeout_handler(void *priv) +{ + if (__this->timemax) { + __this->timeout++; + if (__this->timeout > __this->timemax) { + __this->timemax = 0; + __this->flag = RX_DATA_TIMEOUT; + os_sem_post(&__this->rx_sem); + } + } +} + +static void update_loader_download_task(void *p) +{ + log_info("create %s task\n", THIS_TASK_NAME); + os_sem_create(&__this->sem, 0); + os_sem_create(&__this->rx_sem, 0); + + + while (1) { + update_process_run(); + } +} + +void uart_update_init(uart_update_cfg *cfg) +{ + memcpy(&update_cfg, cfg, sizeof(uart_update_cfg)); + task_create(update_loader_download_task, NULL, THIS_TASK_NAME); + uart_hw_init(update_cfg, uart_data_decode); + +} + +void uart_update_exit(void) +{ + log_info("uart update exit\n"); + + if (__this->uart_timer_hdl) { + sys_timer_del(__this->uart_timer_hdl); + } + + os_sem_del(&__this->sem, 0); + os_sem_del(&__this->rx_sem, 0); + + ufw_file_op_close(); + + uart_close_deal(); + + task_kill(THIS_TASK_NAME); +} + +static void clock_critical_enter(void) +{ + +} + +static void clock_critical_exit(void) +{ + uart_update_set_baud(update_baudrate); +} +CLOCK_CRITICAL_HANDLE_REG(uart_update, clock_critical_enter, clock_critical_exit) + + + + + + + +#endif diff --git a/apps/common/update/update.c b/apps/common/update/update.c new file mode 100644 index 0000000..4930192 --- /dev/null +++ b/apps/common/update/update.c @@ -0,0 +1,715 @@ +#include "update.h" +#include "update_loader_download.h" +#include "asm/crc16.h" +#include "asm/wdt.h" +#include "os/os_api.h" +#include "app_config.h" +#include "cpu.h" +#include "syscfg_id.h" +#include "vm.h" +#include "btcontroller_modules.h" +#include "system/includes.h" +#include "uart_update.h" +#include "dual_bank_updata_api.h" +#if (SMART_BOX_EN && JL_SMART_BOX_EXTRA_FLASH_OPT) +#include "smartbox_extra_flash_opt.h" +#endif + + +#if TCFG_UI_ENABLE +#include "ui/ui_api.h" +#endif + +#if RCSP_BTMATE_EN +#include "rcsp_user_update.h" +#elif RCSP_ADV_EN +#include "rcsp_adv_user_update.h" +#endif + +#include "custom_cfg.h" + +#include "update_tws.h" + + +#define LOG_TAG "[APP-UPDATE]" +#define LOG_INFO_ENABLE +#define LOG_ERROR_ENABLE +#include "system/debug.h" + +extern void *dev_update_get_parm(int type); +extern u8 get_ota_status(); +extern void get_nor_update_param(void *buf); +extern s32 vm_write(vm_hdl hdl, u8 *data_buf, u16 len); +extern const int support_norflash_update_en; + + +#ifdef DEV_UPDATE_SUPPORT_JUMP +extern void __JUMP_TO_MASKROM(); +extern void save_spi_port(); +extern s32 sd1_unmount(void); +extern void usb_sie_close_all(void); +#endif //endif DEV_UPDATE_SUPPORT_JUMP + + +#ifdef UPDATE_VOICE_REMIND +#include "tone_player.h" +#include "audio_config.h" +#endif + +#ifdef UPDATE_LED_REMIND +#include "asm/pwm_led.h" +#endif + +#define DEVICE_UPDATE_KEY_ERR BIT(30) +#define DEVICE_FIRST_START BIT(31) +//升级文件路径必须是短文件名(8+3)结构,仅支持2层目录 +/* const char updata_file_name[] = "/UPDATA/JL_692X.BFU"; */ +const char updata_file_name[] = "/*.UFW"; +u32 g_updata_flag = 0; +u16 update_result_get(void) +{ + u16 ret = UPDATA_NON; + + if (!UPDATE_SUPPORT_DEV_IS_NULL()) { + UPDATA_PARM *p = UPDATA_FLAG_ADDR; + u16 crc_cal; + crc_cal = CRC16(((u8 *)p) + 2, sizeof(UPDATA_PARM) - 2); //2 : crc_val + if (crc_cal && crc_cal == p->parm_crc) { + ret = p->parm_result; + } + g_updata_flag = ret; + g_updata_flag |= ((u32)(p->magic)) << 16; + + memset(p, 0x00, sizeof(UPDATA_PARM)); + } + + return ret; +} + +void update_result_set(u16 result) +{ + if (!UPDATE_SUPPORT_DEV_IS_NULL()) { + UPDATA_PARM *p = UPDATA_FLAG_ADDR; + + memset(p, 0x00, sizeof(UPDATA_PARM)); + p->parm_result = result; + p->parm_crc = CRC16(((u8 *)p) + 2, sizeof(UPDATA_PARM) - 2); + } +} + +bool update_success_boot_check(void) +{ + if (!UPDATE_SUPPORT_DEV_IS_NULL()) { + u16 result = g_updata_flag & 0xffff; + u16 up_tpye = g_updata_flag >> 16; + if ((UPDATA_SUCC == result) && ((SD0_UPDATA == up_tpye) || (USB_UPDATA == up_tpye))) { + return true; + } + } + return false; +} + +bool device_is_first_start() +{ + log_info("g_updata_flag=0x%x\n", g_updata_flag); + if ((g_updata_flag & DEVICE_FIRST_START) || (g_updata_flag & DEVICE_UPDATE_KEY_ERR) || (g_updata_flag == UPDATA_SUCC)) { + puts("\n=================device_is_first_start=========================\n"); + return true; + } + return false; +} + +void led_update_start(void) +{ +#ifdef UPDATE_LED_REMIND + puts("led_update_start\n"); + pwm_led_mode_set(PWM_LED_ALL_OFF); +#endif +} + +void led_update_finish(void) +{ +#ifdef UPDATE_LED_REMIND + puts("led_update_finish\n"); + pwm_led_mode_set(PWM_LED0_LED1_FAST_FLASH); +#endif +} + +static inline void dev_update_close_ui() +{ + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_LED7)) + u8 count = 0; + UI_SHOW_WINDOW(ID_WINDOW_POWER_OFF); +__retry: + if (UI_GET_WINDOW_ID() != ID_WINDOW_POWER_OFF) { + os_time_dly(10);//增加延时防止没有关显示 + if (count < 3) { + goto __retry; + } + count++; + } +#endif +} + +extern void delay_2ms(int cnt); +extern void app_audio_set_wt_volume(s16 volume); + +int update_result_deal() +{ +#ifdef CONFIG_FPGA_ENABLE + return 0; +#endif + + u8 key_voice_cnt = 0; + u16 result = 0; + result = (g_updata_flag & 0xffff); + log_info("<--------update_result_deal=0x%x %x--------->\n", result, g_updata_flag >> 16); +#ifdef CONFIG_DEBUG_ENABLE +#if TCFG_APP_BT_EN + u8 check_update_param_len(void); + ASSERT(check_update_param_len(), "UPDATE_PARAM_LEN ERROR"); +#endif +#endif + if (result == UPDATA_NON || 0 == result) { + return 0; + } +#ifdef UPDATE_VOICE_REMIND +#endif + if (result == UPDATA_SUCC) { +#if(JL_EARPHONE_APP_EN && RCSP_UPDATE_EN) + u8 clear_update_flag = 0; + vm_write(VM_UPDATE_FLAG, &clear_update_flag, 1); +#endif +#if(JL_SMART_BOX_EXTRA_FLASH_OPT && RCSP_UPDATE_EN) + smartbox_eflash_update_flag_set(0); + smartbox_eflash_flag_set(0); +#endif +#ifdef UPDATE_LED_REMIND + led_update_finish(); +#endif + } + + extern u8 get_max_sys_vol(void); + while (1) { + wdt_clear(); + key_voice_cnt++; +#ifdef UPDATE_VOICE_REMIND + if (result == UPDATA_SUCC) { + puts("<<<<<>>>>>>>>>>\n"); + } else { + log_info("!!!!!!!!!!!!!!!updata waring !!!!!!!!!!!=0x%x\n", result); + app_audio_set_volume(APP_AUDIO_STATE_WTONE, get_max_sys_vol() / 2, 1); + tone_play(TONE_SIN_NORMAL, 1); + //tone_play_index(IDEX_TONE_NORMAL, 1); + /* os_time_dly(50); */ + /* tone_stop(); */ + os_time_dly(25); + //delay_2ms(500); + } +#endif + if (key_voice_cnt > 5) { + key_voice_cnt = 0; + //delay_2ms(500); + //os_time_dly(100); + puts("enter_sys_soft_poweroff\n"); + break; + //注:关机要慎重,要设置开机键 + //enter_sys_soft_poweroff(); + } + } + + return 1; +} + +void clr_update_ram_info(void) +{ + UPDATA_PARM *p = UPDATA_FLAG_ADDR; + memset(p, 0x00, sizeof(UPDATA_PARM)); +} + +static u32 loader_start_addr = 0; +void set_loader_start_addr(u32 addr) +{ + loader_start_addr = addr; +} + +void update_close_hw(void *filter_name) +{ + const struct update_target *p; + list_for_each_update_target(p) { + if (0 != memcmp(filter_name, p->name, strlen(filter_name))) { + p->driver_close(); + printf("close Hw Name : %s\n", p->name); + } + } +} + +//write(buf,len); +void updata_parm_set(UPDATA_TYPE up_type, void *priv, u32 len) +{ + UPDATA_PARM *p = UPDATA_FLAG_ADDR; + u8 addr[6]; +#ifdef UPDATE_LED_REMIND + led_update_start(); +#endif + memset((u8 *)p, 0x00, sizeof(UPDATA_PARM)); + p->parm_type = (u16)up_type; + p->parm_result = (u16)UPDATA_READY; + memcpy(p->file_path, updata_file_name, strlen(updata_file_name)); + if (priv) { + if (support_norflash_update_en) { + printf("p->parm_priv:0x%x\n len:%d\n", p->parm_priv, len); + memcpy(p->parm_priv + 12, priv, len); + } else { + printf("p->parm_priv:0x%x priv:0x%x len:%d\n", p->parm_priv, priv, len); + memcpy(p->parm_priv, priv, len); + } + } else { + memset(p->parm_priv, 0x00, sizeof(p->parm_priv)); + if ((up_type == BLE_TEST_UPDATA) && UPDATE_MODULE_IS_SUPPORT(UPDATE_BLE_TEST_EN)) { + extern int le_controller_get_mac(void *addr); + le_controller_get_mac(addr); + memcpy(p->parm_priv, addr, 6); + puts("ble addr:\n"); + put_buf(p->parm_priv, 6); + } + } +#if (USE_SDFILE_NEW == 1) + p->magic = UPDATE_PARAM_MAGIC; + p->ota_addr = loader_start_addr; +#endif + +#ifdef CONFIG_SD_UPDATE_ENABLE + if ((up_type == SD0_UPDATA) || (up_type == SD1_UPDATA)) { + int sd_start = (u32)p + sizeof(UPDATA_PARM); + void *sd = NULL; + sd = dev_update_get_parm(up_type); + if (sd) { + memcpy((void *)sd_start, sd, UPDATE_PRIV_PARAM_LEN); + } else { + memset((void *)sd_start, 0, UPDATE_PRIV_PARAM_LEN); + } + } +#endif + +#ifdef CONFIG_USB_UPDATE_ENABLE + if (up_type == USB_UPDATA) { + log_info("usb updata "); + int usb_start = (u32)p + sizeof(UPDATA_PARM); + memset((void *)usb_start, 0, UPDATE_PRIV_PARAM_LEN); + } +#endif + + /* #if RCSP_UPDATE_EN */ + /* extern u32 ex_cfg_get_start_addr(void); */ + /* if (support_norflash_update_en) { */ + /* *((u32 *)(p->parm_priv + 12)) = ex_cfg_get_start_addr();//12个字节是Norflash升级参数占用 */ + /* } else { */ + /* *((u32 *)(p->parm_priv)) = ex_cfg_get_start_addr(); //为了兼容之前的程序升级 */ + /* } */ + /* #endif */ + if (support_norflash_update_en) { + get_nor_update_param(p->parm_priv); + p->parm_type = NORFLASH_UPDATA; + *((u16 *)((u8 *)p + sizeof(UPDATA_PARM) + 32)) = up_type; //将实际的升级类型保存到ram + } + + p->parm_crc = CRC16(((u8 *)p) + 2, sizeof(UPDATA_PARM) - 2); //2 : crc_val + printf("UPDATA_PARM_ADDR = 0x%x\n", p); + printf_buf((void *)p, sizeof(UPDATA_PARM)); + printf("exif_addr:0x%x\n", *(u32 *)(p->parm_priv)); +} + +//reset +void updata_enter_reset(UPDATA_TYPE up_type) +{ + log_info("updata_enter_reset\n\n\n"); + cpu_reset(); + //reset + //JL_POWER->CON |= BIT(4); + /* JL_CLOCK->PWR_CON |= BIT(4); */ +} + + +#define LOADER_NAME "LOADER.BIN" +const u8 loader_file_path[] = "mnt/norflash/C/"LOADER_NAME""; + +extern void ll_hci_destory(void); +extern void hci_controller_destory(void); +extern const int support_norflash_update_en; +extern void ram_protect_close(void); + +extern void hwi_all_close(void); +static void update_before_jump_common_handle(UPDATA_TYPE up_type) +{ + dev_update_close_ui(); + +#if TCFG_AUDIO_ANC_ENABLE + extern void audio_anc_hw_close(); + audio_anc_hw_close(); +#endif + + local_irq_disable(); + hwi_all_close(); + + /* local_irq_disable(); + for (i = 0; i < 64; i++) { + bit_clr_ie(i); + } */ + +} + +extern void __bt_updata_reset_bt_bredrexm_addr(void); +extern int __bt_updata_save_connection_info(void); +void update_mode_api(UPDATA_TYPE up_type, ...) +{ + u8 i; + u32 addr; + dev_update_close_ui(); +#if RCSP_ADV_EN || RCSP_BTMATE_EN || SMART_BOX_EN + if (up_type == BLE_APP_UPDATA || up_type == SPP_APP_UPDATA) { + addr = ex_cfg_fill_content_api(); + } +#endif + //step 1: disable irq +#if TCFG_USER_TWS_ENABLE || TCFG_USER_BLE_ENABLE + if (up_type == BT_UPDATA) { + log_info("close ble hw\n"); + ll_hci_destory(); + } +#endif + +#if TCFG_AUDIO_ANC_ENABLE + extern void audio_anc_hw_close(); + audio_anc_hw_close(); +#endif + local_irq_disable(); + for (i = 0; i < 64; i++) { + bit_clr_ie(i); + } + //step 2: prepare parm + + printf("update_type:0x%x\n", up_type); + switch (up_type) { +#ifdef CONFIG_SD_UPDATE_ENABLE + case SD0_UPDATA: + case SD1_UPDATA: + updata_parm_set(up_type, (u8 *)loader_file_path, sizeof(loader_file_path)); + break; +#endif +#ifdef CONFIG_USB_UPDATE_ENABLE + case USB_UPDATA: + updata_parm_set(up_type, (u8 *)loader_file_path, sizeof(loader_file_path)); + break; +#endif + + case UART_UPDATA: + /* uart_updata_io_ctrl(&parm); */ + //log_info("up_io = %x\nup_baud = %d\nup_timeout = %dms\n", ((UPDATA_UART *)parm)->control_io, ((UPDATA_UART *)parm)->control_baud, ((UPDATA_UART *)parm)->control_timeout * 10); + /* updata_parm_set(up_type, (u8 *)loader_file_path, sizeof(loader_file_path)); */ + { + va_list argptr; + va_start(argptr, up_type); + u32 baudrate = va_arg(argptr, int); + u32 uart_update_io_tx = va_arg(argptr, int); + u32 uart_update_io_rx = va_arg(argptr, int); + va_end(argptr); + UPDATA_UART uart_param = {.control_baud = baudrate, .control_io_tx = uart_update_io_tx, .control_io_rx = uart_update_io_rx}; + updata_parm_set(up_type, (u8 *)&uart_param, sizeof(UPDATA_UART)); + } + break; + + case BT_UPDATA: + if (UPDATE_MODULE_IS_SUPPORT(UPDATE_BT_LMP_EN)) { + if (__bt_updata_save_connection_info()) { + log_error("bt save conn info fail!\n"); + break; + } + updata_parm_set(up_type, (u8 *)loader_file_path, sizeof(loader_file_path)); + ram_protect_close(); + __bt_updata_reset_bt_bredrexm_addr(); + //note:last func no return; + } + break; + + case BLE_TEST_UPDATA: + if (BT_MODULES_IS_SUPPORT(BT_MODULE_LE)) { + ll_hci_destory(); + updata_parm_set(up_type, NULL, 0); + } + break; + +#if RCSP_UPDATE_EN + case BLE_APP_UPDATA: + updata_parm_set(up_type, (u8 *)&addr, sizeof(addr)); + break; + + case SPP_APP_UPDATA: + updata_parm_set(BLE_APP_UPDATA, (u8 *)&addr, sizeof(addr)); //暂时不支持SPP + break; +#endif + + default: + updata_parm_set(up_type, NULL, 0); + break; + } + + +#ifdef DEV_UPDATE_SUPPORT_JUMP +#if TCFG_BLUETOOTH_BACK_MODE //后台模式需要把蓝牙关掉 + if (BT_MODULES_IS_SUPPORT(BT_MODULE_LE)) { + ll_hci_destory(); + } + hci_controller_destory(); +#endif + update_close_hw(); + ram_protect_close(); + save_spi_port(); + + printf("update jump to mask...\n"); + /* JL_UART0->CON0 = 0; */ + /* JL_UART1->CON0 = 0; */ + __JUMP_TO_MASKROM(); +#else + //step 3: enter updata + updata_enter_reset(up_type); + /* updata_enter_jump(up_type); */ +#endif //DEV_UPDATE_SUPPORT_JUMP +} + +/* void update_param_setting() +{ + u32 saddr + void (* +} */ + +void update_parm_set_and_get_buf(int type, u32 loader_saddr, void **buf_addr, u16 *len) +{ + u32 exif_addr; + + int total_len = sizeof(UPDATA_PARM); + if ((type == SD0_UPDATA) || (type == SD1_UPDATA) || (type == USB_UPDATA)) { + total_len += UPDATE_PRIV_PARAM_LEN; + } + + set_loader_start_addr(loader_saddr); + if ((BLE_APP_UPDATA == type) || (SPP_APP_UPDATA == type)) { +#if RCSP_UPDATE_EN + extern u32 ex_cfg_get_start_addr(void); + exif_addr = ex_cfg_get_start_addr(); + printf("exif_addr:0x%x\n", exif_addr); + updata_parm_set(type, (u8 *)&exif_addr, sizeof(exif_addr)); +#endif + } else if (UART_UPDATA == type) { +#if(USER_UART_UPDATE_ENABLE) && (UART_UPDATE_ROLE == UART_UPDATE_SLAVE) + sava_uart_update_param(); +#endif + } else if (BLE_TEST_UPDATA == type) { + updata_parm_set(type, NULL, 0); + } else { + updata_parm_set(type, (u8 *)loader_file_path, sizeof(loader_file_path)); + } + + *buf_addr = UPDATA_FLAG_ADDR; + *len = total_len; +} +//fill common content +//fill private content +//fill crc16 + +static succ_report_t succ_report; +/* static void (*update_param_private_fill_handle)(UPDATA_PARM *p) = NULL; +static void (*update_before_jump_private_handle)(void) = NULL; +void update_param_private_fill_handle_register(void (*handle)(UPDATA_PARM *p)) +{ + update_param_private_fill_handle = handle; +} + +void update_before_jump_private_handle_register(void (*handle)(u16 type)) +{ + update_before_jump_private_handle = handle; +} */ + +static void update_param_content_fill(int type, UPDATA_PARM *p, void (*priv_param_fill_hdl)(UPDATA_PARM *P)) +{ + memset((u8 *)p, 0x00, sizeof(UPDATA_PARM)); + p->parm_type = (u16)type; + p->parm_result = (u16)UPDATA_READY; + p->magic = UPDATE_PARAM_MAGIC; + p->ota_addr = succ_report.loader_saddr; + + if (0 == p->ota_addr) { + log_error("ota addr err\n"); + return; + } + + if (priv_param_fill_hdl) { + priv_param_fill_hdl(p); + } + + p->parm_crc = CRC16(((u8 *)p) + 2, sizeof(UPDATA_PARM) - 2); //2 : crc_val +} + +static void update_param_ram_set(u8 *buf, u16 len) +{ + u8 *update_ram = UPDATA_FLAG_ADDR; + memcpy(update_ram, (u8 *)buf, len); +} + +void update_mode_api_v2(UPDATA_TYPE type, void (*priv_param_fill_hdl)(UPDATA_PARM *p), void (*priv_update_jump_handle)(int type)) +{ + u16 update_param_len = sizeof(UPDATA_PARM) + UPDATE_PRIV_PARAM_LEN; + + UPDATA_PARM *p = malloc(update_param_len); + + if (p) { + update_param_content_fill(type, p, priv_param_fill_hdl); + + if (succ_report.update_param_write_hdl) { + succ_report.update_param_write_hdl(succ_report.priv_param, p, update_param_len); + } + +#ifdef UPDATE_LED_REMIND + led_update_start(); +#endif + update_before_jump_common_handle(type); + + update_param_ram_set((u8 *)p, update_param_len); + + if (priv_update_jump_handle) { + priv_update_jump_handle(type); + } + + free(p); + } else { + ASSERT(p, "malloc update param err \n"); + } +} + +int update_check_sniff_en(void) + +{ + if (!UPDATE_SUPPORT_DEV_IS_NULL()) { +#if (OTA_TWS_SAME_TIME_ENABLE && RCSP_ADV_EN && !OTA_TWS_SAME_TIME_NEW) + if (tws_ota_control(OTA_STATUS_GET) != OTA_OVER) { + return 0; + } +#endif + if (get_ota_status()) { + log_info("ota ing..."); + return 0; + } else { + return 1; + } + } + return 1; +} + +static volatile u8 ota_status = 0; + +u8 get_ota_status() +{ + return ota_status; +} + +static u8 ota_idle_query(void) +{ + return !ota_status; +} + +REGISTER_LP_TARGET(ota_lp_target) = { + .name = "ota", + .is_idle = ota_idle_query, +}; + +extern void tws_sync_update_api_register(const update_op_tws_api_t *op); +extern update_op_tws_api_t *get_tws_update_api(void); + +extern const int support_dual_bank_update_en; +extern int tws_ota_init(void); +extern void sys_auto_shut_down_disable(void); +extern void sys_auto_shut_down_enable(void); +extern void tws_api_auto_role_switch_disable(); +extern void tws_api_auto_role_switch_enable(); + +static void update_init_common_handle(int type) +{ + ota_status = 1; + if (UPDATE_DUAL_BANK_IS_SUPPORT()) { +#if TCFG_AUTO_SHUT_DOWN_TIME + sys_auto_shut_down_disable(); +#endif + +#if OTA_TWS_SAME_TIME_ENABLE + tws_api_auto_role_switch_disable(); + tws_sync_update_api_register(get_tws_update_api()); + tws_ota_init(); +#endif + } +} + +static void update_exit_common_handle(int type, void *priv) +{ + update_ret_code_t *ret_code = (update_ret_code_t *)priv; + +#if TCFG_AUTO_SHUT_DOWN_TIME + sys_auto_shut_down_enable(); +#endif + +#if OTA_TWS_SAME_TIME_ENABLE + if (UPDATE_DUAL_BANK_IS_SUPPORT()) { + tws_api_auto_role_switch_enable(); + } +#endif + + ota_status = 0; +} + +static void update_common_state_cbk(update_mode_info_t *info, u32 state, void *priv) +{ + int type = info->type; + + log_info("type:%x state:%x code:%x\n", type, state, priv); + + switch (state) { + case UPDATE_CH_INIT: + memset((u8 *)&succ_report, 0x00, sizeof(succ_report_t)); + update_init_common_handle(info->type); + break; + + case UPDATE_CH_SUCESS_REPORT: + log_info("succ report stored\n"); + memcpy((u8 *)&succ_report, (u8 *)priv, sizeof(succ_report_t)); + break; + } + + if (info->state_cbk) { + info->state_cbk(type, state, priv); + } + + switch (state) { + case UPDATE_CH_EXIT: + update_exit_common_handle(info->type, priv); + break; + } +} + +extern void update_module_init(void (*cbk)(update_mode_info_t *, u32, void *)); +extern void testbox_update_init(void); +static void app_update_init(void) +{ + update_module_init(update_common_state_cbk); + testbox_update_init(); +} + +__initcall(app_update_init); + diff --git a/apps/common/usb/device/cdc.c b/apps/common/usb/device/cdc.c new file mode 100644 index 0000000..eac6554 --- /dev/null +++ b/apps/common/usb/device/cdc.c @@ -0,0 +1,479 @@ +#include "usb/device/usb_stack.h" +#include "usb/usb_config.h" +#include "usb/device/cdc.h" +#include "app_config.h" +#include "os/os_api.h" +#include "cdc_defs.h" //need redefine __u8, __u16, __u32 + +#define LOG_TAG_CONST USB +#define LOG_TAG "[USB]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#if TCFG_USB_SLAVE_CDC_ENABLE + + +struct usb_cdc_gadget { + u8 *cdc_buffer; + void *priv; + int (*output)(void *priv, u8 *obuf, u32 olen); + void (*wakeup_handler)(struct usb_device_t *usb_device); + OS_MUTEX mutex_data; +#if CDC_INTR_EP_ENABLE + OS_MUTEX mutex_intr; +#endif + u8 bmTransceiver; + u8 subtype_data[8]; +}; + +static struct usb_cdc_gadget *cdc_hdl; + +#if USB_MALLOC_ENABLE + +#else +static u8 _cdc_buffer[MAXP_SIZE_CDC_BULKOUT] SEC(.cdc_var) __attribute__((aligned(4))); +static struct usb_cdc_gadget _cdc_hdl SEC(.cdc_var); +#endif + +static const u8 cdc_virtual_comport_desc[] = { + //IAD Descriptor + 0x08, //bLength + 0x0b, //bDescriptorType + 0x00, //bFirstInterface + 0x02, //bInterfaceCount + 0x02, //bFunctionClass, Comunication and CDC control + 0x02, //bFunctionSubClass + 0x01, //bFunctionProtocol + 0x00, //iFunction + //Interface 0, Alt 0 + 0x09, //Length + 0x04, //DescriptorType:Interface + 0x00, //InterfaceNum + 0x00, //AlternateSetting + 0x01, //NumEndpoint + 0x02, //InterfaceClass, Communation and CDC control + 0x02, //InterfaceSubClass, Abstract Control Model + 0x01, //InterfaceProtocol, AT commands defined by ITU-T V.250 etc + 0x00, //Interface String + //CDC Interface Descriptor + 0x05, //bLength + 0x24, //bDescriptorType + 0x00, //bDescriptorSubType, Header Functional Desc + 0x10, 0x01, //bcdCDC, version 1.10 + //CDC Interface Descriptor + 0x05, //bLength + 0x24, //bDescriptorType + 0x01, //bDescriptorSubType, Call Management Functional Descriptor + 0x03, //bmCapabilities, D7..D2 reversed + // D7..D2 reversed + // D1 sends/receives call management information only over a Data Class interface + // D0 handle call management itself + 0x01, //bDataInterface + //CDC Interface Descriptor + 0x04, //bLength + 0x24, //bDescriptorType + 0x02, //bDescriptorSubType, Abstract Control Management Functional Descriptor + 0x02, //bmCapabilities, D7..D2 reversed + // D7..D4 reversed + // D3 supports the notification Network_Connection + // D2 not supports the request Send_Break + // D1 supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State + // D0 supports the request combination of Set_Comm_Feature, Clear_Comm_Feature, and Get_Comm_Feature + //CDC Interface Descriptor + 0x05, //bLength + 0x24, //bDescriptorType + 0x06, //bDescriptorSubType, Union Functional Descriptor + 0x00, //bControlInterface + 0x01, //bSubordinateInterface[0] + //Endpoint In + 0x07, //bLength + 0x05, //bDescritorType + 0x82, //bEndpointAddr + 0x03, //bmAttributes, interrupt + 0x08, 0x00, //wMaxPacketSize + 0x01, //bInterval, 1ms + //Interface 1, Alt 0 + 0x09, //Length + 0x04, //DescriptorType:Interface + 0x01, //InterfaceNum + 0x00, //AlternateSetting + 0x02, //NumEndpoint + 0x0a, //InterfaceClass, CDC Data + 0x00, //InterfaceSubClass + 0x00, //InterfaceProtocol + 0x00, //Interface String + //Endpoint Out + 0x07, //bLength + 0x05, //bDescriptor + 0x02, //bEndpointAddr + 0x02, //bmAttributes, bulk + 0x40, 0x00, //wMaxPacketSize + 0x00, //bInterval + //Endpoint In + 0x07, //bLength + 0x05, //bDescritorType + 0x83, //bEndpointAddr + 0x02, //bmAttributes, bulk + 0x40, 0x00, //wMaxPacketSize + 0x00, //bInterval +}; + +static void cdc_endpoint_init(struct usb_device_t *usb_device, u32 itf); +static u32 cdc_setup_rx(struct usb_device_t *usb_device, struct usb_ctrlrequest *ctrl_req); + +static void usb_cdc_line_coding_init(struct usb_cdc_line_coding *lc) +{ + lc->dwDTERate = 460800; + lc->bCharFormat = USB_CDC_1_STOP_BITS; + lc->bParityType = USB_CDC_NO_PARITY; + lc->bDataBits = 8; +} + +static void dump_line_coding(struct usb_cdc_line_coding *lc) +{ + log_debug("dtw rate : %d", lc->dwDTERate); + log_debug("stop bits : %d", lc->bCharFormat); + log_debug("verify bits : %d", lc->bParityType); + log_debug("data bits : %d", lc->bDataBits); +} + +static u32 cdc_setup(struct usb_device_t *usb_device, struct usb_ctrlrequest *ctrl_req) +{ + const usb_dev usb_id = usb_device2id(usb_device); + int recip_type; + u32 len; + + recip_type = ctrl_req->bRequestType & USB_TYPE_MASK; + + switch (recip_type) { + case USB_TYPE_CLASS: + switch (ctrl_req->bRequest) { + case USB_CDC_REQ_SET_LINE_CODING: + log_debug("set line coding"); + usb_set_setup_recv(usb_device, cdc_setup_rx); + break; + case USB_CDC_REQ_GET_LINE_CODING: + log_debug("get line codling"); + len = ctrl_req->wLength < sizeof(struct usb_cdc_line_coding) ? + ctrl_req->wLength : sizeof(struct usb_cdc_line_coding); + if (cdc_hdl == NULL) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + break; + } + usb_set_data_payload(usb_device, ctrl_req, cdc_hdl->subtype_data, len); + dump_line_coding((struct usb_cdc_line_coding *)cdc_hdl->subtype_data); + break; + case USB_CDC_REQ_SET_CONTROL_LINE_STATE: + log_debug("set control line state - %d", ctrl_req->wValue); + if (cdc_hdl) { + /* if (ctrl_req->wValue & BIT(0)) { //DTR */ + cdc_hdl->bmTransceiver |= BIT(0); + /* } else { */ + /* usb_slave->cdc->bmTransceiver &= ~BIT(0); */ + /* } */ + /* if (ctrl_req->wValue & BIT(1)) { //RTS */ + cdc_hdl->bmTransceiver |= BIT(1); + /* } else { */ + /* usb_slave->cdc->bmTransceiver &= ~BIT(1); */ + /* } */ + cdc_hdl->bmTransceiver |= BIT(4); //cfg done + } + usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP); + //cdc_endpoint_init(usb_device, (ctrl_req->wIndex & USB_RECIP_MASK)); + break; + default: + log_error("unsupported class req"); + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + break; + } + break; + default: + log_error("unsupported req type"); + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + break; + } + return 0; +} + +static u32 cdc_setup_rx(struct usb_device_t *usb_device, struct usb_ctrlrequest *ctrl_req) +{ + const usb_dev usb_id = usb_device2id(usb_device); + int recip_type; + struct usb_cdc_line_coding *lc = 0; + u32 len; + u8 read_ep[8]; + + len = ctrl_req->wLength; + usb_read_ep0(usb_id, read_ep, len); + recip_type = ctrl_req->bRequestType & USB_TYPE_MASK; + switch (recip_type) { + case USB_TYPE_CLASS: + switch (ctrl_req->bRequest) { + case USB_CDC_REQ_SET_LINE_CODING: + log_debug("USB_CDC_REQ_SET_LINE_CODING"); + if (cdc_hdl == NULL) { + break; + } + if (len > sizeof(struct usb_cdc_line_coding)) { + len = sizeof(struct usb_cdc_line_coding); + } + memcpy(cdc_hdl->subtype_data, read_ep, len); + lc = (struct usb_cdc_line_coding *)cdc_hdl->subtype_data; + dump_line_coding(lc); + break; + } + break; + } + return USB_EP0_STAGE_SETUP; +} + +static void cdc_reset(struct usb_device_t *usb_device, u32 itf) +{ + log_error("%s()", __func__); + const usb_dev usb_id = usb_device2id(usb_device); +#if USB_ROOT2 + usb_disable_ep(usb_id, CDC_DATA_EP_IN); +#if CDC_INTR_EP_ENABLE + usb_disable_ep(usb_id, CDC_INTR_EP_IN); +#endif +#else + cdc_endpoint_init(usb_device, itf); +#endif +} + +u32 cdc_desc_config(const usb_dev usb_id, u8 *ptr, u32 *itf) +{ + u8 *tptr; + + tptr = ptr; + memcpy(tptr, cdc_virtual_comport_desc, sizeof(cdc_virtual_comport_desc)); + //iad interface number + tptr[2] = *itf; + //control interface number + tptr[8 + 2] = *itf; + tptr[8 + 9 + 5 + 4] = *itf + 1; + tptr[8 + 9 + 5 + 5 + 4 + 3] = *itf; + tptr[8 + 9 + 5 + 5 + 4 + 4] = *itf + 1; + //interrupt in ep + tptr[8 + 9 + 5 + 5 + 4 + 5 + 2] = USB_DIR_IN | CDC_INTR_EP_IN; + tptr[8 + 9 + 5 + 5 + 4 + 5 + 4] = MAXP_SIZE_CDC_INTRIN & 0xff; + tptr[8 + 9 + 5 + 5 + 4 + 5 + 5] = (MAXP_SIZE_CDC_INTRIN >> 8) & 0xff; + //data interface number + tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 2] = *itf + 1; + //bulk out ep + tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 2] = CDC_DATA_EP_OUT; + tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 4] = MAXP_SIZE_CDC_BULKOUT & 0xff; + tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 5] = (MAXP_SIZE_CDC_BULKOUT >> 8) & 0xff; + //bulk in ep + tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 2] = USB_DIR_IN | CDC_DATA_EP_IN; + tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 4] = MAXP_SIZE_CDC_BULKIN & 0xff; + tptr[8 + 9 + 5 + 5 + 4 + 5 + 7 + 9 + 7 + 5] = (MAXP_SIZE_CDC_BULKIN >> 8) & 0xff; + tptr += sizeof(cdc_virtual_comport_desc); + + if (usb_set_interface_hander(usb_id, *itf, cdc_setup) != *itf) { + ASSERT(0, "cdc set interface_hander fail"); + } + if (usb_set_reset_hander(usb_id, *itf, cdc_reset) != *itf) { + + } + *itf += 2; + return (u32)(tptr - ptr); +} + +void cdc_set_wakeup_handler(void (*handle)(struct usb_device_t *usb_device)) +{ + if (cdc_hdl) { + cdc_hdl->wakeup_handler = handle; + } +} + +static void cdc_wakeup_handler(struct usb_device_t *usb_device, u32 ep) +{ + if (cdc_hdl && cdc_hdl->wakeup_handler) { + cdc_hdl->wakeup_handler(usb_device); + } +} + +void cdc_set_output_handle(void *priv, int (*output_handler)(void *priv, u8 *buf, u32 len)) +{ + if (cdc_hdl) { + cdc_hdl->output = output_handler; + cdc_hdl->priv = priv; + } +} + +static void cdc_intrrx(struct usb_device_t *usb_device, u32 ep) +{ + const usb_dev usb_id = usb_device2id(usb_device); + if (cdc_hdl == NULL) { + return; + } + u8 *cdc_rx_buf = cdc_hdl->cdc_buffer; + //由于bulk传输使用双缓冲,无法用usb_get_ep_buffer()知道是哪一个buffer,需要外部buffer接收数据 + u32 len = usb_g_bulk_read(usb_id, CDC_DATA_EP_OUT, cdc_rx_buf, MAXP_SIZE_CDC_BULKOUT, 0); + if (cdc_hdl->output) { + cdc_hdl->output(cdc_hdl->priv, cdc_rx_buf, len); + } +} + +static void cdc_endpoint_init(struct usb_device_t *usb_device, u32 itf) +{ + u8 *ep_buffer; + const usb_dev usb_id = usb_device2id(usb_device); + + ep_buffer = usb_get_ep_buffer(usb_id, CDC_DATA_EP_IN | USB_DIR_IN); + ASSERT(ep_buffer, "usb alloc ep buffer failed"); + usb_g_ep_config(usb_id, CDC_DATA_EP_IN | USB_DIR_IN, USB_ENDPOINT_XFER_BULK, 0, ep_buffer, MAXP_SIZE_CDC_BULKIN); + + ep_buffer = usb_get_ep_buffer(usb_id, CDC_DATA_EP_OUT | USB_DIR_OUT); + ASSERT(ep_buffer, "usb alloc ep buffer failed"); + usb_g_ep_config(usb_id, CDC_DATA_EP_OUT | USB_DIR_OUT, USB_ENDPOINT_XFER_BULK, 1, ep_buffer, MAXP_SIZE_CDC_BULKOUT); + /* usb_g_set_intr_hander(usb_id, CDC_DATA_EP_OUT | USB_DIR_OUT, cdc_intrrx); */ + usb_g_set_intr_hander(usb_id, CDC_DATA_EP_OUT | USB_DIR_OUT, cdc_wakeup_handler); + usb_enable_ep(usb_id, CDC_DATA_EP_IN); + +#if CDC_INTR_EP_ENABLE + ep_buffer = usb_get_ep_buffer(usb_id, CDC_INTR_EP_IN | USB_DIR_IN); + ASSERT(ep_buffer, "usb alloc ep buffer failed"); + usb_g_ep_config(usb_id, CDC_INTR_EP_IN | USB_DIR_IN, USB_ENDPOINT_XFER_INT, 0, ep_buffer, MAXP_SIZE_CDC_INTRIN); + usb_enable_ep(usb_id, CDC_INTR_EP_IN); +#endif +} + +u32 cdc_read_data(const usb_dev usb_id, u8 *buf, u32 len) +{ + u32 rxlen; + if (cdc_hdl == NULL) { + return 0; + } + u8 *cdc_rx_buf = cdc_hdl->cdc_buffer; + os_mutex_pend(&cdc_hdl->mutex_data, 0); + //由于bulk传输使用双缓冲,无法用usb_get_ep_buffer()知道是哪一个buffer,需要外部buffer接收数据 + rxlen = usb_g_bulk_read(usb_id, CDC_DATA_EP_OUT, cdc_rx_buf, MAXP_SIZE_CDC_BULKOUT, 0); + rxlen = rxlen > len ? len : rxlen; + if (rxlen > 0) { + memcpy(buf, cdc_rx_buf, rxlen); + } + os_mutex_post(&cdc_hdl->mutex_data); + return rxlen; +} + +u32 cdc_write_data(const usb_dev usb_id, u8 *buf, u32 len) +{ + u32 txlen, offset; + if (cdc_hdl == NULL) { + return 0; + } + if ((cdc_hdl->bmTransceiver & (BIT(1) | BIT(4))) != (BIT(1) | BIT(4))) { + return 0; + } + offset = 0; + os_mutex_pend(&cdc_hdl->mutex_data, 0); + while (offset < len) { + txlen = len - offset > MAXP_SIZE_CDC_BULKIN ? + MAXP_SIZE_CDC_BULKIN : len - offset; + txlen = usb_g_bulk_write(usb_id, CDC_DATA_EP_IN, buf + offset, txlen); + if (txlen == 0) { + break; + } + if ((cdc_hdl->bmTransceiver & (BIT(1) | BIT(4))) != (BIT(1) | BIT(4))) { + break; + } + offset += txlen; + } + if (txlen == MAXP_SIZE_CDC_BULKIN) { + txlen = usb_g_bulk_write(usb_id, CDC_DATA_EP_IN, NULL, 0); + } + os_mutex_post(&cdc_hdl->mutex_data); + return offset; +} + +u32 cdc_write_inir(const usb_dev usb_id, u8 *buf, u32 len) +{ +#if CDC_INTR_EP_ENABLE + u32 txlen, offset; + if (cdc_hdl == NULL) { + return 0; + } + if ((cdc_hdl->bmTransceiver & BIT(4)) == 0) { + return 0; + } + offset = 0; + os_mutex_pend(&cdc_hdl->mutex_intr, 0); + while (offset < len) { + txlen = len - offset > MAXP_SIZE_CDC_INTRIN ? + MAXP_SIZE_CDC_INTRIN : len - offset; + txlen = usb_g_intr_write(usb_id, CDC_INTR_EP_IN, buf + offset, txlen); + if (txlen == 0) { + break; + } + if ((cdc_hdl->bmTransceiver & BIT(4)) == 0) { + break; + } + offset += txlen; + } + os_mutex_post(&cdc_hdl->mutex_intr); + return offset; +#else + return 0; +#endif +} + +void cdc_register(const usb_dev usb_id) +{ + struct usb_cdc_line_coding *lc; + /* log_info("%s() %d", __func__, __LINE__); */ + if (!cdc_hdl) { +#if USB_MALLOC_ENABLE + cdc_hdl = zalloc(sizeof(struct usb_cdc_gadget)); + if (!cdc_hdl) { + log_error("cdc_register err 1"); + return; + } + cdc_hdl->cdc_buffer = malloc(MAXP_SIZE_CDC_BULKOUT); + if (!cdc_hdl->cdc_buffer) { + log_error("cdc_register err 2"); + goto __exit_err; + } +#else + memset(&_cdc_hdl, 0, sizeof(struct usb_cdc_gadget)); + cdc_hdl = &_cdc_hdl; + cdc_hdl->cdc_buffer = _cdc_buffer; +#endif + lc = (struct usb_cdc_line_coding *)cdc_hdl->subtype_data; + usb_cdc_line_coding_init(lc); + os_mutex_create(&cdc_hdl->mutex_data); +#if CDC_INTR_EP_ENABLE + os_mutex_create(&cdc_hdl->mutex_intr); +#endif + } + return; +__exit_err: +#if USB_MALLOC_ENABLE + if (cdc_hdl->cdc_buffer) { + free(cdc_hdl->cdc_buffer); + } + if (cdc_hdl) { + free(cdc_hdl); + } +#endif + cdc_hdl = NULL; +} + +void cdc_release(const usb_dev usb_id) +{ + /* log_info("%s() %d", __func__, __LINE__); */ + if (cdc_hdl) { +#if USB_MALLOC_ENABLE + free(cdc_hdl->cdc_buffer); + free(cdc_hdl); +#endif + cdc_hdl = NULL; + } +} + +#endif diff --git a/apps/common/usb/device/cdc.h b/apps/common/usb/device/cdc.h new file mode 100644 index 0000000..45a27f7 --- /dev/null +++ b/apps/common/usb/device/cdc.h @@ -0,0 +1,23 @@ +#ifndef __CDC_H__ +#define __CDC_H__ + +#include "usb/device/usb_stack.h" + +#ifdef __cplusplus +extern "C" { +#endif + +u32 cdc_desc_config(const usb_dev usb_id, u8 *ptr, u32 *itf); +void cdc_set_wakeup_handler(void (*handle)(struct usb_device_t *usb_device)); +void cdc_set_output_handle(void *priv, int (*output_handler)(void *priv, u8 *buf, u32 len)); +u32 cdc_read_data(const usb_dev usb_id, u8 *buf, u32 len); +u32 cdc_write_data(const usb_dev usb_id, u8 *buf, u32 len); +u32 cdc_write_inir(const usb_dev usb_id, u8 *buf, u32 len); +void cdc_register(const usb_dev usb_id); +void cdc_release(const usb_dev usb_id); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/apps/common/usb/device/cdc_defs.h b/apps/common/usb/device/cdc_defs.h new file mode 100644 index 0000000..727d8fb --- /dev/null +++ b/apps/common/usb/device/cdc_defs.h @@ -0,0 +1,457 @@ + +/* + * USB Communications Device Class (CDC) definitions + * + * CDC says how to talk to lots of different types of network adapters, + * notably ethernet adapters and various modems. It's used mostly with + * firmware based USB peripherals. + */ + +#ifndef __LINUX_USB_CDC_H +#define __LINUX_USB_CDC_H + +#include "typedef.h" /* __u8 etc */ + +#ifdef __le16 +#undef __le16 +#endif +typedef unsigned short __le16; +#ifdef __le32 +#undef __le32 +#endif +typedef unsigned int __le32; +#ifdef __u8 +#undef __u8 +#endif +typedef unsigned char __u8; +#ifdef __u16 +#undef __u16 +#endif +typedef unsigned short __u16; +#ifdef __u32 +#undef __u32 +#endif +typedef unsigned int __u32; + +#define USB_CDC_SUBCLASS_ACM 0x02 +#define USB_CDC_SUBCLASS_ETHERNET 0x06 +#define USB_CDC_SUBCLASS_WHCM 0x08 +#define USB_CDC_SUBCLASS_DMM 0x09 +#define USB_CDC_SUBCLASS_MDLM 0x0a +#define USB_CDC_SUBCLASS_OBEX 0x0b +#define USB_CDC_SUBCLASS_EEM 0x0c +#define USB_CDC_SUBCLASS_NCM 0x0d +#define USB_CDC_SUBCLASS_MBIM 0x0e + +#define USB_CDC_PROTO_NONE 0 + +#define USB_CDC_ACM_PROTO_AT_V25TER 1 +#define USB_CDC_ACM_PROTO_AT_PCCA101 2 +#define USB_CDC_ACM_PROTO_AT_PCCA101_WAKE 3 +#define USB_CDC_ACM_PROTO_AT_GSM 4 +#define USB_CDC_ACM_PROTO_AT_3G 5 +#define USB_CDC_ACM_PROTO_AT_CDMA 6 +#define USB_CDC_ACM_PROTO_VENDOR 0xff + +#define USB_CDC_PROTO_EEM 7 + +#define USB_CDC_NCM_PROTO_NTB 1 +#define USB_CDC_MBIM_PROTO_NTB 2 + +/*-------------------------------------------------------------------------*/ + +/* + * Class-Specific descriptors ... there are a couple dozen of them + */ + +#define USB_CDC_HEADER_TYPE 0x00 /* header_desc */ +#define USB_CDC_CALL_MANAGEMENT_TYPE 0x01 /* call_mgmt_descriptor */ +#define USB_CDC_ACM_TYPE 0x02 /* acm_descriptor */ +#define USB_CDC_UNION_TYPE 0x06 /* union_desc */ +#define USB_CDC_COUNTRY_TYPE 0x07 +#define USB_CDC_NETWORK_TERMINAL_TYPE 0x0a /* network_terminal_desc */ +#define USB_CDC_ETHERNET_TYPE 0x0f /* ether_desc */ +#define USB_CDC_WHCM_TYPE 0x11 +#define USB_CDC_MDLM_TYPE 0x12 /* mdlm_desc */ +#define USB_CDC_MDLM_DETAIL_TYPE 0x13 /* mdlm_detail_desc */ +#define USB_CDC_DMM_TYPE 0x14 +#define USB_CDC_OBEX_TYPE 0x15 +#define USB_CDC_NCM_TYPE 0x1a +#define USB_CDC_MBIM_TYPE 0x1b + +/* "Header Functional Descriptor" from CDC spec 5.2.3.1 */ +struct usb_cdc_header_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __le16 bcdCDC; +} __attribute__((packed)); + +/* "Call Management Descriptor" from CDC spec 5.2.3.2 */ +struct usb_cdc_call_mgmt_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bmCapabilities; +#define USB_CDC_CALL_MGMT_CAP_CALL_MGMT 0x01 +#define USB_CDC_CALL_MGMT_CAP_DATA_INTF 0x02 + + __u8 bDataInterface; +} __attribute__((packed)); + +/* "Abstract Control Management Descriptor" from CDC spec 5.2.3.3 */ +struct usb_cdc_acm_descriptor { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bmCapabilities; +} __attribute__((packed)); + +/* capabilities from 5.2.3.3 */ + +#define USB_CDC_COMM_FEATURE 0x01 +#define USB_CDC_CAP_LINE 0x02 +#define USB_CDC_CAP_BRK 0x04 +#define USB_CDC_CAP_NOTIFY 0x08 + +/* "Union Functional Descriptor" from CDC spec 5.2.3.8 */ +struct usb_cdc_union_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bMasterInterface0; + __u8 bSlaveInterface0; + /* ... and there could be other slave interfaces */ +} __attribute__((packed)); + +/* "Country Selection Functional Descriptor" from CDC spec 5.2.3.9 */ +struct usb_cdc_country_functional_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 iCountryCodeRelDate; + __le16 wCountyCode0; + /* ... and there can be a lot of country codes */ +} __attribute__((packed)); + +/* "Network Channel Terminal Functional Descriptor" from CDC spec 5.2.3.11 */ +struct usb_cdc_network_terminal_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 bEntityId; + __u8 iName; + __u8 bChannelIndex; + __u8 bPhysicalInterface; +} __attribute__((packed)); + +/* "Ethernet Networking Functional Descriptor" from CDC spec 5.2.3.16 */ +struct usb_cdc_ether_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __u8 iMACAddress; + __le32 bmEthernetStatistics; + __le16 wMaxSegmentSize; + __le16 wNumberMCFilters; + __u8 bNumberPowerFilters; +} __attribute__((packed)); + +/* "Telephone Control Model Functional Descriptor" from CDC WMC spec 6.3..3 */ +struct usb_cdc_dmm_desc { + __u8 bFunctionLength; + __u8 bDescriptorType; + __u8 bDescriptorSubtype; + __u16 bcdVersion; + __le16 wMaxCommand; +} __attribute__((packed)); + +/* "MDLM Functional Descriptor" from CDC WMC spec 6.7.2.3 */ +struct usb_cdc_mdlm_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __le16 bcdVersion; + __u8 bGUID[16]; +} __attribute__((packed)); + +/* "MDLM Detail Functional Descriptor" from CDC WMC spec 6.7.2.4 */ +struct usb_cdc_mdlm_detail_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + /* type is associated with mdlm_desc.bGUID */ + __u8 bGuidDescriptorType; + __u8 bDetailData[0]; +} __attribute__((packed)); + +/* "OBEX Control Model Functional Descriptor" */ +struct usb_cdc_obex_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __le16 bcdVersion; +} __attribute__((packed)); + +/* "NCM Control Model Functional Descriptor" */ +struct usb_cdc_ncm_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __le16 bcdNcmVersion; + __u8 bmNetworkCapabilities; +} __attribute__((packed)); + +/* "MBIM Control Model Functional Descriptor" */ +struct usb_cdc_mbim_desc { + __u8 bLength; + __u8 bDescriptorType; + __u8 bDescriptorSubType; + + __le16 bcdMBIMVersion; + __le16 wMaxControlMessage; + __u8 bNumberFilters; + __u8 bMaxFilterSize; + __le16 wMaxSegmentSize; + __u8 bmNetworkCapabilities; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* + * Class-Specific Control Requests (6.2) + * + * section 3.6.2.1 table 4 has the ACM profile, for modems. + * section 3.8.2 table 10 has the ethernet profile. + * + * Microsoft's RNDIS stack for Ethernet is a vendor-specific CDC ACM variant, + * heavily dependent on the encapsulated (proprietary) command mechanism. + */ + +#define USB_CDC_SEND_ENCAPSULATED_COMMAND 0x00 +#define USB_CDC_GET_ENCAPSULATED_RESPONSE 0x01 +#define USB_CDC_REQ_SET_LINE_CODING 0x20 +#define USB_CDC_REQ_GET_LINE_CODING 0x21 +#define USB_CDC_REQ_SET_CONTROL_LINE_STATE 0x22 +#define USB_CDC_REQ_SEND_BREAK 0x23 +#define USB_CDC_SET_ETHERNET_MULTICAST_FILTERS 0x40 +#define USB_CDC_SET_ETHERNET_PM_PATTERN_FILTER 0x41 +#define USB_CDC_GET_ETHERNET_PM_PATTERN_FILTER 0x42 +#define USB_CDC_SET_ETHERNET_PACKET_FILTER 0x43 +#define USB_CDC_GET_ETHERNET_STATISTIC 0x44 +#define USB_CDC_GET_NTB_PARAMETERS 0x80 +#define USB_CDC_GET_NET_ADDRESS 0x81 +#define USB_CDC_SET_NET_ADDRESS 0x82 +#define USB_CDC_GET_NTB_FORMAT 0x83 +#define USB_CDC_SET_NTB_FORMAT 0x84 +#define USB_CDC_GET_NTB_INPUT_SIZE 0x85 +#define USB_CDC_SET_NTB_INPUT_SIZE 0x86 +#define USB_CDC_GET_MAX_DATAGRAM_SIZE 0x87 +#define USB_CDC_SET_MAX_DATAGRAM_SIZE 0x88 +#define USB_CDC_GET_CRC_MODE 0x89 +#define USB_CDC_SET_CRC_MODE 0x8a + +/* Line Coding Structure from CDC spec 6.2.13 */ +struct usb_cdc_line_coding { + __le32 dwDTERate; + __u8 bCharFormat; +#define USB_CDC_1_STOP_BITS 0 +#define USB_CDC_1_5_STOP_BITS 1 +#define USB_CDC_2_STOP_BITS 2 + + __u8 bParityType; +#define USB_CDC_NO_PARITY 0 +#define USB_CDC_ODD_PARITY 1 +#define USB_CDC_EVEN_PARITY 2 +#define USB_CDC_MARK_PARITY 3 +#define USB_CDC_SPACE_PARITY 4 + + __u8 bDataBits; +} __attribute__((packed)); + +/* table 62; bits in multicast filter */ +#define USB_CDC_PACKET_TYPE_PROMISCUOUS (1 << 0) +#define USB_CDC_PACKET_TYPE_ALL_MULTICAST (1 << 1) /* no filter */ +#define USB_CDC_PACKET_TYPE_DIRECTED (1 << 2) +#define USB_CDC_PACKET_TYPE_BROADCAST (1 << 3) +#define USB_CDC_PACKET_TYPE_MULTICAST (1 << 4) /* filtered */ + + +/*-------------------------------------------------------------------------*/ + +/* + * Class-Specific Notifications (6.3) sent by interrupt transfers + * + * section 3.8.2 table 11 of the CDC spec lists Ethernet notifications + * section 3.6.2.1 table 5 specifies ACM notifications, accepted by RNDIS + * RNDIS also defines its own bit-incompatible notifications + */ + +#define USB_CDC_NOTIFY_NETWORK_CONNECTION 0x00 +#define USB_CDC_NOTIFY_RESPONSE_AVAILABLE 0x01 +#define USB_CDC_NOTIFY_SERIAL_STATE 0x20 +#define USB_CDC_NOTIFY_SPEED_CHANGE 0x2a + +struct usb_cdc_notification { + __u8 bmRequestType; + __u8 bNotificationType; + __le16 wValue; + __le16 wIndex; + __le16 wLength; +} __attribute__((packed)); + +struct usb_cdc_speed_change { + __le32 DLBitRRate; /* contains the downlink bit rate (IN pipe) */ + __le32 ULBitRate; /* contains the uplink bit rate (OUT pipe) */ +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* + * Class Specific structures and constants + * + * CDC NCM NTB parameters structure, CDC NCM subclass 6.2.1 + * + */ + +struct usb_cdc_ncm_ntb_parameters { + __le16 wLength; + __le16 bmNtbFormatsSupported; + __le32 dwNtbInMaxSize; + __le16 wNdpInDivisor; + __le16 wNdpInPayloadRemainder; + __le16 wNdpInAlignment; + __le16 wPadding1; + __le32 dwNtbOutMaxSize; + __le16 wNdpOutDivisor; + __le16 wNdpOutPayloadRemainder; + __le16 wNdpOutAlignment; + __le16 wNtbOutMaxDatagrams; +} __attribute__((packed)); + +/* + * CDC NCM transfer headers, CDC NCM subclass 3.2 + */ + +#define USB_CDC_NCM_NTH16_SIGN 0x484D434E /* NCMH */ +#define USB_CDC_NCM_NTH32_SIGN 0x686D636E /* ncmh */ + +struct usb_cdc_ncm_nth16 { + __le32 dwSignature; + __le16 wHeaderLength; + __le16 wSequence; + __le16 wBlockLength; + __le16 wNdpIndex; +} __attribute__((packed)); + +struct usb_cdc_ncm_nth32 { + __le32 dwSignature; + __le16 wHeaderLength; + __le16 wSequence; + __le32 dwBlockLength; + __le32 dwNdpIndex; +} __attribute__((packed)); + +/* + * CDC NCM datagram pointers, CDC NCM subclass 3.3 + */ + +#define USB_CDC_NCM_NDP16_CRC_SIGN 0x314D434E /* NCM1 */ +#define USB_CDC_NCM_NDP16_NOCRC_SIGN 0x304D434E /* NCM0 */ +#define USB_CDC_NCM_NDP32_CRC_SIGN 0x316D636E /* ncm1 */ +#define USB_CDC_NCM_NDP32_NOCRC_SIGN 0x306D636E /* ncm0 */ + +#define USB_CDC_MBIM_NDP16_IPS_SIGN 0x00535049 /* IPS : IPS0 for now */ +#define USB_CDC_MBIM_NDP32_IPS_SIGN 0x00737069 /* ips : ips0 for now */ +#define USB_CDC_MBIM_NDP16_DSS_SIGN 0x00535344 /* DSS */ +#define USB_CDC_MBIM_NDP32_DSS_SIGN 0x00737364 /* dss */ + +/* 16-bit NCM Datagram Pointer Entry */ +struct usb_cdc_ncm_dpe16 { + __le16 wDatagramIndex; + __le16 wDatagramLength; +} __attribute__((__packed__)); + +/* 16-bit NCM Datagram Pointer Table */ +struct usb_cdc_ncm_ndp16 { + __le32 dwSignature; + __le16 wLength; + __le16 wNextNdpIndex; + struct usb_cdc_ncm_dpe16 dpe16[0]; +} __attribute__((packed)); + +/* 32-bit NCM Datagram Pointer Entry */ +struct usb_cdc_ncm_dpe32 { + __le32 dwDatagramIndex; + __le32 dwDatagramLength; +} __attribute__((__packed__)); + +/* 32-bit NCM Datagram Pointer Table */ +struct usb_cdc_ncm_ndp32 { + __le32 dwSignature; + __le16 wLength; + __le16 wReserved6; + __le32 dwNextNdpIndex; + __le32 dwReserved12; + struct usb_cdc_ncm_dpe32 dpe32[0]; +} __attribute__((packed)); + +/* CDC NCM subclass 3.2.1 and 3.2.2 */ +#define USB_CDC_NCM_NDP16_INDEX_MIN 0x000C +#define USB_CDC_NCM_NDP32_INDEX_MIN 0x0010 + +/* CDC NCM subclass 3.3.3 Datagram Formatting */ +#define USB_CDC_NCM_DATAGRAM_FORMAT_CRC 0x30 +#define USB_CDC_NCM_DATAGRAM_FORMAT_NOCRC 0X31 + +/* CDC NCM subclass 4.2 NCM Communications Interface Protocol Code */ +#define USB_CDC_NCM_PROTO_CODE_NO_ENCAP_COMMANDS 0x00 +#define USB_CDC_NCM_PROTO_CODE_EXTERN_PROTO 0xFE + +/* CDC NCM subclass 5.2.1 NCM Functional Descriptor, bmNetworkCapabilities */ +#define USB_CDC_NCM_NCAP_ETH_FILTER (1 << 0) +#define USB_CDC_NCM_NCAP_NET_ADDRESS (1 << 1) +#define USB_CDC_NCM_NCAP_ENCAP_COMMAND (1 << 2) +#define USB_CDC_NCM_NCAP_MAX_DATAGRAM_SIZE (1 << 3) +#define USB_CDC_NCM_NCAP_CRC_MODE (1 << 4) +#define USB_CDC_NCM_NCAP_NTB_INPUT_SIZE (1 << 5) + +/* CDC NCM subclass Table 6-3: NTB Parameter Structure */ +#define USB_CDC_NCM_NTB16_SUPPORTED (1 << 0) +#define USB_CDC_NCM_NTB32_SUPPORTED (1 << 1) + +/* CDC NCM subclass Table 6-3: NTB Parameter Structure */ +#define USB_CDC_NCM_NDP_ALIGN_MIN_SIZE 0x04 +#define USB_CDC_NCM_NTB_MAX_LENGTH 0x1C + +/* CDC NCM subclass 6.2.5 SetNtbFormat */ +#define USB_CDC_NCM_NTB16_FORMAT 0x00 +#define USB_CDC_NCM_NTB32_FORMAT 0x01 + +/* CDC NCM subclass 6.2.7 SetNtbInputSize */ +#define USB_CDC_NCM_NTB_MIN_IN_SIZE 2048 +#define USB_CDC_NCM_NTB_MIN_OUT_SIZE 2048 + +/* NTB Input Size Structure */ +struct usb_cdc_ncm_ndp_input_size { + __le32 dwNtbInMaxSize; + __le16 wNtbInMaxDatagrams; + __le16 wReserved; +} __attribute__((packed)); + +/* CDC NCM subclass 6.2.11 SetCrcMode */ +#define USB_CDC_NCM_CRC_NOT_APPENDED 0x00 +#define USB_CDC_NCM_CRC_APPENDED 0x01 + +#endif /* __LINUX_USB_CDC_H */ diff --git a/apps/common/usb/device/descriptor.c b/apps/common/usb/device/descriptor.c new file mode 100644 index 0000000..2f804de --- /dev/null +++ b/apps/common/usb/device/descriptor.c @@ -0,0 +1,202 @@ +/** + * @file descriptor.c + * @brief overwrite usb device descriptor + * @version 1.00 + * @date 2019-05-06 + */ + +#include "usb/device/usb_stack.h" +#include "usb/device/descriptor.h" +#include "usb/device/uac_audio.h" + +#include "app_config.h" + +#define LOG_TAG_CONST USB +#define LOG_TAG "[USB]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#if TCFG_USB_SLAVE_ENABLE + +static const u8 sDeviceDescriptor[] = { // in Unicode + 0x02, // iProduct: Index to string descriptor that contains the string in Unicode + 0x03, // iSerialNumber: none + 0x01 // bNumConfigurations: 1 +}; + +static const u8 LANGUAGE_STR[] = { + 0x04, 0x03, 0x09, 0x04 +}; + + +static const u8 product_string[] = { + 42, + 0x03, + 'U', 0x00, + 'S', 0x00, + 'B', 0x00, + ' ', 0x00, + 'C', 0x00, + 'o', 0x00, + 'm', 0x00, + 'p', 0x00, + 'o', 0x00, + 's', 0x00, + 'i', 0x00, + 't', 0x00, + 'e', 0x00, + ' ', 0x00, + 'D', 0x00, + 'e', 0x00, + 'v', 0x00, + 'i', 0x00, + 'c', 0x00, + 'e', 0x00, +}; + +static const u8 MANUFACTURE_STR[] = { + 34, //该描述符的长度为34字节 + 0x03, //字符串描述符的类型编码为0x03 + 0x4a, 0x00, //J + 0x69, 0x00, //i + 0x65, 0x00, //e + 0x6c, 0x00, //l + 0x69, 0x00, //i + 0x20, 0x00, // + 0x54, 0x00, //T + 0x65, 0x00, //e + 0x63, 0x00, //c + 0x68, 0x00, //h + 0x6e, 0x00, //n + 0x6f, 0x00, //o + 0x6c, 0x00, //l + 0x6f, 0x00, //o + 0x67, 0x00, //g + 0x79, 0x00, //y +}; + +static const u8 sConfigDescriptor[] = { //> 4; + if (bcd > 9) { + bcd = bcd - 0xa + 'A'; + } else { + bcd = bcd + '0'; + } + ptr[2 + i * 4] = bcd; + bcd = flash_id[i] & 0xf; + if (bcd > 9) { + bcd = bcd - 0xa + 'A'; + } else { + bcd = bcd + '0'; + } + ptr[2 + i * 4 + 2] = bcd; + } + } else { + memcpy(ptr, serial_string, serial_string[0]); + } +#endif +} + +#if USB_ROOT2 +static const u8 ee_string[] = {0x12, 0x03, 0x4D, 0x00, 0x53, 0x00, 0x46, 0x00, 0x54, + 0x00, 0x31, 0x00, 0x30, 0x00, 0x30, 0x00, 0x90, 0x00 + }; +void get_string_ee(u8 *ptr) +{ + memcpy(ptr, ee_string, ee_string[0]); +} +#endif + +void get_product_str(u8 *ptr) +{ + memcpy(ptr, product_string, product_string[0]); +} + +const u8 *usb_get_config_desc() +{ + return sConfigDescriptor; +} + +const u8 *usb_get_string_desc(u32 id) +{ + const u8 *pstr = uac_get_string(id); + if (pstr != NULL) { + return pstr; + } + return NULL; +} + +#endif diff --git a/apps/common/usb/device/hid.c b/apps/common/usb/device/hid.c new file mode 100644 index 0000000..770906a --- /dev/null +++ b/apps/common/usb/device/hid.c @@ -0,0 +1,302 @@ +#include "os/os_api.h" +#include "usb/device/usb_stack.h" +#include "usb/device/hid.h" +#include "usb_config.h" + +#include "app_config.h" + +#ifdef TCFG_USB_SLAVE_USER_HID +#undef TCFG_USB_SLAVE_HID_ENABLE +#define TCFG_USB_SLAVE_HID_ENABLE 0 +#endif + +#if TCFG_USB_SLAVE_HID_ENABLE + +#define LOG_TAG_CONST USB +#define LOG_TAG "[USB]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" +static const u8 sHIDDescriptor[] = { +//HID + //InterfaceDeszcriptor: + USB_DT_INTERFACE_SIZE, // Length + USB_DT_INTERFACE, // DescriptorType + /* 0x04, // bInterface number */ + 0x00, // bInterface number + 0x00, // AlternateSetting + 0x01, // NumEndpoint + /* 0x02, // NumEndpoint */ + USB_CLASS_HID, // Class = Human Interface Device + 0x00, // Subclass, 0 No subclass, 1 Boot Interface subclass + 0x00, // Procotol, 0 None, 1 Keyboard, 2 Mouse + 0x00, // Interface Name + + //HIDDescriptor: + 0x09, // bLength + USB_HID_DT_HID, // bDescriptorType, HID Descriptor + 0x00, 0x01, // bcdHID, HID Class Specification release NO. + 0x00, // bCuntryCode, Country localization (=none) + 0x01, // bNumDescriptors, Number of descriptors to follow + 0x22, // bDescriptorType, Report Desc. 0x22, Physical Desc. 0x23 + 0,//LOW(ReportLength) + 0, //HIGH(ReportLength) + + //EndpointDescriptor: + USB_DT_ENDPOINT_SIZE, // bLength + USB_DT_ENDPOINT, // bDescriptorType, Type + USB_DIR_IN | HID_EP_IN, // bEndpointAddress + USB_ENDPOINT_XFER_INT, // Interrupt + LOBYTE(MAXP_SIZE_HIDIN), HIBYTE(MAXP_SIZE_HIDIN),// Maximum packet size + 10, // Poll every 10msec seconds + +//@Endpoint Descriptor: + /* USB_DT_ENDPOINT_SIZE, // bLength + USB_DT_ENDPOINT, // bDescriptorType, Type + USB_DIR_OUT | HID_EP_OUT, // bEndpointAddress + USB_ENDPOINT_XFER_INT, // Interrupt + LOBYTE(MAXP_SIZE_HIDOUT), HIBYTE(MAXP_SIZE_HIDOUT),// Maximum packet size + 0x01, // bInterval, for high speed 2^(n-1) * 125us, for full/low speed n * 1ms */ +}; + +static const u8 sHIDReportDesc[] = { + USAGE_PAGE(1, CONSUMER_PAGE), + USAGE(1, CONSUMER_CONTROL), + COLLECTION(1, APPLICATION), + + LOGICAL_MIN(1, 0x00), + LOGICAL_MAX(1, 0x01), + + USAGE(1, VOLUME_INC), + USAGE(1, VOLUME_DEC), + USAGE(1, MUTE), + USAGE(1, PLAY_PAUSE), + USAGE(1, SCAN_NEXT_TRACK), + USAGE(1, SCAN_PREV_TRACK), + USAGE(1, FAST_FORWARD), + USAGE(1, STOP), + + USAGE(1, TRACKING_INC), + USAGE(1, TRACKING_DEC), + USAGE(1, STOP_EJECT), + USAGE(1, VOLUME), + USAGE(2, BALANCE_LEFT), + USAGE(2, BALANCE_RIGHT), + USAGE(1, PLAY), + USAGE(1, PAUSE), + + REPORT_SIZE(1, 0x01), + REPORT_COUNT(1, 0x10), + INPUT(1, 0x42), + END_COLLECTION, + +}; + +static u32 get_hid_report_desc_len(u32 index) +{ + u32 len = 0; + len = sizeof(sHIDReportDesc); + return len; +} +static void *get_hid_report_desc(u32 index) +{ + u8 *ptr = NULL; + ptr = (u8 *)sHIDReportDesc; + return ptr; +} + + +static u32 hid_tx_data(struct usb_device_t *usb_device, const u8 *buffer, u32 len) +{ + const usb_dev usb_id = usb_device2id(usb_device); + return usb_g_intr_write(usb_id, HID_EP_IN, buffer, len); +} +static void hid_rx_data(struct usb_device_t *usb_device, u32 ep) +{ + const usb_dev usb_id = usb_device2id(usb_device); + u8 *ep_buffer = usb_get_ep_buffer(usb_id, HID_EP_OUT); + u32 rx_len = usb_g_intr_read(usb_id, ep, NULL, 64, 0); + hid_tx_data(usb_device, ep_buffer, rx_len); +} + +static void hid_endpoint_init(struct usb_device_t *usb_device, u32 itf) +{ + const usb_dev usb_id = usb_device2id(usb_device); + u8 *ep_buffer = usb_get_ep_buffer(usb_id, HID_EP_IN | USB_DIR_IN); + usb_g_ep_config(usb_id, HID_EP_IN | USB_DIR_IN, USB_ENDPOINT_XFER_INT, 0, ep_buffer, MAXP_SIZE_HIDIN); + + ep_buffer = usb_get_ep_buffer(usb_id, HID_EP_OUT); + usb_g_set_intr_hander(usb_id, HID_EP_OUT, hid_rx_data); + usb_g_ep_config(usb_id, HID_EP_OUT, USB_ENDPOINT_XFER_INT, 1, ep_buffer, MAXP_SIZE_HIDOUT); + usb_enable_ep(usb_id, HID_EP_OUT); +} + +static void hid_reset(struct usb_device_t *usb_device, u32 itf) +{ + const usb_dev usb_id = usb_device2id(usb_device); + log_debug("%s", __func__); +#if USB_ROOT2 + usb_disable_ep(usb_id, HID_EP_OUT); +#else + hid_endpoint_init(usb_device, itf); +#endif +} +static u32 hid_recv_output_report(struct usb_device_t *usb_device, struct usb_ctrlrequest *setup) +{ + const usb_dev usb_id = usb_device2id(usb_device); + u32 ret = 0; + u8 read_ep[8]; + u8 mute; + u16 volume = 0; + usb_read_ep0(usb_id, read_ep, MIN(sizeof(read_ep), setup->wLength)); + ret = USB_EP0_STAGE_SETUP; + put_buf(read_ep, 8); + + + return ret; +} + +static u32 hid_itf_hander(struct usb_device_t *usb_device, struct usb_ctrlrequest *req) +{ + const usb_dev usb_id = usb_device2id(usb_device); + u32 tx_len; + u8 *tx_payload = usb_get_setup_buffer(usb_device); + u32 bRequestType = req->bRequestType & USB_TYPE_MASK; + switch (bRequestType) { + case USB_TYPE_STANDARD: + switch (req->bRequest) { + case USB_REQ_GET_DESCRIPTOR: + switch (HIBYTE(req->wValue)) { + case USB_HID_DT_HID: + tx_payload = (u8 *)sHIDDescriptor + USB_DT_INTERFACE_SIZE; + tx_len = 9; + tx_payload = usb_set_data_payload(usb_device, req, tx_payload, tx_len); + tx_payload[7] = LOBYTE(get_hid_report_desc_len(req->wIndex)); + tx_payload[8] = HIBYTE(get_hid_report_desc_len(req->wIndex)); + break; + case USB_HID_DT_REPORT: + hid_endpoint_init(usb_device, req->wIndex); + tx_len = get_hid_report_desc_len(req->wIndex); + tx_payload = get_hid_report_desc(req->wIndex); + usb_set_data_payload(usb_device, req, tx_payload, tx_len); + break; + }// USB_REQ_GET_DESCRIPTOR + break; + case USB_REQ_SET_DESCRIPTOR: + usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP); + break; + case USB_REQ_SET_INTERFACE: + if (usb_device->bDeviceStates == USB_DEFAULT) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_ADDRESS) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_CONFIGURED) { + //只有一个interface 没有Alternate + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } + break; + case USB_REQ_GET_INTERFACE: + if (req->wLength) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_DEFAULT) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_ADDRESS) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_CONFIGURED) { + tx_len = 1; + tx_payload[0] = 0x00; + usb_set_data_payload(usb_device, req, tx_payload, tx_len); + } + break; + case USB_REQ_GET_STATUS: + if (usb_device->bDeviceStates == USB_DEFAULT) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_ADDRESS) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } + break; + }//bRequest @ USB_TYPE_STANDARD + break; + + case USB_TYPE_CLASS: { + switch (req->bRequest) { + case USB_REQ_SET_IDLE: + usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP); + break; + case USB_REQ_GET_IDLE: + tx_len = 1; + tx_payload[0] = 0; + usb_set_data_payload(usb_device, req, tx_payload, tx_len); + break; + case USB_REQ_SET_REPORT: + usb_set_setup_recv(usb_device, hid_recv_output_report); + break; + }//bRequest @ USB_TYPE_CLASS + } + break; + } + return 0; +} + +u32 hid_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num) +{ + log_debug("hid interface num:%d\n", *cur_itf_num); + u8 *_ptr = ptr; + memcpy(ptr, sHIDDescriptor, sizeof(sHIDDescriptor)); + ptr[2] = *cur_itf_num; + if (usb_set_interface_hander(usb_id, *cur_itf_num, hid_itf_hander) != *cur_itf_num) { + ASSERT(0, "hid set interface_hander fail"); + } + if (usb_set_reset_hander(usb_id, *cur_itf_num, hid_reset) != *cur_itf_num) { + ASSERT(0, "hid set interface_reset_hander fail"); + } + + ptr[USB_DT_INTERFACE_SIZE + 7] = LOBYTE(get_hid_report_desc_len(0)); + ptr[USB_DT_INTERFACE_SIZE + 8] = HIBYTE(get_hid_report_desc_len(0)); + *cur_itf_num = *cur_itf_num + 1; + return sizeof(sHIDDescriptor) ; +} + +void hid_key_handler(struct usb_device_t *usb_device, u32 hid_key) +{ + const usb_dev usb_id = usb_device2id(usb_device); + + u16 key_buf = hid_key; + hid_tx_data(usb_device, (const u8 *)&key_buf, 2); + os_time_dly(2); + key_buf = 0; + hid_tx_data(usb_device, (const u8 *)&key_buf, 2); +} + + +struct hid_button { + u8 report_id; + u8 button1: 1; + u8 button2: 1; + u8 button3: 1; + u8 no_button: 5; + u8 X_axis; + u8 Y_axis; +}; +struct hid_button hid_key; +void hid_test(struct usb_device_t *usb_device) +{ + static u32 tx_count = 0; + + hid_key_handler(usb_device, BIT(tx_count)); + tx_count ++; + if (BIT(tx_count) > USB_AUDIO_PAUSE) { + tx_count = 0; + } +} +#else +void hid_key_handler(struct usb_device_t *usb_device, u32 hid_key) +{ + +} +#endif diff --git a/apps/common/usb/device/msd.c b/apps/common/usb/device/msd.c new file mode 100644 index 0000000..e00c900 --- /dev/null +++ b/apps/common/usb/device/msd.c @@ -0,0 +1,1096 @@ +#include "system/includes.h" +#include "usb/device/usb_stack.h" +#include "usb/device/msd.h" +#include "usb/scsi.h" +#include "usb_config.h" +#include "device/device.h" +#include "app_config.h" + +#if TCFG_DEV_MANAGER_ENABLE +#include "dev_manager.h" +#endif + +#if TCFG_USB_APPLE_DOCK_EN +#include "apple_dock/iAP.h" +#endif + +#if TCFG_USB_SLAVE_MSD_ENABLE + +#define LOG_TAG_CONST USB +#define LOG_TAG "[USB]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + // *INDENT-OFF* +#define USB_MSD_BULK_DEV_USE_ASYNC 1 + +// Mass Storage Class + /*********************************************************/ +static const u8 sMassDescriptor[] = { //= MAX_MSD_DEV) { + cnt = MAX_MSD_DEV; + } + return cnt; +} + +u32 msd_set_wakeup_handle(void (*handle)(struct usb_device_t *usb_device)) +{ + if (msd_handle) { + msd_handle->info.msd_wakeup_handle = handle; + return 1; + } + return 0; +} +static void msd_wakeup(struct usb_device_t *usb_device, u32 ep) +{ + if ((msd_handle) && (msd_handle->info.msd_wakeup_handle)) { + msd_handle->info.msd_wakeup_handle(usb_device); + } +} +static u8 get_cardreader_popup(u32 lun) +{ + return msd_handle->info.bDisk_popup[lun];//弹出 +} +static void set_cardreader_popup(u32 lun, u8 status) +{ + if (msd_handle->info.dev_handle[lun] != NULL) { + msd_handle->info.bDisk_popup[lun] = status;//弹出 + } +} +static void recover_set_cardreader_popup(u32 lun) +{ + if (msd_handle->info.dev_handle[lun] != NULL) { + msd_handle->info.bDisk_popup[lun] = 0;//未弹出 + } +} +static void msd_endpoint_init(struct usb_device_t *usb_device, u32 itf) +{ + const usb_dev usb_id = usb_device2id(usb_device); + u8 *ep_buffer = usb_get_ep_buffer(usb_id, MSD_BULK_EP_IN | USB_DIR_IN); + ASSERT(ep_buffer, "usb alloc ep buffer failed"); + + usb_g_ep_config(usb_id, MSD_BULK_EP_IN | USB_DIR_IN, USB_ENDPOINT_XFER_BULK, 0, ep_buffer, MAXP_SIZE_BULKIN); + ep_buffer = usb_get_ep_buffer(usb_id, MSD_BULK_EP_OUT); + ASSERT(ep_buffer, "usb alloc ep buffer failed"); + + usb_g_ep_config(usb_id, MSD_BULK_EP_OUT, USB_ENDPOINT_XFER_BULK, 1, ep_buffer, MAXP_SIZE_BULKOUT); + usb_g_set_intr_hander(usb_id, MSD_BULK_EP_OUT, msd_wakeup); + + usb_enable_ep(usb_id, MSD_BULK_EP_OUT); +} +static void msd_reset_wakeup(struct usb_device_t *usb_device, u32 itf_num) +{ + const usb_dev usb_id = usb_device2id(usb_device); + if (msd_handle && msd_handle->info.msd_reset_wakeup_handle) { + msd_handle->info.msd_reset_wakeup_handle(usb_device, itf_num); + } +} +void msd_set_reset_wakeup_handle(void (*handle)(struct usb_device_t *usb_device, u32 itf_num)) +{ + if (msd_handle) { + msd_handle->info.msd_reset_wakeup_handle = handle; + } +} +void msd_reset(struct usb_device_t *usb_device, u32 itf_num) +{ + const usb_dev usb_id = usb_device2id(usb_device); + log_debug("%s", __func__); + +#if USB_ROOT2 + usb_disable_ep(usb_id, MSD_BULK_EP_OUT); +#else + msd_endpoint_init(usb_device, itf_num); +#endif +} +static void *check_disk_status(u8 cur_lun) +{ + u32 ret; + u32 online_status; + void *dev_fd = msd_handle->info.dev_handle[cur_lun] ; + const char *dev_name = msd_handle->info.dev_name[cur_lun]; + +#if TCFG_DEV_MANAGER_ENABLE + if (dev_manager_list_check_by_logo((char *)dev_name)) { + if (dev_fd == NULL) { + msd_handle->info.dev_handle[cur_lun] = dev_open(dev_name, NULL); + } else { + //FIXME:need add device state check?? + u32 dev_online = 0; + ret = dev_ioctl(dev_fd, IOCTL_GET_STATUS, (u32)&dev_online); + if (ret || !dev_online) { + goto __dev_offline; + } + } + + if (get_cardreader_popup(cur_lun)) { + return NULL; + } + } else { + if (dev_fd) { + goto __dev_offline; + } + } +#else + if (dev_fd == NULL) { + msd_handle->info.dev_handle[cur_lun] = dev_open(dev_name, NULL); + } else { + u32 dev_online = 0; + ret = dev_ioctl(dev_fd, IOCTL_GET_STATUS, (u32)&dev_online); + if (ret || !dev_online) { + goto __dev_offline; + } + } +#endif + + return msd_handle->info.dev_handle[cur_lun]; + +__dev_offline: + dev_close(dev_fd); + recover_set_cardreader_popup(cur_lun); + msd_handle->info.dev_handle[cur_lun] = NULL; + return NULL; +} +static u32 msd_itf_hander(struct usb_device_t *usb_device, struct usb_ctrlrequest *setup) +{ + u32 tx_len; + u8 *tx_payload = usb_get_setup_buffer(usb_device); + u32 bRequestType = setup->bRequestType & USB_TYPE_MASK; + switch (bRequestType) { + case USB_TYPE_STANDARD: + switch (setup->bRequest) { + case USB_REQ_GET_STATUS: + usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP); + break; + case USB_REQ_GET_INTERFACE: + tx_len = 1; + u8 i = 0; + usb_set_data_payload(usb_device, setup, &i, tx_len); + break; + case USB_REQ_SET_INTERFACE: + usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP); + break; + default: + break; + } + break; + case USB_TYPE_CLASS: + switch (setup->bRequest) { + case USB_MSD_MAX_LUN: + msd_endpoint_init(usb_device, -1); + tx_len = 1; + tx_payload[0] = __get_max_msd_dev() - 1; + usb_set_data_payload(usb_device, setup, tx_payload, tx_len); + break; + case USB_MSD_RESET : + usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP); + break; + default: + break; + } + break; + default: + break; + } + return 0; +} +u32 msd_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num) +{ + log_debug("%s() %d", __func__, *cur_itf_num); + memcpy(ptr, sMassDescriptor, sizeof(sMassDescriptor)); + ptr[2] = *cur_itf_num; +#if TCFG_USB_APPLE_DOCK_EN + if (apple_mfi_chip_online_lib()) { + ptr[5] = 0xff; //bInterfaceClass:Vendor-Specific + ptr[6] = 0xf0; //bInterfaceSubClass:MFi Accessory + ptr[7] = 0x00; //bInterfaceProtocol */ + ptr[8] = MSD_STR_INDEX; //bInterfaceString*/ + } +#endif + if (usb_set_interface_hander(usb_id, *cur_itf_num, msd_itf_hander) != *cur_itf_num) { + + } + if (usb_set_reset_hander(usb_id, *cur_itf_num, msd_reset_wakeup) != *cur_itf_num) { + + } + *cur_itf_num = *cur_itf_num + 1; + return sizeof(sMassDescriptor); +} +u32 msd_usb2mcu(const struct usb_device_t *usb_device, u8 *buffer, u32 len) +{ + usb_dev usb_id = usb_device2id(usb_device); + return usb_g_bulk_read(usb_id, MSD_BULK_EP_OUT, buffer, len, 1); +} +u32 msd_mcu2usb(const struct usb_device_t *usb_device, const u8 *buffer, u32 len) +{ + usb_dev usb_id = usb_device2id(usb_device); + return usb_g_bulk_write(usb_id, MSD_BULK_EP_IN, buffer, len); +} +static u32 msd_usb2mcu_64byte_fast(const struct usb_device_t *usb_device, u8 *buffer, u32 len) +{ + usb_dev usb_id = usb_device2id(usb_device); + return usb_g_bulk_read64byte_fast(usb_id, MSD_BULK_EP_OUT, buffer, len); +} +static u32 get_cbw(const struct usb_device_t *usb_device) +{ + msd_handle->cbw.dCBWSignature = 0; + memset((u8 *)(&(msd_handle->cbw)), 0, sizeof(struct usb_scsi_cbw)); + u32 rx_len = msd_usb2mcu(usb_device, (u8 *)(&(msd_handle->cbw)), sizeof(struct usb_scsi_cbw)); + if (rx_len == 0) { + return 1; + } + if (msd_handle->cbw.dCBWSignature ^ CBW_SIGNATURE) { + if ((msd_handle->cbw.dCBWSignature ^ CBW_SIGNATURE) != CBW_SIGNATURE) { + } + return 1; + } + msd_handle->csw.dCSWTag = msd_handle->cbw.dCBWTag; + msd_handle->csw.uCSWDataResidue = msd_handle->cbw.dCBWDataTransferLength; + + return 0; +} +static void inquiry(const struct usb_device_t *usb_device) +{ + u32 err; + u32 len = min(msd_handle->csw.uCSWDataResidue, sizeof(SCSIInquiryData)); + u32 scsiinquirydata[sizeof(SCSIInquiryData) / 4]; //usb dma 不能访问code区域 + memcpy(scsiinquirydata, SCSIInquiryData, sizeof(SCSIInquiryData)); + err = msd_mcu2usb(usb_device, scsiinquirydata, len); + if (err == 0) { + log_error("write usb err %d", __LINE__); + } + msd_handle->csw.uCSWDataResidue -= len; + msd_handle->csw.bCSWStatus = 0; +} +static void send_csw(const struct usb_device_t *usb_device) +{ + u32 err; + msd_handle->csw.dCSWSignature = CSW_SIGNATURE; + err = msd_mcu2usb(usb_device, (u8 *) & (msd_handle->csw), sizeof(struct usb_scsi_csw)); + if (err == 0) { + log_error("write usb err %d", __LINE__); + } +} +static void stall_inep(const struct usb_device_t *usb_device) +{ + const usb_dev usb_id = usb_device2id(usb_device); + usb_write_txcsr(usb_id, MSD_BULK_EP_IN, TXCSRP_SendStall); + u32 ot = 2000; + + while (1) { + if (ot-- == 0) { + break; + } + if (usb_otg_online(usb_id) == DISCONN_MODE) { + break; + } + if ((usb_read_txcsr(usb_id, MSD_BULK_EP_IN) & TXCSRP_SendStall) == 0) { + break; + } + } +} + +static void stall_outep(const struct usb_device_t *usb_device) +{ + const usb_dev usb_id = usb_device2id(usb_device); + usb_write_rxcsr(usb_id, MSD_BULK_EP_OUT, RXCSRP_SendStall); + u32 ot = 2000; + while (1) { + if (ot-- == 0) { + break; + } + if (usb_otg_online(usb_id) == DISCONN_MODE) { + break; + } + if ((usb_read_rxcsr(usb_id, MSD_BULK_EP_OUT) & RXCSRP_SendStall) == 0) { + break; + } + } +} + +static void unknow(const struct usb_device_t *usb_device, u8 rw) +{ + if (rw) { + stall_outep(usb_device); + } else { + stall_inep(usb_device); + } + + msd_handle->csw.uCSWDataResidue = 0; + msd_handle->csw.bCSWStatus = 0x01; + msd_handle->info.bError = 0x1; + /* msd_handle->info.bError = 0x2; */ +} +static void stall_error(const struct usb_device_t *usb_device, u8 rw, u8 error) +{ + msd_handle->csw.bCSWStatus = 0x01; + unknow(usb_device, rw); + msd_handle->info.bError = error; +} +static void test_unit_ready(const struct usb_device_t *usb_device) +{ + int err; + u8 cur_lun = msd_handle->cbw.bCBWLUN; + + if (NULL == check_disk_status(cur_lun)) { + msd_handle->csw.bCSWStatus = 0x1; + msd_handle->info.bError = 0x0f; + } else { + msd_handle->csw.uCSWDataResidue = 0; + msd_handle->csw.bCSWStatus = 0x0; + } +} +static void allow_medium_removal(const struct usb_device_t *usb_device) +{ + msd_handle->csw.bCSWStatus = 0x0; + if (msd_handle->cbw.lba[2]) { + msd_handle->info.bError = 0x02; + msd_handle->csw.bCSWStatus = 0x01; + } + msd_handle->csw.uCSWDataResidue = 0; +} +static void request_sense(const struct usb_device_t *usb_device) +{ + u32 err; + u32 len; + u8 sense_data[0x12]; + len = min(msd_handle->csw.uCSWDataResidue, 0x12); + if (msd_handle->csw.uCSWDataResidue == 0) { + stall_inep(usb_device); + msd_handle->info.bError = NOT_READY; + msd_handle->csw.uCSWDataResidue = 0; + msd_handle->csw.bCSWStatus = 0x01; + return; + } else { + memset(sense_data, 0x0, sizeof(sense_data)); + sense_data[2] = msd_handle->info.bSenseKey; + sense_data[12] = msd_handle->info.bAdditionalSenseCode; + sense_data[13] = msd_handle->info.bAddiSenseCodeQualifier; + sense_data[0] = 0x70; + sense_data[7] = 0x0a; + err = msd_mcu2usb(usb_device, sense_data, len); + if (err == 0) { + log_error("write usb err %d", __LINE__); + } + } + msd_handle->csw.uCSWDataResidue -= len; + msd_handle->csw.bCSWStatus = 0; +} +static u8 const scsi_mode_sense[4] = { + 0x03, 0x00, 0x00, 0x00 +}; +static void mode_sense(const struct usb_device_t *usb_device) +{ + u32 err; + u32 sense; + err = msd_mcu2usb(usb_device, (u8 *)scsi_mode_sense, sizeof(scsi_mode_sense)); + if (err == 0) { + log_error("write usb err %d", __LINE__); + } + msd_handle->csw.uCSWDataResidue = 0; + msd_handle->csw.bCSWStatus = 0; +} +static void verify(const struct usb_device_t *usb_device) +{ + msd_handle->csw.uCSWDataResidue = 0; + msd_handle->csw.bCSWStatus = 0; +} + +#if USB_MSD_BULK_DEV_USE_ASYNC +static void msd_write_10_async(const struct usb_device_t *usb_device, u8 cur_lun, u32 lba, u16 lba_num) +{ + u32 err = 0; + u16 num = 0; + u8 buf_idx = 0; + u32 have_send_stall = FALSE; + void *dev_fd = NULL; + while (lba_num) { + wdt_clear(); + num = lba_num > MSD_BLOCK_SIZE ? MSD_BLOCK_SIZE : lba_num; + if (msd_handle->csw.uCSWDataResidue == 0) { + msd_handle->csw.bCSWStatus = 1; + break; + } + if (msd_handle->csw.uCSWDataResidue >= num * 0x200) { + msd_handle->csw.uCSWDataResidue -= num * 0x200; + } + err = msd_usb2mcu_64byte_fast(usb_device, msd_handle->msd_buf + buf_idx * MSD_BUFFER_SIZE, num * 0x200); + if (err != num * 0x200) { + log_error("read usb_err %d, dev = %s", + __LINE__, msd_handle->info.dev_name[cur_lun]); + stall_error(usb_device, 1, MEDIUM_ERROR); + have_send_stall = TRUE; + break; + } + dev_fd = check_disk_status(cur_lun); + if (dev_fd) { + dev_ioctl(dev_fd, IOCTL_SET_ASYNC_MODE, 0); + err = dev_bulk_write(dev_fd, msd_handle->msd_buf + buf_idx * MSD_BUFFER_SIZE, lba, num); + if (err != num) { + log_error("write_10 write fail, %d, dev = %s", + err, msd_handle->info.dev_name[cur_lun]); + stall_error(usb_device, 1, MEDIUM_ERROR); + have_send_stall = TRUE; + break; + } + } else { + log_error("write_10 disk offline, dev = %s", + msd_handle->info.dev_name[cur_lun]); + stall_error(usb_device, 1, MEDIUM_ERROR); + have_send_stall = TRUE; + break; + } + buf_idx = !buf_idx; + lba_num -= num; + lba += num; + } + dev_fd = check_disk_status(cur_lun); + if (dev_fd) { + //async mode last block flush + dev_ioctl(dev_fd, IOCTL_FLUSH, 0); + } else { + if (have_send_stall == FALSE) { + log_error("write_10 disk offline while sync, dev = %s", + msd_handle->info.dev_name[cur_lun]); + stall_error(usb_device, 1, MEDIUM_ERROR); + } + } +} + +static void msd_read_10_async(const struct usb_device_t *usb_device, u8 cur_lun, u32 lba, u16 lba_num) +{ + u32 err = 0; + u16 num = 0; + u8 buf_idx = 0; + u32 last_lba = 0, last_num = 0; + void *dev_fd = NULL; + + if (lba_num == 0) { + log_error("lba_num == 0\n"); + stall_error(usb_device, 0, 0x02); + return; + } + num = lba_num > MSD_BLOCK_SIZE ? MSD_BLOCK_SIZE : lba_num; + dev_fd = check_disk_status(cur_lun); + if (dev_fd) { + dev_ioctl(dev_fd, IOCTL_SET_ASYNC_MODE, 0); + err = dev_bulk_read(dev_fd, msd_handle->msd_buf + buf_idx * MSD_BUFFER_SIZE, lba, num); + if (err != num) { + log_error("read disk error0 = %d, dev = %s\n", err, msd_handle->info.dev_name[cur_lun]); + stall_error(usb_device, 0, MEDIUM_ERROR); + return; + } + } else { + log_error("read_10 disk offline, dev = %s\n", msd_handle->info.dev_name[cur_lun]); + stall_error(usb_device, 0, MEDIUM_ERROR); + return; + } + + while (lba_num) { + wdt_clear(); + last_num = num; + last_lba = lba; + buf_idx = !buf_idx; + lba += num; + lba_num -= num; + num = lba_num > MSD_BLOCK_SIZE ? MSD_BLOCK_SIZE : lba_num; + if (msd_handle->csw.uCSWDataResidue == 0) { + msd_handle->csw.bCSWStatus = 1; + break; + } + if (msd_handle->csw.uCSWDataResidue >= last_num * 0x200) { + msd_handle->csw.uCSWDataResidue -= last_num * 0x200; + } + dev_fd = check_disk_status(cur_lun); + if (dev_fd) { + if (num) { + dev_ioctl(dev_fd, IOCTL_SET_ASYNC_MODE, 0); + err = dev_bulk_read(dev_fd, msd_handle->msd_buf + buf_idx * MSD_BUFFER_SIZE, lba, num); + if (err != num) { + log_error("read disk error1 = %d, dev = %s", + err, msd_handle->info.dev_name[cur_lun]); + stall_error(usb_device, 0, MEDIUM_ERROR); + break; + } + } else { + //async mode last block flush + dev_ioctl(dev_fd, IOCTL_FLUSH, 0); + } + } else { + log_error("read_10 disk offline, dev = %s", + msd_handle->info.dev_name[cur_lun]); + stall_error(usb_device, 0, MEDIUM_ERROR); + break; + } + err = msd_mcu2usb(usb_device, msd_handle->msd_buf + !buf_idx * MSD_BUFFER_SIZE, last_num * 0x200); + if (err != last_num * 0x200) { + log_error("read_10 data transfer err %d, dev = %s", + __LINE__, msd_handle->info.dev_name[cur_lun]); + stall_error(usb_device, 0, 0x05); + if (num) { + dev_ioctl(dev_fd, IOCTL_FLUSH, 0); + } + break; + } + } +} +#endif +static u32 read_32(u8 *p) +{ + return ((u32)(p[0]) << 24) | ((u32)(p[1]) << 16) | ((u32)(p[2]) << 8) | (p[3]); +} + + +static void write_10(const struct usb_device_t *usb_device) +{ + u32 err = 0 ; + u32 lba; + u16 lba_num; + u16 num = 0; + lba = read_32(msd_handle->cbw.lba); + lba_num = ((u16)(msd_handle->cbw.LengthH) << 8) | (msd_handle->cbw.LengthL); + u8 cur_lun = msd_handle->cbw.bCBWLUN; + void *dev_fd = msd_handle->info.dev_handle[cur_lun]; + + /* app_status_handler(APP_STATUS_PC_COPY); */ + + +#if USB_MSD_BULK_DEV_USE_ASYNC + /* u32 old_speed; */ + /* dev_fd = check_disk_status(cur_lun); */ + /* if (dev_fd) { */ + /* dev_ioctl(dev_fd, IOCTL_GET_SPEED, (u32)&old_speed); */ + /* dev_ioctl(dev_fd, IOCTL_SET_SPEED, 48000000); */ + /* } */ + msd_write_10_async(usb_device, cur_lun, lba, lba_num); + /* if (dev_fd) { */ + /* dev_ioctl(dev_fd, IOCTL_SET_SPEED, old_speed); */ + /* } */ +#else + + while (lba_num) { + wdt_clear(); + num = lba_num > MSD_BLOCK_SIZE ? MSD_BLOCK_SIZE : lba_num; + if (msd_handle->csw.uCSWDataResidue == 0) { + msd_handle->csw.bCSWStatus = 0x1; + break; + } + if (msd_handle->csw.uCSWDataResidue >= (num * 0x200)) { + msd_handle->csw.uCSWDataResidue -= (num * 0x200); + } + err = msd_usb2mcu_64byte_fast(usb_device, msd_handle->msd_buf, num * 0x200); + if (err == 0) { + stall_error(usb_device, 1, MEDIUM_ERROR); + log_error("read usb, dev = %s", err, msd_handle->info.dev_name[cur_lun]); + break; + } + dev_fd = check_disk_status(cur_lun); + if (dev_fd) { + dev_ioctl(dev_fd, IOCTL_CMD_RESUME, 0); + err = dev_bulk_write(dev_fd, msd_handle->msd_buf, lba, num); + dev_ioctl(dev_fd, IOCTL_CMD_SUSPEND, 0); + if (err != num) { + stall_error(usb_device, 1, MEDIUM_ERROR); + log_error("write disk error =%d, dev = %s", err, msd_handle->info.dev_name[cur_lun]); + break; + } else { + break; + } + lba += num; + lba_num -= num; + } else { + log_error("write disk offline, dev = %s", msd_handle->info.dev_name[cur_lun]); + stall_error(usb_device, 1, MEDIUM_ERROR); + break; + } + } +#endif +} +static void read_10(const struct usb_device_t *usb_device) +{ + u32 err = 0; + u32 lba; + u16 lba_num; + u16 num = 0; + lba = read_32(msd_handle->cbw.lba); + lba_num = ((u16)(msd_handle->cbw.LengthH) << 8) | (msd_handle->cbw.LengthL); + u8 cur_lun = msd_handle->cbw.bCBWLUN; + void *dev_fd = msd_handle->info.dev_handle[cur_lun]; + +#if USB_MSD_BULK_DEV_USE_ASYNC + msd_read_10_async(usb_device, cur_lun, lba, lba_num); +#else + + while (lba_num) { + wdt_clear(); + num = lba_num > MSD_BLOCK_SIZE ? MSD_BLOCK_SIZE : lba_num; + if (msd_handle->csw.uCSWDataResidue == 0) { + msd_handle->csw.bCSWStatus = 0x1; + break; + } + if (msd_handle->csw.uCSWDataResidue >= (num * 0x200)) { + msd_handle->csw.uCSWDataResidue -= (num * 0x200); + } + dev_fd = check_disk_status(cur_lun); + if (dev_fd) { + dev_ioctl(dev_fd, IOCTL_CMD_RESUME, 0); + err = dev_bulk_read(dev_fd, msd_handle->msd_buf, lba, num); + dev_ioctl(dev_fd, IOCTL_CMD_SUSPEND, 0); + if (err != num) { + log_error("read disk error =%d, dev = %s", err, msd_handle->info.dev_name[cur_lun]); + stall_error(usb_device, 0, MEDIUM_ERROR); + break; + } + } else { + log_error("read disk offline, dev = %s", err, msd_handle->info.dev_name[cur_lun]); + stall_error(usb_device, 0, MEDIUM_ERROR); + break; + } + err = msd_mcu2usb(usb_device, msd_handle->msd_buf, num * 0x200); + if (err == 0) { + log_error("write usb err %d, dev = %s", __LINE__, msd_handle->info.dev_name[cur_lun]); + stall_error(usb_device, 0, MEDIUM_ERROR); + break; + } + lba += num; + lba_num -= num; + } +#endif +} +static void read_capacity(const struct usb_device_t *usb_device) +{ + u32 err; + u32 capacity_temp; + u8 capacity[8] = {0}; + u8 cur_lun = msd_handle->cbw.bCBWLUN; + void *dev_fd = check_disk_status(cur_lun); + if (!dev_fd) { + stall_error(usb_device, 0, 0x0f); + return; + } + dev_ioctl(dev_fd, IOCTL_GET_CAPACITY, (u32)&capacity_temp); + capacity_temp = cpu_to_be32(capacity_temp - 1); + memcpy(capacity, &capacity_temp, 4); + dev_ioctl(dev_fd, IOCTL_GET_BLOCK_SIZE, (u32)&capacity_temp); + /* r_printf(">>>[test]:capacity_temp2 = %d\n", capacity_temp); */ + capacity_temp = cpu_to_be32(capacity_temp); + memcpy(&capacity[4], &capacity_temp, 4); + err = msd_mcu2usb(usb_device, capacity, 8); + if (err == 0) { + log_error("write usb err %d", __LINE__); + } + msd_handle->csw.uCSWDataResidue = 0; + msd_handle->csw.bCSWStatus = 0; + +} + +static void read_format_capacity(const struct usb_device_t *usb_device) +{ + u32 err; + u8 capacity[12] = {0}; + u32 capacity_temp; + u8 cur_lun = msd_handle->cbw.bCBWLUN; + void *dev_fd = check_disk_status(cur_lun); + if (!dev_fd) { + stall_error(usb_device, 0, 0x0f); + return; + } + + dev_ioctl(dev_fd, IOCTL_GET_CAPACITY, (u32)&capacity_temp); + + capacity_temp = cpu_to_be32(capacity_temp); + memcpy(&capacity[4], &capacity_temp, 4); + dev_ioctl(dev_fd, IOCTL_GET_BLOCK_SIZE, (u32)&capacity_temp); + capacity_temp = cpu_to_be32(capacity_temp); + memcpy(&capacity[8], &capacity_temp, 4); + capacity[3] = 0x08; + capacity[8] = 0x02; + err = msd_mcu2usb(usb_device, capacity, 12); + if (err == 0) { + log_error("write usb err %d", __LINE__); + } + msd_handle->csw.uCSWDataResidue -= 12; + msd_handle->csw.bCSWStatus = 0; +} + +static void stop_start() +{ + int i; + u8 loej, start; + /* set_cardreader_popup(0, !(msd_handle->cbw.lba[2])); */ + loej = msd_handle->cbw.lba[2] & BIT(1); + start = msd_handle->cbw.lba[2] & BIT(0); + for (i = 0; i < __get_max_msd_dev(); i++) { + if (loej && !start) { + set_cardreader_popup(i, 1); + } else if (loej && start) { + set_cardreader_popup(i, 0); + } + } + + msd_handle->csw.uCSWDataResidue = 0; + msd_handle->csw.bCSWStatus = 0x0; +} + + +u32 private_scsi_cmd(const struct usb_device_t *usb_device, struct usb_scsi_cbw *cbw); + +void USB_MassStorage(const struct usb_device_t *usb_device) +{ + const usb_dev usb_id = usb_device2id(usb_device); + usb_clr_intr_rxe(usb_id, MSD_BULK_EP_OUT); + if (get_cbw(usb_device)) { + usb_set_intr_rxe(usb_id, MSD_BULK_EP_OUT); + return; + } + /* log_debug("opcode %x", msd_handle->cbw.operationCode); */ + if (private_scsi_cmd(usb_device, &(msd_handle->cbw))) { + msd_handle->info.bError = 0; + msd_handle->csw.uCSWDataResidue = 0; + msd_handle->csw.bCSWStatus = 0x0; + } else { + wdt_clear(); + switch (msd_handle->cbw.operationCode) { + case INQUIRY://0x12 + inquiry(usb_device); + break; + case TEST_UNIT_READY://0x00 + test_unit_ready(usb_device); + break; + case VERIFY://0x2f + verify(usb_device); + break; + case ALLOW_MEDIUM_REMOVAL://0x1e + allow_medium_removal(usb_device); + break; + case REQUEST_SENSE://0x03 + request_sense(usb_device); + break; + case MODE_SENSE://0x1a + mode_sense(usb_device); + break; + case READ_10://0x28 + read_10(usb_device); + break; + case WRITE_10://0x2a + write_10(usb_device); + break; + case READ_CAPACITY://0x25 + read_capacity(usb_device); + break; + case READ_FORMAT_CAPACITIES://0x23 + read_format_capacity(usb_device); + break; + case START_STOP://0x1b + stop_start(); + break; + + default: + log_error("opcode %x", msd_handle->cbw.operationCode); + stall_error(usb_device, 0, !(msd_handle->cbw.bmCBWFlags & 0x80)); + break; + } + } + switch (msd_handle->info.bError) { + case 0x00: + msd_handle->info.bSenseKey = NO_SENSE; + msd_handle->info.bAdditionalSenseCode = ASC_NO_ADDITIONAL_SENSE_INFORMATION; + msd_handle->info.bAddiSenseCodeQualifier = ASCQ_NO_ADDITIONAL_SENSE_INFORMATION; + break; + + case 0x02: + msd_handle->info.bSenseKey = ILLEGAL_REQUEST; + msd_handle->info.bAdditionalSenseCode = ASC_INVALID_FIELD_IN_COMMAND_PACKET; + msd_handle->info.bAddiSenseCodeQualifier = ASCQ_INVALID_FIELD_IN_COMMAND_PACKET; + break; + case MEDIUM_ERROR: + msd_handle->info.bSenseKey = MEDIUM_ERROR; + msd_handle->info.bAdditionalSenseCode = ASC_WRITE_FAULT; + msd_handle->info.bAddiSenseCodeQualifier = ASCQ_WRITE_FAULT; + break; + + + case 0x0f: + case 0x05: + msd_handle->info.bSenseKey = NOT_READY; + msd_handle->info.bAdditionalSenseCode = ASC_MEDIUM_PRESENT; + msd_handle->info.bAddiSenseCodeQualifier = ASCQ_MEDIUM_PRESENT; + break; + case 0x06: + msd_handle->info.bSenseKey = ABORTED_COMMAND; + msd_handle->info.bAdditionalSenseCode = ASC_INVALID_COMMAND_OPERATION_CODE; + msd_handle->info.bAddiSenseCodeQualifier = ASCQ_INVALID_COMMAND_OPERATION_CODE; + break; + } + usb_set_intr_rxe(usb_id, MSD_BULK_EP_OUT); + send_csw(usb_device); +} + +u32 msd_register_disk(const char *name, void *arg) +{ + int i; + u32 len, ret = -1; + if (msd_handle) { + for (i = 0; i < __get_max_msd_dev(); i++) { + if (msd_handle->info.dev_name[i][0] == 0) { + ASSERT(strlen(name) <= MSD_DEV_NAME_LEN, "MSD_DEV_NAME_LEN too small"); + strcpy(msd_handle->info.dev_name[i], name); + msd_handle->info.dev_handle[i] = NULL; + break; + } + } + if (i == __get_max_msd_dev()) { + ret = -3; + } + } + return ret; +} +u32 msd_unregister_disk(const char *name) +{ + u32 err; + int i; + if (msd_handle) { + for (i = 0; i < __get_max_msd_dev(); i++) { + if (!strcmp(msd_handle->info.dev_name[i], name)) { + msd_handle->info.dev_name[i][0] = 0; + return 0; + } + } + } + return -1; +} + +u32 msd_unregister_all() +{ + u32 err; + int i; + if (msd_handle) { + for (i = 0; i < __get_max_msd_dev(); i++) { + if (msd_handle->info.dev_handle[i]) { + err = dev_close(msd_handle->info.dev_handle[i]); + msd_handle->info.dev_handle[i] = NULL; + /* memset(msd_handle->info.dev_name[i], 0, MSD_DEV_NAME_LEN); */ + } + } + } + return 0; +} +u32 msd_register() +{ + if (msd_handle == NULL) { +#if USB_MALLOC_ENABLE + msd_handle = (struct usb_msd_handle *)zalloc(sizeof(struct usb_msd_handle)); + if (msd_handle == NULL) { + log_error("msd_register err"); + return -1; + } +#if USB_MSD_BULK_DEV_USE_ASYNC + msd_handle->msd_buf = (u8 *)malloc(MSD_BUFFER_SIZE * 2); +#else + msd_handle->msd_buf = (u8 *)malloc(MSD_BUFFER_SIZE); +#endif + if (msd_handle->msd_buf == NULL) { + log_error("msd_register err"); + return -1; + } +#else + memset(&_msd_handle, 0, sizeof(struct usb_msd_handle)); + _msd_handle.msd_buf = msd_buf; + msd_handle = &_msd_handle; +#endif + log_info("msd_handle = %x", msd_handle); + } + return 0; +} +u32 msd_release() +{ + if (msd_handle) { + for (int i = 0; i < __get_max_msd_dev(); i++) { + void *dev_fd = msd_handle->info.dev_handle[i] ; + if (dev_fd) { + dev_close(dev_fd); + msd_handle->info.dev_handle[i] = NULL; + } + } + +#if USB_MALLOC_ENABLE + if (msd_handle->msd_buf) { + free(msd_handle->msd_buf); + msd_handle->msd_buf = NULL; + } + free(msd_handle); +#endif + msd_handle = NULL; + } + return 0; +} + +#if TCFG_USB_APPLE_DOCK_EN +int usb_g_ep_read_check(const usb_dev id, u32 ep, u32 rx_len) +{ + if (apple_mfi_chip_online_lib()) { + if (ep != MSD_BULK_EP_OUT) { + return 0; + } + u32 dma_size = usb_get_dma_size(id, ep); + /* printf("dma:%d, rl:%d, ep:%d \n", dma_size, rx_len, ep); */ + if (rx_len < dma_size) { + return -1; + } + } + return 0; +} +void apple_usb_msd_wakeup(struct usb_device_t *usb_device) +{ + msd_wakeup(usb_device, MSD_BULK_EP_IN); +} +u8 MCU_SRAMToUSB_app(void *hdl, u8 *pBuf, u16 uCount) +{ + return msd_mcu2usb(hdl, pBuf, uCount); +} +u8 MCU_USBToSRAM_app(void *hdl, u8 *pBuf, u16 uCount) +{ + /* return msd_usb2mcu(hdl, pBuf, uCount); */ + usb_dev usb_id = usb_device2id(hdl); + int ret; + int cnt = 10000; + while (cnt--) { + ret = usb_g_bulk_read(usb_id, MSD_BULK_EP_OUT, pBuf, uCount, 0); + if (ret) { + break; + } + } + // printf("%s,%d, ret:%d, cnt:%d \n", __func__, __LINE__, ret, cnt); + // put_buf(pBuf, ret); + return ret; +} +#endif +#endif diff --git a/apps/common/usb/device/msd_upgrade.c b/apps/common/usb/device/msd_upgrade.c new file mode 100644 index 0000000..6215984 --- /dev/null +++ b/apps/common/usb/device/msd_upgrade.c @@ -0,0 +1,68 @@ +#include "system/includes.h" +#include "usb/device/msd.h" +#include "usb/scsi.h" +#include "usb_config.h" +#include "app_config.h" +#include "cpu.h" +#include "asm/debug.h" + +#define WRITE_FLASH 0xFB +#define READ_FLASH 0xFD +#define OTHER_CMD 0xFC +typedef enum { + UPGRADE_NULL = 0, + UPGRADE_USB_HARD_KEY, + UPGRADE_USB_SOFT_KEY, + UPGRADE_UART_KEY, +} UPGRADE_STATE; + +extern void nvram_set_boot_state(u32 state); +extern void hw_mmu_disable(void); +extern void ram_protect_close(void); + +AT(.volatile_ram_code) +void go_mask_usb_updata() +{ + local_irq_disable(); + ram_protect_close(); + hw_mmu_disable(); + nvram_set_boot_state(UPGRADE_USB_SOFT_KEY); + + JL_CLOCK->PWR_CON |= (1 << 4); + /* chip_reset(); */ + /* cpu_reset(); */ + while (1); +} +#if TCFG_PC_UPDATE + +u32 _usb_bulk_rw_test(const struct usb_device_t *usb_device, struct usb_scsi_cbw *cbw); + +u32 private_scsi_cmd(const struct usb_device_t *usb_device, struct usb_scsi_cbw *cbw) +{ + /* if (_usb_bulk_rw_test(usb_device, cbw)) { */ + /* return TRUE; */ + /* } */ + + switch (cbw->operationCode) { +//////////////////////Boot Loader Custom CMD + case WRITE_FLASH: + case READ_FLASH: + case OTHER_CMD: + log_d("goto mask pc mode\n"); + go_mask_usb_updata(); + break; + + default: + + return FALSE; + } + + return TRUE; +} +#else +u32 private_scsi_cmd(const struct usb_device_t *usb_device, struct usb_scsi_cbw *cbw) +{ + return FALSE; +} +#endif + diff --git a/apps/common/usb/device/task_pc.c b/apps/common/usb/device/task_pc.c new file mode 100644 index 0000000..7d82380 --- /dev/null +++ b/apps/common/usb/device/task_pc.c @@ -0,0 +1,399 @@ +/** + * @file task_pc.c + * @brief 从机模式 + * @author chenrixin@zh-jieli.com + * @version 1.0.0 + * @date 2020-02-29 + */ + +#include "system/app_core.h" +#include "system/includes.h" +#include "server/server_core.h" +#include "app_config.h" +#include "app_action.h" +#include "os/os_api.h" +#include "device/sdmmc.h" +#include "app_sound_box_tool.h" + +#include "app_charge.h" +#include "asm/charge.h" + +#if TCFG_USB_SLAVE_ENABLE +#ifndef USB_PC_NO_APP_MODE +#include "app_task.h" +#endif +#include "usb/usb_config.h" +#include "usb/device/usb_stack.h" + +#if TCFG_USB_SLAVE_HID_ENABLE +#include "usb/device/hid.h" +#endif + +#if TCFG_USB_SLAVE_MSD_ENABLE +#include "usb/device/msd.h" +#endif + +#if TCFG_USB_SLAVE_CDC_ENABLE +#include "usb/device/cdc.h" +#endif + +#if (TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0) +#include "dev_multiplex_api.h" +#endif + +#if TCFG_USB_APPLE_DOCK_EN +#include "apple_dock/iAP.h" +#endif + +#define LOG_TAG_CONST USB +#define LOG_TAG "[USB_TASK]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#define USB_TASK_NAME "usb_msd" + +#define USBSTACK_EVENT 0x80 +#define USBSTACK_MSD_RUN 0x81 +#define USBSTACK_MSD_RELASE 0x82 +#define USBSTACK_HID 0x83 +#define USBSTACK_MSD_RESET 0x84 + +extern int usb_audio_demo_init(void); +extern void usb_audio_demo_exit(void); + +static usb_dev usbfd = 0;//SEC(.usb_g_bss); +static OS_MUTEX msd_mutex ;//SEC(.usb_g_bss); +static u8 msd_in_task; +static u8 msd_run_reset; + + +static void usb_task(void *p) +{ + int ret = 0; + int msg[16]; + while (1) { + ret = os_task_pend("taskq", msg, ARRAY_SIZE(msg)); + if (ret != OS_TASKQ) { + continue; + } + if (msg[0] != Q_MSG) { + continue; + } + switch (msg[1]) { +#if TCFG_USB_SLAVE_MSD_ENABLE + case USBSTACK_MSD_RUN: + os_mutex_pend(&msd_mutex, 0); + msd_in_task = 1; +#if TCFG_USB_APPLE_DOCK_EN + apple_mfi_link((void *)msg[2]); +#else + USB_MassStorage((void *)msg[2]); +#endif + if (msd_run_reset) { + msd_reset((struct usb_device_t *)msg[2], 0); + msd_run_reset = 0; + } + msd_in_task = 0; + os_mutex_post(&msd_mutex); + break; + case USBSTACK_MSD_RELASE: + os_sem_post((OS_SEM *)msg[2]); + while (1) { + os_time_dly(10000); + } + break; +// case USBSTACK_MSD_RESET: +// os_mutex_pend(&msd_mutex, 0); +// msd_reset((struct usb_device_t *)msg[2], (u32)msg[3]); +// os_mutex_post(&msd_mutex); +// break; +#endif + default: + break; + } + } +} + +static void usb_msd_wakeup(struct usb_device_t *usb_device) +{ + os_taskq_post_msg(USB_TASK_NAME, 2, USBSTACK_MSD_RUN, usb_device); +} +static void usb_msd_reset_wakeup(struct usb_device_t *usb_device, u32 itf_num) +{ + /* os_taskq_post_msg(USB_TASK_NAME, 3, USBSTACK_MSD_RESET, usb_device, itf_num); */ + if (msd_in_task) { + msd_run_reset = 1; + } else { +#if TCFG_USB_SLAVE_MSD_ENABLE + msd_reset(usb_device, 0); +#endif + } +} +static void usb_msd_init() +{ + r_printf("%s()", __func__); + int err; + os_mutex_create(&msd_mutex); + err = task_create(usb_task, NULL, USB_TASK_NAME); + if (err != OS_NO_ERR) { + r_printf("usb_msd task creat fail %x\n", err); + } +} +static void usb_msd_free() +{ + r_printf("%s()", __func__); + + os_mutex_del(&msd_mutex, 0); + + int err; + OS_SEM sem; + os_sem_create(&sem, 0); + os_taskq_post_msg(USB_TASK_NAME, 2, USBSTACK_MSD_RELASE, (int)&sem); + os_sem_pend(&sem, 0); + + + err = task_kill(USB_TASK_NAME); + if (!err) { + r_printf("usb_msd_uninit succ!!\n"); + } else { + r_printf("usb_msd_uninit fail!!\n"); + } +} + +#if TCFG_USB_SLAVE_CDC_ENABLE +static void usb_cdc_wakeup(struct usb_device_t *usb_device) +{ + //回调函数在中断里,正式使用不要在这里加太多东西阻塞中断, + //或者先post到任务,由任务调用cdc_read_data()读取再执行后续工作 + const usb_dev usb_id = usb_device2id(usb_device); + u8 buf[64] = {0}; + static u8 buf_rx[256] = {0}; + static u8 rx_len_total = 0; + u32 rlen; + + log_debug("cdc rx hook"); + rlen = cdc_read_data(usb_id, buf, 64); + + /* put_buf(buf, rlen);//固件三部测试使用 */ + /* cdc_write_data(usb_id, buf, rlen);//固件三部测试使用 */ + + if ((buf[0] == 0x5A) && (buf[1] == 0xAA) && (buf[2] == 0xA5)) { + memset(buf_rx, 0, 256); + memcpy(buf_rx, buf, rlen); + /* log_info("need len = %d\n", buf_rx[5] + 6); */ + /* log_info("rx len = %d\n", rlen); */ + if ((buf_rx[5] + 6) == rlen) { + rx_len_total = 0; +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) + /* put_buf(buf_rx, rlen); */ + online_cfg_tool_data_deal(buf_rx, rlen); +#else + put_buf(buf, rlen); + cdc_write_data(usb_id, buf, rlen); +#endif +#endif + } else { + rx_len_total += rlen; + } + } else { + if ((rx_len_total + rlen) > 256) { + memset(buf_rx, 0, 256); + rx_len_total = 0; + return; + } + memcpy(buf_rx + rx_len_total, buf, rlen); + /* log_info("need len = %d\n", buf_rx[5] + 6); */ + /* log_info("rx len = %d\n", rx_len_total + rlen); */ + if ((buf_rx[5] + 6) == (rx_len_total + rlen)) { +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) + /* put_buf(buf_rx, rx_len_total + rlen); */ + online_cfg_tool_data_deal(buf_rx, rx_len_total + rlen); +#else + put_buf(buf, rlen); + cdc_write_data(usb_id, buf, rlen); +#endif +#endif + rx_len_total = 0; + } else { + rx_len_total += rlen; + } + } +} +#endif + +void usb_start() +{ + +#if TCFG_USB_SLAVE_AUDIO_ENABLE + usb_audio_demo_init(); +#endif + +#ifdef USB_DEVICE_CLASS_CONFIG + g_printf("USB_DEVICE_CLASS_CONFIG:%x", USB_DEVICE_CLASS_CONFIG); +#if TCFG_USB_CDC_BACKGROUND_RUN + usb_device_mode(usbfd, USB_DEVICE_CLASS_CONFIG | CDC_CLASS); +#else + usb_device_mode(usbfd, USB_DEVICE_CLASS_CONFIG); +#endif + +#endif + + +#if TCFG_USB_SLAVE_MSD_ENABLE + //没有复用时候判断 sd开关 + //复用时候判断是否参与复用 +#if (!TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 && TCFG_SD0_ENABLE)\ + ||(TCFG_SD0_ENABLE && TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 && TCFG_DM_MULTIPLEX_WITH_SD_PORT != 0) + msd_register_disk("sd0", NULL); +#endif + +#if (!TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 && TCFG_SD1_ENABLE)\ + ||(TCFG_SD1_ENABLE && TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 && TCFG_DM_MULTIPLEX_WITH_SD_PORT != 1) + msd_register_disk("sd1", NULL); +#endif + +#if TCFG_NOR_FAT + msd_register_disk("fat_nor", NULL); +#endif + +#if TCFG_VIR_UDISK_ENABLE + msd_register_disk("vir_udisk0", NULL); +#endif + + msd_set_wakeup_handle(usb_msd_wakeup); + msd_set_reset_wakeup_handle(usb_msd_reset_wakeup); + usb_msd_init(); +#endif + +#if TCFG_USB_SLAVE_CDC_ENABLE + cdc_set_wakeup_handler(usb_cdc_wakeup); +#endif +} +static void usb_remove_disk() +{ +#if TCFG_USB_SLAVE_MSD_ENABLE + os_mutex_pend(&msd_mutex, 0); + msd_unregister_all(); + os_mutex_post(&msd_mutex); +#endif +} +void usb_pause() +{ + log_info("usb pause"); + + usb_sie_disable(usbfd); + +#if TCFG_USB_SLAVE_MSD_ENABLE + if (msd_set_wakeup_handle(NULL)) { + usb_remove_disk(); + usb_msd_free(); + } +#endif + + +#if TCFG_USB_SLAVE_AUDIO_ENABLE + usb_audio_demo_exit(); +#endif + + usb_device_mode(usbfd, 0); +} + +void usb_stop() +{ + log_info("App Stop - usb"); + + usb_pause(); + + usb_sie_close(usbfd); +} + +#if TCFG_USB_CDC_BACKGROUND_RUN +void usb_cdc_background_run() +{ + g_printf("CDC is running in the background"); + usb_device_mode(0, CDC_CLASS); + cdc_set_wakeup_handler(usb_cdc_wakeup); +} +#endif + +int pc_device_event_handler(struct sys_event *event) +{ + if ((int)event->arg != DEVICE_EVENT_FROM_OTG) { + return false; + } + + int switch_app_case = false; + const char *usb_msg = (const char *)event->u.dev.value; + log_debug("usb event : %d DEVICE_EVENT_FROM_OTG %s", event->u.dev.event, usb_msg); + + if (usb_msg[0] == 's') { + if (event->u.dev.event == DEVICE_EVENT_IN) { + log_info("usb %c online", usb_msg[2]); + usbfd = usb_msg[2] - '0'; +#if USB_PC_NO_APP_MODE + usb_start(); +#elif TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + usb_otg_suspend(0, OTG_KEEP_STATE); + mult_sdio_suspend(); + usb_pause(); + mult_sdio_resume(); +#else + + +#if (TWFG_APP_POWERON_IGNORE_DEV && TCFG_USB_CDC_BACKGROUND_RUN && TCFG_PC_ENABLE) + usb_cdc_background_run(); +#elif (TWFG_APP_POWERON_IGNORE_DEV == 0) + usb_pause(); +#endif + + +#endif + switch_app_case = 1; + } else if (event->u.dev.event == DEVICE_EVENT_OUT) { + log_info("usb %c offline", usb_msg[2]); + switch_app_case = 2; +#ifdef USB_PC_NO_APP_MODE + usb_stop(); +#else + +#ifdef CONFIG_SOUNDBOX + if (!app_check_curr_task(APP_PC_TASK)) { +#else + if (!app_cur_task_check(APP_NAME_PC)) { +#endif +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + mult_sdio_suspend(); +#endif + usb_stop(); +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + mult_sdio_resume(); +#endif + } + +#endif + } + } + + return switch_app_case; +} + +#ifdef USB_PC_NO_APP_MODE +void usbstack_init() +{ + register_sys_event_handler(SYS_DEVICE_EVENT, DEVICE_EVENT_FROM_OTG, 2, + pc_device_event_handler); +} + +void usbstack_exit() +{ + unregister_sys_event_handler(pc_device_event_handler); +} +#endif + +#endif diff --git a/apps/common/usb/device/uac1.c b/apps/common/usb/device/uac1.c new file mode 100644 index 0000000..4f29a00 --- /dev/null +++ b/apps/common/usb/device/uac1.c @@ -0,0 +1,1334 @@ +/* Copyright(C) JieLi Technology + * usb audio 1.0 + * All right reserved + * + */ + +#include "system/includes.h" +#include "usb_config.h" +#include "usb/device/usb_stack.h" +#include "usb/device/uac_audio.h" +#include "app_config.h" + +#if TCFG_USB_SLAVE_AUDIO_ENABLE + +#define LOG_TAG_CONST USB +#define LOG_TAG "[USB]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" +static u32 mic_samplingfrequency; +/*********************************************************/ +/* + Audio Class +*/ +/*********************************************************/ +///Standard Interface Association Descriptor +static const u8 uac_audio_interface_association[] = { + USB_DT_INTERFACE_ASSOCIATION_SIZE, //Size of this descriptor in bytes: 8 + USB_DT_INTERFACE_ASSOCIATION,//INTERFACE ASSOCIATION Descriptor + 0,//Interface number of the first interface that is associated with this function + 0,//Number of contiguous interfaces that are associated with this function. + USB_CLASS_AUDIO,//AUDIO_FUNCTION Function Class code + USB_SUBCLASS_AUDIOSTREAMING,//FUNCTION_SUBCLASS_UNDEFINED + PC_PROTOCOL_UNDEFINED,//AF_VERSION_02_00 Function Protocol code. + SPEAKER_STR_INDEX,//Index of a string descriptor that describes this interface. +}; +static const u8 uac_ac_standard_interface_desc[] = { +///standard interface AC descriptor(Interface 0, Alternate Setting 0) + USB_DT_INTERFACE_SIZE, //Length + USB_DT_INTERFACE, //DescriptorType:Inerface + 0x00, //InterfaceNum + 0x00, //AlternateSetting + 0x00, //NumEndpoint + USB_CLASS_AUDIO, //InterfaceClass:audio + USB_SUBCLASS_AUDIOCONTROL, //InterfaceSubClass:audio ctl + PC_PROTOCOL_UNDEFINED, //InterfaceProtocol + SPEAKER_STR_INDEX, //Interface String +}; + +static const u8 uac_spk_ac_interface[] = { +///class-specific AC interface descriptor + 0x09, //Length + USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor + UAC_HEADER, //DescriptorSubType:audio control header + 0x00, 0x01, //bcdADC:audio Device Class v1.00 + 0x28, 0x00, //TotalLength of class-specific AC interface descriptors + 0x01, //InCollection:1 AudioStreaming interface + 0x02, //InterfaceNr(1) - AS #2 id AudioStreaming interface 1 belongs to this AudioControl interface + /* 0x03, //InterfaceNr(1) - AS #2 id AudioStreaming interface 1 belongs to this AudioControl interface */ +}; +static const u8 uac_audio_ac_interface[] = { +///class-specific AC interface descriptor + 0x0a, //Length + USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor + UAC_HEADER, //DescriptorSubType:audio control header + 0x00, 0x01, //bcdADC:audio Device Class v1.00 + 0x47, 0x00, //TotalLength of class-specific AC interface descriptors + 0x02, //InCollection:1 AudioStreaming interface + 0x01, //InterfaceNr(1) - AS #2 id AudioStreaming interface 1 belongs to this AudioControl interface + 0x02, //InterfaceNr(1) - AS #2 id AudioStreaming interface 1 belongs to this AudioControl interface +}; + + +static const u8 uac_spk_input_terminal_desc[] = { + +///USB USB Streaming IT(Speaker) + 0x0c, //Length + USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor + UAC_INPUT_TERMINAL, //DescriptorSubType:Input Terminal + SPK_INPUT_TERMINAL_ID, //TerminalID + LOBYTE(UAC_TERMINAL_STREAMING), HIBYTE(UAC_TERMINAL_STREAMING), //TerminalType:USB Streaming + 0x00, //AssocTerminal + SPK_CHANNEL, //NrChannels:2 channel +#if SPK_CHANNEL == 1 + 0x04, 0x00, //Mono center front channel +#else + 0x03, 0x00, //ChannelConfig:Left Front,Right Front, +#endif + 0x00, //ChannelName String + 0x00, //Terminal String +}; +///Audio Feature Unit Descriptor(Speaker) +static const u8 uac_spk_feature_desc[] = { + 0x07 + (SPK_CHANNEL + 1) * 1, //Length + USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor + UAC_FEATURE_UNIT, //DescriptorSubType:Audio Feature Unit + SPK_FEATURE_UNIT_ID, //UnitID + SPK_INPUT_TERMINAL_ID, //SourceID:1 #USB Streaming IT + 0x01, //ControlSize:1 byte + 0x01, //Controls:BIT[0……7]:Mute,Volume Bass Mid Treble...... + 0x02, //left ch +#if SPK_CHANNEL == 2 + 0x02, //right ch +#endif + 0x00, //Feature String +}; +static const u8 uac_spk_output_terminal_desc[] = { +///USB Speaker OT + 0x09, //Length + USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor + UAC_OUTPUT_TERMINAL, //DescriptorSubTYpe:Output Terminal + SPK_OUTPUT_TERMINAL_ID, //TerminalID + LOBYTE(UAC_OUTPUT_TERMINAL_SPEAKER), HIBYTE(UAC_OUTPUT_TERMINAL_SPEAKER), //TerminalType:Speaker + 0, //AssocTerminal: + SPK_FEATURE_UNIT_ID, //SourceID: Feature UNIT + 0x00, //Terminal String +}; + +static const u8 uac_spk_as_interface_desc[] = { +//-------------------Speaker interface---------------------// +///standard interface AS descriptor(Interface 1, Alternate Setting 0) + USB_DT_INTERFACE_SIZE, //Length + USB_DT_INTERFACE, //DescriptorType:Interface + 0x00, //InterfaceNum:2 + 0x00, //AlternateSetting:0 + 0x00, //NumEndpoint:0 + USB_CLASS_AUDIO, //InterfaceClass:audio + USB_SUBCLASS_AUDIOSTREAMING, //InterfaceSubClass:audio streaming + PC_PROTOCOL_UNDEFINED, //InterfaceProtocol + 0x00, //Interface String + +///standard interface AS descriptor(Interface 2, Alternate Setting 1) + USB_DT_INTERFACE_SIZE, //Length + USB_DT_INTERFACE, //DescriptorType:Interface + 0x00, //InterfaceNum + 0x01, //AlternateSetting + 0x01, //NumEndpoint + USB_CLASS_AUDIO, //InterfaceClass:audio + USB_SUBCLASS_AUDIOSTREAMING, //InterfaceSubClass:audio streaming + PC_PROTOCOL_UNDEFINED, //InterfaceProtocol + 0x00, //Interface String + +///Audio Streaming Interface Descriptor:AS_GENERAL(0x01), + 0x07, //Length + USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor + UAC_AS_GENERAL, //DescriptorSubType:AS_GENERAL + SPK_INPUT_TERMINAL_ID, //TerminalLink:#1 USB Streaming IT + 0x01, //Delay:1 + (SPK_AUDIO_TYPE & 0xFF), (SPK_AUDIO_TYPE >> 8), //FormatTag:PCM + +///Type 1 Format type descriptor + 0x0b, //Length + USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor + UAC_FORMAT_TYPE, //DescriptorSubType:Format_type + UAC_FORMAT_TYPE_I, //FormatType:Format type 1 + SPK_CHANNEL, //NumberOfChannel + 0x02, //SubframeSize:2byte + SPK_AUDIO_RES, //BitsResolution:16bit + 0x01, //SampleFreqType:One sampling frequency. + DW1BYTE(SPK_AUDIO_RATE), DW2BYTE(SPK_AUDIO_RATE), DW3BYTE(SPK_AUDIO_RATE), + +//Isochronous,Synchronization Type(Asynchronous) + 0x09, //Length + USB_DT_ENDPOINT, //DescriptorType:endpoint descriptor + USB_DIR_OUT | SPK_ISO_EP_OUT, //EndpointAddress:Output endpoint 1 + USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ADAPTIVE, //0x09, + LOBYTE(SPK_FRAME_LEN), HIBYTE(SPK_FRAME_LEN), //MaxPacketSize + UAC_ISO_INTERVAL,//one packet per frame 0x00, //Interval //Asynchronous + 0x00,//unused + 0x00,//unused + +//Audio Endpoint descriptor,General + 0x07, //Length + USB_DT_CS_ENDPOINT, //DescriptorType:audio endpoint descriptor + UAC_AS_GENERAL, //DescriptorSubType:audio endpiont general +// 0x01, // bmAttributes (Sampling Freq Control) + 0x00, //Attributes + 0x00, //LockDelayUnits + 0x00, 0x00, //LockDelay +}; + +const u8 speakerStringDescriptor[20] = { + 20, //该描述符的长度为20字节 + 0x03, //字符串描述符的类型编码为0x03 + 'U', 0x00, //U + 'S', 0x00, //S + 'B', 0x00, //B + ' ', 0x00, // + 'A', 0x00, //A + 'u', 0x00, //u + 'd', 0x00, //d + 'i', 0x00, //i + 'o', 0x00, //o +}; +/*********************************************************/ +/* + Microphone Class +*/ +/*********************************************************/ + +///Standard Interface Association Descriptor +static const u8 uac_mic_interface_association[] = { + USB_DT_INTERFACE_ASSOCIATION_SIZE,//Size of this descriptor in bytes + USB_DT_INTERFACE_ASSOCIATION,//INTERFACE ASSOCIATION Descriptor + 2,//Interface number of the first interface that is associated with this function **** + 1,//Number of contiguous interfaces that are associated with this function. + USB_CLASS_AUDIO,//AUDIO_FUNCTION Function Class code + USB_SUBCLASS_AUDIOSTREAMING,//FUNCTION_SUBCLASS_UNDEFINED + PC_PROTOCOL_UNDEFINED,//AF_VERSION_02_00 Function Protocol code. + MIC_STR_INDEX,//Index of a string descriptor that describes this interface +}; +static const u8 uac_mic_ac_interface[] = { +///class-specific AC interface descriptor + 0x09, //Length + USB_DT_CS_INTERFACE, //DescriptorType + UAC_HEADER, //DescriptorSubType + 0x00, 0x01, //bcdADC + 0x27, 0x00, /*TotalLength of class-specific AC interface descriptors */ + /* Includes the combined length */ + /* of this descriptor header and all Unit and */ + /* Terminal descriptors. */ + 0x01, //InCollection:1 AudioStreaming interface + 0x01, //InterfaceNr(1) **** +}; +///USB USB Streaming IT(Microphone) +static const u8 uac_mic_input_terminal_desc[] = { + 0x0c, //Length + USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor + UAC_INPUT_TERMINAL, //DescriptorSubType:Input Terminal + MIC_INPUT_TERMINAL_ID, //TerminalID + LOBYTE(UAC_INPUT_TERMINAL_MICROPHONE), HIBYTE(UAC_INPUT_TERMINAL_MICROPHONE), //TerminalType:Microphone + 0, //AssocTerminal + MIC_CHANNEL, //NrChannels +#if MIC_CHANNEL == 2 + 0x03, 0x00, //wChannelConfig:Left Front right Front +#else + 0x00, 0x00, //wChannelConfig: +#endif + 0x00, //ChannelName String + 0x00, //Terminal String +}; +//SELECTOR_UNIT +static const u8 uac_mic_selector_uint_desc[] = { + 0x7, // bLength 7 + USB_DT_CS_INTERFACE,// bDescriptorType CS_INTERFACE (0x24) + UAC_SELECTOR_UNIT,// bDescriptorSubtype SELECTOR_UNIT (0x05) + MIC_SELECTOR_UNIT_ID,//bUnitID 33 + 1,//bNrInPins 1 + MIC_FEATURE_UNIT_ID, //baSourceID(1) 50 + 0,//iSelector None (0) +}; + +///Audio Feature Unit Descriptor(Microphone) +static const u8 uac_mic_feature_desc[] = { + 7 + (MIC_CHANNEL + 1) * 1, //Length + USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor + UAC_FEATURE_UNIT, //DescriptorSubType:Audio Feature Unit + MIC_FEATURE_UNIT_ID, //UnitID + MIC_INPUT_TERMINAL_ID, //SourceID: #Microphone + 0x01, //ControlSize:1 byte + 0x43, 0x00, // bmaControls[0] (Mute,Volume,Automatic) +#if MIC_CHANNEL == 2 + 0x00, +#endif + 0x00, //Feature String +}; +///USB Microphone OT +static const u8 uac_mic_output_terminal_desc[] = { + 0x09, //Length + USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor + UAC_OUTPUT_TERMINAL, //DescriptorSubTYpe:Output Terminal + MIC_OUTPUT_TERMINAL_ID, //TerminalID + LOBYTE(UAC_TERMINAL_STREAMING), HIBYTE(UAC_TERMINAL_STREAMING), //TerminalType:USB Sreaming + 2, //AssocTerminal: + MIC_SELECTOR_UNIT_ID, //SourceID:A #Feature UNIT + 0x00, //Terminal String +}; + +///standard interface AS descriptor(Interface 1, Alternate Setting 0) +static const u8 uac_mic_as_interface_desc[] = { + USB_DT_INTERFACE_SIZE, //Length + USB_DT_INTERFACE, //DescriptorType:Interface + 0x03, //InterfaceNum **** + 0x00, //AlternateSetting + 0x00, //NumEndpoint + USB_CLASS_AUDIO, //InterfaceClass:audio + USB_SUBCLASS_AUDIOSTREAMING, //InterfaceSubClass:audio streaming + 0x00, //InterfaceProtocol + 0x00, //Interface String + +///standard interface AS descriptor(Interface 2, Alternate Setting 1) + USB_DT_INTERFACE_SIZE, //Length + USB_DT_INTERFACE, //DescriptorType:Interface + 0x02, //InterfaceNum **** + 0x01, //AlternateSetting + 0x01, //NumEndpoint + USB_CLASS_AUDIO, //InterfaceClass:audio + USB_SUBCLASS_AUDIOSTREAMING, //InterfaceSubClass:audio streaming + 0x00, //InterfaceProtocol + 0x00, //Interface String + +///Audio Streaming Interface Descriptor:AS_GENERAL + 0x07, //Length + USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor + UAC_AS_GENERAL, //DescriptorSubType:AS_GENERAL + MIC_OUTPUT_TERMINAL_ID, //TerminalLink:#1 USB Streaming OT + 0x01, //Delay:1 + (MIC_AUDIO_TYPE & 0xFF), (MIC_AUDIO_TYPE >> 8), //FormatTag:PCM + +///Type 1 Format type descriptor + 0x08 + 3 * (MIC_SamplingFrequency), //Length + USB_DT_CS_INTERFACE, //DescriptorType:audio interface descriptor + UAC_FORMAT_TYPE, //DescriptorSubType:Format_type + UAC_FORMAT_TYPE_I_PCM, //FormatType:Format type 1 + MIC_CHANNEL, //NumberOfChannel:1 + MIC_AUDIO_RES / 8, //SubframeSize:2byte + MIC_AUDIO_RES, //BitsResolution:16bit +#if MIC_SamplingFrequency > 1 + MIC_SamplingFrequency, + DW1BYTE(MIC_AUDIO_RATE_1), DW2BYTE(MIC_AUDIO_RATE_1), DW3BYTE(MIC_AUDIO_RATE_1), + DW1BYTE(MIC_AUDIO_RATE_2), DW2BYTE(MIC_AUDIO_RATE_2), DW3BYTE(MIC_AUDIO_RATE_2), + DW1BYTE(MIC_AUDIO_RATE), DW2BYTE(MIC_AUDIO_RATE), DW3BYTE(MIC_AUDIO_RATE), + DW1BYTE(MIC_AUDIO_RATE_4), DW2BYTE(MIC_AUDIO_RATE_4), DW3BYTE(MIC_AUDIO_RATE_4), +#else + 0x01, //SampleFreqType:One sampling frequency. + DW1BYTE(MIC_AUDIO_RATE), DW2BYTE(MIC_AUDIO_RATE), DW3BYTE(MIC_AUDIO_RATE), +#endif + +///Endpoint 1 - Standard Descriptor:Output Endpoint1 +//Isochronous,Synchronization Type(Asynchronous) + USB_DT_ENDPOINT_AUDIO_SIZE, //Length + USB_DT_ENDPOINT, //DescriptorType:endpoint descriptor + USB_DIR_IN | MIC_ISO_EP_IN, //EndpointAddress:Output endpoint + USB_ENDPOINT_XFER_ISOC | USB_ENDPOINT_SYNC_ASYNC, + LOBYTE(MIC_FRAME_LEN), HIBYTE(MIC_FRAME_LEN), //MaxPacketSize + UAC_ISO_INTERVAL,//one packet per frame //Interval + 0x00,//unused + 0x00,//unused + +///Endpoint - Audio Streaming Descriptor +//Audio Endpoint descriptor,General + 0x07, //Length + USB_DT_CS_ENDPOINT, //DescriptorType:audio endpoint descriptor + UAC_AS_GENERAL, //DescriptorSubType:audio endpiont general +#if MIC_SamplingFrequency > 1 + 0x01, // bmAttributes (Sampling Freq Control) +#else + 0x00, //Attributes +#endif + + 0x00, //LockDelayUnits + 0x00, 0x00, //LockDelay +}; +static const u8 micStringDescriptor[30] = { + 30, //该描述符的长度为30字节 + 0x03, //字符串描述符的类型编码为0x03 + 'U', 0x00, //U + 'S', 0x00, //S + 'B', 0x00, //B + ' ', 0x00, // + 'M', 0x00, //M + 'i', 0x00, //i + 'c', 0x00, //c + 'r', 0x00, //r + 'o', 0x00, //o + 'p', 0x00, //p + 'h', 0x00, //h + 'o', 0x00, //o + 'n', 0x00, //n + 'e', 0x00, //e +}; + +const u8 *uac_get_string(u32 id) +{ + if (id == SPEAKER_STR_INDEX) { + return speakerStringDescriptor; + } else if (id == MIC_STR_INDEX) { + return micStringDescriptor; + } + return NULL; +} +struct uac_info_t { + u16 spk_left_vol; + u16 spk_right_vol; + u16 spk_max_vol; + u16 spk_min_vol; + u16 spk_def_vol; + u16 spk_vol_res; + + u16 mic_max_vol; + u16 mic_min_vol; + u16 mic_def_vol; + u16 mic_vol_res; + u16 mic_vol; + + u8 spk_mute: 1; + u8 mic_mute: 1; + u8 bAGC: 1; + u8 res: 5; +}; + + +struct uac_info_t *uac_info; +#if USB_MALLOC_ENABLE +#else +struct uac_info_t _uac_info SEC(.uac_var); +#endif + +static u32 vol_convert(u16 v) +{ + const u16 vol_table[] = { + 0xe3a0, 0xe461, 0xe519, 0xe5c8, 0xe670, 0xe711, 0xe7ac, 0xe840, 0xe8cf, 0xe959, + 0xe9df, 0xea60, 0xeadc, 0xeb55, 0xebca, 0xec3c, 0xecab, 0xed16, 0xed7f, 0xede5, + 0xee48, 0xeea9, 0xef08, 0xef64, 0xefbe, 0xf016, 0xf06c, 0xf0c0, 0xf113, 0xf164, + 0xf1b3, 0xf200, 0xf24c, 0xf297, 0xf2e0, 0xf328, 0xf36e, 0xf3b4, 0xf3f8, 0xf43a, + 0xf47c, 0xf4bd, 0xf4fc, 0xf53b, 0xf579, 0xf5b5, 0xf5f1, 0xf62c, 0xf666, 0xf69f, + 0xf6d7, 0xf70e, 0xf745, 0xf77b, 0xf7b0, 0xf7e5, 0xf818, 0xf84b, 0xf87e, 0xf8b0, + 0xf8e1, 0xf911, 0xf941, 0xf970, 0xf99f, 0xf9cd, 0xf9fb, 0xfa28, 0xfa55, 0xfa81, + 0xfaad, 0xfad8, 0xfb03, 0xfb2d, 0xfb56, 0xfb80, 0xfba9, 0xfbd1, 0xfbf9, 0xfc21, + 0xfc48, 0xfc6f, 0xfc95, 0xfcbb, 0xfce1, 0xfd06, 0xfd2b, 0xfd50, 0xfd74, 0xfd98, + 0xfdbc, 0xfddf, 0xfe02, 0xfe25, 0xfe47, 0xfe69, 0xfe8b, 0xfead, 0xfece, 0xfeef, + 0xff0f, + }; + + if (v <= 100) { + return vol_table[v]; + } + + for (int i = 0; i < sizeof(vol_table) / 2; i++) { + if (v <= vol_table[i]) { + return i; + } + } + + return 0; +} + +void uac_get_cur_vol(const usb_dev usb_id, u16 *l_vol, u16 *r_vol) +{ + if (l_vol) { + *l_vol = 0; + } + if (r_vol) { + *r_vol = 0; + } + if (uac_info) { + if (!uac_info->spk_mute) { + if (l_vol) { + *l_vol = vol_convert(uac_info->spk_left_vol); + } + if (r_vol) { + *r_vol = vol_convert(uac_info->spk_right_vol); + } + } + } +} +u16 uac_get_mic_vol(const usb_dev usb_id) +{ + if (uac_info) { + if (!uac_info->mic_mute) { + return vol_convert(uac_info->mic_vol); + } + } + return 0; +} +static u32 uac_vol_handler(struct usb_device_t *usb_device, struct usb_ctrlrequest *setup) +{ + const usb_dev usb_id = usb_device2id(usb_device); + u32 ret = 0; + u8 read_ep[8]; + u8 mute; + u16 volume = 0; + usb_read_ep0(usb_id, read_ep, setup->wLength); + ret = USB_EP0_STAGE_SETUP; + switch (HIBYTE(setup->wValue)) { + case UAC_FU_MUTE: + if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) { + memcpy((u8 *)&mute, read_ep, 1); + if (mute) { + uac_mute_volume(SPK_FEATURE_UNIT_ID, 0, 0); + uac_info->spk_mute = 1; + } else { + uac_mute_volume(SPK_FEATURE_UNIT_ID, + vol_convert(uac_info->spk_left_vol), + vol_convert(uac_info->spk_right_vol)); + uac_info->spk_mute = 0; + } + } else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) { + memcpy((u8 *)&mute, read_ep, 1); + if (mute) { + uac_mute_volume(MIC_FEATURE_UNIT_ID, 0, 0); + uac_info->mic_mute = 1; + } else { + uac_mute_volume(MIC_FEATURE_UNIT_ID, vol_convert(uac_info->mic_vol), 0); + uac_info->mic_mute = 0; + } + } + break; + case UAC_FU_VOLUME: + if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) { + memcpy((u8 *)&volume, read_ep, setup->wLength); + if (LOBYTE(setup->wValue) == 1) { + uac_info->spk_left_vol = volume; + } else if (LOBYTE(setup->wValue) == 2) { + uac_info->spk_right_vol = volume; + /* printf("%x %d",volume,vol_convert(volume)); */ + } + if (!uac_info->spk_mute) { + uac_mute_volume(SPK_FEATURE_UNIT_ID, + vol_convert(uac_info->spk_left_vol), + vol_convert(uac_info->spk_right_vol)); + } + } else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) { + memcpy((u8 *)&uac_info->mic_vol, read_ep, sizeof(uac_info->mic_vol)); + /* if (uac_info->mic_vol == 0x8000) { */ + /* uac_info->mic_vol = 0; */ + /* } else if (uac_info->mic_vol >= 100) { */ + /* uac_info->mic_vol = 99; */ + /* } */ + if (!uac_info->mic_mute) { + uac_mute_volume(MIC_FEATURE_UNIT_ID, vol_convert(uac_info->mic_vol), 0); + } + } + break; + case UAC_FU_AUTOMATIC_GAIN: + if (read_ep[0]) { + uac_info->bAGC = 1; + } else { + uac_info->bAGC = 0; + } + break; + default : + ret = USB_EP0_SET_STALL; + break; + } + + return ret; +} +#if USB_ROOT2 +static u8 SetInterface_0_Lock; +#endif +static u32 uac_endpoint_recv(struct usb_device_t *usb_device, struct usb_ctrlrequest *setup) +{ + const usb_dev usb_id = usb_device2id(usb_device); + u32 ret = 0; + u8 read_ep[8]; + + usb_read_ep0(usb_id, read_ep, setup->wLength); + + ret = USB_EP0_STAGE_SETUP; + u32 ep = LOBYTE(setup->wIndex); + switch (ep) { + case MIC_ISO_EP_IN|USB_DIR_IN: + memcpy(&mic_samplingfrequency, read_ep, 3); + break; + case SPK_ISO_EP_OUT|USB_DIR_OUT: + /* memcpy(&spk_samplingfrequency,read_ep,3); */ + break; + } + return ret; +} +u32 uac_setup_endpoint(struct usb_device_t *usb_device, struct usb_ctrlrequest *req) +{ + u32 ret = 0; + const usb_dev usb_id = usb_device2id(usb_device); + u8 type = req->bRequestType & USB_TYPE_MASK; + if (type != USB_TYPE_CLASS) { + return ret; + } + if (req->bRequest != 0x01) { + return ret; + } + if (req->wValue != 0x0100) { + return ret; + } + usb_set_setup_recv(usb_device, uac_endpoint_recv); + return 1; +} +static u32 audio_ac_itf_handler(struct usb_device_t *usb_device, struct usb_ctrlrequest *setup) +{ + u8 mute; + + const usb_dev usb_id = usb_device2id(usb_device); + u32 tx_len; + u8 *tx_payload = usb_get_setup_buffer(usb_device); + u32 bRequestType = setup->bRequestType & USB_TYPE_MASK; + u32 ret = 0; + switch (setup->bRequest) { + case USB_REQ_SET_INTERFACE: +#if USB_ROOT2 + SetInterface_0_Lock = 1; + if (usb_device->bDeviceStates == USB_DEFAULT) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_ADDRESS) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_CONFIGURED) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);//no alt setting + } +#else + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL);//no alt setting +#endif + break; + case USB_REQ_GET_INTERFACE: +#if USB_ROOT2 + if (usb_root2_testing()) { + SetInterface_0_Lock = 0; + } +#endif + if (setup->wLength) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_DEFAULT) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_ADDRESS) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_CONFIGURED) { + tx_len = 1; + tx_payload[0] = 0x00; + usb_set_data_payload(usb_device, setup, tx_payload, tx_len); + } + break; + case UAC_SET_CUR: + /* USB_DEBUG_PRINTF("set vol && mute"); */ + usb_set_setup_recv(usb_device, uac_vol_handler); + break; + case UAC_GET_CUR: + switch (HIBYTE(setup->wValue)) { + case UAC_FU_MUTE: + if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) { + mute = uac_info->spk_mute ; + } else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) { + mute = uac_info->mic_mute ; + } + tx_payload = &mute; + tx_len = setup->wLength; + usb_set_data_payload(usb_device, setup, tx_payload, tx_len); + break; + + case UAC_FU_VOLUME: + if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) { + if (LOBYTE(setup->wValue) == 1) { + tx_payload = (u8 *)&uac_info->spk_left_vol; + } else if (LOBYTE(setup->wValue) == 2) { + tx_payload = (u8 *)&uac_info->spk_right_vol; + } + } else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) { + tx_payload = (u8 *)&uac_info->mic_vol; + } + tx_len = setup->wLength; + usb_set_data_payload(usb_device, setup, tx_payload, tx_len); + break; + case UAC_FU_AUTOMATIC_GAIN: + if (uac_info->bAGC) { + tx_payload[0] = 0x01; + } else { + tx_payload[0] = 0x00; + } + tx_len = setup->wLength; + usb_set_data_payload(usb_device, setup, tx_payload, tx_len); + break; + } + break; + case UAC_GET_DEF: + if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) { + tx_payload = (u8 *)&uac_info->spk_def_vol; + } else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) { + tx_payload = (u8 *)&uac_info->mic_def_vol; + } + tx_len = setup->wLength; + usb_set_data_payload(usb_device, setup, tx_payload, tx_len); + break; + case UAC_GET_MAX: + if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) { + tx_payload = (u8 *)&uac_info->spk_max_vol; + } else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) { + tx_payload = (u8 *)&uac_info->mic_max_vol; + } + tx_len = setup->wLength; + usb_set_data_payload(usb_device, setup, tx_payload, tx_len); + break; + case UAC_GET_MIN: + if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) { + tx_payload = (u8 *)&uac_info->spk_min_vol; + } else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) { + tx_payload = (u8 *)&uac_info->mic_min_vol; + } + tx_len = setup->wLength; + usb_set_data_payload(usb_device, setup, tx_payload, tx_len); + break; + case UAC_GET_RES: + if (HIBYTE(setup->wIndex) == SPK_FEATURE_UNIT_ID) { + tx_payload = (u8 *)&uac_info->spk_vol_res; + } else if (HIBYTE(setup->wIndex) == MIC_FEATURE_UNIT_ID) { + tx_payload = (u8 *)&uac_info->mic_vol_res; + } + tx_len = setup->wLength; + usb_set_data_payload(usb_device, setup, tx_payload, tx_len); + break; + case UAC_GET_LEN: + break; + case UAC_GET_INFO: + break; + case USB_REQ_GET_STATUS: + if (usb_device->bDeviceStates == USB_DEFAULT) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_ADDRESS) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } + break; + default: + ret = 1 ; + break; + } + return ret; +} +#define UAC_PLC_EN 0 +#if UAC_PLC_EN +typedef struct _USBAUDIO_PLC_API { + unsigned int (*need_buf)(); + void (*open)(unsigned char *ptr, int sr, int nch); + int (*run)(unsigned char *ptr, short *inbuf, short *oubuf, short len, short err_flag); +} USBAUDIO_PLC_API; + +extern USBAUDIO_PLC_API *get_USBplc_api(); + +static USBAUDIO_PLC_API *uac_plc_api = 0; +static u8 *uac_plc_buffer; + +void usb_audio_plc_open() +{ + uac_plc_api = get_USBplc_api(); + u32 bufsize = uac_plc_api->need_buf(); + uac_plc_buffer = malloc(bufsize); + uac_plc_api->open(uac_plc_buffer, SPK_AUDIO_RATE, SPK_CHANNEL); +} +void usb_audio_plc_close() +{ + if (uac_plc_api) { + uac_plc_api = NULL; + } + if (uac_plc_buffer) { + free(uac_plc_buffer); + uac_plc_buffer = NULL; + } +} +#endif + +static void spk_transfer(struct usb_device_t *usb_device, u32 ep) +{ + const usb_dev usb_id = usb_device2id(usb_device); + u8 *ep_buffer = usb_get_ep_buffer(usb_id, SPK_ISO_EP_OUT); + u32 spk_frame_len = SPK_AUDIO_RATE * (SPK_AUDIO_RES / 8) * SPK_CHANNEL / 1000; + spk_frame_len += (SPK_AUDIO_RATE % 1000 ? (SPK_AUDIO_RES / 8) * SPK_CHANNEL : 0); + u32 rx_len = usb_g_iso_read(usb_id, SPK_ISO_EP_OUT, NULL, spk_frame_len, 0); + +#if UAC_PLC_EN + if (rx_len) { + uac_plc_api->run(uac_plc_buffer, ep_buffer, ep_buffer, rx_len, 0); + } else { + uac_plc_api->run(uac_plc_buffer, ep_buffer, ep_buffer, rx_len, 1); + } +#endif + + uac_speaker_stream_write(ep_buffer, rx_len); +} +static void open_spk(struct usb_device_t *usb_device) +{ + log_info("%s", __func__); + const usb_dev usb_id = usb_device2id(usb_device); + u32 spk_frame_len = SPK_AUDIO_RATE * (SPK_AUDIO_RES / 8) * SPK_CHANNEL / 1000; + spk_frame_len += (SPK_AUDIO_RATE % 1000 ? (SPK_AUDIO_RES / 8) * SPK_CHANNEL : 0); + usb_enable_ep(usb_id, SPK_ISO_EP_OUT); + u8 *ep_buffer = usb_get_ep_buffer(usb_id, SPK_ISO_EP_OUT); + uac_speaker_stream_open(SPK_AUDIO_RATE, SPK_CHANNEL); + +#if UAC_PLC_EN + usb_audio_plc_open(); +#endif + + usb_g_set_intr_hander(usb_id, SPK_ISO_EP_OUT | USB_DIR_OUT, spk_transfer); + + usb_g_ep_config(usb_id, SPK_ISO_EP_OUT | USB_DIR_OUT, USB_ENDPOINT_XFER_ISOC, 1, ep_buffer, spk_frame_len); + +} +static void close_spk(struct usb_device_t *usb_device) +{ + log_info("%s", __func__); + const usb_dev usb_id = usb_device2id(usb_device); + usb_clr_intr_rxe(usb_id, SPK_ISO_EP_OUT); + usb_g_set_intr_hander(usb_id, SPK_ISO_EP_OUT, NULL); + +#if UAC_PLC_EN + usb_audio_plc_close(); +#endif + + uac_speaker_stream_close(); + +} +static u32 spk_as_itf_hander(struct usb_device_t *usb_device, struct usb_ctrlrequest *setup) +{ + const usb_dev usb_id = usb_device2id(usb_device); + u32 tx_len; + u8 *tx_payload = usb_get_setup_buffer(usb_device); + u32 bRequestType = setup->bRequestType & USB_TYPE_MASK; + u32 ret = 0; + + switch (setup->bRequest) { + case USB_REQ_SET_INTERFACE: + if (usb_device->bDeviceStates == USB_DEFAULT) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_ADDRESS) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_CONFIGURED) { +#if USB_ROOT2 + if (!usb_root2_testing()) { + SetInterface_0_Lock = 1; + } + if (SetInterface_0_Lock == 0) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else { + usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP); + if (setup->wValue == 1) { //alt 1 + open_spk(usb_device); + } else if (setup->wValue == 0) { //alt 0 + close_spk(usb_device); + } else { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } + } +#else + usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP); + if (setup->wValue == 1) { //alt 1 + open_spk(usb_device); + } else if (setup->wValue == 0) { //alt 0 + close_spk(usb_device); + } else { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } +#endif + } + + break; + case USB_REQ_GET_INTERFACE: + if (usb_root2_testing()) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else { + if (setup->wLength) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_DEFAULT) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_ADDRESS) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_CONFIGURED) { + tx_len = 1; + tx_payload[0] = 0x00; + usb_set_data_payload(usb_device, setup, tx_payload, tx_len); + } + } + break; + case USB_REQ_GET_STATUS: + if (usb_device->bDeviceStates == USB_DEFAULT) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_ADDRESS) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } + break; + default: + break; + } + return ret; +} +static void mic_transfer(struct usb_device_t *usb_device, u32 ep) +{ + const usb_dev usb_id = usb_device2id(usb_device); + u8 *ep_buffer = usb_get_ep_buffer(usb_id, MIC_ISO_EP_IN | USB_DIR_IN); + + if (mic_samplingfrequency == 0) { + mic_samplingfrequency = MIC_AUDIO_RATE; + } + u32 mic_frame_len = ((mic_samplingfrequency * MIC_AUDIO_RES / 8 * MIC_CHANNEL) / 1000); + mic_frame_len += (mic_samplingfrequency % 1000 ? (MIC_AUDIO_RES / 8) * MIC_CHANNEL : 0); + + int len = uac_mic_stream_read(ep_buffer, mic_frame_len); + usb_g_iso_write(usb_id, MIC_ISO_EP_IN, NULL, len); + +} +static void open_mic(struct usb_device_t *usb_device) +{ + log_info("%s", __func__); + const usb_dev usb_id = usb_device2id(usb_device); + usb_enable_ep(usb_id, MIC_ISO_EP_IN); + u8 *ep_buffer = usb_get_ep_buffer(usb_id, MIC_ISO_EP_IN | USB_DIR_IN); + + usb_g_set_intr_hander(usb_id, MIC_ISO_EP_IN | USB_DIR_IN, mic_transfer); + + if (mic_samplingfrequency == 0) { + mic_samplingfrequency = MIC_AUDIO_RATE; + } + u32 mic_frame_len = ((mic_samplingfrequency * MIC_AUDIO_RES / 8 * MIC_CHANNEL) / 1000); + mic_frame_len += (mic_samplingfrequency % 1000 ? (MIC_AUDIO_RES / 8) * MIC_CHANNEL : 0); + + uac_mic_stream_open(mic_samplingfrequency, mic_frame_len, MIC_CHANNEL); + + usb_g_ep_config(usb_id, + MIC_ISO_EP_IN | USB_DIR_IN, + USB_ENDPOINT_XFER_ISOC, + 1, ep_buffer, mic_frame_len); + + mic_transfer(usb_device, MIC_ISO_EP_IN); +} +static void close_mic(struct usb_device_t *usb_device) +{ + log_info("%s", __func__); + const usb_dev usb_id = usb_device2id(usb_device); + usb_clr_intr_txe(usb_id, MIC_ISO_EP_IN); + usb_g_set_intr_hander(usb_id, MIC_ISO_EP_IN | USB_DIR_IN, NULL); + uac_mic_stream_close(); +} +static u32 mic_as_itf_hander(struct usb_device_t *usb_device, struct usb_ctrlrequest *setup) +{ + const usb_dev usb_id = usb_device2id(usb_device); + u8 *tx_payload = usb_get_setup_buffer(usb_device); + u32 tx_len; + u32 bRequestType = setup->bRequestType & USB_TYPE_MASK; + u32 ret = 0; + + switch (setup->bRequest) { + case USB_REQ_SET_INTERFACE: + if (usb_device->bDeviceStates == USB_DEFAULT) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_ADDRESS) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_CONFIGURED) { +#if USB_ROOT2 + if (!usb_root2_testing()) { + SetInterface_0_Lock = 1; + } + if (SetInterface_0_Lock == 0) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else { + usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP); + if (setup->wValue == 1) {//alt 1 + open_mic(usb_device); + } else if (setup->wValue == 0) { //alt 0 + close_mic(usb_device); + } else { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } + } +#else + usb_set_setup_phase(usb_device, USB_EP0_STAGE_SETUP); + if (setup->wValue == 1) {//alt 1 + open_mic(usb_device); + } else if (setup->wValue == 0) { //alt 0 + close_mic(usb_device); + } else { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } +#endif + } + break; + case USB_REQ_GET_INTERFACE: + if (usb_root2_testing()) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else { + if (setup->wLength) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_DEFAULT) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_ADDRESS) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_CONFIGURED) { + tx_len = 1; + tx_payload[0] = 0x00; + usb_set_data_payload(usb_device, setup, tx_payload, tx_len); + } + } + break; + case USB_REQ_GET_STATUS: + if (usb_device->bDeviceStates == USB_DEFAULT) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else if (usb_device->bDeviceStates == USB_ADDRESS) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } else { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + } + break; + default: + break; + } + return ret; +} +void spk_reset(struct usb_device_t *usb_device, u32 ift_num) +{ + const usb_dev usb_id = usb_device2id(usb_device); + log_debug("%s", __func__); +#if USB_ROOT2 + usb_disable_ep(usb_id, SPK_ISO_EP_OUT); + /* uac_release(usb_id); */ +#else + u8 *ep_buffer; + ep_buffer = usb_get_ep_buffer(usb_id, SPK_ISO_EP_OUT); + usb_g_ep_config(usb_id, SPK_ISO_EP_OUT | USB_DIR_OUT, USB_ENDPOINT_XFER_ISOC, 1, ep_buffer, SPK_FRAME_LEN); +#endif +} +u32 uac_spk_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num) +{ + int i = 0; + u8 *tptr = ptr; + u32 offset; + u32 frame_len; + + log_debug("spkdc:%d\n", *cur_itf_num); + memcpy(tptr, (u8 *)uac_ac_standard_interface_desc, sizeof(uac_ac_standard_interface_desc)); + tptr[2] = *cur_itf_num; + tptr += sizeof(uac_ac_standard_interface_desc);//0x09 + + memcpy(tptr, (u8 *)uac_spk_ac_interface, sizeof(uac_spk_ac_interface)); +#if SPK_CHANNEL == 1 + tptr[5]--; +#endif + tptr[8] = *cur_itf_num + 1; + tptr += sizeof(uac_spk_ac_interface);//0x09 + + memcpy(tptr, (u8 *)uac_spk_input_terminal_desc, sizeof(uac_spk_input_terminal_desc)); + tptr += sizeof(uac_spk_input_terminal_desc);//0x0c + + memcpy(tptr, (u8 *)uac_spk_feature_desc, sizeof(uac_spk_feature_desc)); + tptr += sizeof(uac_spk_feature_desc);//0x0a + + memcpy(tptr, (u8 *)uac_spk_output_terminal_desc, sizeof(uac_spk_output_terminal_desc)); + tptr += sizeof(uac_spk_output_terminal_desc);//0x09 + + memcpy(tptr, (u8 *)uac_spk_as_interface_desc, sizeof(uac_spk_as_interface_desc)); + tptr[2] = *cur_itf_num + 1; + tptr[9 + 2] = *cur_itf_num + 1; + frame_len = SPK_AUDIO_RATE * (SPK_AUDIO_RES / 8) * SPK_CHANNEL / 1000; + frame_len += (SPK_AUDIO_RATE % 1000 ? (SPK_AUDIO_RES / 8) * SPK_CHANNEL : 0); + offset = 9 + 9 + 7 + 11 + 4; + //MaxPacketSize of spk iso out + tptr[offset] = LOBYTE(frame_len); + tptr[offset + 1] = HIBYTE(frame_len); + tptr += sizeof(uac_spk_as_interface_desc);//0x09+0x09+0x07+0x0b+0x09+0x07 + + if (usb_set_interface_hander(usb_id, *cur_itf_num, audio_ac_itf_handler) != *cur_itf_num) { + ASSERT(0, "uac spk set interface_hander fail"); + } + if (usb_set_reset_hander(usb_id, *cur_itf_num, spk_reset) != *cur_itf_num) { + + } + (*cur_itf_num) ++; + if (usb_set_interface_hander(usb_id, *cur_itf_num, spk_as_itf_hander) != *cur_itf_num) { + ASSERT(0, "uac spk set interface_hander fail"); + } + + (*cur_itf_num) ++; + + i = tptr - ptr; + return i; +} +void mic_reset(struct usb_device_t *usb_device, u32 ift_num) +{ + const usb_dev usb_id = usb_device2id(usb_device); + log_error("%s", __func__); +#if USB_ROOT2 + usb_disable_ep(usb_id, SPK_ISO_EP_OUT); + /* uac_release(usb_id); */ +#else + u8 *ep_buffer; + ep_buffer = usb_get_ep_buffer(usb_id, MIC_ISO_EP_IN | USB_DIR_IN); + usb_g_ep_config(usb_id, MIC_ISO_EP_IN | USB_DIR_IN, USB_ENDPOINT_XFER_ISOC, 1, ep_buffer, MIC_FRAME_LEN); +#endif +} +u32 uac_mic_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num) +{ + int i = 0; + u8 *tptr = ptr; + u32 offset; + u32 frame_len; + + log_debug("micdc:%d\n", *cur_itf_num); + + memcpy(tptr, (u8 *)uac_ac_standard_interface_desc, sizeof(uac_ac_standard_interface_desc)); + tptr[2] = *cur_itf_num; + tptr[8] = MIC_STR_INDEX; + tptr += sizeof(uac_ac_standard_interface_desc);//0x09 + + memcpy(tptr, uac_mic_ac_interface, sizeof(uac_mic_ac_interface)); +#if MIC_CHANNEL == 2 + tptr[5]++; +#endif + tptr[8] = *cur_itf_num + 1; + tptr += sizeof(uac_mic_ac_interface); + + memcpy(tptr, (u8 *)uac_mic_input_terminal_desc, sizeof(uac_mic_input_terminal_desc)); + tptr += sizeof(uac_mic_input_terminal_desc);//0x09 + + memcpy(tptr, (u8 *)uac_mic_output_terminal_desc, sizeof(uac_mic_output_terminal_desc)); + tptr += sizeof(uac_mic_output_terminal_desc);//0x09 + + memcpy(tptr, (u8 *)uac_mic_selector_uint_desc, sizeof(uac_mic_selector_uint_desc)); + tptr += sizeof(uac_mic_selector_uint_desc); + + memcpy(tptr, (u8 *)uac_mic_feature_desc, sizeof(uac_mic_feature_desc)); + tptr += sizeof(uac_mic_feature_desc);//0x09 + + + + memcpy(tptr, (u8 *)uac_mic_as_interface_desc, sizeof(uac_mic_as_interface_desc)); + tptr[2] = *cur_itf_num + 1; + tptr[9 + 2] = *cur_itf_num + 1; +#if MIC_SamplingFrequency > 1 + u32 sr = 0; + //find the max sample rate + if (sr < MIC_AUDIO_RATE_1) { + sr = MIC_AUDIO_RATE_1; + } + if (sr < MIC_AUDIO_RATE_2) { + sr = MIC_AUDIO_RATE_2; + } + if (sr < MIC_AUDIO_RATE) { + sr = MIC_AUDIO_RATE; + } + if (sr < MIC_AUDIO_RATE_4) { + sr = MIC_AUDIO_RATE_4; + } + frame_len = sr * (MIC_AUDIO_RES / 8) * MIC_CHANNEL / 1000; + frame_len += (sr % 1000 ? (MIC_AUDIO_RES / 8) * MIC_CHANNEL : 0); +#else + frame_len = MIC_AUDIO_RATE * (MIC_AUDIO_RES / 8) * MIC_CHANNEL / 1000; + frame_len += (MIC_AUDIO_RATE % 1000 ? (MIC_AUDIO_RES / 8) * MIC_CHANNEL : 0); +#endif + offset = 9 + 9 + 7 + (8 + 3 * MIC_SamplingFrequency) + 4; + //MaxPacketSize of mic iso in + tptr[offset] = LOBYTE(frame_len); + tptr[offset + 1] = HIBYTE(frame_len); + tptr += sizeof(uac_mic_as_interface_desc);//0x09 + + if (usb_set_interface_hander(usb_id, *cur_itf_num, audio_ac_itf_handler) != *cur_itf_num) { + ASSERT(0, "uac mic set interface_hander fail"); + } + if (usb_set_reset_hander(usb_id, *cur_itf_num, mic_reset) != *cur_itf_num) { + + } + (*cur_itf_num) ++; + if (usb_set_interface_hander(usb_id, *cur_itf_num, mic_as_itf_hander) != *cur_itf_num) { + ASSERT(0, "uac mic set interface_hander fail"); + } + + (*cur_itf_num) ++; + i = tptr - ptr; + return i; +} +void audio_reset(struct usb_device_t *usb_device, u32 ift_num) +{ + const usb_dev usb_id = usb_device2id(usb_device); + log_debug("%s", __func__); +#if USB_ROOT2 + usb_disable_ep(usb_id, SPK_ISO_EP_OUT); + /* uac_release(usb_id); */ +#else + u8 *ep_buffer; + ep_buffer = usb_get_ep_buffer(usb_id, SPK_ISO_EP_OUT); + usb_g_ep_config(usb_id, SPK_ISO_EP_OUT | USB_DIR_OUT, USB_ENDPOINT_XFER_ISOC, 1, ep_buffer, SPK_FRAME_LEN); + + ep_buffer = usb_get_ep_buffer(usb_id, MIC_ISO_EP_IN | USB_DIR_IN); + usb_g_ep_config(usb_id, MIC_ISO_EP_IN | USB_DIR_IN, USB_ENDPOINT_XFER_ISOC, 1, ep_buffer, MIC_FRAME_LEN); +#endif +} +u32 uac_audio_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num) +{ + int i = 0; + u8 *tptr = ptr; + u32 offset; + u32 frame_len; + + memcpy(tptr, (u8 *)uac_audio_interface_association, sizeof(uac_audio_interface_association)); + tptr[2] = *cur_itf_num; + tptr[3] = 3; + tptr += sizeof(uac_audio_interface_association);//0x09 + + memcpy(tptr, (u8 *)uac_ac_standard_interface_desc, sizeof(uac_ac_standard_interface_desc)); + tptr[2] = *cur_itf_num; + tptr += sizeof(uac_ac_standard_interface_desc);//0x09 + + memcpy(tptr, (u8 *)uac_audio_ac_interface, sizeof(uac_audio_ac_interface)); +#if SPK_CHANNEL == 1 + tptr[5]--; +#endif +#if MIC_CHANNEL == 2 + tptr[5]++; +#endif + tptr[8] = *cur_itf_num + 1; + tptr[9] = *cur_itf_num + 2; + tptr += sizeof(uac_audio_ac_interface);//0x09 + + memcpy(tptr, (u8 *)uac_spk_input_terminal_desc, sizeof(uac_spk_input_terminal_desc)); + tptr += sizeof(uac_spk_input_terminal_desc);//0x09 + + memcpy(tptr, (u8 *)uac_mic_input_terminal_desc, sizeof(uac_mic_input_terminal_desc)); + tptr += sizeof(uac_mic_input_terminal_desc);//0x09 + + memcpy(tptr, (u8 *)uac_spk_output_terminal_desc, sizeof(uac_spk_output_terminal_desc)); + tptr += sizeof(uac_spk_output_terminal_desc);//0x09 + + memcpy(tptr, (u8 *)uac_mic_output_terminal_desc, sizeof(uac_mic_output_terminal_desc)); + tptr += sizeof(uac_mic_output_terminal_desc);//0x09 + + memcpy(tptr, (u8 *)uac_mic_selector_uint_desc, sizeof(uac_mic_selector_uint_desc)); + tptr += sizeof(uac_mic_selector_uint_desc); + + memcpy(tptr, (u8 *)uac_spk_feature_desc, sizeof(uac_spk_feature_desc)); + tptr += sizeof(uac_spk_feature_desc);//0x09 + + memcpy(tptr, (u8 *)uac_mic_feature_desc, sizeof(uac_mic_feature_desc)); + tptr += sizeof(uac_mic_feature_desc);//0x09 + + + memcpy(tptr, (u8 *)uac_spk_as_interface_desc, sizeof(uac_spk_as_interface_desc)); + tptr[2] = *cur_itf_num + 1; + tptr[9 + 2] = *cur_itf_num + 1; + frame_len = SPK_AUDIO_RATE * (SPK_AUDIO_RES / 8) * SPK_CHANNEL / 1000; + frame_len += (SPK_AUDIO_RATE % 1000 ? (SPK_AUDIO_RES / 8) * SPK_CHANNEL : 0); + offset = 9 + 9 + 7 + 11 + 4; + //MaxPacketSize of spk iso out + tptr[offset] = LOBYTE(frame_len); + tptr[offset + 1] = HIBYTE(frame_len); + tptr += sizeof(uac_spk_as_interface_desc);//0x09 + + memcpy(tptr, (u8 *)uac_mic_as_interface_desc, sizeof(uac_mic_as_interface_desc)); + tptr[2] = *cur_itf_num + 2; + tptr[9 + 2] = *cur_itf_num + 2; +#if MIC_SamplingFrequency > 1 + u32 sr = 0; + //find the max sample rate + if (sr < MIC_AUDIO_RATE_1) { + sr = MIC_AUDIO_RATE_1; + } + if (sr < MIC_AUDIO_RATE_2) { + sr = MIC_AUDIO_RATE_2; + } + if (sr < MIC_AUDIO_RATE) { + sr = MIC_AUDIO_RATE; + } + if (sr < MIC_AUDIO_RATE_4) { + sr = MIC_AUDIO_RATE_4; + } + frame_len = sr * (MIC_AUDIO_RES / 8) * MIC_CHANNEL / 1000; + frame_len += (sr % 1000 ? (MIC_AUDIO_RES / 8) * MIC_CHANNEL : 0); +#else + frame_len = MIC_AUDIO_RATE * (MIC_AUDIO_RES / 8) * MIC_CHANNEL / 1000; + frame_len += (MIC_AUDIO_RATE % 1000 ? (MIC_AUDIO_RES / 8) * MIC_CHANNEL : 0); +#endif + offset = 9 + 9 + 7 + (8 + 3 * MIC_SamplingFrequency) + 4; + //MaxPacketSize of mic iso in + tptr[offset] = LOBYTE(frame_len); + tptr[offset + 1] = HIBYTE(frame_len); + tptr += sizeof(uac_mic_as_interface_desc);//0x09 + + log_debug("audio control interface num:%d\n", *cur_itf_num); + if (usb_set_interface_hander(usb_id, *cur_itf_num, audio_ac_itf_handler) != *cur_itf_num) { + ASSERT(0, "uac spk set interface_hander fail"); + } + + if (usb_set_reset_hander(usb_id, *cur_itf_num, audio_reset) != *cur_itf_num) { + + } + (*cur_itf_num) ++; + log_debug("speaker stream interface num:%d\n", *cur_itf_num); + if (usb_set_interface_hander(usb_id, *cur_itf_num, spk_as_itf_hander) != *cur_itf_num) { + ASSERT(0, "uac spk set interface_hander fail"); + } + + (*cur_itf_num) ++; + log_debug("mic stream interface num:%d\n", *cur_itf_num); + if (usb_set_interface_hander(usb_id, *cur_itf_num, mic_as_itf_hander) != *cur_itf_num) { + ASSERT(0, "uac mic set interface_hander fail"); + } + + (*cur_itf_num) ++; + + i = tptr - ptr; + return i; +} +u32 uac_register() +{ + if (uac_info == NULL) { +#if USB_MALLOC_ENABLE + uac_info = (struct uac_info_t *)malloc(sizeof(struct uac_info_t)); + if (uac_info == NULL) { + printf("uac_register err\n"); + return -1; + } +#else + memset(&_uac_info, 0, sizeof(struct uac_info_t)); + uac_info = &_uac_info; +#endif + } + uac_info->spk_def_vol = vol_convert(uac_get_spk_vol()); + uac_info->spk_left_vol = uac_info->spk_def_vol; + uac_info->spk_right_vol = uac_info->spk_def_vol; + uac_info->spk_max_vol = vol_convert(100); + uac_info->spk_min_vol = vol_convert(0); + uac_info->spk_vol_res = 0x30; + uac_info->spk_mute = 0; + + uac_info->mic_max_vol = vol_convert(100); + uac_info->mic_min_vol = vol_convert(0); + uac_info->mic_vol_res = 0x30; + uac_info->mic_def_vol = vol_convert(13 / 14.0 * 100); + uac_info->mic_vol = uac_info->mic_def_vol; + uac_info->mic_mute = 0; + return 0; +} +void uac_release(const usb_dev usb_id) +{ + struct usb_device_t *usb_device = usb_id2device(usb_id); + + if (uac_info) { + close_spk(usb_device); + close_mic(usb_device); +#if USB_MALLOC_ENABLE + free(uac_info); +#endif + uac_info = NULL; + } +} +#endif diff --git a/apps/common/usb/device/uac_stream.c b/apps/common/usb/device/uac_stream.c new file mode 100644 index 0000000..31c8624 --- /dev/null +++ b/apps/common/usb/device/uac_stream.c @@ -0,0 +1,454 @@ +#include "app_config.h" +#include "system/includes.h" +#include "printf.h" +#include "usb/usb_config.h" +#include "usb/device/usb_stack.h" + +#if TCFG_USB_SLAVE_AUDIO_ENABLE +#include "usb/device/uac_audio.h" +#include "uac_stream.h" +#include "audio_config.h" + +#ifdef CONFIG_MEDIA_DEVELOP_ENABLE +#include "audio_track.h" +#endif + + +#define LOG_TAG_CONST USB +#define LOG_TAG "[UAC]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#define UAC_DEBUG_ECHO_MODE 0 + +static volatile u8 speaker_stream_is_open = 0; +struct uac_speaker_handle { + cbuffer_t cbuf; + volatile u8 need_resume; + u8 channel; + u8 alive; + void *buffer; + void *audio_track; + void (*rx_handler)(int, void *, int); +}; + +#if (SOUNDCARD_ENABLE) +#define UAC_BUFFER_SIZE (4 * 1024) +#else +#define UAC_BUFFER_SIZE (2 * 1024) +#endif + +#define UAC_BUFFER_MAX (UAC_BUFFER_SIZE * 50 / 100) + +static struct uac_speaker_handle *uac_speaker = NULL; + +#if USB_MALLOC_ENABLE +#else +static struct uac_speaker_handle uac_speaker_handle SEC(.uac_var); +static u8 uac_rx_buffer[UAC_BUFFER_SIZE] ALIGNED(4) SEC(.uac_rx); +#endif +u32 uac_speaker_stream_length() +{ + return UAC_BUFFER_SIZE; +} +u32 uac_speaker_stream_size() +{ + if (!speaker_stream_is_open) { + return 0; + } + + if (uac_speaker) { + return cbuf_get_data_size(&uac_speaker->cbuf); + } + + return 0; +} + +u32 uac_speaker_get_alive() +{ + if (uac_speaker) { + return uac_speaker->alive; + } + return 0; +} +void uac_speaker_set_alive(u8 alive) +{ + local_irq_disable(); + if (uac_speaker) { + uac_speaker->alive = alive; + } + local_irq_enable(); +} + +void uac_speaker_stream_buf_clear(void) +{ + if (speaker_stream_is_open) { + cbuf_clear(&uac_speaker->cbuf); + } +} + +void set_uac_speaker_rx_handler(void *priv, void (*rx_handler)(int, void *, int)) +{ + if (uac_speaker) { + uac_speaker->rx_handler = rx_handler; + } +} + +int uac_speaker_stream_sample_rate(void) +{ +#ifdef CONFIG_MEDIA_DEVELOP_ENABLE + if (uac_speaker && uac_speaker->audio_track) { + int sr = audio_local_sample_track_rate(uac_speaker->audio_track); + if ((sr < (SPK_AUDIO_RATE + 500)) && (sr > (SPK_AUDIO_RATE - 500))) { + return sr; + } + /* printf("uac audio_track reset \n"); */ + local_irq_disable(); + audio_local_sample_track_close(uac_speaker->audio_track); + uac_speaker->audio_track = audio_local_sample_track_open(SPK_CHANNEL, SPK_AUDIO_RATE, 1000); + local_irq_enable(); + } +#endif + return SPK_AUDIO_RATE; +} + +void uac_speaker_stream_write(const u8 *obuf, u32 len) +{ + if (speaker_stream_is_open) { + //write dac +#ifdef CONFIG_MEDIA_DEVELOP_ENABLE + if (uac_speaker->audio_track) { + audio_local_sample_track_in_period(uac_speaker->audio_track, (len >> 1) / uac_speaker->channel); + } +#endif + int wlen = cbuf_write(&uac_speaker->cbuf, (void *)obuf, len); + if (wlen != len) { + putchar('W'); + } + if (uac_speaker->rx_handler) { + /* if (uac_speaker->cbuf.data_len >= UAC_BUFFER_MAX) { */ + // 马上就要满了,赶紧取走 + uac_speaker->need_resume = 1; //2020-12-22注:无需唤醒 + /* } */ + if (uac_speaker->need_resume) { + uac_speaker->need_resume = 0; + uac_speaker->rx_handler(0, (void *)obuf, len); + } + } + uac_speaker->alive = 0; + } +} + +int uac_speaker_read(void *priv, void *data, u32 len) +{ + int r_len; + int err = 0; + + local_irq_disable(); + if (!speaker_stream_is_open) { + local_irq_enable(); + return 0; + } + + r_len = cbuf_get_data_size(&uac_speaker->cbuf); + if (r_len) { + r_len = r_len > len ? len : r_len; + r_len = cbuf_read(&uac_speaker->cbuf, data, r_len); + if (!r_len) { + putchar('U'); + } + } + + if (r_len == 0) { + uac_speaker->need_resume = 1; + } + local_irq_enable(); + return r_len; +} + +void uac_speaker_stream_open(u32 samplerate, u32 ch) +{ + if (speaker_stream_is_open) { + return; + } + log_info("%s", __func__); + + if (!uac_speaker) { +#if USB_MALLOC_ENABLE + + uac_speaker = zalloc(sizeof(struct uac_speaker_handle)); + if (!uac_speaker) { + return; + } + + uac_speaker->buffer = malloc(UAC_BUFFER_SIZE); + if (!uac_speaker->buffer) { + free(uac_speaker); + uac_speaker = NULL; + goto __err; + } + + +#else + + uac_speaker = &uac_speaker_handle; + + memset(uac_speaker, 0, sizeof(struct uac_speaker_handle)); + + uac_speaker->buffer = uac_rx_buffer; +#endif + uac_speaker->channel = ch; +#ifdef CONFIG_MEDIA_DEVELOP_ENABLE + uac_speaker->audio_track = audio_local_sample_track_open(ch, samplerate, 1000); +#endif + } + + + uac_speaker->rx_handler = NULL; + + cbuf_init(&uac_speaker->cbuf, uac_speaker->buffer, UAC_BUFFER_SIZE); + speaker_stream_is_open = 1; + struct sys_event event; + event.type = SYS_DEVICE_EVENT; + event.arg = (void *)DEVICE_EVENT_FROM_UAC; + event.u.dev.event = USB_AUDIO_PLAY_OPEN; + event.u.dev.value = (int)((ch << 24) | samplerate); + +#if !UAC_DEBUG_ECHO_MODE + sys_event_notify(&event); +#endif + + return; + +__err: + return; +} + +void uac_speaker_stream_close() +{ + if (speaker_stream_is_open == 0) { + return; + } + + log_info("%s", __func__); + speaker_stream_is_open = 0; + + if (uac_speaker) { +#ifdef CONFIG_MEDIA_DEVELOP_ENABLE + audio_local_sample_track_close(uac_speaker->audio_track); +#endif + uac_speaker->audio_track = NULL; +#if USB_MALLOC_ENABLE + if (uac_speaker->buffer) { + free(uac_speaker->buffer); + } + free(uac_speaker); +#endif + uac_speaker = NULL; + } + struct sys_event event; + event.type = SYS_DEVICE_EVENT; + event.arg = (void *)DEVICE_EVENT_FROM_UAC; + event.u.dev.event = USB_AUDIO_PLAY_CLOSE; + event.u.dev.value = (int)0; + + sys_event_notify(&event); +} + +int uac_get_spk_vol() +{ + int max_vol = get_max_sys_vol(); + int vol = app_audio_get_volume(APP_AUDIO_STATE_MUSIC); + if (vol * 100 / max_vol < 100) { + return vol * 100 / max_vol; + } else { + return 99; + } + return 0; +} +static u32 mic_stream_is_open; +void uac_mute_volume(u32 type, u32 l_vol, u32 r_vol) +{ + struct sys_event event; + event.type = SYS_DEVICE_EVENT; + event.arg = (void *)DEVICE_EVENT_FROM_UAC; + + static u32 last_spk_l_vol = (u32) - 1, last_spk_r_vol = (u32) - 1; + static u32 last_mic_vol = (u32) - 1; + + switch (type) { + case MIC_FEATURE_UNIT_ID: //MIC + if (mic_stream_is_open == 0) { + return ; + } + if (l_vol == last_mic_vol) { + return; + } + last_mic_vol = l_vol; + event.u.dev.event = USB_AUDIO_SET_MIC_VOL; + break; + case SPK_FEATURE_UNIT_ID: //SPK + if (speaker_stream_is_open == 0) { + return; + } + if (l_vol == last_spk_l_vol && r_vol == last_spk_r_vol) { + return; + } + last_spk_l_vol = l_vol; + last_spk_r_vol = r_vol; + event.u.dev.event = USB_AUDIO_SET_PLAY_VOL; + break; + default: + break; + } + + event.u.dev.value = (int)(r_vol << 16 | l_vol); + sys_event_notify(&event); +} + + +static int (*mic_tx_handler)(int, void *, int) SEC(.uac_rx); +int uac_mic_stream_read(u8 *buf, u32 len) +{ + if (mic_stream_is_open == 0) { + return 0; + } +#if 0//48K 1ksin + const s16 sin_48k[] = { + 0, 2139, 4240, 6270, 8192, 9974, 11585, 12998, + 14189, 15137, 15826, 16244, 16384, 16244, 15826, 15137, + 14189, 12998, 11585, 9974, 8192, 6270, 4240, 2139, + 0, -2139, -4240, -6270, -8192, -9974, -11585, -12998, + -14189, -15137, -15826, -16244, -16384, -16244, -15826, -15137, + -14189, -12998, -11585, -9974, -8192, -6270, -4240, -2139 + }; + u16 *l_ch = (u16 *)buf; + u16 *r_ch = (u16 *)buf; + r_ch++; + for (int i = 0; i < len / 2; i++) { + *l_ch = sin_48k[i]; + *r_ch = sin_48k[i]; + l_ch += 1; + r_ch += 1; + } + return len; +#elif UAC_DEBUG_ECHO_MODE + uac_speaker_read(NULL, buf, len); +#if MIC_CHANNEL == 2 + const s16 sin_48k[] = { + 0, 2139, 4240, 6270, 8192, 9974, 11585, 12998, + 14189, 15137, 15826, 16244, 16384, 16244, 15826, 15137, + 14189, 12998, 11585, 9974, 8192, 6270, 4240, 2139, + 0, -2139, -4240, -6270, -8192, -9974, -11585, -12998, + -14189, -15137, -15826, -16244, -16384, -16244, -15826, -15137, + -14189, -12998, -11585, -9974, -8192, -6270, -4240, -2139 + }; + u16 *r_ch = (u16 *)buf; + r_ch++; + for (int i = 0; i < len / 4; i++) { + *r_ch = sin_48k[i]; + r_ch += 2; + } +#endif + return len; +#else + if (mic_tx_handler) { +#if 1 + return mic_tx_handler(0, buf, len); +#else + //16bit ---> 24bit + int rlen = mic_tx_handler(0, tmp_buf, len / 3 * 2); + rlen /= 2; //sampe point + for (int i = 0 ; i < rlen ; i++) { + buf[i * 3] = 0; + buf[i * 3 + 1] = tmp_buf[i * 2]; + buf[i * 3 + 2] = tmp_buf[i * 2 + 1]; + } +#endif + } + return 0; +#endif + return 0; +} + +void set_uac_mic_tx_handler(void *priv, int (*tx_handler)(int, void *, int)) +{ + mic_tx_handler = tx_handler; +} + +u32 uac_mic_stream_open(u32 samplerate, u32 frame_len, u32 ch) +{ + if (mic_stream_is_open) { + return 0; + } + + mic_tx_handler = NULL; + log_info("%s", __func__); + + struct sys_event event; + event.type = SYS_DEVICE_EVENT; + event.arg = (void *)DEVICE_EVENT_FROM_UAC; + event.u.dev.event = USB_AUDIO_MIC_OPEN; + event.u.dev.value = (int)((ch << 24) | samplerate); + mic_stream_is_open = 1; + +#if !UAC_DEBUG_ECHO_MODE + sys_event_notify(&event); +#endif + return 0; +} + +void uac_mic_stream_close() +{ + if (mic_stream_is_open == 0) { + return ; + } + log_info("%s", __func__); + struct sys_event event; + event.type = SYS_DEVICE_EVENT; + event.arg = (void *)DEVICE_EVENT_FROM_UAC; + event.u.dev.event = USB_AUDIO_MIC_CLOSE; + event.u.dev.value = (int)0; + mic_stream_is_open = 0; + sys_event_notify(&event); +} + +_WEAK_ +s8 app_audio_get_volume(u8 state) +{ + return 88; +} +_WEAK_ +void usb_audio_demo_exit(void) +{ + +} +_WEAK_ +int usb_audio_demo_init(void) +{ + return 0; +} +_WEAK_ +u8 get_max_sys_vol(void) +{ + return 100; +} +_WEAK_ +void *audio_local_sample_track_open(u8 channel, int sample_rate, int period) +{ + return NULL; +} +_WEAK_ +int audio_local_sample_track_in_period(void *c, int samples) +{ + return 0; +} +_WEAK_ +void audio_local_sample_track_close(void *c) +{ +} +#endif diff --git a/apps/common/usb/device/uac_stream.h b/apps/common/usb/device/uac_stream.h new file mode 100644 index 0000000..6b64adb --- /dev/null +++ b/apps/common/usb/device/uac_stream.h @@ -0,0 +1,31 @@ +/***************************************************************** +>file name : usb_audio.h +>author : lichao +>create time : Wed 22 May 2019 10:39:35 AM CST +*****************************************************************/ +#ifndef _UAC_STREAM_H_ +#define _UAC_STREAM_H_ +#include "typedef.h" + +enum uac_event { + USB_AUDIO_PLAY_OPEN = 0x0, + USB_AUDIO_PLAY_CLOSE, + USB_AUDIO_MIC_OPEN, + USB_AUDIO_MIC_CLOSE, + // USB_AUDIO_MUTE, + USB_AUDIO_SET_PLAY_VOL, + USB_AUDIO_SET_MIC_VOL, +}; + + +void uac_speaker_stream_buf_clear(void); +u32 uac_speaker_stream_length(); +u32 uac_speaker_stream_size(); +void set_uac_speaker_rx_handler(void *priv, void (*rx_handler)(int, void *, int)); +void set_uac_mic_tx_handler(void *priv, int (*tx_handler)(int, void *, int)); +int uac_speaker_stream_sample_rate(void); + +int uac_speaker_read(void *priv, void *data, u32 len); +u32 uac_speaker_get_alive(); +void uac_speaker_set_alive(u8 alive); +#endif diff --git a/apps/common/usb/device/usb_device.c b/apps/common/usb/device/usb_device.c new file mode 100644 index 0000000..9ddcdda --- /dev/null +++ b/apps/common/usb/device/usb_device.c @@ -0,0 +1,217 @@ +#include "usb/device/usb_stack.h" +#include "usb_config.h" +#include "usb/device/msd.h" +#include "usb/scsi.h" +#include "usb/device/hid.h" +#include "usb/device/uac_audio.h" +#include "usb/device/cdc.h" +#include "irq.h" +#include "init.h" +#include "gpio.h" +#include "app_config.h" + +#define LOG_TAG_CONST USB +#define LOG_TAG "[USB]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE + +#include "debug.h" + +#if TCFG_USB_SLAVE_ENABLE + +static void usb_device_init(const usb_dev usb_id) +{ + + usb_config(usb_id); + usb_g_sie_init(usb_id); + usb_slave_init(usb_id); + usb_set_dma_raddr(usb_id, 0, usb_get_ep_buffer(usb_id, 0)); + usb_set_dma_raddr(usb_id, 1, usb_get_ep_buffer(usb_id, 0)); + usb_set_dma_raddr(usb_id, 2, usb_get_ep_buffer(usb_id, 0)); + usb_set_dma_raddr(usb_id, 3, usb_get_ep_buffer(usb_id, 0)); + usb_set_dma_raddr(usb_id, 4, usb_get_ep_buffer(usb_id, 0)); + + usb_write_intr_usbe(usb_id, INTRUSB_RESET_BABBLE | INTRUSB_SUSPEND); + usb_clr_intr_txe(usb_id, -1); + usb_clr_intr_rxe(usb_id, -1); + usb_set_intr_txe(usb_id, 0); + usb_set_intr_rxe(usb_id, 0); + usb_g_isr_reg(usb_id, 3, 0); + /* usb_sof_isr_reg(usb_id,3,0); */ + /* usb_sofie_enable(usb_id); */ + /* USB_DEBUG_PRINTF("ep0 addr %x %x\n", usb_get_dma_taddr(0), ep0_dma_buffer); */ +} +static void usb_device_hold(const usb_dev usb_id) +{ + + usb_g_hold(usb_id); + usb_release(usb_id); +} + + +static int usb_ep_conflict_check(const usb_dev usb_id); +int usb_device_mode(const usb_dev usb_id, const u32 class) +{ + /* usb_device_set_class(CLASS_CONFIG); */ + u8 class_index = 0; + if (class == 0) { + gpio_direction_input(IO_PORT_DM + 2 * usb_id); + gpio_set_pull_up(IO_PORT_DM + 2 * usb_id, 0); + gpio_set_pull_down(IO_PORT_DM + 2 * usb_id, 0); + gpio_set_die(IO_PORT_DM + 2 * usb_id, 0); + + gpio_direction_input(IO_PORT_DP + 2 * usb_id); + gpio_set_pull_up(IO_PORT_DP + 2 * usb_id, 0); + gpio_set_pull_down(IO_PORT_DP + 2 * usb_id, 0); + gpio_set_die(IO_PORT_DP + 2 * usb_id, 0); + + os_time_dly(15); + + gpio_set_die(IO_PORT_DM + 2 * usb_id, 1); + gpio_set_die(IO_PORT_DP + 2 * usb_id, 1); + +#if TCFG_USB_SLAVE_MSD_ENABLE + msd_release(usb_id); +#endif +#if TCFG_USB_SLAVE_AUDIO_ENABLE + uac_release(usb_id); +#endif +#if TCFG_USB_SLAVE_CDC_ENABLE + cdc_release(usb_id); +#endif + usb_device_hold(usb_id); + return 0; + } + + int ret = usb_ep_conflict_check(usb_id); + if (ret) { + return ret; + } + usb_add_desc_config(usb_id, MAX_INTERFACE_NUM, NULL); +#if TCFG_USB_SLAVE_MSD_ENABLE + if ((class & MASSSTORAGE_CLASS) == MASSSTORAGE_CLASS) { + log_info("add desc msd"); + usb_add_desc_config(usb_id, class_index++, msd_desc_config); + msd_register(usb_id); + } +#endif + +#if TCFG_USB_SLAVE_AUDIO_ENABLE + if ((class & AUDIO_CLASS) == AUDIO_CLASS) { + log_info("add audio desc"); + usb_add_desc_config(usb_id, class_index++, uac_audio_desc_config); + uac_register(); + } else if ((class & SPEAKER_CLASS) == SPEAKER_CLASS) { + log_info("add desc speaker"); + usb_add_desc_config(usb_id, class_index++, uac_spk_desc_config); + uac_register(); + } else if ((class & MIC_CLASS) == MIC_CLASS) { + log_info("add desc mic"); + usb_add_desc_config(usb_id, class_index++, uac_mic_desc_config); + uac_register(); + } +#endif + +#if TCFG_USB_SLAVE_HID_ENABLE + if ((class & HID_CLASS) == HID_CLASS) { + log_info("add desc std hid"); + usb_add_desc_config(usb_id, class_index++, hid_desc_config); + } +#endif + +#if TCFG_USB_SLAVE_CDC_ENABLE + if ((class & CDC_CLASS) == CDC_CLASS) { + log_info("add desc cdc"); + usb_add_desc_config(usb_id, class_index++, cdc_desc_config); + cdc_register(usb_id); + } +#endif + + usb_device_init(usb_id); + user_setup_filter_install(usb_id2device(usb_id)); + return 0; +} +/* module_initcall(usb_device_mode); */ + +static int usb_ep_conflict_check(const usb_dev usb_id) +{ + u8 usb_ep_tx_list[] = { +#if TCFG_USB_SLAVE_MSD_ENABLE + MSD_BULK_EP_IN, +#endif +#if TCFG_USB_SLAVE_HID_ENABLE + HID_EP_IN, +#endif +#if TCFG_USB_SLAVE_AUDIO_ENABLE + MIC_ISO_EP_IN, +#endif +#if TCFG_USB_SLAVE_CDC_ENABLE + CDC_DATA_EP_IN, +#if CDC_INTR_EP_ENABLE + CDC_INTR_EP_IN, +#endif +#endif + }; + u8 usb_ep_rx_list[] = { +#if TCFG_USB_SLAVE_MSD_ENABLE + MSD_BULK_EP_OUT, +#endif +#if TCFG_USB_SLAVE_HID_ENABLE + HID_EP_OUT, +#endif +#if TCFG_USB_SLAVE_AUDIO_ENABLE + SPK_ISO_EP_OUT, +#endif +#if TCFG_USB_SLAVE_CDC_ENABLE + CDC_DATA_EP_OUT, +#endif + }; + int ret = 0; + int i, j; + + for (i = 0; i < sizeof(usb_ep_tx_list) - 1; i++) { + for (j = i + 1; j < sizeof(usb_ep_tx_list); j++) { + if (usb_ep_tx_list[i] == usb_ep_tx_list[j]) { + ret = -1; + ASSERT(0, "ep%d conflict, dir in\n", usb_ep_tx_list[i]); + goto __exit; + } + } + } + for (i = 0; i < sizeof(usb_ep_rx_list) - 1; i++) { + for (j = i + 1; j < sizeof(usb_ep_rx_list); j++) { + if (usb_ep_rx_list[i] == usb_ep_rx_list[j]) { + ret = -1; + ASSERT(0, "ep%d conflict, dir out\n", usb_ep_rx_list[i]); + goto __exit; + } + } + } +__exit: + return ret; +} + +#endif + +/* + * @brief otg检测中sof初始化,不要放在TCFG_USB_SLAVE_ENABLE里 + * @parm id usb设备号 + * @return null + */ +void usb_otg_sof_check_init(const usb_dev id) +{ + u32 ep = 0; + u8 *ep_buffer = usb_get_ep_buffer(id, ep); + + usb_g_sie_init(id); + + usb_set_dma_raddr(id, ep, ep_buffer); + + for (ep = 1; ep < USB_MAX_HW_EPNUM; ep++) { + usb_disable_ep(id, ep); + } + usb_sof_clr_pnd(id); +} diff --git a/apps/common/usb/device/user_setup.c b/apps/common/usb/device/user_setup.c new file mode 100644 index 0000000..3c3ac6d --- /dev/null +++ b/apps/common/usb/device/user_setup.c @@ -0,0 +1,202 @@ +#include "usb/device/usb_stack.h" +#include "usb_config.h" +#include "usb/device/msd.h" +#include "usb/scsi.h" +#include "usb/device/hid.h" +#include "usb/device/uac_audio.h" +#include "irq.h" +#include "init.h" +#include "gpio.h" +#include "app_config.h" + +#if TCFG_USB_APPLE_DOCK_EN +#include "apple_dock/iAP.h" +#endif + +#define LOG_TAG_CONST USB +#define LOG_TAG "[USB]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#if TCFG_USB_SLAVE_ENABLE + +static const u8 user_stirng[] = { + 24, + 0x03, + 'U', 0x00, + 'S', 0x00, + 'B', 0x00, + 'A', 0x00, + 'u', 0x00, + 'd', 0x00, + 'i', 0x00, + 'o', 0x00, + '2', 0x00, + '.', 0x00, + '0', 0x00, +}; + +#if TCFG_USB_APPLE_DOCK_EN +static const u8 IAP_interface_string[] = { + 0x1c, 0x03, + //iAP Interface + 0x69, 0x00, 0x41, 0x00, 0x50, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6e, 0x00, 0x74, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x66, 0x00, 0x61, 0x00, 0x63, 0x00, 0x65, 0x00 +}; +#endif + +static u8 root2_testing; +u32 usb_root2_testing() +{ +#if USB_ROOT2 + return root2_testing; +#else + return 0; +#endif +} +u32 check_ep_vaild(u32 ep) +{ + u32 en = 0; + switch (ep) { + case 0: + en = 1; + break; +#if TCFG_USB_SLAVE_MSD_ENABLE + case 1: + en = 1; + break; +#endif +#if TCFG_USB_SLAVE_HID_ENABLE + case 2: + en = 1; + break; +#endif +#if TCFG_USB_SLAVE_AUDIO_ENABLE + case 3: + en = 1; + break; +#endif + case 4: + break; + } + return en; +} +static u32 setup_endpoint(struct usb_device_t *usb_device, struct usb_ctrlrequest *req) +{ + const usb_dev usb_id = usb_device2id(usb_device); + u32 tx_len = 0; + u8 *tx_payload = usb_get_setup_buffer(usb_device); + +#if TCFG_USB_SLAVE_AUDIO_ENABLE + if (uac_setup_endpoint(usb_device, req)) { + return 1; + } +#endif + u32 ep = LOBYTE(req->wIndex) & 0x0f; + if (check_ep_vaild(ep) == 0) { + usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); + return 1;// not zero user handle this request + } + + + return 0; +} +static u32 setup_device(struct usb_device_t *usb_device, struct usb_ctrlrequest *req) +{ + const usb_dev usb_id = usb_device2id(usb_device); + u32 ret = 0; + switch (req->bRequest) { + case USB_REQ_GET_DESCRIPTOR: + switch (HIBYTE(req->wValue)) { + case USB_DT_STRING: + switch (LOBYTE(req->wValue)) { +#if TCFG_USB_SLAVE_AUDIO_ENABLE + case SPEAKER_STR_INDEX: + case MIC_STR_INDEX: + if (usb_device->bDeviceStates == USB_DEFAULT) { + ret = 0; + } else { + usb_set_data_payload(usb_device, req, user_stirng, sizeof(user_stirng)); + ret = 1; + } + break; +#endif +#if TCFG_USB_APPLE_DOCK_EN + case MSD_STR_INDEX: + if (apple_mfi_chip_online_lib()) { + y_printf("MSD_STR_INDEX \n"); + usb_set_data_payload(usb_device, req, IAP_interface_string, sizeof(IAP_interface_string)); + apple_mfi_pass_ready_set_api(); + extern void apple_usb_msd_wakeup(struct usb_device_t *usb_device); + apple_usb_msd_wakeup(usb_device); + ret = 1; + break; + } +#endif + default: + break; + } + break; + case USB_DT_DEVICE: +#if USB_ROOT2 + if (req->wLength == 0xffff) { + root2_testing = 1; + } +#endif + break; + } + break; + case USB_REQ_SET_CONFIGURATION: + break; + case USB_REQ_SET_ADDRESS: + /* if(req->wLength || req->wIndex){ */ + /* ret = 1; */ + /* usb_set_setup_phase(usb_device, USB_EP0_SET_STALL); */ + /* dump_setup_request(req); */ + /* log_debug_hexdump((u8 *)req, 8); */ + /* } */ + break; + } + return ret; +} +static u32 user_setup_filter(struct usb_device_t *usb_device, struct usb_ctrlrequest *request) +{ + // dump_setup_request(request); + // log_debug_hexdump((u8 *)request, 8); + u32 ret = 0; + u32 recip = request->bRequestType & USB_RECIP_MASK; + switch (recip) { + case USB_RECIP_DEVICE: + ret = setup_device(usb_device, request); + break; + case USB_RECIP_INTERFACE: + break; + case USB_RECIP_ENDPOINT: + ret = setup_endpoint(usb_device, request); + break; + case USB_RECIP_OTHER: + break; + } +#if 0 + const char *statas[] = {"USB_ATTACHED", "USB_POWERED", "USB_DEFAULT", + "USB_ADDRESS", "USB_CONFIGURED", "USB_SUSPENDED" + }; + + const char *phases[] = {"SETUP", "IN", "OUT", + "STALL", + }; + + usb_log_d("state:%s phase: %s", statas[usb_device->bDeviceStates], + phases[usb_device->bsetup_phase]); +#endif + return ret;// not zero user handle this request +} +void user_setup_filter_install(struct usb_device_t *usb_device) +{ + usb_set_setup_hook(usb_device, user_setup_filter); +} +#endif diff --git a/apps/common/usb/host/adb.c b/apps/common/usb/host/adb.c new file mode 100644 index 0000000..fa348e3 --- /dev/null +++ b/apps/common/usb/host/adb.c @@ -0,0 +1,459 @@ +#include "includes.h" +#include "asm/includes.h" +#include "system/timer.h" +#include "device/ioctl_cmds.h" +#include "usb/host/usb_host.h" +#include "usb_ctrl_transfer.h" +#include "usb_bulk_transfer.h" +#include "device_drive.h" +#include "adb.h" +#include "usb_config.h" +#include "app_config.h" +#if TCFG_ADB_ENABLE +#define LOG_TAG_CONST USB +#define LOG_TAG "[adb]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +#include "adb_rsa_key.c" + +struct adb_device_t adb; + +struct device adb_device; +void aoa_switch(struct usb_host_device *host_dev); + +static int set_adb_power(struct usb_host_device *host_dev, u32 value) +{ + return DEV_ERR_NONE; +} + +static int get_adb_power(struct usb_host_device *host_dev, u32 value) +{ + return DEV_ERR_NONE; +} + +static const struct interface_ctrl adb_ops = { + .interface_class = USB_CLASS_ADB, + .set_power = set_adb_power, + .get_power = get_adb_power, + .ioctl = NULL, +}; + +static const struct usb_interface_info adb_inf = { + .ctrl = (struct interface_ctrl *) &adb_ops, + .dev.adb = &adb, +}; + +u32 usb_adb_interface_ptp_mtp_parse(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf) +{ + struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf; + pBuf += sizeof(struct usb_interface_descriptor); + int len = 0; + const usb_dev usb_id = host_device2id(host_dev); + + for (int i = 0; i < interface->bNumEndpoints; i++) { + struct usb_endpoint_descriptor *endpoint = (struct usb_endpoint_descriptor *)pBuf; + if (endpoint->bDescriptorType == USB_DT_ENDPOINT) { + if (endpoint->bmAttributes == USB_ENDPOINT_XFER_BULK) { + if (endpoint->bEndpointAddress & USB_DIR_IN) { + adb.extr_in = endpoint->bEndpointAddress & 0xf; + } else { + adb.extr_out = endpoint->bEndpointAddress; + } + } + pBuf += USB_DT_ENDPOINT_SIZE; + } else { + return 0; + } + } + printf("%s() %x %x\n", __func__, adb.extr_in, adb.extr_out); + return pBuf - (u8 *)interface ; +} + +int usb_adb_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf) +{ + struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf; + pBuf += sizeof(struct usb_interface_descriptor); + int len = 0; + const usb_dev usb_id = host_device2id(host_dev); + + adb_device.private_data = host_dev; + + host_dev->interface_info[interface_num] = &adb_inf; + + for (int endnum = 0; endnum < interface->bNumEndpoints; endnum++) { + struct usb_endpoint_descriptor *end_desc = (struct usb_endpoint_descriptor *)pBuf; + + if (end_desc->bDescriptorType != USB_DT_ENDPOINT || + end_desc->bLength != USB_DT_ENDPOINT_SIZE) { + log_error("ep bDescriptorType = %d bLength = %d", end_desc->bDescriptorType, end_desc->bLength); + return -USB_DT_ENDPOINT; + } + + len += USB_DT_ENDPOINT_SIZE; + pBuf += USB_DT_ENDPOINT_SIZE; + + if ((end_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { + if (end_desc->bEndpointAddress & USB_DIR_IN) { + adb.host_epin = usb_get_ep_num(usb_id, USB_DIR_IN, USB_ENDPOINT_XFER_BULK); + adb.target_epin = end_desc->bEndpointAddress & 0x0f; +#if HUSB_MODE + adb.rxmaxp = end_desc->wMaxPacketSize; +#endif + log_debug("D(%d)->H(%d)", adb.target_epin, adb.host_epin); + } else { + adb.host_epout = usb_get_ep_num(usb_id, USB_DIR_OUT, USB_ENDPOINT_XFER_BULK); + adb.target_epout = end_desc->bEndpointAddress & 0x0f; +#if HUSB_MODE + adb.txmaxp = end_desc->wMaxPacketSize; +#endif + log_debug("H(%d)->D(%d)", adb.host_epout, adb.target_epout); + } + } + } + + u8 *ep_buffer = usb_h_get_ep_buffer(usb_id, adb.host_epin | USB_DIR_IN); + usb_h_ep_config(usb_id, adb.host_epin | USB_DIR_IN, USB_ENDPOINT_XFER_BULK, 0, 0, ep_buffer, 64); + + + ep_buffer = usb_h_get_ep_buffer(usb_id, adb.host_epout | USB_DIR_OUT); + usb_h_ep_config(usb_id, adb.host_epout | USB_DIR_OUT, USB_ENDPOINT_XFER_BULK, 0, 0, ep_buffer, 64); + + return len; +} + +static int adb_send_packet(struct amessage *msg, const u8 *data_ptr) +{ + if (msg == NULL) { + return usb_bulk_only_send(&adb_device, adb.host_epout, 64, adb.target_epout, NULL, 0); + } + u32 cnt; + u32 count = msg->data_length; + + msg->magic = msg->command ^ 0xffffffff; + const u8 *_data_ptr = data_ptr; + msg->data_check = 0; + while (count--) { + msg->data_check += *_data_ptr++; + } + int ret = usb_bulk_only_send(&adb_device, adb.host_epout, 64, adb.target_epout, (u8 *)msg, sizeof(*msg)); + if (ret < 0) { + return ret; + } + if (data_ptr != NULL) { + return usb_bulk_only_send(&adb_device, adb.host_epout, 64, adb.target_epout, data_ptr, msg->data_length); + } else { + return 0; + } +} +static int adb_recv(u8 *buffer, u32 len, u32 timeout) +{ + return usb_bulk_only_receive(&adb_device, adb.host_epin, 64, adb.target_epin, buffer, len); +} +#define check_usb_status(ret) do{\ + if(ret < 0){\ + log_info("%s() @ %d %d\n", __func__, __LINE__, ret);\ + return ret;\ + }\ + }while(0); + +static u8 adb_signatrue_data_index ; + +u32 adb_auth() +{ + log_info("%s() %d\n", __func__, __LINE__); + struct amessage msg; + int ret = 0; + u8 *cmd_string; + adb.local_id = 0x58525047; + adb.remote_id = 0; + msg.command = A_CNXN; + msg.arg0 = A_VERSION; + msg.arg1 = 0x00001000; + cmd_string = (u8 *)"host::"; + msg.data_length = strlen((const char *)cmd_string) + 1; + ret = adb_send_packet(&msg, cmd_string); + check_usb_status(ret); + memset(&msg, 0, 24); + ret = adb_recv((u8 *)&msg, 24, 5); + check_usb_status(ret); + + if (msg.command == A_CNXN) { + if (adb_recv(adb.buffer, msg.data_length, 1 * 100)) { + log_error("auth error 0\n"); + return 0; + } + log_info("auth not send rsa pub key\n"); + return 0; + } else if (msg.command == A_AUTH) { + + } else { + log_error("auth error 1\n"); + return 1; + } + + ret = adb_recv(adb.buffer, msg.data_length, 1 * 100); + check_usb_status(ret); + msg.command = A_AUTH; + msg.arg0 = ADB_AUTH_SIGNATURE; + msg.data_length = sizeof(adb_signatrue_data[0]); + if (adb_signatrue_data_index > 2) { + adb_signatrue_data_index = 0; + } + + adb_signatrue_data_index ++; + cmd_string = (u8 *)&adb_signatrue_data[adb_signatrue_data_index][0]; + ret = adb_send_packet(&msg, cmd_string); + check_usb_status(ret); + + ret = adb_send_packet(NULL, NULL);//zero packet + check_usb_status(ret); + + memset(&msg, 0, 24); + ret = adb_recv((u8 *)&msg, 24, 1 * 100); + check_usb_status(ret); + if (msg.command != A_AUTH) { + log_error("auth error 2\n"); + return 1; + } + ret = adb_recv(adb.buffer, msg.data_length, 1 * 100); + check_usb_status(ret); + + +__RETRY: + msg.command = A_AUTH; + msg.arg0 = ADB_AUTH_RSAPUBLICKEY; + msg.arg1 = 0; + msg.data_length = sizeof(adb_rsa_pub_key); + ret = adb_send_packet(&msg, (u8 *)adb_rsa_pub_key); + check_usb_status(ret); + + ret = adb_recv((u8 *)&msg, 24, 30 * 100); + + if (ret < 0) { + if (ret == -DEV_ERR_TIMEOUT) { + goto __RETRY; + } + check_usb_status(ret); + } + + ret = adb_recv(adb.buffer, msg.data_length, 1 * 100);//最长等待30s,等手机点击确认授权adb + if (ret < 0) { + if (ret == -DEV_ERR_TIMEOUT) { + goto __RETRY; + } + check_usb_status(ret); + } + + if (msg.command == A_AUTH) { + goto __RETRY; + } + return 0; +} + +u32 adb_shell_login() +{ + log_info("%s() %d\n", __func__, __LINE__); + struct amessage msg; + u8 *cmd_string; + /* __AUTH_SUCCESS: */ + + cmd_string = (u8 *)"shell:"; + msg.command = A_OPEN; + msg.arg0 = adb.local_id; + msg.arg1 = 0; + msg.data_length = strlen((char const *)cmd_string) + 1; + int ret = adb_send_packet(&msg, cmd_string); + check_usb_status(ret); + + memset(&msg, 0, 24); + ret = adb_recv((u8 *)&msg, 24, 1 * 100); + check_usb_status(ret); + + if (msg.command != A_OKAY) { + log_error("A_OKAY error\n"); + return 4; + } + + ret = adb_recv((u8 *)&msg, 24, 1 * 100); + check_usb_status(ret); + if (msg.command != A_WRTE) { + log_error("A_WRTE error\n"); + return 5; + } + adb.remote_id = msg.arg0; + + ret = adb_recv(adb.buffer, msg.data_length, 1 * 100); + check_usb_status(ret); + + msg.command = A_OKAY; + msg.arg0 = adb.local_id; + msg.arg1 = adb.remote_id; + msg.data_length = 0; + ret = adb_send_packet(&msg, NULL); + check_usb_status(ret); + return 0; +} + +static u32 adb_ex_cmd(const char *cmd_string, u8 *echo_buffer, u32 max_len) +{ + log_info("%s\n", cmd_string); + int ret; + struct amessage msg; + msg.command = A_WRTE; + msg.arg0 = adb.local_id; + msg.arg1 = adb.remote_id; + msg.data_length = strlen(cmd_string); + ret = adb_send_packet(&msg, (u8 *)cmd_string); + check_usb_status(ret); + memset(&msg, 0, 24); + memset(echo_buffer, 0, max_len); + ret = adb_recv((u8 *)&msg, sizeof(msg), 3 * 100); + check_usb_status(ret); + + if (msg.command != A_OKAY) { + return true; + } + u32 offset = 0; + do { + ret = adb_recv((u8 *)&msg, sizeof(msg), 3 * 100); + check_usb_status(ret); + if (msg.command != A_WRTE) { + log_info("command %x\n", msg.command); + return true; + } + if ((offset + msg.data_length) > max_len) { + log_info("%s", echo_buffer); + echo_buffer[offset] = 0; + offset = 0; + } + + ret = adb_recv(&echo_buffer[offset], msg.data_length, 3 * 100); + check_usb_status(ret); + offset += msg.data_length; + + if (msg.data_length == 0) { + log_info("no data_length\n"); + break; + } + + if (offset >= max_len) { + + } + /* echo_buffer[offset] = '\n'; */ + echo_buffer[offset] = 0; + + if (echo_buffer[offset - 2] == 0x24 && echo_buffer[offset - 1] == 0x20) { + /* puts("end\n"); */ + break; + } else if (echo_buffer[offset - 2] == 0x23 && echo_buffer[offset - 1] == 0x20) { + /* puts("end 1\n"); */ + break; + } + msg.command = A_OKAY; + msg.arg0 = adb.local_id; + msg.arg1 = adb.remote_id; + msg.data_length = 0; + ret = adb_send_packet(&msg, NULL); + check_usb_status(ret); + + } while (1); + + msg.command = A_OKAY; + msg.arg0 = adb.local_id; + msg.arg1 = adb.remote_id; + msg.data_length = 0; + /* puts("exit\n"); */ + return adb_send_packet(&msg, NULL); + +} +#define APP_ACTIVITY_PATH "com.zh-jieli.gmaeCenter/com.zh-jieli.gameCenter.activity.guide.SplashActivity\n" +#define APP_WEBSITE "http://www.zh-jieli.com\n" +#define APP_BASH_IN_PATH "/sdcard/jilei/active.bash" +#define APP_BASH_OUT_PATH "/data/local/tmp/active.bash" + +u32 adb_game_active() +{ + log_info("%s() %d\n", __func__, __LINE__); + u32 max_len = adb.max_len;; + u8 *adb_buffer = adb.buffer; + //1,启动app + adb_ex_cmd("am start -n " APP_ACTIVITY_PATH, adb_buffer, max_len); + puts((char *)adb_buffer); + //查找Error字符串,如果找到跳转网页下载app,否则执行adb指令 + if (strstr((const char *)adb_buffer, "Error") != NULL) { + adb_ex_cmd("am start -a android.intent.action.VIEW -d " APP_WEBSITE, adb_buffer, max_len); + puts((char *)adb_buffer); + } else { + adb_ex_cmd("dd if=" APP_BASH_IN_PATH " of=" APP_BASH_OUT_PATH "\n", adb_buffer, max_len); + puts((char *)adb_buffer); + adb_ex_cmd("chown shell " APP_BASH_OUT_PATH";chmod 777 "APP_BASH_OUT_PATH "\n", adb_buffer, max_len); + puts((char *)adb_buffer); + adb_ex_cmd("trap \"\" HUP;sh "APP_BASH_OUT_PATH "&\n", adb_buffer, max_len); + puts((char *)adb_buffer); + } + + return 0; +} +static void mtp_ptp_open_session(u32 is_mtp) +{ + /* usbh_bulk_send_blocking(ADB_HOST_EP, adb_device.extr_out, (u8 *)_open_session, 16); */ + /* usbh_request_bulk_blocking(ADB_HOST_EP, adb_device.extr_in, get_data_buffer(), 12, 3); */ + + /* usbh_bulk_send_blocking(ADB_HOST_EP, adb_device.extr_out, (u8 *)get_device_info, sizeof(get_device_info)); */ + /* usbh_request_bulk_blocking(ADB_HOST_EP, adb_device.extr_in, get_data_buffer(), 512, 3); */ + + /* usbh_request_bulk_blocking(ADB_HOST_EP, adb_device.extr_in, get_data_buffer(), 12, 3); */ +} + +static void adb_open_session() +{ + struct usb_host_device *host_dev = adb_device.private_data; + if (adb.extr_in && adb.extr_out) { + get_ms_extended_compat_id(host_dev, adb.buffer); + get_device_status(host_dev); + get_config_descriptor(host_dev, adb.buffer, 0xff); + /* mtp_ptp_open_session(ac6921_data_buffer[0x12] == 0x4d); */ + } +} +u32 adb_process() +{ + adb.max_len = 1024; + adb.buffer = malloc(adb.max_len); + os_time_dly(20); + do { + + adb_open_session(); + + if (adb_auth()) { + break; + } + + if (adb_shell_login()) { + break; + } + + adb_game_active(); + log_info("adb active succ"); + return 0; + + } while (0); + + free(adb.buffer); + + + log_info("adb active error"); + return 1; +} +void adb_switch_aoa(u32 id) +{ + struct usb_host_device *host_dev = adb_device.private_data; + aoa_switch(host_dev); + /* usb_host_remount(id, 3, 30, 50, 1); */ +} +#endif //TCFG_ADB_ENABLE diff --git a/apps/common/usb/host/adb.h b/apps/common/usb/host/adb.h new file mode 100644 index 0000000..26240a4 --- /dev/null +++ b/apps/common/usb/host/adb.h @@ -0,0 +1,73 @@ +#ifndef __ADB_H__ +#define __ADB_H__ + +#include "system/task.h" +#include "device/device.h" +#include "usb/scsi.h" +#include "usb_bulk_transfer.h" +#include "usb/host/usb_host.h" +struct adb_device_t { + u32 local_id; + u32 remote_id; + void *buffer; + u32 max_len; + + u8 target_epin; + u8 target_epout; + u8 host_epin; + u8 host_epout; + + u8 extr_in; + u8 extr_out; +}; +u32 usb_adb_interface_ptp_mtp_parse(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf); +int usb_adb_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf); +u32 adb_process(); +void adb_switch_aoa(u32 id); + +#if 1 +#define A_SYNC 0x434e5953 +#define A_CNXN 0x4e584e43 +#define A_OPEN 0x4e45504f +#define A_OKAY 0x59414b4f +#define A_CLSE 0x45534c43 +#define A_WRTE 0x45545257 +#define A_AUTH 0x48545541 +//#define S_ID_LOCAL 0x00003456 +/* AUTH packets first argument */ +/* Request */ +#define ADB_AUTH_TOKEN 1 +/* Response */ +#define ADB_AUTH_SIGNATURE 2 +#define ADB_AUTH_RSAPUBLICKEY 3 + +#define A_VERSION 0x01000000 // ADB protocol version + +#define ADB_VERSION_MAJOR 1 // Used for help/version information +#define ADB_VERSION_MINOR 0 // Used for help/version information + +#else +#define A_SYNC 0x53594e43 +#define A_CNXN 0x434e584e +#define A_OPEN 0x4f50454e +#define A_OKAY 0x4f4b4159 +#define A_CLSE 0x434c5345 +#define A_WRTE 0x57525445 + +#define A_VERSION 0x00000001 // ADB protocol version + +#define ADB_VERSION_MAJOR 1 // Used for help/version information +#define ADB_VERSION_MINOR 0 // Used for help/version information + +#endif + +struct amessage { + unsigned long int command; /* command identifier constant */ + unsigned long int arg0; /* first argument */ + unsigned long int arg1; /* second argument */ + unsigned long int data_length; /* length of payload (0 is allowed) */ + unsigned long int data_check; /* checksum of data payload */ + unsigned long int magic; /* command ^ 0xffffffff */ +}; + +#endif /*ADB_H*/ diff --git a/apps/common/usb/host/adb_rsa_key.c b/apps/common/usb/host/adb_rsa_key.c new file mode 100644 index 0000000..06c0170 --- /dev/null +++ b/apps/common/usb/host/adb_rsa_key.c @@ -0,0 +1,115 @@ +#include "typedef.h" +#include "app_config.h" +#if TCFG_ADB_ENABLE +static const u8 _open_session[] = { + 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 +}; +static const u8 get_device_info[] = { + 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x10, 0x01, 0x00, 0x00, 0x00, +}; + + +static const u8 adb_signatrue_data[][256] = { + { + 0xFA, 0xA6, 0xE3, 0x50, 0x3C, 0xC4, 0x95, 0xFE, 0xBB, 0x46, 0xE0, 0x9F, 0xD9, 0x9A, 0x18, 0xC1, + 0x28, 0x67, 0xA9, 0x46, 0xF8, 0x20, 0xBF, 0xDB, 0xFE, 0x6B, 0xC8, 0xC4, 0x0A, 0x09, 0xFA, 0x9A, + 0xCD, 0x51, 0xE3, 0x67, 0xD1, 0xDF, 0xD2, 0x92, 0xD3, 0x9E, 0xFA, 0x17, 0x76, 0x01, 0xF5, 0xE2, + 0xBD, 0x64, 0x9C, 0x92, 0x82, 0x4B, 0xE4, 0x27, 0x21, 0x22, 0x1A, 0x70, 0x99, 0x8F, 0xC5, 0xD5, + 0xE2, 0x02, 0x2C, 0xA4, 0x13, 0x08, 0x1E, 0x42, 0x83, 0x5C, 0x7E, 0x3C, 0x1F, 0x97, 0x1B, 0xAF, + 0x6F, 0x7E, 0x4F, 0xAB, 0xDA, 0x6A, 0x61, 0x56, 0x03, 0x79, 0xB5, 0xF0, 0x97, 0xEE, 0xEC, 0x88, + 0x6F, 0x9E, 0x8D, 0x41, 0xE2, 0x13, 0x9B, 0x21, 0xEE, 0x6F, 0x09, 0x81, 0x62, 0xC1, 0xB5, 0xE7, + 0xC2, 0x5C, 0x4A, 0x8C, 0x39, 0xAA, 0x50, 0x08, 0x48, 0xB5, 0x1D, 0xF6, 0x7C, 0x67, 0xD6, 0x39, + 0x63, 0x7E, 0x5E, 0x49, 0x3D, 0x9B, 0x49, 0x4B, 0x67, 0x8E, 0x06, 0x31, 0x07, 0x4E, 0x56, 0x8A, + 0xC4, 0x9D, 0x84, 0xA9, 0xF4, 0xFC, 0xE3, 0x2D, 0x1D, 0x2A, 0x98, 0x52, 0x40, 0x49, 0x93, 0x71, + 0xA7, 0x43, 0x0D, 0x78, 0xEB, 0xFA, 0x49, 0x7A, 0x39, 0xBF, 0xE4, 0x06, 0x08, 0x1B, 0x20, 0x84, + 0xDC, 0x64, 0xBB, 0xDE, 0x1A, 0x5E, 0x4B, 0xF8, 0x57, 0xBF, 0x9C, 0x8C, 0xB9, 0x1D, 0xEE, 0xB3, + 0x90, 0x17, 0x03, 0x8B, 0x3E, 0x9F, 0x8A, 0x23, 0xEC, 0x30, 0xA7, 0x24, 0x5E, 0x5B, 0x58, 0xAA, + 0x5A, 0xAE, 0xE2, 0x14, 0xC1, 0xAE, 0xA3, 0xF9, 0xAF, 0x70, 0xE0, 0x14, 0x7D, 0x73, 0x3B, 0x6D, + 0x9B, 0x06, 0x2F, 0xAA, 0xFF, 0x7A, 0x2A, 0x56, 0x6F, 0x91, 0x70, 0x6D, 0x4A, 0x18, 0x35, 0x51, + 0xD5, 0x5D, 0xFB, 0xA1, 0x8B, 0x03, 0xF2, 0x0C, 0x56, 0xF0, 0x5A, 0x4A, 0x08, 0x89, 0xFE, 0x86 + }, + { + 0x60, 0xE6, 0x4A, 0x3D, 0x12, 0xD1, 0x48, 0x25, 0x7D, 0x6E, 0x8E, 0x03, 0xE2, 0xC8, 0xE7, 0x66, + 0x96, 0xD7, 0xD3, 0xBF, 0xE6, 0x97, 0x13, 0x3A, 0x2D, 0x2B, 0x85, 0xE7, 0xDA, 0x5C, 0x87, 0xD8, + 0xDC, 0x88, 0xAC, 0xF7, 0xC3, 0xF0, 0x5A, 0xE8, 0x95, 0x66, 0x19, 0xA1, 0xA8, 0x2A, 0xE1, 0x70, + 0x13, 0xF0, 0x05, 0x59, 0x3D, 0x89, 0x04, 0x65, 0x08, 0x03, 0x9C, 0xDC, 0x71, 0x24, 0xC5, 0x9E, + 0x4D, 0x82, 0xD8, 0x72, 0x07, 0xFD, 0x8F, 0xD3, 0x37, 0x56, 0x8C, 0xB6, 0x01, 0xDB, 0x08, 0x5B, + 0xA3, 0x42, 0x8F, 0xF0, 0xCA, 0xDC, 0x80, 0xEB, 0x32, 0xC4, 0x67, 0x1F, 0x73, 0xAF, 0xF0, 0x56, + 0xBC, 0x89, 0x72, 0xB1, 0x7D, 0xDA, 0xA4, 0x79, 0x7D, 0x02, 0x35, 0x38, 0xBA, 0xA0, 0x36, 0xFE, + 0x5A, 0x70, 0x93, 0xF5, 0x10, 0x7A, 0x92, 0xE9, 0xD4, 0xB0, 0xED, 0xF3, 0x00, 0xD0, 0x27, 0x79, + 0x51, 0x54, 0x38, 0x2D, 0x4C, 0xAA, 0x27, 0xEF, 0xA7, 0x8A, 0x34, 0x4E, 0x4B, 0x29, 0x90, 0xC4, + 0x3E, 0xA8, 0x8D, 0x3D, 0x00, 0xD6, 0x84, 0x11, 0x17, 0x32, 0xD6, 0xE9, 0x33, 0x02, 0xCD, 0x04, + 0x35, 0x3F, 0x1A, 0xC3, 0x05, 0xCF, 0x6F, 0xF4, 0x39, 0x65, 0xE5, 0x6B, 0x88, 0x1E, 0x25, 0xA1, + 0xD7, 0xC0, 0x30, 0xE4, 0x0B, 0x2A, 0x61, 0x6D, 0x61, 0xF1, 0x93, 0xAE, 0xC3, 0x42, 0xDC, 0x15, + 0x1D, 0x87, 0x60, 0x09, 0x92, 0x64, 0xC1, 0x63, 0xAD, 0xCA, 0x36, 0x63, 0x0E, 0x69, 0x51, 0x45, + 0xD0, 0x18, 0x5E, 0x10, 0x88, 0x7B, 0xD9, 0xDE, 0xA3, 0x12, 0x85, 0xF9, 0x30, 0x01, 0x0A, 0xE1, + 0x82, 0xD1, 0x49, 0x44, 0xD9, 0x97, 0xE4, 0xF1, 0x55, 0x2D, 0xE2, 0xF3, 0x32, 0xC8, 0xA0, 0xC8, + 0x81, 0xB9, 0x02, 0x87, 0x5C, 0x19, 0xB7, 0x21, 0x6A, 0xB9, 0xB0, 0x81, 0x61, 0x8C, 0x35, 0x78 + }, + { + 0x0C, 0x7E, 0xDC, 0x78, 0x60, 0x1A, 0xC8, 0x9B, 0x3A, 0x23, 0x0B, 0x1D, 0x6F, 0xAE, 0x71, 0x6D, + 0xD8, 0x3C, 0xE9, 0xA3, 0x51, 0x90, 0xAA, 0x7B, 0x7E, 0x2F, 0x2B, 0xBD, 0x34, 0xF4, 0x43, 0x3F, + 0x77, 0xC4, 0x0E, 0x41, 0x04, 0xD9, 0xD4, 0x9C, 0xB3, 0xD2, 0x6B, 0xE1, 0xC6, 0xA8, 0xEF, 0x50, + 0x00, 0x11, 0xE1, 0x08, 0x8B, 0xB4, 0xF1, 0xE3, 0x3D, 0x56, 0x83, 0x07, 0x7F, 0xB8, 0x47, 0xF2, + 0x84, 0xD2, 0xA1, 0x50, 0x64, 0x5A, 0x08, 0x42, 0x36, 0x23, 0x09, 0x31, 0x9A, 0x6B, 0x61, 0x6F, + 0x60, 0x2C, 0xF2, 0x75, 0x4E, 0x6B, 0xB9, 0x15, 0xEE, 0x3C, 0x5E, 0xA2, 0x7F, 0xA0, 0x41, 0xFE, + 0x00, 0x6A, 0x30, 0x49, 0x2C, 0xEC, 0x17, 0x8B, 0x04, 0x32, 0xE9, 0x7A, 0x68, 0xA0, 0xF4, 0xDF, + 0x34, 0xF7, 0x1E, 0x6F, 0x19, 0x09, 0x37, 0x87, 0x99, 0xAA, 0x81, 0x1A, 0xCD, 0xF3, 0x1F, 0x89, + 0x50, 0xB2, 0x17, 0x52, 0x6D, 0x8E, 0xA6, 0x02, 0xC4, 0x2A, 0xAB, 0x3E, 0x5B, 0x38, 0x0C, 0x3F, + 0x50, 0xAA, 0x5F, 0xFE, 0x47, 0x04, 0xED, 0xCD, 0xEE, 0x7C, 0xD5, 0xED, 0x5F, 0x0E, 0xC6, 0x9C, + 0x79, 0x10, 0x11, 0x6F, 0x65, 0x58, 0x37, 0x95, 0x54, 0x50, 0x59, 0x68, 0x4C, 0x8E, 0xE7, 0x35, + 0xF0, 0x96, 0x5A, 0x21, 0x48, 0xB4, 0x53, 0x52, 0xFC, 0xA4, 0x7C, 0x2B, 0xB1, 0xE1, 0x54, 0x2C, + 0x42, 0x3B, 0x68, 0xBF, 0xBB, 0x68, 0x0D, 0x62, 0x16, 0x2F, 0xF5, 0xC8, 0x5F, 0x95, 0x11, 0xF2, + 0xDF, 0x03, 0x1E, 0xCB, 0x7C, 0xD0, 0x9C, 0xE9, 0x89, 0x62, 0xEA, 0xC5, 0x4B, 0xA9, 0xD5, 0xCC, + 0xD2, 0x42, 0x33, 0xA8, 0x7B, 0x2C, 0x56, 0xCF, 0xCE, 0x0D, 0x09, 0x64, 0x62, 0x3F, 0x58, 0x41, + 0x71, 0x79, 0x5D, 0x1D, 0xDF, 0x08, 0x0B, 0x36, 0x97, 0x16, 0x24, 0x20, 0x76, 0x9C, 0x9E, 0xEA + } +}; +static const u8 adb_rsa_pub_key[] = { + 0x51, 0x41, 0x41, 0x41, 0x41, 0x46, 0x4F, 0x56, 0x4F, 0x6E, 0x49, 0x6C, 0x69, 0x51, 0x58, 0x44, + 0x73, 0x42, 0x43, 0x42, 0x31, 0x75, 0x6F, 0x68, 0x70, 0x2B, 0x52, 0x71, 0x6E, 0x6E, 0x59, 0x48, + 0x2F, 0x75, 0x45, 0x58, 0x34, 0x59, 0x6A, 0x50, 0x71, 0x52, 0x4D, 0x35, 0x4B, 0x75, 0x62, 0x56, + 0x50, 0x71, 0x66, 0x57, 0x35, 0x64, 0x56, 0x46, 0x33, 0x2B, 0x76, 0x57, 0x6B, 0x53, 0x4B, 0x71, + 0x35, 0x4C, 0x31, 0x42, 0x4F, 0x4E, 0x4D, 0x36, 0x4B, 0x4F, 0x31, 0x69, 0x31, 0x73, 0x69, 0x4F, + 0x54, 0x69, 0x34, 0x6C, 0x45, 0x30, 0x6F, 0x54, 0x6F, 0x74, 0x30, 0x41, 0x4B, 0x6E, 0x4D, 0x67, + 0x4E, 0x6A, 0x6F, 0x33, 0x45, 0x4D, 0x65, 0x72, 0x30, 0x6C, 0x57, 0x56, 0x54, 0x54, 0x43, 0x39, + 0x68, 0x52, 0x66, 0x67, 0x46, 0x65, 0x56, 0x73, 0x43, 0x32, 0x44, 0x74, 0x71, 0x62, 0x61, 0x6D, + 0x4A, 0x48, 0x63, 0x41, 0x66, 0x59, 0x77, 0x36, 0x54, 0x62, 0x4C, 0x44, 0x6C, 0x4B, 0x70, 0x6A, + 0x38, 0x34, 0x33, 0x63, 0x31, 0x59, 0x5A, 0x65, 0x59, 0x6D, 0x52, 0x56, 0x4D, 0x7A, 0x4D, 0x34, + 0x6E, 0x74, 0x49, 0x78, 0x64, 0x56, 0x33, 0x33, 0x76, 0x4B, 0x75, 0x39, 0x38, 0x34, 0x6A, 0x72, + 0x43, 0x41, 0x47, 0x68, 0x77, 0x4A, 0x41, 0x67, 0x4A, 0x46, 0x53, 0x41, 0x4B, 0x56, 0x59, 0x51, + 0x55, 0x33, 0x6A, 0x4C, 0x76, 0x41, 0x76, 0x57, 0x45, 0x6C, 0x59, 0x47, 0x37, 0x2F, 0x4B, 0x59, + 0x6D, 0x55, 0x34, 0x54, 0x71, 0x73, 0x70, 0x64, 0x76, 0x4C, 0x42, 0x6F, 0x65, 0x36, 0x68, 0x64, + 0x46, 0x44, 0x65, 0x76, 0x4D, 0x4D, 0x43, 0x63, 0x72, 0x6C, 0x44, 0x49, 0x66, 0x65, 0x45, 0x53, + 0x57, 0x68, 0x42, 0x56, 0x35, 0x67, 0x78, 0x6A, 0x57, 0x41, 0x70, 0x4D, 0x47, 0x67, 0x53, 0x71, + 0x53, 0x45, 0x6A, 0x70, 0x36, 0x79, 0x62, 0x6A, 0x33, 0x38, 0x50, 0x4C, 0x72, 0x76, 0x49, 0x51, + 0x48, 0x77, 0x2B, 0x66, 0x70, 0x6F, 0x51, 0x74, 0x6F, 0x4F, 0x4E, 0x65, 0x37, 0x6F, 0x68, 0x66, + 0x42, 0x77, 0x45, 0x66, 0x47, 0x46, 0x4E, 0x63, 0x33, 0x61, 0x70, 0x48, 0x50, 0x6E, 0x59, 0x53, + 0x47, 0x4F, 0x67, 0x70, 0x54, 0x78, 0x70, 0x57, 0x57, 0x75, 0x49, 0x42, 0x79, 0x2F, 0x67, 0x38, + 0x35, 0x2B, 0x65, 0x54, 0x30, 0x44, 0x61, 0x36, 0x53, 0x65, 0x71, 0x33, 0x67, 0x62, 0x4A, 0x59, + 0x64, 0x75, 0x52, 0x44, 0x65, 0x36, 0x5A, 0x39, 0x63, 0x4A, 0x77, 0x48, 0x79, 0x38, 0x43, 0x34, + 0x59, 0x79, 0x6B, 0x44, 0x56, 0x45, 0x4B, 0x6A, 0x39, 0x75, 0x52, 0x41, 0x41, 0x45, 0x59, 0x70, + 0x52, 0x6B, 0x74, 0x39, 0x66, 0x34, 0x79, 0x51, 0x4A, 0x31, 0x73, 0x4D, 0x48, 0x31, 0x5A, 0x75, + 0x4F, 0x55, 0x46, 0x4A, 0x46, 0x65, 0x74, 0x6B, 0x72, 0x67, 0x32, 0x44, 0x46, 0x61, 0x35, 0x30, + 0x50, 0x39, 0x48, 0x61, 0x78, 0x6F, 0x4D, 0x59, 0x30, 0x41, 0x79, 0x78, 0x7A, 0x51, 0x72, 0x53, + 0x77, 0x4D, 0x44, 0x79, 0x6E, 0x36, 0x64, 0x49, 0x65, 0x38, 0x65, 0x58, 0x46, 0x78, 0x51, 0x62, + 0x56, 0x4D, 0x4F, 0x6C, 0x4B, 0x36, 0x79, 0x33, 0x70, 0x6F, 0x2B, 0x4A, 0x4D, 0x42, 0x34, 0x79, + 0x4D, 0x42, 0x36, 0x51, 0x77, 0x30, 0x7A, 0x31, 0x35, 0x62, 0x6F, 0x58, 0x4C, 0x78, 0x4D, 0x4B, + 0x76, 0x4E, 0x59, 0x6E, 0x4B, 0x4E, 0x70, 0x69, 0x6F, 0x33, 0x67, 0x45, 0x78, 0x5A, 0x2B, 0x48, + 0x68, 0x57, 0x62, 0x43, 0x47, 0x69, 0x37, 0x64, 0x4A, 0x6C, 0x56, 0x47, 0x50, 0x6F, 0x74, 0x34, + 0x4D, 0x42, 0x45, 0x4C, 0x7A, 0x43, 0x38, 0x66, 0x4C, 0x55, 0x44, 0x69, 0x41, 0x43, 0x49, 0x54, + 0x37, 0x75, 0x31, 0x58, 0x31, 0x62, 0x68, 0x65, 0x71, 0x6C, 0x35, 0x59, 0x7A, 0x43, 0x30, 0x6C, + 0x67, 0x2F, 0x4B, 0x48, 0x5A, 0x7A, 0x62, 0x36, 0x6D, 0x63, 0x74, 0x4E, 0x2B, 0x34, 0x62, 0x52, + 0x74, 0x79, 0x4B, 0x35, 0x75, 0x52, 0x52, 0x4A, 0x70, 0x48, 0x45, 0x56, 0x63, 0x4B, 0x58, 0x57, + 0x50, 0x34, 0x30, 0x73, 0x31, 0x79, 0x38, 0x37, 0x75, 0x30, 0x6D, 0x49, 0x50, 0x4A, 0x6E, 0x73, + 0x39, 0x6D, 0x4F, 0x2F, 0x2F, 0x44, 0x41, 0x35, 0x4C, 0x32, 0x6D, 0x64, 0x77, 0x56, 0x79, 0x73, + 0x72, 0x74, 0x4B, 0x51, 0x69, 0x51, 0x37, 0x36, 0x57, 0x6A, 0x74, 0x59, 0x51, 0x63, 0x41, 0x73, + 0x46, 0x2B, 0x42, 0x54, 0x4E, 0x56, 0x48, 0x62, 0x41, 0x6E, 0x7A, 0x7A, 0x52, 0x75, 0x6C, 0x52, + 0x61, 0x43, 0x45, 0x78, 0x2B, 0x6E, 0x30, 0x49, 0x6A, 0x35, 0x34, 0x49, 0x45, 0x41, 0x4F, 0x75, + 0x55, 0x4B, 0x70, 0x6F, 0x61, 0x48, 0x71, 0x6F, 0x56, 0x4F, 0x33, 0x51, 0x42, 0x36, 0x52, 0x41, + 0x51, 0x7A, 0x4D, 0x67, 0x70, 0x44, 0x73, 0x41, 0x30, 0x58, 0x34, 0x4C, 0x6A, 0x4F, 0x32, 0x52, + 0x2B, 0x4D, 0x4B, 0x6F, 0x6D, 0x6F, 0x6C, 0x52, 0x5A, 0x6F, 0x32, 0x34, 0x57, 0x32, 0x41, 0x35, + 0x57, 0x2B, 0x30, 0x56, 0x4A, 0x77, 0x45, 0x41, 0x41, 0x51, 0x41, 0x3D, 0x20, 0x75, 0x6E, 0x6B, + 0x6E, 0x6F, 0x77, 0x6E, 0x40, 0x75, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x00 +}; +#endif diff --git a/apps/common/usb/host/aoa.c b/apps/common/usb/host/aoa.c new file mode 100644 index 0000000..34677f9 --- /dev/null +++ b/apps/common/usb/host/aoa.c @@ -0,0 +1,232 @@ +/** + * @file aoa.c + * @brief https://source.android.com/devices/accessories/aoa + * http://www.hackermi.com/2015-04/aoa-analyse/ + * Android 开放配件协议 1.0 + * @author chenrixin@zh-jieli.com + * @version 1 + * @date 2020-03-25 + */ + +#include "includes.h" +#include "app_config.h" + +#include "usb_config.h" +#include "usb/host/usb_host.h" +#include "usb/usb_phy.h" +#include "device_drive.h" +#include "usb_ctrl_transfer.h" +#include "usb_bulk_transfer.h" +#include "usb_storage.h" +#include "adb.h" +#include "aoa.h" +#include "usb_hid_keys.h" +#if TCFG_AOA_ENABLE +#include "gamebox.h" + +#define LOG_TAG_CONST USB +#define LOG_TAG "[AOA]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +//0x2D00 有一个接口,该接口有两个批量端点,用于输入和输出通信。 +//0x2D01 有两个接口,每个接口有两个批量端点,用于输入和输出通信。 +//第一个接口处理标准通信, +//第二个接口则处理 ADB 通信。 +//要使用接口,请找到第一个批量输入和输出端点, +//使用 SET_CONFIGURATION (0x09) 设备请求将设备配置的值设为 1,然后使用端点进行通信 +// + + +static void aoa_timer_handler(void *priv); +static u32 aoa_timer_id; +static struct aoa_device_t aoa; +static struct device aoa_device; + +static int set_power(struct usb_host_device *host_dev, u32 value) +{ + if (aoa_timer_id) { + usr_timer_del(aoa_timer_id); + aoa_timer_id = 0; + } + return DEV_ERR_NONE; +} + +static int get_power(struct usb_host_device *host_dev, u32 value) +{ + return DEV_ERR_NONE; +} +static const struct interface_ctrl aoa_ctrl = { + .interface_class = USB_CLASS_AOA, + .set_power = set_power, + .get_power = get_power, + .ioctl = NULL, +}; + +static const struct usb_interface_info aoa_inf = { + .ctrl = (struct interface_ctrl *) &aoa_ctrl, + .dev.aoa = &aoa, +}; + +static const char *credetials[] = {"JieLiTec", + "GameBox", + "Android accessories devcie !", + "1.0.0", + "http://www.zh-jieli.com", + "1234567890ABCDEF", + }; + +void aoa_switch(struct usb_host_device *host_dev) +{ + u16 version; + log_info("aoa_switch"); + usb_get_aoa_version(host_dev, &version); + log_info("AOA version: %x", version); + for (int i = 0; i < 5; i++) { + log_info("send string [%d] %s", i, credetials[i]); + int r = usb_set_credentials(host_dev, credetials[i], i); + if (r < 0) { + break; + } + } + usb_switch2aoa(host_dev); +} + +int usb_aoa_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf) +{ + struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf; + pBuf += sizeof(struct usb_interface_descriptor); + int len = 0; + const usb_dev usb_id = host_device2id(host_dev); + aoa_device.private_data = host_dev; + host_dev->interface_info[interface_num] = &aoa_inf; + + for (int endnum = 0; endnum < interface->bNumEndpoints; endnum++) { + struct usb_endpoint_descriptor *end_desc = (struct usb_endpoint_descriptor *)pBuf; + + if (end_desc->bDescriptorType != USB_DT_ENDPOINT || + end_desc->bLength != USB_DT_ENDPOINT_SIZE) { + log_error("ep bDescriptorType = %d bLength = %d", end_desc->bDescriptorType, end_desc->bLength); + return -USB_DT_ENDPOINT; + } + + len += USB_DT_ENDPOINT_SIZE; + pBuf += USB_DT_ENDPOINT_SIZE; + + if ((end_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { + if (end_desc->bEndpointAddress & USB_DIR_IN) { + aoa.target_epin = end_desc->bEndpointAddress & 0x0f; +#if HUSB_MODE + aoa.rxmaxp = end_desc->wMaxPacketSize; +#endif + } else { + aoa.target_epout = end_desc->bEndpointAddress & 0x0f; +#if HUSB_MODE + aoa.txmaxp = end_desc->wMaxPacketSize; +#endif + } + } + } + + + return len; +} + +static int aoa_tx_data(const u8 *pbuf, u32 len) +{ + struct usb_host_device *host_dev = aoa_device.private_data; + usb_dev usb_id = host_device2id(host_dev); + g_printf("TX:"); + printf_buf(pbuf, len); + return usb_h_ep_write_async(usb_id, aoa.host_epout, 64, aoa.target_epout, pbuf, len, USB_ENDPOINT_XFER_BULK, 1); +} +static void aoa_epin_isr(struct usb_host_device *host_dev, u32 ep) +{ + u8 buffer[64] = {0}; + usb_dev usb_id = host_device2id(host_dev); + u32 rx_len = usb_h_ep_read_async(usb_id, ep, aoa.target_epin, buffer, sizeof(buffer), USB_ENDPOINT_XFER_BULK, 0); + g_printf("RX:"); + printf_buf(buffer, rx_len); + + usb_h_ep_read_async(usb_id, ep, aoa.target_epin, NULL, 0, USB_ENDPOINT_XFER_BULK, 1); +} + +#define Accessory_assigned_ID 0x0001 + +u32 aoa_process(u32 mode, u32 id) +{ + struct usb_host_device *host_dev = aoa_device.private_data; + struct usb_device_descriptor device_desc; + usb_get_device_descriptor(host_dev, &device_desc); + + if ((device_desc.idVendor == 0x18d1) && + ((device_desc.idProduct & 0x2d00) == 0x2d00)) { + log_info("aoa mode ready idVendor:%x idProduct: %x", + device_desc.idVendor, device_desc.idProduct); + } else { + log_info("aoa switch idVendor:%x idProduct: %x", + device_desc.idVendor, device_desc.idProduct); + + aoa_switch(host_dev); + + usb_host_remount(id, 3, 30, 50, 1); + return 0; + } + + + usb_aoa_register_hid(host_dev, Accessory_assigned_ID, sizeof(hid_report_desc)); + + u32 offset = 0; + while (offset < sizeof(hid_report_desc)) { + u32 cnt = min(sizeof(hid_report_desc) - offset, 63); + usb_aoa_set_hid_report_desc(host_dev, Accessory_assigned_ID, offset, &hid_report_desc[offset], cnt); + offset += cnt; + } + + aoa.host_epout = usb_get_ep_num(id, USB_DIR_OUT, USB_ENDPOINT_XFER_BULK); + aoa.host_epin = usb_get_ep_num(id, USB_DIR_IN, USB_ENDPOINT_XFER_BULK); + log_debug("D(%d)->H(%d)", aoa.target_epin, aoa.host_epin); + log_debug("H(%d)->D(%d)", aoa.host_epout, aoa.target_epout); + + usb_h_set_ep_isr(host_dev, aoa.host_epin | USB_DIR_IN, aoa_epin_isr, host_dev); + u8 *ep_buffer = usb_h_get_ep_buffer(id, aoa.host_epin | USB_DIR_IN); + usb_h_ep_config(id, aoa.host_epin | USB_DIR_IN, USB_ENDPOINT_XFER_BULK, 1, 0, ep_buffer, 64); + int r = usb_h_ep_read_async(id, aoa.host_epin, aoa.target_epin, NULL, 0, USB_ENDPOINT_XFER_BULK, 1); + + ep_buffer = usb_h_get_ep_buffer(id, aoa.host_epout | USB_DIR_OUT); + usb_h_ep_config(id, aoa.host_epout | USB_DIR_OUT, USB_ENDPOINT_XFER_BULK, 0, 0, ep_buffer, 64); + + aoa_timer_id = usr_timer_add((void *)0, aoa_timer_handler, 4, 0); + g_printf("aoa succ"); + + return 1; +} + + +static void aoa_timer_handler(void *priv) +{ + struct usb_host_device *host_dev = aoa_device.private_data; + + u8 tx_buffer[32]; + if (mouse_data_send == 1) { + tx_buffer[0] = MOUSE_POINT_ID; + memcpy(&tx_buffer[1], &mouse_data, sizeof(mouse_data)); + usb_aoa_send_hid_event(host_dev, Accessory_assigned_ID, tx_buffer, sizeof(mouse_data) + 1); + memset(&mouse_data, 0, sizeof(mouse_data)) ; + mouse_data_send = 0; + } + + tx_buffer[0] = TOUCH_SCREEN_ID; + struct touch_screen_t t; + memset(&t, 0, sizeof(t)); + if (point_list_pop(&t)) { + memcpy(&tx_buffer[1], &t, sizeof(t)); + usb_aoa_send_hid_event(host_dev, Accessory_assigned_ID, tx_buffer, sizeof(t) + 1); + } + +} +#endif diff --git a/apps/common/usb/host/aoa.h b/apps/common/usb/host/aoa.h new file mode 100644 index 0000000..73fa8ad --- /dev/null +++ b/apps/common/usb/host/aoa.h @@ -0,0 +1,20 @@ +#ifndef __AOA_H__ +#define __AOA_H__ + +struct aoa_device_t { + u16 version; + + u8 target_epin; + u8 target_epout; + + u8 host_epin; + u8 host_epout; + + struct adb_device_t *adb; +}; +u32 aoa_process(u32 mode, u32 id); +int usb_aoa_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf); + + + +#endif /*AOA_H*/ diff --git a/apps/common/usb/host/apple_mfi.c b/apps/common/usb/host/apple_mfi.c new file mode 100644 index 0000000..ace1c37 --- /dev/null +++ b/apps/common/usb/host/apple_mfi.c @@ -0,0 +1,121 @@ +#include "includes.h" +#include "app_config.h" +#include "device_drive.h" +/* #include "os/os_compat.h" */ +#include "usb_config.h" +#include "usb/host/usb_host.h" +#include "usb/usb_phy.h" +#include "usb_ctrl_transfer.h" +#include "usb_storage.h" +#include "usb/host/usb_host.h" +#include "usb/usb_phy.h" +#include "device_drive.h" +#include "usb_ctrl_transfer.h" +#include "usb_bulk_transfer.h" +#include "usb_storage.h" +#include "usb_hid_keys.h" +/* #include "gamebox.h" */ + +#define LOG_TAG_CONST USB +#define LOG_TAG "[MFI]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#if TCFG_USB_APPLE_DOCK_EN +#include "apple_dock/iAP.h" +#include "apple_mfi.h" + +static u8 usb_apple_descriptor_parser(struct usb_host_device *host_dev) +{ + u8 have_audio = 0; + for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) { + if (host_dev->interface_info[i]) { + switch (host_dev->interface_info[i]->ctrl->interface_class) { +#if TCFG_ADB_ENABLE + case USB_CLASS_ADB: + have_audio = 1; + break; +#endif +#if TCFG_AOA_ENABLE + case USB_CLASS_AOA: + have_audio = 1; + break; +#endif + default: + break; + } + } + } + return have_audio; +} + + +int usb_apple_mfi_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf) +{ + u32 ret = DEV_ERR_NONE; + struct usb_device_descriptor device_desc; + ret = usb_get_device_descriptor(host_dev, &device_desc); + + if (apple_mfi_chip_online_lib()) { + log_info("idV:0x%x, idP:0x%x \n", device_desc.idVendor, device_desc.idProduct); + if ((device_desc.idVendor == 0x05AC) && ((device_desc.idProduct & 0xff00) == 0x1200)) { + u8 cnt; + u8 bDescriptorNum = 0; + for (cnt = 0; cnt <= 3; cnt++) { + struct usb_config_descriptor cfg_desc; + ret = get_config_descriptor_add_value_l(host_dev, &cfg_desc, USB_DT_CONFIG_SIZE, cnt); + /* check_usb_mount(ret); */ + +#if USB_H_MALLOC_ENABLE + u8 *desc_buf = zalloc(cfg_desc.wTotalLength + 16); + ASSERT(desc_buf, "desc_buf"); +#else + u8 desc_buf[128] = {0}; + cfg_desc.wTotalLength = min(sizeof(desc_buf), cfg_desc.wTotalLength); +#endif + + ret = get_config_descriptor_add_value_l(host_dev, desc_buf, cfg_desc.wTotalLength, cnt); + /* check_usb_mount(ret); */ + + /**********set configuration*********/ + /* ret = set_configuration(host_dev); */ + + /* printf_buf(desc_buf, cfg_desc.wTotalLength); */ + /* ret |= usb_descriptor_parser(host_dev, desc_buf, cfg_desc.wTotalLength, &device_desc); */ + + bDescriptorNum = desc_buf[5]; + + u8 have_audio = 0; + have_audio = usb_apple_descriptor_parser(host_dev); + +#if USB_H_MALLOC_ENABLE + log_info("free:desc_buf= %x\n", desc_buf); + free(desc_buf); +#endif + + if (have_audio) { + break; + } + } + ret = set_configuration_add_value(host_dev, bDescriptorNum); + /* check_usb_mount(ret); */ + + usb_mdelay(20); + + ret = usb_switch2slave(host_dev); + /* check_usb_mount(ret); */ + + usb_mdelay(20); + + ret = DEV_ERR_OFFLINE; + /* break; */ + } + } + + return 0; +} +#endif diff --git a/apps/common/usb/host/apple_mfi.h b/apps/common/usb/host/apple_mfi.h new file mode 100644 index 0000000..55a54ea --- /dev/null +++ b/apps/common/usb/host/apple_mfi.h @@ -0,0 +1,8 @@ +#ifndef _APPLE_MFI_H_ +#define _APPLE_MFI_H_ + +int usb_apple_mfi_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf); + + + +#endif diff --git a/apps/common/usb/host/audio.c b/apps/common/usb/host/audio.c new file mode 100644 index 0000000..70b221c --- /dev/null +++ b/apps/common/usb/host/audio.c @@ -0,0 +1,820 @@ +#include "includes.h" +#include "asm/includes.h" +#include "app_config.h" +#include "system/timer.h" +#include "device/ioctl_cmds.h" +#include "device_drive.h" +#if TCFG_HOST_AUDIO_ENABLE +#include "usb/host/usb_host.h" +#include "usb_ctrl_transfer.h" +#include "usb_bulk_transfer.h" +#include "audio.h" +#include "usb_config.h" + +#define LOG_TAG_CONST USB +#define LOG_TAG "[AUDIO]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +/* #define USB_AUDIO_PLAY_TEST */ + +struct usb_audio_play { + u32 sample_rate; + u8 Cur_AlternateSetting; + u8 src_channel; + u8 play_state; + u8 mute; + u8 *send_buf; + u8 *usb_audio_play_buf; + u8 *usb_audio_play_buf2; + cbuffer_t usb_audio_play_cbuf; + u32 usb_audio_remain_len; + OS_SEM sem; + int (*put_buf)(void *ptr, u32 len); +}; +struct usb_audio_mic { + u8 Cur_AlternateSetting; + u32 sample_rate; + u8 record_state; + u8 *usb_audio_record_buf; + u8 *usb_audio_record_buf2; + cbuffer_t usb_audio_record_cbuf; + int *(*get_buf)(void *ptr, u32 len); +}; +struct usb_audio_info { + usb_dev usb_id; + struct usb_audio_play player; + struct usb_audio_mic microphone; +}; + +enum { + AUDIO_PLAY_IDLE = 0, + AUDIO_PLAY_START, + AUDIO_PLAY_STOP, + AUDIO_PLAY_PAUSE, +}; +enum { + AUDIO_RECORD_IDLE = 0, + AUDIO_RECORD_START, + AUDIO_RECORD_STOP, + AUDIO_RECORD_PAUSE, +}; + +#define EP_MAX_PACKET_SIZE (192) + +struct usb_audio_info _usb_audio_info = {0}; +#define __this (&_usb_audio_info) + +struct audio_device_t audio_device[USB_MAX_HW_NUM][MAX_HOST_INTERFACE]; + +static u8 ep_in_dma_buf[256] __attribute__((aligned(4))); +static u8 ep_out_dma_buf[256] __attribute__((aligned(4))); + +static int set_power(struct usb_host_device *host_dev, u32 value) +{ + const usb_dev usb_id = host_device2id(host_dev); + return DEV_ERR_NONE; +} + +static int get_power(struct usb_host_device *host_dev, u32 value) +{ + return DEV_ERR_NONE; +} + +static const struct interface_ctrl uac_ctrl = { + .interface_class = USB_CLASS_AUDIO, + .set_power = set_power, + .get_power = get_power, + .ioctl = NULL, +}; + +static const struct usb_interface_info _uac_if[USB_MAX_HW_NUM][MAX_HOST_INTERFACE] = { + { + { + .ctrl = (struct interface_ctrl *) &uac_ctrl, + .dev.audio = &audio_device[0][0], + }, + { + .ctrl = (struct interface_ctrl *) &uac_ctrl, + .dev.audio = &audio_device[0][1], + }, + { + .ctrl = (struct interface_ctrl *) &uac_ctrl, + .dev.audio = &audio_device[0][2], + }, + { + .ctrl = (struct interface_ctrl *) &uac_ctrl, + .dev.audio = &audio_device[0][3], + }, + }, +}; + +int usb_audio_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf) +{ + struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf; + const usb_dev usb_id = host_device2id(host_dev); + + const struct usb_interface_info *usb_if = &_uac_if[usb_id][interface_num]; + struct audio_streaming_t *as_t = NULL; + memset(usb_if->dev.p, 0, sizeof(struct audio_device_t)); + host_dev->interface_info[interface_num] = usb_if; + usb_if->dev.audio->parent = host_dev; + + if (interface->bInterfaceSubClass == USB_SUBCLASS_AUDIOCONTROL) { + log_info("audio control interface : %d\n", interface_num); + pBuf += sizeof(struct usb_interface_descriptor); + usb_if->dev.audio->subclass = interface->bInterfaceSubClass; + usb_if->dev.audio->interface_num = interface_num; + + return sizeof(struct usb_interface_descriptor); + } + + if (interface->bInterfaceSubClass == USB_SUBCLASS_AUDIOSTREAMING) { + usb_if->dev.audio->subclass = interface->bInterfaceSubClass; + usb_if->dev.audio->interface_num = interface_num; + if (interface->bNumEndpoints == 0) { + pBuf += sizeof(struct usb_interface_descriptor); + do { + struct usb_interface_descriptor *as_interface = (struct usb_interface_descriptor *)pBuf; + if (as_interface->bNumEndpoints == 0 || as_interface->bInterfaceClass != USB_CLASS_AUDIO) { + break; + } + log_info("audio streaming interface : %d ep_num:%d Altersetting:%d", interface_num, as_interface->bNumEndpoints, as_interface->bAlternateSetting); + as_t = &usb_if->dev.audio->as[as_interface->bAlternateSetting - 1]; + as_t->bNumEndpoints = as_interface->bNumEndpoints; + pBuf += (USB_DT_INTERFACE_SIZE + UAC_DT_AS_HEADER_SIZE); + //解析format + struct uac_format_type_i_discrete_descriptor *uac_format_desc = (struct uac_format_type_i_discrete_descriptor *)pBuf; + if (uac_format_desc->bDescriptorSubtype == UAC_FORMAT_TYPE) { + as_t->bFormatType = uac_format_desc->bFormatType; + as_t->bNrChannels = uac_format_desc->bNrChannels; + as_t->bSubframeSize = uac_format_desc->bSubframeSize; + as_t->bBitResolution = uac_format_desc->bBitResolution; + as_t->bSamFreqType = uac_format_desc->bSamFreqType; + for (u8 i = 0; i < as_t->bSamFreqType; i++) { + memcpy(&as_t->tSamFreq[i], &uac_format_desc->tSamFreq[i], 3); + log_info("as bNrChannels:%d bBitResolution:%d tSamFreq : %d", as_t->bNrChannels, as_t->bBitResolution, as_t->tSamFreq[i]); + } + //Endpointdescriptor + pBuf += uac_format_desc->bLength; + /* for (int i = 0; i < as_t->bNumEndpoints; i++) { */ + struct usb_endpoint_descriptor *endpoint = (struct usb_endpoint_descriptor *)pBuf; + if (endpoint->bDescriptorType == USB_DT_ENDPOINT) { + as_t->ep_Interval = endpoint->bInterval; + as_t->ep_max_packet_size = endpoint->wMaxPacketSize; + if (endpoint->bEndpointAddress & USB_DIR_IN) { + as_t->ep = endpoint->bEndpointAddress & 0xf; + log_info("ep in : %x\n", as_t->ep); + usb_if->dev.audio->support = MICROPHONE_SUPPORTED; + } else { + as_t->ep = endpoint->bEndpointAddress; + log_info("ep out : %x\n", as_t->ep); + usb_if->dev.audio->support = HEADPHONE_SUPPORTED; + } + pBuf += (USB_DT_ENDPOINT_AUDIO_SIZE + UAC_ISO_ENDPOINT_DESC_SIZE); + } + /* } */ + } else { + log_error("uac_format_desc->bDescriptorSubtype err!!\n"); + goto __exit; + } + + } while (1); + /* log_info("lennnn:%d\n",pBuf - (u8 *)interface); */ + return pBuf - (u8 *)interface ; + } else { + log_info("audio streaming interface : %d ep_num:%d Altersetting:%d\n", interface_num, interface->bNumEndpoints, interface->bAlternateSetting); + } + + } + +__exit: + return USB_DT_INTERFACE_SIZE; + +} + +static struct audio_device_t *__find_microphone_interface(const struct usb_host_device *host_dev) +{ + struct audio_device_t *audio = NULL; + for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) { + const struct usb_interface_info *usb_if = host_dev->interface_info[i]; + if (usb_if && + (usb_if->ctrl->interface_class == USB_CLASS_AUDIO)) { + audio = usb_if->dev.audio; + if (audio->subclass == USB_SUBCLASS_AUDIOSTREAMING && + audio->support == MICROPHONE_SUPPORTED) { + // find microphone + return audio; + } + } + } + + return NULL; +} +static struct audio_device_t *__find_headphone_interface(const struct usb_host_device *host_dev) +{ + struct audio_device_t *audio = NULL; + for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) { + const struct usb_interface_info *usb_if = host_dev->interface_info[i]; + if (usb_if && + (usb_if->ctrl->interface_class == USB_CLASS_AUDIO)) { + audio = usb_if->dev.audio; + if (audio->subclass == USB_SUBCLASS_AUDIOSTREAMING && + audio->support == HEADPHONE_SUPPORTED) { + // find headphone + return audio; + } + } + } + + return NULL; +} +static u32 play_vol_convert(u16 v) +{ + //固定音量表,更换声卡需要修改音量表 + const u16 vol_table[] = { + //0-100 + 0xd300, //0 + 0xd58f, 0xd7bf, 0xd9a8, 0xdb5b, 0xdce1, 0xde45, 0xdf8a, 0xe0b6, 0xe1cd, 0xe2d1, + 0xe3c5, 0xe4ab, 0xe583, 0xe651, 0xe714, 0xe7cd, 0xe87f, 0xe928, 0xe9ca, 0xea66, + 0xeafc, 0xeb8d, 0xec18, 0xec9e, 0xed20, 0xed9e, 0xee18, 0xee8e, 0xef00, 0xef6f, + 0xefdc, 0xf045, 0xf0ab, 0xf10f, 0xf171, 0xf1d0, 0xf22c, 0xf287, 0xf2e0, 0xf336, + 0xf38b, 0xf3de, 0xf42f, 0xf47e, 0xf4cc, 0xf518, 0xf563, 0xf5ad, 0xf5f5, 0xf63c, + 0xf681, 0xf6c6, 0xf709, 0xf74b, 0xf78c, 0xf7cb, 0xf80a, 0xf848, 0xf885, 0xf8c1, + 0xf8fc, 0xf936, 0xf96f, 0xf9a8, 0xf9df, 0xfa16, 0xfa4c, 0xfa81, 0xfab6, 0xfaea, + 0xfb1d, 0xfb50, 0xfb82, 0xfbb3, 0xfbe4, 0xfc14, 0xfc43, 0xfc72, 0xfca0, 0xfcce, + 0xfcfc, 0xfd28, 0xfd55, 0xfd80, 0xfdab, 0xfdd6, 0xfe01, 0xfe2a, 0xfe54, 0xfe7d, + 0xfea5, 0xfece, 0xfef5, 0xff1d, 0xff43, 0xff6a, 0xff90, 0xffb6, 0xffdb, 0x0000, + }; + + if (v <= 100) { + return vol_table[v]; + } + + for (int i = 0; i < sizeof(vol_table) / 2; i++) { + if (v <= vol_table[i]) { + return i; + } + } + + return 0; +} + +void set_usb_audio_play_volume(u16 vol) +{ + const struct usb_host_device *host_dev = host_id2device(__this->usb_id); + u8 featureUnitID = 6; + usb_audio_volume_control(host_dev, featureUnitID, 1, play_vol_convert(vol)); + usb_audio_volume_control(host_dev, featureUnitID, 2, play_vol_convert(vol)); + if (vol == 0) { + __this->player.mute = 1; + usb_audio_mute_control(host_dev, featureUnitID, __this->player.mute); //mute + } else { + if (__this->player.mute == 1) { + __this->player.mute = 0; + usb_audio_mute_control(host_dev, featureUnitID, __this->player.mute); + } + } +} + +#ifdef USB_AUDIO_PLAY_TEST +static const s16 sin_48k[] = { + 0, 2139, 4240, 6270, 8192, 9974, 11585, 12998, + 14189, 15137, 15826, 16244, 16384, 16244, 15826, 15137, + 14189, 12998, 11585, 9974, 8192, 6270, 4240, 2139, + 0, -2139, -4240, -6270, -8192, -9974, -11585, -12998, + -14189, -15137, -15826, -16244, -16384, -16244, -15826, -15137, + -14189, -12998, -11585, -9974, -8192, -6270, -4240, -2139 +}; +#endif +static void usb_audio_tx_isr(struct usb_host_device *host_dev, u32 ep) +{ + const usb_dev usb_id = host_device2id(host_dev); + struct audio_device_t *audio = NULL; + struct audio_streaming_t *as_t = NULL; + u16 ep_max_packet_size = 0; + u8 channel = 0; + u32 rlen = 0; + static u32 usb_audio_tx_len = 0; + + if (__this->player.play_state != AUDIO_PLAY_START) { + return; + } + + audio = __find_headphone_interface(host_dev); + if (!audio) { + log_error("no find headphone interface!"); + return; + } + + as_t = &audio->as[__this->player.Cur_AlternateSetting - 1]; + /* ep_max_packet_size = as_t->ep_max_packet_size; */ + ep_max_packet_size = EP_MAX_PACKET_SIZE; + channel = as_t->bNrChannels; + + //iso send +#ifdef USB_AUDIO_PLAY_TEST + //For Test + int tx_len = 0; +#if 1 // 单声道双声道输出 + s16 buf[240 / 2]; + for (u8 i = 0, j = 0; i < 240 / 2; i += 2) { + buf[i] = sin_48k[j]; + buf[i + 1] = sin_48k[j]; + j++; + if (j >= sizeof(sin_48k) / sizeof(sin_48k[0])) { + j = 0; + } + } +#else + //单声道直接输出 + u8 buf[248]; + do { + memcpy(&buf[tx_len], sin_48k, sizeof(sin_48k)); + tx_len += sizeof(sin_48k); + } while (tx_len < ep_max_packet_size); +#endif + usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, buf, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 0); +#else + if (__this->player.usb_audio_remain_len == 0) { + cbuf_read_alloc(&__this->player.usb_audio_play_cbuf, &__this->player.usb_audio_remain_len); + usb_audio_tx_len = 0; + } + if (__this->player.usb_audio_remain_len) { + if (usb_audio_tx_len == 0) { + rlen = cbuf_read(&__this->player.usb_audio_play_cbuf, __this->player.usb_audio_play_buf2, __this->player.usb_audio_remain_len); + if (!rlen) { + __this->player.usb_audio_remain_len = 0; + usb_audio_tx_len = 0; + putchar('C'); + usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, NULL, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1); + os_sem_post(&__this->player.sem); + return; + } + os_sem_post(&__this->player.sem); + + } + u8 *send_buf = __this->player.send_buf; + u8 *play_buf = __this->player.usb_audio_play_buf2; + if (channel == 2) { + if (__this->player.src_channel == 1) { + //源数据是单声道数据,转双声道输出 + int j = 0; + for (u8 i = 0; i < ep_max_packet_size; i += 4) { + //left + *(send_buf + i) = *(play_buf + (usb_audio_tx_len + j)); + *(send_buf + i + 1) = *(play_buf + (usb_audio_tx_len + j + 1)); + //right + + *(send_buf + i + 2) = *(play_buf + (usb_audio_tx_len + j)); + *(send_buf + i + 3) = *(play_buf + (usb_audio_tx_len + j + 1)); + j += 2; + } + usb_audio_tx_len += j; + usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, send_buf, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 0); + } else if (__this->player.src_channel == 2) { + //源数据是双声道数据,直接双声道输出 + usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, play_buf + usb_audio_tx_len, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 0); + usb_audio_tx_len += ep_max_packet_size; + } + } else if (channel == 1) { + } + if (usb_audio_tx_len >= __this->player.usb_audio_remain_len) { + __this->player.usb_audio_remain_len = 0; + usb_audio_tx_len = 0; + } + } else { + //audio buf null ,send null packet + putchar('E'); + usb_h_ep_write_async(usb_id, ep, ep_max_packet_size, as_t->ep, NULL, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1); + } + +#endif +} +void set_vol_test(void *p) +{ + struct usb_host_device *host_dev = (struct usb_host_device *)p; + static u16 vol = 100; + set_usb_audio_play_volume(vol); + /* static u8 f = 0; */ + /* void usb_audio_pause_play(void); */ + /* void usb_audio_resume_play(void); */ + /* if (!f) { */ + /* usb_audio_pause_play(); */ + /* } else { */ + /* usb_audio_resume_play(); */ + /* } */ + /* f = !f; */ + vol -= 10; +} +void audio_play_task(void *p) +{ + log_info(">>> Enter usb audio play task"); + struct usb_host_device *host_dev = (struct usb_host_device *)p; + const usb_dev usb_id = host_device2id(host_dev); + u8 *ptr = NULL; + u32 wlen = 0; + u32 ret = 0; + struct audio_device_t *audio = NULL; + audio = __find_headphone_interface(host_dev); + struct audio_streaming_t *as_t = &audio->as[__this->player.Cur_AlternateSetting - 1]; + /* u32 ep_max_packet_size = as_t->ep_max_packet_size; */ + u32 ep_max_packet_size = EP_MAX_PACKET_SIZE; + log_info("ep max packet : %d\n", ep_max_packet_size); + if (__this->player.send_buf) { + free(__this->player.send_buf); + __this->player.send_buf = NULL; + } + __this->player.send_buf = zalloc(ep_max_packet_size); + u32 usb_audio_buf_size = ep_max_packet_size * 5; //预留5个包的缓存 + + /* sys_timer_add(host_dev,set_vol_test,5000); */ + os_sem_create(&__this->player.sem, 0); + u32 host_ep = as_t->host_ep; + __this->player.play_state = AUDIO_PLAY_START; + //分配双缓存 + // 一个缓存保存读卡的数据,一个用于usb发送 + if (!__this->player.usb_audio_play_buf) { + __this->player.usb_audio_play_buf = zalloc(usb_audio_buf_size); + cbuf_init(&__this->player.usb_audio_play_cbuf, __this->player.usb_audio_play_buf, usb_audio_buf_size); + usb_h_ep_write_async(usb_id, host_ep, ep_max_packet_size, as_t->ep, NULL, ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1); //启动iso传输 + } + if (!__this->player.usb_audio_play_buf2) { + __this->player.usb_audio_play_buf2 = zalloc(usb_audio_buf_size); + } + while (1) { + if (__this->player.Cur_AlternateSetting == 0 || __this->player.play_state != AUDIO_PLAY_START) { + putchar('C'); + os_time_dly(50); + continue; + } + ptr = cbuf_write_alloc(&__this->player.usb_audio_play_cbuf, &wlen); + if (wlen) { + putchar('R'); + ret = __this->player.put_buf(ptr, wlen); + if (ret != wlen) { + __this->player.play_state = AUDIO_PLAY_STOP; + goto __task_exit; + + } + cbuf_write_updata(&__this->player.usb_audio_play_cbuf, wlen); + } else { + log_w("usb audio play buf not enough!\n"); + } +__task_exit: + os_sem_pend(&__this->player.sem, 0); + } +} + +void usb_audio_start_play(const usb_dev usb_id, u8 channel, u8 bit_reso, u32 sample_rate) +{ + log_info(" usb audio play\n"); + const struct usb_host_device *host_dev = host_id2device(usb_id); + struct audio_device_t *audio = NULL; + struct audio_streaming_t *as_t = NULL; + u8 *ep_buffer = ep_out_dma_buf; + u8 find_alternatesetting = 0; + audio = __find_headphone_interface(host_dev); + if (!audio) { + log_error("no find headphone interface!"); + return; + } + for (u8 i = 0; i < ARRAY_SIZE(audio->as); i++) { + as_t = &audio->as[i]; + if (as_t->bBitResolution == bit_reso) { + for (u8 j = 0; j < as_t->bSamFreqType; j++) { + if (as_t->tSamFreq[j] == sample_rate) { + find_alternatesetting = i + 1; + break; + } + } + } + } + if (!find_alternatesetting) { + log_e("can not find Alternatesetting,please check bit_reso and sample_rate\n"); + return; + } + + __this->usb_id = usb_id; + //端点分配 + u32 host_ep = usb_get_ep_num(usb_id, USB_DIR_OUT, USB_ENDPOINT_XFER_ISOC); + ASSERT(host_ep != -1, "ep not enough"); + + __this->player.Cur_AlternateSetting = find_alternatesetting; //选择Alternatesetting + __this->player.sample_rate = sample_rate; //选择采样率 + __this->player.src_channel = channel; + as_t = &audio->as[find_alternatesetting - 1]; + u8 target_ep = as_t->ep; + u8 ep_interval = as_t->ep_Interval; + as_t->host_ep = host_ep; + + usb_set_interface(host_dev, audio->interface_num, find_alternatesetting); //interface Alternatesetting + usb_audio_sampling_frequency_control(host_dev, target_ep, sample_rate);//设置采样率 + //设置音量 + /* usb_audio_volume_control(host_dev, 6, 1, vol_convert(5)); */ + /* usb_audio_volume_control(host_dev, 6, 2, vol_convert(5)); */ + + log_info("H2D ep: %x --> %x interval: %d", host_ep, target_ep, ep_interval); + usb_h_set_ep_isr(host_dev, host_ep, usb_audio_tx_isr, host_dev); + usb_h_ep_config(usb_id, host_ep, USB_ENDPOINT_XFER_ISOC, 1, ep_interval, ep_buffer, sizeof(ep_out_dma_buf)); + task_create(audio_play_task, host_dev, "uac_play"); +} + +void usb_audio_stop_play(const usb_dev usb_id) +{ + const struct usb_host_device *host_dev = host_id2device(usb_id); + usb_h_set_ep_isr(NULL, 0, NULL, NULL); + __this->player.put_buf(NULL, 0); + __this->player.Cur_AlternateSetting = 0; + __this->player.sample_rate = 0; + __this->player.src_channel = 0; + if (__this->player.usb_audio_play_buf) { + free(__this->player.usb_audio_play_buf); + __this->player.usb_audio_play_buf = NULL; + } + if (__this->player.usb_audio_play_buf2) { + free(__this->player.usb_audio_play_buf2); + __this->player.usb_audio_play_buf2 = NULL; + } + if (__this->player.send_buf) { + free(__this->player.send_buf); + __this->player.send_buf = NULL; + } + printf("\n[ debug ]--func=%s line=%d\n", __func__, __LINE__); + task_kill("uac_play"); + printf("\n[ debug ]--func=%s line=%d\n", __func__, __LINE__); +} +void usb_audio_pause_play(void) +{ + __this->player.play_state = AUDIO_PLAY_PAUSE; +} +void usb_audio_resume_play(void) +{ + const struct usb_host_device *host_dev = host_id2device(__this->usb_id); + struct audio_device_t *audio = __find_headphone_interface(host_dev); + struct audio_streaming_t *as_t = &audio->as[__this->player.Cur_AlternateSetting - 1]; + __this->player.play_state = AUDIO_PLAY_START; + usb_h_ep_write_async(__this->usb_id, as_t->host_ep, as_t->ep_max_packet_size, as_t->ep, NULL, as_t->ep_max_packet_size, USB_ENDPOINT_XFER_ISOC, 1); //重新启动传输 +} + + +static u32 record_vol_convert(u16 v) +{ + //固定音量表,更换声卡需要修改音量表 + const u16 vol_table[] = { + //0-100 + 0xf400, + 0xf479, 0xf4ee, 0xf560, 0xf5cf, 0xf63a, 0xf6a3, 0xf709, 0xf76c, 0xf7cd, 0xf82b, + 0xf887, 0xf8e1, 0xf939, 0xf98f, 0xf9e4, 0xfa36, 0xfa87, 0xfad6, 0xfb23, 0xfb6f, + 0xfbba, 0xfc03, 0xfc4b, 0xfc91, 0xfcd6, 0xfd1a, 0xfd5d, 0xfd9f, 0xfde0, 0xfe1f, + 0xfe5e, 0xfe9b, 0xfed8, 0xff14, 0xff4e, 0xff88, 0xffc1, 0xfff9, 0x0003, 0x0069, + 0x00a3, 0x00de, 0x0119, 0x0155, 0x0193, 0x01d1, 0x0210, 0x0251, 0x0292, 0x02d5, + 0x0318, 0x035d, 0x03a3, 0x03eb, 0x0434, 0x047e, 0x04c9, 0x0517, 0x0565, 0x05b5, + 0x0607, 0x065b, 0x06b1, 0x0708, 0x0762, 0x07bd, 0x081b, 0x087c, 0x08de, 0x0943, + 0x09ab, 0x0a16, 0x0a84, 0x0af4, 0x0b69, 0x0be1, 0x0c5c, 0x0cdc, 0x0d60, 0x0de9, + 0x0e77, 0x0f0a, 0x0fa2, 0x1041, 0x10e7, 0x1195, 0x124a, 0x1308, 0x13d0, 0x14a3, + 0x1582, 0x166e, 0x176a, 0x1877, 0x1998, 0x1ad0, 0x1c24, 0x1d98, 0x1f33, 0x2100, + }; + + if (v <= 100) { + return vol_table[v]; + } + + for (int i = 0; i < sizeof(vol_table) / 2; i++) { + if (v <= vol_table[i]) { + return i; + } + } + + return 0; +} + +void set_usb_audio_record_volume(u16 vol) +{ + const struct usb_host_device *host_dev = host_id2device(__this->usb_id); + u8 featureUnitID = 5; + usb_audio_volume_control(host_dev, featureUnitID, 0, record_vol_convert(vol)); +} + +static u32 write_file_len = 0; +static void usb_audio_rx_isr(struct usb_host_device *host_dev, u32 ep) +{ + u8 buffer[192] = {0}; + u8 *ptr = NULL; + int rlen, wlen = 0; + usb_dev usb_id = host_device2id(host_dev); + struct audio_device_t *audio = NULL; + struct audio_streaming_t *as_t = NULL; + audio = __find_microphone_interface(host_dev); + if (!audio) { + log_error("no find microphone interface!"); + return; + } + if (__this->microphone.record_state != AUDIO_RECORD_START) { + return; + } + as_t = &audio->as[__this->microphone.Cur_AlternateSetting - 1]; + u8 channel = as_t->bNrChannels; + + u32 rx_len = usb_h_ep_read_async(usb_id, ep, as_t->ep, buffer, sizeof(buffer), USB_ENDPOINT_XFER_ISOC, 0); + /* g_printf("RX:%d\n",rx_len); */ + /* printf_buf(buffer, rx_len); */ + cbuf_write(&__this->microphone.usb_audio_record_cbuf, buffer, rx_len); + cbuf_write_alloc(&__this->microphone.usb_audio_record_cbuf, &wlen); + if (wlen == 0) { + putchar('O'); + if (write_file_len) { + log_w("write againnnnn\n"); + } + /* [> printf("R:%d W:%d\n", rx_len,wlen); <] */ + cbuf_read_alloc(&__this->microphone.usb_audio_record_cbuf, &rlen); + cbuf_read(&__this->microphone.usb_audio_record_cbuf, __this->microphone.usb_audio_record_buf2, rlen); + write_file_len = rlen; + os_taskq_post_msg("uac_record", 2, 0x01, rlen); + /* return; */ + } + + usb_h_ep_read_async(usb_id, ep, as_t->ep, NULL, 0, USB_ENDPOINT_XFER_ISOC, 1); //触发下一个接收中断 +} +void audio_record_task(void *p) +{ + log_info(">>> Enter usb audio record task"); + struct usb_host_device *host_dev = (struct usb_host_device *)p; + const usb_dev usb_id = host_device2id(host_dev); + u8 *ptr = NULL; + u32 rlen = 0; + u32 ret = 0; + int msg[16]; + struct audio_device_t *audio = NULL; + audio = __find_microphone_interface(host_dev); + struct audio_streaming_t *as_t = &audio->as[__this->microphone.Cur_AlternateSetting - 1]; + /* u32 ep_max_packet_size = as_t->ep_max_packet_size; */ + u32 ep_max_packet_size = EP_MAX_PACKET_SIZE; + log_info("ep max packet : %d\n", ep_max_packet_size); + u32 usb_audio_buf_size = ep_max_packet_size * 50; + + u32 host_ep = as_t->host_ep; + u8 target_ep = as_t->ep; + //分配双缓存 + // 一个缓存写卡的数据,一个用于usb接收 + if (!__this->microphone.usb_audio_record_buf) { + __this->microphone.usb_audio_record_buf = zalloc(usb_audio_buf_size); + cbuf_init(&__this->microphone.usb_audio_record_cbuf, __this->microphone.usb_audio_record_buf, usb_audio_buf_size); + + } + if (!__this->microphone.usb_audio_record_buf2) { + __this->microphone.usb_audio_record_buf2 = zalloc(usb_audio_buf_size); + } + + usb_h_ep_read_async(usb_id, host_ep, target_ep, NULL, 0, USB_ENDPOINT_XFER_ISOC, 1); //启动iso + while (1) { + ret = __os_taskq_pend(msg, ARRAY_SIZE(msg), portMAX_DELAY); + if (ret == OS_TASKQ) { + switch (msg[1]) { + case 0x01: + ptr = __this->microphone.usb_audio_record_buf2; + rlen = msg[2]; + putchar('W'); + __this->microphone.get_buf(ptr, rlen); + write_file_len = 0; + break; + } + } + } +} +void usb_audio_start_record(const usb_dev usb_id, u8 bit_reso, u32 sample_rate) +{ + log_info(" usb audio record\n"); + const struct usb_host_device *host_dev = host_id2device(usb_id); + struct audio_device_t *audio = NULL; + struct audio_streaming_t *as_t = NULL; + u8 *ep_buffer = ep_in_dma_buf; + u8 find_alternatesetting = 0; + audio = __find_microphone_interface(host_dev); + if (!audio) { + log_error("no find microphone interface!"); + return; + } + for (u8 i = 0; i < ARRAY_SIZE(audio->as); i++) { + as_t = &audio->as[i]; + if (as_t->bBitResolution == bit_reso) { + for (u8 j = 0; j < as_t->bSamFreqType; j++) { + if (as_t->tSamFreq[j] == sample_rate) { + find_alternatesetting = i + 1; + break; + } + } + } + } + if (!find_alternatesetting) { + log_e("can not find Alternatesetting,please check bit_reso and sample_rate\n"); + return; + } + //端点分配 + u32 host_ep = usb_get_ep_num(usb_id, USB_DIR_IN, USB_ENDPOINT_XFER_ISOC); + ASSERT(host_ep != -1, "ep not enough"); + __this->usb_id = usb_id; + host_ep = host_ep | USB_DIR_IN; + + __this->microphone.Cur_AlternateSetting = find_alternatesetting; //选择Alternatesetting + __this->microphone.sample_rate = sample_rate; //选择采样率 + as_t = &audio->as[find_alternatesetting - 1]; + u8 target_ep = as_t->ep; + u8 ep_interval = as_t->ep_Interval; + as_t->host_ep = host_ep; + + usb_set_interface(host_dev, audio->interface_num, find_alternatesetting); //interface 1 Alternatesetting 1 + usb_audio_sampling_frequency_control(host_dev, target_ep, sample_rate);//设置采样率 + //设置音量 + /* usb_audio_volume_control(host_dev, 6, 1, vol_convert(5)); */ + /* usb_audio_volume_control(host_dev, 6, 2, vol_convert(5)); */ + log_info("D2H ep: %x --> %x", target_ep, host_ep); + usb_h_set_ep_isr(host_dev, host_ep, usb_audio_rx_isr, host_dev); + usb_h_ep_config(usb_id, host_ep, USB_ENDPOINT_XFER_ISOC, 1, ep_interval, ep_buffer, sizeof(ep_in_dma_buf)); + task_create(audio_record_task, host_dev, "uac_record"); + __this->microphone.record_state = AUDIO_RECORD_START; +} +void usb_audio_stop_record(const usb_dev usb_id) +{ + const struct usb_host_device *host_dev = host_id2device(usb_id); + usb_h_set_ep_isr(NULL, 0, NULL, NULL); + __this->microphone.get_buf(NULL, 0); + __this->microphone.Cur_AlternateSetting = 0; + __this->microphone.sample_rate = 0; + if (__this->microphone.usb_audio_record_buf) { + free(__this->microphone.usb_audio_record_buf); + __this->microphone.usb_audio_record_buf = NULL; + } + if (__this->microphone.usb_audio_record_buf2) { + free(__this->microphone.usb_audio_record_buf2); + __this->microphone.usb_audio_record_buf2 = NULL; + } + printf("\n[ debug ]--func=%s line=%d\n", __func__, __LINE__); + task_kill("uac_record"); + printf("\n[ debug ]--func=%s line=%d\n", __func__, __LINE__); +} +void usb_audio_pause_record(void) +{ + __this->microphone.record_state = AUDIO_RECORD_PAUSE; +} +void usb_audio_resume_record(void) +{ + const struct usb_host_device *host_dev = host_id2device(__this->usb_id); + struct audio_device_t *audio = __find_microphone_interface(host_dev); + struct audio_streaming_t *as_t = &audio->as[__this->microphone.Cur_AlternateSetting - 1]; + __this->microphone.record_state = AUDIO_RECORD_START; + usb_h_ep_read_async(__this->usb_id, as_t->host_ep, as_t->ep, NULL, 0, USB_ENDPOINT_XFER_ISOC, 1); //重新启动接收 +} + +void usb_audio_start_process(u32 id) +{ + usb_audio_start_play(id, 1, 16, 48000); //开启headphone + usb_audio_start_record(id, 16, 48000); //开启microphone +} +void usb_audio_stop_process(u32 id) +{ + usb_audio_stop_play(id); + usb_audio_stop_record(id); +} + + +static void usb_audio_event_handler(struct sys_event *event, void *priv) +{ + const char *audio = NULL; + switch (event->type) { + case SYS_DEVICE_EVENT: + if ((u32)event->arg == DEVICE_EVENT_FROM_USB_HOST) { + if ((event->u.dev.event == DEVICE_EVENT_IN) || + (event->u.dev.event == DEVICE_EVENT_CHANGE)) { + audio = (const char *)event->u.dev.value; + usb_audio_start_process(audio[5] - '0'); + + } else if (event->u.dev.event == DEVICE_EVENT_OUT) { + log_error("device out %x", event->u.dev.value); + usb_audio_stop_process(audio[5] - '0'); + } + break; + } + } +} +void usb_host_audio_init(int (*put_buf)(void *ptr, u32 len), int *(*get_buf)(void *ptr, u32 len)) +{ + memset(__this, 0, sizeof(struct usb_audio_info)); + __this->player.put_buf = put_buf; + __this->microphone.get_buf = get_buf; + register_sys_event_handler(SYS_DEVICE_EVENT, DEVICE_EVENT_FROM_USB_HOST, 2, + usb_audio_event_handler); +} +void usb_host_audio_exit() +{ + unregister_sys_event_handler(usb_audio_event_handler); + __this->player.put_buf = NULL; + __this->microphone.get_buf = NULL; +} + +#endif diff --git a/apps/common/usb/host/audio.h b/apps/common/usb/host/audio.h new file mode 100644 index 0000000..9787161 --- /dev/null +++ b/apps/common/usb/host/audio.h @@ -0,0 +1,56 @@ +#ifndef __AUDIO_H__ +#define __AUDIO_H__ + +#include "system/task.h" +#include "device/device.h" +#include "usb_bulk_transfer.h" +#include "usb/host/usb_host.h" +#include "usb/device/uac_audio.h" + + +#define HEADPHONE_SUPPORTED 0x01 +#define MICROPHONE_SUPPORTED 0x02 +#define HEADSET_SUPPORTED 0x03 + +struct audio_streaming_t { + u8 bNumEndpoints; + u8 bFormatType; /** FORMAT_TYPE_1 */ + u8 bNrChannels; /** physical channels in the stream */ + u8 bSubframeSize; + u8 bBitResolution; + u8 bSamFreqType; + u32 tSamFreq[8]; + u8 host_ep; //主机传输端点 + u8 ep; //从机端点(由描述符中指定) + u8 ep_Interval; + u16 ep_max_packet_size; +}; + +struct audio_device_t { + u8 interface_num; //接口号 + u8 subclass; + u8 support; + void *parent; + struct audio_streaming_t as[8]; +}; + +int usb_audio_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf); + +// API +int usb_audio_play_put_buf(void *ptr, u32 len); +int usb_audio_record_get_buf(void *ptr, u32 len); + +//headphone api +void set_usb_audio_play_volume(u16 vol); +void usb_audio_start_play(const usb_dev usb_id, u8 channel, u8 bit_reso, u32 sample_rate); //指定播放数据的声道数,位数,采样率 +void usb_audio_stop_play(const usb_dev usb_id); +void usb_audio_pause_play(void); +void usb_audio_resume_play(void); + +//microphone api +void set_usb_audio_record_volume(u16 vol); +void usb_audio_start_record(const usb_dev usb_id, u8 bit_reso, u32 sample_rate); //指定录制数据的位数,采样率 +void usb_audio_stop_record(const usb_dev usb_id); +void usb_audio_pause_record(void); +void usb_audio_resume_record(void); +#endif diff --git a/apps/common/usb/host/audio_demo.c b/apps/common/usb/host/audio_demo.c new file mode 100644 index 0000000..0e1b4ca --- /dev/null +++ b/apps/common/usb/host/audio_demo.c @@ -0,0 +1,111 @@ +#include "includes.h" +#include "asm/includes.h" +#include "app_config.h" +#include "system/timer.h" +#include "device/ioctl_cmds.h" +#include "device_drive.h" +#if TCFG_HOST_AUDIO_ENABLE +#include "usb/host/usb_host.h" +#include "usb_ctrl_transfer.h" +#include "usb_bulk_transfer.h" +#include "audio.h" +#include "usb_config.h" + +#define LOG_TAG_CONST USB +#define LOG_TAG "[AUDIO]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +#define TEST_FILE_ENABLE (0) //从sd卡读数据; 录制数据至sd卡 +#if (TEST_FILE_ENABLE) +static FILE *play_file = NULL; +int usb_audio_play_put_buf(void *ptr, u32 len) +{ + int ret = 0; + if (ptr == NULL && len == 0) { + //err + if (play_file) { + fclose(play_file); + play_file = NULL; + return 0; + } + } + if (!play_file) { + play_file = fopen("storage/sd0/C/raw.pcm", "r"); //单声道 + /* play_file = fopen("storage/sd0/C/raw2.pcm", "r"); //双声道 */ + if (!play_file) { + log_e("fopen play file faild!\n"); + return -1; + } + } + //读sd卡数据到播放缓存中 + ret = fread(play_file, ptr, len); + if (ret != len) { + log_e(" file read buf err %d\n", ret); + fclose(play_file); + play_file = NULL; + return -1; + } + + return len; +} +static FILE *record_file = NULL; +int usb_audio_record_get_buf(void *ptr, u32 len) +{ +#if (TEST_FILE_ENABLE) + int ret = 0; + static u32 cnt = 0; + if (!record_file) { + record_file = fopen("storage/sd0/C/record01.pcm", "w+"); + cnt = 0; + if (!record_file) { + log_e("fopen play file faild!\n"); + return -1; + } + } + putchar('W'); + ret = fwrite(record_file, ptr, len); + if (ret != len) { + log_e(" file write buf err %d\n", ret); + fclose(record_file); + record_file = NULL; + return -1; + } + //test + if (cnt++ >= 800) { + cnt = 0; + log_info("stop record....\n"); + fclose(record_file); + record_file = NULL; + } +#endif + + return len; +} +#else + +//将数据传入usb +//ptr:usb数据指针 +//len:需要传入的数据长度 +int usb_audio_play_put_buf(void *ptr, u32 len) +{ + return len; +} + +//从usb读取数据 +//ptr:usb数据指针 +//len:读取的数据长度 +int usb_audio_record_get_buf(void *ptr, u32 len) +{ + return len; +} + + +#endif + +#endif diff --git a/apps/common/usb/host/hid.c b/apps/common/usb/host/hid.c new file mode 100644 index 0000000..49a9cc0 --- /dev/null +++ b/apps/common/usb/host/hid.c @@ -0,0 +1,657 @@ +#include "includes.h" +#include "asm/includes.h" +#include "app_config.h" +#include "system/timer.h" +#include "device/ioctl_cmds.h" +#include "device_drive.h" +#if TCFG_HID_HOST_ENABLE +#include "usb/host/usb_host.h" +#include "usb_ctrl_transfer.h" +#include "usb_bulk_transfer.h" +#include "hid.h" +#include "usb_config.h" +#include "usb_hid_keys.h" + +#define MAIN_ITEM 0 +#define GLOBAL_ITEM 1 +#define LOCAL_ITEM 2 + +#define LOG_TAG_CONST USB +#define LOG_TAG "[HID]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +struct hid_device_t hid_device[USB_MAX_HW_NUM][MAX_HOST_INTERFACE]; + +static int set_power(struct usb_host_device *host_dev, u32 value) +{ + const usb_dev usb_id = host_device2id(host_dev); + memset(hid_device[usb_id], 0, sizeof(hid_device[usb_id])); + return DEV_ERR_NONE; +} + +static int get_power(struct usb_host_device *host_dev, u32 value) +{ + return DEV_ERR_NONE; +} + +static const struct interface_ctrl hid_ctrl = { + .interface_class = USB_CLASS_HID, + .set_power = set_power, + .get_power = get_power, + .ioctl = NULL, +}; + +static const struct usb_interface_info _usb_if[USB_MAX_HW_NUM][MAX_HOST_INTERFACE] = { + { + { + .ctrl = (struct interface_ctrl *) &hid_ctrl, + .dev.hid = &hid_device[0][0], + }, + { + .ctrl = (struct interface_ctrl *) &hid_ctrl, + .dev.hid = &hid_device[0][1], + }, + { + .ctrl = (struct interface_ctrl *) &hid_ctrl, + .dev.hid = &hid_device[0][2], + }, + { + .ctrl = (struct interface_ctrl *) &hid_ctrl, + .dev.hid = &hid_device[0][3], + }, + }, +#if USB_MAX_HW_NUM > 1 + { + { + .ctrl = (struct interface_ctrl *) &hid_ctrl, + .dev.hid = &hid_device[1][0], + }, + { + .ctrl = (struct interface_ctrl *) &hid_ctrl, + .dev.hid = &hid_device[1][1], + }, + { + .ctrl = (struct interface_ctrl *) &hid_ctrl, + .dev.hid = &hid_device[1][2], + }, + { + .ctrl = (struct interface_ctrl *) &hid_ctrl, + .dev.hid = &hid_device[1][3], + }, + }, +#endif +}; + +static u8 interval[USB_MAX_HW_NUM][16]; + +int usb_hid_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf) +{ + struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf; + pBuf += sizeof(struct usb_interface_descriptor); + int len = 0; + const usb_dev usb_id = host_device2id(host_dev); + + struct usb_endpoint_descriptor *endpoint; + + pBuf += 9;//hid desc; + + const struct usb_interface_info *usb_if = &_usb_if[usb_id][interface_num]; + + memset(usb_if->dev.p, 0, sizeof(struct hid_device_t)); + + host_dev->interface_info[interface_num] = usb_if; + usb_if->dev.hid->parent = host_dev; + + log_info("hid eps %d %d %x %x", interface->bNumEndpoints, interface_num, usb_if, usb_if->dev.p); + + log_info("parent %x hid @ interface %d usb_if %x hid %x", + host_dev, interface_num, usb_if, usb_if->dev.hid); + + if ((interface->bInterfaceProtocol == 0x02) || + (interface->bInterfaceProtocol == 0x01)) { //mouse & keyboard + + usb_if->dev.hid->bNumEndpoints = interface->bNumEndpoints; + usb_if->dev.hid->report_list[0].usage = interface->bInterfaceProtocol; + for (int i = 0 ; i < interface->bNumEndpoints; i++) { + endpoint = (struct usb_endpoint_descriptor *)pBuf; + if (USB_DIR_IN & endpoint->bEndpointAddress) { + const u8 ep = endpoint->bEndpointAddress & 0x0f; + usb_if->dev.hid->ep_pair[i] = ep; + interval[usb_id][ep] = endpoint->bInterval; + log_info("interfacenum = %d,endpoint = %x interval = %x", + interface->bInterfaceNumber, endpoint->bEndpointAddress, endpoint->bInterval); + } + pBuf += endpoint->bLength; + } + } else { + log_info("vendor"); + host_dev->interface_info[interface_num] = NULL; //??? + for (int i = 0 ; i < interface->bNumEndpoints; i++) { + endpoint = (struct usb_endpoint_descriptor *)pBuf; + if (USB_DIR_IN & endpoint->bEndpointAddress) { + /* interface_endpoint[interface->bInterfaceNumber] = endpoint->bEndpointAddress & 0x0f; */ + log_info("interfacenum = %d,endpoint = %x interval = %x", + interface->bInterfaceNumber, endpoint->bEndpointAddress, endpoint->bInterval); + } + pBuf += endpoint->bLength; + } + return sizeof(struct usb_interface_descriptor); + } + + return pBuf - (u8 *)interface; +} + +static u32 _hid_report_parse(struct hid_device_t *hid, const u8 *report, u32 len) +{ + hid->report_count = 0; + struct report_info_t null_rpt; + struct report_info_t *const rpt = &null_rpt; + + memset(rpt, 0, sizeof(*rpt)); + + unsigned char ops; + int index = 0; + u8 report_size = 0; + u8 report_count = 0; + u8 cur_ops_is_report_size_count = 0; + u8 old_ops_is_report_size_count = 0; + s8 cur_section_bit = 0; + u8 input_bit_index = 0; + u8 total_bits = 0; + u8 output_bit_index = 0; + u8 cur_usage = 0; + u32 undef_type = 0; + u8 undef_usage = 0; + u8 collection_deep = 0; + + while (index < len) { + ops = (char)report[index++]; + char bSize = ops & 0x03; + bSize = bSize == 3 ? 4 : bSize; // size is 4 when bSize is 3 + char bType = (ops >> 2) & 0x03; + char bTag = (ops >> 4) & 0x0F; + + cur_ops_is_report_size_count = 0; + char bSizeActual = 0; + int itemVal = 0; + for (int j = 0; j < bSize; j++) { + if (index + j < len) { + itemVal += report[index + j] << (8 * j); + bSizeActual++; + } + } + if (undef_type) { + undef_type ++; + if (bTag == 0x0A) { + undef_usage ++; + } else if (bTag == 0x0C) { + undef_usage --; + } + if (undef_usage == 0 && undef_type > 2) { + undef_type = 0; + } + index += bSize; + continue; + } + if (undef_type) { + index += bSize; + continue; + } + if (itemVal == 0xffb5) { + undef_type = 1; + index += bSize; + continue; + } else { + undef_type = 0; + } + if (bType == MAIN_ITEM) { + if (old_ops_is_report_size_count) { + cur_section_bit += report_size * report_count; + } + if (bTag == 0x08) { + /* log_info("input %X", itemVal); */ + /* log_info("\tusage %x", cur_usage); */ + /* log_info("\t\tcur_section_bit %d", cur_section_bit); */ + if (rpt->usage == 0x02) { //mouse + if (cur_usage == 1) { + if (rpt->btn_start_bit == 0) { + rpt->btn_start_bit = total_bits ; + } + rpt->btn_width += cur_section_bit ; + /* log_info("btn_width %d-%d", rpt->btn_start_bit, rpt->btn_width); */ + } else if ((cur_usage == 0x30) || (cur_usage == 0x31)) { + + if (rpt->xy_start_bit == 0) { + rpt->xy_start_bit = total_bits; + } + rpt->xy_width = cur_section_bit; + /* log_info("xy_width %d-%d", rpt->xy_start_bit, rpt->xy_width); */ + } else if (cur_usage == 0x38) { + if (rpt->wheel_start_bit == 0) { + rpt->wheel_start_bit = total_bits; + } + if (rpt->xy_width || cur_section_bit < 24) { + rpt->wheel_width = cur_section_bit; + /* log_info("wheel_width %d-%d", rpt->wheel_start_bit, rpt->wheel_width); */ + } else { + rpt->wheel_width = rpt->xy_width = cur_section_bit / 3; + + rpt->xy_start_bit = total_bits; + rpt->wheel_start_bit = rpt->xy_start_bit + rpt->xy_width * 2; + /* log_info("wheel_width %d-%d", rpt->wheel_start_bit, rpt->wheel_width); */ + /* log_info("xy_width %d-%d", rpt->xy_start_bit, rpt->xy_width); */ + } + } else if (cur_usage == 0xb8) { + rpt->wheel_width = rpt->xy_width = cur_section_bit / 4; + rpt->xy_start_bit = total_bits; + rpt->wheel_start_bit = rpt->xy_start_bit + rpt->xy_width * 2; + } + } + total_bits += cur_section_bit; + /* input_bit[input_bit_index++] = cur_section_bit; */ + cur_section_bit = -1; + } else if (bTag == 0x09) { + /* log_info("OUTPUT %X", itemVal); */ + /* log_info("\tusage %x", cur_usage); */ + /* log_info("\t\tcur_section_bit %d", cur_section_bit); */ + /* output_bit[output_bit_index++] = cur_section_bit; */ + cur_section_bit = -1; + } else if (bTag == 0x0B) { + /* log_info("Feature %X", itemVal); */ + /* log_info("\tusage %x", cur_usage); */ + /* log_info("\t\tcur_section_bit %d", cur_section_bit); */ + /* output_bit[output_bit_index++] = cur_section_bit; */ + cur_section_bit = -1; + } else if (bTag == 0x0A) { + collection_deep ++ ; + log_info("Collection %d %x", collection_deep, rpt->usage); + } else if (bTag == 0x0C) { + collection_deep --; + log_info("End Collection %d %x", collection_deep, rpt->usage); + if (collection_deep == 0) { + if (rpt->usage == 0x02 || + rpt->usage == 0x06 || + rpt->usage == 0x07) { + + memcpy(&hid->report_list[hid->report_count], rpt, sizeof(*rpt)); + memset(rpt, 0, sizeof(*rpt)); + + hid->report_count ++; + } + } + if (index < len) { + continue; + } + } else { + log_info("MAIN_ITEM Unknown btag :%x", bTag); + return 1; + } + } else if (bType == GLOBAL_ITEM) { + /* log_info("GLOBAL_ITEM"); */ + if (bTag == 0x00) { + /* log_info("Usage Page %x", itemVal); */ + + if (rpt->usage == 0x06) { + if (itemVal == 0x07) { + rpt->usage = 0x07; + log_info("re set type %x", 0x07); + } + } + if (itemVal == 0x02) { + rpt->usage = 0x02; + log_info("re set type %x", 0x02); + } + + } else if (bTag == 0x01) { + //log_info("Logical Minimum %x", itemVal); + } else if (bTag == 0x02) { + //log_info("Logical Maximum %x", itemVal); + } else if (bTag == 0x03) { + /* log_info("Physical Minimum %x", itemVal); */ + } else if (bTag == 0x04) { + /* log_info("Physical Maximum %x", itemVal); */ + } else if (bTag == 0x05) { + /* log_info("Unit Exponent %x", itemVal); */ + } else if (bTag == 0x06) { + /* log_info("Unit %x", itemVal); */ + } else if (bTag == 0x07) { + /* log_info("Report Size %x", itemVal); */ + report_size = itemVal; + cur_ops_is_report_size_count = 1; + } else if (bTag == 0x08) { + log_info("Report ID %x", itemVal, rpt->usage); + rpt->report_id = itemVal; + } else if (bTag == 0x09) { + /* log_info("Report Count %x", itemVal); */ + report_count = itemVal; + cur_ops_is_report_size_count = 1; + } else if (bTag == 0x0A) { + /* log_info("Push %x", bSizeActual); */ + } else if (bTag == 0x0B) { + /* log_info("Pop %x", bSizeActual); */ + } else { + log_info("GLOBAL_ITEM Unknown btag :%x", bTag); + return 2; + } + } else if (bType == LOCAL_ITEM) { + /* log_info("LOCAL_ITEM"); */ + if (bTag == 0x00) { + if (rpt->usage == 0) { + rpt->usage = itemVal; + log_info("set type %x", rpt->usage); + } + if (itemVal == 0x30) { //X + } else if (itemVal == 0x31) { //y + } else if (itemVal == 0x38) { //wheel + } else { + } + /* log_info("\t change usage %x -> %x", cur_usage, itemVal); */ + cur_usage = itemVal; + if (!collection_deep) { + if (itemVal == 0x06 || itemVal == 0x07 || itemVal == 0x02) { + //仅限键盘和鼠标 + rpt->usage = itemVal; + log_info("set typee %x", rpt->usage); + } + } + /* type = itemVal; */ + } else if (bTag == 0x01) { + // log_info("Usage Minimum %x", itemVal); + } else if (bTag == 0x02) { + // log_info("Usage Maximum %x", itemVal); + } else if (bTag == 0x03) { + /* log_info("Designator Index %x", itemVal); */ + } else if (bTag == 0x04) { + /* log_info("Designator Minimum %x", itemVal); */ + } else if (bTag == 0x05) { + /* log_info("Designator Maximum %x", itemVal); */ + } else if (bTag == 0x07) { + /* log_info("String Index %x", itemVal); */ + } else if (bTag == 0x08) { + /* log_info("String Minimum %x", itemVal); */ + } else if (bTag == 0x09) { + /* log_info("String Maximum %x", itemVal); */ + } else if (bTag == 0x0A) { + /* log_info("Delimiter %x", itemVal); */ + } else { + log_info("LOCAL_ITEM Unknown btag :%x", bTag); + return 3; + } + } else { + log_info("OTHER Unknown btag :%x", bTag); + return 4; + } + if (!cur_ops_is_report_size_count && old_ops_is_report_size_count) { + if (cur_section_bit != -1) { + cur_section_bit += report_size * report_count; + } else { + cur_section_bit = 0; + } + } + if (cur_section_bit == -1) { + cur_section_bit = 0; + } + old_ops_is_report_size_count = cur_ops_is_report_size_count; + index += bSize; + + } + return 0; +} +static u32 hid_report_parse(struct hid_device_t *hid, const u8 *report, u32 len) +{ + u8 type = _hid_report_parse(hid, report, len); + for (int i = 0; i < hid->report_count; i++) { + struct report_info_t *rpt = &hid->report_list[i]; + if (rpt->usage == 0x02) { + if (rpt->report_id == 0) { + rpt->report_id = 0xff; + } + rpt->btn_start_bit /= 8; + rpt->btn_width /= 8; + rpt->xy_start_bit /= 8; + rpt->xy_width /= 8; + rpt->wheel_start_bit /= 8; + rpt->wheel_width /= 8; + + log_info("mouse report_id %d", + rpt->report_id); + + log_info("btn_width %d-%d", + rpt->btn_start_bit, rpt->btn_width); + log_info("xy_width %d-%d", + rpt->xy_start_bit, rpt->xy_width); + log_info("wheel_width %d-%d", + rpt->wheel_start_bit, rpt->wheel_width); + + if (rpt->btn_width != 2) { + rpt->btn_width = 1; + } + + log_info("btn_width %d-%d", + rpt->btn_start_bit, rpt->btn_width); + + } else if (rpt->usage == 6 || rpt->usage == 7) { + if (rpt->report_id == 0) { + rpt->report_id = 0xff; + } + log_info("keyboard report_id %d", rpt->report_id); + } else { + log_info("unknown usage %d", rpt->usage); + } + } + return 0; +} + +void mouse_route(const struct mouse_data_t *p); +/* __attribute__((weak)) void mouse_route(const struct mouse_data_t *p) */ +/* { */ +/* log_info("btn: %x x-y %d %d wheel %d ac_pan %d", */ +/* p->btn, p->x, p->y, p->wheel, p->ac_pan); */ +/* } */ +static void hid_convert_mouse(const struct report_info_t *mouse, const u8 *buffer) +{ + struct mouse_data_t mouse_data; + memset(&mouse_data, 0, sizeof(mouse_data)); + if (mouse->report_id != 0xff) { + if (mouse->report_id != buffer[0]) { + log_error("report_id = %x buffer[0] = %x", mouse->report_id, buffer[0]); + return; + } + buffer++; + } + const u8 *ptr; + ptr = &buffer[mouse->btn_start_bit]; + if (mouse->btn_width == 2) { + mouse_data.btn = ptr[0] | (ptr[1] << 8); + } else { + mouse_data.btn = ptr[0] ; + } + s16 tmp; + ptr = &buffer[mouse->xy_start_bit]; + if (mouse->xy_width == 1 || mouse->xy_width == 2) { + mouse_data.x = (char)ptr[0]; + mouse_data.y = (char)ptr[1]; + } else if (mouse->xy_width == 4) { + mouse_data.x = ptr[0] | (ptr[1] << 8); + ptr += 2; + mouse_data.y = ptr[0] | (ptr[1] << 8); + } else if (mouse->xy_width == 3) { + tmp = (ptr[1] & 0xf) << 12 | ptr[0] << 4; + tmp = tmp >> 4; + mouse_data.x = tmp; + + tmp = (ptr[2] << 8) | ((ptr[1] >> 4) << 4); + tmp = tmp >> 4; + mouse_data.y = tmp; + } else { + log_error("error mouse xy_width %d", mouse->xy_width); + } + + ptr = &buffer[mouse->wheel_start_bit]; + + if (mouse->wheel_width == 1) { + mouse_data.wheel = (char)ptr[0]; + } else { + mouse_data.wheel = ptr[0] | (ptr[1] << 8); + } + + mouse_route(&mouse_data); +} +__attribute__((weak)) void keyboard_route(const u8 *p) +{ + log_info("keyboard_buffer:"); + printf_buf(p, 12); +} +void hid_convert_krbd(const struct report_info_t *kbd, u8 *buffer) +{ +#if 0 + u8 keyboard_buffer[12]; + memset(keyboard_buffer, 0, sizeof(keyboard_buffer)); + if (kbd->report_id != 0xff) { + if (kbd->report_id != buffer[0]) { + log_error("report_id = %x buffer[0] = %x", kbd->report_id, buffer[0]); + return; + } + buffer++; + } + + u8 idx = 0; + u8 index = 0; + int i = 0; + for (i = 0; i < 8; i++) { + if (buffer[0] & BIT(i)) { + keyboard_buffer[idx++] = 0xe0 + i; + } + } + + if (buffer[1] == 0) { + buffer += 2; + } + index = idx; + for (; idx < 12; idx++) { + if (*buffer) { + keyboard_buffer[index] = *buffer; + index++; + } + buffer ++; + } + keyboard_route(keyboard_buffer); +#else + if (kbd->report_id != 0xff) { + if (kbd->report_id != buffer[0]) { + log_error("report_id = %x buffer[0] = %x", kbd->report_id, buffer[0]); + return; + } + buffer++; + } + u8 keyboard_buffer[8]; + memset(keyboard_buffer, 0, sizeof(keyboard_buffer)); + + keyboard_buffer[0] = *buffer; + buffer ++; + + if (*buffer == 0) { + buffer ++; + } + keyboard_buffer[1] = 0; + + /* memcpy(&keyboard_buffer[2], buffer, 6); */ + u8 pos = 2; + for (int i = pos; i < 8; i++) { + if (*buffer) { + keyboard_buffer[pos] = *buffer; + pos++; + } + buffer++; + } + keyboard_route(keyboard_buffer); +#endif +} + +static void hid_route(const struct hid_device_t *hid, const u8 *buffer) +{ + for (int i = 0; i < hid->report_count; i++) { + if (hid->report_list[i].usage == 0x02) { + hid_convert_mouse(&hid->report_list[i], buffer); + } else if ((hid->report_list[i].usage == 0x06) || + (hid->report_list[i].usage == 0x07)) { + hid_convert_krbd(&hid->report_list[i], buffer); + } else { + r_printf("usage %x", hid->report_list[i].usage); + } + } +} +static void hid_isr(struct usb_interface_info *usb_if, u32 ep) +{ + u8 buffer[64] = {0}; + struct usb_host_device *host_dev = usb_if->dev.hid->parent; + usb_dev usb_id = host_device2id(host_dev); + u32 target_ep = usb_if->dev.hid->ep_pair[ep]; + u32 rx_len = usb_h_ep_read_async(usb_id, ep, target_ep, buffer, 64, USB_ENDPOINT_XFER_INT, 0); + + if (rx_len) { + hid_route(usb_if->dev.hid, buffer); + } + /* printf_buf(buffer, rx_len); */ + + usb_h_ep_read_async(usb_id, ep, target_ep, buffer, 8, USB_ENDPOINT_XFER_INT, 1); +} +void hid_process(u32 id) +{ + struct usb_host_device *host_dev = host_id2device(id); + u8 report[256 + 2]; + u8 ep_pair[4]; + + for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) { + struct usb_interface_info *usb_if = host_dev->interface_info[i]; + log_info("parent %x hid @ interface %d usb_if %x hid %x", + host_dev, i, usb_if, usb_if ? usb_if->dev.hid : 0); + if (usb_if && + (usb_if->ctrl->interface_class == USB_CLASS_HID)) { + hid_set_idle(host_dev, i); + memset(report, 0, sizeof(report)); + hid_get_report(host_dev, report, i, 0xff); + printf_buf(report, 256); + hid_report_parse(usb_if->dev.hid, report, 256); + memcpy(ep_pair, usb_if->dev.hid->ep_pair, 4); + + if (usb_if->dev.hid->report_count == 0) { + continue; + } + + for (int i = 0; i < usb_if->dev.hid->bNumEndpoints; i++) { + + u32 host_ep = usb_get_ep_num(id, USB_DIR_IN, USB_ENDPOINT_XFER_INT); + + ASSERT(host_ep != -1, "ep not enough"); + + u32 target_ep = ep_pair[i]; + + usb_if->dev.hid->ep_pair[host_ep] = target_ep; + + log_info("D2H ep: %x --> %x interval %d", + target_ep, host_ep, interval[id][target_ep]); + + usb_h_set_ep_isr(host_dev, host_ep | USB_DIR_IN, hid_isr, usb_if); + + u8 *ep_buffer = usb_h_get_ep_buffer(id, host_ep | USB_DIR_OUT); + usb_h_ep_config(id, host_ep | USB_DIR_IN, USB_ENDPOINT_XFER_INT, 1, + interval[id][target_ep], ep_buffer, 64); + int r = usb_h_ep_read_async(id, host_ep, target_ep, NULL, 0, USB_ENDPOINT_XFER_INT, 1); + } + } else { + if (usb_if) { + log_error("error hid class %x", usb_if->ctrl->interface_class); + } + } + } + +} + +#endif diff --git a/apps/common/usb/host/hid.h b/apps/common/usb/host/hid.h new file mode 100644 index 0000000..126c019 --- /dev/null +++ b/apps/common/usb/host/hid.h @@ -0,0 +1,36 @@ +#ifndef __HID_H__ +#define __HID_H__ + +#include "system/task.h" +#include "device/device.h" +#include "usb/scsi.h" +#include "usb_bulk_transfer.h" +#include "usb/host/usb_host.h" + +struct report_info_t { + u8 report_id; + u8 usage; + + u8 btn_start_bit; + u8 btn_width; + + u8 xy_start_bit; + u8 xy_width; + + u8 wheel_start_bit; + u8 wheel_width; +}; + +#define MAX_REPORT_COUNT 4 +struct hid_device_t { + void *parent; + u8 ep_pair[4]; + u8 report_count; + u8 bNumEndpoints; + struct report_info_t report_list[MAX_REPORT_COUNT]; +}; + +int usb_hid_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf); +void hid_process(u32 id); + +#endif /*HID_H*/ diff --git a/apps/common/usb/host/usb_bulk_transfer.c b/apps/common/usb/host/usb_bulk_transfer.c new file mode 100644 index 0000000..cb8b4ea --- /dev/null +++ b/apps/common/usb/host/usb_bulk_transfer.c @@ -0,0 +1,291 @@ +/** + * @file usb_bulk_transfer.c + * @brief bulk transfer driver + * @author chenrixin@zh-jieli.com + * @version 1.00 + * @date 2017-02-09 + */ + +#include +#include "jiffies.h" +#include "usb_config.h" +#include "usb_bulk_transfer.h" +#include "usb_ctrl_transfer.h" +#include "usb_storage.h" +#include "usb/host/usb_host.h" +#include "usb/usb_phy.h" +#include "app_config.h" +#include "device_drive.h" + +#if USB_HOST_ENABLE +#define LOG_TAG_CONST USB +#define LOG_TAG "[USB]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +struct usb_request_block { + void *ptr; + u32 len; + u32 target_ep; + u16 rxmap; + u16 txmap; + u32 msg; + u32 async_mode; +}; +static struct usb_request_block urb; + +u8 get_async_mode(void) +{ + u8 mode = 0; +#if UDISK_READ_512_ASYNC_ENABLE + local_irq_disable(); + mode = urb.async_mode; + local_irq_enable(); +#endif + return mode; + +} +void set_async_mode(u8 mode) +{ +#if UDISK_READ_512_ASYNC_ENABLE + local_irq_disable(); + urb.async_mode = mode; + local_irq_enable(); +#endif +} +static void usb_bulk_rx_isr(struct usb_host_device *host_dev, u32 ep) +{ + usb_dev usb_id = host_device2id(host_dev); + int l = min(urb.len, urb.rxmap); + l = usb_h_ep_read_async(usb_id, ep, urb.target_ep, urb.ptr, l, USB_ENDPOINT_XFER_BULK, 0); + /* g_printf("%s() %d %d", __func__, l, urb.len); */ + if (l > 0) { + urb.len -= l; + if (urb.ptr) { + urb.ptr += l; + } + urb.msg = 0; + } else { + urb.msg = l; + urb.len = 0; + } + + if (urb.len == 0) { + if (!get_async_mode()) { + usb_sem_post(host_dev); + } else { + if (get_async_mode() == BULK_ASYNC_MODE_SEM_PEND) { + usb_sem_post(host_dev); + } + set_async_mode(BULK_ASYNC_MODE_EXIT); + } + } else { + usb_h_ep_read_async(usb_id, ep, urb.target_ep, urb.ptr, urb.len, USB_ENDPOINT_XFER_BULK, 1); + } +} +s32 usb_bulk_only_receive_async(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + const usb_dev usb_id = host_device2id(host_dev); + + urb.ptr = pBuf; + urb.len = len; + urb.target_ep = target_ep; + +#ifdef CONFIG_USB_SUPPORT_MRX_TX + urb.rxmap = 1 * 1024; +#else + urb.rxmap = 0x40; +#endif + + urb.msg = -DEV_ERR_OFFLINE; + + usb_h_set_ep_isr(host_dev, host_ep | USB_DIR_IN, usb_bulk_rx_isr, host_dev); + usb_set_intr_rxe(usb_id, host_ep); + + int ret = usb_h_ep_read_async(usb_id, host_ep, target_ep, urb.ptr, len, USB_ENDPOINT_XFER_BULK, 1); + if (ret < 0) { + return ret; + } + ret = usb_sem_pend(host_dev, 300); + + usb_clr_intr_rxe(usb_id, host_ep); + usb_h_set_ep_isr(host_dev, host_ep | USB_DIR_IN, NULL, host_dev); + if (ret) { + return -DEV_ERR_TIMEOUT; + } + return urb.msg ? urb.msg : len; +} + +/** + * @brief usb_bulk_receive_async_no_wait 启动USB Bulk 异步预读 + * 不用等信号量,启动传输后返回 + * @param device 设备句柄 + * @param pBuf 读buffer缓冲区,芯片所有memory都可以 + * @param len 需要预读的长度 + * + * @return 负数表示失败 + */ +s32 usb_bulk_receive_async_no_wait(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + const usb_dev usb_id = host_device2id(host_dev); + + urb.async_mode = 1; + urb.ptr = pBuf; + urb.len = len; + urb.target_ep = target_ep; + +#ifdef CONFIG_USB_SUPPORT_MRX_TX + urb.rxmap = 1 * 1024; +#else + urb.rxmap = 0x40; +#endif + + urb.msg = -DEV_ERR_OFFLINE; + + usb_h_set_ep_isr(host_dev, host_ep | USB_DIR_IN, usb_bulk_rx_isr, host_dev); + usb_set_intr_rxe(usb_id, host_ep); + + int ret = usb_h_ep_read_async(usb_id, host_ep, target_ep, urb.ptr, len, USB_ENDPOINT_XFER_BULK, 1); + if (ret < 0) { + if (ret == -DEV_ERR_RXSTALL) { + ret = usb_clear_feature(host_dev, target_ep | USB_DIR_IN); + if (ret == 0) { + return -DEV_ERR_RXSTALL; + } + } + return ret; + } + return len; +} +static s32 _usb_bulk_only_receive(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len) +{ +#if 0 + struct usb_host_device *host_dev = device_to_usbdev(device); + const usb_dev usb_id = host_device2id(host_dev); + return usb_h_bulk_read(usb_id, host_ep, rxmaxp, target_ep, pBuf, len); +#else + return usb_bulk_only_receive_async(device, host_ep, rxmaxp, target_ep, pBuf, len); +#endif +} +s32 usb_bulk_only_receive(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len) +{ + + struct usb_host_device *host_dev = device_to_usbdev(device); + int ret = _usb_bulk_only_receive(device, host_ep, rxmaxp, target_ep, pBuf, len); + if (ret == -DEV_ERR_RXSTALL) { + ret = usb_clear_feature(host_dev, target_ep | USB_DIR_IN); + if (ret == 0) { + return -DEV_ERR_RXSTALL; + } + } + return ret; +} +static void usb_bulk_tx_isr(struct usb_host_device *host_dev, u32 ep) +{ + usb_dev usb_id = host_device2id(host_dev); + int l = min(urb.len, urb.txmap); + l = usb_h_ep_write_async(usb_id, ep, urb.txmap, urb.target_ep, urb.ptr, l, USB_ENDPOINT_XFER_BULK, 0); + + if (l > 0) { + urb.len -= l; + urb.ptr += l; + urb.msg = 0; + } else { + urb.msg = l; + urb.len = 0; + } + + if (urb.len == 0) { + if (urb.msg || l == 0) { + usb_sem_post(host_dev); + } + } +} +s32 usb_bulk_only_send_async(struct device *device, u8 host_ep, u16 txmaxp, u8 target_ep, const u8 *pBuf, u32 len) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + const usb_dev usb_id = host_device2id(host_dev); + + urb.target_ep = target_ep; +#ifdef CONFIG_USB_SUPPORT_MRX_TX + urb.txmap = 8 * 1024; +#else + urb.txmap = 0x40; +#endif + + + urb.msg = -DEV_ERR_OFFLINE; + urb.len = len - min(len, urb.txmap); + urb.ptr = (u8 *)pBuf + min(len, urb.txmap); + + + usb_h_set_ep_isr(host_dev, host_ep, usb_bulk_tx_isr, host_dev); + usb_set_intr_txe(usb_id, host_ep); + + int ret = usb_h_ep_write_async(usb_id, host_ep, txmaxp, target_ep, pBuf, min(len, urb.txmap), USB_ENDPOINT_XFER_BULK, 1); + if (ret < 0) { + return ret; + } + ret = usb_sem_pend(host_dev, 250); + + usb_clr_intr_txe(usb_id, host_ep); + usb_h_set_ep_isr(host_dev, host_ep, NULL, host_dev); + + if (ret) { + r_printf("ret %d", ret); + return -DEV_ERR_TIMEOUT; + } + /* g_printf("%s() %d %d", __func__, urb.len, urb.msg); */ + return urb.msg ? urb.msg : len; +} +/** + * @brief usb_bulk_only_send + * + * @param device + * @param host_ep 主机的端点号 + * @param target_ep 目标设备的端点号 + * @param pBuf + * @param len + * + * @return 负数失败 + * 正数发送的字节数 + */ +static s32 _usb_bulk_only_send(struct device *device, u8 host_ep, u16 txmaxp, u8 target_ep, const u8 *pBuf, u32 len) +{ +#if 0 + struct usb_host_device *host_dev = device_to_usbdev(device); + const usb_dev usb_id = host_device2id(host_dev); + return usb_h_bulk_write(usb_id, host_ep, txmaxp, target_ep, pBuf, len); +#elif 0 + if (len < 512) { + struct usb_host_device *host_dev = device_to_usbdev(device); + const usb_dev usb_id = host_device2id(host_dev); + return usb_h_bulk_write(usb_id, host_ep, txmaxp, target_ep, pBuf, len); + } else { + return usb_bulk_only_send_async(device, host_ep, txmaxp, target_ep, pBuf, len); + } +#else + return usb_bulk_only_send_async(device, host_ep, txmaxp, target_ep, pBuf, len); +#endif +} +s32 usb_bulk_only_send(struct device *device, u8 host_ep, u16 txmaxp, u8 target_ep, const u8 *pBuf, u32 len) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + int ret = _usb_bulk_only_send(device, host_ep, txmaxp, target_ep, pBuf, len); + + if (ret == -DEV_ERR_TXSTALL) { + ret = usb_clear_feature(host_dev, target_ep); + if (ret == 0) { + return -DEV_ERR_TXSTALL; + } + } + return ret; + +} +#endif diff --git a/apps/common/usb/host/usb_bulk_transfer.h b/apps/common/usb/host/usb_bulk_transfer.h new file mode 100644 index 0000000..49f79c3 --- /dev/null +++ b/apps/common/usb/host/usb_bulk_transfer.h @@ -0,0 +1,15 @@ +#ifndef __USB_BULK_TRANSFER_H__ +#define __USB_BULK_TRANSFER_H__ +#include "typedef.h" +#include "device/device.h" + + +s32 usb_bulk_only_receive_async(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len); +s32 usb_bulk_only_receive(struct device *device, u8 host_ep, u16 rxmaxp, u8 ep, u8 *pBuf, u32 len); +s32 usb_bulk_only_send_async(struct device *device, u8 host_ep, u16 txmaxp, u8 target_ep, const u8 *pBuf, u32 len); +s32 usb_bulk_only_send(struct device *device, u8 host_ep, u16 txmaxp, u8 ep, const u8 *pBuf, u32 len); + +u8 get_async_mode(void); +void set_async_mode(u8 mode); +s32 usb_bulk_receive_async_no_wait(struct device *device, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *pBuf, u32 len); +#endif diff --git a/apps/common/usb/host/usb_ctrl_transfer.c b/apps/common/usb/host/usb_ctrl_transfer.c new file mode 100644 index 0000000..fd597c1 --- /dev/null +++ b/apps/common/usb/host/usb_ctrl_transfer.c @@ -0,0 +1,622 @@ +/** + * @file usb_ctrl_transfer.c + * @brief usb 控制传输接口 + * @author chenrixin@zh-jieli.com + * @version 1.00 + * @date 2017-02-09 + */ + +#include "usb/host/usb_host.h" +#include "usb_ctrl_transfer.h" +#include "app_config.h" +#include "device_drive.h" +#include "gpio.h" +#include "usb/scsi.h" + +#define LOG_TAG_CONST USB +#define LOG_TAG "[USB]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#if USB_HOST_ENABLE + +_WEAK_ +void usb_dis_ep0_txdly(const usb_dev id) +{ +} +static void ep0_h_isr(struct usb_host_device *host_dev, u32 ep) +{ + usb_dev usb_id = host_device2id(host_dev); + usb_sem_post(host_dev); +} +/** + * @brief usb_ctlXfer + * + * @param host_dev + * @param urb + * + * @return + */ +static int usb_ctlXfer(struct usb_host_device *host_dev, struct ctlXfer *urb) +{ + u32 ret = DEV_ERR_NONE; + u8 reg = 0; + u32 data_len; + usb_dev usb_id = host_device2id(host_dev); + u8 devnum = host_dev->private_data.devnum; + u32 max_packet_size = host_dev->private_data.ep0_max_packet_size; + + usb_write_faddr(usb_id, devnum); + + switch (urb->stage) { + case USB_PID_SETUP : + usb_write_ep0(usb_id, (u8 *)&urb->setup, 8); + reg = CSR0H_SetupPkt | CSR0H_TxPktRdy; + break; + case USB_PID_IN : + if (urb->setup.wLength) { + reg = CSR0H_ReqPkt; + } else { + reg = CSR0H_StatusPkt | CSR0H_ReqPkt; + } + break; + case USB_PID_OUT: + if (urb->setup.wLength) { + data_len = min(urb->setup.wLength, max_packet_size); + reg = CSR0H_TxPktRdy; + usb_write_ep0(usb_id, urb->buffer, data_len); + urb->setup.wLength -= data_len; + urb->buffer += data_len; + } else { + reg = CSR0H_StatusPkt | CSR0H_TxPktRdy; + } + break; + default : + break; + } + +#if USB_HOST_ASYNC + //config ep0 callback fun + usb_h_set_ep_isr(host_dev, 0, ep0_h_isr, host_dev); + usb_set_intr_txe(usb_id, 0); +#endif + + usb_write_csr0(usb_id, reg); + + u32 st = 0; + u32 ot = get_jiffies() + 500; + while (1) { + if (usb_host_timeout(ot)) { + log_error("time out %x\n", reg); + ret = -DEV_ERR_TIMEOUT; + goto __exit; + } + if (usb_h_dev_status(usb_id)) { + st ++; + } else { + st = 0; + } + if (((usb_read_devctl(usb_id) & BIT(2)) == 0) || (st > 1000)) { + log_error("usb%d_offline\n", usb_id); + ret = -DEV_ERR_OFFLINE; + goto __exit; + } + +#if USB_HOST_ASYNC + ret = usb_sem_pend(host_dev, 250); //wait isr + if (ret) { + log_error("usb%d_offline\n", usb_id); + ret = -DEV_ERR_OFFLINE; + goto __exit; + } +#endif + + reg = usb_read_csr0(usb_id); + if (reg & CSR0H_RxStall) { + log_error(" rxStall CSR0:0x%x", reg); + ret = -DEV_ERR_CONTROL_STALL; + goto __exit; + } + if (reg & CSR0H_Error) { + log_error(" Error CSR0:0x%x", reg); + usb_write_csr0(usb_id, 0); + ret = -DEV_ERR_CONTROL; + goto __exit; + } + if (USB_PID_IN == urb->stage) { + + if (reg & CSR0H_RxPktRdy) { + data_len = usb_read_count0(usb_id); + data_len = min(data_len, urb->setup.wLength); + usb_read_ep0(usb_id, urb->buffer, data_len);; + urb->buffer += data_len; + urb->setup.wLength -= data_len; + if (data_len < max_packet_size) { + urb->setup.wLength = 0; + } + if (urb->setup.wLength) { + usb_write_csr0(usb_id, CSR0H_ReqPkt); + } else { + usb_write_csr0(usb_id, 0); + break; + } + } + } else { + if (!(reg & CSR0H_TxPktRdy)) { + break; + } + } + } +__exit: + usb_clr_intr_txe(usb_id, 0); + usb_dis_ep0_txdly(usb_id); + return ret; +} +/** + * @brief usb_control_transfers + * + * @param struct host_dev + * @param urb + * + * @return + */ +static int usb_control_transfers(struct usb_host_device *host_dev, struct ctlXfer *urb) +{ + usb_dev usb_id = host_device2id(host_dev); + + int res; + /*SETUP*/ + + urb->stage = USB_PID_SETUP; //SETUP transaction + + res = usb_ctlXfer(host_dev, urb); + + if (res) { + return res; + } + + /*IN or OUT*/ + urb->stage = USB_PID_IN; + + + while (urb->setup.wLength) { + if (urb->setup.bRequestType & USB_DIR_IN) { //Request Direction + urb->stage = USB_PID_IN; //IN transaction + + res = usb_ctlXfer(host_dev, urb); + + if (res) { + return res; + } + + urb->stage = USB_PID_OUT; + } else { + urb->stage = USB_PID_OUT; //OUT transaction + + res = usb_ctlXfer(host_dev, urb); + + if (res) { + return res; + } + + urb->stage = USB_PID_IN; + } + } + + res = usb_ctlXfer(host_dev, urb); + + if (res) { + return res; + } + + return DEV_ERR_NONE; +} + +/** + * @brief usb_control_msg + * + * @param host_dev + * @param request + * @param requesttype + * @param value + * @param index + * @param data + * @param size + * + * @return + */ +static int usb_control_msg(struct usb_host_device *host_dev, + u8 request, u8 requesttype, + u16 value, u16 index, + void *data, u16 size) +{ + struct ctlXfer urb; + urb.setup.bRequestType = requesttype; + urb.setup.bRequest = request; + urb.setup.wValue = cpu_to_le16(value); + urb.setup.wIndex = cpu_to_le16(index); + urb.setup.wLength = cpu_to_le16(size); + urb.buffer = data; + + return usb_control_transfers(host_dev, &urb); + +} + +/** + * @brief usb_clear_feature + * + * @param host_dev + * @param ep + * + * @return + */ +int usb_clear_feature(struct usb_host_device *host_dev, u32 ep) +{ + return usb_control_msg(host_dev, USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, ep, NULL, 0); +} + +int set_address(struct usb_host_device *host_dev, u8 devnum) +{ + return usb_control_msg(host_dev, USB_REQ_SET_ADDRESS, 0, devnum, 0, NULL, 0); +} + +int usb_get_device_descriptor(struct usb_host_device *host_dev, struct usb_device_descriptor *desc) +{ + return usb_control_msg(host_dev, + USB_REQ_GET_DESCRIPTOR, + USB_DIR_IN, + (USB_DT_DEVICE << 8), + 0, + desc, + USB_DT_DEVICE_SIZE + ); +} + +int usb_get_string_descriptor(struct usb_host_device *host_dev, struct usb_device_descriptor *desc) +{ + int ret = DEV_ERR_NONE; +#if 0 + struct usb_private_data *private_data = host_dev->private_data ; + /**********get string language*********/ + u8 buf[16]; + memset(buf, 0x0, sizeof(buf)); + ret = usb_control_msg(host_dev, + USB_REQ_GET_DESCRIPTOR, + USB_DIR_IN, + (USB_DT_STRING << 8), + 0, + desc, + sizeof(buf) + ); + if (ret) { + return ret; + } + memcpy(&private_data->language, buf + 2, sizeof(private_data->language)); + + /**********get manufacturer string**********/ + memset(private_data->manufacturer, 0x0, sizeof(private_data->manufacturer)); + if (desc->iManufacturer) { + ret = usb_control_msg(host_dev, + USB_REQ_GET_DESCRIPTOR, + USB_DIR_IN, + (USB_DT_STRING << 8) | desc->iManufacturer, + 0, + private_data->manufacturer, + sizeof(private_data->manufacturer) + ); + if (ret) { + return ret; + } + } + /**********get product string**********/ + memset(private_data->product, 0x0, sizeof(private_data->product)); + if (desc->iProduct) { + ret = usb_control_msg(host_dev, + USB_REQ_GET_DESCRIPTOR, + USB_DIR_IN, + (USB_DT_STRING << 8) | desc->iProduct, + 0, + private_data->product, + sizeof(private_data->product) + ); + if (ret) { + return ret; + } + } +#endif + return ret; +} + +int set_configuration(struct usb_host_device *host_dev) +{ + return usb_control_msg(host_dev, USB_REQ_SET_CONFIGURATION, 0, 1, 0, NULL, 0); +} +int set_configuration_add_value(struct usb_host_device *host_dev, u16 value) +{ + return usb_control_msg(host_dev, USB_REQ_SET_CONFIGURATION, 0, value, 0, NULL, 0); +} +int get_config_descriptor(struct usb_host_device *host_dev, void *cfg_desc, u32 len) +{ + return usb_control_msg(host_dev, + USB_REQ_GET_DESCRIPTOR, + USB_DIR_IN, + (USB_DT_CONFIG << 8), + 0, + cfg_desc, + len); +} + +int get_config_descriptor_add_value_l(struct usb_host_device *host_dev, void *cfg_desc, u32 len, u8 value_l) +{ + return usb_control_msg(host_dev, + USB_REQ_GET_DESCRIPTOR, + USB_DIR_IN, + (USB_DT_CONFIG << 8) | value_l, + 0, + cfg_desc, + len); +} + + +int get_msd_max_lun(struct usb_host_device *host_dev, void *lun) +{ + return usb_control_msg(host_dev, + USB_MSD_MAX_LUN, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0, + 0, + lun, + 1); +} +int set_msd_reset(struct usb_host_device *host_dev) +{ + return usb_control_msg(host_dev, + 0xff, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0, + 0, + NULL, + 0); +} + +int hid_set_idle(struct usb_host_device *host_dev, u32 id) +{ + return usb_control_msg(host_dev, 0x0a, 0x21, 0, id << 8, NULL, 0); +} +int hid_get_report(struct usb_host_device *host_dev, u8 *report, u8 report_id, u16 report_len) +{ + return usb_control_msg(host_dev, + USB_REQ_GET_DESCRIPTOR, + USB_DIR_IN | USB_RECIP_INTERFACE, + 0x2200, + report_id, + report, + report_len); +} +int hid_set_output_report(struct usb_host_device *host_dev, u8 *report, u8 report_id, u8 report_len) +{ + return usb_control_msg(host_dev, + 0x09, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0x0201, + report_id, + report, + report_len); +} +int usb_set_remote_wakeup(struct usb_host_device *host_dev) +{ + return usb_control_msg(host_dev, USB_REQ_SET_FEATURE, USB_RECIP_DEVICE, + USB_DEVICE_REMOTE_WAKEUP, 0, NULL, 0); +} +int get_device_status(struct usb_host_device *host_dev) +{ + u16 status; + return usb_control_msg(host_dev, USB_REQ_GET_STATUS, USB_DIR_IN, 0, 0, (u8 *)&status, 2); +} +int usb_get_device_qualifier(struct usb_host_device *host_dev, u8 *buffer) +{ + return usb_control_msg(host_dev, + USB_REQ_GET_DESCRIPTOR, + USB_DIR_IN, + (USB_DT_DEVICE_QUALIFIER << 8), + 0, + buffer, + 0x0a); + +} +#define AOA_CMD51 0x33 +#define AOA_CMD52 0x34 +#define AOA_CMD53 0x35 + + + + +int usb_get_aoa_version(struct usb_host_device *host_dev, u16 *version) +{ + return usb_control_msg(host_dev, + AOA_CMD51, + USB_DIR_IN | USB_TYPE_VENDOR, + 0, + 0, + version, + 2); +} +int usb_set_credentials(struct usb_host_device *host_dev, const char *string, int index) +{ + return usb_control_msg(host_dev, + AOA_CMD52, + USB_DIR_OUT | USB_TYPE_VENDOR, + 0, + index, + (u8 *)string, + strlen(string)); +} +int usb_switch2aoa(struct usb_host_device *host_dev) +{ + return usb_control_msg(host_dev, + AOA_CMD53, + USB_DIR_OUT | USB_TYPE_VENDOR, + 0, + 0, + NULL, + 0); +} +int usb_switch2slave(struct usb_host_device *host_dev) +{ + return usb_control_msg(host_dev, + 0x51, + USB_DIR_OUT | USB_TYPE_VENDOR, + 0, + 0, + NULL, + 0); +} +/* Control request for registering a HID device. + * Upon registering, a unique ID is sent by the accessory in the + * value parameter. This ID will be used for future commands for + * the device + * + * requestType: USB_DIR_OUT | USB_TYPE_VENDOR + * request: ACCESSORY_REGISTER_HID_DEVICE + * value: Accessory assigned ID for the HID device + * index: total length of the HID report descriptor + * data none + */ +#define ACCESSORY_REGISTER_HID 54 +int usb_aoa_register_hid(struct usb_host_device *host_dev, u16 value, u16 index) +{ + return usb_control_msg(host_dev, + ACCESSORY_REGISTER_HID, + USB_DIR_OUT | USB_TYPE_VENDOR, + value, + index, + NULL, + 0); +} +/* Control request for unregistering a HID device. + * + * requestType: USB_DIR_OUT | USB_TYPE_VENDOR + * request: ACCESSORY_REGISTER_HID + * value: Accessory assigned ID for the HID device + * index: 0 + * data none + */ +#define ACCESSORY_UNREGISTER_HID 55 +int usb_aoa_unregister_hid(struct usb_host_device *host_dev, u16 value) +{ + return usb_control_msg(host_dev, + ACCESSORY_UNREGISTER_HID, + USB_DIR_OUT | USB_TYPE_VENDOR, + value, + 0, + NULL, + 0); +} + +/* Control request for sending the HID report descriptor. + * If the HID descriptor is longer than the endpoint zero max packet size, + * the descriptor will be sent in multiple ACCESSORY_SET_HID_REPORT_DESC + * commands. The data for the descriptor must be sent sequentially + * if multiple packets are needed. + * + * requestType: USB_DIR_OUT | USB_TYPE_VENDOR + * request: ACCESSORY_SET_HID_REPORT_DESC + * value: Accessory assigned ID for the HID device + * index: offset of data in descriptor + * (needed when HID descriptor is too big for one packet) + * data the HID report descriptor + */ +#define ACCESSORY_SET_HID_REPORT_DESC 56 +int usb_aoa_set_hid_report_desc(struct usb_host_device *host_dev, u16 value, u16 offset, const char *pbuf, u32 len) +{ + return usb_control_msg(host_dev, + ACCESSORY_SET_HID_REPORT_DESC, + USB_DIR_OUT | USB_TYPE_VENDOR, + value, + offset, + (u8 *)pbuf, + len); +} + +/* Control request for sending HID events. + * + * requestType: USB_DIR_OUT | USB_TYPE_VENDOR + * request: ACCESSORY_SEND_HID_EVENT + * value: Accessory assigned ID for the HID device + * index: 0 + * data the HID report for the event + */ +#define ACCESSORY_SEND_HID_EVENT 57 +int usb_aoa_send_hid_event(struct usb_host_device *host_dev, u16 value, const u8 *pbuf, u32 len) +{ + return usb_control_msg(host_dev, + ACCESSORY_SEND_HID_EVENT, + USB_DIR_OUT | USB_TYPE_VENDOR, + value, + 0, + (u8 *)pbuf, + len); +} +int get_ms_extended_compat_id(struct usb_host_device *host_dev, u8 *buffer) +{ + return usb_control_msg(host_dev, + 0x01, + USB_DIR_IN | USB_RECIP_DEVICE | USB_TYPE_VENDOR, + 0x0000, + 4, + buffer, + 0x28); +} + + +int usb_set_interface(struct usb_host_device *host_dev, u8 interface, u8 alternateSetting) +{ + log_info("%s Set Interface:%d AlternateSetting:%d", __func__, interface, alternateSetting); + return usb_control_msg(host_dev, + USB_REQ_SET_INTERFACE, + USB_RECIP_INTERFACE, + alternateSetting, + interface, + NULL, + 0); + +} + +int usb_audio_sampling_frequency_control(struct usb_host_device *host_dev, u32 ep, u32 sampe_rate) +{ + log_info("%s ep:%d sampe_rate:%d", __func__, ep, sampe_rate); + return usb_control_msg(host_dev, + 1, + USB_TYPE_CLASS | USB_RECIP_ENDPOINT, + 0x0100, + ep, + &sampe_rate, + 3); +} +int usb_audio_volume_control(struct usb_host_device *host_dev, u8 feature_id, u8 channel_num, u16 volume) +{ + log_info("%s featureID:%d vol:%x", __func__, feature_id, volume); + return usb_control_msg(host_dev, + 1, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, + (0x02 << 8) | channel_num, + feature_id << 8, + &volume, + 2); +} +int usb_audio_mute_control(struct usb_host_device *host_dev, u8 feature_id, u8 mute) +{ + log_info("%s featureID:%d mute:%d", __func__, feature_id, mute); + return usb_control_msg(host_dev, + 1, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0x0100, + feature_id << 8, + &mute, + 1); +} +#endif diff --git a/apps/common/usb/host/usb_ctrl_transfer.h b/apps/common/usb/host/usb_ctrl_transfer.h new file mode 100644 index 0000000..fc346af --- /dev/null +++ b/apps/common/usb/host/usb_ctrl_transfer.h @@ -0,0 +1,71 @@ +#ifndef __USB_CTRL_TRANSFER_H__ +#define __USB_CTRL_TRANSFER_H__ + +#include "usb/ch9.h" +#include "usb/usb_phy.h" +#include "device/device.h" +#include "usb_config.h" + + +/* + * USB Packet IDs (PIDs) + */ +#define USB_PID_EXT 0xf0 /* USB 2.0 LPM ECN */ +#define USB_PID_OUT 0xe1 +#define USB_PID_ACK 0xd2 +#define USB_PID_DATA0 0xc3 +#define USB_PID_PING 0xb4 /* USB 2.0 */ +#define USB_PID_SOF 0xa5 +#define USB_PID_NYET 0x96 /* USB 2.0 */ +#define USB_PID_DATA2 0x87 /* USB 2.0 */ +#define USB_PID_SPLIT 0x78 /* USB 2.0 */ +#define USB_PID_IN 0x69 +#define USB_PID_NAK 0x5a +#define USB_PID_DATA1 0x4b +#define USB_PID_PREAMBLE 0x3c /* Token mode */ +#define USB_PID_ERR 0x3c /* USB 2.0: handshake mode */ +#define USB_PID_SETUP 0x2d +#define USB_PID_STALL 0x1e +#define USB_PID_MDATA 0x0f /* USB 2.0 */ + + + +struct ctlXfer { + struct usb_ctrlrequest setup; + void *buffer; + u8 stage; +}; + + +int usb_clear_feature(struct usb_host_device *usb_dev, u32 ep); +int set_address(struct usb_host_device *usb_dev, u8 devnum); +int usb_get_device_descriptor(struct usb_host_device *usb_dev, struct usb_device_descriptor *desc); +int usb_get_string_descriptor(struct usb_host_device *usb_dev, struct usb_device_descriptor *desc); +int set_configuration(struct usb_host_device *usb_dev); +int set_configuration_add_value(struct usb_host_device *host_dev, u16 value); +int get_config_descriptor(struct usb_host_device *usb_dev, void *cfg_desc, u32 len); +int get_config_descriptor_add_value_l(struct usb_host_device *host_dev, void *cfg_desc, u32 len, u8 value_l); +int get_msd_max_lun(struct usb_host_device *usb_dev, void *lun); +int set_msd_reset(struct usb_host_device *usb_dev); +int hid_set_idle(struct usb_host_device *usb_dev, u32 id); +int hid_get_report(struct usb_host_device *usb_dev, u8 *report, u8 report_id, u16 report_len); +int hid_set_output_report(struct usb_host_device *usb_dev, u8 *report, u8 report_id, u8 report_len); +int usb_set_remote_wakeup(struct usb_host_device *usb_dev); +int get_device_status(struct usb_host_device *usb_dev); +int usb_get_device_qualifier(struct usb_host_device *usb_dev, u8 *buffer); + +int usb_get_aoa_version(struct usb_host_device *host_dev, u16 *version); +int usb_set_credentials(struct usb_host_device *host_dev, const char *string, int index); +int usb_switch2aoa(struct usb_host_device *host_dev); +int usb_switch2slave(struct usb_host_device *host_dev); +int usb_aoa_register_hid(struct usb_host_device *host_dev, u16 value, u16 index); +int usb_aoa_set_hid_report_desc(struct usb_host_device *host_dev, u16 value, u16 offset, const char *pbuf, u32 len); +int usb_aoa_send_hid_event(struct usb_host_device *host_dev, u16 value, const u8 *pbuf, u32 len); +int get_ms_extended_compat_id(struct usb_host_device *host_dev, u8 *buffer); + +int usb_set_interface(struct usb_host_device *host_dev, u8 interface, u8 alternateSetting); +int usb_audio_sampling_frequency_control(struct usb_host_device *host_dev, u32 ep, u32 sampe_rate); +int usb_audio_volume_control(struct usb_host_device *host_dev, u8 feature_id, u8 channel_num, u16 volume); +int usb_audio_mute_control(struct usb_host_device *host_dev, u8 feature_id, u8 mute); + +#endif diff --git a/apps/common/usb/host/usb_hid_keys.h b/apps/common/usb/host/usb_hid_keys.h new file mode 100644 index 0000000..4947e11 --- /dev/null +++ b/apps/common/usb/host/usb_hid_keys.h @@ -0,0 +1,353 @@ +/** + * USB HID Keyboard scan codes as per USB spec 1.11 + * plus some additional codes + * + * Created by MightyPork, 2016 + * Public domain + * + * Adapted from: + * https://source.android.com/devices/input/keyboard-devices.html + */ + +#ifndef USB_HID_KEYS +#define USB_HID_KEYS + +struct keyboard_data_t { + u8 fun_key; + u8 res; + u8 Keypad[6]; +} _GNU_PACKED_ ; + +struct mouse_data_t { + u8 btn; + s16 x; + s16 y; + s8 wheel; + s8 ac_pan; +} _GNU_PACKED_ ; +struct point_t { + u8 tip_switch: 2; + /* u8 in_range: 1; */ + u8 res: 2; + u8 cid: 4; + s16 x; + s16 y; +} _GNU_PACKED_ ; + +struct touch_screen_t { + struct point_t p[3]; +} _GNU_PACKED_; + +struct mouse_point_t { + u8 btn; + s8 x; + s8 y; + s8 wheel; +} _GNU_PACKED_; +/** + * Modifier masks - used for the first byte in the HID report. + * NOTE: The second byte in the report is reserved, 0x00 + */ +#define _KEY_MOD_LCTRL 0x01 +#define _KEY_MOD_LSHIFT 0x02 +#define _KEY_MOD_LALT 0x04 +#define _KEY_MOD_LMETA 0x08 +#define _KEY_MOD_RCTRL 0x10 +#define _KEY_MOD_RSHIFT 0x20 +#define _KEY_MOD_RALT 0x40 +#define _KEY_MOD_RMETA 0x80 + +/** + * Scan codes - last N slots in the HID report (usually 6). + * 0x00 if no key pressed. + * + * If more than N keys are pressed, the HID reports + * KEY_ERR_OVF in all slots to indicate this condition. + */ + +#define _KEY_NONE 0x00 // No key pressed +#define _KEY_ERR_OVF 0x01 // Keyboard Error Roll Over - used for all slots if too many keys are pressed ("Phantom key") +// 0x02 // Keyboard POST Fail +// 0x03 // Keyboard Error Undefined +#define _KEY_A 0x04 // Keyboard a and A +#define _KEY_B 0x05 // Keyboard b and B +#define _KEY_C 0x06 // Keyboard c and C +#define _KEY_D 0x07 // Keyboard d and D +#define _KEY_E 0x08 // Keyboard e and E +#define _KEY_F 0x09 // Keyboard f and F +#define _KEY_G 0x0a // Keyboard g and G +#define _KEY_H 0x0b // Keyboard h and H +#define _KEY_I 0x0c // Keyboard i and I +#define _KEY_J 0x0d // Keyboard j and J +#define _KEY_K 0x0e // Keyboard k and K +#define _KEY_L 0x0f // Keyboard l and L +#define _KEY_M 0x10 // Keyboard m and M +#define _KEY_N 0x11 // Keyboard n and N +#define _KEY_O 0x12 // Keyboard o and O +#define _KEY_P 0x13 // Keyboard p and P +#define _KEY_Q 0x14 // Keyboard q and Q +#define _KEY_R 0x15 // Keyboard r and R +#define _KEY_S 0x16 // Keyboard s and S +#define _KEY_T 0x17 // Keyboard t and T +#define _KEY_U 0x18 // Keyboard u and U +#define _KEY_V 0x19 // Keyboard v and V +#define _KEY_W 0x1a // Keyboard w and W +#define _KEY_X 0x1b // Keyboard x and X +#define _KEY_Y 0x1c // Keyboard y and Y +#define _KEY_Z 0x1d // Keyboard z and Z + +#define _KEY_1 0x1e // Keyboard 1 and ! +#define _KEY_2 0x1f // Keyboard 2 and @ +#define _KEY_3 0x20 // Keyboard 3 and # +#define _KEY_4 0x21 // Keyboard 4 and $ +#define _KEY_5 0x22 // Keyboard 5 and % +#define _KEY_6 0x23 // Keyboard 6 and ^ +#define _KEY_7 0x24 // Keyboard 7 and & +#define _KEY_8 0x25 // Keyboard 8 and * +#define _KEY_9 0x26 // Keyboard 9 and ( +#define _KEY_0 0x27 // Keyboard 0 and ) + +#define _KEY_ENTER 0x28 // Keyboard Return (ENTER) +#define _KEY_ESC 0x29 // Keyboard ESCAPE +#define _KEY_BACKSPACE 0x2a // Keyboard DELETE (Backspace) +#define _KEY_TAB 0x2b // Keyboard Tab +#define _KEY_SPACE 0x2c // Keyboard Spacebar +#define _KEY_MINUS 0x2d // Keyboard - and _ +#define _KEY_EQUAL 0x2e // Keyboard = and + +#define _KEY_LEFTBRACE 0x2f // Keyboard [ and { +#define _KEY_RIGHTBRACE 0x30 // Keyboard ] and } +#define _KEY_BACKSLASH 0x31 // Keyboard \ and | +#define _KEY_HASHTILDE 0x32 // Keyboard Non-US # and ~ +#define _KEY_SEMICOLON 0x33 // Keyboard ; and : +#define _KEY_APOSTROPHE 0x34 // Keyboard ' and " +#define _KEY_GRAVE 0x35 // Keyboard ` and ~ +#define _KEY_COMMA 0x36 // Keyboard , and < +#define _KEY_DOT 0x37 // Keyboard . and > +#define _KEY_SLASH 0x38 // Keyboard / and ? +#define _KEY_CAPSLOCK 0x39 // Keyboard Caps Lock + +#define _KEY_F1 0x3a // Keyboard F1 +#define _KEY_F2 0x3b // Keyboard F2 +#define _KEY_F3 0x3c // Keyboard F3 +#define _KEY_F4 0x3d // Keyboard F4 +#define _KEY_F5 0x3e // Keyboard F5 +#define _KEY_F6 0x3f // Keyboard F6 +#define _KEY_F7 0x40 // Keyboard F7 +#define _KEY_F8 0x41 // Keyboard F8 +#define _KEY_F9 0x42 // Keyboard F9 +#define _KEY_F10 0x43 // Keyboard F10 +#define _KEY_F11 0x44 // Keyboard F11 +#define _KEY_F12 0x45 // Keyboard F12 + +#define _KEY_SYSRQ 0x46 // Keyboard Print Screen +#define _KEY_SCROLLLOCK 0x47 // Keyboard Scroll Lock +#define _KEY_PAUSE 0x48 // Keyboard Pause +#define _KEY_INSERT 0x49 // Keyboard Insert +#define _KEY_HOME 0x4a // Keyboard Home +#define _KEY_PAGEUP 0x4b // Keyboard Page Up +#define _KEY_DELETE 0x4c // Keyboard Delete Forward +#define _KEY_END 0x4d // Keyboard End +#define _KEY_PAGEDOWN 0x4e // Keyboard Page Down +#define _KEY_RIGHT 0x4f // Keyboard Right Arrow +#define _KEY_LEFT 0x50 // Keyboard Left Arrow +#define _KEY_DOWN 0x51 // Keyboard Down Arrow +#define _KEY_UP 0x52 // Keyboard Up Arrow + +#define _KEY_NUMLOCK 0x53 // Keyboard Num Lock and Clear +#define _KEY_KPSLASH 0x54 // Keypad / +#define _KEY_KPASTERISK 0x55 // Keypad * +#define _KEY_KPMINUS 0x56 // Keypad - +#define _KEY_KPPLUS 0x57 // Keypad + +#define _KEY_KPENTER 0x58 // Keypad ENTER +#define _KEY_KP1 0x59 // Keypad 1 and End +#define _KEY_KP2 0x5a // Keypad 2 and Down Arrow +#define _KEY_KP3 0x5b // Keypad 3 and PageDn +#define _KEY_KP4 0x5c // Keypad 4 and Left Arrow +#define _KEY_KP5 0x5d // Keypad 5 +#define _KEY_KP6 0x5e // Keypad 6 and Right Arrow +#define _KEY_KP7 0x5f // Keypad 7 and Home +#define _KEY_KP8 0x60 // Keypad 8 and Up Arrow +#define _KEY_KP9 0x61 // Keypad 9 and Page Up +#define _KEY_KP0 0x62 // Keypad 0 and Insert +#define _KEY_KPDOT 0x63 // Keypad . and Delete + +#define _KEY_102ND 0x64 // Keyboard Non-US \ and | +#define _KEY_COMPOSE 0x65 // Keyboard Application +#define _KEY_POWER 0x66 // Keyboard Power +#define _KEY_KPEQUAL 0x67 // Keypad = + +#define _KEY_F13 0x68 // Keyboard F13 +#define _KEY_F14 0x69 // Keyboard F14 +#define _KEY_F15 0x6a // Keyboard F15 +#define _KEY_F16 0x6b // Keyboard F16 +#define _KEY_F17 0x6c // Keyboard F17 +#define _KEY_F18 0x6d // Keyboard F18 +#define _KEY_F19 0x6e // Keyboard F19 +#define _KEY_F20 0x6f // Keyboard F20 +#define _KEY_F21 0x70 // Keyboard F21 +#define _KEY_F22 0x71 // Keyboard F22 +#define _KEY_F23 0x72 // Keyboard F23 +#define _KEY_F24 0x73 // Keyboard F24 + +#define _KEY_OPEN 0x74 // Keyboard Execute +#define _KEY_HELP 0x75 // Keyboard Help +#define _KEY_PROPS 0x76 // Keyboard Menu +#define _KEY_FRONT 0x77 // Keyboard Select +#define _KEY_STOP 0x78 // Keyboard Stop +#define _KEY_AGAIN 0x79 // Keyboard Again +#define _KEY_UNDO 0x7a // Keyboard Undo +#define _KEY_CUT 0x7b // Keyboard Cut +#define _KEY_COPY 0x7c // Keyboard Copy +#define _KEY_PASTE 0x7d // Keyboard Paste +#define _KEY_FIND 0x7e // Keyboard Find +#define _KEY_MUTE 0x7f // Keyboard Mute +#define _KEY_VOLUMEUP 0x80 // Keyboard Volume Up +#define _KEY_VOLUMEDOWN 0x81 // Keyboard Volume Down +// 0x82 Keyboard Locking Caps Lock +// 0x83 Keyboard Locking Num Lock +// 0x84 Keyboard Locking Scroll Lock +#define _KEY_KPCOMMA 0x85 // Keypad Comma +// 0x86 Keypad Equal Sign +#define _KEY_RO 0x87 // Keyboard International1 +#define _KEY_KATAKANAHIRAGANA 0x88 // Keyboard International2 +#define _KEY_YEN 0x89 // Keyboard International3 +#define _KEY_HENKAN 0x8a // Keyboard International4 +#define _KEY_MUHENKAN 0x8b // Keyboard International5 +#define _KEY_KPJPCOMMA 0x8c // Keyboard International6 +// 0x8d Keyboard International7 +// 0x8e Keyboard International8 +// 0x8f Keyboard International9 +#define _KEY_HANGEUL 0x90 // Keyboard LANG1 +#define _KEY_HANJA 0x91 // Keyboard LANG2 +#define _KEY_KATAKANA 0x92 // Keyboard LANG3 +#define _KEY_HIRAGANA 0x93 // Keyboard LANG4 +#define _KEY_ZENKAKUHANKAKU 0x94 // Keyboard LANG5 +// 0x95 Keyboard LANG6 +// 0x96 Keyboard LANG7 +// 0x97 Keyboard LANG8 +// 0x98 Keyboard LANG9 +// 0x99 Keyboard Alternate Erase +// 0x9a Keyboard SysReq/Attention +// 0x9b Keyboard Cancel +// 0x9c Keyboard Clear +// 0x9d Keyboard Prior +// 0x9e Keyboard Return +// 0x9f Keyboard Separator +// 0xa0 Keyboard Out +// 0xa1 Keyboard Oper +// 0xa2 Keyboard Clear/Again +// 0xa3 Keyboard CrSel/Props +// 0xa4 Keyboard ExSel + +// 0xb0 Keypad 00 +// 0xb1 Keypad 000 +// 0xb2 Thousands Separator +// 0xb3 Decimal Separator +// 0xb4 Currency Unit +// 0xb5 Currency Sub-unit +#define _KEY_KPLEFTPAREN 0xb6 // Keypad ( +#define _KEY_KPRIGHTPAREN 0xb7 // Keypad ) +// 0xb8 Keypad { +// 0xb9 Keypad } +// 0xba Keypad Tab +// 0xbb Keypad Backspace +// 0xbc Keypad A +// 0xbd Keypad B +// 0xbe Keypad C +// 0xbf Keypad D +// 0xc0 Keypad E +// 0xc1 Keypad F +// 0xc2 Keypad XOR +// 0xc3 Keypad ^ +// 0xc4 Keypad % +// 0xc5 Keypad < +// 0xc6 Keypad > +// 0xc7 Keypad & +// 0xc8 Keypad && +// 0xc9 Keypad | +// 0xca Keypad || +// 0xcb Keypad : +// 0xcc Keypad # +// 0xcd Keypad Space +// 0xce Keypad @ +// 0xcf Keypad ! +// 0xd0 Keypad Memory Store +// 0xd1 Keypad Memory Recall +// 0xd2 Keypad Memory Clear +// 0xd3 Keypad Memory Add +// 0xd4 Keypad Memory Subtract +// 0xd5 Keypad Memory Multiply +// 0xd6 Keypad Memory Divide +// 0xd7 Keypad +/- +// 0xd8 Keypad Clear +// 0xd9 Keypad Clear Entry +// 0xda Keypad Binary +// 0xdb Keypad Octal +// 0xdc Keypad Decimal +// 0xdd Keypad Hexadecimal + +#define _KEY_LEFTCTRL 0xe0 // Keyboard Left Control +#define _KEY_LEFTSHIFT 0xe1 // Keyboard Left Shift +#define _KEY_LEFTALT 0xe2 // Keyboard Left Alt +#define _KEY_LEFTMETA 0xe3 // Keyboard Left GUI +#define _KEY_RIGHTCTRL 0xe4 // Keyboard Right Control +#define _KEY_RIGHTSHIFT 0xe5 // Keyboard Right Shift +#define _KEY_RIGHTALT 0xe6 // Keyboard Right Alt +#define _KEY_RIGHTMETA 0xe7 // Keyboard Right GUI + +#define _KEY_MEDIA_PLAYPAUSE 0xe8 +#define _KEY_MEDIA_STOPCD 0xe9 +#define _KEY_MEDIA_PREVIOUSSONG 0xea +#define _KEY_MEDIA_NEXTSONG 0xeb +#define _KEY_MEDIA_EJECTCD 0xec +#define _KEY_MEDIA_VOLUMEUP 0xed +#define _KEY_MEDIA_VOLUMEDOWN 0xee +#define _KEY_MEDIA_MUTE 0xef +#define _KEY_MEDIA_WWW 0xf0 +#define _KEY_MEDIA_BACK 0xf1 +#define _KEY_MEDIA_FORWARD 0xf2 +#define _KEY_MEDIA_STOP 0xf3 +#define _KEY_MEDIA_FIND 0xf4 +#define _KEY_MEDIA_SCROLLUP 0xf5 +#define _KEY_MEDIA_SCROLLDOWN 0xf6 +#define _KEY_MEDIA_EDIT 0xf7 +#define _KEY_MEDIA_SLEEP 0xf8 +#define _KEY_MEDIA_COFFEE 0xf9 +#define _KEY_MEDIA_REFRESH 0xfa +#define _KEY_MEDIA_CALC 0xfb + +#define _KEY_CUSTOM_CTRL_VOL_UP 0x00e9 +#define _KEY_CUSTOM_CTRL_VOL_DOWN 0x00ea +#define _KEY_CUSTOM_CTRL_MUTE 0x00e2 +#define _KEY_CUSTOM_CTRL_FORWARD 0x00b5 +#define _KEY_CUSTOM_CTRL_STOP 0x00cd +#define _KEY_CUSTOM_CTRL_BACK 0x00b6 +#define _KEY_CUSTOM_CTRL_MUSIC 0x0183 +#define _KEY_CUSTOM_CTRL_CALCULATOR 0x0192 +#define _KEY_CUSTOM_CTRL_SEARCH 0x0221 +#define _KEY_CUSTOM_CTRL_EMAIL 0x018A +#define _KEY_CUSTOM_CTRL_HOME 0x0223 +#define _KEY_BRIGHTNESS_INCREASE 0x006F +#define _KEY_BRIGHTNESS_REDUCTION 0x0070 +#define _KEY_ZOOM_IN 0x022D +#define _KEY_ZOOM_OUT 0x022E +#define _KEY_CUSTOM_COPY 0x021B +#define _KEY_CUSTOM_CUT 0x021C +#define _KEY_CUSTOM_PASTE 0x021D +#define _KEY_CUSTOM_SELECT_ALL 0x021E +#define _KEY_CUSTOM_SPLIT_SCREEN 0x0196 +#define _KEY_CUSTOM_LOCK 0x0030 +#define _KEY_CUSTOM_ESC 0x0223 +#define _KEY_CUSTOM_CALENDAR 0x018e +#define _KEY_CUSTOM_MESSAGE 0X018d + +#define _KEY_CUSTOM_BROWER 0x0231 +#define _KEY_CUSTOM_PROCESS 0x023a + +#define _KEY_CUSTOM_SET 0x029b + +#define LED_NUM_LOCK 0x01 +#define LED_CAPS_LOCK 0x02 +#define LED_SCROLL_CLOCK 0x04 +#endif + diff --git a/apps/common/usb/host/usb_host.c b/apps/common/usb/host/usb_host.c new file mode 100644 index 0000000..e13c415 --- /dev/null +++ b/apps/common/usb/host/usb_host.c @@ -0,0 +1,740 @@ +#include "includes.h" +#include "app_config.h" +#include "device_drive.h" +/* #include "os/os_compat.h" */ +#if USB_HOST_ENABLE +#include "usb_config.h" +#include "usb/host/usb_host.h" +#include "usb/usb_phy.h" +#include "usb_ctrl_transfer.h" +#include "usb_storage.h" +#include "adb.h" +#include "aoa.h" +#include "hid.h" +#include "audio.h" + +#if TCFG_USB_APPLE_DOCK_EN +#include "apple_dock/iAP.h" +#include "apple_mfi.h" +#endif + +#define LOG_TAG_CONST USB +#define LOG_TAG "[mount]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +static struct usb_host_device host_devices[USB_MAX_HW_NUM];// SEC(.usb_h_bss); + +#define device_to_usbdev(device) ((struct usb_host_device *)((device)->private_data)) + + +int host_dev_status(const struct usb_host_device *host_dev) +{ + return ((host_dev)->private_data.status); +} + +u32 host_device2id(const struct usb_host_device *host_dev) +{ +#if USB_MAX_HW_NUM > 1 + return ((host_dev)->private_data.usb_id); +#else + return 0; +#endif +} +const struct usb_host_device *host_id2device(const usb_dev id) +{ +#if USB_MAX_HW_NUM > 1 + return &host_devices[id]; +#else + return &host_devices[0]; +#endif +} +int usb_sem_init(struct usb_host_device *host_dev) +{ + usb_dev usb_id = host_device2id(host_dev); + + usb_host_config(usb_id); + + OS_SEM *sem = zalloc(sizeof(OS_SEM)); + ASSERT(sem, "usb alloc sem error"); + host_dev->sem = sem; + g_printf("%s %x %x ", __func__, host_dev, sem); + os_sem_create(host_dev->sem, 0); + return 0; +} +int usb_sem_pend(struct usb_host_device *host_dev, u32 timeout) +{ + if (host_dev->sem == NULL) { + return 1; + } + int ret = os_sem_pend(host_dev->sem, timeout); + if (ret) { + r_printf("%s %d ", __func__, ret); + } + return ret; +} +int usb_sem_post(struct usb_host_device *host_dev) +{ + if (host_dev->sem == NULL) { + return 1; + } + int ret = os_sem_post(host_dev->sem); + if (ret) { + r_printf("%s %d ", __func__, ret); + } + return 0; +} +int usb_sem_del(struct usb_host_device *host_dev) +{ + usb_dev usb_id = host_device2id(host_dev); + + r_printf("1"); + if (host_dev->sem == NULL) { + return 0; + } + r_printf("2"); + r_printf("3"); +#if USB_HUB + if (host_dev && host_ep->sem && host_dev->father == NULL) { + os_sem_del(host_dev->sem); + } +#else + if (host_dev && host_dev->sem) { + os_sem_del(host_dev->sem, 0); + } +#endif + r_printf("4"); + g_printf("%s %x %x ", __func__, host_dev, host_dev->sem); + free(host_dev->sem); + r_printf("5"); + host_dev->sem = NULL; + r_printf("6"); + usb_host_free(usb_id); + r_printf("7"); + return 0; +} + +/** + * @brief usb_descriptor_parser + * + * @param device + * @param pBuf + * @param total_len + * + * @return + */ +static int _usb_msd_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf) +{ + log_info("find udisk @ interface %d", interface_num); +#if TCFG_UDISK_ENABLE + return usb_msd_parser(host_dev, interface_num, pBuf); +#else + return USB_DT_INTERFACE_SIZE; +#endif +} +static int _usb_apple_mfi_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf) +{ + log_info("find udisk @ interface %d", interface_num); +#if TCFG_USB_APPLE_DOCK_EN + return usb_apple_mfi_parser(host_dev, interface_num, pBuf); +#else + return USB_DT_INTERFACE_SIZE; +#endif +} +static int _usb_adb_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf) +{ + log_info("find adb @ interface %d", interface_num); +#if TCFG_ADB_ENABLE + return usb_adb_parser(host_dev, interface_num, pBuf); +#else + return USB_DT_INTERFACE_SIZE; +#endif +} +static int _usb_aoa_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf) +{ + log_info("find aoa @ interface %d", interface_num); +#if TCFG_AOA_ENABLE + return usb_aoa_parser(host_dev, interface_num, pBuf); +#else + return USB_DT_INTERFACE_SIZE; +#endif + +} +static int _usb_hid_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf) +{ + log_info("find hid @ interface %d", interface_num); +#if TCFG_HID_HOST_ENABLE + return usb_hid_parser(host_dev, interface_num, pBuf); +#else + return USB_DT_INTERFACE_SIZE; +#endif +} +static int _usb_audio_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf) +{ + log_info("find audio @ interface %d", interface_num); +#if TCFG_HOST_AUDIO_ENABLE + return usb_audio_parser(host_dev, interface_num, pBuf); +#else + return USB_DT_INTERFACE_SIZE; +#endif +} +static int _usb_adb_interface_ptp_mtp_parse(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf) +{ + log_info("find adbmtp @ interface %d", interface_num); +#if TCFG_ADB_ENABLE + return usb_adb_interface_ptp_mtp_parse(host_dev, interface_num, pBuf); +#else + return USB_DT_INTERFACE_SIZE; +#endif +} +static int usb_descriptor_parser(struct usb_host_device *host_dev, const u8 *pBuf, u32 total_len, struct usb_device_descriptor *device_desc) +{ + int len = 0; + u8 interface_num = 0; + struct usb_private_data *private_data = &host_dev->private_data; + + struct usb_config_descriptor *cfg_desc = (struct usb_config_descriptor *)pBuf; + + if (cfg_desc->bDescriptorType != USB_DT_CONFIG || + cfg_desc->bLength < USB_DT_CONFIG_SIZE) { + log_error("invalid descriptor for config bDescriptorType = %d bLength= %d", + cfg_desc->bDescriptorType, cfg_desc->bLength); + return -USB_DT_CONFIG; + } + + log_info("idVendor %x idProduct %x", device_desc->idVendor, device_desc->idProduct); + + len += USB_DT_CONFIG_SIZE; + pBuf += USB_DT_CONFIG_SIZE; + int i = 0; + u32 have_find_valid_class = 0; + while (len < total_len) { + if (interface_num > 4) { + log_error("interface_num too much"); + break; + } + + struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf; + if (interface->bDescriptorType == USB_DT_INTERFACE) { + + printf("inf class %x subclass %x ep %d", + interface->bInterfaceClass, interface->bInterfaceSubClass, interface->bNumEndpoints); + + if (interface->bInterfaceClass == USB_CLASS_MASS_STORAGE) { + i = _usb_msd_parser(host_dev, interface_num, pBuf); + if (i < 0) { + log_error("---%s %d---", __func__, __LINE__); + len = total_len; + } else { + interface_num++; + len += i; + pBuf += i; + have_find_valid_class = true; + } + } else if ((device_desc->idVendor == 0x05AC) && + ((device_desc->idProduct & 0xff00) == 0x1200)) { + i = _usb_apple_mfi_parser(host_dev, interface_num, pBuf); + if (i < 0) { + log_error("---%s %d---", __func__, __LINE__); + len = total_len; + } else { + interface_num++; + len += i; + pBuf += i; + have_find_valid_class = true; + } + } else if (interface->bInterfaceClass == USB_CLASS_AUDIO) { + i = _usb_audio_parser(host_dev, interface_num, pBuf); + if (i < 0) { + log_error("---%s %d---", __func__, __LINE__); + len = total_len; + } else { + interface_num++; + len += i; + pBuf += i; + have_find_valid_class = true; + } + } else if ((interface->bInterfaceClass == 0xff) && + (interface->bInterfaceSubClass == USB_CLASS_ADB)) { + i = _usb_adb_parser(host_dev, interface_num, pBuf); + if (i < 0) { + log_error("---%s %d---", __func__, __LINE__); + len = total_len; + } else { + interface_num++; + len += i; + pBuf += i; + have_find_valid_class = true; + } + } else if ((device_desc->idVendor == 0x18d1) && + ((device_desc->idProduct & 0x2d00) == 0x2d00)) { + i = _usb_aoa_parser(host_dev, interface_num, pBuf); + if (i < 0) { + log_error("---%s %d---", __func__, __LINE__); + len = total_len; + } else { + interface_num++; + len += i; + pBuf += i; + have_find_valid_class = true; + } + } else if (interface->bInterfaceClass == USB_CLASS_HID) { + i = _usb_hid_parser(host_dev, interface_num, pBuf); + if (i < 0) { + log_error("---%s %d---", __func__, __LINE__); + len = total_len; + } else { + interface_num++; + len += i; + pBuf += i; + have_find_valid_class = true; + } + } else if ((interface->bNumEndpoints == 3) && + (interface->bInterfaceClass == 0xff || interface->bInterfaceClass == 0x06)) { + i = _usb_adb_interface_ptp_mtp_parse(host_dev, interface_num, pBuf); + if (i < 0) { + log_error("---%s %d---", __func__, __LINE__); + len = total_len; + } else { + interface_num++; + len += i; + pBuf += i; + } + have_find_valid_class = true; + } else if ((interface->bInterfaceClass == 0xff) && + (interface->bInterfaceSubClass == 0xff)) { + i = _usb_aoa_parser(host_dev, interface_num, pBuf); + if (i < 0) { + log_error("---%s %d---", __func__, __LINE__); + len = total_len; + } else { + interface_num++; + len += i; + pBuf += i; + } + have_find_valid_class = true; + + } else { + log_info("find unsupport [class %x subClass %x] @ interface %d", + interface->bInterfaceClass, + interface->bInterfaceSubClass, + interface_num); + + len += USB_DT_INTERFACE_SIZE; + pBuf += USB_DT_INTERFACE_SIZE; + } + } else { + /* log_error("unknown section %d %d", len, pBuf[0]); */ + if (pBuf[0]) { + len += pBuf[0]; + pBuf += pBuf[0]; + } else { + len = total_len; + } + } + } + + + log_debug("len %d total_len %d", len, total_len); + return !have_find_valid_class; +} + + +/* --------------------------------------------------------------------------*/ +/** + * @brief usb_host_suspend + * + * @param usb + * + * @return + */ +/* --------------------------------------------------------------------------*/ +void usb_host_suspend(const usb_dev usb_id) +{ + usb_h_entry_suspend(usb_id); +} + +void usb_host_resume(const usb_dev usb_id) +{ + usb_h_resume(usb_id); +} + +static u32 _usb_host_mount(const usb_dev usb_id, u32 retry, u32 reset_delay, u32 mount_timeout) +{ + u32 ret = DEV_ERR_NONE; + struct usb_host_device *host_dev = &host_devices[usb_id]; + struct usb_private_data *private_data = &host_dev->private_data; + + + for (int i = 0; i < retry; i++) { + usb_h_sie_init(usb_id); + ret = usb_host_init(usb_id, reset_delay, mount_timeout); + if (ret) { + reset_delay += 10; + continue; + } + + void *const ep0_dma = usb_h_get_ep_buffer(usb_id, 0); + usb_set_dma_taddr(usb_id, 0, ep0_dma); + + usb_sie_enable(usb_id);//enable sie intr + usb_mdelay(reset_delay); + + /**********get device descriptor*********/ + struct usb_device_descriptor device_desc; + private_data->usb_id = usb_id; + private_data->status = 0; + private_data->devnum = 0; + private_data->ep0_max_packet_size = 8; + ret = usb_get_device_descriptor(host_dev, &device_desc); + + /**********set address*********/ + usb_mdelay(20); + u8 devnum = rand32() % 16 + 1; + ret = set_address(host_dev, devnum); + check_usb_mount(ret); + private_data->devnum = devnum ; + + /**********get device descriptor*********/ + usb_mdelay(20); + ret = usb_get_device_descriptor(host_dev, &device_desc); + check_usb_mount(ret); + private_data->ep0_max_packet_size = device_desc.bMaxPacketSize0; + + /**********get config descriptor*********/ + struct usb_config_descriptor cfg_desc; + ret = get_config_descriptor(host_dev, &cfg_desc, USB_DT_CONFIG_SIZE); + check_usb_mount(ret); + +#if USB_H_MALLOC_ENABLE + u8 *desc_buf = zalloc(cfg_desc.wTotalLength + 16); + ASSERT(desc_buf, "desc_buf"); +#else + u8 desc_buf[128] = {0}; + cfg_desc.wTotalLength = min(sizeof(desc_buf), cfg_desc.wTotalLength); +#endif + + ret = get_config_descriptor(host_dev, desc_buf, cfg_desc.wTotalLength); + check_usb_mount(ret); + + /**********set configuration*********/ + ret = set_configuration(host_dev); + /* printf_buf(desc_buf, cfg_desc.wTotalLength); */ + ret |= usb_descriptor_parser(host_dev, desc_buf, cfg_desc.wTotalLength, &device_desc); +#if USB_H_MALLOC_ENABLE + log_info("free:desc_buf= %x\n", desc_buf); + free(desc_buf); +#endif + check_usb_mount(ret); + + break;//succ + } + + if (ret) { + goto __exit_fail; + } + private_data->status = 1; + return DEV_ERR_NONE; + +__exit_fail: + printf("usb_probe fail"); + private_data->status = 0; + usb_sie_close(usb_id); + return ret; +} +static int usb_event_notify(const struct usb_host_device *host_dev, u32 ev) +{ + const usb_dev id = host_device2id(host_dev); + struct sys_event event; + if (ev == 0) { + event.u.dev.event = DEVICE_EVENT_IN; + } else { + event.u.dev.event = DEVICE_EVENT_CHANGE; + } + u8 have_post_event = 0; + u8 no_send_event; + for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) { + no_send_event = 0; + event.u.dev.value = 0; + if (host_dev->interface_info[i]) { + switch (host_dev->interface_info[i]->ctrl->interface_class) { +#if TCFG_UDISK_ENABLE + case USB_CLASS_MASS_STORAGE: + if (have_post_event & BIT(0)) { + no_send_event = 1; + } else { + have_post_event |= BIT(0); + } + if (id == 0) { + event.u.dev.value = (int)"udisk0"; + } else { + event.u.dev.value = (int)"udisk1"; + } + break; +#endif + +#if TCFG_ADB_ENABLE + case USB_CLASS_ADB: + if (have_post_event & BIT(1)) { + no_send_event = 1; + } else { + have_post_event |= BIT(1); + } + if (id == 0) { + event.u.dev.value = (int)"adb0"; + } else { + event.u.dev.value = (int)"adb1"; + } + break; +#endif +#if TCFG_AOA_ENABLE + case USB_CLASS_AOA: + if (have_post_event & BIT(2)) { + no_send_event = 1; + } else { + have_post_event |= BIT(2); + } + if (id == 0) { + event.u.dev.value = (int)"aoa0"; + } else { + event.u.dev.value = (int)"aoa1"; + } + break; +#endif +#if TCFG_HID_HOST_ENABLE + case USB_CLASS_HID: + if (have_post_event & BIT(3)) { + no_send_event = 1; + } else { + have_post_event |= BIT(3); + } + if (id == 0) { + event.u.dev.value = (int)"hid0"; + } else { + event.u.dev.value = (int)"hid1"; + } + break; +#endif +#if TCFG_HOST_AUDIO_ENABLE + case USB_CLASS_AUDIO: + if (have_post_event & BIT(4)) { + no_send_event = 1; + } else { + have_post_event |= BIT(4); + } + if (id == 0) { + event.u.dev.value = (int)"audio0"; + } else { + event.u.dev.value = (int)"audio1"; + } + break; +#endif + } + + if (!no_send_event && event.u.dev.value) { + log_info("event %x interface %x class %x %s", + event.u.dev.event, i, + host_dev->interface_info[i]->ctrl->interface_class, + (const char *)event.u.dev.value); + + /* printf("usb_host_mount notify >>>>>>>>>>>\n"); */ + event.arg = (void *)DEVICE_EVENT_FROM_USB_HOST; + event.type = SYS_DEVICE_EVENT; + sys_event_notify(&event); + } + } + } + if (have_post_event) { + return DEV_ERR_NONE; + } else { + return DEV_ERR_UNKNOW_CLASS; + } + +} + +const char *usb_host_valid_class_to_dev(const usb_dev id, u32 usbclass) +{ +#if USB_MAX_HW_NUM > 1 + const usb_dev usb_id = id; +#else + const usb_dev usb_id = 0; +#endif + struct usb_host_device *host_dev = &host_devices[usb_id]; + u32 itf_class; + + for (int i = 0; i < MAX_HOST_INTERFACE; i++) { + if (host_dev->interface_info[i] && + host_dev->interface_info[i]->ctrl) { + itf_class = host_dev->interface_info[i]->ctrl->interface_class; + if (itf_class == usbclass) { + switch (itf_class) { + case USB_CLASS_MASS_STORAGE: + if (usb_id == 0) { + return "udisk0"; + } else if (usb_id == 1) { + return "udisk1"; + } + break; + case USB_CLASS_ADB: + if (usb_id == 0) { + return "adb0"; + } else if (usb_id == 1) { + return "adb1"; + } + break; + case USB_CLASS_AOA: + if (usb_id == 0) { + return "aoa0"; + } else if (usb_id == 1) { + return "aoa1"; + } + break; + case USB_CLASS_HID: + if (usb_id == 0) { + return "hid0"; + } else if (usb_id == 1) { + return "hid1"; + } + break; + } + } + } + } + return NULL; +} + +/* --------------------------------------------------------------------------*/ +/** + * @brief usb_host_mount + * + * @param usb + * + * @return + */ +/* --------------------------------------------------------------------------*/ +u32 usb_host_mount(const usb_dev id, u32 retry, u32 reset_delay, u32 mount_timeout) +{ +#if USB_MAX_HW_NUM > 1 + const usb_dev usb_id = id; +#else + const usb_dev usb_id = 0; +#endif + + u32 ret; + struct usb_host_device *host_dev = &host_devices[usb_id]; + memset(host_dev, 0, sizeof(*host_dev)); + + host_dev->private_data.usb_id = id; + usb_otg_resume(usb_id); //打开usb host之后恢复otg检测 + + usb_sem_init(host_dev); + usb_h_isr_reg(usb_id, 1, 0); + + + ret = _usb_host_mount(usb_id, retry, reset_delay, mount_timeout); + if (ret) { + goto __exit_fail; + } + return usb_event_notify(host_dev, 0); + +__exit_fail: + usb_sie_disable(usb_id); + usb_sem_del(host_dev); + return ret; +} + +static u32 _usb_host_unmount(const usb_dev usb_id) +{ + struct usb_host_device *host_dev = &host_devices[usb_id]; + + struct usb_private_data *private_data = &host_dev->private_data; + private_data->status = 0; + + usb_sem_post(host_dev);//拔掉设备时,让读写线程快速释放 + + for (u8 i = 0; i < MAX_HOST_INTERFACE; i++) { + if (host_dev->interface_info[i]) { + host_dev->interface_info[i]->ctrl->set_power(host_dev, -1); + host_dev->interface_info[i] = NULL; + } + } + + usb_sie_close(usb_id); + return DEV_ERR_NONE; +} + +/* --------------------------------------------------------------------------*/ +/** + * @brief usb_host_unmount + * + * @param usb + * + * @return + */ +/* --------------------------------------------------------------------------*/ +/* u32 usb_host_unmount(const usb_dev usb_id, char *device_name) */ +u32 usb_host_unmount(const usb_dev id) +{ +#if USB_MAX_HW_NUM > 1 + const usb_dev usb_id = id; +#else + const usb_dev usb_id = 0; +#endif + u32 ret; + struct usb_host_device *host_dev = &host_devices[usb_id]; + struct sys_event event; + +#if (TCFG_UDISK_ENABLE && UDISK_READ_512_ASYNC_ENABLE) + _usb_stor_async_wait_sem(host_dev); +#endif + ret = _usb_host_unmount(usb_id); + if (ret) { + goto __exit_fail; + } + usb_sem_del(host_dev); + + /* printf("usb_host_unmount notify >>>>>>>>>>>\n"); */ + event.arg = (void *)DEVICE_EVENT_FROM_USB_HOST; + event.type = SYS_DEVICE_EVENT; + event.u.dev.event = DEVICE_EVENT_OUT; + sys_event_notify(&event); + return DEV_ERR_NONE; + +__exit_fail: + return ret; +} + +u32 usb_host_remount(const usb_dev id, u32 retry, u32 delay, u32 ot, u8 notify) +{ +#if USB_MAX_HW_NUM > 1 + const usb_dev usb_id = id; +#else + const usb_dev usb_id = 0; +#endif + u32 ret; + struct sys_event event; + + ret = _usb_host_unmount(usb_id); + if (ret) { + goto __exit_fail; + } + ret = _usb_host_mount(usb_id, retry, delay, ot); + if (ret) { + goto __exit_fail; + } + + if (notify) { + struct usb_host_device *host_dev = &host_devices[usb_id]; + usb_event_notify(host_dev, 1); + } + return DEV_ERR_NONE; + +__exit_fail: + return ret; +} +#endif diff --git a/apps/common/usb/host/usb_storage.c b/apps/common/usb/host/usb_storage.c new file mode 100644 index 0000000..7ef6c2c --- /dev/null +++ b/apps/common/usb/host/usb_storage.c @@ -0,0 +1,2041 @@ +/** * @file usb_storage.c + * @brief + * @author chenrixin@zh-jieli.com + * @version 1.00 + * @date 2017-02-09 + */ + +#include "asm/includes.h" +#include "system/timer.h" +#include "device/ioctl_cmds.h" +#include "usb/host/usb_host.h" +#include "usb_ctrl_transfer.h" +#include "usb_bulk_transfer.h" +#include "device_drive.h" +#include "usb_storage.h" +#include "usb_config.h" +#include "app_config.h" + +#if TCFG_UDISK_ENABLE +#define LOG_TAG_CONST USB +#define LOG_TAG "[USB]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +static int set_stor_power(struct usb_host_device *host_dev, u32 value); +static int get_stor_power(struct usb_host_device *host_dev, u32 value); + +const struct interface_ctrl udisk_ops = { + .interface_class = USB_CLASS_MASS_STORAGE, + .set_power = set_stor_power, + .get_power = get_stor_power, + .ioctl = NULL, +}; + + +static struct mass_storage mass_stor = {0};//SEC(.usb_h_udisk); + +static const struct usb_interface_info udisk_inf = { + .ctrl = (struct interface_ctrl *) &udisk_ops, + .dev.disk = &mass_stor, +}; + +static struct device udisk_device ;//SEC(.usb_h_udisk); +static struct udisk_end_desc udisk_ep ;//SEC(.usb_h_udisk); + +#define host_device2disk(host_dev) (udisk_inf.dev.disk) + +/** + * @brief usb_stor_force_reset + * + * @param device + * + * @return + */ +static int usb_stor_force_reset(const usb_dev usb_id) +{ + /* struct usb_host_device *host_dev = device_to_usbdev(device); + const usb_dev usb_id = host_device2id(host_dev); */ + log_error("============usb_stor_force_reset===============\n"); + return usb_h_force_reset(usb_id); +} +static void usb_stor_set_curlun(struct mass_storage *disk, u32 i) +{ + disk->curlun = i; +} +static int usb_stor_get_curlun(struct mass_storage *disk) +{ + return disk->curlun; +} +static int usb_stor_txmaxp(struct mass_storage *disk) +{ +#if HUSB_MODE + return udisk_ep.txmaxp; +#else + return 0x40; +#endif +} +static int usb_stor_rxmaxp(struct mass_storage *disk) +{ +#if HUSB_MODE + return udisk_ep.rxmaxp; +#else + return 0x40; +#endif +} +#define UDISK_MUTEX_TIMEOUT 5000/10 //5s +static int usb_h_mutex_pend(struct usb_host_device *host_dev) +{ + struct mass_storage *disk = host_device2disk(host_dev); + /* putchar('{'); */ + /* putchar('^'); */ + /* putchar('['); */ + + int r = os_mutex_pend(&disk->mutex, UDISK_MUTEX_TIMEOUT); + if (r) { + log_error("-----------------%d -------------------", r); + } + if (r == OS_TIMEOUT) { + return OS_TIMEOUT; + } + return r; +} +static int usb_h_mutex_post(struct usb_host_device *host_dev) +{ + struct mass_storage *disk = host_device2disk(host_dev); + /* putchar(']'); */ + /* putchar('^'); */ + /* putchar('}'); */ + + int r = os_mutex_post(&disk->mutex); + return r; +} +static int set_stor_power(struct usb_host_device *host_dev, u32 value) +{ + struct mass_storage *disk = host_device2disk(host_dev); + log_debug("%s() %d ", __func__, disk->dev_status); + if (disk == NULL || disk->dev_status == DEV_IDLE) { + return 0; + } + int r = usb_h_mutex_pend(host_dev); + + if (disk->dev_status == DEV_READ || disk->dev_status == DEV_WRITE) { + if (value == -1) { + log_error("%s disk busy", __func__); + } + } + + disk->dev_status = DEV_CLOSE; + + log_debug("%s() %d ", __func__, disk->dev_status); + + if (r == OS_TIMEOUT) { + return OS_TIMEOUT; + } + usb_h_mutex_post(host_dev); + return DEV_ERR_NONE; +} + +static int get_stor_power(struct usb_host_device *host_dev, u32 value) +{ + return DEV_ERR_NONE; +} + +/** + * @brief usb_init_cbw + * + * @param device + */ +static void usb_init_cbw(struct device *device, u32 dir, u32 opcode, u32 length) +{ + struct mass_storage *disk = host_device2disk(host_dev); + + memset(&disk->cbw, 0x00, sizeof(struct usb_scsi_cbw)); + u32 curlun = usb_stor_get_curlun(disk); + disk->cbw.dCBWSignature = CBW_SIGNATURE; + disk->cbw.dCBWTag = rand32(); + disk->cbw.bCBWLUN = curlun; + disk->cbw.lun = curlun << 5; + disk->cbw.bmCBWFlags = dir; + disk->cbw.operationCode = opcode; + disk->cbw.dCBWDataTransferLength = cpu_to_le32(length); +} + +static int usb_stor_check_status(struct usb_host_device *host_dev) +{ + struct mass_storage *disk = host_device2disk(host_dev); + + if (!host_dev) { + return -DEV_ERR_NOT_MOUNT; + } + if (!disk) { + return -DEV_ERR_NOT_MOUNT; + } + if (disk->dev_status == DEV_IDLE) { + return -DEV_ERR_NOT_MOUNT; + } else if (disk->dev_status == DEV_CLOSE) { + return -DEV_ERR_NOT_MOUNT; + } + return 0; +} + +static int usb_stor_reset(struct device *device) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + int ret = DEV_ERR_NONE; + + if (disk == NULL) { + return -DEV_ERR_NOT_MOUNT; + } + //mass storage reset request + ret = set_msd_reset(host_dev); + return ret; +} + +static int usb_stor_resume(struct device *device) +{ + struct usb_device_descriptor device_desc; + struct usb_host_device *host_dev = device_to_usbdev(device); + const usb_dev usb_id = host_device2id(host_dev); + u8 devnum = host_dev->private_data.devnum; + int ret = DEV_ERR_NONE; + ret = usb_stor_check_status(host_dev); + if (ret) { + return ret; + } + + usb_h_resume(usb_id); + + ret = usb_get_device_descriptor(host_dev, &device_desc); + if (ret == 0) { + return ret; + } + usb_h_force_reset(usb_id); + ret = set_address(host_dev, devnum); + if (ret) { + log_error("%s() @ %d %x\n", __func__, __LINE__, ret); + usb_sie_close(usb_id); + return -ret; + } + ret = usb_get_device_descriptor(host_dev, &device_desc); + if (ret) { + log_error("%s() @ %d %x\n", __func__, __LINE__, ret); + usb_sie_close(usb_id); + return -ret; + } + return ret; +} +/** + * @brief usb_stor_inquiry + * + * @param device + * + * @return + */ +static int _usb_stor_inquiry(struct device *device) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + const usb_dev usb_id = host_device2id(host_dev); + + const u32 txmaxp = usb_stor_txmaxp(disk); + const u32 rxmaxp = usb_stor_rxmaxp(disk); + + int ret = DEV_ERR_NONE; + struct inquiry_data inquiry; + + log_info("usb_stor_inquiry disk =%x", (u32)disk); + + u32 total_lun = disk->lun; + u32 init_lun = 0; + + for (int i = 0; i <= total_lun; i ++) { + usb_stor_set_curlun(disk, i); + usb_init_cbw(device, USB_DIR_IN, INQUIRY, sizeof(struct inquiry_data)); + disk->cbw.bCBWLength = 0x06; + disk->cbw.lba[2] = sizeof(struct inquiry_data); + + //cbw + ret = usb_bulk_only_send(device, + udisk_ep.host_epout, + txmaxp, + udisk_ep.target_epout, + (u8 *)&disk->cbw, + sizeof(struct usb_scsi_cbw)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + //data + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&inquiry, + sizeof(struct inquiry_data)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } else if (ret != sizeof(struct inquiry_data)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + /* printf_buf(&inquiry, sizeof(struct inquiry_data)); */ + //csw + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->csw, + sizeof(struct usb_scsi_csw)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + if (inquiry.PeripheralDeviceType) { + if (init_lun == i) { + if (init_lun < total_lun) { + init_lun++; + } else { + init_lun = 0; + } + } + } + } + usb_stor_set_curlun(disk, init_lun); + + return DEV_ERR_NONE; +__exit: + log_error("%s---%d\n", __func__, __LINE__); + return ret; +} + +static int usb_stor_inquiry(struct device *device) +{ + int ret; + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + ret = usb_stor_check_status(host_dev); + if (ret) { + return ret; + } + ret = usb_h_mutex_pend(host_dev); + if (ret == OS_TIMEOUT) { + return -OS_TIMEOUT; + } + + ret = _usb_stor_inquiry(device); + usb_h_mutex_post(host_dev); + return ret; +} +/** + * @brief usb_stor_test_unit_ready + * + * @param device + * + * @return + */ +static int _usb_stor_test_unit_ready(struct device *device) +{ + int ret = DEV_ERR_NONE; + + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + const usb_dev usb_id = host_device2id(host_dev); + + const u32 txmaxp = usb_stor_txmaxp(disk); + const u32 rxmaxp = usb_stor_rxmaxp(disk); + + + usb_init_cbw(device, 0, TEST_UNIT_READY, 0); + disk->cbw.bCBWLength = 6; + //cbw + ret = usb_bulk_only_send(device, + udisk_ep.host_epout, + txmaxp, + udisk_ep.target_epout, + (u8 *)&disk->cbw, + sizeof(struct usb_scsi_cbw)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + //csw + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->csw, + sizeof(struct usb_scsi_csw)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + return DEV_ERR_NONE; +__exit: + log_error("%s---%d\n", __func__, __LINE__); + return ret; +} +static int usb_stor_test_unit_ready(struct device *device) +{ + int ret; + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + ret = usb_stor_check_status(host_dev); + if (ret) { + return ret; + } + ret = usb_h_mutex_pend(host_dev); + if (ret == OS_TIMEOUT) { + return -OS_TIMEOUT; + } + ret = _usb_stor_test_unit_ready(device); + usb_h_mutex_post(host_dev); + return ret; +} + +/** + * @brief usb_stor_mode_sense6 + * + * @param device + * + * @return + * + * @brief disk write protect inquiry + */ +static int _usb_stor_mode_sense6(struct device *device) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + const usb_dev usb_id = host_device2id(host_dev); + u8 *cdb; + int ret = DEV_ERR_NONE; + u8 data_buf[4]; + + + const u32 txmaxp = usb_stor_txmaxp(disk); + const u32 rxmaxp = usb_stor_rxmaxp(disk); + + usb_init_cbw(device, USB_DIR_IN, MODE_SENSE, 4); + disk->cbw.bCBWLUN = 6; + cdb = (u8 *)&disk->cbw.operationCode; + cdb[1] = 0; // PC | DBD + cdb[2] = 0x1c; //page code + cdb[3] = 0; //subpage code + cdb[4] = 192; //allocation length + cdb[5] = 0; //control; + //cbw + ret = usb_bulk_only_send(device, + udisk_ep.host_epout, + txmaxp, + udisk_ep.target_epout, + (u8 *)&disk->cbw, + sizeof(struct usb_scsi_cbw)); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + //data + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, udisk_ep.target_epin, + data_buf, + sizeof(data_buf)); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + disk->read_only = data_buf[2] == 0x80 ? 1 : 0; //write protect + + //csw + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->csw, + sizeof(struct usb_scsi_csw)); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_NONE; + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + return DEV_ERR_NONE; +__exit: + log_error("%s---%d\n", __func__, __LINE__); + return ret; +} +static int usb_stor_mode_sense6(struct device *device) +{ + int ret; + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + ret = usb_stor_check_status(host_dev); + if (ret) { + return ret; + } + ret = usb_h_mutex_pend(host_dev); + if (ret == OS_TIMEOUT) { + return -OS_TIMEOUT; + } + ret = _usb_stor_mode_sense6(device); + usb_h_mutex_post(host_dev); + return ret; + +} +/** + * @brief usb_stor_request_sense + * + * @param device + * + * @return + */ +static int _usb_stor_request_sense(struct device *device) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + const usb_dev usb_id = host_device2id(host_dev); + int ret = DEV_ERR_NONE; + + + const u32 txmaxp = usb_stor_txmaxp(disk); + const u32 rxmaxp = usb_stor_rxmaxp(disk); + + usb_init_cbw(device, USB_DIR_IN, REQUEST_SENSE, sizeof(struct request_sense_data)); + disk->cbw.bCBWLength = 0xC; + disk->cbw.lba[2] = sizeof(struct request_sense_data); + //cbw + ret = usb_bulk_only_send(device, + udisk_ep.host_epout, + txmaxp, + udisk_ep.target_epout, + (u8 *)&disk->cbw, + sizeof(struct usb_scsi_cbw)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + //data + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->sense, + sizeof(struct request_sense_data)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } else if (ret != sizeof(struct request_sense_data)) { + ret = -DEV_ERR_NONE; + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + /* printf_buf(&private_data->dev.disk->sense, sizeof(struct REQUEST_SENSE_DATA)); */ + //csw + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->csw, + sizeof(struct usb_scsi_csw)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + return DEV_ERR_NONE; +__exit: + log_error("%s---%d\n", __func__, __LINE__); + return ret; +} +static int usb_stor_request_sense(struct device *device) +{ + int ret; + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + ret = usb_stor_check_status(host_dev); + if (ret) { + return ret; + } + ret = usb_h_mutex_pend(host_dev); + if (ret == OS_TIMEOUT) { + return -OS_TIMEOUT; + } + ret = _usb_stor_request_sense(device); + usb_h_mutex_post(host_dev); + return ret; +} + +/** + * @brief usb_stor_read_capacity + * + * @param device + * + * @return + */ +static int _usb_stor_read_capacity(struct device *device) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + const usb_dev usb_id = host_device2id(host_dev); + int ret = DEV_ERR_NONE; + + if (disk == NULL) { + return -DEV_ERR_NOT_MOUNT; + } + + const u32 txmaxp = usb_stor_txmaxp(disk); + const u32 rxmaxp = usb_stor_rxmaxp(disk); + + u32 curlun = usb_stor_get_curlun(disk); + + usb_init_cbw(device, USB_DIR_IN, READ_CAPACITY, 8); + disk->cbw.bCBWLength = 0xA; + disk->cbw.bmCBWFlags = USB_DIR_IN; + disk->cbw.operationCode = READ_CAPACITY; + disk->capacity[curlun].block_size = 0; + disk->capacity[curlun].block_num = 0; + + //cbw + ret = usb_bulk_only_send(device, + udisk_ep.host_epout, + txmaxp, + udisk_ep.target_epout, + (u8 *)&disk->cbw, + sizeof(struct usb_scsi_cbw)); + + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + //data + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->capacity[curlun], + sizeof(struct read_capacity_data)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } else if (ret != sizeof(struct read_capacity_data)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + disk->capacity[curlun].block_size = be32_to_cpu(disk->capacity[curlun].block_size); + disk->capacity[curlun].block_num = be32_to_cpu(disk->capacity[curlun].block_num) + 1; + log_info("block_size=%d", disk->capacity[curlun].block_size); + log_info("block_num=%d", disk->capacity[curlun].block_num); + //csw + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->csw, + sizeof(struct usb_scsi_csw)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + return DEV_ERR_NONE; +__exit: + log_error("%s---%d\n", __func__, __LINE__); + return ret; +} +static int usb_stor_read_capacity(struct device *device) +{ + int ret; + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + ret = usb_stor_check_status(host_dev); + if (ret) { + return ret; + } + ret = usb_h_mutex_pend(host_dev); + if (ret == OS_TIMEOUT) { + return -OS_TIMEOUT; + } + ret = _usb_stor_read_capacity(device); + usb_h_mutex_post(host_dev); + return ret; +} + +static int _usb_stro_read_cbw_request(struct device *device, u32 num_lba, u32 lba) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + + const u32 txmaxp = usb_stor_txmaxp(disk); + u32 rx_len = num_lba * 512; //filesystem uses the fixed BLOCK_SIZE + u32 cur_lba = lba; + int ret = 0; + + disk->dev_status = DEV_READ; + disk->suspend_cnt = 0; + usb_init_cbw(device, USB_DIR_IN, READ_10, rx_len); + disk->cbw.bCBWLength = 0xA; + + cur_lba = cpu_to_be32(cur_lba); + memcpy(disk->cbw.lba, &cur_lba, sizeof(cur_lba)); + + disk->cbw.LengthH = HIBYTE(num_lba); + disk->cbw.LengthL = LOBYTE(num_lba); + + //cbw + ret = usb_bulk_only_send(device, + udisk_ep.host_epout, + txmaxp, + udisk_ep.target_epout, + (u8 *)&disk->cbw, + sizeof(struct usb_scsi_cbw)); + + if (ret < DEV_ERR_NONE) { + if (disk->dev_status != DEV_CLOSE) { + disk->dev_status = DEV_OPEN; + } + log_error("%s---%d", __func__, __LINE__); + return ret; + } + return num_lba; +} +static int _usb_stro_read_csw(struct device *device) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + const u32 rxmaxp = usb_stor_rxmaxp(disk); + int ret = 0; + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->csw, + sizeof(struct usb_scsi_csw)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d ret:%d\n", __func__, __LINE__, ret); + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + } + return ret; +} + +static int _usb_stor_read_block_finish(struct device *device, u32 remain_len, u8 num_lba, void *pBuf) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + const u32 txmaxp = usb_stor_txmaxp(disk); + const u32 rxmaxp = usb_stor_rxmaxp(disk); + int ret = 0; + int len = num_lba * 512; + while (remain_len) { + //读完剩余的包,再开始下一次请求 + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + pBuf, + len); + remain_len -= len; + if (remain_len == 0) { + //csw + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->csw, + sizeof(struct usb_scsi_csw)); + } + } + + return 0; +} +static int _usb_stor_read_big_block(struct device *device, u32 disk_block_size, void *pBuf, u8 num_lba, u32 lba) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + const u32 txmaxp = usb_stor_txmaxp(disk); + const u32 rxmaxp = usb_stor_rxmaxp(disk); + int ret = 0; + u32 rx_len = num_lba * 512; //filesystem uses the fixed BLOCK_SIZE + u8 num_block = disk_block_size / 512; //8 + u8 req_offset = lba % num_block; //计算block数据偏移量 + u8 send_cbw = 0; + if ((req_offset == 0) || (lba <= disk->prev_lba) || ((lba - disk->prev_lba) > num_block)) { + //sector 4k地址;或地址不连续时(地址小于上一次地址; 地址和上一次地址不属于同一个sector) + send_cbw = 1; + } else { + //地址连续 + send_cbw = 0; + } + /* y_printf("lba===%d prev_lba=%d req_offset===%d cbw:%d %d",lba,disk->prev_lba,req_offset,send_cbw,abs_value); */ + disk->prev_lba = lba; + lba = lba / num_block; + + if (send_cbw) { + _usb_stor_read_block_finish(device, disk->remain_len, num_lba, pBuf); //确保读完剩余包 */ + disk->remain_len = 0; + disk->dev_status = DEV_READ; + disk->suspend_cnt = 0; + usb_init_cbw(device, USB_DIR_IN, READ_10, disk_block_size / 512 * 512); + disk->cbw.bCBWLength = 0xA; + + lba = cpu_to_be32(lba); + memcpy(disk->cbw.lba, &lba, sizeof(lba)); + + disk->cbw.LengthH = HIBYTE(num_lba); + disk->cbw.LengthL = LOBYTE(num_lba); + //cbw + //请求disk_block_size 大小数据 + ret = usb_bulk_only_send(device, + udisk_ep.host_epout, + txmaxp, + udisk_ep.target_epout, + (u8 *)&disk->cbw, + sizeof(struct usb_scsi_cbw)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + disk->remain_len = disk_block_size; + } else { + req_offset = 0; //地址连续时,读一次data + } + //data + do { + //循环读取,直到读取到偏移量所在的数据为止 + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + pBuf, + rx_len); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + disk->remain_len -= rx_len; + + } while (req_offset--); + + if (!disk->remain_len) { //读完data,需要读csw + //csw + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->csw, + sizeof(struct usb_scsi_csw)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + } + + disk->dev_status = DEV_OPEN; + return num_lba; +__exit: + if (disk->dev_status != DEV_CLOSE) { + disk->dev_status = DEV_OPEN; + } + log_error("%s---%d", __func__, __LINE__); + return 0; +} + +int _usb_stor_async_wait_sem(struct usb_host_device *host_dev) +{ + int ret = 0; +#if UDISK_READ_512_ASYNC_ENABLE + local_irq_disable(); //这里关中断,避免获取变量值被中断打断 + if (get_async_mode() == BULK_ASYNC_MODE_ENTER) { + set_async_mode(BULK_ASYNC_MODE_SEM_PEND); + local_irq_enable(); + ret = os_sem_pend(host_dev->sem, 100); + if (ret) { + r_printf("ret timeout %d", ret); + return -DEV_ERR_TIMEOUT; + } + } else { + local_irq_enable(); + } +#endif + return ret; +} +#if UDISK_READ_BIGBLOCK_ASYNC_ENABLE +static int _usb_stro_read_async(struct device *device, void *pBuf, u32 num_lba, u32 lba) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + const usb_dev usb_id = host_device2id(host_dev); + + usb_h_mutex_pend(host_dev); + const u32 txmaxp = usb_stor_txmaxp(disk); + const u32 rxmaxp = usb_stor_rxmaxp(disk); + int ret = 0; + u8 read_block_num = UDISK_READ_ASYNC_BLOCK_NUM; + u32 rx_len = num_lba * 512; //filesystem uses the fixed BLOCK_SIZE + /* r_printf("read lba : %d %d\n",lba,disk->remain_len); */ + if ((lba != disk->async_prev_lba + 1) || disk->remain_len == 0) { + //这里要确保上次cbw 请求的数据读取完毕 + //data + while (disk->remain_len) { + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + NULL, + rx_len); + disk->remain_len -= rx_len; + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + disk->remain_len = 0; //data 接收错误直接发csw + } + if (disk->remain_len == 0) { + //csw + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->csw, + sizeof(struct usb_scsi_csw)); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + } + break; + } + } + _usb_stro_read_cbw_request(device, read_block_num, lba); //cbw + disk->remain_len = read_block_num * 512; + //data + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + pBuf, + rx_len); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + disk->remain_len -= rx_len; + } else { + //地址连续,直接读取预读的数据 + //data + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + pBuf, + rx_len); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + disk->remain_len -= rx_len; + if (disk->remain_len == 0) { + //预读数据读完,发csw + //csw + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->csw, + sizeof(struct usb_scsi_csw)); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + } + } + disk->async_prev_lba = lba; + + disk->dev_status = DEV_OPEN; + usb_h_mutex_post(host_dev); + return num_lba; +__exit: + if (disk->dev_status != DEV_CLOSE) { + disk->dev_status = DEV_OPEN; + } + log_error("%s---%d", __func__, __LINE__); + usb_h_mutex_post(host_dev); + return 0; +} +#endif +#if UDISK_READ_512_ASYNC_ENABLE +static int _usb_stro_read_async(struct device *device, void *pBuf, u32 num_lba, u32 lba) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + const usb_dev usb_id = host_device2id(host_dev); + + usb_h_mutex_pend(host_dev); + const u32 txmaxp = usb_stor_txmaxp(disk); + const u32 rxmaxp = usb_stor_rxmaxp(disk); + int ret = 0; + u32 rx_len = num_lba * 512; //filesystem uses the fixed BLOCK_SIZE + u8 read_block_num = UDISK_READ_ASYNC_BLOCK_NUM; + /* r_printf("lba : %d %d\n",lba,disk->remain_len); */ + _usb_stor_async_wait_sem(host_dev); + if ((lba != disk->async_prev_lba + 1)) { + if (disk->remain_len == 0) { + if (disk->need_send_csw) { + //已取完data,需要发csw + ret = _usb_stro_read_csw(device); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d ret:%d\n", __func__, __LINE__, ret); + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + } + disk->need_send_csw = 0; + } + } + //这里要确保上次cbw 请求的数据读取完毕 + //data + while (disk->remain_len) { + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + NULL, + rx_len); + disk->remain_len -= rx_len; + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + disk->remain_len = 0; //data 接收错误直接发csw + } + if (disk->remain_len == 0) { + //csw + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->csw, + sizeof(struct usb_scsi_csw)); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + } + break; + } + } + ret = _usb_stro_read_cbw_request(device, read_block_num, lba); //cbw + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + disk->remain_len = read_block_num * 512; + //data + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + pBuf, + rx_len); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + disk->remain_len -= rx_len; + if (disk->remain_len == 0) { + ret = _usb_stro_read_csw(device); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d ret:%d\n", __func__, __LINE__, ret); + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + } + } + } else { + memcpy(pBuf, disk->udisk_512_buf, rx_len); + if (disk->remain_len == 0) { + ret = _usb_stro_read_csw(device); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d ret:%d\n", __func__, __LINE__, ret); + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + } + } + } + disk->async_prev_lba = lba; + //异步预读 + if (disk->remain_len == 0) { + ret = _usb_stro_read_cbw_request(device, read_block_num, lba + 1); //cbw + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + disk->remain_len = read_block_num * 512; + } + //data + ret = usb_bulk_receive_async_no_wait(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + disk->udisk_512_buf, + rx_len); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + disk->remain_len -= rx_len; + if (disk->remain_len == 0) { + //data请求完,等待发送csw + disk->need_send_csw = 1; + } + + disk->dev_status = DEV_OPEN; + usb_h_mutex_post(host_dev); + return num_lba; +__exit: + if (disk->dev_status != DEV_CLOSE) { + disk->dev_status = DEV_OPEN; + } + log_error("%s---%d", __func__, __LINE__); + usb_h_mutex_post(host_dev); + return 0; +} +#endif +/** + * @brief usb_stor_read 从U盘的lba扇区读取num_lba个扇区 + * + * @param device 设备句柄 + * @param pBuf 读buffer缓冲区,芯片所有memory都可以 + * @param lba 需要读取的扇区地址 + * @param num_lba 需要读取的扇区数量 + * + * @return 负数表示失败 + * 大于0的表示读取的字节数(Byte) + */ +static int _usb_stor_read(struct device *device, void *pBuf, u32 num_lba, u32 lba) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + const usb_dev usb_id = host_device2id(host_dev); + + const u32 txmaxp = usb_stor_txmaxp(disk); + const u32 rxmaxp = usb_stor_rxmaxp(disk); + const u32 curlun = usb_stor_get_curlun(disk); + + u8 read_retry = 0; + int ret; + u32 rx_cnt; + /* u32 rx_len = num_lba * disk->capacity[curlun].block_size; */ + u32 rx_len = num_lba * 512; //filesystem uses the fixed BLOCK_SIZE + + if (disk->capacity[curlun].block_size > 512) { + // 扇区大于512Byte + return _usb_stor_read_big_block(device, disk->capacity[curlun].block_size, pBuf, num_lba, lba); + } + + if (lba + num_lba/* - 1*/ >= disk->capacity[curlun].block_num) { + return -DEV_ERR_OVER_CAPACITY; + } +#if (UDISK_READ_BIGBLOCK_ASYNC_ENABLE || UDISK_READ_512_ASYNC_ENABLE) + if (disk->async_en) { + return _usb_stro_read_async(device, pBuf, num_lba, lba); + } +#endif + + ret = _usb_stro_read_cbw_request(device, num_lba, lba); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + //data + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + pBuf, + rx_len); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + //csw + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->csw, + sizeof(struct usb_scsi_csw)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + disk->dev_status = DEV_OPEN; + return num_lba; + +__exit: + if (disk->dev_status != DEV_CLOSE) { + disk->dev_status = DEV_OPEN; + } + log_error("%s---%d", __func__, __LINE__); + return 0; +} +static int usb_stor_read(struct device *device, void *pBuf, u32 num_lba, u32 lba) +{ + int ret; + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + ret = usb_stor_check_status(host_dev); + if (ret) { + return ret; + } + ret = usb_h_mutex_pend(host_dev); + if (ret == OS_TIMEOUT) { + return -OS_TIMEOUT; + } + ret = _usb_stor_read(device, pBuf, num_lba, lba); + usb_h_mutex_post(host_dev); + return ret; +} + +/** + * @brief usb_stor_write 写数据到U盘 + * + * @param device + * @param pBuf 数据buffer + * @param lba 需要写入的扇区地址 + * @param num_lba 需要写入的扇区数量 + * + * @return 负数表示写入失败 + * 正数为写入的字节数 (Byte) + */ +static int _usb_stor_write(struct device *device, void *pBuf, u32 num_lba, u32 lba) +{ + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + const usb_dev usb_id = host_device2id(host_dev); + u32 ret; + + const u32 txmaxp = usb_stor_txmaxp(disk); + const u32 rxmaxp = usb_stor_rxmaxp(disk); + const u32 curlun = usb_stor_get_curlun(disk); + + if (lba + num_lba/* - 1*/ >= disk->capacity[curlun].block_num) { + log_error("%s %d", __func__, __LINE__); + return -DEV_ERR_OVER_CAPACITY; + } + + if (disk->capacity[curlun].block_size > 512) { + log_error(" %s disk bolock size %d not support write", __func__, disk->capacity[curlun].block_size); + return -DEV_ERR_NO_WRITE; + } + + if (disk->read_only) { + log_error("%s %d", __func__, __LINE__); + return -DEV_ERR_NO_WRITE; + } + + /* u32 tx_len = num_lba * disk->capacity[curlun].block_size; */ + u32 tx_len = num_lba * 512; //filesystem uses the fixed BLOCK_SIZE + +#if (UDISK_READ_BIGBLOCK_ASYNC_ENABLE || UDISK_READ_512_ASYNC_ENABLE) + /* r_printf("write lba : %d %d txlen:%d\n",lba,disk->remain_len,tx_len); */ + /* 确保预读read剩余的包读完,才开始写 */ + _usb_stor_async_wait_sem(host_dev); + while (disk->remain_len) { + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + NULL, + tx_len); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + disk->remain_len -= tx_len; + } + if (disk->remain_len == 0) { + //csw + if (disk->need_send_csw) { + ret = _usb_stro_read_csw(device); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + } + disk->need_send_csw = 0; + disk->async_prev_lba = 0; + } +#endif + + disk->dev_status = DEV_WRITE; + disk->suspend_cnt = 0; + usb_init_cbw(device, USB_DIR_OUT, WRITE_10, tx_len); + + disk->cbw.bCBWLength = 0xA; + + lba = cpu_to_be32(lba); + memcpy(disk->cbw.lba, &lba, sizeof(lba)); + + + disk->cbw.LengthH = HIBYTE(num_lba); + disk->cbw.LengthL = LOBYTE(num_lba); + + //cbw + ret = usb_bulk_only_send(device, + udisk_ep.host_epout, + txmaxp, + udisk_ep.target_epout, + (u8 *)&disk->cbw, + sizeof(struct usb_scsi_cbw)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + //data + ret = usb_bulk_only_send(device, + udisk_ep.host_epout, + txmaxp, + udisk_ep.target_epout, + pBuf, + tx_len); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + + //csw + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->csw, + sizeof(struct usb_scsi_csw)); + + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + goto __exit; + } + + if (disk->csw.bCSWStatus) { + ret = usb_stor_request_sense(device); + if (ret) { + ret = -DEV_ERR_OFFLINE; + } + + if (ret == -DEV_ERR_OFFLINE) { + log_error("%s:%d\n", __func__, __LINE__); + goto __exit; + } + log_info("usb_stor_sense =%x", disk->sense.SenseKey); + return 0; + } + + disk->dev_status = DEV_OPEN; + return num_lba;//DEV_ERR_NONE; + +__exit: + if (disk->dev_status != DEV_CLOSE) { + disk->dev_status = DEV_OPEN; + } + log_error("%s---%d\n", __func__, __LINE__); + /* usb_stor_force_reset(usb_id); */ + return 0; +} +static int usb_stor_write(struct device *device, void *pBuf, u32 num_lba, u32 lba) +{ + int ret; + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + ret = usb_stor_check_status(host_dev); + if (ret) { + return ret; + } + ret = usb_h_mutex_pend(host_dev); + if (ret == OS_TIMEOUT) { + return -OS_TIMEOUT; + } + ret = _usb_stor_write(device, pBuf, num_lba, lba); + usb_h_mutex_post(host_dev); + return ret; +} +#if ENABLE_DISK_HOTPLUG +static void usb_stor_tick_handle(void *arg) +{ + struct device *device = (struct device *)arg; + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev);//(device); + const usb_dev usb_id = host_device2id(host_dev); + + int ret; + + r_printf("A"); + if (disk == NULL) { + return; + } + r_printf("B"); + if (disk->dev_status == DEV_OPEN) { + r_printf("C"); + ret = usb_stor_read_capacity(device); + r_printf("D"); + } + +#if 0 +#if 1 + disk->suspend_cnt++; + if ((disk->suspend_cnt > 6) && (disk->dev_status == DEV_OPEN)) { + usb_h_entry_suspend(usb_id); + disk->suspend_cnt = 0; + disk->dev_status = DEV_SUSPEND; + } +#else + ret = usb_stor_test_unit_ready(device); + if (ret < DEV_ERR_NONE) { + return ; + } + if (disk->csw.bCSWStatus) { + usb_stor_request_sense(device); + /* puts("request sense\n"); */ + /* put_buf((u8 *)&disk->sense, sizeof(disk->sense)); */ + if ((disk->sense.SenseKey & 0x0f) == NOT_READY) { + if (disk->sense.ASC == 0x3a && disk->sense.ASCQ == 0x00) { + disk->media_sta_cur = 0; + } + } else if ((disk->sense.SenseKey & 0x0f) == UNIT_ATTENTION) { + if (disk->sense.ASC == 0x28 && disk->sense.ASCQ == 0x00) { + disk->media_sta_cur = 1; + } + } + } else { + disk->media_sta_cur = 1; + } + + if (disk->media_sta_cur != disk->media_sta_prev) { + if (disk->media_sta_cur) { + log_info("udisk media insert"); + usb_stor_read_capacity(device); + usb_stor_mode_sense6(device); + } else { + log_info("udisk media eject"); + } + } + disk->media_sta_prev = disk->media_sta_cur; +#endif +#endif +} +#endif + +/** + * @brief usb_stor_init + * + * @param device + * + * @return + */ +int usb_stor_init(struct device *device) +{ + log_debug("%s---%d\n", __func__, __LINE__); + int ret = DEV_ERR_NONE; + u32 state = 0; + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + log_error("%s() disk = %x", __func__, disk); + + if (!host_dev_status(host_dev)) { + return -DEV_ERR_OFFLINE; + } + + const usb_dev usb_id = host_device2id(host_dev); + if (host_dev->private_data.status == 0) { + return -ENODEV; + } + + if (!disk) { + log_error("%s not enough memory"); + return -DEV_ERR_OUTOFMEMORY; + } + + disk->dev_status = DEV_INIT; + + const u32 txmaxp = usb_stor_txmaxp(disk); + const u32 rxmaxp = usb_stor_rxmaxp(disk); + + u8 lun = 0; + ret = get_msd_max_lun(host_dev, &lun); + if (ret != DEV_ERR_NONE) { + /* disk->dev_status = DEV_IDLE; */ + /* usb_stor_force_reset(usb_id); */ + log_error("ret = %d\n", ret); + /* return ret; */ + } + + disk->lun = lun; + + int retry = 5; + while (retry) { + retry --; + if (ret == -DEV_ERR_OFFLINE) { + log_error("disk offline"); + break; + } + switch (state) { + case 0: + log_info("--- inquery ---"); + ret = usb_stor_inquiry(device); + if (ret < DEV_ERR_NONE) { + os_time_dly(retry); + if (retry == 3) { + ret = -DEV_ERR_OFFLINE; + } + } else { + state++; + } + break; + + case 1: + log_info("--- test unit ready ---"); + ret = usb_stor_test_unit_ready(device); + if (ret < DEV_ERR_NONE) { + os_time_dly(50); + } else if (disk->csw.bCSWStatus) { + os_time_dly(50); + ret = usb_stor_request_sense(device); + if ((disk->sense.SenseKey & 0x0f) != NO_SENSE) { + if (disk->sense.SenseKey == NOT_READY) { + os_time_dly(30); + disk->curlun++; + if (disk->curlun > disk->lun) { + disk->curlun = 0; + } + } + } + } else { + state++; + } + break; + + case 2: + log_info("--- read capacity ---"); + ret = usb_stor_read_capacity(device); + if (ret < DEV_ERR_NONE) { + os_time_dly(50); + } else if (disk->csw.bCSWStatus) { + os_time_dly(50); + ret = usb_stor_request_sense(device); + if ((disk->sense.SenseKey & 0x0f) != NO_SENSE) { + os_time_dly(30); + } + } else { + log_info("udisk mount succ"); + state = 0xff; + } + break; + + default: + retry = 0; + break; + } + } + state = 0; + + if (ret != DEV_ERR_NONE) { + disk->dev_status = DEV_IDLE; + /* usb_stor_force_reset(usb_id); */ + log_error("ret = %d\n", ret); + } else { + /* disk->test_unit_ready_tick = sys_timer_add(device,usb_stor_tick_handle,200); */ +#if ENABLE_DISK_HOTPLUG + disk->media_sta_cur = 1; + disk->media_sta_prev = 1; +#endif + } + disk->suspend_cnt = 0; + return ret; +} + +/** + * @brief usb_stor_ioctrl + * + * @param device + * @param cmd 支持下面的命令 + * |命令|功能| + * |---|---| + * |IOCTL_GET_ID|U盘位于总线的地址0表示不在线| + * |IOCTL_GET_BLOCK_SIZE|获取扇区大小| + * |IOCTL_GET_CAPACITY|获取磁盘容量| + * |IOCTL_GET_MAX_LUN|获取最大磁盘数量<最大支持两个磁盘>| + * |IOCTL_GET_CUR_LUN|获取当前的磁盘号| + * |IOCTL_SET_CUR_LUN|设置当前的磁盘号| + * @param arg + * + * @return 0----成功 + * 其他值---失败- + */ +static int usb_stor_ioctrl(struct device *device, u32 cmd, u32 arg) +{ + int ret = DEV_ERR_NONE; + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + const usb_dev usb_id = host_device2id(host_dev); + u32 devnum = host_dev->private_data.devnum; + u32 curlun = usb_stor_get_curlun(disk); + const u32 rxmaxp = usb_stor_rxmaxp(disk); + + if (disk == NULL) { + return -ENOTTY; + } + + switch (cmd) { + case IOCTL_GET_ID: + *(u32 *)arg = devnum; + break; + + case IOCTL_GET_BLOCK_SIZE: + *(u32 *)arg = disk->capacity[curlun].block_size; + break; + + case IOCTL_GET_BLOCK_NUMBER: + *(u32 *)arg = disk->capacity[curlun].block_num; + break; + + case IOCTL_GET_CAPACITY: + *(u32 *)arg = disk->capacity[curlun].block_num; + break; + + case IOCTL_GET_MAX_LUN: + *(u32 *)arg = disk->lun; + break; + + case IOCTL_GET_CUR_LUN: + *(u32 *)arg = curlun; + break; + + case IOCTL_SET_CUR_LUN: + if (arg > disk->lun) { + return -EINVAL; + } + usb_stor_set_curlun(disk, arg); + ret = usb_stor_read_capacity(device); + if (ret < 0) { + log_error("usb disk unit%d is not ready", curlun); + return -EFAULT; + } else if (disk->csw.bCSWStatus) { + usb_stor_request_sense(device); + if (disk->sense.SenseKey != NO_SENSE) { + log_error("usb disk unit%d is not ready", curlun); + } + return -EFAULT; + } + /* usb_stor_mode_sense6(device); */ + break; + + case IOCTL_CHECK_WRITE_PROTECT: + if (disk->read_only) { + *(u32 *)arg = 1; + } else { + *(u32 *)arg = 0; + } + break; + + case IOCTL_GET_STATUS: +#if ENABLE_DISK_HOTPLUG + if (disk->media_sta_cur) { +#else + if (1) { +#endif + log_info("usb disk unit%d is online", curlun); + *(u32 *)arg = 1; + } else { + log_info("usb disk unit%d is offline", curlun); + *(u32 *)arg = 0; + } + break; + + case IOCTL_SET_FORCE_RESET: + ret = usb_stor_force_reset(usb_id); + break; + case IOCTL_SET_ASYNC_MODE: + g_printf(">> UDISK IOCTL_SET_ASYNC_MODE %d\n", arg); +#if (UDISK_READ_BIGBLOCK_ASYNC_ENABLE || UDISK_READ_512_ASYNC_ENABLE) + usb_h_mutex_pend(host_dev); + _usb_stor_async_wait_sem(host_dev); + if (arg == 0) { + if (disk->remain_len == 0) { + if (disk->need_send_csw) { + //已取完data,需要发csw + ret = _usb_stro_read_csw(device); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d ret:%d\n", __func__, __LINE__, ret); + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + } + disk->need_send_csw = 0; + } + } + //这里要确保上次cbw 请求的数据读取完毕 + //data + while (disk->remain_len) { + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + NULL, + 512); + disk->remain_len -= 512; + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + disk->remain_len = 0; //data 接收错误直接发csw + } + if (disk->remain_len == 0) { + //csw + ret = usb_bulk_only_receive(device, + udisk_ep.host_epin, + rxmaxp, + udisk_ep.target_epin, + (u8 *)&disk->csw, + sizeof(struct usb_scsi_csw)); + if (ret < DEV_ERR_NONE) { + log_error("%s:%d\n", __func__, __LINE__); + } else if (ret != sizeof(struct usb_scsi_csw)) { + ret = -DEV_ERR_UNKNOW; + log_error("%s:%d\n", __func__, __LINE__); + } + break; + } + } + } + disk->async_en = arg; + disk->async_prev_lba = MASS_LBA_INIT; + disk->need_send_csw = 0; + set_async_mode(BULK_ASYNC_MODE_EXIT); + usb_h_mutex_post(host_dev); +#endif + break; + + default: + return -ENOTTY; + } + + return ret; +} + +/** + * @brief usb_msd_parser + * + * @param device + * @param pBuf + * + * @return + */ +int usb_msd_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf) +{ + struct usb_interface_descriptor *interface = (struct usb_interface_descriptor *)pBuf; + pBuf += sizeof(struct usb_interface_descriptor); + int len = 0; + const usb_dev usb_id = host_device2id(host_dev); + + udisk_device.private_data = host_dev; + + host_dev->interface_info[interface_num] = &udisk_inf; + + for (int endnum = 0; endnum < interface->bNumEndpoints; endnum++) { + struct usb_endpoint_descriptor *end_desc = (struct usb_endpoint_descriptor *)pBuf; + + if (end_desc->bDescriptorType != USB_DT_ENDPOINT || + end_desc->bLength != USB_DT_ENDPOINT_SIZE) { + log_error("ep bDescriptorType = %d bLength = %d", end_desc->bDescriptorType, end_desc->bLength); + return -USB_DT_ENDPOINT; + } + + len += USB_DT_ENDPOINT_SIZE; + pBuf += USB_DT_ENDPOINT_SIZE; + + if ((end_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) { + if (end_desc->bEndpointAddress & USB_DIR_IN) { + udisk_ep.host_epin = usb_get_ep_num(usb_id, USB_DIR_IN, USB_ENDPOINT_XFER_BULK); + udisk_ep.target_epin = end_desc->bEndpointAddress & 0x0f; +#if HUSB_MODE + udisk_ep.rxmaxp = end_desc->wMaxPacketSize; +#endif + log_debug("D(%d)->H(%d)", udisk_ep.target_epin, udisk_ep.host_epin); + } else { + udisk_ep.host_epout = usb_get_ep_num(usb_id, USB_DIR_OUT, USB_ENDPOINT_XFER_BULK); + udisk_ep.target_epout = end_desc->bEndpointAddress & 0x0f; +#if HUSB_MODE + udisk_ep.txmaxp = end_desc->wMaxPacketSize; +#endif + log_debug("H(%d)->D(%d)", udisk_ep.host_epout, udisk_ep.target_epout); + } + } + } + u8 *ep_buffer = usb_h_get_ep_buffer(usb_id, udisk_ep.host_epin | USB_DIR_IN); + usb_h_ep_config(usb_id, udisk_ep.host_epin | USB_DIR_IN, USB_ENDPOINT_XFER_BULK, 0, 0, ep_buffer, 64); + + + ep_buffer = usb_h_get_ep_buffer(usb_id, udisk_ep.host_epout | USB_DIR_OUT); + usb_h_ep_config(usb_id, udisk_ep.host_epout | USB_DIR_OUT, USB_ENDPOINT_XFER_BULK, 0, 0, ep_buffer, 64); + return len; +} +/** + * @brief usb_stor_open + * + * @param node + * @param device + * @param arg + * + * @return + */ +static int usb_stor_open(const char *name, struct device **device, void *arg) +{ + int ret; + *device = &udisk_device; + struct usb_host_device *host_dev = device_to_usbdev(*device); + struct mass_storage *disk = host_device2disk(host_dev); + const u32 curlun = usb_stor_get_curlun(disk); + log_debug("=====================usb_stor_open===================== %d", disk->dev_status); + if (disk->dev_status != DEV_IDLE) { + if (disk->dev_status == DEV_CLOSE) { + log_error("%s() fail, disconnect\n", __func__); + return -DEV_ERR_NOT_MOUNT; + } else { + return DEV_ERR_NONE; + } + } + memset(&disk->mutex, 0, sizeof(disk->mutex)); + os_mutex_create(&disk->mutex); + disk->remain_len = 0; + disk->prev_lba = 0; +#if (UDISK_READ_BIGBLOCK_ASYNC_ENABLE || UDISK_READ_512_ASYNC_ENABLE) + disk->async_prev_lba = MASS_LBA_INIT; + disk->need_send_csw = 0; + disk->async_en = 0; //默认关闭预读模式 + set_async_mode(BULK_ASYNC_MODE_EXIT); +#if UDISK_READ_512_ASYNC_ENABLE + if (!disk->udisk_512_buf) { + disk->udisk_512_buf = zalloc(512); + } +#endif +#endif + ret = usb_stor_init(*device); + if (ret) { + log_error("usb_stor_init err %d\n", ret); + return -ENODEV; + } + log_debug("device %x", (u32)*device); + + + usb_h_mutex_pend(host_dev); + if (*device) { + log_error("mass storage dev name %s", name); + disk->dev_status = DEV_OPEN; + usb_h_mutex_post(host_dev); + return DEV_ERR_NONE; + } else { + usb_h_mutex_post(host_dev); + return -ENODEV; + } +} + +/** + * @brief usb_stor_close + * + * @param device + * + * @return + */ +static int usb_stor_close(struct device *device) +{ + log_debug("%s---%d\n", __func__, __LINE__); + struct usb_host_device *host_dev = device_to_usbdev(device); + struct mass_storage *disk = host_device2disk(host_dev); + int ret; + if (disk->dev_status == DEV_IDLE) { + return 0; + } + log_info("=====================usb_stor_close====================="); + if (disk) { + log_info("=====================usb_stor_close===================== 333"); + ret = usb_h_mutex_pend(host_dev); + + disk->dev_status = DEV_IDLE; + + if (ret != OS_ERR_NONE) { + log_error("disk close pend timeout!!!\n"); + } else { + usb_h_mutex_post(host_dev); + } + log_info("=====================usb_stor_close===================== 1222 "); + + os_mutex_del(&disk->mutex, 0); + memset(&disk->mutex, 0, sizeof(disk->mutex)); +#if UDISK_READ_512_ASYNC_ENABLE + if (disk->udisk_512_buf) { + free(disk->udisk_512_buf); + disk->udisk_512_buf = NULL; + } + +#endif + } + return DEV_ERR_NONE; +} + +static bool usb_stor_online(const struct dev_node *node) +{ + struct device *device = &udisk_device; + struct mass_storage *disk = udisk_inf.dev.disk;; + if (disk) { + return true;//disk->media_sta_cur ? true : false; + } + return false; +} + +const struct device_operations mass_storage_ops = { + .init = NULL, + .online = usb_stor_online, + .open = usb_stor_open, + .read = usb_stor_read, + .write = usb_stor_write, + .ioctl = usb_stor_ioctrl, + .close = usb_stor_close, +}; + +static u8 usb_stor_idle_query(void) +{ + struct device *device = &udisk_device; + struct mass_storage *disk = host_device2disk(host_dev); + if (disk) { + return (disk->dev_status == DEV_IDLE) ? true : false; + } + return true; +} + +REGISTER_LP_TARGET(usb_stor_lp_target) = { + .name = "udisk", + .is_idle = usb_stor_idle_query, +}; + +#if 0 +u32 usb_host_mount(const usb_dev id, u32 retry, u32 reset_delay, u32 mount_timeout); +extern u8 msd_test_buf[32 * 1024]; +void dump_usb_buf(); +void usb_host_test() +{ +___usb_test: + usb_host_mount(0, 3, 20, 200); + struct device *device; + usb_stor_open("udisk0", &device, NULL); + log_info("%s---%d\n", __func__, __LINE__); + u32 lba = 0; + while (1) { + + u32 *p = (u32 *)msd_test_buf; + u32 numOflba = sizeof(msd_test_buf) / 512; + + if ((usb_stor_read(device, p, numOflba, lba)) != numOflba) { + printf("read error %d", lba); + while (1); + } +#if 1 + if (usb_stor_write(device, p, numOflba, lba) != numOflba) { + + printf("write error %d", lba); + while (1); + } + + if ((usb_stor_read(device, p, numOflba, lba)) != numOflba) { + printf("read error %d", lba); + while (1); + } +#endif + for (int i = 0; i < numOflba * 512 / 4; i++) { + if (p[i] != (i + lba * 0x80)) { + printf("@lba:%x offset %x %x != %x ", lba, i, p[i], i + lba * 0x80); + /* put_buf(p, numOflba * 512); */ + /* while (1); */ + } + } + wdt_clear(); + + lba += numOflba; + } +} +#endif +#endif diff --git a/apps/common/usb/host/usb_storage.h b/apps/common/usb/host/usb_storage.h new file mode 100644 index 0000000..dfdc5ef --- /dev/null +++ b/apps/common/usb/host/usb_storage.h @@ -0,0 +1,84 @@ +#ifndef __USB_STORAGE_H__ +#define __USB_STORAGE_H__ + +#include "system/task.h" +#include "device/device.h" +#include "usb/scsi.h" +#include "usb_bulk_transfer.h" +#include "usb/host/usb_host.h" + +/* u盘预读功能配置, 二选一 + * 当两种方式都不使能,则表示不开启预读 */ +#define UDISK_READ_BIGBLOCK_ASYNC_ENABLE 0 //使能大扇区预读方式(不需要额外buf,速度比512预读慢10%) +#define UDISK_READ_512_ASYNC_ENABLE 1 //使能512Byte预读方式(需要额外的512byte buffer,速度比大扇区预读快10%) +/****************************/ + +#define UDISK_READ_ASYNC_BLOCK_NUM (16) //预读扇区数 + +//设备状态: +typedef enum usb_sta { + DEV_IDLE = 0, + DEV_INIT, + DEV_OPEN, + DEV_READ, + DEV_WRITE, + DEV_CLOSE, + DEV_SUSPEND, +} USB_STA ; + +struct udisk_end_desc { + u8 host_epout; + u8 target_epout; + u8 host_epin; + u8 target_epin; +#if HUSB_MODE + u16 rxmaxp; + u16 txmaxp; +#endif +}; + +#define ENABLE_DISK_HOTPLUG 0 +struct mass_storage { + OS_MUTEX mutex; + + struct usb_scsi_cbw cbw; + struct usb_scsi_csw csw; + struct request_sense_data sense; + + char *name; + struct read_capacity_data capacity[2]; + u8 lun; + u8 curlun; + + u8 dev_status; + u8 suspend_cnt; + u8 read_only; + + u32 remain_len; + u32 prev_lba; +#if (UDISK_READ_BIGBLOCK_ASYNC_ENABLE || UDISK_READ_512_ASYNC_ENABLE) + u8 async_en; + u8 need_send_csw; + u8 *udisk_512_buf; + u32 async_prev_lba; +#endif +#if ENABLE_DISK_HOTPLUG + u8 media_sta_cur; //for card reader, card removable + u8 media_sta_prev; + + int test_unit_ready_tick; +#endif +}; + +enum usb_async_mode { + BULK_ASYNC_MODE_EXIT = 0, //取消异步模式 + BULK_ASYNC_MODE_ENTER, //异步512预读 + BULK_ASYNC_MODE_SEM_PEND, //异步预读等待信号量 +}; + +#define MASS_LBA_INIT (-2) + +int usb_msd_parser(struct usb_host_device *host_dev, u8 interface_num, const u8 *pBuf); +int _usb_stor_async_wait_sem(struct usb_host_device *host_dev); + +#endif diff --git a/apps/common/usb/usb_common_def.h b/apps/common/usb/usb_common_def.h new file mode 100644 index 0000000..411acc2 --- /dev/null +++ b/apps/common/usb/usb_common_def.h @@ -0,0 +1,146 @@ +#ifndef __USB_COMMON_DEFINE_H__ +#define __USB_COMMON_DEFINE_H__ + +///<<<注意此文件不要放函数声明, 只允许宏定义, 并且差异化定义可以根据需求在对应板卡中重新定义, 除非新增,否则不要直接修改这里 +///<<<注意此文件不要放函数声明, 只允许宏定义, 并且差异化定义可以根据需求在对应板卡中重新定义, 除非新增,否则不要直接修改这里 +///<<<注意此文件不要放函数声明, 只允许宏定义, 并且差异化定义可以根据需求在对应板卡中重新定义, 除非新增,否则不要直接修改这里 +// +/**************************************************************************/ +/* + CLASS BITMAP + 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 + HID AUDIO SPEAKER Mass Storage +*/ +/**************************************************************************/ +#define MASSSTORAGE_CLASS 0x00000001 +#define SPEAKER_CLASS 0x00000002 +#define MIC_CLASS 0x00000004 +#define HID_CLASS 0x00000008 +#define CDC_CLASS 0x00000010 + +#define AUDIO_CLASS (SPEAKER_CLASS|MIC_CLASS) + + +#define USB_ROOT2 0 + +/// board文件没有定义的宏,在这里定义,防止编译报warning +#ifndef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#endif +#ifndef TCFG_HID_HOST_ENABLE +#define TCFG_HID_HOST_ENABLE 0 +#endif +#ifndef TCFG_AOA_ENABLE +#define TCFG_AOA_ENABLE 0 +#endif +#ifndef TCFG_ADB_ENABLE +#define TCFG_ADB_ENABLE 0 +#endif +#ifndef TCFG_USB_APPLE_DOCK_EN +#define TCFG_USB_APPLE_DOCK_EN 0 +#endif +#ifndef TCFG_HOST_AUDIO_ENABLE +#define TCFG_HOST_AUDIO_ENABLE 0 +#endif +#ifndef TCFG_CHARGE_ENABLE +#define TCFG_CHARGE_ENABLE 0 +#endif +#ifndef TCFG_USB_PORT_CHARGE +#define TCFG_USB_PORT_CHARGE 0 +#endif +#ifndef TCFG_USB_MIC_ECHO_ENABLE +#define TCFG_USB_MIC_ECHO_ENABLE 0 +#endif +#ifndef TCFG_USB_MIC_DATA_FROM_MICEFFECT +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT 0 +#endif +#ifndef TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 0 +#endif + +/********************************/ + +#if TCFG_UDISK_ENABLE || TCFG_HID_HOST_ENABLE || TCFG_AOA_ENABLE || TCFG_ADB_ENABLE || TCFG_HOST_AUDIO_ENABLE +#define MOUNT_RETRY 3 +#define MOUNT_RESET 40 +#define MOUNT_TIMEOUT 50 +#define USB_HOST_ENABLE 1 +#else +#define USB_HOST_ENABLE 0 +#endif + +#if TCFG_CHARGE_ENABLE && TCFG_USB_PORT_CHARGE +#define TCFG_OTG_MODE_CHARGE (OTG_CHARGE_MODE) +#else +#define TCFG_OTG_MODE_CHARGE 0 +#endif + +#if (TCFG_PC_ENABLE) +#define TCFG_PC_UPDATE 1 +#define TCFG_OTG_MODE_SLAVE (OTG_SLAVE_MODE) +#else +#define TCFG_PC_UPDATE 0 +#define TCFG_OTG_MODE_SLAVE 0 +#endif + +#if (USB_HOST_ENABLE) +#define TCFG_OTG_MODE_HOST (OTG_HOST_MODE) +#else +#define TCFG_OTG_MODE_HOST 0 +#endif + +#if TCFG_PC_ENABLE +#define TCFG_USB_SLAVE_ENABLE 1 +#if (USB_DEVICE_CLASS_CONFIG & MASSSTORAGE_CLASS) +#define TCFG_USB_SLAVE_MSD_ENABLE 1 +#else +#define TCFG_USB_SLAVE_MSD_ENABLE 0 +#endif + +#if (USB_DEVICE_CLASS_CONFIG & AUDIO_CLASS) +#define TCFG_USB_SLAVE_AUDIO_ENABLE 1 +#else +#define TCFG_USB_SLAVE_AUDIO_ENABLE 0 +#endif + +#if (USB_DEVICE_CLASS_CONFIG & HID_CLASS) +#define TCFG_USB_SLAVE_HID_ENABLE 1 +#else +#define TCFG_USB_SLAVE_HID_ENABLE 0 +#endif + +#if (USB_DEVICE_CLASS_CONFIG & CDC_CLASS) +#define TCFG_USB_SLAVE_CDC_ENABLE 1 +#else +#define TCFG_USB_SLAVE_CDC_ENABLE 0 +#endif + +#else /* TCFG_PC_ENABLE == 0*/ +#define TCFG_USB_SLAVE_ENABLE 0 +#define TCFG_USB_SLAVE_MSD_ENABLE 0 +#define TCFG_USB_SLAVE_AUDIO_ENABLE 0 +#define TCFG_USB_SLAVE_HID_ENABLE 0 +#define TCFG_USB_SLAVE_CDC_ENABLE 0 +#endif + +#define TCFG_OTG_SLAVE_ONLINE_CNT 2 +#define TCFG_OTG_SLAVE_OFFLINE_CNT 2 + +#define TCFG_OTG_HOST_ONLINE_CNT 2 +#define TCFG_OTG_HOST_OFFLINE_CNT 3 + +#ifndef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE) +#endif + +#define TCFG_OTG_DET_INTERVAL 50 + +#if (TCFG_USB_CDC_BACKGROUND_RUN) +#define TCFG_USB_SLAVE_ENABLE 1 + +#undef TCFG_USB_SLAVE_CDC_ENABLE +#define TCFG_USB_SLAVE_CDC_ENABLE 1 +#endif + + +#endif diff --git a/apps/common/usb/usb_config.c b/apps/common/usb/usb_config.c new file mode 100644 index 0000000..e884ccd --- /dev/null +++ b/apps/common/usb/usb_config.c @@ -0,0 +1,284 @@ +#include "usb_config.h" +#include "usb/scsi.h" +#include "irq.h" +#include "init.h" +#include "gpio.h" +#include "app_config.h" +#define LOG_TAG_CONST USB +#define LOG_TAG "[USB]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#define SET_INTERRUPT ___interrupt + + +#define EP0_DMA_SIZE (64+4) +#define HID_DMA_SIZE (64+4) +#define AUDIO_DMA_SIZE (256+4) +#define MSD_DMA_SIZE (64+4) +#define CDC_DMA_SIZE (128+8) +#define MAX_EP_TX 5 +#define MAX_EP_RX 5 +static usb_interrupt usb_interrupt_tx[USB_MAX_HW_NUM][MAX_EP_TX];// SEC(.usb_g_bss); +static usb_interrupt usb_interrupt_rx[USB_MAX_HW_NUM][MAX_EP_RX];// SEC(.usb_h_bss); + +static u8 ep0_dma_buffer[EP0_DMA_SIZE] __attribute__((aligned(4))) SEC(.usb_ep0) ; +#if TCFG_USB_SLAVE_MSD_ENABLE +static u8 msd_dma_buffer[MSD_DMA_SIZE * 2] __attribute__((aligned(4)))SEC(.usb_msd_dma); +#endif +#if TCFG_USB_SLAVE_HID_ENABLE +static u8 hid_dma_rx_buffer[HID_DMA_SIZE] __attribute__((aligned(4)))SEC(.usb_hid_dma); +static u8 hid_dma_tx_buffer[HID_DMA_SIZE] __attribute__((aligned(4)))SEC(.usb_hid_dma); +#endif +#if TCFG_USB_SLAVE_AUDIO_ENABLE +static u8 spk_dma_buffer[AUDIO_DMA_SIZE] __attribute__((aligned(4)))SEC(.usb_iso_dma); +static u8 mic_dma_buffer[AUDIO_DMA_SIZE] __attribute__((aligned(4)))SEC(.usb_iso_dma); +#endif +#if TCFG_USB_SLAVE_CDC_ENABLE +static u8 cdc_dma_rx_buffer[CDC_DMA_SIZE] __attribute__((aligned(4)))SEC(.usb_cdc_dma); +static u8 cdc_dma_tx_buffer[CDC_DMA_SIZE] __attribute__((aligned(4)))SEC(.usb_cdc_dma); +#if CDC_INTR_EP_ENABLE +static u8 cdc_intr_dma_tx_buffer[CDC_DMA_SIZE] __attribute__((aligned(4)))SEC(.usb_cdc_dma); +#endif +#endif + +struct usb_config_var_t { + u8 usb_setup_buffer[USB_SETUP_SIZE]; + struct usb_ep_addr_t usb_ep_addr; + struct usb_setup_t usb_setup; +}; +static struct usb_config_var_t *usb_config_var = {NULL}; + +#if USB_MALLOC_ENABLE +#else +static struct usb_config_var_t _usb_config_var SEC(.usb_config_var); +#endif + +__attribute__((always_inline_when_const_args)) +void *usb_get_ep_buffer(const usb_dev usb_id, u32 ep) +{ + u8 *ep_buffer = NULL; + u32 _ep = ep & 0xf; + if (ep & USB_DIR_IN) { + switch (_ep) { + case 0: + ep_buffer = ep0_dma_buffer; + break; + case 1: +#if TCFG_USB_SLAVE_MSD_ENABLE + ep_buffer = msd_dma_buffer; +#endif + break; + case 2: +#if TCFG_USB_SLAVE_HID_ENABLE + ep_buffer = hid_dma_tx_buffer; +#endif + break; + case 3: +#if TCFG_USB_SLAVE_AUDIO_ENABLE + ep_buffer = mic_dma_buffer; +#endif + break; + case 4: +#if TCFG_USB_SLAVE_CDC_ENABLE + ep_buffer = cdc_dma_tx_buffer; +#endif +#if TCFG_USB_SLAVE_CDC_ENABLE +#if CDC_INTR_EP_ENABLE + ep_buffer = cdc_intr_dma_tx_buffer; +#endif +#endif + //ep_buffer = NULL; + break; + } + } else { + switch (_ep) { + case 0: + ep_buffer = ep0_dma_buffer; + break; + case 1: +#if TCFG_USB_SLAVE_MSD_ENABLE + ep_buffer = msd_dma_buffer; +#endif + break; + case 2: +#if TCFG_USB_SLAVE_HID_ENABLE + ep_buffer = hid_dma_rx_buffer; +#endif + break; + case 3: +#if TCFG_USB_SLAVE_AUDIO_ENABLE + ep_buffer = spk_dma_buffer; +#endif + break; + case 4: +#if TCFG_USB_SLAVE_CDC_ENABLE + ep_buffer = cdc_dma_rx_buffer; +#endif + //ep_buffer = NULL; + break; + } + } + return ep_buffer; +} + + + +void usb_isr(const usb_dev usb_id) +{ + u32 intr_usb, intr_usbe; + u32 intr_tx, intr_txe; + u32 intr_rx, intr_rxe; + + __asm__ volatile("ssync"); + usb_read_intr(usb_id, &intr_usb, &intr_tx, &intr_rx); + usb_read_intre(usb_id, &intr_usbe, &intr_txe, &intr_rxe); + struct usb_device_t *usb_device = usb_id2device(usb_id); + + intr_usb &= intr_usbe; + intr_tx &= intr_txe; + intr_rx &= intr_rxe; + + if (intr_usb & INTRUSB_SUSPEND) { + log_error("usb suspend"); + usb_sie_close(usb_id); + } + if (intr_usb & INTRUSB_RESET_BABBLE) { + log_error("usb reset"); + usb_reset_interface(usb_device); + } + if (intr_usb & INTRUSB_RESUME) { + log_error("usb resume"); + } + + if (intr_tx & BIT(0)) { + if (usb_interrupt_rx[usb_id][0]) { + usb_interrupt_rx[usb_id][0](usb_device, 0); + } else { + usb_control_transfer(usb_device); + } + } + + for (int i = 1; i < MAX_EP_TX; i++) { + if (intr_tx & BIT(i)) { + if (usb_interrupt_tx[usb_id][i]) { + usb_interrupt_tx[usb_id][i](usb_device, i); + } + } + } + + for (int i = 1; i < MAX_EP_RX; i++) { + if (intr_rx & BIT(i)) { + if (usb_interrupt_rx[usb_id][i]) { + usb_interrupt_rx[usb_id][i](usb_device, i); + } + } + } + __asm__ volatile("csync"); +} + +void usb_sof_isr(const usb_dev usb_id) +{ + usb_sof_clr_pnd(usb_id); + static u32 sof_count = 0; + if ((sof_count++ % 1000) == 0) { + log_d("sof 1s isr frame:%d", usb_read_sofframe(usb_id)); + } +} + +SET_INTERRUPT +void usb0_g_isr() +{ + usb_isr(0); +} +SET_INTERRUPT +void usb0_sof_isr() +{ + usb_sof_isr(0); +} + +#if USB_MAX_HW_NUM == 2 +SET_INTERRUPT +void usb1_g_isr() +{ + usb_isr(1); +} +SET_INTERRUPT +void usb1_sof_isr() +{ + usb_sof_isr(1); +} +#endif +__attribute__((always_inline_when_const_args)) +u32 usb_g_set_intr_hander(const usb_dev usb_id, u32 ep, usb_interrupt hander) +{ + if (ep & USB_DIR_IN) { + usb_interrupt_tx[usb_id][ep & 0xf] = hander; + } else { + usb_interrupt_rx[usb_id][ep] = hander; + } + return 0; +} +void usb_g_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id) +{ + if (usb_id == 0) { + request_irq(IRQ_USB_CTRL_IDX, priority, usb0_g_isr, cpu_id); + } else { +#if USB_MAX_HW_NUM == 2 + request_irq(IRQ_USB1_CTRL_IDX, priority, usb1_g_isr, cpu_id); +#endif + } +} +void usb_sof_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id) +{ + if (usb_id == 0) { + request_irq(IRQ_USB_SOF_IDX, priority, usb0_sof_isr, cpu_id); + } else { +#if USB_MAX_HW_NUM == 2 + request_irq(IRQ_USB1_SOF_IDX, priority, usb1_sof_isr, cpu_id); +#endif + } +} +u32 usb_config(const usb_dev usb_id) +{ + memset(usb_interrupt_rx[usb_id], 0, sizeof(usb_interrupt_rx[usb_id])); + memset(usb_interrupt_tx[usb_id], 0, sizeof(usb_interrupt_tx[usb_id])); + + if (!usb_config_var) { +#if USB_MALLOC_ENABLE + usb_config_var = (struct usb_config_var_t *)zalloc(sizeof(struct usb_config_var_t)); + if (!usb_config_var) { + return -1; + } +#else + memset(&_usb_config_var, 0, sizeof(_usb_config_var)); + usb_config_var = &_usb_config_var; +#endif + } + log_debug("zalloc: usb_config_var = %x\n", usb_config_var); + + usb_var_init(usb_id, &(usb_config_var->usb_ep_addr)); + usb_setup_init(usb_id, &(usb_config_var->usb_setup), usb_config_var->usb_setup_buffer); + return 0; +} + +u32 usb_release(const usb_dev usb_id) +{ + log_debug("free zalloc: usb_config_var = %x\n", usb_id, usb_config_var); + usb_var_init(usb_id, NULL); + usb_setup_init(usb_id, NULL, NULL); +#if USB_MALLOC_ENABLE + if (usb_config_var) { + log_debug("free: usb_config_var = %x\n", usb_config_var); + free(usb_config_var); + } +#endif + + usb_config_var = NULL; + + return 0; +} diff --git a/apps/common/usb/usb_config.h b/apps/common/usb/usb_config.h new file mode 100644 index 0000000..9d30f94 --- /dev/null +++ b/apps/common/usb/usb_config.h @@ -0,0 +1,23 @@ +#ifndef __USB_CONFIG_H__ +#define __USB_CONFIG_H__ + +#include "typedef.h" +#include "asm/usb.h" +#include "usb/device/usb_stack.h" +#include "usb/host/usb_host.h" + +void usb_host_config(usb_dev usb_id); +void usb_host_free(usb_dev usb_id); +void *usb_h_get_ep_buffer(const usb_dev usb_id, u32 ep); +void usb_h_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id); +void usb_g_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id); + + + +void usb_sof_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id); +void *usb_get_ep_buffer(const usb_dev usb_id, u32 ep); +u32 usb_config(const usb_dev usb_id); +u32 usb_release(const usb_dev usb_id); +void usb_otg_sof_check_init(const usb_dev id); + +#endif /*USB_CONFIG_H*/ diff --git a/apps/common/usb/usb_host_config.c b/apps/common/usb/usb_host_config.c new file mode 100644 index 0000000..3920734 --- /dev/null +++ b/apps/common/usb/usb_host_config.c @@ -0,0 +1,188 @@ +#include "usb_config.h" +#include "usb/scsi.h" +#include "irq.h" +#include "init.h" +#include "gpio.h" +#include "app_config.h" +#define LOG_TAG_CONST USB +#define LOG_TAG "[USB]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#define SET_INTERRUPT ___interrupt + +#if TCFG_UDISK_ENABLE || TCFG_ADB_ENABLE ||TCFG_AOA_ENABLE || TCFG_HID_HOST_ENABLE || TCFG_HOST_AUDIO_ENABLE + +#if TCFG_HID_HOST_ENABLE +#define MAX_HOST_EP_RX 4 +#define MAX_HOST_EP_TX 4 +#else +#define MAX_HOST_EP_RX 2 +#define MAX_HOST_EP_TX 2 //ep0 & ep1(msd) +#endif + +struct host_var_t { + struct usb_ep_addr_t host_ep_addr ; + usb_h_interrupt usb_h_interrupt_rx[MAX_HOST_EP_RX] ; + usb_h_interrupt usb_h_interrupt_tx[MAX_HOST_EP_TX] ; + struct usb_host_device *dev_at_ep[MAX_HOST_EP_RX]; +}; +static struct host_var_t *host_var[USB_MAX_HW_NUM];// SEC(.usb_h_bss); +static struct host_var_t __host_var[USB_MAX_HW_NUM]; +#if TCFG_ADB_ENABLE && TCFG_AOA_ENABLE && TCFG_HID_HOST_ENABLE +static u8 ep0_dma[USB_MAX_HW_NUM][64 + 4] __attribute__((aligned(4))); +static u8 ep1_dma[USB_MAX_HW_NUM][64 * 2 + 4] __attribute__((aligned(4))); +static u8 ep2_dma[USB_MAX_HW_NUM][64 * 2 + 4] __attribute__((aligned(4))); +static u8 ep3_dma[USB_MAX_HW_NUM][64 * 2 + 4] __attribute__((aligned(4))); +static u8 ep4_dma[USB_MAX_HW_NUM][64 * 2 + 4] __attribute__((aligned(4))); +#else +static u8 msd_h_dma_buffer[2][64 + 4] __attribute__((aligned(4))) SEC(.usb_h_dma); +#endif + +void usb_h_isr(const usb_dev usb_id) +{ + u32 intr_usb, intr_usbe; + u32 intr_tx, intr_txe; + u32 intr_rx, intr_rxe; + + __asm__ volatile("ssync"); + + usb_read_intr(usb_id, &intr_usb, &intr_tx, &intr_rx); + usb_read_intre(usb_id, &intr_usbe, &intr_txe, &intr_rxe); + struct usb_host_device *host_dev = NULL; + + /* r_printf("usb_h_isr %x %x %x %x",host_dev,intr_usb,intr_tx,intr_rx); */ + intr_usb &= intr_usbe; + intr_tx &= intr_txe; + intr_rx &= intr_rxe; + + if (intr_usb & INTRUSB_SUSPEND) { + log_error("usb suspend"); + } + if (intr_usb & INTRUSB_RESET_BABBLE) { + log_error("usb reset"); + } + if (intr_usb & INTRUSB_RESUME) { + log_error("usb resume"); + } + + if (intr_tx & BIT(0)) { + if (host_var[usb_id]->usb_h_interrupt_tx[0]) { + host_dev = host_var[usb_id]->dev_at_ep[0]; + host_var[usb_id]->usb_h_interrupt_tx[0](host_dev, 0); + } + } + + for (int i = 1; i < MAX_HOST_EP_TX; i++) { + if (intr_tx & BIT(i)) { + if (host_var[usb_id]->usb_h_interrupt_tx[i]) { + host_dev = host_var[usb_id]->dev_at_ep[i]; + host_var[usb_id]->usb_h_interrupt_tx[i](host_dev, i); + } + } + } + + for (int i = 1; i < MAX_HOST_EP_RX; i++) { + if (intr_rx & BIT(i)) { + if (host_var[usb_id]->usb_h_interrupt_rx[i]) { + host_dev = host_var[usb_id]->dev_at_ep[i]; + host_var[usb_id]->usb_h_interrupt_rx[i](host_dev, i); + } + } + } + __asm__ volatile("csync"); +} +SET_INTERRUPT +void usb0_h_isr() +{ + usb_h_isr(0); +} +SET_INTERRUPT +void usb1_h_isr() +{ + usb_h_isr(1); +} +__attribute__((always_inline_when_const_args)) +u32 usb_h_set_intr_hander(const usb_dev usb_id, u32 ep, usb_h_interrupt hander) +{ + if (ep & USB_DIR_IN) { + host_var[usb_id]->usb_h_interrupt_rx[ep & 0xf] = hander; + } else { + host_var[usb_id]->usb_h_interrupt_tx[ep] = hander; + } + return 0; +} +void usb_h_isr_reg(const usb_dev usb_id, u8 priority, u8 cpu_id) +{ + if (usb_id == 0) { + request_irq(IRQ_USB_CTRL_IDX, priority, usb0_h_isr, cpu_id); +#if USB_MAX_HW_NUM > 1 + } else if (usb_id == 1) { + request_irq(IRQ_USB1_CTRL_IDX, priority, usb1_h_isr, cpu_id); +#endif + } +} + +__attribute__((always_inline_when_const_args)) +void *usb_h_get_ep_buffer(const usb_dev usb_id, u32 ep) +{ +#if TCFG_ADB_ENABLE && TCFG_AOA_ENABLE && TCFG_HID_HOST_ENABLE + u8 dir = !!(ep & USB_DIR_IN); + u8 *p = NULL; + switch (ep & 0xf) { + case 0: + p = &ep0_dma[usb_id][0]; + break; + case 1: + p = &ep1_dma[usb_id][dir * 64]; + break; + case 2: + p = &ep2_dma[usb_id][dir * 64]; + break; + case 3: + p = &ep3_dma[usb_id][dir * 64]; + break; + case 4: + p = &ep4_dma[usb_id][dir * 64]; + break; + } + return p; +#else + return msd_h_dma_buffer; +#endif +} +void usb_h_set_ep_isr(struct usb_host_device *host_dev, u32 ep, usb_h_interrupt hander, void *p) +{ + if (host_dev) { + usb_dev usb_id = host_device2id(host_dev); + host_var[usb_id]->dev_at_ep[ep & 0xf] = p; + usb_h_set_intr_hander(usb_id, ep, hander); + } +} +void usb_host_config(usb_dev usb_id) +{ + /* host_var[usb_id] = zalloc(sizeof(struct host_var_t)); */ + host_var[usb_id] = &__host_var[usb_id]; + + ASSERT(host_var[usb_id], "host_var_t"); + + g_printf("%s() %x %x", __func__, host_var[usb_id], &(host_var[usb_id]->host_ep_addr)); + usb_var_init(usb_id, &(host_var[usb_id]->host_ep_addr)); +} +void usb_host_free(usb_dev usb_id) +{ + g_printf("%s() %x", __func__, host_var[usb_id]); + OS_ENTER_CRITICAL(); + /* free(host_var[usb_id]); */ + /* host_var[usb_id] = NULL; */ + if (host_var[usb_id]) { + memset(host_var[usb_id]->usb_h_interrupt_rx, 0, sizeof(usb_h_interrupt) * MAX_HOST_EP_RX); + memset(host_var[usb_id]->usb_h_interrupt_tx, 0, sizeof(usb_h_interrupt) * MAX_HOST_EP_TX); + } + OS_EXIT_CRITICAL(); +} +#endif diff --git a/apps/common/usb/usb_std_class_def.h b/apps/common/usb/usb_std_class_def.h new file mode 100644 index 0000000..778bf6a --- /dev/null +++ b/apps/common/usb/usb_std_class_def.h @@ -0,0 +1,101 @@ +#ifndef __USB_STD_CLASS_DEF_H__ +#define __USB_STD_CLASS_DEF_H__ + +#define USB_MALLOC_ENABLE 0 +#define USB_HOST_ASYNC 1 +#define USB_H_MALLOC_ENABLE 1 +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS|MASSSTORAGE_CLASS) + +///////////MassStorage Class + +#define MSD_BULK_EP_OUT 1 +#define MSD_BULK_EP_IN 1 + + +#define MAXP_SIZE_BULKOUT 64 +#define MAXP_SIZE_BULKIN 64 + +#define MSD_STR_INDEX 7 + +///////////HID class +#define HID_EP_IN 2 +#define HID_EP_OUT 2 + +#define MAXP_SIZE_HIDOUT 8 +#define MAXP_SIZE_HIDIN 8 +/* #define MAXP_SIZE_HIDOUT 64 */ +/* #define MAXP_SIZE_HIDIN 64 */ + + + +/////////////Audio Class +#define UAC_ISO_INTERVAL 1 +//speaker class +#define SPK_AUDIO_RATE 48000 +#define SPK_AUDIO_RES 16 + +#define SPK_CHANNEL 2 +#define SPK_FRAME_LEN (((SPK_AUDIO_RATE) * SPK_AUDIO_RES / 8 * SPK_CHANNEL)/1000+4) + +#define SPK_PCM_Type (SPK_AUDIO_RES >> 4) // 0=8 ,1=16 +#define SPK_AUDIO_TYPE (0x02 - SPK_PCM_Type) // TYPE1_PCM16 + + +#define SPK_ISO_EP_OUT 3 + +#define SPEAKER_STR_INDEX 5 + +#define SPK_INPUT_TERMINAL_ID 1 +#define SPK_FEATURE_UNIT_ID 2 +#define SPK_OUTPUT_TERMINAL_ID 3 + +/////////////Microphone Class + +#define MIC_SamplingFrequency 1 + +#if MIC_SamplingFrequency == 1 + +#define MIC_AUDIO_RATE 48000 + +#else + +#define MIC_AUDIO_RATE 192000 +#define MIC_AUDIO_RATE_1 44100 +#define MIC_AUDIO_RATE_2 48000 +#define MIC_AUDIO_RATE_4 96000 + +#endif + +#define MIC_AUDIO_RES 16 + +#define MIC_CHANNEL 1 + +#define MIC_FRAME_LEN ((MIC_AUDIO_RATE * MIC_AUDIO_RES / 8 * MIC_CHANNEL)/1000) + +#define MIC_PCM_TYPE (MIC_AUDIO_RES >> 4) // 0=8 ,1=16 +#define MIC_AUDIO_TYPE (0x02 - MIC_PCM_TYPE) + + + +#define MIC_ISO_EP_IN 3 + +#define MIC_STR_INDEX 6 + +#define MIC_INPUT_TERMINAL_ID 4 +#define MIC_FEATURE_UNIT_ID 5 +#define MIC_OUTPUT_TERMINAL_ID 6 +#define MIC_SELECTOR_UNIT_ID 7 + + +////////////CDC Class +#define CDC_DATA_EP_IN 4 +#define CDC_DATA_EP_OUT 4 +#define CDC_INTR_EP_IN 5 + +#define MAXP_SIZE_CDC_BULKIN 64 +#define MAXP_SIZE_CDC_BULKOUT 64 +#define MAXP_SIZE_CDC_INTRIN 8 + +#define CDC_INTR_EP_ENABLE 0 + +#endif diff --git a/apps/soundbox/aec/br23/audio_aec.c b/apps/soundbox/aec/br23/audio_aec.c new file mode 100644 index 0000000..aa63b66 --- /dev/null +++ b/apps/soundbox/aec/br23/audio_aec.c @@ -0,0 +1,822 @@ +/* +********************************************************************* +* Audio AEC APIs + +* Description:AEC用户调用接口 +* Note(s) :ANS等级和AEC滤波器长度可根据实际需要进行配置 +* (1)CONST_ANS_MODE:ANS降噪等级配置 +* (2)AEC_TAIL_LENGTH:AEC滤波器长度配置 +********************************************************************* +*/ +#include "system/includes.h" +#include "app_config.h" +#include "audio_config.h" +#include "aec_user.h" +#include "media/includes.h" +#include "media/audio_eq_drc_apply.h" +#include "circular_buf.h" +#include "clock_cfg.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" + +#if !defined(TCFG_CVP_DEVELOP_ENABLE) || (TCFG_CVP_DEVELOP_ENABLE == 0) + +#define LOG_TAG_CONST AEC_USER +#define LOG_TAG "[AEC_USER]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#define AEC_MALLOC_ENABLE 1 + +/*AEC_TOGGLE:AEC模块使能开关,Disable则数据完全不经过处理,AEC模块不占用资源*/ +#if (TCFG_AEC_ENABLE) +#define AEC_TOGGLE 1 +#else +#define AEC_TOGGLE 0 +#endif/*TCFG_AEC_ENABLE*/ + +#if (TCFG_EQ_ENABLE == 1) +#define AEC_DCCS_EN 1 /*mic去直流滤波eq*/ +#define AEC_UL_EQ_EN 1 /*mic 普通eq*/ +#else +#define AEC_DCCS_EN 0 +#define AEC_UL_EQ_EN 0 +#endif/*TCFG_EQ_ENABLE*/ + +/*使能即可跟踪通话过程的内存情况*/ +#define CVP_MEM_TRACE_ENABLE 0 + +#ifdef CONFIG_FPGA_ENABLE +const u8 CONST_AEC_ENABLE = 0; +#else +const u8 CONST_AEC_ENABLE = 1; +#endif/*CONFIG_FPGA_ENABLE*/ + +#ifdef AUDIO_PCM_DEBUG +/*AEC串口数据导出*/ +const u8 CONST_AEC_EXPORT = 1; +#else +const u8 CONST_AEC_EXPORT = 0; +#endif/*AUDIO_PCM_DEBUG*/ + +/* + *ANS等级:0~2, + *等级1比等级0多6k左右的ram + *等级2比等级1多3k左右的ram + */ +const u8 CONST_ANS_MODE = 1; + +/*参考数据变采样处理*/ +const u8 CONST_REF_SRC = 0; + +/* + *ANS版本配置 + *ANS_V100:传统降噪 + *ANS_V200:AI降噪,需要更多的ram和mips + **/ +#if (TCFG_AUDIO_CVP_NS_MODE == CVP_ANS_MODE) +const u8 CONST_ANS_VERSION = ANS_V100; +#else/*CVP_DNS_MODE*/ +const u8 CONST_ANS_VERSION = ANS_V200; +#endif/*TCFG_AUDIO_CVP_NS_MODE*/ + +/* + *延时估计使能 + *点烟器/单工模式需要做延时估计 + *其他的暂时不需要做 + */ +#if ((TCFG_APP_FM_EMITTER_EN) || TCFG_AEC_SIMPLEX) +const u8 CONST_AEC_DLY_EST = 1; +#else +const u8 CONST_AEC_DLY_EST = 0; +#endif + +/* + *AEC复杂等级,等级越高,ram和mips越大,适应性越好 + *回音路径不定/回音失真等情况才需要比较高的等级 + *音箱建议使用等级:5 + *耳机建议使用等级:2 + */ +#define AEC_TAIL_LENGTH 5 /*range:2~10,default:5*/ + +//////////////////Simplex Parameters(单工调试参数)///////////////////// +#if TCFG_AEC_SIMPLEX +const u8 CONST_AEC_SIMPLEX = 1; +#else +const u8 CONST_AEC_SIMPLEX = 0; +#endif/*TCFG_AEC_SIMPLEX*/ +/*单工连续清0的帧数*/ +#define AEC_SIMPLEX_TAIL 15 +/**远端数据大于CONST_AEC_SIMPLEX_THR,即清零近端数据 + *越小,回音限制得越好,同时也就越容易卡*/ +#define AEC_SIMPLEX_THR 100000 /*default:260000*/ +/////////////////////////////////////////////////////////////////////// + +#define AEC_OUT_DUMP_PACKET 15 /*数据输出开头丢掉的数据包数*/ +#define AEC_IN_DUMP_PACKET 1 /*数据输出开头丢掉的数据包数*/ + +/*AEC默认使能模块:AEC_MODE_REDUCE or AEC_MODE_ADVANCE */ +#define AEC_MODULE_BIT AEC_MODE_ADVANCE + +extern struct adc_platform_data adc_data; +extern void mem_state_dump(); + +__attribute__((weak))u32 usb_mic_is_running() +{ + return 0; +} + +/*复用lmp rx buf(一般通话的时候复用) + *rx_buf概率产生碎片,导致alloc失败,因此默认配0 + */ +#define MALLOC_MULTIPLEX_EN 0 +extern void *lmp_malloc(int); +extern void lmp_free(void *); +void *zalloc_mux(int size) +{ +#if MALLOC_MULTIPLEX_EN + void bredr_rx_bulk_state(); + bredr_rx_bulk_state(); + void *p = NULL; + do { + p = lmp_malloc(size); + if (p) { + break; + } + printf("aec_malloc wait...\n"); + os_time_dly(2); + } while (1); + if (p) { + memset(p, 0, size); + } + printf("[malloc_mux]p = 0x%x,size = %d\n", p, size); + return p; +#else + return zalloc(size); +#endif +} + +void free_mux(void *p) +{ +#if MALLOC_MULTIPLEX_EN + printf("[free_mux]p = 0x%x\n", p); + lmp_free(p); +#else + free(p); +#endif +} + +void aec_param_dump(struct aec_s_attr *param) +{ + log_info("===========dump aec param==================\n"); + log_info("toggle:%d\n", param->toggle); + log_info("EnableBit:%x\n", param->EnableBit); + log_info("ul_eq_en:%x\n", param->ul_eq_en); + //log_info("AGC_fade:%d\n", (int)(param->AGC_gain_step * 100)); + log_info("AGC_NDT_max_gain:%d\n", (int)(param->AGC_NDT_max_gain * 100)); + log_info("AGC_NDT_min_gain:%d\n", (int)(param->AGC_NDT_min_gain * 100)); + log_info("AGC_NDT_speech_thr:%d\n", (int)(param->AGC_NDT_speech_thr * 100)); + log_info("AGC_DT_max_gain:%d\n", (int)(param->AGC_DT_max_gain * 100)); + log_info("AGC_DT_min_gain:%d\n", (int)(param->AGC_DT_min_gain * 100)); + log_info("AGC_DT_speech_thr:%d\n", (int)(param->AGC_DT_speech_thr * 100)); + log_info("AGC_echo_present_thr:%d\n", (int)(param->AGC_echo_present_thr * 100)); + log_info("AEC_DT_AggressiveFactor:%d\n", (int)(param->AEC_DT_AggressiveFactor * 100)); + log_info("AEC_RefEngThr:%d\n", (int)(param->AEC_RefEngThr * 100)); + log_info("ES_AggressFactor:%d\n", (int)(param->ES_AggressFactor * 100)); + log_info("ES_MinSuppress:%d\n", (int)(param->ES_MinSuppress * 100)); + log_info("ANS_AggressFactor:%d\n", (int)(param->ANS_AggressFactor * 100)); + log_info("ANS_MinSuppress:%d\n", (int)(param->ANS_MinSuppress * 100)); + log_info("=================END=======================\n"); +} + +struct audio_aec_hdl { + u8 start; //aec模块状态 + u8 inbuf_clear_cnt; //aec输入数据丢掉 + u8 output_fade_in; //aec输出淡入使能 + u8 output_fade_in_gain; //aec输出淡入增益 +#if AEC_UL_EQ_EN + struct audio_eq *ul_eq; //上行数据eq处理 +#endif/*AEC_UL_EQ_EN*/ +#if AEC_DCCS_EN + struct audio_eq *dccs_eq;//省电容mic去直流滤波 +#endif/*AEC_DCCS_EN*/ + u16 dump_packet; //前面如果有杂音,丢掉几包 + u8 output_buf[1000]; //aec数据输出缓存 + cbuffer_t output_cbuf; + struct aec_s_attr attr; //aec模块参数属性 +}; +#if AEC_MALLOC_ENABLE +struct audio_aec_hdl *aec_hdl = NULL; +#else +struct audio_aec_hdl aec_handle; +#endif + +extern int esco_adc_mic_en(); +void audio_aec_ref_start(u8 en) +{ + if (aec_hdl && (aec_hdl->attr.fm_tx_start == 0)) { + if (esco_adc_mic_en() == 0) { + aec_hdl->attr.fm_tx_start = en; + y_printf("fm_tx_start:%d\n", en); + } + } +} + +#if AEC_DCCS_EN +const int DCCS_8k_Coeff[5] = { + (943718 << 2), -(856687 << 2), (1048576 << 2), (1887437 << 2), -(2097152 << 2) +}; +const int DCCS_16k_Coeff[5] = { + (1006633 << 2), -(967542 << 2), (1048576 << 2), (2013266 << 2), -(2097152 << 2) +}; +int aec_dccs_eq_filter(void *eq, int sr, struct audio_eq_filter_info *info) +{ + //r_printf("dccs_eq sr:%d\n", sr); + if (sr == 16000) { + info->L_coeff = (void *)DCCS_16k_Coeff; + info->R_coeff = (void *)DCCS_16k_Coeff; + } else { + info->L_coeff = (void *)DCCS_8k_Coeff; + info->R_coeff = (void *)DCCS_8k_Coeff; + } + info->L_gain = 0; + info->R_gain = 0; + info->nsection = 1; + return 0; +} + +static int dccs_eq_output(void *priv, void *data, u32 len) +{ + return 0; +} +#endif/*AEC_DCCS_EN*/ + +#if AEC_UL_EQ_EN + +static int ul_eq_output(void *priv, void *data, u32 len) +{ + return 0; +} +#endif/*AEC_UL_EQ_EN*/ + +/* +********************************************************************* +* Audio AEC Process_Probe +* Description: AEC模块数据前处理回调 +* Arguments : data 数据地址 +* len 数据长度 +* Return : 0 成功 其他 失败 +* Note(s) : 在源数据经过AEC模块前,可以增加自定义处理 +********************************************************************* +*/ +static int audio_aec_probe(s16 *data, u16 len) +{ +#if AEC_DCCS_EN + if (aec_hdl->dccs_eq) { + audio_eq_run(aec_hdl->dccs_eq, data, len); + } +#endif/*AEC_DCCS_EN*/ + return 0; +} + +/* +********************************************************************* +* Audio AEC Process_Post +* Description: AEC模块数据后处理回调 +* Arguments : data 数据地址 +* len 数据长度 +* Return : 0 成功 其他 失败 +* Note(s) : 在数据处理完毕,可以增加自定义后处理 +********************************************************************* +*/ +static int audio_aec_post(s16 *data, u16 len) +{ +#if AEC_UL_EQ_EN + if (aec_hdl->ul_eq) { + audio_eq_run(aec_hdl->ul_eq, data, len); + } +#endif/*AEC_UL_EQ_EN*/ + return 0; +} + +/*跟踪系统内存使用情况:physics memory size xxxx bytes*/ +static void sys_memory_trace(void) +{ + static int cnt = 0; + if (cnt++ > 200) { + cnt = 0; + mem_stats(); + } +} + +/* +********************************************************************* +* Audio AEC Output Handle +* Description: AEC模块数据输出回调 +* Arguments : data 输出数据地址 +* len 输出数据长度 +* Return : 数据输出消耗长度 +* Note(s) : None. +********************************************************************* +*/ +extern void esco_enc_resume(void); +static int audio_aec_output(s16 *data, u16 len) +{ + u16 outlen = len; + s16 *outdat = data; +#if CVP_MEM_TRACE_ENABLE + sys_memory_trace(); +#endif/*CVP_MEM_TRACE_ENABLE*/ + /*数据清0处理*/ + if (aec_hdl->dump_packet) { + aec_hdl->dump_packet--; + memset(data, 0, len); + } else { + /*数据淡入处理*/ + if (aec_hdl->output_fade_in) { + s32 tmp_data; + //printf("fade:%d\n",aec_hdl->output_fade_in_gain); + for (int i = 0; i < len / 2; i++) { + tmp_data = data[i]; + data[i] = tmp_data * aec_hdl->output_fade_in_gain >> 7; + } + aec_hdl->output_fade_in_gain += 12; + if (aec_hdl->output_fade_in_gain >= 128) { + aec_hdl->output_fade_in = 0; + } + } + } + + u16 wlen = cbuf_write(&aec_hdl->output_cbuf, outdat, outlen); + /* printf("wlen:%d-%d-%d-%d\n",wlen, outlen, len,aec_hdl->output_cbuf.data_len); */ + + esco_enc_resume(); +#if 1 + static u32 aec_output_max = 0; + if (aec_output_max < aec_hdl->output_cbuf.data_len) { + aec_output_max = aec_hdl->output_cbuf.data_len; + y_printf("o_max:%d", aec_output_max); + } +#endif + if (wlen != outlen) { + putchar('F'); + } + return len; +} + +/* +********************************************************************* +* Audio AEC Output Query +* Description: 查询aec模块的输出数据缓存大小 +* Arguments : None. +* Return : 数据缓存大小 +* Note(s) : None. +********************************************************************* +*/ +int audio_aec_output_data_size(void) +{ + local_irq_disable(); + if (!aec_hdl || !aec_hdl->start) { + printf("audio_aec close now"); + local_irq_enable(); + return -EINVAL; + } + int len = cbuf_get_data_size(&aec_hdl->output_cbuf); + local_irq_enable(); + return len; +} + +/* +********************************************************************* +* Audio AEC Output Read +* Description: 读取aec模块的输出数据 +* Arguments : buf 读取数据存放地址 +* len 读取数据长度 +* Return : 数据读取长度 +* Note(s) : None. +********************************************************************* +*/ +int audio_aec_output_read(s16 *buf, u16 len) +{ + /* printf("rlen:%d-%d\n",len,aec_hdl->output_cbuf.data_len); */ + local_irq_disable(); + if (!aec_hdl || !aec_hdl->start) { + printf("audio_aec close now"); + local_irq_enable(); + return -EINVAL; + } + u16 rlen = cbuf_read(&aec_hdl->output_cbuf, buf, len); + if (rlen == 0) { + //putchar('N'); + } + local_irq_enable(); + return rlen; +} + +static const char *CVP_ModuleName[] = { + "AEC", "NLP", "ANS", "ENC", "AGC" +}; +static const char *CVP_ModuleStatus[] = { + "Disable", "Enable" +}; +static void dumpModulaStatus(int EnableBit) +{ + printf("EnableBitDebug = 0x%x\n", EnableBit); + for (int i = 0; i < 5; i++) { + int k = 1 << i; + printf("%s : %s\n", CVP_ModuleName[i], CVP_ModuleStatus[((EnableBit & k) != 0)]); + } +} +/* +********************************************************************* +* Audio AEC Parameters +* Description: AEC模块配置参数 +* Arguments : p 参数指针 +* Return : None. +* Note(s) : 读取配置文件成功,则使用配置文件的参数配置,否则使用默 +* 认参数配置 +********************************************************************* +*/ +static void audio_aec_param_read_config(struct aec_s_attr *p) +{ + AEC_CONFIG cfg; +#if (TCFG_AUDIO_CVP_NS_MODE == CVP_DNS_MODE) + int ret = syscfg_read(CFG_SMS_DNS_ID, &cfg, sizeof(AEC_CONFIG)); +#else + int ret = syscfg_read(CFG_AEC_ID, &cfg, sizeof(AEC_CONFIG)); +#endif/*TCFG_AUDIO_CVP_NS_MODE*/ + if (ret == sizeof(AEC_CONFIG)) { + log_info("audio_aec read config ok\n"); + p->AGC_NDT_fade_in_step = cfg.ndt_fade_in; + p->AGC_NDT_fade_out_step = cfg.ndt_fade_out; + p->AGC_DT_fade_in_step = cfg.dt_fade_in; + p->AGC_DT_fade_out_step = cfg.dt_fade_out; + p->AGC_NDT_max_gain = cfg.ndt_max_gain; + p->AGC_NDT_min_gain = cfg.ndt_min_gain; + p->AGC_NDT_speech_thr = cfg.ndt_speech_thr; + p->AGC_DT_max_gain = cfg.dt_max_gain; + p->AGC_DT_min_gain = cfg.dt_min_gain; + p->AGC_DT_speech_thr = cfg.dt_speech_thr; + p->AGC_echo_present_thr = cfg.echo_present_thr; + p->AEC_DT_AggressiveFactor = cfg.aec_dt_aggress; + p->AEC_RefEngThr = cfg.aec_refengthr; + p->ES_AggressFactor = cfg.es_aggress_factor; + p->ES_MinSuppress = cfg.es_min_suppress; + p->ES_Unconverge_OverDrive = cfg.es_min_suppress; + p->ANS_AggressFactor = cfg.ans_aggress; + p->ANS_MinSuppress = cfg.ans_suppress; +#if (TCFG_AUDIO_CVP_NS_MODE == CVP_DNS_MODE) + p->DNS_OverDrive = cfg.ans_aggress; + p->DNS_GainFloor = cfg.ans_suppress; + p->DNS_Loudness = 1.0f; + extern void put_float(double fv); + printf("DNS_OverDrive:"); + put_float(p->DNS_OverDrive); + printf("DNS_GainFloor:"); + put_float(p->DNS_GainFloor); +#endif/*TCFG_AUDIO_CVP_NS_MODE*/ + //dumpModulaStatus(cfg.aec_mode); + p->EnableBit = (cfg.aec_mode & AEC_MODE_ADVANCE); + if (p->EnableBit == 0) { + p->toggle = 0; + printf("cvp toggle off\n"); + } + if ((cfg.aec_mode & AGC_EN) == 0) { + p->agc_en = (cfg.aec_mode & AGC_EN) ? 1 : 0; + } + p->ul_eq_en = cfg.ul_eq_en; + printf("aec_mode:%x,agc_en:%d,ul_eq_en:%d\n", cfg.aec_mode, p->agc_en, p->ul_eq_en); + //aec_param_dump(p); + } else { + log_error("read audio_aec param err:%x", ret); + } +} + +/* +********************************************************************* +* Audio AEC Open +* Description: 初始化AEC模块 +* Arguments : sr 采样率(8000/16000) +* enablebit 使能模块(AEC/NLP/AGC/ANS...) +* out_hdl 自定义回调函数,NULL则用默认的回调 +* Return : 0 成功 其他 失败 +* Note(s) : 该接口是对audio_aec_init的扩展,支持自定义使能模块以及 +* 数据输出回调函数 +********************************************************************* +*/ +int audio_aec_open(u16 sample_rate, s16 enablebit, int (*out_hdl)(s16 *data, u16 len)) +{ + struct aec_s_attr *aec_param; + printf("audio_aec_open,sr = %d\n", sample_rate); + mem_stats(); +#if AEC_MALLOC_ENABLE + aec_hdl = zalloc(sizeof(struct audio_aec_hdl)); + if (aec_hdl == NULL) { + log_error("aec_hdl malloc failed"); + return -ENOMEM; + } +#else + aec_hdl = &aec_handle; +#endif/*AEC_MALLOC_ENABLE*/ + cbuf_init(&aec_hdl->output_cbuf, aec_hdl->output_buf, sizeof(aec_hdl->output_buf)); + aec_hdl->start = 1; + aec_hdl->dump_packet = AEC_OUT_DUMP_PACKET; + aec_hdl->inbuf_clear_cnt = AEC_IN_DUMP_PACKET; + aec_hdl->output_fade_in = 1; + aec_hdl->output_fade_in_gain = 0; + aec_param = &aec_hdl->attr; + +#if (TCFG_APP_FM_EMITTER_EN) + aec_param->output_way = 1; +#elif (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC) + aec_param->output_way = 0; +#else + aec_param->output_way = 1; +#endif + + aec_param->toggle = 1; + aec_param->EnableBit = AEC_MODULE_BIT; + aec_param->agc_en = 1; + aec_param->wideband = 0; + aec_param->ul_eq_en = 1; + aec_param->packet_dump = 50;/*0~255(u8)*/ + + aec_param->AGC_NDT_fade_in_step = 1.3f; + aec_param->AGC_NDT_fade_out_step = 0.9f; + aec_param->AGC_DT_fade_in_step = 1.3f; + aec_param->AGC_DT_fade_out_step = 0.9f; + aec_param->AGC_NDT_max_gain = 12.f; + aec_param->AGC_NDT_min_gain = 0.f; + aec_param->AGC_NDT_speech_thr = -50.f; + aec_param->AGC_DT_max_gain = 12.f; + aec_param->AGC_DT_min_gain = 0.f; + aec_param->AGC_DT_speech_thr = -40.f; + aec_param->AGC_echo_look_ahead = 100; + aec_param->AGC_echo_present_thr = -70.f; + aec_param->AGC_echo_hold = 400; + + /*AEC*/ + aec_param->AEC_DT_AggressiveFactor = 1.f; /*范围:1~5,越大追踪越好,但会不稳定,如破音*/ + aec_param->AEC_RefEngThr = -70.f; + + /*ES*/ + aec_param->ES_AggressFactor = -3.0f; + aec_param->ES_MinSuppress = 4.f; + aec_param->ES_Unconverge_OverDrive = aec_param->ES_MinSuppress; + + /*ANS*/ + aec_param->ANS_mode = CONST_ANS_MODE; + aec_param->ANS_AggressFactor = 1.25f; /*范围:1~2,动态调整,越大越强(1.25f)*/ + aec_param->ANS_MinSuppress = 0.04f; /*范围:0~1,静态定死最小调整,越小越强(0.09f)*/ + aec_param->ANS_NoiseLevel = 2.2e4f; + +#if TCFG_AEC_SIMPLEX + aec_param->wn_en = 1; +#else + aec_param->wn_en = 0; +#endif/*TCFG_AEC_SIMPLEX*/ + + aec_param->aec_tail_length = AEC_TAIL_LENGTH; + aec_param->wn_gain = 331; + aec_param->SimplexTail = AEC_SIMPLEX_TAIL; + aec_param->SimplexThr = AEC_SIMPLEX_THR; +#if ((TCFG_APP_FM_EMITTER_EN) || TCFG_AEC_SIMPLEX) + aec_param->dly_est = 1; +#else + aec_param->dly_est = 0; +#endif/*DLY_EST config*/ + + aec_param->dst_delay = 50; + aec_param->aec_probe = audio_aec_probe; + aec_param->aec_post = audio_aec_post; + aec_param->output_handle = audio_aec_output; + aec_param->ref_sr = usb_mic_is_running(); + if (aec_param->ref_sr == 0) { + aec_param->ref_sr = sample_rate; + } + + audio_aec_param_read_config(aec_param); + if (enablebit >= 0) { + aec_param->EnableBit = enablebit; + } + if (out_hdl) { + aec_param->output_handle = out_hdl; + } + + if (sample_rate == 16000) { + aec_param->wideband = 1; + aec_param->hw_delay_offset = 50; + if (aec_param->EnableBit == AEC_MODE_ADVANCE) { + clock_add(AEC16K_ADV_CLK); + } else { + clock_add(AEC16K_CLK); + } + } else { + aec_param->wideband = 0; + aec_param->hw_delay_offset = 75; + if (aec_param->EnableBit == AEC_MODE_ADVANCE) { + clock_add(AEC8K_ADV_CLK); + } else { + clock_add(AEC8K_CLK); + } + } + clock_set_cur(); +#if TCFG_AEC_SIMPLEX + aec_param->EnableBit = AEC_MODE_SIMPLEX; + if (sample_rate == 8000) { + aec_param->SimplexTail = aec_param->SimplexTail / 2; + } +#endif/*TCFG_AEC_SIMPLEX*/ + + +#if AEC_UL_EQ_EN + if (aec_param->ul_eq_en) { + /* memset(&aec_hdl->ul_eq, 0, sizeof(struct audio_eq)); */ + /* memset(&aec_hdl->ul_eq_ch, 0, sizeof(struct hw_eq_ch)); */ + /* aec_hdl->ul_eq.eq_ch = &aec_hdl->ul_eq_ch; */ + u8 mode = 2; + if (sample_rate == 8000) { + mode = 3; + } + struct audio_eq_param ul_eq_param = {0}; + ul_eq_param.sr = sample_rate; + ul_eq_param.channels = 1; + ul_eq_param.max_nsection = phone_mode[mode].eq_parm.seg_num; + ul_eq_param.nsection = phone_mode[mode].eq_parm.seg_num; + ul_eq_param.seg = phone_mode[mode].eq_parm.seg; + ul_eq_param.global_gain = phone_mode[mode].eq_parm.global_gain; + ul_eq_param.cb = eq_get_filter_info; + ul_eq_param.eq_name = AEID_ESCO_UL_EQ; + aec_hdl->ul_eq = audio_dec_eq_open(&ul_eq_param); + /* audio_eq_open(&aec_hdl->ul_eq, &ul_eq_param); */ + /* audio_eq_set_samplerate(&aec_hdl->ul_eq, sample_rate); */ + /* audio_eq_set_output_handle(&aec_hdl->ul_eq, ul_eq_output, NULL); */ + /* audio_eq_start(&aec_hdl->ul_eq); */ + } +#endif/*AEC_UL_EQ_EN*/ + +#if AEC_DCCS_EN + if (adc_data.mic_capless) { + /* memset(&aec_hdl->dccs_eq, 0, sizeof(struct audio_eq)); */ + /* memset(&aec_hdl->dccs_eq_ch, 0, sizeof(struct hw_eq_ch)); */ + + /* .eq_ch = &aec_hdl->dccs_eq_ch; */ + struct audio_eq_param dccs_eq_param = {0}; + dccs_eq_param.sr = sample_rate; + dccs_eq_param.channels = 1; + dccs_eq_param.max_nsection = 1; + dccs_eq_param.cb = aec_dccs_eq_filter; + aec_hdl->dccs_eq = audio_dec_eq_open(&dccs_eq_param); + /* audio_eq_open(&aec_hdl->dccs_eq, &dccs_eq_param); */ + /* audio_eq_set_samplerate(&aec_hdl->dccs_eq, sample_rate); */ + /* audio_eq_set_output_handle(&aec_hdl->dccs_eq, dccs_eq_output, NULL); */ + /* audio_eq_start(&aec_hdl->dccs_eq); */ + } +#endif/*AEC_DCCS_EN*/ + + //aec_param->toggle = 1; + //aec_param->EnableBit = AEC_MODULE_BIT; + //aec_param_dump(aec_param); + +#if AEC_TOGGLE + aec_open(aec_param); +#endif + mem_stats(); + printf("audio_aec_open succ\n"); + return 0; +} + +/* +********************************************************************* +* Audio AEC Init +* Description: 初始化AEC模块 +* Arguments : sr 采样率(8000/16000) +* Return : 0 成功 其他 失败 +* Note(s) : None. +********************************************************************* +*/ +int audio_aec_init(u16 sample_rate) +{ + return audio_aec_open(sample_rate, -1, NULL); +} + +/* +********************************************************************* +* Audio AEC Close +* Description: 关闭AEC模块 +* Arguments : None. +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_aec_close(void) +{ + printf("audio_aec_close:%x", (u32)aec_hdl); + struct aec_s_attr *aec_param; + if (aec_hdl) { + aec_hdl->start = 0; + + aec_param = &aec_hdl->attr; + if (aec_param->wideband) { + if (aec_param->EnableBit == AEC_MODE_ADVANCE) { + clock_remove(AEC16K_ADV_CLK); + } else { + clock_remove(AEC16K_CLK); + } + } else { + if (aec_param->EnableBit == AEC_MODE_ADVANCE) { + clock_remove(AEC8K_ADV_CLK); + } else { + clock_remove(AEC8K_CLK); + } + } + clock_set_cur(); + +#if AEC_TOGGLE + aec_close(); +#endif/*AEC_TOGGLE*/ +#if AEC_DCCS_EN + if (aec_hdl->dccs_eq) { + audio_dec_eq_close(aec_hdl->dccs_eq); + } +#endif/*AEC_DCCS_EN*/ +#if AEC_UL_EQ_EN + if (aec_hdl->ul_eq) { + audio_dec_eq_close(aec_hdl->ul_eq); + } +#endif/*AEC_UL_EQ_EN*/ + local_irq_disable(); +#if AEC_MALLOC_ENABLE + free(aec_hdl); +#endif/*AEC_MALLOC_ENABLE*/ + aec_hdl = NULL; + local_irq_enable(); + } + printf("audio_aec_close ok\n"); +} + +/* +********************************************************************* +* Audio AEC Input +* Description: AEC源数据输入 +* Arguments : buf 输入源数据地址 +* len 输入源数据长度 +* Return : None. +* Note(s) : 输入一帧数据,唤醒一次运行任务处理数据,默认帧长256点 +********************************************************************* +*/ +void audio_aec_inbuf(s16 *buf, u16 len) +{ + if (aec_hdl && aec_hdl->start) { +#if AEC_TOGGLE + if (aec_hdl->inbuf_clear_cnt) { + aec_hdl->inbuf_clear_cnt--; + memset(buf, 0, len); + } + int ret = aec_in_data((u8 *)buf, len); + if (ret == -1) { +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC) + /* log_info("fill dac data\n"); + u8 tmp_buf[64] = {0}; + for (u8 i = 0; i < 512 / sizeof(tmp_buf); i++) { + app_audio_output_write(tmp_buf, sizeof(tmp_buf)); + } */ +#endif + } else if (ret == -2) { + log_error("aec inbuf full\n"); + } +#else + audio_aec_output(buf, len); +#endif/*AEC_TOGGLE*/ + } +} + +/* +********************************************************************* +* Audio AEC Reference +* Description: AEC模块参考数据输入 +* Arguments : buf 输入参考数据地址 +* len 输入参考数据长度 +* Return : None. +* Note(s) : 声卡设备是DAC,默认不用外部提供参考数据 +********************************************************************* +*/ +void audio_aec_refbuf(s16 *buf, u16 len) +{ + if (aec_hdl && aec_hdl->start) { +#if AEC_TOGGLE + aec_ref_data((u8 *)buf, len); +#endif/*AEC_TOGGLE*/ + } +} + +/* void aec_estimate_dump(int DlyEst) +{ + printf("DlyEst:%d\n",DlyEst); +} */ + +#endif /*TCFG_CVP_DEVELOP_ENABLE*/ diff --git a/apps/soundbox/aec/br23/audio_aec_demo.c b/apps/soundbox/aec/br23/audio_aec_demo.c new file mode 100644 index 0000000..785bc1e --- /dev/null +++ b/apps/soundbox/aec/br23/audio_aec_demo.c @@ -0,0 +1,483 @@ +/* + *************************************************************************** + * AUDIO AEC DEMO + * File : audio_aec_demo.c + * By : GZR + * Notes : 1.可用内存 + * (1)free_ram: 动态内存(mem_stats:physics memory size xxxx bytes) + * (2)mux_rx_bulk:蓝牙复用空间(MUX_RX_BULK_MAX) + * 2.demo默认将输入数据copy到输出,相关处理只需在运算函数 + * audio_aec_run()实现即可 + * 3.双mic ENC开发,只需打开对应板级以下配置即可: + * #define TCFG_AUDIO_DUAL_MIC_ENABLE ENABLE_THIS_MOUDLE + * 4.建议算法开发者使用宏定义将自己的代码模块包起来 + * 5.算法处理完的数据,如有需要,可以增加EQ处理:AEC_UL_EQ_EN + * 6.开发阶段,默认使用芯片最高主频240MHz,可以通过修改AEC_CLK来修改 + 运行频率。 + *************************************************************************** + */ +#include "aec_user.h" +#include "system/includes.h" +#include "media/includes.h" +#include "media/audio_eq_drc_apply.h" +#include "circular_buf.h" +#include "debug.h" + +#if defined(TCFG_CVP_DEVELOP_ENABLE) && (TCFG_CVP_DEVELOP_ENABLE == 1) + +#define AEC_MALLOC_ENABLE 0 /*是否使用动态内存*/ + +#define AEC_EXTERN_REFERENCE_ENABLE 0 /*是否使用外部取的参考dac数据*/ + +#define AEC_CLK (160 * 1000000L) /*模块运行时钟(MaxFre:240MHz)*/ +#define AEC_FRAME_POINTS 256 /*AEC处理帧长,跟mic采样长度关联*/ +#define AEC_FRAME_SIZE (AEC_FRAME_POINTS << 1) + +#if TCFG_AUDIO_DUAL_MIC_ENABLE /*ac695不支持双mic*/ +#define AEC_MIC_NUM 2 /*双mic*/ +#else +#define AEC_MIC_NUM 1 /*单mic*/ +#endif/*TCFG_AUDIO_DUAL_MIC_ENABLE*/ + +#ifdef AUDIO_PCM_DEBUG +/*AEC串口数据导出*/ +const u8 CONST_AEC_EXPORT = 1; +#else +const u8 CONST_AEC_EXPORT = 0; +#endif/*AUDIO_PCM_DEBUG*/ + +/*上行数据eq*/ +#define AEC_UL_EQ_EN 0//TCFG_AEC_UL_EQ_ENABLE + + +extern int audio_dac_read_reset(void); +extern int audio_dac_read(s16 points_offset, void *data, int len); +extern void esco_enc_resume(void); +extern int aec_uart_init(); +extern int aec_uart_fill(u8 ch, void *buf, u16 size); +extern void aec_uart_write(void); +extern int aec_uart_close(void); + +/* + *蓝牙收数buf复用使用说明 + *(1)打开复用:apps/earphone/log_config/lib_btctrler_config.c + * const int CONFIG_ESCO_MUX_RX_BULK_ENABLE = 1; + *(2)MUX_RX_BULK_TEST_DEMO是使用范例 + *(3)zalloc_mux_rx_bulk/free_mux_rx_bulk用法和普通malloc/free一样 + */ +//#define MUX_RX_BULK_TEST_DEMO /*蓝牙收数buf复用使用范例*/ +#define MUX_RX_BULK_MAX (9 * 1024 - 100) /*蓝牙收数buf最多可以申请到7k*/ +extern void *zalloc_mux_rx_bulk(int size); +extern void free_mux_rx_bulk(void *buf); +int *mux_rx_bulk_test = NULL; + +/*AEC输入buf复用mic_adc采样buf*/ +#define MIC_BULK_MAX 3 +struct mic_bulk { + struct list_head entry; + s16 *addr; + u16 len; + u16 used; +}; + +struct audio_aec_hdl { + u8 start; + volatile u8 busy; + u8 output_buf[1000]; /*aec模块输出缓存*/ + cbuffer_t output_cbuf; + s16 *mic; /*主mic数据地址*/ + s16 *mic_ref; /*参考mic数据地址*/ + s16 *free_ram; /*当前可用内存*/ + s16 spk_ref[AEC_FRAME_POINTS]; /*扬声器参考数据*/ + s16 out[AEC_FRAME_POINTS]; /*运算输出地址*/ + OS_SEM sem; + /*数据复用相关数据结构*/ + struct mic_bulk in_bulk[MIC_BULK_MAX]; + struct mic_bulk inref_bulk[MIC_BULK_MAX]; + struct list_head in_head; + struct list_head inref_head; +#if AEC_UL_EQ_EN + struct audio_eq *ul_eq; +#endif/*AEC_UL_EQ_EN*/ + struct aec_s_attr attr; +#if AEC_EXTERN_REFERENCE_ENABLE + u8 extern_ref_buf[1000]; /*aec外部参考数据缓存*/ + cbuffer_t extern_ref_cbuf; +#endif // AEC_EXTERN_REFERENCE_ENABLE +}; +struct audio_aec_hdl *aec_hdl = NULL; +#if (AEC_MALLOC_ENABLE == 0) +struct audio_aec_hdl aec_hdl_mem AT(.aec_mem); +#endif /*AEC_MALLOC_ENABLE*/ + +extern void esco_adc_mic_en(); +void audio_aec_ref_start(u8 en) +{ + if (aec_hdl) { + if (en != aec_hdl->attr.fm_tx_start) { + aec_hdl->attr.fm_tx_start = en; + esco_adc_mic_en(); + y_printf("fm_tx_start:%d\n", en); + } + } +} + +int audio_aec_output_read(s16 *buf, u16 len) +{ + local_irq_disable(); + if (!aec_hdl || !aec_hdl->start) { + printf("audio_aec close now"); + local_irq_enable(); + return -EINVAL; + } + u16 rlen = cbuf_read(&aec_hdl->output_cbuf, buf, len); + if (rlen == 0) { + //putchar('N'); + } + local_irq_enable(); + return rlen; +} + +static int audio_aec_output(s16 *buf, u16 len) +{ + u16 wlen = 0; + if (aec_hdl && aec_hdl->start) { + wlen = cbuf_write(&aec_hdl->output_cbuf, buf, len); + if (wlen != len) { + printf("aec_out_full:%d,%d\n", len, wlen); + } + esco_enc_resume(); + } + return wlen; +} + +#if AEC_UL_EQ_EN +static int ul_eq_output(void *priv, void *data, u32 len) +{ + return 0; +} +#endif/*AEC_UL_EQ_EN*/ + +/* + *跟踪系统内存使用情况:physics memory size xxxx bytes + *正常的系统运行过程,应该至少有3k bytes的剩余空间给到系统调度开销 + */ +static void sys_memory_trace(void) +{ + static int cnt = 0; + if (cnt++ > 200) { + cnt = 0; + mem_stats(); + } +} + +/* +********************************************************************* +* Audio AEC RUN +* Description: AEC数据处理核心 +* Arguments : in 主mic数据 +* inref 参考mic数据(双mic降噪有用) +* ref speaker参考数据 +* out 数据输出 +* Return : 数据运算输出长度 +* Note(s) : 在这里实现AEC_core +********************************************************************* +*/ +static int audio_aec_run(s16 *in, s16 *inref, s16 *ref, s16 *out, u16 points) +{ + int out_size = 0; + putchar('.'); + memcpy(out, in, (points << 1)); + //memcpy(out, inref, (points << 1)); + out_size = points << 1; +#if AEC_UL_EQ_EN + if (aec_hdl->ul_eq) { + //putchar('Q'); + audio_eq_run(aec_hdl->ul_eq, out, out_size); + } +#endif/*AEC_UL_EQ_EN*/ + sys_memory_trace(); + return out_size; +} + +/* +********************************************************************* +* Audio AEC Task +* Description: AEC任务 +* Arguments : priv 私用参数 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +static void audio_aec_task(void *priv) +{ + printf("==Audio AEC Task==\n"); + struct mic_bulk *bulk = NULL; + struct mic_bulk *bulk_ref = NULL; + u8 pend = 1; + while (1) { + if (pend) { + os_sem_pend(&aec_hdl->sem, 0); + } + pend = 1; + if (aec_hdl->start) { + if (!list_empty(&aec_hdl->in_head)) { + aec_hdl->busy = 1; + local_irq_disable(); + /*1.获取主mic数据*/ + bulk = list_first_entry(&aec_hdl->in_head, struct mic_bulk, entry); + list_del(&bulk->entry); + aec_hdl->mic = bulk->addr; +#if (AEC_MIC_NUM == 2) + /*2.获取参考mic数据*/ + bulk_ref = list_first_entry(&aec_hdl->inref_head, struct mic_bulk, entry); + list_del(&bulk_ref->entry); + aec_hdl->mic_ref = bulk_ref->addr; +#endif/*Dual_Microphone*/ + local_irq_enable(); +#if AEC_EXTERN_REFERENCE_ENABLE + /*3.获取外部参考数据*/ + //audio_dac_read(60, aec_hdl->spk_ref, AEC_FRAME_SIZE); + cbuf_read(&aec_hdl->extern_ref_cbuf, aec_hdl->spk_ref, AEC_FRAME_SIZE); +#else + /*3.获取speaker参考数据*/ + audio_dac_read(60, aec_hdl->spk_ref, AEC_FRAME_SIZE); +#endif //AEC_EXTERN_REFERENCE_ENABLE + /*4.算法处理*/ + int out_len = audio_aec_run(aec_hdl->mic, aec_hdl->mic_ref, aec_hdl->spk_ref, aec_hdl->out, AEC_FRAME_POINTS); + + /*5.结果输出*/ + audio_aec_output(aec_hdl->out, out_len); + + /*6.数据导出*/ + if (CONST_AEC_EXPORT) { + aec_uart_fill(0, aec_hdl->mic, 512); //主mic数据 + // aec_uart_fill(1, aec_hdl->mic_ref, 512); //副mic数据 + aec_uart_fill(1, aec_hdl->spk_ref, 512); //扬声器数据 + aec_uart_fill(2, aec_hdl->out, out_len); //算法运算结果 + aec_uart_write(); + } + bulk->used = 0; +#if (AEC_MIC_NUM == 2) + bulk_ref->used = 0; +#endif/*Dual_Microphone*/ + aec_hdl->busy = 0; + pend = 0; + } + } + } +} + +/* +********************************************************************* +* Audio AEC Init +* Description: 初始化AEC模块 +* Arguments : sample_rate 采样率(8000/16000) +* Return : 0 成功 其他 失败 +* Note(s) : None. +********************************************************************* +*/ +int audio_aec_init(u16 sample_rate) +{ + printf("audio_aec_init,sr = %d\n", sample_rate); + mem_stats(); + if (aec_hdl) { + return -1; + } +#if AEC_MALLOC_ENABLE + aec_hdl = zalloc(sizeof(struct audio_aec_hdl)); +#else /*AEC_MALLOC_ENABLE == 0*/ + memset(&aec_hdl_mem, 0, sizeof(aec_hdl_mem)); + aec_hdl = &aec_hdl_mem; +#endif /*AEC_MALLOC_ENABLE*/ + printf("aec_hdl size:%d\n", sizeof(struct audio_aec_hdl)); + clk_set("sys", AEC_CLK); + INIT_LIST_HEAD(&aec_hdl->in_head); + INIT_LIST_HEAD(&aec_hdl->inref_head); + cbuf_init(&aec_hdl->output_cbuf, aec_hdl->output_buf, sizeof(aec_hdl->output_buf)); +#if AEC_EXTERN_REFERENCE_ENABLE + cbuf_init(&aec_hdl->extern_ref_cbuf, aec_hdl->extern_ref_buf, sizeof(aec_hdl->extern_ref_buf)); +#endif // AEC_EXTERN_REFERENCE_ENABLE + if (CONST_AEC_EXPORT) { + aec_uart_init(); + printf("aec_uart_init \n"); + } +#if AEC_UL_EQ_EN + struct audio_eq_param ul_eq_param = {0}; + ul_eq_param.sr = sample_rate; + ul_eq_param.channels = 1; + ul_eq_param.online_en = 1; + ul_eq_param.mode_en = 0; + ul_eq_param.remain_en = 0; + ul_eq_param.max_nsection = EQ_SECTION_MAX; + ul_eq_param.cb = aec_ul_eq_filter; + ul_eq_param.eq_name = aec_eq_mode; + aec_hdl->ul_eq = audio_dec_eq_open(&ul_eq_param); + /* audio_eq_open(&aec_hdl->ul_eq, &ul_eq_param); */ + /* audio_eq_set_samplerate(&aec_hdl->ul_eq, sample_rate); */ + /* audio_eq_set_output_handle(&aec_hdl->ul_eq, ul_eq_output, NULL); */ + /* audio_eq_start(&aec_hdl->ul_eq); */ +#endif/*AEC_UL_EQ_EN*/ + os_sem_create(&aec_hdl->sem, 0); + task_create(audio_aec_task, NULL, "aec"); + audio_dac_read_reset(); + aec_hdl->start = 1; + + mem_stats(); +#if 0 + aec_hdl->free_ram = malloc(1024 * 63); + mem_stats(); +#endif + +#ifdef MUX_RX_BULK_TEST_DEMO + mux_rx_bulk_test = zalloc_mux_rx_bulk(MUX_RX_BULK_MAX); + if (mux_rx_bulk_test) { + printf("mux_rx_bulk_test:0x%x\n", mux_rx_bulk_test); + free_mux_rx_bulk(mux_rx_bulk_test); + mux_rx_bulk_test = NULL; + } +#endif/*MUX_RX_BULK_TEST_DEMO*/ + + printf("audio_aec_init succ\n"); + return 0; +} + +/* +********************************************************************* +* Audio AEC Close +* Description: 关闭AEC模块 +* Arguments : None. +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_aec_close(void) +{ + printf("audio_aec_close succ\n"); + if (aec_hdl) { + aec_hdl->start = 0; + while (aec_hdl->busy) { + os_time_dly(2); + } + task_kill("aec"); + if (CONST_AEC_EXPORT) { + aec_uart_close(); + } +#if AEC_UL_EQ_EN + if (aec_hdl->ul_eq) { + audio_dec_eq_close(aec_hdl->ul_eq); + } +#endif/*AEC_UL_EQ_EN*/ + local_irq_disable(); + if (aec_hdl->free_ram) { + free(aec_hdl->free_ram); + } +#if AEC_MALLOC_ENABLE + free(aec_hdl); +#endif /*AEC_MALLOC_ENABLE*/ + aec_hdl = NULL; + local_irq_enable(); + printf("audio_aec_close succ\n"); + } +} + +/* +********************************************************************* +* Audio AEC Input +* Description: AEC源数据输入 +* Arguments : buf 输入源数据地址 +* len 输入源数据长度 +* Return : None. +* Note(s) : 输入一帧数据,唤醒一次运行任务处理数据,默认帧长256点 +********************************************************************* +*/ +void audio_aec_inbuf(s16 *buf, u16 len) +{ + if (aec_hdl && aec_hdl->start) { + int i = 0; + for (i = 0; i < MIC_BULK_MAX; i++) { + if (aec_hdl->in_bulk[i].used == 0) { + break; + } + } + if (i < MIC_BULK_MAX) { + aec_hdl->in_bulk[i].addr = buf; + aec_hdl->in_bulk[i].used = 0x55; + aec_hdl->in_bulk[i].len = len; + list_add_tail(&aec_hdl->in_bulk[i].entry, &aec_hdl->in_head); + } else { + printf(">>>aec_in_full\n"); + /*align reset*/ + struct mic_bulk *bulk; + list_for_each_entry(bulk, &aec_hdl->in_head, entry) { + bulk->used = 0; + __list_del_entry(&bulk->entry); + } + return; + } + os_sem_set(&aec_hdl->sem, 0); + os_sem_post(&aec_hdl->sem); + } +} + +void audio_aec_inbuf_ref(s16 *buf, u16 len) +{ + if (aec_hdl && aec_hdl->start) { + int i = 0; + for (i = 0; i < MIC_BULK_MAX; i++) { + if (aec_hdl->inref_bulk[i].used == 0) { + break; + } + } + if (i < MIC_BULK_MAX) { + aec_hdl->inref_bulk[i].addr = buf; + aec_hdl->inref_bulk[i].used = 0x55; + aec_hdl->inref_bulk[i].len = len; + list_add_tail(&aec_hdl->inref_bulk[i].entry, &aec_hdl->inref_head); + } else { + printf(">>>aec_inref_full\n"); + /*align reset*/ + struct mic_bulk *bulk; + list_for_each_entry(bulk, &aec_hdl->inref_head, entry) { + bulk->used = 0; + __list_del_entry(&bulk->entry); + } + return; + } + } +} + +/* +********************************************************************* +* Audio AEC Reference +* Description: AEC模块参考数据输入 +* Arguments : buf 输入参考数据地址 +* len 输入参考数据长度 +* Return : None. +* Note(s) : 声卡设备是DAC,默认不用外部提供参考数据 +********************************************************************* +*/ +void audio_aec_refbuf(s16 *buf, u16 len) +{ +#if AEC_EXTERN_REFERENCE_ENABLE + u16 wlen = 0; + if (aec_hdl && aec_hdl->start) { + wlen = cbuf_write(&aec_hdl->extern_ref_cbuf, buf, len); + } +#endif // AEC_EXTERN_REFERENCE_ENABLE +} + + + + + +void aec_cfg_fill(AEC_CONFIG *cfg) +{ +} +void audio_aec_dlyest_en(void) +{ + +} + +#endif /*TCFG_CVP_DEVELOP_ENABLE*/ + diff --git a/apps/soundbox/app_main.c b/apps/soundbox/app_main.c new file mode 100644 index 0000000..f4ce2eb --- /dev/null +++ b/apps/soundbox/app_main.c @@ -0,0 +1,150 @@ +#include "system/includes.h" +#include "app_config.h" +#include "asm/pwm_led.h" +#include "tone_player.h" +#include "ui_manage.h" +#include "app_main.h" +#include "app_task.h" +#include "asm/charge.h" +#include "app_power_manage.h" +#include "app_charge.h" +#include "user_cfg.h" +#include "power_on.h" +#include "bt.h" +#include "soundcard/peripheral.h" +#include "audio.h" +#include "vm.h" + + +#define LOG_TAG_CONST APP +#define LOG_TAG "[APP]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + + +APP_VAR app_var; + + +void app_entry_idle() +{ + app_task_switch_to(APP_IDLE_TASK); +} + + + +void app_task_loop() +{ + while (1) { + switch (app_curr_task) { + case APP_POWERON_TASK: + log_info("APP_POWERON_TASK \n"); + app_poweron_task(); + break; + case APP_POWEROFF_TASK: + log_info("APP_POWEROFF_TASK \n"); + app_poweroff_task(); + break; + case APP_BT_TASK: + log_info("APP_BT_TASK \n"); + app_bt_task(); + break; + case APP_MUSIC_TASK: + log_info("APP_MUSIC_TASK \n"); + app_music_task(); + break; + case APP_FM_TASK: + log_info("APP_FM_TASK \n"); + app_fm_task(); + break; + case APP_RECORD_TASK: + log_info("APP_RECORD_TASK \n"); + app_record_task(); + break; + case APP_LINEIN_TASK: + log_info("APP_LINEIN_TASK \n"); + app_linein_task(); + break; + case APP_RTC_TASK: + log_info("APP_RTC_TASK \n"); + app_rtc_task(); + break; + case APP_PC_TASK: + log_info("APP_PC_TASK \n"); + app_pc_task(); + break; + case APP_SPDIF_TASK: + log_info("APP_SPDIF_TASK \n"); + app_spdif_task(); + break; + case APP_IDLE_TASK: + log_info("APP_IDLE_TASK \n"); + app_idle_task(); + break; + case APP_SLEEP_TASK: + log_info("APP_SLEEP_TASK \n"); + app_sleep_task(); + break; + case APP_SMARTBOX_ACTION_TASK: + log_info("APP_SMARTBOX_ACTION_TASK \n"); + app_smartbox_task(); + break; + } + app_task_clear_key_msg();//清理按键消息 + //检查整理VM + vm_check_all(0); + } +} + +void app_main() +{ + log_info("app_main\n"); + + app_var.start_time = timer_get_ms(); + + if (get_charge_online_flag()) { + + app_var.poweron_charge = 1; + +#if (TCFG_SYS_LVD_EN == 1) + vbat_check_init(); +#endif + +#ifndef PC_POWER_ON_CHARGE + app_curr_task = APP_IDLE_TASK; +#else + app_curr_task = APP_POWERON_TASK; +#endif + } else { +#if SOUNDCARD_ENABLE + soundcard_peripheral_init(); +#endif + +#if TCFG_HOST_AUDIO_ENABLE + void usb_host_audio_init(int (*put_buf)(void *ptr, u32 len), int *(*get_buf)(void *ptr, u32 len)); + usb_host_audio_init(usb_audio_play_put_buf, usb_audio_record_get_buf); +#endif + + /* endless_loop_debug_int(); */ + ui_update_status(STATUS_POWERON); + + app_curr_task = APP_POWERON_TASK; + } + +#if TCFG_CHARGE_BOX_ENABLE + app_curr_task = APP_IDLE_TASK; +#endif + +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) + usb_cdc_background_run(); +#endif + + app_task_loop(); +} + + + diff --git a/apps/soundbox/board/br23/board_ac6083a/board_ac6083a.c b/apps/soundbox/board/br23/board_ac6083a/board_ac6083a.c new file mode 100644 index 0000000..51e1b93 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6083a/board_ac6083a.c @@ -0,0 +1,1347 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC6083A + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "fm/fm_manage.h" +#include "asm/power/p33.h" +#include "norflash.h" +#include "asm/spi.h" +#include "ui_manage.h" +#include "spi/nor_fs.h" +#include "user_api/app_status_api.h" +#include "app_main.h" +#include "app_task.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +enum{ + TURN_ON, + TURN_OFF, + FAST_BLINK, + SLOW_BLINK, +}; + + +#define LED_CNT_BASE 5//闪灯频率控制 + + +int cur_led_mode=FAST_BLINK;//闪灯状态 +static u16 music_turnoff_timer=0; +static u16 led_blink_timer1=0; +static u16 led_blink_timer2=0; +static u16 power_on_timer=0; + +static u32 ot;//pc状态区分 +static u16 cr_t_id=0; + +static u16 led_scan_timer; +static soft_poweroff_timer; + + + +/*******************相关定时处理******************/ +static void led_open() +{ + static u16 cnt_1=0; + if(cnt_1>10)//变幅 + gpio_set_output_value(IO_PORTB_10,1); + else + gpio_set_output_value(IO_PORTB_10,0); + cnt_1++; + if(cnt_1>11) + cnt_1=0; +} + +static void led_close() +{ + gpio_set_output_value(IO_PORTB_10,0); +} + +static void poweron_led_blink() +{ + if(cur_led_mode==FAST_BLINK) + cur_led_mode=TURN_ON; +} + +static void poweroff_led_blink1() +{ + if(get_charge_online_flag()==0) + cur_led_mode=FAST_BLINK; + else + cur_led_mode=TURN_OFF; +} + +static void poweroff_led_blink2() +{ + cur_led_mode=TURN_OFF; +} + +static void music_turnoff() +{ + if(get_charge_online_flag()==0){ + app_var.goto_poweroff_flag=1; + app_task_switch_to(APP_POWEROFF_TASK); + } + else{ + app_task_switch_to(APP_IDLE_TASK); + } +} + +static void card_reader_timer() +{ + ot--; + if(ot){ + cur_led_mode=FAST_BLINK; + } + else{ + if(cr_t_id) + sys_timer_del(cr_t_id); + cur_led_mode=TURN_ON; + cr_t_id=0; + } + +} + +static void pc_led_handler() +{ + if(!cr_t_id) + cr_t_id=sys_timer_add(NULL,card_reader_timer,100); + ot=3; +} + +static void soft_poweroff() +{ + int poweroff_pin_value=gpio_read(IO_PORTA_01); + if(poweroff_pin_value==0){ + P33_CON_SET(P3_PINR_CON, 0, 1, 1); + P33_CON_SET(P3_PINR_CON, 2, 1, 1); + app_var.goto_poweroff_flag=1; + app_task_switch_to(APP_POWEROFF_TASK); + }else{ + P33_CON_SET(P3_PINR_CON, 0, 1, 1); + P33_CON_SET(P3_PINR_CON, 2, 1, 0); + } +} + +/****************led状态处理**************/ +void led_scan() +{ + + /* gpio_set_output_value(IO_PORT_DP,1); */ + static u16 cnt; + switch(cur_led_mode){ + case TURN_OFF: + led_close(); + break; + case TURN_ON: + led_open(); + break; + case FAST_BLINK: + if(cnt>LED_CNT_BASE*25/2)//变频 + led_open(); + else + led_close(); + cnt++; + if(cnt>LED_CNT_BASE*25) + cnt=0; + break; + case SLOW_BLINK: + if(cnt>LED_CNT_BASE*250/2){ + led_open(); + } + else{ + led_close(); + } + cnt++; + if(cnt>LED_CNT_BASE*250) + cnt=0; + break; + default: + break; + } + /* gpio_set_output_value(IO_PORT_DP,0); */ +} + +void app_status_6083_handler(enum APP_STATUS status) +{ + switch(status){ + case APP_STATUS_POWER_ON: + if(cur_led_mode==FAST_BLINK) + cur_led_mode=TURN_ON; + break; + case APP_STATUS_POWER_CLOSE: + cur_led_mode=TURN_OFF; + break; + case APP_STATUS_POWER_OFF: + cur_led_mode=FAST_BLINK; + break; + case APP_STATUS_MUSIC: + cur_led_mode=SLOW_BLINK; + break; + case APP_STATUS_MUSIC_QUIT: + cur_led_mode=TURN_ON; + break; + case APP_STATUS_MUSIC_PP: + cur_led_mode=TURN_ON; + music_turnoff_timer=sys_timeout_add(NULL,music_turnoff,30000); + led_blink_timer1 = sys_timeout_add(NULL,poweroff_led_blink1,28000); + led_blink_timer2 = sys_timeout_add(NULL, poweroff_led_blink2, 29500); + break; + case APP_STATUS_MUSIC_PLAY: + case APP_STATUS_MUSIC_PN: + case APP_STATUS_MUSIC_FFR: + cur_led_mode=SLOW_BLINK; + if(music_turnoff_timer) + sys_timeout_del(music_turnoff_timer); + if(led_blink_timer1) + sys_timeout_del(led_blink_timer1); + if(led_blink_timer2) + sys_timeout_del(led_blink_timer2); + break; + case APP_STATUS_PC: + cur_led_mode=TURN_ON; + if(music_turnoff_timer) + sys_timeout_del(music_turnoff_timer); + if(led_blink_timer1) + sys_timeout_del(led_blink_timer1); + if(led_blink_timer2) + sys_timeout_del(led_blink_timer2); + break; + case APP_STATUS_PC_COPY: + pc_led_handler(); + break; + default: + break; + } +} + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_VOLDOWN_CONNECT_WAY, //IO按键的连接方式 + .key_type.cust_one_io.port = TCFG_IOKEY_VOLDOWN_ONE_PORT, //IO按键对应的引脚 + .key_type.cust_one_io.fun=cust_one_io_get_key_value, + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_VOLUP_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_VOLUP_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.two_io.out_port = TCFG_IOKEY_PREV_OUT_PORT, + .key_type.two_io.in_port = TCFG_IOKEY_PREV_IN_PORT, + .key_value = 2, + } + +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, +#if TCFG_SD1_ENABLE + .pin_cfg.pin7.pin[0] = IO_PORTA_02, + .pin_cfg.pin7.pin[1] = IO_PORTA_03, + .pin_cfg.pin7.pin[2] = IO_PORTA_04, + .pin_cfg.pin7.pin[3] = IO_PORTA_06, + .pin_cfg.pin7.pin[4] = IO_PORTA_07, + .pin_cfg.pin7.pin[5] = IO_PORTA_08, + .pin_cfg.pin7.pin[6] = IO_PORTA_09, +#else + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if TCHFG_SOFT_I2C_ENABLE +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; +#endif + +#if TCHFG_HW_I2C_ENABLE +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NOR_FAT +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 0, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_FS +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 1*1024*1024, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_REC +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 2*1024*1024, + .size = 2*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_FM_ENABLE + +FM_DEV_PLATFORM_DATA_BEGIN(fm_dev_data) + .iic_hdl = 0, + .iic_delay = 50, +FM_DEV_PLATFORM_DATA_END(); + +#endif + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +#if TCFG_NOR_FAT + { "fat_nor", &norflash_dev_ops , (void *)&norflash_fat_dev_data}, +#endif + +#if TCFG_NOR_FS + { "res_nor", &norfs_dev_ops , (void *)&norflash_norfs_dev_data}, +#endif + +#if TCFG_NOR_REC + {"rec_nor", &norfs_dev_ops , (void *)&norflash_norfs_rec_dev_data}, +#endif +#endif +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , + +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif + +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTB_01, //唤醒口选择 +}; + +struct port_wakeup port1 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTA_01, //唤醒口选择 +}; + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + .port[2] = &port1, + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} +static void key_wakeup_disable() +{ + power_wakeup_index_disable(1); +} +static void key_wakeup_enable() +{ + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE || TCFG_6083_ADKEY_ENABLE) + + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + +void adkey_reuse_exit_callback(u32 ch)//adkey复用,把IO设置为led模式 +{ +#if TCFG_ADKEY_LED_IO_REUSE + if(ch == TCFG_ADKEY_AD_CHANNEL){ + + gpio_set_pull_up(TCFG_ADKEY_PORT,1); + gpio_set_pull_down(TCFG_ADKEY_PORT,1); + gpio_set_die(TCFG_ADKEY_PORT,1); + gpio_set_output_value(TCFG_ADKEY_PORT,1); + gpio_set_direction(TCFG_ADKEY_PORT,0); + + } + +#endif + + +} +void adkey_reuse_enter_callback(u32 ch)//adkey复用,把IO设置为adkey模式 +{ +#if TCFG_ADKEY_LED_IO_REUSE + if(ch == TCFG_ADKEY_AD_CHANNEL){ + + gpio_set_die(TCFG_ADKEY_PORT, 0); + gpio_set_direction(TCFG_ADKEY_PORT, 1); + gpio_set_pull_down(TCFG_ADKEY_PORT, 0); + if (TCFG_ADKEY_EXTERN_UP_ENABLE) { + gpio_set_pull_up(TCFG_ADKEY_PORT, 0); + } else { + gpio_set_pull_up(TCFG_ADKEY_PORT, 1); + } + + } + + +#endif +} + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + + /* gpio_set_pull_down(IO_PORTB_05, 1); */ + /* os_time_dly(10); */ +#if TCFG_FM_ENABLE + fm_dev_init(&fm_dev_data); +#endif + +#if TCFG_NOR_REC + nor_fs_ops_init(); +#endif + +#if TCFG_NOR_FS + init_norsdfile_hdl(); +#endif + +#if FLASH_INSIDE_REC_ENABLE + sdfile_rec_ops_init(); +#endif + + dev_manager_init(); + board_devices_init(); + +#if TCFG_ADKEY_LED_IO_REUSE + adkey_reuse_set_callback(adkey_reuse_enter_callback,adkey_reuse_exit_callback); +#endif + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + //针对硅mic要输出1给mic供电(按实际使用情况配置) + /* if(!adc_data.mic_capless){ */ + /* gpio_set_pull_up(IO_PORTA_04, 0); */ + /* gpio_set_pull_down(IO_PORTA_04, 0); */ + /* gpio_set_direction(IO_PORTA_04, 0); */ + /* gpio_set_output_value(IO_PORTA_04,1); */ + /* } */ + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +#if USER_UART_UPDATE_ENABLE + { +#include "uart_update.h" + uart_update_cfg update_cfg = { + .rx = IO_PORTA_02, + .tx = IO_PORTA_03, + .output_channel = CH1_UT1_TX, + .input_channel = INPUT_CH0 + }; + uart_update_init(&update_cfg); + } +#endif + + gpio_set_pull_up(IO_PORTA_01, 0); + gpio_set_pull_down(IO_PORTA_01, 0); + gpio_set_die(IO_PORTA_01, 1); + gpio_set_direction(IO_PORTA_01, 1); + + gpio_set_pull_up(IO_PORTB_10, 0); + gpio_set_pull_down(IO_PORTB_10, 0); + gpio_set_die(IO_PORTB_10, 1); + gpio_set_direction(IO_PORTB_10, 0); + + /* gpio_set_pull_up(IO_PORT_DP, 0); */ + /* gpio_set_pull_down(IO_PORT_DP, 0); */ + /* gpio_set_die(IO_PORT_DP, 1); */ + /* gpio_set_direction(IO_PORT_DP, 0); */ + + soft_poweroff_timer=sys_timer_add(NULL,soft_poweroff,50); + power_on_timer=sys_timeout_add(NULL,poweron_led_blink,500); + led_scan_timer=sys_hi_timer_add(NULL,led_scan,2); +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + key_wakeup_enable(); + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + /* portb_value &= ~BIT(1); */ + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_set_direction(IO_PORTA_01,1); + gpio_set_pull_down(IO_PORTA_01,0); + gpio_set_pull_up(IO_PORTA_01,0); + gpio_set_die(IO_PORTA_01,1); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + os_time_dly(10); + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); + key_wakeup_disable(); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + key_wakeup_enable(); + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); + key_wakeup_disable(); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif diff --git a/apps/soundbox/board/br23/board_ac6083a/board_ac6083a_cfg.h b/apps/soundbox/board/br23/board_ac6083a/board_ac6083a_cfg.h new file mode 100644 index 0000000..b2bceb2 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6083a/board_ac6083a_cfg.h @@ -0,0 +1,984 @@ +#ifndef CONFIG_BOARD_AC6083A_CFG_H +#define CONFIG_BOARD_AC6083A_CFG_H + +#ifdef CONFIG_BOARD_AC6083A + + +/* +把蓝牙关闭后,可以把蓝牙库不进入编译,减少代码 + +*/ + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 + +#define NO_CONFIG_PORT (-1) + + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 0 +#define TCFG_APP_MUSIC_EN 1 +#define TCFG_APP_LINEIN_EN 0 +#define TCFG_APP_FM_EN 0 +#define TCFG_APP_PC_EN 1 +#define TCFG_APP_RTC_EN 0 +#define TCFG_APP_RECORD_EN 0 +#define TCFG_APP_SPDIF_EN 0 +#define TCFG_APP_SLEEP_EN 1 + +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORT_DP //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +/*软件IIC设置*/ +#define TCHFG_SOFT_I2C_ENABLE DISABLE_THIS_MOUDLE //软件IIC使能 +#define TCFG_SW_I2C0_CLK_PORT IO_PORTB_00 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTB_03 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCHFG_HW_I2C_ENABLE DISABLE_THIS_MOUDLE //硬件IIC使能 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 4000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE 1//DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE 1//DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_7 + +#define TCFG_CHARGE_MA CHARGE_mA_80 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CMD_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE DISABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#include "usb_std_class_def.h" + + +#define PC_POWER_ON_CHARGE 1 +#define TCFG_USB_PORT_CHARGE DISABLE + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DP_ONLY) + +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE 0//ENABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_VOLDOWN_CONNECT_WAY ONE_PORT_TO_LOW +#define TCFG_IOKEY_VOLDOWN_ONE_PORT IO_PORTA_01 + +#define TCFG_IOKEY_VOLUP_CONNECT_WAY ONE_PORT_TO_LOW +#define TCFG_IOKEY_VOLUP_ONE_PORT IO_PORTB_01 + +#define TCFG_IOKEY_PP_CONNECT_WAY DOUBLE_PORT_TO_IO +#define TCFG_IOKEY_PP_IN_PORT IO_PORTA_01 +#define TCFG_IOKEY_PP_OUT_PORT IO_PORTB_10 + + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_LED_IO_REUSE DISABLE_THIS_MOUDLE //ADKEY 和 LED IO复用,led只能设置蓝灯显示 +#define TCFG_ADKEY_PORT IO_PORTB_01 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PB1 +#define TCFG_ADKEY_EXTERN_UP_ENABLE DISABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +// #define TCFG_6083_ADKEY_ENABLE 1 + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 15 / (15 + R_UP)) //1.5k +#define TCFG_ADKEY_AD2 (0x3ffL * 33 / (33 + R_UP)) //3.3k +#define TCFG_ADKEY_AD3 (0x3ffL * 68 / (68 + R_UP)) //6.8k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k + +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 + + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTA_00 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTA_01 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 + DAC_OUTPUT_FRONT_LR_REAR_LR 四声道输出 +*/ +//#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC //LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE ENABLE +#define DAC_AUTO_HIGH_Z_EN ENABLE //处理直推串音问题, 隔直不要开 + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define VOL_TYPE_DIGGROUP 4 //独立通道数字音量 + +//每个解码通道都开启数字音量管理,音量类型为VOL_TYPE_DIGGROUP时要使能 +#define SYS_DIGVOL_GROUP_EN DISABLE + +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE DISABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + + +//#define TCFG_GPIO_RAM_ENABLE //gpio 设置是否放ram + +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_RCL //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_32V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 0 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 0 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 0 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 1 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 0 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 0 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 0 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 1 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 1 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc + +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 0 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 1 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 0 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 0 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 0 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 1 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif +#endif + +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 1 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 0// 4000//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +#define TCFG_AUDIO_DEC_OUT_TASK 0 // 解码使用单独任务做输出 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 0 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 1 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN 0//ENABLE//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE 0//ENABLE//音乐播放录音区分使能 + + +#if RECORDER_MIX_EN//限制不能同时打开 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE +#endif + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR +#define TCFG_LINEIN_CHECK_PORT IO_PORTB_03 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd口 + +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE DISABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE 0//ENABLE +#define TCFG_DEC_WAV_ENABLE 0//ENABLE +#define TCFG_DEC_FLAC_ENABLE DISABLE +#define TCFG_DEC_APE_ENABLE DISABLE +#define TCFG_DEC_M4A_ENABLE DISABLE +#define TCFG_DEC_ALAC_ENABLE DISABLE +#define TCFG_DEC_AMR_ENABLE DISABLE +#define TCFG_DEC_DTS_ENABLE DISABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE DISABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE //需要使能软件IIC模块 +#define TCFG_FM_BK1080_ENABLE DISABLE //需要使能软件IIC模块 +#define TCFG_FM_QN8035_ENABLE DISABLE //需要使能软件IIC模块 + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE // +#define TCFG_IIS_OUTPUT_EN ENABLE // +#define TCFG_IIS_OUTPUT_PORT ALINK1_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL (BIT(0)) + +#define TCFG_IIS_INPUT_EN DISABLE// +#define TCFG_IIS_INPUT_PORT ALINK1_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR (44100l) +#define TCFG_IIS_INPUT_DATAPORT_SEL (BIT(0)) + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE DISABLE +#define TCFG_ENC_MSBC_ENABLE DISABLE +#define TCFG_ENC_G726_ENABLE DISABLE +#define TCFG_ENC_MP3_ENABLE DISABLE +#define TCFG_ENC_ADPCM_ENABLE DISABLE +#define TCFG_ENC_PCM_ENABLE DISABLE +#define TCFG_ENC_SBC_ENABLE DISABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + +//*********************************************************************************// +//ali ai profile +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 0 //not surport +#define ANCS_CLIENT_EN 0 + +#if (DUEROS_DMA_EN || TRANS_DATA_EN || ANCS_CLIENT_EN) +#define BT_FOR_APP_EN 1 +#else +#define BT_FOR_APP_EN 0 +#endif + +//*********************************************************************************// + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif + +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC6083 +#endif //CONFIG_BOARD_AC6083_CFG_H diff --git a/apps/soundbox/board/br23/board_ac6083a/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac6083a/key_table/adkey_table.c new file mode 100644 index 0000000..9867db4 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6083a/key_table/adkey_table.c @@ -0,0 +1,222 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6083A +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_UP, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_PREV, KEY_MUSIC_FR, KEY_MUSIC_FR, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_NEXT, KEY_MUSIC_FF, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_PREV, KEY_MUSIC_FR, KEY_MUSIC_FR, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_NEXT, KEY_MUSIC_FF, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6083a/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac6083a/key_table/iokey_table.c new file mode 100644 index 0000000..884bc6e --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6083a/key_table/iokey_table.c @@ -0,0 +1,248 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6083A +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6083a/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac6083a/key_table/irkey_table.c new file mode 100644 index 0000000..b01abd4 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6083a/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6083A +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6083a/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac6083a/key_table/rdec_key_table.c new file mode 100644 index 0000000..f7e80c8 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6083a/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6951G +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6083a/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac6083a/key_table/touch_key_table.c new file mode 100644 index 0000000..ac10330 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6083a/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6083A +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6083a_iap/board_ac6083a_iap.c b/apps/soundbox/board/br23/board_ac6083a_iap/board_ac6083a_iap.c new file mode 100644 index 0000000..13f541b --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6083a_iap/board_ac6083a_iap.c @@ -0,0 +1,1098 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC6083A_IAP + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "fm/fm_manage.h" +#include "asm/power/p33.h" +#include "norflash.h" +#include "asm/spi.h" +#include "ui_manage.h" +#include "spi/nor_fs.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 0, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 0, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_VOLDOWN_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_VOLDOWN_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_VOLUP_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_VOLUP_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.two_io.out_port = TCFG_IOKEY_PREV_OUT_PORT, + .key_type.two_io.in_port = TCFG_IOKEY_PREV_IN_PORT, + .key_value = 2, + }, + + { + .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, + .key_type.two_io.out_port = TCFG_IOKEY_NEXT_OUT_PORT, + .key_type.two_io.in_port = TCFG_IOKEY_NEXT_IN_PORT, + .key_value = 3, + }, + + { + .connect_way = TCFG_IOKEY_PP_CONNECT_WAY, + .key_type.two_io.out_port = TCFG_IOKEY_PP_OUT_PORT, + .key_type.two_io.in_port = TCFG_IOKEY_PP_IN_PORT, + .key_value = 4, + } +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, +#if TCFG_SD1_ENABLE + .pin_cfg.pin7.pin[0] = IO_PORTA_02, + .pin_cfg.pin7.pin[1] = IO_PORTA_03, + .pin_cfg.pin7.pin[2] = IO_PORTA_04, + .pin_cfg.pin7.pin[3] = IO_PORTA_06, + .pin_cfg.pin7.pin[4] = IO_PORTA_07, + .pin_cfg.pin7.pin[5] = IO_PORTA_08, + .pin_cfg.pin7.pin[6] = IO_PORTA_09, +#else + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if 1 +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; + + +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NOR_FAT +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 0, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_FS +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 1*1024*1024, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_REC +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 2*1024*1024, + .size = 2*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_FM_ENABLE + +FM_DEV_PLATFORM_DATA_BEGIN(fm_dev_data) + .iic_hdl = 0, + .iic_delay = 50, +FM_DEV_PLATFORM_DATA_END(); + +#endif + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +#if TCFG_NOR_FAT + { "fat_nor", &norflash_dev_ops , (void *)&norflash_fat_dev_data}, +#endif + +#if TCFG_NOR_FS + { "res_nor", &norfs_dev_ops , (void *)&norflash_norfs_dev_data}, +#endif + +#if TCFG_NOR_REC + {"rec_nor", &norfs_dev_ops , (void *)&norflash_norfs_rec_dev_data}, +#endif +#endif +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , + +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif + +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTA_10, //唤醒口选择 +}; + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} +static void key_wakeup_disable() +{ + power_wakeup_index_disable(1); +} +static void key_wakeup_enable() +{ + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + +#if TCFG_FM_ENABLE + fm_dev_init(&fm_dev_data); +#endif + +#if TCFG_NOR_REC + nor_fs_ops_init(); +#endif + +#if TCFG_NOR_FS + init_norsdfile_hdl(); +#endif + +#if FLASH_INSIDE_REC_ENABLE + sdfile_rec_ops_init(); +#endif + + dev_manager_init(); + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + //针对硅mic要输出1给mic供电(按实际使用情况配置) + /* if(!adc_data.mic_capless){ */ + /* gpio_set_pull_up(IO_PORTA_04, 0); */ + /* gpio_set_pull_down(IO_PORTA_04, 0); */ + /* gpio_set_direction(IO_PORTA_04, 0); */ + /* gpio_set_output_value(IO_PORTA_04,1); */ + /* } */ + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +#if USER_UART_UPDATE_ENABLE + { +#include "uart_update.h" + uart_update_cfg update_cfg = { + .rx = IO_PORTA_02, + .tx = IO_PORTA_03, + .output_channel = CH1_UT1_TX, + .input_channel = INPUT_CH0 + }; + uart_update_init(&update_cfg); + } +#endif +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + key_wakeup_enable(); + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); + key_wakeup_disable(); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + key_wakeup_enable(); + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ +#if TCFG_USB_APPLE_DOCK_EN + /* 注意: + * power_wakeup_init()里面用到PORTA B C D的DIE、DIEH寄存器, + * 操作了这些寄存器会导致mfi认证失败, + * 原因不明 + * */ + return ; +#endif /*TCFG_USB_APPLE_DOCK_EN*/ + + power_wakeup_init(&wk_param); + key_wakeup_disable(); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif diff --git a/apps/soundbox/board/br23/board_ac6083a_iap/board_ac6083a_iap_cfg.h b/apps/soundbox/board/br23/board_ac6083a_iap/board_ac6083a_iap_cfg.h new file mode 100644 index 0000000..f9cd07f --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6083a_iap/board_ac6083a_iap_cfg.h @@ -0,0 +1,999 @@ +#ifndef CONFIG_BOARD_AC6083A_IAP_CFG_H +#define CONFIG_BOARD_AC6083A_IAP_CFG_H + +#ifdef CONFIG_BOARD_AC6083A_IAP + + +/* +把蓝牙关闭后,可以把蓝牙库不进入编译,减少代码 + +*/ + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 + +#define NO_CONFIG_PORT (-1) + + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 0 +#define TCFG_APP_MUSIC_EN 0 +#define TCFG_APP_LINEIN_EN 0 +#define TCFG_APP_FM_EN 0 +#define TCFG_APP_PC_EN 1 +#define TCFG_APP_RTC_EN 0 +#define TCFG_APP_RECORD_EN 0 +#define TCFG_APP_SPDIF_EN 0 +#define TCFG_APP_SLEEP_EN 0 + +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTB_01 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCFG_SW_I2C0_CLK_PORT IO_PORTC_04 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTC_05 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCFG_HW_I2C0_PORTS 'D' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 4000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE DISABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CMD_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE DISABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#include "usb_std_class_def.h" + +#define TCFG_USB_APPLE_DOCK_EN 1 + +#define TCFG_USB_PORT_CHARGE DISABLE + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DP_ONLY) + +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_VOLDOWN_CONNECT_WAY ONE_PORT_TO_HIGH +#define TCFG_IOKEY_VOLDOWN_ONE_PORT IO_PORTA_01 + +#define TCFG_IOKEY_VOLUP_CONNECT_WAY ONE_PORT_TO_HIGH +#define TCFG_IOKEY_VOLUP_ONE_PORT IO_PORTB_01 + +#define TCFG_IOKEY_PREV_CONNECT_WAY CUST_DOUBLE_PORT_TO_IO +#define TCFG_IOKEY_PREV_IN_PORT IO_PORTA_01 +#define TCFG_IOKEY_PREV_OUT_PORT IO_PORTB_10 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY CUST_DOUBLE_PORT_TO_IO +#define TCFG_IOKEY_NEXT_IN_PORT IO_PORTB_01 +#define TCFG_IOKEY_NEXT_OUT_PORT IO_PORTB_10 + +#define TCFG_IOKEY_PP_CONNECT_WAY CUST_DOUBLE_PORT_TO_IO +#define TCFG_IOKEY_PP_IN_PORT IO_PORTB_01 +#define TCFG_IOKEY_PP_OUT_PORT IO_PORTA_01 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE 0// ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_LED_IO_REUSE DISABLE_THIS_MOUDLE //ADKEY 和 LED IO复用,led只能设置蓝灯显示 +#define TCFG_ADKEY_PORT IO_PORTB_01 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PB1 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTA_00 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTA_01 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 + DAC_OUTPUT_FRONT_LR_REAR_LR 四声道输出 +*/ +//#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC //LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define VOL_TYPE_DIGGROUP 4 //独立通道数字音量 + +//每个解码通道都开启数字音量管理,音量类型为VOL_TYPE_DIGGROUP时要使能 +#define SYS_DIGVOL_GROUP_EN DISABLE + +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE DISABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE DISABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + + +//#define TCFG_GPIO_RAM_ENABLE //gpio 设置是否放ram + +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_RCL //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +// #define TCFG_LOWPOWER_POWER_SEL PWR_DCDC15 //电源模式设置,可选DCDC和LDO + +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 0 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 1 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 1 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 1 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 1 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 1 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 1 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 1 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 1 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc + +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 1 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 1 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 1 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 1 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 1 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 1 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif +#endif + +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 0 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 0// 4000//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 0 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 0 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 1 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 0 //不支持后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN DISABLE//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE DISABLE//音乐播放录音区分使能 + + +#if RECORDER_MIX_EN//限制不能同时打开 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE +#endif + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR +#define TCFG_LINEIN_CHECK_PORT IO_PORTB_03 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd口 + +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE DISABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE ENABLE +#define TCFG_DEC_WAV_ENABLE ENABLE +#define TCFG_DEC_FLAC_ENABLE DISABLE +#define TCFG_DEC_APE_ENABLE DISABLE +#define TCFG_DEC_M4A_ENABLE DISABLE +#define TCFG_DEC_ALAC_ENABLE DISABLE +#define TCFG_DEC_AMR_ENABLE DISABLE +#define TCFG_DEC_DTS_ENABLE DISABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE ENABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE +#define TCFG_FM_BK1080_ENABLE DISABLE +#define TCFG_FM_QN8035_ENABLE DISABLE + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE // +#define TCFG_IIS_OUTPUT_EN ENABLE // +#define TCFG_IIS_OUTPUT_PORT ALINK1_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL (BIT(0)) + +#define TCFG_IIS_INPUT_EN DISABLE// +#define TCFG_IIS_INPUT_PORT ALINK1_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR (44100l) +#define TCFG_IIS_INPUT_DATAPORT_SEL (BIT(0)) + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE DISABLE +#define TCFG_ENC_MSBC_ENABLE DISABLE +#define TCFG_ENC_G726_ENABLE DISABLE +#define TCFG_ENC_MP3_ENABLE DISABLE +#define TCFG_ENC_ADPCM_ENABLE DISABLE +#define TCFG_ENC_PCM_ENABLE DISABLE +#define TCFG_ENC_SBC_ENABLE DISABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + +//*********************************************************************************// +//ali ai profile +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 0 //not surport +#define ANCS_CLIENT_EN 0 + +#if (DUEROS_DMA_EN || TRANS_DATA_EN || ANCS_CLIENT_EN) +#define BT_FOR_APP_EN 1 +#else +#define BT_FOR_APP_EN 0 +#endif + +//*********************************************************************************// + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 + +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC695X_DEMO +#endif //CONFIG_BOARD_AC695X_DEMO_CFG_H diff --git a/apps/soundbox/board/br23/board_ac6083a_iap/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac6083a_iap/key_table/adkey_table.c new file mode 100644 index 0000000..4df4417 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6083a_iap/key_table/adkey_table.c @@ -0,0 +1,356 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6083A_IAP +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_UP, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_DOWN, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_MUSIC_CHANGE_REPEAT, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_MUSIC_FR, KEY_MUSIC_FR, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_MUSIC_FF, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6083a_iap/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac6083a_iap/key_table/iokey_table.c new file mode 100644 index 0000000..7715d6d --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6083a_iap/key_table/iokey_table.c @@ -0,0 +1,248 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6083A_IAP +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6083a_iap/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac6083a_iap/key_table/irkey_table.c new file mode 100644 index 0000000..566b91b --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6083a_iap/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6083A_IAP +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6083a_iap/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac6083a_iap/key_table/rdec_key_table.c new file mode 100644 index 0000000..f7e80c8 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6083a_iap/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6951G +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6083a_iap/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac6083a_iap/key_table/touch_key_table.c new file mode 100644 index 0000000..1f99700 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6083a_iap/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6083A_IAP +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6951_kgb_v1/board_ac6951_kgb_cfg.h b/apps/soundbox/board/br23/board_ac6951_kgb_v1/board_ac6951_kgb_cfg.h new file mode 100644 index 0000000..664969d --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6951_kgb_v1/board_ac6951_kgb_cfg.h @@ -0,0 +1,1016 @@ +#ifndef CONFIG_BOARD_AC6951_KGB_V1_CFG_H +#define CONFIG_BOARD_AC6951_KGB_V1_CFG_H + +#ifdef CONFIG_BOARD_AC6951_KGB_V1 + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 +#define LINEIN_INPUT_WAY_DAC 2 + +#define NO_CONFIG_PORT (-1) + + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 0 +#define TCFG_APP_LINEIN_EN 0 +#define TCFG_APP_FM_EN 0 +#define TCFG_APP_PC_EN 0 +#define TCFG_APP_RTC_EN 0 +#define TCFG_APP_RECORD_EN 0 +#define TCFG_APP_SPDIF_EN 0 +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +// #define TCFG_UART0_TX_PORT IO_PORTA_05 //串口发送脚配置 +#define TCFG_UART0_TX_PORT IO_PORTB_07 //串口发送脚配置 +// #define TCFG_UART0_TX_PORT IO_PORTB_08 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// USER配置 // +//*********************************************************************************// +#define MUTE_ABD_PORT1 IO_PORTB_10 +#define MUTE_ABD_PORT2 IO_PORTB_11 + + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCHFG_SOFT_I2C_ENABLE DISABLE_THIS_MOUDLE //软件IIC使能 +#define TCFG_SW_I2C0_CLK_PORT IO_PORTB_00 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTB_03 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCHFG_HW_I2C_ENABLE DISABLE_THIS_MOUDLE //硬件IIC使能 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE 0//ENABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 4000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE 0//ENABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_NANDFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE 0// ENABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE ENABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#define TCFG_VIR_UDISK_ENABLE 0//ENABLE_THIS_MOUDLE + +#define TCFG_USB_PORT_CHARGE DISABLE + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE + +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DP_ONLY) + +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 + +#define TCFG_KEY_TONE_EN 0//ENABLE // 按键提示音。建议音频输出使用固定采样率 + +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE 1//DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO + +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_02 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_LED_IO_REUSE DISABLE_THIS_MOUDLE //ADKEY 和 LED IO复用,led只能设置蓝灯显示 +#define TCFG_ADKEY_PORT IO_PORTB_01 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PB1 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTA_00 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTA_01 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 + DAC_OUTPUT_FRONT_LR_REAR_LR 四声道输出 +*/ +//#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC //LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define VOL_TYPE_DIGGROUP 4 //独立通道数字音量 + +//每个解码通道都开启数字音量管理,音量类型为VOL_TYPE_DIGGROUP时要使能 +#define SYS_DIGVOL_GROUP_EN 1//DISABLE + +#define SYS_VOL_TYPE VOL_TYPE_DIGGROUP //VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE ENABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE 0//ENABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + +#define TCFG_LED7_RUN_RAM DISABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) + +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 1 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 1 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 1 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 1 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 1 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 1 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 1 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 1 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 1 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc + +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 1 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 1 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 1 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 1 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 1 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 1 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif + +#endif + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 1 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 0//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +#define TCFG_AUDIO_DEC_OUT_TASK 0 // 解码使用单独任务做输出 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 1 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 1 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN DISABLE//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE DISABLE//音乐播放录音区分使能 + + +#if RECORDER_MIX_EN//限制不能同时打开 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE +#endif + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR +#define TCFG_LINEIN_CHECK_PORT IO_PORTB_03 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd口 +#define TCFG_LINEIN_DETECT_ENABLE 0 +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE ENABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE ENABLE +#define TCFG_DEC_WAV_ENABLE ENABLE +#define TCFG_DEC_FLAC_ENABLE ENABLE +#define TCFG_DEC_APE_ENABLE ENABLE +#define TCFG_DEC_M4A_ENABLE ENABLE +#define TCFG_DEC_ALAC_ENABLE ENABLE +#define TCFG_DEC_AMR_ENABLE ENABLE +#define TCFG_DEC_DTS_ENABLE ENABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE ENABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE //需要使能软件IIC模块 +#define TCFG_FM_BK1080_ENABLE DISABLE //需要使能软件IIC模块 +#define TCFG_FM_QN8035_ENABLE DISABLE //需要使能软件IIC模块 + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE) +#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE))) +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#else +#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif +#else +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/ + +#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE) +#undef TCFG_LED7_RUN_RAM +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/ + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) || (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC_IIS) +#define TCFG_IIS_ENABLE ENABLE_THIS_MOUDLE +#else +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE +#endif + +#define TCFG_IIS_MODE (0) // 0:master 1:slave + +#define TCFG_IIS_OUTPUT_EN (ENABLE && TCFG_IIS_ENABLE) +#define TCFG_IIS_OUTPUT_PORT ALINK0_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL 0 + +#define TCFG_IIS_INPUT_EN (DISABLE && TCFG_IIS_ENABLE) +#define TCFG_IIS_INPUT_PORT ALINK0_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR 44100 +#define TCFG_IIS_INPUT_DATAPORT_SEL 1 + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE ENABLE +#define TCFG_ENC_MSBC_ENABLE ENABLE +#define TCFG_ENC_G726_ENABLE ENABLE +#define TCFG_ENC_MP3_ENABLE ENABLE +#define TCFG_ENC_ADPCM_ENABLE ENABLE +#define TCFG_ENC_PCM_ENABLE ENABLE +#define TCFG_ENC_SBC_ENABLE ENABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + +//*********************************************************************************// +//ali ai profile +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 0 //not surport +#define ANCS_CLIENT_EN 0 + +#if (DUEROS_DMA_EN || TRANS_DATA_EN || ANCS_CLIENT_EN) +#define BT_FOR_APP_EN 1 +#else +#define BT_FOR_APP_EN 0 +#endif + +//*********************************************************************************// + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 + +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif + +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC695X_DEMO +#endif //CONFIG_BOARD_AC695X_DEMO_CFG_H diff --git a/apps/soundbox/board/br23/board_ac6951_kgb_v1/board_ac6951_kgb_v1.c b/apps/soundbox/board/br23/board_ac6951_kgb_v1/board_ac6951_kgb_v1.c new file mode 100644 index 0000000..44a4f46 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6951_kgb_v1/board_ac6951_kgb_v1.c @@ -0,0 +1,1166 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC6951_KGB_V1 + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "fm/fm_manage.h" +#include "asm/power/p33.h" +#include "norflash.h" +#include "asm/spi.h" +#include "ui_manage.h" +#include "spi/nor_fs.h" +#include "nandflash.h" +#include "audio_link.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +#if TCFG_IIS_ENABLE +ALINK_PARM alink0_param = { + .port_select = ALINK0_PORTA, //MCLK:PA8 SCLK:PA2 LRCK:PA3 CH0:PA4 CH1:PA5 CH2:PA6 CH3:PA7 + /* .port_select = ALINK0_PORTB, //MCLK:PA15 SCLK:PA9 LRCK:PA10 CH0:PA11 CH1:PA12 CH2:PA13 CH3:PA14 */ + /* .port_select = ALINK1_PORTA, //MCLK:PB0 SCLK:PC0 LRCK:PC1 CH0:PC2 CH1:PC3 CH2:PC4 CH3:PC5 */ + .ch_cfg[0].enable = 1, + .ch_cfg[1].enable = 1, + .mode = ALINK_MD_IIS, +#if TCFG_IIS_MODE + .role = ALINK_ROLE_SLAVE, +#else + .role = ALINK_ROLE_MASTER, +#endif + .clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE, + .bitwide = ALINK_LEN_16BIT, + .sclk_per_frame = ALINK_FRAME_64SCLK, + .dma_len = ALNK_BUF_POINTS_NUM * 2 * 2 * 2, + .sample_rate = TCFG_IIS_OUTPUT_SR, +}; + +ALINK_PARM alink1_param = { + /* .port_select = ALINK0_PORTA, //MCLK:PA8 SCLK:PA2 LRCK:PA3 CH0:PA4 CH1:PA5 CH2:PA6 CH3:PA7 */ + /* .port_select = ALINK0_PORTB, //MCLK:PA15 SCLK:PA9 LRCK:PA10 CH0:PA11 CH1:PA12 CH2:PA13 CH3:PA14 */ + .port_select = ALINK1_PORTA, //MCLK:PB0 SCLK:PC0 LRCK:PC1 CH0:PC2 CH1:PC3 CH2:PC4 CH3:PC5 + .ch_cfg[0].enable = 1, + .ch_cfg[1].enable = 1, + .mode = ALINK_MD_IIS, +#if TCFG_IIS_MODE + .role = ALINK_ROLE_SLAVE, +#else + .role = ALINK_ROLE_MASTER, +#endif + .clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE, + .bitwide = ALINK_LEN_16BIT, + .sclk_per_frame = ALINK_FRAME_64SCLK, + .dma_len = ALNK_BUF_POINTS_NUM * 2 * 2 * 2, + .sample_rate = TCFG_IIS_OUTPUT_SR, +}; + + +#endif + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 21, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 3, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + /* { */ + /* .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, */ + /* .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, */ + /* .key_value = 1, */ + /* }, */ + /* */ + /* { */ + /* .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, */ + /* .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, */ + /* .key_value = 2, */ + /* }, */ +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, +#if TCFG_SD1_ENABLE + .pin_cfg.pin7.pin[0] = IO_PORTA_02, + .pin_cfg.pin7.pin[1] = IO_PORTA_03, + .pin_cfg.pin7.pin[2] = IO_PORTA_04, + .pin_cfg.pin7.pin[3] = IO_PORTA_06, + .pin_cfg.pin7.pin[4] = IO_PORTA_07, + .pin_cfg.pin7.pin[5] = IO_PORTA_08, + .pin_cfg.pin7.pin[6] = IO_PORTA_09, +#else + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if TCHFG_SOFT_I2C_ENABLE +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; +#endif + +#if TCHFG_HW_I2C_ENABLE +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NANDFLASH_DEV_ENABLE +NANDFLASH_DEV_PLATFORM_DATA_BEGIN(nandflash_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, + .start_addr = 0, + .size = 0, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif +NANDFLASH_DEV_PLATFORM_DATA_END() +#endif + + +#if TCFG_NOR_FAT +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 0, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_FS +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 1*1024*1024, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_REC +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 2*1024*1024, + .size = 2*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_FM_ENABLE + +FM_DEV_PLATFORM_DATA_BEGIN(fm_dev_data) + .iic_hdl = 0, + .iic_delay = 50, +FM_DEV_PLATFORM_DATA_END(); + +#endif + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +#if TCFG_NOR_FAT + { "fat_nor", &norflash_dev_ops , (void *)&norflash_fat_dev_data}, +#endif + +#if TCFG_NOR_FS + { "res_nor", &norfs_dev_ops , (void *)&norflash_norfs_dev_data}, +#endif + +#if TCFG_NOR_REC + {"rec_nor", &norfs_dev_ops , (void *)&norflash_norfs_rec_dev_data}, +#endif +#endif + +#if TCFG_NANDFLASH_DEV_ENABLE + {"nand_flash", &nandflash_dev_ops , (void *)&nandflash_dev_data}, +#endif + + +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , + +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif + +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTB_02, //唤醒口选择 +}; + +/* RTC PR0 PR1 唤醒 */ +/* struct port_wakeup rtc_port0 = { */ + /* .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 */ + /* .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 */ + /* .attribute = BLUETOOTH_RESUME, //保留参数 */ + /* .iomap = IO_PORT_PR_00, //唤醒口选择 */ +/* }; */ + +/* struct port_wakeup rtc_port1 = { */ + /* .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 */ + /* .edge = RISING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 */ + /* .attribute = BLUETOOTH_RESUME, //保留参数 */ + /* .iomap = IO_PORT_PR_01, //唤醒口选择 */ +/* }; */ + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + /* .rtc_port[0] = &rtc_port0, */ + /* .rtc_port[1] = &rtc_port1, */ + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} +static void key_wakeup_disable() +{ + power_wakeup_index_disable(1); +} +static void key_wakeup_enable() +{ + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + +#if TCFG_FM_ENABLE + fm_dev_init(&fm_dev_data); +#endif + +#if TCFG_NOR_REC + nor_fs_ops_init(); +#endif + +#if TCFG_NOR_FS + init_norsdfile_hdl(); +#endif + +#if FLASH_INSIDE_REC_ENABLE + sdfile_rec_ops_init(); +#endif + + dev_manager_init(); + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + gpio_set_pull_up(MUTE_ABD_PORT1, 0); + gpio_set_pull_down(MUTE_ABD_PORT1, 0); + gpio_set_direction(MUTE_ABD_PORT1, 0); + gpio_set_output_value(MUTE_ABD_PORT1,1); + + gpio_set_pull_up(MUTE_ABD_PORT2, 0); + gpio_set_pull_down(MUTE_ABD_PORT2, 0); + gpio_set_direction(MUTE_ABD_PORT2, 0); + gpio_set_output_value(MUTE_ABD_PORT2,1); //mute + //针对硅mic要输出1给mic供电(按实际使用情况配置) + /* if(!adc_data.mic_capless){ */ + /* gpio_set_pull_up(IO_PORTA_04, 0); */ + /* gpio_set_pull_down(IO_PORTA_04, 0); */ + /* gpio_set_direction(IO_PORTA_04, 0); */ + /* gpio_set_output_value(IO_PORTA_04,1); */ + /* } */ + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +#if USER_UART_UPDATE_ENABLE + { +#include "uart_update.h" + uart_update_cfg update_cfg = { + .rx = IO_PORTA_02, + .tx = IO_PORTA_03, + .output_channel = CH1_UT1_TX, + .input_channel = INPUT_CH0 + }; + uart_update_init(&update_cfg); + } +#endif +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + key_wakeup_enable(); + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); + key_wakeup_disable(); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + key_wakeup_enable(); + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); + key_wakeup_disable(); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif diff --git a/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/adkey_table.c new file mode 100644 index 0000000..5cb8c44 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/adkey_table.c @@ -0,0 +1,356 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6951_KGB_V1 +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_REVERB_SWITCH, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [3] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_REVERB_OPEN, KEY_REVERB_OPEN, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_REVERB_SWITCH, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_UP, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_DOWN, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_MUSIC_CHANGE_REPEAT, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_MUSIC_FR, KEY_MUSIC_FR, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_MUSIC_FF, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_PLAYER_AB_REPEAT_SWITCH, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/iokey_table.c new file mode 100644 index 0000000..ba68961 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/iokey_table.c @@ -0,0 +1,248 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6951_KGB_V1 +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/irkey_table.c new file mode 100644 index 0000000..59ec447 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6951_KGB_V1 +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_IR_NUM_0, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_IR_NUM_1, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_IR_NUM_2, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_IR_NUM_3, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_IR_NUM_4, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_IR_NUM_5, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_IR_NUM_6, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_IR_NUM_7, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_IR_NUM_8, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_IR_NUM_9, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/rdec_key_table.c new file mode 100644 index 0000000..85d08d2 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6951_KGB_V1 +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/touch_key_table.c new file mode 100644 index 0000000..881b287 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6951_KGB_V1 +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6951g/board_ac6951g.c b/apps/soundbox/board/br23/board_ac6951g/board_ac6951g.c new file mode 100644 index 0000000..55421ed --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6951g/board_ac6951g.c @@ -0,0 +1,1074 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC6951G + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "fm/fm_manage.h" +#include "asm/power/p33.h" +#include "norflash.h" +#include "asm/spi.h" +#include "ui_manage.h" +#include "spi/nor_fs.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, + .key_value = 2, + }, +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, +#if TCFG_SD1_ENABLE + .pin_cfg.pin7.pin[0] = IO_PORTA_02, + .pin_cfg.pin7.pin[1] = IO_PORTA_03, + .pin_cfg.pin7.pin[2] = IO_PORTA_04, + .pin_cfg.pin7.pin[3] = IO_PORTA_06, + .pin_cfg.pin7.pin[4] = IO_PORTA_07, + .pin_cfg.pin7.pin[5] = IO_PORTA_08, + .pin_cfg.pin7.pin[6] = IO_PORTA_09, +#else + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if 0 +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; + + +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NOR_FAT +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 0, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_FS +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 1*1024*1024, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_REC +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 2*1024*1024, + .size = 2*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_FM_ENABLE + +FM_DEV_PLATFORM_DATA_BEGIN(fm_dev_data) + .iic_hdl = 0, + .iic_delay = 50, +FM_DEV_PLATFORM_DATA_END(); + +#endif + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +#if TCFG_NOR_FAT + { "fat_nor", &norflash_dev_ops , (void *)&norflash_fat_dev_data}, +#endif + +#if TCFG_NOR_FS + { "res_nor", &norfs_dev_ops , (void *)&norflash_norfs_dev_data}, +#endif + +#if TCFG_NOR_REC + {"rec_nor", &norfs_dev_ops , (void *)&norflash_norfs_rec_dev_data}, +#endif +#endif +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , + +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif + +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTA_10, //唤醒口选择 +}; + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} +static void key_wakeup_disable() +{ + power_wakeup_index_disable(1); +} +static void key_wakeup_enable() +{ + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + +#if TCFG_FM_ENABLE + fm_dev_init(&fm_dev_data); +#endif + +#if TCFG_NOR_REC + nor_fs_ops_init(); +#endif + +#if TCFG_NOR_FS + init_norsdfile_hdl(); +#endif + +#if FLASH_INSIDE_REC_ENABLE + sdfile_rec_ops_init(); +#endif + + dev_manager_init(); + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + //针对硅mic要输出1给mic供电(按实际使用情况配置) + /* if(!adc_data.mic_capless){ */ + /* gpio_set_pull_up(IO_PORTA_04, 0); */ + /* gpio_set_pull_down(IO_PORTA_04, 0); */ + /* gpio_set_direction(IO_PORTA_04, 0); */ + /* gpio_set_output_value(IO_PORTA_04,1); */ + /* } */ + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +#if USER_UART_UPDATE_ENABLE + { +#include "uart_update.h" + uart_update_cfg update_cfg = { + .rx = IO_PORTA_02, + .tx = IO_PORTA_03, + .output_channel = CH1_UT1_TX, + .input_channel = INPUT_CH0 + }; + uart_update_init(&update_cfg); + } +#endif +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + key_wakeup_enable(); + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); + key_wakeup_disable(); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + key_wakeup_enable(); + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); + key_wakeup_disable(); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif diff --git a/apps/soundbox/board/br23/board_ac6951g/board_ac6951g_cfg.h b/apps/soundbox/board/br23/board_ac6951g/board_ac6951g_cfg.h new file mode 100644 index 0000000..846e169 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6951g/board_ac6951g_cfg.h @@ -0,0 +1,996 @@ +#ifndef CONFIG_BOARD_AC6951G_CFG_H +#define CONFIG_BOARD_AC6951G_CFG_H + +#ifdef CONFIG_BOARD_AC6951G + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 +#define LINEIN_INPUT_WAY_DAC 2 + +#define NO_CONFIG_PORT (-1) + + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 0 +#define TCFG_APP_MUSIC_EN 1 +#define TCFG_APP_LINEIN_EN 1 +#define TCFG_APP_FM_EN 1 +#define TCFG_APP_PC_EN 0 +#define TCFG_APP_RTC_EN 1 +#define TCFG_APP_RECORD_EN 0 +#define TCFG_APP_SPDIF_EN 0 +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTA_05 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCFG_SW_I2C0_CLK_PORT IO_PORTA_09 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTA_10 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 4000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE ENABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE ENABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#include "usb_std_class_def.h" + + +#define TCFG_USB_PORT_CHARGE DISABLE + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DP_ONLY) + +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO + +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_LED_IO_REUSE DISABLE_THIS_MOUDLE //ADKEY 和 LED IO复用,led只能设置蓝灯显示 +#define TCFG_ADKEY_PORT IO_PORTA_10 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PA10 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTA_00 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTA_01 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 + DAC_OUTPUT_FRONT_LR_REAR_LR 四声道输出 +*/ +//#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC //LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define VOL_TYPE_DIGGROUP 4 //独立通道数字音量 + +//每个解码通道都开启数字音量管理,音量类型为VOL_TYPE_DIGGROUP时要使能 +#define SYS_DIGVOL_GROUP_EN DISABLE + +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE ENABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + +#define TCFG_LED7_RUN_RAM DISABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) + +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_RCL //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 1 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 1 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 1 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 1 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 1 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 1 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 1 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 1 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 1 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc + +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 1 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 1 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 1 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 1 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 1 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 1 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif +#endif + +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 1 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 4000//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +#define TCFG_AUDIO_DEC_OUT_TASK 0 // 解码使用单独任务做输出 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 0 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 1 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN ENABLE//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE ENABLE//音乐播放录音区分使能 + + +#if RECORDER_MIX_EN//限制不能同时打开 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE +#endif + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR +#define TCFG_LINEIN_CHECK_PORT IO_PORTB_03 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd口 + +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE ENABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE ENABLE +#define TCFG_DEC_WAV_ENABLE ENABLE +#define TCFG_DEC_FLAC_ENABLE ENABLE +#define TCFG_DEC_APE_ENABLE ENABLE +#define TCFG_DEC_M4A_ENABLE ENABLE +#define TCFG_DEC_ALAC_ENABLE ENABLE +#define TCFG_DEC_AMR_ENABLE ENABLE +#define TCFG_DEC_DTS_ENABLE ENABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE ENABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE +#define TCFG_FM_BK1080_ENABLE DISABLE +#define TCFG_FM_QN8035_ENABLE DISABLE + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE) +#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE))) +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#else +#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif +#else +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/ + +#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE) +#undef TCFG_LED7_RUN_RAM +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/ + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE // +#define TCFG_IIS_OUTPUT_EN ENABLE // +#define TCFG_IIS_OUTPUT_PORT ALINK1_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL (BIT(0)) + +#define TCFG_IIS_INPUT_EN DISABLE// +#define TCFG_IIS_INPUT_PORT ALINK1_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR (44100l) +#define TCFG_IIS_INPUT_DATAPORT_SEL (BIT(0)) + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE ENABLE +#define TCFG_ENC_MSBC_ENABLE ENABLE +#define TCFG_ENC_G726_ENABLE ENABLE +#define TCFG_ENC_MP3_ENABLE ENABLE +#define TCFG_ENC_ADPCM_ENABLE ENABLE +#define TCFG_ENC_PCM_ENABLE ENABLE +#define TCFG_ENC_SBC_ENABLE ENABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + +//*********************************************************************************// +//ali ai profile +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 0 //not surport +#define ANCS_CLIENT_EN 0 + +#if (DUEROS_DMA_EN || TRANS_DATA_EN || ANCS_CLIENT_EN) +#define BT_FOR_APP_EN 1 +#else +#define BT_FOR_APP_EN 0 +#endif + +//*********************************************************************************// + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC695X_DEMO +#endif //CONFIG_BOARD_AC695X_DEMO_CFG_H diff --git a/apps/soundbox/board/br23/board_ac6951g/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac6951g/key_table/adkey_table.c new file mode 100644 index 0000000..6dc8d3b --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6951g/key_table/adkey_table.c @@ -0,0 +1,356 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6951G +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_UP, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_DOWN, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_MUSIC_CHANGE_REPEAT, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_MUSIC_FR, KEY_MUSIC_FR, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_MUSIC_FF, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6951g/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac6951g/key_table/iokey_table.c new file mode 100644 index 0000000..3ebdd18 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6951g/key_table/iokey_table.c @@ -0,0 +1,248 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6951G +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6951g/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac6951g/key_table/irkey_table.c new file mode 100644 index 0000000..5a92f98 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6951g/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6951G +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6951g/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac6951g/key_table/rdec_key_table.c new file mode 100644 index 0000000..f7e80c8 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6951g/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6951G +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6951g/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac6951g/key_table/touch_key_table.c new file mode 100644 index 0000000..cd52822 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6951g/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6951G +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6952e_lighter/board_ac6952e_lighter.c b/apps/soundbox/board/br23/board_ac6952e_lighter/board_ac6952e_lighter.c new file mode 100644 index 0000000..6f9efbe --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6952e_lighter/board_ac6952e_lighter.c @@ -0,0 +1,1081 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC6952E_LIGHTER + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "fm/fm_manage.h" +#include "asm/power/p33.h" +#include "norflash.h" +#include "asm/spi.h" +#include "ui_manage.h" +#include "spi/nor_fs.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, + .key_value = 2, + }, + + { + .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_MODE_CONNECT_WAY, + .key_type.two_io.in_port = TCFG_IOKEY_MODE_TWO_PORT_IN, + .key_type.two_io.out_port = TCFG_IOKEY_MODE_TWO_PORT_OUT, + .key_value = 3, + }, +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_04, + .pin_cfg.pin7.pin[1] = IO_PORTB_06, + .pin_cfg.pin7.pin[2] = IO_PORTB_07, + .pin_cfg.pin7.pin[3] = IO_PORTB_08, + .pin_cfg.pin7.pin[4] = IO_PORTB_09, + .pin_cfg.pin7.pin[5] = IO_PORTB_10, + .pin_cfg.pin7.pin[6] = (u8)-1, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if 0 +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; + + +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NOR_FAT +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 0, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_FS +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 1*1024*1024, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_REC +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 2*1024*1024, + .size = 2*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_FM_ENABLE + +FM_DEV_PLATFORM_DATA_BEGIN(fm_dev_data) + .iic_hdl = 0, + .iic_delay = 50, +FM_DEV_PLATFORM_DATA_END(); + +#endif + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +#if TCFG_NOR_FAT + { "fat_nor", &norflash_dev_ops , (void *)&norflash_fat_dev_data}, +#endif + +#if TCFG_NOR_FS + { "res_nor", &norfs_dev_ops , (void *)&norflash_norfs_dev_data}, +#endif + +#if TCFG_NOR_REC + {"rec_nor", &norfs_dev_ops , (void *)&norflash_norfs_rec_dev_data}, +#endif +#endif +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTA_10, //唤醒口选择 +}; + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} +static void key_wakeup_disable() +{ + power_wakeup_index_disable(1); +} +static void key_wakeup_enable() +{ + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + +#if TCFG_APP_FM_EMITTER_EN + ui_set_led(MENU_LED0, 1, 1, 250, 500); + ui_set_led(MENU_LED1, 1, 0, 250, 500); +#endif + + return; +} + +extern void cfg_file_parse(u8 idx); +extern void uartSendInit(); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + +#if TCFG_FM_ENABLE + fm_dev_init(&fm_dev_data); +#endif + +#if TCFG_NOR_REC + nor_fs_ops_init(); +#endif + +#if TCFG_NOR_FS + init_norsdfile_hdl(); +#endif + +#if FLASH_INSIDE_REC_ENABLE + sdfile_rec_ops_init(); +#endif + + dev_manager_init(); + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + //针对硅mic要输出1给mic供电(按实际使用情况配置) + /* if(!adc_data.mic_capless){ */ + /* gpio_set_pull_up(IO_PORTA_04, 0); */ + /* gpio_set_pull_down(IO_PORTA_04, 0); */ + /* gpio_set_direction(IO_PORTA_04, 0); */ + /* gpio_set_output_value(IO_PORTA_04,1); */ + /* } */ + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +#if USER_UART_UPDATE_ENABLE + { +#include "uart_update.h" + uart_update_cfg update_cfg = { + .rx = IO_PORTA_02, + .tx = IO_PORTA_03, + .output_channel = CH1_UT1_TX, + .input_channel = INPUT_CH0 + }; + uart_update_init(&update_cfg); + } +#endif +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + key_wakeup_enable(); + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); + key_wakeup_disable(); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + key_wakeup_enable(); + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} +struct reset_param rs_param = { + .en = 0, + .mode = LONG_8S_RESET, + .level = 0, + .iomap = IO_PORTB_05, +}; + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +/* void power_reset_init(const struct reset_param *rs_param); + power_reset_init(&rs_param); */ + + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif diff --git a/apps/soundbox/board/br23/board_ac6952e_lighter/board_ac6952e_lighter_cfg.h b/apps/soundbox/board/br23/board_ac6952e_lighter/board_ac6952e_lighter_cfg.h new file mode 100644 index 0000000..5bc2129 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6952e_lighter/board_ac6952e_lighter_cfg.h @@ -0,0 +1,980 @@ +#ifndef CONFIG_BOARD_AC695E_LIGHTER_CFG_H +#define CONFIG_BOARD_AC695E_LIGHTER_CFG_H + +#ifdef CONFIG_BOARD_AC6952E_LIGHTER + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 +#define LINEIN_INPUT_WAY_DAC 2 + +#define NO_CONFIG_PORT (-1) + + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 1 +#define TCFG_APP_LINEIN_EN 1 +#define TCFG_APP_FM_EN 0 +#define TCFG_APP_PC_EN 0 +#define TCFG_APP_RTC_EN 0 +#define TCFG_APP_RECORD_EN 0 +#define TCFG_APP_SPDIF_EN 0 +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +// #define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 +//*********************************************************************************// +// UART配置(使用PB1打印需要注意长按复位问题) // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTA_05 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCFG_SW_I2C0_CLK_PORT IO_PORTA_09 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTA_10 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 4000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CMD_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE ENABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#include "usb_std_class_def.h" + + +#define TCFG_USB_PORT_CHARGE DISABLE + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DP_ONLY) + +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTA_05 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTC_05 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTA_09 + +#define TCFG_IOKEY_MODE_CONNECT_WAY DOUBLE_PORT_TO_IO +#define TCFG_IOKEY_MODE_TWO_PORT_IN IO_PORTA_05 //IO按键端口 +#define TCFG_IOKEY_MODE_TWO_PORT_OUT IO_PORTA_09 //IO按键端口 + + +#define TCFG_IO_MULTIPLEX_WITH_SD ENABLE // IO_KEY与 SD_CLK复用 +#define TCFG_MULTIPLEX_PORT TCFG_IOKEY_PREV_ONE_PORT // 复用的引脚 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_LED_IO_REUSE DISABLE_THIS_MOUDLE //ADKEY 和 LED IO复用,led只能设置蓝灯显示 +#define TCFG_ADKEY_PORT IO_PORTA_10 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PA10 +#define TCFG_ADKEY_EXTERN_UP_ENABLE 0//ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTB_01 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_80V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 + DAC_OUTPUT_FRONT_LR_REAR_LR 四声道输出 +*/ +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC //LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define VOL_TYPE_DIGGROUP 4 //独立通道数字音量 + +//每个解码通道都开启数字音量管理,音量类型为VOL_TYPE_DIGGROUP时要使能 +#define SYS_DIGVOL_GROUP_EN DISABLE + +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE ENABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE ENABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 //ui风格 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 +#define TCFG_UI_LED1888_ENABLE ENABLE_THIS_MOUDLE //UI使用LED1888 +// #define TCFG_UI_LED7_ENABLE ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) + +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 64000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 0 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 0 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 0 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 0 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 0 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 0 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 0 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 0 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 0 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 0 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 0 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 0 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 0 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 0 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 0 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif + +#endif +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 0 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 4000//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + + +#define USER_SUPPORT_PROFILE_SPP 0 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 + + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 180 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 1 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN ENABLE//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE ENABLE//音乐播放录音区分使能 + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR +#define TCFG_LINEIN_CHECK_PORT IO_PORTC_04 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL AD_CH_PC4//NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 1000 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC +#define TCFG_LINEIN_MULTIPLEX_WITH_SD ENABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 1// 0:sd0 1:sd1 //选择复用的sd + +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE ENABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE DISABLE +#define TCFG_DEC_WAV_ENABLE ENABLE +#define TCFG_DEC_FLAC_ENABLE ENABLE +#define TCFG_DEC_APE_ENABLE ENABLE +#define TCFG_DEC_M4A_ENABLE DISABLE +#define TCFG_DEC_ALAC_ENABLE DISABLE +#define TCFG_DEC_AMR_ENABLE DISABLE +#define TCFG_DEC_DTS_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE DISABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE +#define TCFG_FM_BK1080_ENABLE DISABLE +#define TCFG_FM_QN8035_ENABLE DISABLE + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN ENABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE ENABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE DISABLE +#define TCFG_HDMI_ARC_ENABLE DISABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE // +#define TCFG_IIS_OUTPUT_EN ENABLE // +#define TCFG_IIS_OUTPUT_PORT ALINK1_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL (BIT(0)) + +#define TCFG_IIS_INPUT_EN DISABLE// +#define TCFG_IIS_INPUT_PORT ALINK1_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR (44100l) +#define TCFG_IIS_INPUT_DATAPORT_SEL (BIT(0)) + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE ENABLE +#define TCFG_ENC_MSBC_ENABLE ENABLE +#define TCFG_ENC_G726_ENABLE DISABLE +#define TCFG_ENC_MP3_ENABLE DISABLE +#define TCFG_ENC_ADPCM_ENABLE DISABLE +#define TCFG_ENC_PCM_ENABLE DISABLE +#define TCFG_ENC_SBC_ENABLE DISABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + +//*********************************************************************************// +//ali ai profile +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 0 //not surport +#define ANCS_CLIENT_EN 0 + +#if (DUEROS_DMA_EN || TRANS_DATA_EN || ANCS_CLIENT_EN) +#define BT_FOR_APP_EN 1 +#else +#define BT_FOR_APP_EN 0 +#endif + +//*********************************************************************************// + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC693X_DEMO +#endif //CONFIG_BOARD_AC693X_DEMO_CFG_H diff --git a/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/adkey_table.c new file mode 100644 index 0000000..4a48f61 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/adkey_table.c @@ -0,0 +1,356 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6952E_LIGHTER +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [3] = { + KEY_FM_EMITTER_PERV_FREQ, KEY_FM_EMITTER_PERV_FREQ, KEY_FM_EMITTER_PERV_FREQ, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_EMITTER_NEXT_FREQ, KEY_FM_EMITTER_NEXT_FREQ, KEY_FM_EMITTER_NEXT_FREQ, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_FM_EMITTER_PERV_FREQ, KEY_FM_EMITTER_PERV_FREQ, KEY_FM_EMITTER_PERV_FREQ, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_EMITTER_NEXT_FREQ, KEY_FM_EMITTER_NEXT_FREQ, KEY_FM_EMITTER_NEXT_FREQ, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + } +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_MUSIC_CHANGE_REPEAT, KEY_NULL + }, + [1] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_FM_EMITTER_PERV_FREQ, KEY_FM_EMITTER_PERV_FREQ, KEY_FM_EMITTER_PERV_FREQ, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_EMITTER_NEXT_FREQ, KEY_FM_EMITTER_NEXT_FREQ, KEY_FM_EMITTER_NEXT_FREQ, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_MUSIC_FR, KEY_MUSIC_FR, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_MUSIC_FF, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_MUSIC_CHANGE_REPEAT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [5] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/iokey_table.c new file mode 100644 index 0000000..a0a86c9 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/iokey_table.c @@ -0,0 +1,248 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6952E_LIGHTER +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/irkey_table.c new file mode 100644 index 0000000..d75a6ea --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6952E_LIGHTER +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/rdec_key_table.c new file mode 100644 index 0000000..63f04d3 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6952E_LIGHTER +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/touch_key_table.c new file mode 100644 index 0000000..9d0e104 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6952E_LIGHTER +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6954a_demo/board_ac6954a_demo.c b/apps/soundbox/board/br23/board_ac6954a_demo/board_ac6954a_demo.c new file mode 100644 index 0000000..f636730 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6954a_demo/board_ac6954a_demo.c @@ -0,0 +1,1072 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC6954A_DEMO + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "fm/fm_manage.h" +#include "asm/power/p33.h" +#include "norflash.h" +#include "asm/spi.h" +#include "ui_manage.h" +#include "spi/nor_fs.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, + .key_value = 2, + }, +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, +#if TCFG_SD1_ENABLE + .pin_cfg.pin7.pin[0] = IO_PORTA_02, + .pin_cfg.pin7.pin[1] = IO_PORTA_03, + .pin_cfg.pin7.pin[2] = IO_PORTA_04, + .pin_cfg.pin7.pin[3] = IO_PORTA_06, + .pin_cfg.pin7.pin[4] = IO_PORTA_07, + .pin_cfg.pin7.pin[5] = IO_PORTA_08, + .pin_cfg.pin7.pin[6] = IO_PORTA_09, +#else + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if 0 +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; + + +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NOR_FAT +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 0, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_FS +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 1*1024*1024, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_REC +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 2*1024*1024, + .size = 2*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_FM_ENABLE + +FM_DEV_PLATFORM_DATA_BEGIN(fm_dev_data) + .iic_hdl = 0, + .iic_delay = 50, +FM_DEV_PLATFORM_DATA_END(); + +#endif + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +#if TCFG_NOR_FAT + { "fat_nor", &norflash_dev_ops , (void *)&norflash_fat_dev_data}, +#endif + +#if TCFG_NOR_FS + { "res_nor", &norfs_dev_ops , (void *)&norflash_norfs_dev_data}, +#endif + +#if TCFG_NOR_REC + {"rec_nor", &norfs_dev_ops , (void *)&norflash_norfs_rec_dev_data}, +#endif +#endif +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTA_10, //唤醒口选择 +}; + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} +static void key_wakeup_disable() +{ + power_wakeup_index_disable(1); +} +static void key_wakeup_enable() +{ + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + +#if TCFG_FM_ENABLE + fm_dev_init(&fm_dev_data); +#endif + +#if TCFG_NOR_REC + nor_fs_ops_init(); +#endif + +#if TCFG_NOR_FS + init_norsdfile_hdl(); +#endif + +#if FLASH_INSIDE_REC_ENABLE + sdfile_rec_ops_init(); +#endif + + dev_manager_init(); + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + //针对硅mic要输出1给mic供电(按实际使用情况配置) + /* if(!adc_data.mic_capless){ */ + /* gpio_set_pull_up(IO_PORTA_04, 0); */ + /* gpio_set_pull_down(IO_PORTA_04, 0); */ + /* gpio_set_direction(IO_PORTA_04, 0); */ + /* gpio_set_output_value(IO_PORTA_04,1); */ + /* } */ + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +#if USER_UART_UPDATE_ENABLE + { +#include "uart_update.h" + uart_update_cfg update_cfg = { + .rx = IO_PORTA_02, + .tx = IO_PORTA_03, + .output_channel = CH1_UT1_TX, + .input_channel = INPUT_CH0 + }; + uart_update_init(&update_cfg); + } +#endif +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + key_wakeup_enable(); + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); + key_wakeup_disable(); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + key_wakeup_enable(); + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); + key_wakeup_disable(); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif diff --git a/apps/soundbox/board/br23/board_ac6954a_demo/board_ac6954a_demo_cfg.h b/apps/soundbox/board/br23/board_ac6954a_demo/board_ac6954a_demo_cfg.h new file mode 100644 index 0000000..e8a0ae0 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6954a_demo/board_ac6954a_demo_cfg.h @@ -0,0 +1,985 @@ +#ifndef CONFIG_BOARD_AC6954A_DEMO_CFG_H +#define CONFIG_BOARD_AC6954A_DEMO_CFG_H + +#ifdef CONFIG_BOARD_AC6954A_DEMO + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 + +#define NO_CONFIG_PORT (-1) + + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 0 +#define TCFG_APP_LINEIN_EN 0 +#define TCFG_APP_FM_EN 0 +#define TCFG_APP_PC_EN 1 +#define TCFG_APP_RTC_EN 0 +#define TCFG_APP_RECORD_EN 0 +#define TCFG_APP_SPDIF_EN 1 +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTA_05 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCFG_SW_I2C0_CLK_PORT IO_PORTA_09 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTA_10 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 2000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE ENABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'B' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE ENABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#include "usb_std_class_def.h" + + +#define TCFG_USB_PORT_CHARGE DISABLE + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DP_ONLY) + +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO + +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_LED_IO_REUSE DISABLE_THIS_MOUDLE //ADKEY 和 LED IO复用,led只能设置蓝灯显示 +#define TCFG_ADKEY_PORT IO_PORTB_03 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PB3 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTA_00 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTA_01 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 +*/ +//#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC //LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define VOL_TYPE_DIGGROUP 4 //独立通道数字音量 + +//每个解码通道都开启数字音量管理,音量类型为VOL_TYPE_DIGGROUP时要使能 +#define SYS_DIGVOL_GROUP_EN DISABLE + +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE ENABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE DISABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + +#define TCFG_LED7_RUN_RAM DISABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0// SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 0 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 0 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 0 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 0 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 0 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 0 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 0 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 0 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 0 //DRC总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 0 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 0 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 0 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 0 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 0 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 0 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif + +#endif +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 1 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 4000//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +#define TCFG_AUDIO_DEC_OUT_TASK 0 // 解码使用单独任务做输出 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 0 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 0 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN 0//ENABLE//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE ENABLE//音乐播放录音区分使能 + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR +#define TCFG_LINEIN_CHECK_PORT IO_PORTB_02 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd + +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE ENABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE ENABLE +#define TCFG_DEC_WAV_ENABLE ENABLE +#define TCFG_DEC_FLAC_ENABLE 0//ENABLE +#define TCFG_DEC_APE_ENABLE 0//ENABLE +#define TCFG_DEC_M4A_ENABLE ENABLE +#define TCFG_DEC_ALAC_ENABLE DISABLE +#define TCFG_DEC_AMR_ENABLE ENABLE +#define TCFG_DEC_DTS_ENABLE ENABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE ENABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE +#define TCFG_FM_BK1080_ENABLE DISABLE +#define TCFG_FM_QN8035_ENABLE DISABLE + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE) +#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE))) +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#else +#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif +#else +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/ + +#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE) +#undef TCFG_LED7_RUN_RAM +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/ + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE 0//ENABLE +#define TCFG_HDMI_ARC_ENABLE 0//ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_12 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE // +#define TCFG_IIS_OUTPUT_EN ENABLE // +#define TCFG_IIS_OUTPUT_PORT ALINK1_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL (BIT(0)) + +#define TCFG_IIS_INPUT_EN DISABLE// +#define TCFG_IIS_INPUT_PORT ALINK1_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR (44100l) +#define TCFG_IIS_INPUT_DATAPORT_SEL (BIT(0)) + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE ENABLE +#define TCFG_ENC_MSBC_ENABLE ENABLE +#define TCFG_ENC_G726_ENABLE ENABLE +#define TCFG_ENC_MP3_ENABLE ENABLE +#define TCFG_ENC_ADPCM_ENABLE ENABLE +#define TCFG_ENC_PCM_ENABLE ENABLE +#define TCFG_ENC_SBC_ENABLE ENABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + + +//*********************************************************************************// +//ali ai profile +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 0 //not surport +#define ANCS_CLIENT_EN 0 + +#if (DUEROS_DMA_EN || TRANS_DATA_EN || ANCS_CLIENT_EN) +#define BT_FOR_APP_EN 1 +#else +#define BT_FOR_APP_EN 0 +#endif + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC695X_DEMO +#endif //CONFIG_BOARD_AC695X_DEMO_CFG_H diff --git a/apps/soundbox/board/br23/board_ac6954a_demo/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac6954a_demo/key_table/adkey_table.c new file mode 100644 index 0000000..6e2cecb --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6954a_demo/key_table/adkey_table.c @@ -0,0 +1,353 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6954A_DEMO +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_CHANGE_REPEAT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_NULL, KEY_MUSIC_FR, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6954a_demo/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac6954a_demo/key_table/iokey_table.c new file mode 100644 index 0000000..d58f09c --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6954a_demo/key_table/iokey_table.c @@ -0,0 +1,248 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6954A_DEMO +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6954a_demo/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac6954a_demo/key_table/irkey_table.c new file mode 100644 index 0000000..1b50abf --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6954a_demo/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6954A_DEMO +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6954a_demo/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac6954a_demo/key_table/rdec_key_table.c new file mode 100644 index 0000000..f2e5ccd --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6954a_demo/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6954A_DEMO +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6954a_demo/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac6954a_demo/key_table/touch_key_table.c new file mode 100644 index 0000000..ebc2ea0 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6954a_demo/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6954A_DEMO +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6955f_headset_mono/board_ac6955f_headset_mono.c b/apps/soundbox/board/br23/board_ac6955f_headset_mono/board_ac6955f_headset_mono.c new file mode 100644 index 0000000..d639c98 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6955f_headset_mono/board_ac6955f_headset_mono.c @@ -0,0 +1,886 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC6955F_HEADSET_MONO + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "asm/power/p33.h" +#include "ui_manage.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, + .key_value = 2, + }, +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if 0 +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; + + +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .dcdc_port = TCFG_DCDC_PORT_SEL, + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_LRC,//OSC_TYPE_BT_OSC , +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTB_01,//IO_PORTA_10, //唤醒口选择 +}; + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_TOUCH_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +extern int devices_charge_init(); +extern u8 get_dcdc_ctl_port(void); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + + dev_manager_init(); + + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + + + +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + if(TCFG_LOWPOWER_POWER_SEL == PWR_DCDC15){ + power_set_mode(PWR_LDO15); + gpio_set_die(power_param.dcdc_port, 1); + gpio_direction_output(power_param.dcdc_port, 0); + } + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + if(TCFG_LOWPOWER_POWER_SEL == PWR_DCDC15){ + gpio_set_die(power_param.dcdc_port, 1); + gpio_direction_output(power_param.dcdc_port, 1); + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + APP_IO_DEBUG_1(A, 6); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + if(TCFG_LOWPOWER_POWER_SEL == PWR_DCDC15){ + power_set_mode(PWR_LDO15); + gpio_set_die(power_param.dcdc_port, 1); + gpio_direction_output(power_param.dcdc_port, 0); + } + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif diff --git a/apps/soundbox/board/br23/board_ac6955f_headset_mono/board_ac6955f_headset_mono_cfg.h b/apps/soundbox/board/br23/board_ac6955f_headset_mono/board_ac6955f_headset_mono_cfg.h new file mode 100644 index 0000000..9fbbc38 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6955f_headset_mono/board_ac6955f_headset_mono_cfg.h @@ -0,0 +1,848 @@ +#ifndef CONFIG_BOARD_AC6955F_HEADSET_MONO_CFG_H +#define CONFIG_BOARD_AC6955F_HEADSET_MONO_CFG_H + +#ifdef CONFIG_BOARD_AC6955F_HEADSET_MONO + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 + +#define NO_CONFIG_PORT (-1) + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 1 +#define TCFG_APP_LINEIN_EN 1 +#define TCFG_APP_FM_EN 0 +#define TCFG_APP_PC_EN 0 +#define TCFG_APP_RTC_EN 0 +#define TCFG_APP_RECORD_EN 0 +#define TCFG_APP_SPDIF_EN 0 + +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTA_05 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCFG_SW_I2C0_CLK_PORT IO_PORTA_09 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTA_10 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE ENABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_80 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define TCFG_SD0_ENABLE ENABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE DISABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#include "usb_std_class_def.h" + + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO + +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_PORT IO_PORTB_01 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PB1 +#define TCFG_ADKEY_EXTERN_UP_ENABLE DISABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + + +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT + +/* +DAC硬件上的连接方式,可选的配置: +*/ +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define VOL_TYPE_DIGGROUP 4 //独立通道数字音量 + +//每个解码通道都开启数字音量管理,音量类型为VOL_TYPE_DIGGROUP时要使能 +#define SYS_DIGVOL_GROUP_EN DISABLE + +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//*********************************************************************************// +#define TCFG_PWMLED_ENABLE ENABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTA_00 //LED使用的IO口 + +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE DISABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + +#define TCFG_LED7_RUN_RAM DISABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_DCDC_PORT_SEL NO_CONFIG_PORT //DCDC控制脚设置,只有在选择DCDC的时候起作用 +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 0 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 0 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 0 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 0 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 0 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 0 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 0 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 0 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE +#define TCFG_DRC_ENABLE 0 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 0 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 0 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 0 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 0 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 0 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 0 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif + +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif + +#endif +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 1 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 1 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 3700//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 1 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 1 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 0 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 180 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 0 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR +#define TCFG_LINEIN_CHECK_PORT IO_PORTA_01 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 0 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL AD_CH_PA1 // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 960 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC//LINEIN_INPUT_WAY_ANALOG +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd + +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE ENABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE ENABLE +#define TCFG_DEC_WAV_ENABLE ENABLE +#define TCFG_DEC_FLAC_ENABLE ENABLE +#define TCFG_DEC_APE_ENABLE ENABLE +#define TCFG_DEC_M4A_ENABLE ENABLE +#define TCFG_DEC_ALAC_ENABLE DISABLE +#define TCFG_DEC_AMR_ENABLE ENABLE +#define TCFG_DEC_DTS_ENABLE ENABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE ENABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE +#define TCFG_FM_BK1080_ENABLE DISABLE +#define TCFG_FM_QN8035_ENABLE DISABLE + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE) +#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE))) +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#else +#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif +#else +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/ + +#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE) +#undef TCFG_LED7_RUN_RAM +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/ + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define TCFG_LINEIN_REC_EN DISABLE + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE ENABLE +#define TCFG_ENC_MSBC_ENABLE ENABLE +#define TCFG_ENC_G726_ENABLE ENABLE +#define TCFG_ENC_MP3_ENABLE ENABLE +#define TCFG_ENC_ADPCM_ENABLE ENABLE +#define TCFG_ENC_PCM_ENABLE ENABLE +#define TCFG_ENC_SBC_ENABLE ENABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + +//*********************************************************************************// +//ali ai profile +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 1 //数传demo + + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif +#endif diff --git a/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/adkey_table.c new file mode 100644 index 0000000..692493d --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/adkey_table.c @@ -0,0 +1,347 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6955F_HEADSET_MONO +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_CHANGE_REPEAT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_NULL, KEY_MUSIC_FR, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/iokey_table.c new file mode 100644 index 0000000..2e4fec3 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/iokey_table.c @@ -0,0 +1,239 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6955F_HEADSET_MONO +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/irkey_table.c new file mode 100644 index 0000000..3d31d55 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6955F_HEADSET_MONO +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/rdec_key_table.c new file mode 100644 index 0000000..6bc27b6 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6955F_HEADSET_MONO +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/touch_key_table.c new file mode 100644 index 0000000..599671b --- /dev/null +++ b/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC6955F_HEADSET_MONO +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_audio_effects/board_ac695x_audio_effects.c b/apps/soundbox/board/br23/board_ac695x_audio_effects/board_ac695x_audio_effects.c new file mode 100644 index 0000000..8cf8c60 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_audio_effects/board_ac695x_audio_effects.c @@ -0,0 +1,1158 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC695X_AUDIO_EFFECTS + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "fm/fm_manage.h" +#include "asm/power/p33.h" +#include "norflash.h" +#include "asm/spi.h" +#include "ui_manage.h" +#include "spi/nor_fs.h" +#include "nandflash.h" +#include "audio_link.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +#if TCFG_IIS_ENABLE +ALINK_PARM alink0_param = { + .port_select = ALINK0_PORTA, //MCLK:PA8 SCLK:PA2 LRCK:PA3 CH0:PA4 CH1:PA5 CH2:PA6 CH3:PA7 + /* .port_select = ALINK0_PORTB, //MCLK:PA15 SCLK:PA9 LRCK:PA10 CH0:PA11 CH1:PA12 CH2:PA13 CH3:PA14 */ + /* .port_select = ALINK1_PORTA, //MCLK:PB0 SCLK:PC0 LRCK:PC1 CH0:PC2 CH1:PC3 CH2:PC4 CH3:PC5 */ + .ch_cfg[0].enable = 1, + .ch_cfg[1].enable = 1, + .mode = ALINK_MD_IIS, +#if TCFG_IIS_MODE + .role = ALINK_ROLE_SLAVE, +#else + .role = ALINK_ROLE_MASTER, +#endif + .clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE, + .bitwide = ALINK_LEN_16BIT, + .sclk_per_frame = ALINK_FRAME_64SCLK, + .dma_len = ALNK_BUF_POINTS_NUM * 2 * 2 * 2, + .sample_rate = TCFG_IIS_OUTPUT_SR, +}; + +ALINK_PARM alink1_param = { + /* .port_select = ALINK0_PORTA, //MCLK:PA8 SCLK:PA2 LRCK:PA3 CH0:PA4 CH1:PA5 CH2:PA6 CH3:PA7 */ + /* .port_select = ALINK0_PORTB, //MCLK:PA15 SCLK:PA9 LRCK:PA10 CH0:PA11 CH1:PA12 CH2:PA13 CH3:PA14 */ + .port_select = ALINK1_PORTA, //MCLK:PB0 SCLK:PC0 LRCK:PC1 CH0:PC2 CH1:PC3 CH2:PC4 CH3:PC5 + .ch_cfg[0].enable = 1, + .ch_cfg[1].enable = 1, + .mode = ALINK_MD_IIS, +#if TCFG_IIS_MODE + .role = ALINK_ROLE_SLAVE, +#else + .role = ALINK_ROLE_MASTER, +#endif + .clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE, + .bitwide = ALINK_LEN_16BIT, + .sclk_per_frame = ALINK_FRAME_64SCLK, + .dma_len = ALNK_BUF_POINTS_NUM * 2 * 2 * 2, + .sample_rate = TCFG_IIS_OUTPUT_SR, +}; + + +#endif + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, + .key_value = 2, + }, +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, +#if TCFG_SD1_ENABLE + .pin_cfg.pin7.pin[0] = IO_PORTA_02, + .pin_cfg.pin7.pin[1] = IO_PORTA_03, + .pin_cfg.pin7.pin[2] = IO_PORTA_04, + .pin_cfg.pin7.pin[3] = IO_PORTA_06, + .pin_cfg.pin7.pin[4] = IO_PORTA_07, + .pin_cfg.pin7.pin[5] = IO_PORTA_08, + .pin_cfg.pin7.pin[6] = IO_PORTA_09, +#else + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if TCHFG_SOFT_I2C_ENABLE +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; +#endif + +#if TCHFG_HW_I2C_ENABLE +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NANDFLASH_DEV_ENABLE +NANDFLASH_DEV_PLATFORM_DATA_BEGIN(nandflash_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, + .start_addr = 0, + .size = 0, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif +NANDFLASH_DEV_PLATFORM_DATA_END() +#endif + + +#if TCFG_NOR_FAT +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 0, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_FS +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 1*1024*1024, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_REC +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 2*1024*1024, + .size = 2*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_FM_ENABLE + +FM_DEV_PLATFORM_DATA_BEGIN(fm_dev_data) + .iic_hdl = 0, + .iic_delay = 50, +FM_DEV_PLATFORM_DATA_END(); + +#endif + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +#if TCFG_NOR_FAT + { "fat_nor", &norflash_dev_ops , (void *)&norflash_fat_dev_data}, +#endif + +#if TCFG_NOR_FS + { "res_nor", &norfs_dev_ops , (void *)&norflash_norfs_dev_data}, +#endif + +#if TCFG_NOR_REC + {"rec_nor", &norfs_dev_ops , (void *)&norflash_norfs_rec_dev_data}, +#endif +#endif + +#if TCFG_NANDFLASH_DEV_ENABLE + {"nand_flash", &nandflash_dev_ops , (void *)&nandflash_dev_data}, +#endif + + +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , + +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif + +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTA_10, //唤醒口选择 +}; + +/* RTC PR0 PR1 唤醒 */ +/* struct port_wakeup rtc_port0 = { */ + /* .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 */ + /* .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 */ + /* .attribute = BLUETOOTH_RESUME, //保留参数 */ + /* .iomap = IO_PORT_PR_00, //唤醒口选择 */ +/* }; */ + +/* struct port_wakeup rtc_port1 = { */ + /* .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 */ + /* .edge = RISING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 */ + /* .attribute = BLUETOOTH_RESUME, //保留参数 */ + /* .iomap = IO_PORT_PR_01, //唤醒口选择 */ +/* }; */ + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + /* .rtc_port[0] = &rtc_port0, */ + /* .rtc_port[1] = &rtc_port1, */ + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} +static void key_wakeup_disable() +{ + power_wakeup_index_disable(1); +} +static void key_wakeup_enable() +{ + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + +#if TCFG_FM_ENABLE + fm_dev_init(&fm_dev_data); +#endif + +#if TCFG_NOR_REC + nor_fs_ops_init(); +#endif + +#if TCFG_NOR_FS + init_norsdfile_hdl(); +#endif + +#if FLASH_INSIDE_REC_ENABLE + sdfile_rec_ops_init(); +#endif + + dev_manager_init(); + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + //针对硅mic要输出1给mic供电(按实际使用情况配置) + /* if(!adc_data.mic_capless){ */ + /* gpio_set_pull_up(IO_PORTA_04, 0); */ + /* gpio_set_pull_down(IO_PORTA_04, 0); */ + /* gpio_set_direction(IO_PORTA_04, 0); */ + /* gpio_set_output_value(IO_PORTA_04,1); */ + /* } */ + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +#if USER_UART_UPDATE_ENABLE + { +#include "uart_update.h" + uart_update_cfg update_cfg = { + .rx = IO_PORTA_02, + .tx = IO_PORTA_03, + .output_channel = CH1_UT1_TX, + .input_channel = INPUT_CH0 + }; + uart_update_init(&update_cfg); + } +#endif +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + key_wakeup_enable(); + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); + key_wakeup_disable(); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + key_wakeup_enable(); + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); + key_wakeup_disable(); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_audio_effects/board_ac695x_audio_effects_cfg.h b/apps/soundbox/board/br23/board_ac695x_audio_effects/board_ac695x_audio_effects_cfg.h new file mode 100644 index 0000000..0bbab3f --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_audio_effects/board_ac695x_audio_effects_cfg.h @@ -0,0 +1,1059 @@ +#ifndef CONFIG_BOARD_AC695X_AUDIO_EFFECTS_CFG_H +#define CONFIG_BOARD_AC695X_AUDIO_EFFECTS_CFG_H + +#ifdef CONFIG_BOARD_AC695X_AUDIO_EFFECTS + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 +#define LINEIN_INPUT_WAY_DAC 2 + +#define NO_CONFIG_PORT (-1) + + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 1 +#define TCFG_APP_LINEIN_EN 1 +#define TCFG_APP_FM_EN 1 +#define TCFG_APP_PC_EN 1 +#define TCFG_APP_RTC_EN 1 +#define TCFG_APP_RECORD_EN 1 +#define TCFG_APP_SPDIF_EN 0 +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTA_05 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCHFG_SOFT_I2C_ENABLE DISABLE_THIS_MOUDLE //软件IIC使能 +#define TCFG_SW_I2C0_CLK_PORT IO_PORTB_00 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTB_03 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCHFG_HW_I2C_ENABLE DISABLE_THIS_MOUDLE //硬件IIC使能 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 4000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_NANDFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + +//*********************************************************************************// +// 设备异步读 配置 // +//*********************************************************************************// + +#define TCFG_DEVICE_BULK_READ_ASYNC_ENABLE + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE ENABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE ENABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#define TCFG_VIR_UDISK_ENABLE 0//ENABLE_THIS_MOUDLE +#include "usb_std_class_def.h" +#undef USB_MALLOC_ENABLE +#define USB_MALLOC_ENABLE 1 + +#define TCFG_USB_PORT_CHARGE DISABLE + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE + +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DP_ONLY) + +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 + +#define TCFG_KEY_TONE_EN 0//ENABLE // 按键提示音。建议音频输出使用固定采样率 + +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO + +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_LED_IO_REUSE DISABLE_THIS_MOUDLE //ADKEY 和 LED IO复用,led只能设置蓝灯显示 +#define TCFG_ADKEY_PORT IO_PORTA_10 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PA10 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTA_00 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTA_01 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 + DAC_OUTPUT_FRONT_LR_REAR_LR 四声道输出 +*/ +//#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC //LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define VOL_TYPE_DIGGROUP 4 //独立通道数字音量 + +//每个解码通道都开启数字音量管理,音量类型为VOL_TYPE_DIGGROUP时要使能 +#define SYS_DIGVOL_GROUP_EN DISABLE + +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) + +//AudioEffects代码链接管理 +#define AUDIO_EFFECTS_DRC_AT_RAM 1 +#define AUDIO_EFFECTS_REVERB_AT_RAM 1 +#define AUDIO_EFFECTS_ECHO_AT_RAM 0 +#define AUDIO_EFFECTS_AFC_AT_RAM 1 +#define AUDIO_EFFECTS_EQ_AT_RAM 1 +#define AUDIO_EFFECTS_NOISEGATE_AT_RAM 0 +#define AUDIO_EFFECTS_MIC_EFFECT_AT_RAM 0 +#define AUDIO_EFFECTS_MIC_STREAM_AT_RAM 0 +#define AUDIO_EFFECTS_DEBUG_AT_RAM 0 + +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE ENABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE DISABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE DISABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + +#define TCFG_LED7_RUN_RAM DISABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) + +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 240000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 1 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 1 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 1 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 1 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 1 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 0 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 1 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 1 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后置EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 1 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc + +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 1 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 1 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 1 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 1 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 1 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 1 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后的drc +#endif//TCFG_DRC_ENABLE + +#define LINEIN_MODE_SOLE_EQ_EN 0 //linein模式是否需要独立的eq与drc + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 1//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + + +#define TCFG_MIC_VOICE_CHANGER_ENABLE DISABLE //变声模块使能 + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif + +#endif +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 1 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 4000//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +#define TCFG_AUDIO_DEC_OUT_TASK 0 // 解码使用单独任务做输出 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 1 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 0 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN DISABLE//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE DISABLE//音乐播放录音区分使能 + + +#if RECORDER_MIX_EN//限制不能同时打开 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE +#endif + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR +#define TCFG_LINEIN_CHECK_PORT IO_PORTB_03 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd口 +#define TCFG_LINEIN_DETECT_ENABLE 0 +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE ENABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE ENABLE +#define TCFG_DEC_WAV_ENABLE ENABLE +#define TCFG_DEC_FLAC_ENABLE ENABLE +#define TCFG_DEC_APE_ENABLE DISABLE +#define TCFG_DEC_M4A_ENABLE DISABLE +#define TCFG_DEC_ALAC_ENABLE DISABLE +#define TCFG_DEC_AMR_ENABLE DISABLE +#define TCFG_DEC_DTS_ENABLE DISABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE ENABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE //需要使能软件IIC模块 +#define TCFG_FM_BK1080_ENABLE DISABLE //需要使能软件IIC模块 +#define TCFG_FM_QN8035_ENABLE DISABLE //需要使能软件IIC模块 + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE) +#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE))) +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#else +#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif +#else +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/ + +#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE) +#undef TCFG_LED7_RUN_RAM +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/ + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) || (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC_IIS) +#define TCFG_IIS_ENABLE ENABLE_THIS_MOUDLE +#else +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE +#endif + +#define TCFG_IIS_MODE (0) // 0:master 1:slave + +#define TCFG_IIS_OUTPUT_EN (ENABLE && TCFG_IIS_ENABLE) +#define TCFG_IIS_OUTPUT_PORT ALINK0_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL 0 + +#define TCFG_IIS_INPUT_EN (DISABLE && TCFG_IIS_ENABLE) +#define TCFG_IIS_INPUT_PORT ALINK0_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR 44100 +#define TCFG_IIS_INPUT_DATAPORT_SEL 1 + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE ENABLE +#define TCFG_ENC_MSBC_ENABLE ENABLE +#define TCFG_ENC_G726_ENABLE ENABLE +#define TCFG_ENC_MP3_ENABLE ENABLE +#define TCFG_ENC_ADPCM_ENABLE ENABLE +#define TCFG_ENC_PCM_ENABLE ENABLE +#define TCFG_ENC_SBC_ENABLE ENABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + +//*********************************************************************************// +//ali ai profile +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 0 //not surport +#define ANCS_CLIENT_EN 0 + +#if (DUEROS_DMA_EN || TRANS_DATA_EN || ANCS_CLIENT_EN) +#define BT_FOR_APP_EN 1 +#else +#define BT_FOR_APP_EN 0 +#endif + +//*********************************************************************************// + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 + +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 2.X声道配置(需使能板极四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR) +// 2.1 两个全频较弱的全频音箱 + 一个低音炮 +// 2.2 两个全频较弱的全频音箱 + 2个低音炮 +//*********************************************************************************// +#define SOUND_TRACK_2_P_X_CH_CONFIG 0 //2.X声道总使能 + +#if SOUND_TRACK_2_P_X_CH_CONFIG +#define TWO_POINT_ONE_CH BIT(0) //2.1声道 +#define TWO_POINT_TWO_CH BIT(1) //2.2声道 +#define TWO_POINT_X_CH TWO_POINT_ONE_CH//选配使用2.1 还是2.2 声道 + +#if (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#undef TCFG_AUDIO_DAC_CONNECT_MODE +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#endif +#endif/*SOUND_TRACK_2_P_X_CH_CONFIG*/ + + + + + + +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)&&(TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE)) +#error "使能配置工具时,需临时关闭flac解码 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif + +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC695X_AUDIO_EFFECTS +#endif //CONFIG_BOARD_AC695X_AUDIO_EFFECTS_CFG_H diff --git a/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/adkey_table.c new file mode 100644 index 0000000..369ec7d --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/adkey_table.c @@ -0,0 +1,356 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_AUDIO_EFFECTS +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_UP, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_DOWN, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_MUSIC_CHANGE_REPEAT, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_MUSIC_FR, KEY_MUSIC_FR, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_MUSIC_FF, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_PLAYER_AB_REPEAT_SWITCH, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/iokey_table.c new file mode 100644 index 0000000..48d08ee --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/iokey_table.c @@ -0,0 +1,248 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_AUDIO_EFFECTS +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/irkey_table.c new file mode 100644 index 0000000..6048790 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_AUDIO_EFFECTS +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_IR_NUM_0, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_IR_NUM_1, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_IR_NUM_2, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_IR_NUM_3, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_IR_NUM_4, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_IR_NUM_5, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_IR_NUM_6, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_IR_NUM_7, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_IR_NUM_8, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_IR_NUM_9, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/rdec_key_table.c new file mode 100644 index 0000000..b372c2d --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_AUDIO_EFFECTS +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/touch_key_table.c new file mode 100644 index 0000000..7575574 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_AUDIO_EFFECTS +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_btemitter/board_ac695x_btemitter.c b/apps/soundbox/board/br23/board_ac695x_btemitter/board_ac695x_btemitter.c new file mode 100644 index 0000000..0f23709 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_btemitter/board_ac695x_btemitter.c @@ -0,0 +1,1072 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC695X_BTEMITTER + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "fm/fm_manage.h" +#include "asm/power/p33.h" +#include "norflash.h" +#include "asm/spi.h" +#include "ui_manage.h" +#include "spi/nor_fs.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, + .key_value = 2, + }, +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, +#if TCFG_SD1_ENABLE + .pin_cfg.pin7.pin[0] = IO_PORTA_02, + .pin_cfg.pin7.pin[1] = IO_PORTA_03, + .pin_cfg.pin7.pin[2] = IO_PORTA_04, + .pin_cfg.pin7.pin[3] = IO_PORTA_06, + .pin_cfg.pin7.pin[4] = IO_PORTA_07, + .pin_cfg.pin7.pin[5] = IO_PORTA_08, + .pin_cfg.pin7.pin[6] = IO_PORTA_09, +#else + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if 0 +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; + + +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NOR_FAT +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 0, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_FS +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 1*1024*1024, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_REC +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 2*1024*1024, + .size = 2*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_FM_ENABLE + +FM_DEV_PLATFORM_DATA_BEGIN(fm_dev_data) + .iic_hdl = 0, + .iic_delay = 50, +FM_DEV_PLATFORM_DATA_END(); + +#endif + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +#if TCFG_NOR_FAT + { "fat_nor", &norflash_dev_ops , (void *)&norflash_fat_dev_data}, +#endif + +#if TCFG_NOR_FS + { "res_nor", &norfs_dev_ops , (void *)&norflash_norfs_dev_data}, +#endif + +#if TCFG_NOR_REC + {"rec_nor", &norfs_dev_ops , (void *)&norflash_norfs_rec_dev_data}, +#endif +#endif +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTA_10, //唤醒口选择 +}; + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} +static void key_wakeup_disable() +{ + power_wakeup_index_disable(1); +} +static void key_wakeup_enable() +{ + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + +#if TCFG_FM_ENABLE + fm_dev_init(&fm_dev_data); +#endif + +#if TCFG_NOR_REC + nor_fs_ops_init(); +#endif + +#if TCFG_NOR_FS + init_norsdfile_hdl(); +#endif + +#if FLASH_INSIDE_REC_ENABLE + sdfile_rec_ops_init(); +#endif + + dev_manager_init(); + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + //针对硅mic要输出1给mic供电(按实际使用情况配置) + /* if(!adc_data.mic_capless){ */ + /* gpio_set_pull_up(IO_PORTA_04, 0); */ + /* gpio_set_pull_down(IO_PORTA_04, 0); */ + /* gpio_set_direction(IO_PORTA_04, 0); */ + /* gpio_set_output_value(IO_PORTA_04,1); */ + /* } */ + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +#if USER_UART_UPDATE_ENABLE + { +#include "uart_update.h" + uart_update_cfg update_cfg = { + .rx = IO_PORTA_02, + .tx = IO_PORTA_03, + .output_channel = CH1_UT1_TX, + .input_channel = INPUT_CH0 + }; + uart_update_init(&update_cfg); + } +#endif +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + key_wakeup_enable(); + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); + key_wakeup_disable(); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + key_wakeup_enable(); + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); + key_wakeup_disable(); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_btemitter/board_ac695x_btemitter.h b/apps/soundbox/board/br23/board_ac695x_btemitter/board_ac695x_btemitter.h new file mode 100644 index 0000000..a84ae85 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_btemitter/board_ac695x_btemitter.h @@ -0,0 +1,1059 @@ +#ifndef CONFIG_BOARD_AC695X_BTEMITTER_CFG_H +#define CONFIG_BOARD_AC695X_BTEMITTER_CFG_H + +#ifdef CONFIG_BOARD_AC695X_BTEMITTER + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 + +#define NO_CONFIG_PORT (-1) + + +#define BT_EMITTER_TEST_ENABLE 0 +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 1 +#define TCFG_APP_LINEIN_EN 1 +#define TCFG_APP_FM_EN 0 +#define TCFG_APP_PC_EN 0 +#define TCFG_APP_RTC_EN 0 +#define TCFG_APP_RECORD_EN 0 +#define TCFG_APP_SPDIF_EN 0 + +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +// #define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTA_05 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 2000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCFG_SW_I2C0_CLK_PORT IO_PORTA_09 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTA_10 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 4000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE DISABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE 0//ENABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'B' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE ENABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#include "usb_std_class_def.h" + + +#define TCFG_USB_PORT_CHARGE DISABLE + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DP_ONLY) + +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO + +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_LED_IO_REUSE DISABLE_THIS_MOUDLE //ADKEY 和 LED IO复用,led只能设置蓝灯显示 +#define TCFG_ADKEY_PORT IO_PORTA_10 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PA10 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 +*/ +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR + +/* +解码后音频的输出方式: + AUDIO_OUTPUT_ORIG_CH 按原始声道输出 + AUDIO_OUTPUT_STEREO 按立体声 + AUDIO_OUTPUT_L_CH 只输出原始声道的左声道 + AUDIO_OUTPUT_R_CH 只输出原始声道的右声道 + AUDIO_OUTPUT_MONO_LR_CH 输出左右合成的单声道 + */ + +#define AUDIO_OUTPUT_MODE AUDIO_OUTPUT_MONO_LR_CH + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_BT // AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC // LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +// 每个解码通道都开启数字音量管理 +#define SYS_DIGVOL_GROUP_EN DISABLE + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE ENABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE DISABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE 0//ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + + +#define TCFG_LED7_RUN_RAM DISABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) + +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +//EQ配置,使用在线EQ时,EQ文件和EQ模式无效。有EQ文件时,使能TCFG_USE_EQ_FILE,默认不用EQ模式切换功能 +#define TCFG_EQ_ENABLE 0 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 0 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 0 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 0 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 0 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 0 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 0 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 0 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 0 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 0 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 0 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 0 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 0 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 0 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 0 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif +//AudioEffects代码链接管理 +#define AUDIO_EFFECTS_DRC_AT_RAM 0 +#define AUDIO_EFFECTS_REVERB_AT_RAM 0 +#define AUDIO_EFFECTS_ECHO_AT_RAM 0 +#define AUDIO_EFFECTS_AFC_AT_RAM 1 +#define AUDIO_EFFECTS_EQ_AT_RAM 1 +#define AUDIO_EFFECTS_NOISEGATE_AT_RAM 0 +#define AUDIO_EFFECTS_MIC_EFFECT_AT_RAM 0 +#define AUDIO_EFFECTS_MIC_STREAM_AT_RAM 0 +#define AUDIO_EFFECTS_DEBUG_AT_RAM 0 +/**********************************************************************************/ + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif + +#endif +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 0 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 4000//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + + +//*********************************************************************************// +// AI配置 // +//*********************************************************************************// + +// #define CONFIG_APP_BT_ENABLE // AI功能、流程总开关 +#define CONFIG_TIDY_CODE_DEBUG //工程整理代码导致编译不过,加一下调试代码让工程编译通过 + + +#ifdef CONFIG_APP_BT_ENABLE +#define TRANS_DATA_EN 0 +#define SMART_BOX_EN 0 +#define TUYA_DEMO_EN 0 +#define TRANS_MULTI_BLE_EN 1//蓝牙BLE多机使能 +#define TUYA_MULTI_BLE_EN 0//TUYA BLE多机使能 +#define AI_APP_PROTOCOL 0 +#else +#define TRANS_DATA_EN 0 +#define SMART_BOX_EN 0 +#define TUYA_DEMO_EN 0 +#define TRANS_MULTI_BLE_EN 0 +#define TUYA_MULTI_BLE_EN 0//TUYA BLE多机使能 +#define AI_APP_PROTOCOL 0 +#endif + +//蓝牙BLE多连接 +#if TRANS_MULTI_BLE_EN //蓝牙BLE多连:1主1从,或者2主 +#define LE_DEBUG_PRINT_EN 1 +#define TRANS_MULTI_BLE_TEST_CLIENT 0 +#define TRANS_MULTI_BLE_SLAVE_NUMS 1 //range(0~1) +#define TRANS_MULTI_BLE_MASTER_NUMS 1 //range(0~2) +#endif + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 1 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 1 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 0 +#define USER_SUPPORT_PROFILE_PNP 0 +#define USER_SUPPORT_PROFILE_PBAP 0 +#define USER_SUPPORT_PROFILE_HFP_AG 1 + + +#if TCFG_USER_EMITTER_ENABLE +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 +#else +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 +#endif + + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#else +#if USER_SUPPORT_DUAL_A2DP_SOURCE +#define TCFG_BD_NUM 2 //连接设备个数配置 +#else +#define TCFG_BD_NUM 2 //连接设备个数配置 +#endif +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 0 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 1 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN DISABLE//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE DISABLE//音乐播放录音区分使能 + + +#if RECORDER_MIX_EN//限制不能同时打开 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE +#endif + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN2_LR +#define TCFG_LINEIN_CHECK_PORT NO_CONFIG_PORT // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd口 + +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE ENABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE DISABLE +#define TCFG_DEC_WAV_ENABLE DISABLE +#define TCFG_DEC_FLAC_ENABLE DISABLE +#define TCFG_DEC_APE_ENABLE DISABLE +#define TCFG_DEC_M4A_ENABLE DISABLE +#define TCFG_DEC_ALAC_ENABLE DISABLE +#define TCFG_DEC_AMR_ENABLE DISABLE +#define TCFG_DEC_DTS_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE ENABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE +#define TCFG_FM_BK1080_ENABLE DISABLE +#define TCFG_FM_QN8035_ENABLE DISABLE + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE) +#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE))) +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#else +#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif +#else +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/ + +#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE) +#undef TCFG_LED7_RUN_RAM +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/ + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE // +#define TCFG_IIS_OUTPUT_EN ENABLE // +#define TCFG_IIS_OUTPUT_PORT ALINK1_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL (BIT(0)) + +#define TCFG_IIS_INPUT_EN DISABLE// +#define TCFG_IIS_INPUT_PORT ALINK1_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR (44100l) +#define TCFG_IIS_INPUT_DATAPORT_SEL (BIT(0)) + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE ENABLE +#define TCFG_ENC_MSBC_ENABLE ENABLE +#define TCFG_ENC_G726_ENABLE DISABLE +#define TCFG_ENC_MP3_ENABLE DISABLE +#define TCFG_ENC_ADPCM_ENABLE DISABLE +#define TCFG_ENC_PCM_ENABLE DISABLE +#define TCFG_ENC_SBC_ENABLE ENABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + +//*********************************************************************************// +//ali ai profile +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 0 //not surport +#define ANCS_CLIENT_EN 0 + +#if (DUEROS_DMA_EN || TRANS_DATA_EN || ANCS_CLIENT_EN) +#define BT_FOR_APP_EN 1 +#else +#define BT_FOR_APP_EN 0 +#endif + +//*********************************************************************************// + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + + + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC695X_DEMO +#endif //CONFIG_BOARD_AC695X_DEMO_CFG_H diff --git a/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/adkey_table.c new file mode 100644 index 0000000..071e32b --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/adkey_table.c @@ -0,0 +1,356 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_BTEMITTER +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_BT_EMITTER_RECEIVER_SW, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_HCI_DISCONNECT_CLEAR_VM, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_TEST, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_TEST_4, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_TEST_3, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_TEST_2, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_BT_EMITTER_RECEIVER_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_UP, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_DOWN, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_MUSIC_CHANGE_REPEAT, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_MUSIC_FR, KEY_MUSIC_FR, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_MUSIC_FF, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/iokey_table.c new file mode 100644 index 0000000..97005eb --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/iokey_table.c @@ -0,0 +1,239 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_BTEMITTER +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/irkey_table.c new file mode 100644 index 0000000..da0cd42 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_BTEMITTER +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/rdec_key_table.c new file mode 100644 index 0000000..17c81e8 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_BTEMITTER +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/touch_key_table.c new file mode 100644 index 0000000..017c155 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_BTEMITTER +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_charging_bin/board_ac695x_charging_bin.c b/apps/soundbox/board/br23/board_ac695x_charging_bin/board_ac695x_charging_bin.c new file mode 100644 index 0000000..39d5bfc --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_charging_bin/board_ac695x_charging_bin.c @@ -0,0 +1,1095 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC695X_CHARGING_BIN + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "asm/spi.h" +#include "norflash.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "asm/ctmu.h" +#include "asm/power/p33.h" +#include "ui_manage.h" +#include "chargeIc_manage.h" +#include "chgbox_det.h" +#include "ic_self.h" +#include "chgbox_ctrl.h" +#include "chgbox_wireless.h" +#include "chgbox_handshake.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + /* { */ + /* .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, */ + /* .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, */ + /* .key_value = 1, */ + /* }, */ + /* */ + /* { */ + /* .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, */ + /* .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, */ + /* .key_value = 2, */ + /* }, */ +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .press_cfg = TCFG_CTMU_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, +#if TCFG_SD1_ENABLE + .pin_cfg.pin7.pin[0] = IO_PORTA_02, + .pin_cfg.pin7.pin[1] = IO_PORTA_03, + .pin_cfg.pin7.pin[2] = IO_PORTA_04, + .pin_cfg.pin7.pin[3] = IO_PORTA_06, + .pin_cfg.pin7.pin[4] = IO_PORTA_07, + .pin_cfg.pin7.pin[5] = IO_PORTA_08, + .pin_cfg.pin7.pin[6] = IO_PORTA_09, +#else + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if 0 +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; + + +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif +#if TCFG_NORFLASH_DEV_ENABLE + { "norflash", &norflash_dev_ops , (void *)&norflash_dev_data}, + { "nor_tone", &norflash_dev_ops , (void *)&norflash_dev_data}, +#if TCFG_NOR_FS_ENABLE + {"nor_fs", &norflash_dev_ops , (void *)&norflash_dev_data}, +#endif +#endif + +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup usbin_det_port = { + .pullup_down_enable = DISABLE, //配置I/O 内部上下拉是否使能 + .edge = RISING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTA_06, //唤醒口选择 +}; + +struct port_wakeup hall_det_port = { + .pullup_down_enable = DISABLE, //配置I/O 内部上下拉是否使能 + .edge = RISING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTB_00, //唤醒口选择 +}; + +struct port_wakeup key_port = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTB_01, //唤醒口选择 +}; + +#if WIRELESS_ENABLE +struct port_wakeup wl_det_port = { + .pullup_down_enable = DISABLE, //配置I/O 内部上下拉是否使能 + .edge = RISING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTB_08, //唤醒口选择 +}; +#endif + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +struct wakeup_param wk_param = { + .port[1] = &usbin_det_port, + .port[2] = &hall_det_port, + .port[3] = &key_port, +#if (WIRELESS_ENABLE) + .port[4] = &wl_det_port, +#endif + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +/************************** CHARGE config ****************************/ +#if(TCFG_CHARGE_BOX_ENABLE) +const struct chargeIc_platform_data chargeIc_data = { + .iic = 0, + .chargeIc_name = "IC_SELF", +}; + +const struct io_det_platform_data hall_det_data = { + .port = TCFG_HALL_PORT, + .level = TCFG_HALL_OPEN_STATUS, + .online_time = 10, + .offline_time = 30, + }; + +#endif + + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_TOUCH_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + key_driver_init(); +#endif + +#if TCFG_NORFLASH_DEV_ENABLE + extern u32 init_norsdfile_hdl(void); + init_norsdfile_hdl(); +#endif + + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + +#if 0 /* SPI 屏幕驱动测试 */ + log_info("test tft>>>>>>>\n"); + extern void SPI_LcdTest(); + SPI_LcdTest(); + log_info("test tft over\n"); +#endif + +#if TCFG_NOR_FS_ENABLE + extern int nor_fs_ops_init(void); + nor_fs_ops_init(); +#endif + + dev_manager_init(); + + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + //针对硅mic要输出1给mic供电 + if(!adc_data.mic_capless){ + gpio_set_pull_up(IO_PORTA_04, 0); + gpio_set_pull_down(IO_PORTA_04, 0); + gpio_set_direction(IO_PORTA_04, 0); + gpio_set_output_value(IO_PORTA_04,1); + } + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +#if USER_UART_UPDATE_ENABLE + { +#include "uart_update.h" + uart_update_cfg update_cfg = { + .rx = IO_PORTA_02, + .tx = IO_PORTA_03, + .output_channel = CH1_UT1_TX, + .input_channel = INPUT_CH0 + }; + uart_update_init(&update_cfg); + } +#endif + +} + +//根据需要进入休眠时设置相关的IO +void chgbox_enter_soft_power_off(void) +{ + u32 tt = 0; + log_info("enter chgbox soft power off set\n"); + ///唤醒口的重设置 + if(gpio_read(USB_ONLE_DET_IO) && sys_info.status[USB_DET]==STATUS_ONLINE){ + usbin_det_port.edge = FALLING_EDGE; + }else if(!gpio_read(USB_ONLE_DET_IO) && sys_info.status[USB_DET]==STATUS_OFFLINE){ + usbin_det_port.edge = RISING_EDGE; + } + + if(gpio_read(TCFG_HALL_PORT) && sys_info.status[LID_DET]==STATUS_ONLINE){ + hall_det_port.edge = FALLING_EDGE; + }else if(!gpio_read(TCFG_HALL_PORT) && sys_info.status[LID_DET]==STATUS_OFFLINE){ + hall_det_port.edge = RISING_EDGE; + } + +#if(WIRELESS_ENABLE) + if(gpio_read(WL_AD_DET_IO) && sys_info.status[WIRELESS_DET]==STATUS_ONLINE){ + //当前无线充在线,关掉无线充的唤醒,免一直被唤醒 + wk_param.port[4] = NULL; +#if(DCDC_CTRL_EN==0)//无dcdcen,要关掉usb 唤醒,避免一直唤醒 + wk_param.port[1] = NULL; +#endif + } +#endif + + + //重新初始化唤醒口 + reset_the_wakeup_param(&wk_param); + + //进入soft poweroff + power_set_soft_poweroff(); +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + +#if TCFG_CHARGE_BOX_SOFT_POWER_OFF_IO_CTRL_ENABLE + ////需要设置的IO + gpio_set_pull_down(BOOST_CTRL_IO, 1);//5v升压en要低,开下拉 + + gpio_set_pull_down(VOL_CTRL_IO, 1);//power lr en 要低,开下拉 + + gpio_set_pull_down(VOR_CTRL_IO, 1);//power lr en 要低,开下拉 + + gpio_set_output_value(CHGBOX_HANDSHAKE_IO,1); //握手需要拉高 + +#if(WIRELESS_ENABLE && DCDC_CTRL_EN) + gpio_set_output_value(DCDC_EN_IO,0); //dcdc en 需要关闭 +#endif + +#endif + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif//CONFIG_BOARD_AC695X_CHARGING_BIN diff --git a/apps/soundbox/board/br23/board_ac695x_charging_bin/board_ac695x_charging_bin.h b/apps/soundbox/board/br23/board_ac695x_charging_bin/board_ac695x_charging_bin.h new file mode 100644 index 0000000..c3b3bdd --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_charging_bin/board_ac695x_charging_bin.h @@ -0,0 +1,985 @@ +#ifndef CONFIG_BOARD_AC695X_CHARGING_BIN_H +#define CONFIG_BOARD_AC695X_CHARGING_BIN_H + +#ifdef CONFIG_BOARD_AC695X_CHARGING_BIN + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + + +#define NO_CONFIG_PORT (-1) + + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 0 +#define TCFG_APP_LINEIN_EN 0 +#define TCFG_APP_FM_EN 0 +#define TCFG_APP_PC_EN 0 +#define TCFG_APP_RTC_EN 0 +#define TCFG_APP_RECORD_EN 0 +#define TCFG_APP_SPDIF_EN 0 + + + +//*********************************************************************************// +// undef or redef // +//*********************************************************************************// +#ifdef TCFG_MIXER_EXT_ENABLE + +#undef TCFG_MIXER_EXT_ENABLE +#define TCFG_MIXER_EXT_ENABLE 1 + +#define MIX_OUTPUT_DUAL_TO_QUAD_POINTS 512 + +#define MIX_OUTPUT_DUAL_TO_QUAD_TYPE_COPY_ONLY 0 +#define MIX_OUTPUT_DUAL_TO_QUAD_TYPE_MAINFLFR_EXT0RLRR 1 +#define MIX_OUTPUT_DUAL_TO_QUAD_TYPE_MAINRLRR_EXT0FLFR 2 +#define MIX_OUTPUT_DUAL_TO_QUAD_TYPE (MIX_OUTPUT_DUAL_TO_QUAD_TYPE_COPY_ONLY) + +#endif//TCFG_MIXER_EXT_ENABLE + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 +#define LINEIN_INPUT_WAY_DAC 2 + +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTC_01 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCFG_SW_I2C0_CLK_PORT IO_PORTA_09 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTA_10 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 2000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE DISABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define TCFG_SD0_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE DISABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#include "usb_std_class_def.h" + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE/*|TCFG_OTG_MODE_CHARGE*/|OTG_DET_DP_ONLY) +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE ENABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_PORT IO_PORTA_10 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PA10 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTA_00 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTA_01 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: +DAC_OUTPUT_LR 立体声 +DAC_OUTPUT_FRONT_LR_REAR_LR 四声道输出 +*/ +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC //LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +// 每个解码通道都开启数字音量管理 +#define SYS_DIGVOL_GROUP_EN DISABLE + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//*********************************************************************************// +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 + +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE DISABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + +#define TCFG_LED7_RUN_RAM DISABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) + +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0// SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 0 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 0 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 0 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 0 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 0 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 0 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 0 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 0 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 0 //DRC总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 0 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 0 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 0 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 0 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 0 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 0 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif + +#endif +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 0 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 3700//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 0 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 1 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + +//*********************************************************************************// +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR +#define TCFG_LINEIN_CHECK_PORT IO_PORTB_03 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd口 + +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE 1//DISABLE +#define TCFG_DEC_MP3_ENABLE DISABLE +#define TCFG_DEC_WMA_ENABLE DISABLE +#define TCFG_DEC_WAV_ENABLE DISABLE +#define TCFG_DEC_FLAC_ENABLE 0//ENABLE +#define TCFG_DEC_APE_ENABLE 0//ENABLE +#define TCFG_DEC_M4A_ENABLE DISABLE +#define TCFG_DEC_ALAC_ENABLE DISABLE +#define TCFG_DEC_AMR_ENABLE DISABLE +#define TCFG_DEC_DTS_ENABLE 0//ENABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE ENABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE +#define TCFG_FM_BK1080_ENABLE DISABLE +#define TCFG_FM_QN8035_ENABLE DISABLE + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE // +#define TCFG_IIS_OUTPUT_EN ENABLE // +#define TCFG_IIS_OUTPUT_PORT ALINK1_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL (BIT(0)) + +#define TCFG_IIS_INPUT_EN DISABLE// +#define TCFG_IIS_INPUT_PORT ALINK1_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR (44100l) +#define TCFG_IIS_INPUT_DATAPORT_SEL (BIT(0)) + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE DISABLE + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FS_ENABLE 0//ENABLE +#else +#define TCFG_NOR_FS_ENABLE 0 +#endif + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define TCFG_LINEIN_REC_EN DISABLE +#define TCFG_MIXERCH_REC_EN DISABLE +#define TCFG_MIC_REC_PITCH_EN DISABLE +#define TCFG_MIC_REC_REVERB_EN DISABLE + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE DISABLE +#define TCFG_ENC_MSBC_ENABLE DISABLE +#define TCFG_ENC_G726_ENABLE DISABLE +#define TCFG_ENC_MP3_ENABLE DISABLE +#define TCFG_ENC_ADPCM_ENABLE DISABLE +#define TCFG_ENC_PCM_ENABLE DISABLE +#define TCFG_ENC_SBC_ENABLE DISABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + + +//*********************************************************************************// + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度 + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + + +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 充电盒配置 // +//*********************************************************************************// +//是否支持充电盒(作为盒子使用) +#define TCFG_CHARGE_BOX_ENABLE 1//DISABLE_THIS_MOUDLE + +#if(TCFG_CHARGE_BOX_ENABLE) +#define WIRELESS_ENABLE ENABLE_THIS_MOUDLE //是否支持无线充 +#define TCFG_CHARGE_BOX_SOFT_POWER_OFF_IO_CTRL_ENABLE ENABLE_THIS_MOUDLE //一些外设(如某些升压芯片)休眠时需要设置上下拉来维持关闭态 +#else +#define WIRELESS_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_CHARGE_BOX_SOFT_POWER_OFF_IO_CTRL_ENABLE DISABLE_THIS_MOUDLE +#endif + +#define TCFG_HALL_OPEN_STATUS 1 //开盖时电平(1高电平 0低电平) +#define TCFG_HALL_PORT IO_PORTB_00 //hall 传感器的IO + +///注意out/inputchannel 冲突问题 +#define TCFG_CHARGEBOX_L_PORT IO_PORTB_05 //充电盒和左耳通信的IO口需要为高压IO +#define TCFG_CHARGEBOX_R_PORT IO_PORTB_02 //充电盒和右耳通信的IO口需要为高压IO + +//如果使用iic与充电IC通信 +#define TCFG_CHARGE_IC_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +#define TCFG_CHARGGBOX_AUTO_SHUT_DOWN_TIME 8 //充电仓自动休眠时间 单位秒 + + +//*********************************************************************************// +// AI配置 // +//*********************************************************************************// +#define CONFIG_APP_BT_ENABLE // AI功能、流程总开关 + +#ifdef CONFIG_APP_BT_ENABLE +#define TRANS_DATA_EN 0 +#define SMART_BOX_EN 1 +#else +#define TRANS_DATA_EN 0 +#define SMART_BOX_EN 0 +#endif + + +#if (SMART_BOX_EN) +#undef JL_SMART_BOX_CUSTOM_APP_EN +#define JL_SMART_BOX_CUSTOM_APP_EN + +#undef TCFG_USER_BLE_ENABLE +#define TCFG_USER_BLE_ENABLE 1 + +#undef TCFG_USER_BT_CLASSIC_ENABLE +#define TCFG_USER_BT_CLASSIC_ENABLE 0 + +// #undef TCFG_USER_EMITTER_ENABLE +// #define TCFG_USER_EMITTER_ENABLE 1 + +#define MUTIl_CHARGING_BOX_EN 1 +#endif + + +#ifdef JL_SMART_BOX_CUSTOM_APP_EN +#define SMARTBOX_SPP_INTERACTIVE_SUPPORT 0 +#define SMARTBOX_BLE_INTERACTIVE_SUPPORT 1 + +#define RCSP_USE_BLE 0 +#define RCSP_USE_SPP 1 +#define RCSP_CHANNEL_SEL RCSP_USE_BLE + +#define RCSP_ADV_NAME_SET_ENABLE 0 +#define RCSP_ADV_KEY_SET_ENABLE 0 +#define RCSP_ADV_LED_SET_ENABLE 0 +#define RCSP_ADV_MIC_SET_ENABLE 0 +#define RCSP_ADV_WORK_SET_ENABLE 0 +#define RCSP_ADV_EQ_SET_ENABLE 0 +#define RCSP_ADV_MUSIC_INFO_ENABLE 0 +#define RCSP_ADV_HIGH_LOW_SET 0 +#define RCSP_ADV_PRODUCT_MSG_ENABLE 0 +#define RCSP_ADV_FIND_DEVICE_ENABLE 0 +#define RCSP_ADV_COLOR_LED_SET_ENABLE 0 +#endif +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if(TRANS_DATA_EN && DUEROS_DMA_EN) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + + +#endif //CONFIG_BOARD_AC695X_CHARGING_BIN +#endif //CONFIG_BOARD_AC695X_CHARGING_BIN_H diff --git a/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/adkey_table.c new file mode 100644 index 0000000..378667f --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/adkey_table.c @@ -0,0 +1,353 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_CHARGING_BIN +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_CHANGE_REPEAT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_NULL, KEY_MUSIC_FR, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/iokey_table.c new file mode 100644 index 0000000..465daa0 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/iokey_table.c @@ -0,0 +1,239 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_CHARGING_BIN +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/irkey_table.c new file mode 100644 index 0000000..575c192 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_CHARGING_BIN +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/rdec_key_table.c new file mode 100644 index 0000000..ebb6b1b --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_CHARGING_BIN +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/touch_key_table.c new file mode 100644 index 0000000..4b0aa9b --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_CHARGING_BIN +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_cvp_develop/board_ac695x_cvp_develop.c b/apps/soundbox/board/br23/board_ac695x_cvp_develop/board_ac695x_cvp_develop.c new file mode 100644 index 0000000..1a340c4 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_cvp_develop/board_ac695x_cvp_develop.c @@ -0,0 +1,1157 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC695X_CVP_DEVELOP + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "fm/fm_manage.h" +#include "asm/power/p33.h" +#include "norflash.h" +#include "asm/spi.h" +#include "ui_manage.h" +#include "spi/nor_fs.h" +#include "nandflash.h" +#include "audio_link.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +#if TCFG_IIS_ENABLE +ALINK_PARM alink0_param = { + .port_select = ALINK0_PORTA, //MCLK:PA8 SCLK:PA2 LRCK:PA3 CH0:PA4 CH1:PA5 CH2:PA6 CH3:PA7 + /* .port_select = ALINK0_PORTB, //MCLK:PA15 SCLK:PA9 LRCK:PA10 CH0:PA11 CH1:PA12 CH2:PA13 CH3:PA14 */ + /* .port_select = ALINK1_PORTA, //MCLK:PB0 SCLK:PC0 LRCK:PC1 CH0:PC2 CH1:PC3 CH2:PC4 CH3:PC5 */ + .ch_cfg[0].enable = 1, + .ch_cfg[1].enable = 1, + .mode = ALINK_MD_IIS, +#if TCFG_IIS_MODE + .role = ALINK_ROLE_SLAVE, +#else + .role = ALINK_ROLE_MASTER, +#endif + .clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE, + .bitwide = ALINK_LEN_16BIT, + .sclk_per_frame = ALINK_FRAME_64SCLK, + .dma_len = ALNK_BUF_POINTS_NUM * 2 * 2 * 2, + .sample_rate = TCFG_IIS_OUTPUT_SR, +}; + +ALINK_PARM alink1_param = { + /* .port_select = ALINK0_PORTA, //MCLK:PA8 SCLK:PA2 LRCK:PA3 CH0:PA4 CH1:PA5 CH2:PA6 CH3:PA7 */ + /* .port_select = ALINK0_PORTB, //MCLK:PA15 SCLK:PA9 LRCK:PA10 CH0:PA11 CH1:PA12 CH2:PA13 CH3:PA14 */ + .port_select = ALINK1_PORTA, //MCLK:PB0 SCLK:PC0 LRCK:PC1 CH0:PC2 CH1:PC3 CH2:PC4 CH3:PC5 + .ch_cfg[0].enable = 1, + .ch_cfg[1].enable = 1, + .mode = ALINK_MD_IIS, +#if TCFG_IIS_MODE + .role = ALINK_ROLE_SLAVE, +#else + .role = ALINK_ROLE_MASTER, +#endif + .clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE, + .bitwide = ALINK_LEN_16BIT, + .sclk_per_frame = ALINK_FRAME_64SCLK, + .dma_len = ALNK_BUF_POINTS_NUM * 2 * 2 * 2, + .sample_rate = TCFG_IIS_OUTPUT_SR, +}; + + +#endif + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, + .key_value = 2, + }, +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, +#if TCFG_SD1_ENABLE + .pin_cfg.pin7.pin[0] = IO_PORTA_02, + .pin_cfg.pin7.pin[1] = IO_PORTA_03, + .pin_cfg.pin7.pin[2] = IO_PORTA_04, + .pin_cfg.pin7.pin[3] = IO_PORTA_06, + .pin_cfg.pin7.pin[4] = IO_PORTA_07, + .pin_cfg.pin7.pin[5] = IO_PORTA_08, + .pin_cfg.pin7.pin[6] = IO_PORTA_09, +#else + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if 0 +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; + + +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NANDFLASH_DEV_ENABLE +NANDFLASH_DEV_PLATFORM_DATA_BEGIN(nandflash_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, + .start_addr = 0, + .size = 0, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif +NANDFLASH_DEV_PLATFORM_DATA_END() +#endif + + +#if TCFG_NOR_FAT +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 0, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_FS +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 1*1024*1024, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_REC +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 2*1024*1024, + .size = 2*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_FM_ENABLE + +FM_DEV_PLATFORM_DATA_BEGIN(fm_dev_data) + .iic_hdl = 0, + .iic_delay = 50, +FM_DEV_PLATFORM_DATA_END(); + +#endif + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +#if TCFG_NOR_FAT + { "fat_nor", &norflash_dev_ops , (void *)&norflash_fat_dev_data}, +#endif + +#if TCFG_NOR_FS + { "res_nor", &norfs_dev_ops , (void *)&norflash_norfs_dev_data}, +#endif + +#if TCFG_NOR_REC + {"rec_nor", &norfs_dev_ops , (void *)&norflash_norfs_rec_dev_data}, +#endif +#endif + +#if TCFG_NANDFLASH_DEV_ENABLE + {"nand_flash", &nandflash_dev_ops , (void *)&nandflash_dev_data}, +#endif + + +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , + +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif + +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTA_10, //唤醒口选择 +}; + +/* RTC PR0 PR1 唤醒 */ +/* struct port_wakeup rtc_port0 = { */ + /* .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 */ + /* .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 */ + /* .attribute = BLUETOOTH_RESUME, //保留参数 */ + /* .iomap = IO_PORT_PR_00, //唤醒口选择 */ +/* }; */ + +/* struct port_wakeup rtc_port1 = { */ + /* .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 */ + /* .edge = RISING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 */ + /* .attribute = BLUETOOTH_RESUME, //保留参数 */ + /* .iomap = IO_PORT_PR_01, //唤醒口选择 */ +/* }; */ + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + /* .rtc_port[0] = &rtc_port0, */ + /* .rtc_port[1] = &rtc_port1, */ + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} +static void key_wakeup_disable() +{ + power_wakeup_index_disable(1); +} +static void key_wakeup_enable() +{ + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + +#if TCFG_FM_ENABLE + fm_dev_init(&fm_dev_data); +#endif + +#if TCFG_NOR_REC + nor_fs_ops_init(); +#endif + +#if TCFG_NOR_FS + init_norsdfile_hdl(); +#endif + +#if FLASH_INSIDE_REC_ENABLE + sdfile_rec_ops_init(); +#endif + + dev_manager_init(); + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + //针对硅mic要输出1给mic供电(按实际使用情况配置) + /* if(!adc_data.mic_capless){ */ + /* gpio_set_pull_up(IO_PORTA_04, 0); */ + /* gpio_set_pull_down(IO_PORTA_04, 0); */ + /* gpio_set_direction(IO_PORTA_04, 0); */ + /* gpio_set_output_value(IO_PORTA_04,1); */ + /* } */ + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +#if USER_UART_UPDATE_ENABLE + { +#include "uart_update.h" + uart_update_cfg update_cfg = { + .rx = IO_PORTA_02, + .tx = IO_PORTA_03, + .output_channel = CH1_UT1_TX, + .input_channel = INPUT_CH0 + }; + uart_update_init(&update_cfg); + } +#endif +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + key_wakeup_enable(); + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); + key_wakeup_disable(); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + key_wakeup_enable(); + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); + key_wakeup_disable(); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_cvp_develop/board_ac695x_cvp_develop_cfg.h b/apps/soundbox/board/br23/board_ac695x_cvp_develop/board_ac695x_cvp_develop_cfg.h new file mode 100644 index 0000000..6582d7b --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_cvp_develop/board_ac695x_cvp_develop_cfg.h @@ -0,0 +1,1005 @@ +#ifndef CONFIG_BOARD_AC695X_CVP_DEVELOP_CFG_H +#define CONFIG_BOARD_AC695X_CVP_DEVELOP_CFG_H + +#ifdef CONFIG_BOARD_AC695X_CVP_DEVELOP + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 +#define LINEIN_INPUT_WAY_DAC 2 + +#define NO_CONFIG_PORT (-1) + + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 1 +#define TCFG_APP_LINEIN_EN 1 +#define TCFG_APP_FM_EN 0 +#define TCFG_APP_PC_EN 0 +#define TCFG_APP_RTC_EN 1 +#define TCFG_APP_RECORD_EN 1 +#define TCFG_APP_SPDIF_EN 0 +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTA_05 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCFG_SW_I2C0_CLK_PORT IO_PORTA_09 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTA_10 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 4000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_NANDFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE ENABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE ENABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#include "usb_std_class_def.h" + +#define TCFG_VIR_UDISK_ENABLE 1//ENABLE_THIS_MOUDLE + +#define TCFG_USB_PORT_CHARGE DISABLE + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE + +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DP_ONLY) + +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 + +#define TCFG_KEY_TONE_EN 0//ENABLE // 按键提示音。建议音频输出使用固定采样率 + +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO + +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_LED_IO_REUSE DISABLE_THIS_MOUDLE //ADKEY 和 LED IO复用,led只能设置蓝灯显示 +#define TCFG_ADKEY_PORT IO_PORTA_10 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PA10 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTA_00 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTA_01 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +//第三方清晰语音开发使能 +#define TCFG_CVP_DEVELOP_ENABLE 1//ENABLE_THIS_MOUDLE + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 + DAC_OUTPUT_FRONT_LR_REAR_LR 四声道输出 +*/ +//#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC //LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define VOL_TYPE_DIGGROUP 4 //独立通道数字音量 + +//每个解码通道都开启数字音量管理,音量类型为VOL_TYPE_DIGGROUP时要使能 +#define SYS_DIGVOL_GROUP_EN DISABLE + +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE ENABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE ENABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + +#define TCFG_LED7_RUN_RAM DISABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) + +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 1 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 1 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 1 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 1 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 1 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 1 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 1 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 1 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 1 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc + +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 1 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 1 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 1 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 1 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 1 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 1 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif + +#endif +/**********************************************************************************/ +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 1 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 0//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +#define TCFG_AUDIO_DEC_OUT_TASK 0 // 解码使用单独任务做输出 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 0 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 1 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + +/*在线调试,需要打开SPP和在线调试功能*/ +#define APP_ONLINE_DEBUG 0 + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN DISABLE//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE DISABLE//音乐播放录音区分使能 + + +#if RECORDER_MIX_EN//限制不能同时打开 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE +#endif + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR +#define TCFG_LINEIN_CHECK_PORT IO_PORTB_03 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd口 + +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE ENABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE ENABLE +#define TCFG_DEC_WAV_ENABLE DISABLE +#define TCFG_DEC_FLAC_ENABLE DISABLE +#define TCFG_DEC_APE_ENABLE DISABLE +#define TCFG_DEC_M4A_ENABLE DISABLE +#define TCFG_DEC_ALAC_ENABLE DISABLE +#define TCFG_DEC_AMR_ENABLE DISABLE +#define TCFG_DEC_DTS_ENABLE DISABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE ENABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE +#define TCFG_FM_BK1080_ENABLE DISABLE +#define TCFG_FM_QN8035_ENABLE DISABLE + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE) +#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE))) +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#else +#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif +#else +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/ + +#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE) +#undef TCFG_LED7_RUN_RAM +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/ + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) || (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC_IIS) +#define TCFG_IIS_ENABLE ENABLE_THIS_MOUDLE +#else +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE +#endif + +#define TCFG_IIS_MODE (0) // 0:master 1:slave + +#define TCFG_IIS_OUTPUT_EN (ENABLE && TCFG_IIS_ENABLE) +#define TCFG_IIS_OUTPUT_PORT ALINK0_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL 0 + +#define TCFG_IIS_INPUT_EN (DISABLE && TCFG_IIS_ENABLE) +#define TCFG_IIS_INPUT_PORT ALINK0_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR 44100 +#define TCFG_IIS_INPUT_DATAPORT_SEL 1 + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE ENABLE +#define TCFG_ENC_MSBC_ENABLE ENABLE +#define TCFG_ENC_G726_ENABLE ENABLE +#define TCFG_ENC_MP3_ENABLE ENABLE +#define TCFG_ENC_ADPCM_ENABLE ENABLE +#define TCFG_ENC_PCM_ENABLE ENABLE +#define TCFG_ENC_SBC_ENABLE ENABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + +//*********************************************************************************// +//ali ai profile +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 0 //not surport +#define ANCS_CLIENT_EN 0 + +#if (DUEROS_DMA_EN || TRANS_DATA_EN || ANCS_CLIENT_EN) +#define BT_FOR_APP_EN 1 +#else +#define BT_FOR_APP_EN 0 +#endif + +//*********************************************************************************// + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC695X_CVP_DEVELOP +#endif //CONFIG_BOARD_AC695X_CVP_DEVELOP_CFG_H diff --git a/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/adkey_table.c new file mode 100644 index 0000000..8c18051 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/adkey_table.c @@ -0,0 +1,356 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_CVP_DEVELOP +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_UP, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_DOWN, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_MUSIC_CHANGE_REPEAT, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_MUSIC_FR, KEY_MUSIC_FR, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_MUSIC_FF, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_PLAYER_AB_REPEAT_SWITCH, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/iokey_table.c new file mode 100644 index 0000000..964a935 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/iokey_table.c @@ -0,0 +1,248 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_CVP_DEVELOP +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/irkey_table.c new file mode 100644 index 0000000..70db42e --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_CVP_DEVELOP +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_IR_NUM_0, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_IR_NUM_1, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_IR_NUM_2, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_IR_NUM_3, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_IR_NUM_4, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_IR_NUM_5, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_IR_NUM_6, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_IR_NUM_7, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_IR_NUM_8, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_IR_NUM_9, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/rdec_key_table.c new file mode 100644 index 0000000..a942af9 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_CVP_DEVELOP +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/touch_key_table.c new file mode 100644 index 0000000..0198ee6 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_CVP_DEVELOP +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_demo/board_ac695x_demo.c b/apps/soundbox/board/br23/board_ac695x_demo/board_ac695x_demo.c new file mode 100644 index 0000000..c85ab67 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_demo/board_ac695x_demo.c @@ -0,0 +1,1158 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC695X_DEMO + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "fm/fm_manage.h" +#include "asm/power/p33.h" +#include "norflash.h" +#include "asm/spi.h" +#include "ui_manage.h" +#include "spi/nor_fs.h" +#include "nandflash.h" +#include "audio_link.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +#if TCFG_IIS_ENABLE +ALINK_PARM alink0_param = { + .port_select = ALINK0_PORTA, //MCLK:PA8 SCLK:PA2 LRCK:PA3 CH0:PA4 CH1:PA5 CH2:PA6 CH3:PA7 + /* .port_select = ALINK0_PORTB, //MCLK:PA15 SCLK:PA9 LRCK:PA10 CH0:PA11 CH1:PA12 CH2:PA13 CH3:PA14 */ + /* .port_select = ALINK1_PORTA, //MCLK:PB0 SCLK:PC0 LRCK:PC1 CH0:PC2 CH1:PC3 CH2:PC4 CH3:PC5 */ + .ch_cfg[0].enable = 1, + .ch_cfg[1].enable = 1, + .mode = ALINK_MD_IIS, +#if TCFG_IIS_MODE + .role = ALINK_ROLE_SLAVE, +#else + .role = ALINK_ROLE_MASTER, +#endif + .clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE, + .bitwide = ALINK_LEN_16BIT, + .sclk_per_frame = ALINK_FRAME_64SCLK, + .dma_len = ALNK_BUF_POINTS_NUM * 2 * 2 * 2, + .sample_rate = TCFG_IIS_OUTPUT_SR, +}; + +ALINK_PARM alink1_param = { + /* .port_select = ALINK0_PORTA, //MCLK:PA8 SCLK:PA2 LRCK:PA3 CH0:PA4 CH1:PA5 CH2:PA6 CH3:PA7 */ + /* .port_select = ALINK0_PORTB, //MCLK:PA15 SCLK:PA9 LRCK:PA10 CH0:PA11 CH1:PA12 CH2:PA13 CH3:PA14 */ + .port_select = ALINK1_PORTA, //MCLK:PB0 SCLK:PC0 LRCK:PC1 CH0:PC2 CH1:PC3 CH2:PC4 CH3:PC5 + .ch_cfg[0].enable = 1, + .ch_cfg[1].enable = 1, + .mode = ALINK_MD_IIS, +#if TCFG_IIS_MODE + .role = ALINK_ROLE_SLAVE, +#else + .role = ALINK_ROLE_MASTER, +#endif + .clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE, + .bitwide = ALINK_LEN_16BIT, + .sclk_per_frame = ALINK_FRAME_64SCLK, + .dma_len = ALNK_BUF_POINTS_NUM * 2 * 2 * 2, + .sample_rate = TCFG_IIS_OUTPUT_SR, +}; + + +#endif + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, + .key_value = 2, + }, +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, +#if TCFG_SD1_ENABLE + .pin_cfg.pin7.pin[0] = IO_PORTA_02, + .pin_cfg.pin7.pin[1] = IO_PORTA_03, + .pin_cfg.pin7.pin[2] = IO_PORTA_04, + .pin_cfg.pin7.pin[3] = IO_PORTA_06, + .pin_cfg.pin7.pin[4] = IO_PORTA_07, + .pin_cfg.pin7.pin[5] = IO_PORTA_08, + .pin_cfg.pin7.pin[6] = IO_PORTA_09, +#else + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if TCHFG_SOFT_I2C_ENABLE +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; +#endif + +#if TCHFG_HW_I2C_ENABLE +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NANDFLASH_DEV_ENABLE +NANDFLASH_DEV_PLATFORM_DATA_BEGIN(nandflash_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, + .start_addr = 0, + .size = 0, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif +NANDFLASH_DEV_PLATFORM_DATA_END() +#endif + + +#if TCFG_NOR_FAT +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 0, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_FS +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 1*1024*1024, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_REC +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 2*1024*1024, + .size = 2*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_FM_ENABLE + +FM_DEV_PLATFORM_DATA_BEGIN(fm_dev_data) + .iic_hdl = 0, + .iic_delay = 50, +FM_DEV_PLATFORM_DATA_END(); + +#endif + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +#if TCFG_NOR_FAT + { "fat_nor", &norflash_dev_ops , (void *)&norflash_fat_dev_data}, +#endif + +#if TCFG_NOR_FS + { "res_nor", &norfs_dev_ops , (void *)&norflash_norfs_dev_data}, +#endif + +#if TCFG_NOR_REC + {"rec_nor", &norfs_dev_ops , (void *)&norflash_norfs_rec_dev_data}, +#endif +#endif + +#if TCFG_NANDFLASH_DEV_ENABLE + {"nand_flash", &nandflash_dev_ops , (void *)&nandflash_dev_data}, +#endif + + +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , + +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif + +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTA_10, //唤醒口选择 +}; + +/* RTC PR0 PR1 唤醒 */ +/* struct port_wakeup rtc_port0 = { */ + /* .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 */ + /* .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 */ + /* .attribute = BLUETOOTH_RESUME, //保留参数 */ + /* .iomap = IO_PORT_PR_00, //唤醒口选择 */ +/* }; */ + +/* struct port_wakeup rtc_port1 = { */ + /* .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 */ + /* .edge = RISING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 */ + /* .attribute = BLUETOOTH_RESUME, //保留参数 */ + /* .iomap = IO_PORT_PR_01, //唤醒口选择 */ +/* }; */ + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + /* .rtc_port[0] = &rtc_port0, */ + /* .rtc_port[1] = &rtc_port1, */ + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} +static void key_wakeup_disable() +{ + power_wakeup_index_disable(1); +} +static void key_wakeup_enable() +{ + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + +#if TCFG_FM_ENABLE + fm_dev_init(&fm_dev_data); +#endif + +#if TCFG_NOR_REC + nor_fs_ops_init(); +#endif + +#if TCFG_NOR_FS + init_norsdfile_hdl(); +#endif + +#if FLASH_INSIDE_REC_ENABLE + sdfile_rec_ops_init(); +#endif + + dev_manager_init(); + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + //针对硅mic要输出1给mic供电(按实际使用情况配置) + /* if(!adc_data.mic_capless){ */ + /* gpio_set_pull_up(IO_PORTA_04, 0); */ + /* gpio_set_pull_down(IO_PORTA_04, 0); */ + /* gpio_set_direction(IO_PORTA_04, 0); */ + /* gpio_set_output_value(IO_PORTA_04,1); */ + /* } */ + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +#if USER_UART_UPDATE_ENABLE + { +#include "uart_update.h" + uart_update_cfg update_cfg = { + .rx = IO_PORTA_02, + .tx = IO_PORTA_03, + .output_channel = CH1_UT1_TX, + .input_channel = INPUT_CH0 + }; + uart_update_init(&update_cfg); + } +#endif +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + key_wakeup_enable(); + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); + key_wakeup_disable(); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + key_wakeup_enable(); + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); + key_wakeup_disable(); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_demo/board_ac695x_demo_cfg.h b/apps/soundbox/board/br23/board_ac695x_demo/board_ac695x_demo_cfg.h new file mode 100644 index 0000000..06954b5 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_demo/board_ac695x_demo_cfg.h @@ -0,0 +1,1059 @@ +#ifndef CONFIG_BOARD_AC695X_DEMO_CFG_H +#define CONFIG_BOARD_AC695X_DEMO_CFG_H + +#ifdef CONFIG_BOARD_AC695X_DEMO + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 +#define LINEIN_INPUT_WAY_DAC 2 + +#define NO_CONFIG_PORT (-1) + + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 1 +#define TCFG_APP_LINEIN_EN 1 +#define TCFG_APP_FM_EN 1 +#define TCFG_APP_PC_EN 1 +#define TCFG_APP_RTC_EN 0 +#define TCFG_APP_RECORD_EN 0 +#define TCFG_APP_SPDIF_EN 0 +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTA_05 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCHFG_SOFT_I2C_ENABLE DISABLE_THIS_MOUDLE //软件IIC使能 +#define TCFG_SW_I2C0_CLK_PORT IO_PORTB_00 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTB_03 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCHFG_HW_I2C_ENABLE DISABLE_THIS_MOUDLE //硬件IIC使能 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 4000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_NANDFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + +//*********************************************************************************// +// 设备异步读 配置 // +//*********************************************************************************// + +#define TCFG_DEVICE_BULK_READ_ASYNC_ENABLE + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE ENABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE ENABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#define TCFG_VIR_UDISK_ENABLE 0//ENABLE_THIS_MOUDLE + +#define TCFG_USB_PORT_CHARGE DISABLE + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE + +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DP_ONLY) + +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 + +#define TCFG_KEY_TONE_EN 0//ENABLE // 按键提示音。建议音频输出使用固定采样率 + +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO + +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_LED_IO_REUSE DISABLE_THIS_MOUDLE //ADKEY 和 LED IO复用,led只能设置蓝灯显示 +#define TCFG_ADKEY_PORT IO_PORTA_10 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PA10 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTA_00 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTA_01 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 + DAC_OUTPUT_FRONT_LR_REAR_LR 四声道输出 +*/ +//#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC //LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define VOL_TYPE_DIGGROUP 4 //独立通道数字音量 + +//每个解码通道都开启数字音量管理,音量类型为VOL_TYPE_DIGGROUP时要使能 +#define SYS_DIGVOL_GROUP_EN DISABLE + +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) + +//AudioEffects代码链接管理 +#define AUDIO_EFFECTS_DRC_AT_RAM 0 +#define AUDIO_EFFECTS_REVERB_AT_RAM 0 +#define AUDIO_EFFECTS_ECHO_AT_RAM 0 +#define AUDIO_EFFECTS_AFC_AT_RAM 1 +#define AUDIO_EFFECTS_EQ_AT_RAM 1 +#define AUDIO_EFFECTS_NOISEGATE_AT_RAM 0 +#define AUDIO_EFFECTS_MIC_EFFECT_AT_RAM 0 +#define AUDIO_EFFECTS_MIC_STREAM_AT_RAM 0 +#define AUDIO_EFFECTS_DEBUG_AT_RAM 0 + +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE ENABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE 0//ENABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE 0//ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + +#define TCFG_LED7_RUN_RAM DISABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) + +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 1 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 1 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 1 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 1 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 1 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 1 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 1 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 1 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后置EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 1 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc + +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 1 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 1 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 1 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 1 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 1 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 1 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后的drc +#endif//TCFG_DRC_ENABLE + +#define LINEIN_MODE_SOLE_EQ_EN 0 //linein模式是否需要独立的eq与drc + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + + +#define TCFG_MIC_VOICE_CHANGER_ENABLE DISABLE //变声模块使能 + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif + +#endif +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 1 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 4000//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +#define TCFG_AUDIO_DEC_OUT_TASK 0 // 解码使用单独任务做输出 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 1 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 1 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN DISABLE//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE DISABLE//音乐播放录音区分使能 + + +#if RECORDER_MIX_EN//限制不能同时打开 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE +#endif + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR +#define TCFG_LINEIN_CHECK_PORT IO_PORTB_03 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd口 +#define TCFG_LINEIN_DETECT_ENABLE 0 +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE ENABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE DISABLE +#define TCFG_DEC_WAV_ENABLE DISABLE +#define TCFG_DEC_FLAC_ENABLE DISABLE +#define TCFG_DEC_APE_ENABLE DISABLE +#define TCFG_DEC_M4A_ENABLE DISABLE +#define TCFG_DEC_ALAC_ENABLE DISABLE +#define TCFG_DEC_AMR_ENABLE DISABLE +#define TCFG_DEC_DTS_ENABLE DISABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE ENABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE //需要使能软件IIC模块 +#define TCFG_FM_BK1080_ENABLE DISABLE //需要使能软件IIC模块 +#define TCFG_FM_QN8035_ENABLE DISABLE //需要使能软件IIC模块 + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE) +#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE))) +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#else +#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif +#else +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/ + +#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE) +#undef TCFG_LED7_RUN_RAM +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/ + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) || (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC_IIS) +#define TCFG_IIS_ENABLE ENABLE_THIS_MOUDLE +#else +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE +#endif + +#define TCFG_IIS_MODE (0) // 0:master 1:slave + +#define TCFG_IIS_OUTPUT_EN (ENABLE && TCFG_IIS_ENABLE) +#define TCFG_IIS_OUTPUT_PORT ALINK0_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL 0 + +#define TCFG_IIS_INPUT_EN (DISABLE && TCFG_IIS_ENABLE) +#define TCFG_IIS_INPUT_PORT ALINK0_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR 44100 +#define TCFG_IIS_INPUT_DATAPORT_SEL 1 + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE ENABLE +#define TCFG_ENC_MSBC_ENABLE ENABLE +#define TCFG_ENC_G726_ENABLE DISABLE +#define TCFG_ENC_MP3_ENABLE DISABLE +#define TCFG_ENC_ADPCM_ENABLE DISABLE +#define TCFG_ENC_PCM_ENABLE ENABLE +#define TCFG_ENC_SBC_ENABLE ENABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + +//*********************************************************************************// +//ali ai profile +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 0 //not surport +#define ANCS_CLIENT_EN 0 + +#if (DUEROS_DMA_EN || TRANS_DATA_EN || ANCS_CLIENT_EN) +#define BT_FOR_APP_EN 1 +#else +#define BT_FOR_APP_EN 0 +#endif + +//*********************************************************************************// + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 + +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 2.X声道配置(需使能板极四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR) +// 2.1 两个全频较弱的全频音箱 + 一个低音炮 +// 2.2 两个全频较弱的全频音箱 + 2个低音炮 +//*********************************************************************************// +#define SOUND_TRACK_2_P_X_CH_CONFIG 0 //2.X声道总使能 + +#if SOUND_TRACK_2_P_X_CH_CONFIG +#define TWO_POINT_ONE_CH BIT(0) //2.1声道 +#define TWO_POINT_TWO_CH BIT(1) //2.2声道 +#define TWO_POINT_X_CH TWO_POINT_ONE_CH//选配使用2.1 还是2.2 声道 + +#if (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#undef TCFG_AUDIO_DAC_CONNECT_MODE +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#endif +#endif/*SOUND_TRACK_2_P_X_CH_CONFIG*/ + + + + + + +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +// #error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif +#if ((TCFG_MIC_EFFECT_ENABLE) && (TCFG_USER_TWS_ENABLE)&&(TCFG_DEC_M4A_ENABLE)) +#error "TWS+混响 暂不支持M4A解码" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif + +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC695X_DEMO +#endif //CONFIG_BOARD_AC695X_DEMO_CFG_H diff --git a/apps/soundbox/board/br23/board_ac695x_demo/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac695x_demo/key_table/adkey_table.c new file mode 100644 index 0000000..7b0f7aa --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_demo/key_table/adkey_table.c @@ -0,0 +1,356 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_DEMO +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_UP, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_DOWN, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_MUSIC_CHANGE_REPEAT, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_MUSIC_FR, KEY_MUSIC_FR, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_MUSIC_FF, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_PLAYER_AB_REPEAT_SWITCH, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_demo/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac695x_demo/key_table/iokey_table.c new file mode 100644 index 0000000..49f5e9c --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_demo/key_table/iokey_table.c @@ -0,0 +1,248 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_DEMO +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_demo/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac695x_demo/key_table/irkey_table.c new file mode 100644 index 0000000..54c4a91 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_demo/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_DEMO +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_IR_NUM_0, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_IR_NUM_1, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_IR_NUM_2, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_IR_NUM_3, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_IR_NUM_4, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_IR_NUM_5, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_IR_NUM_6, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_IR_NUM_7, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_IR_NUM_8, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_IR_NUM_9, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_demo/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac695x_demo/key_table/rdec_key_table.c new file mode 100644 index 0000000..bee5615 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_demo/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_DEMO +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_demo/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac695x_demo/key_table/touch_key_table.c new file mode 100644 index 0000000..d8732c7 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_demo/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_DEMO +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_lcd/board_ac695x_lcd.c b/apps/soundbox/board/br23/board_ac695x_lcd/board_ac695x_lcd.c new file mode 100644 index 0000000..47b334e --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_lcd/board_ac695x_lcd.c @@ -0,0 +1,1052 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC695X_LCD + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "fm_emitter/fm_emitter_manage.h" +#include "dev_manager.h" +#include "fm/fm_manage.h" +#include "asm/power/p33.h" +#include "norflash.h" +#include "asm/spi.h" +#include "ui_manage.h" +#include "spi/nor_fs.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ +SD0_PLATFORM_DATA_BEGIN(sd0_data) + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = NULL,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = NULL,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) + .port = TCFG_SD1_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 0, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 0, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V + .vcmo_en = 1, //是否打开VCOMO + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 3, + .lpf_isel = 0x8, + .zero_cross_detect = 1, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PA2)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, + .key_value = 2, + }, +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = 1, //TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTC_01, + .pin_cfg.pin7.pin[1] = IO_PORTC_02, + .pin_cfg.pin7.pin[2] = IO_PORTC_03, + .pin_cfg.pin7.pin[3] = IO_PORTC_04, + .pin_cfg.pin7.pin[4] = IO_PORTC_05, + .pin_cfg.pin7.pin[5] = IO_PORTB_06, + .pin_cfg.pin7.pin[6] = IO_PORTB_07, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if 0 +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; + + +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + +#if TCFG_HW_SPI0_ENABLE +const struct spi_platform_data spi0_p_data = { + .port = TCFG_HW_SPI0_PORT, + .mode = TCFG_HW_SPI0_MODE, + .clk = TCFG_HW_SPI0_BAUD, + .role = TCFG_HW_SPI0_ROLE, +}; +#endif + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NOR_FAT +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 0, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_FS +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 1*1024*1024, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_REC +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 2*1024*1024, + .size = 2*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + + +#if (TCFG_SPI_LCD_ENABLE || TCFG_SIMPLE_LCD_ENABLE) + +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + +#if TCFG_LCD_OLED_ENABLE + .pin_reset = IO_PORTC_01, + .pin_cs = IO_PORTC_03, + .pin_rs = IO_PORTC_02, + .pin_bl = IO_PORTC_00, +#else + .pin_reset = -1, + .pin_cs = IO_PORTC_03, + .pin_rs = IO_PORTC_02, + .pin_bl = IO_PORTC_01, +#endif + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_FM_ENABLE + +FM_DEV_PLATFORM_DATA_BEGIN(fm_dev_data) + .iic_hdl = 0, + .iic_delay = 50, +FM_DEV_PLATFORM_DATA_END(); + +#endif + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif + +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +#if TCFG_NOR_FAT + { "fat_nor", &norflash_dev_ops , (void *)&norflash_fat_dev_data}, +#endif + +#if TCFG_NOR_FS + { "res_nor", &norfs_dev_ops , (void *)&norflash_norfs_dev_data}, +#endif + +#if TCFG_NOR_REC + {"rec_nor", &norfs_dev_ops , (void *)&norflash_norfs_rec_dev_data}, +#endif +#endif +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTB_01, //唤醒口选择 +}; + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} +static void key_wakeup_disable() +{ + power_wakeup_index_disable(1); +} +static void key_wakeup_enable() +{ + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + +#if TCFG_APP_FM_EMITTER_EN + fm_emitter_manage_init(930); +#endif + + return; +} + + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + sdpg_config(1); +/* #endif */ + +#if TCFG_FM_ENABLE + fm_dev_init(&fm_dev_data); +#endif + +#if TCFG_NOR_REC + nor_fs_ops_init(); +#endif + +#if TCFG_NOR_FS + init_norsdfile_hdl(); +#endif + +#if FLASH_INSIDE_REC_ENABLE + sdfile_rec_ops_init(); +#endif + + dev_manager_init(); + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + //针对硅mic要输出1给mic供电(按实际使用情况配置) + /* if(!adc_data.mic_capless){ */ + /* gpio_set_pull_up(IO_PORTA_04, 0); */ + /* gpio_set_pull_down(IO_PORTA_04, 0); */ + /* gpio_set_direction(IO_PORTA_04, 0); */ + /* gpio_set_output_value(IO_PORTA_04,1); */ + /* } */ + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + key_wakeup_enable(); + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); + key_wakeup_disable(); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + key_wakeup_enable(); + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); + key_wakeup_disable(); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif /* #ifdef CONFIG_BOARD_AC696X_LCD */ diff --git a/apps/soundbox/board/br23/board_ac695x_lcd/board_ac695x_lcd_cfg.h b/apps/soundbox/board/br23/board_ac695x_lcd/board_ac695x_lcd_cfg.h new file mode 100644 index 0000000..e1fa462 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_lcd/board_ac695x_lcd_cfg.h @@ -0,0 +1,1040 @@ +#ifndef CONFIG_BOARD_AC695X_LCD_CFG_H +#define CONFIG_BOARD_AC695X_LCD_CFG_H + +#ifdef CONFIG_BOARD_AC695X_LCD + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 +#define LINEIN_INPUT_WAY_DAC 2 + +#define NO_CONFIG_PORT (-1) + +/*********************************************************************************/ +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 1 +#define TCFG_APP_LINEIN_EN 1 +#define TCFG_APP_FM_EN 1 +#define TCFG_APP_PC_EN 0 +#define TCFG_APP_RTC_EN 1 +#define TCFG_APP_RECORD_EN 1 +#define TCFG_APP_SPDIF_EN 0 +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTA_02 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCFG_SW_I2C0_CLK_PORT IO_PORTA_09 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTA_10 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI0_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PD2 DO: PD1 CLK: PD0 D2:PB7 D3:PD5 +//B组IO: DI: PA14 DO: PD1 CLK: PD0 D2:PA15 D3:PD5 +//C组IO: DI: PA6 DO: PA8 CLK: PA3 D2:PA7 D3:PA2 +//D组IO: DI: PB8 DO: PB10 CLK: PB5 D2:PB9 D3:PB4 +#define TCFG_HW_SPI0_PORT 'C' +#define TCFG_HW_SPI0_BAUD 48000000L +#define TCFG_HW_SPI0_MODE SPI_MODE_BIDIR_1BIT //SPI_MODE_UNIDIR_1BIT// +#define TCFG_HW_SPI0_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'B' +#define TCFG_HW_SPI1_BAUD 20000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_NANDFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE ENABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE ENABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#include "usb_std_class_def.h" + + +#define TCFG_USB_PORT_CHARGE DISABLE + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE + + +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DP_ONLY) + +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 + +#define TCFG_KEY_TONE_EN 0//ENABLE // 按键提示音。建议音频输出使用固定采样率 + +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO + +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_PORT IO_PORTB_01 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PB1 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 100 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 51 / (51 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 150 / (150 + R_UP)) //9.1k +#define TCFG_ADKEY_AD3 (0x3ffL * 330 / (330 + R_UP)) //15k +#define TCFG_ADKEY_AD4 (0x3ffL * 1000 / (1000 + R_UP)) //24k +#define TCFG_ADKEY_AD5 (0x3ffL)// * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD6 (0x3ffL)// * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD7 (0x3ffL)// * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL)//* 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL)// * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 (不支持) // +//*********************************************************************************// +//#define TCFG_TOUCH_KEY_ENABLE ENABLE_THIS_MOUDLE //是否使能触摸按键 +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTA_00 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTA_01 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 + DAC_OUTPUT_FRONT_LR_REAR_LR 四声道输出 +*/ +//#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define VOL_TYPE_DIGGROUP 4 //独立通道数字音量 + +//每个解码通道都开启数字音量管理,音量类型为VOL_TYPE_DIGGROUP时要使能 +#define SYS_DIGVOL_GROUP_EN DISABLE + +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE ENABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE ENABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_SOUNDBOX +// #define CONFIG_UI_STYLE STYLE_UI_SIMPLE //这是309 sdk ui 风格 需要再开启TCFG_SIMPLE_LCD_ENABLE +// #define TCFG_UI_LED7_ENABLE ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_LRC_LYRICS_ENABLE ENABLE_THIS_MOUDLE //歌词显示 +#define TCFG_LCD_OLED_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE ENABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_SIMPLE_LCD_ENABLE DISABLE_THIS_MOUDLE//去ui 框架的驱动开关 开启请关闭了TCFG_SPI_LCD_ENABLE +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 +#define LCD_SPI_INTERRUPT_ENABLE 0//默认开启 需要主动关闭 +#define ALL_KEY_EVENT_CLICK_ONLY 1 //是否全部按键只响应单击事件 + +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN //SNIFF状态下芯片是否进入powerdown +/*强VDDIO等级配置,可选: + VDDIOM_VOL_20V VDDIOM_VOL_22V VDDIOM_VOL_24V VDDIOM_VOL_26V + VDDIOM_VOL_30V VDDIOM_VOL_30V VDDIOM_VOL_32V VDDIOM_VOL_36V*/ +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V //VDDIO 设置的值要和vbat的压差要大于300mv左右,否则会出现DAC杂音 +/*弱VDDIO等级配置,可选: + VDDIOW_VOL_21V VDDIOW_VOL_24V VDDIOW_VOL_28V VDDIOW_VOL_32V*/ +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 1 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 1 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 1 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 1 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 1 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 0 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 0 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 1 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 1 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 1 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 1 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 1 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 0 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 0 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 1 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif + +#endif +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 1 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 4000//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +#define TCFG_AUDIO_DEC_OUT_TASK 0 // 解码使用单独任务做输出 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 0 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 1 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN DISABLE//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE DISABLE//音乐播放录音区分使能 + + +#if RECORDER_MIX_EN//限制不能同时打开 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE +#endif + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#if (RECORDER_MIX_EN) +#define TCFG_LINEIN_LR_CH AUDIO_LIN0L_CH//AUDIO_LIN0_LR +#else +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR//AUDIO_LIN0R_CH +#endif/*RECORDER_MIX_EN*/ +#define TCFG_LINEIN_CHECK_PORT NO_CONFIG_PORT // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#if(TCFG_MIC_EFFECT_ENABLE) +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ANALOG +#else +#if (RECORDER_MIX_EN) +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC//LINEIN_INPUT_WAY_ANALOG +#else +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC//LINEIN_INPUT_WAY_ANALOG +#endif/*RECORDER_MIX_EN*/ +#endif +#define TCFG_LINEIN_MULTIPLEX_WITH_FM DISABLE // linein 脚与 FM 脚复用 +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd + +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE ENABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE ENABLE +#define TCFG_DEC_WAV_ENABLE ENABLE +#define TCFG_DEC_FLAC_ENABLE ENABLE +#define TCFG_DEC_APE_ENABLE ENABLE +#define TCFG_DEC_M4A_ENABLE ENABLE +#define TCFG_DEC_ALAC_ENABLE ENABLE +#define TCFG_DEC_AMR_ENABLE ENABLE +#define TCFG_DEC_DTS_ENABLE ENABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE ENABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE +#define TCFG_FM_BK1080_ENABLE DISABLE +#define TCFG_FM_QN8035_ENABLE DISABLE + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE) +#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE))) +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#else +#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif +#else +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/ + +#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE) +#undef TCFG_LED7_RUN_RAM +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/ + +//*********************************************************************************// +// fm emitter 配置 (不支持) // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN +#define TCFG_USE_VIRTUAL_RTC 0// ENABLE //假时钟 + +//*********************************************************************************// +// SPDIF & ARC 配置(不支持) // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) || (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC_IIS) +#define TCFG_IIS_ENABLE ENABLE_THIS_MOUDLE +#else +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE +#endif + +#define TCFG_IIS_MODE (0) // 0:master 1:slave + +#define TCFG_IIS_OUTPUT_EN (ENABLE && TCFG_IIS_ENABLE) +#define TCFG_IIS_OUTPUT_PORT ALINK0_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL 0 + +#define TCFG_IIS_INPUT_EN (DISABLE && TCFG_IIS_ENABLE) +#define TCFG_IIS_INPUT_PORT ALINK0_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR 44100 +#define TCFG_IIS_INPUT_DATAPORT_SEL 1 + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// + +#define TCFG_ENC_CVSD_ENABLE ENABLE +#define TCFG_ENC_MSBC_ENABLE ENABLE +#define TCFG_ENC_G726_ENABLE ENABLE +#define TCFG_ENC_MP3_ENABLE ENABLE +#define TCFG_ENC_ADPCM_ENABLE ENABLE +#define TCFG_ENC_PCM_ENABLE ENABLE +#define TCFG_ENC_SBC_ENABLE ENABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + +//*********************************************************************************// +//ali ai profile +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 0 //not surport +#define ANCS_CLIENT_EN 0 + +#if (DUEROS_DMA_EN || TRANS_DATA_EN || ANCS_CLIENT_EN) +#define BT_FOR_APP_EN 1 +#else +#define BT_FOR_APP_EN 0 +#endif + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) + +#if ((TCFG_SPI_LCD_ENABLE && TCFG_SIMPLE_LCD_ENABLE)) +#error "TCFG_SPI_LCD_ENABLE and TCFG_SIMPLE_LCD_ENABLE, please close one !!!" +#endif //(TCFG_SPI_LCD_ENABLE && TCFG_SIMPLE_LCD_ENABLE) + +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC693X_DEMO +#endif //CONFIG_BOARD_AC693X_DEMO_CFG_H diff --git a/apps/soundbox/board/br23/board_ac695x_lcd/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac695x_lcd/key_table/adkey_table.c new file mode 100644 index 0000000..4a56a98 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_lcd/key_table/adkey_table.c @@ -0,0 +1,254 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" +#ifdef CONFIG_BOARD_AC695X_LCD +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, + }, + [1] = { + KEY_OK, KEY_MENU, + }, + [2] = { + KEY_DOWN, KEY_VOLUME_DEC, KEY_VOLUME_DEC, + }, + [3] = { + KEY_UP, KEY_VOLUME_INC, KEY_VOLUME_INC, + }, + [4] = { + KEY_NULL, KEY_MODE, + }, + +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, + }, + [1] = { + KEY_OK, KEY_MENU, + }, + [2] = { + KEY_DOWN, KEY_VOLUME_DEC, KEY_VOLUME_DEC, + }, + [3] = { + KEY_UP, KEY_VOLUME_INC, KEY_VOLUME_INC, + }, + [4] = { + KEY_NULL, KEY_MODE, + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, + }, + [1] = { + KEY_OK, KEY_MENU, + }, + [2] = { + KEY_DOWN, KEY_VOLUME_DEC, KEY_VOLUME_DEC, + }, + [3] = { + KEY_UP, KEY_VOLUME_INC, KEY_VOLUME_INC, + }, + [4] = { + KEY_NULL, KEY_MODE, + }, + +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, + }, + [1] = { + KEY_OK, KEY_MENU, + }, + [2] = { + KEY_DOWN, KEY_VOLUME_DEC, KEY_VOLUME_DEC, + }, + [3] = { + KEY_UP, KEY_VOLUME_INC, KEY_VOLUME_INC, + }, + [4] = { + KEY_NULL, KEY_MODE, + }, + +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, + }, + [1] = { + KEY_OK, KEY_MENU, + }, + [2] = { + KEY_DOWN + }, + [3] = { + KEY_UP + }, + [4] = { + KEY_NULL, KEY_MODE, + }, + +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, + }, + [1] = { + KEY_OK, KEY_MENU + }, + [2] = { + KEY_DOWN, KEY_VOLUME_DEC, KEY_VOLUME_DEC, + }, + [3] = { + KEY_UP, KEY_VOLUME_INC, KEY_VOLUME_INC, + }, + [4] = { + KEY_ENC, KEY_MODE, + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, + }, + [1] = { + KEY_OK, KEY_MENU + }, + [2] = { + KEY_DOWN, KEY_VOLUME_DEC, KEY_VOLUME_DEC, + }, + [3] = { + KEY_UP, KEY_VOLUME_INC, KEY_VOLUME_INC, + }, + [4] = { + KEY_NULL, KEY_MODE, + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_lcd/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac695x_lcd/key_table/iokey_table.c new file mode 100644 index 0000000..fd1ae62 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_lcd/key_table/iokey_table.c @@ -0,0 +1,248 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_LCD +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_lcd/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac695x_lcd/key_table/irkey_table.c new file mode 100644 index 0000000..3869bd9 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_lcd/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_LCD +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_lcd/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac695x_lcd/key_table/rdec_key_table.c new file mode 100644 index 0000000..ad7db9d --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_lcd/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_LCD +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_lcd/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac695x_lcd/key_table/touch_key_table.c new file mode 100644 index 0000000..8acbc8d --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_lcd/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_LCD +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_megaphone/board_ac695x_megaphone.c b/apps/soundbox/board/br23/board_ac695x_megaphone/board_ac695x_megaphone.c new file mode 100644 index 0000000..302a5a7 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_megaphone/board_ac695x_megaphone.c @@ -0,0 +1,1158 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC695X_MEGAPHONE + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "fm/fm_manage.h" +#include "asm/power/p33.h" +#include "norflash.h" +#include "asm/spi.h" +#include "ui_manage.h" +#include "spi/nor_fs.h" +#include "nandflash.h" +#include "audio_link.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +#if TCFG_IIS_ENABLE +ALINK_PARM alink0_param = { + .port_select = ALINK0_PORTA, //MCLK:PA8 SCLK:PA2 LRCK:PA3 CH0:PA4 CH1:PA5 CH2:PA6 CH3:PA7 + /* .port_select = ALINK0_PORTB, //MCLK:PA15 SCLK:PA9 LRCK:PA10 CH0:PA11 CH1:PA12 CH2:PA13 CH3:PA14 */ + /* .port_select = ALINK1_PORTA, //MCLK:PB0 SCLK:PC0 LRCK:PC1 CH0:PC2 CH1:PC3 CH2:PC4 CH3:PC5 */ + .ch_cfg[0].enable = 1, + .ch_cfg[1].enable = 1, + .mode = ALINK_MD_IIS, +#if TCFG_IIS_MODE + .role = ALINK_ROLE_SLAVE, +#else + .role = ALINK_ROLE_MASTER, +#endif + .clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE, + .bitwide = ALINK_LEN_16BIT, + .sclk_per_frame = ALINK_FRAME_64SCLK, + .dma_len = ALNK_BUF_POINTS_NUM * 2 * 2 * 2, + .sample_rate = TCFG_IIS_OUTPUT_SR, +}; + +ALINK_PARM alink1_param = { + /* .port_select = ALINK0_PORTA, //MCLK:PA8 SCLK:PA2 LRCK:PA3 CH0:PA4 CH1:PA5 CH2:PA6 CH3:PA7 */ + /* .port_select = ALINK0_PORTB, //MCLK:PA15 SCLK:PA9 LRCK:PA10 CH0:PA11 CH1:PA12 CH2:PA13 CH3:PA14 */ + .port_select = ALINK1_PORTA, //MCLK:PB0 SCLK:PC0 LRCK:PC1 CH0:PC2 CH1:PC3 CH2:PC4 CH3:PC5 + .ch_cfg[0].enable = 1, + .ch_cfg[1].enable = 1, + .mode = ALINK_MD_IIS, +#if TCFG_IIS_MODE + .role = ALINK_ROLE_SLAVE, +#else + .role = ALINK_ROLE_MASTER, +#endif + .clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE, + .bitwide = ALINK_LEN_16BIT, + .sclk_per_frame = ALINK_FRAME_64SCLK, + .dma_len = ALNK_BUF_POINTS_NUM * 2 * 2 * 2, + .sample_rate = TCFG_IIS_OUTPUT_SR, +}; + + +#endif + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, + .key_value = 2, + }, +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, +#if TCFG_SD1_ENABLE + .pin_cfg.pin7.pin[0] = IO_PORTA_02, + .pin_cfg.pin7.pin[1] = IO_PORTA_03, + .pin_cfg.pin7.pin[2] = IO_PORTA_04, + .pin_cfg.pin7.pin[3] = IO_PORTA_06, + .pin_cfg.pin7.pin[4] = IO_PORTA_07, + .pin_cfg.pin7.pin[5] = IO_PORTA_08, + .pin_cfg.pin7.pin[6] = IO_PORTA_09, +#else + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if TCHFG_SOFT_I2C_ENABLE +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; +#endif + +#if TCHFG_HW_I2C_ENABLE +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NANDFLASH_DEV_ENABLE +NANDFLASH_DEV_PLATFORM_DATA_BEGIN(nandflash_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, + .start_addr = 0, + .size = 0, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif +NANDFLASH_DEV_PLATFORM_DATA_END() +#endif + + +#if TCFG_NOR_FAT +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 0, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_FS +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 1*1024*1024, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_REC +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 2*1024*1024, + .size = 2*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_FM_ENABLE + +FM_DEV_PLATFORM_DATA_BEGIN(fm_dev_data) + .iic_hdl = 0, + .iic_delay = 50, +FM_DEV_PLATFORM_DATA_END(); + +#endif + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +#if TCFG_NOR_FAT + { "fat_nor", &norflash_dev_ops , (void *)&norflash_fat_dev_data}, +#endif + +#if TCFG_NOR_FS + { "res_nor", &norfs_dev_ops , (void *)&norflash_norfs_dev_data}, +#endif + +#if TCFG_NOR_REC + {"rec_nor", &norfs_dev_ops , (void *)&norflash_norfs_rec_dev_data}, +#endif +#endif + +#if TCFG_NANDFLASH_DEV_ENABLE + {"nand_flash", &nandflash_dev_ops , (void *)&nandflash_dev_data}, +#endif + + +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , + +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif + +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTA_10, //唤醒口选择 +}; + +/* RTC PR0 PR1 唤醒 */ +/* struct port_wakeup rtc_port0 = { */ + /* .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 */ + /* .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 */ + /* .attribute = BLUETOOTH_RESUME, //保留参数 */ + /* .iomap = IO_PORT_PR_00, //唤醒口选择 */ +/* }; */ + +/* struct port_wakeup rtc_port1 = { */ + /* .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 */ + /* .edge = RISING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 */ + /* .attribute = BLUETOOTH_RESUME, //保留参数 */ + /* .iomap = IO_PORT_PR_01, //唤醒口选择 */ +/* }; */ + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + /* .rtc_port[0] = &rtc_port0, */ + /* .rtc_port[1] = &rtc_port1, */ + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} +static void key_wakeup_disable() +{ + power_wakeup_index_disable(1); +} +static void key_wakeup_enable() +{ + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + +#if TCFG_FM_ENABLE + fm_dev_init(&fm_dev_data); +#endif + +#if TCFG_NOR_REC + nor_fs_ops_init(); +#endif + +#if TCFG_NOR_FS + init_norsdfile_hdl(); +#endif + +#if FLASH_INSIDE_REC_ENABLE + sdfile_rec_ops_init(); +#endif + + dev_manager_init(); + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + //针对硅mic要输出1给mic供电(按实际使用情况配置) + /* if(!adc_data.mic_capless){ */ + /* gpio_set_pull_up(IO_PORTA_04, 0); */ + /* gpio_set_pull_down(IO_PORTA_04, 0); */ + /* gpio_set_direction(IO_PORTA_04, 0); */ + /* gpio_set_output_value(IO_PORTA_04,1); */ + /* } */ + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +#if USER_UART_UPDATE_ENABLE + { +#include "uart_update.h" + uart_update_cfg update_cfg = { + .rx = IO_PORTA_02, + .tx = IO_PORTA_03, + .output_channel = CH1_UT1_TX, + .input_channel = INPUT_CH0 + }; + uart_update_init(&update_cfg); + } +#endif +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + key_wakeup_enable(); + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); + key_wakeup_disable(); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + key_wakeup_enable(); + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); + key_wakeup_disable(); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_megaphone/board_ac695x_megaphone_cfg.h b/apps/soundbox/board/br23/board_ac695x_megaphone/board_ac695x_megaphone_cfg.h new file mode 100644 index 0000000..9a74bfe --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_megaphone/board_ac695x_megaphone_cfg.h @@ -0,0 +1,1055 @@ +#ifndef CONFIG_BOARD_AC695X_MEGAPHONE_CFG_H +#define CONFIG_BOARD_AC695X_MEGAPHONE_CFG_H + +#ifdef CONFIG_BOARD_AC695X_MEGAPHONE + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 +#define LINEIN_INPUT_WAY_DAC 2 + +#define NO_CONFIG_PORT (-1) + + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 1 +#define TCFG_APP_LINEIN_EN 1 +#define TCFG_APP_FM_EN 1 +#define TCFG_APP_PC_EN 1 +#define TCFG_APP_RTC_EN 1 +#define TCFG_APP_RECORD_EN 1 +#define TCFG_APP_SPDIF_EN 0 +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTA_05 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCHFG_SOFT_I2C_ENABLE DISABLE_THIS_MOUDLE //软件IIC使能 +#define TCFG_SW_I2C0_CLK_PORT IO_PORTB_00 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTB_03 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCHFG_HW_I2C_ENABLE DISABLE_THIS_MOUDLE //硬件IIC使能 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 4000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_NANDFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + +//*********************************************************************************// +// 设备异步读 配置 // +//*********************************************************************************// + +#define TCFG_DEVICE_BULK_READ_ASYNC_ENABLE + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE ENABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE ENABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#define TCFG_VIR_UDISK_ENABLE 0//ENABLE_THIS_MOUDLE + +#define TCFG_USB_PORT_CHARGE DISABLE + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE + +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DP_ONLY) + +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 + +#define TCFG_KEY_TONE_EN 0//ENABLE // 按键提示音。建议音频输出使用固定采样率 + +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO + +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_LED_IO_REUSE DISABLE_THIS_MOUDLE //ADKEY 和 LED IO复用,led只能设置蓝灯显示 +#define TCFG_ADKEY_PORT IO_PORTA_10 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PA10 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTA_00 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTA_01 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 + DAC_OUTPUT_FRONT_LR_REAR_LR 四声道输出 +*/ +//#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC //LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define VOL_TYPE_DIGGROUP 4 //独立通道数字音量 + +//每个解码通道都开启数字音量管理,音量类型为VOL_TYPE_DIGGROUP时要使能 +#define SYS_DIGVOL_GROUP_EN DISABLE + +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) + +//AudioEffects代码链接管理 +#define AUDIO_EFFECTS_DRC_AT_RAM 1 +#define AUDIO_EFFECTS_REVERB_AT_RAM 1 +#define AUDIO_EFFECTS_ECHO_AT_RAM 0 +#define AUDIO_EFFECTS_AFC_AT_RAM 1 +#define AUDIO_EFFECTS_EQ_AT_RAM 0 +#define AUDIO_EFFECTS_NOISEGATE_AT_RAM 0 +#define AUDIO_EFFECTS_MIC_EFFECT_AT_RAM 0 +#define AUDIO_EFFECTS_MIC_STREAM_AT_RAM 0 +#define AUDIO_EFFECTS_DEBUG_AT_RAM 0 + +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE ENABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE DISABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE DISABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + +#define TCFG_LED7_RUN_RAM DISABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) + +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 240000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 1 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 1 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 1 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 1 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 1 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 0 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 1 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 1 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后置EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 1 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc + +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 1 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 1 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 1 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 1 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 1 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 1 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后的drc +#endif//TCFG_DRC_ENABLE + +#define LINEIN_MODE_SOLE_EQ_EN 0 //linein模式是否需要独立的eq与drc + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 1//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_MEGAPHONE + + +#define TCFG_MIC_VOICE_CHANGER_ENABLE DISABLE //变声模块使能 + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif + +#endif +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 1 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 4000//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +#define TCFG_AUDIO_DEC_OUT_TASK 0 // 解码使用单独任务做输出 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 1 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 0 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN DISABLE//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE DISABLE//音乐播放录音区分使能 + + +#if RECORDER_MIX_EN//限制不能同时打开 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE +#endif + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR +#define TCFG_LINEIN_CHECK_PORT IO_PORTB_03 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd口 +#define TCFG_LINEIN_DETECT_ENABLE 0 +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE ENABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE ENABLE +#define TCFG_DEC_WAV_ENABLE ENABLE +#define TCFG_DEC_FLAC_ENABLE ENABLE +#define TCFG_DEC_APE_ENABLE DISABLE +#define TCFG_DEC_M4A_ENABLE DISABLE +#define TCFG_DEC_ALAC_ENABLE DISABLE +#define TCFG_DEC_AMR_ENABLE DISABLE +#define TCFG_DEC_DTS_ENABLE DISABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE ENABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE //需要使能软件IIC模块 +#define TCFG_FM_BK1080_ENABLE DISABLE //需要使能软件IIC模块 +#define TCFG_FM_QN8035_ENABLE DISABLE //需要使能软件IIC模块 + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE) +#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE))) +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#else +#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif +#else +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/ + +#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE) +#undef TCFG_LED7_RUN_RAM +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/ + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) || (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC_IIS) +#define TCFG_IIS_ENABLE ENABLE_THIS_MOUDLE +#else +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE +#endif + +#define TCFG_IIS_MODE (0) // 0:master 1:slave + +#define TCFG_IIS_OUTPUT_EN (ENABLE && TCFG_IIS_ENABLE) +#define TCFG_IIS_OUTPUT_PORT ALINK0_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL 0 + +#define TCFG_IIS_INPUT_EN (DISABLE && TCFG_IIS_ENABLE) +#define TCFG_IIS_INPUT_PORT ALINK0_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR 44100 +#define TCFG_IIS_INPUT_DATAPORT_SEL 1 + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE ENABLE +#define TCFG_ENC_MSBC_ENABLE ENABLE +#define TCFG_ENC_G726_ENABLE ENABLE +#define TCFG_ENC_MP3_ENABLE ENABLE +#define TCFG_ENC_ADPCM_ENABLE ENABLE +#define TCFG_ENC_PCM_ENABLE ENABLE +#define TCFG_ENC_SBC_ENABLE ENABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + +//*********************************************************************************// +//ali ai profile +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 0 //not surport +#define ANCS_CLIENT_EN 0 + +#if (DUEROS_DMA_EN || TRANS_DATA_EN || ANCS_CLIENT_EN) +#define BT_FOR_APP_EN 1 +#else +#define BT_FOR_APP_EN 0 +#endif + +//*********************************************************************************// + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 + +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 2.X声道配置(需使能板极四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR) +// 2.1 两个全频较弱的全频音箱 + 一个低音炮 +// 2.2 两个全频较弱的全频音箱 + 2个低音炮 +//*********************************************************************************// +#define SOUND_TRACK_2_P_X_CH_CONFIG 0 //2.X声道总使能 + +#if SOUND_TRACK_2_P_X_CH_CONFIG +#define TWO_POINT_ONE_CH BIT(0) //2.1声道 +#define TWO_POINT_TWO_CH BIT(1) //2.2声道 +#define TWO_POINT_X_CH TWO_POINT_ONE_CH//选配使用2.1 还是2.2 声道 + +#if (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#undef TCFG_AUDIO_DAC_CONNECT_MODE +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#endif +#endif/*SOUND_TRACK_2_P_X_CH_CONFIG*/ + + + + + + +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)&&(TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE)) +#error "使能配置工具时,需临时关闭flac解码 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif + +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC695X_MEGAPHONE +#endif //CONFIG_BOARD_AC695X_MEGAPHONE_CFG_H diff --git a/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/adkey_table.c new file mode 100644 index 0000000..f94393c --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/adkey_table.c @@ -0,0 +1,356 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_MEGAPHONE +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_UP, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_DOWN, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_MUSIC_CHANGE_REPEAT, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_MUSIC_FR, KEY_MUSIC_FR, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_MUSIC_FF, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_PLAYER_AB_REPEAT_SWITCH, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/iokey_table.c new file mode 100644 index 0000000..7627df4 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/iokey_table.c @@ -0,0 +1,248 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_MEGAPHONE +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/irkey_table.c new file mode 100644 index 0000000..033aaa3 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_MEGAPHONE +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_IR_NUM_0, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_IR_NUM_1, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_IR_NUM_2, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_IR_NUM_3, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_IR_NUM_4, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_IR_NUM_5, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_IR_NUM_6, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_IR_NUM_7, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_IR_NUM_8, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_IR_NUM_9, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/rdec_key_table.c new file mode 100644 index 0000000..5517d28 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_MEGAPHONE +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/touch_key_table.c new file mode 100644 index 0000000..ca34728 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_MEGAPHONE +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/board_ac695x_multimedia_charging_bin.c b/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/board_ac695x_multimedia_charging_bin.c new file mode 100644 index 0000000..06c6953 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/board_ac695x_multimedia_charging_bin.c @@ -0,0 +1,970 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC695X_MULTIMEDIA_CHARGING_BIN + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "asm/spi.h" +#include "norflash.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "asm/ctmu.h" +#include "asm/power/p33.h" +#include "ui_manage.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + /* .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL */ + .power = NULL, +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, + .key_value = 2, + }, +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .press_cfg = TCFG_CTMU_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if 0 +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; + + +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + +#if TCFG_SPI_LCD_ENABLE + +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + +#if TCFG_LCD_OLED_ENABLE + .pin_reset = IO_PORTC_01, + .pin_cs = IO_PORTC_03, + .pin_rs = IO_PORTC_02, + .pin_bl = IO_PORTC_00, +#else + .pin_reset = -1, + .pin_cs = IO_PORTC_03, + .pin_rs = IO_PORTC_02, + .pin_bl = IO_PORTC_01, +#endif + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif +#if TCFG_NORFLASH_DEV_ENABLE + { "norflash", &norflash_dev_ops , (void *)&norflash_dev_data}, +#endif +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTB_01, //唤醒口选择 +}; + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_TOUCH_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + sdpg_config(1); +/* #endif */ + +#if 0 /* SPI 屏幕驱动测试 */ + log_info("test tft>>>>>>>\n"); + extern void SPI_LcdTest(); + SPI_LcdTest(); + log_info("test tft over\n"); +#endif + + dev_manager_init(); + + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + /* void bt_menu_list_init(); */ + /* bt_menu_list_init(); */ + + //针对硅mic要输出1给mic供电 + if(!adc_data.mic_capless){ + gpio_set_pull_up(IO_PORTA_04, 0); + gpio_set_pull_down(IO_PORTA_04, 0); + gpio_set_direction(IO_PORTA_04, 0); + gpio_set_output_value(IO_PORTA_04,1); + } + + gpio_set_direction(IO_PORTB_06, 1); + gpio_set_pull_up(IO_PORTB_06, 0); + gpio_set_pull_down(IO_PORTB_06, 0); + gpio_set_die(IO_PORTB_06, 0); + + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif//CONFIG_BOARD_AC695X_MULTIMEDIA_CHARGING_BIN diff --git a/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/board_ac695x_multimedia_charging_bin.h b/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/board_ac695x_multimedia_charging_bin.h new file mode 100644 index 0000000..51b6635 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/board_ac695x_multimedia_charging_bin.h @@ -0,0 +1,906 @@ +#ifndef BOARD_AC695X_MULTIMEDIA_CHARGING_BIN_H +#define BOARD_AC695X_MULTIMEDIA_CHARGING_BIN_H + +#ifdef CONFIG_BOARD_AC695X_MULTIMEDIA_CHARGING_BIN + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 +#define LINEIN_INPUT_WAY_DAC 2 + +#define NO_CONFIG_PORT (-1) + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 1 +#define TCFG_APP_LINEIN_EN 1 +#define TCFG_APP_FM_EN 0 +#define TCFG_APP_PC_EN 1 +#define TCFG_APP_RTC_EN 1 +#define TCFG_APP_RECORD_EN 1 +#define TCFG_APP_SPDIF_EN 0 + +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORT_DP //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCFG_SW_I2C0_CLK_PORT IO_PORTA_09 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTA_10 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'B' +#define TCFG_HW_SPI1_BAUD 20000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define TCFG_SD0_ENABLE ENABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE ENABLE_THIS_MOUDLE//PC模块使能 +#define TCFG_UDISK_ENABLE DISABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#include "usb_std_class_def.h" + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO + +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_PORT IO_PORTB_01 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PB1 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 51 / (51 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 150 / (150 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 330 / (330 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 1000 / (1000 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 2200 / (2200 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL)// * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL)// * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL)//* 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL)// * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTA_00 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTA_01 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: +DAC_OUTPUT_LR 立体声 +DAC_OUTPUT_FRONT_LR_REAR_LR 四声道输出 +*/ +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE + +// 每个解码通道都开启数字音量管理 +#define SYS_DIGVOL_GROUP_EN DISABLE + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//*********************************************************************************// +#define TCFG_PWMLED_ENABLE ENABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 + +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE ENABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_SOUNDBOX +// #define TCFG_UI_LED7_ENABLE ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789V_ENABLE DISABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_LCD_OLED_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_LRC_LYRICS_ENABLE ENABLE_THIS_MOUDLE //歌词显示 +#define TCFG_SPI_LCD_ENABLE ENABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + +#define TCFG_LED7_RUN_RAM DISABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0// SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 0 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 0 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 0 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 0 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 0 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 0 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 0 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 0 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 0 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 0 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 0 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 0 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 0 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 0 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 0 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#endif +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 1 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 3700//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 +#define TCFG_AUDIO_DEC_OUT_TASK 0 // 解码使用单独任务做输出 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 0 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 1 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + +//*********************************************************************************// +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN1R_CH +#define TCFG_LINEIN_CHECK_PORT IO_PORTB_10 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL AD_CH_PB10 // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 1000 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ANALOG//LINEIN_INPUT_WAY_ADC// +#define TCFG_LINEIN_MULTIPLEX_WITH_SD 0//ENABLE // linein 检测与 SD cmd 复用 + +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE ENABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE ENABLE +#define TCFG_DEC_WAV_ENABLE ENABLE +#define TCFG_DEC_FLAC_ENABLE DISABLE +#define TCFG_DEC_APE_ENABLE DISABLE +#define TCFG_DEC_M4A_ENABLE ENABLE +#define TCFG_DEC_ALAC_ENABLE DISABLE +#define TCFG_DEC_AMR_ENABLE ENABLE +#define TCFG_DEC_DTS_ENABLE DISABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE DISABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE +#define TCFG_FM_BK1080_ENABLE DISABLE +#define TCFG_FM_QN8035_ENABLE DISABLE + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE) +#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE))) +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#else +#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif +#else +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/ + +#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE) +#undef TCFG_LED7_RUN_RAM +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/ + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE // +#define TCFG_IIS_OUTPUT_EN ENABLE // +#define TCFG_IIS_OUTPUT_PORT ALINK1_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL (BIT(0)) + +#define TCFG_IIS_INPUT_EN DISABLE// +#define TCFG_IIS_INPUT_PORT ALINK1_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR (44100l) +#define TCFG_IIS_INPUT_DATAPORT_SEL (BIT(0)) + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE +#define TCFG_DEC_FILE_NAME_ENABLE 1//DISABLE//支持长文件名 + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// + +#define TCFG_APP_MUSIC_EN ((TCFG_UDISK_ENALBE || TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) && CONFIG_FATFS_ENABLE) +#define TCFG_APP_LINEIN_EN (TCFG_LINEIN_ENABLE) +#define TCFG_APP_FM_EN (TCFG_FM_ENABLE) +#define TCFG_APP_PC_EN (TCFG_PC_ENABLE) +#define TCFG_APP_RTC_EN (TCFG_RTC_ENABLE) +#define TCFG_APP_RECORD_EN DISABLE_THIS_MOUDLE//((TCFG_UDISK_ENABLE || TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) && CONFIG_FATFS_ENABLE) +#define TCFG_APP_SPDIF_EN (TCFG_SPDIF_ENABLE) + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define TCFG_LINEIN_REC_EN DISABLE +#define TCFG_MIXERCH_REC_EN DISABLE +#define TCFG_MIC_REC_PITCH_EN DISABLE +#define TCFG_MIC_REC_REVERB_EN DISABLE + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE ENABLE +#define TCFG_ENC_MSBC_ENABLE ENABLE +#define TCFG_ENC_G726_ENABLE ENABLE +#define TCFG_ENC_MP3_ENABLE ENABLE +#define TCFG_ENC_ADPCM_ENABLE ENABLE +#define TCFG_ENC_PCM_ENABLE ENABLE +#define TCFG_ENC_SBC_ENABLE ENABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + + +//*********************************************************************************// +//ali ai profile +// +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 0 //数传demo +#define SMART_BOX_EN 1 + +#if (DUEROS_DMA_EN || TRANS_DATA_EN || SMART_BOX_EN || RCSP_BTMATE_EN) +#undef TCFG_USER_BLE_ENABLE +#define TCFG_USER_BLE_ENABLE 1 +#else +#endif + +#if (SMART_BOX_EN) +#undef TCFG_USER_EMITTER_ENABLE +#define TCFG_USER_EMITTER_ENABLE 0 + +#undef RCSP_FILE_OPT +#define RCSP_FILE_OPT 0 +#endif + + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if(TRANS_DATA_EN && DUEROS_DMA_EN) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC695X_MULTIMEDIA_CHARGING_BIN +#endif //BOARD_AC695X_MULTIMEDIA_CHARGING_BIN_H diff --git a/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/adkey_table.c new file mode 100644 index 0000000..b36b638 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/adkey_table.c @@ -0,0 +1,356 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_MULTIMEDIA_CHARGING_BIN +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_CHANGE_REPEAT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_NULL, KEY_MUSIC_FR, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [5] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/iokey_table.c new file mode 100644 index 0000000..d921489 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/iokey_table.c @@ -0,0 +1,239 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_MULTIMEDIA_CHARGING_BIN +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/irkey_table.c new file mode 100644 index 0000000..e8487dd --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_MULTIMEDIA_CHARGING_BIN +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/rdec_key_table.c new file mode 100644 index 0000000..b383e01 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_MULTIMEDIA_CHARGING_BIN +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/touch_key_table.c new file mode 100644 index 0000000..bfa3483 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_MULTIMEDIA_CHARGING_BIN +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_smartbox/board_ac695x_smartbox.c b/apps/soundbox/board/br23/board_ac695x_smartbox/board_ac695x_smartbox.c new file mode 100644 index 0000000..55004ec --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_smartbox/board_ac695x_smartbox.c @@ -0,0 +1,1073 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC695X_SMARTBOX + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "fm/fm_manage.h" +#include "asm/power/p33.h" +#include "norflash.h" +#include "asm/spi.h" +#include "ui_manage.h" +#include "spi/nor_fs.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, + .key_value = 2, + }, +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, +#if TCFG_SD1_ENABLE + .pin_cfg.pin7.pin[0] = IO_PORTA_02, + .pin_cfg.pin7.pin[1] = IO_PORTA_03, + .pin_cfg.pin7.pin[2] = IO_PORTA_04, + .pin_cfg.pin7.pin[3] = IO_PORTA_06, + .pin_cfg.pin7.pin[4] = IO_PORTA_07, + .pin_cfg.pin7.pin[5] = IO_PORTA_08, + .pin_cfg.pin7.pin[6] = IO_PORTA_09, +#else + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if 0 +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; + + +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NOR_FAT +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 0, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_FS +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 1*1024*1024, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_REC +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 2*1024*1024, + .size = 2*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_FM_ENABLE + +FM_DEV_PLATFORM_DATA_BEGIN(fm_dev_data) + .iic_hdl = 0, + .iic_delay = 50, +FM_DEV_PLATFORM_DATA_END(); + +#endif + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +#if TCFG_NOR_FAT + { "fat_nor", &norflash_dev_ops , (void *)&norflash_fat_dev_data}, +#endif + +#if TCFG_NOR_FS + { "res_nor", &norfs_dev_ops , (void *)&norflash_norfs_dev_data}, +#endif + +#if TCFG_NOR_REC + {"rec_nor", &norfs_dev_ops , (void *)&norflash_norfs_rec_dev_data}, +#endif +#endif +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTA_10, //唤醒口选择 +}; + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} +static void key_wakeup_disable() +{ + power_wakeup_index_disable(1); +} +static void key_wakeup_enable() +{ + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + + +#if TCFG_FM_ENABLE + fm_dev_init(&fm_dev_data); +#endif + +#if TCFG_NOR_REC + nor_fs_ops_init(); +#endif + +#if TCFG_NOR_FS + init_norsdfile_hdl(); +#endif + +#if FLASH_INSIDE_REC_ENABLE + sdfile_rec_ops_init(); +#endif + + dev_manager_init(); + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + //针对硅mic要输出1给mic供电(按实际使用情况配置) + /* if(!adc_data.mic_capless){ */ + /* gpio_set_pull_up(IO_PORTA_04, 0); */ + /* gpio_set_pull_down(IO_PORTA_04, 0); */ + /* gpio_set_direction(IO_PORTA_04, 0); */ + /* gpio_set_output_value(IO_PORTA_04,1); */ + /* } */ + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +#if USER_UART_UPDATE_ENABLE + { +#include "uart_update.h" + uart_update_cfg update_cfg = { + .rx = IO_PORTA_02, + .tx = IO_PORTA_03, + .output_channel = CH1_UT1_TX, + .input_channel = INPUT_CH0 + }; + uart_update_init(&update_cfg); + } +#endif +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + key_wakeup_enable(); + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); + key_wakeup_disable(); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + key_wakeup_enable(); + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); + key_wakeup_disable(); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_smartbox/board_ac695x_smartbox.h b/apps/soundbox/board/br23/board_ac695x_smartbox/board_ac695x_smartbox.h new file mode 100644 index 0000000..ce88acb --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_smartbox/board_ac695x_smartbox.h @@ -0,0 +1,1070 @@ +#ifndef CONFIG_BOARD_AC695X_SMARTBOX_CFG_H +#define CONFIG_BOARD_AC695X_SMARTBOX_CFG_H + +#ifdef CONFIG_BOARD_AC695X_SMARTBOX + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 + +#define NO_CONFIG_PORT (-1) + + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 1 +#define TCFG_APP_LINEIN_EN 1 +#define TCFG_APP_FM_EN 1 +#define TCFG_APP_PC_EN 1 +#define TCFG_APP_RTC_EN 1 +#define TCFG_APP_RECORD_EN 1 +#define TCFG_APP_SPDIF_EN 0 +#define TCFG_APP_RTC_SIMULATE_EN 0 + +#if (TCFG_APP_RTC_EN && TCFG_APP_RTC_SIMULATE_EN) +#define rtc_dev_ops rtc_simulate_ops +#endif + +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTA_05 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCFG_SW_I2C0_CLK_PORT IO_PORTA_09 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTA_10 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 2000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE 0 +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE 0 +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE 0 + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE ENABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE ENABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#include "usb_std_class_def.h" + +#define TCFG_VIR_UDISK_ENABLE 1//ENABLE_THIS_MOUDLE + +#define TCFG_USB_PORT_CHARGE DISABLE + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DP_ONLY) + +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO + +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//DISABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_LED_IO_REUSE DISABLE_THIS_MOUDLE //ADKEY 和 LED IO复用,led只能设置蓝灯显示 +#define TCFG_ADKEY_PORT IO_PORTA_10 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PA10 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTA_00 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTA_01 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 +*/ +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR + +/* +解码后音频的输出方式: + AUDIO_OUTPUT_ORIG_CH 按原始声道输出 + AUDIO_OUTPUT_STEREO 按立体声 + AUDIO_OUTPUT_L_CH 只输出原始声道的左声道 + AUDIO_OUTPUT_R_CH 只输出原始声道的右声道 + AUDIO_OUTPUT_MONO_LR_CH 输出左右合成的单声道 + */ + +#define AUDIO_OUTPUT_MODE AUDIO_OUTPUT_MONO_LR_CH + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC //LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +// 每个解码通道都开启数字音量管理 +#define SYS_DIGVOL_GROUP_EN DISABLE + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE ENABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE DISABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + + +#define TCFG_LED7_RUN_RAM DISABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0// SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 1 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 1 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 1 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE TCFG_APP_MUSIC_EN //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE TCFG_APP_LINEIN_EN //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE TCFG_APP_FM_EN //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE TCFG_APP_SPDIF_EN //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE TCFG_APP_PC_EN //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 1 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc + +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 1 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 1 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 1 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 1 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 0 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 0 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 1 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif + +#endif +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 1 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 3700//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +//*********************************************************************************// +// AI配置 // +//*********************************************************************************// + +#define CONFIG_APP_BT_ENABLE // AI功能、流程总开关 +#define CONFIG_TIDY_CODE_DEBUG //工程整理代码导致编译不过,加一下调试代码让工程编译通过 + + +#ifdef CONFIG_APP_BT_ENABLE +#define TRANS_DATA_EN 0 +#define SMART_BOX_EN 0 +#define TUYA_DEMO_EN 0 +#define TRANS_MULTI_BLE_EN 0//蓝牙BLE多机使能 +#define TUYA_MULTI_BLE_EN 0//TUYA BLE多机使能 +#define AI_APP_PROTOCOL 0 +#else +#define TRANS_DATA_EN 0 +#define SMART_BOX_EN 0 +#define TUYA_DEMO_EN 0 +#define TRANS_MULTI_BLE_EN 0 +#define TUYA_MULTI_BLE_EN 0//TUYA BLE多机使能 +#define AI_APP_PROTOCOL 0 +#endif + +//蓝牙BLE多连接 +#if TRANS_MULTI_BLE_EN //蓝牙BLE多连:1主1从,或者2主 +#define TRANS_MULTI_BLE_SLAVE_NUMS 1 //range(0~1) +#define TRANS_MULTI_BLE_MASTER_NUMS 1 //range(0~2) +#endif + +//蓝牙BLE多连接 +#if TUYA_MULTI_BLE_EN //TUYA BLE多连:1主1从,或者2主 +#define TRANS_MULTI_BLE_SLAVE_NUMS 1 //range(0~1) +#define TRANS_MULTI_BLE_MASTER_NUMS 1 //range(0~2) +#endif + + +#if (SMART_BOX_EN) //rcsp需要打开ble +#define CONFIG_DOUBLE_BANK_ENABLE 0 +#define RCSP_UPDATE_EN 1 //是否支持rcsp升级 +#define OTA_TWS_SAME_TIME_ENABLE 0 //是否支持TWS同步升级 +#define UPDATE_MD5_ENABLE 1 //升级是否支持MD5校验 +#define RCSP_FILE_OPT 1 +#define JL_EARPHONE_APP_EN 1 +#define TCFG_LFN_EN 1 +#define TCFG_BS_DEV_PATH_EN 1 +#else +#define OTA_TWS_SAME_TIME_ENABLE 0 +#define RCSP_UPDATE_EN 0 +#define UPDATE_MD5_ENABLE 0 //升级是否支持MD5校验 +#define RCSP_FILE_OPT 0 +#define JL_EARPHONE_APP_EN 0 +#endif + +///注意:对应的第三方应用平台是否需要支持语音上报, 如果需要请使能BT_MIC_EN +//对应的语音编码参数在mic_rec.c中定义 +#define BT_MIC_EN 0 + +#if RCSP_UPDATE_EN +#define APP_UPDATE_EN 0 //需要使用APP升级的话要把该宏打开 +#else +#define APP_UPDATE_EN 0 //客户如需要开发自己的app升级协议需要把这个宏打开,并提供升级需要的read\seek等接口,具体请参照说明文档 +#endif + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#ifdef CONFIG_APP_BT_ENABLE +#define TCFG_USER_BLE_ENABLE 1 //双模工程,默认打开BLE功能使能 +#else +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#endif +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 1 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + + +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 1 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN 0//TCFG_APP_RECORD_EN//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE DISABLE//APP不允许使用该配置 + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR +#define TCFG_LINEIN_CHECK_PORT IO_PORTB_03 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd + +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE ENABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE ENABLE +#define TCFG_DEC_WAV_ENABLE ENABLE +#define TCFG_DEC_FLAC_ENABLE ENABLE +#define TCFG_DEC_APE_ENABLE ENABLE +#define TCFG_DEC_M4A_ENABLE ENABLE +#define TCFG_DEC_ALAC_ENABLE ENABLE +#define TCFG_DEC_AMR_ENABLE ENABLE +#define TCFG_DEC_DTS_ENABLE ENABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE ENABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE +#define TCFG_FM_BK1080_ENABLE DISABLE +#define TCFG_FM_QN8035_ENABLE DISABLE + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE) +#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE))) +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#else +#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif +#else +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/ + +#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE) +#undef TCFG_LED7_RUN_RAM +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/ + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + + +// 0 - 旧闹钟,只支持提示音闹铃 +// 1 - 新闹钟,可选择提示音或者设备音乐作为闹铃 +#define CUR_RTC_ALARM_MODE 1 + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE // +#define TCFG_IIS_OUTPUT_EN ENABLE // +#define TCFG_IIS_OUTPUT_PORT ALINK1_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL (BIT(0)) + +#define TCFG_IIS_INPUT_EN DISABLE// +#define TCFG_IIS_INPUT_PORT ALINK1_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR (44100l) +#define TCFG_IIS_INPUT_DATAPORT_SEL (BIT(0)) + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE ENABLE +#define TCFG_ENC_MSBC_ENABLE ENABLE +#define TCFG_ENC_G726_ENABLE DISABLE +#define TCFG_ENC_MP3_ENABLE ENABLE//DISABLE +#define TCFG_ENC_ADPCM_ENABLE DISABLE +#define TCFG_ENC_PCM_ENABLE ENABLE//DISABLE +#define TCFG_ENC_SBC_ENABLE DISABLE +#define TCFG_ENC_OPUS_ENABLE ENABLE//DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + + +//*********************************************************************************// + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + + + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +#if (SMART_BOX_EN) +#error "音效相关有修改,暂不支持杰理之家APP" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC695X_DEMO +#endif //CONFIG_BOARD_AC695X_DEMO_CFG_H diff --git a/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/adkey_table.c new file mode 100644 index 0000000..d09ce4c --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/adkey_table.c @@ -0,0 +1,356 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_SMARTBOX +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_TWS_SEARCH_REMOVE_PAIR, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_SEND_SPEECH_START, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_UP, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_DOWN, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_MINOR_OPT, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_MINOR_OPT, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_MUSIC_CHANGE_REPEAT, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_MUSIC_FR, KEY_MUSIC_FR, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_MUSIC_FF, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_MINOR_OPT, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/iokey_table.c new file mode 100644 index 0000000..538afc2 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/iokey_table.c @@ -0,0 +1,239 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_SMARTBOX +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/irkey_table.c new file mode 100644 index 0000000..96edf17 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_SMARTBOX +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/rdec_key_table.c new file mode 100644 index 0000000..714e391 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_SMARTBOX +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/touch_key_table.c new file mode 100644 index 0000000..dcfacdc --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_SMARTBOX +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_soundcard/board_ac695x_soundcard.c b/apps/soundbox/board/br23/board_ac695x_soundcard/board_ac695x_soundcard.c new file mode 100644 index 0000000..c742a32 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_soundcard/board_ac695x_soundcard.c @@ -0,0 +1,1144 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC695X_SOUNDCARD + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "asm/spi.h" +#include "norflash.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "asm/ctmu.h" +#include "asm/power/p33.h" +#include "common/user_msg.h" +#include "soundcard/peripheral.h" +#include "audio_dec_board_cfg.h" +#include "ui_manage.h" +#include "soundcard/soundcard.h" +#include "app_power_manage.h" + + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 0, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0|BIT(7), //按键值 + }, + { + .connect_way = ONE_PORT_TO_LOW, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_KEY1_ONE_PORT, //IO按键对应的引脚 + .key_value = 1|BIT(7), //按键值 + }, + { + .connect_way = ONE_PORT_TO_LOW, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_KEY2_ONE_PORT, //IO按键对应的引脚 + .key_value = 2|BIT(7), //按键值 + }, + { + .connect_way = ONE_PORT_TO_LOW, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_KEY3_ONE_PORT, //IO按键对应的引脚 + .key_value = 3|BIT(7), //按键值 + }, + { + .connect_way = ONE_PORT_TO_LOW, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_KEY4_ONE_PORT, //IO按键对应的引脚 + .key_value = 4|BIT(7), //按键值 + }, + { + .connect_way = ONE_PORT_TO_LOW, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_KEY5_ONE_PORT, //IO按键对应的引脚 + .key_value = 5|BIT(7), //按键值 + }, + { + .connect_way = ONE_PORT_TO_LOW, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_KEY6_ONE_PORT, //IO按键对应的引脚 + .key_value = 6|BIT(7), //按键值 + }, + { + .connect_way = DOUBLE_PORT_TO_IO, //IO按键的连接方式 + .key_type.two_io.in_port = TCFG_IOKEY_KEY1_ONE_PORT, //IO按键对应的引脚 + .key_type.two_io.out_port = TCFG_IOKEY_KEY2_ONE_PORT, //IO按键对应的引脚 + .key_value = 7|BIT(7), //按键值 + }, + { + .connect_way = DOUBLE_PORT_TO_IO, //IO按键的连接方式 + .key_type.two_io.in_port = TCFG_IOKEY_KEY1_ONE_PORT, //IO按键对应的引脚 + .key_type.two_io.out_port = TCFG_IOKEY_KEY3_ONE_PORT, //IO按键对应的引脚 + .key_value = 8|BIT(7), //按键值 + }, + { + .connect_way = DOUBLE_PORT_TO_IO, //IO按键的连接方式 + .key_type.two_io.in_port = TCFG_IOKEY_KEY1_ONE_PORT, //IO按键对应的引脚 + .key_type.two_io.out_port = TCFG_IOKEY_KEY4_ONE_PORT, //IO按键对应的引脚 + .key_value = 9|BIT(7), //按键值 + }, + { + .connect_way = DOUBLE_PORT_TO_IO, //IO按键的连接方式 + .key_type.two_io.in_port = TCFG_IOKEY_KEY1_ONE_PORT, //IO按键对应的引脚 + .key_type.two_io.out_port = TCFG_IOKEY_KEY5_ONE_PORT, //IO按键对应的引脚 + .key_value = 10|BIT(7), //按键值 + }, + { + .connect_way = DOUBLE_PORT_TO_IO, //IO按键的连接方式 + .key_type.two_io.in_port = TCFG_IOKEY_KEY1_ONE_PORT, //IO按键对应的引脚 + .key_type.two_io.out_port = TCFG_IOKEY_KEY6_ONE_PORT, //IO按键对应的引脚 + .key_value = 11|BIT(7), //按键值 + }, + { + .connect_way = DOUBLE_PORT_TO_IO, //IO按键的连接方式 + .key_type.two_io.in_port = TCFG_IOKEY_KEY2_ONE_PORT, //IO按键对应的引脚 + .key_type.two_io.out_port = TCFG_IOKEY_KEY3_ONE_PORT, //IO按键对应的引脚 + .key_value = 12|BIT(7), //按键值 + }, + { + .connect_way = DOUBLE_PORT_TO_IO, //IO按键的连接方式 + .key_type.two_io.in_port = TCFG_IOKEY_KEY2_ONE_PORT, //IO按键对应的引脚 + .key_type.two_io.out_port = TCFG_IOKEY_KEY4_ONE_PORT, //IO按键对应的引脚 + .key_value = 13|BIT(7), //按键值 + }, + { + .connect_way = DOUBLE_PORT_TO_IO, //IO按键的连接方式 + .key_type.two_io.in_port = TCFG_IOKEY_KEY2_ONE_PORT, //IO按键对应的引脚 + .key_type.two_io.out_port = TCFG_IOKEY_KEY5_ONE_PORT, //IO按键对应的引脚 + .key_value = 14|BIT(7), //按键值 + }, + { + .connect_way = DOUBLE_PORT_TO_IO, //IO按键的连接方式 + .key_type.two_io.in_port = TCFG_IOKEY_KEY2_ONE_PORT, //IO按键对应的引脚 + .key_type.two_io.out_port = TCFG_IOKEY_KEY6_ONE_PORT, //IO按键对应的引脚 + .key_value = 15|BIT(7), //按键值 + }, + { + .connect_way = DOUBLE_PORT_TO_IO, //IO按键的连接方式 + .key_type.two_io.in_port = TCFG_IOKEY_KEY3_ONE_PORT, //IO按键对应的引脚 + .key_type.two_io.out_port = TCFG_IOKEY_KEY4_ONE_PORT, //IO按键对应的引脚 + .key_value = 16|BIT(7), //按键值 + }, + { + .connect_way = DOUBLE_PORT_TO_IO, //IO按键的连接方式 + .key_type.two_io.in_port = TCFG_IOKEY_KEY3_ONE_PORT, //IO按键对应的引脚 + .key_type.two_io.out_port = TCFG_IOKEY_KEY5_ONE_PORT, //IO按键对应的引脚 + .key_value = 17|BIT(7), //按键值 + }, + { + .connect_way = DOUBLE_PORT_TO_IO, //IO按键的连接方式 + .key_type.two_io.in_port = TCFG_IOKEY_KEY3_ONE_PORT, //IO按键对应的引脚 + .key_type.two_io.out_port = TCFG_IOKEY_KEY6_ONE_PORT, //IO按键对应的引脚 + .key_value = 18|BIT(7), //按键值 + }, +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .press_cfg = TCFG_CTMU_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +#if TCFG_SLIDE_KEY_ENABLE +const struct slidekey_port slidekey_list[] = { + { + .io = IO_PORTB_04, + .io_up_en = 0, + .level = 30, + .ad_channel = AD_CH_PB4, + .msg = KEY_SOUNDCARD_SLIDE_MIC, + }, + { + .io = IO_PORTA_05, + .io_up_en = 0, + .level = 30, + .ad_channel = AD_CH_PA5, + .msg = KEY_SOUNDCARD_SLIDE_WET_GAIN, + }, + { + .io = IO_PORTC_05, + .io_up_en = 0, + .level = 10, + .ad_channel = AD_CH_PC5, + .msg = KEY_SOUNDCARD_SLIDE_HIGH_SOUND, + }, + { + .io = IO_PORTC_04, + .io_up_en = 0, + .level = 10, + .ad_channel = AD_CH_PC4, + .msg = KEY_SOUNDCARD_SLIDE_LOW_SOUND, + }, + { + .io = IO_PORTA_12, + .io_up_en = 0, + .level = 30, + .ad_channel = AD_CH_PA12, + .msg = KEY_SOUNDCARD_SLIDE_RECORD_VOL, + }, + { + .io = IO_PORTA_10, + .io_up_en = 0, + .level = 30, + .ad_channel = AD_CH_PA10, + .msg = KEY_SOUNDCARD_SLIDE_MUSIC_VOL, + }, + { + .io = IO_PORTB_03, + .io_up_en = 0, + .level = 30, + .ad_channel = AD_CH_PB3, + .msg = KEY_SOUNDCARD_SLIDE_EARPHONE_VOL, + }, +}; +const struct slidekey_platform_data slidekey_data = { + .enable = 1, + .num = ARRAY_SIZE(slidekey_list), + .port = slidekey_list, +}; +#endif // TCFG_SLIDE_KEY_ENABLE + + + + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = NO_CONFIG_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if 0 +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; + + +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif +#if TCFG_NORFLASH_DEV_ENABLE + { "norflash", &norflash_dev_ops , (void *)&norflash_dev_data}, +#endif +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTB_01, //唤醒口选择 +}; + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_TOUCH_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + + sdpg_config(1); + +#if 0 /* SPI 屏幕驱动测试 */ + log_info("test tft>>>>>>>\n"); + extern void SPI_LcdTest(); + SPI_LcdTest(); + log_info("test tft over\n"); +#endif + + dev_manager_init(); + + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + +#if 0 + //针对硅mic要输出1给mic供电 + if(!adc_data.mic_capless){ + gpio_set_pull_up(IO_PORTA_04, 0); + gpio_set_pull_down(IO_PORTA_04, 0); + gpio_set_direction(IO_PORTA_04, 0); + gpio_set_output_value(IO_PORTA_04,1); + } +#endif + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +} + + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if 1 //(TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif + + +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); + + + +// 根据每个解码通道的logo来决定启动时候的数字音量等级 +u16 get_ch_digvol_start(char *logo) +{ + u16 music_vol = soundcard_get_music_vol(); + if(music_vol > 100){ + music_vol = 0;//旋钮音量还没有更新之前, 已经启动了, 默认先设置为0 + } + + if (!strcmp(logo, "music_a2dp")) { + return music_vol; + } else if (!strcmp(logo, "music_linein")) { + return music_vol; + } else if (!strcmp(logo, "music_pc")) { + return music_vol; + } else if (!strcmp(logo, "tone_tone")) { + return 20;//100;; + } else if (!strcmp(logo, "mic_mic")) { + return soundcard_get_mic_vol(); + } + return 100; +} + + +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_soundcard/board_ac695x_soundcard.h b/apps/soundbox/board/br23/board_ac695x_soundcard/board_ac695x_soundcard.h new file mode 100644 index 0000000..7495b4e --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_soundcard/board_ac695x_soundcard.h @@ -0,0 +1,1129 @@ +#ifndef CONFIG_BOARD_AC695X_SOUNDCARD_CFG_H +#define CONFIG_BOARD_AC695X_SOUNDCARD_CFG_H + +#ifdef CONFIG_BOARD_AC695X_SOUNDCARD + + + + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 +#define LINEIN_INPUT_WAY_DAC 2 + +#define NO_CONFIG_PORT (-1) + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 0 +#define TCFG_APP_LINEIN_EN 1 +#define TCFG_APP_FM_EN 0 +#define TCFG_APP_PC_EN 1 +#define TCFG_APP_RTC_EN 0 +#define TCFG_APP_RECORD_EN 0 +#define TCFG_APP_SPDIF_EN 0 + + +//*********************************************************************************// +// undef or redef // +//*********************************************************************************// +#ifdef TCFG_DEV_MANAGER_ENABLE +#undef TCFG_DEV_MANAGER_ENABLE +#define TCFG_DEV_MANAGER_ENABLE 0 +#endif + + + + + +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTA_08 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCFG_SW_I2C0_CLK_PORT IO_PORTA_09 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTA_10 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 4000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE DISABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE DISABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#include "usb_std_class_def.h" + +#define TCFG_USB_PORT_CHARGE DISABLE + +///USB 配置重定义 +#ifdef USB_DEVICE_CLASS_CONFIG +#undef USB_DEVICE_CLASS_CONFIG +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS) +#endif//SPK_AUDIO_RATE + +#ifdef SPK_AUDIO_RATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE 44100 +#endif//SPK_AUDIO_RATE + +#ifdef MIC_AUDIO_RATE +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE 44100 +#endif//MIC_AUDIO_RATE + + +#undef USB_MALLOC_ENABLE +#define USB_MALLOC_ENABLE 1 + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE + +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE/*|TCFG_OTG_MODE_CHARGE*/|OTG_DET_DP_ONLY) +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 20 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE ENABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO + +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +#define TCFG_IOKEY_KEY1_ONE_PORT IO_PORTC_03 +#define TCFG_IOKEY_KEY2_ONE_PORT IO_PORTC_02 +#define TCFG_IOKEY_KEY3_ONE_PORT IO_PORTC_01 +#define TCFG_IOKEY_KEY4_ONE_PORT IO_PORTC_00 +#define TCFG_IOKEY_KEY5_ONE_PORT IO_PORTA_11 +#define TCFG_IOKEY_KEY6_ONE_PORT IO_PORTA_09 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_LED_IO_REUSE DISABLE_THIS_MOUDLE //ADKEY 和 LED IO复用,led只能设置蓝灯显示 +#define TCFG_ADKEY_PORT IO_PORTA_10 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PA10 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTA_00 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTA_01 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + + +//*********************************************************************************// +// slide_key 配置 // +//*********************************************************************************// +#define TCFG_SLIDE_KEY_ENABLE ENABLE_THIS_MOUDLE //是否使能电位器 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 + DAC_OUTPUT_FRONT_LR_REAR_LR 四声道输出 +*/ +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC //LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +// 每个解码通道都开启数字音量管理 +#define SYS_DIGVOL_GROUP_EN ENABLE +#define AUDIO_VOL_MANUAL ENABLE//手动调节系统音量 + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define SYS_VOL_TYPE VOL_TYPE_ANALOG//VOL_TYPE_DIGITAL_HW +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE ENABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE DISABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + + +#define TCFG_LED7_RUN_RAM DISABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) + +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 1 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 0 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 0 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 0 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 0 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 0 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 0 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 0 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 0 //DRC总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 0 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 0 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 0 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 0 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 0 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 0 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif + +#endif +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE +#define TCFG_USB_MIC_DATA_FROM_DAC 1//DISABLE //要与混响一同使用 +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 1 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 1 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 4000//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +#define TCFG_MIXER_CYCLIC_TASK_EN 0//ENABLE // 循环mixer使能任务输出 + +//*********************************************************************************// +// AI配置 // +//*********************************************************************************// + +#define CONFIG_APP_BT_ENABLE // AI功能、流程总开关 + +#ifdef CONFIG_APP_BT_ENABLE +#define TRANS_DATA_EN 0 +#define SMART_BOX_EN 1 +#else +#define TRANS_DATA_EN 0 +#define SMART_BOX_EN 0 +#endif + +#if (SMART_BOX_EN) //rcsp需要打开ble +#define RCSP_UPDATE_EN 1 //是否支持rcsp升级 +#define OTA_TWS_SAME_TIME_ENABLE 0 //是否支持TWS同步升级 +#define UPDATE_MD5_ENABLE 1 //升级是否支持MD5校验 +#define RCSP_FILE_OPT 0 +#define JL_EARPHONE_APP_EN 1 +#define TCFG_LFN_EN 0 +#define TCFG_BS_DEV_PATH_EN 0 +#else +#define OTA_TWS_SAME_TIME_ENABLE 0 +#define RCSP_UPDATE_EN 0 +#define UPDATE_MD5_ENABLE 0 //升级是否支持MD5校验 +#define RCSP_FILE_OPT 0 +#define JL_EARPHONE_APP_EN 0 +#endif + +#if RCSP_UPDATE_EN +#define APP_UPDATE_EN 0 //需要使用APP升级的话要把该宏打开 +//#define CONFIG_SPP_AND_LE_CASE_ENABLE 1 //选择升级对应的isd_config.ini文件 +#else +#define APP_UPDATE_EN 0 //客户如需要开发自己的app升级协议需要把这个宏打开,并提供升级需要的read\seek等接口,具体请参照说明文档 +// #define CONFIG_SPP_AND_LE_CASE_ENABLE 0 +#endif + +#if (SMART_BOX_EN) +#undef JL_SMART_BOX_CUSTOM_APP_EN +#define JL_SMART_BOX_CUSTOM_APP_EN +#endif + +#ifdef JL_SMART_BOX_CUSTOM_APP_EN + +#define SMARTBOX_SPP_INTERACTIVE_SUPPORT 1 +#define SMARTBOX_BLE_INTERACTIVE_SUPPORT 1 + +#define RCSP_USE_BLE 0 +#define RCSP_USE_SPP 1 +#define RCSP_CHANNEL_SEL RCSP_USE_SPP + +#define RCSP_ADV_NAME_SET_ENABLE 1 +#define RCSP_ADV_KEY_SET_ENABLE 0 +#define RCSP_ADV_LED_SET_ENABLE 0 +#define RCSP_ADV_MIC_SET_ENABLE 0 +#define RCSP_ADV_WORK_SET_ENABLE 0 +#define RCSP_ADV_MUSIC_INFO_ENABLE 1 +#define RCSP_ADV_PRODUCT_MSG_ENABLE 1 +#define RCSP_ADV_COLOR_LED_SET_ENABLE 1 +#define RCSP_ADV_KARAOKE_SET_ENABLE 1 +#define RCSP_ADV_KARAOKE_EQ_SET_ENABLE 1 + +#define RCSP_SOUND_EFFECT_FUNC_DISABLE 1 + +#if RCSP_SOUND_EFFECT_FUNC_DISABLE +#define RCSP_ADV_HIGH_LOW_SET 0 +#define RCSP_ADV_EQ_SET_ENABLE 0 +#define RCSP_ADV_FIND_DEVICE_ENABLE 0 +#else +#define RCSP_ADV_HIGH_LOW_SET 1 +#define RCSP_ADV_EQ_SET_ENABLE 1 +#define RCSP_ADV_FIND_DEVICE_ENABLE 1 +#endif + +#endif + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 0 //tws功能使能 +#ifdef CONFIG_APP_BT_ENABLE +#define TCFG_USER_BLE_ENABLE 1 //双模工程,默认打开BLE功能使能 +#else +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#endif +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 0 +#define USER_SUPPORT_PROFILE_HFP 0 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 0 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 + +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 0 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 1 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 1 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN DISABLE//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE DISABLE//音乐播放录音区分使能 + + +#if RECORDER_MIX_EN//限制不能同时打开 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE +#endif + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN1_LR // 如果需要使能一路AUX走数字, 另外两路走模拟直达, 必须走数字那一路是选择AUX1, 并且初始化要求是先初始化数字, 在打开模拟,请注意 +#define TCFG_LINEIN_DETECT_ENABLE DISABLE +#define TCFG_LINEIN_CHECK_PORT IO_PORTB_03 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd + +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE DISABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE DISABLE +#define TCFG_DEC_WAV_ENABLE DISABLE +#define TCFG_DEC_FLAC_ENABLE DISABLE +#define TCFG_DEC_APE_ENABLE DISABLE +#define TCFG_DEC_M4A_ENABLE DISABLE +#define TCFG_DEC_ALAC_ENABLE DISABLE +#define TCFG_DEC_AMR_ENABLE DISABLE +#define TCFG_DEC_DTS_ENABLE DISABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE DISABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE +#define TCFG_FM_BK1080_ENABLE DISABLE +#define TCFG_FM_QN8035_ENABLE DISABLE + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE) +#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE))) +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#else +#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif +#else +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/ + +#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE) +#undef TCFG_LED7_RUN_RAM +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/ + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE DISABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE // +#define TCFG_IIS_OUTPUT_EN ENABLE // +#define TCFG_IIS_OUTPUT_PORT ALINK1_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL (BIT(0)) + +#define TCFG_IIS_INPUT_EN DISABLE// +#define TCFG_IIS_INPUT_PORT ALINK1_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR (44100l) +#define TCFG_IIS_INPUT_DATAPORT_SEL (BIT(0)) + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE DISABLE +#define TCFG_ENC_MSBC_ENABLE DISABLE +#define TCFG_ENC_G726_ENABLE DISABLE +#define TCFG_ENC_MP3_ENABLE DISABLE +#define TCFG_ENC_ADPCM_ENABLE DISABLE +#define TCFG_ENC_PCM_ENABLE DISABLE +#define TCFG_ENC_SBC_ENABLE DISABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + +//*********************************************************************************// +// 启用三路ADC接口 +//*********************************************************************************// +// #if((TCFG_REVERB_ENABLE) && (LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ADC)) +// #define THREE_ADC_ENABLE +// #endif + +//*********************************************************************************// +// 四声道的 RL RR是否合成后输出 +//*********************************************************************************// + +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) +#define RL_RR_MIX_ENABLE 1 +#endif + +//*********************************************************************************// +// SOUNDCARD配置 // +//*********************************************************************************// +#define SOUNDCARD_ENABLE ENABLE_THIS_MOUDLE + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC695X_DEMO +#endif //CONFIG_BOARD_AC695X_DEMO_CFG_H diff --git a/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/adkey_table.c new file mode 100644 index 0000000..f850ffa --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/adkey_table.c @@ -0,0 +1,356 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_SOUNDCARD +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_CHANGE_REPEAT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_NULL, KEY_MUSIC_FR, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [5] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/iokey_table.c new file mode 100644 index 0000000..3dbbe83 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/iokey_table.c @@ -0,0 +1,317 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_SOUNDCARD +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_SOUNDCARD_USB_MIC_MUTE_SWICH, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_SOUNDCARD_MODE_ELECTRIC, KEY_NULL, KEY_SOUNDCARD_MODE_ELECTRIC_CANCEL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_SOUNDCARD_MODE_PITCH, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_SOUNDCARD_MODE_MAGIC, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_SOUNDCARD_MODE_BOOM, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_SOUNDCARD_MODE_SHOUTING_WHEAT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_SOUNDCARD_MODE_DODGE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_SOUNDCARD_MAKE_NOISE0, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_SOUNDCARD_MAKE_NOISE1, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_SOUNDCARD_MAKE_NOISE2, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_SOUNDCARD_MAKE_NOISE3, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_SOUNDCARD_MAKE_NOISE4, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_SOUNDCARD_MAKE_NOISE5, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_SOUNDCARD_MAKE_NOISE6, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_SOUNDCARD_MAKE_NOISE7, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_SOUNDCARD_MAKE_NOISE8, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_SOUNDCARD_MAKE_NOISE9, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_SOUNDCARD_MAKE_NOISE10, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_SOUNDCARD_MAKE_NOISE11, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_SOUNDCARD_USB_MIC_MUTE_SWICH, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_SOUNDCARD_MODE_ELECTRIC, KEY_NULL, KEY_SOUNDCARD_MODE_ELECTRIC_CANCEL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_SOUNDCARD_MODE_PITCH, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_SOUNDCARD_MODE_MAGIC, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_SOUNDCARD_MODE_BOOM, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_SOUNDCARD_MODE_SHOUTING_WHEAT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_SOUNDCARD_MODE_DODGE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_SOUNDCARD_MAKE_NOISE0, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_SOUNDCARD_MAKE_NOISE1, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_SOUNDCARD_MAKE_NOISE2, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_SOUNDCARD_MAKE_NOISE3, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_SOUNDCARD_MAKE_NOISE4, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_SOUNDCARD_MAKE_NOISE5, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_SOUNDCARD_MAKE_NOISE6, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_SOUNDCARD_MAKE_NOISE7, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_SOUNDCARD_MAKE_NOISE8, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_SOUNDCARD_MAKE_NOISE9, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_SOUNDCARD_MAKE_NOISE10, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_SOUNDCARD_MAKE_NOISE11, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/irkey_table.c new file mode 100644 index 0000000..160de52 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_SOUNDCARD +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/rdec_key_table.c new file mode 100644 index 0000000..f0b1c97 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_SOUNDCARD +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/touch_key_table.c new file mode 100644 index 0000000..59d5341 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_SOUNDCARD +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_tws/board_ac695x_tws.c b/apps/soundbox/board/br23/board_ac695x_tws/board_ac695x_tws.c new file mode 100644 index 0000000..376273e --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_tws/board_ac695x_tws.c @@ -0,0 +1,1078 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC695X_TWS + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "fm/fm_manage.h" +#include "asm/power/p33.h" +#include "norflash.h" +#include "asm/spi.h" +#include "ui_manage.h" +#include "spi/nor_fs.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, + .key_value = 2, + }, +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, +#if TCFG_SD1_ENABLE + .pin_cfg.pin7.pin[0] = IO_PORTA_02, + .pin_cfg.pin7.pin[1] = IO_PORTA_03, + .pin_cfg.pin7.pin[2] = IO_PORTA_04, + .pin_cfg.pin7.pin[3] = IO_PORTA_06, + .pin_cfg.pin7.pin[4] = IO_PORTA_07, + .pin_cfg.pin7.pin[5] = IO_PORTA_08, + .pin_cfg.pin7.pin[6] = IO_PORTA_09, +#else + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if 0 +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; + + +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NOR_FAT +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 0, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_FS +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 1*1024*1024, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_REC +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 2*1024*1024, + .size = 2*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_FM_ENABLE + +FM_DEV_PLATFORM_DATA_BEGIN(fm_dev_data) + .iic_hdl = 0, + .iic_delay = 50, +FM_DEV_PLATFORM_DATA_END(); + +#endif + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +#if TCFG_NOR_FAT + { "fat_nor", &norflash_dev_ops , (void *)&norflash_fat_dev_data}, +#endif + +#if TCFG_NOR_FS + { "res_nor", &norfs_dev_ops , (void *)&norflash_norfs_dev_data}, +#endif + +#if TCFG_NOR_REC + {"rec_nor", &norfs_dev_ops , (void *)&norflash_norfs_rec_dev_data}, +#endif +#endif +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTA_10, //唤醒口选择 +}; + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} +static void key_wakeup_disable() +{ + power_wakeup_index_disable(1); +} +static void key_wakeup_enable() +{ + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); +#if TCFG_PWMLED_ENABLE + if(power_param.osc_type == OSC_TYPE_BT_OSC){//LRC EN + p33_tx_1byte(P3_LRC_CON0, 0x41); + p33_tx_1byte(P3_LRC_CON1, 0x3e); + } +#endif + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + +#if TCFG_FM_ENABLE + fm_dev_init(&fm_dev_data); +#endif + +#if TCFG_NOR_REC + nor_fs_ops_init(); +#endif + +#if TCFG_NOR_FS + init_norsdfile_hdl(); +#endif + +#if FLASH_INSIDE_REC_ENABLE + sdfile_rec_ops_init(); +#endif + + dev_manager_init(); + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + //针对硅mic要输出1给mic供电(按实际使用情况配置) + /* if(!adc_data.mic_capless){ */ + /* gpio_set_pull_up(IO_PORTA_04, 0); */ + /* gpio_set_pull_down(IO_PORTA_04, 0); */ + /* gpio_set_direction(IO_PORTA_04, 0); */ + /* gpio_set_output_value(IO_PORTA_04,1); */ + /* } */ + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +#if USER_UART_UPDATE_ENABLE + { +#include "uart_update.h" + uart_update_cfg update_cfg = { + .rx = IO_PORTA_02, + .tx = IO_PORTA_03, + .output_channel = CH1_UT1_TX, + .input_channel = INPUT_CH0 + }; + uart_update_init(&update_cfg); + } +#endif +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + key_wakeup_enable(); + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); + key_wakeup_disable(); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + key_wakeup_enable(); + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); + key_wakeup_disable(); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_tws/board_ac695x_tws.h b/apps/soundbox/board/br23/board_ac695x_tws/board_ac695x_tws.h new file mode 100644 index 0000000..a4d10bd --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_tws/board_ac695x_tws.h @@ -0,0 +1,1000 @@ +#ifndef CONFIG_BOARD_AC695X_TWS_CFG_H +#define CONFIG_BOARD_AC695X_TWS_CFG_H + +#ifdef CONFIG_BOARD_AC695X_TWS + +///// + + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 +#define LINEIN_INPUT_WAY_DAC 2 + +#define NO_CONFIG_PORT (-1) + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 0 +#define TCFG_APP_LINEIN_EN 0 +#define TCFG_APP_FM_EN 0 +#define TCFG_APP_PC_EN 0 +#define TCFG_APP_RTC_EN 0 +#define TCFG_APP_RECORD_EN 0 +#define TCFG_APP_SPDIF_EN 0 +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTA_05 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCFG_SW_I2C0_CLK_PORT IO_PORTA_09 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTA_10 //软件IIC DAT脚选择 +#define TCFG_SW_I2C0_DELAY_CNT 50 //IIC延时参数,影响通讯时钟频率 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 4000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE DISABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#include "usb_std_class_def.h" + + +#define TCFG_USB_PORT_CHARGE DISABLE + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DP_ONLY) + +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO + +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_LED_IO_REUSE DISABLE_THIS_MOUDLE //ADKEY 和 LED IO复用,led只能设置蓝灯显示 +#define TCFG_ADKEY_PORT IO_PORTA_10 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PA10 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 +*/ +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +// 每个解码通道都开启数字音量管理 +#define SYS_DIGVOL_GROUP_EN DISABLE + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define VOL_TYPE_DIGGROUP 4 //独立通道数字音量 + +//每个解码通道都开启数字音量管理,音量类型为VOL_TYPE_DIGGROUP时要使能 +#define SYS_DIGVOL_GROUP_EN DISABLE + +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE ENABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE DISABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + +#define TCFG_LED7_RUN_RAM DISABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 1 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 1 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 1 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 0 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 0 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 0 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 0 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 0 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 0 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 0 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 0 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 0 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 0 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 0 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 0 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif + +#endif +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 1 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 4000//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +#define TCFG_AUDIO_DEC_OUT_TASK 0 // 解码使用单独任务做输出 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 1 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 0 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + + +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 1 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 180 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 0 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 0 //后台模式 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && defined(CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 0 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 0 // pcm编码转发 +#define TCFG_PCM2TWS_SBC_ENABLE 0 // pcm转发采样sbc编码 +#define TCFG_TONE2TWS_ENABLE 0 // 提示音转发 +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_PCM2TWS_SBC_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#endif + + + +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN DISABLE//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE DISABLE//音乐播放录音区分使能 + + +#if RECORDER_MIX_EN//限制不能同时打开 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE +#endif + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR +#define TCFG_LINEIN_CHECK_PORT IO_PORTB_03 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC//LINEIN_INPUT_WAY_ANALOG +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd + +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE ENABLE +#define TCFG_DEC_MP3_ENABLE DISABLE +#define TCFG_DEC_WMA_ENABLE DISABLE +#define TCFG_DEC_WAV_ENABLE DISABLE +#define TCFG_DEC_FLAC_ENABLE DISABLE +#define TCFG_DEC_APE_ENABLE DISABLE +#define TCFG_DEC_M4A_ENABLE DISABLE +#define TCFG_DEC_ALAC_ENABLE DISABLE +#define TCFG_DEC_AMR_ENABLE 0//ENABLE +#define TCFG_DEC_DTS_ENABLE 0//ENABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE DISABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE +#define TCFG_FM_BK1080_ENABLE DISABLE +#define TCFG_FM_QN8035_ENABLE DISABLE + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ANALOG + +#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE) +#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE))) +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#else +#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif +#else +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/ + +#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE) +#undef TCFG_LED7_RUN_RAM +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/ + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE DISABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE // +#define TCFG_IIS_OUTPUT_EN ENABLE // +#define TCFG_IIS_OUTPUT_PORT ALINK1_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL (BIT(0)) + +#define TCFG_IIS_INPUT_EN DISABLE// +#define TCFG_IIS_INPUT_PORT ALINK1_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR (44100l) +#define TCFG_IIS_INPUT_DATAPORT_SEL (BIT(0)) + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE ENABLE +#define TCFG_ENC_MSBC_ENABLE ENABLE +#define TCFG_ENC_G726_ENABLE ENABLE +#define TCFG_ENC_MP3_ENABLE DISABLE +#define TCFG_ENC_ADPCM_ENABLE DISABLE +#define TCFG_ENC_PCM_ENABLE DISABLE +#define TCFG_ENC_SBC_ENABLE DISABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + +//*********************************************************************************// +//ali ai profile +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 0 //not surport +#define ANCS_CLIENT_EN 0 + +#if (DUEROS_DMA_EN || TRANS_DATA_EN || ANCS_CLIENT_EN) +#define BT_FOR_APP_EN 1 +#else +#define BT_FOR_APP_EN 0 +#endif + +//*********************************************************************************// + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 0 + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 + +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +#error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC695X_DEMO +#endif //CONFIG_BOARD_AC695X_DEMO_CFG_H diff --git a/apps/soundbox/board/br23/board_ac695x_tws/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac695x_tws/key_table/adkey_table.c new file mode 100644 index 0000000..654268e --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_tws/key_table/adkey_table.c @@ -0,0 +1,356 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_TWS +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_TWS_SEARCH_REMOVE_PAIR, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_UP, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_DOWN, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_MUSIC_CHANGE_REPEAT, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_MUSIC_FR, KEY_MUSIC_FR, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_MUSIC_FF, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_tws/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac695x_tws/key_table/iokey_table.c new file mode 100644 index 0000000..ad586e4 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_tws/key_table/iokey_table.c @@ -0,0 +1,239 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_TWS +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_tws/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac695x_tws/key_table/irkey_table.c new file mode 100644 index 0000000..187d359 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_tws/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_TWS +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_tws/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac695x_tws/key_table/rdec_key_table.c new file mode 100644 index 0000000..3b4c8b5 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_tws/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_TWS +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_tws/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac695x_tws/key_table/touch_key_table.c new file mode 100644 index 0000000..49b62ee --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_tws/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_TWS +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_tws_box/board_ac695x_tws_box.c b/apps/soundbox/board/br23/board_ac695x_tws_box/board_ac695x_tws_box.c new file mode 100644 index 0000000..5f59cd8 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_tws_box/board_ac695x_tws_box.c @@ -0,0 +1,1122 @@ +#include "app_config.h" + +#ifdef CONFIG_BOARD_AC695X_TWS_BOX + +#include "system/includes.h" +#include "media/includes.h" +#include "asm/sdmmc.h" +#include "asm/chargestore.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/rtc.h" +#include "tone_player.h" +#include "audio_config.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" +#include "gSensor/gSensor_manage.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "linein/linein_dev.h" +#include "usb/otg.h" +#include "ui/ui_api.h" +#include "dev_manager.h" +#include "fm/fm_manage.h" +#include "asm/power/p33.h" +#include "norflash.h" +#include "asm/spi.h" +#include "ui_manage.h" +#include "spi/nor_fs.h" +#include "audio_link.h" +#include "app_power_manage.h" + +#define LOG_TAG_CONST BOARD +#define LOG_TAG "[BOARD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void board_power_init(void); + +/*各个状态下默认的闪灯方式和提示音设置,如果USER_CFG中设置了USE_CONFIG_STATUS_SETTING为1,则会从配置文件读取对应的配置来填充改结构体*/ +STATUS_CONFIG status_config = { + //提示音设置 + .tone = { + .charge_start = IDEX_TONE_NONE, + .charge_full = IDEX_TONE_NONE, + .power_on = IDEX_TONE_POWER_ON, + .power_off = IDEX_TONE_POWER_OFF, + .lowpower = IDEX_TONE_LOW_POWER, + .max_vol = IDEX_TONE_MAX_VOL, + .phone_in = IDEX_TONE_NONE, + .phone_out = IDEX_TONE_NONE, + .phone_activ = IDEX_TONE_NONE, + .bt_init_ok = IDEX_TONE_BT_MODE, + .bt_connect_ok = IDEX_TONE_BT_CONN, + .bt_disconnect = IDEX_TONE_BT_DISCONN, + .tws_connect_ok = IDEX_TONE_TWS_CONN, + .tws_disconnect = IDEX_TONE_TWS_DISCONN, + } +}; + +#define __this (&status_config) + + +// *INDENT-OFF* +/************************** UART config****************************/ +#if TCFG_UART0_ENABLE +UART0_PLATFORM_DATA_BEGIN(uart0_data) + .tx_pin = TCFG_UART0_TX_PORT, + .rx_pin = TCFG_UART0_RX_PORT, + .baudrate = TCFG_UART0_BAUDRATE, + + .flags = UART_DEBUG, +UART0_PLATFORM_DATA_END() +#endif //TCFG_UART0_ENABLE + + +/************************** SD config ****************************/ +#if TCFG_SD0_ENABLE +/* int sdmmc_0_io_detect(const struct sdmmc_platform_data *data) */ +/* { */ +/* return 1; */ +/* } */ + +/* void sd_set_power(u8 enable) */ +/* { */ +/* static u8 old_enable = 0xff; */ +/* */ +/* if(old_enable == enable){ */ +/* return; */ +/* } */ +/* if(enable){ */ +/* sdpg_config(1); */ +/* }else{ */ +/* sdpg_config(0); */ +/* } */ +/* old_enable = enable; */ +/* } */ + +SD0_PLATFORM_DATA_BEGIN(sd0_data) +// .port = 'B', //sd0 support port 'A' and port 'B' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD0_PORTS, //sd0 support port 'A' and port 'B' + .data_width = TCFG_SD0_DAT_MODE, + .speed = TCFG_SD0_CLK, + .detect_mode = TCFG_SD0_DET_MODE, + + .priority = 3, +#if (TCFG_SD0_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD0_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD0_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD0_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_0_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD0_PLATFORM_DATA_END() +#endif + +#if TCFG_SD1_ENABLE +SD1_PLATFORM_DATA_BEGIN(sd1_data) +// .port = 'A', //sd1 only support port 'A' +// .data_width = 1, +// .speed = 3000000, +// .detect_mode = SD_CMD_DECT, + .port = TCFG_SD1_PORTS, //sd1 only support port 'A' + .data_width = TCFG_SD1_DAT_MODE, + .speed = TCFG_SD1_CLK, + .detect_mode = TCFG_SD1_DET_MODE, + + .priority = 3, +#if (TCFG_SD1_DET_MODE == SD_IO_DECT) + .detect_io = TCFG_SD1_DET_IO,//当检测模式为io口检测是有效 + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_io_detect,//库函数,需要detect_io和detect_io_level两个元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#elif (TCFG_SD1_DET_MODE == SD_CLK_DECT) + .detect_io_level = TCFG_SD1_DET_IO_LEVEL,//0:低电平检测到卡。 1:高电平检测到卡 + .detect_func = sdmmc_1_clk_detect,//库函数,需要detect_io_level元素作为参数。可以自行重写一个检测函数,在线返回1,不在线返回0,即可。 + .power = sd_set_power,//库函数,使用SDPG引脚。可以自行重写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。如果电源硬件已固定不可控,则该函数无效,可以填NULL + /* .power = NULL, */ +#else + .detect_func = sdmmc_cmd_detect, + .power = NULL,//cmd检测需要全程供电,建议用硬件固定电源。当然,可以自行写其他的SD卡电源控制函数,传入0:关电源。传入1,开电源。 + /* .power = sd_set_power, */ +#endif +SD1_PLATFORM_DATA_END() +#endif + + +/************************** CHARGE config****************************/ +#if TCFG_CHARGE_ENABLE +CHARGE_PLATFORM_DATA_BEGIN(charge_data) + .charge_en = TCFG_CHARGE_ENABLE, //内置充电使能 + .charge_poweron_en = TCFG_CHARGE_POWERON_ENABLE, //是否支持充电开机 + .charge_full_V = TCFG_CHARGE_FULL_V, //充电截止电压 + .charge_full_mA = TCFG_CHARGE_FULL_MA, //充电截止电流 + .charge_mA = TCFG_CHARGE_MA, //充电电流 +/*ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出 + 对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的 + 充电仓,需要根据实际情况设置该值大小*/ + .ldo5v_off_filter = 100, +/*ldo5v的10k下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1,默认值设置为1 + 对于充电舱需要按键升压,且维持电压是从充电舱经过上拉电阻到充电口的舱,请将该值改为0*/ + .ldo5v_pulldown_en = 1, +CHARGE_PLATFORM_DATA_END() +#endif//TCFG_CHARGE_ENABLE + +#if TCFG_IIS_ENABLE +ALINK_PARM alink0_param = { + .port_select = ALINK0_PORTA, //MCLK:PA8 SCLK:PA2 LRCK:PA3 CH0:PA4 CH1:PA5 CH2:PA6 CH3:PA7 + /* .port_select = ALINK0_PORTB, //MCLK:PA15 SCLK:PA9 LRCK:PA10 CH0:PA11 CH1:PA12 CH2:PA13 CH3:PA14 */ + /* .port_select = ALINK1_PORTA, //MCLK:PB0 SCLK:PC0 LRCK:PC1 CH0:PC2 CH1:PC3 CH2:PC4 CH3:PC5 */ + .ch_cfg[0].enable = 1, + .ch_cfg[1].enable = 1, + .mode = ALINK_MD_IIS, +#if TCFG_IIS_MODE + .role = ALINK_ROLE_SLAVE, +#else + .role = ALINK_ROLE_MASTER, +#endif + .clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE, + .bitwide = ALINK_LEN_16BIT, + .sclk_per_frame = ALINK_FRAME_64SCLK, + .dma_len = ALNK_BUF_POINTS_NUM * 2 * 2 * 2, + .sample_rate = TCFG_IIS_OUTPUT_SR, +}; + +ALINK_PARM alink1_param = { + /* .port_select = ALINK0_PORTA, //MCLK:PA8 SCLK:PA2 LRCK:PA3 CH0:PA4 CH1:PA5 CH2:PA6 CH3:PA7 */ + /* .port_select = ALINK0_PORTB, //MCLK:PA15 SCLK:PA9 LRCK:PA10 CH0:PA11 CH1:PA12 CH2:PA13 CH3:PA14 */ + .port_select = ALINK1_PORTA, //MCLK:PB0 SCLK:PC0 LRCK:PC1 CH0:PC2 CH1:PC3 CH2:PC4 CH3:PC5 + .ch_cfg[0].enable = 1, + .ch_cfg[1].enable = 1, + .mode = ALINK_MD_IIS, +#if TCFG_IIS_MODE + .role = ALINK_ROLE_SLAVE, +#else + .role = ALINK_ROLE_MASTER, +#endif + .clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE, + .bitwide = ALINK_LEN_16BIT, + .sclk_per_frame = ALINK_FRAME_64SCLK, + .dma_len = ALNK_BUF_POINTS_NUM * 2 * 2 * 2, + .sample_rate = TCFG_IIS_OUTPUT_SR, +}; + + +#endif + +/************************** DAC ****************************/ +#if TCFG_AUDIO_DAC_ENABLE +struct dac_platform_data dac_data = { + .ldo_volt = TCFG_AUDIO_DAC_LDO_VOLT, //DACVDD等级.需要根据具体硬件来设置(高低压)可选:1.2V/1.3V/2.35V/2.5V/2.65V/2.8V/2.95V/3.1V +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .vcmo_en = 0, //四声道与双声道差分关闭VCOMO +#else + .vcmo_en = 1, //是否打开VCOMO +#endif + .output = TCFG_AUDIO_DAC_CONNECT_MODE, //DAC输出配置,和具体硬件连接有关,需根据硬件来设置 + .ldo_isel = 3, + .ldo_fb_isel = 2, + .lpf_isel = 0x8, +}; +#endif + +/************************** ADC ****************************/ +#if TCFG_AUDIO_ADC_ENABLE +struct adc_platform_data adc_data = { +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ + .mic_ldo_isel = TCFG_AUDIO_ADC_LDO_SEL, +/*MIC 是否省隔直电容: + 0: 不省电容 1: 省电容 */ +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + .mic_capless = 0,//四声道与双声道差分使用,不省电容接法 +#else + .mic_capless = TCFG_MIC_CAPLESS_ENABLE, +#endif +/*MIC内部上拉电阻挡位配置,影响MIC的偏置电压 + 21:1.18K 20:1.42K 19:1.55K 18:1.99K 17:2.2K 16:2.4K 15:2.6K 14:2.91K 13:3.05K 12:3.5K 11:3.73K + 10:3.91K 9:4.41K 8:5.0K 7:5.6K 6:6K 5:6.5K 4:7K 3:7.6K 2:8.0K 1:8.5K */ + .mic_bias_res = 16, +/*MIC LDO电压档位设置,也会影响MIC的偏置电压 + 0:2.3v 1:2.5v 2:2.7v 3:3.0v */ + .mic_ldo_vsel = 2, +/*MIC电容隔直模式使用内部mic偏置(PC7)*/ + .mic_bias_inside = 1, +/*保持内部mic偏置输出*/ + .mic_bias_keep = 0, +}; +#endif/*TCFG_AUDIO_ADC_ENABLE*/ + +/************************** IO KEY ****************************/ +#if TCFG_IOKEY_ENABLE +const struct iokey_port iokey_list[] = { + { + .connect_way = TCFG_IOKEY_POWER_CONNECT_WAY, //IO按键的连接方式 + .key_type.one_io.port = TCFG_IOKEY_POWER_ONE_PORT, //IO按键对应的引脚 + .key_value = 0, //按键值 + }, + + { + .connect_way = TCFG_IOKEY_PREV_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_PREV_ONE_PORT, + .key_value = 1, + }, + + { + .connect_way = TCFG_IOKEY_NEXT_CONNECT_WAY, + .key_type.one_io.port = TCFG_IOKEY_NEXT_ONE_PORT, + .key_value = 2, + }, +}; +const struct iokey_platform_data iokey_data = { + .enable = TCFG_IOKEY_ENABLE, //是否使能IO按键 + .num = ARRAY_SIZE(iokey_list), //IO按键的个数 + .port = iokey_list, //IO按键参数表 +}; + +#if MULT_KEY_ENABLE +//组合按键消息映射表 +//配置注意事项:单个按键按键值需要按照顺序编号,如power:0, prev:1, next:2 +//bit_value = BIT(0) | BIT(1) 指按键值为0和按键值为1的两个按键被同时按下, +//remap_value = 3指当这两个按键被同时按下后重新映射的按键值; +const struct key_remap iokey_remap_table[] = { + {.bit_value = BIT(0) | BIT(1), .remap_value = 3}, + {.bit_value = BIT(0) | BIT(2), .remap_value = 4}, + {.bit_value = BIT(1) | BIT(2), .remap_value = 5}, +}; + +const struct key_remap_data iokey_remap_data = { + .remap_num = ARRAY_SIZE(iokey_remap_table), + .table = iokey_remap_table, +}; +#endif + +#endif + +/************************** AD KEY ****************************/ +#if TCFG_ADKEY_ENABLE +const struct adkey_platform_data adkey_data = { + .enable = TCFG_ADKEY_ENABLE, //AD按键使能 + .adkey_pin = TCFG_ADKEY_PORT, //AD按键对应引脚 + .ad_channel = TCFG_ADKEY_AD_CHANNEL, //AD通道值 + .extern_up_en = TCFG_ADKEY_EXTERN_UP_ENABLE, //是否使用外接上拉电阻 + .ad_value = { //根据电阻算出来的电压值 + TCFG_ADKEY_VOLTAGE0, + TCFG_ADKEY_VOLTAGE1, + TCFG_ADKEY_VOLTAGE2, + TCFG_ADKEY_VOLTAGE3, + TCFG_ADKEY_VOLTAGE4, + TCFG_ADKEY_VOLTAGE5, + TCFG_ADKEY_VOLTAGE6, + TCFG_ADKEY_VOLTAGE7, + TCFG_ADKEY_VOLTAGE8, + TCFG_ADKEY_VOLTAGE9, + }, + .key_value = { //AD按键各个按键的键值 + TCFG_ADKEY_VALUE0, + TCFG_ADKEY_VALUE1, + TCFG_ADKEY_VALUE2, + TCFG_ADKEY_VALUE3, + TCFG_ADKEY_VALUE4, + TCFG_ADKEY_VALUE5, + TCFG_ADKEY_VALUE6, + TCFG_ADKEY_VALUE7, + TCFG_ADKEY_VALUE8, + TCFG_ADKEY_VALUE9, + }, +}; +#endif + + +/************************** IR KEY ****************************/ +#if TCFG_IRKEY_ENABLE +const struct irkey_platform_data irkey_data = { + .enable = TCFG_IRKEY_ENABLE, //IR按键使能 + .port = TCFG_IRKEY_PORT, //IR按键口 +}; +#endif + + +/************************** TOUCH_KEY ****************************/ +#if TCFG_TOUCH_KEY_ENABLE +const struct touch_key_port touch_key_list[] = { + { + .port = TCFG_TOUCH_KEY0_PORT, + .key_value = TCFG_TOUCH_KEY0_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, + + { + .port = TCFG_TOUCH_KEY1_PORT, + .key_value = TCFG_TOUCH_KEY1_VALUE, //该值由时钟配置和硬件结构决定, 需要调试 + }, +}; + +const struct touch_key_platform_data touch_key_data = { + .num = ARRAY_SIZE(touch_key_list), + .clock = TCFG_TOUCH_KEY_CLK, + .change_gain = TCFG_TOUCH_KEY_CHANGE_GAIN, + .press_cfg = TCFG_TOUCH_KEY_PRESS_CFG, + .release_cfg0 = TCFG_TOUCH_KEY_RELEASE_CFG0, + .release_cfg1 = TCFG_TOUCH_KEY_RELEASE_CFG1, + .port_list = touch_key_list, +}; +#endif /* #if TCFG_TOUCH_KEY_ENABLE */ + +/**************************CTMU_TOUCH_KEY ****************************/ +#if TCFG_CTMU_TOUCH_KEY_ENABLE +#include "asm/ctmu.h" +static const struct ctmu_key_port touch_ctmu_port[] = { + { + .port = TCFG_CTMU_TOUCH_KEY0_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY0_VALUE, + }, + { + .port = TCFG_CTMU_TOUCH_KEY1_PORT, + .key_value = TCFG_CTMU_TOUCH_KEY1_VALUE, + }, +}; + +const struct ctmu_touch_key_platform_data ctmu_touch_key_data = { + .num = ARRAY_SIZE(touch_ctmu_port), + .port_list = touch_ctmu_port, +}; +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + +/************************** linein KEY ****************************/ +#if TCFG_LINEIN_ENABLE +struct linein_dev_data linein_data = { + .enable = TCFG_LINEIN_ENABLE, + .port = TCFG_LINEIN_CHECK_PORT, + .up = TCFG_LINEIN_PORT_UP_ENABLE, + .down = TCFG_LINEIN_PORT_DOWN_ENABLE, + .ad_channel = TCFG_LINEIN_AD_CHANNEL, + .ad_vol = TCFG_LINEIN_VOLTAGE, +}; +#endif + +/************************** RDEC_KEY ****************************/ +#if TCFG_RDEC_KEY_ENABLE +const struct rdec_device rdeckey_list[] = { + { + .index = RDEC0 , + .sin_port0 = TCFG_RDEC0_ECODE1_PORT, + .sin_port1 = TCFG_RDEC0_ECODE2_PORT, + .key_value0 = TCFG_RDEC0_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC0_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC1 , + .sin_port0 = TCFG_RDEC1_ECODE1_PORT, + .sin_port1 = TCFG_RDEC1_ECODE2_PORT, + .key_value0 = TCFG_RDEC1_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC1_KEY1_VALUE | BIT(7), + }, + + { + .index = RDEC2 , + .sin_port0 = TCFG_RDEC2_ECODE1_PORT, + .sin_port1 = TCFG_RDEC2_ECODE2_PORT, + .key_value0 = TCFG_RDEC2_KEY0_VALUE | BIT(7), + .key_value1 = TCFG_RDEC2_KEY1_VALUE | BIT(7), + }, + + +}; +const struct rdec_platform_data rdec_key_data = { + .enable = TCFG_RDEC_KEY_ENABLE, //是否使能RDEC按键 + .num = ARRAY_SIZE(rdeckey_list), //RDEC按键的个数 + .rdec = rdeckey_list, //RDEC按键参数表 +}; +#endif + +/************************** otg data****************************/ +#if TCFG_OTG_MODE +struct otg_dev_data otg_data = { + .usb_dev_en = TCFG_OTG_USB_DEV_EN, + .slave_online_cnt = TCFG_OTG_SLAVE_ONLINE_CNT, + .slave_offline_cnt = TCFG_OTG_SLAVE_OFFLINE_CNT, + .host_online_cnt = TCFG_OTG_HOST_ONLINE_CNT, + .host_offline_cnt = TCFG_OTG_HOST_OFFLINE_CNT, + .detect_mode = TCFG_OTG_MODE, + .detect_time_interval = TCFG_OTG_DET_INTERVAL, +}; +#endif + + +/************************** rtc ****************************/ + +#if TCFG_RTC_ENABLE +const struct rtc_dev_data rtc_data = { + .port = (u8)-1, + .edge = 0, //0 leading edge, 1 falling edge + .port_en = false, + .rtc_ldo = false,//使用内部ldo 供电 + .clk_res = RTC_CLK_RES_SEL, +}; +#endif + +/************************** PWM_LED ****************************/ +#if TCFG_PWMLED_ENABLE +LED_PLATFORM_DATA_BEGIN(pwm_led_data) + .io_mode = TCFG_PWMLED_IOMODE, //推灯模式设置:支持单个IO推两个灯和两个IO推两个灯 + .io_cfg.one_io.pin = TCFG_PWMLED_PIN, //单个IO推两个灯的IO口配置 +LED_PLATFORM_DATA_END() +#endif + + +#if TCFG_UI_LED7_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, +#if TCFG_SD1_ENABLE + .pin_cfg.pin7.pin[0] = IO_PORTA_02, + .pin_cfg.pin7.pin[1] = IO_PORTA_03, + .pin_cfg.pin7.pin[2] = IO_PORTA_04, + .pin_cfg.pin7.pin[3] = IO_PORTA_06, + .pin_cfg.pin7.pin[4] = IO_PORTA_07, + .pin_cfg.pin7.pin[5] = IO_PORTA_08, + .pin_cfg.pin7.pin[6] = IO_PORTA_09, +#else + .pin_cfg.pin7.pin[0] = IO_PORTC_00, + .pin_cfg.pin7.pin[1] = IO_PORTC_01, + .pin_cfg.pin7.pin[2] = IO_PORTC_02, + .pin_cfg.pin7.pin[3] = IO_PORTC_03, + .pin_cfg.pin7.pin[4] = IO_PORTC_04, + .pin_cfg.pin7.pin[5] = IO_PORTC_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_02, +#endif +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + +#if TCFG_UI_LED1888_ENABLE +LED7_PLATFORM_DATA_BEGIN(led7_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = (u8)-1,//IO_PORTB_06, +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LED_7, + .private_data = (void *)&led7_data, +}; +#endif /* #if TCFG_UI_LED7_ENABLE */ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_data) + .vlcd = LCD_SEG3X9_VOLTAGE_3_3V, + .bias = LCD_SEG3X9_BIAS_1_3, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, +LCD_SEG3X9_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = LCD_SEG3X9, + .private_data = (void *)&lcd_seg3x9_data, +}; + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + +#if TCHFG_SOFT_I2C_ENABLE +const struct soft_iic_config soft_iic_cfg[] = { + //iic0 data + { + .scl = TCFG_SW_I2C0_CLK_PORT, //IIC CLK脚 + .sda = TCFG_SW_I2C0_DAT_PORT, //IIC DAT脚 + .delay = TCFG_SW_I2C0_DELAY_CNT, //软件IIC延时参数,影响通讯时钟频率 + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +#if 0 + //iic1 data + { + .scl = IO_PORTA_05, + .sda = IO_PORTA_06, + .delay = 50, + .io_pu = 1, + }, +#endif +}; +#endif + +#if TCHFG_HW_I2C_ENABLE +const struct hw_iic_config hw_iic_cfg[] = { + //iic0 data + { + /*硬件IIC端口下选择 + SCL SDA + 'A': IO_PORT_DP IO_PORT_DM + 'B': IO_PORTA_09 IO_PORTA_10 + 'C': IO_PORTA_07 IO_PORTA_08 + 'D': IO_PORTA_05 IO_PORTA_06 + */ + .port = TCFG_HW_I2C0_PORTS, + .baudrate = TCFG_HW_I2C0_CLK, //IIC通讯波特率 + .hdrive = 0, //是否打开IO口强驱 + .io_filter = 1, //是否打开滤波器(去纹波) + .io_pu = 1, //是否打开上拉电阻,如果外部电路没有焊接上拉电阻需要置1 + }, +}; +#endif + + + + +#if TCFG_HW_SPI1_ENABLE +const struct spi_platform_data spi1_p_data = { + .port = TCFG_HW_SPI1_PORT, + .mode = TCFG_HW_SPI1_MODE, + .clk = TCFG_HW_SPI1_BAUD, + .role = TCFG_HW_SPI1_ROLE, +}; +#endif + +#if TCFG_HW_SPI2_ENABLE +const struct spi_platform_data spi2_p_data = { + .port = TCFG_HW_SPI2_PORT, + .mode = TCFG_HW_SPI2_MODE, + .clk = TCFG_HW_SPI2_BAUD, + .role = TCFG_HW_SPI2_ROLE, +}; +#endif + +#if TCFG_NOR_FAT +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_fat_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 0, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_FS +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 1*1024*1024, + .size = 1*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + +#if TCFG_NOR_REC +NORFLASH_DEV_PLATFORM_DATA_BEGIN(norflash_norfs_rec_dev_data) + .spi_hw_num = TCFG_FLASH_DEV_SPI_HW_NUM, + .spi_cs_port = TCFG_FLASH_DEV_SPI_CS_PORT, +#if (TCFG_FLASH_DEV_SPI_HW_NUM == 1) + .spi_pdata = &spi1_p_data, +#elif (TCFG_FLASH_DEV_SPI_HW_NUM == 2) + .spi_pdata = &spi2_p_data, +#endif + .start_addr = 2*1024*1024, + .size = 2*1024*1024, +NORFLASH_DEV_PLATFORM_DATA_END() +#endif + + + +#if TCFG_SPI_LCD_ENABLE +LCD_SPI_PLATFORM_DATA_BEGIN(lcd_spi_data) + .pin_reset = -1, + .pin_cs = IO_PORTA_00, + .pin_rs = IO_PORTA_01, + .pin_bl = IO_PORTA_03, + +#if (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 1) + .spi_cfg = SPI1, + .spi_pdata = &spi1_p_data, +#elif (TCFG_TFT_LCD_DEV_SPI_HW_NUM == 2) + .spi_cfg = SPI2, + .spi_pdata = &spi2_p_data, +#endif + +LED7_PLATFORM_DATA_END() + +const struct ui_devices_cfg ui_cfg_data = { + .type = TFT_LCD, + .private_data = (void *)&lcd_spi_data, +}; +#endif + + +#if TCFG_GSENSOR_ENABLE +#if TCFG_DA230_EN + +GSENSOR_PLATFORM_DATA_BEGIN(gSensor_data) + .iic = 0, + .gSensor_name = "da230", + .gSensor_int_io = IO_PORTB_08, +GSENSOR_PLATFORM_DATA_END(); +#endif //end if DA230_EN +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_FM_ENABLE + +FM_DEV_PLATFORM_DATA_BEGIN(fm_dev_data) + .iic_hdl = 0, + .iic_delay = 50, +FM_DEV_PLATFORM_DATA_END(); + +#endif + +extern const struct device_operations mass_storage_ops; +REGISTER_DEVICES(device_table) = { + /* { "audio", &audio_dev_ops, (void *) &audio_data }, */ + +/* #if TCFG_CHARGE_ENABLE */ +/* { "charge", &charge_dev_ops, (void *)&charge_data }, */ +/* #endif */ + + +#if TCFG_SD0_ENABLE + { "sd0", &sd_dev_ops, (void *) &sd0_data}, +#endif +#if TCFG_SD1_ENABLE + { "sd1", &sd_dev_ops, (void *) &sd1_data}, +#endif + +#if TCFG_LINEIN_ENABLE + { "linein", &linein_dev_ops, (void *)&linein_data}, +#endif +#if TCFG_OTG_MODE + { "otg", &usb_dev_ops, (void *) &otg_data}, +#endif +#if TCFG_UDISK_ENABLE + { "udisk0", &mass_storage_ops , NULL}, +#endif +#if TCFG_RTC_ENABLE +#if TCFG_USE_VIRTUAL_RTC + { "rtc", &rtc_simulate_ops , (void *)&rtc_data}, +#else + { "rtc", &rtc_dev_ops , (void *)&rtc_data}, +#endif +#endif + +#if TCFG_NORFLASH_DEV_ENABLE +#if TCFG_NOR_FAT + { "fat_nor", &norflash_dev_ops , (void *)&norflash_fat_dev_data}, +#endif + +#if TCFG_NOR_FS + { "res_nor", &norfs_dev_ops , (void *)&norflash_norfs_dev_data}, +#endif + +#if TCFG_NOR_REC + {"rec_nor", &norfs_dev_ops , (void *)&norflash_norfs_rec_dev_data}, +#endif +#endif +}; + +/************************** LOW POWER config ****************************/ +const struct low_power_param power_param = { + .config = TCFG_LOWPOWER_LOWPOWER_SEL, //0:sniff时芯片不进入低功耗 1:sniff时芯片进入powerdown + .btosc_hz = TCFG_CLOCK_OSC_HZ, //外接晶振频率 + .delay_us = TCFG_CLOCK_SYS_HZ / 1000000L, //提供给低功耗模块的延时(不需要需修改) + .btosc_disable = TCFG_LOWPOWER_BTOSC_DISABLE, //进入低功耗时BTOSC是否保持 + .vddiom_lev = TCFG_LOWPOWER_VDDIOM_LEVEL, //强VDDIO等级,可选:2.0V 2.2V 2.4V 2.6V 2.8V 3.0V 3.2V 3.6V + .vddiow_lev = TCFG_LOWPOWER_VDDIOW_LEVEL, //弱VDDIO等级,可选:2.1V 2.4V 2.8V 3.2V + .osc_type = OSC_TYPE_BT_OSC , +#if TCFG_USE_VIRTUAL_RTC + .virtual_rtc = 1, +#endif +}; + + + +/************************** PWR config ****************************/ +struct port_wakeup port0 = { + .pullup_down_enable = ENABLE, //配置I/O 内部上下拉是否使能 + .edge = FALLING_EDGE, //唤醒方式选择,可选:上升沿\下降沿 + .attribute = BLUETOOTH_RESUME, //保留参数 + .iomap = IO_PORTA_10, //唤醒口选择 +}; + +const struct sub_wakeup sub_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct charge_wakeup charge_wkup = { + .attribute = BLUETOOTH_RESUME, +}; + +const struct wakeup_param wk_param = { + .port[1] = &port0, + .sub = &sub_wkup, + .charge = &charge_wkup, +}; + +void gSensor_wkupup_disable(void) +{ + log_info("gSensor wkup disable\n"); + power_wakeup_index_disable(1); +} + +void gSensor_wkupup_enable(void) +{ + log_info("gSensor wkup enable\n"); + power_wakeup_index_enable(1); +} +static void key_wakeup_disable() +{ + power_wakeup_index_disable(1); +} +static void key_wakeup_enable() +{ + power_wakeup_index_enable(1); +} + +void debug_uart_init(const struct uart_platform_data *data) +{ +#if TCFG_UART0_ENABLE + if (data) { + uart_init(data); + } else { + uart_init(&uart0_data); + } +#endif +} + + +STATUS *get_led_config(void) +{ + return &(__this->led); +} + +STATUS *get_tone_config(void) +{ + return &(__this->tone); +} + +u8 get_sys_default_vol(void) +{ + return 21; +} + +u8 get_power_on_status(void) +{ +#if TCFG_IOKEY_ENABLE + struct iokey_port *power_io_list = NULL; + power_io_list = iokey_data.port; + + if (iokey_data.enable) { + if (gpio_read(power_io_list->key_type.one_io.port) == power_io_list->connect_way){ + return 1; + } + } +#endif + +#if TCFG_ADKEY_ENABLE + if (adkey_data.enable) { + if (adc_get_value(adkey_data.ad_channel) < 10) { + return 1; + } + } +#endif + + return 0; +} + +static void board_devices_init(void) +{ +#if TCFG_PWMLED_ENABLE + ui_pwm_led_init(&pwm_led_data); +#endif + +#if (TCFG_IOKEY_ENABLE || TCFG_ADKEY_ENABLE || TCFG_IRKEY_ENABLE || TCFG_RDEC_KEY_ENABLE || TCFG_CTMU_TOUCH_KEY_ENABLE) + + key_driver_init(); +#endif + +#if TCFG_GSENSOR_ENABLE + gravity_sensor_init(&gSensor_data); +#endif //end if CONFIG_GSENSOR_ENABLE + +#if TCFG_UI_ENABLE + UI_INIT(&ui_cfg_data); +#endif /* #if TCFG_UI_ENABLE */ + + return; +} + +void uartSendInit(); +extern void alarm_init(); +extern void cfg_file_parse(u8 idx); +void board_init() +{ + board_power_init(); +#if TCFG_PWMLED_ENABLE + if(power_param.osc_type == OSC_TYPE_BT_OSC){//LRC EN + p33_tx_1byte(P3_LRC_CON0, 0x41); + p33_tx_1byte(P3_LRC_CON1, 0x3e); + } +#endif + adc_vbg_init(); + adc_init(); + cfg_file_parse(0); + +#if TCFG_CHARGE_ENABLE + extern int charge_init(const struct dev_node *node, void *arg); + charge_init(NULL, (void *)&charge_data); +#endif + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + } + +/* #if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) */ + /* sdpg_config(1); */ +/* #endif */ + +#if TCFG_FM_ENABLE + fm_dev_init(&fm_dev_data); +#endif + +#if TCFG_NOR_REC + nor_fs_ops_init(); +#endif + +#if TCFG_NOR_FS + init_norsdfile_hdl(); +#endif + +#if FLASH_INSIDE_REC_ENABLE + sdfile_rec_ops_init(); +#endif + + dev_manager_init(); + board_devices_init(); + + if(get_charge_online_flag()){ + power_set_mode(PWR_LDO15); + }else{ + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } + + //针对硅mic要输出1给mic供电(按实际使用情况配置) + /* if(!adc_data.mic_capless){ */ + /* gpio_set_pull_up(IO_PORTA_04, 0); */ + /* gpio_set_pull_down(IO_PORTA_04, 0); */ + /* gpio_set_direction(IO_PORTA_04, 0); */ + /* gpio_set_output_value(IO_PORTA_04,1); */ + /* } */ + + #if TCFG_UART0_ENABLE + if (uart0_data.rx_pin < IO_MAX_NUM) { + gpio_set_die(uart0_data.rx_pin, 1); + } +#endif + +#ifdef AUDIO_PCM_DEBUG + uartSendInit(); +#endif + +#if TCFG_RTC_ENABLE + alarm_init(); +#endif + +#if USER_UART_UPDATE_ENABLE + { +#include "uart_update.h" + uart_update_cfg update_cfg = { + .rx = IO_PORTA_02, + .tx = IO_PORTA_03, + .output_channel = CH1_UT1_TX, + .input_channel = INPUT_CH0 + }; + uart_update_init(&update_cfg); + } +#endif +} + +/*进软关机之前默认将IO口都设置成高阻状态,需要保留原来状态的请修改该函数*/ +extern void dac_power_off(void); +extern void dac_sniff_power_off(void); +void board_set_soft_poweroff(void) +{ + u8 mode = (JL_SFC->CON >> 8) & 0x0f; + + u32 porta_value = 0xffff; + u32 portb_value = 0xffff; + u32 portc_value = 0xffff; + + extern u32 spi_get_port(void); + if (spi_get_port() != 0) { + if ((mode == 0b0101) || (mode == 0b0111)) { + porta_value = 0x1fff; + } else { + porta_value = 0x9fff; + } + } + + gpio_write(MIC_HW_IO, 0); + + key_wakeup_enable(); + gpio_dir(GPIOA, 0, 16, porta_value, GPIO_OR); + gpio_set_pu(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_set_pd(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_die(GPIOA, 0, 16, ~porta_value, GPIO_AND); + gpio_dieh(GPIOA, 0, 16, ~porta_value, GPIO_AND); + + //保留长按Reset Pin - PB1 + portb_value &= ~BIT(1); + gpio_dir(GPIOB, 0, 16, portb_value, GPIO_OR); + gpio_set_pu(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_set_pd(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_die(GPIOB, 0, 16, ~portb_value, GPIO_AND); + gpio_dieh(GPIOB, 0, 16, ~portb_value, GPIO_AND); + + gpio_dir(GPIOC, 0, 16, portc_value, GPIO_OR); + gpio_set_pu(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_set_pd(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_die(GPIOC, 0, 16, ~portc_value, GPIO_AND); + gpio_dieh(GPIOC, 0, 16, ~portc_value, GPIO_AND); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_dieh(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + gpio_set_dieh(IO_PORT_DM, 0); + + VDDIOW_VOL_SEL(power_param.vddiow_lev); +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + sdpg_config(0); +#endif + + //dac_power_off(); +} + +#define APP_IO_DEBUG_0(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define APP_IO_DEBUG_1(i,x) //{JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} + +void sleep_exit_callback(u32 usec) +{ + /* putchar('>'); */ + APP_IO_DEBUG_1(A, 6); + key_wakeup_disable(); +} + +void sleep_enter_callback(u8 step) +{ + /* 此函数禁止添加打印 */ + if (step == 1) { + /* putchar('<'); */ + APP_IO_DEBUG_0(A, 6); + dac_sniff_power_off(); + /* dac_power_off(); */ + } else { + key_wakeup_enable(); + gpio_set_pull_up(IO_PORTA_03, 0); + gpio_set_pull_down(IO_PORTA_03, 0); + gpio_set_direction(IO_PORTA_03, 1); + + usb_iomode(1); + + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + gpio_set_die(IO_PORT_DP, 0); + + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); + gpio_set_die(IO_PORT_DM, 0); + } +} + +void board_power_init(void) +{ + log_info("Power init : %s", __FILE__); + + power_init(&power_param); + + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + + power_keep_dacvdd_en(0); + + /* power_wakeup_init(&wk_param); */ + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) + charge_check_and_set_pinr(0); +#endif +} + +static void board_power_wakeup_init(void) +{ + power_wakeup_init(&wk_param); + key_wakeup_disable(); +#if TCFG_POWER_ON_NEED_KEY + extern u8 power_reset_src; + if ((power_reset_src & BIT(0)) || (power_reset_src & BIT(1))) { +#if TCFG_CHARGE_ENABLE + log_info("is ldo5v wakeup:%d\n",is_ldo5v_wakeup()); + if (is_ldo5v_wakeup()) { + return; + } + if (get_ldo5v_online_hw()) { + return; + } + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif + power_set_callback(TCFG_LOWPOWER_LOWPOWER_SEL, sleep_enter_callback, sleep_exit_callback, board_set_soft_poweroff); + power_set_soft_poweroff(); + } +#endif +} +early_initcall(board_power_wakeup_init); +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_tws_box/board_ac695x_tws_box.h b/apps/soundbox/board/br23/board_ac695x_tws_box/board_ac695x_tws_box.h new file mode 100644 index 0000000..db08f92 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_tws_box/board_ac695x_tws_box.h @@ -0,0 +1,1003 @@ +#ifndef CONFIG_BOARD_AC695X_TWS_BOX_CFG_H +#define CONFIG_BOARD_AC695X_TWS_BOX_CFG_H + +#ifdef CONFIG_BOARD_AC695X_TWS_BOX + +#define CONFIG_SDFILE_ENABLE +#define CONFIG_FLASH_SIZE (1024 * 1024) + +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +#define ENABLE_THIS_MOUDLE 1 +#define DISABLE_THIS_MOUDLE 0 + +#define ENABLE 1 +#define DISABLE 0 + +#define LINEIN_INPUT_WAY_ANALOG 0 +#define LINEIN_INPUT_WAY_ADC 1 +#define LINEIN_INPUT_WAY_DAC 2 + +#define NO_CONFIG_PORT (-1) + +//*********************************************************************************// +// app 配置 // +//*********************************************************************************// +#define TCFG_APP_BT_EN 1 +#define TCFG_APP_MUSIC_EN 1 +#define TCFG_APP_LINEIN_EN 1 +#define TCFG_APP_FM_EN 1 +#define TCFG_APP_PC_EN 1 +#define TCFG_APP_RTC_EN 0 +#define TCFG_APP_RECORD_EN 0 +#define TCFG_APP_SPDIF_EN 0 +//*********************************************************************************// +// PCM_DEBUG调试配置 // +//*********************************************************************************// + +//#define AUDIO_PCM_DEBUG //PCM串口调试,写卡通话数据 + +//*********************************************************************************// +// UART配置 // +//*********************************************************************************// +#define TCFG_UART0_ENABLE ENABLE_THIS_MOUDLE //串口打印模块使能 +#define TCFG_UART0_RX_PORT NO_CONFIG_PORT //串口接收脚配置(用于打印可以选择NO_CONFIG_PORT) +#define TCFG_UART0_TX_PORT IO_PORTA_05 //串口发送脚配置 +#define TCFG_UART0_BAUDRATE 1000000 //串口波特率配置 + +//*********************************************************************************// +// IIC配置 // +//*********************************************************************************// +/*软件IIC设置*/ +#define TCHFG_SOFT_I2C_ENABLE DISABLE_THIS_MOUDLE //软件IIC使能 +#define TCFG_SW_I2C0_CLK_PORT IO_PORTB_00 //软件IIC CLK脚选择 +#define TCFG_SW_I2C0_DAT_PORT IO_PORTB_03 //软件IIC DAT脚选择 + +//A组IO: SDA: DM SCL: DP B组IO: SDA: PC4 SCL: PC5 +//C组IO: SDA: PB4 SCL: PB6 D组IO: SDA: PA5 SCL: PA6 +#define TCHFG_HW_I2C_ENABLE DISABLE_THIS_MOUDLE //硬件IIC使能 +#define TCFG_HW_I2C0_PORTS 'B' //选择第几组硬件引脚 +#define TCFG_HW_I2C0_CLK 100000 //硬件IIC波特率 + +//*********************************************************************************// +// 硬件SPI 配置 // +//*********************************************************************************// +#define TCFG_HW_SPI1_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB2 DO: PB1 CLK: PB0 +//B组IO: DI: PC3 DO: PC5 CLK: PC4 +#define TCFG_HW_SPI1_PORT 'A' +#define TCFG_HW_SPI1_BAUD 4000000L +#define TCFG_HW_SPI1_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI1_ROLE SPI_ROLE_MASTER + +#define TCFG_HW_SPI2_ENABLE ENABLE_THIS_MOUDLE +//A组IO: DI: PB8 DO: PB10 CLK: PB9 +//B组IO: DI: PA13 DO: DM CLK: DP +#define TCFG_HW_SPI2_PORT 'A' +#define TCFG_HW_SPI2_BAUD 2000000L +#define TCFG_HW_SPI2_MODE SPI_MODE_BIDIR_1BIT +#define TCFG_HW_SPI2_ROLE SPI_ROLE_MASTER + +//*********************************************************************************// +// FLASH 配置 // +//*********************************************************************************// +#define TCFG_NORFLASH_DEV_ENABLE DISABLE_THIS_MOUDLE +#define TCFG_FLASH_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 +#define TCFG_FLASH_DEV_SPI_CS_PORT IO_PORTA_03 + + +//*********************************************************************************// +// 充电参数配置 // +//*********************************************************************************// +//是否支持芯片内置充电 +#define TCFG_CHARGE_ENABLE DISABLE_THIS_MOUDLE +//是否支持开机充电 +#define TCFG_CHARGE_POWERON_ENABLE DISABLE +//是否支持拔出充电自动开机功能 +#define TCFG_CHARGE_OFF_POWERON_NE DISABLE + +#define TCFG_CHARGE_FULL_V CHARGE_FULL_V_4202 + +#define TCFG_CHARGE_FULL_MA CHARGE_FULL_mA_10 + +#define TCFG_CHARGE_MA CHARGE_mA_60 + + +//*********************************************************************************// +// SD 配置 // +//*********************************************************************************// +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 +#define TCFG_SD0_ENABLE ENABLE_THIS_MOUDLE +//A组IO: CMD:PA9 CLK:PA10 DAT0:PA5 DAT1:PA6 DAT2:PA7 DAT3:PA8 +//B组IO: CMD:PB10 CLK:PB9 DAT0:PB8 DAT1:PB6 DAT2:PB5 DAT3:PB4 +#define TCFG_SD0_PORTS 'B' +#define TCFG_SD0_DAT_MODE 1 +#define TCFG_SD0_DET_MODE SD_CMD_DECT +#define TCFG_SD0_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD0_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD0_CLK (3000000*4L) + +#define TCFG_SD1_ENABLE DISABLE_THIS_MOUDLE +//A组IO: CMD:PC4 CLK:PC5 DAT0:PC3 DAT1:PC2 DAT2:PC1 DAT3:PC0 +//B组IO: CMD:PB5 CLK:PB6 DAT0:PB4 DAT1:PB8 DAT2:PB9 DAT3:PB10 +#define TCFG_SD1_PORTS 'A' +#define TCFG_SD1_DAT_MODE 1 +#define TCFG_SD1_DET_MODE SD_CLK_DECT +#define TCFG_SD1_DET_IO IO_PORT_DM//当SD_DET_MODE为2时有效 +#define TCFG_SD1_DET_IO_LEVEL 0//IO检查,0:低电平检测到卡。 1:高电平(外部电源)检测到卡。 2:高电平(SD卡电源)检测到卡。 +#define TCFG_SD1_CLK (3000000*4L) + + +//*********************************************************************************// +// USB 配置 // +//*********************************************************************************// +#define TCFG_PC_ENABLE TCFG_APP_PC_EN//PC模块使能 +#define TCFG_UDISK_ENABLE ENABLE_THIS_MOUDLE//U盘模块使能 +#define TCFG_OTG_USB_DEV_EN BIT(0)//USB0 = BIT(0) USB1 = BIT(1) + +#include "usb_std_class_def.h" + + +#define TCFG_USB_PORT_CHARGE DISABLE + +#define TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 DISABLE +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 +//复用情况下,如果使用此USB口作为充电(即LDO5V_IN连接到此USB口), +//TCFG_OTG_MODE需要或上TCFG_OTG_MODE_CHARGE,用来把charge从host区 +//分开;否则不需要,如果LDO5V_IN与其他IO绑定,则不能或上 +//TCFG_OTG_MODE_CHARGE +#define TCFG_DM_MULTIPLEX_WITH_SD_PORT 0//0:sd0 1:sd1 //dm 参与复用的sd配置 +#undef TCFG_OTG_MODE +#define TCFG_OTG_MODE (TCFG_OTG_MODE_HOST|TCFG_OTG_MODE_SLAVE|TCFG_OTG_MODE_CHARGE|OTG_DET_DP_ONLY) + +#undef USB_DEVICE_CLASS_CONFIG +#if TCFG_SD0_SD1_USE_THE_SAME_HW //开启了双卡的可以使能读卡器存续设备 +#define USB_DEVICE_CLASS_CONFIG (MASSSTORAGE_CLASS|SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#else +#define USB_DEVICE_CLASS_CONFIG (SPEAKER_CLASS|MIC_CLASS|HID_CLASS) +#endif + +#undef TCFG_SD0_DET_MODE +#define TCFG_SD0_DET_MODE SD_CLK_DECT +#define TCFG_USB_SD_MULTIPLEX_IO IO_PORTB_08 + +#endif + +//*********************************************************************************// +// fat_FLASH 配置 // +//*********************************************************************************// +#define TCFG_CODE_FLASH_ENABLE DISABLE_THIS_MOUDLE + +#define FLASH_INSIDE_REC_ENABLE 0 + +#if TCFG_NORFLASH_DEV_ENABLE +#define TCFG_NOR_FAT 1//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 1//ENABLE +#else +#define TCFG_NOR_FAT 0//ENABLE +#define TCFG_NOR_FS 0//ENABLE +#define TCFG_NOR_REC 0//ENABLE +#endif + + + +//*********************************************************************************// +// key 配置 // +//*********************************************************************************// +//#define KEY_NUM_MAX 10 +//#define KEY_NUM 3 +#define KEY_IO_NUM_MAX 6 +#define KEY_AD_NUM_MAX 10 +#define KEY_IR_NUM_MAX 21 +#define KEY_TOUCH_NUM_MAX 6 +#define KEY_RDEC_NUM_MAX 3 +#define KEY_CTMU_TOUCH_NUM_MAX 6 + +#define MULT_KEY_ENABLE DISABLE //是否使能组合按键消息, 使能后需要配置组合按键映射表 +//*********************************************************************************// +// iokey 配置 // +//*********************************************************************************// +#define TCFG_IOKEY_ENABLE DISABLE_THIS_MOUDLE //是否使能IO按键 + +#define TCFG_IOKEY_POWER_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO + +#define TCFG_IOKEY_POWER_ONE_PORT IO_PORTB_01 //IO按键端口 + +#define TCFG_IOKEY_PREV_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_PREV_ONE_PORT IO_PORTB_00 + +#define TCFG_IOKEY_NEXT_CONNECT_WAY ONE_PORT_TO_LOW //按键一端接低电平一端接IO +#define TCFG_IOKEY_NEXT_ONE_PORT IO_PORTB_02 + +//*********************************************************************************// +// adkey 配置 // +//*********************************************************************************// +#define TCFG_ADKEY_ENABLE ENABLE_THIS_MOUDLE//是否使能AD按键 +#define TCFG_ADKEY_LED_IO_REUSE DISABLE_THIS_MOUDLE //ADKEY 和 LED IO复用,led只能设置蓝灯显示 +#define TCFG_ADKEY_PORT IO_PORTA_10 //AD按键端口(需要注意选择的IO口是否支持AD功能) +#define TCFG_ADKEY_AD_CHANNEL AD_CH_PA10 +#define TCFG_ADKEY_EXTERN_UP_ENABLE ENABLE_THIS_MOUDLE //是否使用外部上拉 + +#if TCFG_ADKEY_EXTERN_UP_ENABLE +#define R_UP 220 //22K,外部上拉阻值在此自行设置 +#else +#define R_UP 100 //10K,内部上拉默认10K +#endif + +//必须从小到大填电阻,没有则同VDDIO,填0x3ffL +#define TCFG_ADKEY_AD0 (0) //0R +#define TCFG_ADKEY_AD1 (0x3ffL * 30 / (30 + R_UP)) //3k +#define TCFG_ADKEY_AD2 (0x3ffL * 62 / (62 + R_UP)) //6.2k +#define TCFG_ADKEY_AD3 (0x3ffL * 91 / (91 + R_UP)) //9.1k +#define TCFG_ADKEY_AD4 (0x3ffL * 150 / (150 + R_UP)) //15k +#define TCFG_ADKEY_AD5 (0x3ffL * 240 / (240 + R_UP)) //24k +#define TCFG_ADKEY_AD6 (0x3ffL * 330 / (330 + R_UP)) //33k +#define TCFG_ADKEY_AD7 (0x3ffL * 510 / (510 + R_UP)) //51k +#define TCFG_ADKEY_AD8 (0x3ffL * 1000 / (1000 + R_UP)) //100k +#define TCFG_ADKEY_AD9 (0x3ffL * 2200 / (2200 + R_UP)) //220k +#define TCFG_ADKEY_VDDIO (0x3ffL) + +#define TCFG_ADKEY_VOLTAGE0 ((TCFG_ADKEY_AD0 + TCFG_ADKEY_AD1) / 2) +#define TCFG_ADKEY_VOLTAGE1 ((TCFG_ADKEY_AD1 + TCFG_ADKEY_AD2) / 2) +#define TCFG_ADKEY_VOLTAGE2 ((TCFG_ADKEY_AD2 + TCFG_ADKEY_AD3) / 2) +#define TCFG_ADKEY_VOLTAGE3 ((TCFG_ADKEY_AD3 + TCFG_ADKEY_AD4) / 2) +#define TCFG_ADKEY_VOLTAGE4 ((TCFG_ADKEY_AD4 + TCFG_ADKEY_AD5) / 2) +#define TCFG_ADKEY_VOLTAGE5 ((TCFG_ADKEY_AD5 + TCFG_ADKEY_AD6) / 2) +#define TCFG_ADKEY_VOLTAGE6 ((TCFG_ADKEY_AD6 + TCFG_ADKEY_AD7) / 2) +#define TCFG_ADKEY_VOLTAGE7 ((TCFG_ADKEY_AD7 + TCFG_ADKEY_AD8) / 2) +#define TCFG_ADKEY_VOLTAGE8 ((TCFG_ADKEY_AD8 + TCFG_ADKEY_AD9) / 2) +#define TCFG_ADKEY_VOLTAGE9 ((TCFG_ADKEY_AD9 + TCFG_ADKEY_VDDIO) / 2) + +#define TCFG_ADKEY_VALUE0 0 +#define TCFG_ADKEY_VALUE1 1 +#define TCFG_ADKEY_VALUE2 2 +#define TCFG_ADKEY_VALUE3 3 +#define TCFG_ADKEY_VALUE4 4 +#define TCFG_ADKEY_VALUE5 5 +#define TCFG_ADKEY_VALUE6 6 +#define TCFG_ADKEY_VALUE7 7 +#define TCFG_ADKEY_VALUE8 8 +#define TCFG_ADKEY_VALUE9 9 + +//*********************************************************************************// +// irkey 配置 // +//*********************************************************************************// +#define TCFG_IRKEY_ENABLE DISABLE_THIS_MOUDLE//是否使能ir按键 +#define TCFG_IRKEY_PORT IO_PORTA_02 //IR按键端口 + +//*********************************************************************************// +// tocuh key 配置 // +//*********************************************************************************// +#define TCFG_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能触摸按键 + +/* 触摸按键计数参考时钟选择, 频率越高, 精度越高 +** 可选参数: + 1.TOUCH_KEY_OSC_CLK, + 2.TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + 3.TOUCH_KEY_PLL_192M_CLK, + 4.TOUCH_KEY_PLL_240M_CLK, +*/ +#define TCFG_TOUCH_KEY_CLK TOUCH_KEY_PLL_192M_CLK //触摸按键时钟配置 +#define TCFG_TOUCH_KEY_CHANGE_GAIN 4 //变化放大倍数, 一般固定 +#define TCFG_TOUCH_KEY_PRESS_CFG -100//触摸按下灵敏度, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG0 -50 //触摸释放灵敏度0, 类型:s16, 数值越大, 灵敏度越高 +#define TCFG_TOUCH_KEY_RELEASE_CFG1 -80 //触摸释放灵敏度1, 类型:s16, 数值越大, 灵敏度越高 + +//key0配置 +#define TCFG_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键IO配置 +#define TCFG_TOUCH_KEY0_VALUE 1 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_TOUCH_KEY1_VALUE 2 //触摸按键key1按键值 + +//*********************************************************************************// +// ctmu tocuh key 配置 // +//*********************************************************************************// +#define TCFG_CTMU_TOUCH_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能CTMU触摸按键 +#define TCFG_CTMU_TOUCH_KEY_PRESS_CFG 40//按下灵敏度(s16),数值越小, 灵敏度越高,一般设置30-100 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG0 10 //释放灵敏度0(s16),数值越小,灵敏度越高,必须比按下灵敏度小 +#define TCFG_CTMU_TOUCH_KEY_RELEASE_CFG1 160 //释放灵敏度1(s16), 数值越小, 灵敏度越高,一般只需要调节上面两个 + +//key0配置 +#define TCFG_CTMU_TOUCH_KEY0_PORT IO_PORTB_06 //触摸按键key0 IO配置 +#define TCFG_CTMU_TOUCH_KEY0_VALUE 0 //触摸按键key0 按键值 + +//key1配置 +#define TCFG_CTMU_TOUCH_KEY1_PORT IO_PORTB_07 //触摸按键key1 IO配置 +#define TCFG_CTMU_TOUCH_KEY1_VALUE 1 //触摸按键key1 按键值 + +//*********************************************************************************// +// rdec_key 配置 // +//*********************************************************************************// +#define TCFG_RDEC_KEY_ENABLE DISABLE_THIS_MOUDLE //是否使能RDEC按键 +//默认硬件引脚配置 +//RDEC0配置 +#define TCFG_RDEC0_ECODE1_PORT IO_PORTA_02 +#define TCFG_RDEC0_ECODE2_PORT IO_PORTA_03 +#define TCFG_RDEC0_KEY0_VALUE 0 +#define TCFG_RDEC0_KEY1_VALUE 1 + +//RDEC1配置 +#define TCFG_RDEC1_ECODE1_PORT IO_PORTB_02 +#define TCFG_RDEC1_ECODE2_PORT IO_PORTB_03 +#define TCFG_RDEC1_KEY0_VALUE 2 +#define TCFG_RDEC1_KEY1_VALUE 3 + +//RDEC2配置 +#define TCFG_RDEC2_ECODE1_PORT IO_PORTB_04 +#define TCFG_RDEC2_ECODE2_PORT IO_PORTB_06 +#define TCFG_RDEC2_KEY0_VALUE 4 +#define TCFG_RDEC2_KEY1_VALUE 5 + + +//*********************************************************************************// +// Audio配置 // +//*********************************************************************************// +#define TCFG_AUDIO_ADC_ENABLE ENABLE_THIS_MOUDLE +//MIC只有一个声道,固定选择右声道 +#define TCFG_AUDIO_ADC_MIC_CHA LADC_CH_MIC_R +//省电容MIC使能 +#define TCFG_MIC_CAPLESS_ENABLE DISABLE_THIS_MOUDLE +/*MIC LDO电流档位设置: + 0:0.625ua 1:1.25ua 2:1.875ua 3:2.5ua*/ +#define TCFG_AUDIO_ADC_LDO_SEL 2 + +// LADC通道 +#define TCFG_AUDIO_ADC_LINE_CHA0 LADC_LINE1_MASK +#define TCFG_AUDIO_ADC_LINE_CHA1 LADC_CH_LINE0_L + +#define TCFG_AUDIO_DAC_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_AUDIO_DAC_LDO_SEL 1 + +#define TCFG_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V +/*预留接口,未使用*/ +#define TCFG_AUDIO_DAC_PA_PORT NO_CONFIG_PORT +/* +DAC硬件上的连接方式,可选的配置: + DAC_OUTPUT_MONO_L 左声道 + DAC_OUTPUT_MONO_R 右声道 + DAC_OUTPUT_LR 立体声 + DAC_OUTPUT_MONO_LR_DIFF 单声道差分输出 +*/ +//#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_FRONT_LR_REAR_LR +#define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_LR +// #define TCFG_AUDIO_DAC_CONNECT_MODE DAC_OUTPUT_MONO_LR_DIFF + +/*通话降噪模式配置*/ +#define CVP_ANS_MODE 0 /*传统降噪*/ +#define CVP_DNS_MODE 1 /*神经网络降噪*/ +#define TCFG_AUDIO_CVP_NS_MODE CVP_ANS_MODE + +#define AUDIO_OUTPUT_WAY_DAC 0 +#define AUDIO_OUTPUT_WAY_IIS 1 +#define AUDIO_OUTPUT_WAY_FM 2 +#define AUDIO_OUTPUT_WAY_HDMI 3 +#define AUDIO_OUTPUT_WAY_SPDIF 4 +#define AUDIO_OUTPUT_WAY_BT 5 // bt emitter +#define AUDIO_OUTPUT_WAY_DAC_IIS 6 +#define AUDIO_OUTPUT_WAY_DONGLE 7 +#define AUDIO_OUTPUT_WAY AUDIO_OUTPUT_WAY_DAC +#define LINEIN_INPUT_WAY LINEIN_INPUT_WAY_ADC //LINEIN_INPUT_WAY_ANALOG + +#define AUDIO_OUTPUT_AUTOMUTE 0//ENABLE +#define DAC_AUTO_HIGH_Z_EN DISABLE //处理直推串音问题, 隔直不要开 + +/* + *系统音量类型选择 + *软件数字音量是指纯软件对声音进行运算后得到的 + *硬件数字音量是指dac内部数字模块对声音进行运算后输出 + */ +#define VOL_TYPE_DIGITAL 0 //软件数字音量 +#define VOL_TYPE_ANALOG 1 //硬件模拟音量 +#define VOL_TYPE_AD 2 //联合音量(模拟数字混合调节) +#define VOL_TYPE_DIGITAL_HW 3 //硬件数字音量 +#define VOL_TYPE_DIGGROUP 4 //独立通道数字音量 + +//每个解码通道都开启数字音量管理,音量类型为VOL_TYPE_DIGGROUP时要使能 +#define SYS_DIGVOL_GROUP_EN DISABLE + +#define SYS_VOL_TYPE VOL_TYPE_ANALOG +/* + *通话的时候使用数字音量 + *0:通话使用和SYS_VOL_TYPE一样的音量调节类型 + *1:通话使用数字音量调节,更加平滑 + */ +#define TCFG_CALL_USE_DIGITAL_VOLUME 0 + +// 使能改宏,提示音音量使用music音量 +#define APP_AUDIO_STATE_WTONE_BY_MUSIC (1) +// 0:提示音不使用默认音量; 1:默认提示音音量值 +#define TONE_MODE_DEFAULE_VOLUME (0) +//*********************************************************************************// +// 充电仓配置 // +//*********************************************************************************// +#define TCFG_CHARGESTORE_ENABLE DISABLE_THIS_MOUDLE //是否支持智能充点仓 +#define TCFG_TEST_BOX_ENABLE 0 +#define TCFG_CHARGESTORE_PORT IO_PORTA_02 //耳机和充点仓通讯的IO口 +#define TCFG_CHARGESTORE_UART_ID IRQ_UART1_IDX //通讯使用的串口号 + +#ifdef AUDIO_PCM_DEBUG +#ifdef TCFG_TEST_BOX_ENABLE +#undef TCFG_TEST_BOX_ENABLE +#define TCFG_TEST_BOX_ENABLE 0 //因为使用PCM使用到了串口1 +#endif +#endif/*AUDIO_PCM_DEBUG*/ + +//*********************************************************************************// +// LED 配置 // +//****************************************************************************** +#if TCFG_ADKEY_LED_IO_REUSE +//打开ADKEY和LED IO复用功能,LED使用ADKEY_IO +#define TCFG_PWMLED_ENABLE ENABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN TCFG_ADKEY_PORT //LED使用的IO口 + +#else + +#define TCFG_PWMLED_ENABLE DISABLE_THIS_MOUDLE //是否支持PMW LED推灯模块 +#define TCFG_PWMLED_IOMODE LED_ONE_IO_MODE //LED模式,单IO还是两个IO推灯 +#define TCFG_PWMLED_PIN IO_PORTB_06 //LED使用的IO口 注意和led7是否有io冲突 + +#endif +//*********************************************************************************// +// UI 配置 // +//*********************************************************************************// +#define TCFG_UI_ENABLE DISABLE_THIS_MOUDLE //UI总开关 +#define CONFIG_UI_STYLE STYLE_JL_LED7 +#define TCFG_UI_LED7_ENABLE ENABLE_THIS_MOUDLE //UI使用LED7显示 +// #define TCFG_UI_LCD_SEG3X9_ENABLE ENABLE_THIS_MOUDLE //UI使用LCD段码屏显示 +// #define TCFG_LCD_ST7735S_ENABLE ENABLE_THIS_MOUDLE +// #define TCFG_LCD_ST7789VW_ENABLE ENABLE_THIS_MOUDLE +#define TCFG_SPI_LCD_ENABLE DISABLE_THIS_MOUDLE //spi lcd开关 +#define TCFG_TFT_LCD_DEV_SPI_HW_NUM 1// 1: SPI1 2: SPI2 配置lcd选择的spi口 + +#define TCFG_LED7_RUN_RAM DISABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +//*********************************************************************************// +// 时钟配置 // +//*********************************************************************************// +#define TCFG_CLOCK_SYS_SRC SYS_CLOCK_INPUT_PLL_BT_OSC //系统时钟源选择 +#define TCFG_CLOCK_SYS_HZ 24000000 //系统时钟设置 +#define TCFG_CLOCK_OSC_HZ 24000000 //外界晶振频率设置 +#define TCFG_CLOCK_MODE CLOCK_MODE_ADAPTIVE + +//*********************************************************************************// +// 低功耗配置 // +//*********************************************************************************// +#define TCFG_LOWPOWER_POWER_SEL PWR_LDO15 //电源模式设置,可选DCDC和LDO +#define TCFG_LOWPOWER_BTOSC_DISABLE 0 //低功耗模式下BTOSC是否保持 +#define TCFG_LOWPOWER_LOWPOWER_SEL 0// SLEEP_EN //SNIFF状态下芯片是否进入powerdown + + +#define TCFG_LOWPOWER_VDDIOM_LEVEL VDDIOM_VOL_34V + +#define TCFG_LOWPOWER_VDDIOW_LEVEL VDDIOW_VOL_28V //弱VDDIO等级配置 + + +//*********************************************************************************// +// EQ配置 // +//*********************************************************************************// +#define TCFG_EQ_ENABLE 1 //支持EQ功能,EQ总使能 +#if TCFG_EQ_ENABLE +#define TCFG_BT_MUSIC_EQ_ENABLE 1 //支持蓝牙音乐EQ +#define TCFG_PHONE_EQ_ENABLE 1 //支持通话近端EQ +#define TCFG_MUSIC_MODE_EQ_ENABLE 1 //支持音乐模式EQ +#define TCFG_LINEIN_MODE_EQ_ENABLE 1 //支持linein近端EQ +#define TCFG_FM_MODE_EQ_ENABLE 0 //支持fm模式EQ +#define TCFG_SPDIF_MODE_EQ_ENABLE 0 //支持SPDIF模式EQ +#define TCFG_PC_MODE_EQ_ENABLE 1 //支持pc模式EQ +#define TCFG_AUDIO_OUT_EQ_ENABLE 0 //高低音EQ +#define TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE 0 //MIC音效后级EQ使能(includes DRC) + + +#define EQ_SECTION_MAX 20//eq 段数 +#define TCFG_DYNAMIC_EQ_ENABLE 0 //动态eq使能,接在eq后,需输入32bit位宽数据 +#endif//TCFG_EQ_ENABLE + +#define TCFG_DRC_ENABLE 1 //DRC 总使能 +#define TCFG_AUDIO_MDRC_ENABLE 0 //多带drc使能 0:关闭多带drc, 1:使能多带drc 2:使能多带drc 并且 多带drc后再做一次全带的drc +#if TCFG_DRC_ENABLE +#define TCFG_BT_MUSIC_DRC_ENABLE 1 //支持蓝牙音乐DRC +#define TCFG_MUSIC_MODE_DRC_ENABLE 1 //支持音乐模式DRC +#define TCFG_LINEIN_MODE_DRC_ENABLE 1 //支持LINEIN模式DRC +#define TCFG_FM_MODE_DRC_ENABLE 0 //支持FM模式DRC +#define TCFG_SPDIF_MODE_DRC_ENABLE 0 //支持SPDIF模式DRC +#define TCFG_PC_MODE_DRC_ENABLE 1 //支持PC模式DRC +#define TCFG_AUDIO_OUT_DRC_ENABLE 0 //高低音EQ后drc +#endif//TCFG_DRC_ENABLE + + +//*********************************************************************************// +// 新音箱配置工具 && 调音工具 // +//*********************************************************************************// +#define TCFG_SOUNDBOX_TOOL_ENABLE DISABLE //是否支持音箱在线配置工具 +#define TCFG_EFFECT_TOOL_ENABLE DISABLE //是否支持在线音效调试,使能该项还需使能EQ总使能TCFG_EQ_ENABL, +#define TCFG_NULL_COMM 0 //不支持通信 +#define TCFG_UART_COMM 1 //串口通信 +#define TCFG_USB_COMM 2 //USB通信 +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#define TCFG_COMM_TYPE TCFG_USB_COMM //通信方式选择 +#else +#define TCFG_COMM_TYPE TCFG_NULL_COMM +#endif +#define TCFG_TOOL_TX_PORT IO_PORT_DP //UART模式调试TX口选择 +#define TCFG_TOOL_RX_PORT IO_PORT_DM //UART模式调试RX口选择 +#define TCFG_ONLINE_ENABLE (TCFG_EFFECT_TOOL_ENABLE) //是否支持音效在线调试功能 + +/***********************************非用户配置区***********************************/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if TCFG_COMM_TYPE == TCFG_UART_COMM +#undef TCFG_UDISK_ENABLE +#define TCFG_UDISK_ENABLE 0 +#undef TCFG_SD0_PORTS +#define TCFG_SD0_PORTS 'B' +#endif +#endif + +#include "usb_std_class_def.h" +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_EFFECT_TOOL_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN ENABLE +#if (TCFG_USB_CDC_BACKGROUND_RUN && (!TCFG_PC_ENABLE)) +#define TCFG_OTG_USB_DEV_EN 0 +#endif +#endif +#if (TCFG_COMM_TYPE == TCFG_UART_COMM) +#define TCFG_USB_CDC_BACKGROUND_RUN DISABLE +#endif +#endif + +/**********************************************************************************/ + + +//*********************************************************************************// +// 混响配置 // +//*********************************************************************************// +#define TCFG_MIC_EFFECT_ENABLE 0//DISABLE +#define TCFG_MIC_EFFECT_START_DIR 0//开机直接启动混响 + +#define MIC_EFFECT_REVERB 1//BIT(0) +#define MIC_EFFECT_ECHO 2//BIT(1) +#define MIC_EFFECT_REVERB_ECHO 3//(BIT(1)|BIT(0)) +#define MIC_EFFECT_MEGAPHONE 4//BIT(2) +// #define TCFG_MIC_EFFECT_SEL MIC_EFFECT_REVERB +#define TCFG_MIC_EFFECT_SEL MIC_EFFECT_ECHO + +/***********************************非用户配置区***********************************/ +#if TCFG_MIC_EFFECT_ENABLE +#undef EQ_SECTION_MAX +#define EQ_SECTION_MAX 25 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE + +#if TCFG_DYNAMIC_EQ_ENABLE +#undef TCFG_DYNAMIC_EQ_ENABLE +#define TCFG_DYNAMIC_EQ_ENABLE 0 +#endif + +#if TCFG_AUDIO_MDRC_ENABLE +#undef TCFG_AUDIO_MDRC_ENABLE +#define TCFG_AUDIO_MDRC_ENABLE 0 +#endif +#endif +#if !TCFG_EQ_ENABLE +#undef TCFG_EQ_ENABLE +#define TCFG_EQ_ENABLE 1//混响必开eq +#endif +#if !TCFG_DRC_ENABLE +#undef TCFG_DRC_ENABLE +#define TCFG_DRC_ENABLE 1//混响必开drc +#endif +/**********************************************************************************/ + +#define TCFG_MIC_DODGE_EN 0//闪避是否使能 + + +#define TCFG_REVERB_SAMPLERATE_DEFUAL (44100) +#define MIC_EFFECT_SAMPLERATE (44100L) + +#if TCFG_MIC_EFFECT_ENABLE +#undef MIC_SamplingFrequency +#define MIC_SamplingFrequency 1 +#undef MIC_AUDIO_RATE +#define MIC_AUDIO_RATE MIC_EFFECT_SAMPLERATE +#undef SPK_AUDIO_RATE +#define SPK_AUDIO_RATE TCFG_REVERB_SAMPLERATE_DEFUAL +#endif + + + +#define TCFG_LOUDSPEAKER_ENABLE DISABLE //不能与TCFG_MIC_EFFECT_ENABLE同时打开 +#define TCFG_USB_MIC_ECHO_ENABLE DISABLE // +#define TCFG_USB_MIC_DATA_FROM_MICEFFECT DISABLE // +#define TCFG_KARAOKE_EARPHONE DISABLE + +//*********************************************************************************// +// g-sensor配置 // +//*********************************************************************************// +#define TCFG_GSENSOR_ENABLE 0 //gSensor使能 +#define TCFG_DA230_EN 0 +#define TCFG_SC7A20_EN 0 +#define TCFG_STK8321_EN 0 +#define TCFG_GSENOR_USER_IIC_TYPE 0 //0:软件IIC 1:硬件IIC + +//*********************************************************************************// +// 系统配置 // +//*********************************************************************************// +#define TCFG_AUTO_SHUT_DOWN_TIME 0 //没有蓝牙连接自动关机时间 +#define TCFG_SYS_LVD_EN 1 //电量检测使能 +#define TCFG_POWER_ON_NEED_KEY 0 //是否需要按按键开机配置 +#define TWFG_APP_POWERON_IGNORE_DEV 4000//上电忽略挂载设备,0时不忽略,非0则n毫秒忽略 + +#define TCFG_AUDIO_DEC_OUT_TASK 0 // 解码使用单独任务做输出 + +//*********************************************************************************// +// 蓝牙配置 // +//*********************************************************************************// +#define TCFG_USER_TWS_ENABLE 1 //tws功能使能 +#define TCFG_USER_BLE_ENABLE 0 //BLE功能使能 +#define TCFG_USER_BT_CLASSIC_ENABLE 1 //经典蓝牙功能使能 +#define TCFG_BT_SUPPORT_AAC 0 //AAC格式支持 +#define TCFG_USER_EMITTER_ENABLE 0 //emitter功能使能 +#define TCFG_BT_SNIFF_ENABLE 0 //bt sniff 功能使能 + +#define USER_SUPPORT_PROFILE_SPP 0 +#define USER_SUPPORT_PROFILE_HFP 1 +#define USER_SUPPORT_PROFILE_A2DP 1 +#define USER_SUPPORT_PROFILE_AVCTP 1 +#define USER_SUPPORT_PROFILE_HID 1 +#define USER_SUPPORT_PROFILE_PNP 1 +#define USER_SUPPORT_PROFILE_PBAP 0 + + +#define USER_SUPPORT_DUAL_A2DP_SOURCE 0 + +#if TCFG_USER_TWS_ENABLE +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 0 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 1 //对箱通话slave出声音 +#else +#define TCFG_BD_NUM 1 //连接设备个数配置 +#define TCFG_AUTO_STOP_PAGE_SCAN_TIME 180 //配置一拖二第一台连接后自动关闭PAGE SCAN的时间(单位分钟) +#define TCFG_USER_ESCO_SLAVE_MUTE 0 //对箱通话slave出声音 +#endif + + +#define BT_INBAND_RINGTONE 0 //是否播放手机自带来电铃声 +#define BT_PHONE_NUMBER 1 //是否播放来电报号 +#define BT_SYNC_PHONE_RING 1 //是否TWS同步播放来电铃声 +#define BT_SUPPORT_DISPLAY_BAT 1 //是否使能电量检测 +#define BT_SUPPORT_MUSIC_VOL_SYNC 1 //是否使能音量同步 + +#define TCFG_BLUETOOTH_BACK_MODE 1 //后台模式 + +#define CONFIG_LOCAL_TWS_ENABLE 1 + +#if (TCFG_USER_TWS_ENABLE && TCFG_BLUETOOTH_BACK_MODE) && (TCFG_BT_SNIFF_ENABLE==0) && (CONFIG_LOCAL_TWS_ENABLE) +#define TCFG_DEC2TWS_ENABLE 1 // 本地解码转发 +#define TCFG_PCM_ENC2TWS_ENABLE 1 // pcm编码转发 +#define TCFG_TONE2TWS_ENABLE 1 // 提示音转发 +#define TCFG_DEC2TWS_TASK_ENABLE 0 // localtws使用单独task +#else +#define TCFG_DEC2TWS_ENABLE 0 +#define TCFG_PCM_ENC2TWS_ENABLE 0 +#define TCFG_TONE2TWS_ENABLE 0 +#define TCFG_DEC2TWS_TASK_ENABLE 0 +#endif +#if (APP_ONLINE_DEBUG && !USER_SUPPORT_PROFILE_SPP) +#error "NEED ENABLE USER_SUPPORT_PROFILE_SPP!!!" +#endif + +//*********************************************************************************// +// REC 配置 // +//*********************************************************************************// +#define RECORDER_MIX_EN DISABLE//混合录音使能 +#define TCFG_RECORD_FOLDER_DEV_ENABLE DISABLE//音乐播放录音区分使能 + + +#if RECORDER_MIX_EN//限制不能同时打开 +#ifdef TCFG_AEC_ENABLE +#undef TCFG_AEC_ENABLE +#define TCFG_AEC_ENABLE 0 +#endif//TCFG_AEC_ENABLE +#endif + +// linein配置 // +//*********************************************************************************// +#define TCFG_LINEIN_ENABLE TCFG_APP_LINEIN_EN // linein使能 +// #define TCFG_LINEIN_LADC_IDX 0 // linein使用的ladc通道,对应ladc_list +#define TCFG_LINEIN_LR_CH AUDIO_LIN0_LR +#define TCFG_LINEIN_CHECK_PORT IO_PORTB_03 // linein检测IO +#define TCFG_LINEIN_PORT_UP_ENABLE 1 // 检测IO上拉使能 +#define TCFG_LINEIN_PORT_DOWN_ENABLE 0 // 检测IO下拉使能 +#define TCFG_LINEIN_AD_CHANNEL NO_CONFIG_PORT // 检测IO是否使用AD检测 +#define TCFG_LINEIN_VOLTAGE 0 // AD检测时的阀值 +#define TCFG_LINEIN_INPUT_WAY LINEIN_INPUT_WAY +#define TCFG_LINEIN_MULTIPLEX_WITH_SD DISABLE // linein 检测与 SD cmd 复用 +#define TCFG_LINEIN_SD_PORT 0// 0:sd0 1:sd1 //选择复用的sd + +//*********************************************************************************// +// music 配置 // +//*********************************************************************************// +#define TCFG_DEC_G729_ENABLE ENABLE +#define TCFG_DEC_MP3_ENABLE ENABLE +#define TCFG_DEC_WMA_ENABLE ENABLE +#define TCFG_DEC_WAV_ENABLE ENABLE +#define TCFG_DEC_FLAC_ENABLE DISABLE +#define TCFG_DEC_APE_ENABLE DISABLE +#define TCFG_DEC_M4A_ENABLE DISABLE +#define TCFG_DEC_ALAC_ENABLE DISABLE +#define TCFG_DEC_AMR_ENABLE DISABLE +#define TCFG_DEC_DTS_ENABLE DISABLE +#define TCFG_DEC_G726_ENABLE DISABLE +#define TCFG_DEC_MIDI_ENABLE DISABLE +#define TCFG_DEC_MTY_ENABLE DISABLE +#define TCFG_DEC_SBC_ENABLE ENABLE +#define TCFG_DEC_PCM_ENABLE ENABLE +#define TCFG_DEC_CVSD_ENABLE ENABLE +#define TCFG_DEC_WTGV2_ENABLE DISABLE + +#define TCFG_DEC_ID3_V1_ENABLE DISABLE +#define TCFG_DEC_ID3_V2_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_ENABLE DISABLE +#define TCFG_DEC_DECRYPT_KEY (0x12345678) + +////<变速变调 +#define TCFG_SPEED_PITCH_ENABLE DISABLE// +//*********************************************************************************// +// fm 配置 // +//*********************************************************************************// +#define TCFG_FM_ENABLE TCFG_APP_FM_EN // fm 使能 +#define TCFG_FM_INSIDE_ENABLE ENABLE +#define TCFG_FM_RDA5807_ENABLE DISABLE //需要使能软件IIC模块 +#define TCFG_FM_BK1080_ENABLE DISABLE //需要使能软件IIC模块 +#define TCFG_FM_QN8035_ENABLE DISABLE //需要使能软件IIC模块 + +#define TCFG_FMIN_LADC_IDX 1 // linein使用的ladc通道,对应ladc_list +#define TCFG_FMIN_LR_CH AUDIO_LIN1_LR +#define TCFG_FM_INPUT_WAY LINEIN_INPUT_WAY_ADC //LINEIN_INPUT_WAY_ANALOG + +#if (TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE) +#if (((TCFG_USER_TWS_ENABLE) || (RECORDER_MIX_EN) || (TCFG_MIC_EFFECT_ENABLE))) +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#else +#define TCFG_CODE_RUN_RAM_FM_MODE ENABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif +#else +#define TCFG_CODE_RUN_RAM_FM_MODE DISABLE_THIS_MOUDLE //FM模式 代码跑ram +#endif /*(TCFG_FM_INSIDE_ENABLE && TCFG_FM_ENABLE)*/ + +#if (TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE) +#undef TCFG_LED7_RUN_RAM +#define TCFG_LED7_RUN_RAM ENABLE_THIS_MOUDLE //led7跑ram 不屏蔽中断(需要占据2k附近ram) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE && TCFG_UI_ENABLE)*/ + +//*********************************************************************************// +// fm emitter 配置 // +//*********************************************************************************// +#define TCFG_APP_FM_EMITTER_EN DISABLE_THIS_MOUDLE +#define TCFG_FM_EMITTER_INSIDE_ENABLE DISABLE +#define TCFG_FM_EMITTER_AC3433_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8007_ENABLE DISABLE +#define TCFG_FM_EMITTER_QN8027_ENABLE DISABLE + +//*********************************************************************************// +// rtc 配置 // +//*********************************************************************************// +#define TCFG_RTC_ENABLE TCFG_APP_RTC_EN + +#define TCFG_USE_VIRTUAL_RTC 0//ENABLE //假时钟 + + +//*********************************************************************************// +// SPDIF & ARC 配置 // +//*********************************************************************************// +#define TCFG_SPDIF_ENABLE TCFG_APP_SPDIF_EN +#define TCFG_SPDIF_OUTPUT_ENABLE ENABLE +#define TCFG_HDMI_ARC_ENABLE ENABLE +#define TCFG_HDMI_CEC_PORT IO_PORTA_02 + +//*********************************************************************************// +// IIS 配置 // +//*********************************************************************************// +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) || (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC_IIS) +#define TCFG_IIS_ENABLE ENABLE_THIS_MOUDLE +#else +#define TCFG_IIS_ENABLE DISABLE_THIS_MOUDLE +#endif + +#define TCFG_IIS_MODE (0) // 0:master 1:slave + +#define TCFG_IIS_OUTPUT_EN (ENABLE && TCFG_IIS_ENABLE) +#define TCFG_IIS_OUTPUT_PORT ALINK0_PORTA +#define TCFG_IIS_OUTPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_OUTPUT_SR 44100 +#define TCFG_IIS_OUTPUT_DATAPORT_SEL 0 + +#define TCFG_IIS_INPUT_EN (DISABLE && TCFG_IIS_ENABLE) +#define TCFG_IIS_INPUT_PORT ALINK0_PORTA +#define TCFG_IIS_INPUT_CH_NUM 1 //0:mono,1:stereo +#define TCFG_IIS_INPUT_SR 44100 +#define TCFG_IIS_INPUT_DATAPORT_SEL 1 + +//*********************************************************************************// +// fat 文件系统配置 // +//*********************************************************************************// +#define CONFIG_FATFS_ENABLE ENABLE + + + + +//*********************************************************************************// +// encoder 配置 // +//*********************************************************************************// +#define TCFG_ENC_CVSD_ENABLE ENABLE +#define TCFG_ENC_MSBC_ENABLE ENABLE +#define TCFG_ENC_G726_ENABLE ENABLE +#define TCFG_ENC_MP3_ENABLE ENABLE +#define TCFG_ENC_ADPCM_ENABLE ENABLE +#define TCFG_ENC_PCM_ENABLE ENABLE +#define TCFG_ENC_SBC_ENABLE ENABLE +#define TCFG_ENC_OPUS_ENABLE DISABLE +#define TCFG_ENC_SPEEX_ENABLE DISABLE + +//*********************************************************************************// +//ali ai profile +#define DUEROS_DMA_EN 0 //not surport +#define TRANS_DATA_EN 0 //not surport +#define ANCS_CLIENT_EN 0 + +#if (DUEROS_DMA_EN || TRANS_DATA_EN || ANCS_CLIENT_EN) +#define BT_FOR_APP_EN 1 +#else +#define BT_FOR_APP_EN 0 +#endif + +//*********************************************************************************// + +//*********************************************************************************// +// 电源切换配置 // +//*********************************************************************************// + +#define CONFIG_PHONE_CALL_USE_LDO15 1 + + + + + + + + +//*********************************************************************************// +// 解码叠加配置 +//*********************************************************************************// +#define DEC_MIX_ENABLE 0 + + + +//*********************************************************************************// +// 人声消除使能 +//*********************************************************************************// +#define AUDIO_VOCAL_REMOVE_EN 0 + +///*********************************************************************************// +// 等响度 开启后,需要固定模拟音量,调节软件数字音量 +// 等响度使用eq实现,同个数据流中,若打开等响度,请开eq总使能,关闭其他eq,例如蓝牙模式eq +//*********************************************************************************// +#define AUDIO_EQUALLOUDNESS_CONFIG 0 //等响度, 不支持四声道 + +///*********************************************************************************// +// 环绕音效使能 +//*********************************************************************************// +#define AUDIO_SURROUND_CONFIG 0//3d环绕 + +#define AUDIO_VBASS_CONFIG 0//虚拟低音,虚拟低音不支持四声道 +#define AUDIO_SPECTRUM_CONFIG 0 //频响能量值获取接口 +#define AUDIO_MIDI_CTRL_CONFIG 0 //midi电子琴接口使能 + +#define TCFG_EQ_DIVIDE_ENABLE 0 // 四声道eq是否独立 0 使用同个eq效果 +//*********************************************************************************// +// 编译警告 // +//*********************************************************************************// +#if ((ANCS_CLIENT_EN || TRANS_DATA_EN || ((TCFG_ONLINE_TX_PORT == IO_PORT_DP) && TCFG_ONLINE_ENABLE) ||((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE)) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE || TCFG_SD0_PORTS == 'E')) +// #error "eq online adjust enable, plaease close usb marco and sdcard port not e!!!" +#endif// ((TRANS_DATA_EN || TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) +#error "eq online adjust enable, plaease close usb marco" +#endif// ((TCFG_ONLINE_ENABLE) && (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE)) + +#if ((TCFG_COMM_TYPE == TCFG_UART_COMM) && TCFG_SOUNDBOX_TOOL_ENABLE ) && TCFG_PC_ENABLE +#error "soundbox tool enable, plaease close pc marco" +#endif// (TCFG_SOUNDBOX_TOOL_ENABLE) && (TCFG_PC_ENABLE) + +#if TCFG_UI_ENABLE +#if ((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#error "flash spi port == lcd spi port, please close one !!!" +#endif//((TCFG_SPI_LCD_ENABLE && TCFG_CODE_FLASH_ENABLE) && (TCFG_FLASH_DEV_SPI_HW_NUM == TCFG_TFT_LCD_DEV_SPI_HW_NUM)) +#endif//TCFG_UI_ENABLE + +#if((TRANS_DATA_EN + DUEROS_DMA_EN + ANCS_CLIENT_EN) > 1) +#error "they can not enable at the same time,just select one!!!" +#endif//(TRANS_DATA_EN && DUEROS_DMA_EN) + +#if (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) +// #error "对箱支持音源转发,请关闭混响录音等功能 !!!" +#endif// (TCFG_DEC2TWS_ENABLE && (TCFG_MIC_EFFECT_ENABLE ||TCFG_APP_RECORD_EN || TCFG_APP_RTC_EN ||TCFG_DRC_ENABLE)) + +#if (TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) +#error "无损格式+混响暂时不支持同时打开 !!!" +#endif//(TCFG_MIC_EFFECT_ENABLE && (TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE)) + +#if (TCFG_REVERB_DODGE_EN && (USER_DIGITAL_VOLUME_ADJUST_ENABLE == 0)) +#error "使用闪避功能,打开自定义数字音量调节 !!!" +#endif + +#if ((TCFG_NORFLASH_DEV_ENABLE || TCFG_NOR_FS_ENABLE) && TCFG_UI_ENABLE) +#error "引脚复用问题,使用norflash需要关闭UI !!!" +#endif + +#if ((TCFG_APP_RECORD_EN) && (TCFG_USER_TWS_ENABLE)) +#error "TWS 暂不支持录音功能" +#endif + +#if ((AUDIO_EQUALLOUDNESS_CONFIG) && (SYS_VOL_TYPE == VOL_TYPE_ANALOG)) +#error "开启等响度 需要使用数字音量" +#endif + +#if ((TCFG_APP_FM_EN) && (TCFG_MIC_EFFECT_ENABLE) && (RECORDER_MIX_EN)) +#error "FM模式下开混响暂不支持混合录音" +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG +#if (TCFG_EQ_ENABLE == 0) +#error "开启等响度 需要打开EQ总使能" +#endif +#if (TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE) +#error "开启等响度 需要打开EQ总使能,关闭其他模式的eq,例如关闭蓝牙播歌eq" +#endif +#endif +#if TCFG_MIC_DODGE_EN +#if !SYS_DIGVOL_GROUP_EN +#error "请使能软件数字音量SYS_DIGVOL_GROUP_EN" +#endif +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_DRC_ENABLE //动态eq使能后,需接入drc进行幅度控制 +#error "动态eq使能后,需使能TCFG_DRC_ENABLE接入drc进行幅度控制" +#endif +#if TCFG_DYNAMIC_EQ_ENABLE && !TCFG_AUDIO_MDRC_ENABLE +#error "动态eq使能后,需使能TCFG_AUDIO_MDRC_ENABLE 为1接入多带drc进行幅度控制" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && LINEIN_MODE_SOLE_EQ_EN +#error "2.1/2.2声道不支持 linein模式独立的eq\drc配置" +#endif +#if TCFG_EQ_DIVIDE_ENABLE && (TCFG_AUDIO_DAC_CONNECT_MODE != DAC_OUTPUT_FRONT_LR_REAR_LR) +#error "eq效果独立,需使能四声道宏DAC_OUTPUT_FRONT_LR_REAR_LR" +#endif +#if SOUND_TRACK_2_P_X_CH_CONFIG && !TCFG_EQ_DIVIDE_ENABLE +#error "2.1/2.2声道,需使能宏TCFG_EQ_DIVIDE_ENABLE" +#endif +#if TCFG_MIC_VOICE_CHANGER_ENABLE && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) +#error "变声目前支持加载ECHO音效下" +#endif +#if TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE &&((TCFG_MIC_EFFECT_SEL != MIC_EFFECT_ECHO) && (TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE)) +#error "tws时,只支持ehco混响或者megaphone" +#endif + +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! +///<<<<所有宏定义不要在编译警告后面定义!!!!!!!!!!!!!!!!!!!!!!!!!! + + +//*********************************************************************************// +// 配置结束 // +//*********************************************************************************// + + +#endif //CONFIG_BOARD_AC695X_DEMO +#endif //CONFIG_BOARD_AC695X_DEMO_CFG_H diff --git a/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/adkey_table.c b/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/adkey_table.c new file mode 100644 index 0000000..aa09dc7 --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/adkey_table.c @@ -0,0 +1,356 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_TWS_BOX +/*********************************************************** + * bt 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_TWS_SEARCH_REMOVE_PAIR, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_FM_PREV_STATION, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_FM_SCAN_ALL_DOWN, KEY_NULL + }, + [3] = { + KEY_FM_NEXT_STATION, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_UP, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_DOWN, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_MUSIC_CHANGE_DEV, KEY_NULL, KEY_NULL, KEY_MUSIC_CHANGE_REPEAT, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_MUSIC_PLAYE_PREV_FOLDER, KEY_MUSIC_FR, KEY_MUSIC_FR, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_MUSIC_PLAYE_NEXT_FOLDER, KEY_MUSIC_FF, KEY_MUSIC_FF, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_PREV, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_ENC_START, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_RTC_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_RTC_UP, KEY_RTC_UP, KEY_RTC_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_REVERB_OPEN, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 adkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_CHANGE_MODE, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 adkey table + ***********************************************************/ +const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX] = { + //单击 //长按 //hold //抬起 //双击 //三击 + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/iokey_table.c b/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/iokey_table.c new file mode 100644 index 0000000..e7810fb --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/iokey_table.c @@ -0,0 +1,239 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_TWS_BOX +/*********************************************************** + * bt 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_CALL_HANG_UP, KEY_NULL, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_NEXT, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_CALL_LAST_NO, KEY_NULL + }, + [1] = { + KEY_FM_NEXT_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_FM_PREV_STATION, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_FM_SCAN_ALL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_FM_NEXT_FREQ, KEY_FM_SCAN_ALL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_FM_PREV_FREQ, KEY_FM_SCAN_ALL_UP, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_MUSIC_NEXT, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_MUSIC_PREV, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_VOL_UP, KEY_VOL_UP, KEY_VOL_UP, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_VOL_DOWN, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_RTC_SW_POS, KEY_RTC_SW, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 iokey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_MUSIC_PP, KEY_POWEROFF, KEY_POWEROFF_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_SPDIF_SW_SOURCE, KEY_NULL + }, + [3] = { + KEY_CHANGE_MODE, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 iokey table + ***********************************************************/ +const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_POWER_ON, KEY_POWER_ON_HOLD, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/irkey_table.c b/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/irkey_table.c new file mode 100644 index 0000000..dbc4b2f --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/irkey_table.c @@ -0,0 +1,644 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_TWS_BOX +/*********************************************************** + * bt 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 irkey table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 irkey table + ***********************************************************/ +const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [6] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [7] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [8] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [9] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [10] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [11] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [12] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [13] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [14] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [15] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [16] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [17] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [18] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [19] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [20] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/rdec_key_table.c b/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/rdec_key_table.c new file mode 100644 index 0000000..89629dd --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/rdec_key_table.c @@ -0,0 +1,158 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_TWS_BOX +/*********************************************************** + * bt 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 rdec_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 rdec_key table + ***********************************************************/ +const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/touch_key_table.c b/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/touch_key_table.c new file mode 100644 index 0000000..8a2b94e --- /dev/null +++ b/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/touch_key_table.c @@ -0,0 +1,239 @@ +#include "board_config.h" +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "app_task.h" + +#ifdef CONFIG_BOARD_AC695X_TWS_BOX +/*********************************************************** + * bt 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_BT_EN +const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * fm 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_FM_EN +const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * linein 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_LINEIN_EN +const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * music 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_MUSIC_EN +const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * pc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_PC_EN +const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * record 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RECORD_EN +const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * rtc 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_RTC_EN +const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * spdif 模式的 touch_key table + ***********************************************************/ +#if TCFG_APP_SPDIF_EN +const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif + +/*********************************************************** + * idle 模式的 touch_key table + ***********************************************************/ +const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX] = { + [0] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [1] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [2] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [3] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [4] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, + [5] = { + KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL, KEY_NULL + }, +}; +#endif diff --git a/apps/soundbox/board/br23/board_config.h b/apps/soundbox/board/br23/board_config.h new file mode 100644 index 0000000..92b94bc --- /dev/null +++ b/apps/soundbox/board/br23/board_config.h @@ -0,0 +1,79 @@ +#ifndef BOARD_CONFIG_H +#define BOARD_CONFIG_H + +/* + * 板级配置选择 + */ + +// #define CONFIG_BOARD_AC695X_DEMO +// #define CONFIG_BOARD_AC6951_KGB_V1 +// #define CONFIG_BOARD_AC6955F_HEADSET_MONO +// #define CONFIG_BOARD_AC6952E_LIGHTER +// #define CONFIG_BOARD_AC695X_CHARGING_BIN +#define CONFIG_BOARD_AC695X_BTEMITTER +// #define CONFIG_BOARD_AC695X_TWS_BOX +// #define CONFIG_BOARD_AC695X_TWS +// #define CONFIG_BOARD_AC695X_MULTIMEDIA_CHARGING_BIN +// #define CONFIG_BOARD_AC695X_SOUNDCARD +// #define CONFIG_BOARD_AC6954A_DEMO +// #define CONFIG_BOARD_AC695X_SMARTBOX +// #define CONFIG_BOARD_AC695X_LCD +// #define CONFIG_BOARD_AC695X_CVP_DEVELOP//第三方清晰语音处理模块开发 +/* + *CONFIG_BOARD_AC695X_AUDIO_EFFECTS板级用于开发音效方案 + *(1)使用说明:该板级根据现有芯片资源,优化配置了音效模块组合 + * 如果修改了里面某些配置,导致数据流卡顿,则表示不支持(触及芯片性能极限) + *(2)适用场景:K歌宝 + */ +// #define CONFIG_BOARD_AC695X_AUDIO_EFFECTS + +/* + *CONFIG_BOARD_AC695X_MEGAPHONE板级用于开发大声公方案 + *(1)使用说明:该板级根据现有芯片资源,优化配置了音效模块组合 + * 如果修改了里面某些配置,导致数据流卡顿,则表示不支持(触及芯片性能极限) + *(2)适用场景:大声公/扩音器 + */ +// #define CONFIG_BOARD_AC695X_MEGAPHONE + +// #define CONFIG_BOARD_AC6951G +// #define CONFIG_BOARD_AC6083A +// #define CONFIG_BOARD_AC6083A_IAP + + +#define DAC_OUTPUT_MONO_L 0 //左声道 +#define DAC_OUTPUT_MONO_R 1 //右声道 +#define DAC_OUTPUT_LR 2 //立体声 +#define DAC_OUTPUT_MONO_LR_DIFF 3 //单声道差分输出 + +#define DAC_OUTPUT_DUAL_LR_DIFF 6 //双声道差分 +#define DAC_OUTPUT_FRONT_LR_REAR_L 7 //三声道单端输出 前L+前R+后L (不可设置vcmo公共端) +#define DAC_OUTPUT_FRONT_LR_REAR_R 8 //三声道单端输出 前L+前R+后R (可设置vcmo公共端) +#define DAC_OUTPUT_FRONT_LR_REAR_LR 9 //四声道单端输出(不可设置vcmo公共端) + +#include "board_ac6954a_demo/board_ac6954a_demo_cfg.h" //SPDIF-HDMI-IIS测试板 +#include "board_ac695x_demo/board_ac695x_demo_cfg.h" +#include "board_ac6951_kgb_v1/board_ac6951_kgb_cfg.h" +#include "board_ac6952e_lighter/board_ac6952e_lighter_cfg.h" //蓝牙点烟器 +#include "board_ac6955f_headset_mono/board_ac6955f_headset_mono_cfg.h" //蓝牙带卡耳机 +#include "board_ac695x_charging_bin/board_ac695x_charging_bin.h" //智能充电仓 +#include "board_ac695x_btemitter/board_ac695x_btemitter.h" //蓝牙发射器 +#include "board_ac695x_tws_box/board_ac695x_tws_box.h" //对箱 +#include "board_ac695x_tws/board_ac695x_tws.h" //纯对箱 +#include "board_ac695x_multimedia_charging_bin/board_ac695x_multimedia_charging_bin.h" //多媒体智能充电仓发射器 +#include "board_ac695x_soundcard/board_ac695x_soundcard.h" //声卡 +#include "board_ac695x_smartbox/board_ac695x_smartbox.h" //杰理之家智能音箱 +#include "board_ac695x_lcd/board_ac695x_lcd_cfg.h"// +#include "board_ac695x_cvp_develop/board_ac695x_cvp_develop_cfg.h" //第三方清晰语音处理模块开发 +#include "board_ac695x_audio_effects/board_ac695x_audio_effects_cfg.h" //K歌宝开发 +#include "board_ac695x_megaphone/board_ac695x_megaphone_cfg.h" //大声公/扩音器开发 + +#include "board_ac6951g/board_ac6951g_cfg.h" + +#include "board_ac6083a/board_ac6083a_cfg.h" +#include "board_ac6083a_iap/board_ac6083a_iap_cfg.h" + + +#define DUT_AUDIO_DAC_LDO_VOLT DACVDD_LDO_2_90V + + +#endif diff --git a/apps/soundbox/board/br23/irq_config.c b/apps/soundbox/board/br23/irq_config.c new file mode 100644 index 0000000..032260b --- /dev/null +++ b/apps/soundbox/board/br23/irq_config.c @@ -0,0 +1,97 @@ +#include "system/includes.h" + +static const u8 irq_pro_list[MAX_IRQ_ENTRY_NUM] = { + [IRQ_EMUEXCPT_IDX ] = 0, + [IRQ_EXCEPTION_IDX ] = 7, + [IRQ_SYSCALL_IDX ] = 0, + [IRQ_TICK_TMR_IDX ] = 1, + [IRQ_TIME0_IDX ] = 5,//ir + [IRQ_TIME1_IDX ] = 3, + +#if TCFG_LED7_RUN_RAM + [IRQ_TIME2_IDX ] = 6,//总中断关闭,不关闭优先级6的中断、扫屏led7 +#else + [IRQ_TIME2_IDX ] = 5,//总中断关闭,不关闭优先级5的中断、扫屏led7 +#endif + + [IRQ_TIME3_IDX ] = 3, + [IRQ_USB_SOF_IDX ] = 1, + [IRQ_USB_CTRL_IDX ] = 3, + [IRQ_RTC_WDT_IDX ] = 0, + [IRQ_ALINK0_IDX ] = 3, + [IRQ_AUDIO_IDX ] = 2, + [IRQ_PORT_IDX ] = 0, + [IRQ_SPI0_IDX ] = 0, + [IRQ_SPI1_IDX ] = 0, + [IRQ_SD0_IDX ] = 3, + [IRQ_SD1_IDX ] = 3, + [IRQ_UART0_IDX ] = 3, + [IRQ_UART1_IDX ] = 3, + [IRQ_UART2_IDX ] = 0, + [IRQ_PAP_IDX ] = 0, + [IRQ_IIC_IDX ] = 0, + [IRQ_SARADC_IDX ] = 0, + [IRQ_PDM_LINK_IDX ] = 1, + [IRQ_RDEC0_IDX ] = 1, + [IRQ_LRCT_IDX ] = 2, + [IRQ_BREDR_IDX ] = 2, + [IRQ_BT_CLKN_IDX ] = 2, + [IRQ_BT_DBG_IDX ] = 0, + [IRQ_WL_LOFC_IDX ] = 2, + [IRQ_SRC_IDX ] = 1, + [IRQ_FFT_IDX ] = 1, + [IRQ_EQ_IDX ] = 1, + [IRQ_LP_TIMER0_IDX ] = 3, + [IRQ_LP_TIMER1_IDX ] = 3, + [IRQ_ALINK1_IDX ] = 3, + [IRQ_OSA_IDX ] = 0, + [IRQ_BLE_RX_IDX ] = 2, + [IRQ_BLE_EVENT_IDX ] = 2, + [IRQ_AES_IDX ] = 0, + [IRQ_MCTMRX_IDX ] = 0, + [IRQ_CHX_PWM_IDX ] = 0, + [IRQ_FMRX_IDX ] = 0, + [IRQ_SPI2_IDX ] = 0, + [IRQ_SBC_IDX ] = 1, + [IRQ_GPC_IDX ] = 0, + [IRQ_FMTX_IDX ] = 4, + [IRQ_DCP_IDX ] = 1, + [IRQ_RDEC1_IDX ] = 1, + [IRQ_RDEC2_IDX ] = 1, + [IRQ_SPDIF_IDX ] = 2, + [IRQ_PWM_LED_IDX ] = 1, + [IRQ_CTM_IDX ] = 1, + [IRQ_SOFT0_IDX ] = 0, + [IRQ_SOFT1_IDX ] = 0, + [IRQ_SOFT2_IDX ] = 0, + [IRQ_SOFT3_IDX ] = 0, +}; + +void irq_disable_t() +{ + u8 i; + for (i = 0; i < MAX_IRQ_ENTRY_NUM; i++) { + irq_disable(i); + } +} + +void irq_enable_t() +{ + u8 i; + for (i = 0; i < MAX_IRQ_ENTRY_NUM; i++) { + irq_enable(i); + } +} + + + +u8 irq_priority_get(u8 index) +{ + /* printf("irq index = %d\n", index); */ + ///测试如果有问题, 请先直接该函数返回0xff,即可以还原之前中断优先级配置 + if (index >= MAX_IRQ_ENTRY_NUM) { + return 0xff; + } + return irq_pro_list[index]; +} + diff --git a/apps/soundbox/common/app_sound_box_tool.c b/apps/soundbox/common/app_sound_box_tool.c new file mode 100644 index 0000000..a5a43e0 --- /dev/null +++ b/apps/soundbox/common/app_sound_box_tool.c @@ -0,0 +1,731 @@ +#include "app_sound_box_tool.h" +#include "event.h" +#include "usb/device/cdc.h" +#include "boot.h" +#include "ioctl_cmds.h" +#include "board_config.h" +#include "app_online_cfg.h" +#include "asm/crc16.h" + +#define LOG_TAG_CONST APP_SOUNDBOX_TOOL +#define LOG_TAG "[APP_SOUNDBOX_TOOL]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +struct sound_box_tool_info { + /*PC往小机发送的DATA*/ + R_QUERY_BASIC_INFO r_basic_info; + R_QUERY_FILE_SIZE r_file_size; + R_QUERY_FILE_CONTENT r_file_content; + R_PREPARE_WRITE_FILE r_prepare_write_file; + R_READ_ADDR_RANGE r_read_addr_range; + R_ERASE_ADDR_RANGE r_erase_addr_range; + R_WRITE_ADDR_RANGE r_write_addr_range; + R_ENTER_UPGRADE_MODE r_enter_upgrade_mode; + + /*小机返回PC发送的DATA*/ + S_QUERY_BASIC_INFO s_basic_info; + S_QUERY_FILE_SIZE s_file_size; + S_PREPARE_WRITE_FILE s_prepare_write_file; +}; + +static struct sound_box_tool_info info = { + .s_basic_info.protocolVer = PROTOCOL_VER, +}; + +#define TEMP_BUF_SIZE 256 + +extern const char *sdk_version_info_get(void); +extern u8 *sdfile_get_burn_code(u8 *len); +extern int norflash_erase(u32 cmd, u32 addr); + +static u8 local_packet[TEMP_BUF_SIZE]; +const char error_return[] = "FA"; //表示失败 +const char ok_return[] = "OK"; //表示成功 +static u32 size_total_write = 0; + +extern void doe(u16 k, void *pBuf, u32 lenIn, u32 addr); +extern int norflash_erase(u32 cmd, u32 addr); + +#ifdef ALIGN +#undef ALIGN +#endif + +#define ALIGN(a, b) \ + ({ \ + int m = (u32)(a) & ((b)-1); \ + int ret = (u32)(a) + (m?((b)-m):0); \ + ret;\ + }) + +static u32 sound_box_encode_data_by_user_key(u16 key, u8 *buff, u16 size, u32 dec_addr, u8 dec_len) +{ + u16 key_addr; + u16 r_len; + + while (size) { + r_len = (size > dec_len) ? dec_len : size; + key_addr = (dec_addr >> 2)^key; + doe(key_addr, buff, r_len, 0); + buff += r_len; + dec_addr += r_len; + size -= r_len; + } + + return dec_addr; +} + +/*全封装与发送*/ +void all_assemble_package_send_to_pc(u8 id, u8 sq, u8 *buf, u32 len) +{ + u8 send_buf[TEMP_BUF_SIZE]; + u16 crc16_data; + + /*添加报头*/ + send_buf[0] = 0x5A; + send_buf[1] = 0xAA; + send_buf[2] = 0xA5; + + + /*L*/ + send_buf[5] = 2 + len; + + /*T*/ + send_buf[6] = id; + + /*SQ*/ + send_buf[7] = sq; + + /*组包完成*/ + memcpy(send_buf + 8, buf, len); + + /*添加CRC16*/ + crc16_data = CRC16(&send_buf[5], len + 3); + send_buf[3] = crc16_data & 0xff; + send_buf[4] = (crc16_data >> 8) & 0xff; + + + /* printf_buf(send_buf, len + 8); */ + + /*发送给PC*/ +#if TCFG_ONLINE_ENABLE +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) + cdc_write_data(0, send_buf, len + 8); +#else + ci_uart_write(send_buf, len + 8); +#endif +#endif +} + +/*组包与发送*/ +void assemble_package_send_to_pc(u8 *buf, u32 len) +{ + u8 send_buf[TEMP_BUF_SIZE]; + u16 crc16_data; + + /*添加报头*/ + send_buf[0] = 0x5A; + send_buf[1] = 0xAA; + send_buf[2] = 0xA5; + + /*添加CRC16*/ + crc16_data = CRC16(buf, len); + send_buf[3] = crc16_data & 0xff; + send_buf[4] = (crc16_data >> 8) & 0xff; + + /*组包完成*/ + memcpy(send_buf + 5, buf, len); + + /* printf_buf(send_buf, len + 5); */ + + /*发送给PC*/ +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) +#if (TCFG_COMM_TYPE == TCFG_USB_COMM) + cdc_write_data(0, send_buf, len + 5); +#else + ci_uart_write(send_buf, len + 5); +#endif +#endif +} + +/*6个byte的校验码数组转为字符串*/ +void hex2text(u8 *buf, u8 *out) +{ + sprintf(out, "%02x%02x-%02x%02x%02x%02x", buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]); +} + +extern void nvram_set_boot_state(u32 state); +extern void hw_mmu_disable(void); +extern void ram_protect_close(void); + +AT(.volatile_ram_code) +void soundbox_tool_go_mask_usb_updata() +{ + local_irq_disable(); + ram_protect_close(); + hw_mmu_disable(); + nvram_set_boot_state(2); + + JL_CLOCK->PWR_CON |= (1 << 4); + /* chip_reset(); */ + /* cpu_reset(); */ + while (1); +} + +int app_soundbox_tool_event_handler(struct soundbox_tool_event *soundbox_tool_dev) +{ + u8 buf[TEMP_BUF_SIZE]; + u8 *buf_temp = NULL; + u8 *buf_temp_0 = NULL; + u32 erase_cmd; + int write_len; + u8 crc_temp_len, sdkname_temp_len; + char proCrc_fw[32] = {0}; + char sdkName_fw[32] = {0}; + const struct tool_interface *p; + + /* printf_buf(soundbox_tool_dev->packet, soundbox_tool_dev->size); */ + + buf_temp_0 = (u8 *)malloc(256); + buf_temp_0 = (u8 *)ALIGN(buf_temp_0, 4); + memset(buf_temp_0, 0, 256); + memcpy(buf_temp_0 + 1, soundbox_tool_dev->packet, soundbox_tool_dev->size); + + /*数据进行处理*/ + list_for_each_tool_interface(p) { + if (p->id == soundbox_tool_dev->packet[1]) { + p->tool_message_deal(buf_temp_0 + 2, soundbox_tool_dev->size - 1); + if (buf_temp_0) { + free(buf_temp_0); + } + return 0; + } + } + + memset(buf, 0, TEMP_BUF_SIZE); + + switch (soundbox_tool_dev->event) { + case ONLINE_SUB_OP_QUERY_BASIC_INFO: + log_info("event_ONLINE_SUB_OP_QUERY_BASIC_INFO\n"); + + /*获取校验码*/ + u8 *p = sdfile_get_burn_code(&crc_temp_len); + memcpy(info.s_basic_info.progCrc, p + 8, 6); + /* printf_buf(info.s_basic_info.progCrc, 6); */ + hex2text(info.s_basic_info.progCrc, proCrc_fw); + /* log_info("crc:%s\n", proCrc_fw); */ + + /*获取固件版本信息*/ + sdkname_temp_len = strlen(sdk_version_info_get()); + memcpy(info.s_basic_info.sdkName, sdk_version_info_get(), sdkname_temp_len); + memcpy(sdkName_fw, info.s_basic_info.sdkName, sdkname_temp_len); + log_info("version:%s\n", sdk_version_info_get()); + + struct flash_head flash_head_for_pid_vid; + + for (u8 i = 0; i < 5; i++) { + norflash_read(NULL, (u8 *)&flash_head_for_pid_vid, 32, 0x1000 * i); + doe(0xffff, (u8 *)&flash_head_for_pid_vid, 32, 0); + if (flash_head_for_pid_vid.crc == 0xffff) { + continue; + } else { + log_info("flash head addr = 0x%x\n", 0x1000 * i); + break; + } + } + + struct flash_head _head; + struct flash_head *temp_p = &_head; + memcpy(temp_p, &flash_head_for_pid_vid, 32); + + /*获取PID*/ + memset(info.s_basic_info.pid, 0, sizeof(info.s_basic_info.pid)); + memcpy(info.s_basic_info.pid, temp_p->pid, sizeof(info.s_basic_info.pid)); + for (u8 i = 0; i < sizeof(info.s_basic_info.pid); i++) { + if (~info.s_basic_info.pid[i] == 0x00) { + info.s_basic_info.pid[i] = 0x00; + } + } + /* printf_buf(info.s_basic_info.pid, 16); */ + + /*获取VID*/ + memset(info.s_basic_info.vid, 0, sizeof(info.s_basic_info.vid)); + memcpy(info.s_basic_info.vid, temp_p->vid, 4); + /* printf_buf(info.s_basic_info.vid, 16); */ + + /*第一次组包*/ + buf[0] = 1 + 1 + sizeof(info.s_basic_info.protocolVer) + sizeof(proCrc_fw) + sizeof(sdkName_fw) + 32; + buf[1] = REPLY_STYLE; + buf[2] = soundbox_tool_dev->packet[2]; + buf[3] = (info.s_basic_info.protocolVer >> 8) & 0xff; + buf[4] = info.s_basic_info.protocolVer & 0xff; + memcpy(buf + 5, proCrc_fw, sizeof(proCrc_fw)); + memcpy(buf + 5 + sizeof(proCrc_fw), sdkName_fw, sizeof(sdkName_fw)); + memcpy(buf + 5 + sizeof(proCrc_fw) + sizeof(sdkName_fw), info.s_basic_info.pid, 16); + memcpy(buf + 5 + sizeof(proCrc_fw) + sizeof(sdkName_fw) + 16, info.s_basic_info.vid, 16); + + /* printf_buf(buf, buf[0] + 1); */ + + /*二次组包添加报头与CRC16并发送*/ + assemble_package_send_to_pc(buf, buf[0] + 1); + break; + case ONLINE_SUB_OP_QUERY_FILE_SIZE: + log_info("event_ONLINE_SUB_OP_QUERY_FILE_SIZE\n"); + + /*读取文件ID*/ + info.r_file_size.file_id = (soundbox_tool_dev->packet[7] | (soundbox_tool_dev->packet[8] << 8) | \ + (soundbox_tool_dev->packet[9] << 16) | (soundbox_tool_dev->packet[10] << 24)); + + if ((info.r_file_size.file_id == CFG_TOOL_FILEID) || (info.r_file_size.file_id == CFG_EQ_FILEID)) { + /*根据名字获取文件句柄*/ + FILE *cfg_fp = NULL; + + if ((info.r_file_size.file_id == CFG_TOOL_FILEID)) { + cfg_fp = fopen(CFG_TOOL_FILE, "r"); + log_info("open cfg_tool.bin\n"); + if (cfg_fp == NULL) { + log_error("file open error!\n"); + break; + } + } else { + cfg_fp = fopen(CFG_EQ_FILE, "r"); + log_info("open eq_cfg_hw.bin\n"); + if (cfg_fp == NULL) { + log_error("file open error!\n"); + break; + } + } + + /*根据文件句柄获取文件属性*/ + struct vfs_attr attr; + fget_attrs(cfg_fp, &attr); + + /* log_info("file addr:%x,file size:%d\n", attr.sclust, attr.fsize); */ + info.s_file_size.file_size = attr.fsize; + + /*第一次组包*/ + buf[0] = 1 + 1 + sizeof(info.s_file_size.file_size);//长度 + buf[1] = REPLY_STYLE;//包的类型 + buf[2] = soundbox_tool_dev->packet[2];//回复序列号 + + /*小端格式*/ + buf[6] = (info.s_file_size.file_size >> 24) & 0xff; + buf[5] = (info.s_file_size.file_size >> 16) & 0xff; + buf[4] = (info.s_file_size.file_size >> 8) & 0xff; + buf[3] = info.s_file_size.file_size & 0xff; + + /*二次组包添加报头与CRC16并发送*/ + assemble_package_send_to_pc(buf, buf[0] + 1); + + fclose(cfg_fp); + } + break; + case ONLINE_SUB_OP_QUERY_FILE_CONTENT: + log_info("event_ONLINE_SUB_OP_QUERY_FILE_CONTENT\n"); + + /*读取文件的ID*/ + info.r_file_content.file_id = (soundbox_tool_dev->packet[7] | (soundbox_tool_dev->packet[8] << 8) | \ + (soundbox_tool_dev->packet[9] << 16) | (soundbox_tool_dev->packet[10] << 24)); + /*读取文件的偏移*/ + info.r_file_content.offset = (soundbox_tool_dev->packet[11] | (soundbox_tool_dev->packet[12] << 8) | \ + (soundbox_tool_dev->packet[13] << 16) | (soundbox_tool_dev->packet[14] << 24)); + /*读取文件的大小*/ + info.r_file_content.size = (soundbox_tool_dev->packet[15] | (soundbox_tool_dev->packet[16] << 8) | \ + (soundbox_tool_dev->packet[17] << 16) | (soundbox_tool_dev->packet[18] << 24)); + + if ((info.r_file_content.file_id == CFG_TOOL_FILEID) || (info.r_file_content.file_id == CFG_EQ_FILEID)) { + /*根据名字获取文件句柄*/ + FILE *cfg_fp = NULL; + + if ((info.r_file_content.file_id == CFG_TOOL_FILEID)) { + cfg_fp = fopen(CFG_TOOL_FILE, "r"); + log_info("open cfg_tool.bin\n"); + if (cfg_fp == NULL) { + log_error("file open error!\n"); + break; + } + } else { + cfg_fp = fopen(CFG_EQ_FILE, "r"); + log_info("open eq_cfg_hw.bin\n"); + if (cfg_fp == NULL) { + log_error("file open error!\n"); + break; + } + } + + /*根据文件句柄获取文件属性*/ + struct vfs_attr attr; + fget_attrs(cfg_fp, &attr); + + /* log_info("file addr:%x,file size:%d\n", attr.sclust, attr.fsize); */ + if (info.r_file_content.size > attr.fsize) { + fclose(cfg_fp); + log_error("reading size more than actual size!\n"); + break; + } + + /*逻辑地址转换成flash物理地址*/ + u32 flash_addr = sdfile_cpu_addr2flash_addr(attr.sclust); + /* log_info("flash_addr:0x%x", flash_addr); */ + + /*读取文件内容*/ + buf_temp = (char *)malloc(info.r_file_content.size); + norflash_read(NULL, (void *)buf_temp, info.r_file_content.size, flash_addr + info.r_file_content.offset); + /* printf_buf(buf_temp, info.r_file_content.size); */ + + /*第一次组包*/ + buf[0] = 1 + 1 + info.r_file_content.size; + buf[1] = REPLY_STYLE; + buf[2] = soundbox_tool_dev->packet[2]; + memcpy(buf + 3, buf_temp, info.r_file_content.size); + + /*二次组包添加报头与CRC16并发送*/ + assemble_package_send_to_pc(buf, buf[0] + 1); + + if (buf_temp) { + free(buf_temp); + } + + fclose(cfg_fp); + } + break; + case ONLINE_SUB_OP_PREPARE_WRITE_FILE: + log_info("event_ONLINE_SUB_OP_PREPARE_WRITE_FILE\n"); + + /*读取文件的ID*/ + info.r_prepare_write_file.file_id = (soundbox_tool_dev->packet[7] | (soundbox_tool_dev->packet[8] << 8) | \ + (soundbox_tool_dev->packet[9] << 16) | (soundbox_tool_dev->packet[10] << 24)); + /*读取文件的大小*/ + info.r_prepare_write_file.size = (soundbox_tool_dev->packet[11] | (soundbox_tool_dev->packet[12] << 8) | \ + (soundbox_tool_dev->packet[13] << 16) | (soundbox_tool_dev->packet[14] << 24)); + + if ((info.r_prepare_write_file.file_id == CFG_TOOL_FILEID) || (info.r_prepare_write_file.file_id == CFG_EQ_FILEID)) { + /*根据名字获取文件句柄*/ + FILE *cfg_fp = NULL; + + if ((info.r_prepare_write_file.file_id == CFG_TOOL_FILEID)) { + cfg_fp = fopen(CFG_TOOL_FILE, "r"); + log_info("open cfg_tool.bin\n"); + if (cfg_fp == NULL) { + log_error("file open error!\n"); + break; + } + } else { + cfg_fp = fopen(CFG_EQ_FILE, "r"); + log_info("open eq_cfg_hw.bin\n"); + if (cfg_fp == NULL) { + log_error("file open error!\n"); + break; + } + } + + /*根据文件句柄获取文件属性*/ + struct vfs_attr attr; + fget_attrs(cfg_fp, &attr); + + /* log_info("file addr:%x,file size:%d\n", attr.sclust, attr.fsize); */ + if (info.r_prepare_write_file.size > attr.fsize) { + //fclose(cfg_fp); + //log_error("preparing to write size more than actual size!\n"); + //break; + } + + /*获取文件实际大小*/ + info.s_prepare_write_file.file_size = attr.fsize; + log_info("file_size = %d\n", info.s_prepare_write_file.file_size); + + /*逻辑地址转换成flash物理地址*/ + info.s_prepare_write_file.file_addr = sdfile_cpu_addr2flash_addr(attr.sclust); + log_info("file_flash_addr:0x%x\n", info.s_prepare_write_file.file_addr); + + /*获取flash擦除单元*/ + info.s_prepare_write_file.earse_unit = boot_info.vm.align * 256; + log_info("earse_unit = %d\n", info.s_prepare_write_file.earse_unit); + + /*第一次组包*/ + buf[0] = 1 + 1 + sizeof(info.s_prepare_write_file.file_size) * 3; + buf[1] = REPLY_STYLE; + buf[2] = soundbox_tool_dev->packet[2]; + + buf[6] = (info.s_prepare_write_file.file_addr >> 24) & 0xff; + buf[5] = (info.s_prepare_write_file.file_addr >> 16) & 0xff; + buf[4] = (info.s_prepare_write_file.file_addr >> 8) & 0xff; + buf[3] = info.s_prepare_write_file.file_addr & 0xff; + + buf[10] = (info.s_prepare_write_file.file_size >> 24) & 0xff; + buf[9] = (info.s_prepare_write_file.file_size >> 16) & 0xff; + buf[8] = (info.s_prepare_write_file.file_size >> 8) & 0xff; + buf[7] = info.s_prepare_write_file.file_size & 0xff; + + buf[14] = (info.s_prepare_write_file.earse_unit >> 24) & 0xff; + buf[13] = (info.s_prepare_write_file.earse_unit >> 16) & 0xff; + buf[12] = (info.s_prepare_write_file.earse_unit >> 8) & 0xff; + buf[11] = info.s_prepare_write_file.earse_unit & 0xff; + + /*二次组包添加报头与CRC16并发送*/ + assemble_package_send_to_pc(buf, buf[0] + 1); + + fclose(cfg_fp); + } + break; + case ONLINE_SUB_OP_READ_ADDR_RANGE: + log_info("event_ONLINE_SUB_OP_READ_ADDR_RANGE\n"); + + /*要读取的flash物理地址*/ + info.r_read_addr_range.addr = (soundbox_tool_dev->packet[7] | (soundbox_tool_dev->packet[8] << 8) | \ + (soundbox_tool_dev->packet[9] << 16) | (soundbox_tool_dev->packet[10] << 24)); + log_info("reading flash addr:0x%x\n", info.r_read_addr_range.addr); + + /*要读取的大小*/ + info.r_read_addr_range.size = (soundbox_tool_dev->packet[11] | (soundbox_tool_dev->packet[12] << 8) | \ + (soundbox_tool_dev->packet[13] << 16) | (soundbox_tool_dev->packet[14] << 24)); + log_info("reading size = %d\n", info.r_read_addr_range.size); + + /*读取文件内容*/ + buf_temp = (char *)malloc(info.r_read_addr_range.size); + norflash_read(NULL, (void *)buf_temp, info.r_read_addr_range.size, info.r_read_addr_range.addr); + /* printf_buf(buf_temp, info.r_read_addr_range.size); */ + + /*第一次组包*/ + buf[0] = 1 + 1 + info.r_read_addr_range.size; + buf[1] = REPLY_STYLE; + buf[2] = soundbox_tool_dev->packet[2]; + memcpy(buf + 3, buf_temp, info.r_read_addr_range.size); + + /*二次组包添加报头与CRC16并发送*/ + assemble_package_send_to_pc(buf, buf[0] + 1); + + if (buf_temp) { + free(buf_temp); + } + break; + case ONLINE_SUB_OP_ERASE_ADDR_RANGE: + log_info("event_ONLINE_SUB_OP_ERASE_ADDR_RANGE\n"); + + /*要擦除的flash物理起始地址*/ + info.r_erase_addr_range.addr = (soundbox_tool_dev->packet[7] | (soundbox_tool_dev->packet[8] << 8) | \ + (soundbox_tool_dev->packet[9] << 16) | (soundbox_tool_dev->packet[10] << 24)); + log_info("erasing flash start addr:0x%x\n", info.r_erase_addr_range.addr); + + /*要擦除的大小,会保证按earse_unit对齐,即总是erase_unit的倍数*/ + info.r_erase_addr_range.size = (soundbox_tool_dev->packet[11] | (soundbox_tool_dev->packet[12] << 8) | \ + (soundbox_tool_dev->packet[13] << 16) | (soundbox_tool_dev->packet[14] << 24)); + log_info("erasing size = %d\n", info.r_erase_addr_range.size); + + log_info("earse_unit = %d\n", info.s_prepare_write_file.earse_unit); + switch (info.s_prepare_write_file.earse_unit) { + case 256: + erase_cmd = IOCTL_ERASE_PAGE; + break; + case (4*1024): + erase_cmd = IOCTL_ERASE_SECTOR; + break; + case (64*1024): + erase_cmd = IOCTL_ERASE_BLOCK; + break; +defualt: + memcpy(buf + 3, error_return, sizeof(error_return)); + log_error("erase error!"); + break; + } + + for (u8 i = 0; i < (info.r_erase_addr_range.size / info.s_prepare_write_file.earse_unit); i ++) { + u8 ret = norflash_erase(erase_cmd, info.r_erase_addr_range.addr + (i * info.s_prepare_write_file.earse_unit)); + if (ret) { + memcpy(buf + 3, error_return, sizeof(error_return)); + log_error("erase error!"); + } else { + memcpy(buf + 3, ok_return, sizeof(ok_return)); + log_info("erase success"); + } + } + + /*第一次组包*/ + buf[0] = 1 + 1 + sizeof(error_return); + buf[1] = REPLY_STYLE; + buf[2] = soundbox_tool_dev->packet[2]; + + /*二次组包添加报头与CRC16并发送*/ + assemble_package_send_to_pc(buf, buf[0] + 1); + break; + case ONLINE_SUB_OP_WRITE_ADDR_RANGE: + log_info("event_ONLINE_SUB_OP_WRITE_ADDR_RANGE\n"); + + /*要写入的flash物理起始地址*/ + info.r_write_addr_range.addr = (soundbox_tool_dev->packet[7] | (soundbox_tool_dev->packet[8] << 8) | \ + (soundbox_tool_dev->packet[9] << 16) | (soundbox_tool_dev->packet[10] << 24)); + /*要写入的大小*/ + info.r_write_addr_range.size = (soundbox_tool_dev->packet[11] | (soundbox_tool_dev->packet[12] << 8) | \ + (soundbox_tool_dev->packet[13] << 16) | (soundbox_tool_dev->packet[14] << 24)); + + log_info("writing flash start addr:0x%x\n", info.r_write_addr_range.addr); + log_info("writing size = %d\n", info.r_write_addr_range.size); + + /*读取要写入文件的内容*/ + buf_temp = (char *)malloc(info.r_write_addr_range.size); + memcpy(buf_temp, soundbox_tool_dev->packet + 15, info.r_write_addr_range.size); + /* printf_buf(buf_temp, info.r_write_addr_range.size); */ + + sound_box_encode_data_by_user_key(boot_info.chip_id, buf_temp, info.r_write_addr_range.size, info.r_write_addr_range.addr - boot_info.sfc.sfc_base_addr, 0x20); + + /*写入数据*/ + write_len = norflash_write(NULL, buf_temp, info.r_write_addr_range.size, info.r_write_addr_range.addr); + + /* norflash_read(NULL, buf_temp, info.r_write_addr_range.size, info.r_write_addr_range.addr); */ + /* printf_buf(buf_temp, info.r_write_addr_range.size); */ + + if (write_len != info.r_write_addr_range.size) { + memcpy(buf + 3, error_return, sizeof(error_return)); + log_error("write error!"); + } else { + memcpy(buf + 3, ok_return, sizeof(ok_return)); + } + + /*第一次组包*/ + buf[0] = 1 + 1 + sizeof(error_return); + buf[1] = REPLY_STYLE; + buf[2] = soundbox_tool_dev->packet[2]; + + /*二次组包添加报头与CRC16并发送*/ + assemble_package_send_to_pc(buf, buf[0] + 1); + + if (buf_temp) { + free(buf_temp); + } + + if (info.r_prepare_write_file.file_id == CFG_TOOL_FILEID) { + size_total_write += info.r_write_addr_range.size; + + log_info("size_total_write = %d\n", size_total_write); + log_info("erasing size = %d\n", info.r_erase_addr_range.size); + + if (size_total_write >= info.r_erase_addr_range.size) { + size_total_write = 0; + log_info("cpu_reset\n"); + extern void cpu_reset(); + cpu_reset(); + } + } + break; + case ONLINE_SUB_OP_ENTER_UPGRADE_MODE: + log_info("event_ONLINE_SUB_OP_ENTER_UPGRADE_MODE\n"); + soundbox_tool_go_mask_usb_updata(); + break; + default: + log_error("invalid data\n"); + break; + } + + if (buf_temp_0) { + free(buf_temp_0); + } + + return 0; +} + +void soundbox_tool_event_to_user(u8 *packet, u32 type, u8 event, u8 size) +{ + struct sys_event e; + e.type = SYS_DEVICE_EVENT; + if (packet != NULL) { + if (size > sizeof(local_packet)) { + return; + } + e.u.soundbox_tool.packet = local_packet; + memcpy(e.u.soundbox_tool.packet, packet, size); + } + e.arg = (void *)type; + e.u.soundbox_tool.event = event; + e.u.soundbox_tool.size = size; + sys_event_notify(&e); +} + +/*不在中断处理 post消息出去*/ +void app_sound_box_tool_message_deal(u8 *buf, u32 len) +{ + u8 cmd = buf[8]; + switch (cmd) { + case ONLINE_SUB_OP_QUERY_BASIC_INFO: + /* log_info("PC is querying basic info\n"); */ + info.r_basic_info.cmd_id = cmd; + soundbox_tool_event_to_user(&buf[5], DEVICE_EVENT_FROM_SOUNDBOX_TOOL, ONLINE_SUB_OP_QUERY_BASIC_INFO, buf[5] + 1); + break; + case ONLINE_SUB_OP_QUERY_FILE_SIZE: + /* log_info("PC is querying file size\n"); */ + info.r_file_size.cmd_id = cmd; + soundbox_tool_event_to_user(&buf[5], DEVICE_EVENT_FROM_SOUNDBOX_TOOL, ONLINE_SUB_OP_QUERY_FILE_SIZE, buf[5] + 1); + break; + case ONLINE_SUB_OP_QUERY_FILE_CONTENT: + /* log_info("PC is querying file content\n"); */ + info.r_file_content.cmd_id = cmd; + soundbox_tool_event_to_user(&buf[5], DEVICE_EVENT_FROM_SOUNDBOX_TOOL, ONLINE_SUB_OP_QUERY_FILE_CONTENT, buf[5] + 1); + break; + case ONLINE_SUB_OP_PREPARE_WRITE_FILE: + /* log_info("PC is preparing to write file\n"); */ + info.r_prepare_write_file.cmd_id = cmd; + soundbox_tool_event_to_user(&buf[5], DEVICE_EVENT_FROM_SOUNDBOX_TOOL, ONLINE_SUB_OP_PREPARE_WRITE_FILE, buf[5] + 1); + break; + case ONLINE_SUB_OP_READ_ADDR_RANGE: + /* log_info("PC is reading address range\n"); */ + info.r_read_addr_range.cmd_id = cmd; + soundbox_tool_event_to_user(&buf[5], DEVICE_EVENT_FROM_SOUNDBOX_TOOL, ONLINE_SUB_OP_READ_ADDR_RANGE, buf[5] + 1); + break; + case ONLINE_SUB_OP_ERASE_ADDR_RANGE: + /* log_info("PC is erasing address range\n"); */ + info.r_erase_addr_range.cmd_id = cmd; + soundbox_tool_event_to_user(&buf[5], DEVICE_EVENT_FROM_SOUNDBOX_TOOL, ONLINE_SUB_OP_ERASE_ADDR_RANGE, buf[5] + 1); + break; + case ONLINE_SUB_OP_WRITE_ADDR_RANGE: + /* log_info("PC is writing address range\n"); */ + info.r_write_addr_range.cmd_id = cmd; + soundbox_tool_event_to_user(&buf[5], DEVICE_EVENT_FROM_SOUNDBOX_TOOL, ONLINE_SUB_OP_WRITE_ADDR_RANGE, buf[5] + 1); + break; + case ONLINE_SUB_OP_ENTER_UPGRADE_MODE: + /* log_info("PC is entering upgrade mode\n"); */ + info.r_enter_upgrade_mode.cmd_id = cmd; + soundbox_tool_event_to_user(&buf[5], DEVICE_EVENT_FROM_SOUNDBOX_TOOL, ONLINE_SUB_OP_ENTER_UPGRADE_MODE, buf[5] + 1); + break; + default: + /* log_info("other tools data\n"); */ + soundbox_tool_event_to_user(&buf[5], DEVICE_EVENT_FROM_SOUNDBOX_TOOL, DEFAULT_ACTION, buf[5] + 1); + break; + } +} + +/*数据包内容校验与处理*/ +void online_cfg_tool_data_deal(void *buf, u32 len) +{ + u8 *data_buf = buf; + u16 crc16_data; + + /* printf_buf(buf, len); */ + + /*DATA前的固定字节包括 (5A AA A5 CRC L T SQ)共8个字节 */ + if (len < 8) { + log_error("Data length is too short, receive an invalid message!\n"); + return; + } + + /*检查报头 5A AA A5是否正确*/ + if ((data_buf[0] != 0x5a) || (data_buf[1] != 0xaa) || (data_buf[2] != 0xa5)) { + log_error("Header check error, receive an invalid message!\n"); + return; + } + + /*CRC16校验,CRC16校验码位于数据包的buf[3]和buf[4]*/ + crc16_data = (data_buf[4] << 8) | data_buf[3]; + if (crc16_data != CRC16(data_buf + 5, len - 5)) { + log_error("CRC16 check error, receive an invalid message!\n"); + return; + } + + /* log_info("The crc16 is %04x\n", crc16_data); */ + /* printf_buf(buf, len); */ + + app_sound_box_tool_message_deal(buf, len); +} + diff --git a/apps/soundbox/common/dev_status.c b/apps/soundbox/common/dev_status.c new file mode 100644 index 0000000..8a240f3 --- /dev/null +++ b/apps/soundbox/common/dev_status.c @@ -0,0 +1,209 @@ +#include "common/dev_status.h" +#include "dev_manager.h" +#include "dev_update.h" +#include "app_config.h" +#include "dev_multiplex_api.h" +#include "app_task.h" +#include "smartbox/smartbox.h" +#include "music/music.h" + + +usb_dev g_usb_id = (usb_dev) - 1; +//*----------------------------------------------------------------------------*/ +/**@brief 设备上线预处理 + @param + event:设备事件 + @return + @note 根据特殊情景,这里可以处理一些例如io复用处理 +*/ +/*----------------------------------------------------------------------------*/ +static int dev_manager_add_prepare(struct sys_event *event) +{ + int ret = 0; + switch ((u32)event->arg) { + case DRIVER_EVENT_FROM_SD0: + case DRIVER_EVENT_FROM_SD1: + case DRIVER_EVENT_FROM_SD2: + //传入0 sd0 1:sd1 + mult_sd_online_mount_before(!!((int)event->arg - DRIVER_EVENT_FROM_SD0), g_usb_id); + break; +#if TCFG_UDISK_ENABLE || TCFG_HOST_AUDIO_ENABLE + case DEVICE_EVENT_FROM_OTG: + ///host mount + mult_usb_mount_before(g_usb_id); + + ret = usb_host_mount(g_usb_id, + MOUNT_RETRY, + MOUNT_RESET, + MOUNT_TIMEOUT); + break; +#endif + } + return ret; +} +//*----------------------------------------------------------------------------*/ +/**@brief 设备上线后处理 + @param + event:设备事件 + err:设备上线错误码 + @return + @note 根据特殊情景,这里可以处理一些例如io复用处理 +*/ +/*----------------------------------------------------------------------------*/ +static int dev_manager_add_after(struct sys_event *event, int err) +{ + int ret = 0; + switch ((u32)event->arg) { + case DRIVER_EVENT_FROM_SD0: + case DRIVER_EVENT_FROM_SD1: + case DRIVER_EVENT_FROM_SD2: + //传入0 sd0 1:sd1 + mult_sd_online_mount_after(!!((int)event->arg - DRIVER_EVENT_FROM_SD0), g_usb_id, err); + break; +#if TCFG_UDISK_ENABLE + case DEVICE_EVENT_FROM_OTG: + mult_usb_online_mount_after(g_usb_id, err); + break; +#endif + } + return ret; +} +//*----------------------------------------------------------------------------*/ +/**@brief 设备下线预处理 + @param + event:设备事件 + @return + @note 根据特殊情景,这里可以处理一些例如io复用处理 +*/ +/*----------------------------------------------------------------------------*/ +static int dev_manager_del_prepare(struct sys_event *event) +{ + int ret = 0; + switch ((u32)event->arg) { + case DRIVER_EVENT_FROM_SD0: + case DRIVER_EVENT_FROM_SD1: + case DRIVER_EVENT_FROM_SD2: + mult_sd_offline_before((char *)event->u.dev.value, g_usb_id); + break; +#if TCFG_UDISK_ENABLE || TCFG_HOST_AUDIO_ENABLE + case DEVICE_EVENT_FROM_OTG: + ///host umount + usb_host_unmount(g_usb_id); + break; +#endif + } + return ret; +} +//*----------------------------------------------------------------------------*/ +/**@brief 设备下线后处理 + @param + event:设备事件 + err:设备下线错误码 + @return + @note 根据特殊情景,这里可以处理一些例如io复用处理 +*/ +/*----------------------------------------------------------------------------*/ +static int dev_manager_del_after(struct sys_event *event, int err) +{ + int ret = 0; + switch ((u32)event->arg) { + case DRIVER_EVENT_FROM_SD0: + case DRIVER_EVENT_FROM_SD1: + case DRIVER_EVENT_FROM_SD2: + break; +#if TCFG_UDISK_ENABLE + case DEVICE_EVENT_FROM_OTG: + mult_usb_mount_offline(g_usb_id); + g_usb_id = (usb_dev) - 1; + break; +#endif + } + return ret; +} +//*----------------------------------------------------------------------------*/ +/**@brief 设备事件响应处理 + @param + event:设备事件 + @return + @note 设备上线和下线会动态添加到设备管理链表中, + 通过dev_manager系列接口可以进行设备操作,例如:例如查找、检查在线等 +*/ +/*----------------------------------------------------------------------------*/ +int dev_status_event_filter(struct sys_event *event) +{ + int ret = true; + int err = 0; + char *add = NULL; + char *del = NULL; + switch ((u32)event->arg) { + case DRIVER_EVENT_FROM_SD0: + case DRIVER_EVENT_FROM_SD1: + case DRIVER_EVENT_FROM_SD2: + printf("DEVICE_EVENT_FROM_SD%d\n", (u32)event->arg - DRIVER_EVENT_FROM_SD0); + if (event->u.dev.event == DEVICE_EVENT_IN) { + ///上线处理, 设备管理挂载 + printf("DEVICE_EVENT_IN\n"); + add = (char *)event->u.dev.value; + } else { + ///下线处理,设备管理卸载 + printf("DEVICE_EVENT_OUT\n"); + del = (char *)event->u.dev.value; + } + break; +#if TCFG_UDISK_ENABLE || TCFG_HOST_AUDIO_ENABLE + case DEVICE_EVENT_FROM_OTG: + printf("DEVICE_EVENT_FROM_OTG %d", event->u.dev.event); + g_usb_id = ((char *)event->u.dev.value)[2] - '0'; + if (((char *)event->u.dev.value)[0] == 'h') { + ///是host, 准备挂载设备, usb host mount/umout + if (event->u.dev.event == DEVICE_EVENT_IN) { + ///加入到设备管理列表 + printf("DEVICE_EVENT_IN\n"); + add = (char *)"udisk0"; + } else { + printf("DEVICE_EVENT_OUT\n"); + del = (char *)"udisk0"; + } + } + break; + case DEVICE_EVENT_FROM_USB_HOST: + printf("DEVICE_EVENT_FROM_USB_HOST %s", (const char *)event->u.dev.value); + break; +#endif + default: + ret = false; + break; + } + + ////dev manager add/del操作 + if (add) { + err = dev_manager_add_prepare(event); + if (!err) { + err = dev_manager_add(add); + if (!err) { +#if (MUSIC_DEV_ONLINE_START_AFTER_MOUNT_EN) + music_task_dev_online_start(); +#endif +#if (TCFG_DEV_UPDATE_IF_NOFILE_ENABLE == 0) + if (app_check_curr_task(APP_PC_TASK) == false) { + ///检查设备升级 + dev_update_check(add); + } +#endif/*TCFG_DEV_UPDATE_IF_NOFILE_ENABLE*/ + } else { + ret = false; + } + } else { + ret = false; + } + dev_manager_add_after(event, err); + } + if (del) { + dev_manager_del_prepare(event); + dev_manager_del(del); + dev_manager_del_after(event, 0); + } + SMARTBOX_UPDATE(COMMON_FUNCTION, BIT(COMMON_FUNCTION_ATTR_TYPE_DEV_INFO)); + return ret; +} + diff --git a/apps/soundbox/common/init.c b/apps/soundbox/common/init.c new file mode 100644 index 0000000..872fa09 --- /dev/null +++ b/apps/soundbox/common/init.c @@ -0,0 +1,227 @@ + +#include "app_config.h" +#include "system/includes.h" +#include "asm/charge.h" +#include "app_power_manage.h" +#include "update.h" +#include "app_main.h" +#include "app_charge.h" +#include "chgbox_ctrl.h" +#include "update_loader_download.h" + + +extern void setup_arch(); +extern int audio_dec_init(); +extern int audio_enc_init(); + +static void do_initcall() +{ + __do_initcall(initcall); +} + +static void do_early_initcall() +{ + __do_initcall(early_initcall); +} + +static void do_late_initcall() +{ + __do_initcall(late_initcall); +} + +static void do_platform_initcall() +{ + __do_initcall(platform_initcall); +} + +static void do_module_initcall() +{ + __do_initcall(module_initcall); +} + +void __attribute__((weak)) board_init() +{ + +} +void __attribute__((weak)) board_early_init() +{ + +} + +int eSystemConfirmStopStatus(void) +{ + /* 系统进入在未来时间里,无任务超时唤醒,可根据用户选择系统停止,或者系统定时唤醒(100ms) */ + //1:Endless Sleep + //0:100 ms wakeup + if (get_charge_full_flag()) { + log_i("Endless Sleep"); + power_set_soft_poweroff(); + return 1; + } else { + log_i("100 ms wakeup"); + return 0; + } + +} + +static void check_power_on_key(void) +{ + u32 delay_10ms_cnt = 0; + u32 delay_10msp_cnt = 0; + + while (1) { + clr_wdt(); + os_time_dly(2); + + extern u8 get_power_on_status(void); + if (get_power_on_status()) { + putchar('+'); + delay_10msp_cnt = 0; + delay_10ms_cnt++; + if (delay_10ms_cnt > 70) { + return; + } + } else { + putchar('-'); + delay_10ms_cnt = 0; + + delay_10msp_cnt++; + if (delay_10msp_cnt > 20) { + puts("enter softpoweroff\n"); + power_set_soft_poweroff(); + } + } + } +} + +static void app_init() +{ + int update; + + do_early_initcall(); + do_platform_initcall(); + + board_init(); + + do_initcall(); + + do_module_initcall(); + do_late_initcall(); + + + audio_enc_init(); + audio_dec_init(); + + if (!UPDATE_SUPPORT_DEV_IS_NULL()) { + update = update_result_deal(); + } + + app_var.play_poweron_tone = 1; + + if (!get_charge_online_flag()) { + check_power_on_voltage(); + +#if TCFG_POWER_ON_NEED_KEY + /*充电拔出,CPU软件复位, 不检测按键,直接开机*/ +#if TCFG_CHARGE_OFF_POWERON_NE + if ((!update && cpu_reset_by_soft()) || is_ldo5v_wakeup()) { +#else + if (!update && cpu_reset_by_soft()) { +#endif + app_var.play_poweron_tone = 0; + } else { + check_power_on_key(); + } +#endif + } + +#if (TCFG_MC_BIAS_AUTO_ADJUST == MC_BIAS_ADJUST_POWER_ON) + extern u8 power_reset_src; + u8 por_flag = 0; + u8 cur_por_flag = 0; + /* + *1.update + *2.power_on_reset(BIT0:上电复位) + *3.pin reset(BIT4:长按复位) + */ + if (update || (power_reset_src & BIT(0)) || (power_reset_src & BIT(4))) { + //log_info("reset_flag:0x%x",power_reset_src); + cur_por_flag = 0xA5; + } + int ret = syscfg_read(CFG_POR_FLAG, &por_flag, 1); + if ((cur_por_flag == 0xA5) && (por_flag != cur_por_flag)) { + //log_info("update POR flag"); + ret = syscfg_write(CFG_POR_FLAG, &cur_por_flag, 1); + } +#endif + +#if (TCFG_CHARGE_ENABLE && TCFG_CHARGE_POWERON_ENABLE) + if (is_ldo5v_wakeup()) { //LDO5V唤醒 + extern u8 get_charge_online_flag(void); + if (get_charge_online_flag()) { //关机时,充电插入 + + } else { //关机时,充电拔出 + power_set_soft_poweroff(); + } + } +#endif + +#if(TCFG_CHARGE_BOX_ENABLE) + /* clock_add_set(CHARGE_BOX_CLK); */ + chgbox_init_app(); +#endif +} + +static void app_task_handler(void *p) +{ + app_init(); + app_main(); +} + +__attribute__((used)) int *__errno() +{ + static int err; + return &err; +} + +int main() +{ + + +#if(CONFIG_CPU_BR25) + +#if (TCFG_DEC2TWS_ENABLE ||RECORDER_MIX_EN || TCFG_DRC_ENABLE || TCFG_USER_BLE_ENABLE || TCFG_DEC_APE_ENABLE || TCFG_DEC_FLAC_ENABLE || TCFG_DEC_DTS_ENABLE || TCFG_USER_EMITTER_ENABLE) + clock_set_sfc_max_freq(100 * 1000000, 100 * 1000000); +#else + +#if ((TCFG_AEC_ENABLE) && (TCFG_USER_TWS_ENABLE)) + clock_set_sfc_max_freq(80 * 1000000, 80 * 1000000); +#else + clock_set_sfc_max_freq(64 * 1000000, 64 * 1000000); +#endif + +#endif + +#endif + + wdt_close(); + + os_init(); + + setup_arch(); + + board_early_init(); + + task_create(app_task_handler, NULL, "app_core"); + + os_start(); + + local_irq_enable(); + + while (1) { + asm("idle"); + } + + return 0; +} + diff --git a/apps/soundbox/common/task_table.c b/apps/soundbox/common/task_table.c new file mode 100644 index 0000000..d7c069a --- /dev/null +++ b/apps/soundbox/common/task_table.c @@ -0,0 +1,200 @@ +#include "system/includes.h" +#include "app_config.h" + + +/*任务列表, 注意:stack_size设置为32*n*/ +const struct task_info task_info_table[] = { + {"app_core", 1, 896, 768 }, + {"sys_event", 6, 256, 0 }, + {"btctrler", 4, 512, 512 }, + {"btencry", 1, 512, 128 }, +#if TCFG_USER_TWS_ENABLE + {"tws", 5, 512, 128 }, +#endif +#if (TCFG_USER_TWS_ENABLE || TCFG_USER_BLE_ENABLE || TCFG_USER_EMITTER_ENABLE) + {"btstack", 3, 768, 512 }, +#else + {"btstack", 3, 512, 256 }, +#endif +#if TCFG_DEC2TWS_TASK_ENABLE + {"local_dec", 3, 768, 128 }, +#endif +#if ((TCFG_USER_TWS_ENABLE && TCFG_MIC_EFFECT_ENABLE)||(SOUNDCARD_ENABLE)) + {"audio_dec", 3, 768 + 128 + 128, 128 }, +#else + {"audio_dec", 3, 768 + 32, 128 }, +#endif + {"audio_enc", 3, 512, 128 }, +#if TCFG_AUDIO_DEC_OUT_TASK + {"audio_out", 2, 384, 0}, +#endif + {"aec", 2, 768, 0 }, + {"aec_dbg", 3, 128, 128 }, + {"update", 1, 512, 0 }, + {"dw_update", 2, 256, 128 }, +#if(USER_UART_UPDATE_ENABLE) + {"uart_update", 1, 256, 128 }, +#endif + {"systimer", 6, 128, 0 }, + {"dev_mg", 3, 512, 512 }, +#ifndef CONFIG_SOUNDBOX_FLASH_256K + {"usb_msd", 1, 512, 128 }, + {"usb_audio", 5, 256, 256 }, + {"plnk_dbg", 5, 256, 256 }, + {"adc_linein", 2, 768, 128 }, + /* {"src_write", 1, 768, 256 }, */ + {"fm_task", 3, 512, 128 }, +#endif + {"enc_write", 1, 768, 0 }, +#if (RCSP_BTMATE_EN || RCSP_ADV_EN) + {"rcsp_task", 4, 768, 128 }, +#endif +#if (TCFG_SPI_LCD_ENABLE||TCFG_SIMPLE_LCD_ENABLE) + {"ui", 2, 768, 256 }, +#else + {"ui", 3, 384 - 64, 128 }, +#endif + +#if(TCFG_CHARGE_BOX_ENABLE) + {"chgbox_n", 6, 512, 128 }, +#endif +#if (SMART_BOX_EN) + {"smartbox", 4, 768, 128 }, +#endif//SMART_BOX_EN +#if (AI_APP_PROTOCOL) + {"app_proto", 2, 512, 64 }, + {"dw_update", 2, 256, 128 }, +#endif +#if (GMA_EN) + {"tm_gma", 3, 768, 256 }, +#endif +#if RCSP_FILE_OPT + {"file_bs", 1, 768, 64 }, +#endif +#if TCFG_KEY_TONE_EN + {"key_tone", 5, 256, 32}, +#endif +#if TCFG_MIXER_CYCLIC_TASK_EN + {"mix_out", 5, 256, 0}, +#endif + + {"mic_stream", 5, 768, 128 }, +#if(TCFG_HOST_AUDIO_ENABLE) + {"uac_play", 6, 768, 0 }, + {"uac_record", 6, 768, 32 }, +#endif +#if (TUYA_DEMO_EN) + {"user_deal", 7, 512, 512 },//定义线程 tuya任务调度 +#endif + {0, 0}, +}; + +enum { + KEY_USER_DEAL_POST = 0, + KEY_USER_DEAL_POST_MSG, + KEY_USER_DEAL_POST_EVENT, + KEY_USER_DEAL_POST_2, +}; + +#include "system/includes.h" +#include "system/event.h" + +///自定义事件推送的线程 + +#define Q_USER_DEAL 0xAABBCC ///自定义队列类型 +#define Q_USER_DATA_SIZE 10///理论Queue受任务声明struct task_info.qsize限制,但不宜过大,建议<=6 + +void user_deal_send_ver(void) +{ + //os_taskq_post("user_deal", 1,KEY_USER_DEAL_POST); + os_taskq_post_msg("user_deal", 1, KEY_USER_DEAL_POST_MSG); + //os_taskq_post_event("user_deal",1, KEY_USER_DEAL_POST_EVENT); +} + +void user_deal_rand_set(u32 rand) +{ + os_taskq_post("user_deal", 2, KEY_USER_DEAL_POST_2, rand); +} + +void user_deal_send_array(int *msg, int argc) +{ + if (argc > Q_USER_DATA_SIZE) { + return; + } + os_taskq_post_type("user_deal", Q_USER_DEAL, argc, msg); +} +void user_deal_send_msg(void) +{ + os_taskq_post_event("user_deal", 1, KEY_USER_DEAL_POST_EVENT); +} + +void user_deal_send_test(void)///模拟测试函数,可按键触发调用,自行看打印 +{ + user_deal_send_ver(); + user_deal_rand_set(0x11223344); + static u32 data[Q_USER_DATA_SIZE] = {0x11223344, 0x55667788, 0x11223344, 0x55667788, 0x11223344, + 0xff223344, 0x556677ee, 0x11223344, 0x556677dd, 0x112233ff, + }; + user_deal_send_array(data, sizeof(data) / sizeof(int)); +} + +static void user_deal_task_handle(void *p) +{ + int msg[Q_USER_DATA_SIZE + 1] = {0, 0, 0, 0, 0, 0, 0, 0, 00, 0}; + int res = 0; + while (1) { + res = os_task_pend("taskq", msg, ARRAY_SIZE(msg)); + if (res != OS_TASKQ) { + continue; + } + r_printf("user_deal_task_handle:0x%x", msg[0]); + put_buf(msg, (Q_USER_DATA_SIZE + 1) * 4); + if (msg[0] == Q_MSG) { + printf("use os_taskq_post_msg"); + switch (msg[1]) { + case KEY_USER_DEAL_POST_MSG: + printf("KEY_USER_DEAL_POST_MSG"); + break; + default: + break; + } + } else if (msg[0] == Q_EVENT) { + printf("use os_taskq_post_event"); + switch (msg[1]) { + case KEY_USER_DEAL_POST_EVENT: + printf("KEY_USER_DEAL_POST_EVENT"); + break; + default: + break; + } + } else if (msg[0] == Q_CALLBACK) { + } else if (msg[0] == Q_USER) { + printf("use os_taskq_post"); + switch (msg[1]) { + case KEY_USER_DEAL_POST: + printf("KEY_USER_DEAL_POST"); + break; + case KEY_USER_DEAL_POST_2: + printf("KEY_USER_DEAL_POST_2:0x%x", msg[2]); + break; + default: + break; + } + } else if (msg[0] == Q_USER_DEAL) { + printf("use os_taskq_post_type"); + printf("0x%x 0x%x 0x%x 0x%x 0x%x", msg[1], msg[2], msg[3], msg[4], msg[5]); + printf("0x%x 0x%x 0x%x 0x%x 0x%x", msg[6], msg[7], msg[8], msg[9], msg[10]); + } + puts(""); + } +} + +void user_deal_init(void) +{ + task_create(user_deal_task_handle, NULL, "user_deal"); +} + +void user_deal_exit(void) +{ + task_kill("user_deal"); +} diff --git a/apps/soundbox/common/tone_table.c b/apps/soundbox/common/tone_table.c new file mode 100644 index 0000000..285c863 --- /dev/null +++ b/apps/soundbox/common/tone_table.c @@ -0,0 +1,38 @@ +#include "app_config.h" +#include "audio_config.h" +#include "tone_player.h" + +const char *tone_table[] = { + [IDEX_TONE_NUM_0] = TONE_RES_ROOT_PATH"tone/0.*", + [IDEX_TONE_NUM_1] = TONE_RES_ROOT_PATH"tone/1.*", + [IDEX_TONE_NUM_2] = TONE_RES_ROOT_PATH"tone/2.*", + [IDEX_TONE_NUM_3] = TONE_RES_ROOT_PATH"tone/3.*", + [IDEX_TONE_NUM_4] = TONE_RES_ROOT_PATH"tone/4.*", + [IDEX_TONE_NUM_5] = TONE_RES_ROOT_PATH"tone/5.*", + [IDEX_TONE_NUM_6] = TONE_RES_ROOT_PATH"tone/6.*", + [IDEX_TONE_NUM_7] = TONE_RES_ROOT_PATH"tone/7.*", + [IDEX_TONE_NUM_8] = TONE_RES_ROOT_PATH"tone/8.*", + [IDEX_TONE_NUM_9] = TONE_RES_ROOT_PATH"tone/9.*", + [IDEX_TONE_BT_MODE] = TONE_RES_ROOT_PATH"tone/bt.*", + [IDEX_TONE_BT_CONN] = TONE_RES_ROOT_PATH"tone/bt_conn.*", + [IDEX_TONE_BT_DISCONN] = TONE_RES_ROOT_PATH"tone/bt_dconn.*", + [IDEX_TONE_TWS_CONN] = TONE_RES_ROOT_PATH"tone/tws_conn.*", + [IDEX_TONE_TWS_DISCONN] = TONE_RES_ROOT_PATH"tone/tws_dconn.*", + [IDEX_TONE_LOW_POWER] = TONE_RES_ROOT_PATH"tone/low_power.*", + [IDEX_TONE_POWER_OFF] = TONE_RES_ROOT_PATH"tone/power_off.*", + [IDEX_TONE_POWER_ON] = TONE_RES_ROOT_PATH"tone/power_on.*", + [IDEX_TONE_RING] = TONE_RES_ROOT_PATH"tone/ring.*", + [IDEX_TONE_MAX_VOL] = TONE_NORMAL, + [IDEX_TONE_NORMAL] = TONE_NORMAL, + [IDEX_TONE_MUSIC] = TONE_RES_ROOT_PATH"tone/music.*", + [IDEX_TONE_LINEIN] = TONE_RES_ROOT_PATH"tone/linein.*", + [IDEX_TONE_FM] = TONE_RES_ROOT_PATH"tone/fm.*", + [IDEX_TONE_PC] = TONE_RES_ROOT_PATH"tone/pc.*", + [IDEX_TONE_RTC] = TONE_RES_ROOT_PATH"tone/rtc.*", + [IDEX_TONE_RECORD] = TONE_RES_ROOT_PATH"tone/record.*", + [IDEX_TONE_UDISK] = TONE_RES_ROOT_PATH"tone/udisk.*", + [IDEX_TONE_SD] = TONE_RES_ROOT_PATH"tone/sd.*", + [IDEX_TONE_SPEECH_START] = TONE_NORMAL,//TONE_RES_ROOT_PATH"tone/speech.*", + +}; + diff --git a/apps/soundbox/common/user_cfg_new.c b/apps/soundbox/common/user_cfg_new.c new file mode 100644 index 0000000..dbb1fb4 --- /dev/null +++ b/apps/soundbox/common/user_cfg_new.c @@ -0,0 +1,672 @@ +#include "app_config.h" +#include "user_cfg.h" +#include "fs.h" +#include "string.h" +#include "system/includes.h" +#include "vm.h" +#include "btcontroller_config.h" +#include "app_main.h" +#include "media/includes.h" +#include "audio_config.h" +#include "asm/pwm_led.h" +#include "aec_user.h" +#include "app_power_manage.h" + + +#define LOG_TAG_CONST USER_CFG +#define LOG_TAG "[USER_CFG]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +#define LOG_DUMP_ENABLE +#define LOG_CLI_ENABLE +#include "debug.h" + +#define USE_CONFIG_STATUS_SETTING 1 //状态设置,包括灯状态和提示音 +#define USE_CONFIG_AUDIO_SETTING 0 //音频设置 +#define USE_CONFIG_MIC_TYPE_SETTING 0 //MIC类型设置 +#define USE_CONFIG_AUTO_OFF_SETTING 1 //自动关机时间设置 +#define USE_CONFIG_COMBINE_VOL_SETTING 1 //联合音量读配置 + +void lp_winsize_init(struct lp_ws_t *lp); +void bt_max_pwr_set(u8 pwr, u8 pg_pwr, u8 iq_pwr, u8 ble_pwr); +void app_set_sys_vol(s16 vol_l, s16 vol_r); + +BT_CONFIG bt_cfg = { + .edr_name = {'j', 'l', '_', 's', 'o', 'u', 'n', 'd', 'b', 'o', 'x', '_', '1'}, + .mac_addr = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .tws_local_addr = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .rf_power = 10, + .dac_analog_gain = 25, + .mic_analog_gain = 7, + .tws_device_indicate = 0x6688, + .ble_name = {'j', 'l', '_', 's', 'o', 'u', 'n', 'd', 'b', 'o', 'x', '_', 'b', 'l', 'e'}, + .ble_mac_addr = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, + .ble_rf_power = 10, +}; + +AUDIO_CONFIG audio_cfg = { + .max_sys_vol = SYS_MAX_VOL, + .default_vol = SYS_DEFAULT_VOL, + .tone_vol = SYS_DEFAULT_TONE_VOL, +}; + +//======================================================================================// +// BTIF配置项表 // +// 参数1: 配置项名字 // +// 参数2: 配置项需要多少个byte存储 // +// 说明: 配置项ID注册到该表后该配置项将读写于BTIF区域, 其它没有注册到该表 // +// 的配置项则默认读写于VM区域. // +//======================================================================================// +const struct btif_item btif_table[] = { +// item id len // + {CFG_BT_MAC_ADDR, 6 }, + {CFG_BT_FRE_OFFSET, 6 }, //测试盒矫正频偏值 + //{CFG_DAC_DTB, 2 }, + //{CFG_MC_BIAS, 1 }, + {0, 0 }, //reserved cfg +}; + +//============================= VM 区域空间最大值 ======================================// +const int vm_max_size_config = VM_MAX_SIZE_CONFIG; //该宏在app_cfg中配置 +//======================================================================================// + +struct lp_ws_t lp_winsize = { + .lrc_ws_inc = 480, //260 + .lrc_ws_init = 400, + .bt_osc_ws_inc = 480, + .bt_osc_ws_init = 140, + .osc_change_mode = 1, +}; + +#if CONFIG_TWS_PAIR_BY_BOTH_SIDES +static u8 tws_pair_by_both_sides_en = 0; + +void bt_set_pair_code_en(u8 en) +{ + tws_pair_by_both_sides_en = en; +} +#endif + +u16 bt_get_tws_device_indicate(u8 *tws_device_indicate) +{ +#if CONFIG_TWS_PAIR_BY_BOTH_SIDES + if (tws_pair_by_both_sides_en) { + return bt_cfg.tws_device_indicate; + } else { + return bt_cfg.tws_device_indicate + 1; + } +#else + return bt_cfg.tws_device_indicate; +#endif +} + +const u8 *bt_get_mac_addr() +{ + return bt_cfg.mac_addr; +} + +void bt_update_mac_addr(u8 *addr) +{ + memcpy(bt_cfg.mac_addr, addr, 6); +} + +static u8 bt_mac_addr_for_testbox[6] = {0}; +void bt_get_vm_mac_addr(u8 *addr) +{ +#if 0 + //中断不能调用syscfg_read; + int ret = 0; + + ret = syscfg_read(CFG_BT_MAC_ADDR, addr, 6); + if ((ret != 6)) { + syscfg_write(CFG_BT_MAC_ADDR, addr, 6); + } +#else + + memcpy(addr, bt_mac_addr_for_testbox, 6); +#endif +} +void bt_update_testbox_addr(u8 *addr) +{ + log_info("update textbox_addr"); + put_buf(addr, 6); + memcpy(bt_mac_addr_for_testbox, addr, 6); +} +void bt_get_tws_local_addr(u8 *addr) +{ + memcpy(addr, bt_cfg.tws_local_addr, 6); +} + +const char *sdk_version_info_get(void) +{ + extern u32 __VERSION_BEGIN; + char *version_str = ((char *)&__VERSION_BEGIN) + 4; + + return version_str; +} + +const char *bt_get_local_name() +{ + return (const char *)(bt_cfg.edr_name); +} + +const char *bt_get_pin_code() +{ + return "0000"; +} + + +void bt_reset_and_get_mac_addr(u8 *addr) +{ + get_random_number(addr, 6); + syscfg_write(CFG_BT_MAC_ADDR, addr, 6); + memcpy(bt_cfg.mac_addr, addr, 6); +} + + + + +extern STATUS_CONFIG status_config; +extern struct charge_platform_data charge_data; +/* extern struct dac_platform_data dac_data; */ +extern struct adkey_platform_data adkey_data; +extern struct led_platform_data pwm_led_data; +extern struct adc_platform_data adc_data; + +#include "fm_emitter/fm_emitter_manage.h" + +u8 get_max_sys_vol(void) +{ +#if TCFG_APP_FM_EMITTER_EN + return FM_EMITTER_MAX_VOL; +#else + return (audio_cfg.max_sys_vol); +#endif +} + +#if 1 +u8 get_tone_vol(void) +{ + if (!audio_cfg.tone_vol) { + return (get_max_sys_vol()); + } + if (audio_cfg.tone_vol > get_max_sys_vol()) { + return (get_max_sys_vol()); + } + + return (audio_cfg.tone_vol); +} +#endif + +__BANK_INIT_ENTRY +void cfg_file_parse(u8 idx) +{ + u8 tmp[128] = {0}; + int ret = 0; + + memset(tmp, 0x00, sizeof(tmp)); + + /*************************************************************************/ + /* CFG READ IN cfg_tools.bin */ + /*************************************************************************/ + + //-----------------------------CFG_COMBINE_VOL----------------------------------// +#if (SYS_VOL_TYPE == VOL_TYPE_AD) + audio_combined_vol_init(USE_CONFIG_COMBINE_VOL_SETTING); +#endif/*SYS_VOL_TYPE*/ + + //-----------------------------CFG_BT_NAME--------------------------------------// + ret = syscfg_read(CFG_BT_NAME, tmp, 32); + if (ret < 0) { + log_info("read bt name err\n"); + } else if (ret >= LOCAL_NAME_LEN) { + memset(bt_cfg.edr_name, 0x00, LOCAL_NAME_LEN); + memcpy(bt_cfg.edr_name, tmp, LOCAL_NAME_LEN); + bt_cfg.edr_name[LOCAL_NAME_LEN - 1] = 0; + log_info("read new cfg bt name config:%s\n", tmp); + } else { + memset(bt_cfg.edr_name, 0x00, LOCAL_NAME_LEN); + memcpy(bt_cfg.edr_name, tmp, ret); + log_info("read new cfg bt name config:%s\n", tmp); + } + /* g_printf("bt name config:%s\n", bt_cfg.edr_name); */ + log_info("bt name config:%s\n", bt_cfg.edr_name); + +//-----------------------------CFG_BLE_NAME--------------------------------------// + ret = syscfg_read(CFG_BLE_NAME, tmp, 32); + if (ret < 0) { + log_info("read ble name err\n"); + } else if (ret >= LOCAL_NAME_LEN) { + memset(bt_cfg.ble_name, 0x00, LOCAL_NAME_LEN); + memcpy(bt_cfg.ble_name, tmp, LOCAL_NAME_LEN); + bt_cfg.ble_name[LOCAL_NAME_LEN - 1] = 0; + log_info("read new cfg ble name config:%s\n", tmp); + } else { + memset(bt_cfg.ble_name, 0x00, LOCAL_NAME_LEN); + memcpy(bt_cfg.ble_name, tmp, ret); + log_info("read new cfg ble name config:%s\n", tmp); + } + /* g_printf("bt name config:%s\n", bt_cfg.edr_name); */ + log_info("ble name config:%s\n", bt_cfg.ble_name); + + //-----------------------------CFG_TWS_PAIR_CODE_ID----------------------------// + ret = syscfg_read(CFG_TWS_PAIR_CODE_ID, &bt_cfg.tws_device_indicate, 2); + log_info("new cfg tws pair code config:\n"); + log_info_hexdump(&bt_cfg.tws_device_indicate, 2); + if (ret < 0) { + log_debug("read pair code err\n"); + bt_cfg.tws_device_indicate = 0xFFFF; + } + /* g_printf("tws pair code config:\n"); */ + log_info("tws pair code config:\n"); + log_info_hexdump(&bt_cfg.tws_device_indicate, 2); + + //-----------------------------CFG_BT_RF_POWER_ID----------------------------// + ret = syscfg_read(CFG_BT_RF_POWER_ID, &app_var.rf_power, 1); + log_info("read new cfg rf config:%d\n", app_var.rf_power); + if (ret < 0) { + log_debug("read rf err\n"); + app_var.rf_power = 10; + } + /* g_printf("rf config:%d\n", app_var.rf_power); */ + log_info("rf config:%d\n", app_var.rf_power); + + //-----------------------------CFG_BLE_RF_POWER_ID----------------------------// + ret = syscfg_read(CFG_BLE_RF_POWER_ID, &app_var.ble_rf_power, 1); + log_info("read new cfg ble rf config:%d\n", app_var.rf_power); + if (ret < 0) { + log_debug("read ble rf err\n"); + app_var.ble_rf_power = 10; + } + /* g_printf("ble rf config:%d\n", app_var.ble_rf_power); */ + log_info("ble rf config:%d\n", app_var.ble_rf_power); + +#if TCFG_APP_BT_EN + bt_max_pwr_set(app_var.rf_power, 5, 8, app_var.ble_rf_power); +#endif + + //-----------------------------CFG_AEC_ID------------------------------------// + /* g_printf("aec config:\n"); */ + log_info("aec config:\n"); + AEC_CONFIG aec; + ret = syscfg_read(CFG_AEC_ID, &aec, sizeof(AEC_CONFIG)); + if (ret > 0) { + log_info_hexdump(&aec, sizeof(AEC_CONFIG)); + app_var.aec_mic_gain = aec.mic_again; + app_var.aec_dac_gain = aec.dac_again; + app_var.aec_mode = aec.aec_mode; + app_var.ul_eq_en = aec.ul_eq_en; + app_var.ndt_fade_in = aec.ndt_fade_in; + app_var.ndt_fade_out = aec.ndt_fade_out; + app_var.dt_fade_in = aec.dt_fade_in; + app_var.dt_fade_out = aec.dt_fade_out; + app_var.ndt_max_gain = aec.ndt_max_gain; + app_var.ndt_min_gain = aec.ndt_min_gain; + app_var.ndt_speech_thr = aec.ndt_speech_thr; + app_var.dt_max_gain = aec.dt_max_gain; + app_var.dt_min_gain = aec.dt_min_gain; + app_var.dt_speech_thr = aec.dt_speech_thr; + app_var.echo_present_thr = aec.echo_present_thr; + app_var.aec_dt_aggress = aec.aec_dt_aggress; + app_var.aec_refengthr = aec.aec_refengthr; + app_var.es_aggress_factor = aec.es_aggress_factor; + app_var.es_min_suppress = aec.es_min_suppress; + app_var.ans_aggress = aec.ans_aggress; + app_var.ans_suppress = aec.ans_suppress; + +#if AEC_READ_CONFIG +#ifdef CONFIG_MEDIA_ORIGIN_ENABLE + aec_cfg_fill(&aec); +#endif/*CONFIG_MEDIA_ORIGIN_ENABLE*/ +#endif/*AEC_READ_CONFIG*/ + } else { + log_debug("read aec err\n"); + app_var.aec_mic_gain = 3; + app_var.aec_dac_gain = 22; + app_var.aec_mode = 2; + app_var.ul_eq_en = 1; + app_var.ndt_fade_in = 1.3f; + app_var.ndt_fade_out = 1.3f; + app_var.dt_fade_in = 1.3f; + app_var.dt_fade_out = 1.3f; + app_var.ndt_max_gain = 6; + app_var.ndt_min_gain = 3; + app_var.ndt_speech_thr = -50.f; + app_var.dt_max_gain = 12; + app_var.dt_min_gain = 0; + app_var.dt_speech_thr = -40.f; + app_var.echo_present_thr = -70.f; + app_var.aec_dt_aggress = 1; + app_var.aec_refengthr = -70.f; + app_var.es_aggress_factor = -3.f; + app_var.es_min_suppress = 4; + app_var.ans_aggress = 1.25f; + app_var.ans_suppress = 0.09f; + } + log_info("aec_cfg mic_gain:%d dac_gain:%d", app_var.aec_mic_gain, app_var.aec_dac_gain); + + //-----------------------------CFG_MIC_TYPE_ID------------------------------------// +#if USE_CONFIG_MIC_TYPE_SETTING + /* g_printf("mic_type_config:\n"); */ + log_info("mic_type_config:\n"); + MIC_TYPE_CONFIG mic_type; + ret = syscfg_read(CFG_MIC_TYPE_ID, &mic_type, sizeof(MIC_TYPE_CONFIG)); + if (ret > 0) { + log_info_hexdump(&mic_type, sizeof(MIC_TYPE_CONFIG)); + adc_data.mic_capless = mic_type.type; +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + if (adc_data.mic_capless == 1) { //四声道与双声道差分 使用不省电容接法mic_capless = 0 + log_error("adc_data.mic_capless err, CHECK !!!\n"); + ASSERT(0); + } +#endif + adc_data.mic_bias_res = mic_type.pull_up; + adc_data.mic_ldo_vsel = mic_type.ldo_lev; + } else { + log_debug("read mic type err\n"); + mic_type.type = 0; + adc_data.mic_capless = mic_type.type; + } +#endif + +#if TCFG_MC_BIAS_AUTO_ADJUST + ret = syscfg_read(CFG_MC_BIAS, &adc_data.mic_bias_res, 1); + log_info("mic_bias_res:%d\n", adc_data.mic_bias_res); + if (ret != 1) { + log_info("mic_bias_adjust NULL\n"); + } + u8 mic_ldo_idx; + ret = syscfg_read(CFG_MIC_LDO_VSEL, &mic_ldo_idx, 1); + if (ret == 1) { + adc_data.mic_ldo_vsel = mic_ldo_idx & 0x3; + log_info("mic_ldo_vsel:%d,%d\n", adc_data.mic_ldo_vsel, mic_ldo_idx); + } else { + log_info("mic_ldo_vsel_adjust NULL\n"); + } +#endif + +#if USE_CONFIG_STATUS_SETTING + /* g_printf("status_config:\n"); */ + log_info("status_config:\n"); + STATUS_CONFIG *status = (STATUS_CONFIG *)tmp; + ret = syscfg_read(CFG_UI_TONE_STATUS_ID, status, sizeof(STATUS_CONFIG)); + if (ret > 0) { + memcpy((u8 *)&status_config, (u8 *)status, sizeof(STATUS_CONFIG)); + log_info_hexdump(&status_config, sizeof(STATUS_CONFIG)); + } +#endif + +#if USE_CONFIG_AUDIO_SETTING + /* g_printf("app audio_config:\n"); */ + log_info("app audio_config:\n"); + ret = syscfg_read(CFG_AUDIO_ID, (u8 *)&audio_cfg, sizeof(AUDIO_CONFIG)); + if (ret > 0) { + log_info_hexdump((u8 *)&audio_cfg, sizeof(AUDIO_CONFIG)); + log_info("max vol:%d default vol:%d tone vol:%d\n", audio_cfg.max_sys_vol, audio_cfg.default_vol, audio_cfg.tone_vol); +#else + { +#endif + /* dac_data.max_ana_vol = audio_cfg.max_sys_vol; */ + /* if (dac_data.max_ana_vol > 30) { */ + /* dac_data.max_ana_vol = 30; */ + /* } */ + + //// pc usb mic gain + s8 usb_mic_gain = -1; + ret = syscfg_read(VM_USB_MIC_GAIN, &usb_mic_gain, 1); + if (ret < 0) { + usb_mic_gain = 7; + } + app_var.usb_mic_gain = usb_mic_gain; + log_info("usb_mic_gain: %d\n", app_var.usb_mic_gain); + + s8 default_volume = -1; + s8 music_volume = -1; +#if SYS_DEFAULT_VOL + default_volume = audio_cfg.default_vol; +#else + ret = syscfg_read(CFG_SYS_VOL, &default_volume, 1); + if (ret < 0) { + default_volume = -1; + } + ret = syscfg_read(CFG_MUSIC_VOL, &music_volume, 1); + if (ret < 0) { + music_volume = -1; + } +#endif + if (default_volume > audio_cfg.max_sys_vol) { + default_volume = audio_cfg.max_sys_vol; + } + if (default_volume <= 0) { + default_volume = audio_cfg.max_sys_vol / 2; + } + +#if (SMART_BOX_EN) + app_var.music_volume = music_volume < 0 ? default_volume : music_volume; +#else + app_var.music_volume = music_volume <= 0 ? default_volume : music_volume; +#endif + app_var.wtone_volume = audio_cfg.tone_vol; + app_var.call_volume = app_var.aec_dac_gain; + app_var.opid_play_vol_sync = app_var.music_volume * 127 / audio_cfg.max_sys_vol; + + log_info("max vol:%d default vol:%d tone vol:%d vol_sync:%d\n", audio_cfg.max_sys_vol, default_volume, audio_cfg.tone_vol, app_var.opid_play_vol_sync); + } + +#if (USE_CONFIG_CHARGE_SETTING) && (TCFG_CHARGE_ENABLE) + /* g_printf("app charge config:\n"); */ + log_info("app charge config:\n"); + CHARGE_CONFIG *charge = (CHARGE_CONFIG *)tmp; + ret = syscfg_read(CFG_CHARGE_ID, charge, sizeof(CHARGE_CONFIG)); + if (ret > 0) { + log_info_hexdump(charge, sizeof(CHARGE_CONFIG)); + log_info("sw:%d poweron_en:%d full_v:%d full_mA:%d charge_mA:%d\n", + charge->sw, charge->poweron_en, charge->full_v, charge->full_c, charge->charge_c); + memcpy((u8 *)&charge_data, (u8 *)charge, sizeof(CHARGE_CONFIG)); + } +#endif + +#if (USE_CONFIG_KEY_SETTING) && (TCFG_ADKEY_ENABLE || TCFG_IOKEY_ENABLE) + /* g_printf("app key config:\n"); */ + log_info("app key config:\n"); + KEY_OP *key_msg = (KEY_OP *)tmp; + ret = syscfg_read(CFG_KEY_MSG_ID, key_msg, sizeof(KEY_OP) * KEY_NUM_MAX); + if (ret > 0) { + log_info_hexdump(key_msg, sizeof(KEY_OP) * KEY_NUM); + memcpy(key_table, key_msg, sizeof(KEY_OP) * KEY_NUM); + } + + log_info("key_msg:"); + log_info_hexdump((u8 *)key_table, KEY_EVENT_MAX * KEY_NUM_MAX); +#endif + + +#if USE_CONFIG_LOWPOWER_V_SETTING + /* g_printf("auto low power config:\n"); */ + log_info("auto low power config:\n"); + AUTO_LOWPOWER_V_CONFIG auto_lowpower; + ret = syscfg_read(CFG_LOWPOWER_V_ID, &auto_lowpower, sizeof(AUTO_LOWPOWER_V_CONFIG)); + if (ret > 0) { + app_var.warning_tone_v = auto_lowpower.warning_tone_v; + app_var.poweroff_tone_v = auto_lowpower.poweroff_tone_v; + } + log_info("warning_tone_v:%d poweroff_tone_v:%d\n", app_var.warning_tone_v, app_var.poweroff_tone_v); +#else + app_var.warning_tone_v = LOW_POWER_WARN_VAL; + app_var.poweroff_tone_v = LOW_POWER_OFF_VAL; + log_info("warning_tone_v:%d poweroff_tone_v:%d\n", app_var.warning_tone_v, app_var.poweroff_tone_v); +#endif + +#if USE_CONFIG_AUTO_OFF_SETTING + /* g_printf("auto off time config:\n"); */ + log_info("auto off time config:\n"); + AUTO_OFF_TIME_CONFIG auto_off_time; + ret = syscfg_read(CFG_AUTO_OFF_TIME_ID, &auto_off_time, sizeof(AUTO_OFF_TIME_CONFIG)); + if (ret > 0) { + app_var.auto_off_time = auto_off_time.auto_off_time * 60; + log_info("read new cfg auto time %d\n", auto_off_time.auto_off_time); + } else { + auto_off_time.auto_off_time = 3; + app_var.auto_off_time = auto_off_time.auto_off_time * 60; + log_info("read auto time cfg err\n"); + } + log_info("auto_off_time:%d\n", app_var.auto_off_time); +#else + app_var.auto_off_time = TCFG_AUTO_SHUT_DOWN_TIME; + log_info("auto_off_time:%d\n", app_var.auto_off_time); +#endif + +#if TCFG_APP_MUSIC_EN + ret = syscfg_read(CFG_MUSIC_MODE, &app_var.cycle_mode, 1); + if (ret < 0) { + log_info("read music play mode err\n"); + } + if (app_var.cycle_mode >= FCYCLE_MAX || app_var.cycle_mode == 0) { + app_var.cycle_mode = FCYCLE_ALL; + } +#endif + + /*************************************************************************/ + /* CFG READ IN VM */ + /*************************************************************************/ +#if TCFG_APP_BT_EN + u8 mac_buf[6]; + u8 ble_mac_buf[6]; + u8 mac_buf_tmp[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + u8 mac_buf_tmp2[6] = {0, 0, 0, 0, 0, 0}; +#if TCFG_USER_TWS_ENABLE + int len = syscfg_read(CFG_TWS_LOCAL_ADDR, bt_cfg.tws_local_addr, 6); + if (len != 6) { + get_random_number(bt_cfg.tws_local_addr, 6); + syscfg_write(CFG_TWS_LOCAL_ADDR, bt_cfg.tws_local_addr, 6); + log_info(">>>init mac tws addr!!!\n"); + } + log_info("tws_local_mac:"); + log_info_hexdump(bt_cfg.tws_local_addr, sizeof(bt_cfg.tws_local_addr)); + +#if CONFIG_TWS_USE_COMMMON_ADDR + ret = syscfg_read(CFG_TWS_COMMON_ADDR, mac_buf, 6); + if (ret != 6 || !memcmp(mac_buf, mac_buf_tmp, 6)) +#endif +#endif + +#if TCFG_SOUNDBOX_TOOL_ENABLE + do { + ret = syscfg_read_btmac_blemac_from_bin(CFG_BT_MAC_ADDR, mac_buf, 6); + if ((ret != 6) || !memcmp(mac_buf, mac_buf_tmp, 6) || !memcmp(mac_buf, mac_buf_tmp2, 6)) { + ret = syscfg_read(CFG_BT_MAC_ADDR, mac_buf, 6); + if ((ret != 6) || !memcmp(mac_buf, mac_buf_tmp, 6) || !memcmp(mac_buf, mac_buf_tmp2, 6)) { + get_random_number(mac_buf, 6); + syscfg_write(CFG_BT_MAC_ADDR, mac_buf, 6); + log_info(">>>init tws addr!!!\n"); + } + } + ret = 0; + ret = syscfg_read_btmac_blemac_from_bin(CFG_BLE_MAC_ADDR, ble_mac_buf, 6); + if ((ret != 6) || !memcmp(ble_mac_buf, mac_buf_tmp, 6) || !memcmp(ble_mac_buf, mac_buf_tmp2, 6)) { + ret = syscfg_read(CFG_BLE_MAC_ADDR, ble_mac_buf, 6); + if ((ret != 6) || !memcmp(ble_mac_buf, mac_buf_tmp, 6) || !memcmp(ble_mac_buf, mac_buf_tmp2, 6)) { + get_random_number(ble_mac_buf, 6); + syscfg_write(CFG_BLE_MAC_ADDR, ble_mac_buf, 6); + log_info(">>>init ble addr!!!\n"); + } + } + } while (0); +#else + do { + ret = syscfg_read(CFG_BT_MAC_ADDR, mac_buf, 6); + if ((ret != 6) || !memcmp(mac_buf, mac_buf_tmp, 6) || !memcmp(mac_buf, mac_buf_tmp2, 6)) { + get_random_number(mac_buf, 6); + syscfg_write(CFG_BT_MAC_ADDR, mac_buf, 6); + log_info(">>>init tws addr!!!\n"); + } + ret = 0; + ret = syscfg_read(CFG_BLE_MAC_ADDR, ble_mac_buf, 6); + if ((ret != 6) || !memcmp(ble_mac_buf, mac_buf_tmp, 6) || !memcmp(ble_mac_buf, mac_buf_tmp2, 6)) { + get_random_number(ble_mac_buf, 6); + syscfg_write(CFG_BLE_MAC_ADDR, ble_mac_buf, 6); + log_info(">>>init ble addr!!!\n"); + } + } while (0); +#endif + + syscfg_read(CFG_BT_MAC_ADDR, bt_mac_addr_for_testbox, 6); + +#if CONFIG_TWS_USE_COMMMON_ADDR + if (!memcmp(bt_mac_addr_for_testbox, mac_buf_tmp, 6)) { + get_random_number(bt_mac_addr_for_testbox, 6); + syscfg_write(CFG_BT_MAC_ADDR, bt_mac_addr_for_testbox, 6); + log_info(">>>init mac addr!!!\n"); + } +#endif + + log_info("mac:"); + log_info_hexdump(mac_buf, sizeof(mac_buf)); + memcpy(bt_cfg.mac_addr, mac_buf, 6); + log_info("ble mac:"); + log_info_hexdump(ble_mac_buf, sizeof(ble_mac_buf)); + memcpy(bt_cfg.ble_mac_addr, ble_mac_buf, 6); + + +#if (CONFIG_BT_MODE != BT_NORMAL) + const u8 dut_name[] = "AC693x_DUT"; + const u8 dut_addr[6] = {0x12, 0x34, 0x56, 0x56, 0x34, 0x12}; + memcpy(bt_cfg.edr_name, dut_name, sizeof(dut_name)); + memcpy(bt_cfg.mac_addr, dut_addr, 6); +#endif + + /*************************************************************************/ + /* CFG READ IN isd_config.ini */ + /*************************************************************************/ + LRC_CONFIG lrc_cfg; + ret = syscfg_read(CFG_LRC_ID, &lrc_cfg, sizeof(LRC_CONFIG)); + if (ret > 0) { + log_info("lrc cfg:"); + log_info_hexdump(&lrc_cfg, sizeof(LRC_CONFIG)); + lp_winsize.lrc_ws_inc = lrc_cfg.lrc_ws_inc; + lp_winsize.lrc_ws_init = lrc_cfg.lrc_ws_init; + lp_winsize.bt_osc_ws_inc = lrc_cfg.btosc_ws_inc; + lp_winsize.bt_osc_ws_init = lrc_cfg.btosc_ws_init; + lp_winsize.osc_change_mode = lrc_cfg.lrc_change_mode; + } else { + log_info("read new lrc cfg err\n"); + } + /* printf("%d %d %d \n",lp_winsize.lrc_ws_inc,lp_winsize.lrc_ws_init,lp_winsize.osc_change_mode); */ + lp_winsize_init(&lp_winsize); +#endif +} + +extern void hci_vendor_update_name(void); +int bt_modify_name(u8 *new_name) +{ + u8 new_len = strlen(new_name); + + if (new_len >= LOCAL_NAME_LEN) { + new_name[LOCAL_NAME_LEN - 1] = 0; + } + + if (strcmp(new_name, bt_cfg.edr_name)) { + syscfg_write(CFG_BT_NAME, new_name, LOCAL_NAME_LEN); + memcpy(bt_cfg.edr_name, new_name, LOCAL_NAME_LEN); + hci_vendor_update_name(); + log_info("mdy_name sucess\n"); + return 1; + } + return 0; +} + + +char *get_edr_name(void) +{ + return bt_cfg.edr_name; +} + +const u8 *bt_get_ble_mac_addr() +{ + return bt_cfg.ble_mac_addr; +} + + + + diff --git a/apps/soundbox/font/fontinit.c b/apps/soundbox/font/fontinit.c new file mode 100644 index 0000000..3799992 --- /dev/null +++ b/apps/soundbox/font/fontinit.c @@ -0,0 +1,87 @@ +#include "font/font_all.h" +#include "font/language_list.h" +#include "app_config.h" +#include "ui/res_config.h" + +#if TCFG_UI_ENABLE +#if (TCFG_SPI_LCD_ENABLE || TCFG_SIMPLE_LCD_ENABLE) + + +extern void platform_putchar(struct font_info *info, u8 *pixel, u16 width, u16 height, u16 x, u16 y);//字库输出显示函数 +extern void ui_simple_putchar(struct font_info *info, u8 *pixel, u16 width, u16 height, u16 x, u16 y);//字库输出显示函数 + +#if TCFG_SPI_LCD_ENABLE +#define font_putchar (platform_putchar) +#else +#define font_putchar (ui_simple_putchar) +#endif + +/* 语言字库配置 */ + +#define LANGUAGE BIT(Chinese_Simplified)|\ + BIT(English)|\ + BIT(Chinese_Traditional) + +const struct font_info font_info_table[] = { + +#if LANGUAGE&BIT(Chinese_Simplified) + //gb2312 + { + .language_id = Chinese_Simplified, + .flags = FONT_SHOW_PIXEL | FONT_SHOW_MULTI_LINE, + .pixel.file.name = (char *)FONT_PATH"F_GB2312.PIX", + .ascpixel.file.name = (char *)FONT_PATH"F_ASCII.PIX", + .tabfile.name = (char *)FONT_PATH"F_GB2312.TAB", + .isgb2312 = true, + .bigendian = false, + .putchar = font_putchar, + }, + //gbk + /* { */ + /* .language_id = Chinese_Simplified, */ + /* .flags = FONT_SHOW_PIXEL | FONT_SHOW_MULTI_LINE, */ + /* .pixel.file.name = (char *)"mnt/sdfile/res/F_GBK.PIX", */ + /* .ascpixel.file.name = (char *)"mnt/sdfile/res/F_ASCII.PIX", */ + /* .tabfile.name = (char *)"mnt/sdfile/res/F_GBK.TAB", */ + /* .isgb2312 = false, */ + /* .bigendian = false, */ + /* .putchar = platform_putchar, */ + /* }, */ +#endif + +#if LANGUAGE&BIT(Chinese_Traditional) + { + .language_id = Chinese_Traditional, + .flags = FONT_SHOW_PIXEL | FONT_SHOW_MULTI_LINE, + .pixel.file.name = (char *)FONT_PATH"F_GBK.PIX", + .ascpixel.file.name = (char *)FONT_PATH"F_ASCII.PIX", + .tabfile.name = (char *)FONT_PATH"F_GBK.TAB", + .isgb2312 = false, + .bigendian = false, + .putchar = font_putchar, + }, +#endif + +#if LANGUAGE&BIT(English) + { + .language_id = English, + .flags = FONT_SHOW_PIXEL | FONT_SHOW_MULTI_LINE, + .pixel.file.name = (char *)"mnt/sdfile/res/F_GBK.PIX", + .ascpixel.file.name = (char *)"mnt/sdfile/res/F_ASCII.PIX", + .tabfile.name = (char *)"mnt/sdfile/res/F_GBK.TAB", + .isgb2312 = false, + .bigendian = false, + .putchar = font_putchar, + }, +#endif + { + .language_id = 0,//不能删 + }, + +}; + + + + +#endif +#endif diff --git a/apps/soundbox/include/aec_user.h b/apps/soundbox/include/aec_user.h new file mode 100644 index 0000000..c42341c --- /dev/null +++ b/apps/soundbox/include/aec_user.h @@ -0,0 +1,136 @@ +#ifndef _AEC_USER_H_ +#define _AEC_USER_H_ + +#include "generic/typedef.h" +#include "user_cfg.h" +#include "commproc.h" + +#define AEC_DEBUG_ONLINE 0 +#define AEC_READ_CONFIG 1 + +/*清晰语音处理模块定义*/ +#define AEC_EN BIT(0) //回音消除 +#define NLP_EN BIT(1) //回音压制 +#define ANS_EN BIT(2) //语音降噪 +#define AGC_EN BIT(4) //AGC自动增益控制 +/*TDE_EN和TDEYE_EN只有在TCFG_AUDIO_SMS_ENABLE = SMS_TDE有效*/ +#define TDE_EN BIT(5) //延时估计模块使能 +#define TDEYE_EN BIT(6) //延时估计模块结果使用(前提是模块使能) + +/*清晰语音处理模式定义*/ +#define AEC_MODE_ADVANCE (AEC_EN | NLP_EN | ANS_EN) //高级模式 +#define AEC_MODE_REDUCE (NLP_EN | ANS_EN) //精简模式 +#define AEC_MODE_SIMPLEX (ANS_EN) //单工模式 + +/* + *SMS模式选择 + *(1)SMS模式性能更好,同时也需要更多的ram和mips + *(2)SMS_NORMAL和SMS_TDE功能一样,只是SMS_TDE内置了延时估计和延时补偿 + *可以更好的兼容延时不固定的场景 + */ +#define SMS_DISABLE 0 +#define SMS_NORMAL 1 +#define SMS_TDE 2 +#define TCFG_AUDIO_SMS_ENABLE SMS_DISABLE + +#if (TCFG_AUDIO_SMS_ENABLE == SMS_NORMAL) +#define aec_open sms_init +#define aec_close sms_exit +#define aec_in_data sms_fill_in_data +#define aec_ref_data sms_fill_ref_data +#elif (TCFG_AUDIO_SMS_ENABLE == SMS_TDE) +#define aec_open sms_tde_init +#define aec_close sms_tde_exit +#define aec_in_data sms_tde_fill_in_data +#define aec_ref_data sms_tde_fill_ref_data +#else +#define aec_open aec_init +#define aec_close aec_exit +#define aec_in_data aec_fill_in_data +#define aec_ref_data aec_fill_ref_data +#endif/*TCFG_AUDIO_SMS_ENABLE*/ + +/* +********************************************************************* +* Audio AEC Init +* Description: 初始化AEC模块 +* Arguments : sr 采样率(8000/16000) +* Return : 0 成功 其他 失败 +* Note(s) : None. +********************************************************************* +*/ +int audio_aec_init(u16 sample_rate); + +/* +********************************************************************* +* Audio AEC Open +* Description: 初始化AEC模块 +* Arguments : sr 采样率(8000/16000) +* enablebit 使能模块(AEC/NLP/AGC/ANS...) +* out_hdl 自定义回调函数,NULL则用默认的回调 +* Return : 0 成功 其他 失败 +* Note(s) : 该接口是对audio_aec_init的扩展,支持自定义使能模块以及 +* 数据输出回调函数 +********************************************************************* +*/ +int audio_aec_open(u16 sample_rate, s16 enablebit, int (*out_hdl)(s16 *data, u16 len)); + +/* +********************************************************************* +* Audio AEC Close +* Description: 关闭AEC模块 +* Arguments : None. +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_aec_close(void); + +/* +********************************************************************* +* Audio AEC Input +* Description: AEC源数据输入 +* Arguments : buf 输入源数据地址 +* len 输入源数据长度 +* Return : None. +* Note(s) : 输入一帧数据,唤醒一次运行任务处理数据,默认帧长256点 +********************************************************************* +*/ +void audio_aec_inbuf(s16 *buf, u16 len); + +/* +********************************************************************* +* Audio AEC Reference +* Description: AEC模块参考数据输入 +* Arguments : buf 输入参考数据地址 +* len 输入参考数据长度 +* Return : None. +* Note(s) : 声卡设备是DAC,默认不用外部提供参考数据 +********************************************************************* +*/ +void audio_aec_refbuf(s16 *buf, u16 len); + +/* +********************************************************************* +* Audio AEC Output Query +* Description: 查询aec模块的输出数据缓存大小 +* Arguments : None. +* Return : 数据缓存大小 +* Note(s) : None. +********************************************************************* +*/ +int audio_aec_output_data_size(void); + +/* +********************************************************************* +* Audio AEC Output Read +* Description: 读取aec模块的输出数据 +* Arguments : buf 读取数据存放地址 +* len 读取数据长度 +* Return : 数据读取长度 +* Note(s) : None. +********************************************************************* +*/ +int audio_aec_output_read(s16 *buf, u16 len); + +#endif/*_AEC_USER_H_*/ diff --git a/apps/soundbox/include/app_action.h b/apps/soundbox/include/app_action.h new file mode 100644 index 0000000..10a1d71 --- /dev/null +++ b/apps/soundbox/include/app_action.h @@ -0,0 +1,64 @@ +#ifndef APP_ACTION_H +#define APP_ACTION_H + +#include "app_config.h" +#include "system/app_core.h" +#include "system/task.h" +#include "common/user_msg.h" + +#if (TCFG_TONE2TWS_ENABLE) +#include "bt_tws.h" +#endif + +#define ACTION_APP_MAIN 0x0001 + + +#define APP_NAME_POWERON "poweron" +#define APP_NAME_POWEROFF "poweroff" +#define APP_NAME_BT "bt" +#define APP_NAME_MUSIC "music" +#define APP_NAME_FM "fm" +#define APP_NAME_RECORD "record" +#define APP_NAME_LINEIN "linein" +#define APP_NAME_RTC "rtc" +#define APP_NAME_PC "pc" +#define APP_NAME_SPDIF "spdif" +#define APP_NAME_IDLE "idle" +#define APP_NAME_BOX "box" + +extern struct application app_begin[]; +extern struct application app_end[]; +#define list_for_each_app(p) \ + for (p=app_begin; p> 30) & 0x3) == 0x1 ? 1 : 0) +#define IS_REPEAT_END(a) ((((u32)a >> 30) & 0x3) == 0x2 ? 1 : 0) +#define TONE_REPEAT_COUNT(a) (((u32)a) & 0xffff) + +#define DEFAULT_SINE_TONE(a) (char *)(((u32)0x3 << 30) | (a)) +#define IS_DEFAULT_SINE(a) ((((u32)a >> 30) & 0x3) == 0x3 ? 1 : 0) +#define DEFAULT_SINE_ID(a) ((u32)a & 0xffff) + +#if CONFIG_USE_DEFAULT_SINE +#undef TONE_TWS_CONN +#define TONE_TWS_CONN DEFAULT_SINE_TONE(SINE_WTONE_TWS_CONNECT) +#undef TONE_TWS_DISCONN +#define TONE_TWS_DISCONN DEFAULT_SINE_TONE(SINE_WTONE_TWS_DISCONNECT) + +#undef TONE_MAX_VOL +#define TONE_MAX_VOL DEFAULT_SINE_TONE(SINE_WTONE_MAX_VOLUME) + +#undef TONE_NORMAL +#define TONE_NORMAL DEFAULT_SINE_TONE(SINE_WTONE_NORAML) +#if BT_PHONE_NUMBER + +#else +#undef TONE_RING +#define TONE_RING DEFAULT_SINE_TONE(SINE_WTONE_RING) +#endif + +#undef TONE_LOW_POWER +#define TONE_LOW_POWER DEFAULT_SINE_TONE(SINE_WTONE_LOW_POWER) +#endif + +#define TONE_SIN_NORMAL DEFAULT_SINE_TONE(SINE_WTONE_NORAML) + +extern const char *tone_table[]; +int tone_play(const char *name, u8 preemption); +int tone_play_index(u8 index, u8 preemption); +int tone_play_index_with_callback(u8 index, u8 preemption, void (*user_evt_handler)(void *priv), void *priv); +int tone_file_list_play(const char **list, u8 preemption); +int tone_play_stop(void); +int tone_play_stop_by_index(u8 index); +int tone_play_stop_by_path(char *path); +int tone_get_status(); +int tone_play_by_path(const char *name, u8 preemption); + +int tone_dec_wait_stop(u32 timeout_ms); + +// 按序列号播放提示音 +int tone_play_with_callback_by_index(u8 index, // 序列号 + u8 preemption, // 打断标记 + void (*evt_handler)(void *priv, int flag), // 事件回调接口 //flag: 0正常关闭,1被打断关闭 + void *evt_priv // 事件回调私有句柄 + ); + +// 按名字播放提示音 +int tone_play_with_callback_by_name(char *name, // 带有路径的文件名 + u8 preemption, // 打断标记 + void (*evt_handler)(void *priv, int flag), // 事件回调接口 //flag: 0正常关闭,1被打断关闭 + void *evt_priv // 事件回调私有句柄 + ); + +// 按列表播放提示音 +int tone_play_with_callback_by_list(const char **list, // 文件名列表 + u8 preemption, // 打断标记 + void (*evt_handler)(void *priv, int flag), // 事件回调接口 //flag: 0正常关闭,1被打断关闭 + void *evt_priv // 事件回调私有句柄 + ); + +// 按键提示音初始化 +int audio_key_tone_init(void); +// 注销按键提示音播放 +void audio_key_tone_destroy(void); + +// 播放正弦波数组 +int audio_key_tone_play_sin(struct audio_sin_param *sin, u8 sin_num, u8 preemption); +// 播放文件 +int audio_key_tone_play_name(const char *name, u8 preemption); +// 按序号播放文件 // 使用key_tone_index[]数组 +int audio_key_tone_play_index(u8 index, u8 preemption); +// 按键提示音播放 // 默认播放数组中第一个 +void audio_key_tone_play(void); + +// 检测按键提示音是否在播放 +int audio_key_tone_is_play(void); + +// 设置按键提示音的音量 +void audio_key_tone_digvol_set(u8 volume); + + +#endif diff --git a/apps/soundbox/include/ui/color_led/color_led.h b/apps/soundbox/include/ui/color_led/color_led.h new file mode 100644 index 0000000..c1a90b4 --- /dev/null +++ b/apps/soundbox/include/ui/color_led/color_led.h @@ -0,0 +1,39 @@ +#ifndef _COLOR_LED_H +#define _COLOR_LED_H + +typedef struct _color_cell { + u8 type; + u32 led_io; + u32 show_time;/*ms,'0' means never stop,used display_time_by_step if display_time_by_step not zero */ + struct { + struct { + u32 color; + } color; + + struct { + u32 loop_num; + u32 back_step; + } loop; + + struct { + u32 start_color; + u8 color_sel : 3/*BIT0:RED BIT1:GREE BIT2:BLUE*/; + u8 start_direction : 3; + u8 reserved : 2; + u32 step_time; + u8 step; + u8 flood; + u8 ceil; + u32 display_time_by_step;/*used display_time_by_step if display_time_by_step not zero */ + } pwm_color; + } type_action; +} __attribute__((packed)) color_cell_t; + +typedef enum { + COLOR_TYPE_SET = 1, + COLOR_TYPE_LOOP, + COLOR_TYPE_PWM, +} COLOR_TYPE; + +int color_led_set(const color_cell_t table[], u32 numberofmembers, void (*led_select)(u32 led_io)); +#endif diff --git a/apps/soundbox/include/ui/color_led/color_led_app.h b/apps/soundbox/include/ui/color_led/color_led_app.h new file mode 100644 index 0000000..5289d6c --- /dev/null +++ b/apps/soundbox/include/ui/color_led/color_led_app.h @@ -0,0 +1,52 @@ +#ifndef _COLOR_LED_APP_H +#define _COLOR_LED_APP_H +#include "color_led_driver.h" +#include "color_led.h" + +typedef enum { + COLOR_LED_MODE_RAINBOW = 0, + COLOR_LED_MODE_HEARTBEAT = 1, + COLOR_LED_MODE_CANDLELIGHT = 2, + COLOR_LED_MODE_NIGHTLIGNT = 3, + COLOR_LED_MODE_STAGE = 4, + COLOR_LED_MODE_WANDERFUL_BREATH = 5, + COLOR_LED_MODE_RED_BREATH = 6, + COLOR_LED_MODE_GREEN_BREATH = 7, + COLOR_LED_MODE_BLUE_BREATH = 8, + COLOR_LED_MODE_NICE_EMOTION = 9, + COLOR_LED_MODE_SUNSET = 10, + COLOR_LED_MODE_FOLLOW_MUSIC = 11, + COLOR_LED_MODE_LIGHT = 12, + COLOR_LED_MODE_COLORFUL_TWINKLE = 13, + COLOR_LED_MODE_TWINKLE = 14, +} COLOR_LED_MODE; + +#define TWINKLE_FAST 0 +#define TWINKLE_SLOW 1 +#define TWINKLE_MID 2 +#define TWINKLE_FOLLOW_MUSIC 3 +#define TWINKLE_PAUSE 4 + +#define TWINKLE_SLOW_FRE 900 +#define TWINKLE_MID_FRE 600 +#define TWINKLE_FAST_FRE 300 + +#define TWINKLE_SLOW_THRESHOLD 100 +#define TWINKLE_MID_THRESHOLD 1000 + +#if TCFG_COLORLED_ENABLE +#define COLOR_LED_SET(table,led_select) \ + color_led_set(table,table##_size,led_select) +#else +#define COLOR_LED_SET(table,led_select) +#endif + +#define COLORLED_PLATFORM_DATA_BEGIN(data) \ + const colorled_platform_data data = { + +#define COLORLED_PLATFORM_DATA_END() \ +}; + +void color_led_init(void *data); +int color_led_set_api(u8 mode, u8 fre_mode, u32 color); +#endif diff --git a/apps/soundbox/include/ui/color_led/color_led_driver.h b/apps/soundbox/include/ui/color_led/color_led_driver.h new file mode 100644 index 0000000..3e1cb4e --- /dev/null +++ b/apps/soundbox/include/ui/color_led/color_led_driver.h @@ -0,0 +1,38 @@ +#ifndef _COLOR_LED_DRIVER_H +#define _COLOR_LED_DRIVER_H + + +#define COLOR_LED_MODE_NORNAL 0 +#define COLOR_LED_MODE_PWM 1 +#define PWM_NO_OUTPUT_CH (-1) + +typedef struct _colorled_platform_data { + struct { + u8 pin; + JL_TIMER_TypeDef *timer_hdl; + int output_ch;/*"-1": do not used output channel*/ + } pin_red, pin_gree, pin_blue; + u8 work_mode; +} colorled_platform_data; + +void __color_set(u32 color); +void __color_led_io_set(const colorled_platform_data *cfg_data); +#define COLOR_SET(color) __color_set(color) +#define COLOR_LED_IO_SET(cfg_data) __color_led_io_set(cfg_data) + +/* + * BYTE3(reserved) BYTE2(BLUE) BYTE1(GREE) BYTE0(RED) + * */ +#define COLOR_RED 0X000000FF +#define COLOR_GREEN 0X0000FF00 +#define COLOR_BLUE 0X00FF0000 +#define COLOR_YELLOW 0X0000FFFF +#define COLOR_PURPLE 0X00FF00FF +#define COLOR_CYAN 0X00FFFF00 +#define COLOR_WHITE 0X00FFFFFF +#define COLOR_BLACK 0X00000000 +#define COLOR_ORANGE 0X000080FF + + + +#endif diff --git a/apps/soundbox/include/ui/color_led/color_led_table.h b/apps/soundbox/include/ui/color_led/color_led_table.h new file mode 100644 index 0000000..729d02d --- /dev/null +++ b/apps/soundbox/include/ui/color_led/color_led_table.h @@ -0,0 +1,88 @@ +#ifndef _COLOR_LED_TABLE_H +#define _COLOR_LED_TABLE_H +#include "color_led_app.h" + +#define RED_EN BIT(0) +#define GREEN_EN BIT(1) +#define BLUE_EN BIT(2) +/* +description: + 本步骤可以设置RGB灯处于一个特定的颜色状态,并且可以持续的时间 + +parameter: + led_io: + 对应int color_led_set(const color_cell_t table[], u32 numberofmembers, void (*led_select)(u32 led_io))接口中的 + led_select回调接口中的led_io参数 + show_time:本步骤持续的时间,单位ms,0为本步骤持续无限久 + color:显示的颜色,和三基色对应,BIT(0)对应红色,BIT(1)对应绿色,BIT(2)对应蓝色,BIT(3)保留未使用 + * */ +#define COLOR_TYPE_COLOR_INIT(led_io,show_time,color) {COLOR_TYPE_SET,led_io,show_time,color,0x11223344,0x11223344} +/* +description: + 本步骤可以让现在的控制跳到特定的步骤,从而实现循环控制。 + +parameter: + back_step:返回到相对于开始位置的步骤值 + loop_num:循环的次数 + * */ +#define COLOR_TYPE_LOOP_INIT(back_step,loop_num) {COLOR_TYPE_LOOP,0xffffffff,0,0x11223344,loop_num,back_step} +/* +description: + 本步骤可以实现RGB灯的呼吸灯效果控制。可以选择RGB其中的某几个颜色做呼吸灯控制,另外的灯保持start_color状态。也可以选择 + RGB灯每个颜色灯开始是PWM递增还是PWM递减。 + +parameter: + show_time:本步骤持续的时间,单位ms,0为本步骤持续无限久 + start_color:开始color设置 + color_sel:选择RGB灯中的特定灯做呼吸灯效果变化,BIT(0)对应红色,BIT(1)对应绿色,BIT(2)对应蓝色,‘1’为做呼吸灯效果,‘0’为 + 保持start_color的状态。 + start_direction:RGB灯每个颜色灯开始是PWM递增还是PWM递减。BIT(0)对应红色,BIT(1)对应绿色,BIT(2)对应蓝色,‘1’为递增,‘0’ + 为递减。 + step_time:每递增或者递减一个step长度的时间。 + step:每一个步骤递增或者递减的RGB值。例如R当前为0xA8,方向为递减,step为2,下一个step_time时间R会变成0xA6。 + floor:递减的最小值,当递减值小于floor时候,方向就会自动变为递增。 + ceil:递增的最大值,当递增至大于ceil时候,方向就会自动变为递减。 + display_time_by_step:显示的时间,时间单位是“step_time” + * */ +#define BREATH_RGB_SEL(R,G,B) (R|G|B) +#define BREATH_RGB_DIR_UP(R,G,B) (R|G|B) +#define COLOR_TYPE_BREATH_INIT(led_io,show_time,start_color,color_sel,start_direction,step_time,step,floor,ceil) \ + {COLOR_TYPE_PWM,led_io,show_time,0x11223344,0x11223344,0x11223344,\ + start_color,color_sel,start_direction,0,step_time,step,floor,ceil,0} +#define COLOR_TYPE_BREATH_MEASURE_BY_STEP_INIT(led_io,display_time_by_step,start_color,color_sel,start_direction,step_time,step,floor,ceil) \ + {COLOR_TYPE_PWM,led_io,0,0x11223344,0x11223344,0x11223344,\ + start_color,color_sel,start_direction,0,step_time,step,floor,ceil,display_time_by_step} + +/* +description: + 加个结束标志,效果是黑色(灯全灭),一直持续。防止table不规范导致控制越界。 + +parameter: + * */ +#define COLOR_END() COLOR_TYPE_COLOR_INIT(0xffffffff,0,COLOR_BLACK) + +#define COLOR_TABLE_REGISTER(name) const u32 name##_size = sizeof(name) / sizeof(name[0]); +#define COLOR_TABLE_EXTERN(name) \ + extern const color_cell_t name[];\ + extern const u32 name##_size; + +COLOR_TABLE_EXTERN(color_table_demo1); +COLOR_TABLE_EXTERN(color_table_sunset); +COLOR_TABLE_EXTERN(color_table_nice_emotion); +COLOR_TABLE_EXTERN(color_table_blue_breath); +COLOR_TABLE_EXTERN(color_table_green_breath); +COLOR_TABLE_EXTERN(color_table_red_breath); +COLOR_TABLE_EXTERN(color_table_wonderful_breath); +COLOR_TABLE_EXTERN(color_table_nightlight); +COLOR_TABLE_EXTERN(color_table_candlelight); +COLOR_TABLE_EXTERN(color_table_heartbeat); +COLOR_TABLE_EXTERN(color_table_rainbow); +COLOR_TABLE_EXTERN(color_table_colorful_twinkle_slow); +COLOR_TABLE_EXTERN(color_table_colorful_twinkle_mid); +COLOR_TABLE_EXTERN(color_table_colorful_twinkle_fast); +COLOR_TABLE_EXTERN(color_table_twinkle_base); +COLOR_TABLE_EXTERN(color_table_light_base); +COLOR_TABLE_EXTERN(color_table_stage); +COLOR_TABLE_EXTERN(color_table_colorful_twinkle_pause); + +#endif diff --git a/apps/soundbox/include/ui/lcd_seg/lcd_seg3x9_driver.h b/apps/soundbox/include/ui/lcd_seg/lcd_seg3x9_driver.h new file mode 100644 index 0000000..b8f3a72 --- /dev/null +++ b/apps/soundbox/include/ui/lcd_seg/lcd_seg3x9_driver.h @@ -0,0 +1,134 @@ +#ifndef _LCD_SEG3X9_DRV_H_ +#define _LCD_SEG3X9_DRV_H_ + +typedef struct _lcd_seg3x9_var { + u8 bCoordinateX; + u8 bFlashChar; + u8 bShowBuff[4]; //[0] ~ [3]显示的数字/字母显示的所有段 + u32 bShowIcon; //每1bit对应LED4的1段, maybe icon > 7段 + u32 bFlashIcon; //闪烁标志 +} LCD_SEG3X9_VAR; + +#define LCD_SEG3X9_USB BIT(0) //0: USB图标 +#define LCD_SEG3X9_SD BIT(1) //1: SD图标 +#define LCD_SEG3X9_VOL BIT(2) //2: SD图标 +#define LCD_SEG3X9_MHZ BIT(3) //3: FM图标 +#define LCD_SEG3X9_DIGIT1 BIT(4) //4: 数字1 +#define LCD_SEG3X9_2POINT BIT(5) //5: 冒号 +#define LCD_SEG3X9_DOT BIT(6) //6: 点 + +typedef u32 UI_LCD_SEG3X9_ICON; + +struct lcd_seg3x9_pin { + u8 pin_com[3]; + u8 pin_seg[9]; +}; + +enum LCD_SEG3X9_BIAS { + LCD_SEG3X9_BIAS_OFF = 0, + LCD_SEG3X9_BIAS_1_2, // 1/2 bias + LCD_SEG3X9_BIAS_1_3, // 1/3 bias + LCD_SEG3X9_BIAS_1_4, // 1/4 bias +}; + +enum LCD_SEG3X9_COM_NUMBER { + LCD_SEG3X9_COM_NUMBER_3 = 0, + LCD_SEG3X9_COM_NUMBER_4, + LCD_SEG3X9_COM_NUMBER_5, + LCD_SEG3X9_COM_NUMBER_6, +}; + +enum LCD_SEG3X9_VOLTAGE { + LCD_SEG3X9_VOLTAGE_2_6V = 0, //000b + LCD_SEG3X9_VOLTAGE_2_7V, //001b + LCD_SEG3X9_VOLTAGE_2_8V, //010b + LCD_SEG3X9_VOLTAGE_2_9V, //011b + LCD_SEG3X9_VOLTAGE_3_0V, //100b + LCD_SEG3X9_VOLTAGE_3_1V, //101b + LCD_SEG3X9_VOLTAGE_3_2V, //110b + LCD_SEG3X9_VOLTAGE_3_3V, //111b +}; + + +struct lcd_seg3x9_platform_data { + enum LCD_SEG3X9_VOLTAGE vlcd; + enum LCD_SEG3X9_BIAS bias; + struct lcd_seg3x9_pin pin_cfg; +}; + + +//=================================================================================// +// 关于LCD段码屏接线问题 // +// 1.COM口需要从COM0按顺序开始连接, 如3COM, 则IO必须占用COM0/1/2,而不能COM1/2/3; +// 2.COM0/1/2与LCD屏可以不按照对应需要接线, 如: +// LCD_COM0 --> CHIP_COM2; +// LCD_COM1 --> CHIP_COM1; +// LCD_COM2 --> CHIP_COM0; +// 但一般建议按顺序接线; +// 2.SEG可以根据实际情况选择SEG0~SEG21接线, 如; +// LCD_SEG0 --> CHIP_SEG7; +// LCD_SEG1 --> CHIP_SEG8; +// LCD_SEG2 --> CHIP_SEG9; +//=================================================================================// +#define LCD_SEG3X9_PLATFORM_DATA_BEGIN(data) \ + const struct lcd_seg3x9_platform_data data = { + +#define LCD_SEG3X9_PLATFORM_DATA_END() \ +}; + +//UI LED7 API: +//=================================================================================// +// 模块初始化显示接口 // +//=================================================================================// +void lcd_seg3x9_init(const struct lcd_seg3x9_platform_data *_data); +const struct ui_display_api *ui_lcd_seg3x9_init(void *para); +//=================================================================================// +// 设置显示坐标接口 // +/* + ___ ___ ___ + |___| |___| |___| + |___| |___| |___| + ---0------1------2----> X +*/ +//=================================================================================// +void lcd_seg3x9_setX(u8 X); + +//=================================================================================// +// 字符类显示接口 // +//=================================================================================// +void lcd_seg3x9_show_char(u8 chardata); //显示字符(追加方式) +void lcd_seg3x9_flash_char_start(u8 index); //闪烁单个字符 +void lcd_seg3x9_flash_char_stop(u8 index); //取消闪烁单个字符 +void lcd_seg3x9_show_string(u8 *str); //显示字符串(追加方式) +void lcd_seg3x9_show_string_reset_x(u8 *str); //显示字符串, x从0开始 +void lcd_seg3x9_show_string_align_right(u8 *str); //led7显示字符串(清屏&右方式) +void lcd_seg3x9_show_string_align_left(u8 *str); //led7显示字符串(清屏&左方式) + +//=================================================================================// +// 数字类显示接口 // +//=================================================================================// +void lcd_seg3x9_show_number(u16 val); //显示数字(清屏&高位显示0) +void lcd_seg3x9_show_number2(u16 val); //显示数字(清屏&高位不显示) +void lcd_seg3x9_show_number_add(u16 val); //显示数字(追加方式) + +//=================================================================================// +// 图标类显示接口 // +//=================================================================================// +void lcd_seg3x9_show_icon(UI_LCD_SEG3X9_ICON icon); //显示单个图标(追加) +void lcd_seg3x9_flash_icon(UI_LCD_SEG3X9_ICON icon); //闪烁单个图标(追加) + +//=================================================================================// +// 模式类类显示接口 // +//=================================================================================// + +//=================================================================================// +// 清屏类显示接口 // +//=================================================================================// +void lcd_seg3x9_show_null(void); //清除所有显示(数字,字符串和图标) +void lcd_seg3x9_clear_string(void); //清除显示数字和字母 +void lcd_seg3x9_clear_icon(UI_LCD_SEG3X9_ICON icon); //清除显示单个图标 +void lcd_seg3x9_clear_all_icon(void); //清除显示所有图标 + + +#endif /* #ifndef _LCD_SEG3X9_DRV_H_ */ + diff --git a/apps/soundbox/include/ui/lcd_simple/menu.h b/apps/soundbox/include/ui/lcd_simple/menu.h new file mode 100644 index 0000000..87f3880 --- /dev/null +++ b/apps/soundbox/include/ui/lcd_simple/menu.h @@ -0,0 +1,363 @@ + +//generated by ResBuilder in 2011// + +#ifndef _MENU_H_ +#define _MENU_H_ + +////StringResID Define Table//// +#define Chinese_Simplified 1 +#define Chinese_Traditional 2 +#define Japanese 3 +#define Korean 4 +#define English 5 +#define French 6 +#define German 7 +#define Italian 8 +#define Dutch 9 +#define Portuguese 10 +#define Spanish 11 +#define Swedish 12 +#define Czech 13 +#define Danish 14 +#define Polish 15 +#define Russian 16 +#define Turkey 17 +#define Hebrew 18 +#define Thai 19 +#define Hungarian 20 +#define Romanian 21 +#define Arabic 22 + +#define LANGUAGEID_SUM 22 + + + +////Multi Language Define Table//// +#define vplaym1 1 +#define mplay2 2 +#define mplay4 3 +#define mplay5 4 +#define vstopm1 5 +#define vstopm2 6 +#define udisk 7 +#define cdelfile 8 +#define cdelall 9 +#define mstop5 10 +#define vloopm1 11 +#define vloopm2 12 +#define vloopm3 13 +#define vloopm4 14 +#define vloopm5 15 +#define vloopm6 16 +#define meq1 17 +#define meq2 18 +#define meq3 19 +#define meq4 20 +#define meq5 21 +#define meq6 22 +#define meq7 23 +#define meq8 24 +#define recpara 25 +#define mrstop3 26 +#define rsetgain 27 +#define main2 28 +#define mbps 29 +#define msrate 30 +#define smain7 31 +#define mrbps0 32 +#define mrbps1 33 +#define mrbps2 34 +#define mrbps3 35 +#define mrbps4 36 +#define mrbps5 37 +#define mrbps6 38 +#define mrbps7 39 +#define mrbps8 40 +#define mrbps9 41 +#define mrbps10 42 +#define mrbps11 43 +#define srate48k 44 +#define srate32k 45 +#define srate24k 46 +#define srate16k 47 +#define srate12k 48 +#define record1 49 +#define record2 50 +#define record 51 +#define rsaving 52 +#define fmenu16 53 +#define sreplay1 54 +#define fmenu1 55 +#define fmenu15 56 +#define fmfreq 57 +#define fmenu2 58 +#define fmenu3 59 +#define smain1 60 +#define smain2 61 +#define smain3 62 +#define s_tools 63 +#define kvoice1 64 +#define kvoice2 65 +#define smain6 66 +#define smain8 67 +#define smain9 68 +#define slan1 69 +#define slan3 70 +#define slan4 71 +#define slan5 72 +#define slan2 73 +#define slan6 74 +#define slan7 75 +#define slan8 76 +#define slan9 77 +#define slan10 78 +#define slan11 79 +#define slan12 80 +#define slan13 81 +#define slan14 82 +#define slan15 83 +#define slan16 84 +#define slan17 85 +#define slan18 86 +#define slan19 87 +#define slan20 88 +#define slan21 89 +#define slan22 90 +#define smain4 91 +#define clock 92 +#define fmset 93 +#define alarmon 94 +#define alarmoff 95 +#define alarmtm 96 +#define alarmcyc 97 +#define alarmmus 98 +#define alarmvol 99 +#define ringonce 100 +#define ringday 101 +#define ringweek 102 +#define ringinl 103 +#define fm_rmon 104 +#define fm_rtue 105 +#define fm_rwed 106 +#define fm_rthu 107 +#define fm_rfri 108 +#define fm_rsat 109 +#define fm_rsun 110 +#define timingfmon 111 +#define timingfmoff 112 +#define fmrecordon 113 +#define fmrecordoff 114 +#define fmtime 115 +#define fm_manual 116 +#define fmautoload 117 +#define fm_switch 118 +#define fm_vol 119 +#define t_cal 120 +#define t_music 121 +#define t_record 122 +#define t_fm 123 +#define t_sys 124 +#define f_browse 125 +#define alarm1 126 +#define t_ebook 127 +#define sel_file 128 +#define play_set 129 +#define handplay 130 +#define autoplay 131 +#define playspeed 132 + +#define STRINGID_SUM 132 + + + +////BmpResID Define Table//// +#define CH_NOFILE 1 +#define CLOCK 2 +#define CLOCKA 3 +#define CONTRSTW 4 +#define DELLA 5 +#define DIRROOTA 6 +#define EBOOK 7 +#define EBOOKA 8 +#define ENGDELLA 9 +#define EN_NOFILE 10 +#define FM 11 +#define FMA 12 +#define MMP3 13 +#define MUSIC1 14 +#define MUSICA 15 +#define MWAV 16 +#define MWMA 17 +#define NOUDISK 18 +#define PMDSCOM 19 +#define RTC_NUM_0 20 +#define RTC_NUM_1 21 +#define RTC_NUM_2 22 +#define RTC_NUM_3 23 +#define RTC_NUM_4 24 +#define RTC_NUM_5 25 +#define RTC_NUM_6 26 +#define RTC_NUM_7 27 +#define RTC_NUM_8 28 +#define RTC_NUM_9 29 +#define RTC_NUM_A 30 +#define RTC_NUM_B 31 +#define RECORD1 32 +#define RECORDA 33 +#define SDMMC 34 +#define SIGNAL_1 35 +#define SIGNAL_2 36 +#define SIGNAL_3 37 +#define SIGNAL_4 38 +#define SIGNAL_5 39 +#define SIGNAL_6 40 +#define SYSTEM1 41 +#define SYSTEMA 42 +#define UDISK 43 +#define UDISKOUT 44 +#define ACTIVE 45 +#define ALARM 46 +#define ALARM_C 47 +#define ALARM_CA 48 +#define ALARM_O 49 +#define ALARM_OA 50 +#define ALARM_T 51 +#define ALARM_TA 52 +#define ALARM_V 53 +#define ALARM_VA 54 +#define ALMICON 55 +#define BATTERY01 56 +#define BATTERY02 57 +#define BATTERY03 58 +#define BATTERY04 59 +#define BATTERY05 60 +#define BATTERY06 61 +#define BIGBAT1 62 +#define BIGBAT2 63 +#define BIGBAT3 64 +#define BIGBAT4 65 +#define BIGBAT5 66 +#define BKCLR1 67 +#define BPS128 68 +#define BPS160 69 +#define BPS48 70 +#define BPS64 71 +#define BPS96 72 +#define C_NOSEL 73 +#define C_SEL 74 +#define CALENDAR 75 +#define CALENDAR1 76 +#define CALENDAR2 77 +#define CARDOUT 78 +#define CDEL_NO 79 +#define CDEL_YES 80 +#define CHNDEL 81 +#define CHNSAVE 82 +#define CHNWAIT 83 +#define CONTRSTB 84 +#define CYCLE1 85 +#define CYCLE2 86 +#define CYCLE3 87 +#define CYCLE4 88 +#define DELFILE 89 +#define DISCERR 90 +#define EDELFILE 91 +#define EFICON 92 +#define ENGCOUT 93 +#define ENGDEL 94 +#define ENGDICERR 95 +#define ENGNOCARD 96 +#define ENGNODISK 97 +#define ENGNOSPAC 98 +#define ENGSAVE 99 +#define ENGUOUT 100 +#define ENGWAIT 101 +#define ENOFILE 102 +#define EQCLAS 103 +#define EQDBB 104 +#define EQJAZZ 105 +#define EQNOR 106 +#define EQPOP 107 +#define EQROCK 108 +#define EQSOFT 109 +#define EQWOW 110 +#define FLASH 111 +#define FMUSIC 112 +#define FOLDER 113 +#define FOLDERM 114 +#define FQBAR 115 +#define FQBAR2 116 +#define GOODBYTE 117 +#define LARROW 118 +#define LINEIN1 119 +#define LINEIN2 120 +#define LINEINBIG 121 +#define LINEINXXX 122 +#define LOGOFM 123 +#define LOWBAT 124 +#define MICIN 125 +#define MLOOP1 126 +#define MLOOP2 127 +#define MLOOP3 128 +#define MLOOP4 129 +#define MLOOP5 130 +#define MLOOP6 131 +#define MP3_128 132 +#define MP3_16 133 +#define MP3_192 134 +#define MP3_24K 135 +#define MP3_256 136 +#define MP3_32 137 +#define MP3_320 138 +#define MP3_32K 139 +#define MP3_48 140 +#define MP3_48K 141 +#define MP3_64 142 +#define MP3_8 143 +#define MP3_96 144 +#define MREC 145 +#define MWAV128K 146 +#define MWAV176K 147 +#define MWAV192K 148 +#define MWAV256K 149 +#define MWAV32K 150 +#define MWAV353K 151 +#define MWAV384K 152 +#define MWAV64K 153 +#define MWMA128K 154 +#define MWMA176K 155 +#define MWMA192K 156 +#define MWMA32K 157 +#define MWMA64K 158 +#define MWMA96K 159 +#define NO_ICON 160 +#define NOCARD 161 +#define NOFILE 162 +#define NOMEMORY 163 +#define NONGZI 164 +#define OFF_SEL 165 +#define ON_SEL 166 +#define PAUSE 167 +#define PAUSE1 168 +#define RARROW 169 +#define REC_FILE 170 +#define RECSAVE 171 +#define SCANSD1 172 +#define SCANSDMMC 173 +#define SCANUD1 174 +#define SCANUDISK 175 +#define SLIDER 176 +#define SLIDER_P 177 +#define TOOLP 178 +#define TOOLPA 179 +#define UNACTIVE 180 +#define WAV_12K 181 +#define WAV_16K 182 +#define WAV_24K 183 +#define WAV_32K 184 +#define WAV_48K 185 +#define WAV_8K 186 + +#define BMPID_SUM 186 + +#endif diff --git a/apps/soundbox/include/ui/lcd_simple/ui.h b/apps/soundbox/include/ui/lcd_simple/ui.h new file mode 100644 index 0000000..f1c7326 --- /dev/null +++ b/apps/soundbox/include/ui/lcd_simple/ui.h @@ -0,0 +1,76 @@ +#ifndef __LCDSIMULATOR_H__ +#define __LCDSIMULATOR_H__ + +#include "menu.h" +#include "font/language_list.h" +#include "typedef.h" + +// #define USE_BLANK_FUNC 1 +// #define LCDPAGE 8 +// #define LCDCOLUMN 128 +// #define SCR_WIDTH LCDCOLUMN +// #define SCR_HEIGHT (LCDPAGE*8) + +#define MENUICONWIDTH 12 //菜单项目左边图标的宽度(象素) +#define MENUITEMHEIGHT 16 //菜单项目的高度(象素) +#define SCROLLBARWIDTH 6 //垂直滚动条的宽度(象素) +#define MENUITEMSUMPERSCR (SCR_HEIGHT/MENUITEMHEIGHT) //每屏可显示的最大菜单项 +#define MENUITEMPAGEHEIGHT 2 //每个菜单项所占的页数 2个LCDPAGE --> 2*8=16个像素 + +#define RESFILESTARTADDRESS 0 //资源文件的起始地址 + + +#define PROGRESSLENGTH 100 //进度条长度(象素) +#define SLIDERLENGTH 100 //滑动条长度(象素) +#define SLIDERMOVESTEP 5 //滑动块的移动步长 +#define SLIDER_NOMOVE_TIMEEXIT 10 //滑动条不动超过此时间自动退出,(*0.5S) + +#define MENUWAITTIME (8*2) //菜单界面不操作超过MENUWAITTIME时间则自动返回 + +#define ntohl(x) (unsigned long)((x>>24)|((x>>8)&0xff00)|(x<<24)|((x&0xff00)<<8)) +#define ntoh(x) (unsigned short int )((x>>8&0x00ff)|x<<8&0xff00) + +//#pragma pack(1) +typedef u8(* FUN)(u8 mode); + +typedef struct _MENULIST { + u8 ItemSum; //菜单项目总数 + u8 ActiveItemNum; //当前活动菜单项目序号:1--ItemSum + u8 IconID[2]; //第一个为菜单选中时显示图标的ID号,第二个为菜单未选中时显示图标的ID号 + u16 TitleID; //菜单的标题字符串ID号,没有标题此值为0 + u16 *ItemString; //菜单项目对应的字符串ID号 +// FUN fun; +} MENULIST; + +//////函数声明////// + +u8 TurnPixelReverse_Page(u8 startpage, u8 pagelen); +u8 TurnPixelReverse_Rect(u8 left, u8 top, u8 right, u8 bottom); + +void UI_MenuSelectOn(u8 showitemnum); +void Scrol_String(u16 StringID); +u8 SetScrollBar(u8 Start_x); +u8 SetSlideBlock(u8 Start_x, u8 Start_y); + +u8 UI_Slider(FUN gslider); +u8 UI_Progress(u8 currentpos, u8 progress_y_pos, u8 progresslength); +u8 SetSlider(u8 start_x, u8 start_y, u8 length); +u8 SetProgress(u8 start_x, u8 start_y, u8 length); +u8 ClearLcdBuf_Page(u8 startpage, u8 pagelen); +u8 ClearLcdBuf_Rect(u8 left, u8 top, u8 right, u8 bottom); +u8 draw_slider(s8 currentpos, u8 slider_y_pos, u8 sliderlength); +#define UI_SLIDER_CURR_VALUE 0 +#define UI_SLIDER_DEC 1 +#define UI_SLIDER_INC 2 + +extern s8 MenuItemSelectOnNum; //当前屏幕活动page序号:0--(MENUITEMSUMPERSCR-1) +extern s8 CurrentScreenNum; //当前所处屏幕数,从0序号开始 +extern u8 NeedScreenSumViaItem; //菜单项目总数将占用屏幕的屏数 +extern u8 LaseScreenRemainMenuItem; //最后一屏只需显示的菜单项目数 +extern u8 LanguageMode; + +extern void clear_lcd(); +extern void draw_lcd(u8 start_page, u8 page_len); +extern void clear_lcd_area(u8 start_page, u8 end_page); + +#endif diff --git a/apps/soundbox/include/ui/lcd_simple/ui_mainmenu.h b/apps/soundbox/include/ui/lcd_simple/ui_mainmenu.h new file mode 100644 index 0000000..312f324 --- /dev/null +++ b/apps/soundbox/include/ui/lcd_simple/ui_mainmenu.h @@ -0,0 +1,21 @@ +#ifndef __UI_MAINMENU_H__ +#define __UI_MAINMENU_H__ + +#define AUTORUNTIMEMAX 10 +#define TASKTOTLE 24 //任务总数 +#define SCREENSHOWTASKSUM 5 //屏幕需显示的任务图标 +//#define SHOWTASKSUM 8 //需显示的任务图标总数 + +typedef struct { + u8 taskname[16]; //任务名 + u16 bmpID; //该任务在主界面显示的图标 + u16 strID; //该任务在主界面显示的字符串 + u8 showflag; //标识该任务是否显式的显示任务图标 +} TASKSTRUCT; + +extern const TASKSTRUCT taskbuf[TASKTOTLE]; +extern u8 taskshow[TASKTOTLE]; + +u8 UI_mainmenu(s8 apprun); +void findtaskexist(u8 tasksum); +#endif diff --git a/apps/soundbox/include/ui/lcd_spi/lcd_drive.h b/apps/soundbox/include/ui/lcd_spi/lcd_drive.h new file mode 100644 index 0000000..d4765cb --- /dev/null +++ b/apps/soundbox/include/ui/lcd_spi/lcd_drive.h @@ -0,0 +1,150 @@ +#ifndef __SPI_LCD_DRIVER_H +#define __SPI_LCD_DRIVER_H + + +#include "asm/spi.h" + + +#if (SPI_LCD_DEBUG_ENABLE == 0) +#define lcd_d(...) +#define lcd_w(...) +#define lcd_e(fmt, ...) printf("[LCD ERROR]: "fmt, ##__VA_ARGS__) +#elif (SPI_LCD_DEBUG_ENABLE == 1) +#define lcd_d(...) +#define lcd_w(fmt, ...) printf("[LCD WARNING]: "fmt, ##__VA_ARGS__) +#define lcd_e(fmt, ...) printf("[LCD ERROR]: "fmt, ##__VA_ARGS__) +#else +#define lcd_d(fmt, ...) printf("[LCD DEBUG]: "fmt, ##__VA_ARGS__) +#define lcd_w(fmt, ...) printf("[LCD WARNING]: "fmt, ##__VA_ARGS__) +#define lcd_e(fmt, ...) printf("[LCD ERROR]: "fmt, ##__VA_ARGS__) +#endif + +// 两毫秒延时 +extern void delay_2ms(int cnt); +#define delay2ms(t) delay_2ms(t) + + +/* 定义初始化数据结构体 */ +typedef struct { + u8 cmd; // 地址 + u8 cnt; // 数据个数 + u8 dat[64]; // 数据 +} InitCode; + +#define REGFLAG_DELAY 0xFF + +struct spi_lcd_init { + char *name; // 名称 + u8 spi_pending; + u8 soft_spi; + u16 lcd_width; + u16 lcd_height; + u8 color_format; + u8 interface; + u8 column_addr_align; + u8 row_addr_align; + u8 backlight_status; + u8 *dispbuf; + u32 bufsize; + InitCode *initcode; // 初始化代码 + u16 initcode_cnt; // 初始化代码条数 + void (*Init)(void); + void (*WriteComm)(u16 cmd); // 写命令 + void (*WriteData)(u16 dat); // 写数据 + void (*WriteMap)(char *map, int size); // 写整个buf + void (*WritePAGE)(char *map, u8 page_star, u8 page_len); // 写page + void (*SetDrawArea)(int, int, int, int); + void (*Reset)(void); + void (*BackLightCtrl)(u8); + void (*EnterSleep)(); + void (*ExitSleep)(); +}; + + +void spi_dma_send_byte(u8 dat); +void spi_dma_send_map(u8 *map, u32 size); +void SPI_LcdTest(); + + + + +struct lcd_spi_platform_data { + u32 pin_reset; + u32 pin_cs; + u32 pin_rs; + u32 pin_bl; + spi_dev spi_cfg; + const struct spi_platform_data *spi_pdata; +}; + + + +// LCD 初始化接口 +#define REGISTER_LCD_DRIVE() \ + const struct spi_lcd_init dev_drive + +enum LCD_COLOR { + LCD_COLOR_RGB565, + LCD_COLOR_MONO, +}; + +enum LCD_IF { + LCD_SPI, + LCD_EMI, +}; + +struct lcd_info { + u16 width; + u16 height; + u8 color_format; + u8 interface; + u8 col_align; + u8 row_align; + u8 bl_status; +}; + + +struct lcd_interface { + void (*init)(void *); + void (*get_screen_info)(struct lcd_info *info); + void (*buffer_malloc)(u8 **buf, u32 *size); + void (*buffer_free)(u8 *buf); + void (*draw)(u8 *buf, u32 len, u8 wait); + void (*set_draw_area)(u16 xs, u16 xe, u16 ys, u16 ye); + void (*clear_screen)(u16 color); + int (*backlight_ctrl)(u8 on); + void (*draw_page)(u8 *buf, u8 page_star, u8 page_len); +}; + +extern struct lcd_interface lcd_interface_begin[]; +extern struct lcd_interface lcd_interface_end[]; + +#define REGISTER_LCD_INTERFACE(lcd) \ + static const struct lcd_interface lcd sec(.lcd_if_info) __attribute__((used)) + +struct lcd_interface *lcd_get_hdl(); + +#define LCD_SPI_PLATFORM_DATA_BEGIN(data) \ + const struct lcd_spi_platform_data data = { + +#define LCD_SPI__PLATFORM_DATA_END() \ +}; + + +void lcd_reset_l(); +void lcd_reset_h(); +void lcd_cs_l(); +void lcd_cs_h(); +void lcd_rs_l(); +void lcd_rs_h(); +void lcd_bl_l(); +void lcd_bl_h(); +u8 lcd_bl_io(); + +extern int lcd_backlight_status(); +u8 lcd_spi_recv_byte(); +int lcd_spi_send_byte(u8 byte); + +#endif + + diff --git a/apps/soundbox/include/ui/led7/led7_driver.h b/apps/soundbox/include/ui/led7/led7_driver.h new file mode 100644 index 0000000..6edfb97 --- /dev/null +++ b/apps/soundbox/include/ui/led7/led7_driver.h @@ -0,0 +1,143 @@ +#ifndef _LED7_DRV_H_ +#define _LED7_DRV_H_ + + +typedef struct _led7_VAR { + u8 bCoordinateX; + u8 bFlashChar; + u8 bShowBuff[4]; //[0] ~ [3]显示的数字/字母显示的所有段 + u32 bShowIcon; //每1bit对应LED4的1段, maybe icon > 7段 + u32 bFlashIcon; //闪烁标志 + u8 bShowBuff1[9]; //[i]->第i个管脚, value的每一bit对应一个管脚, scan时使用 +} LED7_VAR; + +#define LED7_PLAY BIT(0) //0: 播放图标 +#define LED7_PAUSE BIT(1) //1: 暂停图标 +#define LED7_USB BIT(2) //2: USB图标 +#define LED7_SD BIT(3) //3: SD图标 +#define LED7_2POINT BIT(4) //4: 冒号图标 +#define LED7_FM BIT(5) //5: FM图标 +#define LED7_DOT BIT(6) //6: 小数点图标 +#define LED7_MP3 BIT(7) //7: MP3图标 +#define LED7_REPEAT BIT(8) //8: REPEAT图标 +#define LED7_CHARGE BIT(9) //9: 充电图标 +#define LED7_BT BIT(10) //10: 充电图标 +#define LED7_AUX BIT(11) //11: AUX图标 +#define LED7_WMA BIT(12) //12: WMA图标 + +typedef u32 UI_LED7_ICON; + +typedef enum _led7_pin_type { + LED7_PIN7, //7个引脚 + LED7_PIN12, //12个引脚 + LED7_PIN13, //13个引脚 +} LED7_PIN_TYPE; + +struct seg2pin { + u8 pinH; + u8 pinL; +}; + +struct icon_seg2pin { + UI_LED7_ICON icon; + struct seg2pin seg2pin; +}; + +struct led7_pin7 { + u8 pin[7]; +}; + +struct led7_pin12 { + u8 pin_comh[5]; + u8 pin_segl[7]; +}; + +struct led7_pin13 { + u8 pin_com[6]; + u8 pin_seg[7]; +}; + + +union led7_pin_cfg { + struct led7_pin7 pin7; + struct led7_pin12 pin12; + struct led7_pin13 pin13; +}; + +#define LED_A BIT(0) +#define LED_B BIT(1) +#define LED_C BIT(2) +#define LED_D BIT(3) +#define LED_E BIT(4) +#define LED_F BIT(5) +#define LED_G BIT(6) +#define LED_H BIT(7) + + +struct led7_platform_data { + LED7_PIN_TYPE pin_type; + union led7_pin_cfg pin_cfg; +}; + +#define LED7_PLATFORM_DATA_BEGIN(data) \ + const struct led7_platform_data data = { + +#define LED7_PLATFORM_DATA_END() \ +}; + +//UI LED7 API: +//=================================================================================// +// 模块初始化显示接口 // +//=================================================================================// +void *led7_init(const struct led7_platform_data *_data); +const struct ui_display_api *ui_led7_init(void *para); + +//=================================================================================// +// 设置显示坐标接口 // +/* + ___ ___ ___ ___ + |___| |___| |___| |___| + |___| |___| |___| |___| + ---0------1------2------3------> X +*/ +//=================================================================================// +void led7_setX(u8 X); + +//=================================================================================// +// 字符类显示接口 // +//=================================================================================// +void led7_show_char(u8 chardata); //显示字符(追加方式) +void led7_flash_char_start(u8 index); //闪烁单个字符 +void led7_flash_char_stop(u8 index); //取消闪烁单个字符 +void led7_show_string(u8 *str); //显示字符串(追加方式) +void led7_show_string_reset_x(u8 *str); //显示字符串, x从0开始 +void led7_show_string_align_right(u8 *str); //led7显示字符串(清屏&右方式) +void led7_show_string_align_left(u8 *str); //led7显示字符串(清屏&左方式) + +//=================================================================================// +// 数字类显示接口 // +//=================================================================================// +void led7_show_number(u16 val); //显示数字(清屏&高位显示0) +void led7_show_number2(u16 val); //显示数字(清屏&高位不显示) +void led7_show_number_add(u16 val); //显示数字(追加方式) + +//=================================================================================// +// 图标类显示接口 // +//=================================================================================// +void led7_show_icon(UI_LED7_ICON icon); //显示单个图标(追加) +void led7_flash_icon(UI_LED7_ICON icon); //闪烁单个图标(追加) + +//=================================================================================// +// 模式类类显示接口 // +//=================================================================================// + +//=================================================================================// +// 清屏类显示接口 // +//=================================================================================// +void led7_show_null(void); //清除所有显示(数字,字符串和图标) +void led7_clear_string(void); //清除显示数字和字母 +void led7_clear_icon(UI_LED7_ICON icon); //清除显示单个图标 +void led7_clear_all_icon(void); //清除显示所有图标 + + +#endif /* _LED_H_ */ diff --git a/apps/soundbox/include/ui/res_config.h b/apps/soundbox/include/ui/res_config.h new file mode 100644 index 0000000..422477b --- /dev/null +++ b/apps/soundbox/include/ui/res_config.h @@ -0,0 +1,26 @@ +#ifndef __RES_CONFIG_H__ +#define __RES_CONFIG_H__ + + +#define EXTERN_PATH "storage/virfat_flash/C/" +#define INTERN_PATH "mnt/sdfile/res/" +#define RES_PATH INTERN_PATH + +#define FONT_PATH RES_PATH + + +#define UI_STY_CHECK_PATH \ + RES_PATH"JL.sty", + +#define UI_RES_CHECK_PATH \ + RES_PATH"JL.res", + +#define UI_STR_CHECK_PATH \ + RES_PATH"JL.str", + + + +#define UI_WATCH_RES_ENABLE 0//表盘功能 + + +#endif diff --git a/apps/soundbox/include/ui/style_led7.h b/apps/soundbox/include/ui/style_led7.h new file mode 100644 index 0000000..b8516b2 --- /dev/null +++ b/apps/soundbox/include/ui/style_led7.h @@ -0,0 +1,130 @@ +#ifndef UI_STYLE_LED7_H +#define UI_STYLE_LED7_H + +#include "ui/ui_common.h" +#include "ui/led7/led7_driver.h" +#include "ui/lcd_seg/lcd_seg3x9_driver.h" + + + +enum ui_menu_main { + UI_MENU_MAIN_NULL = 0, + UI_RTC_MENU_MAIN, + UI_MUSIC_MENU_MAIN, + UI_AUX_MENU_MAIN, + UI_BT_MENU_MAIN, + UI_RECORD_MENU_MAIN, + UI_FM_MENU_MAIN, + UI_PC_MENU_MAIN, + UI_IDLE_MENU_MAIN, +}; + + + + + +enum { + + MENU_POWER_UP = 1, + MENU_WAIT, + MENU_BT, + MENU_PC, + MENU_PC_VOL_UP, + MENU_PC_VOL_DOWN, + MENU_AUX, + MENU_ALM_UP, + + MENU_SHOW_STRING, + MENU_MAIN_VOL, + MENU_SET_EQ, + MENU_SET_PLAY_MODE, + + MENU_PLAY_TIME, + MENU_FILENUM, + MENU_INPUT_NUMBER, + MENU_MUSIC_PAUSE, + MENU_MUSIC_REPEATMODE, + + MENU_FM_MAIN, + MENU_FM_DISP_FRE, + MENU_FM_SET_FRE, + MENU_FM_STATION, + MENU_IR_FM_SET_FRE, + + MENU_RTC_SET, + MENU_RTC_PWD, + MENU_ALM_SET, + + MENU_BT_SEARCH_DEVICE, + MENU_BT_CONNECT_DEVICE, + MENU_BT_DEVICE_ADD, + MENU_BT_DEVICE_NAME, + MENU_RECODE_MAIN, + MENU_RECODE_ERR, + MENU_POWER, + MENU_LIST_DISPLAY, + + + MENU_LED0, + MENU_LED1, + + + MENU_RECORD, + + MENU_SEC_REFRESH = 0x80, + MENU_REFRESH, + MENU_MAIN = 0xff, +}; + + + + + + + +//=================================================================================// +// UI 配置数据结构 // +//=================================================================================// +struct ui_dis_api { + int ui; + void *(*open)(void *hd); + void (*ui_main)(void *hd, void *private); + int (*ui_user)(void *hd, void *private, int menu, int arg); + void (*close)(void *hd, void *private); +}; + + + +typedef struct _LCD_DISP_API { + void (*clear)(void); + void (*setXY)(u32 x, u32 y); + void (*FlashChar)(u32); + void (*Clear_FlashChar)(u32); + void (*show_string)(u8 *); + void (*show_char)(u8); + void (*show_number)(u8); + void (*show_icon)(u32); + void (*flash_icon)(u32); + void (*clear_icon)(u32); + void (*show_pic)(u32); + void (*hide_pic)(u32); + void (*lock)(u32); +} LCD_API; + + + +extern const struct ui_dis_api bt_main; +extern const struct ui_dis_api fm_main; +extern const struct ui_dis_api music_main; +extern const struct ui_dis_api record_main; +extern const struct ui_dis_api rtc_main; +extern const struct ui_dis_api pc_main; +extern const struct ui_dis_api linein_main; +extern const struct ui_dis_api idle_main; + + + + +#endif + + diff --git a/apps/soundbox/include/ui/ui_api.h b/apps/soundbox/include/ui/ui_api.h new file mode 100644 index 0000000..b2b69e0 --- /dev/null +++ b/apps/soundbox/include/ui/ui_api.h @@ -0,0 +1,131 @@ +#ifndef _UI_API_H_ +#define _UI_API_H_ + +#include "app_config.h" +#include "ui/lcd_spi/lcd_drive.h" +#include "ui/ui.h" +#include "ui/ui_style.h" + +#define GRT_CUR_MENU (0) +#define GET_MAIN_MENU (1) + + +enum ui_devices_type { + LED_7, + LCD_SEG3X9, + TFT_LCD,//彩屏 + DOT_LCD,//点阵屏 +}; + +//板级配置数据结构 +struct ui_devices_cfg { + enum ui_devices_type type; + void *private_data; +}; + + +struct touch_event { + int event; + int x; + int y; +}; + + +//led7 api +extern int led7_ui_init(const struct ui_devices_cfg *ui_cfg); +extern void ui_set_main_menu(enum ui_menu_main menu); +extern void ui_menu_reflash(u8 break_in);//break_in 是否打断显示,例如显示设置过程中需要刷新新界面。是是否打断设置界面显示 +extern u8 ui_get_app_menu(u8); +extern void ui_set_led(u8 app_menu, u8 on, u8 phase, u16 highlight, u16 period); +extern void ui_set_auto_reflash(u32 msec);//自动刷新主页 +extern void ui_close_main_menu(); +extern void ui_set_tmp_menu(u8 app_menu, u16 ret_time, s32 arg, void (*timeout_cb)(u8 menu)); +extern void ui_common(void *hd, void *private, u8 menu, u32 arg);//公共显示 + + +//lcd api +// +extern int lcd_ui_init(void *arg); +extern int ui_hide_main(int id); +extern int ui_show_main(int id); + +extern int ui_server_msg_post(const char *msg, ...); +extern int ui_hide_curr_main(); +extern int ui_touch_msg_post(struct touch_event *event); +extern int ui_key_msg_post(int msg); +extern void key_ui_takeover(u8 on); +extern int key_is_ui_takeover(); +extern void ui_backlight_open(void); +extern void ui_backlight_close(void); + +extern void ui_touch_timer_delete(); +extern void ui_touch_timer_start(); +extern void ui_auto_shut_down_modify(void); +extern void ui_auto_shut_down_enable(void); +extern void ui_auto_shut_down_disable(void); +extern int ui_simple_key_msg_post(int, int); + + + + + +//=================================================================================// +// UI API // +//=================================================================================// +#if (TCFG_UI_ENABLE) +#if(CONFIG_UI_STYLE == STYLE_JL_LED7)//led7 显示 +#define UI_INIT(a) led7_ui_init(a) +#define UI_SHOW_WINDOW(a) ui_set_main_menu(a) +#define UI_HIDE_WINDOW(...) ui_close_main_menu() +#define UI_HIDE_CURR_WINDOW() ui_close_main_menu() +#define UI_GET_WINDOW_ID() ui_get_app_menu(GET_MAIN_MENU) +#define UI_GET_CURR_MENU() ui_get_app_menu(GRT_CUR_MENU) +#define UI_REFLASH_WINDOW(a) ui_menu_reflash(a) +#define UI_SHOW_MENU ui_set_tmp_menu +#define UI_MSG_POST(...) +#define UI_KEY_MSG_POST(...) + + +#elif(CONFIG_UI_STYLE == STYLE_UI_SIMPLE)//去框架显示显示 + +#define UI_INIT(a) lcd_ui_init(a) +#define UI_SHOW_WINDOW(...) +#define UI_HIDE_WINDOW(...) +#define UI_GET_WINDOW_ID() (0) +#define UI_HIDE_CURR_WINDOW() +#define UI_SHOW_MENU(...) +#define UI_MSG_POST(...) +#define UI_REFLASH_WINDOW(a) +#define UI_KEY_MSG_POST(a) + +#else + +#define UI_INIT(a) lcd_ui_init(a) +#define UI_SHOW_WINDOW(a) ui_show_main(a) +#define UI_HIDE_WINDOW(a) ui_hide_main(a) +#define UI_HIDE_CURR_WINDOW() ui_hide_curr_main() +#define UI_GET_WINDOW_ID() ui_get_current_window_id() +#define UI_MSG_POST ui_server_msg_post +#define UI_SHOW_MENU(...) +#define UI_GET_CURR_MENU() +#define UI_REFLASH_WINDOW(a) +#define UI_KEY_MSG_POST(a) ui_key_msg_post + + +#endif//if(CONFIG_UI_STYLE == STYLE_JL_LED7) + +#else + +//common api lcd屏和led7 通用api +#define UI_INIT(...) +#define UI_SHOW_WINDOW(...) +#define UI_HIDE_WINDOW(...) +#define UI_GET_WINDOW_ID() +#define UI_HIDE_CURR_WINDOW() +#define UI_SHOW_MENU(...) +#define UI_MSG_POST(...) +#define UI_REFLASH_WINDOW(a) +#define UI_KEY_MSG_POST(...) +#endif /* #if TCFG_UI_ENABLE */ + +#endif diff --git a/apps/soundbox/include/ui/ui_common.h b/apps/soundbox/include/ui/ui_common.h new file mode 100644 index 0000000..0308088 --- /dev/null +++ b/apps/soundbox/include/ui/ui_common.h @@ -0,0 +1,15 @@ +#ifndef _UI_COMMON_H_ +#define _UI_COMMON_H_ + +#include "typedef.h" +/* =================== 十进制数值(1位)转ASCII值 =================== */ +void itoa1(u8 i, u8 *buf); +/* =================== 十进制数值(2位)转ASCII值 =================== */ +void itoa2(u8 i, u8 *buf); +/* =================== 十进制数值(3位)转ASCII值 =================== */ +void itoa3(u16 i, u8 *buf); +/* =================== 十进制数值(4位)转ASCII值 =================== */ +void itoa4(u16 i, u8 *buf); + + +#endif diff --git a/apps/soundbox/include/ui/ui_style.h b/apps/soundbox/include/ui/ui_style.h new file mode 100644 index 0000000..cabadc4 --- /dev/null +++ b/apps/soundbox/include/ui/ui_style.h @@ -0,0 +1,72 @@ +#ifndef UI_STYLE_H +#define UI_STYLE_H + +#include "ui/style_led7.h"//led7 + + + +#if(CONFIG_UI_STYLE == STYLE_JL_WTACH) +#include "ui/style_jl01.h"//彩屏// +#define ID_WINDOW_MAIN PAGE_3 +#define ID_WINDOW_BT PAGE_0 +#define ID_WINDOW_MUSIC PAGE_1 +#define ID_WINDOW_LINEIN PAGE_1 +// #define ID_WINDOW_FM PAGE_2 +#define ID_WINDOW_CLOCK PAGE_0 +// #define ID_WINDOW_BT_MENU PAGE_3 +#define ID_WINDOW_POWER_ON PAGE_4 +#define ID_WINDOW_POWER_OFF PAGE_5 +#define CONFIG_UI_STYLE_JL_ENABLE +#endif + + + +#if(CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX) +#include "ui/style_jl02.h"//点阵// +#define ID_WINDOW_MAIN PAGE_0 +#define ID_WINDOW_BT PAGE_1 +#define ID_WINDOW_FM PAGE_2 +#define ID_WINDOW_CLOCK PAGE_3 +#define ID_WINDOW_MUSIC PAGE_4 +#define ID_WINDOW_LINEIN PAGE_9 +#define ID_WINDOW_POWER_ON PAGE_5 +#define ID_WINDOW_POWER_OFF PAGE_6 +#define ID_WINDOW_SYS PAGE_7 +#define ID_WINDOW_PC PAGE_8 +#define ID_WINDOW_IDLE (-1) +#define ID_WINDOW_REC PAGE_10 +#endif + + + +#if(CONFIG_UI_STYLE == STYLE_JL_LED7)//led7 显示 +#define ID_WINDOW_BT UI_BT_MENU_MAIN +#define ID_WINDOW_FM UI_FM_MENU_MAIN +#define ID_WINDOW_CLOCK UI_RTC_MENU_MAIN +#define ID_WINDOW_MUSIC UI_MUSIC_MENU_MAIN +#define ID_WINDOW_LINEIN UI_AUX_MENU_MAIN +#define ID_WINDOW_PC UI_PC_MENU_MAIN +#define ID_WINDOW_REC UI_RECORD_MENU_MAIN +#define ID_WINDOW_POWER_ON UI_IDLE_MENU_MAIN +#define ID_WINDOW_POWER_OFF UI_IDLE_MENU_MAIN +#define ID_WINDOW_SPDIF UI_IDLE_MENU_MAIN +#define ID_WINDOW_IDLE UI_IDLE_MENU_MAIN +#endif + +#if(CONFIG_UI_STYLE == STYLE_UI_SIMPLE)//lcd 去架构 +#define ID_WINDOW_BT (0) +#define ID_WINDOW_FM (0) +#define ID_WINDOW_CLOCK (0) +#define ID_WINDOW_MUSIC (0) +#define ID_WINDOW_LINEIN (0) +#define ID_WINDOW_PC (0) +#define ID_WINDOW_REC (0) +#define ID_WINDOW_POWER_ON (0) +#define ID_WINDOW_POWER_OFF (0) +#define ID_WINDOW_SPDIF (0) +#define ID_WINDOW_IDLE (0) +#endif + + + +#endif diff --git a/apps/soundbox/include/ui/ui_sys_param.h b/apps/soundbox/include/ui/ui_sys_param.h new file mode 100644 index 0000000..fab0cd5 --- /dev/null +++ b/apps/soundbox/include/ui/ui_sys_param.h @@ -0,0 +1,24 @@ +#ifndef _UI_SYS_PARAM__H_ +#define _UI_SYS_PARAM__H_ + + +void set_sys_param_default(void); + +void sys_param_write2vm(void); + +void sys_param_init(void); + +void set_backlight_time(u16 time); + +u16 get_backlight_time(void); + +void set_backlight_brightness(u16 brightness); + +u16 get_backlight_brightness(void); +u16 get_backlight_brightness_item(void); + + + + +#endif + diff --git a/apps/soundbox/include/ui_manage.h b/apps/soundbox/include/ui_manage.h new file mode 100644 index 0000000..b2b61d3 --- /dev/null +++ b/apps/soundbox/include/ui_manage.h @@ -0,0 +1,77 @@ +#ifndef __UI_MANAGE_H_ +#define __UI_MANAGE_H_ + +#include "typedef.h" +#include "asm/pwm_led.h" + +typedef enum { + STATUS_NULL = 0, + STATUS_POWERON, + STATUS_POWEROFF, + STATUS_POWERON_LOWPOWER, + STATUS_BT_INIT_OK, + STATUS_BT_CONN, + STATUS_BT_SLAVE_CONN_MASTER, + STATUS_BT_MASTER_CONN_ONE, + STATUS_BT_DISCONN, + STATUS_BT_TWS_CONN, + STATUS_BT_TWS_DISCONN, + STATUS_PHONE_INCOME, + STATUS_PHONE_OUT, + STATUS_PHONE_ACTIV, + STATUS_CHARGE_START, + STATUS_CHARGE_FULL, + STATUS_CHARGE_CLOSE, + STATUS_CHARGE_ERR, + STATUS_LOWPOWER, + STATUS_CHARGE_LDO5V_OFF, + STATUS_EXIT_LOWPOWER, + STATUS_NORMAL_POWER, + STATUS_POWER_NULL, + + STATUS_MUSIC_MODE, + STATUS_MUSIC_PLAY, + STATUS_MUSIC_PAUSE, + STATUS_LINEIN_MODE, + STATUS_LINEIN_PLAY, + STATUS_LINEIN_PAUSE, + STATUS_PC_MODE, + STATUS_PC_PLAY, + STATUS_PC_PAUSE, + STATUS_FM_MODE, + STATUS_RECORD_MODE, + STATUS_SPDIF_MODE, + STATUS_RTC_MODE, + STATUS_DEMO_MODE, + +} UI_STATUS; + +typedef struct __LED_REMAP_STATUS { + u8 charge_start; //开始充电 + u8 charge_full; //充电完成 + u8 power_on; //开机 + u8 power_off; //关机 + u8 lowpower; //低电 + u8 max_vol; //最大音量 + u8 phone_in; //来电 + u8 phone_out; //去电 + u8 phone_activ; //通话中 + u8 bt_init_ok; //蓝牙初始化完成 + u8 bt_connect_ok; //蓝牙连接成功 + u8 bt_disconnect; //蓝牙断开 + u8 tws_connect_ok; //蓝牙连接成功 + u8 tws_disconnect; //蓝牙断开 + u8 music_play; //音乐模式播放音乐 + u8 music_pause; //音乐模式停止播放 + u8 linein_play; //Linein模式播放音乐 + u8 linein_mute; //Linein模式静音 +} _GNU_PACKED_ LED_REMAP_STATUS; + + +void ui_pwm_led_init(const struct led_platform_data *user_data); +int ui_manage_init(void); +void ui_update_status(u8 status); +u8 get_ui_busy_status(); +void *led_get_remap_t(void); + +#endif diff --git a/apps/soundbox/include/user_api/app_status_api.h b/apps/soundbox/include/user_api/app_status_api.h new file mode 100644 index 0000000..5c7101b --- /dev/null +++ b/apps/soundbox/include/user_api/app_status_api.h @@ -0,0 +1,36 @@ +#ifndef _APP_STATUS_API_H +#define _APP_STATUS_API_H + +#include "btstack/avctp_user.h" +enum APP_STATUS { //此枚举可自行添加状态 + APP_STATUS_POWER_ON, + APP_STATUS_POWER_OFF, + APP_STATUS_POWER_CLOSE, + APP_STATUS_IDLE, + APP_STATUS_BT_SECOND_CONNECTED, + APP_STATUS_BT_FIRST_CONNECTED, + APP_STATUS_BT_FIRST_DISCONNECT, + APP_STATUS_BT_SECOND_DISCONNECT, + APP_STATUS_BT_PHONE_INCOME, + APP_STATUS_BT_PHONE_OUT, + APP_STATUS_BT_PHONE_ACTIVE, + APP_STATUS_BT_PHONE_HANGUP, + APP_STATUS_BT_PHONE_NUMBER, + APP_STATUS_BT_SCO_STATUS_CHANGE, + APP_STATUS_BT_VOICE_RECOGNITION, + APP_STATUS_BT_A2DP_MEDIA_START, + APP_STATUS_BT_INIT_OK, + APP_STATUS_BT_A2DP_MEDIA_STOP, + APP_STATUS_MUSIC, + APP_STATUS_MUSIC_QUIT, + APP_STATUS_MUSIC_PLAY, + APP_STATUS_MUSIC_PP, + APP_STATUS_MUSIC_PN, + APP_STATUS_MUSIC_FFR, + APP_STATUS_PC, + APP_STATUS_PC_COPY, +}; + + +void app_status_handler(enum APP_STATUS status); +#endif diff --git a/apps/soundbox/include/user_api/dev_multiplex_api.h b/apps/soundbox/include/user_api/dev_multiplex_api.h new file mode 100644 index 0000000..c0de44b --- /dev/null +++ b/apps/soundbox/include/user_api/dev_multiplex_api.h @@ -0,0 +1,24 @@ +#ifndef __DEV_MULTIPLEX_API_H__ +#define __DEV_MULTIPLEX_API_H__ + +#include "generic/typedef.h" +#include "app_config.h" +#include "usb/host/usb_host.h" + +extern usb_dev g_usb_id; + +void mult_sdio_resume(); +int mult_sdio_suspend(); +int dev_sd_change_usb(); +int dev_usb_change_sd(); +int mult_sd_online_mount_before(int sd_dev, usb_dev usb_id); +int mult_sd_offline_before(void *logo, usb_dev usb_id); +int mult_sd_online_mount_after(int sd_dev, usb_dev usb_id, int err); +int mult_usb_online_mount_after(usb_dev usb_id, int err); +int mult_usb_mount_before(usb_dev usb_id); +int mult_usb_mount_offline(usb_dev usb_id); +void pc_dm_multiplex_init(); +void pc_dm_multiplex_exit(); + + +#endif//__DEV_MULTIPLEX_API_H__ diff --git a/apps/soundbox/include/user_api/product_info_api.h b/apps/soundbox/include/user_api/product_info_api.h new file mode 100644 index 0000000..b90fe25 --- /dev/null +++ b/apps/soundbox/include/user_api/product_info_api.h @@ -0,0 +1,9 @@ +#ifndef __PRODUCT_INFO_API_H__ +#define __PRODUCT_INFO_API_H__ + +#include "generic/typedef.h" +#include "app_config.h" + +int product_info_prase(u8 *buf, u16 len); + +#endif//__PRODUCT_INFO_API_H__ diff --git a/apps/soundbox/include/user_cfg_id.h b/apps/soundbox/include/user_cfg_id.h new file mode 100644 index 0000000..ac94ab5 --- /dev/null +++ b/apps/soundbox/include/user_cfg_id.h @@ -0,0 +1,126 @@ +#ifndef _USER_CFG_ID_H_ +#define _USER_CFG_ID_H_ + +//=================================================================================// +// 与APP CASE相关配置项[1 ~ 60] // +//=================================================================================// +#define VM_FM_EMITTER_FREQ 1 +// #define VM_FM_EMITTER_DIG_VOL 2 +// #define VM_MUSIC_LAST_DEV 3 +// #define VM_WAKEUP_PND 4 +#define VM_USB_MIC_GAIN 5 +#define VM_ALARM_0 6 +#define VM_ALARM_1 7 +#define VM_ALARM_2 8 +#define VM_ALARM_3 9 +#define VM_ALARM_4 10 +#define VM_ALARM_MASK 11 +#define VM_ALARM_NAME_0 12 +#define VM_ALARM_NAME_1 13 +#define VM_ALARM_NAME_2 14 +#define VM_ALARM_NAME_3 15 +#define VM_ALARM_NAME_4 16 +#define VM_FM_INFO 17 +// #define VM_RTC_TRIM 18 + +#define CFG_RCSP_ADV_HIGH_LOW_VOL 19 +#define CFG_RCSP_ADV_EQ_MODE_SETTING 20 +#define CFG_RCSP_ADV_EQ_DATA_SETTING 21 +#define ADV_SEQ_RAND 22 +#define CFG_RCSP_ADV_TIME_STAMP 23 +#define CFG_RCSP_ADV_WORK_SETTING 24 +#define CFG_RCSP_ADV_MIC_SETTING 25 +#define CFG_RCSP_ADV_LED_SETTING 26 +#define CFG_RCSP_ADV_KEY_SETTING 27 +#define CFG_RCSP_MISC_DRC_SETTING 28 +#define CFG_RCSP_MISC_REVERB_ON_OFF 29 +#define VM_ALARM_RING_NAME_0 30 +#define VM_ALARM_RING_NAME_1 31 +#define VM_ALARM_RING_NAME_2 32 +#define VM_ALARM_RING_NAME_3 33 +#define VM_ALARM_RING_NAME_4 34 +#define VM_COLOR_LED_SETTING 35 +#define VM_KARAOKE_EQ_SETTING 36 + +// #define CFG_FLASH_BREAKPOINT 29 +// #define CFG_USB_BREAKPOINT 30 +// #define CFG_SD0_BREAKPOINT 31 +// #define CFG_SD1_BREAKPOINT 32 +// #define CFG_MUSIC_DEVICE 33 +// #define CFG_FM_RECEIVER_INFO 34 +// #define CFG_FM_TRANSMIT_INFO 35 +// #define CFG_AAP_MODE_INFO 36 +#define CFG_UI_SYS_INFO 37 +// +// +// +#define VM_TWS_ROLE 38 + +#if (VM_ITEM_MAX_NUM > 128) + +#define CFG_FLASH_BREAKPOINT0 128 +#define CFG_FLASH_BREAKPOINT1 129 +#define CFG_FLASH_BREAKPOINT2 130 +#define CFG_FLASH_BREAKPOINT3 131 +#define CFG_FLASH_BREAKPOINT4 132 +#define CFG_FLASH_BREAKPOINT5 133 +#define CFG_FLASH_BREAKPOINT6 134 +#define CFG_FLASH_BREAKPOINT7 135 +#define CFG_FLASH_BREAKPOINT8 136 +#define CFG_FLASH_BREAKPOINT9 137 +#define CFG_USB_BREAKPOINT0 138 +#define CFG_USB_BREAKPOINT1 139 +#define CFG_USB_BREAKPOINT2 140 +#define CFG_USB_BREAKPOINT3 141 +#define CFG_USB_BREAKPOINT4 142 +#define CFG_USB_BREAKPOINT5 143 +#define CFG_USB_BREAKPOINT6 144 +#define CFG_USB_BREAKPOINT7 145 +#define CFG_USB_BREAKPOINT8 146 +#define CFG_USB_BREAKPOINT9 147 +#define CFG_SD0_BREAKPOINT0 148 +#define CFG_SD0_BREAKPOINT1 149 +#define CFG_SD0_BREAKPOINT2 150 +#define CFG_SD0_BREAKPOINT3 151 +#define CFG_SD0_BREAKPOINT4 152 +#define CFG_SD0_BREAKPOINT5 153 +#define CFG_SD0_BREAKPOINT6 154 +#define CFG_SD0_BREAKPOINT7 155 +#define CFG_SD0_BREAKPOINT8 156 +#define CFG_SD0_BREAKPOINT9 157 +#define CFG_SD1_BREAKPOINT0 158 +#define CFG_SD1_BREAKPOINT1 159 +#define CFG_SD1_BREAKPOINT2 160 +#define CFG_SD1_BREAKPOINT3 161 +#define CFG_SD1_BREAKPOINT4 162 +#define CFG_SD1_BREAKPOINT5 163 +#define CFG_SD1_BREAKPOINT6 164 +#define CFG_SD1_BREAKPOINT7 165 +#define CFG_SD1_BREAKPOINT8 166 +#define CFG_SD1_BREAKPOINT9 167 +#define CFG_CHGBOX_ADDR 168 +#define CFG_REMOTE_DN_00 169 +#define CFG_REMOTE_DN_01 170 +#define CFG_REMOTE_DN_02 171 +#define CFG_REMOTE_DN_03 172 +#define CFG_REMOTE_DN_04 173 +#define CFG_REMOTE_DN_05 174 +#define CFG_REMOTE_DN_06 175 +#define CFG_REMOTE_DN_07 176 +#define CFG_REMOTE_DN_08 177 +#define CFG_REMOTE_DN_09 178 +#define CFG_REMOTE_DN_10 179 +#define CFG_REMOTE_DN_11 180 +#define CFG_REMOTE_DN_12 181 +#define CFG_REMOTE_DN_13 182 +#define CFG_REMOTE_DN_14 183 +#define CFG_REMOTE_DN_15 184 +#define CFG_REMOTE_DN_16 185 +#define CFG_REMOTE_DN_17 186 +#define CFG_REMOTE_DN_18 187 +#define CFG_REMOTE_DN_19 188 +#define CFG_MUSIC_MODE 189 + +#endif//(VM_ITEM_MAX_NUM > 128) + +#endif /* #ifndef _USER_CFG_ID_H_ */ diff --git a/apps/soundbox/log_config/app_config.c b/apps/soundbox/log_config/app_config.c new file mode 100644 index 0000000..053905e --- /dev/null +++ b/apps/soundbox/log_config/app_config.c @@ -0,0 +1,200 @@ +/********************************************************************************************* + * Filename : log_config.c + + * Description : Optimized Code & RAM (编译优化Log配置) + + * Author : Bingquan + + * Email : caibingquan@zh-jieli.com + + * Last modifiled : 2019-03-18 14:45 + + * Copyright:(c)JIELI 2011-2019 @ , All Rights Reserved. +*********************************************************************************************/ +#include "system/includes.h" + +/** + * @brief Bluetooth Controller Log + */ +/*-----------------------------------------------------------*/ +const char log_tag_const_v_SETUP AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_SETUP AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_SETUP AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_d_SETUP AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_SETUP AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_BOARD AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_BOARD AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_BOARD AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_w_BOARD AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_BOARD AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_BT AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_BT AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_BT AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_w_BT AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_BT AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_UI AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_UI AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_UI AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_UI AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_UI AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_COLOR_LED AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_COLOR_LED AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_COLOR_LED AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_COLOR_LED AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_COLOR_LED AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_CHARGE AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_CHARGE AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_CHARGE AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_CHARGE AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_CHARGE AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_KEY_EVENT_DEAL AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_KEY_EVENT_DEAL AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_KEY_EVENT_DEAL AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_KEY_EVENT_DEAL AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_KEY_EVENT_DEAL AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_CHARGESTORE AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_CHARGESTORE AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_CHARGESTORE AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_CHARGESTORE AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_CHARGESTORE AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_SOUNDBOX_TOOL AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_SOUNDBOX_TOOL AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_SOUNDBOX_TOOL AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_SOUNDBOX_TOOL AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_SOUNDBOX_TOOL AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_IDLE AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_IDLE AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_IDLE AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_IDLE AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_IDLE AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_POWER AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_POWER AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_POWER AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_POWER AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_POWER AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_USER_CFG AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_USER_CFG AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_USER_CFG AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_USER_CFG AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_USER_CFG AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_TONE AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_TONE AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_TONE AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_TONE AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_TONE AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_BT_TWS AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_BT_TWS AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_BT_TWS AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_BT_TWS AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_BT_TWS AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_AEC_USER AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_AEC_USER AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_AEC_USER AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_AEC_USER AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_AEC_USER AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_BT_BLE AT(.LOG_TAG_CONST) = 0; +const char log_tag_const_i_BT_BLE AT(.LOG_TAG_CONST) = 0; +const char log_tag_const_d_BT_BLE AT(.LOG_TAG_CONST) = 1; +const char log_tag_const_w_BT_BLE AT(.LOG_TAG_CONST) = 1; +const char log_tag_const_e_BT_BLE AT(.LOG_TAG_CONST) = 1; + +const char log_tag_const_v_APP_ACTION AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_ACTION AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_ACTION AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_ACTION AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_ACTION AT(.LOG_TAG_CONST) = TRUE; + + +const char log_tag_const_v_APP_STORAGE_DEV AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_STORAGE_DEV AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_STORAGE_DEV AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_STORAGE_DEV AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_STORAGE_DEV AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_FILE_OPERATE AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_FILE_OPERATE AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_FILE_OPERATE AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_FILE_OPERATE AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_FILE_OPERATE AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_MUSIC AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_MUSIC AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_MUSIC AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_MUSIC AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_MUSIC AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_LINEIN AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_LINEIN AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_LINEIN AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_LINEIN AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_LINEIN AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_FM AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_FM AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_FM AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_FM AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_FM AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_FM_EMITTER AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_FM_EMITTER AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_FM_EMITTER AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_FM_EMITTER AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_FM_EMITTER AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_PC AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_PC AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_PC AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_w_APP_PC AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_PC AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_RTC AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_i_APP_RTC AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_RTC AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_w_APP_RTC AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_RTC AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_RECORD AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_RECORD AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_RECORD AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_RECORD AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_RECORD AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_BOX AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_BOX AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_BOX AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_BOX AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_BOX AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_APP_CHGBOX AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_i_APP_CHGBOX AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_d_APP_CHGBOX AT(.LOG_TAG_CONST) = FALSE; +const char log_tag_const_w_APP_CHGBOX AT(.LOG_TAG_CONST) = TRUE; +const char log_tag_const_e_APP_CHGBOX AT(.LOG_TAG_CONST) = TRUE; + +const char log_tag_const_v_ONLINE_DB AT(.LOG_TAG_CONST) = 0; +const char log_tag_const_i_ONLINE_DB AT(.LOG_TAG_CONST) = 0; +const char log_tag_const_d_ONLINE_DB AT(.LOG_TAG_CONST) = 0; +const char log_tag_const_w_ONLINE_DB AT(.LOG_TAG_CONST) = 0; +const char log_tag_const_e_ONLINE_DB AT(.LOG_TAG_CONST) = 1; + diff --git a/apps/soundbox/log_config/lib_btctrler_config.c b/apps/soundbox/log_config/lib_btctrler_config.c new file mode 100644 index 0000000..1a8af22 --- /dev/null +++ b/apps/soundbox/log_config/lib_btctrler_config.c @@ -0,0 +1,439 @@ +/********************************************************************************************* + * Filename : btctrler_config.c + + * Description : Optimized Code & RAM (编译优化配置) + + * Author : Bingquan + + * Email : caibingquan@zh-jieli.com + + * Last modifiled : 2019-03-16 11:49 + + * Copyright:(c)JIELI 2011-2019 @ , All Rights Reserved. +*********************************************************************************************/ +#include "app_config.h" +#include "system/includes.h" +#include "btcontroller_config.h" +#include "bt_common.h" + +/** + * @brief Bluetooth Module + */ + +#if TCFG_USER_TWS_ENABLE + +const int config_btctler_modules = (BT_MODULE_CLASSIC | BT_MODULE_LE); +const int config_btctler_le_tws = 1; +const int CONFIG_BTCTLER_TWS_ENABLE = 1; +const int CONFIG_TWS_AFH_ENABLE = 1; +const int CONFIG_TWS_POWER_BALANCE_ENABLE = 0; +const int CONFIG_LOW_LATENCY_ENABLE = 0; +const int ble_disable_wait_enable = 0; + +#else + +const int config_btctler_modules = 0 +#if (TCFG_USER_BT_CLASSIC_ENABLE) + | BT_MODULE_CLASSIC +#endif//TCFG_USER_BLE_ENABLE +#if (TCFG_USER_BLE_ENABLE) + | BT_MODULE_LE +#endif//TCFG_USER_BLE_ENABLE + ; + +const int config_btctler_le_tws = 0; +const int CONFIG_BTCTLER_TWS_ENABLE = 0; +const int CONFIG_TWS_AFH_ENABLE = 0; +const int CONFIG_LOW_LATENCY_ENABLE = 0; +const int ble_disable_wait_enable = 1; + +#endif + +const int CONFIG_TWS_SUPER_TIMEOUT = 4000; + +#if (CONFIG_BT_MODE != BT_NORMAL) +const int config_btctler_hci_standard = 1; +#else +const int config_btctler_hci_standard = 0; +#endif + +const int config_btctler_mode = CONFIG_BT_MODE; + +//固定使用正常发射功率的等级:0-使用不同模式的各自等级;1~10-固定发射功率等级 +const int config_force_bt_pwr_tab_using_normal_level = 0; +/*-----------------------------------------------------------*/ + +/** + * @brief Bluetooth Classic setting + */ +const u8 rx_fre_offset_adjust_enable = 1; + +const int config_bredr_fcc_fix_fre = 0; + +const int config_btctler_eir_version_info_len = 0; + +const int config_delete_link_key = 1; //配置是否连接失败返回PIN or Link Key Missing时删除linkKey + +#ifdef CONFIG_SOUNDBOX_FLASH_256K +const int CONFIG_TEST_DUT_CODE = 1; +const int CONFIG_TEST_FCC_CODE = 0; +const int CONFIG_TEST_DUT_ONLY_BOX_CODE = 0; +#else +const int CONFIG_TEST_DUT_CODE = 1; +const int CONFIG_TEST_FCC_CODE = 1; +const int CONFIG_TEST_DUT_ONLY_BOX_CODE = 0; +#endif + + +#ifdef CONFIG_SOUNDBOX_FLASH_256K +const int CONFIG_BREDR_INQUIRY = 0; +#else +const int CONFIG_BREDR_INQUIRY = 1; +#endif + +const int CONFIG_ESCO_MUX_RX_BULK_ENABLE = 0; +const int CONFIG_INQUIRY_PAGE_OFFSET_ADJUST = 0; + +const int CONFIG_LMP_NAME_REQ_ENABLE = 1; +const int CONFIG_LMP_PASSKEY_ENABLE = 1; +const int CONFIG_LMP_MASTER_ESCO_ENABLE = 1; + + +const int config_bt_function = BT_ENCTRY_TASK ; + + +#if ((AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) && (TCFG_BD_NUM == 2)) +const int config_btctler_bredr_master = 0; +#if USER_SUPPORT_DUAL_A2DP_SOURCE +const int config_btctler_dual_a2dp = 1; +#else +const int config_btctler_dual_a2dp = 0; +#endif +#else +///bredr 强制 做 maseter +const int config_btctler_bredr_master = 0; +const int config_btctler_dual_a2dp = 0; +#endif + +///afh maseter 使用app设置的map 通过USER_CTRL_AFH_CHANNEL 设置 +const int config_bredr_afh_user = 0; +/*-----------------------------------------------------------*/ + +/** + * @brief Bluetooth LE setting + */ + +#if (TCFG_USER_BLE_ENABLE) +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) +const int config_btctler_le_roles = (LE_ADV); +const uint64_t config_btctler_le_features = 0; +#elif (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_CLIENT) +const uint64_t config_btctler_le_features = LE_ENCRYPTION; +const int config_btctler_le_roles = (LE_SCAN | LE_INIT | LE_MASTER); + +#elif (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_MULTI) +const uint64_t config_btctler_le_features = LE_ENCRYPTION; +const int config_btctler_le_roles = (LE_ADV | LE_SLAVE) | (LE_SCAN | LE_INIT | LE_MASTER); + +#elif (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_TUYA_MULTI) +const uint64_t config_btctler_le_features = LE_ENCRYPTION; +const int config_btctler_le_roles = (LE_ADV | LE_SLAVE) | (LE_SCAN | LE_INIT | LE_MASTER); + +#else +const int config_btctler_le_roles = (LE_ADV | LE_SLAVE); +const uint64_t config_btctler_le_features = LE_ENCRYPTION; +#endif +#else +const int config_btctler_le_roles = 0; +const uint64_t config_btctler_le_features = 0; +#endif + +#if(TCFG_USER_TWS_ENABLE) + +#ifdef CONFIG_NEW_BREDR_ENABLE +const int config_btctler_le_hw_nums = 1; +#else +const int config_btctler_le_hw_nums = 2; +#endif + +#else +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_MULTI) +const int config_btctler_le_hw_nums = 2; +#elif (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_TUYA_MULTI) +const int config_btctler_le_hw_nums = 2; +#else +const int config_btctler_le_hw_nums = 1; +#endif +#endif + + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_CLIENT) +// Master AFH +const int config_btctler_le_afh_en = 1; +// LE RAM Control +const int config_btctler_le_rx_nums = 8; +const int config_btctler_le_acl_packet_length = 27; +const int config_btctler_le_acl_total_nums = 5; +const int config_btctler_le_master_multilink = 0; + +#elif (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_MULTI) +// Master AFH +const int config_btctler_le_afh_en = 1; +// LE RAM Control######## +const int config_btctler_le_rx_nums = 10; //le_hw_nums*5 +const int config_btctler_le_acl_packet_length = 27; +const int config_btctler_le_acl_total_nums = 10; //le_hw_nums*5 +const int config_btctler_le_master_multilink = 1; + +#elif (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_TUYA_MULTI) +// Master AFH +const int config_btctler_le_afh_en = 1; +// LE RAM Control######## +const int config_btctler_le_rx_nums = 10; //le_hw_nums*5 +const int config_btctler_le_acl_packet_length = 27; +const int config_btctler_le_acl_total_nums = 10; //le_hw_nums*5 +const int config_btctler_le_master_multilink = 1; + +#else +// Master AFH +const int config_btctler_le_afh_en = 0; +// LE RAM Control +const int config_btctler_le_rx_nums = 5; +const int config_btctler_le_acl_packet_length = 27; +const int config_btctler_le_acl_total_nums = 5; +const int config_btctler_le_master_multilink = 0; +#endif + +const int config_bt_security_vulnerability = 0; + +const int CONFIG_A2DP_DELAY_TIME = 200; + +/* const uint64_t config_btctler_le_features = 0; */ +/* #ifdef ENABLE_BLE */ +/* const int config_btctler_le_roles = (LE_ADV | LE_SLAVE); */ +/* #else */ +/* #if TCFG_USER_BLE_ENABLE */ +/* const int config_btctler_le_roles = (LE_ADV); */ +/* #else */ +/* const int config_btctler_le_roles = 0; */ +/* #endif */ +/* #endif */ + +const int config_btctler_le_slave_conn_update_winden = 2500;//range:100 to 2500 +/*-----------------------------------------------------------*/ +/** + * @brief Bluetooth Analog setting + */ +/*-----------------------------------------------------------*/ +#if ((!TCFG_USER_BT_CLASSIC_ENABLE) && TCFG_USER_BLE_ENABLE) +const int config_btctler_single_carrier_en = 1; ////单模ble才设置 +#else +const int config_btctler_single_carrier_en = 0; +#endif + +const int config_le_sm_sub_sc_bridge_edr_enable = 0; + +/** + * @brief Log (Verbose/Info/Debug/Warn/Error) + */ +/*-----------------------------------------------------------*/ +//RF part +const char log_tag_const_v_Analog AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_Analog AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_Analog AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_Analog AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_e_Analog AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); + +const char log_tag_const_v_RF AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_RF AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_RF AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_RF AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_e_RF AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); + +//Classic part +const char log_tag_const_v_HCI_LMP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_HCI_LMP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_d_HCI_LMP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_HCI_LMP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_HCI_LMP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LMP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LMP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_d_LMP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LMP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LMP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +//LE part +const char log_tag_const_v_LE_BB AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LE_BB AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LE_BB AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_LE_BB AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LE_BB AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LE5_BB AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LE5_BB AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LE5_BB AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LE5_BB AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LE5_BB AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_HCI_LL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_HCI_LL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_HCI_LL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_HCI_LL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_HCI_LL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_LL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_E AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_E AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LL_E AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_E AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_E AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_M AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_M AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LL_M AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_M AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_M AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_ADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_ADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LL_ADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_ADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_ADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_SCAN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_SCAN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LL_SCAN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_SCAN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_SCAN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_INIT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_INIT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LL_INIT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_INIT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_INIT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_EXT_ADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_EXT_ADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LL_EXT_ADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_EXT_ADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_EXT_ADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_EXT_SCAN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_EXT_SCAN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LL_EXT_SCAN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_EXT_SCAN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_EXT_SCAN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_EXT_INIT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_EXT_INIT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LL_EXT_INIT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_EXT_INIT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_EXT_INIT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_TWS_ADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_TWS_ADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LL_TWS_ADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_TWS_ADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_TWS_ADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_TWS_SCAN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_TWS_SCAN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LL_TWS_SCAN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_TWS_SCAN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_TWS_SCAN AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_S AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_S AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_d_LL_S AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_S AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_S AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_RL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_RL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_d_LL_RL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_RL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_RL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_WL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_WL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_d_LL_WL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_WL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_WL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_AES AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_AES AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_AES AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_AES AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_AES AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_PADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_PADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LL_PADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_PADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_PADV AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_DX AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_DX AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LL_DX AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_DX AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_DX AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_PHY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_PHY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_LL_PHY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_LL_PHY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_PHY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_LL_AFH AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_LL_AFH AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_d_LL_AFH AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_LL_AFH AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_LL_AFH AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +//HCI part +const char log_tag_const_v_Thread AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_Thread AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_Thread AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_Thread AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_Thread AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_HCI_STD AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_HCI_STD AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_HCI_STD AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_HCI_STD AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_HCI_STD AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_HCI_LL5 AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_HCI_LL5 AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_HCI_LL5 AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_HCI_LL5 AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_HCI_LL5 AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + +const char log_tag_const_v_BL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_BL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_BL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_BL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_e_BL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_c_BL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + + +const char log_tag_const_v_TWS_LE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_i_TWS_LE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_TWS_LE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_TWS_LE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_e_TWS_LE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_c_TWS_LE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); + + +const char log_tag_const_v_TWS_LMP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_i_TWS_LMP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_d_TWS_LMP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_TWS_LMP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_e_TWS_LMP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); + diff --git a/apps/soundbox/log_config/lib_btstack_config.c b/apps/soundbox/log_config/lib_btstack_config.c new file mode 100644 index 0000000..7260a64 --- /dev/null +++ b/apps/soundbox/log_config/lib_btstack_config.c @@ -0,0 +1,77 @@ +/********************************************************************************************* + * Filename : btstack_config.c + + * Description : Optimized Code & RAM (编译优化配置) + + * Author : Bingquan + + * Email : caibingquan@zh-jieli.com + + * Last modifiled : 2019-03-16 11:49 + + * Copyright:(c)JIELI 2011-2019 @ , All Rights Reserved. +*********************************************************************************************/ +#include "app_config.h" +#include "system/includes.h" +#include "btcontroller_config.h" +#include "bt_common.h" + +/** + * @brief Bluetooth Stack Module + */ +const u8 user_at_cmd_send_support = 1; + +#ifdef CONFIG_SOUNDBOX_FLASH_256K +const int CONFIG_BTSTACK_BIG_FLASH_ENABLE = 0; +#else +const int CONFIG_BTSTACK_BIG_FLASH_ENABLE = 1; +#endif + + +#if TCFG_BT_SUPPORT_AAC +const int CONFIG_BTSTACK_SUPPORT_AAC = 1; +#else +const int CONFIG_BTSTACK_SUPPORT_AAC = 0; +#endif + +//协议栈接收到命令是否自动退出sniff +const int config_btstask_auto_exit_sniff = 1; + + + +#if SMART_BOX_EN +const int config_rcsp_stack_enable = 1; +#else +const int config_rcsp_stack_enable = 0; +#endif + +#if TCFG_USER_BLE_ENABLE + +#if TRANS_MULTI_BLE_EN +const int config_le_hci_connection_num = 2;//支持同时连接个数 +const int config_le_sm_support_enable = 0; //是否支持加密配对 +const int config_le_gatt_server_num = 1; //支持server角色个数 +const int config_le_gatt_client_num = 1; //支持client角色个数 + +#elif TUYA_MULTI_BLE_EN +const int config_le_hci_connection_num = 2;//支持同时连接个数 +const int config_le_sm_support_enable = 0; //是否支持加密配对 +const int config_le_gatt_server_num = 1; //支持server角色个数 +const int config_le_gatt_client_num = 1; //支持client角色个数 + +#else +const int config_le_hci_connection_num = 1;//支持同时连接个数 +const int config_le_sm_support_enable = 0; //是否支持加密配对 +const int config_le_gatt_server_num = 1; //支持server角色个数 +const int config_le_gatt_client_num = 0; //支持client角色个数 +#endif + +#else +const int config_le_hci_connection_num = 0;//支持同时连接个数 +const int config_le_sm_support_enable = 0; //是否支持加密配对 +const int config_le_gatt_server_num = 0; //支持server角色个数 +const int config_le_gatt_client_num = 0; //支持client角色个数 + +#endif + +const int config_btstask_use_malloc = 1; diff --git a/apps/soundbox/log_config/lib_driver_config.c b/apps/soundbox/log_config/lib_driver_config.c new file mode 100644 index 0000000..c439f01 --- /dev/null +++ b/apps/soundbox/log_config/lib_driver_config.c @@ -0,0 +1,190 @@ +/********************************************************************************************* + * Filename : lib_driver_config.c + + * Description : Optimized Code & RAM (编译优化配置) + + * Author : Bingquan + + * Email : caibingquan@zh-jieli.com + + * Last modifiled : 2019-03-18 14:58 + + * Copyright:(c)JIELI 2011-2019 @ , All Rights Reserved. +*********************************************************************************************/ +#include "app_config.h" +#include "system/includes.h" + + +#if TCFG_SD0_SD1_USE_THE_SAME_HW +const int sd0_sd1_use_the_same_hw = 1; +#else +const int sd0_sd1_use_the_same_hw = 0; +#endif + +#if TCFG_KEEP_CARD_AT_ACTIVE_STATUS +const int keep_card_at_active_status = 1; +#else +const int keep_card_at_active_status = 0; +#endif + +#if TCFG_SDX_CAN_OPERATE_MMC_CARD +const int sdx_can_operate_mmc_card = 1; +#else +const int sdx_can_operate_mmc_card = 0; +#endif + +#if (TCFG_CLOCK_SYS_SRC == SYS_CLOCK_INPUT_PLL_RCL) //系统时钟源选择 +const int clock_sys_src_use_lrc_hw = 1; //当使用lrc时timer.c需要特殊设置 +#else +const int clock_sys_src_use_lrc_hw = 0; +#endif +/** + * @brief Log (Verbose/Info/Debug/Warn/Error) + */ +/*-----------------------------------------------------------*/ +const char log_tag_const_v_CLOCK AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_CLOCK AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_CLOCK AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_w_CLOCK AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_CLOCK AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_LP_TIMER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_LP_TIMER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_LP_TIMER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_LP_TIMER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_LP_TIMER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_LRC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_LRC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_LRC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_LRC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_LRC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_P33_MISC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_P33_MISC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_P33_MISC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_P33_MISC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_P33_MISC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_P33 AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_P33 AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_d_P33 AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_P33 AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_P33 AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_PMU AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_PMU AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_d_PMU AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_PMU AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_PMU AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_c_PMU AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_WKUP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_WKUP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_WKUP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_w_WKUP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_WKUP AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_SDFILE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_SDFILE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_SDFILE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_SDFILE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_SDFILE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_CHARGE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_CHARGE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_d_CHARGE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_CHARGE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_CHARGE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_DEBUG AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_DEBUG AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_DEBUG AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_DEBUG AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_DEBUG AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_PWM_LED AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_PWM_LED AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_PWM_LED AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_PWM_LED AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_PWM_LED AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_KEY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_KEY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_KEY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_KEY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_KEY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_TMR AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_TMR AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_TMR AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_w_TMR AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_TMR AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_VM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_VM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_VM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_VM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_e_VM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); + +const char log_tag_const_v_TRIM_VDD AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE) ; +const char log_tag_const_i_TRIM_VDD AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_d_TRIM_VDD AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_w_TRIM_VDD AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_TRIM_VDD AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +//audio dac +const char log_tag_const_v_SYS_DAC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_SYS_DAC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_SYS_DAC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_SYS_DAC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_e_SYS_DAC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); + +const char log_tag_const_v_APP_DAC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_APP_DAC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_APP_DAC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_APP_DAC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_e_APP_DAC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); + +const char log_tag_const_v_APP_EDET AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_APP_EDET AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_APP_EDET AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_APP_EDET AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_e_APP_EDET AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_FM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_FM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_d_FM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_FM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_e_FM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); + +const char log_tag_const_v_CORE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_CORE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_d_CORE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_CORE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_e_CORE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); + +const char log_tag_const_v_CACHE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_CACHE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(1); +const char log_tag_const_d_CACHE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_CACHE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_e_CACHE AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); + +const char log_tag_const_v_LP_KEY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_LP_KEY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_d_LP_KEY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_LP_KEY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_LP_KEY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_USB AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_i_USB AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_d_USB AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_w_USB AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_USB AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_SD AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_SD AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_d_SD AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_SD AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_e_SD AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + diff --git a/apps/soundbox/log_config/lib_media_config.c b/apps/soundbox/log_config/lib_media_config.c new file mode 100644 index 0000000..d7d9c28 --- /dev/null +++ b/apps/soundbox/log_config/lib_media_config.c @@ -0,0 +1,434 @@ +/********************************************************************************************* + * Filename : lib_driver_config.c + + * Description : Optimized Code & RAM (编译优化配置) + + * Author : Bingquan + + * Email : caibingquan@zh-jieli.com + + * Last modifiled : 2019-03-18 14:58 + + * Copyright:(c)JIELI 2011-2019 @ , All Rights Reserved. +*********************************************************************************************/ +#include "app_config.h" +#include "system/includes.h" +#include "media/includes.h" +#include "audio_config.h" + + +#if (TCFG_AUDIO_DECODER_OCCUPY_TRACE) +const u8 audio_decoder_occupy_trace_enable = 1; +const u8 audio_decoder_occupy_trace_dump = 0; +#else +const u8 audio_decoder_occupy_trace_enable = 0; +const u8 audio_decoder_occupy_trace_dump = 0; +#endif/*TCFG_AUDIO_DECODER_OCCUPY_TRACE*/ + +/*************************************************************************************************/ +const int config_audio_eq_en = 0 +#if TCFG_EQ_ENABLE + | EQ_EN //eq使能 +#if TCFG_EQ_ONLINE_ENABLE + | EQ_ONLINE_EN //在线调试使能 + | EQ_ONLINE_FILE_SAVE //eq在线调试保存到vm使能 +#endif/*TCFG_AUDIO_OUT_EQ_ENABLE*/ +#if TCFG_USE_EQ_FILE + | EQ_FILE_EN //使用eq_cfg_hw.bin文件效果 + //|EQ_FILE_SWITCH_EN //使能eq_cfg_hw.bin多文件切换,对应旧版config_audio_eq_file_sw_en +#endif/*TCFG_USE_EQ_FILE*/ +#if TCFG_AUDIO_OUT_EQ_ENABLE + | EQ_HIGH_BASS_EN //高低音接口使能 + | EQ_HIGH_BASS_FADE_EN //高低音接口数据更新使用淡入淡出,配合config_audio_eq_fade_step步进使用 +#endif/*TCFG_AUDIO_OUT_EQ_ENABLE*/ +#if (RCSP_ADV_EN)&&(JL_EARPHONE_APP_EN)&&(TCFG_DRC_ENABLE == 0) + /* |EQ_FILTER_COEFF_LIMITER_ZERO_EN */ +#endif +#ifndef CONFIG_SOUNDBOX_FLASH_256K + | EQ_HW_UPDATE_COEFF_ONLY_EN + | EQ_HW_LR_ALONE +#endif/* CONFIG_SOUNDBOX_FLASH_256K */ +#if defined(EQ_CORE_V1) && TCFG_DRC_ENABLE + | EQ_SUPPORT_MULIT_CHANNEL_EN //eq是否支持多声道(3~8) 打开:支持 否则:仅支持1~2声道*/ + | EQ_HW_CROSSOVER_TYPE0_EN //硬件分频器用序列进序列出 + //|EQ_HW_CROSSOVER_TYPE1_EN //硬件分频器使用块出方式,会增加mem(该方式仅支持单声道处理) +#endif/*(EQ_CORE_V1) && TCFG_DRC_ENABLE*/ +#if defined(TCFG_EQ_DIVIDE_ENABLE) && TCFG_EQ_DIVIDE_ENABLE + | EQ_LR_DIVIDE_EN +#endif/*TCFG_EQ_DIVIDE_ENABLE*/ + | EQ_SUPPORT_32BIT_SYNC_EN //32bit同步方式eq使能,eq_lite_en后,该宏需使能 + | EQ_DRC_PROCESS_SPLIT + +#if defined(EQ_LITE_CODE) && EQ_LITE_CODE + | EQ_LITE_VER_EN //不支持异步,不支持默认效果切换接口,仅支持文件解析 +#if TCFG_DRC_ENABLE + | EQ_SUPPORT_32BIT_SYNC_EN //32bit同步方式eq使能,eq_lite_en后,该宏需使能 +#endif/*TCFG_DRC_ENABLE*/ +#endif/* EQ_LITE_CODE */ +#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) &&SOUND_TRACK_2_P_X_CH_CONFIG + | EQ_SUPPORT_32BIT_SYNC_EN //32bit同步方式eq使能 +#endif + + //|EQ_FILTER_COEFF_FADE_EN//默认系数切换更新时使用淡入淡出 +#endif/* TCFG_EQ_ENABLE */ + | 0; //end + +const float config_audio_eq_fade_step = 0.1f;//播歌高低音增益调节步进 + +const int const_eq_debug = 1; +const int AUDIO_EQ_CLEAR_MEM_BY_MUTE_TIME_MS = 0;//300 //连续多长时间静音就清除EQ MEM +const int AUDIO_EQ_CLEAR_MEM_BY_MUTE_LIMIT = 0; //静音判断阀值 + +const int config_audio_drc_en = 0 +#if TCFG_DRC_ENABLE + | DRC_EN //drc使能 + | WDRC_TYPE_EN + /* |DRC_COMPRESSOF_DIS //关闭压缩器 */ + /* |DRC_NBAND_DIS //关闭多带压缩器,关闭多带限幅器 */ +#endif + | 0; //end +/*************************************************************************************************/ +#if TCFG_MIC_EFFECT_ENABLE +const int config_audio_dac_mix_enable = 1; +#else +const int config_audio_dac_mix_enable = 0; +#endif + +const int config_audio_dac_noisefloor_optimize_enable = 0; + +#ifdef CONFIG_SOUNDBOX_FLASH_256K +// mixer模块使能。不使能将关闭大部分功能,mix为直通 +const int config_mixer_en = 0; +// mixer变采样使能 +const int config_mixer_src_en = 0; + +// audio解码资源叠加功能使能。不使能,如果配置了叠加方式,将改成抢占方式 +const int config_audio_dec_wait_protect_en = 0; + +// audio数据流分支功能使能。 +const int config_audio_stream_frame_copy_en = 0; + +// audio dec app调用mixer相关函数控制。关闭后需上层设置数据流的输出节点 +const int audio_dec_app_mix_en = 0; + +#else + +// mixer模块使能。不使能将关闭大部分功能,mix为直通 +const int config_mixer_en = 1; +// mixer变采样使能 +const int config_mixer_src_en = 1; + +// audio解码资源叠加功能使能。不使能,如果配置了叠加方式,将改成抢占方式 +const int config_audio_dec_wait_protect_en = 1; + +// audio数据流分支功能使能。 +const int config_audio_stream_frame_copy_en = 1; + +// audio dec app调用mixer相关函数控制。关闭后需上层设置数据流的输出节点 +const int audio_dec_app_mix_en = 1; + +#endif + +//wts解码支持采样率可选择,可以同时打开也可以单独打开 +const int silk_fsN_enable = 1; //支持8-12k采样率 +const int silk_fsW_enable = 1; //支持16-24k采样率 + +// audio数据流分支cbuf大小控制 +const int config_audio_stream_frame_copy_cbuf_min = 128; +const int config_audio_stream_frame_copy_cbuf_max = 1024; + +#if RECORDER_MIX_EN +// 超时等待其他解码unactive步骤完成 +const int config_audio_dec_unactive_to = 50; +// audio数据流ioctrl使能 +const int config_audio_stream_frame_ioctrl_en = 1; +#else +// 超时等待其他解码unactive步骤完成 +const int config_audio_dec_unactive_to = 0; +// audio数据流ioctrl使能 +const int config_audio_stream_frame_ioctrl_en = 0; +#endif + +#if TCFG_TONE2TWS_ENABLE + +// audio dec app tws同步使能 +const int audio_dec_app_sync_en = 1; + +// wma tws 解码控制 +const int WMA_TWSDEC_EN = 1; + +// wav最大支持比特率,单位kbps +const int WAV_MAX_BITRATEV = (48 * 2 * 12); + +#else + +// audio dec app tws同步使能 +const int audio_dec_app_sync_en = 0; + +// wma tws 解码控制 +const int WMA_TWSDEC_EN = 0; + +// wav最大支持比特率,单位kbps +const int WAV_MAX_BITRATEV = (48 * 2 * 32); + +#endif + + +#if TCFG_DEC2TWS_ENABLE || SOUNDCARD_ENABLE || TCFG_MIC_EFFECT_ENABLE || RECORDER_MIX_EN || TCFG_USER_EMITTER_ENABLE + +// 解码一次输出点数,1代表32对点,n就是n*32对点 +// 超过1时,解码需要使用malloc,如config_mp3_dec_use_malloc=1 +#if(CONFIG_CPU_BR25) +const int MP3_OUTPUT_LEN = 4; +const int WMA_OUTPUT_LEN = 4; +#else +const int MP3_OUTPUT_LEN = 4; +const int WMA_OUTPUT_LEN = 4; +#endif + +// output超过1时,如果不使用malloc,需要增大对应buf +// 可以看打印中解码器需要的大小,一般输出每增加1长度增加32*2*2 +int mp3_mem_ext[(16100 + 3) / 4] SEC(.mp3_mem); +int wma_mem_ext[(23900 + 3) / 4] SEC(.wma_mem); +int wma_mem_tws_ext[(29314 + 3) / 4] SEC(.wma_mem); + +#else + +// 解码一次输出点数,1代表32对点,n就是n*32对点 +// 超过1时,解码需要使用malloc,如config_mp3_dec_use_malloc=1 +const int MP3_OUTPUT_LEN = 1; +const int WMA_OUTPUT_LEN = 1; +#endif + +// mixer在单独任务中输出 +#if TCFG_MIXER_CYCLIC_TASK_EN +const int config_mixer_task = 1; +#else +const int config_mixer_task = 0; +#endif + +// tws音频解码自动设置输出声道。 +// 单声道:AUDIO_CH_L/AUDIO_CH_R。双声道:AUDIO_CH_DUAL_L/AUDIO_CH_DUAL_R +// 关闭后,按照output_ch_num和output_ch_type/ch_type设置输出声道 +const int audio_tws_auto_channel = 1; + + +// 解码使用单独任务做输出 +#if TCFG_AUDIO_DEC_OUT_TASK +const int config_audio_dec_out_task_en = 1; +#else +const int config_audio_dec_out_task_en = 0; +#endif + + +/*省电容mic配置*/ +#if TCFG_SUPPORT_MIC_CAPLESS +const u8 const_mic_capless_en = 1; +#else +const u8 const_mic_capless_en = 0; +#endif/*TCFG_SUPPORT_MIC_CAPLESS*/ + +#if AUDIO_EQUALLOUDNESS_CONFIG +const int const_equall_loundness_en = 1; +#else +const int const_equall_loundness_en = 0; +#endif + +#if AUDIO_VBASS_CONFIG +const int const_vbass_en = 1; +#else +const int const_vbass_en = 0; +#endif + +#if AUDIO_SURROUND_CONFIG +const int const_surround_en = 1;//|BIT(1) ;//或上bit1 将使能effect_3d_type2 mips消耗55M ram占33k +#else +const int const_surround_en = 0; +#endif + + + + +#ifdef CONFIG_MIDI_DEC_ADDR +const int MIDI_TONE_MODE = 0;//0是地址访问(仅支持在内置flash,读数快,消耗mips低),1 是文件访问(内置、外挂flash,sd,u盘均可,读数慢,消耗mips较大) +#else +const int MIDI_TONE_MODE = 1; +#endif +const int MAINTRACK_USE_CHN = 0; //MAINTRACK_USE_CHN控制主通道区分方式; 0用track号区分主通道 1用chn号区分主通道 +const int MAX_PLAYER_CNT = 18; //控制可配置的最大同时发声的key数的BUF[1,32] + +#if TCFG_MEDIA_LIB_USE_MALLOC +const int config_mp3_dec_use_malloc = 1; +const int config_mp3pick_dec_use_malloc = 1; +const int config_wma_dec_use_malloc = 1; +const int config_wmapick_dec_use_malloc = 1; +const int config_m4a_dec_use_malloc = 1; +const int config_m4apick_dec_use_malloc = 1; +const int config_wav_dec_use_malloc = 1; +const int config_alac_dec_use_malloc = 1; +const int config_dts_dec_use_malloc = 1; +const int config_amr_dec_use_malloc = 1; +const int config_flac_dec_use_malloc = 1; +const int config_ape_dec_use_malloc = 1; +const int config_aac_dec_use_malloc = 1; +const int config_aptx_dec_use_malloc = 1; +const int config_midi_dec_use_malloc = 1; +#else +const int config_mp3_dec_use_malloc = 0; +const int config_mp3pick_dec_use_malloc = 0; +const int config_wma_dec_use_malloc = 0; +const int config_wmapick_dec_use_malloc = 0; +const int config_m4a_dec_use_malloc = 0; +const int config_m4apick_dec_use_malloc = 0; +const int config_wav_dec_use_malloc = 0; +const int config_alac_dec_use_malloc = 0; +const int config_dts_dec_use_malloc = 0; +const int config_amr_dec_use_malloc = 0; +const int config_flac_dec_use_malloc = 0; +const int config_ape_dec_use_malloc = 0; +const int config_aac_dec_use_malloc = 0; +const int config_aptx_dec_use_malloc = 0; +const int config_midi_dec_use_malloc = 0; +#endif + +enum { + PLATFORM_FREQSHIFT_CORDIC = 0, + PLATFORM_FREQSHIFT_CORDICV2 = 1 +}; + +/* 备注: */ +/* br23/br25/br30/br34/br40是PLATFORM_FREQSHIFT_CORDIC */ +/* , br36/br28/br27是PLATFORM_FREQSHIFT_CORDICV2 */ +const int howling_freshift_PLATFORM = PLATFORM_FREQSHIFT_CORDIC; + +const int vc_pitchshift_fastmode_flag = 1; //变声快速模式使能 +const int vc_pitchshift_only = 0; +//变声库数学函数版本配置,br23/br25/br30/br34/br40是PLATFORM_VOICECHANGE_CORDIC,br27/br28/br36是PLATFORM_VOICECHANGE_CORDICV2 +const int voicechange_mathfun_PLATFORM = PLATFORM_FREQSHIFT_CORDIC; +//变声库的fft配置, br28是PLATFORM_VOICECHANGE_FFTV2, br23/br25/br30/br36/br40是PLATFORM_VOICECHANGE_FFT +const int voicechange_fft_PLATFORM = PLATFORM_FREQSHIFT_CORDIC; + +const int vc_pitchshift_downmode_flag = 0; //变声下采样处理使能 +const int VC_KINDO_TVM = 1; //含义为EFFECT_VOICECHANGE_KIN0是否另一种算法 : 0表示跟原来一样,1表示用另一种 +const int howling_freshift_highmode_flag = 0; //移频快速模式 +const int howling_pitchshift_fastmode_flag = 1;//移频啸叫抑制快速模式使能 +const int RS_FAST_MODE_QUALITY = 2; //软件变采样 滤波阶数配置,范围2到8, 8代表16阶的变采样模式 ,速度跟它的大小呈正相关 +/* const int RMAX_ROOMSIZE = 1; */ +const int config_howling_enable_pemafrow_mode = 0; +const int config_howling_enable_trap_mode = 1;//陷波啸叫抑制模式使能 +const int config_howling_enable_pitchps_mode = 1; //移频啸叫抑制模式使能 +const int ECHO_INT_VAL_OUT = 0; // 置1: echo的输出是int 后级需接DRC限幅 功能未实现 + +#if(CONFIG_CPU_BR25) +const int DOWN_S_FLAG = 1; //混响降采样处理使能 +#else +const int DOWN_S_FLAG = 0; //混响降采样处理使能 +#endif +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DONGLE) +const int config_mp3_enc_use_layer_3 = 1; +#else +const int config_mp3_enc_use_layer_3 = 0; +#endif + +#define FAST_FREQ_restrict 0x01 //限制超过16k的频率不解【一般超出人耳听力范围,但是仪器会测出来】 +#define FAST_FILTER_restrict 0x02 //限制滤波器长度【子带滤波器旁瓣加大,边缘不够陡】 +#define FAST_CHANNEL_restrict 0x04 //混合左右声道,再解码【如果是左右声道独立性较强的歌曲,会牺牲空间感,特别耳机听会听出来的话】 +const int config_mp3_dec_speed_mode = 0;//FAST_FREQ_restrict | FAST_FILTER_restrict | FAST_CHANNEL_restrict; //3个开关都置上,是最快的解码模式 + +// 快进快退到文件end返回结束消息 +const int config_decoder_ff_fr_end_return_event_end = 0; + +/** + * @brief Log (Verbose/Info/Debug/Warn/Error) + */ +/*-----------------------------------------------------------*/ +/* const char log_tag_const_v_EQ_CFG AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); */ +/* const char log_tag_const_i_EQ_CFG AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); */ +/* const char log_tag_const_d_EQ_CFG AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); */ +/* const char log_tag_const_w_EQ_CFG AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); */ +/* const char log_tag_const_e_EQ_CFG AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); */ + +/* const char log_tag_const_v_EQ_CFG_TOOL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); */ +/* const char log_tag_const_i_EQ_CFG_TOOL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); */ +/* const char log_tag_const_d_EQ_CFG_TOOL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); */ +/* const char log_tag_const_w_EQ_CFG_TOOL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); */ +/* const char log_tag_const_e_EQ_CFG_TOOL AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); */ + +const char log_tag_const_v_EQ_APPLY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_EQ_APPLY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_EQ_APPLY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_EQ_APPLY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_EQ_APPLY AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_DRC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_DRC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_DRC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_DRC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_DRC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_APP_DRC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_APP_DRC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_APP_DRC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_APP_DRC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_APP_DRC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + + +const char log_tag_const_v_EQ AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_EQ AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_EQ AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_EQ AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_EQ AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + + +const char log_tag_const_v_VBASS AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_VBASS AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_VBASS AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_VBASS AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_VBASS AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_AUD_ADC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_AUD_ADC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_AUD_ADC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_AUD_ADC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_e_AUD_ADC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); + +const char log_tag_const_v_AUD_DAC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_AUD_DAC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_AUD_DAC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_AUD_DAC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_e_AUD_DAC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); + +const char log_tag_const_v_AUD_AUX AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_AUD_AUX AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_AUD_AUX AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_w_AUD_AUX AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_e_AUD_AUX AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); + + + +const char log_tag_const_v_MIXER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_c_MIXER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_MIXER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_MIXER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_MIXER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_AUDIO_STREAM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_c_AUDIO_STREAM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_AUDIO_STREAM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_AUDIO_STREAM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_AUDIO_STREAM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_AUDIO_DECODER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_c_AUDIO_DECODER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_AUDIO_DECODER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_AUDIO_DECODER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_AUDIO_DECODER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_AUDIO_ENCODER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_c_AUDIO_ENCODER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_i_AUDIO_ENCODER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(0); +const char log_tag_const_d_AUDIO_ENCODER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_AUDIO_ENCODER AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + + + diff --git a/apps/soundbox/log_config/lib_system_config.c b/apps/soundbox/log_config/lib_system_config.c new file mode 100644 index 0000000..640c7ae --- /dev/null +++ b/apps/soundbox/log_config/lib_system_config.c @@ -0,0 +1,109 @@ +/********************************************************************************************* + * Filename : lib_system_config.c + + * Description : Optimized Code & RAM (编译优化配置) + + * Author : Bingquan + + * Email : caibingquan@zh-jieli.com + + * Last modifiled : 2019-03-18 15:22 + + * Copyright:(c)JIELI 2011-2019 @ , All Rights Reserved. +*********************************************************************************************/ + +#include "app_config.h" +#include "system/includes.h" + + +///打印是否时间打印信息 +const int config_printf_time = 1; + +///异常中断,asser打印开启 +#ifdef CONFIG_RELEASE_ENABLE +const int config_asser = 1; +#else +const int config_asser = 1; +#endif + +const int config_system_info = 0; + +//================================================// +// SDFILE 精简使能 // +//================================================// +#ifdef CONFIG_SOUNDBOX_FLASH_256K +const int SDFILE_VFS_REDUCE_ENABLE = 1; +#else +const int SDFILE_VFS_REDUCE_ENABLE = 0; +#endif + +//================================================// +// FLASH FAT管理使能 // +//================================================// +#ifdef TCFG_VIRFAT_FLASH_SIMPLE +const int VIRFAT_FLASH_ENABLE = 1; +#else +const int VIRFAT_FLASH_ENABLE = 0; +#endif + +//================================================// +// dev使用异步读使能 // +//================================================// +#ifdef TCFG_DEVICE_BULK_READ_ASYNC_ENABLE +const int device_bulk_read_async_enable = 1; +#else +const int device_bulk_read_async_enable = 0; +#endif + +/** + * @brief Log (Verbose/Info/Debug/Warn/Error) + */ +/*-----------------------------------------------------------*/ +const char log_tag_const_v_SYS_TMR AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_SYS_TMR AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_SYS_TMR AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_SYS_TMR AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_SYS_TMR AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_JLFS AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_JLFS AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_JLFS AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_JLFS AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_JLFS AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +//FreeRTOS +const char log_tag_const_v_PORT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_PORT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_PORT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_PORT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_PORT AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_KTASK AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_KTASK AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_KTASK AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_KTASK AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_KTASK AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_uECC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_uECC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_uECC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_uECC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_uECC AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_HEAP_MEM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_HEAP_MEM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_HEAP_MEM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_w_HEAP_MEM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_HEAP_MEM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_V_MEM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_V_MEM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_V_MEM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_V_MEM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_V_MEM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); + +const char log_tag_const_v_P_MEM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_i_P_MEM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_d_P_MEM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(FALSE); +const char log_tag_const_w_P_MEM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); +const char log_tag_const_e_P_MEM AT(.LOG_TAG_CONST) = CONFIG_DEBUG_LIB(TRUE); diff --git a/apps/soundbox/log_config/lib_update_config.c b/apps/soundbox/log_config/lib_update_config.c new file mode 100644 index 0000000..3840926 --- /dev/null +++ b/apps/soundbox/log_config/lib_update_config.c @@ -0,0 +1,54 @@ + +#include "app_config.h" +#include "system/includes.h" +#include "update_loader_download.h" + +#ifdef CONFIG_256K_FLASH +const int config_update_mode = UPDATE_UART_EN; +#else +#ifdef CONFIG_SOUNDBOX_FLASH_256K +const int config_update_mode = UPDATE_UART_EN; +#else +#ifdef CONFIG_AC608N +const int config_update_mode = UPDATE_STORAGE_DEV_EN | UPDATE_UART_EN; +#else +#ifdef CONFIG_BOARD_AC6083A +const int config_update_mode = UPDATE_STORAGE_DEV_EN | UPDATE_UART_EN; +#else +const int config_update_mode = UPDATE_BT_LMP_EN | UPDATE_STORAGE_DEV_EN | UPDATE_UART_EN | UPDATE_APP_EN; +#endif +#endif +#endif +#endif + +//是否采用双备份升级方案:0-单备份;1-双备份 +#if CONFIG_DOUBLE_BANK_ENABLE +const int support_dual_bank_update_en = 1; +#else +const int support_dual_bank_update_en = 0; +#endif + +//是否支持外挂flash升级,需要打开Board.h中的TCFG_NOR_FS_ENABLE +const int support_norflash_update_en = 0; + +//支持从外挂flash读取ufw文件升级使能 +const int support_norflash_ufw_update_en = 0; + +#if OTA_TWS_SAME_TIME_NEW //使用新的同步升级流程 +const int support_ota_tws_same_time_new = 1; +#else +const int support_ota_tws_same_time_new = 0; +#endif + +//是否支持升级之后保留vm数据 +#if (((defined CONFIG_CPU_BR25) || (defined CONFIG_CPU_BR23)) && SMART_BOX_EN) +const int support_vm_data_keep = 1; +#else +const int support_vm_data_keep = 0; +#endif + +const char log_tag_const_v_UPDATE AT(.LOG_TAG_CONST) = LIB_DEBUG & FALSE; +const char log_tag_const_i_UPDATE AT(.LOG_TAG_CONST) = LIB_DEBUG & TRUE; +const char log_tag_const_d_UPDATE AT(.LOG_TAG_CONST) = LIB_DEBUG & FALSE; +const char log_tag_const_w_UPDATE AT(.LOG_TAG_CONST) = LIB_DEBUG & TRUE; +const char log_tag_const_e_UPDATE AT(.LOG_TAG_CONST) = LIB_DEBUG & TRUE; diff --git a/apps/soundbox/power_manage/app_charge.c b/apps/soundbox/power_manage/app_charge.c new file mode 100644 index 0000000..006a4a6 --- /dev/null +++ b/apps/soundbox/power_manage/app_charge.c @@ -0,0 +1,463 @@ +#include "app_config.h" +#include "asm/charge.h" +#include "asm/pwm_led.h" +#include "asm/power_interface.h" +#include "ui_manage.h" +#include "system/event.h" +#include "system/app_core.h" +#include "system/includes.h" +#include "app_action.h" +#include "asm/wdt.h" +#include "app_power_manage.h" +#include "app_chargestore.h" +#include "btstack/avctp_user.h" +#include "app_action.h" +#include "app_main.h" +#include "bt_tws.h" +#include "usb/otg.h" +#include "bt_common.h" +#include "app_task.h" + +#define LOG_TAG_CONST APP_CHARGE +#define LOG_TAG "[APP_CHARGE]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +extern void sys_enter_soft_poweroff(void *priv); +extern void gSensor_wkupup_enable(void); +extern void gSensor_wkupup_disable(void); +extern u32 dual_bank_update_exist_flag_get(void); +extern u32 classic_update_task_exist_flag_get(void); + +#if TCFG_CHARGE_ENABLE + +#if (!TCFG_IOKEY_ENABLE && !TCFG_ADKEY_ENABLE) +#ifndef TCFG_CHARGE_CHECK_SET_LDOIN_PINR +#define TCFG_CHARGE_CHECK_SET_LDOIN_PINR +#endif +#endif + +static u8 charge_full_flag = 0; +#if TCFG_TEST_BOX_ENABLE +static int ldo5v_keep_timer = 0; +#endif + +extern void power_event_to_user(u8 event); + +u8 get_charge_full_flag(void) +{ + return charge_full_flag; +} + +void charge_start_deal(void) +{ + log_info("%s\n", __FUNCTION__); + + power_set_mode(PWR_LDO15); //充电切到LDO模式,DCDC模式会直接消耗VBat的电 + + u8 app = app_get_curr_task(); + if (app == APP_IDLE_TASK) { + ui_update_status(STATUS_CHARGE_START); + } +} + + +static void ldo5v_keep_delay_deal(void *priv) +{ + log_info("%s\n", __func__); + +#if TCFG_TEST_BOX_ENABLE + ldo5v_keep_timer = 0; + if (chargestore_get_testbox_status()) { + log_info("testbox online!\n"); + return; + } +#endif + + u8 app = app_get_curr_task(); + if (app != APP_IDLE_TASK) { + sys_enter_soft_poweroff((void *)2); + } + + pwm_led_mode_set(PWM_LED_ALL_OFF); + os_time_dly(30); + pwm_led_mode_set(PWM_LED1_ON); + os_time_dly(40); + + //兼容一些充电仓5v输出慢的时候会导致无法充电的问题 + if (get_lvcmp_det()) { + log_info("...charge ing...\n"); + cpu_reset(); + } + + log_info("get_charge_online_flag:%d %d\n", get_charge_online_flag(), get_ldo5v_online_hw()); + if (get_ldo5v_online_hw() && get_charge_online_flag()) { + power_set_soft_poweroff(); + } else { +#if TCFG_CHARGE_OFF_POWERON_NE + cpu_reset(); +#else +#ifdef TCFG_CHARGE_CHECK_SET_LDOIN_PINR + charge_check_and_set_pinr(1); +#endif + power_set_soft_poweroff(); +#endif + } +} + + +/*ldoin电压大于拔出电压(0.6V左右)且小于VBat电压时调用该函数进行一些错误提示或其他处理*/ +void ldo5v_keep_deal(void) +{ + + log_info("%s\n", __func__); + + //插入交换 + power_event_to_user(POWER_EVENT_POWER_CHANGE); + +#if TCFG_GSENSOR_ENABLE + //在舱关闭gSensor + gSensor_wkupup_disable(); +#endif + +#if TCFG_LP_TOUCH_KEY_ENABLE + extern void lp_touch_key_charge_mode_enter(); + lp_touch_key_charge_mode_enter(); +#endif /* #if TCFG_LP_TOUCH_KEY_ENABLE */ + +#if TCFG_GX8002_NPU_ENABLE + extern void gx8002_module_suspend(u8 keep_vddio); + gx8002_module_suspend(0); +#endif /* #if TCFG_GX8002_NPU_ENABLE */ + + +#ifdef TCFG_CHARGE_CHECK_SET_LDOIN_PINR + charge_check_and_set_pinr(0); +#endif + + if (get_charge_poweron_en() == 0) { +#if TCFG_CHARGESTORE_ENABLE + //智能充电舱不处理充电err + u8 app = app_get_curr_task(); + if (app == APP_IDLE_TASK) { + ui_update_status(STATUS_CHARGE_LDO5V_OFF); + } + +#else //TCFG_CHARGESTORE_ENABLE + +#if defined(TCFG_CHARGE_KEEP_UPDATA) && TCFG_CHARGE_KEEP_UPDATA + if (dual_bank_update_exist_flag_get() || classic_update_task_exist_flag_get()) { + return; + } +#endif + +#if TCFG_TEST_BOX_ENABLE + if (ldo5v_keep_timer == 0) { + //延时执行避免测试盒通信不上 + ldo5v_keep_timer = sys_timeout_add(NULL, ldo5v_keep_delay_deal, 250); + } +#else + ldo5v_keep_delay_deal(NULL); +#endif//TCFG_TEST_BOX_ENABLE +#endif//TCFG_CHARGESTORE_ENABLE + } else { + ui_update_status(STATUS_CHARGE_ERR); + } +} + +void charge_full_deal(void) +{ + log_info("%s\n", __func__); + + charge_full_flag = 1; + + /* charge_close(); */ + if (get_charge_poweron_en() == 0) { + /* power_set_soft_poweroff(); */ +#if TCFG_USER_TWS_ENABLE + +#else + ui_update_status(STATUS_CHARGE_FULL); +#endif +#if (!TCFG_CHARGESTORE_ENABLE) + vbat_timer_delete(); +#endif + } else { + ui_update_status(STATUS_CHARGE_FULL); + } +} + +void charge_close_deal(void) +{ + + log_info("%s\n", __FUNCTION__); + + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + +#if TCFG_USER_TWS_ENABLE + //在idle的时候才执行充电关闭的UI + u8 app = app_get_curr_task(); + if (app == APP_IDLE_TASK) { + ui_update_status(STATUS_CHARGE_LDO5V_OFF); + } +#endif +} + + +void charge_ldo5v_in_deal(void) +{ + log_info("%s\n", __FUNCTION__); + + +#if TCFG_IRSENSOR_ENABLE + if (get_bt_tws_connect_status()) { + tws_api_sync_call_by_uuid('T', SYNC_CMD_EARPHONE_CHAREG_START, 300); + } +#endif + + //插入交换 + power_event_to_user(POWER_EVENT_POWER_CHANGE); + + charge_full_flag = 0; + +#if TCFG_GSENSOR_ENABLE + //入舱关闭gSensor + gSensor_wkupup_disable(); +#endif + +#if TCFG_LP_TOUCH_KEY_ENABLE + extern void lp_touch_key_charge_mode_enter(); + lp_touch_key_charge_mode_enter(); +#endif /* #if TCFG_LP_TOUCH_KEY_ENABLE */ + +#if TCFG_GX8002_NPU_ENABLE + extern void gx8002_module_suspend(u8 keep_vddio); + gx8002_module_suspend(0); +#endif /* #if TCFG_GX8002_NPU_ENABLE */ + +#ifdef TCFG_CHARGE_CHECK_SET_LDOIN_PINR + charge_check_and_set_pinr(0); +#endif + +#if TCFG_TEST_BOX_ENABLE + chargestore_clear_testbox_status(); + if (ldo5v_keep_timer) { + sys_timeout_del(ldo5v_keep_timer); + ldo5v_keep_timer = 0; + } +#endif + +#if TCFG_CHARGESTORE_ENABLE + chargestore_shutdown_reset(); +#endif + + if (get_charge_poweron_en() == 0) { +#if defined(TCFG_CHARGE_KEEP_UPDATA) && TCFG_CHARGE_KEEP_UPDATA + if (dual_bank_update_exist_flag_get() || classic_update_task_exist_flag_get()) { + return; + } +#endif + u8 app = app_get_curr_task(); + if (app != APP_IDLE_TASK) { + +#if (TCFG_CHARGESTORE_ENABLE && TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) + if (!chargestore_check_going_to_poweroff()) { +#endif + sys_enter_soft_poweroff((void *)1); +#if (TCFG_CHARGESTORE_ENABLE && TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) + } else { + log_info("chargestore do poweroff!\n"); + } +#endif + } else { + //添加cpu_reset防止刚开机app还是NULL的时候,进这里导致无法进idle充电 + extern int cpu_reset_by_soft(); + if (cpu_reset_by_soft()) { + charge_start(); + } else { + cpu_reset(); + } + wdt_init(WDT_32S); + log_info("set wdt to 32s!\n"); + goto _check_reset; + } + } else { + charge_start(); + goto _check_reset; + } + return; + +_check_reset: + //防止耳机低电时,插拔充电有几率出现关机不充电问题 + if (app_var.goto_poweroff_flag) { + cpu_reset(); + } +} + +void charge_ldo5v_off_deal(void) +{ + log_info("%s\n", __FUNCTION__); + + + //拨出交换 + power_event_to_user(POWER_EVENT_POWER_CHANGE); +#if (TCFG_CHARGESTORE_ENABLE && TCFG_USER_TWS_ENABLE) + if (TWS_ROLE_SLAVE == tws_api_get_role()) { + chargestore_set_power_level(0xFF); + } +#endif + charge_full_flag = 0; + + charge_close(); + + u8 app = app_get_curr_task(); + if (app == APP_IDLE_TASK) { + ui_update_status(STATUS_CHARGE_LDO5V_OFF); + } + +#ifdef TCFG_CHARGE_CHECK_SET_LDOIN_PINR + charge_check_and_set_pinr(1); +#endif + +#if TCFG_TEST_BOX_ENABLE + if (chargestore_get_testbox_status() && !get_total_connect_dev()) { + log_info("<<<<<<<<<<<<<>>>>>>>>>>>>>>\n"); + cpu_reset(); + } + chargestore_clear_testbox_status(); + if (ldo5v_keep_timer) { + sys_timeout_del(ldo5v_keep_timer); + ldo5v_keep_timer = 0; + } +#endif + +#if TCFG_CHARGESTORE_ENABLE + chargestore_shutdown_reset(); +#endif + + if ((get_charge_poweron_en() == 0)) { + + wdt_init(WDT_4S); + log_info("set wdt to 4s!\n"); +#if TCFG_CHARGESTORE_ENABLE + if (chargestore_get_power_status()) { +#endif +#if TCFG_CHARGE_OFF_POWERON_NE + log_info("ldo5v off,task switch to BT\n"); + app_var.play_poweron_tone = 0; +#if TCFG_SYS_LVD_EN + vbat_check_init(); +#endif + if ((app != APP_BT_TASK) && (app_var.goto_poweroff_flag == 0)) { +#if TCFG_SYS_LVD_EN + if (get_vbat_need_shutdown() == FALSE) { + task_switch_to_bt(); + } else { + log_info("ldo5v off,lowpower,need enter softpoweroff\n"); + power_set_soft_poweroff(); + } +#else //TCFG_SYS_LVD_EN + task_switch_to_bt(); +#endif //TCFG_SYS_LVD_EN + } +#else //TCFG_CHARGE_OFF_POWERON_NE + log_info("ldo5v off,enter softpoweroff\n"); + power_set_soft_poweroff(); +#endif //TCFG_CHARGE_OFF_POWERON_NE +#if TCFG_CHARGESTORE_ENABLE + } else { + log_info("ldo5v off,enter softpoweroff\n"); + if (app != APP_IDLE_TASK) { + sys_enter_soft_poweroff(NULL);//软关机 + } else { + power_set_soft_poweroff(); + } + } +#endif + } else { + if (app == APP_IDLE_TASK) { + power_set_soft_poweroff(); + } + } +#if TCFG_GSENSOR_ENABLE + //出舱使能gSensor + gSensor_wkupup_enable(); +#endif + +#if TCFG_LP_TOUCH_KEY_ENABLE + extern void lp_touch_key_charge_mode_exit(); + lp_touch_key_charge_mode_exit(); +#endif /* #if TCFG_LP_TOUCH_KEY_ENABLE */ + +#if TCFG_GX8002_NPU_ENABLE + extern void gx8002_module_resumed(); + gx8002_module_resumed(); +#endif /* #if TCFG_GX8002_NPU_ENABLE */ +} + +int app_charge_event_handler(struct device_event *dev) +{ + int ret = false; + u8 otg_status = 0; + + switch (dev->event) { + case CHARGE_EVENT_CHARGE_START: + charge_start_deal(); + break; + case CHARGE_EVENT_CHARGE_CLOSE: + charge_close_deal(); + break; + case CHARGE_EVENT_CHARGE_FULL: + charge_full_deal(); + break; + case CHARGE_EVENT_LDO5V_KEEP: + ldo5v_keep_deal(); + break; + case CHARGE_EVENT_LDO5V_IN: +#if ((TCFG_OTG_MODE & OTG_SLAVE_MODE) && (TCFG_OTG_MODE & OTG_CHARGE_MODE)) + while (1) { + otg_status = usb_otg_online(0); + if (otg_status != IDLE_MODE) { + break; + } + os_time_dly(2); + } +#endif + if (otg_status != SLAVE_MODE) { + charge_ldo5v_in_deal(); + } + break; + case CHARGE_EVENT_LDO5V_OFF: +#if ((TCFG_OTG_MODE & OTG_SLAVE_MODE) && (TCFG_OTG_MODE & OTG_CHARGE_MODE)) + while (1) { + otg_status = usb_otg_online(0); + if (otg_status != IDLE_MODE) { + break; + } + os_time_dly(2); + } +#endif + if (otg_status != SLAVE_MODE) { + charge_ldo5v_off_deal(); + } + break; + default: + break; + } + + return ret; +} + +#else + +u8 get_charge_full_flag(void) +{ + return 0; +} + +#endif + diff --git a/apps/soundbox/power_manage/app_chargestore.c b/apps/soundbox/power_manage/app_chargestore.c new file mode 100644 index 0000000..8ab75fd --- /dev/null +++ b/apps/soundbox/power_manage/app_chargestore.c @@ -0,0 +1,1013 @@ +#include "init.h" +#include "app_config.h" +#include "system/includes.h" +#include "asm/charge.h" +#include "asm/chargestore.h" +#include "user_cfg.h" +#include "app_chargestore.h" +#include "device/vm.h" +#include "btstack/avctp_user.h" +#include "app_power_manage.h" +#include "app_action.h" +#include "app_main.h" +#include "app_charge.h" +#include "classic/tws_api.h" +#include "update.h" +#include "bt_ble.h" +#include "bt_tws.h" +#include "app_action.h" +#include "bt_common.h" +#include "le_rcsp_adv_module.h" +#include "app_task.h" +#include "update_loader_download.h" + +#define LOG_TAG_CONST APP_CHARGESTORE +#define LOG_TAG "[APP_CHARGESTORE]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#define CMD_TWS_CHANNEL_SET 0x01 +#define CMD_TWS_REMOTE_ADDR 0x02 +#define CMD_TWS_ADDR_DELETE 0x03 +#define CMD_BOX_TWS_CHANNEL_SEL 0x04//测试盒获取地址 +#define CMD_BOX_TWS_REMOTE_ADDR 0x05//测试盒交换地址 +#define CMD_POWER_LEVEL_OPEN 0x06//开盖充电舱报告/获取电量 +#define CMD_POWER_LEVEL_CLOSE 0x07//合盖充电舱报告/获取电量 +#define CMD_RESTORE_SYS 0x08//恢复出厂设置 +#define CMD_ENTER_DUT 0x09//进入测试模式 +#define CMD_EX_FIRST_READ_INFO 0x0A//F95读取数据首包信息 +#define CMD_EX_CONTINUE_READ_INFO 0x0B//F95读取数据后续包信息 +#define CMD_EX_FIRST_WRITE_INFO 0x0C//F95写入数据首包信息 +#define CMD_EX_CONTINUE_WRITE_INFO 0x0D//F95写入数据后续包信息 +#define CMD_EX_INFO_COMPLETE 0x0E//F95完成信息交换 +#define CMD_TWS_SET_CHANNEL 0x0F//F95设置左右声道信息 +#define CMD_BOX_UPDATE 0x20//测试盒升级 +#define CMD_BOX_MODULE 0x21//测试盒一级命令 + +#define CMD_SHUT_DOWN 0x80//充电舱关机,充满电关机,或者是低电关机 +#define CMD_CLOSE_CID 0x81//充电舱盒盖 +#define CMD_ANC_MODULE 0x90//ANC一级命令 +#define CMD_UNDEFINE 0xff//未知命令回复 + +//testbox sub cmd +#define CMD_BOX_BT_NAME_INFO 0x01 //获取蓝牙名 +#define CMD_BOX_SDK_VERSION 0x02 //获取sdk版本信息 +#define CMD_BOX_BATTERY_VOL 0x03 //获取电量 +#define CMD_BOX_ENTER_DUT 0x04 //进入dut模式 + +struct chargestore_info { + int timer; + int shutdown_timer; + u8 version; + u8 chip_type; + u8 max_packet_size;//充电舱端一包的最大值 + u8 bt_init_ok;//蓝牙协议栈初始化成功 + u8 power_level;//本机记录的充电舱电量百分比 + u8 pre_power_lvl; + u8 sibling_chg_lev;//对耳同步的充电舱电量 + u8 power_status;//充电舱供电状态 0:断电 5V不在线 1:升压 5V在线 + u8 cover_status;//充电舱盖子状态 0:合盖 1:开盖 + u8 testbox_status;//测试盒在线状态 + u8 connect_status;//通信成功 + u8 ear_number;//盒盖时耳机在线数 + u8 channel;//左右 + u8 tws_power;//对耳的电量 + u8 power_sync;//第一次获取到充电舱电量时,同步到对耳 + u8 pair_flag;//配对标记 + u8 close_ing;//等待合窗超时 + u8 active_disconnect;//主动断开连接 + u8 event_hdl_flag; + u8 switch2bt; +}; + +extern void sys_enter_soft_poweroff(void *priv); +//extern void bt_tws_cancle_wait_pair(); +extern int tws_api_cancle_wait_pair_internal(); +extern int tws_cancle_create_connection_internal(); +extern void tws_api_set_connect_aa_allways(u32 connect_aa); +extern u32 tws_le_get_pair_aa(void); +extern u32 tws_le_get_connect_aa(void); +extern u32 tws_le_get_search_aa(void); +extern void bt_page_scan_for_test(); +extern u8 get_jl_chip_id(void); +extern u8 get_jl_chip_id2(void); +extern void bt_get_vm_mac_addr(u8 *addr); +extern bool get_tws_sibling_connect_state(void); +extern bool get_tws_phone_connect_state(void); +extern void local_irq_disable(); +extern void cpu_reset(); +extern u32 dual_bank_update_exist_flag_get(void); +extern u32 classic_update_task_exist_flag_get(void); +extern void chargestore_api_set_timeout(u8 timeout); + + +#if TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE || TCFG_ANC_BOX_ENABLE + +static struct chargestore_info info; +#define __this (&info) +static u8 send_buf[36]; +static u8 local_packet[36]; +static CHARGE_STORE_INFO read_info, write_info; +static u8 read_index, write_index; + +#if TCFG_CHARGESTORE_ENABLE +void chargestore_clean_tws_conn_info(u8 type) +{ + CHARGE_STORE_INFO charge_store_info; + log_info("chargestore_clean_tws_conn_info=%d\n", type); + if (type == TWS_DEL_TWS_ADDR) { + log_info("TWS_DEL_TWS_ADDR\n"); + } else if (type == TWS_DEL_PHONE_ADDR) { + log_info("TWS_DEL_PHONE_ADDR\n"); + } else if (type == TWS_DEL_ALL_ADDR) { + log_info("TWS_DEL_ALL_ADDR\n"); + } + memset(&charge_store_info, 0xff, sizeof(CHARGE_STORE_INFO)); + syscfg_write(CFG_TWS_REMOTE_ADDR, charge_store_info.tws_remote_addr, sizeof(charge_store_info.tws_remote_addr)); +} +#endif + +#if TCFG_USER_TWS_ENABLE + +extern void bt_tws_remove_pairs(); +bool chargestore_set_tws_remote_info(u8 *data, u8 len) +{ + u8 i; + bool ret = true; + u8 remote_addr[6]; + u8 common_addr[6]; + u8 local_addr[6]; + CHARGE_STORE_INFO *charge_store_info = (CHARGE_STORE_INFO *)data; + if (len > sizeof(CHARGE_STORE_INFO)) { + log_error("len err\n"); + return false; + } + //set remote addr + syscfg_read(CFG_TWS_REMOTE_ADDR, remote_addr, sizeof(remote_addr)); + if (memcmp(remote_addr, charge_store_info->tws_local_addr, sizeof(remote_addr))) { + ret = false; + } + syscfg_write(CFG_TWS_REMOTE_ADDR, charge_store_info->tws_local_addr, sizeof(charge_store_info->tws_remote_addr)); + +#if (CONFIG_TWS_COMMON_ADDR_SELECT != CONFIG_TWS_COMMON_ADDR_USED_LEFT) + //set common addr + bt_get_tws_local_addr(local_addr); + syscfg_read(CFG_TWS_COMMON_ADDR, common_addr, sizeof(common_addr)); + + for (i = 0; i < sizeof(common_addr); i++) { + if (common_addr[i] != (u8)(local_addr[i] + charge_store_info->tws_local_addr[i])) { + ret = false; + } + common_addr[i] = local_addr[i] + charge_store_info->tws_local_addr[i]; + } + syscfg_write(CFG_TWS_COMMON_ADDR, common_addr, sizeof(common_addr)); +#endif + +#ifndef CONFIG_NEW_BREDR_ENABLE + if (__this->channel == 'L') { + if (tws_le_get_connect_aa() != tws_le_get_pair_aa()) { + ret = false; + } + tws_api_set_connect_aa_allways(tws_le_get_pair_aa()); + } else { + if (tws_le_get_connect_aa() != charge_store_info->pair_aa) { + ret = false; + } + tws_api_set_connect_aa_allways(charge_store_info->pair_aa); + } +#endif + if (__this->testbox_status) { + u8 cmd = CMD_BOX_TWS_REMOTE_ADDR; + chargestore_api_write(&cmd, 1); + + } + return ret; +} +#endif + +#define WRITE_LIT_U16(a,src) {*((u8*)(a)+1) = (u8)(src>>8); *((u8*)(a)+0) = (u8)(src&0xff); } +#define EXTEND_TWS_REMOTE_ADDR_SIZE (1 + sizeof(u16) + sizeof(u16)) +extern char tws_api_get_local_channel(); +extern u16 bt_get_tws_device_indicate(u8 *tws_device_indicate); +u16 chargestore_get_tws_remote_info(u8 *data) +{ + u16 ret_len = 0; + u16 device_ind; + u16 reserved_data = 0; + CHARGE_STORE_INFO *charge_store_info = (CHARGE_STORE_INFO *)data; + bt_get_tws_local_addr(charge_store_info->tws_local_addr); + bt_get_vm_mac_addr(charge_store_info->tws_mac_addr); +#ifndef CONFIG_NEW_BREDR_ENABLE + charge_store_info->search_aa = tws_le_get_search_aa(); + charge_store_info->pair_aa = tws_le_get_pair_aa(); +#endif + if (1 == __this->testbox_status) { +#if (CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_AS_LEFT_CHANNEL) \ + ||(CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_AS_RIGHT_CHANNEL) \ + ||(CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_EXTERN_DOWN_AS_LEFT) \ + ||(CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_EXTERN_UP_AS_LEFT) + data[sizeof(CHARGE_STORE_INFO)] = tws_api_get_local_channel(); +#else + data[sizeof(CHARGE_STORE_INFO)] = 'U'; +#endif + device_ind = bt_get_tws_device_indicate(NULL); + WRITE_LIT_U16(&data[sizeof(CHARGE_STORE_INFO) + 1], device_ind); + WRITE_LIT_U16(&data[sizeof(CHARGE_STORE_INFO) + 1 + 2], reserved_data); + //printf("tws_ch:%c %x\n", data[sizeof(CHARGE_STORE_INFO)], device_ind); + ret_len = sizeof(CHARGE_STORE_INFO) + EXTEND_TWS_REMOTE_ADDR_SIZE; + } else { + ret_len = sizeof(CHARGE_STORE_INFO); + } + + return ret_len; +} + +#if TCFG_CHARGESTORE_ENABLE +u16 chargestore_f95_read_tws_remote_info(u8 *data, u8 flag) +{ + u8 read_len; + u8 *pbuf = (u8 *)&read_info; + if (flag) {//first packet + read_index = 0; + chargestore_get_tws_remote_info((u8 *)&read_info); + } + read_len = sizeof(read_info) - read_index; + read_len = (read_len > (__this->max_packet_size - 1)) ? (__this->max_packet_size - 1) : read_len; + memcpy(data, pbuf + read_index, read_len); + read_index += read_len; + return read_len; +} + +u16 chargestore_f95_write_tws_remote_info(u8 *data, u8 len, u8 flag) +{ + u8 write_len; + u8 *pbuf = (u8 *)&write_info; + if (flag) { + write_index = 0; + memset(&write_info, 0, sizeof(write_info)); + } + write_len = sizeof(write_info) - write_index; + write_len = (write_len >= len) ? len : write_len; + memcpy(pbuf + write_index, data, write_len); + write_index += write_len; + return write_len; +} +#endif + +void chargestore_set_tws_channel_info(void) +{ + if ((__this->channel == 'L') || (__this->channel == 'R')) { + syscfg_write(CFG_CHARGESTORE_TWS_CHANNEL, &__this->channel, 1); + } +} + +#if TCFG_CHARGESTORE_ENABLE +void chargestore_timeout_deal(void *priv) +{ + __this->timer = 0; + __this->close_ing = 0; + if ((!__this->cover_status) || __this->active_disconnect) {//当前为合盖或者主动断开连接 + u8 app = app_get_curr_task(); + if (app == APP_IDLE_TASK) { + sys_enter_soft_poweroff((void *)1); + } + } else { + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) + + /* if ((!get_total_connect_dev()) && (tws_api_get_role() == TWS_ROLE_MASTER) && (get_bt_tws_connect_status())) { */ + if (tws_api_get_role() == TWS_ROLE_MASTER) { + printf("charge_icon_ctl...\n"); + bt_ble_icon_reset(); +#if CONFIG_NO_DISPLAY_BUTTON_ICON + if (get_total_connect_dev()) { + //蓝牙未真正断开;重新广播 + bt_ble_icon_open(ICON_TYPE_RECONNECT); + } else { + //蓝牙未连接,重新开可见性 + bt_ble_icon_open(ICON_TYPE_INQUIRY); + } +#else + //不管蓝牙是否连接,默认打开 + bt_ble_icon_open(ICON_TYPE_RECONNECT); +#endif + + } +#elif (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV_RCSP) + if (tws_api_get_role() == TWS_ROLE_MASTER) { + printf("charge_icon_ctl...\n"); +#if CONFIG_NO_DISPLAY_BUTTON_ICON + if (get_total_connect_dev()) { + //蓝牙未真正断开;重新广播 + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_CONNECTED, 1); + } else { + //蓝牙未连接,重新开可见性 + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_UNCONNECTED, 1); + } +#else + //不管蓝牙是否连接,默认打开 + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_CONNECTED, 1); +#endif + + } +#endif + + } + __this->ear_number = 1; +} + +void chargestore_set_phone_disconnect(void) +{ +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) +#if (!CONFIG_NO_DISPLAY_BUTTON_ICON) + if (__this->pair_flag && get_tws_sibling_connect_state()) { + //check ble inquiry + //printf("get box log_key...con_dev=%d\n",get_tws_phone_connect_state()); + if ((bt_ble_icon_get_adv_state() == ADV_ST_RECONN) + || (bt_ble_icon_get_adv_state() == ADV_ST_DISMISS) + || (bt_ble_icon_get_adv_state() == ADV_ST_END)) { + bt_ble_icon_reset(); + bt_ble_icon_open(ICON_TYPE_INQUIRY); + } + } +#endif + __this->pair_flag = 0; +#elif (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV_RCSP) +#if (!CONFIG_NO_DISPLAY_BUTTON_ICON) + if (__this->pair_flag && get_tws_sibling_connect_state()) { + //check ble inquiry + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_UNCONNECTED, 1); + } +#endif + __this->pair_flag = 0; +#endif +} + +void chargestore_set_phone_connect(void) +{ + __this->active_disconnect = 0; +} + +#endif + +int app_chargestore_event_handler(struct chargestore_event *chargestore_dev) +{ + int ret = false; + + u8 app = app_get_curr_task(); + +#if defined(TCFG_CHARGE_KEEP_UPDATA) && TCFG_CHARGE_KEEP_UPDATA + //在升级过程中,不响应智能充电舱app层消息 + if (dual_bank_update_exist_flag_get() || classic_update_task_exist_flag_get()) { + return ret; + } +#endif + + switch (chargestore_dev->event) { + case CMD_RESTORE_SYS: +#if (TCFG_AUDIO_ANC_ENABLE == ANC_RUN_MODE) + +#if TCFG_USER_TWS_ENABLE + bt_tws_remove_pairs(); +#endif + user_send_cmd_prepare(USER_CTRL_DEL_ALL_REMOTE_INFO, 0, NULL); + cpu_reset(); +#endif + break; +#if TCFG_TEST_BOX_ENABLE + case CMD_BOX_TWS_CHANNEL_SEL: + __this->event_hdl_flag = 0; + chargestore_set_tws_channel_info(); +#if TCFG_SYS_LVD_EN + if (get_vbat_need_shutdown() == TRUE) { + //电压过低,不进行测试 + break; + } +#endif +#if TCFG_APP_BT_EN + if (app != APP_BT_TASK) { + if (!app_var.goto_poweroff_flag) { + app_var.play_poweron_tone = 0; + task_switch_to_bt(); + } + } else { + if ((!__this->connect_status) && __this->bt_init_ok) { + log_info("\n\nbt_page_scan_for_test\n\n"); + __this->connect_status = 1; +#if TCFG_USER_TWS_ENABLE + bt_page_scan_for_test(); +#endif + } + } +#endif + break; +#if TCFG_USER_TWS_ENABLE + case CMD_BOX_TWS_REMOTE_ADDR: + log_info("event_CMD_BOX_TWS_REMOTE_ADDR \n"); + chargestore_set_tws_remote_info(chargestore_dev->packet, chargestore_dev->size); + break; +#endif +#endif +#if TCFG_CHARGESTORE_ENABLE + case CMD_TWS_CHANNEL_SET: + chargestore_set_tws_channel_info(); + break; +#if TCFG_USER_TWS_ENABLE + case CMD_TWS_REMOTE_ADDR: + log_info("event_CMD_TWS_REMOTE_ADDR\n"); + if (chargestore_set_tws_remote_info(chargestore_dev->packet, chargestore_dev->size) == false) { + //交换地址后,断开与手机连接,并删除所有连过的手机地址 + user_send_cmd_prepare(USER_CTRL_DEL_ALL_REMOTE_INFO, 0, NULL); + __this->ear_number = 2; + sys_enter_soft_poweroff((void *)1); + } else { + __this->pair_flag = 1; + if (get_tws_phone_connect_state() == TRUE) { + __this->active_disconnect = 1; + user_send_cmd_prepare(USER_CTRL_DISCONNECTION_HCI, 0, NULL); + } else { + chargestore_set_phone_disconnect(); + } + } + break; + case CMD_TWS_ADDR_DELETE: + log_info("event_CMD_TWS_ADDR_DELETE\n"); + chargestore_clean_tws_conn_info(chargestore_dev->packet[0]); + break; +#endif + case CMD_POWER_LEVEL_OPEN: + log_info("event_CMD_POWER_LEVEL_OPEN\n"); + + //电压过低,不进响应开盖命令 +#if TCFG_SYS_LVD_EN + if (get_vbat_need_shutdown() == TRUE) { + log_info(" lowpower deal!\n"); + break; + } +#endif + + if (__this->cover_status) {//当前为开盖 + if (__this->power_sync) { + if (chargestore_sync_chg_level() == 0) { + __this->power_sync = 0; + } + } + + if ((app == APP_IDLE_TASK) && (app_var.goto_poweroff_flag == 0)) { + /* app_var.play_poweron_tone = 1; */ + app_var.play_poweron_tone = 0; + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + __this->switch2bt = 1; + task_switch_to_bt(); + __this->switch2bt = 0; + } + } + break; + case CMD_POWER_LEVEL_CLOSE: + log_info("event_CMD_POWER_LEVEL_CLOSE\n"); + if (!__this->cover_status) {//当前为合盖 + if (app != APP_IDLE_TASK) { + sys_enter_soft_poweroff((void *)1); + } + } + break; + case CMD_CLOSE_CID: + log_info("event_CMD_CLOSE_CID\n"); + if (!__this->cover_status) {//当前为合盖 +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) + if ((__this->bt_init_ok) && (tws_api_get_role() == TWS_ROLE_MASTER)) { + bt_ble_icon_close(1); + } +#elif (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV_RCSP) + if ((__this->bt_init_ok) && (tws_api_get_role() == TWS_ROLE_MASTER)) { + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_DISMISS, 1); + } +#endif + if (!__this->timer) { + __this->timer = sys_timeout_add(NULL, chargestore_timeout_deal, 2000); + if (!__this->timer) { + log_error("timer alloc err!\n"); + } else { + __this->close_ing = 1; + } + } else { + sys_timer_modify(__this->timer, 2000); + __this->close_ing = 1; + } + } else { + __this->ear_number = 1; + __this->close_ing = 0; + } + break; +#endif + default: + break; + } + + return ret; +} + +#if TCFG_CHARGESTORE_ENABLE + +u8 chargestore_get_vbat_percent(void) +{ + u8 power; +#if CONFIG_DISPLAY_DETAIL_BAT + power = get_vbat_percent();//显示个位数的电量 +#else + power = get_self_battery_level() * 10 + 10; //显示10%~100% +#endif + +#if TCFG_CHARGE_ENABLE + if (get_charge_full_flag()) { + power = 100; + } else if (power == 100) { + power = 99; + } + if (get_charge_online_flag()) { + power |= BIT(7); + } +#endif + return power; +} + +void chargestore_set_power_status(u8 *buf, u8 len) +{ + __this->version = buf[0] & 0x0f; + __this->chip_type = (buf[0] >> 4) & 0x0f; + //f95可能传一个大于100的电量 + if ((buf[1] & 0x7f) > 100) { + __this->power_level = (buf[1] & 0x80) | 100; + } else { + __this->power_level = buf[1]; + } + if (len > 2) { + __this->max_packet_size = buf[2]; + if (len > 3) { + __this->tws_power = buf[3]; + } + } +} + +void chargestore_shutdown_do(void *priv) +{ + log_info("chargestore shutdown!\n"); + power_set_soft_poweroff(); +} + +#endif + + +void chargestore_event_to_user(u8 *packet, u32 type, u8 event, u8 size) +{ + struct sys_event e; + e.type = SYS_DEVICE_EVENT; + if (packet != NULL) { + if (size > sizeof(local_packet)) { + return; + } + e.u.chargestore.packet = local_packet; + memcpy(e.u.chargestore.packet, packet, size); + } + e.arg = (void *)type; + e.u.chargestore.event = event; + e.u.chargestore.size = size; + sys_event_notify(&e); +} + +extern const char *bt_get_local_name(); +extern u16 get_vbat_value(void); +extern const int config_btctler_eir_version_info_len; +extern const char *sdk_version_info_get(void); +void app_chargestore_testbox_sub_cmd_handle(u8 *buf, u8 len) +{ + u8 name_len; + u8 send_len = 0; + + send_buf[0] = buf[0]; + send_buf[1] = buf[1]; + + log_info("sub_cmd:%x\n", buf[1]); + + switch (buf[1]) { + case CMD_BOX_BT_NAME_INFO: + name_len = strlen(bt_get_local_name()); + if (name_len < (sizeof(send_buf) - 2)) { + memcpy(&send_buf[2], bt_get_local_name(), name_len); + send_len = name_len + 2; + chargestore_api_write(send_buf, send_len); + } else { + log_error("bt name buf len err\n"); + } + break; + + case CMD_BOX_BATTERY_VOL: + send_buf[2] = get_vbat_value(); + send_buf[3] = get_vbat_value() >> 8; + send_len = sizeof(u16) + 2; + log_info("bat_val:%x\n", get_vbat_value()); + chargestore_api_write(send_buf, send_len); + break; + + case CMD_BOX_SDK_VERSION: + if (config_btctler_eir_version_info_len) { + log_info("version:%s\n", sdk_version_info_get()); + memcpy(send_buf + 2, sdk_version_info_get(), config_btctler_eir_version_info_len); + send_len = config_btctler_eir_version_info_len + 2; + chargestore_api_write(send_buf, send_len); + } + break; + + case CMD_BOX_ENTER_DUT: + log_info("enter dut\n"); + if (!get_total_connect_dev()) { //未连接手机 + extern void bredr_set_dut_enble(u8 en, u8 phone); + bredr_set_dut_enble(1, 1); + } + chargestore_api_write(send_buf, 2); + break; + + default: + send_buf[0] = CMD_UNDEFINE; + send_len = 1; + chargestore_api_write(send_buf, send_len); + break; + } + + log_info_hexdump(send_buf, send_len); +} + +void app_chargestore_data_deal(u8 *buf, u8 len) +{ + //u8 send_buf[30]; + /* log_info_hexdump(buf, len); */ +#if TCFG_CHARGESTORE_ENABLE//有通信则关机定时器删掉 + chargestore_shutdown_reset(); +#endif + send_buf[0] = buf[0]; +#ifdef CONFIG_CHARGESTORE_REMAP_ENABLE + if (remap_app_chargestore_data_deal(buf, len)) { + return; + } +#endif + switch (buf[0]) { +#if TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE +#if TCFG_TEST_BOX_ENABLE + //case CMD_ENTER_DUT: + // __this->testbox_status = 1; + //log_info("enter_dut\n"); + //break; + + case CMD_BOX_MODULE: + app_chargestore_testbox_sub_cmd_handle(buf, len); + break; + + case CMD_BOX_UPDATE: + if (UPDATE_MODULE_IS_SUPPORT(UPDATE_UART_EN)) { + __this->testbox_status = 1; + if (buf[13] == get_jl_chip_id() || buf[13] == get_jl_chip_id2()) { + chargestore_set_update_ram(); + cpu_reset(); + } else { + send_buf[1] = 0x01;//chip id err + chargestore_api_write(send_buf, 2); + } + } + break; + case CMD_BOX_TWS_CHANNEL_SEL: + __this->testbox_status = 1; +#endif +#if TCFG_CHARGESTORE_ENABLE + case CMD_TWS_CHANNEL_SET: +#endif + __this->channel = (buf[1] == TWS_CHANNEL_LEFT) ? 'L' : 'R'; + if (0 == __this->event_hdl_flag) { + chargestore_event_to_user(NULL, DEVICE_EVENT_CHARGE_STORE, buf[0], 0); + __this->event_hdl_flag = 1; + } +#if TCFG_APP_BT_EN + if (__this->bt_init_ok) { + len = chargestore_get_tws_remote_info(&send_buf[1]); + chargestore_api_write(send_buf, len + 1); + } else { + send_buf[0] = CMD_UNDEFINE; + chargestore_api_write(send_buf, 1); + } +#else + len = chargestore_get_tws_remote_info(&send_buf[1]); + chargestore_api_write(send_buf, len + 1); +#endif + break; +#endif +#if TCFG_CHARGESTORE_ENABLE + case CMD_TWS_SET_CHANNEL: + __this->channel = (buf[1] == TWS_CHANNEL_LEFT) ? 'L' : 'R'; + log_info("f95 set channel = %c\n", __this->channel); + chargestore_event_to_user(NULL, DEVICE_EVENT_CHARGE_STORE, CMD_TWS_CHANNEL_SET, 0); + if (__this->bt_init_ok) { + chargestore_api_write(send_buf, 1); + } else { + send_buf[0] = CMD_UNDEFINE; + chargestore_api_write(send_buf, 1); + } + break; +#endif + +#if TCFG_USER_TWS_ENABLE +#if TCFG_TEST_BOX_ENABLE + case CMD_BOX_TWS_REMOTE_ADDR: + len -= EXTEND_TWS_REMOTE_ADDR_SIZE; + __this->testbox_status = 1; + __this->close_ing = 0; + chargestore_event_to_user((u8 *)&buf[1], DEVICE_EVENT_CHARGE_STORE, buf[0], len - 1); + chargestore_api_set_timeout(100); + break; +#endif +#if TCFG_CHARGESTORE_ENABLE + case CMD_TWS_REMOTE_ADDR: + __this->close_ing = 0; + chargestore_event_to_user((u8 *)&buf[1], DEVICE_EVENT_CHARGE_STORE, buf[0], len - 1); + chargestore_api_write(send_buf, 1); + break; + case CMD_EX_FIRST_READ_INFO: + log_info("read first!\n"); + __this->close_ing = 0; + len = chargestore_f95_read_tws_remote_info(&send_buf[1], 1); + chargestore_api_write(send_buf, len + 1); + break; + case CMD_EX_CONTINUE_READ_INFO: + log_info("read continue!\n"); + __this->close_ing = 0; + len = chargestore_f95_read_tws_remote_info(&send_buf[1], 0); + chargestore_api_write(send_buf, len + 1); + break; + case CMD_EX_FIRST_WRITE_INFO: + log_info("write first!\n"); + __this->close_ing = 0; + chargestore_f95_write_tws_remote_info(&buf[1], len - 1, 1); + chargestore_api_write(send_buf, 1); + break; + case CMD_EX_CONTINUE_WRITE_INFO: + log_info("write continue!\n"); + __this->close_ing = 0; + chargestore_f95_write_tws_remote_info(&buf[1], len - 1, 0); + chargestore_api_write(send_buf, 1); + break; + case CMD_EX_INFO_COMPLETE: + log_info("ex complete!\n"); + chargestore_event_to_user((u8 *)&write_info, DEVICE_EVENT_CHARGE_STORE, CMD_TWS_REMOTE_ADDR, sizeof(write_info)); + chargestore_api_write(send_buf, 1); + break; +#endif +#endif + +#if TCFG_CHARGESTORE_ENABLE + case CMD_TWS_ADDR_DELETE: + __this->close_ing = 0; + chargestore_event_to_user(&buf[1], DEVICE_EVENT_CHARGE_STORE, CMD_TWS_ADDR_DELETE, len - 1); + chargestore_api_write(send_buf, 1); + break; + case CMD_POWER_LEVEL_OPEN: + __this->power_status = 1; + __this->cover_status = 1; + __this->close_ing = 0; + if (__this->power_level == 0xff) { + __this->power_sync = 1; + } + chargestore_set_power_status(&buf[1], len - 1); + if (__this->power_level != __this->pre_power_lvl) { + __this->power_sync = 1; + } + __this->pre_power_lvl = __this->power_level; + send_buf[1] = chargestore_get_vbat_percent(); + send_buf[2] = chargestore_get_det_level(__this->chip_type); + chargestore_api_write(send_buf, 3); + //切模式过程中不发送消息,防止堆满消息 + if (__this->switch2bt == 0) { + chargestore_event_to_user(NULL, DEVICE_EVENT_CHARGE_STORE, CMD_POWER_LEVEL_OPEN, 0); + } + break; + case CMD_POWER_LEVEL_CLOSE: + __this->power_status = 1; + __this->cover_status = 0; + __this->close_ing = 0; + chargestore_set_power_status(&buf[1], len - 1); + send_buf[1] = chargestore_get_vbat_percent(); + send_buf[2] = chargestore_get_det_level(__this->chip_type); + chargestore_api_write(send_buf, 3); + chargestore_event_to_user(NULL, DEVICE_EVENT_CHARGE_STORE, CMD_POWER_LEVEL_CLOSE, 0); + break; + case CMD_SHUT_DOWN: + log_info("shut down\n"); + __this->power_status = 0; + __this->cover_status = 0; + __this->close_ing = 0; + chargestore_api_write(send_buf, 1); + __this->shutdown_timer = sys_hi_timer_add(NULL, chargestore_shutdown_do, 1000); + break; + case CMD_CLOSE_CID: + log_info("close cid\n"); + __this->power_status = 1; + __this->cover_status = 0; + __this->ear_number = buf[1]; + chargestore_api_write(send_buf, 1); + chargestore_event_to_user(NULL, DEVICE_EVENT_CHARGE_STORE, CMD_CLOSE_CID, 0); + break; + + case CMD_RESTORE_SYS: + r_printf("restore sys\n"); + __this->power_status = 1; + __this->cover_status = 1; + __this->close_ing = 0; + chargestore_api_write(send_buf, 1); + chargestore_event_to_user(NULL, DEVICE_EVENT_CHARGE_STORE, CMD_RESTORE_SYS, 0); + break; +#endif + +#if TCFG_ANC_BOX_ENABLE + case CMD_ANC_MODULE: + app_ancbox_module_deal(buf, len); + break; +#endif + default: + send_buf[0] = CMD_UNDEFINE; + chargestore_api_write(send_buf, 1); + break; + } +} + +#if TCFG_CHARGESTORE_ENABLE +u8 chargestore_get_power_level(void) +{ + if ((__this->power_level == 0xff) || + ((!get_charge_online_flag()) && + (__this->sibling_chg_lev != 0xff))) { + return __this->sibling_chg_lev; + } + return __this->power_level; +} + +u8 chargestore_get_power_status(void) +{ + return __this->power_status; +} + +u8 chargestore_get_cover_status(void) +{ + return __this->cover_status; +} + +u8 chargestore_get_earphone_online(void) +{ + return __this->ear_number; +} + +void chargestore_set_earphone_online(u8 ear_number) +{ + __this->ear_number = ear_number; +} + +void chargestore_set_pair_flag(u8 pair_flag) +{ + __this->pair_flag = pair_flag; +} + +void chargestore_set_active_disconnect(u8 active_disconnect) +{ + __this->active_disconnect = active_disconnect; +} + +u8 chargestore_get_earphone_pos(void) +{ + log_info("get_ear_channel = %c\n", __this->channel); + return __this->channel; +} + +u8 chargestore_get_sibling_power_level(void) +{ + return __this->tws_power; +} + + +#if TCFG_USER_TWS_ENABLE + + +static void set_tws_sibling_charge_level(void *_data, u16 len, bool rx) +{ + if (rx) { + u8 *data = (u8 *)_data; + chargestore_set_sibling_chg_lev(data[0]); + } +} + +REGISTER_TWS_FUNC_STUB(charge_level_stub) = { + .func_id = TWS_FUNC_ID_CHARGE_SYNC, + .func = set_tws_sibling_charge_level, +}; + +#endif + +int chargestore_sync_chg_level(void) +{ +#if TCFG_USER_TWS_ENABLE + int err = -1; + u8 app = app_get_curr_task(); + if (app == APP_BT_TASK) && ((!app_var.goto_poweroff_flag)) { + err = tws_api_send_data_to_sibling((u8 *)&__this->power_level, 1, + TWS_FUNC_ID_CHARGE_SYNC); + } + return err; +#else + return 0; +#endif +} + +void chargestore_set_sibling_chg_lev(u8 chg_lev) +{ + __this->sibling_chg_lev = chg_lev; +} + +void chargestore_set_power_level(u8 power) +{ + __this->power_level = power; +} + +u8 chargestore_check_going_to_poweroff(void) +{ + return __this->close_ing; +} + +void chargestore_shutdown_reset(void) +{ + if (__this->shutdown_timer) { + sys_hi_timer_del(__this->shutdown_timer); + __this->shutdown_timer = 0; + } +} + +#endif + +void chargestore_set_bt_init_ok(u8 flag) +{ + __this->bt_init_ok = flag; +} + +#if TCFG_TEST_BOX_ENABLE +u8 chargestore_get_connect_status(void) +{ + return __this->connect_status; +} + +void chargestore_clear_connect_status(void) +{ + __this->connect_status = 0; +} + +u8 chargestore_get_testbox_status(void) +{ + return __this->testbox_status; +} + +void chargestore_clear_testbox_status(void) +{ + __this->testbox_status = 0; + chargestore_clear_connect_status(); +} + +#endif + +CHARGESTORE_PLATFORM_DATA_BEGIN(chargestore_data) +.uart_irq = TCFG_CHARGESTORE_UART_ID, + .io_port = TCFG_CHARGESTORE_PORT, + CHARGESTORE_PLATFORM_DATA_END() + + __BANK_INIT + int app_chargestore_init(void) +{ + __this->power_status = 1; + __this->cover_status = 0; + __this->bt_init_ok = 0; + __this->testbox_status = 0; + __this->connect_status = 0; + __this->ear_number = 1; + __this->tws_power = 0xff; + __this->power_level = 0xff; + __this->sibling_chg_lev = 0xff; + __this->max_packet_size = 32; + __this->channel = 'U'; + __this->close_ing = 0; + __this->event_hdl_flag = 0; + __this->switch2bt = 0; + chargestore_api_init(&chargestore_data); + syscfg_read(CFG_CHARGESTORE_TWS_CHANNEL, &__this->channel, 1); + log_info("channel = %c\n", __this->channel); + return 0; +} +__initcall(app_chargestore_init); + +#endif + diff --git a/apps/soundbox/power_manage/app_power_manage.c b/apps/soundbox/power_manage/app_power_manage.c new file mode 100644 index 0000000..57c1bd0 --- /dev/null +++ b/apps/soundbox/power_manage/app_power_manage.c @@ -0,0 +1,514 @@ +#include "system/includes.h" +#include "app_power_manage.h" +#include "app_main.h" +#include "app_config.h" +#include "app_action.h" +#include "asm/charge.h" +#include "ui_manage.h" +#include "tone_player.h" +#include "asm/adc_api.h" +#include "btstack/avctp_user.h" +#include "user_cfg.h" +#include "bt.h" +#include "asm/charge.h" + +#if TCFG_USER_TWS_ENABLE +#include "bt_tws.h" +#endif + +#define LOG_TAG_CONST APP_POWER +#define LOG_TAG "[APP_POWER]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +enum { + VBAT_NORMAL = 0, + VBAT_WARNING, + VBAT_LOWPOWER, +} VBAT_STATUS; + +#define VBAT_DETECT_CNT 6 +static int vbat_slow_timer = 0; +static int vbat_fast_timer = 0; +static int lowpower_timer = 0; +static u8 old_battery_level = 9; +static u16 bat_val = 0; +static volatile u8 cur_battery_level = 0; +static u16 battery_full_value = 0; +static u8 tws_sibling_bat_level = 0xff; +static u8 tws_sibling_bat_percent_level = 0xff; +static u8 cur_bat_st = VBAT_NORMAL; + +void vbat_check(void *priv); +void sys_enter_soft_poweroff(void *priv); +void clr_wdt(void); +void power_event_to_user(u8 event); + + +u8 get_tws_sibling_bat_level(void) +{ +#if TCFG_USER_TWS_ENABLE + /* log_info("***********get_tws_sibling_bat_level: %2x", tws_sibling_bat_percent_level); */ + return tws_sibling_bat_level & 0x7f; +#endif + return 0xff; +} + +u8 get_tws_sibling_bat_persent(void) +{ +#if TCFG_USER_TWS_ENABLE + /* log_info("***********get_tws_sibling_bat_level: %2x", tws_sibling_bat_percent_level); */ + return tws_sibling_bat_percent_level; +#endif + return 0xff; +} + +void app_power_set_tws_sibling_bat_level(u8 vbat, u8 percent) +{ +#if TCFG_USER_TWS_ENABLE + tws_sibling_bat_level = vbat; + tws_sibling_bat_percent_level = percent; + /* + ** 发出电量同步事件进行进一步处理 + **/ + power_event_to_user(POWER_EVENT_SYNC_TWS_VBAT_LEVEL); + + log_info("set_sibling_bat_level: %d, %d\n", vbat, percent); +#endif +} + + +static void set_tws_sibling_bat_level(void *_data, u16 len, bool rx) +{ + u8 *data = (u8 *)_data; + + if (rx) { + app_power_set_tws_sibling_bat_level(data[0], data[1]); + } +} + +#if TCFG_USER_TWS_ENABLE +REGISTER_TWS_FUNC_STUB(vbat_sync_stub) = { + .func_id = TWS_FUNC_ID_VBAT_SYNC, + .func = set_tws_sibling_bat_level, +}; +#endif + +void tws_sync_bat_level(void) +{ +#if (TCFG_USER_TWS_ENABLE && BT_SUPPORT_DISPLAY_BAT) + u8 battery_level = cur_battery_level; +#if CONFIG_DISPLAY_DETAIL_BAT + u8 percent_level = get_vbat_percent(); +#else + u8 percent_level = get_self_battery_level() * 10 + 10; +#endif + if (get_charge_online_flag()) { + percent_level |= BIT(7); + } + + u8 data[2]; + data[0] = battery_level; + data[1] = percent_level; + tws_api_send_data_to_sibling(data, 2, TWS_FUNC_ID_VBAT_SYNC); + + log_info("tws_sync_bat_level: %d,%d\n", battery_level, percent_level); +#endif +} + +void power_event_to_user(u8 event) +{ + struct sys_event e; + e.type = SYS_DEVICE_EVENT; + e.arg = (void *)DEVICE_EVENT_FROM_POWER; + e.u.dev.event = event; + e.u.dev.value = 0; + sys_event_notify(&e); +} + +int app_power_event_handler(struct device_event *dev) +{ + int ret = false; + +#if(TCFG_SYS_LVD_EN == 1) + switch (dev->event) { + case POWER_EVENT_POWER_NORMAL: + ui_update_status(STATUS_EXIT_LOWPOWER); + if (lowpower_timer) { + sys_timer_del(lowpower_timer); + lowpower_timer = 0 ; + } + break; + case POWER_EVENT_POWER_WARNING: + /* ui_update_status(STATUS_LOWPOWER); */ + if (lowpower_timer == 0) { + lowpower_timer = sys_timer_add((void *)POWER_EVENT_POWER_WARNING, (void (*)(void *))power_event_to_user, LOW_POWER_WARN_TIME); + } + break; + case POWER_EVENT_POWER_LOW: + r_printf(" POWER_EVENT_POWER_LOW"); + vbat_timer_delete(); + if (lowpower_timer) { + sys_timer_del(lowpower_timer); + lowpower_timer = 0 ; + } +#if TCFG_APP_BT_EN +#if (RCSP_ADV_EN) + extern u8 adv_tws_both_in_charge_box(u8 type); + adv_tws_both_in_charge_box(1); +#endif + soft_poweroff_mode(1); ///强制关机 + sys_enter_soft_poweroff(NULL); +#else + void app_entry_idle() ; + app_entry_idle() ; +#ifdef CONFIG_BOARD_AC6083A + power_set_soft_poweroff(); +#endif + +#endif + break; +#if TCFG_APP_BT_EN +#if TCFG_USER_TWS_ENABLE + case POWER_EVENT_SYNC_TWS_VBAT_LEVEL: + if (tws_api_get_role() == TWS_ROLE_MASTER) { + user_send_cmd_prepare(USER_CTRL_HFP_CMD_UPDATE_BATTARY, 0, NULL); + } + break; +#endif + + case POWER_EVENT_POWER_CHANGE: + /* log_info("POWER_EVENT_POWER_CHANGE\n"); */ +#if TCFG_USER_TWS_ENABLE + if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) { + if (tws_api_get_tws_state()&TWS_STA_ESCO_OPEN) { + break; + } + tws_sync_bat_level(); + } +#endif + user_send_cmd_prepare(USER_CTRL_HFP_CMD_UPDATE_BATTARY, 0, NULL); +#endif + break; + case POWER_EVENT_POWER_CHARGE: + if (lowpower_timer) { + sys_timer_del(lowpower_timer); + lowpower_timer = 0 ; + } + break; + default: + break; + } +#endif + + return ret; +} + + +u16 get_vbat_level(void) +{ + //return 370; //debug + return (adc_get_voltage(AD_CH_VBAT) * 4 / 10); +} + +__attribute__((weak)) u8 remap_calculate_vbat_percent(u16 bat_val) +{ + return 0; +} + +u16 get_vbat_value(void) +{ + return bat_val; +} + +u8 get_vbat_percent(void) +{ + u16 tmp_bat_val; + u16 bat_val = get_vbat_level(); + if (battery_full_value == 0) { +#if TCFG_CHARGE_ENABLE + battery_full_value = (get_charge_full_value() - 100) / 10; //防止部分电池充不了这么高电量,充满显示未满的情况 +#else + battery_full_value = 420; +#endif + } + + if (bat_val <= app_var.poweroff_tone_v) { + return 0; + } + + tmp_bat_val = remap_calculate_vbat_percent(bat_val); + if (!tmp_bat_val) { + tmp_bat_val = ((u32)bat_val - app_var.poweroff_tone_v) * 100 / (battery_full_value - app_var.poweroff_tone_v); + if (tmp_bat_val > 100) { + tmp_bat_val = 100; + } + } + return (u8)tmp_bat_val; +} + +bool get_vbat_need_shutdown(void) +{ + if ((bat_val <= LOW_POWER_SHUTDOWN) || adc_check_vbat_lowpower()) { + return TRUE; + } + return FALSE; +} + +//将当前电量转换为1~9级发送给手机同步电量 +u8 battery_value_to_phone_level(u16 bat_val) +{ + u8 battery_level = 0; + u8 vbat_percent = get_vbat_percent(); + + if (vbat_percent < 5) { //小于5%电量等级为0,显示10% + return 0; + } + + battery_level = (vbat_percent - 5) / 10; + + return battery_level; +} + +//获取自身的电量 +u8 get_self_battery_level(void) +{ + return cur_battery_level; +} + +u8 get_cur_battery_level(void) +{ + u8 bat_lev = tws_sibling_bat_level & (~BIT(7)); +#if TCFG_USER_TWS_ENABLE + if (bat_lev == 0x7f) { + return cur_battery_level; + } + +#if (CONFIG_DISPLAY_TWS_BAT_TYPE == CONFIG_DISPLAY_TWS_BAT_LOWER) + return cur_battery_level < bat_lev ? cur_battery_level : bat_lev; +#elif (CONFIG_DISPLAY_TWS_BAT_TYPE == CONFIG_DISPLAY_TWS_BAT_HIGHER) + return cur_battery_level < bat_lev ? bat_lev : cur_battery_level; +#elif (CONFIG_DISPLAY_TWS_BAT_TYPE == CONFIG_DISPLAY_TWS_BAT_LEFT) + return tws_api_get_local_channel() == 'L' ? cur_battery_level : bat_lev; +#elif (CONFIG_DISPLAY_TWS_BAT_TYPE == CONFIG_DISPLAY_TWS_BAT_RIGHT) + return tws_api_get_local_channel() == 'R' ? cur_battery_level : bat_lev; +#else + return cur_battery_level; +#endif //END CONFIG_DISPLAY_TWS_BAT_TYPE + +#else //TCFG_USER_TWS_ENABLE == 0 + return cur_battery_level; +#endif +} + +void vbat_check_slow(void *priv) +{ + if (vbat_fast_timer == 0) { + vbat_fast_timer = usr_timer_add(NULL, vbat_check, 10, 1); + } + if (get_charge_online_flag()) { + sys_timer_modify(vbat_slow_timer, 60 * 1000); + } else { + sys_timer_modify(vbat_slow_timer, 10 * 1000); + } +} + +void vbat_check_init(void) +{ + if (vbat_slow_timer == 0) { + vbat_slow_timer = sys_timer_add(NULL, vbat_check_slow, 10 * 1000); + } else { + sys_timer_modify(vbat_slow_timer, 10 * 1000); + } + + if (vbat_fast_timer == 0) { + vbat_fast_timer = usr_timer_add(NULL, vbat_check, 10, 1); + } +} + +void vbat_timer_delete(void) +{ + if (vbat_slow_timer) { + sys_timer_del(vbat_slow_timer); + vbat_slow_timer = 0; + } + if (vbat_fast_timer) { + usr_timer_del(vbat_fast_timer); + vbat_fast_timer = 0; + } +} + +void vbat_check(void *priv) +{ + static u8 unit_cnt = 0; + static u8 low_warn_cnt = 0; + static u8 low_off_cnt = 0; + static u8 low_voice_cnt = 0; + static u8 low_power_cnt = 0; + static u8 power_normal_cnt = 0; + static u8 charge_ccvol_v_cnt = 0; + static u8 charge_online_flag = 0; + static u8 low_voice_first_flag = 1;//进入低电后先提醒一次 + + if (!bat_val) { + bat_val = get_vbat_level(); + } else { + bat_val = (get_vbat_level() + bat_val) / 2; + } + + cur_battery_level = battery_value_to_phone_level(bat_val); + + //printf("bv:%d, bl:%d , check_vbat:%d\n", bat_val, cur_battery_level, adc_check_vbat_lowpower()); + + unit_cnt++; + + /* if (bat_val < LOW_POWER_OFF_VAL) { */ + if (adc_check_vbat_lowpower() || (bat_val <= app_var.poweroff_tone_v)) { + low_off_cnt++; + } + /* if (bat_val < LOW_POWER_WARN_VAL) { */ + if (bat_val <= app_var.warning_tone_v) { + low_warn_cnt++; + } +#if TCFG_CHARGE_ENABLE + if (bat_val >= CHARGE_CCVOL_V) { + charge_ccvol_v_cnt++; + } +#endif + + /* log_info("unit_cnt:%d\n", unit_cnt); */ + + if (unit_cnt >= VBAT_DETECT_CNT) { + + if (get_charge_online_flag() == 0) { + if (low_off_cnt > (VBAT_DETECT_CNT / 2)) { //低电关机 + low_power_cnt++; + low_voice_cnt = 0; + power_normal_cnt = 0; + cur_bat_st = VBAT_LOWPOWER; + if (low_power_cnt > 6) { + log_info("\n*******Low Power,enter softpoweroff********\n"); + + low_power_cnt = 0; + power_event_to_user(POWER_EVENT_POWER_LOW); + usr_timer_del(vbat_fast_timer); + vbat_fast_timer = 0; + } + } else if (low_warn_cnt > (VBAT_DETECT_CNT / 2)) { //低电提醒 + low_voice_cnt ++; + low_power_cnt = 0; + power_normal_cnt = 0; + cur_bat_st = VBAT_WARNING; + if ((low_voice_first_flag && low_voice_cnt > 1) || //第一次进低电10s后报一次 + (!low_voice_first_flag && low_voice_cnt >= 5)) { + low_voice_first_flag = 0; + low_voice_cnt = 0; + if (!lowpower_timer) { + log_info("\n**Low Power,Please Charge Soon!!!**\n"); + power_event_to_user(POWER_EVENT_POWER_WARNING); + } + } + } else { + power_normal_cnt++; + low_voice_cnt = 0; + low_power_cnt = 0; + if (power_normal_cnt > 2) { + if (cur_bat_st != VBAT_NORMAL) { + log_info("[Noraml power]\n"); + cur_bat_st = VBAT_NORMAL; + power_event_to_user(POWER_EVENT_POWER_NORMAL); + } + } + } + } else { + power_event_to_user(POWER_EVENT_POWER_CHARGE); +#if TCFG_CHARGE_ENABLE + if (charge_ccvol_v_cnt > (VBAT_DETECT_CNT / 2)) { + set_charge_mA(get_charge_mA_config()); + } +#endif + } + + unit_cnt = 0; + low_off_cnt = 0; + low_warn_cnt = 0; + charge_ccvol_v_cnt = 0; + + if (cur_bat_st != VBAT_LOWPOWER) { + usr_timer_del(vbat_fast_timer); + vbat_fast_timer = 0; + cur_battery_level = battery_value_to_phone_level(bat_val); + if (cur_battery_level != old_battery_level) { + power_event_to_user(POWER_EVENT_POWER_CHANGE); + } else { + if (charge_online_flag != get_charge_online_flag()) { + //充电变化也要交换,确定是否在充电仓 + power_event_to_user(POWER_EVENT_POWER_CHANGE); + } + } + charge_online_flag = get_charge_online_flag(); + old_battery_level = cur_battery_level; + } + } +} + +bool vbat_is_low_power(void) +{ + return (cur_bat_st != VBAT_NORMAL); +} + +void check_power_on_voltage(void) +{ +#if(TCFG_SYS_LVD_EN == 1) + + u16 val = 0; + u8 normal_power_cnt = 0; + u8 low_power_cnt = 0; + + while (1) { + clr_wdt(); + val = get_vbat_level(); + printf("vbat: %d\n", val); + if ((val < app_var.poweroff_tone_v) || adc_check_vbat_lowpower()) { + low_power_cnt++; + normal_power_cnt = 0; + if (low_power_cnt > 10) { + ui_update_status(STATUS_POWERON_LOWPOWER); + os_time_dly(100); + log_info("power on low power , enter softpoweroff!\n"); + power_set_soft_poweroff(); + } + } else { + normal_power_cnt++; + low_power_cnt = 0; + if (normal_power_cnt > 10) { + vbat_check_init(); + return; + } + } + } +#endif +} + + +#if(CONFIG_CPU_BR25) +void app_reset_vddiom_lev(u8 lev) +{ + if (TCFG_LOWPOWER_VDDIOM_LEVEL == VDDIOM_VOL_34V) { + /* printf("\n\n\n\n\n -------------------set vddiom again %d -----------------------\n\n\n\n\n",lev); */ + reset_vddiom_lev(lev); + } +} +#else +void app_reset_vddiom_lev(u8 lev) +{ + +} +#endif + + + diff --git a/apps/soundbox/sdk_version.z.S b/apps/soundbox/sdk_version.z.S new file mode 100644 index 0000000..e6a1a45 --- /dev/null +++ b/apps/soundbox/sdk_version.z.S @@ -0,0 +1,5 @@ +.section .sys.version, "ax" + +.long 194498644 +//.asciz "????-@20220301-$ba93110" +.asciz "AC695N_V310-@20220301-$ba93110" diff --git a/apps/soundbox/smartbox/browser/browser.c b/apps/soundbox/smartbox/browser/browser.c new file mode 100644 index 0000000..75645ba --- /dev/null +++ b/apps/soundbox/smartbox/browser/browser.c @@ -0,0 +1,416 @@ +#include "browser/browser.h" +#include "smartbox/smartbox.h" +#include "dev_manager.h" +#include "music_player.h" +#include "music/music.h" +#include "file_operate/file_bs_deal.h" +#include "smartbox/event.h" + +#define FILE_BROWSE_BUF_LEN 250//要小于RCSP MTU, 不要随意改大 +#define FILE_BROWSE_NAME_MAX_LIMIT 128//限制最大文件夹名称大小 + +#define FILE_BROWSE_TASK_NAME "file_bs" +#define MAX_DEEPTH 9/* 0~9 deepth of system */ + + +enum { + BS_FLODER = 0, + BS_FILE, +}; + +enum { + BS_UNICODE = 0, + BS_ANSI, +}; + +static const char *dev_logo[] = { + [BS_UDISK] = "udisk0", + [BS_SD0] = "sd0", + [BS_SD1] = "sd1", + [BS_FLASH] = "flash", +}; + +#pragma pack(1) +struct __browser { + u8 path_type;/// + u8 read_file_num; + u16 start_num; + u32 dev_handle; + u16 path_len; + u32 path_clust[MAX_DEEPTH]; +}; + +struct JL_FILE_DATA { + u8 type : 1; + u8 format : 1; + u8 device : 2; + u8 reserve : 4; + + u32 clust; + u16 file_num; + u8 name_len; + u8 file_data[0]; +}; +#pragma pack() + + + +static const char dec_file_ext[][3] = { +#if (TCFG_DEC_MP3_ENABLE) + {"MP1"}, + {"MP2"}, + {"MP3"}, +#endif + +#if (TCFG_DEC_WMA_ENABLE) + {"WMA"}, +#endif + +#if (TCFG_DEC_WAV_ENABLE || TCFG_DEC_DTS_ENABLE) + {"WAV"}, +#endif + +#if (TCFG_DEC_FLAC_ENABLE) + {"FLA"}, +#endif + +#if (TCFG_DEC_APE_ENABLE) + {"APE"}, +#endif + +#if (TCFG_DEC_DECRYPT_ENABLE) + {"SMP"}, +#endif + +#if (TCFG_DEC_AMR_ENABLE) + {"AMR"}, +#endif + +#if (TCFG_DEC_M4A_ENABLE) + {"M4A"}, + {"AAC"}, +#endif +#if (TCFG_DEC_M4A_ENABLE || TCFG_DEC_ALAC_ENABLE) + {"MP4"}, +#endif + {'\0'}, +}; + +static struct __browser *browser = NULL; + +char *smartbox_browser_file_ext(void) +{ + return (char *)dec_file_ext; +} + +u16 smartbox_browser_file_ext_size(void) +{ + return strlen((const char *)dec_file_ext); +} + +char *smartbox_browser_dev_remap(u32 index) +{ + if (index >= BS_DEV_MAX) { + return NULL; + } + return (char *)dev_logo[index]; +} + +u16 file_name_cut(u8 *name, u16 len, u16 len_limit) +{ + u8 ex_type[8]; + u8 three_point_hex[] = {0x2E, 0x00, 0x2E, 0x00, 0x2E, 0x00}; //... 显示unicode码 + if (len > len_limit) { + memcpy(name + len_limit - sizeof(three_point_hex), three_point_hex, sizeof(three_point_hex)); + return len_limit; + } + return len; +} + +static bool browser_get_dir_info(FILE_BS_DEAL *fil_bs, u8 *path_buf, u16 len, u8 type, void *ptr) +{ + s16 ret = 0; + u16 i, j = 0; + u32 deep_clust = 0; + FS_DIR_INFO dir_info; + //open root + ret = file_bs_entern_dir(fil_bs, NULL); + if (ret == 0) { + goto end; + } + + if (len == 4 && type == BS_FLODER) { + /* printf("root deep\n"); */ + if (ptr) { + *((u32 *)ptr) = ret; + } + goto end; + } else if (len == 4 && type == BS_FILE) { + /* printf("play file path\n"); */ + memcpy((u8 *)&deep_clust, path_buf, 4); + deep_clust = app_ntohl(deep_clust); + if (ptr) { + *((u32 *)ptr) = deep_clust; + } + goto end; + } + //deep check + u8 deep = len / 4; + if (deep > MAX_DEEPTH) { + printf("deep err : %d\n", deep); + return false; + } + /* printf("get deep%d data\n", deep - 1); */ + for (i = 1; i < deep; i++) { + memcpy((u8 *)&deep_clust, path_buf + 4 * i, 4); + deep_clust = app_ntohl(deep_clust); + /* printf("deep_clust:%x\n", deep_clust); */ + for (j = 1; j < ret + 1; j++) { + /* file_browse_get_dir(obj, (void *)&dir_info, j, 1); */ + file_bs_get_dir_info(fil_bs, &dir_info, j, 1); + if (dir_info.sclust == deep_clust) { + break; + } + } + if (i < deep - 1) { + ret = file_bs_entern_dir(fil_bs, &dir_info); + if (ret == 0) { + goto end; + } + } + } + if (type == BS_FILE) { + if (ptr) { + *((u32 *)ptr) = dir_info.sclust; //file return clust + } + goto end; + } else { + ret = file_bs_entern_dir(fil_bs, &dir_info); + if (ret == 0) { + goto end; + } + + if (ptr) { + *((u32 *)ptr) = ret; //file return clust + } + } +end: + return true; +} + +static u32 browse_open_dir(FILE_BS_DEAL *fil_bs, u8 *path_buf, u16 len) +{ + u32 file_cnt = 0; + browser_get_dir_info(fil_bs, path_buf, len, BS_FLODER, (void *)&file_cnt); + return file_cnt; +} + +static void file_printf_dir(FS_DIR_INFO *dir_inf, u8 cnt) +{ + u8 i; + LONG_FILE_NAME *l_name_pt; + + for (i = 0; i < cnt; i++) { + /* printf("file type %d nt:%d clust %x \n", dir_inf[i].dir_type, dir_inf[i].fn_type, dir_inf[i].sclust); */ + l_name_pt = &dir_inf[i].lfn_buf; + if (dir_inf[i].fn_type == BS_FNAME_TYPE_SHORT) { + file_comm_display_83name((void *)&l_name_pt->lfn[32], (void *)l_name_pt->lfn); + strcpy(l_name_pt->lfn, &l_name_pt->lfn[32]); + l_name_pt->lfn_cnt = strlen(l_name_pt->lfn); + printf("%s\n", l_name_pt->lfn); + } else { + if (l_name_pt->lfn_cnt > 510) { + l_name_pt->lfn_cnt = 510; + puts("***get long name err!!!"); + } + l_name_pt->lfn_cnt = file_comm_long_name_fix((void *)l_name_pt->lfn, l_name_pt->lfn_cnt); + l_name_pt->lfn[l_name_pt->lfn_cnt] = 0; + l_name_pt->lfn[l_name_pt->lfn_cnt + 1] = 0; + + /* printf("file name len : %d \n", l_name_pt->lfn_cnt); */ + /* put_buf((u8 *)l_name_pt->lfn, l_name_pt->lfn_cnt); */ + } + } +} +static u16 add_one_iterm_to_sendbuf(u8 *dest, u16 max_buf_len, u16 offset, FS_DIR_INFO *p_dir_info, u16 file_cnt, u8 dev_type) +{ + struct JL_FILE_DATA file_data; + memset((u8 *)&file_data, 0, sizeof(struct JL_FILE_DATA)); + + + file_data.type = p_dir_info->dir_type; + + if (p_dir_info->fn_type == BS_FNAME_TYPE_SHORT) { + file_data.format = BS_ANSI; + } else { + file_data.format = BS_UNICODE; + } + + ///限制文件名长度 + p_dir_info->lfn_buf.lfn_cnt = file_name_cut((u8 *)p_dir_info->lfn_buf.lfn, p_dir_info->lfn_buf.lfn_cnt, FILE_BROWSE_NAME_MAX_LIMIT); + + file_data.device = dev_type; + file_data.clust = app_htonl(p_dir_info->sclust); + file_data.file_num = app_htons(file_cnt); + file_data.name_len = p_dir_info->lfn_buf.lfn_cnt; + + memcpy(dest + offset, (u8 *)&file_data, sizeof(struct JL_FILE_DATA)); + memcpy(dest + offset + sizeof(struct JL_FILE_DATA), (u8 *)p_dir_info->lfn_buf.lfn, p_dir_info->lfn_buf.lfn_cnt); + + /* printf("add send data:"); */ + /* put_buf(dest+offset,p_dir_info->lfn_buf.lfn_cnt + sizeof(struct JL_FILE_DATA)); */ + return (p_dir_info->lfn_buf.lfn_cnt + sizeof(struct JL_FILE_DATA)); +} + +static void smartbox_browser_task(void *p) +{ + u8 reason = 0; + u32 play_file_clust = 0; + FS_DIR_INFO dir_info; + FILE_BS_DEAL fil_bs; + u8 *path_data = NULL; + + memset((u8 *)&dir_info, 0, sizeof(FS_DIR_INFO)); + memset((u8 *)&fil_bs, 0, sizeof(FILE_BS_DEAL)); + + fil_bs.dev = dev_manager_find_spec(smartbox_browser_dev_remap(browser->dev_handle), 0); + if (fil_bs.dev == NULL) { + reason = 1; + printf("dev nofound!!!\n"); + goto _EXIT; + } + file_bs_open_handle(&fil_bs, (u8 *)smartbox_browser_file_ext()); + + u32 dir_file_cnt = browse_open_dir(&fil_bs, (u8 *)browser->path_clust, browser->path_len); + if (browser->start_num + browser->read_file_num >= dir_file_cnt) { + printf("file range err\n"); + reason = 1; + browser->read_file_num = dir_file_cnt - browser->start_num + 1; + /* goto _EXIT; */ + } + /* printf("start num:%d read file num:%d\n", browser->start_num, browser->read_file_num); */ + + u16 offset = 0; + u32 ret = 0; + path_data = (u8 *)zalloc(FILE_BROWSE_BUF_LEN); + if (path_data == NULL) { + reason = 1; + printf("no ram for path_data!! \n"); + goto _EXIT; + } + for (int i = browser->start_num ; i < (browser->start_num + browser->read_file_num); i++) { + ret = file_bs_get_dir_info(&fil_bs, &dir_info, i, 1); + if (!ret) { + break; + } + + file_printf_dir(&dir_info, 1); + if (offset && ((offset + dir_info.lfn_buf.lfn_cnt + sizeof(struct JL_FILE_DATA)) > FILE_BROWSE_BUF_LEN)) { + ///如果buf不够填充了, 先将数据发送了先,再重新填充 + ret = JL_DATA_send(JL_OPCODE_DATA, JL_OPCODE_FILE_BROWSE_REQUEST_START, path_data, offset, JL_NOT_NEED_RESPOND); + if (ret) { + printf("send data err: %d, %d\n", ret, offset); + goto _EXIT; + } + //reset send buf + offset = 0; + memset(path_data, 0, FILE_BROWSE_BUF_LEN); + offset += add_one_iterm_to_sendbuf(path_data, FILE_BROWSE_BUF_LEN, offset, &dir_info, i, browser->dev_handle); + } else { + offset += add_one_iterm_to_sendbuf(path_data, FILE_BROWSE_BUF_LEN, offset, &dir_info, i, browser->dev_handle); + } + } + + //send last package + if (offset) { + ret = JL_DATA_send(JL_OPCODE_DATA, JL_OPCODE_FILE_BROWSE_REQUEST_START, path_data, offset, JL_NOT_NEED_RESPOND); + if (ret) { + printf("send data err: %d\n", ret); + goto _EXIT; + } + } + +_EXIT: + file_bs_close_handle(&fil_bs); + if (path_data) { + free(path_data); + } + smartbox_msg_post( + USER_MSG_SMARTBOX_BS_END, + 4, + (int)smartbox_handle_get(), + (int)reason, + (int)smartbox_browser_dev_remap(browser->dev_handle), + (int)play_file_clust); + + while (1) { + os_time_dly(10); + } +} + +void smartbox_browser_start(u8 *data, u16 len) +{ + ///检查数据是否有效 + if (len > sizeof(struct __browser)) { + return ; + } + ///创建数据解析句柄 + browser = (struct __browser *)zalloc(sizeof(struct __browser)); + if (browser == NULL) { + return ; + } + ///解析数据 + memcpy((u8 *)browser, data, sizeof(struct __browser)); + browser->start_num = app_ntohs(browser->start_num); + browser->dev_handle = app_ntohl(browser->dev_handle); + browser->path_len = app_ntohs(browser->path_len); + ///检查设备范围 + if (browser->dev_handle >= BS_DEV_MAX) { + printf("bs dev hdl err !!\n"); + free(browser); + browser = NULL; + return ; + } + ///检查是否是已经选定好文件播放 + if (browser->path_type) { + u8 reason = 2; + u32 play_file_clust = app_ntohl(browser->path_clust[0]); + smartbox_msg_post( + USER_MSG_SMARTBOX_BS_END, + 4, + (int)smartbox_handle_get(), + (int)reason, + (int)smartbox_browser_dev_remap(browser->dev_handle), + (int)play_file_clust); + return ; + } + ///目录浏览线程创建 + if (task_create(smartbox_browser_task, (void *)NULL, FILE_BROWSE_TASK_NAME)) { + free(browser); + browser = NULL; + printf("smartbox_browser_task creat fail\n"); + } +} + +bool smartbox_browser_busy(void) +{ + if (browser) { + return false; + } else { + return true; + } +} + + +void smartbox_browser_stop(void) +{ + ///删除线程,释放资源 + task_kill(FILE_BROWSE_TASK_NAME); + if (browser) { + free(browser); + browser = NULL; + } +} + + + diff --git a/apps/soundbox/smartbox/browser/browser.h b/apps/soundbox/smartbox/browser/browser.h new file mode 100644 index 0000000..1c46481 --- /dev/null +++ b/apps/soundbox/smartbox/browser/browser.h @@ -0,0 +1,33 @@ +#ifndef __BROWSER_H__ +#define __BROWSER_H__ + +#include "typedef.h" +#include "app_config.h" + +///smartbox 对应的设备id枚举 +enum { + BS_UDISK = 0, + BS_SD0, + BS_SD1, + BS_FLASH, + BS_AUX, + BS_DEV_MAX, +}; + +//smartbox浏览设备映射 +char *smartbox_browser_dev_remap(u32 index); +//smartbox获取文件浏览后缀配置 +char *smartbox_browser_file_ext(void); +//smartbox获取文件浏览后缀配置数据长度 +u16 smartbox_browser_file_ext_size(void); +//smartbox限制文件名长度(包括文件夹,如:xxx~~~, 省略以"~~~"表示) +u16 file_name_cut(u8 *name, u16 len, u16 len_limit); +//smartbox文件浏览开始 +void smartbox_browser_start(u8 *data, u16 len); +//smartbox文件浏览停止 +void smartbox_browser_stop(void); +//smartbox文件浏览繁忙查询 +bool smartbox_browser_busy(void); + +#endif//__SMARTBOX_H__ + diff --git a/apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_adv.c b/apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_adv.c new file mode 100644 index 0000000..48407b0 --- /dev/null +++ b/apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_adv.c @@ -0,0 +1,837 @@ +/********************************************************************************************* + * Filename : le_server_module.c + + * Description : + + * Author : + + * Email : zh-jieli.com + + * Last modifiled : 2017-01-17 11:14 + + * Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved. +*********************************************************************************************/ + +// ***************************************************************************** +/* EXAMPLE_START(le_counter): LE Peripheral - Heartbeat Counter over GATT + * + * @text All newer operating systems provide GATT Client functionality. + * The LE Counter examples demonstrates how to specify a minimal GATT Database + * with a custom GATT Service and a custom Characteristic that sends periodic + * notifications. + */ +// ***************************************************************************** +#include "system/app_core.h" +#include "system/includes.h" +#include "smartbox/config.h" + +#include "app_action.h" + +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "user_cfg.h" +#include "vm.h" +#include "app_power_manage.h" +#include "btcontroller_modules.h" +#include "bt_common.h" +#include "3th_profile_api.h" +#include "btstack/avctp_user.h" +#include "app_chargestore.h" + +#include "btcrypt.h" +#include "custom_cfg.h" +#include "smartbox_music_info_setting.h" +#include "classic/tws_api.h" +#include "le_smartbox_module.h" +#include "smartbox_rcsp_manage.h" +#include "bt/bt_tws.h" + +#include "asm/charge.h" + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_RCSP_DEMO) + + +#if 1 +extern void printf_buf(u8 *buf, u32 len); +#define log_info printf +#define log_info_hexdump printf_buf +#else +#define log_info(...) +#define log_info_hexdump(...) +#endif + +static u8 adv_data_len; +static u8 adv_data[ADV_RSP_PACKET_MAX];//max is 31 +static u8 scan_rsp_data_len; +static u8 scan_rsp_data[ADV_RSP_PACKET_MAX];//max is 31 +static u32 ble_timer_handle = 0; +u16 sibling_ver_info = 0; + +#define BLE_TIMER_SET (500) + +struct _bt_adv_handle { + + u8 seq_rand; + u8 connect_flag; + + u8 bat_charge_L; + u8 bat_charge_R; + u8 bat_charge_C; + u8 bat_percent_L; + u8 bat_percent_R; + u8 bat_percent_C; + + u8 modify_flag; + u8 adv_disable_cnt; + + u8 ble_adv_notify; +} bt_adv_handle = {0}; + +#define __this (&bt_adv_handle) + +extern u8 get_tws_sibling_bat_persent(void); + +u8 get_adv_notify_state(void) +{ + return __this->ble_adv_notify; +} + +void set_adv_notify_state(u8 notify) +{ + __this->ble_adv_notify = notify; +} + +static void rcsp_adv_fill_mac_addr(u8 *mac_addr_buf) +{ +#if (MUTIl_CHARGING_BOX_EN) + extern u8 *get_chargebox_adv_addr(void); + u8 *mac_addr = get_chargebox_adv_addr(); + if (mac_addr) { + swapX(mac_addr, mac_addr_buf, 6); + } + + /* printf("mac_addr:"); */ + /* printf_buf(mac_addr_buf, 6); */ + +#else + swapX(bt_get_mac_addr(), mac_addr_buf, 6); +#endif +} + +int smartbox_make_set_adv_data(void) +{ + u8 i; + u8 *buf = adv_data; + buf[0] = 0x1E; + buf[1] = 0xFF; + + buf[2] = 0xD6; // JL ID + buf[3] = 0x05; + +#if 1 + u16 vid = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG); + buf[4] = vid & 0xFF; + buf[5] = vid >> 8; + + u16 pid = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG); + buf[6] = pid & 0xFF; + buf[7] = pid >> 8; +#else + buf[4] = 0x02; // VID + buf[5] = 0x00; + + buf[6] = 0x33; // PID + buf[7] = 0x00; +#endif + +#if (MUTIl_CHARGING_BOX_EN) + buf[8] = 0x01; // 0:音箱类型 | protocol verson +#else // MUTIl_CHARGING_BOX_EN +#if (SOUNDCARD_ENABLE) + buf[8] = 0x40; // 4:声卡类型 | protocol verson +#else + buf[8] = 0x0; // 0:音箱类型 | protocol verson +#endif + if (RCSP_SPP == get_defalut_bt_channel_sel()) { + buf[8] |= 2; + } +#endif // MUTIl_CHARGING_BOX_EN end + + rcsp_adv_fill_mac_addr(&buf[9]); + buf[15] = __this->connect_flag; + + /* buf[16] = 0xC1; */ + /* buf[17] = 0x40; */ + /* buf[18] = 0x30; */ + buf[16] = __this->bat_percent_L ? (((!!__this->bat_charge_L) << 7) | (__this->bat_percent_L & 0x7F)) : 0; + buf[17] = __this->bat_percent_R ? (((!!__this->bat_charge_R) << 7) | (__this->bat_percent_R & 0x7F)) : 0; + buf[18] = __this->bat_percent_C ? (((!!__this->bat_charge_C) << 7) | (__this->bat_percent_C & 0x7F)) : 0; + + memset(&buf[19], 0x00, 4); // reserve + + buf[19] = __this->seq_rand; + +#if (MUTIl_CHARGING_BOX_EN) + buf[20] = 1; +#else + if (RCSP_SPP == get_defalut_bt_channel_sel()) { + buf[20] = 1; + } +#endif + + u8 t_buf[16]; + btcon_hash(&buf[2], 16, &buf[15], 4, t_buf); // hash + + for (i = 0; i < 8; i++) { // single byte + buf[23 + i] = t_buf[2 * i + 1]; + } + + __this->modify_flag = 0; + adv_data_len = 31; + ble_user_cmd_prepare(BLE_CMD_ADV_DATA, 2, 31, buf); + r_printf("ADV data():"); + put_buf(buf, 31); + return 0; +} + +int smartbox_make_set_rsp_data(void) +{ + u8 offset = 0; + u8 *buf = scan_rsp_data; + u8 *edr_name = bt_get_local_name(); + + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_FLAGS, 0x06, 1); + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME, (void *)edr_name, strlen(edr_name)); + /* ble_printf("RSP data(%d):,offset"); */ + /* ble_put_buf(buf, offset); */ + + scan_rsp_data_len = 31; + ble_user_cmd_prepare(BLE_CMD_RSP_DATA, 2, 31, buf); + return 0; +} + + +static int update_adv_data(u8 *buf) +{ + u8 i; + buf[1] = 0xD6; // JL ID + buf[0] = 0x05; + +#if 1 + u16 vid = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG); + buf[3] = vid & 0xFF; + buf[2] = vid >> 8; + + u16 pid = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG); + buf[5] = pid & 0xFF; + buf[4] = pid >> 8; +#else + buf[3] = 0x02; // VID + buf[2] = 0x00; + + buf[5] = 0x33; // PID + buf[4] = 0x00; +#endif + +#if (SOUNDCARD_ENABLE) + buf[6] = 0x40; // 4:声卡类型 | protocol verson +#else + buf[6] = 0x0; // 0:音箱类型 | protocol verson +#endif + if (RCSP_SPP == get_defalut_bt_channel_sel()) { + buf[6] |= 2; + } + + swapX(bt_get_mac_addr(), &buf[7], 6); + + buf[13] = __this->connect_flag; + + buf[14] = __this->bat_percent_L ? (((!!__this->bat_charge_L) << 7) | (__this->bat_percent_L & 0x7F)) : 0; + buf[15] = __this->bat_percent_R ? (((!!__this->bat_charge_R) << 7) | (__this->bat_percent_R & 0x7F)) : 0; + buf[16] = __this->bat_percent_C ? (((!!__this->bat_charge_C) << 7) | (__this->bat_percent_C & 0x7F)) : 0; + + buf[17] = __this->seq_rand; + + return 0; +} + + +u8 *ble_get_scan_rsp_ptr(u16 *len) +{ + if (len) { + *len = scan_rsp_data_len; + } +#if 0//RCSP_UPDATE_EN + u8 offset = 0; + offset = make_eir_packet_val(&scan_rsp_data[offset], offset, HCI_EIR_DATATYPE_FLAGS, 0x02, 1); +#endif + return scan_rsp_data; +} + +u8 *ble_get_adv_data_ptr(u16 *len) +{ + if (len) { + *len = adv_data_len; + } +#if RCSP_UPDATE_EN + adv_data[15] = 1; + adv_data[20] = 0; + u8 t_buf[16]; + btcon_hash(&adv_data[2], 16, &adv_data[15], 4, t_buf); + for (u8 i = 0; i < 8; i++) { + adv_data[23 + i] = t_buf[2 * i + 1]; + } +#endif + return adv_data; +} + + + + + +static u8 update_dev_battery_level(void) +{ + + u8 master_bat = 0; + u8 master_charge = 0; + u8 slave_bat = 0; + u8 slave_charge = 0; + u8 box_bat = 0; + u8 box_charge = 0; + +// Master bat +#if CONFIG_DISPLAY_DETAIL_BAT + master_bat = get_vbat_percent(); +#else + master_bat = get_self_battery_level() * 10 + 10; +#endif + if (master_bat > 100) { + master_bat = 100; + } + master_charge = get_charge_online_flag(); + + +// Slave bat + +#if TCFG_USER_TWS_ENABLE + slave_bat = get_tws_sibling_bat_persent(); +#if TCFG_CHARGESTORE_ENABLE + if (slave_bat == 0xff) { + /* log_info("--update_bat_01\n"); */ + if (get_bt_tws_connect_status()) { + slave_bat = chargestore_get_sibling_power_level(); + } + } +#endif + + if (slave_bat == 0xff) { + /* log_info("--update_bat_02\n"); */ + slave_bat = 0x00; + } + + slave_charge = !!(slave_bat & 0x80); + slave_bat &= 0x7F; +#else + slave_charge = 0; + slave_bat = 0; +#endif + +// Box bat + if ((master_charge && (master_bat != 0)) + || (slave_charge && (slave_bat != 0))) { + //earphone in charge +#if TCFG_CHARGESTORE_ENABLE + box_bat = chargestore_get_power_level(); + if (box_bat == 0xFF) { + box_bat = 0; + } +#else + box_bat = 0; +#endif + } else { + //all not in charge + box_bat = 0; + } + box_charge = !!(box_bat & 0x80); + box_bat &= 0x7F; +// check if master is L + + u8 tbat_charge_L = 0; + u8 tbat_charge_R = 0; + u8 tbat_percent_L = 0; + u8 tbat_percent_R = 0; + u8 tbat_percent_C = box_bat; + u8 tbat_charge_C = box_charge; +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + if ('L' == tws_api_get_local_channel()) { + tbat_charge_L = master_charge; + tbat_charge_R = slave_charge; + tbat_percent_L = master_bat; + tbat_percent_R = slave_bat; + } else if ('R' == tws_api_get_local_channel()) { + tbat_charge_L = slave_charge; + tbat_charge_R = master_charge; + tbat_percent_L = slave_bat; + tbat_percent_R = master_bat; + } + } else { + switch (tws_api_get_local_channel()) { + case 'R': + tbat_charge_R = master_charge; + tbat_percent_R = master_bat; + break; + case 'L': + default: + tbat_charge_L = master_charge; + tbat_percent_L = master_bat; + break; + } + } +#else + tbat_charge_L = master_charge; + tbat_percent_L = master_bat; +#endif + +#if 0//TCFG_CHARGESTORE_ENABLE + u8 tpercent = 0; + u8 tcharge = 0; + if (chargestore_get_earphone_pos() == 'L') { + //switch position + log_info("is L pos\n"); + tpercent = tbat_percent_R; + tcharge = tbat_charge_R; + tbat_percent_R = tbat_percent_L; + tbat_charge_R = tbat_charge_L; + tbat_percent_L = tpercent; + tbat_charge_L = tcharge; + } else { + log_info("is R pos\n"); + } +#endif + + if ((!!__this->bat_charge_L) || (!!__this->bat_charge_R) || (!!__this->bat_charge_C)) { + if (((__this->bat_percent_C + 1) & 0x7F) <= 0x2) { + __this->bat_percent_C = 0x2; + } + } +// check if change + u8 tchange = 0; + if ((tbat_charge_L != __this->bat_charge_L) + || (tbat_charge_R != __this->bat_charge_R) + || (tbat_charge_C != __this->bat_charge_C) + || (tbat_percent_L != __this->bat_percent_L) + || (tbat_percent_R != __this->bat_percent_R) + || (tbat_percent_C != __this->bat_percent_C)) { + tchange = 1; + } + + __this->bat_charge_L = tbat_charge_L; + __this->bat_charge_R = tbat_charge_R; + __this->bat_charge_C = tbat_charge_C; + __this->bat_percent_L = tbat_percent_L; + __this->bat_percent_R = tbat_percent_R; + __this->bat_percent_C = tbat_percent_C; + + /* u8 *buf = adv_data; */ + /* buf[16] = __this->bat_percent_L ? (((!!__this->bat_charge_L) << 7) | (__this->bat_percent_L & 0x7F)):0; */ + /* buf[17] = __this->bat_percent_R ? (((!!__this->bat_charge_R) << 7) | (__this->bat_percent_R & 0x7F)):0; */ + /* buf[18] = __this->bat_percent_C ? (((!!__this->bat_charge_C) << 7) | (__this->bat_percent_C & 0x7F)):0; */ + + return tchange; +} + + +static u8 update_dev_connect_flag(void) +{ + u8 old_flag = __this->connect_flag; + + + extern u8 get_bt_connect_status(void); + if (get_bt_connect_status() == BT_STATUS_WAITINT_CONN) { + __this->connect_flag = 1; + } else { + __this->connect_flag = 2; + } + + if (old_flag != __this->connect_flag) { + return 1; + } + return 0; +} + +static void bt_ble_rcsp_adv_enable_do(void) +{ +#if(TCFG_CHARGE_BOX_ENABLE) + extern u8 get_tws_ear_status(void); + if (!get_tws_ear_status()) { + return; + } +#endif + +#if TCFG_USER_TWS_ENABLE + if (tws_api_get_role() == TWS_ROLE_SLAVE) { + if (!(get_rcsp_connect_status() && RCSP_SPP == bt_3th_get_cur_bt_channel_sel())) { + return; + } + } +#endif + + + ble_state_e cur_state = smartbox_get_ble_work_state(); + // battery + if (update_dev_battery_level()) { + __this->modify_flag = 1; + } + + // connect flag + /* if (update_dev_connect_flag()) { */ + /* __this->modify_flag = 1; */ + /* } */ + + extern u8 adv_info_notify(u8 * buf, u8 len); + extern u8 JL_rcsp_get_auth_flag(void); +#if (!MUTIl_CHARGING_BOX_EN) && (RCSP_ADV_EN) && (TCFG_USER_TWS_ENABLE) + if ((smartbox_get_con_handle() || get_rcsp_connect_status()) && JL_rcsp_get_auth_flag()) { + /* extern void deal_adv_setting_gain_time_stamp(void); */ + /* deal_adv_setting_gain_time_stamp(); */ + } +#endif + if ((smartbox_get_con_handle() || get_rcsp_connect_status()) && JL_rcsp_get_auth_flag() && (__this->ble_adv_notify || __this->modify_flag)) { + printf("adv con_handle %d\n", smartbox_get_con_handle()); + /* u8 data[5]; */ + /* data[0] = __this->seq_rand; */ + /* data[1] = __this->connect_flag; */ + /* data[2] = __this->bat_percent_L ? (((!!__this->bat_charge_L) << 7) | (__this->bat_percent_L & 0x7F)):0; */ + /* data[3] = __this->bat_percent_R ? (((!!__this->bat_charge_R) << 7) | (__this->bat_percent_R & 0x7F)):0; */ + /* data[4] = __this->bat_percent_C ? (((!!__this->bat_charge_C) << 7) | (__this->bat_percent_C & 0x7F)):0; */ + /* adv_info_notify(data, 5); */ + u8 data[18]; + update_adv_data(data); + adv_info_notify(data, 18); + __this->modify_flag = 0; + return; + } + +#if (!MUTIl_CHARGING_BOX_EN) + if (cur_state != BLE_ST_ADV) { + return; + } +#endif + + if (__this->modify_flag == 0) { + return; + } + + printf("adv modify!!!!!!\n"); + bt_ble_adv_enable(0); + smartbox_make_set_adv_data(); + smartbox_make_set_rsp_data(); + bt_ble_adv_enable(1); +} + +void bt_ble_rcsp_adv_enable(void) +{ +#if (MUTIl_CHARGING_BOX_EN) +#if (TCFG_CHARGE_BOX_ENABLE) + extern u8 get_chgbox_lid_status(void); + if (0 == get_chgbox_lid_status()) { + return; + } +#endif + __this->modify_flag = 1; + bt_ble_rcsp_adv_enable_do(); +#endif + ble_timer_handle = sys_timer_add(NULL, bt_ble_rcsp_adv_enable_do, BLE_TIMER_SET); +} + + +void bt_ble_rcsp_adv_disable(void) +{ + if (ble_timer_handle) { + sys_timer_del(ble_timer_handle); + ble_timer_handle = 0; + } + ble_app_disconnect(); + smartbox_set_adv_enable(0, 0); + bt_adv_seq_change(); +} + +// 同步seq到对端 +#define TWS_FUNC_ID_SEQ_RAND_SYNC (('S' << (3 * 8)) | ('E' << (2 * 8)) | ('Q' << (1 * 8)) | ('\0')) +void tws_conn_switch_role(); +static void deal_sibling_seq_rand_sync(void *data, u16 len, bool rx) +{ + put_buf(data, len); + if (rx) { + switch (((u8 *)data)[0]) { + case TWS_ADV_SEQ_CHANGE: + __this->seq_rand = ((u8 *) data)[1]; + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_SEQ, NULL, 0); + break; + case TWS_VERSON_INFO: + printf("get sibling version:0x%x\n", ((u8 *)data)[1] | ((u8 *)data)[2] << 8); + sibling_ver_info = ((u8 *)data)[1] | ((u8 *)data)[2] << 8; + u16 cur_ver_info = get_vid_pid_ver_from_cfg_file(GET_VER_FROM_EX_CFG); + if ((cur_ver_info > sibling_ver_info) && (tws_api_get_role() == TWS_ROLE_MASTER)) { //如果主机版本号比从机高需要进行role_switch + //tws_conn_switch_role(); + } + break; + + } + } +} +REGISTER_TWS_FUNC_STUB(adv_seq_rand_sync) = { + .func_id = TWS_FUNC_ID_SEQ_RAND_SYNC, + .func = deal_sibling_seq_rand_sync, +}; +void adv_seq_vaule_sync(void) +{ + syscfg_write(ADV_SEQ_RAND, &__this->seq_rand, sizeof(__this->seq_rand)); +} +void bt_adv_seq_change(void) +{ + u8 trand; + u8 data[2]; + syscfg_read(ADV_SEQ_RAND, &trand, 1); + log_info("adv seq read: %x\n", trand); + trand++; + syscfg_write(ADV_SEQ_RAND, &trand, 1); + log_info("adv seq write: %x\n", trand); + __this->seq_rand = trand; + data[0] = TWS_ADV_SEQ_CHANGE; + data[1] = __this->seq_rand; +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status() && tws_api_get_role() == TWS_ROLE_MASTER) { + tws_api_send_data_to_sibling(data, sizeof(data), TWS_FUNC_ID_SEQ_RAND_SYNC); + } +#endif +} + +u8 get_ble_adv_notify(void) +{ + return __this->ble_adv_notify; +} + +void set_ble_adv_notify(u8 en) +{ + + __this->ble_adv_notify = en; +} + +u8 get_connect_flag(void) +{ + return __this->connect_flag; +} + +void set_connect_flag(u8 value) +{ + __this->connect_flag = value; +} + +void bt_ble_init_do(void) +{ + log_info("bt_ble_test_tag_do\n"); + //初始化三个电量值 + /* swapX(bt_get_mac_addr(), &user_tag_data[7], 6); */ + + __this->connect_flag = 0; + __this->bat_charge_L = 1; + __this->bat_charge_R = 1; + __this->bat_charge_C = 1; + __this->bat_percent_L = 100; + __this->bat_percent_R = 100; + __this->bat_percent_C = 100; + __this->modify_flag = 0; + __this->ble_adv_notify = 0; + update_dev_battery_level(); + bt_adv_seq_change(); + //update_dev_connect_flag(); +} + +int bt_ble_adv_ioctl(u32 cmd, u32 priv, u8 mode) +{ + printf(" bt_ble_adv_ioctl %d %d %d\n", cmd, priv, mode); + ble_state_e cur_state = smartbox_get_ble_work_state(); + if (mode) { // set + switch (cmd) { + case BT_ADV_ENABLE: + break; + case BT_ADV_DISABLE: + if (cur_state == BLE_ST_ADV) { + printf("ADV DISABLE !!!\n"); + bt_ble_adv_enable(0); + return 0; + } + __this->connect_flag = SECNE_DISMISS; + break; + case BT_ADV_SET_EDR_CON_FLAG: + __this->connect_flag = priv; + if (priv == SECNE_UNCONNECTED) { + bt_adv_seq_change(); + } +#if (RCSP_ADV_MUSIC_INFO_ENABLE) + extern void rcsp_adv_music_info_set_state(u8 state, u32 time); + if (priv == SECNE_UNCONNECTED) { + rcsp_adv_music_info_set_state(0, 1); + } else if (priv == SECNE_CONNECTED) { + rcsp_adv_music_info_set_state(1, 1000); + } +#endif + break; + case BT_ADV_SET_BAT_CHARGE_L: + __this->bat_charge_L = priv; + break; + case BT_ADV_SET_BAT_CHARGE_R: + __this->bat_charge_R = priv; + break; + case BT_ADV_SET_BAT_CHARGE_C: + __this->bat_charge_C = priv; + break; + case BT_ADV_SET_BAT_PERCENT_L: + __this->bat_percent_L = priv; + break; + case BT_ADV_SET_BAT_PERCENT_R: + __this->bat_percent_R = priv; + break; + case BT_ADV_SET_BAT_PERCENT_C: + __this->bat_percent_C = priv; + break; + case BT_ADV_SET_NOTIFY_EN: + __this->ble_adv_notify = priv; + break; + default: + return -1; + } + + __this->modify_flag = 1; + } else { // get + switch (cmd) { + case BT_ADV_ENABLE: + case BT_ADV_DISABLE: + break; + case BT_ADV_SET_EDR_CON_FLAG: + break; + case BT_ADV_SET_BAT_CHARGE_L: + break; + case BT_ADV_SET_BAT_CHARGE_R: + break; + case BT_ADV_SET_BAT_CHARGE_C: + break; + case BT_ADV_SET_BAT_PERCENT_L: + break; + case BT_ADV_SET_BAT_PERCENT_R: + break; + case BT_ADV_SET_BAT_PERCENT_C: + break; + default: + break; + } + } + return 0; +} + + + + + +void bt_adv_get_bat(u8 *buf) +{ + buf[0] = __this->bat_percent_L ? (((!!__this->bat_charge_L) << 7) | (__this->bat_percent_L & 0x7F)) : 0; + buf[1] = __this->bat_percent_R ? (((!!__this->bat_charge_R) << 7) | (__this->bat_percent_R & 0x7F)) : 0; + buf[2] = __this->bat_percent_C ? (((!!__this->bat_charge_C) << 7) | (__this->bat_percent_C & 0x7F)) : 0; +} + +extern u8 jl_app_init_setting(void); +u8 btstck_app_init_setting(void) +{ + jl_app_init_setting(); + return 1; +} + +#define TWS_FUNC_ID_ADV_STATE_INFO_SYNC (('A' << (3 * 8)) | ('S' << (2 * 8)) | ('S' << (1 * 8)) | ('Y')) +static void deal_sibling_adv_state_info_sync(void *data, u16 len, bool rx) +{ + if (rx) { + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDAET_ADV_STATE_INFO, data, len); + } +} +REGISTER_TWS_FUNC_STUB(adv_state_sync) = { + .func_id = TWS_FUNC_ID_ADV_STATE_INFO_SYNC, + .func = deal_sibling_adv_state_info_sync, +}; +static void adv_state_info_sync(void) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + u8 param[2] = {0}; + param[0] = JL_rcsp_get_auth_flag(); + param[1] = __this->ble_adv_notify; + tws_api_send_data_to_sibling(param, sizeof(param), TWS_FUNC_ID_ADV_STATE_INFO_SYNC); + } +#endif +} + +// type : 0 - 正常关机检查 // 1 - 低电关机检测 +u8 adv_tws_both_in_charge_box(u8 type) +{ + if (0 == ((!!__this->bat_percent_L) & (!!__this->bat_percent_R))) { + return 0; + } + static u8 ret = 0; + if (ret) { + goto check_changes; + } + + if (type) { +#if TCFG_USER_TWS_ENABLE + if (TWS_ROLE_MASTER == tws_api_get_role()) { + ret = 1; + } +#endif + return ret; + } + + ret = ((!!__this->bat_charge_L) ^ (!!__this->bat_charge_R)); +check_changes: + if (smartbox_get_con_handle()) { + return ret; + } + if (get_rcsp_connect_status() && ret) { + adv_state_info_sync(); + } + return 0; +} + +// 切换后触发 +void adv_role_switch_handle(void) +{ +#if TCFG_USER_TWS_ENABLE + if (tws_api_get_tws_state()) { + if (RCSP_BLE == bt_3th_get_cur_bt_channel_sel()) { + if (tws_api_get_role() == TWS_ROLE_MASTER) { + ble_module_enable(1); + } else { + u8 adv_cmd = 0x3; + extern u8 adv_info_device_request(u8 * buf, u16 len); + adv_info_device_request(&adv_cmd, sizeof(adv_cmd)); + ble_module_enable(0); + } + } + } +#endif +} + +void send_version_to_sibling(void) +{ + u8 data[3] = {0}; + u16 ver = 0; + ver = get_vid_pid_ver_from_cfg_file(GET_VER_FROM_EX_CFG); + printf("%s---verson:%x\n", ver); + data[0] = TWS_VERSON_INFO; + data[1] = ver; + data[2] = ver >> 8; + tws_api_send_data_to_sibling(data, sizeof(data), TWS_FUNC_ID_SEQ_RAND_SYNC); +} +#endif + diff --git a/apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_adv.h b/apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_adv.h new file mode 100644 index 0000000..56a2315 --- /dev/null +++ b/apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_adv.h @@ -0,0 +1,20 @@ +// binary representation +// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) + +#ifndef _LE_SMARTBOX_ADV_H +#define _LE_SMARTBOX_ADV_H + +#include +#include "bt_common.h" +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_RCSP_DEMO) + +u8 get_adv_notify_state(void); +void set_adv_notify_state(u8 notify); +int smartbox_make_set_rsp_data(void); +int smartbox_make_set_adv_data(void); +void bt_ble_init_do(void); +int bt_ble_adv_ioctl(u32 cmd, u32 priv, u8 mode); +void set_connect_flag(u8 value); + +#endif +#endif diff --git a/apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_module.c b/apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_module.c new file mode 100644 index 0000000..4659a1b --- /dev/null +++ b/apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_module.c @@ -0,0 +1,770 @@ +/********************************************************************************************* + * Filename : le_server_module.c + + * Description : + + * Author : + + * Email : zh-jieli.com + + * Last modifiled : 2017-01-17 11:14 + + * Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved. +*********************************************************************************************/ + +// ***************************************************************************** +/* EXAMPLE_START(le_counter): LE Peripheral - Heartbeat Counter over GATT + * + * @text All newer operating systems provide GATT Client functionality. + * The LE Counter examples demonstrates how to specify a minimal GATT Database + * with a custom GATT Service and a custom Characteristic that sends periodic + * notifications. + */ +// ***************************************************************************** +#include "system/app_core.h" +#include "system/includes.h" +#include "smartbox/config.h" + +#include "app_action.h" + +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "user_cfg.h" +#include "vm.h" +#include "app_power_manage.h" +#include "btcontroller_modules.h" +#include "bt_common.h" +#include "3th_profile_api.h" +#include "btstack/avctp_user.h" +#include "app_chargestore.h" + +#include "btcrypt.h" +#include "custom_cfg.h" +#include "smartbox_music_info_setting.h" +#include "le_smartbox_adv.h" +#include "le_smartbox_module.h" +#include "classic/tws_api.h" + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_RCSP_DEMO) + +#if 1 +extern void printf_buf(u8 *buf, u32 len); +#define log_info printf +#define log_info_hexdump printf_buf +#else +#define log_info(...) +#define log_info_hexdump(...) +#endif + +#define EIR_TAG_STRING 0xd6, 0x05, 0x08, 0x00, 'J', 'L', 'A', 'I', 'S', 'D','K' +static const char user_tag_string[] = {EIR_TAG_STRING}; + +//------ +#define ATT_LOCAL_PAYLOAD_SIZE (200) //note: need >= 20 +#define ATT_SEND_CBUF_SIZE (512) //note: need >= 20,缓存大小,可修改 +#define ATT_RAM_BUFSIZE (ATT_CTRL_BLOCK_SIZE + ATT_LOCAL_PAYLOAD_SIZE + ATT_SEND_CBUF_SIZE) //note: +static u8 att_ram_buffer[ATT_RAM_BUFSIZE] __attribute__((aligned(4))); +//--------------- + +//--------------- +#define ADV_INTERVAL_MIN (160) + +static hci_con_handle_t con_handle; + +//加密设置 +static const uint8_t sm_min_key_size = 7; + +//连接参数设置 +static const uint8_t connection_update_enable = 1; ///0--disable, 1--enable +static uint8_t connection_update_cnt = 0; // +static const struct conn_update_param_t connection_param_table[] = { + {16, 24, 16, 600}, + {12, 28, 14, 600},//11 + {8, 20, 20, 600},//3.7 + /* {12, 28, 4, 600},//3.7 */ + /* {12, 24, 30, 600},//3.05 */ +}; + +static const struct conn_update_param_t connection_param_table_update[] = { + {96, 120, 0, 600}, + {60, 80, 0, 600}, + {60, 80, 0, 600}, +}; + +static u8 conn_update_param_index = 0; +static u8 conn_param_len = sizeof(connection_param_table) / sizeof(struct conn_update_param_t); +#define CONN_PARAM_TABLE_CNT (sizeof(connection_param_table)/sizeof(struct conn_update_param_t)) + +#if (ATT_RAM_BUFSIZE < 64) +#error "adv_data & rsp_data buffer error!!!!!!!!!!!!" +#endif + + +static char *gap_device_name = "AC697N_ble_test"; +static u8 gap_device_name_len = 0; +volatile static u8 ble_work_state = 0; +static u8 test_read_write_buf[4]; +static u8 adv_ctrl_en; + + +static void (*app_recieve_callback)(void *priv, void *buf, u16 len) = NULL; +static void (*app_ble_state_callback)(void *priv, ble_state_e state) = NULL; +static void (*ble_resume_send_wakeup)(void) = NULL; +static u32 channel_priv; +//------------------------------------------------------ + +static int app_send_user_data_check(u16 len); +static int app_send_user_data_do(void *priv, u8 *data, u16 len); +static int app_send_user_data(u16 handle, u8 *data, u16 len, u8 handle_type); +//------------------------------------------------------ +//广播参数设置 +static void advertisements_setup_init(); +extern const char *bt_get_local_name(); +static int set_adv_enable(void *priv, u32 en); +static int get_buffer_vaild_len(void *priv); +//------------------------------------------------------ +static void send_request_connect_parameter(u8 table_index) +{ + struct conn_update_param_t *param = NULL; //static ram + switch (conn_update_param_index) { + case 0: + param = (void *)&connection_param_table[table_index]; + break; + case 1: + param = (void *)&connection_param_table_update[table_index]; + break; + default: + break; + } + + log_info("update_request:-%d-%d-%d-%d-\n", param->interval_min, param->interval_max, param->latency, param->timeout); + if (con_handle) { + ble_user_cmd_prepare(BLE_CMD_REQ_CONN_PARAM_UPDATE, 2, con_handle, param); + } +} + +static void check_connetion_updata_deal(void) +{ + if (connection_update_enable) { + if (connection_update_cnt < CONN_PARAM_TABLE_CNT) { + send_request_connect_parameter(connection_update_cnt); + } + } +} + +static void connection_update_complete_success(u8 *packet) +{ + int con_handle, conn_interval, conn_latency, conn_timeout; + + con_handle = hci_subevent_le_connection_update_complete_get_connection_handle(packet); + conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet); + conn_latency = hci_subevent_le_connection_update_complete_get_conn_latency(packet); + conn_timeout = hci_subevent_le_connection_update_complete_get_supervision_timeout(packet); + + log_info("conn_interval = %d\n", conn_interval); + log_info("conn_latency = %d\n", conn_latency); + log_info("conn_timeout = %d\n", conn_timeout); +} + + +static void set_ble_work_state(ble_state_e state) +{ + if (state != ble_work_state) { + log_info("ble_work_st:%x->%x\n", ble_work_state, state); + ble_work_state = state; + if (app_ble_state_callback) { + app_ble_state_callback((void *)channel_priv, state); + } + } +} + +static ble_state_e get_ble_work_state(void) +{ + return ble_work_state; +} + +ble_state_e smartbox_get_ble_work_state(void) +{ + return ble_work_state; +} + +static void cbk_sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + sm_just_event_t *event = (void *)packet; + u32 tmp32; + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + case SM_EVENT_JUST_WORKS_REQUEST: + sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); + log_info("Just Works Confirmed.\n"); + break; + case SM_EVENT_PASSKEY_DISPLAY_NUMBER: + log_info_hexdump(packet, size); + memcpy(&tmp32, event->data, 4); + log_info("Passkey display: %06u.\n", tmp32); + break; + } + break; + } +} + +static void can_send_now_wakeup(void) +{ + putchar('E'); + if (ble_resume_send_wakeup) { + ble_resume_send_wakeup(); + } + +} + +_WEAK_ +u8 ble_update_get_ready_jump_flag(void) +{ + return 0; +} + +/* + * @section Packet Handler + * + * @text The packet handler is used to: + * - stop the counter after a disconnect + * - send a notification when the requested ATT_EVENT_CAN_SEND_NOW is received + */ + + +/* LISTING_START(packetHandler): Packet Handler */ +static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + int mtu; + u32 tmp; + + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + + /* case DAEMON_EVENT_HCI_PACKET_SENT: */ + /* break; */ + case ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE: + log_info("ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE\n"); + case ATT_EVENT_CAN_SEND_NOW: + can_send_now_wakeup(); + break; + + case HCI_EVENT_LE_META: + switch (hci_event_le_meta_get_subevent_code(packet)) { + case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: { + set_app_connect_type(TYPE_BLE); + con_handle = little_endian_read_16(packet, 4); + log_info("HCI_SUBEVENT_LE_CONNECTION_COMPLETE: %0x\n", con_handle); + connection_update_complete_success(packet + 8); + ble_user_cmd_prepare(BLE_CMD_ATT_SEND_INIT, 4, con_handle, att_ram_buffer, ATT_RAM_BUFSIZE, ATT_LOCAL_PAYLOAD_SIZE); + set_ble_work_state(BLE_ST_CONNECT); + +#if (0 == BT_CONNECTION_VERIFY) + JL_rcsp_auth_reset(); +#endif + bt_3th_type_dev_select(RCSP_BLE); + set_adv_notify_state(1); + } + break; + + case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: + connection_update_complete_success(packet); + break; + } + break; + + case HCI_EVENT_DISCONNECTION_COMPLETE: + log_info("HCI_EVENT_DISCONNECTION_COMPLETE: %0x\n", packet[5]); + con_handle = 0; +#if RCSP_ADV_MUSIC_INFO_ENABLE + extern void stop_get_music_timer(u8 en); + stop_get_music_timer(1); +#endif + /* #if (0 == BT_CONNECTION_VERIFY) */ + /* JL_rcsp_auth_reset(); */ + /* #endif */ + ble_user_cmd_prepare(BLE_CMD_ATT_SEND_INIT, 4, con_handle, 0, 0, 0); + set_ble_work_state(BLE_ST_DISCONN); + set_app_connect_type(TYPE_NULL); + if (!ble_update_get_ready_jump_flag()) { +#if TCFG_USER_TWS_ENABLE + if (!(tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED)) { + printf(")))))))) 1\n"); + bt_ble_adv_enable(1); + } else { + printf("))))))))>>>> %d\n", tws_api_get_role()); + if (tws_api_get_role() == TWS_ROLE_MASTER) { + bt_ble_adv_enable(1); + } + } +#else + bt_ble_adv_enable(1); +#endif + } + connection_update_cnt = 0; + break; + + case ATT_EVENT_MTU_EXCHANGE_COMPLETE: + mtu = att_event_mtu_exchange_complete_get_MTU(packet) - 3; + log_info("ATT MTU = %u\n", mtu); + ble_user_cmd_prepare(BLE_CMD_ATT_MTU_SIZE, 1, mtu); + break; + + case HCI_EVENT_VENDOR_REMOTE_TEST: + log_info("--- HCI_EVENT_VENDOR_REMOTE_TEST\n"); + break; + + case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE: + tmp = little_endian_read_16(packet, 4); + log_info("-update_rsp: %02x\n", tmp); + if (tmp) { + connection_update_cnt++; + log_info("remoter reject!!!\n"); + check_connetion_updata_deal(); + } else { + connection_update_cnt = CONN_PARAM_TABLE_CNT; + } + break; + + case HCI_EVENT_ENCRYPTION_CHANGE: + log_info("HCI_EVENT_ENCRYPTION_CHANGE= %d\n", packet[2]); + break; + } + break; + } +} + + +/* LISTING_END */ + +/* + * @section ATT Read + * + * @text The ATT Server handles all reads to constant data. For dynamic data like the custom characteristic, the registered + * att_read_callback is called. To handle long characteristics and long reads, the att_read_callback is first called + * with buffer == NULL, to request the total value length. Then it will be called again requesting a chunk of the value. + * See Listing attRead. + */ + + +static uint16_t att_read_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t offset, uint8_t *buffer, uint16_t buffer_size) +{ + + uint16_t att_value_len = 0; + uint16_t handle = att_handle; + + /* printf("READ Callback, handle %04x, offset %u, buffer size %u\n", handle, offset, buffer_size); */ + + log_info("read_callback, handle= 0x%04x,buffer= %08x\n", handle, (u32)buffer); + + switch (handle) { + case ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE: + att_value_len = strlen(gap_device_name); + + if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) { + break; + } + + if (buffer) { + memcpy(buffer, &gap_device_name[offset], buffer_size); + att_value_len = buffer_size; + log_info("\n------read gap_name: %s \n", gap_device_name); + } + break; + + case ATT_CHARACTERISTIC_ae10_01_VALUE_HANDLE: + att_value_len = sizeof(test_read_write_buf); + if ((offset >= att_value_len) || (offset + buffer_size) > att_value_len) { + break; + } + + if (buffer) { + memcpy(buffer, &test_read_write_buf[offset], buffer_size); + att_value_len = buffer_size; + } + break; + + + case ATT_CHARACTERISTIC_ae04_01_CLIENT_CONFIGURATION_HANDLE: + case ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE: + case ATT_CHARACTERISTIC_ae05_01_CLIENT_CONFIGURATION_HANDLE: + buffer[0] = att_get_ccc_config(handle); + buffer[1] = 0; + att_value_len = 2; + break; + + default: + break; + } + + log_info("att_value_len= %d\n", att_value_len); + return att_value_len; + +} + + +/* LISTING_END */ +/* + * @section ATT Write + * + * @text The only valid ATT write in this example is to the Client Characteristic Configuration, which configures notification + * and indication. If the ATT handle matches the client configuration handle, the new configuration value is stored and used + * in the heartbeat handler to decide if a new value should be sent. See Listing attWrite. + */ + +/* LISTING_START(attWrite): ATT Write */ +static int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size) +{ + int result = 0; + u16 tmp16; + + u16 handle = att_handle; + + /* log_info("write_callback, handle= 0x%04x\n", handle); */ + + switch (handle) { + + case ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE: + tmp16 = BT_NAME_LEN_MAX; + if ((offset >= tmp16) || (offset + buffer_size) > tmp16) { + break; + } + + if (offset == 0) { + memset(gap_device_name, 0x00, BT_NAME_LEN_MAX); + } + memcpy(&gap_device_name[offset], buffer, buffer_size); + log_info("\n------write gap_name:"); + break; + + case ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE: + case ATT_CHARACTERISTIC_ae04_01_CLIENT_CONFIGURATION_HANDLE: + case ATT_CHARACTERISTIC_ae05_01_CLIENT_CONFIGURATION_HANDLE: + /* JL_rcsp_auth_reset(); */ + set_ble_work_state(BLE_ST_NOTIFY_IDICATE); + check_connetion_updata_deal(); + log_info("\n------write ccc:%04x, %02x\n", handle, buffer[0]); + att_set_ccc_config(handle, buffer[0]); + can_send_now_wakeup(); + break; + + case ATT_CHARACTERISTIC_ae10_01_VALUE_HANDLE: + tmp16 = sizeof(test_read_write_buf); + if ((offset >= tmp16) || (offset + buffer_size) > tmp16) { + break; + } + memcpy(&test_read_write_buf[offset], buffer, buffer_size); + break; + + case ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE: + /* if (!JL_rcsp_get_auth_flag()) { */ + /* JL_rcsp_auth_recieve(buffer, buffer_size); */ + /* break; */ + /* } */ + if (app_recieve_callback) { + app_recieve_callback(0, buffer, buffer_size); + } + // JL_rcsp_auth_recieve(data, len); + break; + + case ATT_CHARACTERISTIC_ae03_01_VALUE_HANDLE: + break; + + default: + break; + } + + return 0; +} + +static int app_send_user_data(u16 handle, u8 *data, u16 len, u8 handle_type) +{ + u32 ret = APP_BLE_NO_ERROR; + + if (!con_handle) { + return APP_BLE_OPERATION_ERROR; + } + + ret = ble_user_cmd_prepare(BLE_CMD_ATT_SEND_DATA, 4, handle, data, len, handle_type); + if (ret == BLE_BUFFER_FULL) { + ret = APP_BLE_BUFF_FULL; + } + + if (ret) { + log_info("app_send_fail:%d !!!!!!\n", ret); + } + return ret; +} + + +static int make_set_adv_data(void) +{ + return smartbox_make_set_adv_data(); +} + +static int make_set_rsp_data(void) +{ + return smartbox_make_set_rsp_data(); +} + + +u8 *ble_get_gatt_profile_data(u16 *len) +{ + *len = sizeof(profile_data); + return (u8 *)profile_data; +} + +//广播参数设置 +static void advertisements_setup_init() +{ + uint8_t adv_type = 0; + uint8_t adv_channel = 7; + int ret = 0; + u16 adv_interval = 0x30; + + ble_user_cmd_prepare(BLE_CMD_ADV_PARAM, 3, adv_interval, adv_type, adv_channel); + + ret |= make_set_adv_data(); + ret |= make_set_rsp_data(); + + if (ret) { + puts("advertisements_setup_init fail !!!!!!\n"); + return; + } + +} + + +void ble_sm_setup_init(io_capability_t io_type, u8 auth_req, uint8_t min_key_size, u8 security_en) +{ + //setup SM: Display only + sm_init(); + sm_set_io_capabilities(io_type); + sm_set_authentication_requirements(auth_req); + sm_set_encryption_key_size_range(min_key_size, 16); + sm_set_request_security(security_en); + sm_event_callback_set(&cbk_sm_packet_handler); +} + + +extern void le_device_db_init(void); +void ble_profile_init(void) +{ + printf("ble profile init\n"); + le_device_db_init(); + ble_sm_setup_init(IO_CAPABILITY_NO_INPUT_NO_OUTPUT, SM_AUTHREQ_BONDING, 7, TCFG_BLE_SECURITY_EN); + /* setup ATT server */ + att_server_init(profile_data, att_read_callback, att_write_callback); + att_server_register_packet_handler(cbk_packet_handler); + /* gatt_client_register_packet_handler(packet_cbk); */ + + // register for HCI events + hci_event_callback_set(&cbk_packet_handler); + /* ble_l2cap_register_packet_handler(packet_cbk); */ + /* sm_event_packet_handler_register(packet_cbk); */ + le_l2cap_register_packet_handler(&cbk_packet_handler); +} + + +static int set_adv_enable(void *priv, u32 en) +{ + ble_state_e next_state, cur_state; + + if (get_app_connect_type() == TYPE_SPP) { + return APP_BLE_OPERATION_ERROR; + } + + if (!adv_ctrl_en) { + return APP_BLE_OPERATION_ERROR; + } + + printf("con_handle %d\n", con_handle); + if (con_handle) { + return APP_BLE_OPERATION_ERROR; + } + + if (en) { + next_state = BLE_ST_ADV; + } else { + next_state = BLE_ST_IDLE; + } + + cur_state = get_ble_work_state(); + printf("get_ble_work_state %d\n", cur_state); + switch (cur_state) { + case BLE_ST_ADV: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + break; + default: + return APP_BLE_OPERATION_ERROR; + break; + } + + if (cur_state == next_state) { + printf("cur_state == next_state \n"); + return APP_BLE_NO_ERROR; + } + log_info("adv_en:%d\n", en); + set_ble_work_state(next_state); + if (en) { + advertisements_setup_init(); + } + ble_user_cmd_prepare(BLE_CMD_ADV_ENABLE, 1, en); + printf("> set_adv_enable %d\n", en); + return APP_BLE_NO_ERROR; +} + +int smartbox_set_adv_enable(void *priv, u32 en) +{ + return set_adv_enable(priv, en); +} + +static int ble_disconnect(void *priv) +{ + if (con_handle) { + if (BLE_ST_SEND_DISCONN != get_ble_work_state()) { + log_info(">>>ble send disconnect\n"); + set_ble_work_state(BLE_ST_SEND_DISCONN); + ble_user_cmd_prepare(BLE_CMD_DISCONNECT, 1, con_handle); + } else { + log_info(">>>ble wait disconnect...\n"); + } + return APP_BLE_NO_ERROR; + } else { + return APP_BLE_OPERATION_ERROR; + } +} + + +static int get_buffer_vaild_len(void *priv) +{ + u32 vaild_len = 0; + ble_user_cmd_prepare(BLE_CMD_ATT_VAILD_LEN, 1, &vaild_len); + return vaild_len; +} + +static int app_send_user_data_do(void *priv, u8 *data, u16 len) +{ + return app_send_user_data(ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE, data, len, ATT_OP_AUTO_READ_CCC); +} + +static int app_send_user_data_check(u16 len) +{ + u32 buf_space = get_buffer_vaild_len(0); + if (len <= buf_space) { + return 1; + } + return 0; +} + +static int regiest_wakeup_send(void *priv, void *cbk) +{ + ble_resume_send_wakeup = cbk; + return APP_BLE_NO_ERROR; +} + +static int regiest_recieve_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_recieve_callback = cbk; + return APP_BLE_NO_ERROR; +} + +static int regiest_state_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_ble_state_callback = cbk; + return APP_BLE_NO_ERROR; +} + +void bt_ble_adv_enable(u8 enable) +{ + set_adv_enable(0, enable); +} + +void ble_module_enable(u8 en) +{ + log_info("mode_en:%d\n", en); + if (en) { + adv_ctrl_en = 1; +#if (!MUTIl_CHARGING_BOX_EN) + bt_ble_adv_enable(1); +#endif + } else { + if (con_handle) { + adv_ctrl_en = 0; + ble_disconnect(NULL); + } else { + bt_ble_adv_enable(0); + adv_ctrl_en = 0; + } + } +} + + +const struct ble_server_operation_t ble_operation = { + .adv_enable = set_adv_enable, + .disconnect = ble_disconnect, + .get_buffer_vaild = get_buffer_vaild_len, + .send_data = (void *)app_send_user_data_do, + .regist_wakeup_send = regiest_wakeup_send, + .regist_recieve_cbk = regiest_recieve_cbk, + .regist_state_cbk = regiest_state_cbk, +}; + +void ble_get_server_operation_table(struct ble_server_operation_t **interface_pt) +{ + *interface_pt = (void *)&ble_operation; +} + +void bt_ble_init(void) +{ + log_info("***** ble_init******\n"); + + gap_device_name = bt_get_local_name(); + gap_device_name_len = strlen(gap_device_name); + if (gap_device_name_len > BT_NAME_LEN_MAX) { + gap_device_name_len = BT_NAME_LEN_MAX; + } + + log_info("ble name(%d): %s \n", gap_device_name_len, gap_device_name); + + set_ble_work_state(BLE_ST_INIT_OK); + bt_ble_init_do(); + + + bt_ble_rcsp_adv_enable(); + ble_module_enable(1); + + +} + +void bt_ble_exit(void) +{ + log_info("***** ble_exit******\n"); + ble_module_enable(0); +#if SMART_BOX_EN + extern void smartbox_exit(void); + smartbox_exit(); +#endif +} + + +void ble_app_disconnect(void) +{ + ble_disconnect(NULL); +} + +hci_con_handle_t smartbox_get_con_handle(void) +{ + return con_handle; +} + + +#endif + diff --git a/apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_module.h b/apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_module.h new file mode 100644 index 0000000..0ba1366 --- /dev/null +++ b/apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_module.h @@ -0,0 +1,166 @@ +// binary representation +// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) + +#ifndef _LE_SMARTBOX_MODULE_H +#define _LE_SMARTBOX_MODULE_H + +#include +#include "bt_common.h" +#include "ble_user.h" +#include "btstack/btstack_typedef.h" +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_RCSP_DEMO) +// +// gatt profile include file, generated by jieli gatt_inc_generator.exe +// +static const uint8_t profile_data[] = { + ////////////////////////////////////////////////////// + // + // 0x0001 PRIMARY_SERVICE 1800 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x18, + + /* CHARACTERISTIC, 2a00, READ | WRITE | DYNAMIC, */ + // 0x0002 CHARACTERISTIC 2a00 READ | WRITE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x0a, 0x03, 0x00, 0x00, 0x2a, + // 0x0003 VALUE 2a00 READ | WRITE | DYNAMIC + 0x08, 0x00, 0x0a, 0x01, 0x03, 0x00, 0x00, 0x2a, + + ////////////////////////////////////////////////////// + // + // 0x0004 PRIMARY_SERVICE ae00 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x80, 0x00, 0x00, 0x28, 0x00, 0xae, + + /* CHARACTERISTIC, ae01, WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x0040 CHARACTERISTIC ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x81, 0x00, 0x03, 0x28, 0x04, 0x82, 0x00, 0x01, 0xae, + // 0x0041 VALUE ae01 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x08, 0x00, 0x04, 0x01, 0x82, 0x00, 0x01, 0xae, + + /* CHARACTERISTIC, ae02, NOTIFY, */ + // 0x0042 CHARACTERISTIC ae02 NOTIFY + 0x0d, 0x00, 0x02, 0x00, 0x83, 0x00, 0x03, 0x28, 0x10, 0x84, 0x00, 0x02, 0xae, + // 0x0043 VALUE ae02 NOTIFY + 0x08, 0x00, 0x10, 0x00, 0x84, 0x00, 0x02, 0xae, + // 0x0044 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x85, 0x00, 0x02, 0x29, 0x00, 0x00, + + ////////////////////////////////////////////////////// + // + // 0x0014 PRIMARY_SERVICE 1812 + // + ////////////////////////////////////////////////////// + // 0x0a, 0x00, 0x02, 0x00, 0x14, 0x00, 0x00, 0x28, 0x12, 0x18, + +#if 0// authentication + // + 10, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x28, 0x0A, 0x18, //primary service declaration + 13, 0x00, 0x02, 0x00, 0x1B, 0x00, 0x03, 0x28, 0x02, 0x1C, 0x00, 0x50, 0x2A, //characteristic declaration + 15, 0x00, 0x02, 0x04, 0x1C, 0x00, 0x50, 0x2A, 0x02, 0x8A, 0x24, 0x66, 0x82, 0x34, 0x36, //PnP ID +#endif + + // END + 0x00, 0x00, +}; +// +// characteristics <--> handles +// +#define ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE 0x0003 +#define ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE 0x0082 +#define ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE 0x0084 +#define ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE 0x0085 +// #define ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE 0x0003 +// #define ATT_CHARACTERISTIC_ae01_01_VALUE_HANDLE 0x0006 +// #define ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE 0x0008 +// #define ATT_CHARACTERISTIC_ae02_01_CLIENT_CONFIGURATION_HANDLE 0x0009 +#define ATT_CHARACTERISTIC_ae03_01_VALUE_HANDLE 0x000b +#define ATT_CHARACTERISTIC_ae04_01_VALUE_HANDLE 0x000d +#define ATT_CHARACTERISTIC_ae04_01_CLIENT_CONFIGURATION_HANDLE 0x000e +#define ATT_CHARACTERISTIC_ae05_01_VALUE_HANDLE 0x0010 +#define ATT_CHARACTERISTIC_ae05_01_CLIENT_CONFIGURATION_HANDLE 0x0011 +#define ATT_CHARACTERISTIC_ae10_01_VALUE_HANDLE 0x0013 + + + +#define JL_OPCODE_SET_ADV 0xC0 +#define JL_OPCODE_GET_ADV 0xC1 +#define JL_OPCODE_ADV_DEVICE_NOTIFY 0xC2 +#define JL_OPCODE_ADV_NOTIFY_SETTING 0xC3 +#define JL_OPCODE_ADV_DEVICE_REQUEST 0xC4 + +#define ATTR_TYPE_BAT_VALUE (0) +#define ATTR_TYPE_EDR_NAME (1) +#define ATTR_TYPE_KEY_SETTING (2) +#define ATTR_TYPE_LED_SETTING (3) +#define ATTR_TYPE_MIC_SETTING (4) +#define ATTR_TYPE_WORK_MODE (5) +#define ATTR_TYPE_PRODUCT_MESSAGE (6) +#define ATTR_TYPE_TIME_STAMP (7) +#define ATTR_TYPE_EQ_SETTING (8) +#define ATTR_TYPE_HIGH_LOW_VOL (9) +#define ATTR_TYPE_VOL_SETTING (10) +#define ATTR_TYPE_MISC_SETTING (11) +#define ATTR_TYPE_COLOR_LED_SETTING (12) +#define ATTR_TYPE_KARAOKE_EQ_SETTING (13) +#define ATTR_TYPE_KARAOKE_SETTING (14) + +#ifndef JL_SMART_BOX_CUSTOM_APP_EN +//rcsp功能模块使能 +#define RCSP_ADV_NAME_SET_ENABLE 1 +#define RCSP_ADV_KEY_SET_ENABLE 0 +#define RCSP_ADV_LED_SET_ENABLE 1 +#define RCSP_ADV_MIC_SET_ENABLE 0 +#define RCSP_ADV_WORK_SET_ENABLE 0 +#define RCSP_ADV_EQ_SET_ENABLE 1 +#define RCSP_ADV_MUSIC_INFO_ENABLE 1 +#define RCSP_ADV_HIGH_LOW_SET 1 +#define RCSP_ADV_PRODUCT_MSG_ENABLE 1 +#define RCSP_ADV_FIND_DEVICE_ENABLE 1 +#define RCSP_ADV_COLOR_LED_SET_ENABLE 1 +#define RCSP_ADV_KARAOKE_SET_ENABLE 0 +#define RCSP_ADV_KARAOKE_EQ_SET_ENABLE 0 +#endif + +enum { + BT_ADV_ENABLE, + BT_ADV_DISABLE, + BT_ADV_SET_EDR_CON_FLAG, + BT_ADV_SET_BAT_CHARGE_L, + BT_ADV_SET_BAT_CHARGE_R, + BT_ADV_SET_BAT_CHARGE_C, + BT_ADV_SET_BAT_PERCENT_L, + BT_ADV_SET_BAT_PERCENT_R, + BT_ADV_SET_BAT_PERCENT_C, + BT_ADV_SET_NOTIFY_EN, +}; + +// BT_ADV_SET_EDR_CON_FLAG +#define SECNE_DISMISS (0x00) +#define SECNE_UNCONNECTED (0x01) +#define SECNE_CONNECTED (0x02) +#define SECNE_CONNECTING (0x03) +#define SECNE_CONNECTINLESS (0x04) + +enum { + TWS_ADV_SEQ_CHANGE = 0, + TWS_VERSON_INFO, +}; + +extern int bt_ble_adv_ioctl(u32 cmd, u32 priv, u8 mode); +extern void bt_adv_seq_change(void); +void ble_app_disconnect(void); +void bt_ble_rcsp_adv_enable(void); +void bt_ble_rcsp_adv_disable(void); +u8 get_ble_adv_notify(void); +void set_ble_adv_notify(u8 en); +u8 get_connect_flag(void); +void set_connect_flag(u8 value); +hci_con_handle_t smartbox_get_con_handle(void); +int smartbox_set_adv_enable(void *priv, u32 en); +void ble_module_enable(u8 en); +ble_state_e smartbox_get_ble_work_state(void); + +#endif +#endif diff --git a/apps/soundbox/smartbox/bt_manage/smartbox_bt_manage.c b/apps/soundbox/smartbox/bt_manage/smartbox_bt_manage.c new file mode 100644 index 0000000..cc4213d --- /dev/null +++ b/apps/soundbox/smartbox/bt_manage/smartbox_bt_manage.c @@ -0,0 +1,447 @@ +#include "smartbox/config.h" +#include "smartbox/smartbox.h" +#include "smartbox_update.h" +#include "smartbox/function.h" +#include "smartbox_setting_sync.h" + +#include "app_main.h" +#include "adv_mic_setting.h" +#include "smartbox_update_tws.h" +#include "3th_profile_api.h" +#include "adv_time_stamp_setting.h" + +#include "btstack/avctp_user.h" +#include "btstack/btstack_task.h" +#include "bt_tws.h" +#include "le_smartbox_adv.h" +#include "le_smartbox_module.h" + +#if SMART_BOX_EN + +#define LOG_TAG "[RCSP-ADV]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +u8 ble_adv_miss_flag = 0; +u8 ble_adv_poweron_flag = 0; + +int smartbox_bt_state_set_page_scan_enable() +{ +#if (TCFG_USER_TWS_ENABLE == 0) + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_UNCONNECTED, 1); +#elif (CONFIG_NO_DISPLAY_BUTTON_ICON || !TCFG_CHARGESTORE_ENABLE) + if (tws_api_get_role() == TWS_ROLE_MASTER) { + printf("switch_icon_ctl11...\n"); + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_UNCONNECTED, 1); + } +#endif + return 0; +} + +int smartbox_bt_state_get_connect_mac_addr() +{ + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_CONNECTING, 1); + return 0; +} + +int smartbox_bt_state_cancel_page_scan() +{ +#if (TCFG_USER_TWS_ENABLE == 0) + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_UNCONNECTED, 1); +#elif (CONFIG_NO_DISPLAY_BUTTON_ICON || !TCFG_CHARGESTORE_ENABLE) + if (tws_api_get_role() == TWS_ROLE_MASTER) { + if (ble_adv_miss_flag) { + ble_adv_miss_flag = 0; + puts("ble_adv_miss_flag...\n"); + } else { + printf("switch_icon_ctl00...\n"); + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_UNCONNECTED, 1); + } + } +#endif + return 0; +} + +int smartbox_bt_state_tws_init(int paired) +{ + ble_adv_poweron_flag = 1; + + if (paired) { + if (tws_api_get_role() == TWS_ROLE_MASTER) { + bt_ble_adv_ioctl(BT_ADV_ENABLE, 0, 1); + } else { + //slave close + bt_ble_adv_ioctl(BT_ADV_DISABLE, 0, 1); + } + } else { +#if 0 //disable + //no_pair_adv,last do + if (tws_api_get_role() == TWS_ROLE_MASTER) { + printf("switch_icon_ctl no_pair...\n"); + bt_ble_set_control_en(1); + bt_ble_icon_open(ICON_TYPE_INQUIRY); + } else { + bt_ble_set_control_en(0); + } +#endif + } + return 0; +} + +int smartbox_bt_state_tws_connected(int first_pair, u8 *comm_addr) +{ +#if RCSP_ADV_MUSIC_INFO_ENABLE + extern void stop_get_music_timer(u8 en) ; + stop_get_music_timer(0); +#endif + + if (first_pair) { + extern void ble_module_enable(u8 en); + extern void bt_update_mac_addr(u8 * addr); + extern void lib_make_ble_address(u8 * ble_address, u8 * edr_address); + /* bt_ble_adv_enable(0); */ + u8 tmp_ble_addr[6] = {0}; + lib_make_ble_address(tmp_ble_addr, comm_addr); + le_controller_set_mac(tmp_ble_addr);//将ble广播地址改成公共地址 + bt_update_mac_addr(comm_addr); + /* bt_ble_adv_enable(1); */ + + + /*新的连接,公共地址改变了,要重新将新的地址广播出去*/ + if (tws_api_get_role() == TWS_ROLE_MASTER) { + printf("\nNew Connect Master!!!\n\n"); + ble_app_disconnect(); + bt_ble_adv_enable(0); + bt_ble_adv_enable(1); + } else { + printf("\nConnect Slave!!!\n\n"); + /*从机ble关掉*/ + ble_app_disconnect(); + bt_ble_adv_enable(0); + } + } + + return 0; +} + +int smartbox_bt_state_enter_soft_poweroff() +{ +#if TCFG_USER_TWS_ENABLE + if (tws_api_get_role() == TWS_ROLE_MASTER) { + u8 adv_cmd = 0x3; + extern u8 adv_info_device_request(u8 * buf, u16 len); + extern u8 adv_tws_both_in_charge_box(u8 type); + if (adv_tws_both_in_charge_box(0)) { + adv_info_device_request(&adv_cmd, sizeof(adv_cmd)); + } + } +#endif + bt_ble_exit(); + return 0; +} + +static int smartbox_bt_status_event_handler(struct bt_event *bt) +{ + switch (bt->event) { + case BT_STATUS_SECOND_CONNECTED: + case BT_STATUS_FIRST_CONNECTED: +#if TCFG_USER_TWS_ENABLE + if (tws_api_get_role() == TWS_ROLE_MASTER || bt_3th_get_cur_bt_channel_sel() == RCSP_SPP) { + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_CONNECTED, 1); + } else { + //maybe slave already open + bt_ble_adv_ioctl(BT_ADV_DISABLE, 0, 1); + } +#else + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_CONNECTED, 1); +#endif + break; + case BT_STATUS_FIRST_DISCONNECT: + case BT_STATUS_SECOND_DISCONNECT: + bt_adv_seq_change(); + if (!app_var.goto_poweroff_flag) { +#if TCFG_USER_TWS_ENABLE + if (tws_api_get_role() == TWS_ROLE_MASTER || bt_3th_get_cur_bt_channel_sel() == RCSP_SPP) { + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_UNCONNECTED, 1); + } else { + //maybe slave already open + bt_ble_adv_ioctl(BT_ADV_DISABLE, 0, 1); + } +#else + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_UNCONNECTED, 1); +#endif + } + break; + case BT_STATUS_SCO_STATUS_CHANGE: +#if TCFG_USER_TWS_ENABLE + if (bt->value != 0xff) { + /* rcsp_user_mic_fixed_deal(1); */ + } else { + /* rcsp_user_mic_fixed_deal(0); */ + } +#endif + break; + + case BT_STATUS_PHONE_INCOME: + case BT_STATUS_PHONE_OUT: + case BT_STATUS_PHONE_ACTIVE: + printf("BT_STATUS_PHONE_ACTIVE\n"); +#if RCSP_ADV_FIND_DEVICE_ENABLE + extern void smartbox_send_find_device_stop(void); + smartbox_send_find_device_stop(); +#endif + smartbox_function_update(COMMON_FUNCTION, BIT(COMMON_FUNCTION_ATTR_TYPE_PHONE_SCO_STATE_INFO)); + break; + case BT_STATUS_PHONE_HANGUP: + printf("BT_STATUS_PHONE_HANGUP\n"); + smartbox_function_update(COMMON_FUNCTION, BIT(COMMON_FUNCTION_ATTR_TYPE_PHONE_SCO_STATE_INFO)); + break; + } + return 0; +} + + +static int smartbox_hci_event_handler(struct bt_event *bt) +{ + switch (bt->event) { + case HCI_EVENT_CONNECTION_COMPLETE: + switch (bt->value) { + case ERROR_CODE_PIN_OR_KEY_MISSING: +#if (CONFIG_NO_DISPLAY_BUTTON_ICON && TCFG_CHARGESTORE_ENABLE) + //已取消配对了, 切换广播 + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_UNCONNECTED, 1); +#endif + break; + } + break; + } + + return 0; +} + +static void smartbox_app_opt_tws_event_handler(struct bt_event *bt) +{ + int reason = bt->args[2]; + switch (bt->event) { + case APP_OPT_TWS_EVENT_SYNC_FUN_CMD: +#if (TCFG_USER_TWS_ENABLE) + if (reason == APP_OPT_SYNC_CMD_APP_RESET_LED_UI) { +#if RCSP_ADV_LED_SET_ENABLE + extern void update_led_setting_state(void); + update_led_setting_state(); +#endif + } else if (reason == APP_OPT_SYNC_CMD_MUSIC_INFO) { +#if RCSP_ADV_MUSIC_INFO_ENABLE + extern void get_music_info(void); + get_music_info(); +#endif + } else if (reason == APP_OPT_SYNC_CMD_RCSP_AUTH_RES) { + extern void rcsp_tws_auth_sync_deal(void); + rcsp_tws_auth_sync_deal(); + } else if (reason == APP_OPT_SYNC_CMD_MUSIC_PLAYER_STATE) { +#if RCSP_ADV_MUSIC_INFO_ENABLE + void rcsp_update_player_state(void); + rcsp_update_player_state(); +#endif + } else if (reason == APP_OPT_SYNC_CMD_MUSIC_PLAYER_TIEM_EN) { +#if RCSP_ADV_MUSIC_INFO_ENABLE + extern void reset_player_time_en(void); + reset_player_time_en(); +#endif + } +#endif + break; + } +} + +static void smartbox_bt_tws_event_handler(struct bt_event *bt) +{ + int role = bt->args[0]; + int phone_link_connection = bt->args[1]; + int reason = bt->args[2]; + + switch (bt->event) { + case TWS_EVENT_CONNECTED: + //bt_ble_adv_enable(1); + if (tws_api_get_role() == TWS_ROLE_MASTER) { + //master enable + log_info("master do icon_open\n"); + if (phone_link_connection) { + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_CONNECTED, 1); + } else { +#if (TCFG_CHARGESTORE_ENABLE && !CONFIG_NO_DISPLAY_BUTTON_ICON) + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_CONNECTED, 1); +#else + if (ble_adv_poweron_flag) { //上电标记 + if (bt_user_priv_var.auto_connection_counter > 0) { + //有回连手机动作 + /* g_printf("ICON_TYPE_RECONNECT"); */ + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_CONNECTING, 1); + //没按键配对的话,等回连成功的时候才显示电量。如果在这里显示,手机取消配对后耳机开机,会显示出按键的界面 + } else { + //没有回连,设可连接 + /* g_printf("ICON_TYPE_INQUIRY"); */ + bt_ble_adv_ioctl(BT_ADV_SET_EDR_CON_FLAG, SECNE_UNCONNECTED, 1); + } + + } +#endif + } + } else { + //slave disable + printf("\nConnect Slave!!!\n\n"); + /*从机ble关掉*/ + ble_app_disconnect(); + bt_ble_adv_enable(0); + } + send_version_to_sibling(); + ble_adv_poweron_flag = 0; + + + /* sync_setting_by_time_stamp(); */ + + break; + case TWS_EVENT_PHONE_LINK_DETACH: + /* + * 跟手机的链路LMP层已完全断开, 只有tws在连接状态才会收到此事件 + */ + if (reason == 0x0b) { + //CONNECTION ALREADY EXISTS + ble_adv_miss_flag = 1; + } else { + ble_adv_miss_flag = 0; + } + break; + case TWS_EVENT_CONNECTION_DETACH: + /* + * TWS连接断开 + */ + if (app_var.goto_poweroff_flag) { + break; + } + if (get_app_connect_type() == 0) { + printf("\ntws detach to open ble~~~\n\n"); + bt_ble_adv_enable(1); + } + set_ble_connect_type(TYPE_NULL); + + /* deal_adv_setting_gain_time_stamp(); */ + break; + case TWS_EVENT_ROLE_SWITCH: + if (role == TWS_ROLE_MASTER) { // 切换后触发 +#if RCSP_ADV_LED_SET_ENABLE + extern void update_led_setting_state(void); + update_led_setting_state(); +#endif + } + { + extern void adv_role_switch_handle(void); + adv_role_switch_handle(); + } + break; + } + +#if OTA_TWS_SAME_TIME_ENABLE + tws_ota_app_event_deal(bt->event); +#endif +} + +int sys_event_handler_specific(struct sys_event *event) +{ + switch (event->type) { + case SYS_BT_EVENT: + if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) { + smartbox_bt_status_event_handler(&event->u.bt); + } else if ((u32)event->arg == SYS_BT_EVENT_TYPE_HCI_STATUS) { + smartbox_hci_event_handler(&event->u.bt); + } +#if TCFG_USER_TWS_ENABLE + else if (((u32)event->arg == SYS_BT_EVENT_FROM_TWS)) { + smartbox_bt_tws_event_handler(&event->u.bt); + } else if (((u32)event->arg == SYS_BT_EVENT_FROM_APP_OPT_TWS)) { + smartbox_app_opt_tws_event_handler(&event->u.bt); + } +#endif +#if OTA_TWS_SAME_TIME_ENABLE + else if (((u32)event->arg == SYS_BT_OTA_EVENT_TYPE_STATUS)) { + bt_ota_event_handler(&event->u.bt); + } +#endif + break; + case SYS_DEVICE_EVENT: + if ((u32)event->arg == DEVICE_EVENT_FROM_RCSP) { + int JL_rcsp_event_handler(struct rcsp_event * rcsp); + JL_rcsp_event_handler(&event->u.rcsp); + } + break; + } + + return 0; +} + + +int smartbox_user_spp_state_specific(u8 packet_type) +{ + + switch (packet_type) { + case 1: + ble_app_disconnect(); + bt_ble_adv_enable(0); + set_app_connect_type(TYPE_SPP); + + extern void smartbox_spp_setting(void); + smartbox_spp_setting(); + break; + case 2: + + set_app_connect_type(TYPE_NULL); +#if RCSP_UPDATE_EN + if (get_jl_update_flag()) { //进入升级前不再开广播了 + return 0; + } +#endif + +#if TCFG_USER_TWS_ENABLE + if (!(tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED)) { + ble_module_enable(1); + } else { + if (tws_api_get_role() == TWS_ROLE_MASTER) { + ble_module_enable(1); + } + } +#else + ble_module_enable(1); +#endif + + break; + } + return 0; +} + +int jl_phone_app_init() +{ + printf("jl_phone_app_init\n"); +#if RCSP_ADV_MUSIC_INFO_ENABLE + extern void rcsp_adv_music_info_deal(u8 type, u32 time, u8 * info, u16 len); + bt_music_info_handle_register(rcsp_adv_music_info_deal); +#endif + return 0; +} + + +int smartbox_bt_state_init() +{ + /* jl_rcsp_spp_init(); */ + smartbox_init(); + jl_phone_app_init(); + return 0; +} + + + +#endif diff --git a/apps/soundbox/smartbox/bt_manage/smartbox_bt_manage.h b/apps/soundbox/smartbox/bt_manage/smartbox_bt_manage.h new file mode 100644 index 0000000..7b8e42b --- /dev/null +++ b/apps/soundbox/smartbox/bt_manage/smartbox_bt_manage.h @@ -0,0 +1,37 @@ +// binary representation +// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) + +#ifndef _SMARTBOX_BT_MANAGE_H +#define _SMARTBOX_BT_MANAGE_H + +#define DEVICE_EVENT_FROM_RCSP (('R' << 24) | ('C' << 16) | ('S' << 8) | 'P') + + +enum RCSP_MSG_T { + MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET, + MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE, + MSG_JL_LOADER_DOWNLOAD_START, + MSG_JL_UPDATE_START, + MSG_JL_ENTER_UPDATE_MODE, + MSG_JL_DEV_DISCONNECT, + MSG_JL_BLE_UPDATE_START, + MSG_JL_SPP_UPDATE_START, + MSG_JL_ADV_SETTING_SYNC, + MSG_JL_ADV_SETTING_UPDATE, + MSG_JL_UPDATE_EQ, + MSG_JL_UPDATE_SEQ, + MSG_JL_SWITCH_DEVICE, + MSG_JL_UPDATE_PLAYER_TIME, + MSG_JL_UPDATE_PLAYER_STATE, + MSG_JL_UPDATE_MUSIC_INFO, + MSG_JL_UPDATE_MUSIC_PLAYER_TIME_TEMER, + MSG_JL_UPDAET_ADV_STATE_INFO, + MSG_JL_REBOOT_DEV, + MSG_JL_USER_SPP_BLE_STATE, + MSG_JL_PLAYER_STATE_CHANGE, + MSG_JL_AVRCP_CH_SYNC_MUSIC_INFO, +}; + +int smartbox_soundbox_state_init(); +void send_version_to_sibling(void); +#endif diff --git a/apps/soundbox/smartbox/cmd_data_deal/cmd_recieve.c b/apps/soundbox/smartbox/cmd_data_deal/cmd_recieve.c new file mode 100644 index 0000000..dbc82c8 --- /dev/null +++ b/apps/soundbox/smartbox/cmd_data_deal/cmd_recieve.c @@ -0,0 +1,304 @@ +#include "smartbox/config.h" +#include "smartbox/smartbox.h" +#include "smartbox/function.h" +#include "smartbox/feature.h" +#include "smartbox/switch_device.h" +#include "file_transfer.h" +#include "file_delete.h" +#include "dev_format.h" +#include "smartbox/event.h" +#include "btstack/avctp_user.h" +#include "app_action.h" +#include "smartbox_adv_bluetooth.h" +#include "smartbox_update.h" +#include "le_smartbox_module.h" +#include "fs.h" + +////<<<<<<<= limit){ \ + }else{ \ + return ; \ + }\ + }while(0); + + +static void get_target_feature(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return ; + } + + smart->A_platform = data[4]; + + u32 mask = READ_BIG_U32(data); + u32 wlen = 0; + u8 *resp = zalloc(TARGET_FEATURE_RESP_BUF_SIZE); + ASSERT(resp, "func = %s, line = %d, no ram!!\n", __FUNCTION__, __LINE__); + wlen = target_feature_parse_packet(priv, resp, TARGET_FEATURE_RESP_BUF_SIZE, mask); + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, resp, wlen); + free(resp); +} + +static void switch_device(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return ; + } + smart->trans_chl = data[0];//指spp还是ble + printf("smart->trans_chl:%x\n", smart->trans_chl); + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0); + smartbox_switch_device(data); +} + +static void get_sys_info(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + ASSET_CMD_DATA_LEN(len, 1); + u8 function = data[0]; + u8 *resp = zalloc(TARGET_FEATURE_RESP_BUF_SIZE); + resp[0] = function; + u32 rlen = smartbox_function_get(priv, function, data + 1, len - 1, resp + 1, TARGET_FEATURE_RESP_BUF_SIZE - 1); + if (rlen == 0) { + printf("get_sys_info LTV NULL !!!!\n"); + } + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, resp, (u16)rlen + 1); + free(resp); +} + +static void set_sys_info(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + ASSET_CMD_DATA_LEN(len, 1); + + u8 function = data[0]; + bool ret = smartbox_function_set(priv, function, data + 1, len - 1); + if (ret == true) { + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0); + } else { + JL_CMD_response_send(OpCode, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0); + } +} + +static void disconnect_edr(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return ; + } + printf("notify disconnect edr\n"); + smartbox_msg_post(USER_MSG_SMARTBOX_DISCONNECT_EDR, 1, (int)priv); + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0); +} + +static void file_bs_start(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + /* printf("JL_OPCODE_FILE_BROWSE_REQUEST_START\n"); */ + /* put_buf(data, len); */ +#if RCSP_FILE_OPT + if (smartbox_browser_busy() == false) { + JL_CMD_response_send(OpCode, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0); + } else { + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0); + smartbox_browser_start(data, len); + } +#endif +} + +static void open_bt_scan(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + u8 result = 0; + bool ret = smartbox_msg_post(USER_MSG_SMARTBOX_BT_SCAN_OPEN, 1, (int)priv); + if (ret == true) { + result = 1; + } + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, &result, 1); +} + +static void stop_bt_scan(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + u8 result = 0; + bool ret = smartbox_msg_post(USER_MSG_SMARTBOX_BT_SCAN_STOP, 1, (int)priv); + if (ret == true) { + result = 1; + } + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, &result, 1); +} + +static void connect_bt_spec_addr(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + u8 result = 0; + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return ; + } + if (len != 6) { + printf("connect_bt_spec_addr data len err = %d\n", len); + } + memcpy(smart->emitter_con_addr, data, 6); + bool ret = smartbox_msg_post(USER_MSG_SMARTBOX_BT_CONNECT_SPEC_ADDR, 1, (int)priv); + if (ret == true) { + result = 1; + } + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, &result, 1); +} + +static void function_cmd_handle(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + ASSET_CMD_DATA_LEN(len, 1); + + u8 function = data[0]; + bool ret = smartbox_function_cmd_set(priv, function, data + 1, len - 1); + if (ret == true) { + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0); + } else { + JL_CMD_response_send(OpCode, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0); + } +} + +static void find_device_handle(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ +#if RCSP_ADV_FIND_DEVICE_ENABLE + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return ; + } + if (!smart->find_dev_en) { + return; + } + if (BT_CALL_HANGUP != get_call_status()) { + return ; + } + u8 type = data[0]; + u8 opt = data[1]; + if (opt) { + // 播放铃声 + u16 timeout = READ_BIG_U16(data + 2); + extern void find_device_timeout_handle(u32 sec); + find_device_timeout_handle(timeout); + } else { + // 关闭铃声 + extern void smartbox_stop_find_device(void *priv); + smartbox_stop_find_device(NULL); + } + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0); +#endif +} + +static void get_md5_handle(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return ; + } + u8 md5[32] = {0}; + FILE *fp = fopen(RES_MD5_FILE, "r"); + if (!fp) { + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0); + return; + } + u32 r_len = fread(fp, (void *)md5, 32); + if (r_len != 32) { + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0); + return; + } + /* printf("get [md5] succ:"); */ + /* put_buf(md5, 32); */ + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, md5, 32); + fclose(fp); +} + +static void get_low_latency_param(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return ; + } + u8 low_latency_param[6] = {0}; + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, low_latency_param, 6); +} + + + +void cmd_recieve(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + switch (OpCode) { + case JL_OPCODE_GET_TARGET_FEATURE: + get_target_feature(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_DISCONNECT_EDR: + disconnect_edr(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_SWITCH_DEVICE: + switch_device(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_SYS_INFO_GET: + get_sys_info(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_SYS_INFO_SET: + set_sys_info(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_FILE_BROWSE_REQUEST_START: + file_bs_start(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_SYS_OPEN_BT_SCAN: + open_bt_scan(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_SYS_STOP_BT_SCAN: + stop_bt_scan(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_SYS_BT_CONNECT_SPEC: + connect_bt_spec_addr(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_FUNCTION_CMD: + function_cmd_handle(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_SYS_FIND_DEVICE: + find_device_handle(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_GET_MD5: + get_md5_handle(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_LOW_LATENCY_PARAM: + get_low_latency_param(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_CUSTOMER_USER: + smartbox_user_cmd_recieve(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_FILE_TRANSFER_START: + file_transfer_download_start(OpCode_SN, data, len); + break; + case JL_OPCODE_FILE_TRANSFER_CANCEL: + file_transfer_download_passive_cancel(OpCode_SN, data, len); + break; + case JL_OPCODE_FILE_DELETE: + file_delete_start(OpCode_SN, data, len); + break; + case JL_OPCODE_ACTION_PREPARE: + app_smartbox_task_prepare(1, data[0], OpCode_SN); + break; + case JL_OPCODE_DEVICE_FORMAT: + dev_format_start(OpCode_SN, data, len); + break; + + default: +#if 1//RCSP_SMARTBOX_ADV_EN + if (0 == JL_smartbox_adv_cmd_resp(priv, OpCode, OpCode_SN, data, len)) { + break; + } +#endif +#if RCSP_UPDATE_EN + if (0 == JL_rcsp_update_cmd_resp(priv, OpCode, OpCode_SN, data, len)) { + break; + } +#endif + break; + } +} + +#endif//SMART_BOX_EN diff --git a/apps/soundbox/smartbox/cmd_data_deal/cmd_recieve_no_respone.c b/apps/soundbox/smartbox/cmd_data_deal/cmd_recieve_no_respone.c new file mode 100644 index 0000000..7544d59 --- /dev/null +++ b/apps/soundbox/smartbox/cmd_data_deal/cmd_recieve_no_respone.c @@ -0,0 +1,12 @@ +#include "smartbox/config.h" +#include "smartbox/event.h" + +///>>>>>>>>>>>>>收到APP发来不需要响应的命令处理 +#if (SMART_BOX_EN) +void cmd_recieve_no_respone(void *priv, u8 OpCode, u8 *data, u16 len) +{ + printf("cmd_recieve_no_respone, %x\n", OpCode); +} +#endif//SMART_BOX_EN + + diff --git a/apps/soundbox/smartbox/cmd_data_deal/cmd_respone.c b/apps/soundbox/smartbox/cmd_data_deal/cmd_respone.c new file mode 100644 index 0000000..ff6e963 --- /dev/null +++ b/apps/soundbox/smartbox/cmd_data_deal/cmd_respone.c @@ -0,0 +1,31 @@ +#include "smartbox/config.h" +#include "smartbox/event.h" +#include "smartbox_update.h" +#include "file_transfer.h" + +///>>>>>>>>>>>>>>>设备接收到上报给APP端命令的回复 +void cmd_respone(void *priv, u8 OpCode, u8 status, u8 *data, u16 len) +{ + printf("cmd_respone:%x\n", OpCode); +#if RCSP_UPDATE_EN + if (0 == JL_rcsp_update_cmd_receive_resp(priv, OpCode, status, data, len)) { + return; + } +#endif + + switch (OpCode) { + case JL_OPCODE_FILE_TRANSFER_END: + file_transfer_download_end(status, data, len); + break; + case JL_OPCODE_FILE_TRANSFER_CANCEL: + file_transfer_download_active_cancel_response(status, data, len); + break; + case JL_OPCODE_FILE_RENAME: + file_transfer_file_rename(status, data, len); + break; + default: + break; + } +} + + diff --git a/apps/soundbox/smartbox/cmd_data_deal/cmd_user.c b/apps/soundbox/smartbox/cmd_data_deal/cmd_user.c new file mode 100644 index 0000000..ff75fbc --- /dev/null +++ b/apps/soundbox/smartbox/cmd_data_deal/cmd_user.c @@ -0,0 +1,43 @@ +#include "smartbox/cmd_user.h" + +//*----------------------------------------------------------------------------*/ +/**@brief smartbox自定义命令数据接收处理 + @param priv:全局smartbox结构体, OpCode:当前命令, OpCode_SN:当前的SN值, data:数据, len:数据长度 + @return + @note 二次开发需要增加自定义命令,通过JL_OPCODE_CUSTOMER_USER进行扩展, + 不要定义这个命令以外的命令,避免后续SDK更新导致命令冲突 +*/ +/*----------------------------------------------------------------------------*/ +void smartbox_user_cmd_recieve(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + //自定义数据接收 + printf("%s:", __FUNCTION__); + put_buf(data, len); +#if 0 + ///以下是发送测试代码 + u8 test_send_buf[] = {0x04, 0x05, 0x06}; + smartbox_user_cmd_send(test_send_buf, sizeof(test_send_buf)); +#endif + + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0); + +} + + +//*----------------------------------------------------------------------------*/ +/**@brief smartbox自定义命令数据发送接口 + @param data:数据, len:数据长度 + @return + @note 二次开发需要增加自定义命令,通过JL_OPCODE_CUSTOMER_USER进行扩展, + 不要定义这个命令以外的命令,避免后续SDK更新导致命令冲突 +*/ +/*----------------------------------------------------------------------------*/ +JL_ERR smartbox_user_cmd_send(u8 *data, u16 len) +{ + //自定义数据接收 + printf("%s:", __FUNCTION__); + put_buf(data, len); + return JL_CMD_send(JL_OPCODE_CUSTOMER_USER, data, len, 1); +} + + diff --git a/apps/soundbox/smartbox/cmd_data_deal/command.c b/apps/soundbox/smartbox/cmd_data_deal/command.c new file mode 100644 index 0000000..5cde13d --- /dev/null +++ b/apps/soundbox/smartbox/cmd_data_deal/command.c @@ -0,0 +1,128 @@ +#include "smartbox/config.h" +#include "smartbox/command.h" +#include "btstack/avctp_user.h" +#include "smartbox/event.h" +#include "system/timer.h" +#include "le_smartbox_module.h" +#include "smartbox_rcsp_manage.h" + +#if (SMART_BOX_EN) + +void smartbox_command_send_bt_scan_result(char *name, u8 name_len, u8 *addr, u32 dev_class, char rssi) +{ + u8 send_len = sizeof(dev_class) + 6 + sizeof(rssi) + sizeof(name_len) + name_len; + u8 *send_buf = (u8 *)zalloc(send_len); + if (send_buf == NULL) { + return ; + } + WRITE_BIG_U32(send_buf, dev_class); + memcpy(send_buf + sizeof(dev_class), addr, 6); + memcpy(send_buf + sizeof(dev_class) + 6, &rssi, 1); + memcpy(send_buf + sizeof(dev_class) + 6 + sizeof(rssi), &name_len, 1); + memcpy(send_buf + sizeof(dev_class) + 6 + sizeof(rssi) + sizeof(name_len), name, name_len); + JL_CMD_send(JL_OPCODE_SYS_UPDATE_BT_STATUS, send_buf, send_len, JL_NOT_NEED_RESPOND); + free(send_buf); + printf("bt name = %s\n", name); +} + +void smartbox_command_send_conncecting_bt_status(u8 *addr, u8 status) +{ + u8 send_buf[7] = {0}; + send_buf[0] = status; + memcpy(send_buf, addr, 6); + JL_CMD_send(JL_OPCODE_SYS_EMITTER_BT_CONNECT_STATUS, send_buf, sizeof(send_buf), JL_NOT_NEED_RESPOND); +} + + +#if RCSP_ADV_FIND_DEVICE_ENABLE +static u16 find_device_timer = 0; +static u8 find_device_key_flag = 0; +static void smartbox_command_send_find_device(void *priv) +{ + struct smartbox *smart = (struct smartbox *) priv; + if (smart == NULL) { + return ; + } + if (!smart->find_dev_en) { + return; + } + // 查找手机 播放铃声 超时时间(默认10s) + u8 send_buf[4] = {0x00, 0x01, 0x00, 0x0A}; + JL_CMD_send(JL_OPCODE_SYS_FIND_DEVICE, send_buf, sizeof(send_buf), JL_NOT_NEED_RESPOND); +} + +u8 smartbox_find_device_key_flag_get(void) +{ + return find_device_key_flag; +} + +void smartbox_send_find_device_stop(void) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL || 0 == get_rcsp_connect_status()) { + return ; + } + if (!smart->find_dev_en) { + return ; + } + // 查找手机 关闭铃声 超时时间(不限制) + u8 send_buf[4] = {0x00, 0x00, 0x00, 0x00}; + JL_CMD_send(JL_OPCODE_SYS_FIND_DEVICE, send_buf, sizeof(send_buf), JL_NOT_NEED_RESPOND); +} + +void smartbox_find_device_reset(void) +{ + find_device_key_flag = 0; + if (find_device_timer) { + sys_timeout_del(find_device_timer); + find_device_timer = 0; + } +} + +void smartbox_stop_find_device(void *priv) +{ + smartbox_find_device_reset(); + smartbox_send_find_device_stop(); + + extern void smartbox_set_vol_for_find_device(u8 vol_flag); + smartbox_set_vol_for_find_device(find_device_key_flag); +} + +void find_device_timeout_handle(u32 sec) +{ + find_device_key_flag = 1; + if (sec && (0 == find_device_timer)) { + find_device_timer = sys_timeout_add(NULL, smartbox_stop_find_device, sec * 1000); + } + + extern void smartbox_set_vol_for_find_device(u8 vol_flag); + smartbox_set_vol_for_find_device(find_device_key_flag); +} + +void smartbox_find_device(void) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL || 0 == get_rcsp_connect_status()) { + return ; + } + if (!smart->find_dev_en) { + return ; + } + + if (find_device_key_flag) { + smartbox_stop_find_device(NULL); + } else { + find_device_key_flag = 1; + if ((1 == smart->A_platform) && (0 != get_curr_channel_state())) { + // IOS平台 + user_send_cmd_prepare(USER_CTRL_DISCONNECTION_HCI, 0, NULL); + } + smartbox_command_send_find_device(smart); + } +} +#endif + + +#endif//SMART_BOX_EN + + diff --git a/apps/soundbox/smartbox/cmd_data_deal/data_recieve.c b/apps/soundbox/smartbox/cmd_data_deal/data_recieve.c new file mode 100644 index 0000000..74bdcdd --- /dev/null +++ b/apps/soundbox/smartbox/cmd_data_deal/data_recieve.c @@ -0,0 +1,13 @@ +#include "smartbox/config.h" +#include "smartbox/event.h" + +///>>>>>>>>设备接收到APP下发需要设备回复的数据 +#if (SMART_BOX_EN) + +void data_recieve(void *priv, u8 OpCode_SN, u8 CMD_OpCode, u8 *data, u16 len) +{ + printf("data_recieve, %x\n", CMD_OpCode); +} + +#endif//SMART_BOX_EN + diff --git a/apps/soundbox/smartbox/cmd_data_deal/data_recieve_no_respone.c b/apps/soundbox/smartbox/cmd_data_deal/data_recieve_no_respone.c new file mode 100644 index 0000000..870aff4 --- /dev/null +++ b/apps/soundbox/smartbox/cmd_data_deal/data_recieve_no_respone.c @@ -0,0 +1,17 @@ +#include "smartbox/config.h" +#include "smartbox/event.h" +#include "file_transfer.h" + +///>>>>>>>>>>>设备接收到APP下发不需要回复数据 +#if (SMART_BOX_EN) +void data_recieve_no_respone(void *priv, u8 CMD_OpCode, u8 *data, u16 len) +{ +// printf("data_recieve_no_respone %x\n", CMD_OpCode); + switch (CMD_OpCode) { + case JL_OPCODE_FILE_TRANSFER: + file_transfer_download_doing(data, len); + break; + } +} +#endif//SMART_BOX_EN + diff --git a/apps/soundbox/smartbox/cmd_data_deal/data_respone.c b/apps/soundbox/smartbox/cmd_data_deal/data_respone.c new file mode 100644 index 0000000..1735805 --- /dev/null +++ b/apps/soundbox/smartbox/cmd_data_deal/data_respone.c @@ -0,0 +1,11 @@ +#include "smartbox/config.h" +#include "smartbox/event.h" + +////>>>>>>>>>>>>>>>设备接收到上报数据的回复 +#if (SMART_BOX_EN) +void data_respone(void *priv, u8 status, u8 CMD_OpCode, u8 *data, u16 len) +{ + printf("data_respone, %x\n", CMD_OpCode); +} +#endif//SMART_BOX_EN + diff --git a/apps/soundbox/smartbox/config.c b/apps/soundbox/smartbox/config.c new file mode 100644 index 0000000..1f34609 --- /dev/null +++ b/apps/soundbox/smartbox/config.c @@ -0,0 +1,124 @@ +#include "smartbox/config.h" +#include "le_common.h" +#include "smartbox/event.h" +#include "le_smartbox_adv.h" +#include "le_smartbox_module.h" +#include "custom_cfg.h" +#include "smartbox_adv_bluetooth.h" + +#if (SMART_BOX_EN) + +#define RCSP_DEBUG_EN +#ifdef RCSP_DEBUG_EN +#define rcsp_putchar(x) putchar(x) +#define rcsp_printf printf +#define rcsp_printf_buf(x,len) put_buf(x,len) +#else +#define rcsp_putchar(...) +#define rcsp_printf(...) +#define rcsp_printf_buf(...) +#endif + +#ifndef JL_SMART_BOX_CUSTOM_APP_EN +#define RCSP_USE_BLE 0 +#define RCSP_USE_SPP 1 +#define RCSP_CHANNEL_SEL RCSP_USE_SPP +#endif + + + + +u8 get_defalut_bt_channel_sel(void) +{ +#if (RCSP_CHANNEL_SEL) + return RCSP_CHANNEL_SEL; +#else + return 0; +#endif +} + + + +void smartbox_spp_setting(void) +{ + bt_3th_dev_type_spp(); + set_connect_flag(2); + bt_ble_adv_ioctl(BT_ADV_SET_NOTIFY_EN, 1, 1); +} + +void smartbox_config(struct smartbox *smart) +{ + if (smart == NULL) { + return ; + } + + ///配置app支持功能展示, 跟进具体方案进行配置 +#if TCFG_APP_BT_EN + smart->function_mask |= BIT(BT_FUNCTION_MASK); +#endif +#if TCFG_APP_MUSIC_EN + smart->function_mask |= BIT(MUSIC_FUNCTION_MASK); +#endif +#if (TCFG_APP_LINEIN_EN && !SOUNDCARD_ENABLE) + smart->function_mask |= BIT(LINEIN_FUNCTION_MASK); +#endif +#if TCFG_APP_RTC_EN + smart->function_mask |= BIT(RTC_FUNCTION_MASK); +#endif +#if TCFG_APP_FM_EN + smart->function_mask |= BIT(FM_FUNCTION_MASK); +#endif +#if TCFG_COLORLED_ENABLE + smart->function_mask |= BIT(COLOR_LED_MASK); +#endif + +#if (TCFG_APP_MUSIC_EN) + smart->music_icon_mask = DEV_ICON_ALL_DISPLAY + | BIT(USB_ICON_DISPLAY) + | BIT(SD0_ICON_DISPLAY) + | BIT(SD1_ICON_DISPLAY) + ; +#endif + +#if (RCSP_SDK_TYPE) + ///sdk类型 + smart->sdk_type = RCSP_SDK_TYPE; +#endif + + ///OTA升级类型 + extern const int support_dual_bank_update_en; + smart->ota_type = support_dual_bank_update_en; + +#if (BT_CONNECTION_VERIFY) + ///是否需要握手配置 0-校验,1-不校验 + smart->auth_check = BT_CONNECTION_VERIFY; + JL_rcsp_set_auth_flag(smart->auth_check); +#endif + + ///是否使能发射器功能配置 + smart->emitter_en = 0; + +#if (RCSP_ADV_FIND_DEVICE_ENABLE) + ///是否支持查找设备 + smart->find_dev_en = RCSP_ADV_FIND_DEVICE_ENABLE; +#endif + ///是否支持游戏模式 + smart->game_mode_en = 0; + ///是否支持md5升级 + smart->md5_support = UPDATE_MD5_ENABLE; + ///是否支持卡拉ok功能 + smart->karaoke_en = RCSP_ADV_KARAOKE_SET_ENABLE; + +#ifdef RCSP_SOUND_EFFECT_FUNC_DISABLE + ///是否屏蔽声效 + smart->sound_effects_disable = RCSP_SOUND_EFFECT_FUNC_DISABLE; +#endif + + bt_3th_type_dev_select(RCSP_BLE); + bt_3th_set_ble_callback_priv(smart); + bt_3th_set_spp_callback_priv(smart); +} + + +#endif//SMART_BOX_EN + diff --git a/apps/soundbox/smartbox/event.c b/apps/soundbox/smartbox/event.c new file mode 100644 index 0000000..036a533 --- /dev/null +++ b/apps/soundbox/smartbox/event.c @@ -0,0 +1,298 @@ +#include "smartbox/config.h" +#include "smartbox/event.h" +#include "smartbox/smartbox.h" +#include "btstack/btstack_task.h" +#include "btstack/avctp_user.h" +#include "smartbox/function.h" + +#include "fm_emitter/fm_emitter_manage.h" +#include "app_action.h" +#include "key_event_deal.h" +#include "audio_config.h" +#include "smartbox_setting_opt.h" +#include "le_smartbox_module.h" + +#if (SMART_BOX_EN) + +extern void bt_search_device(void); + +extern void emitter_search_stop(u8 result); + +static void smartbox_common_event_deal(int msg, int argc, int *argv) +{ + int err = 0; + struct smartbox *smart = (struct smartbox *)argv[0]; + if (smart == NULL) { + printf("smart hdl NULL err!!\n"); + return ; + } + + switch (msg) { + case USER_MSG_SMARTBOX_DISCONNECT_EDR: + printf("USER_MSG_SMARTBOX_DISCONNECT_EDR\n"); + if (get_curr_channel_state() != 0) { + user_send_cmd_prepare(USER_CTRL_A2DP_CMD_CLOSE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_DISCONNECTION_HCI, 0, NULL); + } + break; +#if TCFG_USER_EMITTER_ENABLE + case USER_MSG_SMARTBOX_BT_SCAN_OPEN: + printf("USER_MSG_SMARTBOX_BT_SCAN_OPEN\n"); + bt_search_device(); + break; + case USER_MSG_SMARTBOX_BT_SCAN_STOP: + printf("USER_MSG_SMARTBOX_BT_SCAN_STOP\n"); + emitter_search_stop(0); + break; + + case USER_MSG_SMARTBOX_BT_CONNECT_SPEC_ADDR: + printf("USER_MSG_SMARTBOX_BT_CONNECT_SPEC_ADDR\n"); + put_buf(smart->emitter_con_addr, 6); + user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR, 6, smart->emitter_con_addr); + break; +#endif//TCFG_USER_EMITTER_ENABLE + + case USER_MSG_SMARTBOX_SET_VOL: + printf("USER_MSG_SMARTBOX_SET_VOL\n"); + smartbox_function_update(COMMON_FUNCTION, (u32)argv[1]); + break; + case USER_MSG_SMARTBOX_SET_EQ_PARAM: + printf("USER_MSG_SMARTBOX_SET_EQ_PARAM\n"); + smartbox_function_update(COMMON_FUNCTION, (u32)argv[1]); + break; + case USER_MSG_SMARTBOX_SET_FMTX_FREQ: + printf("USER_MSG_SMARTBOX_SET_FMTX_FREQ\n"); +#if (TCFG_APP_FM_EMITTER_EN && TCFG_FM_EMITTER_INSIDE_ENABLE) + u16 freq = (u16)argv[1]; + printf("freq %d\n", freq); + fm_emitter_manage_set_fre(freq); +#endif + /* #if TCFG_UI_ENABLE */ + /* ui_set_menu_ioctl(MENU_FM_DISP_FRE, freq); */ + /* #endif */ + break; +#if TCFG_USER_EMITTER_ENABLE + case USER_MSG_SMARTBOX_SET_BT_EMITTER_SW: + printf("USER_MSG_SMARTBOX_SET_BT_EMITTER_SW\n"); + break; + case USER_MSG_SMARTBOX_SET_BT_EMITTER_CONNECT_STATES: + printf("USER_MSG_SMARTBOX_SET_BT_EMITTER_CONNECT_STATES, state = %d\n", argv[1]); + if (argv[1]) { + emitter_search_stop(0); + put_buf(smart->emitter_con_addr, 6); + user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR, 6, smart->emitter_con_addr); + } else { + if (get_curr_channel_state() != 0) { + printf("-----------------11111111111111111\n"); + user_send_cmd_prepare(USER_CTRL_A2DP_CMD_CLOSE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_DISCONNECTION_HCI, 0, NULL); + } + } + break; +#endif//TCFG_USER_EMITTER_ENABLE + +#if (RCSP_FILE_OPT && TCFG_APP_MUSIC_EN) + case USER_MSG_SMARTBOX_BS_END: + printf("USER_MSG_SMARTBOX_BS_END\n"); + u8 reason = (u8)argv[1]; + char *dev_logo = (char *)argv[2]; + char *cur_dev_logo = music_player_get_dev_cur(); + u32 sclust = (u32)argv[3]; + smartbox_browser_stop(); + printf("reason = %d, dev_loop = %s, sclust = %x\n", reason, dev_logo, sclust); + if (2 == reason) { + u8 app = app_get_curr_task(); + if (app == APP_MUSIC_TASK) { + printf("is music mode \n"); + if ((music_player_get_file_sclust() == sclust) //簇号相同 + && (cur_dev_logo && (strcmp(cur_dev_logo, dev_logo) == 0)) //设备相同 + && (music_player_get_play_status() == FILE_DEC_STATUS_PLAY) //正在播放 + ) { + //同一个设备的同一首歌曲,在播放的情况,浏览选中不重新播放 + printf("the same music file!!\n"); + } else { + dev_manager_set_active_by_logo(dev_logo); + app_task_put_key_msg(KEY_MUSIC_PLAYE_BY_DEV_SCLUST, sclust); + } + } else { + printf("is not music mode\n"); + ///设定音乐模式初次播放参数为按照簇号播放 + music_task_set_parm(MUSIC_TASK_START_BY_SCLUST, sclust); + ///将选定的设备设置为活动设备 + dev_manager_set_active_by_logo(dev_logo); + ///切换模式 + app_task_switch_to(APP_MUSIC_TASK); + } + } + JL_CMD_send(JL_OPCODE_FILE_BROWSE_REQUEST_STOP, &reason, 1, JL_NEED_RESPOND); + break; +#endif + case USER_MSG_SMARTBOX_MODE_SWITCH: + printf("USER_MSG_SMARTBOX_MODE_SWITCH\n"); + bool ret = true; + u8 mode = (u8)argv[1]; + switch (mode) { + case FM_FUNCTION_MASK: +#if TCFG_APP_FM_EN + ret = app_task_switch_to(APP_FM_TASK); +#endif + break; + case BT_FUNCTION_MASK: +#if TCFG_APP_BT_EN + ret = app_task_switch_to(APP_BT_TASK); +#endif + break; + case MUSIC_FUNCTION_MASK: +#if TCFG_APP_MUSIC_EN + ret = app_task_switch_to(APP_MUSIC_TASK); +#endif + break; + case RTC_FUNCTION_MASK: +#if TCFG_APP_RTC_EN + ret = app_task_switch_to(APP_RTC_TASK); +#endif + break; + case LINEIN_FUNCTION_MASK: +#if TCFG_APP_LINEIN_EN + ret = app_task_switch_to(APP_LINEIN_TASK); +#endif + break; + case FMTX_FUNCTION_MASK: + break; + } + if (false == ret) { + extern void function_change_inform(u8 app_mode, u8 ret); + function_change_inform(app_get_curr_task(), ret); + } + break; + case USER_MSG_SMARTBOX_FM_UPDATE_STATE: + printf("USER_MSG_SMARTBOX_FM_UPDATE_STATE\n"); + extern void smartbot_fm_msg_deal(int msg); + smartbot_fm_msg_deal(-1); + break; + case USER_MSG_SMARTBOX_RTC_UPDATE_STATE: + /* printf("USER_MSG_SMARTBOX_RTC_UPDATE_STATE\n"); */ + /* extern void smartbot_rtc_msg_deal(int msg); */ + /* smartbot_rtc_msg_deal(-1); */ + break; + default: + break; + } +} + +#define APP_SMART_BOX_MSG_VAL_MAX 8 +bool smartbox_msg_post(int msg, int argc, ...) +{ + int argv[APP_SMART_BOX_MSG_VAL_MAX] = {0}; + bool ret = true; + va_list argptr; + va_start(argptr, argc); + + if (argc > APP_SMART_BOX_MSG_VAL_MAX) { + printf("%s, msg argc err\n", __FUNCTION__); + ret = false; + } else { + argv[0] = (int) smartbox_common_event_deal; + argv[2] = msg; + for (int i = 0; i < argc; i++) { + argv[i + 3] = va_arg(argptr, int); + } + + if (argc >= 2) { + argv[1] = argc + 1; + } else { + argv[1] = 3; + argc = 3; + } + int r = os_taskq_post_type("app_core", Q_CALLBACK, argc + 3, argv); + if (r) { + printf("app_next post msg err %x\n", r); + ret = false; + } + } + return ret; +} + +int smartbox_bt_key_event_deal(int key_event, int ret) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL) { + return ret; + } + if (BT_CALL_HANGUP != get_call_status()) { + return ret; + } + switch (key_event) { + case KEY_VOL_DOWN: + case KEY_VOL_UP: + smartbox_function_update(COMMON_FUNCTION, BIT(COMMON_FUNCTION_ATTR_TYPE_VOL)); + break; + } + return ret; +} + +int smartbox_common_key_event_deal(int key_event, int ret) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL) { + return ret; + } + if (BT_CALL_HANGUP != get_call_status()) { + return ret; + } + switch (key_event) { + case KEY_MINOR_OPT: +#if RCSP_ADV_FIND_DEVICE_ENABLE + printf("smartbox_find_dev\n"); + extern void smartbox_find_device(void); + smartbox_find_device(); + ret = true; +#endif + break; + case KEY_VOL_DOWN: + case KEY_VOL_UP: + smartbox_function_update(COMMON_FUNCTION, BIT(COMMON_FUNCTION_ATTR_TYPE_VOL)); + break; + default: + if (smartbox_opt_key_event_update(key_event, NULL)) { + break; + } + break; + } + return ret; +} + +bool smartbox_key_event_filter_before(int key_event) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL) { + return false; + } + if (0 == smart->dev_vol_sync) { + return false; + } + bool ret = false; + switch (key_event) { + case KEY_VOL_UP: + printf("COMMON KEY_VOL_UP\n"); + extern void volume_up(void); + volume_up(); + UI_SHOW_MENU(MENU_MAIN_VOL, 1000, app_audio_get_volume(APP_AUDIO_CURRENT_STATE), NULL); + ret = true; + break; + case KEY_VOL_DOWN: + printf("COMMON KEY_VOL_DOWN\n"); + extern void volume_down(void); + volume_down(); + UI_SHOW_MENU(MENU_MAIN_VOL, 1000, app_audio_get_volume(APP_AUDIO_CURRENT_STATE), NULL); + ret = true; + break; + } + if (ret) { + smartbox_function_update(COMMON_FUNCTION, BIT(COMMON_FUNCTION_ATTR_TYPE_VOL)); + } + return ret; +} + +#endif + diff --git a/apps/soundbox/smartbox/feature.c b/apps/soundbox/smartbox/feature.c new file mode 100644 index 0000000..225e755 --- /dev/null +++ b/apps/soundbox/smartbox/feature.c @@ -0,0 +1,351 @@ +#include "smartbox/config.h" +#include "smartbox/feature.h" +#include "btstack/avctp_user.h" +#include "smartbox/event.h" +#include "custom_cfg.h" +#include "JL_rcsp_packet.h" + +#if (SMART_BOX_EN) + +#pragma pack(1) +struct _SYS_info { + u8 bat_lev; + u8 sys_vol; + u8 max_vol; + u8 vol_is_sync; +}; + +struct _EDR_info { + u8 addr_buf[6]; + u8 profile; + u8 state; +}; + +struct _MUSIC_STATUS_info { + u8 status; + u32 cur_time; + u32 total_time; + u8 cur_dev; +}; + +struct _dev_version { + u16 _sw_ver2: 4; //software l version + u16 _sw_ver1: 4; //software m version + u16 _sw_ver0: 4; //software h version + u16 _hw_ver: 4; //hardware version +}; +#pragma pack() + +static u32 target_feature_attr_protocol_version(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + u8 ver = get_rcsp_version(); + rlen = add_one_attr(buf, buf_size, offset, attr, &ver, 1); + return rlen; +} +static u32 target_feature_attr_sys_info(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return 0; + } + struct _SYS_info sys_info = {0}; + extern void smartbox_get_cur_dev_vol_info(u8 * vol_info); + extern void smartbox_get_max_vol_info(u8 * vol_info); + extern u8 get_vbat_percent(void); + sys_info.bat_lev = get_vbat_percent(); //get_battery_level() / 10; + smartbox_get_max_vol_info(&sys_info.max_vol); + smartbox_get_cur_dev_vol_info(&sys_info.sys_vol); +#if BT_SUPPORT_MUSIC_VOL_SYNC + if (get_remote_vol_sync() || (1 == smart->A_platform)) { + sys_info.vol_is_sync |= BIT(0); + smart->dev_vol_sync = 1; + } +#endif + rlen = add_one_attr(buf, buf_size, offset, attr, (u8 *)&sys_info, sizeof(sys_info)); + return rlen; +} +static u32 target_feature_attr_edr_addr(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + struct _EDR_info edr_info; + extern const u8 *bt_get_mac_addr(); + u8 taddr_buf[6]; + memcpy(taddr_buf, bt_get_mac_addr(), 6); + edr_info.addr_buf[0] = taddr_buf[5]; + edr_info.addr_buf[1] = taddr_buf[4]; + edr_info.addr_buf[2] = taddr_buf[3]; + edr_info.addr_buf[3] = taddr_buf[2]; + edr_info.addr_buf[4] = taddr_buf[1]; + edr_info.addr_buf[5] = taddr_buf[0]; + edr_info.profile = 0x0E; + if (get_defalut_bt_channel_sel()) { + edr_info.profile |= BIT(7); + } else { + edr_info.profile &= ~BIT(7); + } + extern u8 get_bt_connect_status(void); + if (get_bt_connect_status() == BT_STATUS_WAITINT_CONN) { + edr_info.state = 0; + } else { + edr_info.state = 1; + } + rlen = add_one_attr(buf, buf_size, offset, attr, (u8 *)&edr_info, sizeof(struct _EDR_info)); + return rlen; +} +static u32 target_feature_attr_platform(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + return rlen; +} +static u32 target_feature_function_info(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return 0; + } + extern u8 get_cur_mode(u8 app_mode); + + u32 rlen = 0; + u8 tmp_buf[6] = {0}; + u32 func_mask = app_htonl(smart->function_mask); + u8 cur_fun = get_cur_mode(app_get_curr_task()); + memcpy(tmp_buf, (u8 *)&func_mask, 4); + memcpy(tmp_buf + 4, &cur_fun, 1); + memcpy(tmp_buf + 5, &smart->music_icon_mask, 1); + rlen = add_one_attr(buf, buf_size, offset, attr, tmp_buf, sizeof(tmp_buf)); + return rlen; +} +static u32 target_feature_dev_version(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + u16 ver = get_vid_pid_ver_from_cfg_file(GET_VER_FROM_EX_CFG); + ver = READ_BIG_U16(&ver); + rlen = add_one_attr(buf, buf_size, offset, attr, (u8 *)&ver, sizeof(ver)); + return rlen; +} +static u32 target_feature_sdk_type(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return 0; + } + u32 rlen = 0; + u8 sdk_type = smart->sdk_type; + rlen = add_one_attr(buf, buf_size, offset, attr, &sdk_type, 1); + return rlen; +} +static u32 target_feature_uboot_version(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + u8 *uboot_ver_flag = (u8 *)(0x1C000 - 0x8); + u8 uboot_version[2] = {uboot_ver_flag[0], uboot_ver_flag[1]}; + rlen = add_one_attr(buf, buf_size, offset, attr, uboot_version, sizeof(uboot_version)); + return rlen; +} +static u32 target_feature_ota_double_parition(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return 0; + } + u32 rlen = 0; + u8 double_partition_value; + u8 ota_loader_need_download_flag; + u8 update_channel_sel; + + if (smart->ota_type) { + double_partition_value = 0x1; + ota_loader_need_download_flag = 0x00; + } else { + double_partition_value = 0x0; + ota_loader_need_download_flag = 0x01; + } + update_channel_sel = 0x1; //强制使用BLE升级 + u8 update_param[3] = { + double_partition_value, + ota_loader_need_download_flag, + update_channel_sel, + }; + + rlen = add_one_attr(buf, buf_size, offset, attr, (u8 *)update_param, sizeof(update_param)); + return rlen; +} +static u32 target_feature_ota_update_status(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + u8 update_status_value = 0x0; + rlen = add_one_attr(buf, buf_size, offset, attr, (u8 *)&update_status_value, sizeof(update_status_value)); + return rlen; +} +static u32 target_feature_pid_vid(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + u16 pvid[2] = {0}; + pvid[0] = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG); + pvid[1] = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG); + pvid[0] = READ_BIG_U16(&pvid[0]); + pvid[1] = READ_BIG_U16(&pvid[1]); + rlen = add_one_attr(buf, buf_size, offset, attr, (u8 *)&pvid, sizeof(pvid)); + return rlen; +} +static u32 target_feature_authkey(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; +#if VER_INFO_EXT_COUNT + u8 authkey_len = 0; + u8 *local_authkey_data = NULL; + get_authkey_procode_from_cfg_file(&local_authkey_data, &authkey_len, GET_AUTH_KEY_FROM_EX_CFG); + if (local_authkey_data && authkey_len) { + put_buf(local_authkey_data, authkey_len); + rlen = add_one_attr(buf, buf_size, offset, attr, local_authkey_data, authkey_len); + } +#endif + return rlen; +} +static u32 target_feature_procode(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; +#if VER_INFO_EXT_COUNT + u8 procode_len = 0; + u8 *local_procode_data = NULL; + get_authkey_procode_from_cfg_file(&local_procode_data, &procode_len, GET_PRO_CODE_FROM_EX_CFG); + if (local_procode_data && procode_len) { + put_buf(local_procode_data, procode_len); + rlen = add_one_attr(buf, buf_size, offset, attr, local_procode_data, procode_len); + } +#endif + return rlen; +} +static u32 target_feature_mtu(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + u16 rx_max_mtu = JL_packet_get_rx_max_mtu(); + u16 tx_max_mtu = JL_packet_get_tx_max_mtu(); + u8 t_buf[4]; + t_buf[0] = (tx_max_mtu >> 8) & 0xFF; + t_buf[1] = tx_max_mtu & 0xFF; + t_buf[2] = (rx_max_mtu >> 8) & 0xFF; + t_buf[3] = rx_max_mtu & 0xFF; + rlen = add_one_attr(buf, buf_size, offset, attr, t_buf, 4); + return rlen; +} +static u32 target_feature_ble_only(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + /* u8 flag = 1; */ + + extern void lib_make_ble_address(u8 * ble_address, u8 * edr_address); + extern const u8 *bt_get_mac_addr(); + u8 taddr_buf[7]; + taddr_buf[0] = 0; + lib_make_ble_address(taddr_buf + 1, (void *)bt_get_mac_addr()); + for (u8 i = 0; i < (6 / 2); i++) { + taddr_buf[i + 1] ^= taddr_buf[7 - i - 1]; + taddr_buf[7 - i - 1] ^= taddr_buf[i + 1]; + taddr_buf[i + 1] ^= taddr_buf[7 - i - 1]; + } + + /* rlen = add_one_attr(buf, buf_size, offset, attr, &flag, 1); */ + rlen = add_one_attr(buf, buf_size, offset, attr, taddr_buf, sizeof(taddr_buf)); + return rlen; +} +static u32 target_feature_bt_emitter_info(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return 0; + } + + u32 rlen = 0; + u8 val = 0; + val |= smart->emitter_en; + val |= smart->emitter_sw; + printf("val = %d, emitter_en = %d, emitter_sw = %d\n", val, smart->emitter_en, smart->emitter_sw); + rlen = add_one_attr(buf, buf_size, offset, attr, &val, 1); + return rlen; +} + +static u32 target_feature_md5_game_support(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return 0; + } + + u32 rlen = 0; + u8 md5_support = 0; + if (md5_support) { + md5_support = UPDATE_MD5_ENABLE; + } + /* if(get_work_setting() == 2) */ + if (smart->game_mode_en) { + md5_support |= BIT(1); + } + if (smart->find_dev_en) { + md5_support |= BIT(2); + } + if (smart->karaoke_en) { + md5_support |= BIT(3); + } + if (smart->sound_effects_disable) { + md5_support |= BIT(4); + } + if (md5_support) { + rlen = add_one_attr(buf, buf_size, offset, attr, &md5_support, 1); + } + + return rlen; +} + + +enum { + FEATURE_ATTR_TYPE_PROTOCOL_VERSION = 0, + FEATURE_ATTR_TYPE_SYS_INFO = 1, + FEATURE_ATTR_TYPE_EDR_ADDR = 2, + FEATURE_ATTR_TYPE_PLATFORM = 3, + FEATURE_ATTR_TYPE_FUNCTION_INFO = 4, + FEATURE_ATTR_TYPE_DEV_VERSION = 5, + FEATURE_ATTR_TYPE_SDK_TYPE = 6, + FEATURE_ATTR_TYPE_UBOOT_VERSION = 7, + FEATURE_ATTR_TYPE_DOUBLE_PARITION = 8, + FEATURE_ATTR_TYPE_UPDATE_STATUS = 9, + FEATURE_ATTR_TYPE_DEV_VID_PID = 10, + FEATURE_ATTR_TYPE_DEV_AUTHKEY = 11, + FEATURE_ATTR_TYPE_DEV_PROCODE = 12, + FEATURE_ATTR_TYPE_DEV_MAX_MTU = 13, + FEATURE_ATTR_TYPE_CONNECT_BLE_ONLY = 17, + FEATURE_ATTR_TYPE_BT_EMITTER_INFO = 18, + FEATURE_ATTR_TYPE_MD5_GAME_SUPPORT = 19, + FEATURE_ATTR_TYPE_MAX, +}; + +static const attr_get_func target_feature_mask_get_tab[FEATURE_ATTR_TYPE_MAX] = { + [FEATURE_ATTR_TYPE_PROTOCOL_VERSION ] = target_feature_attr_protocol_version, + [FEATURE_ATTR_TYPE_SYS_INFO ] = target_feature_attr_sys_info, + [FEATURE_ATTR_TYPE_EDR_ADDR ] = target_feature_attr_edr_addr, + [FEATURE_ATTR_TYPE_PLATFORM ] = target_feature_attr_platform, + [FEATURE_ATTR_TYPE_FUNCTION_INFO ] = target_feature_function_info, + [FEATURE_ATTR_TYPE_DEV_VERSION ] = target_feature_dev_version, + [FEATURE_ATTR_TYPE_SDK_TYPE ] = target_feature_sdk_type, + [FEATURE_ATTR_TYPE_UBOOT_VERSION ] = target_feature_uboot_version, + [FEATURE_ATTR_TYPE_DOUBLE_PARITION ] = target_feature_ota_double_parition, + [FEATURE_ATTR_TYPE_UPDATE_STATUS ] = target_feature_ota_update_status, + [FEATURE_ATTR_TYPE_DEV_VID_PID ] = target_feature_pid_vid, + [FEATURE_ATTR_TYPE_DEV_AUTHKEY ] = target_feature_authkey, + [FEATURE_ATTR_TYPE_DEV_PROCODE ] = target_feature_procode, + [FEATURE_ATTR_TYPE_DEV_MAX_MTU ] = target_feature_mtu, + [FEATURE_ATTR_TYPE_CONNECT_BLE_ONLY ] = target_feature_ble_only, + [FEATURE_ATTR_TYPE_BT_EMITTER_INFO ] = target_feature_bt_emitter_info, + [FEATURE_ATTR_TYPE_MD5_GAME_SUPPORT ] = target_feature_md5_game_support, +}; + +u32 target_feature_parse_packet(void *priv, u8 *buf, u16 buf_size, u32 mask) +{ + printf("target_feature_parse_packet, mask = %x\n", mask); + return attr_get(priv, buf, buf_size, target_feature_mask_get_tab, FEATURE_ATTR_TYPE_MAX, mask); +} +#endif//SMART_BOX_EN + + diff --git a/apps/soundbox/smartbox/file_transfer/dev_format.c b/apps/soundbox/smartbox/file_transfer/dev_format.c new file mode 100644 index 0000000..118241a --- /dev/null +++ b/apps/soundbox/smartbox/file_transfer/dev_format.c @@ -0,0 +1,90 @@ +#include "dev_format.h" +#include "smartbox/smartbox.h" +#include "system/fs/fs.h" +#include "dev_manager.h" + +#if (SMART_BOX_EN && TCFG_DEV_MANAGER_ENABLE) +enum { + DEV_FORMAT_ERR_NONE = 0, + DEV_FORMAT_ERR_OFFLINE, + DEV_FORMAT_ERR_FAIL, +}; + +void (*end_cbk)(void) = NULL; + +//*----------------------------------------------------------------------------*/ +/**@brief 设备格式化初始化(手机客户端发指令) + @param + @return 格式化完成回调 + @note +*/ +/*----------------------------------------------------------------------------*/ +void dev_format_init(void (*end_callback)(void)) +{ + end_cbk = end_callback; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 设备格式化退出 + @param + @return 格式化完成回调 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void dev_format_close(void) +{ + if (end_cbk) { + end_cbk(); + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief 设备格式化处理响应(手机客户端发指令) + @param + @return 格式化完成回调 + @note +*/ +/*----------------------------------------------------------------------------*/ +void dev_format_start(u8 OpCode_SN, u8 *data, u16 len) +{ + u8 reason = DEV_FORMAT_ERR_NONE; + u32 dev_handle = READ_BIG_U32(data); + char *logo = smartbox_browser_dev_remap(dev_handle); + if (logo == NULL) { + reason = DEV_FORMAT_ERR_FAIL ; + JL_CMD_response_send(JL_OPCODE_DEVICE_FORMAT, JL_PRO_STATUS_FAIL, OpCode_SN, &reason, 1); + dev_format_close(); + return ; + } + + char *root_path = dev_manager_get_root_path_by_logo(logo); + if (root_path) { + + wdt_disable(); + int err = f_format(root_path, "fat", 32 * 1024); + wdt_enable(); + if (err) { + reason = DEV_FORMAT_ERR_FAIL ; + JL_CMD_response_send(JL_OPCODE_DEVICE_FORMAT, JL_PRO_STATUS_FAIL, OpCode_SN, &reason, 1); + } else { + printf("dev format ok\n"); + JL_CMD_response_send(JL_OPCODE_DEVICE_FORMAT, JL_PRO_STATUS_SUCCESS, OpCode_SN, &reason, 1); + dev_format_close(); + return ; + } + } else { + reason = DEV_FORMAT_ERR_OFFLINE ; + JL_CMD_response_send(JL_OPCODE_DEVICE_FORMAT, JL_PRO_STATUS_FAIL, OpCode_SN, &reason, 1); + } + dev_format_close(); + printf("dev format fail\n"); +} +#else +void dev_format_init(void (*end_callback)(void)) +{ +} +void dev_format_start(u8 OpCode_SN, u8 *data, u16 len) +{ +} +#endif + diff --git a/apps/soundbox/smartbox/file_transfer/dev_format.h b/apps/soundbox/smartbox/file_transfer/dev_format.h new file mode 100644 index 0000000..688d1a2 --- /dev/null +++ b/apps/soundbox/smartbox/file_transfer/dev_format.h @@ -0,0 +1,12 @@ + +#ifndef __DEV_FORMAT_H__ +#define __DEV_FORMAT_H__ + +#include "typedef.h" +#include "app_config.h" + +void dev_format_init(void (*end_callback)(void)); +void dev_format_start(u8 OpCode_SN, u8 *data, u16 len); + +#endif//__DEV_FORMAT_H__ + diff --git a/apps/soundbox/smartbox/file_transfer/file_delete.c b/apps/soundbox/smartbox/file_transfer/file_delete.c new file mode 100644 index 0000000..0eb409d --- /dev/null +++ b/apps/soundbox/smartbox/file_transfer/file_delete.c @@ -0,0 +1,336 @@ +#include "file_delete.h" +#include "smartbox/smartbox.h" +#include "system/includes.h" +#include "system/fs/fs.h" +#include "btstack_3th_protocol_user.h" +#include "dev_manager.h" +#include "key_event_deal.h" +#include "app_task.h" +#include "common/dev_status.h" +#include "bt/bt.h" +#include "common/dev_status.h" +#include "app_task.h" +#include "app_msg.h" +#include "clock_cfg.h" +#include "file_operate/file_manager.h" + +#if (SMART_BOX_EN && TCFG_DEV_MANAGER_ENABLE) + +#define FILE_DELELET_TIMEOUT (10*1000) + +#define FILE_DEL_DEBUG_EN +#ifdef FILE_DEL_DEBUG_EN +#define file_del_printf printf +#else +#define file_del_printf(...) +#endif + +struct __file_del { + struct __dev *dev;//当前设备节点 + struct vfscan *fsn;//设备扫描句柄 + u8 scandisk_break; + u8 busy; + u16 timerout; + void (*end_callback)(void); +}; + +struct __file_del *file_d = NULL; +#define __this file_d + +///播放参数,文件扫描时用,文件后缀等 +static const char scan_parm[] = "-t" +#if (TCFG_DEC_MP3_ENABLE) + "MP1MP2MP3" +#endif +#if (TCFG_DEC_WMA_ENABLE) + "WMA" +#endif +#if ( TCFG_DEC_WAV_ENABLE || TCFG_DEC_DTS_ENABLE) + "WAVDTS" +#endif +#if (TCFG_DEC_FLAC_ENABLE) + "FLA" +#endif +#if (TCFG_DEC_APE_ENABLE) + "APE" +#endif +#if (TCFG_DEC_M4A_ENABLE) + "M4AAAC" +#endif +#if (TCFG_DEC_M4A_ENABLE || TCFG_DEC_ALAC_ENABLE) + "MP4" +#endif +#if (TCFG_DEC_AMR_ENABLE) + "AMR" +#endif +#if (TCFG_DEC_DECRYPT_ENABLE) + "SMP" +#endif +#if (TCFG_DEC_MIDI_ENABLE) + "MID" +#endif + " -sn -r" + ; + +//*----------------------------------------------------------------------------*/ +/**@brief 文件删除扫盘匹配文件过程系统消息获取处理接口 + @param + @return 1:中断文件扫描处理, 0:继续扫盘 + @note 可以在这个函数内相应所需的消息事件 +*/ +/*----------------------------------------------------------------------------*/ +static int file_delete_scandisk_break(void) +{ + ///注意: + ///需要break fsn的事件, 请在这里拦截, + int msg[32] = {0}; + struct sys_event *event = NULL; + char *logo = NULL; + char *evt_logo = NULL; + app_task_get_msg(msg, ARRAY_SIZE(msg), 0); + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + event = (struct sys_event *)(&msg[1]); + switch (event->type) { + case SYS_DEVICE_EVENT: + switch ((u32)event->arg) { + case DRIVER_EVENT_FROM_SD0: + case DRIVER_EVENT_FROM_SD1: + case DRIVER_EVENT_FROM_SD2: + evt_logo = (char *)event->u.dev.value; + case DEVICE_EVENT_FROM_OTG: + if ((u32)event->arg == DEVICE_EVENT_FROM_OTG) { + evt_logo = (char *)"udisk0"; + } + ///设备上下线底层推出的设备逻辑盘符是跟跟音乐设备一致的(音乐/录音设备, 详细看接口注释) + logo = dev_manager_get_phy_logo(__this->dev); + ///响应设备插拔打断 + if (event->u.dev.event == DEVICE_EVENT_OUT) { + log_i("__func__ = %s logo=%s evt_logo=%s \n", __FUNCTION__, logo, evt_logo); + if (logo && evt_logo && (0 == strcmp(logo, evt_logo))) { + ///相同的设备才响应 + __this->scandisk_break = 1; + } + } else { + ///响应新设备上线 + __this->scandisk_break = 1; + } + if (__this->scandisk_break == 0) { + log_i("__func__ = %s DEVICE_EVENT_OUT TODO\n", __FUNCTION__); + dev_status_event_filter(event); + log_i("__func__ = %s DEVICE_EVENT_OUT OK\n", __FUNCTION__); + } + break; + } + break; + case SYS_BT_EVENT: + if (bt_background_event_handler_filter(event)) { + __this->scandisk_break = 1; + } + break; + case SYS_KEY_EVENT: + switch (event->u.key.event) { + case KEY_CHANGE_MODE: + ///响应切换模式事件 + __this->scandisk_break = 1; + break; + } + if (__this->scandisk_break) { + app_task_put_key_msg(event->u.key.event, (int)event->u.key.value); + return -1; + } + break; + } + break; + } + if (__this->scandisk_break) { + ///查询到需要打断的事件, 返回1, 并且重新推送一次该事件,跑主循环处理流程 + file_del_printf("\n--func=%s, line=%d\n", __FUNCTION__, __LINE__); + sys_event_notify(event); + file_del_printf("scandisk_break!!!!!!\n"); + return 1; + } else { + return 0; + } +} + +static void scan_enter(struct __dev *dev) +{ + __this->busy = 1; + clock_add_set(SCAN_DISK_CLK); +} + +static void scan_exit(struct __dev *dev) +{ + clock_remove_set(SCAN_DISK_CLK); + __this->busy = 0; +} + +static const struct __scan_callback scan_cb = { + .enter = scan_enter, + .exit = scan_exit, + .scan_break = file_delete_scandisk_break, +}; + + +//*----------------------------------------------------------------------------*/ +/**@brief 文件删除超时处理 + @param + @return + @note 这里是等待手机删除命令超时(即没有等到删除命令) +*/ +/*----------------------------------------------------------------------------*/ +static void file_delete_timeout(void *p) +{ + //批量删除超时, 退出删除流程 + if (__this && __this->timerout) { + file_del_printf("file_delete_timeout !!\n"); + file_delete_end(); + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件删除结束处理 + @param + @return + @note 释放资源 +*/ +/*----------------------------------------------------------------------------*/ +void file_delete_end(void) +{ + if (__this) { + dev_manager_scan_disk_release(__this->fsn); + if (__this->timerout) { + sys_timeout_del(__this->timerout); + __this->timerout = 0; + } + if (__this->end_callback) { + __this->end_callback(); + } + free(__this); + __this = NULL; + file_del_printf("file_delete_end\n"); + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件删除开始处理 + @param OpCode_SN:命名包的sn码, 命名回复时用到 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void file_delete_start(u8 OpCode_SN, u8 *data, u16 len) +{ + FILE *file = NULL; + u8 reason = 0; + u8 last = data[0]; + u32 dev_handle = READ_BIG_U32(data + 1); + u8 type = data[5]; + u32 sclust = READ_BIG_U32(data + 6); + file_del_printf("last = %d,dev_handle = %d,sclust = %d,type = %d,\n", last, dev_handle, sclust, type); + + char *logo = smartbox_browser_dev_remap(dev_handle); + if (logo == NULL) { + goto __err; + } + + if (__this == NULL) { + __this = zalloc(sizeof(struct __file_del)); + if (__this == NULL) { + goto __err; + } + } + + if (__this->timerout) { + sys_timeout_del(__this->timerout); + __this->timerout = 0; + } + + if (__this->fsn == NULL) { + __this->dev = dev_manager_find_spec(logo, 0); + if (__this->dev) { + __this->fsn = dev_manager_scan_disk(__this->dev, NULL, scan_parm, 0, &scan_cb); + if (__this->fsn == NULL) { + free(__this); + __this = NULL; + goto __err; + } + file_del_printf("%s, fscan ok\n", __FUNCTION__); + } + } else { + file_del_printf("%s, fscan aready\n", __FUNCTION__); + if (__this->busy) { + //正在执行删除, 回复APP繁忙 + printf("file delete busy\n"); + JL_CMD_response_send(JL_OPCODE_FILE_DELETE, JL_PRO_STATUS_BUSY, OpCode_SN, NULL, 0); + return ; + } + } + + file = file_manager_select(__this->dev, __this->fsn, FSEL_BY_SCLUST, sclust, &scan_cb);//根据文件簇号查找断点文件 + if (file) { + fdelete(file); + file_del_printf("delete file ok!!\n"); + JL_CMD_response_send(JL_OPCODE_FILE_DELETE, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0); + if (last == 0) { + if (__this->timerout == 0) { + __this->timerout = sys_timeout_add(NULL, file_delete_timeout, FILE_DELELET_TIMEOUT); + } else { + sys_timer_modify(__this->timerout, FILE_DELELET_TIMEOUT); + } + //批量删除, 还没有删除完毕, 等待继续删除 + file_del_printf("wait delete file more\n"); + return; + } + } else { + file_del_printf("file delete, no this file\n"); + JL_CMD_response_send(JL_OPCODE_FILE_DELETE, JL_PRO_STATUS_PARAM_ERR, OpCode_SN, NULL, 0); + } + file_delete_end(); + return ; + +__err: + JL_CMD_response_send(JL_OPCODE_FILE_DELETE, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0); + file_delete_end(); +} + + +//*----------------------------------------------------------------------------*/ +/**@brief 文件删除初始化 + @param end_callback:文件删除结束回调处理 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void file_delete_init(void (*end_callback)(void)) +{ + if (__this) { + printf("file_delete_init aready err!!\n"); + return ; + } + __this = zalloc(sizeof(struct __file_del)); + if (__this == NULL) { + printf("file_delete_init fail\n"); + if (end_callback) { + end_callback(); + } + return ; + } + __this->end_callback = end_callback; + //启动定时器, 防止APP后续没有发执行删除的命令过来, 可以超时退出 + __this->timerout = sys_timeout_add(NULL, file_delete_timeout, 2000); +} +#else +void file_delete_init(void (*end_callback)(void)) +{ +} +void file_delete_start(u8 OpCode_SN, u8 *data, u16 len) +{ +} +void file_delete_end(void) +{ +} +#endif + + diff --git a/apps/soundbox/smartbox/file_transfer/file_delete.h b/apps/soundbox/smartbox/file_transfer/file_delete.h new file mode 100644 index 0000000..2c1e05e --- /dev/null +++ b/apps/soundbox/smartbox/file_transfer/file_delete.h @@ -0,0 +1,12 @@ +#ifndef __FILE_DELETE_H__ +#define __FILE_DELETE_H__ + +#include "typedef.h" +#include "app_config.h" + +void file_delete_init(void (*end_callback)(void)); +void file_delete_start(u8 OpCode_SN, u8 *data, u16 len); +void file_delete_end(void); + +#endif//__FILE_DELETE_H__ + diff --git a/apps/soundbox/smartbox/file_transfer/file_transfer.c b/apps/soundbox/smartbox/file_transfer/file_transfer.c new file mode 100644 index 0000000..71cfc77 --- /dev/null +++ b/apps/soundbox/smartbox/file_transfer/file_transfer.c @@ -0,0 +1,795 @@ +#include "file_transfer.h" +#include "system/includes.h" +#include "system/fs/fs.h" +#include "btstack_3th_protocol_user.h" +#include "dev_manager.h" + +#if (SMART_BOX_EN && TCFG_DEV_MANAGER_ENABLE) + +#define FTP_FILE_DATA_UNIT (512) //(234)//不能超过RCSP协议的MTU大小 +#define FTP_FILE_DATA_RECIEVE_REMAIN_SIZE (128) //接收缓存预留 +#define FTP_FILE_DATA_RECIEVE_BUF_MIN_SIZE (FTP_FILE_DATA_UNIT + FTP_FILE_DATA_RECIEVE_REMAIN_SIZE) +#define FTP_FILE_DATA_RECIEVE_TIMEOUT (3*1000) //超时拉取数据等待时长, 超时时间到了,自动拉取 +#define FTP_DOWNLOAD_FOLDER_NAME "downlad" //下载目录 +#define FTP_FILE_VAILD_MARK "JL_FTP" //断点续传需要用到的文件内容标记 +#define FTP_FILE_VAILD_MARK_TIMER_UNIT (10*1000) //单位ms +#define FTP_FILE_CRC_CAC_MAX_COUNTER (100) //文件校验一次校验的数据块个数 + +//#define FTP_DEBUG_ENABLE +#ifdef FTP_DEBUG_ENABLE +#define ftp_printf printf +#else +#define ftp_printf(...) +#endif//FTP_DEBUG_ENABLE + +enum { + FTP_END_REASON_NONE = 0, //没有错误 + FTP_END_REASON_WRITE_ERR, //写失败 + FTP_END_REASON_DATA_OVER_LIMIT, //数据超范围 + FTP_END_REASON_DATA_CRC_ERR, //文件校验失败 +}; + +struct __file_check { + u16 crc_tmp; + u32 counter; + u32 remain; +}; + + +struct __ftp_download { + u32 file_size; + u32 file_offset; + u8 win[FTP_FILE_DATA_UNIT]; + u8 packet_id; + u8 packet_id_max; + u8 last_packet; + u16 mark_timer; + u16 get_timeout; + u16 start_timerout; + u16 file_crc; + struct __file_check check; + char *filepath; + FILE *file; + struct __dev *dev; + void (*end_callback)(void); +}; +static struct __ftp_download *ftp_d = NULL; + +static void file_transfer_download_get_data(void); +static void __file_transfer_download_file_check_caculate(void *priv); + +//*----------------------------------------------------------------------------*/ +/**@brief 校验分次处理消息发送处理 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void file_transfer_download_file_check_continue(void) +{ + int msg[4]; + msg[0] = (int)__file_transfer_download_file_check_caculate; + msg[1] = 1; + msg[2] = 0; + os_taskq_post_type("app_core", Q_CALLBACK, 3, msg); +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件数据块crc校验 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void __file_transfer_download_file_check_caculate(void *priv) +{ + if (ftp_d == NULL) { + return ; + } + wdt_clear(); + JL_ERR err = 0; + u32 cnt; + if (ftp_d->check.counter >= FTP_FILE_CRC_CAC_MAX_COUNTER) { + cnt = FTP_FILE_CRC_CAC_MAX_COUNTER; + } else { + cnt = ftp_d->check.counter; + } + printf("cnt = %d, check.counter = %d, crc_tmp = %x\n", cnt, ftp_d->check.counter, ftp_d->check.crc_tmp); + for (int i = 0; i < cnt; i++) { + fread(ftp_d->file, ftp_d->win, sizeof(ftp_d->win)); + ftp_d->check.crc_tmp = CRC16_with_initval(ftp_d->win, sizeof(ftp_d->win), ftp_d->check.crc_tmp); + } + ftp_d->check.counter -= cnt; + if (ftp_d->check.counter == 0) { + if (ftp_d->check.remain) { + fread(ftp_d->file, ftp_d->win, ftp_d->check.remain); + printf("remain\n"); + put_buf(ftp_d->win, ftp_d->check.remain); + ftp_d->check.crc_tmp = CRC16_with_initval(ftp_d->win, ftp_d->check.remain, ftp_d->check.crc_tmp); + } + //crc_check end + if (ftp_d->check.crc_tmp == ftp_d->file_crc) { + printf("crc check ok!!, start rename\n"); + fseek(ftp_d->file, ftp_d->file_size, SEEK_SET); + //进入重命名流程 + err = JL_CMD_send(JL_OPCODE_FILE_RENAME, NULL, 0, 1); + if (err) { + //命令发送失败, 直接停止 + file_transfer_close(); + } + return ; + } else { + printf("crc check fail, crc_tmp = %x, file_crc = %x!!\n", ftp_d->check.crc_tmp, ftp_d->file_crc); + u8 reason = FTP_END_REASON_DATA_CRC_ERR; + fdelete(ftp_d->file); + ftp_d->file = NULL; + JL_ERR err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1); + if (err) { + //命令发送失败, 直接停止 + file_transfer_close(); + } + } + } else { + file_transfer_download_file_check_continue(); + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件文件校验处理 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void file_transfer_download_file_check(void) +{ + ftp_d->check.crc_tmp = 0; + ftp_d->check.counter = ftp_d->file_size / sizeof(ftp_d->win); + ftp_d->check.remain = ftp_d->file_size % sizeof(ftp_d->win); + ftp_d->file_offset = ftp_d->file_size; + printf("crc_tmp = %x, counter = %d, remain = %d\n", ftp_d->check.crc_tmp, ftp_d->check.counter, ftp_d->check.remain); + fseek(ftp_d->file, 0, SEEK_SET); + file_transfer_download_file_check_continue(); +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件传输重命名 + @param rename:重命名 + @return + @note 此过程接收的数据是实际文件传输的内容 +*/ +/*----------------------------------------------------------------------------*/ +static int file_rename(const char *rename) +{ + if (ftp_d && ftp_d->file) { + //rename之前先关闭文件 + fclose(ftp_d->file); + ftp_d->file = NULL; + //重新打开文件 + //printf("ftp_d->filepath:%s, rename:%s\n", ftp_d->filepath, rename); + ftp_d->file = fopen(ftp_d->filepath, "r"); + //free(path); + if (ftp_d->file) { + //文件打开成功, 重命名 + int ret = frename(ftp_d->file, rename); + if (ret) { + printf("rename fail\n"); + } else { + printf("rename ok\n"); + } + return ret; + } else { + printf("rename file open err!!"); + } + } + return -1; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件重传文件头信息保存处理 + @param file:文件句柄,win:临时缓存,offset:文件偏移 + @return + @note 文件传输过程, 定时会触发断点续传信息保存处理 +*/ +/*----------------------------------------------------------------------------*/ +static void file_transfer_download_vaild_mark_fill(FILE *file, u8 *win, u32 offset) +{ + if (file) { + fseek(file, 0, SEEK_SET); + memset(win, 0, FTP_FILE_DATA_UNIT); + memcpy(win, FTP_FILE_VAILD_MARK, strlen(FTP_FILE_VAILD_MARK)); + memcpy(win + strlen(FTP_FILE_VAILD_MARK), &offset, sizeof(offset)); + fwrite(file, win, FTP_FILE_DATA_UNIT); + fseek(file, offset, SEEK_SET); + printf("============================================%s, offset = %d\n", __FUNCTION__, offset); + } +} + + +//*----------------------------------------------------------------------------*/ +/**@brief 断点续传信息解析处理 + @param file:文件句柄, 文件偏移获取指针 + @return + @note 在文件传输开始的时候进行解析, 目的是找到续传文件偏移 +*/ +/*----------------------------------------------------------------------------*/ +static void file_transfer_download_intermittent_parse(FILE *file, u32 *offset) +{ + if (file) { + char mark[10] = {0}; + fseek(file, 0, SEEK_SET); + int rlen = fread(file, mark, strlen(FTP_FILE_VAILD_MARK)); + if (rlen) { + if (strcmp(mark, FTP_FILE_VAILD_MARK) == 0) { + printf("find VAILD_MARK !!\n"); + rlen = fread(file, offset, sizeof(u32)); + if (rlen) { + printf("read offset ok, %d!!\n", *offset); + fseek(file, *offset, SEEK_SET); + } else { + printf("read offset fail!!\n"); + *offset = 0; + } + } + } + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件下载数据拉取超时处理 + @param priv:私有参数, + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void file_transfer_download_get_timeout(void *priv) +{ + ftp_printf("timeout!!!\n"); + //在超时时间内没有收完所需要的数据, 重新拉取数据 + file_transfer_download_get_data(); +} + +//*----------------------------------------------------------------------------*/ +/**@brief 断点续传定时保存处理 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void file_transfer_download_vaild_mark_scan(void *priv) +{ + if (ftp_d && ftp_d->file && ftp_d->mark_timer && ftp_d->last_packet == 0) { + file_transfer_download_vaild_mark_fill(ftp_d->file, ftp_d->win, ftp_d->file_offset); + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件下载数据拉取处理 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void file_transfer_download_get_data(void) +{ + if (ftp_d == NULL || ftp_d->file == NULL) { + ftp_printf("file not ready %d!!\n", __LINE__); + return; + } + + u32 file_offset = 0; + u16 recieve_max = rcsp_packet_write_alloc_len(); + if (recieve_max < FTP_FILE_DATA_RECIEVE_BUF_MIN_SIZE) { + ftp_printf("not enough buf to recieve!!\n"); + return; + } else { + ///预留些接收缓存给其他通信使用 + recieve_max -= FTP_FILE_DATA_RECIEVE_REMAIN_SIZE; + } + + ftp_d->packet_id = 0; + ftp_d->packet_id_max = recieve_max / FTP_FILE_DATA_UNIT; + recieve_max = ftp_d->packet_id_max * FTP_FILE_DATA_UNIT; + + if (ftp_d->last_packet) { + recieve_max = FTP_FILE_DATA_UNIT; + file_offset = 0; + } else { + file_offset = ftp_d->file_offset; + } + ftp_printf("[get]recieve_max:%d, file_offset %d\n", recieve_max, file_offset); + u8 parm[7] = {0}; + parm[0] = 0; + WRITE_BIG_U16(parm + 1, recieve_max); + WRITE_BIG_U32(parm + 3, file_offset); + JL_ERR err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER, parm, sizeof(parm), 0); + if (err) { + ftp_printf("%s fail!!! %d\n", __FUNCTION__, err); + return; + } + if (ftp_d->get_timeout == 0) { + ftp_d->get_timeout = sys_timeout_add(NULL, file_transfer_download_get_timeout, FTP_FILE_DATA_RECIEVE_TIMEOUT); + } + return; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件路径长度统计 + @param root_path:根目录, folder:文件夹,filename:文件名 + @return 文件路径长度 + @note +*/ +/*----------------------------------------------------------------------------*/ +static u32 creat_path_len(char *root_path, const char *folder, u8 *name, u16 name_len) +{ + return (strlen(root_path) + strlen(folder) + name_len + strlen("/") + 1); +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件路径组装处理 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void creat_file_path(char *path, char *root_path, const char *folder, u8 *name, u16 name_len) +{ + strcat(path, root_path); + strcat(path, folder); + strcat(path, "/"); + //strcat(path, name); + memcpy(path + strlen(root_path) + strlen(folder) + 1, name, name_len); + //printf("path = %s\n", path); +} + + +//*----------------------------------------------------------------------------*/ +/**@brief 文件下载开始 + @param OpCode_SN:数据包序列号,data:数据, len:数据长度 + @return 文件路径长度 + @note +*/ +/*----------------------------------------------------------------------------*/ +void file_transfer_download_start(u8 OpCode_SN, u8 *data, u16 len) +{ + if (ftp_d) { + //收到了文件传输开始命令, 停止启动超时处理 + if (ftp_d->start_timerout) { + sys_timeout_del(ftp_d->start_timerout); + ftp_d->start_timerout = 0; + } + } + + JL_ERR err = 0; + ///创建文件 + u32 file_size = READ_BIG_U32(data);//占用4byte + u16 file_crc = READ_BIG_U16(data + 4);//占用2byte + u8 *file_name = data + 4 + 2; + u16 file_name_len = len - 6; + if (ftp_d == NULL) { + ftp_d = zalloc(sizeof(struct __ftp_download)); + if (ftp_d) { + printf("%s, no mem\n", __FUNCTION__); + JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_START, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0); + return ; + } + } + + ftp_printf("file_size = %d, file_crc = %x\n", file_size, file_crc); + + struct __dev *dev = dev_manager_find_active(0); + if (!dev) { + file_transfer_close(); + ftp_printf("no dev online !!\n"); + JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_START, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0); + return ; + } + char *root_path = dev_manager_get_root_path(dev); + char *folder = FTP_DOWNLOAD_FOLDER_NAME; + char *path = zalloc(creat_path_len(root_path, folder, file_name, file_name_len)); + + u8 new_file = 0; + ASSERT(path); + creat_file_path(path, root_path, folder, file_name, file_name_len); + ftp_d->file = fopen(path, "r"); + if (ftp_d->file) { + printf("file exist\n"); + new_file = 0; + fclose(ftp_d->file); + ftp_d->file = NULL; + } else { + printf("file new\n"); + new_file = 1; + } + + ftp_d->file = fopen(path, "w+"); + ftp_d->filepath = path; + //free(path); + if (ftp_d->file == NULL) { + ftp_printf("file create err\n"); + file_transfer_close(); + ///文件打开失败, 回复APP文件传输失败 + JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_START, JL_PRO_STATUS_FAIL, OpCode_SN, NULL, 0); + return ; + } + ftp_d->dev = dev; + ftp_d->file_offset = 0; + ftp_d->file_crc = file_crc; + ftp_d->last_packet = 0; + ftp_d->file_size = file_size; + if (ftp_d->file_size > sizeof(ftp_d->win)) { + if (new_file == 0) { + ///解析断点续传的文件偏移 + file_transfer_download_intermittent_parse(ftp_d->file, &ftp_d->file_offset); + } + if (ftp_d->file_offset == 0 || ftp_d->file_offset > file_size) { + printf("file offset err !! reset offset \n"); + ftp_d->file_offset = sizeof(ftp_d->win); + file_transfer_download_vaild_mark_fill(ftp_d->file, ftp_d->win, ftp_d->file_offset); + } else if (ftp_d->file_offset == file_size) { + //上次文件已经收完, 进入校验流程 + printf("file aready download end \n"); + file_transfer_download_file_check(); + return ; + } + } else { + ftp_d->last_packet = 1; + } + ///回复APP文件传输准备就绪 + u16 file_data_unit = 0; + WRITE_BIG_U16(&file_data_unit, FTP_FILE_DATA_UNIT); + err = JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_START, JL_PRO_STATUS_SUCCESS, OpCode_SN, (u8 *)&file_data_unit, sizeof(u16)); + if (err == 0) { + printf("%s ok!! file_offset: %d, data unit = %d\n", __FUNCTION__, ftp_d->file_offset, FTP_FILE_DATA_UNIT); + ///回复启动成功之后,启动数据拉取操作(这里是第一次) + //fseek(ftp_d->file, ftp_d->file_offset, SEEK_SET);//重定位下文件位置 + file_transfer_download_get_data(); + ftp_d->mark_timer = sys_timer_add(NULL, file_transfer_download_vaild_mark_scan, FTP_FILE_VAILD_MARK_TIMER_UNIT); + return ; + } else { + ftp_printf("%s resp fail!!\n", __FUNCTION__); + file_transfer_close(); + ftp_d = NULL; + } + return; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件传输, 重命名处理 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void file_transfer_file_rename(u8 status, u8 *data, u16 len) +{ + if (ftp_d) { + if (status == JL_PRO_STATUS_SUCCESS) { + printf("%s !!, %d\n", __FUNCTION__, __LINE__); + put_buf(data, len); + //重命名 + if (file_rename((const char *)data) == 0) { + u8 reason = FTP_END_REASON_NONE; + int err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1); + if (err) { + file_transfer_close(); + } + dev_manager_set_valid(ftp_d->dev, 1); + } else { + //有重名的, 重新获取新名称, 如:“xxx_n.mp3”,n为数字 + int err = JL_CMD_send(JL_OPCODE_FILE_RENAME, NULL, 0, 1); + if (err) { + file_transfer_close(); + } + } + } else { + ftp_printf("%s fail!! %d\n", __FUNCTION__, status); + if (ftp_d->file) { + //重命名失败,删除文件 + printf("renam file fail, delete file\n"); + fdelete(ftp_d->file); + ftp_d->file = NULL; + } + file_transfer_close(); + } + } +} + + +//*----------------------------------------------------------------------------*/ +/**@brief 文件下载结束(F->A的回复处理) + @param status:命令执行状态,data:数据, len:数据长度 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void file_transfer_download_end(u8 status, u8 *data, u16 len) +{ + if (ftp_d) { + ftp_printf("%s status %d\n", __FUNCTION__, status); + file_transfer_close(); + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件传输,最后一包数据接收处理 + @param data:数据内容 len:数据长度 + @return + @note 文件传输流程是最后才写文件第一包数据 +*/ +/*----------------------------------------------------------------------------*/ +static void file_transfer_download_doing_last_packet(u8 *data, u16 len) +{ + u8 reason = FTP_END_REASON_NONE; + JL_ERR err = 0; + if (len > FTP_FILE_DATA_UNIT) { + printf("last packet data len err!!\n"); + reason = FTP_END_REASON_DATA_OVER_LIMIT; + err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1); + if (err) { + //命令发送失败, 直接停止 + file_transfer_close(); + } + return ; + } + if (ftp_d->get_timeout) { + sys_timeout_del(ftp_d->get_timeout); + ftp_d->get_timeout = 0; + } + printf("get last packet ok\n"); + fseek(ftp_d->file, 0, SEEK_SET); + int wlen = fwrite(ftp_d->file, data, len); + if (wlen != len) { + ftp_printf("%s err !! %d\n", __FUNCTION__, wlen); + reason = FTP_END_REASON_WRITE_ERR;//文件写异常 + err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1); + if (err) { + //命令发送失败, 直接停止 + file_transfer_close(); + } + } else { + //文件接收完成,文件校验 + file_transfer_download_file_check(); + } + //fseek(ftp_d->file, ftp_d->file_offset, SEEK_SET); +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件传输过程处理(A->F) + @param data:数据, len:数据长度 + @return + @note 此过程接收的数据是实际文件传输的内容 +*/ +/*----------------------------------------------------------------------------*/ +void file_transfer_download_doing(u8 *data, u16 len) +{ + if (ftp_d && ftp_d->file) { + ftp_printf("id = %d, len = %d\n", data[0], len - 1); + + if (ftp_d->packet_id != data[0]) { + ftp_printf("warning !! packet_id err %d, %d\n", ftp_d->packet_id, data[0]); + return ; + } + len -= 1; + data += 1; + ftp_d->packet_id ++; + u8 reason = FTP_END_REASON_NONE; + int wlen = 0; + JL_ERR err = 0; + + if (ftp_d->last_packet) { + file_transfer_download_doing_last_packet(data, len); + return ; + } + + if (ftp_d->file_offset >= ftp_d->file_size) { + printf("err, file data is over limit!!\n"); + reason = FTP_END_REASON_DATA_OVER_LIMIT;//数据超范围 + err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1); + if (err) { + //命令发送失败, 直接停止 + file_transfer_close(); + } + return ; + } + + wlen = fwrite(ftp_d->file, data, len); + if (wlen != len) { + ftp_printf("%s err !! %d\n", __FUNCTION__, wlen); + reason = FTP_END_REASON_WRITE_ERR;//文件写异常 + err = JL_CMD_send(JL_OPCODE_FILE_TRANSFER_END, &reason, 1, 1); + if (err) { + //命令发送失败, 直接停止 + file_transfer_close(); + } + } else { + if (len != FTP_FILE_DATA_UNIT) { + ftp_printf("data is not a normal unit !!\n"); + } + ftp_d->file_offset += len; + ftp_printf("ftp_d->file_offset:%d, ftp_d->file_size:%d, len:%d\n", ftp_d->file_offset, ftp_d->file_size, len); + if (ftp_d->file_offset >= ftp_d->file_size) { + ftp_printf("file recieve end!! get file first packet\n"); + if (ftp_d->mark_timer) { + sys_timer_del(ftp_d->mark_timer); + ftp_d->mark_timer = 0; + } + ftp_d->last_packet = 1; + file_transfer_download_get_data(); + return; + } + ftp_d->last_packet = 0; + if (ftp_d->get_timeout) { + //接收数据成功,重置一下超时 + ftp_printf("reset timeout!!\n"); + sys_timer_modify(ftp_d->get_timeout, FTP_FILE_DATA_RECIEVE_TIMEOUT); + } + if (ftp_d->packet_id >= ftp_d->packet_id_max) { + //该次数据包已经收完,拉取新的数据 + ftp_printf("get more!!\n"); + file_transfer_download_get_data(); + } + } + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件传输,被动取消处理 + @param OpCode_SN:数据包sn码, 回复的时候用的 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void file_transfer_download_passive_cancel(u8 OpCode_SN, u8 *data, u16 len) +{ + file_transfer_close(); + printf("passive_cancel answer\n"); + JL_CMD_response_send(JL_OPCODE_FILE_TRANSFER_CANCEL, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0); +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件传输,主动取消处理 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void file_transfer_download_active_cancel(void) +{ + if (ftp_d) { + file_transfer_close(); + JL_CMD_send(JL_OPCODE_FILE_TRANSFER_CANCEL, NULL, 0, 1); + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件传输,主动取消处理回复处理 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void file_transfer_download_active_cancel_response(u8 status, u8 *data, u16 len) +{ + if (status == JL_PRO_STATUS_SUCCESS) { + printf("active_cancel_response ok!!"); + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件传输关闭处理 + @param + @return + @note 主要是做一些资源释放处理 +*/ +/*----------------------------------------------------------------------------*/ +void file_transfer_close(void) +{ + if (ftp_d) { + if (ftp_d->check.counter) { + printf("crc caculating !! close err\n"); + return ; + } + if (ftp_d->start_timerout) { + sys_timeout_del(ftp_d->start_timerout); + ftp_d->start_timerout = 0; + } + if (ftp_d->get_timeout) { + sys_timeout_del(ftp_d->get_timeout); + ftp_d->get_timeout = 0; + } + if (ftp_d->mark_timer) { + sys_timer_del(ftp_d->mark_timer); + ftp_d->mark_timer = 0; + } + if (ftp_d->file) { + if (ftp_d->last_packet == 0) { + //文件没有传输完, 如果不是直接断电, 有机会执行更新断点续传的文件偏移信息 + file_transfer_download_vaild_mark_fill(ftp_d->file, ftp_d->win, ftp_d->file_offset); + } + fclose(ftp_d->file); + } + if (ftp_d->filepath) { + free(ftp_d->filepath); + } + if (ftp_d->end_callback) { + ftp_d->end_callback(); + } + free(ftp_d); + ftp_d = NULL; + printf("file_transfer_close!!!!!!\n"); + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief 文件传输启动超时处理 + @param + @return + @note 响应app预处理,之后在设定时间内没有发文件传输开始命令过来触发超时 +*/ +/*----------------------------------------------------------------------------*/ +static void file_transfer_start_timeout(void) +{ + printf("%s\n", __FUNCTION__); + file_transfer_close(); +} + + +//*----------------------------------------------------------------------------*/ +/**@brief 文件传输初始化处理 + @param end_callback:文件传输结束处理回调 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void file_transfer_init(void (*end_callback)(void)) +{ + if (ftp_d) { + ftp_printf("file downloading err %d!!\n", __LINE__); + return ; + } + ftp_d = zalloc(sizeof(struct __ftp_download)); + if (ftp_d == NULL) { + if (end_callback) { + end_callback(); + } + return ; + } + ftp_d->end_callback = end_callback; + //如果在超时时间内都没有发文件传输开始命令, 退出文件传输流程 + ftp_d->start_timerout = sys_timeout_add(NULL, file_transfer_start_timeout, 2000); +} +#else + +void file_transfer_init(void (*end_callback)(void)) +{ +} +void file_transfer_download_start(u8 OpCode_SN, u8 *data, u16 len) +{ +} +void file_transfer_download_end(u8 status, u8 *data, u16 len) +{ +} +void file_transfer_download_doing(u8 *data, u16 len) +{ +} +void file_transfer_download_passive_cancel(u8 OpCode_SN, u8 *data, u16 len) +{ +} +void file_transfer_download_active_cancel(void) +{ +} +void file_transfer_download_active_cancel_response(u8 status, u8 *data, u16 len) +{ +} +void file_transfer_file_rename(u8 status, u8 *data, u16 len) +{ +} +void file_transfer_close(void) +{ +} + +#endif + + + diff --git a/apps/soundbox/smartbox/file_transfer/file_transfer.h b/apps/soundbox/smartbox/file_transfer/file_transfer.h new file mode 100644 index 0000000..abbb342 --- /dev/null +++ b/apps/soundbox/smartbox/file_transfer/file_transfer.h @@ -0,0 +1,18 @@ +#ifndef __FILE_TRANSFER_H__ +#define __FILE_TRANSFER_H__ + +#include "typedef.h" +#include "app_config.h" + +void file_transfer_init(void (*end_callback)(void)); +void file_transfer_download_start(u8 OpCode_SN, u8 *data, u16 len); +void file_transfer_download_end(u8 status, u8 *data, u16 len); +void file_transfer_download_doing(u8 *data, u16 len); +void file_transfer_download_passive_cancel(u8 OpCode_SN, u8 *data, u16 len); +void file_transfer_download_active_cancel(void); +void file_transfer_download_active_cancel_response(u8 status, u8 *data, u16 len); +void file_transfer_file_rename(u8 status, u8 *data, u16 len); +void file_transfer_close(void); + +#endif//__FILE_TRANSFER_H__ + diff --git a/apps/soundbox/smartbox/func_cmd/bt_func.c b/apps/soundbox/smartbox/func_cmd/bt_func.c new file mode 100644 index 0000000..5b5c5d9 --- /dev/null +++ b/apps/soundbox/smartbox/func_cmd/bt_func.c @@ -0,0 +1,73 @@ +#include "smartbox/func_cmd/bt_func.h" +#include "smartbox/func_cmd_common.h" +#include "smartbox/function.h" +#include "smartbox/config.h" +#include "smartbox/event.h" +#include "app_action.h" + +#include "le_smartbox_module.h" +#include "smartbox_music_info_setting.h" + +#if (SMART_BOX_EN) + +bool bt_func_set(void *priv, u8 *data, u16 len) +{ +#if RCSP_ADV_MUSIC_INFO_ENABLE + music_info_cmd_handle(data, len); +#endif + return true; +} + +u32 bt_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask) +{ + u16 offset = 0; + u16 music_sec = 0; + u32 curr_music_sec = 0; + u8 music_state = 0; + u8 player_time[4]; + +#if RCSP_ADV_MUSIC_INFO_ENABLE + if (mask & BIT(BT_INFO_ATTR_MUSIC_TITLE)) { + offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_TITLE, get_music_title(), get_music_title_len()); + } + if (mask & BIT(BT_INFO_ATTR_MUSIC_ARTIST)) { + offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_ARTIST, get_music_artist(), get_music_artist_len()); + } + if (mask & BIT(BT_INFO_ATTR_MUSIC_ALBUM)) { + offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_ALBUM, get_music_album(), get_music_album_len()); + } + if (mask & BIT(BT_INFO_ATTR_MUSIC_NUMBER)) { + offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_NUMBER, get_music_number(), get_music_number_len()); + } + if (mask & BIT(BT_INFO_ATTR_MUSIC_TOTAL)) { + offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_TOTAL, get_music_total(), get_music_total_len()); + } + if (mask & BIT(BT_INFO_ATTR_MUSIC_GENRE)) { + offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_GENRE, get_music_genre(), get_music_genre_len()); + } + if (mask & BIT(BT_INFO_ATTR_MUSIC_TIME)) { + music_sec = get_music_total_time(); + player_time[0] = music_sec >> 8; + player_time[1] = music_sec; + offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_TIME, player_time, 2); + } + if (mask & BIT(BT_INFO_ATTR_MUSIC_STATE)) { + //printf("\n music state\n"); + music_state = get_music_player_state(); + offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_STATE, &music_state, 1); + } + if (mask & BIT(BT_INFO_ATTR_MUSIC_CURR_TIME)) { + //printf("\nmusic curr time\n"); + curr_music_sec = get_music_curr_time(); + player_time[0] = curr_music_sec >> 24; + player_time[1] = curr_music_sec >> 16; + player_time[2] = curr_music_sec >> 8; + player_time[3] = curr_music_sec; + offset += add_one_attr(buf, buf_size, offset, BT_INFO_ATTR_MUSIC_CURR_TIME, player_time, 4); + } +#endif + + return offset; +} + +#endif diff --git a/apps/soundbox/smartbox/func_cmd/fm_func.c b/apps/soundbox/smartbox/func_cmd/fm_func.c new file mode 100644 index 0000000..dec655b --- /dev/null +++ b/apps/soundbox/smartbox/func_cmd/fm_func.c @@ -0,0 +1,317 @@ +#include "smartbox/func_cmd/fm_func.h" +#include "smartbox/func_cmd_common.h" +#include "smartbox/function.h" +#include "smartbox/config.h" +#include "smartbox/event.h" +#include "app_action.h" + +#include "key_event_deal.h" + +#if (SMART_BOX_EN) + +#if (TCFG_APP_FM_EN) +#include "fm/fm_api.h" +#include "fm/fm_rw.h" + +#pragma pack(1) +struct _FM_STATUS_INFO { + u8 status; + u8 cur_channel; + u16 cur_fre; + u8 mode; +}; +#pragma pack() + +#define FM_INFO_ATTR_STATUS (0) +#define FM_INFO_ATTR_FRE (1) + +#define SCANE_ALL (0x01) +#define SCANE_DOWN (0x02) +#define SCANE_UP (0x03) + +enum { + FM_FUNC_MUSIC_PP = 0x1, + FM_FUNC_PREV_FREQ, + FM_FUNC_NEXT_FREQ, + FM_FUNC_PREV_STATION, + FM_FUNC_NEXT_STATION, + FM_FUNC_SCAN, + FM_FUNC_SET_STATION, + FM_FUNC_DEL_STATION, + FM_FUNC_SET_FRE, + FM_FUNC_DEL_FRE, +}; + +enum { + FM_FUNC_SCAN_ALL = 0x0, + FM_FUNC_SCAN_ALL_DOWN, + FM_FUNC_SCAN_ALL_UP, + FM_FUNC_SCAN_STOP, +}; + +enum { + FM_FUNC_STATUS_PLAY = 0x01, + FM_FUNC_STATUS_PAUSE, + FM_FUNC_STATUS_SCANING, +}; + +extern u8 fm_get_scan_flag(void); +extern u8 fm_get_fm_dev_mute(void); + +static u8 fm_get_status(u8 scan_all_en) +{ + u8 scan_flag = fm_get_scan_flag(); + u8 fm_dev_mute = fm_get_fm_dev_mute(); + if (SCANE_DOWN == scan_flag || SCANE_UP == scan_flag) { + return FM_FUNC_STATUS_SCANING; + } else if (SCANE_ALL == scan_flag) { + if (scan_all_en && 0 == fm_dev_mute) { + smartbox_function_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE)); + } + return FM_FUNC_STATUS_SCANING; + } else if (0 == fm_dev_mute) { + return FM_FUNC_STATUS_PLAY; + } else { + return FM_FUNC_STATUS_PAUSE; + } +} + +static u16 fm_scan_timer = 0; +static void fm_scan_state_func(void *priv) +{ + /* printf("fm_scan_state_func\n"); */ + if (FM_FUNC_STATUS_SCANING == fm_get_status(1)) { + return; + } + if (fm_scan_timer) { + sys_hi_timer_del(fm_scan_timer); + fm_scan_timer = 0; + } + // 更新 + smartbox_function_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE)); +} + +bool fm_func_set(void *priv, u8 *data, u16 len) +{ + /* printf("fm_func_set\n"); */ + /* put_buf(data, len); */ + u8 fun_cmd = data[0]; + u16 cmd_param = 0; + u16 param_len = len - 1; + switch (fun_cmd) { + case FM_FUNC_MUSIC_PP: + printf("fm pp\n"); + fm_volume_pp(); + smartbox_function_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE)); + break; + case FM_FUNC_PREV_FREQ: + printf("fm prev fre\n"); + fm_prev_freq(); + smartbox_function_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE)); + break; + case FM_FUNC_NEXT_FREQ: + printf("fm next fre\n"); + fm_next_freq(); + smartbox_function_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE)); + break; + case FM_FUNC_PREV_STATION: + printf("fm prev station\n"); + fm_prev_station(); + smartbox_function_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE)); + break; + case FM_FUNC_NEXT_STATION: + printf("fm next station\n"); + fm_next_station(); + smartbox_function_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE)); + break; + case FM_FUNC_SCAN: + printf("fm scan\n"); + if (1 == param_len) { + cmd_param = data[1]; + switch (cmd_param) { + case FM_FUNC_SCAN_ALL: + printf("fm scan all\n"); + fm_scan_all(); + break; + case FM_FUNC_SCAN_ALL_DOWN: + printf("fm scan prev\n"); + fm_scan_up(); + break; + case FM_FUNC_SCAN_ALL_UP: + printf("fm scan next\n"); + fm_scan_down(); + break; + case FM_FUNC_SCAN_STOP: + printf("fm scan stop\n"); + if (FM_FUNC_STATUS_SCANING == fm_get_status(0)) { + fm_scan_stop(); + } + break; + default: + printf("fm scan default\n"); + break; + } + if (0 == fm_scan_timer) { + fm_scan_timer = sys_hi_timer_add(NULL, fm_scan_state_func, 1000); + } + } + break; + case FM_FUNC_SET_STATION: + printf("fm sel station\n"); + extern void fm_sel_station(u8 channel); + if (1 == param_len) { + cmd_param = data[1]; + fm_sel_station(cmd_param); + } + break; + case FM_FUNC_DEL_STATION: + printf("fm del station\n"); + break; + case FM_FUNC_SET_FRE: + printf("fm sel fre\n"); + extern u8 fm_set_fre(u16 fre); + printf("param_len : %d\n", param_len); + for (u8 i = 0; i < param_len; i++) { + printf("data[%d] : 0x%x\n", i, data[i + 1]); + } + if (2 == param_len) { + cmd_param = (data[1] << 8 | data[2]) * 10; + printf("fm target = %d\n", cmd_param); + fm_set_fre(cmd_param); + } + break; + case FM_FUNC_DEL_FRE: + printf("fm del ...\n"); + break; + default: + break; + } + + switch (fun_cmd) { + case FM_FUNC_SET_FRE: + case FM_FUNC_SET_STATION: + // 更新状态 + smartbox_msg_post(USER_MSG_SMARTBOX_FM_UPDATE_STATE, 1, (int)priv); + break; + } + + return true; +} + +u32 fm_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask) +{ + u16 offset = 0; + if (mask & BIT(FM_INFO_ATTR_STATUS)) { + extern u8 fm_get_cur_channel(void); + extern u16 fm_get_cur_fre(void); + extern u8 fm_get_mode(void); + + struct _FM_STATUS_INFO fm_status_info; + u16 fre = fm_get_cur_fre(); + fre = app_htons(fre); + fm_status_info.cur_fre = fre; + fm_status_info.cur_channel = fm_get_cur_channel(); + fm_status_info.status = fm_get_status(0); + if (FM_FUNC_STATUS_PLAY != fm_status_info.status) { + fm_status_info.status = 0; + } + fm_status_info.mode = fm_get_mode(); + + /* printf("fm_func_get, %d, %d, %d, %d\n", fm_status_info.cur_fre, fm_status_info.cur_channel, fm_status_info.status, fm_status_info.mode); */ + offset = add_one_attr(buf, buf_size, offset, FM_INFO_ATTR_STATUS, (u8 *)&fm_status_info, sizeof(fm_status_info)); + } + + if (mask & BIT(FM_INFO_ATTR_FRE)) { + FM_INFO fm_info = {0}; + fm_read_info(&fm_info); + /* printf("get_fm_channel_fre_info:\n"); */ + /* put_buf(&fm_info, sizeof(fm_info)); */ + u8 fm_info_size = fm_info.total_chanel * 3 + 1; + u8 *fm_fre_info = zalloc(fm_info_size); + if (fm_fre_info) { + u8 *ptr = fm_fre_info; + u16 fm_fre = 0; + u8 total = 1; + u8 i; + u8 k; + *ptr++ = fm_info.total_chanel; + for (i = 0; i < (MEM_FM_LEN); i++) { + for (k = 0; k < 8; k++) { + if (fm_info.dat[i] & BIT(k)) { + fm_fre = i * 8 + k + 874; + fm_fre = app_htons(fm_fre); + *ptr++ = total++; + memcpy(ptr, &fm_fre, sizeof(fm_fre)); + ptr += 2; + } + } + } + offset += add_one_attr(buf, buf_size, offset, FM_INFO_ATTR_FRE, fm_fre_info, fm_info_size); + free(fm_fre_info); + } + } + + return offset; +} + +void smartbot_fm_msg_deal(int msg) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL) { + return ; + } + switch (msg) { + case KEY_MUSIC_PP: + case KEY_FM_PREV_FREQ: + case KEY_FM_NEXT_FREQ: + case KEY_FM_PREV_STATION: + case KEY_FM_NEXT_STATION: + case (int)-1: + smartbox_function_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE)); + break; + case KEY_FM_SCAN_ALL: + case KEY_FM_SCAN_ALL_UP: + case KEY_FM_SCAN_ALL_DOWN: + case KEY_FM_SCAN_DOWN: + case KEY_FM_SCAN_UP: + if (!fm_get_scan_flag()) { + smartbox_function_update(FM_FUNCTION_MASK, BIT(FM_INFO_ATTR_STATUS) | BIT(FM_INFO_ATTR_FRE)); + } + break; + } +} + +void fm_func_stop(void) +{ + if (fm_get_fm_dev_mute) { + fm_volume_pp(); + } +} + + + + + +#else + +bool fm_func_set(void *priv, u8 *data, u16 len) +{ + return true; +} + +u32 fm_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask) +{ + return 0; +} + +void smartbot_fm_msg_deal(int msg) +{ + +} + +void fm_func_stop(void) +{ + +} +#endif +#endif diff --git a/apps/soundbox/smartbox/func_cmd/linein_func.c b/apps/soundbox/smartbox/func_cmd/linein_func.c new file mode 100644 index 0000000..f0800ac --- /dev/null +++ b/apps/soundbox/smartbox/func_cmd/linein_func.c @@ -0,0 +1,101 @@ +#include "smartbox/func_cmd/linein_func.h" +#include "smartbox/func_cmd_common.h" +#include "smartbox/function.h" +#include "smartbox/config.h" +#include "smartbox/event.h" +#include "app_action.h" + +#include "app_msg.h" +#include "key_event_deal.h" + +#if SMART_BOX_EN + +#if (TCFG_APP_LINEIN_EN && !SOUNDCARD_ENABLE) +#include "linein/linein.h" +#include "tone_player.h" + +#define LINEIN_INFO_ATTR_STATUS (0) +bool linein_func_set(void *priv, u8 *data, u16 len) +{ + if (0 != tone_get_status()) { + return true; + } + u8 fun_cmd = data[0]; + u16 param_len = len - 1; + switch (fun_cmd) { + case 1: + app_task_put_key_msg(KEY_MUSIC_PP, 0); //test demo + break; + default: + break; + } + return true; +} + +u32 linein_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask) +{ + u16 offset = 0; + if (mask & BIT(LINEIN_INFO_ATTR_STATUS)) { + u8 status = linein_get_status(); + offset = add_one_attr(buf, buf_size, offset, LINEIN_INFO_ATTR_STATUS, (u8 *)&status, sizeof(status)); + } + return offset; +} + +void smartbox_linein_msg_deal(int msg, u8 ret) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL) { + return ; + } + switch (msg) { + case KEY_VOL_DOWN: + case KEY_VOL_UP: + smartbox_function_update(COMMON_FUNCTION, BIT(COMMON_FUNCTION_ATTR_TYPE_VOL)); + break; + case (int)-1: + case KEY_MUSIC_PP: + case KEY_LINEIN_START: + smartbox_function_update(LINEIN_FUNCTION_MASK, BIT(LINEIN_INFO_ATTR_STATUS)); + break; + } +} + +void linein_func_stop(void) +{ + if (linein_get_status()) { + app_task_put_key_msg(KEY_MUSIC_PP, 0); + } +} + + + + +#else + +bool linein_func_set(void *priv, u8 *data, u16 len) +{ + return true; +} + +u32 linein_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask) +{ + return 0; +} + +void smartbox_linein_msg_deal(int msg, u8 ret) +{ + +} + +void smartbot_linein_msg_deal(int msg) +{ + +} + +void linein_func_stop(void) +{ + +} +#endif +#endif diff --git a/apps/soundbox/smartbox/func_cmd/music_func.c b/apps/soundbox/smartbox/func_cmd/music_func.c new file mode 100644 index 0000000..e1a3b02 --- /dev/null +++ b/apps/soundbox/smartbox/func_cmd/music_func.c @@ -0,0 +1,208 @@ +#include "smartbox/func_cmd/music_func.h" +#include "smartbox/func_cmd_common.h" +#include "smartbox/smartbox.h" +#include "smartbox/function.h" +#include "smartbox/config.h" + +#include "key_event_deal.h" + +#if (SMART_BOX_EN && TCFG_APP_MUSIC_EN) +#include "music/music_player.h" + +#pragma pack(1) +struct _MUSIC_STATUS_info { + u8 status; + u32 cur_time; + u32 total_time; + u8 cur_dev; +}; +#pragma pack() + +enum { + MUSIC_FUNC_PP = 0x1, + MUSIC_FUNC_PREV, + MUSIC_FUNC_NEXT, + MUSIC_FUNC_MODE, + MUSIC_FUNC_EQ_MODE, + MUSIC_FUNC_REWIND, + MUSIC_FUNC_FAST_FORWORD, +}; + + +enum { + REPEAT_MODE_ALL = 0x1, + REPEAT_MODE_DEV, + REPEAT_MODE_ONE, + REPEAT_MODE_RANDOM, + REPEAT_MODE_FOLDER, +}; + +const u8 smartbox_repeat_mode_remap[] = { + [FCYCLE_ALL] = REPEAT_MODE_ALL, + [FCYCLE_ONE] = REPEAT_MODE_ONE, + [FCYCLE_FOLDER] = REPEAT_MODE_FOLDER, + [FCYCLE_RANDOM] = REPEAT_MODE_RANDOM, +}; + + +#define SMARTBOX_MUSIC_FILE_NAME_MAX_LIMIT (128) + +// 本文件内用到 +static u8 music_func_add_one_attr_ex(u8 *buf, u16 max_len, u8 offset, u8 type, u8 *data, u8 size, u8 att_size) +{ + if (offset + size + 2 > max_len) { + printf("add attr err\n"); + return 0; + } + buf[offset] = att_size + 1; + buf[offset + 1] = type; + memcpy(&buf[offset + 2], data, size); + return size + 2; +} + +// 本文件内用到 +static u8 mucis_func_add_one_attr_continue(u8 *buf, u16 max_len, u8 offset, u8 type, u8 *data, u8 size) +{ + if ((offset + size) > max_len) { + printf("add attr err 2\n"); + return 0; + } + memcpy(&buf[offset], data, size); + return size; +} + +u32 music_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask) +{ + u16 offset = 0; +#if (TCFG_APP_MUSIC_EN) + u8 app = app_get_curr_task(); + if (app != APP_MUSIC_TASK) { + return 0; + } + ///获取当前播放状态 + struct smartbox *smart = (struct smartbox *) priv; + FILE *file = music_player_get_file_hdl(); + if (file == NULL) { + printf("music_function_info file err\n"); + return 0; + } + + if (mask & BIT(MUSIC_INFO_ATTR_STATUS)) { + /* printf("MUSIC_INFO_ATTR_STATUS\n"); */ + struct _MUSIC_STATUS_info music_info; + music_info.status = music_player_get_play_status(); + music_info.cur_time = app_htonl(music_player_get_dec_cur_time()); + music_info.total_time = app_htonl(music_player_get_dec_total_time()); + char *logo = music_player_get_dev_cur(); + char *tmp = NULL; + if (logo) { + for (int i = 0; i < BS_DEV_MAX; i++) { + tmp = smartbox_browser_dev_remap(i); + if (tmp && strcmp(tmp, logo) == 0) { + music_info.cur_dev = i; + offset += add_one_attr(buf, buf_size, offset, MUSIC_INFO_ATTR_STATUS, (u8 *)&music_info, sizeof(music_info)); + break; + } + } + } + } + + if (mask & BIT(MUSIC_INFO_ATTR_FILE_NAME)) { + /* printf("MUSIC_INFO_ATTR_FILE_NAME\n"); */ + u8 *lfn_buf = zalloc(512); + if (lfn_buf) { + int lfn_len = fget_name(file, lfn_buf, 512); + lfn_len = file_name_cut(lfn_buf, lfn_len, SMARTBOX_MUSIC_FILE_NAME_MAX_LIMIT); + struct vfs_attr tmp_attr = {0}; + fget_attrs(file, &tmp_attr); + u32 clust = app_htonl(tmp_attr.sclust); + /* u32 clust = tmp_attr.sclust; */ + /* printf("clust %x\n", clust); */ + u8 code_type = 1; + u8 *tmp_buf = lfn_buf; + if (lfn_buf[0] == '\\' && lfn_buf[1] == 'U') { + code_type = 0; + lfn_len -= 2; + tmp_buf += 2; + } + + offset += music_func_add_one_attr_ex(buf, buf_size, offset, MUSIC_INFO_ATTR_FILE_NAME, (u8 *)&clust, sizeof(u32), lfn_len + sizeof(code_type) + sizeof(clust)); + offset += mucis_func_add_one_attr_continue(buf, buf_size, offset, MUSIC_INFO_ATTR_FILE_NAME, (u8 *)&code_type, 1); + offset += mucis_func_add_one_attr_continue(buf, buf_size, offset, MUSIC_INFO_ATTR_FILE_NAME, tmp_buf, lfn_len); + free(lfn_buf); + } + } + + if (mask & BIT(MUSIC_INFO_ATTR_FILE_PLAY_MODE)) { + /* printf("MUSIC_INFO_ATTR_FILE_PLAY_MODE\n"); */ + u8 play_mode = music_player_get_repeat_mode(); + /* printf("play_mode = %d\n", play_mode); */ + play_mode = smartbox_repeat_mode_remap[play_mode]; + /* printf("remap = %d\n", play_mode); */ + offset += add_one_attr(buf, buf_size, offset, MUSIC_INFO_ATTR_FILE_PLAY_MODE, &play_mode, 1); + } +#endif + return offset; +} + +bool music_func_set(void *priv, u8 *data, u16 len) +{ + /* printf("%s, %d\n", __func__, data[0]); */ +#if (TCFG_APP_MUSIC_EN) + switch (data[0]) { + case MUSIC_FUNC_PP: + app_task_put_key_msg(KEY_MUSIC_PP, 0); + break; + case MUSIC_FUNC_PREV: + app_task_put_key_msg(KEY_MUSIC_PREV, 0); + break; + case MUSIC_FUNC_NEXT: + app_task_put_key_msg(KEY_MUSIC_NEXT, 0); + break; + case MUSIC_FUNC_MODE: + app_task_put_key_msg(KEY_MUSIC_CHANGE_REPEAT, 0); + break; + case MUSIC_FUNC_REWIND: + /* printf("MUSIC_FUNC_REWIND = %d\n", (int)(data[1] << 8 | data[2])); */ + music_player_fr((int)(data[1] << 8 | data[2])); + break; + case MUSIC_FUNC_FAST_FORWORD: + /* printf("MUSIC_FUNC_FAST_FORWORD = %d\n", (int)(data[1] << 8 | data[2])); */ + music_player_ff((int)(data[1] << 8 | data[2])); + break; + default: + break; + } + + SMARTBOX_UPDATE(MUSIC_FUNCTION_MASK, + BIT(MUSIC_INFO_ATTR_STATUS) | BIT(MUSIC_INFO_ATTR_FILE_PLAY_MODE)); +#endif + return true; +} + +void music_func_stop(void) +{ + if (music_player_get_play_status() != FILE_DEC_STATUS_PLAY) { + app_task_put_key_msg(KEY_MUSIC_PP, 0); + } +} + +#else + +u32 music_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask) +{ + return 0; +} + +bool music_func_set(void *priv, u8 *data, u16 len) +{ + return true; +} + +void music_func_stop(void) +{ + +} + +#endif + diff --git a/apps/soundbox/smartbox/func_cmd/rtc_func.c b/apps/soundbox/smartbox/func_cmd/rtc_func.c new file mode 100644 index 0000000..48a32c2 --- /dev/null +++ b/apps/soundbox/smartbox/func_cmd/rtc_func.c @@ -0,0 +1,699 @@ +#include "smartbox/func_cmd/rtc_func.h" +#include "smartbox/func_cmd_common.h" +#include "smartbox/function.h" +#include "smartbox/config.h" +#include "smartbox/event.h" +#include "app_action.h" + +#include "smartbox_music_info_setting.h" +#include "btstack/avctp_user.h" +#include "JL_rcsp_packet.h" +#include "key_event_deal.h" +#include "app_msg.h" + +#include "smartbox_rcsp_manage.h" + +#if (SMART_BOX_EN) + +#if TCFG_RTC_ENABLE +#include "rtc/alarm.h" +#include "tone_player.h" +#include "linein/linein.h" +#include "music_player.h" +#include "general_player.h" +#include "browser/browser.h" +#include "clock_cfg.h" + +#define RTC_INFO_ATTR_RTC_TIME (0) +#define RTC_INFO_ATTR_RTC_ALRAM (1) +#define RTC_INFO_ATTR_RTC_ALRAM_ACTIVE (2) +#define RTC_INFO_ATTR_RTC_ALRAM_UNACTIVE (3) +#define RTC_INFO_ATTR_RTC_ALRAM_STRUCTURE (4) +#define RTC_INFO_ATTR_RTC_ALRAM_DEFAULT_RING (5) +#define RTC_INFO_ATTR_RTC_ALRAM_RING_AUDITION (6) + +// 0是不停止 +#define SMARTBOX_ALARM_RING_MAX 50 + +#pragma pack(1) +typedef struct __APP_ALARM__ { + u8 index; + u8 sw; + u8 mode; + u8 bHour; + u8 bMin; + u8 name_len; +} T_ALARM_APP, *PT_ALARM_APP; + +typedef struct __APP_ALARM_EXTRA_DATA__ { + u8 type; + u8 dev; + u32 clust; + u8 ring_name_len; + u8 ring_name[32]; +} T_ALARM_APP_EXTRA_DATA, *PT_ALARM_APP_EXTRA_DATA; + +typedef struct __APP_ALARM_RING_AUDITION__ { + u8 prev_app_mode; + u8 ring_op; + u8 ring_type; + u8 ring_dev; + u32 ring_clust; + u32 ring_timeout; +} T_ALARM_APP_RING_AUDITION, *PT_ALARM_APP_RING_AUDITION; +#pragma pack() + +enum { + E_ALARM_SET = 0x00, + E_ALARM_DELETE, + E_ALARM_UNACTIVE, +}; + +enum { + ALARM_IDEX_TONE_NUM_0 = 0, + ALARM_IDEX_TONE_NUM_1 = 1, + ALARM_IDEX_TONE_NUM_2 = 2, + ALARM_IDEX_TONE_NUM_3 = 3, + ALARM_IDEX_TONE_NUM_4 = 4, + ALARM_IDEX_TONE_NUM_5 = 5, + ALARM_IDEX_TONE_NUM_6 = 6, + ALARM_IDEX_TONE_NUM_7 = 7, + ALARM_IDEX_TONE_NUM_8 = 8, + ALARM_IDEX_TONE_NUM_9 = 9, + + ALARM_IDEX_TONE_MAX_NUM = 10, +}; +static const char *default_ringtone_table[] = { + [ALARM_IDEX_TONE_NUM_0] = TONE_RES_ROOT_PATH"tone/0.*", + [ALARM_IDEX_TONE_NUM_1] = TONE_RES_ROOT_PATH"tone/1.*", + [ALARM_IDEX_TONE_NUM_2] = TONE_RES_ROOT_PATH"tone/2.*", + [ALARM_IDEX_TONE_NUM_3] = TONE_RES_ROOT_PATH"tone/3.*", + [ALARM_IDEX_TONE_NUM_4] = TONE_RES_ROOT_PATH"tone/4.*", + [ALARM_IDEX_TONE_NUM_5] = TONE_RES_ROOT_PATH"tone/5.*", + [ALARM_IDEX_TONE_NUM_6] = TONE_RES_ROOT_PATH"tone/6.*", + [ALARM_IDEX_TONE_NUM_7] = TONE_RES_ROOT_PATH"tone/7.*", + [ALARM_IDEX_TONE_NUM_8] = TONE_RES_ROOT_PATH"tone/8.*", + [ALARM_IDEX_TONE_NUM_9] = TONE_RES_ROOT_PATH"tone/9.*", +}; + +static const char *default_ringtone_name_table[] = { + [ALARM_IDEX_TONE_NUM_0] = "提示音0", + [ALARM_IDEX_TONE_NUM_1] = "1", + [ALARM_IDEX_TONE_NUM_2] = "2", + [ALARM_IDEX_TONE_NUM_3] = "3", + [ALARM_IDEX_TONE_NUM_4] = "4", + [ALARM_IDEX_TONE_NUM_5] = "5", + [ALARM_IDEX_TONE_NUM_6] = "6", + [ALARM_IDEX_TONE_NUM_7] = "7", + [ALARM_IDEX_TONE_NUM_8] = "8", + [ALARM_IDEX_TONE_NUM_9] = "9", +}; + +static void scan_enter(struct __dev *dev) +{ + clock_add_set(SCAN_DISK_CLK); +} + +static void scan_exit(struct __dev *dev) +{ + clock_remove_set(SCAN_DISK_CLK); +} + +static const struct __scan_callback scan_cb = { + .enter = scan_enter, + .exit = scan_exit, + .scan_break = general_player_scandisk_break, +}; + +static u8 rtc_func_structure_flag = CUR_RTC_ALARM_MODE; +static u8 rtc_ringing_prev_mode = -1; +static T_ALARM_APP_RING_AUDITION g_ring_audition = { + .prev_app_mode = -1, +}; + +static u8 smart_rtc_get_alarm_info(PT_ALARM_APP p, u8 index) +{ + extern u8 alarm_get_info(PT_ALARM p, u8 index); + u8 ret = 0; + T_ALARM alarm_param; + ret = alarm_get_info(&alarm_param, index); + p->index = alarm_param.index; + p->sw = alarm_param.sw; + p->mode = alarm_param.mode; + p->bHour = alarm_param.time.hour; + p->bMin = alarm_param.time.min; + p->name_len = alarm_param.name_len; + return ret; +} + +static u8 smartbox_rtc_get_alarm_total(void) +{ + extern u8 alarm_get_total(void); + u8 total = 0; + total = alarm_get_total(); + return total; +} + +static u8 m_func_alarm_get_active_index(void) +{ + extern u8 alarm_get_active_index(void); + return alarm_get_active_index(); +} + +static u8 m_func_alarm_name_get(u8 *p, u8 index) +{ + extern u8 alarm_name_get(u8 * p, u8 index); + return alarm_name_get(p, index); +} + +static void smart_rtc_update_time(RTC_TIME *p) +{ + extern void rtc_update_time_api(struct sys_time * time); + struct sys_time time = {0}; + time.year = p->dYear; + time.month = p->bMonth; + time.day = p->bDay; + time.hour = p->bHour; + time.min = p->bMin; + time.sec = p->bSec; + rtc_update_time_api(&time); +} + +static u8 mfunc_alarm_deal_data(PT_ALARM_APP p) +{ + extern u8 alarm_add(PT_ALARM p, u8 index); + T_ALARM tmp_alarm = {0}; + tmp_alarm.index = p->index; + tmp_alarm.sw = p->sw; + tmp_alarm.mode = p->mode; + tmp_alarm.time.hour = p->bHour; + tmp_alarm.time.min = p->bMin; + tmp_alarm.name_len = p->name_len; + return alarm_add(&tmp_alarm, p->index); +} + +static void m_func_alarm_name_set(u8 *p, u8 index, u8 len) +{ + extern void alarm_name_set(u8 * p, u8 index, u8 len); + alarm_name_set(p, index, len); +} + +static void m_func_alarm_dealte(u8 index) +{ + extern void alarm_delete(u8 index); + alarm_delete(index); +} + +static u8 smart_rtc_alarm_extra_data_set(u8 index, u8 *p, u8 len) +{ + u8 offset = 0; + T_ALARM_APP_EXTRA_DATA data = {0}; + data.type = p[offset++]; + data.dev = p[offset++]; + data.clust = READ_BIG_U32(p + offset); + offset += sizeof(data.clust); + u8 data_len = p[offset++]; + data.ring_name_len = data_len > 32 ? 32 : data_len; + memcpy(data.ring_name, p + offset, data.ring_name_len); + offset += data.ring_name_len; + printf("ring_type : %d, ring_dev : %d, ring_clust : %d, ring_name_len : %d\n", data.type, data.dev, data.clust, data.ring_name_len); + syscfg_write(VM_ALARM_RING_NAME_0 + index, &data, sizeof(data)); + return offset; +} + +static u8 smart_rtc_alarm_deal(void *priv, u8 *p, u8 len) +{ + u8 ret = E_SUCCESS; + u8 op = 0; + u8 nums = 0; + u8 index = 0; + u8 *pTmp = 0; + u8 i = 0; + u8 ring_info_offset = 0; + + T_ALARM_APP alarm_tab; + + if (len >= 3) { + op = p[2]; + printf("op = %d\n", op); + } + if (len >= 4) { + nums = p[3]; + printf("nums = %d\n", nums); + } + if (nums > M_MAX_ALARM_NUMS) { + printf("nums is error\n"); + return E_FAILURE; + } + + switch (op) { + case E_ALARM_SET: + printf("E_ALARM_SET\n"); + for (i = 0; i < nums; i++) { + pTmp = &(p[4 + i * (6 + alarm_tab.name_len) + ring_info_offset]); + alarm_tab.index = pTmp[0]; + alarm_tab.sw = pTmp[1]; + alarm_tab.mode = pTmp[2]; + alarm_tab.bHour = pTmp[3]; + alarm_tab.bMin = pTmp[4]; + alarm_tab.name_len = pTmp[5]; + + printf("index : %d, sw : %d, mode : %d, hour : %d, min : %d, name_len : %d\n", pTmp[0], pTmp[1], pTmp[2], pTmp[3], pTmp[4], pTmp[5]); + ret = mfunc_alarm_deal_data(&alarm_tab); + if (E_SUCCESS == ret) { + m_func_alarm_name_set(&(pTmp[6]), alarm_tab.index, alarm_tab.name_len); + } + + if (rtc_func_structure_flag) { + ring_info_offset += smart_rtc_alarm_extra_data_set(alarm_tab.index, &pTmp[6 + alarm_tab.name_len], len); + } + } + break; + case E_ALARM_DELETE: + printf("E_ALARM_DELETE\n"); + for (i = 0; i < nums; i++) { + index = p[4 + i]; + m_func_alarm_dealte(index); + } + break; + case E_ALARM_UNACTIVE: + printf("E_ALARM_UNACTIVE\n"); + extern void alarm_stop(void); + alarm_stop(); + smartbox_function_update(RTC_FUNCTION_MASK, BIT(RTC_INFO_ATTR_RTC_ALRAM_UNACTIVE)); + break; + default: + printf("alarm no action!\n"); + break; + } + return ret; +} + +static u8 smartbox_rtc_play_dev_ring(PT_ALARM_APP_RING_AUDITION ring_param) +{ + u8 ret = 0; + printf("neet to play the dev music, dev %s, clust %x\n", smartbox_browser_dev_remap(ring_param->ring_dev), ring_param->ring_clust); + ret = general_play_by_sculst(smartbox_browser_dev_remap(ring_param->ring_dev), ring_param->ring_clust); + if (ret) { + ring_param->ring_type = 0; + ring_param->ring_clust = 0; + } + return ret; +} + +static void music_tone_play_end_callback(void *priv, int flag) +{ + +} + +static u8 smart_rtc_ring_audition_deal(PT_ALARM_APP_RING_AUDITION ring_param) +{ + u8 ret = 0; + printf("ring stop"); + /* tone_play_stop(); */ + general_player_stop(0); + if (1 == ring_param->ring_op) { + printf("ringing\n"); + if (0 == ring_param->ring_type) { + general_player_stop(0); + /* tone_play_by_path(default_ringtone_table[ring_param->ring_clust], 0); */ + tone_play_with_callback_by_name(default_ringtone_table[ring_param->ring_clust], 1, music_tone_play_end_callback, (void *)ring_param->ring_clust); + } else if (1 == ring_param->ring_type) { + /* tone_play_stop(); */ + smartbox_rtc_play_dev_ring(ring_param); + } + } + return ret; +} + +static u8 smart_rtc_ring_audition_prepare(void *priv, u8 *data, u16 len) +{ + u8 ret = 0; + struct smartbox *smart = (struct smartbox *)priv; + g_ring_audition.ring_op = data[0]; + switch (g_ring_audition.ring_op) { + case 0: + // 回到原来的模式 + if ((u8) - 1 != g_ring_audition.prev_app_mode) { + smartbox_msg_post(USER_MSG_SMARTBOX_MODE_SWITCH, 2, (int)smart, g_ring_audition.prev_app_mode); + g_ring_audition.prev_app_mode = -1; + } else { + smart_rtc_ring_audition_deal(&g_ring_audition); + } + break; + case 1: + g_ring_audition.ring_type = data[1]; + g_ring_audition.ring_dev = data[2]; + g_ring_audition.ring_clust = READ_BIG_U32(data + 3); + // 进入rtc模式 + if (RTC_FUNCTION != smart->cur_app_mode) { + g_ring_audition.prev_app_mode = smart->cur_app_mode; + // 切换rtc模式 + smartbox_msg_post(USER_MSG_SMARTBOX_MODE_SWITCH, 2, (int)smart, RTC_FUNCTION_MASK); + } else { + smart_rtc_ring_audition_deal(&g_ring_audition); + } + break; + } + return ret; +} + +bool rtc_func_set(void *priv, u8 *data, u16 len) +{ + u8 ret = 0; + u8 offset = 0; + RTC_TIME time_info; + while (offset < len) { + u8 len_tmp = data[offset]; + u8 type = data[offset + 1]; + printf("rtc info:\n"); + put_buf(&data[offset], len_tmp + 1); + + switch (type) { + case RTC_INFO_ATTR_RTC_TIME: + printf("RTC_INFO_ATTR_RTC_TIME\n"); + memcpy((u8 *)&time_info, data + 2, sizeof(time_info)); + time_info.dYear = app_htons(time_info.dYear); + smart_rtc_update_time(&time_info); + break; + case RTC_INFO_ATTR_RTC_ALRAM: + printf("RTC_INFO_ATTR_RTC_ALRAM\n"); + put_buf(data, len); + ret = smart_rtc_alarm_deal(priv, data, len); + break; + case RTC_INFO_ATTR_RTC_ALRAM_RING_AUDITION: + printf("RTC_INFO_ATTR_RTC_ALRAM_RING_AUDITION\n"); + ret = smart_rtc_ring_audition_prepare(priv, data + offset + 2, len); + break; + } + offset += len_tmp + 1; + } + return (E_SUCCESS == ret); +} + +static u8 smart_rtc_alarm_extra_data_get(u8 *p, u8 index, u8 is_conversion) +{ + u8 offset = 0; + T_ALARM_APP_EXTRA_DATA data = {0}; + if (sizeof(data) != syscfg_read(VM_ALARM_RING_NAME_0 + index, &data, sizeof(data))) { + // 默认数据 + data.type = 0; + data.dev = 0; + data.clust = 0; + memcpy(data.ring_name, default_ringtone_name_table[data.clust], strlen(default_ringtone_name_table[data.clust]) + 1); + data.ring_name_len = strlen(data.ring_name) + 1; + } + p[offset++] = data.type; + p[offset++] = data.dev; + if (is_conversion) { + WRITE_BIG_U32(p + offset, data.clust); + } else { + memcpy(p + offset, &data.clust, sizeof(data.clust)); + } + offset += sizeof(data.clust); + p[offset++] = data.ring_name_len; + memcpy(p + offset, data.ring_name, data.ring_name_len); + offset += data.ring_name_len; + return offset; +} + +u32 rtc_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask) +{ + u16 offset = 0; + if (mask & BIT(RTC_INFO_ATTR_RTC_TIME)) { + printf("RTC_INFO_ATTR_RTC_TIME\n"); + RTC_TIME time_info = { + .dYear = 2020, + .bMonth = 5, + .bDay = 15, + .bHour = 19, + .bMin = 55, + .bSec = 40, + }; + offset += add_one_attr(buf, buf_size, offset, RTC_INFO_ATTR_RTC_TIME, (u8 *)&time_info, sizeof(time_info)); + } + + if (mask & BIT(RTC_INFO_ATTR_RTC_ALRAM)) { + printf("RTC_INFO_ATTR_RTC_ALRAM\n"); + u8 alarm_data[M_MAX_ALARM_NUMS * (sizeof(T_ALARM_APP) + M_MAX_ALARM_NAME_LEN + sizeof(T_ALARM_APP_EXTRA_DATA))]; + u8 total = 0; + u8 index = 0; + u8 name_len = 0; + u8 *pTmp; + u8 data_len = 0; + u8 ret = 0; + + pTmp = alarm_data; + + total = smartbox_rtc_get_alarm_total(); + printf("total %d alarm!\n", total); + + pTmp[0] = total; + + pTmp++; + data_len++; + + for (index = 0; index < 5; index++) { + ret = smart_rtc_get_alarm_info((PT_ALARM_APP)pTmp, index); + if (0 == ret) { + pTmp += sizeof(T_ALARM_APP); + data_len += sizeof(T_ALARM_APP); + + name_len = m_func_alarm_name_get(pTmp, index); + pTmp += name_len; + data_len += name_len; + + if (rtc_func_structure_flag) { + name_len = smart_rtc_alarm_extra_data_get(pTmp, index, 1); + pTmp += name_len; + data_len += name_len; + } + + printf("data_len = %d\n", data_len); + } + } + + put_buf(alarm_data, data_len); + offset += add_one_attr(buf, buf_size, offset, RTC_INFO_ATTR_RTC_ALRAM, alarm_data, data_len); + } + + if (mask & BIT(RTC_INFO_ATTR_RTC_ALRAM_ACTIVE)) { + printf("RTC_INFO_ATTR_RTC_ALRAM_ACTIVE\n"); + u8 index_mask = 0; + index_mask = m_func_alarm_get_active_index(); + printf("active alarm index : %d\n", index_mask); + offset += add_one_attr(buf, buf_size, offset, RTC_INFO_ATTR_RTC_ALRAM_ACTIVE, (u8 *)&index_mask, sizeof(index_mask)); + + /* extern void alarm_update_info_after_isr(void); */ + /* alarm_update_info_after_isr(); */ + } + + if (mask & BIT(RTC_INFO_ATTR_RTC_ALRAM_UNACTIVE)) { + printf("RTC_INFO_ATTR_RTC_ALRAM_UNACTIVE\n"); + offset += add_one_attr(buf, buf_size, offset, RTC_INFO_ATTR_RTC_ALRAM_UNACTIVE, NULL, 0); + } + + if (mask & BIT(RTC_INFO_ATTR_RTC_ALRAM_STRUCTURE)) { + printf("RTC_INFO_ATTR_RTC_ALRAM_STRUCTURE\n"); + offset += add_one_attr(buf, buf_size, offset, RTC_INFO_ATTR_RTC_ALRAM_STRUCTURE, &rtc_func_structure_flag, sizeof(rtc_func_structure_flag)); + } + + if (mask & BIT(RTC_INFO_ATTR_RTC_ALRAM_DEFAULT_RING)) { + printf("RTC_INFO_ATTR_RTC_ALRAM_DEFAULT_RING\n"); + u8 i; + // total + index + u8 ring_info_len = 1 + ALARM_IDEX_TONE_MAX_NUM; + for (i = 0; i < ALARM_IDEX_TONE_MAX_NUM; i++) { + // name_len + name_data + ring_info_len += 1 + strlen(default_ringtone_name_table[i]) + 1; + } + + u8 default_offset = 0; + u8 ring_name_len = 0; + u8 *default_ring = zalloc(ring_info_len); + default_ring[default_offset++] = ALARM_IDEX_TONE_MAX_NUM; + for (i = 0; i < ALARM_IDEX_TONE_MAX_NUM; i++) { + ring_name_len = strlen(default_ringtone_name_table[i]) + 1; + default_ring[default_offset++] = i; + default_ring[default_offset++] = ring_name_len; + if (ring_name_len) { + memcpy(default_ring + default_offset, default_ringtone_name_table[i], ring_name_len); + } + default_offset += ring_name_len; + } + + offset += add_one_attr(buf, buf_size, offset, RTC_INFO_ATTR_RTC_ALRAM_DEFAULT_RING, default_ring, ring_info_len); + if (default_ring) { + free(default_ring); + } + + } + + return offset; +} + +void smartbot_rtc_msg_deal(int msg) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL) { + return ; + } + + switch (msg) { + case (int)-1 : + rtc_ringing_prev_mode = smart->cur_app_mode; + smartbox_function_update(RTC_FUNCTION_MASK, BIT(RTC_INFO_ATTR_RTC_ALRAM_ACTIVE)); + break; + } +} + +static void rtc_ring_stop_handle(void) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL) { + return ; + } + smartbox_function_update(RTC_FUNCTION_MASK, BIT(RTC_INFO_ATTR_RTC_ALRAM_STRUCTURE) | BIT(RTC_INFO_ATTR_RTC_ALRAM_UNACTIVE)); + smartbox_function_update(RTC_FUNCTION_MASK, BIT(RTC_INFO_ATTR_RTC_ALRAM)); + if ((u8) - 1 != rtc_ringing_prev_mode) { + extern void alarm_play_timer_del(void); + alarm_play_timer_del(); + smartbox_msg_post(USER_MSG_SMARTBOX_MODE_SWITCH, 2, (int)smart, rtc_ringing_prev_mode); + rtc_ringing_prev_mode = -1; + } +} + +u8 rtc_app_alarm_ring_play(u8 alarm_state) +{ + // 防止g_ring_audition成为临界资源,所以定义多一个局部变量 + static T_ALARM_APP_RING_AUDITION ringing_info = {0}; + u8 active_flag = m_func_alarm_get_active_index(); + u8 index; + if (0 == active_flag && 0 == rtc_func_structure_flag) { + return rtc_func_structure_flag; + } + + if (0 == alarm_state) { + ringing_info.prev_app_mode = 0; + ringing_info.ring_op = 0; + ringing_info.ring_timeout = 0; + smart_rtc_ring_audition_deal(&ringing_info); + rtc_ring_stop_handle(); + return rtc_func_structure_flag; + } else { + if ((u32) - 1 == (--ringing_info.ring_timeout)) { + ringing_info.ring_timeout = SMARTBOX_ALARM_RING_MAX; + } else if (0 == ringing_info.ring_timeout) { + extern void alarm_stop(void); + alarm_stop(); + return rtc_func_structure_flag; + } + } + + for (index = 0; index < 5; index++) { + if (active_flag & BIT(index)) { + break; + } + } + + if (index < 5) { + if (0 == ringing_info.prev_app_mode) { + // 响铃会进入始终模式,这个时全局变量prev_app_mode应该清除 + g_ring_audition.prev_app_mode = -1; + // 暂停正在播放的提示音或设备音乐 + g_ring_audition.ring_op = 0; + smart_rtc_ring_audition_deal(&g_ring_audition); + + T_ALARM_APP_EXTRA_DATA data = {0}; + u32 data_len = 0; + + smart_rtc_alarm_extra_data_get(&data, index, 0); + + ringing_info.prev_app_mode = -1; + ringing_info.ring_op = 1; + ringing_info.ring_type = data.type; + ringing_info.ring_dev = data.dev; + ringing_info.ring_clust = data.clust; + } + + if (get_rcsp_connect_status()) { + smartbox_function_update(RTC_FUNCTION_MASK, BIT(RTC_INFO_ATTR_RTC_ALRAM_ACTIVE)); + } + + if (ringing_info.ring_type) { + if (!music_player_get_play_status()) { + // 播放设备音乐 + printf("ringing............................\n"); + smartbox_rtc_play_dev_ring(&ringing_info); + } + } else { + /* tone_play_by_path(default_ringtone_table[ringing_info.ring_clust], 0); */ + tone_play_with_callback_by_name(default_ringtone_table[ringing_info.ring_clust], 1, music_tone_play_end_callback, (void *)ringing_info.ring_clust); + } + } + return rtc_func_structure_flag; +} + +u8 smartbox_rtc_ring_tone(void) +{ + general_player_init((struct __scan_callback *)&scan_cb); + if ((u8) - 1 != g_ring_audition.prev_app_mode) { + smart_rtc_ring_audition_deal(&g_ring_audition); + } else if ((u8) - 1 == rtc_ringing_prev_mode) { + app_task_switch_next(); + } + return false; +} + +void smartbox_rtc_mode_exit(void) +{ + general_player_exit(); + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL) { + return ; + } + if ((u8) - 1 != rtc_ringing_prev_mode) { + rtc_ringing_prev_mode = smart->cur_app_mode; + rtc_ring_stop_handle(); + } +} + +void rtc_func_stop(void) +{ + +} + +#else + +u32 rtc_func_get(void *priv, u8 *buf, u16 buf_size, u32 mask) +{ + return 0; +} + +bool rtc_func_set(void *priv, u8 *data, u16 len) +{ + return true; +} + +void smartbot_rtc_msg_deal(int msg) +{ + +} + +u8 smartbox_rtc_ring_tone(void) +{ + return true; +} + +void smartbox_rtc_mode_exit(void) +{ + +} + +void rtc_func_stop(void) +{ + +} +#endif + +#endif diff --git a/apps/soundbox/smartbox/function.c b/apps/soundbox/smartbox/function.c new file mode 100644 index 0000000..2934351 --- /dev/null +++ b/apps/soundbox/smartbox/function.c @@ -0,0 +1,715 @@ +#include "smartbox/config.h" +#include "smartbox/function.h" +#include "smartbox/smartbox.h" +#include "smartbox/event.h" +#include "smartbox/func_cmd_common.h" +#include "fm_emitter/fm_emitter_manage.h" + +#include "le_smartbox_module.h" +#include "smartbox_setting_opt.h" +#include "dev_manager.h" +#include "btstack/avctp_user.h" + +#include "app_main.h" +#include "app_action.h" + +#if (SMART_BOX_EN) + +#define ASSERT_SET_LEN(len, limit) \ + do{ \ + if(len >= limit){ \ + }else{ \ + return 0; \ + }\ + }while(0); + + +#define ASSERT_SET_LEN_RETURN_NULL(len, limit) \ + do{ \ + if(len >= limit){ \ + }else{ \ + return ; \ + }\ + }while(0); + +#define FUNCTION_UPDATE_MAX_LEN (256) + +#pragma pack(1) +struct _DEV_info { + u8 status; + u32 usb_handle; + u32 sd0_handle; + u32 sd1_handle; + u32 flash_handle; +}; +#pragma pack() + +typedef bool (*func_set)(void *priv, u8 *data, u16 len); +typedef u32(*func_get)(void *priv, u8 *buf, u16 buf_size, u32 mask); +static const func_set set_tab[FUNCTION_MASK_MAX] = { + [BT_FUNCTION_MASK] = bt_func_set, + [MUSIC_FUNCTION_MASK] = music_func_set, + [RTC_FUNCTION_MASK] = rtc_func_set, + [LINEIN_FUNCTION_MASK] = linein_func_set, + [FM_FUNCTION_MASK] = fm_func_set, + [FMTX_FUNCTION_MASK] = NULL, +}; + +static const func_get get_tab[FUNCTION_MASK_MAX] = { + [BT_FUNCTION_MASK] = bt_func_get, + [MUSIC_FUNCTION_MASK] = music_func_get, + [RTC_FUNCTION_MASK] = rtc_func_get, + [LINEIN_FUNCTION_MASK] = linein_func_get, + [FM_FUNCTION_MASK] = fm_func_get, + [FMTX_FUNCTION_MASK] = NULL, +}; + +static void common_function_attr_vol_set(void *priv, u8 attr, u8 *data, u16 len) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return ; + } + if (BT_CALL_HANGUP != get_call_status()) { + smart->err_code = -1; + return; + } + ASSERT_SET_LEN_RETURN_NULL(len, 1); + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_VOL_SETTING); + if (setting_opt_hdl) { + set_smartbox_opt_setting(setting_opt_hdl, data); + } +} +static void common_function_attr_eq_set(void *priv, u8 attr, u8 *data, u16 len) +{ + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_EQ_SETTING); + if (setting_opt_hdl) { + set_smartbox_opt_setting(setting_opt_hdl, data); + u32 mask = BIT(attr); + smartbox_msg_post(USER_MSG_SMARTBOX_SET_EQ_PARAM, 2, (int)priv, mask); + } +} +static void common_function_attr_fmtx_freq_set(void *priv, u8 attr, u8 *data, u16 len) +{ +#if (TCFG_APP_FM_EMITTER_EN && TCFG_FM_EMITTER_INSIDE_ENABLE) + ASSERT_SET_LEN_RETURN_NULL(len, 2); + u16 freq = READ_BIG_U16(data); + smartbox_msg_post(USER_MSG_SMARTBOX_SET_FMTX_FREQ, 2, (int)priv, (int)freq); +#endif +} +static void common_function_attr_bt_emitter_sw_set(void *priv, u8 attr, u8 *data, u16 len) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return ; + } + ASSERT_SET_LEN_RETURN_NULL(len, 1); + smart->emitter_sw = data[0]; + smartbox_msg_post(USER_MSG_SMARTBOX_SET_BT_EMITTER_SW, 1, (int)priv); +} +static void common_function_attr_bt_emitter_connect_state_set(void *priv, u8 attr, u8 *data, u16 len) +{ + ASSERT_SET_LEN_RETURN_NULL(len, 7); + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return ; + } + memcpy(smart->emitter_con_addr, data + 1, 6); + smartbox_msg_post(USER_MSG_SMARTBOX_SET_BT_EMITTER_CONNECT_STATES, 2, (int)priv, (int)data[0]); +} + +static void common_function_attr_high_low_set(void *priv, u8 attr, u8 *data, u16 len) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return ; + } + if (BT_CALL_HANGUP != get_call_status()) { + smart->err_code = -1; + return; + } + + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_HIGH_LOW_VOL); + if (!set_setting_extra_handle(setting_opt_hdl, data, NULL)) { + set_smartbox_opt_setting(setting_opt_hdl, NULL); + } +} + +static void common_function_attr_misc_setting_set(void *priv, u8 attr, u8 *data, u16 len) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return ; + } + if (BT_CALL_HANGUP != get_call_status()) { + smart->err_code = -1; + return; + } + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_MISC_SETTING); + if (setting_opt_hdl) { + if (!set_setting_extra_handle(setting_opt_hdl, data, NULL)) { + set_smartbox_opt_setting(setting_opt_hdl, data); + } else { + smart->err_code = -1; + } + } +} + +static void common_function_attr_color_led_setting_set(void *priv, u8 attr, u8 *data, u16 len) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return ; + } + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_COLOR_LED_SETTING); + if (setting_opt_hdl) { + set_smartbox_opt_setting(setting_opt_hdl, data); + } +} + +static void common_function_attr_karaoke_eq_setting_set(void *priv, u8 attr, u8 *data, u16 len) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return ; + } + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_KARAOKE_EQ_SETTING); + if (setting_opt_hdl) { + set_smartbox_opt_setting(setting_opt_hdl, data); + u32 mask = BIT(attr); + smartbox_msg_post(USER_MSG_SMARTBOX_SET_EQ_PARAM, 2, (int)priv, mask); + } +} + +static void common_function_attr_karaoke_setting_set(void *priv, u8 attr, u8 *data, u16 len) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return ; + } + + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_KARAOKE_SETTING); + if (setting_opt_hdl) { + if (!set_setting_extra_handle(setting_opt_hdl, data, &len)) { + set_smartbox_opt_setting(setting_opt_hdl, NULL); + } + } +} + +static const attr_set_func common_function_set_tab[COMMON_FUNCTION_ATTR_TYPE_MAX] = { + [COMMON_FUNCTION_ATTR_TYPE_BATTERY ] = NULL, + [COMMON_FUNCTION_ATTR_TYPE_VOL ] = common_function_attr_vol_set, + [COMMON_FUNCTION_ATTR_TYPE_DEV_INFO ] = NULL, + [COMMON_FUNCTION_ATTR_TYPE_ERROR_STATS ] = NULL, + [COMMON_FUNCTION_ATTR_TYPE_EQ_INFO ] = common_function_attr_eq_set,//NULL, + [COMMON_FUNCTION_ATTR_TYPE_BS_FILE_TYPE ] = NULL, + [COMMON_FUNCTION_ATTR_TYPE_FUNCTION_MODE ] = NULL, + [COMMON_FUNCTION_ATTR_TYPE_FMTX_FREQ ] = common_function_attr_fmtx_freq_set, + [COMMON_FUNCTION_ATTR_TYPE_BT_EMITTER_SW ] = common_function_attr_bt_emitter_sw_set, + [COMMON_FUNCTION_ATTR_TYPE_BT_EMITTER_CONNECT_STATES ] = common_function_attr_bt_emitter_connect_state_set, + [COMMON_FUNCTION_ATTR_TYPE_HIGH_LOW_SET ] = common_function_attr_high_low_set, + [COMMON_FUNCTION_ATTR_TYPE_PRE_FETCH_ALL_EQ_INFO ] = NULL, + [COMMON_FUNCTION_ATTR_TYPE_PHONE_SCO_STATE_INFO ] = NULL, + [COMMON_FUNCTION_ATTR_TYPE_MISC_SETTING_INFO ] = common_function_attr_misc_setting_set, + [COMMON_FUNCTION_ATTR_TYPE_COLOR_LED_SETTING_INFO ] = common_function_attr_color_led_setting_set, + [COMMON_FUNCTION_ATTR_TYPE_PRE_FETCH_KARAOKE_EQ_INFO ] = NULL, + [COMMON_FUNCTION_ATTR_TYPE_KARAOKE_EQ_SETTING_INFO ] = common_function_attr_karaoke_eq_setting_set, + [COMMON_FUNCTION_ATTR_TYPE_KARAOKE_SETTING_INFO ] = common_function_attr_karaoke_setting_set, +}; + + +static u32 common_function_attr_battery_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + extern u8 get_vbat_percent(void); + u8 vbat = get_vbat_percent(); + rlen = add_one_attr(buf, buf_size, offset, attr, &vbat, sizeof(vbat)); + return rlen; +} +static u32 common_function_attr_vol_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + //extern s8 app_audio_get_volume(u8 state); + //u8 cur_vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + if (BT_CALL_HANGUP != get_call_status()) { + return 0; + } + u8 cur_vol; + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_VOL_SETTING); + if (setting_opt_hdl) { + get_smartbox_opt_setting(setting_opt_hdl, (u8 *)&cur_vol); + rlen = add_one_attr(buf, buf_size, offset, attr, &cur_vol, sizeof(cur_vol)); + } + return rlen; +} +static u32 common_function_attr_dev_info_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + struct smartbox *smart = (struct smartbox *) priv; + struct _DEV_info dev_info = {0}; + u32 dev_status_tmp = 0; + +#if (TCFG_DEV_MANAGER_ENABLE) + if (dev_manager_get_root_path_by_logo("udisk0")) { + printf("dev [udisk0] online\n"); + dev_info.status |= BIT(BS_UDISK); + dev_info.usb_handle |= app_htonl((u32)BS_UDISK); + } + + if (dev_manager_get_root_path_by_logo("sd0")) { + printf("dev [sd0] online\n"); + dev_info.status |= BIT(BS_SD0); + dev_info.sd0_handle |= app_htonl((u32)BS_SD0); + } + + if (dev_manager_get_root_path_by_logo("sd1")) { + printf("dev [sd1] online\n"); + dev_info.status |= BIT(BS_SD1); + dev_info.sd1_handle = app_htonl((u32)BS_SD1); + } +#endif + + extern int linein_app_check(void); + if (linein_app_check()) { + dev_info.status |= BIT(BS_AUX); + } + + rlen = add_one_attr(buf, buf_size, offset, attr, (u8 *)&dev_info, sizeof(dev_info)); + return rlen; +} +static u32 common_function_attr_error_states_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + return rlen; +} + +static u32 common_function_attr_pre_fetch_all_eq_info_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + u8 eq_pre_fetch_info[1 + 20 + (1 + 10) * 10] = {0}; // num + freq + all_gain_of_eq [max] + u16 eq_per_fetch_size = sizeof(eq_pre_fetch_info); + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_EQ_SETTING); + if (setting_opt_hdl) { + eq_per_fetch_size = get_setting_extra_handle(setting_opt_hdl, eq_pre_fetch_info, &eq_per_fetch_size); + if (eq_per_fetch_size) { + rlen = add_one_attr(buf, buf_size, offset, attr, eq_pre_fetch_info, eq_per_fetch_size); + } + } + return rlen; +} + +static u32 common_function_attr_phone_sco_state_info_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + u8 phone_state = 0; + if (BT_CALL_HANGUP != get_call_status()) { + phone_state = 1; + } + rlen = add_one_attr(buf, buf_size, offset, attr, &phone_state, sizeof(phone_state)); + return rlen; +} + +static u32 common_function_attr_eq_param_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + u8 eq_info[11] = {0}; + u16 eq_info_size = sizeof(eq_info); + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_EQ_SETTING); + if (setting_opt_hdl) { + eq_info_size = get_setting_extra_handle(setting_opt_hdl, eq_info, &eq_info_size); + if (eq_info_size) { + rlen = add_one_attr(buf, buf_size, offset, attr, eq_info, eq_info_size); + } + } + return rlen; +} + +static u32 common_function_attr_bs_file_type(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; +#if RCSP_FILE_OPT + /* printf("%s\n", smartbox_browser_file_ext()); */ + rlen = add_one_attr(buf, buf_size, offset, attr, (u8 *)smartbox_browser_file_ext(), smartbox_browser_file_ext_size()); +#endif + return rlen; +} +static u32 common_function_attr_function_mode_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + struct smartbox *smart = (struct smartbox *) priv; + rlen = add_one_attr(buf, buf_size, offset, attr, &smart->cur_app_mode, sizeof(smart->cur_app_mode)); + return rlen; +} +static u32 common_function_attr_fmtx_freq_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; +#if (TCFG_APP_FM_EMITTER_EN && TCFG_FM_EMITTER_INSIDE_ENABLE) + u16 freq = fm_emitter_manage_get_fre(); + printf("freq %d\n", freq); + freq = app_htons(freq); + rlen = add_one_attr(buf, buf_size, offset, attr, (u8 *)&freq, sizeof(freq)); +#endif + return rlen; +} +static u32 common_function_attr_bt_emitter_sw_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return 0; + } + u32 rlen = 0; + u8 sw = smart->emitter_sw; + rlen = add_one_attr(buf, buf_size, offset, attr, &sw, 1); + return rlen; +} +static u32 common_function_attr_bt_emitter_connect_state_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return 0; + } + + u32 rlen = 0; + u8 send_buf[7] = {0}; + /* if(smart->emitter_sw) */ + { + send_buf[0] = smart->emitter_bt_state; + memcpy(send_buf + 1, smart->emitter_con_addr, 6); + } + printf("stata = %d\n", send_buf[0]); + put_buf(send_buf + 1, 6); + rlen = add_one_attr(buf, buf_size, offset, attr, send_buf, sizeof(send_buf)); + return rlen; +} +static u32 common_function_attr_high_low_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + u8 data[8] = {0}; + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_HIGH_LOW_VOL); + if (setting_opt_hdl) { + u8 size = get_setting_extra_handle(setting_opt_hdl, data, NULL); + if (size) { + rlen = add_one_attr(buf, buf_size, offset, attr, data, size); + } + } + + return rlen; +} + +static u32 common_function_attr_misc_setting_info_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + extern u32 get_misc_setting_data_len(void); + u32 data_len = get_misc_setting_data_len(); + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_MISC_SETTING); + if (data_len && setting_opt_hdl) { + u8 *misc_data = zalloc(data_len); + data_len = get_smartbox_opt_setting(setting_opt_hdl, misc_data); + rlen = add_one_attr(buf, buf_size, offset, attr, misc_data, data_len); + if (misc_data) { + free(misc_data); + } + } + return rlen; +} + +static u32 common_function_attr_color_led_setting_info_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + extern u32 get_color_led_setting_data_len(void); + u32 data_len = get_color_led_setting_data_len(); + u8 color_led_data[data_len]; + + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_COLOR_LED_SETTING); + if (setting_opt_hdl) { + get_smartbox_opt_setting(setting_opt_hdl, color_led_data); + rlen = add_one_attr(buf, buf_size, offset, attr, color_led_data, data_len); + } + return rlen; +} + +static u32 common_function_attr_karaoke_eq_setting_info_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + u8 karaoke_eq_info[9] = {0}; + u16 karaoke_eq_size = sizeof(karaoke_eq_info); + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_KARAOKE_EQ_SETTING); + if (setting_opt_hdl) { + karaoke_eq_size = get_setting_extra_handle(setting_opt_hdl, karaoke_eq_info, &karaoke_eq_size); + if (karaoke_eq_size) { + rlen = add_one_attr(buf, buf_size, offset, attr, karaoke_eq_info, karaoke_eq_size); + } + } + return rlen; +} + +static u32 common_function_attr_karaoke_setting_info_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + u8 *data = NULL; + u8 data_len = 0; + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_KARAOKE_SETTING); + if (setting_opt_hdl) { + data = (u8 *)zalloc(setting_opt_hdl->data_len); + data_len = get_setting_extra_handle(setting_opt_hdl, data, NULL); + if (data_len) { + rlen = add_one_attr(buf, buf_size, offset, attr, data, data_len); + } + } + if (data) { + free(data); + } + return rlen; +} + +static u32 common_function_attr_karaoke_pre_fetch_eq_setting_info_get(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset) +{ + u32 rlen = 0; + u8 karaoke_eq_pre_fetch_info[1 + 8 * 2] = {0}; // num + freq * 2 + u16 karaoke_eq_pre_fetch_size = sizeof(karaoke_eq_pre_fetch_info); + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_KARAOKE_EQ_SETTING); + if (setting_opt_hdl) { + karaoke_eq_pre_fetch_size = get_setting_extra_handle(setting_opt_hdl, karaoke_eq_pre_fetch_info, &karaoke_eq_pre_fetch_size); + if (karaoke_eq_pre_fetch_size) { + rlen = add_one_attr(buf, buf_size, offset, attr, karaoke_eq_pre_fetch_info, karaoke_eq_pre_fetch_size); + } + } + return rlen; +} + +static const attr_get_func target_common_function_get_tab[COMMON_FUNCTION_ATTR_TYPE_MAX] = { + [COMMON_FUNCTION_ATTR_TYPE_BATTERY ] = common_function_attr_battery_get, + [COMMON_FUNCTION_ATTR_TYPE_VOL ] = common_function_attr_vol_get, + [COMMON_FUNCTION_ATTR_TYPE_DEV_INFO ] = common_function_attr_dev_info_get, + [COMMON_FUNCTION_ATTR_TYPE_ERROR_STATS ] = NULL, + [COMMON_FUNCTION_ATTR_TYPE_EQ_INFO ] = common_function_attr_eq_param_get, + [COMMON_FUNCTION_ATTR_TYPE_BS_FILE_TYPE ] = common_function_attr_bs_file_type, + [COMMON_FUNCTION_ATTR_TYPE_FUNCTION_MODE ] = common_function_attr_function_mode_get, + [COMMON_FUNCTION_ATTR_TYPE_FMTX_FREQ ] = common_function_attr_fmtx_freq_get, + [COMMON_FUNCTION_ATTR_TYPE_BT_EMITTER_SW ] = common_function_attr_bt_emitter_sw_get, + [COMMON_FUNCTION_ATTR_TYPE_BT_EMITTER_CONNECT_STATES ] = common_function_attr_bt_emitter_connect_state_get, + [COMMON_FUNCTION_ATTR_TYPE_HIGH_LOW_SET ] = common_function_attr_high_low_get, + [COMMON_FUNCTION_ATTR_TYPE_PRE_FETCH_ALL_EQ_INFO ] = common_function_attr_pre_fetch_all_eq_info_get, + [COMMON_FUNCTION_ATTR_TYPE_PHONE_SCO_STATE_INFO ] = common_function_attr_phone_sco_state_info_get, + [COMMON_FUNCTION_ATTR_TYPE_MISC_SETTING_INFO ] = common_function_attr_misc_setting_info_get, + [COMMON_FUNCTION_ATTR_TYPE_COLOR_LED_SETTING_INFO ] = common_function_attr_color_led_setting_info_get, + [COMMON_FUNCTION_ATTR_TYPE_PRE_FETCH_KARAOKE_EQ_INFO ] = common_function_attr_karaoke_pre_fetch_eq_setting_info_get, + [COMMON_FUNCTION_ATTR_TYPE_KARAOKE_EQ_SETTING_INFO ] = common_function_attr_karaoke_eq_setting_info_get, + [COMMON_FUNCTION_ATTR_TYPE_KARAOKE_SETTING_INFO ] = common_function_attr_karaoke_setting_info_get, +}; + + + +static bool smartbox_common_function_set(void *priv, u8 *data, u16 len) +{ + printf("smartbox_common_function_set\n"); + struct smartbox *smart = (struct smartbox *)priv; + if (smart == NULL) { + return false; + } + put_buf(data, len); + attr_set(priv, data, len, common_function_set_tab, COMMON_FUNCTION_ATTR_TYPE_MAX); + if (smart->err_code) { + smart->err_code = 0; + return false; + } + return true; +} + +static u32 smartbox_common_function_get(void *priv, u8 *buf, u16 buf_size, u32 mask) +{ + printf("smartbox_common_function_get, mask = %x\n", mask); + return attr_get(priv, buf, buf_size, target_common_function_get_tab, COMMON_FUNCTION_ATTR_TYPE_MAX, mask); +} + +bool smartbox_function_set(void *priv, u8 function, u8 *data, u16 len) +{ + if (function >= FUNCTION_MASK_MAX) { + if (function == COMMON_FUNCTION) { + return smartbox_common_function_set(priv, data, len); + } else { + return false; + } + } + + func_set func = set_tab[function]; + if (func) { + return func(priv, data, len); + } + + return false; +} + +u32 smartbox_function_get(void *priv, u8 function, u8 *data, u16 len, u8 *buf, u16 buf_size) +{ + ASSERT_SET_LEN(len, 4); + u32 mask = READ_BIG_U32(data); + if (function >= FUNCTION_MASK_MAX) { + if (function == COMMON_FUNCTION) { + return smartbox_common_function_get(priv, buf, buf_size, mask); + } else { + return 0; + } + } + + func_get func = get_tab[function]; + if (func) { + return func(priv, buf, buf_size, mask); + } + return 0; +} + +bool smartbox_function_cmd_set(void *priv, u8 function, u8 *data, u16 len) +{ + if (COMMON_FUNCTION == function) { + // 模式切换 + smartbox_msg_post(USER_MSG_SMARTBOX_MODE_SWITCH, 2, (int)priv, (int)data[0]); + return true; + } + return smartbox_function_set(priv, function, data, len); +} + +void smartbox_function_update(u8 function, u32 mask) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL || 0 == JL_rcsp_get_auth_flag()) { + return ; + } + u32 rlen = 0; + u8 *buf = zalloc(FUNCTION_UPDATE_MAX_LEN); + if (buf == NULL) { + printf("no ram err!!\n"); + return ; + } + buf[0] = function; + if (function >= FUNCTION_MASK_MAX) { + if (function == COMMON_FUNCTION) { + rlen = attr_get((void *)smart, buf + 1, FUNCTION_UPDATE_MAX_LEN - 1, target_common_function_get_tab, COMMON_FUNCTION_ATTR_TYPE_MAX, mask); + } + } else { + func_get func = get_tab[function]; + if (func) { + rlen = func(smart, buf + 1, FUNCTION_UPDATE_MAX_LEN - 1, mask); + } + } + if (rlen) { + JL_CMD_send(JL_OPCODE_SYS_INFO_AUTO_UPDATE, buf, rlen + 1, JL_NOT_NEED_RESPOND); + } + free(buf); +} + +void smartbox_update_bt_emitter_connect_state(u8 state, u8 *addr) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL) { + return ; + } + smart->emitter_bt_state = state; + memcpy(smart->emitter_con_addr, addr, 6); + smartbox_function_update(COMMON_FUNCTION, BIT(COMMON_FUNCTION_ATTR_TYPE_BT_EMITTER_CONNECT_STATES)); +} + +void smartbox_update_dev_state(u32 event) +{ + switch (event) { + case DEVICE_EVENT_FROM_ALM: + printf("DEVICE_EVENT_FROM_ALM\n"); + extern void smartbot_rtc_msg_deal(int msg); + smartbot_rtc_msg_deal(-1); + break; + case DEVICE_EVENT_FROM_LINEIN: + smartbox_function_update(COMMON_FUNCTION, BIT(COMMON_FUNCTION_ATTR_TYPE_DEV_INFO)); + break; + } +} + +u8 get_cur_mode(u8 app_mode) +{ + u8 current_mode; + switch (app_mode) { + case APP_MUSIC_TASK: + current_mode = MUSIC_FUNCTION; + break; + case APP_RTC_TASK: + current_mode = RTC_FUNCTION; + break; + case APP_LINEIN_TASK: + current_mode = LINEIN_FUNCTION; + break; + case APP_FM_TASK: + current_mode = FM_FUNCTION; + break; + case APP_BT_TASK: + default: + current_mode = BT_FUNCTION; + break; + } + return current_mode; +} + +void function_change_inform(u8 app_mode, u8 ret) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL) { + return ; + } + if (LINEIN_FUNCTION == smart->cur_app_mode) { + smartbox_function_update(COMMON_FUNCTION, BIT(COMMON_FUNCTION_ATTR_TYPE_DEV_INFO)); + } + smart->cur_app_mode = get_cur_mode(app_mode); + smartbox_function_update(COMMON_FUNCTION, BIT(COMMON_FUNCTION_ATTR_TYPE_FUNCTION_MODE)); +} + +void smartbox_function_setting_stop(void) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL) { + return ; + } + switch (smart->cur_app_mode) { + case BT_FUNCTION: + printf("BT_FUNCTION STOP\n"); +#if TCFG_APP_BT_EN + // 蓝牙模式是否播放 +#endif + break; + case MUSIC_FUNCTION: + printf("MUSIC_FUNCTION STOP\n"); +#if TCFG_APP_MUSIC_EN + // 音乐模式是否播放 + extern void music_func_stop(void); + music_func_stop(); +#endif + break; + case RTC_FUNCTION: + printf("RTC_FUNCTION STOP\n"); +#if TCFG_APP_RTC_EN + // RTC模式是否播放 + extern void rtc_func_stop(void); + rtc_func_stop(); +#endif + break; + case LINEIN_FUNCTION: + printf("LINEIN_FUNCTION STOP\n"); +#if TCFG_APP_LINEIN_EN + // linein模式是否播放 + extern void linein_func_stop(void); + linein_func_stop(); +#endif + break; + case FM_FUNCTION: + printf("FM_FUNCTION STOP\n"); +#if TCFG_APP_FM_EN + // fm模式是否播放 + extern void fm_func_stop(void); + fm_func_stop(); +#endif + break; + case FMTX_FUNCTION: + break; + } + // 调用各种设置的release函数 + smartbox_opt_release(); +} + +#endif diff --git a/apps/soundbox/smartbox/smartbox.c b/apps/soundbox/smartbox/smartbox.c new file mode 100644 index 0000000..29eb1bd --- /dev/null +++ b/apps/soundbox/smartbox/smartbox.c @@ -0,0 +1,160 @@ +#include "smartbox/smartbox.h" +#include +#include +#include +#include "string.h" +#include "system/timer.h" +#include "app_core.h" +#include "spp_user.h" +#include "app_task.h" +#include "system/task.h" +#include "smartbox/config.h" +#include "smartbox/event.h" +#include "btstack_3th_protocol_user.h" +#include "smartbox_rcsp_manage.h" +#include "smartbox_setting_opt.h" + +#if (SMART_BOX_EN) +#define SMARTBOX_TASK_NAME "smartbox" + +#ifndef JL_SMART_BOX_CUSTOM_APP_EN +#define SMARTBOX_SPP_INTERACTIVE_SUPPORT 1 +#define SMARTBOX_BLE_INTERACTIVE_SUPPORT 1 +#endif + +struct smartbox *__this = NULL; + +extern void cmd_recieve(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len); +extern void cmd_recieve_no_respone(void *priv, u8 OpCode, u8 *data, u16 len); +extern void cmd_respone(void *priv, u8 OpCode, u8 status, u8 *data, u16 len); +extern void data_recieve(void *priv, u8 OpCode_SN, u8 CMD_OpCode, u8 *data, u16 len); +extern void data_recieve_no_respone(void *priv, u8 CMD_OpCode, u8 *data, u16 len); +extern void data_respone(void *priv, u8 status, u8 CMD_OpCode, u8 *data, u16 len); + + +extern void JL_recieve_packet_parse_process(void); +void JL_rcsp_recieve_resume(void) +{ + int argv[3]; + argv[0] = (int)JL_recieve_packet_parse_process; + argv[1] = 1; + argv[2] = 0; + int ret = os_taskq_post_type("app_core", Q_CALLBACK, 3, argv); +} + +void JL_rcsp_resume_do(void) +{ + os_sem_post(&__this->sem); + JL_rcsp_recieve_resume(); +} + +static void smartbox_process(void *p) +{ + int res; + while (1) { + os_sem_pend(&__this->sem, 0); + JL_send_packet_process(); + /* JL_protocol_process(); */ + } +} + + +struct smartbox *smartbox_handle_get(void) +{ + return __this; +} + +static u16 smartbox_timer = 0; + +static void smartbox_process_timer() +{ + os_sem_post(&__this->sem); +} + +extern int smartbox_user_spp_state_specific(u8 packet_type); + +static BT_3TH_USER_CB bt_rcsp_callback = { + .type = APP_TYPE_RCSP, + + .bt_config = 0 +#if (SMARTBOX_BLE_INTERACTIVE_SUPPORT) + | BT_CONFIG_BLE +#endif +#if (SMARTBOX_SPP_INTERACTIVE_SUPPORT) + | BT_CONFIG_SPP +#endif + , + + .bt_3th_handler.priv = NULL, + .bt_3th_handler.fw_ready = NULL, + .bt_3th_handler.fw_send = NULL, + .bt_3th_handler.CMD_resp = cmd_recieve, + .bt_3th_handler.CMD_no_resp = cmd_recieve_no_respone, + .bt_3th_handler.CMD_recieve_resp = cmd_respone, + .bt_3th_handler.DATA_resp = data_recieve, + .bt_3th_handler.DATA_no_resp = data_recieve_no_respone, + .bt_3th_handler.DATA_recieve_resp = data_respone, + .bt_3th_handler.wait_resp_timeout = NULL, + .BT_3TH_spp_state_specific = smartbox_user_spp_state_specific, + .BT_3TH_event_handler = rcsp_user_event_handler, +}; + +void smartbox_init(void) +{ + if (__this) { + return; + } + + btstack_3th_protocol_user_init(&bt_rcsp_callback); + + //set_jl_mtu_resv(); + ///设置rcsp最大发送buf, 即MTU + set_jl_mtu_send(264); + + //如果支持大文件传输可以通过修改接收buf大小优化传输速度 + set_jl_rcsp_recieve_buf_size(4 * 1024); + + u32 size = rcsp_protocol_need_buf_size(); + u8 *ptr = zalloc(size); + ASSERT(ptr, "no ram for rcsp !!\n"); + JL_protocol_init(ptr, size); + + struct smartbox *smart = (struct smartbox *)zalloc(sizeof(struct smartbox)); + ASSERT(smart, "no ram for smartbox !!\n"); + smartbox_config(smart); + __this = smart; + __this->smartbox_buf = ptr; + + os_sem_create(&__this->sem, 0); + smartbox_timer = sys_timer_add(NULL, smartbox_process_timer, 500); + + ///从vm获取相关配置 + smart_setting_init(); + + int err = task_create(smartbox_process, (void *)smart, SMARTBOX_TASK_NAME); + if (err) { + printf("smartbox creat fail %x\n", err); + } +} + +void smartbox_exit(void) +{ + //extern void rcsp_resume(void); + //rcsp_resume(); + if (smartbox_timer) { + sys_timer_del(smartbox_timer); + smartbox_timer = 0; + } + task_kill(SMARTBOX_TASK_NAME); + if (__this->smartbox_buf) { + free(__this->smartbox_buf); + __this->smartbox_buf = NULL; + } + if (__this) { + free(__this); + __this = NULL; + } + smartbox_opt_release(); +} + +#endif//SMART_BOX_EN diff --git a/apps/soundbox/smartbox/smartbox_rcsp_manage.c b/apps/soundbox/smartbox/smartbox_rcsp_manage.c new file mode 100644 index 0000000..d3815dd --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_rcsp_manage.c @@ -0,0 +1,298 @@ +#include "smartbox/config.h" + +#include "app_main.h" +#include "smartbox_update_tws.h" +#include "3th_profile_api.h" + +#include "btstack/avctp_user.h" +#include "btstack/btstack_task.h" +#include "bt_tws.h" +#include "smartbox_rcsp_manage.h" +#include "le_smartbox_module.h" + +#include "smartbox_setting_opt.h" +#include "smartbox_adv_bluetooth.h" +#include "smartbox/function.h" +#include "smartbox_music_info_setting.h" +#include "smartbox_update.h" +#include "JL_rcsp_protocol.h" +#include "file_transfer.h" + +#if SMART_BOX_EN + +#define LOG_TAG "[RCSP-ADV]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +extern u8 check_le_pakcet_sent_finish_flag(void); +static void smartbox_user_state_handler(u8 *param, u8 param_len); + +u8 get_rcsp_connect_status(void) +{ +#if 1//RCSP_UPDATE_EN + if (RCSP_BLE == bt_3th_get_cur_bt_channel_sel()) { + if (bt_3th_get_jl_ble_status() == BLE_ST_CONNECT || bt_3th_get_jl_ble_status() == BLE_ST_NOTIFY_IDICATE) { + return 1; + } else { + return 0; + } + } else { + return bt_3th_get_jl_spp_status(); + } +#else + return 0; +#endif +} + +void JL_rcsp_event_to_user(u32 type, u8 event, u8 *msg, u8 size) +{ + struct sys_event e; + e.type = SYS_DEVICE_EVENT; + + if (size > sizeof(e.u.rcsp.args)) { + printf("rcsp event size overflow:%x %x\n", size, sizeof(e.u.rcsp.args)); + } + + e.arg = (void *)type; + e.u.rcsp.event = event; + + if (size) { + memcpy(e.u.rcsp.args, msg, size); + } + + e.u.rcsp.size = size; + + sys_event_notify(&e); +} + +static void wait_response_and_disconn_ble(void *priv) +{ + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_SWITCH_DEVICE, NULL, 0); +} + +int JL_rcsp_event_handler(struct rcsp_event *rcsp) +{ + int ret = 0; + switch (rcsp->event) { + case MSG_JL_ADV_SETTING_SYNC: + update_smartbox_setting(-1); + break; + case MSG_JL_ADV_SETTING_UPDATE: + update_info_from_vm_info(); + break; + case MSG_JL_SWITCH_DEVICE: + printf("MSG_JL_SWITCH_DEVICE\n"); + static u16 wait_response_timeout = 0; + static u8 wait_cnt = 0; + // ble切换spp:前一个条件开始不满足,之后满足; 后一个条件开始满足,之后不满足; 超时10次后自动断开ble + if (wait_response_timeout || (RCSP_BLE == bt_3th_get_cur_bt_channel_sel() && RCSP_SPP == rcsp->args[0])) { + if ((10 == wait_cnt) || (rcsp_send_list_is_empty() && check_le_pakcet_sent_finish_flag())) { + if (wait_response_timeout) { + sys_timeout_del(wait_response_timeout); + wait_response_timeout = 0; + } + wait_cnt = 0; + ble_app_disconnect(); + } else { + wait_cnt++; + wait_response_timeout = sys_timeout_add(NULL, wait_response_and_disconn_ble, 100); + } + } + break; + case MSG_JL_USER_SPP_BLE_STATE: + smartbox_user_state_handler(rcsp->args, rcsp->size); + break; +#if RCSP_ADV_MUSIC_INFO_ENABLE + case MSG_JL_UPDATE_PLAYER_TIME: + if (JL_rcsp_get_auth_flag()) { + smartbox_function_update(BT_FUNCTION_MASK, 0x100); + } + break; + case MSG_JL_UPDATE_PLAYER_STATE: + if (JL_rcsp_get_auth_flag()) { + smartbox_function_update(BT_FUNCTION_MASK, 0x80); + } + break; + case MSG_JL_UPDATE_MUSIC_INFO: + if (JL_rcsp_get_auth_flag()) { + /* printf("rcsp type %x\n",rcsp->args[0]); */ + smartbox_function_update(BT_FUNCTION_MASK, BIT(rcsp->args[0] - 1)); + } + break; + case MSG_JL_UPDATE_MUSIC_PLAYER_TIME_TEMER: + if (JL_rcsp_get_auth_flag()) { + music_player_time_timer_deal(rcsp->args[0]); + } + break; + case MSG_JL_PLAYER_STATE_CHANGE: + music_player_status_change(); + break; + case MSG_JL_AVRCP_CH_SYNC_MUSIC_INFO: + music_sync_info(); + break; +#endif + + default: +#if 1//RCSP_SMARTBOX_ADV_EN + if (0 == JL_smartbox_adv_event_handler(rcsp)) { + break; + } +#endif +#if RCSP_UPDATE_EN + if (0 == JL_rcsp_update_msg_deal(NULL, rcsp->event, rcsp->args)) { + break; + } +#endif + break; + } + + return ret; +} + +static void smartbox_rcsp_disconnect(void) +{ + file_transfer_close(); +} + +static void smartbox_rcsp_connect(void) +{ + +} + +static void smartbox_user_state_event(u8 opcode, u8 state) +{ + u8 data[2] = {0}; + data[0] = opcode; + data[1] = state; + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_USER_SPP_BLE_STATE, data, sizeof(data)); +} + +static void rcsp_user_event_ble_handler(ble_state_e ble_status, u8 flag) +{ + switch (ble_status) { + case BLE_ST_IDLE: +#if RCSP_UPDATE_EN + if (get_jl_update_flag()) { + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_START, NULL, 0); + } +#endif + break; + case BLE_ST_CONNECT: + if (flag) { + smartbox_user_state_event(BT_3TH_EVENT_COMMON_BLE_STATUS, BLE_ST_CONNECT); + break; + } + smartbox_rcsp_connect(); +#if (RCSP_ADV_FIND_DEVICE_ENABLE) + printf("smartbox_find_device_reset\n"); + extern void smartbox_find_device_reset(void); + smartbox_find_device_reset(); +#endif +#if (MUTIl_CHARGING_BOX_EN) + ble_app_disconnect(); +#endif + break; + case BLE_ST_DISCONN: + if (flag) { + smartbox_user_state_event(BT_3TH_EVENT_COMMON_BLE_STATUS, BLE_ST_DISCONN); + break; + } + smartbox_rcsp_disconnect(); +#if RCSP_UPDATE_EN + if (get_jl_update_flag()) { + bt_ble_adv_enable(0); + } +#endif + break; + } +} + +static void rcsp_user_event_spp_handler(u8 spp_status, u8 flag) +{ + switch (spp_status) { + case 0: + break; + case 1: + if (flag) { + smartbox_user_state_event(BT_3TH_EVENT_COMMON_SPP_STATUS, spp_status); + break; + } + smartbox_rcsp_connect(); +#if (0 == BT_CONNECTION_VERIFY) + JL_rcsp_auth_reset(); +#endif +#if (RCSP_ADV_FIND_DEVICE_ENABLE) + printf("smartbox_find_device_reset\n"); + extern void smartbox_find_device_reset(void); + smartbox_find_device_reset(); +#endif + break; + default: + if (flag) { + smartbox_user_state_event(BT_3TH_EVENT_COMMON_SPP_STATUS, spp_status); + break; + } + smartbox_rcsp_disconnect(); +#if RCSP_ADV_MUSIC_INFO_ENABLE + stop_get_music_timer(1); +#endif +#if (0 == BT_CONNECTION_VERIFY) + JL_rcsp_auth_reset(); +#endif +#if RCSP_UPDATE_EN + if (get_jl_update_flag()) { + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_START, NULL, 0); + } +#endif //rcsp_update_en + break; + } +} + +static void rcsp_user_event_select_handler(void) +{ +#if RCSP_UPDATE_EN + set_jl_update_flag(0); +#endif +} + +static void smartbox_user_state_handler(u8 *param, u8 param_len) +{ + u8 opcode = param[0]; + u8 state = param[1]; + switch (opcode) { + case BT_3TH_EVENT_COMMON_BLE_STATUS: + rcsp_user_event_ble_handler((ble_state_e)state, 0); + break; + case BT_3TH_EVENT_COMMON_SPP_STATUS: + rcsp_user_event_spp_handler(state, 0); + break; + } +} + +void rcsp_user_event_handler(u16 opcode, u8 *data, int size) +{ + ble_state_e ble_status; + u8 spp_status; + + switch (opcode) { + case BT_3TH_EVENT_COMMON_BLE_STATUS: + ble_status = data[0]; + rcsp_user_event_ble_handler(ble_status, 1); + break; + + case BT_3TH_EVENT_COMMON_SPP_STATUS: + spp_status = data[0]; + rcsp_user_event_spp_handler(spp_status, 1); + break; + + case BT_3TH_EVENT_RCSP_DEV_SELECT: + rcsp_user_event_select_handler(); + break; + } +} + +#endif diff --git a/apps/soundbox/smartbox/smartbox_rcsp_manage.h b/apps/soundbox/smartbox/smartbox_rcsp_manage.h new file mode 100644 index 0000000..88358c3 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_rcsp_manage.h @@ -0,0 +1,11 @@ +// binary representation +// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) + +#ifndef _SMARTBOX_RCSP_MANAGE_H +#define _SMARTBOX_RCSP_MANAGE_H + +void JL_rcsp_event_to_user(u32 type, u8 event, u8 *msg, u8 size); +u8 get_rcsp_connect_status(void); +void rcsp_user_event_handler(u16 opcode, u8 *data, int size); + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/adv_bt_name_setting.c b/apps/soundbox/smartbox/smartbox_setting/adv_bt_name_setting.c new file mode 100644 index 0000000..60f3bed --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/adv_bt_name_setting.c @@ -0,0 +1,114 @@ +#include "app_config.h" +#include "user_cfg.h" +#include "syscfg_id.h" +#include "le_smartbox_module.h" + +#include "smartbox_setting_opt.h" + +//#if (SMART_BOX_EN && RCSP_SMARTBOX_ADV_EN) +#if (SMART_BOX_EN) +#if RCSP_ADV_NAME_SET_ENABLE + +static u8 g_edr_name[32] = {0}; + +extern int get_bt_tws_connect_status(); + +void adv_edr_name_change_now(void) +{ + extern BT_CONFIG bt_cfg; + extern const char *bt_get_local_name(); + extern void lmp_hci_write_local_name(const char *name); + memcpy(bt_cfg.edr_name, g_edr_name, LOCAL_NAME_LEN); + lmp_hci_write_local_name(bt_get_local_name()); +} + +static void set_bt_name_setting(u8 *bt_name_setting) +{ + memcpy(g_edr_name, bt_name_setting, 32); +} + +static int get_bt_name_setting(u8 *bt_name_setting) +{ + memcpy(bt_name_setting, g_edr_name, 32); + return 0; +} + +// 1、写入VM +static void update_bt_name_vm_value(u8 *bt_name_setting) +{ + syscfg_write(CFG_BT_NAME, bt_name_setting, 32); +} +// 2、同步对端 +static void bt_name_sync(u8 *bt_name_setting) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_smartbox_setting(ATTR_TYPE_EDR_NAME); + } +#endif +} + +static void deal_bt_name_setting(u8 *bt_name_setting, u8 write_vm, u8 tws_sync) +{ + if (bt_name_setting) { + set_bt_name_setting(bt_name_setting); + } + if (write_vm) { + update_bt_name_vm_value(g_edr_name); + } + if (tws_sync) { + bt_name_sync(g_edr_name); + } +} + +static int bt_name_set_setting_extra_handle(void *setting_data, void *param) +{ + int ret = 0; + u8 dlen = *((u8 *)param); + u8 *bt_name_setting_data = (u8 *) setting_data; + u8 bt_name[32] = {0}; + if (dlen > 20) { + ret = 2; + } else { + memcpy(bt_name, bt_name_setting_data, dlen); + bt_name[dlen] = '\0'; + memcpy(g_edr_name, bt_name, sizeof(bt_name)); + } + return ret; +} + +static int bt_name_get_setting_extra_handle(void *setting_data, void *param) +{ + int **setting_data_ptr = (int **)setting_data; + *setting_data_ptr = g_edr_name; + return strlen(g_edr_name); +} + +static SMARTBOX_SETTING_OPT adv_bt_name_opt = { + .data_len = 32, + .setting_type = ATTR_TYPE_EDR_NAME, + .syscfg_id = CFG_BT_NAME, + .deal_opt_setting = deal_bt_name_setting, + .set_setting = set_bt_name_setting, + .get_setting = get_bt_name_setting, + .custom_setting_init = NULL, + .custom_vm_info_update = NULL, + .custom_setting_update = NULL, + .custom_sibling_setting_deal = NULL, + .custom_setting_release = NULL, + .set_setting_extra_handle = bt_name_set_setting_extra_handle, + .get_setting_extra_handle = bt_name_get_setting_extra_handle, +}; + +REGISTER_APP_SETTING_OPT(adv_bt_name_opt); + +#else + +void adv_edr_name_change_now(void) +{ + +} + +#endif + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/adv_key_setting.c b/apps/soundbox/smartbox/smartbox_setting/adv_key_setting.c new file mode 100644 index 0000000..6d4808f --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/adv_key_setting.c @@ -0,0 +1,263 @@ +#include "app_config.h" +#include "syscfg_id.h" +#include "key_event_deal.h" +#include "le_smartbox_module.h" + +#include "smartbox_setting_sync.h" +#include "smartbox_setting_opt.h" + +//#if (SMART_BOX_EN && RCSP_SMARTBOX_ADV_EN) +#if (SMART_BOX_EN) +#if RCSP_ADV_KEY_SET_ENABLE + +extern int get_bt_tws_connect_status(); +static u8 rcsp_adv_key_event_flag = 0x0; + + +static u8 g_key_setting[12] = { + 0x01, 0x01, 0x05, \ + 0x02, 0x01, 0x05, \ + 0x01, 0x02, 0x08, \ + 0x02, 0x02, 0x08 +}; + +static void enable_adv_key_event(void) +{ + rcsp_adv_key_event_flag = 1; +} + +static u8 get_adv_key_event_status(void) +{ + return rcsp_adv_key_event_flag; +} + +static void disable_adv_key_event(void) +{ + rcsp_adv_key_event_flag = 0; +} + +static void set_key_setting(u8 *key_setting_info) +{ + g_key_setting[3 * 0 + 2] = key_setting_info[0]; + g_key_setting[3 * 2 + 2] = key_setting_info[1]; + g_key_setting[3 * 1 + 2] = key_setting_info[2]; + g_key_setting[3 * 3 + 2] = key_setting_info[3]; +} + +static int get_key_setting(u8 *key_setting_info) +{ + key_setting_info[0] = g_key_setting[3 * 0 + 2]; + key_setting_info[1] = g_key_setting[3 * 2 + 2]; + key_setting_info[2] = g_key_setting[3 * 1 + 2]; + key_setting_info[3] = g_key_setting[3 * 3 + 2]; + return 0; +} + +static void update_key_setting_vm_value(u8 *key_setting_info) +{ + syscfg_write(CFG_RCSP_ADV_KEY_SETTING, key_setting_info, 4); +} + +static void key_setting_sync(u8 *key_setting_info) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_smartbox_setting(ATTR_TYPE_KEY_SETTING); + } +#endif +} + +static void deal_key_setting(u8 *key_setting_info, u8 write_vm, u8 tws_sync) +{ + u8 key_setting[4]; + if (!key_setting_info) { + get_key_setting(key_setting); + } else { + memcpy(key_setting, key_setting_info, 4); + } + // 1、写入VM + if (write_vm) { + update_key_setting_vm_value(key_setting); + } + // 2、同步对端 + if (tws_sync) { + key_setting_sync(key_setting); + } + // 3、更新状态 + enable_adv_key_event(); +} + +#define ADV_POWER_ON_OFF 0 +enum ADV_KEY_TYPE { + ADV_KEY_TYPE_NULL = 0x0, +#if ADV_POWER_ON_OFF + ADV_KEY_TYPE_POWER_ON, + ADV_KEY_TYPE_POWER_OFF, +#endif + ADV_KEY_TYPE_PREV = 0x3, + ADV_KEY_TYPE_NEXT, + ADV_KEY_TYPE_PP, + ADV_KEY_TYPE_ANSWER_CALL, + ADV_KEY_TYPE_HANG_UP, + ADV_KEY_TYPE_CALL_BACK, + ADV_KEY_TYPE_INC_VOICE, + ADV_KEY_TYPE_DESC_VOICE, + ADV_KEY_TYPE_TAKE_PHOTO, +}; + +static u8 get_adv_key_opt(u8 key_action, u8 channel) +{ + u8 opt; + for (opt = 0; opt < sizeof(g_key_setting); opt += 3) { + if (g_key_setting[opt] == channel && + g_key_setting[opt + 1] == key_action) { + break; + } + } + if (sizeof(g_key_setting) == opt) { + return -1; + } + + switch (g_key_setting[opt + 2]) { + case ADV_KEY_TYPE_NULL: + //opt = KEY_NULL; + opt = ADV_KEY_TYPE_NULL; + break; +#if ADV_POWER_ON_OFF + case ADV_KEY_TYPE_POWER_ON: + opt = KEY_POWER_ON; + break; + case ADV_KEY_TYPE_POWER_OFF: + opt = KEY_RCSP_POWEROFF; + break; +#endif + case ADV_KEY_TYPE_PREV: + opt = KEY_MUSIC_PREV; + break; + case ADV_KEY_TYPE_NEXT: + opt = KEY_MUSIC_NEXT; + break; + case ADV_KEY_TYPE_PP: + opt = KEY_MUSIC_PP; + break; + case ADV_KEY_TYPE_ANSWER_CALL: + opt = KEY_CALL_ANSWER; + break; + case ADV_KEY_TYPE_HANG_UP: + opt = KEY_CALL_HANG_UP; + break; + case ADV_KEY_TYPE_CALL_BACK: + opt = KEY_CALL_LAST_NO; + break; + case ADV_KEY_TYPE_INC_VOICE: + opt = KEY_VOL_UP; + break; + case ADV_KEY_TYPE_DESC_VOICE: + opt = KEY_VOL_DOWN; + break; + case ADV_KEY_TYPE_TAKE_PHOTO: + opt = KEY_HID_CONTROL; + break; + } + return opt; +} + +void set_key_event_by_rcsp_info(struct sys_event *event, u8 *key_event) +{ + if (0 == get_adv_key_event_status()) { + return; + } + + u8 key_action = 0; + struct key_event *key = &event->u.key; + switch (key->event) { + case 0: + // 单击 + key_action = 0x1; + break; + case 4: + // 双击 + key_action = 0x2; + break; + default: + return; + } + +#if (TCFG_CHARGESTORE_ENABLE && TCFG_USER_TWS_ENABLE) + u8 channel = tws_api_get_local_channel(); + + if (get_bt_tws_connect_status()) { + channel = tws_api_get_local_channel(); + } +#else + u8 channel = 'U'; +#endif + + switch (channel) { + case 'U': + case 'L': + channel = (u32) event->arg == KEY_EVENT_FROM_TWS ? 2 : 1; + break; + case 'R': + channel = (u32) event->arg == KEY_EVENT_FROM_TWS ? 1 : 2; + break; + default: + return; + } + + key_action = get_adv_key_opt(key_action, channel); + if ((u8) - 1 != key_action) { + *key_event = key_action ? key_action : KEY_NULL; + } +} + +static int key_set_setting_extra_handle(void *setting_data, void *param) +{ + u8 dlen = *((u8 *)param); + u8 *key_setting_data = (u8 *) setting_data; + while (dlen >= 3) { + if (key_setting_data[0] == 0x01) { + if (key_setting_data[1] == 0x01) { + g_key_setting[2] = key_setting_data[2]; + } else if (key_setting_data[1] == 0x02) { + g_key_setting[8] = key_setting_data[2]; + } + } else if (key_setting_data[0] == 0x02) { + if (key_setting_data[1] == 0x01) { + g_key_setting[5] = key_setting_data[2]; + } else if (key_setting_data[1] == 0x02) { + g_key_setting[11] = key_setting_data[2]; + } + } + dlen -= 3; + key_setting_data += 3; + } + return 0; +} + +static int key_get_setting_extra_handle(void *setting_data, void *param) +{ + int **setting_data_ptr = (int **)setting_data; + *setting_data_ptr = g_key_setting; + return sizeof(g_key_setting); +} + +static SMARTBOX_SETTING_OPT adv_key_opt = { + .data_len = 4, + .setting_type = ATTR_TYPE_KEY_SETTING, + .syscfg_id = CFG_RCSP_ADV_KEY_SETTING, + .deal_opt_setting = deal_key_setting, + .set_setting = set_key_setting, + .get_setting = get_key_setting, + .custom_setting_init = NULL, + .custom_vm_info_update = NULL, + .custom_setting_update = NULL, + .custom_sibling_setting_deal = NULL, + .custom_setting_release = NULL, + .set_setting_extra_handle = key_set_setting_extra_handle, + .get_setting_extra_handle = key_get_setting_extra_handle, +}; +REGISTER_APP_SETTING_OPT(adv_key_opt); + +#endif +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/adv_led_setting.c b/apps/soundbox/smartbox/smartbox_setting/adv_led_setting.c new file mode 100644 index 0000000..43b5c3c --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/adv_led_setting.c @@ -0,0 +1,226 @@ +#include "app_config.h" +#include "syscfg_id.h" +#include "user_cfg.h" +#include "le_smartbox_module.h" + +#include "smartbox_setting_sync.h" +#include "smartbox_setting_opt.h" + +//#if (SMART_BOX_EN && RCSP_SMARTBOX_ADV_EN) +#if (SMART_BOX_EN) +#if RCSP_ADV_LED_SET_ENABLE +#include "asm/pwm_led.h" +#include "ui_manage.h" + +enum ADV_LED_TYPE { + ADV_LED_TYPE_ALL_OFF = 0x0, + ADV_LED_TYPE_RED_ON, + ADV_LED_TYPE_BLUE_ON, + ADV_LED_TYPE_RAD_BREATHE, + ADV_LED_TYPE_BLUE_BREATHE, + ADV_LED_TYPE_FAST_FLASH, + ADV_LED_TYPE_SLOW_FLASH, +}; + +static u8 g_led_status[14] = { + 0x01, 0x06, \ + 0x02, 0x05, \ + 0x03, 0x04, \ + 0x04, 0x00, \ + 0x05, 0x00, \ + 0x06, 0x00, \ + 0x07, 0x00 +}; + +extern STATUS *get_led_config(void); +extern int get_bt_tws_connect_status(); + + +__attribute__((weak)) +u8 adv_get_led_status(void) +{ + return 1; +} + +static u8 adv_led_value_conversion(u8 adv_led_opt) +{ + u8 conversion_value = adv_led_opt; + switch (adv_led_opt) { + case ADV_LED_TYPE_ALL_OFF: + conversion_value = PWM_LED_ALL_OFF; + break; + case ADV_LED_TYPE_RED_ON: + conversion_value = PWM_LED1_ON; + break; + case ADV_LED_TYPE_BLUE_ON: + conversion_value = PWM_LED0_ON; + break; + case ADV_LED_TYPE_RAD_BREATHE: + conversion_value = PWM_LED1_BREATHE; + break; + case ADV_LED_TYPE_BLUE_BREATHE: + conversion_value = PWM_LED0_BREATHE; + break; + case ADV_LED_TYPE_FAST_FLASH: + conversion_value = PWM_LED0_LED1_FAST_FLASH; + break; + case ADV_LED_TYPE_SLOW_FLASH: + conversion_value = PWM_LED0_LED1_SLOW_FLASH; + break; + } + return conversion_value; +} + +static void set_led_setting(u8 *led_setting_info) +{ + g_led_status[2 * 0 + 1] = led_setting_info[0]; + g_led_status[2 * 1 + 1] = led_setting_info[1]; + g_led_status[2 * 2 + 1] = led_setting_info[2]; + g_led_status[2 * 3 + 1] = led_setting_info[3]; + g_led_status[2 * 4 + 1] = led_setting_info[4]; + g_led_status[2 * 5 + 1] = led_setting_info[5]; + g_led_status[2 * 6 + 1] = led_setting_info[6]; +} + +static int get_led_setting(u8 *led_setting_info) +{ + led_setting_info[0] = g_led_status[2 * 0 + 1]; + led_setting_info[1] = g_led_status[2 * 1 + 1]; + led_setting_info[2] = g_led_status[2 * 2 + 1]; + led_setting_info[3] = g_led_status[2 * 3 + 1]; + led_setting_info[4] = g_led_status[2 * 4 + 1]; + led_setting_info[5] = g_led_status[2 * 5 + 1]; + led_setting_info[6] = g_led_status[2 * 6 + 1]; + return 0; +} + +// 1、写入VM +static void update_led_setting_vm_value(u8 *led_setting_info) +{ + syscfg_write(CFG_RCSP_ADV_LED_SETTING, led_setting_info, 7); +} +// 2、同步对端 +static void led_setting_sync(u8 *led_setting_info) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_smartbox_setting(ATTR_TYPE_LED_SETTING); + } +#endif +} +// 3、更新状态 +void update_led_setting_state(void) +{ + u8 led_setting_info[7]; + get_led_setting(led_setting_info); + + // 直接修改led表 + LED_REMAP_STATUS *p_led = led_get_remap_t(); + // 未配对 + p_led->bt_init_ok = adv_led_value_conversion(led_setting_info[0]); + // 未连接 + p_led->tws_connect_ok = adv_led_value_conversion(led_setting_info[1]); + // 连接 + p_led->bt_connect_ok = adv_led_value_conversion(led_setting_info[2]); + // 断开连接 + p_led->bt_disconnect = adv_led_value_conversion(led_setting_info[1]); + // 音乐模式播放音乐 + p_led->music_play = adv_led_value_conversion(led_setting_info[3]); + // 音乐模式停止播放 + p_led->music_pause = adv_led_value_conversion(led_setting_info[4]); + // Linein模式播放音乐 + p_led->linein_play = adv_led_value_conversion(led_setting_info[5]); + // Linein模式静音 + p_led->linein_mute = adv_led_value_conversion(led_setting_info[6]); + + switch (adv_get_led_status()) { + case STATUS_BT_INIT_OK: + case STATUS_BT_DISCONN: + ui_update_status(STATUS_BT_INIT_OK); + break; + case STATUS_BT_TWS_CONN: + ui_update_status(STATUS_BT_TWS_CONN); + break; + case STATUS_PHONE_ACTIV: + case STATUS_PHONE_OUT: + case STATUS_PHONE_INCOME: + case STATUS_BT_CONN: + ui_update_status(STATUS_BT_CONN); + break; + case STATUS_MUSIC_MODE: + case STATUS_MUSIC_PLAY: + ui_update_status(STATUS_MUSIC_PLAY); + break; + case STATUS_MUSIC_PAUSE: + ui_update_status(STATUS_MUSIC_PAUSE); + break; + case STATUS_LINEIN_MODE: + case STATUS_LINEIN_PLAY: + ui_update_status(STATUS_LINEIN_PLAY); + break; + case STATUS_LINEIN_PAUSE: + ui_update_status(STATUS_LINEIN_PAUSE); + break; + } +} + +static void deal_led_setting(u8 *led_setting_info, u8 write_vm, u8 tws_sync) +{ + u8 led_setting[7]; + if (!led_setting_info) { + get_led_setting(led_setting); + } else { + memcpy(led_setting, led_setting_info, 7); + set_led_setting(led_setting_info); + } + if (write_vm) { + update_led_setting_vm_value(led_setting); + } + if (tws_sync) { + led_setting_sync(led_setting); + } + update_led_setting_state(); +} + +static int led_set_setting_extra_handle(void *setting_data, void *param) +{ + u8 dlen = *((u8 *)param); + u8 *led_setting_data = (u8 *) setting_data; + while (dlen >= 2) { + if (led_setting_data[0] == 0 || led_setting_data[0] > 7) { + return -1; + } else { + g_led_status[2 * (led_setting_data[0] - 1) + 1] = led_setting_data[1]; + } + dlen -= 2; + led_setting_data += 2; + } + return 0; +} + +static int led_get_setting_extra_handle(void *setting_data, void *param) +{ + int **setting_data_ptr = (int **)setting_data; + *setting_data_ptr = g_led_status; + return sizeof(g_led_status); +} + +static SMARTBOX_SETTING_OPT adv_led_opt = { + .data_len = 7, + .setting_type = ATTR_TYPE_LED_SETTING, + .syscfg_id = CFG_RCSP_ADV_LED_SETTING, + .deal_opt_setting = deal_led_setting, + .set_setting = set_led_setting, + .get_setting = get_led_setting, + .custom_setting_init = NULL, + .custom_vm_info_update = NULL, + .custom_setting_update = NULL, + .custom_sibling_setting_deal = NULL, + .custom_setting_release = NULL, + .set_setting_extra_handle = led_set_setting_extra_handle, + .get_setting_extra_handle = led_get_setting_extra_handle, +}; +REGISTER_APP_SETTING_OPT(adv_led_opt); + +#endif +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/adv_mic_setting.c b/apps/soundbox/smartbox/smartbox_setting/adv_mic_setting.c new file mode 100644 index 0000000..ba53267 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/adv_mic_setting.c @@ -0,0 +1,191 @@ +#include "app_config.h" +#include "syscfg_id.h" +#include "le_smartbox_module.h" + +#include "adv_mic_setting.h" +#include "smartbox_setting_sync.h" +#include "smartbox_setting_opt.h" + +//#if (SMART_BOX_EN && RCSP_SMARTBOX_ADV_EN) +#if (SMART_BOX_EN) +#if RCSP_ADV_MIC_SET_ENABLE + +static u8 g_mic_mode = 1; + +extern void test_esco_role_switch(u8 flag); +extern void tws_conn_switch_role(); +extern int get_bt_tws_connect_status(); +static void mic_setting_info_deal(u8 *mic_info_data) +{ +#if TCFG_USER_TWS_ENABLE + u8 channel = tws_api_get_local_channel(); + printf("%s, %d\n", __FUNCTION__, channel); + + if (tws_api_get_role() == TWS_ROLE_MASTER) { + printf("-----master-----\n"); + } else { + printf("-----role-----\n"); + } + switch (*mic_info_data) { + case 0x01: + if (get_bt_tws_connect_status()) { + printf("-------auto--------\n"); + tws_api_auto_role_switch_enable(); + } + break; + case 0x02: + if (get_bt_tws_connect_status()) { + if (channel != 'L') { + printf("-------!L--------\n"); + tws_api_auto_role_switch_disable(); + tws_conn_switch_role(); + } + } + break; + case 0x03: + if (get_bt_tws_connect_status()) { + if (channel != 'R') { + printf("-------!R--------\n"); + tws_api_auto_role_switch_disable(); + tws_conn_switch_role(); + } + } + break; + default: + break; + } +#endif +} + +static void set_mic_setting(u8 *mic_setting_info) +{ + g_mic_mode = *mic_setting_info; +} + +static int get_mic_setting(u8 *mic_setting_info) +{ + *mic_setting_info = g_mic_mode; + return 0; +} + +static void update_mic_setting_vm_value(u8 *mic_setting_info) +{ + syscfg_write(CFG_RCSP_ADV_MIC_SETTING, mic_setting_info, 1); +} + +static void adv_mic_setting_sync(u8 *mic_setting_info) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_smartbox_setting(ATTR_TYPE_MIC_SETTING); + } +#endif +} + +static void deal_mic_setting(u8 *mic_setting_info, u8 write_vm, u8 tws_sync) +{ + if (mic_setting_info) { + set_mic_setting(mic_setting_info); + } + if (write_vm) { + update_mic_setting_vm_value(&g_mic_mode); + } + if (tws_sync) { + adv_mic_setting_sync(&g_mic_mode); + } + mic_setting_info_deal(&g_mic_mode); +} + + +//通话时,固定mic的位置,mode--esco state +void rcsp_user_mic_fixed_deal(u8 mode) +{ + u8 channel = tws_api_get_local_channel(); + + if (!get_bt_tws_connect_status()) { + return; + } + + if (mode == 0) { + test_esco_role_switch(0); + return; + } + + u8 adv_mic_setting = 0; + get_mic_setting(&adv_mic_setting); + if ((tws_api_get_role() == TWS_ROLE_MASTER) + && (tws_api_get_tws_state() | TWS_STA_ESCO_OPEN)) { + + switch (adv_mic_setting) { + case 0x02: + if (get_bt_tws_connect_status()) { + if (channel != 'L') { + printf("mic_sw_l\n"); + test_esco_role_switch(1); + } + } + break; + + case 0x03: + if (get_bt_tws_connect_status()) { + if (channel != 'R') { + printf("mic_sw_r\n"); + test_esco_role_switch(1); + + } + } + + break; + + default: + printf("mic_sw_auto\n"); + test_esco_role_switch(0); + break; + } + } +} + +static int mic_set_setting_extra_handle(void *setting_data, void *param) +{ + u8 dlen = *((u8 *)param); + u8 *led_setting_data = (u8 *) setting_data; + + SMARTBOX_SETTING_OPT *work_setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_WORK_MODE); + if (work_setting_opt_hdl) { + u8 work_mode = 0; + get_smartbox_opt_setting(work_setting_opt_hdl, &work_mode); + if (2 == work_mode) { + return 1; + } + } + memcpy(&g_mic_mode, led_setting_data, dlen); + return 0; +} + +static int mic_get_setting_extra_handle(void *setting_data, void *param) +{ + int **setting_data_ptr = (int **)setting_data; + *setting_data_ptr = &g_mic_mode; + return sizeof(g_mic_mode); +} + +static SMARTBOX_SETTING_OPT adv_mic_opt = { + .data_len = 1, + .setting_type = ATTR_TYPE_MIC_SETTING, + .syscfg_id = CFG_RCSP_ADV_MIC_SETTING, + .deal_opt_setting = deal_mic_setting, + .set_setting = set_mic_setting, + .get_setting = get_mic_setting, + .custom_setting_init = NULL, + .custom_vm_info_update = NULL, + .custom_setting_update = NULL, + .custom_sibling_setting_deal = NULL, + .custom_setting_release = NULL, + .set_setting_extra_handle = mic_set_setting_extra_handle, + .get_setting_extra_handle = mic_get_setting_extra_handle, +}; +REGISTER_APP_SETTING_OPT(adv_mic_opt); + +#endif + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/adv_mic_setting.h b/apps/soundbox/smartbox/smartbox_setting/adv_mic_setting.h new file mode 100644 index 0000000..4479580 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/adv_mic_setting.h @@ -0,0 +1,14 @@ +#ifndef __ADV_MIC_SETTING_H__ +#define __ADV_MIC_SETTING_H__ + + +#include "le_rcsp_adv_module.h" + +#if RCSP_ADV_MIC_SET_ENABLE + +//void set_mic_setting(u8 *mic_setting_info); +//void get_mic_setting(u8 *mic_setting_info); +void rcsp_user_mic_fixed_deal(u8 mode); + +#endif +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/adv_time_stamp_setting.c b/apps/soundbox/smartbox/smartbox_setting/adv_time_stamp_setting.c new file mode 100644 index 0000000..e39435c --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/adv_time_stamp_setting.c @@ -0,0 +1,125 @@ +#include "smartbox/config.h" +#include "syscfg_id.h" +#include "le_smartbox_module.h" + +#include "adv_time_stamp_setting.h" +#include "smartbox_setting_sync.h" +#include "smartbox_setting_opt.h" +#include "smartbox_adv_bluetooth.h" + +#include "smartbox_rcsp_manage.h" + +//#if (SMART_BOX_EN && RCSP_SMARTBOX_ADV_EN) +#if (SMART_BOX_EN) +extern int get_bt_tws_connect_status(); +static u32 adv_time_stamp = 0; +static int get_adv_time_stamp(u8 *time_stamp) +{ + memcpy(time_stamp, (u8 *)&adv_time_stamp, sizeof(adv_time_stamp)); + return 0; +} + +static void set_adv_time_stamp(u8 *time_stamp) +{ + memcpy((u8 *)&adv_time_stamp, time_stamp, sizeof(adv_time_stamp)); +} + +void sync_setting_by_time_stamp(void) +{ + tws_api_send_data_to_sibling((u8 *)&adv_time_stamp, sizeof(adv_time_stamp), TWS_FUNC_ID_TIME_STAMP_SYNC); +} + +void deal_sibling_time_stamp_setting_switch(void *data, u16 len) +{ + u32 time_stamp = *((u32 *)data); + if (adv_time_stamp > time_stamp) { + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_ADV_SETTING_SYNC, NULL, 0); + } +} + +void deal_adv_setting_gain_time_stamp(void) +{ +#if TCFG_USER_TWS_ENABLE + extern u8 adv_info_device_request(u8 * buf, u16 len); + static u8 tws_pair = 0; + u8 buf = 2; + u8 ret = 0; + if (get_bt_tws_connect_status()) { + tws_pair = 1; + } else { + if (tws_pair) { + tws_pair = 0; + ret = adv_info_device_request(&buf, sizeof(buf)); + } + } +#endif +} + +// 1、写入VM +static void update_time_stamp_vm_value(u8 *time_stamp) +{ + syscfg_write(CFG_RCSP_ADV_TIME_STAMP, time_stamp, 4); +} +// 2、同步对端 +static void adv_time_stamp_sync(u8 *time_stamp) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_smartbox_setting(ATTR_TYPE_TIME_STAMP); + } +#endif +} + +static void deal_time_stamp_setting(u8 *time_stamp, u8 write_vm, u8 tws_sync) +{ + if (time_stamp) { + set_adv_time_stamp(time_stamp); + } + if (write_vm) { + update_time_stamp_vm_value((u8 *)&adv_time_stamp); + } + if (tws_sync) { + adv_time_stamp_sync((u8 *)&adv_time_stamp); + } +} + +static int adv_time_stamp_sibling_settting_deal(u8 *setting_data) +{ + u32 time_stamp = (setting_data[0] | (setting_data[1] << 8) | (setting_data[2] << 16) | (setting_data[3] << 24)); + set_adv_time_stamp((u8 *)&time_stamp); + return 0; +} + +static int time_stamp_set_setting_extra_handle(void *setting_data, void *param) +{ + u8 dlen = *((u8 *)param); + u8 *time_stamp_setting_data = (u8 *) setting_data; + adv_time_stamp = (((time_stamp_setting_data[0] << 8) | time_stamp_setting_data[1]) << 8 | time_stamp_setting_data[2]) << 8 | time_stamp_setting_data[3]; + + u8 bt_name[32] = {0}; + syscfg_read(CFG_BT_NAME, bt_name, sizeof(bt_name)); + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(ATTR_TYPE_EDR_NAME); + if (setting_opt_hdl && setting_opt_hdl->set_setting) { + setting_opt_hdl->set_setting(bt_name); + } + return 0; +} + +static SMARTBOX_SETTING_OPT adv_time_stamp_opt = { + .data_len = 4, + .setting_type = ATTR_TYPE_TIME_STAMP, + .syscfg_id = CFG_RCSP_ADV_TIME_STAMP, + .deal_opt_setting = deal_time_stamp_setting, + .set_setting = set_adv_time_stamp, + .get_setting = get_adv_time_stamp, + .custom_setting_init = NULL, + .custom_vm_info_update = NULL, + .custom_setting_update = NULL, + .custom_sibling_setting_deal = adv_time_stamp_sibling_settting_deal, + .custom_setting_release = NULL, + .set_setting_extra_handle = time_stamp_set_setting_extra_handle, + .get_setting_extra_handle = NULL, +}; +REGISTER_APP_SETTING_OPT(adv_time_stamp_opt); + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/adv_time_stamp_setting.h b/apps/soundbox/smartbox/smartbox_setting/adv_time_stamp_setting.h new file mode 100644 index 0000000..cab13a1 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/adv_time_stamp_setting.h @@ -0,0 +1,10 @@ +#ifndef __ADV_TIME_STAMP_SETTING_H__ +#define __ADV_TIME_STAMP_SETTING_H__ + +//void set_adv_time_stamp(u8 *time_stamp); +//void get_adv_time_stamp(u8 *time_stamp); +void deal_sibling_time_stamp_setting_switch(void *data, u16 len); +extern void sync_setting_by_time_stamp(void); +void deal_adv_setting_gain_time_stamp(void); + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/adv_work_setting.c b/apps/soundbox/smartbox/smartbox_setting/adv_work_setting.c new file mode 100644 index 0000000..eed1d04 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/adv_work_setting.c @@ -0,0 +1,141 @@ +#include "app_config.h" +#include "syscfg_id.h" +#include "le_smartbox_module.h" + +#include "smartbox_setting_sync.h" +#include "smartbox_setting_opt.h" +#include "os/os_api.h" +#include "btstack/avctp_user.h" + +//#if (SMART_BOX_EN && RCSP_SMARTBOX_ADV_EN) +#if (SMART_BOX_EN) +#if RCSP_ADV_WORK_SET_ENABLE + +static u8 g_work_mode = 1; + +extern int get_bt_tws_connect_status(); +extern void bt_set_low_latency_mode(int enable); +static void set_work_setting(u8 *work_setting_info) +{ + g_work_mode = *work_setting_info; +} + +static int get_work_setting(u8 *work_setting_info) +{ + *work_setting_info = g_work_mode; + return 0; +} + +static void adv_work_setting_vm_value(u8 *work_setting_info) +{ + /* syscfg_write(CFG_RCSP_ADV_WORK_SETTING, &work_setting_info, 1); */ +} + +static void adv_work_setting_sync(u8 *work_setting_info) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_smartbox_setting(ATTR_TYPE_WORK_MODE); + } +#endif +} + +static void __rcsp_work_set_call(void) +{ + //r_f_printf("__rcsp_work_set_call\n"); + if (1 == g_work_mode) { + bt_set_low_latency_mode(0); + } else if (2 == g_work_mode) { + bt_set_low_latency_mode(1); + } +} + +static void rcsp_work_set_deal(void) +{ + int err; + int msg[3]; + msg[0] = (int) __rcsp_work_set_call; + msg[1] = 1; + msg[2] = 0; + + err = os_taskq_post_type("app_core", Q_CALLBACK, 3, msg); + //r_printf("err %x\n",err); + + +} + +static void update_work_setting_state(void) +{ + //r_f_printf("set deal\n"); + rcsp_work_set_deal(); +} + +static void deal_work_setting(u8 *work_setting_info, u8 write_vm, u8 tws_sync) +{ + if (work_setting_info) { + set_work_setting(work_setting_info); + } + if (write_vm) { + adv_work_setting_vm_value(&g_work_mode); + } + if (tws_sync) { + adv_work_setting_sync(&g_work_mode); + } + update_work_setting_state(); +} + + +int ble_vendor_is_slow_state(void) +{ + if ((BT_STATUS_PLAYING_MUSIC == get_bt_connect_status()) && (2 == g_work_mode)) { + return 1; + } else { + return 0; + } +} + +static int adv_work_opt_init(void) +{ + u8 work_setting_info = 0; + if (smartbox_read_data_from_vm(CFG_RCSP_ADV_WORK_SETTING, &work_setting_info, sizeof(work_setting_info))) { + set_work_setting(&work_setting_info); + __rcsp_work_set_call(); + } + return 0; +} + +static int work_set_setting_extra_handle(void *setting_data, void *param) +{ + u8 dlen = *((u8 *)param); + u8 *led_setting_data = (u8 *) setting_data; + memcpy(&g_work_mode, led_setting_data, dlen); + return 0; +} + +static int work_get_setting_extra_handle(void *setting_data, void *param) +{ + int **setting_data_ptr = (int **)setting_data; + *setting_data_ptr = &g_work_mode; + return sizeof(g_work_mode); +} + +static SMARTBOX_SETTING_OPT adv_work_opt = { + .data_len = 1, + .setting_type = ATTR_TYPE_WORK_MODE, + .syscfg_id = CFG_RCSP_ADV_WORK_SETTING, + .deal_opt_setting = deal_work_setting, + .set_setting = set_work_setting, + .get_setting = get_work_setting, + .custom_setting_init = adv_work_opt_init, + .custom_vm_info_update = NULL, + .custom_setting_update = NULL, + .custom_sibling_setting_deal = NULL, + .custom_setting_release = NULL, + .set_setting_extra_handle = work_set_setting_extra_handle, + .get_setting_extra_handle = work_get_setting_extra_handle, +}; + +REGISTER_APP_SETTING_OPT(adv_work_opt); + +#endif +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/smartbox_color_led_setting.c b/apps/soundbox/smartbox/smartbox_setting/smartbox_color_led_setting.c new file mode 100644 index 0000000..9cb3bc2 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/smartbox_color_led_setting.c @@ -0,0 +1,230 @@ +#include "app_config.h" +#include "syscfg_id.h" +#include "user_cfg.h" +#include "le_smartbox_module.h" + +#include "smartbox_setting_sync.h" +#include "smartbox_setting_opt.h" + +//#if (SMART_BOX_EN && RCSP_SMARTBOX_ADV_EN) +#if (SMART_BOX_EN) + +#if RCSP_ADV_COLOR_LED_SET_ENABLE +#include "ui_manage.h" +#include "asm/pwm_led.h" +#include "color_led_app.h" +#define IS_COLOR_LED_LEGAL(color_led) \ + ((color_led.open_status <= 2) && \ + (color_led.mode <= 2) && \ + (color_led.fre_mode <= 3)) + +enum { + OPEN_STATUS_CLOSE = 0, + OPEN_STATUS_OPEN = 1, + OPEN_STATUS_SETTING = 2, +}; +enum { + MODE_LIGHT = 0, + MODE_TWINKLE = 1, + MODE_USER = 2, +}; +const u32 twinkle_color_table[] = { + COLOR_RED, + COLOR_ORANGE, + COLOR_YELLOW, + COLOR_GREEN, + COLOR_CYAN, + COLOR_BLUE, + COLOR_PURPLE, +}; + +typedef struct { + u8 open_status : 2;//0:关闭 1:打开 2:设置模式 + u8 mode : 3;//0:彩色 2:闪烁 3:情景模式 + u8 reseved : 3; + u8 red; + u8 green; + u8 blue; + u8 twinkle_mode; + u8 fre_mode; + u8 user_mode; + u16 hue; + u8 saturation; + u8 lightness; +} __attribute__((packed)) color_led_t; +static color_led_t color_led; + +#define COLOR_LED_PROTOCOL_DATA_LEN (sizeof(color_led_t)) + +u32 get_color_led_setting_data_len(void) +{ + return COLOR_LED_PROTOCOL_DATA_LEN; +} + +static void set_color_led_setting(u8 *color_led_setting_info) +{ + put_buf(color_led_setting_info, COLOR_LED_PROTOCOL_DATA_LEN); + color_led_t color_led_cur; + memcpy((u8 *)&color_led_cur, color_led_setting_info, sizeof(color_led_t)); + if ((color_led_cur.open_status == 0) || (color_led_cur.open_status == 1)) { + //switch active,not set other_status + color_led.open_status = color_led_cur.open_status; + return; + } + + memcpy((u8 *)&color_led, color_led_setting_info, sizeof(color_led_t)); +} + +static int get_color_led_setting(u8 *color_led_setting_info) +{ + color_led_t color_led_cur; + int len = syscfg_read(VM_COLOR_LED_SETTING, color_led_setting_info, COLOR_LED_PROTOCOL_DATA_LEN); + + if (len != COLOR_LED_PROTOCOL_DATA_LEN) { + printf("!!!!!!!!color led data read error !!!!!!!!!!!!!!! \n"); + } + return 0; +} + +// 1、写入VM +static void update_color_led_setting_vm_value(u8 *color_led_setting_info) +{ + color_led_t color_led_cur; + memcpy((u8 *)&color_led_cur, color_led_setting_info, sizeof(color_led_t)); + if ((color_led_cur.open_status == 0) || (color_led_cur.open_status == 1)) { + //switch active,not set other_status + u8 open_status = color_led_cur.open_status; + int len = syscfg_read(VM_COLOR_LED_SETTING, (u8 *)&color_led_cur, COLOR_LED_PROTOCOL_DATA_LEN); + color_led_cur.open_status = open_status; + syscfg_write(VM_COLOR_LED_SETTING, (u8 *)&color_led_cur, COLOR_LED_PROTOCOL_DATA_LEN); + return; + } + + syscfg_write(VM_COLOR_LED_SETTING, color_led_setting_info, COLOR_LED_PROTOCOL_DATA_LEN); +} +// 2、同步对端 +static void color_led_setting_sync(u8 *color_led_setting_info) +{ +#if TCFG_USER_TWS_ENABLE + extern int get_bt_tws_connect_status(); + if (get_bt_tws_connect_status()) { + update_smartbox_setting(ATTR_TYPE_COLOR_LED_SETTING); + } +#endif +} + +static void color_led_flash(void) +{ + + color_led_t color_led_cur; + get_color_led_setting((u8 *)&color_led_cur); + if (!IS_COLOR_LED_LEGAL(color_led_cur)) { + printf("color led illegal data \n"); + return; + } + + u8 mode = 0; + u8 fre_mode = 0; + u32 color = 0; + + if (color_led_cur.open_status == OPEN_STATUS_CLOSE) { + mode = COLOR_LED_MODE_LIGHT; + color = COLOR_BLACK; + color_led_set_api(mode, fre_mode, color); + return; + } + + fre_mode = color_led_cur.fre_mode; + color = color_led_cur.red + ((int)color_led_cur.green << 8) + ((int)color_led_cur.blue << 16); + switch (color_led_cur.mode) { + case MODE_LIGHT: + mode = COLOR_LED_MODE_LIGHT; + break; + case MODE_TWINKLE: + if (color_led_cur.twinkle_mode == 0) { + mode = COLOR_LED_MODE_COLORFUL_TWINKLE; + } else { + mode = COLOR_LED_MODE_TWINKLE; + color = twinkle_color_table[color_led_cur.twinkle_mode - 1]; + } + break; + case MODE_USER: + mode = COLOR_LED_MODE_RAINBOW + color_led_cur.user_mode; + break; + default: + break; + } + + printf("mode:%d fre_mode:%d color:0x%x \n", mode, fre_mode, color); + color_led_set_api(mode, fre_mode, color); +} + +static void deal_color_led_setting(u8 *color_led_setting_info, u8 write_vm, u8 tws_sync) +{ + u8 led_setting[COLOR_LED_PROTOCOL_DATA_LEN]; + if (!color_led_setting_info) { + get_color_led_setting(led_setting); + } else { + memcpy(led_setting, color_led_setting_info, COLOR_LED_PROTOCOL_DATA_LEN); + set_color_led_setting(color_led_setting_info); + } + if (write_vm) { + update_color_led_setting_vm_value(led_setting); + } + if (tws_sync) { + color_led_setting_sync(led_setting); + } + + color_led_flash(); +} + +static int smartbox_color_led_init(void) +{ + color_led_t color_led_cur; + int len = syscfg_read(VM_COLOR_LED_SETTING, (u8 *)&color_led_cur, COLOR_LED_PROTOCOL_DATA_LEN); + + if ((!IS_COLOR_LED_LEGAL(color_led)) || (len != COLOR_LED_PROTOCOL_DATA_LEN)) { + printf("first time start device,reset color led data \n"); + memset((u8 *)&color_led_cur, 0x00, sizeof(color_led_cur)); + color_led_cur.open_status = OPEN_STATUS_SETTING; + color_led_cur.mode = MODE_USER; + color_led_cur.red = 64; + color_led_cur.green = 191; + color_led_cur.blue = 191; + color_led_cur.hue = 180; + color_led_cur.saturation = 50; + color_led_cur.lightness = 50; + color_led_set_api(COLOR_LED_MODE_RAINBOW + color_led_cur.user_mode, 0, 0); + syscfg_write(VM_COLOR_LED_SETTING, (u8 *)&color_led_cur, COLOR_LED_PROTOCOL_DATA_LEN); + color_led = color_led_cur; + } + + set_color_led_setting((u8 *)&color_led_cur); + deal_color_led_setting(NULL, 0, 0); + + return 0; +} + +static SMARTBOX_SETTING_OPT adv_color_led_opt = { + .data_len = COLOR_LED_PROTOCOL_DATA_LEN, + .setting_type = ATTR_TYPE_COLOR_LED_SETTING, + .syscfg_id = VM_COLOR_LED_SETTING, + .deal_opt_setting = deal_color_led_setting, + .set_setting = set_color_led_setting, + .get_setting = get_color_led_setting, + .custom_setting_init = smartbox_color_led_init, + .custom_vm_info_update = NULL, + .custom_setting_update = NULL, + .custom_sibling_setting_deal = NULL, + .custom_setting_release = NULL, +}; +REGISTER_APP_SETTING_OPT(adv_color_led_opt); + +#else + +u32 get_color_led_setting_data_len(void) +{ + return 0; +} +#endif +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/smartbox_eq_setting.c b/apps/soundbox/smartbox/smartbox_setting/smartbox_eq_setting.c new file mode 100644 index 0000000..136d5a1 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/smartbox_eq_setting.c @@ -0,0 +1,269 @@ +#include "app_config.h" +#include "syscfg_id.h" +#include "le_smartbox_module.h" + +#include "smartbox_setting_sync.h" +#include "smartbox_setting_opt.h" + +#if (TCFG_EQ_ENABLE && SMART_BOX_EN && RCSP_ADV_EQ_SET_ENABLE) + +#ifndef CONFIG_MEDIA_NEW_ENABLE +#include "application/eq_config.h" +#else +#include "audio_eq.h" +#endif + +/* extern int get_bt_tws_connect_status(); */ +/* extern int eq_mode_get_freq(u8 mode, u16 index); */ +/* extern s8 eq_mode_get_gain(u8 mode, u16 index); */ +/* extern int eq_mode_set_custom_param(u16 index, int gain); */ +/* extern int eq_mode_set(u8 mode); */ +/* extern int eq_mode_get_cur(void); */ + +static u8 g_eq_setting_info[11] = {0}; + +/* int __attribute__((weak)) eq_mode_get_freq(u8 mode, u16 index) */ +/* { */ +/* return 0; */ +/* } */ + +static void eq_setting_info_deal(u8 *eq_info_data) +{ + u8 data; + u8 status; + u8 mode; + if (eq_info_data[0] >> 7) { + status = eq_info_data[2]; + } else { + status = *(((u8 *)eq_info_data) + 1); + } + mode = eq_info_data[0] & 0x7F; + if (mode < EQ_MODE_CUSTOM) { + eq_mode_set(mode); + } else { + // 自定义修改EQ参数 + if (EQ_MODE_CUSTOM == mode) { + if (status != 0x7F) { + u8 i; + for (i = 0; i < EQ_SECTION_MAX; i++) { + if (eq_info_data[0] >> 7) { + data = eq_info_data[i + 2]; + } else { + data = eq_info_data[i + 1]; + } + eq_mode_set_custom_param(i, (s8)data); + } + } + eq_mode_set(mode); + } + } +} + +static void set_eq_setting(u8 *eq_setting) +{ + u8 i; + u8 eq_setting_mode = eq_setting[0]; + if (eq_setting_mode >> 7) { + // 多段eq + for (i = 2; i < eq_setting[1] + 2; i++) { + if ((eq_setting[i] > 12) && (eq_setting[i] < -12)) { + eq_setting[i] = 0; + } + } + } else { + // 10段eq + for (i = 1; i < 11; i++) { + if ((eq_setting[i] > 12) && (eq_setting[i] < -12)) { + eq_setting[i] = 0; + } + } + } + memcpy(g_eq_setting_info, eq_setting, 11); +} + +static int get_eq_setting(u8 *eq_setting) +{ + memcpy(eq_setting, g_eq_setting_info, 11); + return 0; +} + +// 1、写入VM +static void update_eq_vm_value(u8 *eq_setting) +{ + u8 status = *(((u8 *)eq_setting) + 1); + + syscfg_write(CFG_RCSP_ADV_EQ_MODE_SETTING, eq_setting, 1); + + /*自定义修改EQ参数*/ + if (EQ_MODE_CUSTOM == (eq_setting[0] & 0x7F)) { + if (eq_setting[0] >> 7) { + // 多段eq + status = eq_setting[2]; + } + if (status != 0x7F) { + syscfg_write(CFG_RCSP_ADV_EQ_DATA_SETTING, &eq_setting[1], 10); + } + } + +} +// 2、同步对端 +static void eq_sync(u8 *eq_setting) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_smartbox_setting(ATTR_TYPE_EQ_SETTING); + } +#endif +} + +static void deal_eq_setting(u8 *eq_setting, u8 write_vm, u8 tws_sync) +{ + u8 eq_info[11] = {0}; + if (!eq_setting) { + get_eq_setting(eq_info); + } else { + u8 status = *(((u8 *)eq_setting) + 1); + /*自定义修改EQ参数*/ + if (EQ_MODE_CUSTOM == (eq_setting[0] & 0x7F)) { + if (eq_setting[0] >> 7) { + status = eq_setting[2]; + } + + if (status != 0x7F) { + memcpy(eq_info, eq_setting, 11); + set_eq_setting(eq_info); + } else { + g_eq_setting_info[0] = eq_setting[0]; + get_eq_setting(eq_info); + } + } else { + memcpy(eq_info, eq_setting, 11); + g_eq_setting_info[0] = eq_setting[0]; + } + + } + if (write_vm) { + update_eq_vm_value(eq_info); + } + if (tws_sync) { + eq_sync(eq_info); + } + eq_setting_info_deal(eq_info); +} + + +static u8 app_get_eq_info(u8 *get_eq_info) +{ + u16 i; + get_eq_info[0] = eq_mode_get_cur(); + u8 data_len = 1; + + if (10 == EQ_SECTION_MAX) { + // 10段eq : mode + gain[10byte] + for (i = 0; i < 10; i++) { + get_eq_info[data_len] = eq_mode_get_gain(get_eq_info[0], i); + data_len++; + } + } else { + // 多段eq : mode + num + value(freq[2byte] + gain[1byte]) + get_eq_info[1] = EQ_SECTION_MAX; + data_len++; + for (i = 0; i < EQ_SECTION_MAX; i++) { + get_eq_info[data_len] = eq_mode_get_gain(get_eq_info[0], i); + data_len++; + } + get_eq_info[0] |= (1 << 7); + } + return data_len; +} + +static u8 app_get_eq_all_info(u8 *get_eq_info) +{ + u16 i; + u8 mode = EQ_MODE_NORMAL; + get_eq_info[0] = EQ_SECTION_MAX; + u8 data_len = 1; + // get freq + for (i = 0; i < EQ_SECTION_MAX; i++) { + u16 eq_freq = (u16)(eq_mode_get_freq(mode, i) & ((u16) - 1)); + eq_freq = ((((u8 *)&eq_freq)[0] << 8) + ((u8 *)&eq_freq)[1]); + memcpy(get_eq_info + data_len, &eq_freq, sizeof(eq_freq)); + data_len += 2; + } + // get gain + for (; mode < EQ_MODE_CUSTOM; mode++) { + get_eq_info[data_len] = mode; + if (10 != EQ_SECTION_MAX) { + get_eq_info[data_len] |= (1 << 7); + } + data_len++; + for (i = 0; i < EQ_SECTION_MAX; i++) { + u8 eq_gain = eq_mode_get_gain(mode, i); + get_eq_info[data_len] = eq_gain; + data_len++; + } + } + // get custom + get_eq_info[data_len] = EQ_MODE_CUSTOM; + if (10 != EQ_SECTION_MAX) { + get_eq_info[data_len] |= (1 << 7); + } + data_len++; + for (i = 0; i < EQ_SECTION_MAX; i++) { + if (10 == EQ_SECTION_MAX) { + get_eq_info[data_len] = g_eq_setting_info[i + 1]; + } else { + get_eq_info[data_len] = g_eq_setting_info[i + 2]; + } + data_len++; + } + + return data_len; +} + +static int eq_opt_init(void) +{ + u8 eq_setting_vm_info[11] = {0}; + u8 eq_setting_info[10] = {0}; + u8 eq_setting_mode = 0; + u8 i; + if (smartbox_read_data_from_vm(CFG_RCSP_ADV_EQ_DATA_SETTING, &eq_setting_info, sizeof(eq_setting_info))) { + if (smartbox_read_data_from_vm(CFG_RCSP_ADV_EQ_MODE_SETTING, &eq_setting_mode, sizeof(eq_setting_mode))) { + eq_setting_vm_info[0] = eq_setting_mode; + memcpy(&eq_setting_vm_info[1], eq_setting_info, 10); + set_eq_setting(eq_setting_vm_info); + deal_eq_setting(NULL, 0, 0); + } + } + return 0; +} + +static int eq_get_setting_extra_handle(void *setting_data, void *param) +{ + u16 data_len = *((u16 *) param); + if (data_len > sizeof(g_eq_setting_info)) { + data_len = app_get_eq_all_info(setting_data); + } else { + data_len = app_get_eq_info(setting_data); + } + return data_len; +} + +static SMARTBOX_SETTING_OPT eq_opt = { + .data_len = 11, + .setting_type = ATTR_TYPE_EQ_SETTING, + .syscfg_id = CFG_RCSP_ADV_EQ_DATA_SETTING, + .deal_opt_setting = deal_eq_setting, + .set_setting = set_eq_setting, + .get_setting = get_eq_setting, + .custom_setting_init = eq_opt_init, + .custom_vm_info_update = NULL, + .custom_setting_update = NULL, + .custom_sibling_setting_deal = NULL, + .custom_setting_release = NULL, + .set_setting_extra_handle = NULL, + .get_setting_extra_handle = eq_get_setting_extra_handle, +}; +REGISTER_APP_SETTING_OPT(eq_opt); + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/smartbox_high_low_vol_setting.c b/apps/soundbox/smartbox/smartbox_setting/smartbox_high_low_vol_setting.c new file mode 100644 index 0000000..c8932ad --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/smartbox_high_low_vol_setting.c @@ -0,0 +1,126 @@ +#include "app_config.h" +#include "syscfg_id.h" + +#include "smartbox_setting_sync.h" +#include "smartbox_setting_opt.h" +#include "le_smartbox_module.h" + +#include "JL_rcsp_protocol.h" + +#if (SMART_BOX_EN && RCSP_ADV_HIGH_LOW_SET && TCFG_AUDIO_OUT_EQ_ENABLE) +#include "audio_dec.h" + +struct _HIGH_LOW_VOL { + int low_vol; + int high_vol; +}; + +static struct _HIGH_LOW_VOL high_low_vol = { + .low_vol = 12, + .high_vol = 12, +}; + +extern int get_bt_tws_connect_status(); +extern int audio_out_eq_spec_set_gain(u8 idx, int gain); + +static int get_high_low_vol_info(u8 *vol_gain_param) +{ + memcpy(vol_gain_param, &high_low_vol, sizeof(struct _HIGH_LOW_VOL)); + return 0; +} + +static void set_high_low_vol_info(u8 *vol_gain_param) +{ + memcpy(&high_low_vol, vol_gain_param, sizeof(struct _HIGH_LOW_VOL)); +} + +static void update_high_low_vol_vm_value(u8 *vol_gain_param) +{ + syscfg_write(CFG_RCSP_ADV_HIGH_LOW_VOL, vol_gain_param, sizeof(struct _HIGH_LOW_VOL)); +} + +static void high_low_vol_setting_sync(u8 *vol_gain_param) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_smartbox_setting(ATTR_TYPE_HIGH_LOW_VOL); + } +#endif +} + +static void high_low_vol_state_update(void) +{ + static int low_vol = 0; + static int high_vol = 0; + struct high_bass param = {0}; + if (low_vol != high_low_vol.low_vol) { + param.gain = high_low_vol.low_vol - 12; + mix_out_high_bass(AUDIO_EQ_BASS, ¶m); + low_vol = high_low_vol.low_vol; + } + if (high_vol != high_low_vol.high_vol) { + param.gain = high_low_vol.high_vol - 12; + mix_out_high_bass(AUDIO_EQ_HIGH, ¶m); + high_vol = high_low_vol.high_vol; + } +} + +static void deal_high_low_vol(u8 *vol_gain_data, u8 write_vm, u8 tws_sync) +{ + if (vol_gain_data) { + set_high_low_vol_info(vol_gain_data); + printf("low %d, high %d\n", high_low_vol.low_vol, high_low_vol.high_vol); + } + if (write_vm) { + update_high_low_vol_vm_value((u8 *)&high_low_vol); + } + if (tws_sync) { + high_low_vol_setting_sync((u8 *)&high_low_vol); + } + high_low_vol_state_update(); +} + +static int high_low_set_setting_extra_handle(void *setting_data, void *param) +{ + high_low_vol.low_vol = READ_BIG_U32(setting_data) + 12; + high_low_vol.high_vol = READ_BIG_U32(setting_data + 4) + 12; + high_low_vol.low_vol = high_low_vol.low_vol > 24 ? 24 : high_low_vol.low_vol; + high_low_vol.low_vol = high_low_vol.low_vol < 0 ? 0 : high_low_vol.low_vol; + high_low_vol.high_vol = high_low_vol.high_vol > 24 ? 24 : high_low_vol.high_vol; + high_low_vol.high_vol = high_low_vol.high_vol < 0 ? 0 : high_low_vol.high_vol; + return 0; +} + +static int high_low_get_setting_extra_handle(void *setting_data, void *param) +{ + struct _HIGH_LOW_VOL gain_param = {0}; + gain_param.low_vol = high_low_vol.low_vol < 0 ? 0 : high_low_vol.low_vol; + gain_param.low_vol = high_low_vol.low_vol > 24 ? 24 : high_low_vol.low_vol; + gain_param.high_vol = high_low_vol.high_vol < 0 ? 0 : high_low_vol.high_vol; + gain_param.high_vol = high_low_vol.high_vol > 24 ? 24 : high_low_vol.high_vol; + gain_param.low_vol -= 12; + gain_param.high_vol -= 12; + gain_param.low_vol = READ_BIG_U32((u8 *)&gain_param.low_vol); + gain_param.high_vol = READ_BIG_U32((u8 *)&gain_param.high_vol); + memcpy(setting_data, &gain_param, sizeof(gain_param)); + return sizeof(gain_param); +} + +static SMARTBOX_SETTING_OPT high_low_vol_opt = { + .data_len = 8, + .setting_type = ATTR_TYPE_HIGH_LOW_VOL, + .syscfg_id = CFG_RCSP_ADV_HIGH_LOW_VOL, + .deal_opt_setting = deal_high_low_vol, + .set_setting = set_high_low_vol_info, + .get_setting = get_high_low_vol_info, + .custom_setting_init = NULL, + .custom_setting_release = NULL, + .custom_vm_info_update = NULL, + .custom_setting_update = NULL, + .custom_sibling_setting_deal = NULL, + .set_setting_extra_handle = high_low_set_setting_extra_handle, + .get_setting_extra_handle = high_low_get_setting_extra_handle, +}; +REGISTER_APP_SETTING_OPT(high_low_vol_opt); + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/smartbox_karaoke_eq_setting.c b/apps/soundbox/smartbox/smartbox_setting/smartbox_karaoke_eq_setting.c new file mode 100644 index 0000000..5f57495 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/smartbox_karaoke_eq_setting.c @@ -0,0 +1,133 @@ +#include "app_config.h" +#include "syscfg_id.h" +#include "le_smartbox_module.h" + +#include "smartbox_setting_sync.h" +#include "smartbox_setting_opt.h" + +#if (TCFG_EQ_ENABLE && MIC_EFFECT_EQ_EN && SMART_BOX_EN && RCSP_ADV_KARAOKE_EQ_SET_ENABLE && RCSP_ADV_KARAOKE_SET_ENABLE) + +#include "effect_cfg.h" +#include "effect_tool.h" +#include "mic_effect.h" + +static u8 g_karaoke_setting_info[9] = {EFFECT_EQ_SECTION_MAX, 0}; + +static void update_eq_setting_info(u8 *eq_info_data) +{ + // 更新卡拉ok的EQ值 + struct eq_seg_info *eq_info = NULL; + for (u8 i = 0; i < EFFECT_EQ_SECTION_MAX; i++) { + eq_info = mic_eq_get_info(i); + s8 gain = g_karaoke_setting_info[i + 1]; + if (gain != (eq_info->gain >> 20)) { + eq_info->gain = gain << 20; + mic_eq_set_info(eq_info); + } + } +} + +static void set_karaoke_eq_setting(u8 *eq_setting) +{ + memcpy(g_karaoke_setting_info, eq_setting, sizeof(g_karaoke_setting_info)); +} + +static int get_karaoke_eq_setting(u8 *eq_setting) +{ + memcpy(eq_setting, g_karaoke_setting_info, sizeof(g_karaoke_setting_info)); + return sizeof(g_karaoke_setting_info); +} + +// 1、写入VM +static void update_karaoke_eq_vm_value(u8 *eq_setting) +{ + syscfg_write(VM_KARAOKE_EQ_SETTING, g_karaoke_setting_info, 9); +} + +// 2、同步对端 +static void karaoke_eq_sync(u8 *eq_setting) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_smartbox_setting(ATTR_TYPE_KARAOKE_EQ_SETTING); + } +#endif +} + +static void deal_karaoke_eq_setting(u8 *eq_setting, u8 write_vm, u8 tws_sync) +{ + if (eq_setting) { + set_karaoke_eq_setting(eq_setting); + } + if (write_vm) { + update_karaoke_eq_vm_value(eq_setting); + } + if (tws_sync) { + karaoke_eq_sync(eq_setting); + } + update_eq_setting_info(eq_setting); +} + +// 0 - gain +// 1 - freq +static u8 get_karaoke_eq_info(u8 *get_eq_info, u8 type) +{ + u8 i; + u8 data_len = 1; + struct eq_seg_info *eq_info = NULL; + get_eq_info[0] = EFFECT_EQ_SECTION_MAX; + for (i = 0; i < EFFECT_EQ_SECTION_MAX; i++) { + eq_info = mic_eq_get_info(i); + if (type) { + u16 eq_freq = eq_info->freq; + eq_freq = ((((u8 *)&eq_freq)[0] << 8) + ((u8 *)&eq_freq)[1]); + memcpy(get_eq_info + data_len, &eq_freq, sizeof(eq_freq)); + data_len += sizeof(eq_freq); + } else { + u8 eq_gain = (eq_info->gain >> 20) & 0xFF; + memcpy(get_eq_info + data_len, &eq_gain, sizeof(eq_gain)); + data_len += sizeof(eq_gain); + } + } + + return data_len; +} + +static u8 get_karaoke_eq_all_freq_info(u8 *get_eq_info) +{ + return get_karaoke_eq_info(get_eq_info, 1); +} + +static u8 get_karoke_eq_all_gain_info(u8 *get_eq_info) +{ + return get_karaoke_eq_info(get_eq_info, 0); +} + +static int karaoke_eq_get_setting_extra_handle(void *setting_data, void *param) +{ + u16 data_len = *((u16 *) param); + if (data_len > sizeof(g_karaoke_setting_info)) { + data_len = get_karaoke_eq_all_freq_info(setting_data); + } else { + data_len = get_karaoke_eq_setting(setting_data); + } + return data_len; +} + +static SMARTBOX_SETTING_OPT karaoke_eq_opt = { + .data_len = 9, + .setting_type = ATTR_TYPE_KARAOKE_EQ_SETTING, + .syscfg_id = VM_KARAOKE_EQ_SETTING, + .deal_opt_setting = deal_karaoke_eq_setting, + .set_setting = set_karaoke_eq_setting, + .get_setting = get_karaoke_eq_setting, + .custom_vm_info_update = NULL, + .custom_setting_update = NULL, + .custom_sibling_setting_deal = NULL, + .custom_setting_release = NULL, + .set_setting_extra_handle = NULL, + .get_setting_extra_handle = karaoke_eq_get_setting_extra_handle, +}; +REGISTER_APP_SETTING_OPT(karaoke_eq_opt); + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/smartbox_karaoke_setting.c b/apps/soundbox/smartbox/smartbox_setting/smartbox_karaoke_setting.c new file mode 100644 index 0000000..6ca4e70 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/smartbox_karaoke_setting.c @@ -0,0 +1,598 @@ +#include "smartbox/config.h" +#include "syscfg_id.h" +#include "le_smartbox_module.h" + +#include "smartbox_setting_sync.h" +#include "smartbox_setting_opt.h" +#include "smartbox/function.h" + +#if (SOUNDCARD_ENABLE && SMART_BOX_EN && RCSP_ADV_KARAOKE_SET_ENABLE) + +#include "key_event_deal.h" +#include "mic_effect.h" +#include "JL_rcsp_packet.h" +#include "soundcard/soundcard.h" + +// mask : 8byte +// 音效 : index(1byte) + value(2byte) +// 气氛 : index(1byte) + value(2byte) +// 参数 : [index(1byte) + value(2byte)] * 7 +#define KARAOKE_SETTING_SIZE (8 + ((1 + 2) * 2) + ((1 + 2) * 7)) +#define KARAOKE_SETTING_ATMOSPHERE_TYPE_SET 0 + +enum karaoke_setting_index { + // 音效 + KARAOKE_SETTING_SOUND_EFFECT_NORMAL = 0, + KARAOKE_SETTING_SOUND_EFFECT_BOY = 1, + KARAOKE_SETTING_SOUND_EFFECT_GRIL = 2, + KARAOKE_SETTING_SOUND_EFFECT_KIDS = 3, + KARAOKE_SETTING_SOUND_EFFECT_MAGIC = 4, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_A_MAJOR = 5, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Ashop_MAJOR = 6, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_B_MAJOR = 7, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_C_MAJOR = 8, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Cshop_MAJOR = 9, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_D_MAJOR = 10, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Dshop_MAJOR = 11, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_E_MAJOR = 12, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_F_MAJOR = 13, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Fshop_MAJOR = 14, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_G_MAJOR = 15, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Gshop_MAJOR = 16, + // 气氛 + KARAOKE_SETTING_ATMOSPHERE_CHEERS = 17, + KARAOKE_SETTING_ATMOSPHERE_EMBARRASSED = 18, + KARAOKE_SETTING_ATMOSPHERE_GUNFIRE = 19, + KARAOKE_SETTING_ATMOSPHERE_DESPISE = 20, + KARAOKE_SETTING_ATMOSPHERE_OPEN = 21, + KARAOKE_SETTING_ATMOSPHERE_KISS = 22, + KARAOKE_SETTING_ATMOSPHERE_LAUGHTER = 23, + KARAOKE_SETTING_ATMOSPHERE_APPLAUSE = 24, + KARAOKE_SETTING_ATMOSPHERE_PAY_ATTENTION_TO = 25, + KARAOKE_SETTING_ATMOSPHERE_MUA = 26, + KARAOKE_SETTING_ATMOSPHERE_A_THIEF = 27, + KARAOKE_SETTING_ATMOSPHERE_IF_YOU_ARE_THE_ONE = 28, + // 参数 + KARAOKE_SETTING_MIC_PARAM_MIC_VOL = 29, + KARAOKE_SETTING_MIC_PARAM_RECORD_VOL = 30, + KARAOKE_SETTING_MIC_PARAM_REVERBERATION = 31, + KARAOKE_SETTING_MIC_PARAM_HIGH = 32, + KARAOKE_SETTING_MIC_PARAM_BASS = 33, + KARAOKE_SETTING_MIC_PARAM_ACCOMPANIMENT_VOL = 34, + KARAOKE_SETTING_MIC_PARAM_MONITOR_VOL = 35, + // 其他 + KARAOKE_SETTING_OTHER_EFFECT_POPPING = 36, + KARAOKE_SETTING_OTHER_EFFECT_SHOUT = 37, + KARAOKE_SETTING_OTHER_EFFECT_DODGE = 38, + + KARAOKE_SETTING_INDEX_END, +}; + +enum { + APP_PITCH_NONE = 0, + APP_PITCH_BOY, + APP_PITCH_GIRL, + APP_PITCH_KIDS, + APP_PITCH_MAGIC, + /* 电音 */ + APP_SOUNDCARD_MODE_ELECTRIC_A_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_Ashop_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_B_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_C_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_Cshop_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_D_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_Dshop_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_E_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_F_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_Fshop_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_G_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_Gshop_MAJOR, + + APP_SOUNDCARD_MODE_BOOM, // 爆音 + APP_SOUNDCARD_MODE_SHOUTING_WHEAT, // 喊麦 + APP_SOUNDCARD_MODE_DODGE, // 闪避 +}; + +const static u8 g_mutex_type_table[] = { + KARAOKE_SETTING_SOUND_EFFECT_NORMAL, + KARAOKE_SETTING_SOUND_EFFECT_BOY, + KARAOKE_SETTING_SOUND_EFFECT_GRIL, + KARAOKE_SETTING_SOUND_EFFECT_KIDS, + KARAOKE_SETTING_SOUND_EFFECT_MAGIC, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_A_MAJOR, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Ashop_MAJOR, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_B_MAJOR, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_C_MAJOR, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Cshop_MAJOR, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_D_MAJOR, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Dshop_MAJOR, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_E_MAJOR, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_F_MAJOR, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Fshop_MAJOR, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_G_MAJOR, + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_Gshop_MAJOR, + KARAOKE_SETTING_OTHER_EFFECT_POPPING, + KARAOKE_SETTING_OTHER_EFFECT_SHOUT +}; + +const static u8 g_atmosphere_type_table[] = { + KARAOKE_SETTING_ATMOSPHERE_CHEERS, + KARAOKE_SETTING_ATMOSPHERE_EMBARRASSED, + KARAOKE_SETTING_ATMOSPHERE_GUNFIRE, + KARAOKE_SETTING_ATMOSPHERE_DESPISE, + KARAOKE_SETTING_ATMOSPHERE_OPEN, + KARAOKE_SETTING_ATMOSPHERE_KISS, + KARAOKE_SETTING_ATMOSPHERE_LAUGHTER, + KARAOKE_SETTING_ATMOSPHERE_APPLAUSE, + KARAOKE_SETTING_ATMOSPHERE_PAY_ATTENTION_TO, + KARAOKE_SETTING_ATMOSPHERE_MUA, + KARAOKE_SETTING_ATMOSPHERE_A_THIEF, + KARAOKE_SETTING_ATMOSPHERE_IF_YOU_ARE_THE_ONE +}; + +const static u8 g_common_type_table[] = { + KARAOKE_SETTING_OTHER_EFFECT_DODGE +}; + +const static u8 g_value_type_table[] = { + KARAOKE_SETTING_MIC_PARAM_MIC_VOL, + KARAOKE_SETTING_MIC_PARAM_RECORD_VOL, + KARAOKE_SETTING_MIC_PARAM_REVERBERATION, + KARAOKE_SETTING_MIC_PARAM_HIGH, + KARAOKE_SETTING_MIC_PARAM_BASS, + KARAOKE_SETTING_MIC_PARAM_ACCOMPANIMENT_VOL, + KARAOKE_SETTING_MIC_PARAM_MONITOR_VOL +}; + +#pragma pack(1) +typedef struct { + u8 mask[8]; + u8 mic_vol_index; + u16 mic_vol_value; + u8 mic_record_index; + u16 mic_record_value; + u8 mic_reververation_index; + u16 mic_reververation_value; + u8 mic_high_index; + u16 mic_high_value; + u8 mic_low_index; + u16 mic_low_value; + u8 mic_accompaniment_index; + u16 mic_accompaniment_value; + u8 mic_moitor_index; + u16 mic_moitor_value; +} karaoke_setting; +#pragma pack() + +static u8 g_update_index_record = -1; +static karaoke_setting g_karaoke_setting = {0}; + +extern u8 get_curr_soundcard_pitch_by_value(void); +extern u8 get_curr_soundcard_pitch(void); +extern u8 curr_soundcard_mode_is_normal(void); + +static void karaoke_setting_mask_set_bit(u8 *mask, u8 index, u8 type) +{ + if (type) { + mask[index / 8] |= BIT(index % 8); + } else { + mask[index / 8] &= ~BIT(index % 8); + } +} + +static int karaoke_setting_setting_init(void) +{ + // 不读VM + // 需要从接口获取初始值并填充 + // mic_vol_index + g_karaoke_setting.mic_vol_index = KARAOKE_SETTING_MIC_PARAM_MIC_VOL; + g_karaoke_setting.mic_vol_value = soundcard_get_mic_vol(); + + // mic_record_index + g_karaoke_setting.mic_record_index = KARAOKE_SETTING_MIC_PARAM_RECORD_VOL; + g_karaoke_setting.mic_record_value = soundcard_get_rec_vol(); + + // mic_reververation_index + g_karaoke_setting.mic_reververation_index = KARAOKE_SETTING_MIC_PARAM_REVERBERATION; + g_karaoke_setting.mic_reververation_value = soundcard_get_reverb_wet_vol(); + + // mic_high_index + g_karaoke_setting.mic_high_index = KARAOKE_SETTING_MIC_PARAM_HIGH; + g_karaoke_setting.mic_high_value = soundcard_get_high_sound_vol(); + + // mic_low_index + g_karaoke_setting.mic_low_index = KARAOKE_SETTING_MIC_PARAM_BASS; + g_karaoke_setting.mic_low_value = soundcard_get_low_sound_vol(); + + // mic_accompaniment_index + g_karaoke_setting.mic_accompaniment_index = KARAOKE_SETTING_MIC_PARAM_ACCOMPANIMENT_VOL; + g_karaoke_setting.mic_accompaniment_value = soundcard_get_music_vol(); + + // mic_moitor_index + g_karaoke_setting.mic_moitor_index = KARAOKE_SETTING_MIC_PARAM_MONITOR_VOL; + g_karaoke_setting.mic_moitor_value = soundcard_get_earphone_vol(); + + // effect_index + karaoke_setting_mask_set_bit(g_karaoke_setting.mask, KARAOKE_SETTING_SOUND_EFFECT_NORMAL, 1); + + // atomsphere_index +#if KARAOKE_SETTING_ATMOSPHERE_TYPE_SET + karaoke_setting_mask_set_bit(g_karaoke_setting.mask, KARAOKE_SETTING_ATMOSPHERE_CHEERS, 1); +#endif + + return 0; +} + +static void set_karaoke_setting_setting(u8 *karaoke_setting) +{ + memcpy(&g_karaoke_setting, karaoke_setting, sizeof(g_karaoke_setting)); +} + +static int get_karaoke_setting_setting(u8 *karaoke_setting) +{ + memcpy(karaoke_setting, &g_karaoke_setting, sizeof(g_karaoke_setting)); + return sizeof(g_karaoke_setting); +} + +static int karaoke_setting_set_value(u8 *data, u8 index, u16 value) +{ + int offset = 0; + data[offset++] = index; + data[offset++] = ((u8 *)&value)[1]; + data[offset++] = ((u8 *)&value)[0]; + return offset; +} + +static int karaoke_get_setting_extra_handle(void *karaoke_setting, void *param) +{ + // 全局变量g_karaoke_setting已经把值都存好,只需要进行大小端转化即可 + int offset = 0; + u8 *data = (u8 *)karaoke_setting; + for (; offset < sizeof(g_karaoke_setting.mask); offset ++) { + data[sizeof(g_karaoke_setting.mask) - offset - 1] = g_karaoke_setting.mask[offset]; + } + + if ((u8) - 1 == g_update_index_record) { + // mic_vol_value + offset += karaoke_setting_set_value(data + offset, g_karaoke_setting.mic_vol_index, g_karaoke_setting.mic_vol_value); + // mic_record_value + offset += karaoke_setting_set_value(data + offset, g_karaoke_setting.mic_record_index, g_karaoke_setting.mic_record_value); + // mic_reververation_value + offset += karaoke_setting_set_value(data + offset, g_karaoke_setting.mic_reververation_index, g_karaoke_setting.mic_reververation_value); + // mic_high_value + offset += karaoke_setting_set_value(data + offset, g_karaoke_setting.mic_high_index, g_karaoke_setting.mic_high_value); + // mic_low_value + offset += karaoke_setting_set_value(data + offset, g_karaoke_setting.mic_low_index, g_karaoke_setting.mic_low_value); + // mic_accompaniment_value + offset += karaoke_setting_set_value(data + offset, g_karaoke_setting.mic_accompaniment_index, g_karaoke_setting.mic_accompaniment_value); + // mic_moitor_value + offset += karaoke_setting_set_value(data + offset, g_karaoke_setting.mic_moitor_index, g_karaoke_setting.mic_moitor_value); + } else { + switch (g_update_index_record) { + case KARAOKE_SETTING_MIC_PARAM_MIC_VOL: + offset += karaoke_setting_set_value(data + offset, g_update_index_record, g_karaoke_setting.mic_vol_value); + break; + case KARAOKE_SETTING_MIC_PARAM_RECORD_VOL: + offset += karaoke_setting_set_value(data + offset, g_update_index_record, g_karaoke_setting.mic_record_value); + break; + case KARAOKE_SETTING_MIC_PARAM_REVERBERATION: + offset += karaoke_setting_set_value(data + offset, g_update_index_record, g_karaoke_setting.mic_reververation_value); + break; + case KARAOKE_SETTING_MIC_PARAM_HIGH: + offset += karaoke_setting_set_value(data + offset, g_update_index_record, g_karaoke_setting.mic_high_value); + break; + case KARAOKE_SETTING_MIC_PARAM_BASS: + offset += karaoke_setting_set_value(data + offset, g_update_index_record, g_karaoke_setting.mic_low_value); + break; + case KARAOKE_SETTING_MIC_PARAM_ACCOMPANIMENT_VOL: + offset += karaoke_setting_set_value(data + offset, g_update_index_record, g_karaoke_setting.mic_accompaniment_value); + break; + case KARAOKE_SETTING_MIC_PARAM_MONITOR_VOL: + offset += karaoke_setting_set_value(data + offset, g_update_index_record, g_karaoke_setting.mic_moitor_value); + break; + } + g_update_index_record = -1; + } + return offset; +} + +static bool karaoke_setting_table_check(u8 index, u8 *table, u8 table_len) +{ + for (u8 i = 0; i < table_len; i++) { + if (index == table[i]) { + return true; + } + } + return false; +} + +static bool karaoke_setting_mask_set(u8 index, u8 *table, u8 table_len) +{ + if (karaoke_setting_table_check(index, table, table_len)) { + for (u8 i = 0; i < table_len; i++) { + karaoke_setting_mask_set_bit(g_karaoke_setting.mask, table[i], 0); + } + karaoke_setting_mask_set_bit(g_karaoke_setting.mask, index, 1); + return true; + } + return false; +} + +static int karaoke_set_setting_extra_handle(void *karaoke_setting, void *param) +{ + u16 data_len = *((u16 *) param) - 1; + u8 *data = (u8 *) karaoke_setting; + u8 i = 0; + while (i < data_len) { + u8 index = data[i++]; + u16 value = data[i++] << 8 | data[i++]; + karaoke_setting_mask_set(index, g_mutex_type_table, sizeof(g_mutex_type_table)); +#if KARAOKE_SETTING_ATMOSPHERE_TYPE_SET + karaoke_setting_mask_set(index, g_atmosphere_type_table, sizeof(g_atmosphere_type_table)); +#endif + if (karaoke_setting_table_check(index, g_common_type_table, sizeof(g_common_type_table))) { + karaoke_setting_mask_set_bit(g_karaoke_setting.mask, index, 1); + } + karaoke_setting_mask_set(index, g_value_type_table, sizeof(g_value_type_table)); + g_update_index_record = index; + switch (index) { + case KARAOKE_SETTING_MIC_PARAM_MIC_VOL: + g_karaoke_setting.mic_vol_index = index; + g_karaoke_setting.mic_vol_value = value; + break; + case KARAOKE_SETTING_MIC_PARAM_RECORD_VOL: + g_karaoke_setting.mic_record_index = index; + g_karaoke_setting.mic_record_value = value; + break; + case KARAOKE_SETTING_MIC_PARAM_REVERBERATION: + g_karaoke_setting.mic_reververation_index = index; + g_karaoke_setting.mic_reververation_value = value; + break; + case KARAOKE_SETTING_MIC_PARAM_HIGH: + g_karaoke_setting.mic_high_index = index; + g_karaoke_setting.mic_high_value = value; + break; + case KARAOKE_SETTING_MIC_PARAM_BASS: + g_karaoke_setting.mic_low_index = index; + g_karaoke_setting.mic_low_value = value; + break; + case KARAOKE_SETTING_MIC_PARAM_ACCOMPANIMENT_VOL: + g_karaoke_setting.mic_accompaniment_index = index; + g_karaoke_setting.mic_accompaniment_value = value; + break; + case KARAOKE_SETTING_MIC_PARAM_MONITOR_VOL: + g_karaoke_setting.mic_moitor_index = index; + g_karaoke_setting.mic_moitor_value = value; + break; + } + } + return 0; +} + +static void update_karaoke_setting_vm_value(u8 *karaoke_setting) +{ + // 不写VM +} + +static void karaoke_setting_sync(u8 *color_led_setting_info) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_smartbox_setting(ATTR_TYPE_KARAOKE_SETTING); + } +#endif +} + +static void karaoke_setting_update(void) +{ + switch (g_update_index_record) { + case KARAOKE_SETTING_MIC_PARAM_MIC_VOL: + app_task_put_key_msg(KEY_SOUNDCARD_SLIDE_MIC, g_karaoke_setting.mic_vol_value); + break; + case KARAOKE_SETTING_MIC_PARAM_RECORD_VOL: + app_task_put_key_msg(KEY_SOUNDCARD_SLIDE_RECORD_VOL, g_karaoke_setting.mic_record_value); + break; + case KARAOKE_SETTING_MIC_PARAM_REVERBERATION: + app_task_put_key_msg(KEY_SOUNDCARD_SLIDE_WET_GAIN, g_karaoke_setting.mic_reververation_value); + break; + case KARAOKE_SETTING_MIC_PARAM_HIGH: + app_task_put_key_msg(KEY_SOUNDCARD_SLIDE_HIGH_SOUND, g_karaoke_setting.mic_high_value); + break; + case KARAOKE_SETTING_MIC_PARAM_BASS: + app_task_put_key_msg(KEY_SOUNDCARD_SLIDE_LOW_SOUND, g_karaoke_setting.mic_low_value); + break; + case KARAOKE_SETTING_MIC_PARAM_ACCOMPANIMENT_VOL: + app_task_put_key_msg(KEY_SOUNDCARD_SLIDE_MUSIC_VOL, g_karaoke_setting.mic_accompaniment_value); + break; + case KARAOKE_SETTING_MIC_PARAM_MONITOR_VOL: + app_task_put_key_msg(KEY_SOUNDCARD_SLIDE_EARPHONE_VOL, g_karaoke_setting.mic_moitor_value); + break; + case KARAOKE_SETTING_OTHER_EFFECT_POPPING: + app_task_put_key_msg(KEY_SOUNDCARD_MODE_BOOM, 0); + break; + case KARAOKE_SETTING_SOUND_EFFECT_MAGIC: + app_task_put_key_msg(KEY_SOUNDCARD_MODE_MAGIC, 0); + break; + case KARAOKE_SETTING_OTHER_EFFECT_SHOUT: + app_task_put_key_msg(KEY_SOUNDCARD_MODE_SHOUTING_WHEAT, 0); + break; + case KARAOKE_SETTING_OTHER_EFFECT_DODGE: + app_task_put_key_msg(KEY_SOUNDCARD_MODE_DODGE, 0); + break; + default: + if (karaoke_setting_table_check(g_update_index_record, g_mutex_type_table, sizeof(g_mutex_type_table))) { + app_task_put_key_msg(KEY_SOUNDCARD_MODE_PITCH_BY_VALUE, g_update_index_record); + break; + } else if (karaoke_setting_table_check(g_update_index_record, g_atmosphere_type_table, sizeof(g_atmosphere_type_table))) { + app_task_put_key_msg(KEY_SOUNDCARD_MAKE_NOISE0 + g_update_index_record - KARAOKE_SETTING_ATMOSPHERE_CHEERS, 0); + break; + } + break; + } + /* g_update_index_record = -1; */ + +} + + +static void deal_karaoke_setting(u8 *karaoke_setting, u8 write_vm, u8 tws_sync) +{ + if (karaoke_setting) { + set_karaoke_setting_setting(karaoke_setting); + } + if (write_vm) { + update_karaoke_setting_vm_value(karaoke_setting); + } + if (tws_sync) { + karaoke_setting_sync(karaoke_setting); + } + karaoke_setting_update(); +} + +static int karaoke_setting_key_event_update(int event, void *param) +{ + int ret = false; + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL || 0 == JL_rcsp_get_auth_flag()) { + return ret; + } + switch (event) { + case KEY_SOUNDCARD_MAKE_NOISE0: + case KEY_SOUNDCARD_MAKE_NOISE1: + case KEY_SOUNDCARD_MAKE_NOISE2: + case KEY_SOUNDCARD_MAKE_NOISE3: + case KEY_SOUNDCARD_MAKE_NOISE4: + case KEY_SOUNDCARD_MAKE_NOISE5: + case KEY_SOUNDCARD_MAKE_NOISE6: + case KEY_SOUNDCARD_MAKE_NOISE7: + case KEY_SOUNDCARD_MAKE_NOISE8: + case KEY_SOUNDCARD_MAKE_NOISE9: + case KEY_SOUNDCARD_MAKE_NOISE10: + case KEY_SOUNDCARD_MAKE_NOISE11: + g_update_index_record = KARAOKE_SETTING_ATMOSPHERE_CHEERS + event - KEY_SOUNDCARD_MAKE_NOISE0; +#if KARAOKE_SETTING_ATMOSPHERE_TYPE_SET + karaoke_setting_mask_set(g_update_index_record, g_atmosphere_type_table, sizeof(g_atmosphere_type_table)); +#endif + ret = true; + break; + case KEY_SOUNDCARD_MODE_PITCH: + g_update_index_record = get_curr_soundcard_pitch(); + karaoke_setting_mask_set(g_update_index_record, g_mutex_type_table, sizeof(g_mutex_type_table)); + ret = true; + break; + case KEY_SOUNDCARD_MODE_PITCH_BY_VALUE: + g_update_index_record = get_curr_soundcard_pitch_by_value(); + switch (g_update_index_record) { + case APP_SOUNDCARD_MODE_BOOM: + karaoke_setting_mask_set(KARAOKE_SETTING_OTHER_EFFECT_POPPING, g_mutex_type_table, sizeof(g_mutex_type_table)); + break; + case APP_SOUNDCARD_MODE_SHOUTING_WHEAT: + karaoke_setting_mask_set(KARAOKE_SETTING_OTHER_EFFECT_SHOUT, g_mutex_type_table, sizeof(g_mutex_type_table)); + break; + default: + if (g_update_index_record >= APP_SOUNDCARD_MODE_ELECTRIC_A_MAJOR && g_update_index_record <= APP_SOUNDCARD_MODE_ELECTRIC_Gshop_MAJOR) { + karaoke_setting_mask_set(g_update_index_record - APP_SOUNDCARD_MODE_ELECTRIC_A_MAJOR + KARAOKE_SETTING_SOUND_EFFECT_ELECTRIC_A_MAJOR, g_mutex_type_table, sizeof(g_mutex_type_table)); + break; + } + karaoke_setting_mask_set(g_update_index_record, g_mutex_type_table, sizeof(g_mutex_type_table)); + break; + } + ret = true; + break; + case KEY_SOUNDCARD_MODE_BOOM: + g_update_index_record = KARAOKE_SETTING_OTHER_EFFECT_POPPING; + karaoke_setting_mask_set(g_update_index_record, g_mutex_type_table, sizeof(g_mutex_type_table)); + if (curr_soundcard_mode_is_normal()) { + karaoke_setting_mask_set_bit(g_karaoke_setting.mask, g_update_index_record, 0); + } + ret = true; + break; + case KEY_SOUNDCARD_MODE_SHOUTING_WHEAT: + g_update_index_record = KARAOKE_SETTING_OTHER_EFFECT_SHOUT; + karaoke_setting_mask_set(g_update_index_record, g_mutex_type_table, sizeof(g_mutex_type_table)); + if (curr_soundcard_mode_is_normal()) { + karaoke_setting_mask_set_bit(g_karaoke_setting.mask, g_update_index_record, 0); + } + ret = true; + case KEY_SOUNDCARD_MODE_DODGE: + g_update_index_record = KARAOKE_SETTING_OTHER_EFFECT_DODGE; + if (mic_dodge_get_status()) { + karaoke_setting_mask_set_bit(g_karaoke_setting.mask, g_update_index_record, 1); + } else { + karaoke_setting_mask_set_bit(g_karaoke_setting.mask, g_update_index_record, 0); + } + ret = true; + break; + case KEY_SOUNDCARD_MODE_ELECTRIC: + g_update_index_record = get_curr_soundcard_pitch_by_value(); + karaoke_setting_mask_set(g_update_index_record, g_mutex_type_table, sizeof(g_mutex_type_table)); + ret = true; + break; + case KEY_SOUNDCARD_MODE_MAGIC: + g_update_index_record = KARAOKE_SETTING_SOUND_EFFECT_MAGIC; + karaoke_setting_mask_set(g_update_index_record, g_mutex_type_table, sizeof(g_mutex_type_table)); + if (curr_soundcard_mode_is_normal()) { + karaoke_setting_mask_set_bit(g_karaoke_setting.mask, g_update_index_record, 0); + } + ret = true; + break; + case KEY_SOUNDCARD_SLIDE_MIC: + g_update_index_record = KARAOKE_SETTING_MIC_PARAM_MIC_VOL; + g_karaoke_setting.mic_vol_value = soundcard_get_mic_vol(); + ret = true; + break; + case KEY_SOUNDCARD_SLIDE_LOW_SOUND: + g_update_index_record = KARAOKE_SETTING_MIC_PARAM_BASS; + // 更新对应全局变量 + g_karaoke_setting.mic_low_value = soundcard_get_low_sound_vol(); + ret = true; + break; + case KEY_SOUNDCARD_SLIDE_HIGH_SOUND: + g_update_index_record = KARAOKE_SETTING_MIC_PARAM_HIGH; + // 更新对应全局变量 + g_karaoke_setting.mic_high_value = soundcard_get_high_sound_vol(); + ret = true; + break; + case KEY_SOUNDCARD_SLIDE_WET_GAIN: + g_update_index_record = KARAOKE_SETTING_MIC_PARAM_REVERBERATION; + g_karaoke_setting.mic_reververation_value = soundcard_get_reverb_wet_vol(); + ret = true; + break; + case KEY_SOUNDCARD_SLIDE_RECORD_VOL: + g_update_index_record = KARAOKE_SETTING_MIC_PARAM_RECORD_VOL; + // 更新对应全局变量 + g_karaoke_setting.mic_record_value = soundcard_get_rec_vol(); + ret = true; + break; + case KEY_SOUNDCARD_SLIDE_MUSIC_VOL: + g_update_index_record = KARAOKE_SETTING_MIC_PARAM_ACCOMPANIMENT_VOL; + // 更新对应全局变量 + g_karaoke_setting.mic_accompaniment_value = soundcard_get_music_vol(); + ret = true; + break; + case KEY_SOUNDCARD_SLIDE_EARPHONE_VOL: + g_update_index_record = KARAOKE_SETTING_MIC_PARAM_MONITOR_VOL; + // 更新对应全局变量 + g_karaoke_setting.mic_moitor_value = soundcard_get_earphone_vol(); + ret = true; + break; + } + if (ret) { + SMARTBOX_UPDATE(COMMON_FUNCTION, BIT(COMMON_FUNCTION_ATTR_TYPE_KARAOKE_SETTING_INFO)); + } + return ret; +} + +static SMARTBOX_SETTING_OPT karaoke_setting_opt = { + .data_len = KARAOKE_SETTING_SIZE, + .setting_type = ATTR_TYPE_KARAOKE_SETTING, + .deal_opt_setting = deal_karaoke_setting, + .set_setting = set_karaoke_setting_setting, + .get_setting = get_karaoke_setting_setting, + .custom_setting_init = karaoke_setting_setting_init, + .set_setting_extra_handle = karaoke_set_setting_extra_handle, + .get_setting_extra_handle = karaoke_get_setting_extra_handle, + .custom_setting_key_event_update = karaoke_setting_key_event_update, +}; +REGISTER_APP_SETTING_OPT(karaoke_setting_opt); + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_drc_setting.c b/apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_drc_setting.c new file mode 100644 index 0000000..abcdb38 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_drc_setting.c @@ -0,0 +1,64 @@ +#include "app_config.h" +#include "syscfg_id.h" + +#include "smartbox_misc_setting.h" +#include "le_smartbox_module.h" + +#if (SMART_BOX_EN && SMARTBOX_DRC_VAL_SETTING && TCFG_AUDIO_OUT_EQ_ENABLE && TCFG_DRC_ENABLE && TCFG_AUDIO_OUT_DRC_ENABLE && RCSP_ADV_EQ_SET_ENABLE) +#include "audio_dec.h" + +extern int high_bass_drc_set_filter_info(int th); + +static s16 drc_val = 0; + +static int drc_setting_set(u8 *misc_setting, u8 is_conversion) +{ + u32 offset = 0; + if (is_conversion) { + drc_val = misc_setting[offset++] << 8 | misc_setting[offset++]; + drc_val = drc_val < 0 ? (drc_val + 61) : drc_val; + } else { + memcpy((u8 *)&drc_val, misc_setting, sizeof(drc_val)); + offset += 2; + } + return offset; +} + +static int drc_setting_get(u8 *misc_setting, u8 is_conversion) +{ + u32 offset = 0; + if (is_conversion) { + drc_val = drc_val > 0 ? (drc_val - 61) : drc_val; + misc_setting[offset++] = (drc_val >> 8) & 0xFF; + misc_setting[offset++] = (drc_val) & 0xFF; + } else { + memcpy(misc_setting, (u8 *)&drc_val, sizeof(drc_val)); + offset += 2; + } + return offset; +} + +static int drc_state_update(u8 *misc_setting) +{ + // 值不相同才设置 + static s16 prev_drc_val = -1; + if (-1 == prev_drc_val || prev_drc_val != drc_val) { + high_bass_drc_set_filter_info(drc_val > 0 ? drc_val - 61 : drc_val); + prev_drc_val = drc_val; + } + return 0; +} + +static SMARTBOX_MISC_SETTING_OPT drc_setting_opt = { + .misc_data_len = 2, + .misc_setting_type = MISC_SETTING_DRC_VAL, + .misc_syscfg_id = CFG_RCSP_MISC_DRC_SETTING, + .misc_set_setting = drc_setting_set, + .misc_get_setting = drc_setting_get, + .misc_state_update = drc_state_update, + .misc_custom_setting_init = NULL, + .misc_custom_write_vm = NULL, +}; +REGISTER_APP_MISC_SETTING_OPT(drc_setting_opt); + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_reverbration_setting.c b/apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_reverbration_setting.c new file mode 100644 index 0000000..333603d --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_reverbration_setting.c @@ -0,0 +1,149 @@ +#include "app_config.h" +#include "syscfg_id.h" + +#include "smartbox_setting_opt.h" +#include "smartbox_misc_setting.h" +#include "le_smartbox_module.h" + +#if (SMART_BOX_EN && SMARTBOX_REVERBERATION_SETTING && TCFG_MIC_EFFECT_ENABLE && RCSP_ADV_EQ_SET_ENABLE) +#include "mic_effect.h" +#include "key_event_deal.h" + +extern void mic_effect_set_echo_delay(u32 delay); +extern u32 mic_effect_get_echo_delay(void); +extern void mic_effect_set_echo_decay(u32 decay); +extern u32 mic_effect_get_echo_decay(void); +extern u8 mic_effect_get_status(void); + +#pragma pack(1) +struct t_reverbration { + u8 state; + u16 depth_val; + u16 strength_val; +}; +#pragma pack() + +static struct t_reverbration reverbration; + +static int reverbration_setting_set(u8 *misc_setting, u8 is_conversion) +{ + u32 offset = 0; + reverbration.state = misc_setting[offset++]; + + if (is_conversion) { + reverbration.depth_val = misc_setting[offset++] << 8 | misc_setting[offset++]; + reverbration.strength_val = misc_setting[offset++] << 8 | misc_setting[offset++]; + } else { + memcpy((u8 *)&reverbration.depth_val, misc_setting + offset, sizeof(reverbration.depth_val)); + offset += 2; + memcpy((u8 *)&reverbration.strength_val, misc_setting + offset, sizeof(reverbration.strength_val)); + offset += 2; + } + return offset; +} + +static int reverbration_setting_get(u8 *misc_setting, u8 is_conversion) +{ + u32 offset = 0; + misc_setting[offset++] = reverbration.state; + if (is_conversion) { + misc_setting[offset++] = (reverbration.depth_val >> 8) & 0xFF; + misc_setting[offset++] = (reverbration.depth_val) & 0xFF; + misc_setting[offset++] = (reverbration.strength_val >> 8) & 0xFF; + misc_setting[offset++] = (reverbration.strength_val) & 0xFF; + } else { + memcpy(misc_setting + offset, (u8 *)&reverbration.depth_val, sizeof(reverbration.depth_val)); + offset += 2; + memcpy(misc_setting + offset, (u8 *)&reverbration.strength_val, sizeof(reverbration.strength_val)); + offset += 2; + } + return offset; +} + +static int reverbration_write_vm(u8 *misc_setting) +{ + u8 reverbration_state = 0; + syscfg_read(CFG_RCSP_MISC_REVERB_ON_OFF, &reverbration_state, sizeof(reverbration_state)); + if (reverbration_state != reverbration.state) { + syscfg_write(CFG_RCSP_MISC_REVERB_ON_OFF, &reverbration.state, sizeof(reverbration.state)); + } + return 0; +} + +static int reverbration_state_update(u8 *misc_setting) +{ + // 值不相同才设置 + static u16 prev_depth_val = -1; + static u16 prev_strength_val = -1; + if (reverbration.state != mic_effect_get_status()) { + app_task_put_key_msg(KEY_REVERB_OPEN, 0); + } + + if (mic_effect_get_status() && (-1 == prev_depth_val || reverbration.depth_val != prev_depth_val)) { + mic_effect_set_echo_delay(reverbration.depth_val * 2); + prev_depth_val = reverbration.depth_val; + } + + if (mic_effect_get_status() && (-1 == prev_strength_val || reverbration.strength_val != prev_strength_val)) { + mic_effect_set_echo_decay(reverbration.strength_val * 70 / 100); + prev_strength_val = reverbration.strength_val; + } + + if (0 == mic_effect_get_status()) { + prev_depth_val = -1; + prev_strength_val = -1; + } + return 0; +} + +static int reverbration_custom_setting_init(void) +{ + u8 reverbration_state = 0; + if (sizeof(reverbration_state) == syscfg_read(CFG_RCSP_MISC_REVERB_ON_OFF, &reverbration_state, sizeof(reverbration_state))) { + reverbration.state = reverbration_state; + } else { + reverbration.state = mic_effect_get_status(); + } + reverbration.depth_val = mic_effect_get_echo_delay() / 2; + reverbration.strength_val = mic_effect_get_echo_decay() * 100 / 70; + return 0; +} + +static int reverbartion_key_event_callback_deal(int event, void *param) +{ + int ret = false; + switch (event) { + case KEY_REVERB_OPEN: + reverbration.state = mic_effect_get_status(); + reverbration_write_vm(NULL); + reverbration_state_update(NULL); + ret = true; + break; + } + return ret; +} + +static int reverbration_custom_setting_release(void) +{ + if (reverbration.state) { + app_task_put_key_msg(KEY_REVERB_OPEN, 0); + } + return 0; +} + +static SMARTBOX_MISC_SETTING_OPT reverbration_setting_opt = { + .be_notify_app = 1, + .misc_data_len = 5, + .misc_syscfg_id = CFG_RCSP_MISC_REVERB_ON_OFF, + .misc_setting_type = MISC_SETTING_REVERBERATION, + .misc_set_setting = reverbration_setting_set, + .misc_get_setting = reverbration_setting_get, + .misc_state_update = reverbration_state_update, + .misc_custom_setting_init = reverbration_custom_setting_init, + .misc_custom_write_vm = reverbration_write_vm, + .misc_custom_key_event_callback_deal = reverbartion_key_event_callback_deal, + .misc_custom_setting_release = reverbration_custom_setting_release, +}; +REGISTER_APP_MISC_SETTING_OPT(reverbration_setting_opt); + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_setting.c b/apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_setting.c new file mode 100644 index 0000000..5dd1596 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_setting.c @@ -0,0 +1,268 @@ +#include "smartbox/config.h" +#include "syscfg_id.h" +#include "smartbox_misc_setting.h" + +#include "smartbox_setting_sync.h" +#include "smartbox_setting_opt.h" +#include "le_smartbox_module.h" + +#include "smartbox/function.h" +#if (SMART_BOX_EN) + +extern int get_bt_tws_connect_status(); + +static int misc_setting_init(void); +static int get_misc_setting_info(u8 *misc_setting); +static int set_misc_setting_extra_handle(void *setting_data, void *param); +static void set_misc_setting_info(u8 *misc_setting); +static void deal_misc_setting(u8 *misc_setting, u8 write_vm, u8 tws_sync); +static int smartbox_misc_key_event_deal(int event, void *param); +static int smartbox_misc_setting_release(void); + +static SMARTBOX_SETTING_OPT misc_setting_opt = { + .data_len = 0, + .setting_type = ATTR_TYPE_MISC_SETTING, + .deal_opt_setting = deal_misc_setting, + .set_setting = set_misc_setting_info, + .get_setting = get_misc_setting_info, + .custom_setting_init = misc_setting_init, + .set_setting_extra_handle = set_misc_setting_extra_handle, + .custom_setting_key_event_update = smartbox_misc_key_event_deal, + .custom_setting_release = smartbox_misc_setting_release, +}; +REGISTER_APP_SETTING_OPT(misc_setting_opt); + +static SMARTBOX_MISC_SETTING_OPT *g_misc_opt_link_head = NULL; +static u32 g_misc_setting_update_type = -1; + +int register_smartbox_setting_misc_setting(void *misc_setting) +{ + // 需要排序 + SMARTBOX_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head; + SMARTBOX_MISC_SETTING_OPT *item = (SMARTBOX_SETTING_OPT *)misc_setting; + SMARTBOX_MISC_SETTING_OPT *existed_item = NULL; + while (misc_opt && item) { + if (misc_opt->misc_setting_type == item->misc_setting_type) { + return 0; + } else if (item->misc_setting_type > misc_opt->misc_setting_type) { + existed_item = misc_opt; + } + misc_opt = misc_opt->next; + } + + if (!g_misc_opt_link_head) { + item->next = g_misc_opt_link_head; + g_misc_opt_link_head = item; + return 0; + } else if (item && existed_item) { + item->next = existed_item->next; + existed_item->next = item; + return 0; + } + + return -1; +} + +static int misc_setting_init(void) +{ + u32 total_len = sizeof(u32); // 1个mask的长度 + SMARTBOX_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head; + while (misc_opt) { + u8 *data = zalloc(misc_opt->misc_data_len); + if (misc_opt->misc_custom_setting_init) { + misc_opt->misc_custom_setting_init(); + } else if (smartbox_read_data_from_vm(misc_opt->misc_syscfg_id, data, misc_opt->misc_data_len)) { + if (misc_opt->misc_set_setting) { + misc_opt->misc_set_setting(data, 0); + } + } + if (data) { + free(data); + } + total_len += misc_opt->misc_data_len; + misc_opt = misc_opt->next; + } + if (g_misc_opt_link_head && g_misc_opt_link_head != misc_opt) { + misc_setting_opt.data_len = total_len; + deal_misc_setting(NULL, 0, 0); + } + return 0; +} + +static int get_misc_setting_info(u8 *misc_setting) +{ + u32 mask = 0; + u32 offset = sizeof(mask); + SMARTBOX_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head; + u32 update_mics_setting_type = g_misc_setting_update_type; + g_misc_setting_update_type = -1; + while (misc_opt) { + if (update_mics_setting_type & BIT(misc_opt->misc_setting_type)) { + if (misc_opt->misc_get_setting) { + misc_opt->misc_get_setting(misc_setting + offset, 1); + } + offset += misc_opt->misc_data_len; + mask |= BIT(misc_opt->misc_setting_type); + } + misc_opt = misc_opt->next; + } + + misc_setting[0] = (mask >> 24) & 0xFF; + misc_setting[1] = (mask >> 16) & 0xFF; + misc_setting[2] = (mask >> 8) & 0xFF; + misc_setting[3] = (mask) & 0xFF; + return offset; +} + +static int set_misc_setting_extra_handle(void *setting_data, void *param) +{ + u8 *misc_setting = (u8 *)setting_data; + u32 mask = (misc_setting[0] << 24 | misc_setting[1] << 16 | misc_setting[2] << 8 | misc_setting[3]); + if (0 == mask) { + return -1; + } + SMARTBOX_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head; + u32 update_mics_setting_type = 0; + while (misc_opt) { + if (mask & BIT(misc_opt->misc_setting_type) && misc_opt->be_notify_app) { + update_mics_setting_type |= BIT(misc_opt->misc_setting_type); + } + misc_opt = misc_opt->next; + } + if (!param && update_mics_setting_type) { + g_misc_setting_update_type = update_mics_setting_type; + } + return 0; +} + +static u32 g_set_mask = -1; +static void set_misc_setting_info(u8 *misc_setting) +{ + u32 offset = 0; + g_set_mask = (misc_setting[offset++] << 24 | misc_setting[offset++] << 16 | misc_setting[offset++] << 8 | misc_setting[offset++]); + SMARTBOX_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head; + while (misc_opt) { + if (g_set_mask & BIT(misc_opt->misc_setting_type)) { + if (misc_opt->misc_set_setting) { + misc_opt->misc_set_setting(misc_setting + offset, 1); + } + offset += misc_opt->misc_data_len; + } + misc_opt = misc_opt->next; + } +} + +static int write_misc_setting_vm_value(int syscfg_id, u8 *data, u32 data_len) +{ + if (!data_len) { + goto end; + } + u8 *vm_data = zalloc(data_len); + syscfg_read(syscfg_id, vm_data, data_len); + if (memcmp(vm_data, data, data_len)) { + syscfg_write(syscfg_id, data, data_len); + } + if (vm_data) { + free(vm_data); + } +end: + return 0; +} + +static void update_misc_setting_vm_value(u8 *misc_setting) +{ + SMARTBOX_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head; + while (misc_opt) { + if (g_set_mask & BIT(misc_opt->misc_setting_type)) { + if (misc_opt->misc_custom_write_vm) { + misc_opt->misc_custom_write_vm(misc_setting); + } else if (misc_opt->misc_syscfg_id && misc_opt->misc_get_setting) { + u8 *data = zalloc(misc_opt->misc_data_len); + misc_opt->misc_get_setting(data, 0); + write_misc_setting_vm_value(misc_opt->misc_syscfg_id, data, misc_opt->misc_data_len); + if (data) { + free(data); + } + } + } + misc_opt = misc_opt->next; + } +} + +static void misc_setting_sync(u8 *misc_setting) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_smartbox_setting(ATTR_TYPE_MISC_SETTING); + } +#endif +} + +static void misc_setting_state_update(u8 *misc_setting) +{ + SMARTBOX_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head; + while (misc_opt) { + if (g_set_mask & BIT(misc_opt->misc_setting_type)) { + if (misc_opt->misc_state_update) { + misc_opt->misc_state_update(misc_setting); + } + } + misc_opt = misc_opt->next; + } +} + +static void deal_misc_setting(u8 *misc_setting, u8 write_vm, u8 tws_sync) +{ + if (misc_setting) { + set_misc_setting_info(misc_setting); + } + if (write_vm) { + update_misc_setting_vm_value(misc_setting); + } + if (tws_sync) { + misc_setting_sync(misc_setting); + } + misc_setting_state_update(misc_setting); +} + +static int smartbox_misc_key_event_deal(int event, void *param) +{ + SMARTBOX_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head; + while (misc_opt) { + if (misc_opt->misc_custom_key_event_callback_deal && misc_opt->misc_custom_key_event_callback_deal(event, param)) { + if (misc_opt->be_notify_app) { + SMARTBOX_UPDATE(COMMON_FUNCTION, BIT(COMMON_FUNCTION_ATTR_TYPE_MISC_SETTING_INFO)); + } + return true; + } + misc_opt = misc_opt->next; + } + g_misc_setting_update_type = -1; + return false; +} + +static int smartbox_misc_setting_release(void) +{ + SMARTBOX_MISC_SETTING_OPT *misc_opt = g_misc_opt_link_head; + while (misc_opt) { + if (misc_opt->misc_custom_setting_release) { + misc_opt->misc_custom_setting_release(); + } + misc_opt = misc_opt->next; + } + return 0; +} + +u32 get_misc_setting_data_len(void) +{ + return misc_setting_opt.data_len; +} + +#else + +u32 get_misc_setting_data_len(void) +{ + return 0; +} + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_setting.h b/apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_setting.h new file mode 100644 index 0000000..0a4dd41 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_setting.h @@ -0,0 +1,54 @@ +#ifndef __SMARTBOX_MISC_SETTING__ +#define __SMARTBOX_MISC_SETTING__ + +#include "system/includes.h" + +#define REGISTER_APP_MISC_SETTING_OPT(smart_misc_opt) \ +int smart_misc_opt##_setting_init(void) {\ + return register_smartbox_setting_misc_setting(&smart_misc_opt);\ +}\ +late_initcall(smart_misc_opt##_setting_init); + +#define SMARTBOX_REVERBERATION_SETTING 1 +#define SMARTBOX_DRC_VAL_SETTING 1 +#define SMARTBOX_KARAOKE_SOUND_EFFECT 1 +#define SMARTBOX_KARAOKE_ATMOSPHERE 1 +#define SMARTBOX_KARAOKE_SOUND_PARAM 1 + +enum { + MISC_SETTING_REVERBERATION = 0, + MISC_SETTING_DRC_VAL = 1, + MISC_SETTING_MASK_MAX, // 最多只支持32个 +}; + +#pragma pack(1) +typedef struct _SMARTBOX_MISC_SETTING_OPT { + struct _SMARTBOX_MISC_SETTING_OPT *next; + bool be_notify_app; // 接收到数据并更新效果完后是否需要通知app, 如果需要通知app则置1 + u32 misc_data_len; + int misc_setting_type; + int misc_syscfg_id; + + // misc_set_setting函数参数: + // misc_setting : 传入数据 + // is_conversion : 1 - 需要转换,从大端转为小端 + // 0 - 不需要转换 + int (*misc_set_setting)(u8 *misc_setting, u8 is_conversion); + + // misc_get_setting函数参数: + // misc_setting : 传出数据 + // is_conversion : 1 - 需要转换,从小端转为大端 + // 0 - 不需要转换 + int (*misc_get_setting)(u8 *misc_setting, u8 is_conversion); + int (*misc_state_update)(u8 *misc_setting); // 参数用于判断当前更新是设置状态(非空)还是初始化/同步(未空) + + // 上面是必填,下面是选填 + int (*misc_custom_setting_init)(void); + int (*misc_custom_write_vm)(u8 *misc_setting); + int (*misc_custom_key_event_callback_deal)(int event, void *param); + int (*misc_custom_setting_release)(void); +} SMARTBOX_MISC_SETTING_OPT; +#pragma pack() + +int register_smartbox_setting_misc_setting(void *misc_setting); +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/smartbox_music_info_setting.c b/apps/soundbox/smartbox/smartbox_setting/smartbox_music_info_setting.c new file mode 100644 index 0000000..95fe46f --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/smartbox_music_info_setting.c @@ -0,0 +1,532 @@ +#include "smartbox/config.h" +#include "syscfg_id.h" +#include "le_smartbox_module.h" +#include "smartbox_adv_bluetooth.h" + +#include "smartbox_setting_sync.h" +#include "smartbox_setting_opt.h" +#include "smartbox_music_info_setting.h" +#include "btstack/avctp_user.h" +#include "bt_tws.h" + +#if (SMART_BOX_EN && RCSP_ADV_MUSIC_INFO_ENABLE) + +struct music_info_t { + u8 title_len; + char title[64]; + u8 artist_len; + char artist[64]; + u8 album_len; + char album[64]; + u8 num_len; + char number; + u8 total_len; + char total[2]; + u8 genre_len; + char genre[16]; + char time[8]; + u8 player_state; + u8 player_time_min; + u8 player_time_sec; + u32 curr_player_time; + u8 player_time_en; + u32 total_time; + volatile int get_music_player_timer; +}; + +static struct music_info_t music_info; +void JL_rcsp_event_to_user(u32 type, u8 event, u8 *msg, u8 size); +static u8 rcsp_adv_music_info_vaild(void); + + +u8 get_player_time_en(void) +{ + return music_info.player_time_en; +} + +void set_player_time_en(u8 en) +{ + music_info.player_time_en = en; +} + +void reset_player_time_en(void) +{ + music_player_time_timer_deal(music_info.player_time_en); +} + +void music_player_time_deal(void *priv) +{ + if (BT_STATUS_PLAYING_MUSIC == get_bt_connect_status()) { + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_GET_PLAY_TIME, 0, NULL); + } +} + +void get_music_info(void) +{ + //printf("\nsend music info\n"); + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_GET_MUSIC_INFO, 0, NULL); +} + +void btstack_avrcp_ch_creat_ok(void) +{ + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_AVRCP_CH_SYNC_MUSIC_INFO, NULL, 0); +} + + +void music_sync_info(void) +{ + if (tws_api_get_role() == TWS_ROLE_SLAVE) { + //printf("\n\n\n\nrcsp ge music info\n"); + tws_api_sync_call_by_uuid(TWS_FUNC_APP_OPT_UUID, APP_OPT_SYNC_CMD_MUSIC_INFO, 300); + } else { + if ((tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) == 0) { + //printf("\n\n\nno tws rcsp ge music info\n\n"); + get_music_info(); + } + } +} + +char *get_music_title(void) +{ + return music_info.title; +} + +u8 get_music_title_len(void) +{ + return music_info.title_len; +} + +char *get_music_artist(void) +{ + return music_info.artist; +} + +u8 get_music_artist_len(void) +{ + return music_info.artist_len; +} + +char *get_music_album(void) +{ + return music_info.album; +} + +u8 get_music_album_len(void) +{ + return music_info.album_len; +} + +char *get_music_number(void) +{ + return &music_info.number; +} + +u8 get_music_number_len(void) +{ + return music_info.num_len; +} + +char *get_music_total(void) +{ + return music_info.total; +} + +u8 get_music_total_len(void) +{ + return music_info.total_len; +} + +char *get_music_genre(void) +{ + return music_info.genre; +} + +u8 get_music_genre_len(void) +{ + return music_info.genre_len; +} + +u16 get_music_total_time(void) +{ + return (music_info.total_time / 1000); +} + +u32 get_music_curr_time(void) +{ + return music_info.curr_player_time; + /* return (music_info.player_time_min * 60 + music_info.player_time_sec); */ +} + +u8 bt_music_total_time(u32 time) +{ + music_info.total_time = time; + /* printf("get music time %d\n", music_info.total_time); */ + return 0; +} + +u8 get_music_player_state(void) +{ + return music_info.player_state; +} + +void rcsp_update_player_state(void) +{ + struct smartbox *smart = smartbox_handle_get(); + if (1 == smart->A_platform && rcsp_adv_music_info_vaild()) { + return; + } + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_PLAYER_STATE, NULL, 0); +} + + +void bt_status_change(u8 state) +{ + if (BT_STATUS_PLAYING_MUSIC == state) { + music_info.player_state = 1; + } else { + music_info.player_state = 0; + } + if ((tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) == 0) { + rcsp_update_player_state(); + } else { + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_PLAYER_STATE_CHANGE, NULL, 0); + } +} + +void music_player_status_change(void) +{ + if (tws_api_get_role() == TWS_ROLE_MASTER) { + tws_api_sync_call_by_uuid(TWS_FUNC_APP_OPT_UUID, APP_OPT_SYNC_CMD_MUSIC_PLAYER_STATE, 300); + } else { + tws_api_sync_call_by_uuid(TWS_FUNC_APP_OPT_UUID, APP_OPT_SYNC_CMD_MUSIC_PLAYER_TIEM_EN, 300); + } +} + +void stop_get_music_timer(u8 en) +{ + if (en) { + music_info.player_time_en = 0; + } + + if (music_info.get_music_player_timer) { + sys_timeout_del(music_info.get_music_player_timer); + music_info.get_music_player_timer = 0; + } +} + + +void music_player_time_timer_deal(u8 en) +{ + if (en) { + if (music_info.get_music_player_timer == 0) { + music_info.get_music_player_timer = sys_timer_add(NULL, music_player_time_deal, 800); + } + } else { + if (music_info.get_music_player_timer) { + sys_timer_del(music_info.get_music_player_timer); + music_info.get_music_player_timer = 0; + } + } + + +} + + +void music_info_cmd_handle(u8 *p, u16 len) +{ + u8 cmd = *p; + u8 *data = p + 1; + + switch (cmd) { + case 0x01: + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_PLAY, 0, NULL); + break; + + case 0x02: + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_PREV, 0, NULL); + break; + + case 0x03: + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_NEXT, 0, NULL); + break; + + case 0x04: + + music_info.player_time_en = *data; + + if (*data) { + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_MUSIC_PLAYER_TIME_TEMER, data, 1); + } else { + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_MUSIC_PLAYER_TIME_TEMER, data, 1); + } + break; + + default: + break; + } +} + +u32 char_to_hex(char num, u8 ten_num) +{ + u32 char_num; + switch (num) { + case '0': + char_num = 0; + break; + case '1': + char_num = 1; + break; + case '2': + char_num = 2; + break; + case '3': + char_num = 3; + break; + case '4': + char_num = 4; + break; + case '5': + char_num = 5; + break; + + case '6': + char_num = 6; + break; + + case '7': + char_num = 7; + break; + + case '8': + char_num = 8; + break; + case '9': + char_num = 9; + break; + default: + char_num = 0; + + } + + switch (ten_num) { + case 0: + char_num = char_num; + break; + case 1: + char_num = char_num * 10; + break; + case 2: + char_num = char_num * 100; + break; + case 3: + char_num = char_num * 1000; + break; + case 4: + char_num = char_num * 10000; + break; + case 5: + char_num = char_num * 100000; + break; + + case 6: + char_num = char_num * 1000000; + break; + + case 7: + char_num = char_num * 10000000; + break; + + default: + char_num = char_num; + } + + return char_num; +} + +u32 num_char_to_hex(char *c, len) +{ + u32 total_num = 0; + u8 i; + for (i = 0; i < len; i++) { + total_num += char_to_hex(*(c + i), len - i - 1); + } + return total_num; + +} + +static void rcsp_adv_update_music_info(void *priv) +{ + u8 i; + u32 type = *((u32 *)priv); + if (music_info.player_time_en) { + for (i = 0; i < (sizeof(type) * 8); i++) { + if (type & BIT(i)) { + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_MUSIC_INFO, &i, 1); + } + } + } +} + +static u8 music_info_state = 0; +static void rcsp_adv_music_info_state(void *priv) +{ + music_info_state = *((u8 *)priv); +} + +static u8 rcsp_adv_music_info_vaild(void) +{ + return music_info_state == 0; +} + +void rcsp_adv_music_info_set_state(u8 state, u32 time) +{ + static u8 cur_state = 0; + cur_state = state; + sys_timeout_add(&cur_state, rcsp_adv_music_info_state, time); +} + +void rcsp_adv_music_info_deal(u8 type, u32 time, u8 *info, u16 len) +{ + //printf("info len \n"); + //put_buf(info,len); + struct smartbox *smart = smartbox_handle_get(); + if (1 == smart->A_platform && rcsp_adv_music_info_vaild()) { + return; + } +#if RCSP_ADV_FIND_DEVICE_ENABLE + extern u8 smartbox_find_device_key_flag_get(void); + if (smartbox_find_device_key_flag_get()) { + return ; + } +#endif + static u32 deal_type = 0; + static u32 final_type = 0; + switch (type) { + case 0: + if (time && time != music_info.total_time) { + /* if(music_info.player_time_en) */ + { + music_info.curr_player_time = time; + music_info.player_time_min = time / 1000 / 60; + music_info.player_time_sec = time / 1000 - (music_info.player_time_min * 60); + + /* printf("total time %d %d->", music_info.total_time, time); */ + /* printf("muisc time %d %d->", music_info.player_time_min, music_info.player_time_sec); */ + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_PLAYER_TIME, NULL, 0); + } + } + return; + case 1: + if ((info)) { + if (len > 64) { + len = 64; + } + if (len) { + music_info.title_len = len; + memcpy(music_info.title, info, len); + } else { + music_info.title[0] = 0; + music_info.title_len = 1; + } + deal_type |= BIT(type); + } + break; + case 2: + if ((info)) { + if (len > 64) { + len = 64; + } + if (len) { + music_info.artist_len = len; + memcpy(music_info.artist, info, len); + } else { + music_info.artist[0] = 0; + music_info.artist_len = 1; + } + deal_type |= BIT(type); + } + break; + case 3: + if ((info)) { + if (len > 64) { + len = 64; + } + if (len) { + music_info.album_len = len; + memcpy(music_info.album, info, len); + } else { + music_info.album[0] = 0; + music_info.album_len = 1; + } + deal_type |= BIT(type); + } + break; + case 4: + if ((info)) { + len = 1; + music_info.num_len = len; + memcpy(&music_info.number, info, len); + deal_type |= BIT(type); + } + break; + case 5: + if ((info)) { + len = 2; + music_info.total_len = len; + memcpy(music_info.total, info, len); + deal_type |= BIT(type); + } + break; + case 6: + if ((info)) { + if (len > 16) { + len = 16; + } + music_info.genre_len = len; + memcpy(music_info.genre, info, len); + deal_type |= BIT(type); + } + break; + case 7: + if ((info)) { + if (len > 8) { + len = 8; + } + memcpy(music_info.time, info, len); + + /* printf("get time %s\n", info); */ + /* put_buf(music_info.time, len); */ + music_info.total_time = num_char_to_hex(music_info.time, len); + deal_type |= BIT(type); + final_type = deal_type; + if (0 == music_info.player_time_en) { + sys_timeout_add(&final_type, rcsp_adv_update_music_info, 500); + } + deal_type = 0; + } + break; + default: + break; + } + + if (music_info.player_time_en) { + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_MUSIC_INFO, &type, 1); + } + /* os_time_dly(2); */ +} + +void avrcp_element_attr_rsp_ext_process(u8 type, u32 time, u8 *info, u16 len) +{ + if (0 == len) { + rcsp_adv_music_info_deal(type, time, info, len); + } +} + + +#else +u8 get_player_time_en(void) +{ + return 0; +} + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/smartbox_music_info_setting.h b/apps/soundbox/smartbox/smartbox_setting/smartbox_music_info_setting.h new file mode 100644 index 0000000..dc52560 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/smartbox_music_info_setting.h @@ -0,0 +1,31 @@ +#ifndef __SMARTBOX_MUSIC_INFO_SETTING_H__ +#define __SMARTBOX_MUSIC_INFO_SETTING_H__ + + +#include "le_smartbox_module.h" + +#if RCSP_ADV_MUSIC_INFO_ENABLE + +char *get_music_title(void); +u8 get_music_title_len(void); +char *get_music_artist(void); +u8 get_music_artist_len(void); +char *get_music_album(void); +u8 get_music_album_len(void); +char *get_music_number(void); +u8 get_music_number_len(void); +char *get_music_total(void); +u8 get_music_total_len(void); +char *get_music_genre(void); +u8 get_music_genre_len(void); +u16 get_music_total_time(void); +u32 get_music_curr_time(void); +u8 get_music_player_state(void); +void music_info_cmd_handle(u8 *p, u16 len); +void stop_get_music_timer(u8 en); +extern void music_player_time_timer_deal(u8 en); +u8 get_player_time_en(void); +void set_player_time_en(u8 en); +void rcsp_adv_music_info_deal(u8 type, u32 time, u8 *info, u16 len); +#endif +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting/smartbox_vol_setting.c b/apps/soundbox/smartbox/smartbox_setting/smartbox_vol_setting.c new file mode 100644 index 0000000..1a5cf57 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting/smartbox_vol_setting.c @@ -0,0 +1,226 @@ +#include "smartbox/config.h" + +#include "syscfg_id.h" + +#include "smartbox_setting_sync.h" +#include "smartbox_setting_opt.h" +#include "le_smartbox_module.h" +#include "smartbox/function.h" + +#include "key_event_deal.h" +#include "audio_config.h" +#include "bt/vol_sync.h" +#if (SMART_BOX_EN && RCSP_ADV_EQ_SET_ENABLE) + +static u8 vol_setting[1] = {0}; +extern int get_bt_tws_connect_status(); + +bool smartbox_set_device_volume(int volume) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL) { + return false; + } + if (0 == smart->dev_vol_sync) { + return false; + } + if (0 == smart->A_platform) { + set_music_device_volume(volume); + } + + return true; +} + +bool smartbox_set_volume(s8 volume) +{ + static cur_flag = 0; + struct smartbox *smart = smartbox_handle_get(); + if (cur_flag || smart == NULL) { + cur_flag = 0; + return false; + } + if (0 == smart->dev_vol_sync) { + return false; + } +#if TCFG_APP_LINEIN_EN + if (LINEIN_FUNCTION == smart->cur_app_mode) { + cur_flag = 1; + extern int linein_volume_set(u8 vol); + linein_volume_set(volume); + cur_flag = 0; + return true; + } +#endif + return false; +} + +bool samrtbox_key_volume_down(u8 value) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL) { + return false; + } + if (0 == smart->dev_vol_sync) { + return false; + } +#if TCFG_APP_LINEIN_EN + if (LINEIN_FUNCTION == smart->cur_app_mode) { + extern void linein_key_vol_down(); + linein_key_vol_down(); + return true; + } +#endif + return false; +} + +bool smartbox_key_volume_up(u8 value) +{ + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL) { + return false; + } + if (0 == smart->dev_vol_sync) { + return false; + } +#if TCFG_APP_LINEIN_EN + if (LINEIN_FUNCTION == smart->cur_app_mode) { + extern void linein_key_vol_up(); + linein_key_vol_up(); + true; + } +#endif + return false; +} + +void smartbox_get_max_vol_info(u8 *vol_info) +{ + *vol_info = get_max_sys_vol(); +} + +void smartbox_get_cur_dev_vol_info(u8 *vol_info) +{ + *vol_info = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); +} + +void smartbox_set_vol_for_find_device(u8 vol_flag) +{ + static u8 vol = 0; + static u8 state = 0; + if (state == vol_flag) { + return ; + } + if (vol_flag) { + // 停止媒体 + vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + // 最大声 + app_audio_set_volume(app_audio_get_state(), get_max_sys_vol(), 1); + + } else { + // 恢复 + app_audio_set_volume(app_audio_get_state(), vol, 1); + } + + smartbox_function_update(COMMON_FUNCTION, BIT(COMMON_FUNCTION_ATTR_TYPE_VOL)); + state = vol_flag; +} + +static int smartbox_get_vol_info(u8 *vol_info) +{ + *vol_info = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + return 0; +} + +static void set_vol_info(u8 *vol_info) +{ + memcpy(vol_setting, vol_info, sizeof(vol_setting)); +} + +static void update_vol_vm_value(u8 *vol_info) +{ + // 不需要写vm操作,5s后会自动保持音量值 + //syscfg_write(CFG_MUSIC_VOL, vol_setting, sizeof(vol_setting)); +} + +static void vol_setting_sync(u8 *vol_info) +{ +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + update_smartbox_setting(ATTR_TYPE_VOL_SETTING); + } +#endif +} + +static void vol_state_update(void) +{ + // 更新操作,包含写vm操作 + struct smartbox *smart = smartbox_handle_get(); + if (smart == NULL) { + return ; + } + u8 vol = vol_setting[0]; + if (LINEIN_FUNCTION == smart->cur_app_mode) { +#if TCFG_APP_LINEIN_EN + extern int linein_volume_set(u8 vol); + linein_volume_set(vol); +#endif + } else { + app_audio_set_volume(app_audio_get_state(), vol, 1); + } +} + +static void deal_vol_setting(u8 *vol_info, u8 write_vm, u8 tws_sync) +{ + if (vol_info) { + set_vol_info(vol_info); + } + if (write_vm) { + update_vol_vm_value(vol_setting); + } + if (tws_sync) { + vol_setting_sync(vol_setting); + } + vol_state_update(); +} + +static int vol_setting_init(void) +{ + int ret = 0; + u8 cur_vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + set_vol_info(&cur_vol); + + return 0; +} + +static SMARTBOX_SETTING_OPT vol_setting_opt = { + .data_len = 1, + .setting_type = ATTR_TYPE_VOL_SETTING, + .syscfg_id = CFG_MUSIC_VOL, + .deal_opt_setting = deal_vol_setting, + .set_setting = set_vol_info, + .get_setting = smartbox_get_vol_info, + .custom_setting_init = vol_setting_init, // 初始化不需要vm操作,所以重新实现 + .custom_setting_release = NULL, + .custom_vm_info_update = NULL, + .custom_setting_update = NULL, + .custom_sibling_setting_deal = NULL, +}; +REGISTER_APP_SETTING_OPT(vol_setting_opt); + +#else + +bool smartbox_set_device_volume(int volume) +{ + return false; +} + +void smartbox_get_max_vol_info(u8 *vol_info) +{ + *vol_info = get_max_sys_vol(); +} + +void smartbox_get_cur_dev_vol_info(u8 *vol_info) +{ + *vol_info = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); +} + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_adv_bluetooth.c b/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_adv_bluetooth.c new file mode 100644 index 0000000..40e68a0 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_adv_bluetooth.c @@ -0,0 +1,319 @@ +#include "smartbox/config.h" +#include "le_smartbox_module.h" +#include "smartbox_adv_bluetooth.h" +#include "smartbox_setting_opt.h" +#include "smartbox_setting_sync.h" +#include "custom_cfg.h" +#include "btstack/avctp_user.h" +#include "smartbox_rcsp_manage.h" +#include "smartbox_music_info_setting.h" + +//#if (SMART_BOX_EN && RCSP_SMARTBOX_ADV_EN) +#if (SMART_BOX_EN) + +#define RCSP_DEBUG_EN +#ifdef RCSP_DEBUG_EN +#define rcsp_putchar(x) putchar(x) +#define rcsp_printf printf +#define rcsp_printf_buf(x,len) put_buf(x,len) +#else +#define rcsp_putchar(...) +#define rcsp_printf(...) +#define rcsp_printf_buf(...) +#endif + +#define JL_OPCODE_SET_DEVICE_REBOOT 0xE7 + +extern int get_bt_tws_connect_status(); + +static u8 adv_setting_result = 0; +static u8 adv_set_deal_one_attr(u8 *buf, u8 size, u8 offset) +{ + u8 rlen = buf[offset]; + if ((offset + rlen + 1) > (size - offset)) { + rcsp_printf("\n\ndeal attr end!\n\n"); + return rlen; + } + u8 type = buf[offset + 1]; + u8 *pbuf = &buf[offset + 2]; + u8 dlen = rlen - 1; + adv_setting_result = 0; + + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(type); + if (setting_opt_hdl) { + adv_setting_result = set_setting_extra_handle(setting_opt_hdl, pbuf, &dlen); + } + if (!adv_setting_result) { + set_smartbox_opt_setting(setting_opt_hdl, NULL); + } + + return rlen + 1; +} + +static u32 JL_opcode_set_adv_info(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + rcsp_printf("JL_opcode_set_adv_info:\n"); + rcsp_printf_buf(data, len); + u8 offset = 0; + while (offset < len) { + offset += adv_set_deal_one_attr(data, len, offset); + } + u8 ret = 0; + if (adv_setting_result) { + ret = adv_setting_result; + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, &ret, 1); + } else { + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, &ret, 1); + } + return 0; +} + +static u8 smartbox_adv_get_and_fill_adv_info(u8 *buf, u16 max_len, u8 offset, u8 type) +{ + u8 *adv_data = NULL; + SMARTBOX_SETTING_OPT *setting_opt_hdl = get_smartbox_setting_opt_hdl(type); + u8 size = get_setting_extra_handle(setting_opt_hdl, &adv_data, NULL); + if (size && adv_data) { + size = add_one_attr(buf, max_len, offset, type, (void *)adv_data, size); + } + return size; +} + +extern void bt_adv_get_bat(u8 *buf); +static u32 JL_opcode_get_adv_info(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + u8 buf[256]; + u8 offset = 0; + + u32 ret = 0; + u32 mask = READ_BIG_U32(data); + rcsp_printf("FEATURE MASK : %x\n", mask); + /* #define ATTR_TYPE_BAT_VALUE (0) */ + /* #define ATTR_TYPE_EDR_NAME (1) */ + //get version + if (mask & BIT(ATTR_TYPE_BAT_VALUE)) { + rcsp_printf("ATTR_TYPE_BAT_VALUE\n"); + u8 bat[3]; + bt_adv_get_bat(bat); + offset += add_one_attr(buf, sizeof(buf), offset, ATTR_TYPE_BAT_VALUE, bat, 3); + } + + if (mask & BIT(ATTR_TYPE_EDR_NAME)) { + rcsp_printf("ATTR_TYPE_EDR_NAME\n"); + offset += smartbox_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_EDR_NAME); + } + + if (mask & BIT(ATTR_TYPE_KEY_SETTING)) { + rcsp_printf("ATTR_TYPE_KEY_SETTING\n"); + offset += smartbox_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_KEY_SETTING); + } + + if (mask & BIT(ATTR_TYPE_LED_SETTING)) { + rcsp_printf("ATTR_TYPE_LED_SETTING\n"); + offset += smartbox_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_LED_SETTING); + } + + + if (mask & BIT(ATTR_TYPE_MIC_SETTING)) { + rcsp_printf("ATTR_TYPE_MIC_SETTING\n"); + offset += smartbox_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_MIC_SETTING); + } + + if (mask & BIT(ATTR_TYPE_WORK_MODE)) { + rcsp_printf("ATTR_TYPE_WORK_MODE\n"); + offset += smartbox_adv_get_and_fill_adv_info(buf, sizeof(buf), offset, ATTR_TYPE_WORK_MODE); + } + +#if RCSP_ADV_PRODUCT_MSG_ENABLE + if (mask & BIT(ATTR_TYPE_PRODUCT_MESSAGE)) { + rcsp_printf("ATTR_TYPE_PRODUCT_MESSAGE\n"); + u16 vid = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG); + u16 pid = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG); + u8 tversion[6]; + tversion[0] = 0x05; + tversion[1] = 0xD6; + tversion[3] = vid & 0xFF; + tversion[2] = vid >> 8; + tversion[5] = pid & 0xFF; + tversion[4] = pid >> 8; + offset += add_one_attr(buf, sizeof(buf), offset, ATTR_TYPE_PRODUCT_MESSAGE, (void *)tversion, 6); + + } +#endif + rcsp_printf_buf(buf, offset); + + ret = JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, buf, offset); + + return ret; +} + +u8 adv_info_notify(u8 *buf, u16 len) +{ + return JL_CMD_send(JL_OPCODE_ADV_DEVICE_NOTIFY, buf, len, JL_NOT_NEED_RESPOND); +} + +u8 adv_info_device_request(u8 *buf, u16 len) +{ + printf("JL_OPCODE_ADV_DEVICE_REQUEST\n"); + return JL_CMD_send(JL_OPCODE_ADV_DEVICE_REQUEST, buf, len, JL_NEED_RESPOND); +} + +int JL_smartbox_adv_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + rcsp_printf("JL_rcsp_adv_cmd_resp\n"); + switch (OpCode) { + case JL_OPCODE_SET_ADV: + rcsp_printf(" JL_OPCODE_SET_ADV\n"); + JL_opcode_set_adv_info(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_GET_ADV: + rcsp_printf(" JL_OPCODE_GET_ADV\n"); + JL_opcode_get_adv_info(priv, OpCode, OpCode_SN, data, len); + break; + case JL_OPCODE_ADV_NOTIFY_SETTING: + rcsp_printf(" JL_OPCODE_ADV_NOTIFY_SETTING\n"); + bt_ble_adv_ioctl(BT_ADV_SET_NOTIFY_EN, *((u8 *)data), 1); + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0); + break; + case JL_OPCODE_ADV_DEVICE_REQUEST: + rcsp_printf("JL_OPCODE_ADV_DEVICE_REQUEST\n"); + break; + case JL_OPCODE_SET_DEVICE_REBOOT: + rcsp_printf("JL_OPCODE_SET_DEVICE_REBOOT\n"); + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, NULL, 0); + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_REBOOT_DEV, NULL, 0); + break; + default: + return 1; + } + return 0; +} + +static void smartbox_wait_reboot_dev(void *priv) +{ + if (NULL == priv && !rcsp_send_list_is_empty()) { + return; + } + user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL); + extern void ble_module_enable(u8 en); + ble_module_enable(0); + cpu_reset(); +} + +static void smartbox_rcsp_reboot_dev(void) +{ + extern void adv_edr_name_change_now(void); + adv_edr_name_change_now(); +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + modify_bt_name_and_reset(500); + } else { + if (sys_timer_add(NULL, smartbox_wait_reboot_dev, 500) == 0) { + smartbox_wait_reboot_dev((void *)1); + } + } +#else + if (sys_timer_add(NULL, smartbox_wait_reboot_dev, 500) == 0) { + smartbox_wait_reboot_dev((void *)1); + } +#endif + +} + +int JL_smartbox_adv_event_handler(struct rcsp_event *rcsp) +{ + switch (rcsp->event) { + case MSG_JL_REBOOT_DEV: + smartbox_rcsp_reboot_dev(); + break; + case MSG_JL_UPDATE_SEQ: + /* printf("MSG_JL_UPDATE_SEQ\n"); */ + /* extern void adv_seq_vaule_sync(void); */ + /* adv_seq_vaule_sync(); */ + break; + case MSG_JL_UPDAET_ADV_STATE_INFO: + /* if (get_rcsp_connect_status()) { */ + /* JL_rcsp_set_auth_flag(rcsp->args[0]); */ + /* bt_ble_adv_ioctl(BT_ADV_SET_NOTIFY_EN, rcsp->args[1], 1); */ + /* } */ + break; + default: + return 1; + } + return 0; +} + +// 下面是弹窗的其他设置 +int app_core_data_for_send(u8 *packet, u16 size) +{ + //printf("for app send size %d\n", size); + + if (JL_rcsp_get_auth_flag()) { + *packet = 1; + } else { + *packet = 0; + } + + if (RCSP_SPP == bt_3th_get_cur_bt_channel_sel()) { + if (get_ble_adv_notify()) { + *(packet + 1) = 1; + } else { + *(packet + 1) = 0; + } + +#if RCSP_ADV_MUSIC_INFO_ENABLE + if (get_player_time_en()) { + *(packet + 2) = 1; + } else { + *(packet + 2) = 0; + } +#else + *(packet + 2) = 0; +#endif + + *(packet + 3) = get_connect_flag(); + } + + return 4; +} + +void app_core_data_for_set(u8 *packet, u16 size) +{ + u8 rcsp_auth_flag = *packet; + u8 ble_adv_notify = *(packet + 1); + u8 player_time_en = *(packet + 2); + u8 connect_flag = *(packet + 3); + + if (RCSP_SPP == bt_3th_get_cur_bt_channel_sel()) { + JL_rcsp_set_auth_flag(rcsp_auth_flag); + set_ble_adv_notify(ble_adv_notify); +#if RCSP_ADV_MUSIC_INFO_ENABLE + set_player_time_en(player_time_en); +#endif + set_connect_flag(connect_flag); + } + + return; +} + +u8 smart_auth_res_deal(void) +{ + printf("smart_auth_res_deal\n"); + if ((tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED)) { + if (RCSP_SPP == bt_3th_get_cur_bt_channel_sel()) { + tws_api_sync_call_by_uuid(TWS_FUNC_APP_OPT_UUID, APP_OPT_SYNC_CMD_RCSP_AUTH_RES, 300); + return 0; + } else { + return 1; + } + } else { + return 1; + } +} + + +void rcsp_tws_auth_sync_deal(void) +{ + smart_auth_res_pass(); +} +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_adv_bluetooth.h b/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_adv_bluetooth.h new file mode 100644 index 0000000..31e7e30 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_adv_bluetooth.h @@ -0,0 +1,41 @@ +#ifndef __SMARTBOX_ADV_BLUETOOTH__ +#define __SMARTBOX_ADV_BLUETOOTH__ +#include "typedef.h" +#include "system/event.h" + + +#define SDK_TYPE_AC690X 0x0 +#define SDK_TYPE_AC692X 0x1 +#define SDK_TYPE_AC693X 0x2 +#define SDK_TYPE_AC695X 0x3 +#define SDK_TYPE_AC697X 0x4 +#define SDK_TYPE_AC696X 0x5 +#define SDK_TYPE_AC696X_TWS 0x6 +#define SDK_TYPE_AC695X_SOUNDCARD 0x7 + +#if (defined CONFIG_CPU_BR21) +#define RCSP_SDK_TYPE SDK_TYPE_AC692X +#elif (defined CONFIG_CPU_BR22) +#define RCSP_SDK_TYPE SDK_TYPE_AC693X +#elif (defined CONFIG_CPU_BR23 && SOUNDCARD_ENABLE) +#define RCSP_SDK_TYPE SDK_TYPE_AC695X_SOUNDCARD +#elif (defined CONFIG_CPU_BR23) +#define RCSP_SDK_TYPE SDK_TYPE_AC696X//SDK_TYPE_AC695X +#elif (defined CONFIG_CPU_BR25) +#define RCSP_SDK_TYPE SDK_TYPE_AC696X +#elif (defined CONFIG_CPU_BR30) +#define RCSP_SDK_TYPE SDK_TYPE_AC697X +#else +#define RCSP_SDK_TYPE SDK_TYPE_AC693X +#endif + +// enum RCSP_ADV_MSG_T { +// MSG_JL_ADV_SETTING_SYNC, +// MSG_JL_ADV_SETTING_UPDATE, +// }; +// +// bool smartbox_adv_msg_post(int msg, int argc, ...); +int JL_smartbox_adv_event_handler(struct rcsp_event *rcsp); +int JL_smartbox_adv_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len); + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_opt.c b/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_opt.c new file mode 100644 index 0000000..7e987bc --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_opt.c @@ -0,0 +1,263 @@ +#include "smartbox/config.h" +#include "smartbox_setting_opt.h" +#include "smartbox_setting_sync.h" +#include "smartbox_rcsp_manage.h" +#include "btstack/avctp_user.h" +#include "bt_tws.h" + + +#if (SMART_BOX_EN) + +static SMARTBOX_SETTING_OPT *g_opt_link_head = NULL; +static u32 g_opt_total_size = 0; + +int register_smartbox_setting_opt_setting(void *opt_param) +{ + SMARTBOX_SETTING_OPT *opt = g_opt_link_head; + SMARTBOX_SETTING_OPT *item = (SMARTBOX_SETTING_OPT *)opt_param; + while (opt && item) { + if (opt->setting_type == item->setting_type) { + return 0; + } + opt = opt->next; + } + + if (item) { + item->next = g_opt_link_head; + g_opt_link_head = item; + return 0; + } + + return -1; +} + +static u8 deal_setting_string_item(u8 *des, u8 *src, u8 src_len, u8 type) +{ + u8 offset = 0; + if (src_len) { + des[offset++] = type; + memcpy(des + offset, src, src_len); + offset += src_len; + } + return offset; +} + +u8 smartbox_read_data_from_vm(u8 syscfg_id, u8 *buf, u8 buf_len) +{ + int len = 0; + u8 i = 0; + + len = syscfg_read(syscfg_id, buf, buf_len); + + if (len > 0) { + for (i = 0; i < buf_len; i++) { + if (buf[i] != 0xff) { + return (buf_len == len); + } + } + } + + return 0; +} + +void smart_setting_init(void) +{ + SMARTBOX_SETTING_OPT *opt = g_opt_link_head; + u32 opt_total_size = 0; + while (opt) { + u8 *data = NULL; + if (opt->data_len) { + data = zalloc(opt->data_len); + } + if (opt->custom_setting_init) { + opt->custom_setting_init(); + } else if (smartbox_read_data_from_vm(opt->syscfg_id, data, opt->data_len)) { + if (opt->set_setting && opt->deal_opt_setting) { + opt->set_setting(data); + opt->deal_opt_setting(NULL, 0, 0); + } + } + + if (data) { + free(data); + } + if (opt->data_len) { + opt_total_size += (opt->data_len + 1); + } + opt = opt->next; + } + + if (opt_total_size) { + g_opt_total_size = opt_total_size + 1; + } +} + +void update_smartbox_setting(u8 type) +{ + u16 offset = sizeof(u16); + u8 *setting_to_sync = NULL; + if (g_opt_total_size) { + setting_to_sync = zalloc(g_opt_total_size); + } else { + return; + } + SMARTBOX_SETTING_OPT *opt = g_opt_link_head; + + while (opt) { + if (((u8) - 1 == type) || (type == opt->setting_type)) { + u8 *data = NULL; + if (opt->data_len) { + data = zalloc(opt->data_len); + } + if (opt->custom_setting_update) { + opt->custom_setting_update(data); + } else if (opt->get_setting) { + opt->get_setting(data); + } + offset += deal_setting_string_item(setting_to_sync + offset, data, opt->data_len, opt->setting_type); + if (data) { + free(data); + } + } + opt = opt->next; + } + + if (offset > sizeof(u16)) { + memcpy(setting_to_sync, &offset, sizeof(offset)); + if (((u8) - 1) == type) { + tws_api_send_data_to_sibling(setting_to_sync, offset, TWS_FUNC_ID_ADV_SETTING_SYNC); + tws_api_sync_call_by_uuid(TWS_FUNC_APP_OPT_UUID, APP_OPT_SYNC_CMD_APP_RESET_LED_UI, 300); + } else { + if (tws_api_get_role() == TWS_ROLE_MASTER) { + tws_api_send_data_to_sibling(setting_to_sync, offset, TWS_FUNC_ID_ADV_SETTING_SYNC); + tws_api_sync_call_by_uuid(TWS_FUNC_APP_OPT_UUID, APP_OPT_SYNC_CMD_APP_RESET_LED_UI, 300); + } + } + } + + if (setting_to_sync) { + free(setting_to_sync); + } +} + +void deal_sibling_setting(u8 *buf) +{ + u8 type; + u16 len = 0; + memcpy(&len, buf, sizeof(len)); + u16 offset = sizeof(len); + u8 *data; + while (offset < len) { + type = buf[offset++]; + data = buf + offset; + SMARTBOX_SETTING_OPT *opt = g_opt_link_head; + while (opt) { + if (type == opt->setting_type) { + if (opt->custom_sibling_setting_deal) { + opt->custom_sibling_setting_deal(data); + } else if (opt->set_setting) { + opt->set_setting(data); + } + offset += opt->data_len; + opt->need_opt = true; + break; + } + opt = opt->next; + } + } + // 发送事件 + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_ADV_SETTING_UPDATE, NULL, 0); +} + +void update_info_from_vm_info(void) +{ + SMARTBOX_SETTING_OPT *opt = g_opt_link_head; + while (opt) { + if (opt->need_opt) { + if (opt->custom_vm_info_update) { + opt->custom_vm_info_update(); + } else if (opt->deal_opt_setting) { + opt->deal_opt_setting(NULL, 1, 0); + } + opt->need_opt = false; + } + opt = opt->next; + } +} + +SMARTBOX_SETTING_OPT *get_smartbox_setting_opt_hdl(u16 setting_type) +{ + SMARTBOX_SETTING_OPT *opt = g_opt_link_head; + while (opt) { + if (opt->setting_type == setting_type) { + return opt; + } + opt = opt->next; + } + return NULL; +} + +void set_smartbox_opt_setting(SMARTBOX_SETTING_OPT *setting_opt_hdl, u8 *data) +{ + if (setting_opt_hdl && setting_opt_hdl->deal_opt_setting) { + setting_opt_hdl->deal_opt_setting(data, 1, 1); + } +} + +int get_smartbox_opt_setting(SMARTBOX_SETTING_OPT *setting_opt_hdl, u8 *data) +{ + if (setting_opt_hdl && setting_opt_hdl->get_setting) { + return setting_opt_hdl->get_setting(data); + } + return 0; +} + +int set_setting_extra_handle(SMARTBOX_SETTING_OPT *setting_opt_hdl, void *setting_data, void *param) +{ + if (setting_opt_hdl && setting_opt_hdl->set_setting_extra_handle) { + return setting_opt_hdl->set_setting_extra_handle(setting_data, param); + } + return -1; +} + +int get_setting_extra_handle(SMARTBOX_SETTING_OPT *setting_opt_hdl, void *setting_data, void *param) +{ + if (setting_opt_hdl && setting_opt_hdl->get_setting_extra_handle) { + return setting_opt_hdl->get_setting_extra_handle(setting_data, param); + } + return 0; +} + +void smartbox_opt_release(void) +{ + SMARTBOX_SETTING_OPT *opt = g_opt_link_head; + while (opt) { + if (opt->custom_setting_release) { + opt->custom_setting_release(); + } + opt = opt->next; + } +} + +int smartbox_opt_key_event_update(int event, void *param) +{ + SMARTBOX_SETTING_OPT *opt = g_opt_link_head; + while (opt) { + if (opt->custom_setting_key_event_update) { + if (opt->custom_setting_key_event_update(event, param)) { + return true; + } + } + opt = opt->next; + } + return false; +} + +#if 1//RCSP_SMARTBOX_ADV_EN +void modify_bt_name_and_reset(u32 msec) +{ + tws_api_sync_call_by_uuid(TWS_FUNC_ID_ADV_RESET_SYNC, 0, msec); +} +#endif + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_opt.h b/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_opt.h new file mode 100644 index 0000000..ceacb76 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_opt.h @@ -0,0 +1,53 @@ +#ifndef __SMARTBOX_SETTING_OPT_H__ +#define __SMARTBOX_SETTING_OPT_H__ + +#include "system/includes.h" + +#define REGISTER_APP_SETTING_OPT(smart_opt) \ +int smart_opt##_setting_init(void) {\ + return register_smartbox_setting_opt_setting(&smart_opt);\ +}\ +late_initcall(smart_opt##_setting_init); + +#pragma pack(1) +typedef struct _SMARTBOX_SETTING_OPT { + struct _SMARTBOX_SETTING_OPT *next; + bool need_opt; + u32 data_len; + int setting_type; + int syscfg_id; + int (*get_setting)(u8 *setting_data); + void (*set_setting)(u8 *setting_data); + void (*deal_opt_setting)(u8 *setting_data, u8 write_vm, u8 tws_sync); + + // 上面是必填,下面是选填 + int (*custom_setting_init)(void); + int (*custom_vm_info_update)(void); + int (*custom_setting_update)(u8 *setting_data); + int (*custom_setting_key_event_update)(int event, void *param); + int (*custom_sibling_setting_deal)(u8 *setting_data); + int (*custom_setting_release)(void); + int (*set_setting_extra_handle)(void *setting_data, void *param); + int (*get_setting_extra_handle)(void *setting_data, void *param); +} SMARTBOX_SETTING_OPT; +#pragma pack() + +void deal_sibling_setting(u8 *buf); +u8 smartbox_read_data_from_vm(u8 syscfg_id, u8 *buf, u8 buf_len); +int register_smartbox_setting_opt_setting(void *opt_param); + +SMARTBOX_SETTING_OPT *get_smartbox_setting_opt_hdl(u16 setting_type); +void set_smartbox_opt_setting(SMARTBOX_SETTING_OPT *setting_opt, u8 *data); +int get_smartbox_opt_setting(SMARTBOX_SETTING_OPT *setting_opt, u8 *data); +int set_setting_extra_handle(SMARTBOX_SETTING_OPT *setting_opt_hdl, void *setting_data, void *param); +int get_setting_extra_handle(SMARTBOX_SETTING_OPT *setting_opt_hdl, void *setting_data, void *param); +int smartbox_opt_key_event_update(int event, void *param); + +void smart_setting_init(void); +void update_smartbox_setting(u8 type); +void update_info_from_vm_info(void); +void smartbox_opt_release(void); + +//属于弹窗 +void modify_bt_name_and_reset(u32 msec); +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_sync.c b/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_sync.c new file mode 100644 index 0000000..d71d27c --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_sync.c @@ -0,0 +1,64 @@ +#include "app_config.h" +#include "smartbox_setting_sync.h" +#include "smartbox_setting_opt.h" +#include "adv_time_stamp_setting.h" + +#if (SMART_BOX_EN && TCFG_USER_TWS_ENABLE) +static void smartbox_sync_tws_func_t(void *data, u16 len, bool rx) +{ + if (rx) { + deal_sibling_setting((u8 *)data); + } +} + +REGISTER_TWS_FUNC_STUB(adv_tws_sync) = { + .func_id = TWS_FUNC_ID_ADV_SETTING_SYNC, + .func = smartbox_sync_tws_func_t, +}; + +static void tws_app_opt_sync_call_fun(int cmd) +{ + struct sys_event event; + + event.type = SYS_BT_EVENT; + event.arg = (void *)SYS_BT_EVENT_FROM_APP_OPT_TWS; + + event.u.bt.event = APP_OPT_TWS_EVENT_SYNC_FUN_CMD; + event.u.bt.args[0] = 0; + event.u.bt.args[1] = 0; + event.u.bt.args[2] = cmd; + sys_event_notify(&event); +} + +TWS_SYNC_CALL_REGISTER(tws_app_opt_sync) = { + .uuid = TWS_FUNC_APP_OPT_UUID, + .func = tws_app_opt_sync_call_fun, +}; + +#if 1//RCSP_SMARTBOX_ADV_EN +static void adv_sync_time_stamp_func_t(void *data, u16 len, bool rx) +{ + if (rx) { + deal_sibling_time_stamp_setting_switch(data, len); + } +} + +REGISTER_TWS_FUNC_STUB(adv_time_stamp_sync) = { + .func_id = TWS_FUNC_ID_TIME_STAMP_SYNC, + .func = adv_sync_time_stamp_func_t, +}; + + +static void adv_sync_reset_sync_func_t(int args) +{ + extern void cpu_reset(); + cpu_reset(); +} + +TWS_SYNC_CALL_REGISTER(adv_reset_sync) = { + .uuid = TWS_FUNC_ID_ADV_RESET_SYNC, + .func = adv_sync_reset_sync_func_t, +}; +#endif + +#endif diff --git a/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_sync.h b/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_sync.h new file mode 100644 index 0000000..96592f5 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_sync.h @@ -0,0 +1,45 @@ +#ifndef __RCSP_ADV_TWS_SYNC_H__ +#define __RCSP_ADV_TWS_SYNC_H__ + +#include "classic/tws_api.h" + +#define TWS_FUNC_ID_ADV_SETTING_SYNC \ + TWS_FUNC_ID('R', 'C', 'S', 'P') + +#define TWS_FUNC_APP_OPT_UUID \ + TWS_FUNC_ID('A' + 'P' + 'P', \ + 'O' + 'P' + 'T', \ + 'T' + 'W' + 'S', \ + 'U' + 'U' + 'I' + 'D') + +#define SYS_BT_EVENT_FROM_APP_OPT_TWS \ + TWS_FUNC_ID('A' + 'P' + 'P', \ + 'O' + 'P' + 'T', \ + 'T' + 'S' + 'S', \ + 'E' + 'V' + 'E' + 'N' + 'T') +// ----属于弹窗---- +#define TWS_FUNC_ID_TIME_STAMP_SYNC \ + TWS_FUNC_ID('R' + 'C' + 'S' + 'P', \ + 'A' + 'D' + 'V', \ + 'T' + 'I' + 'M' + 'E', \ + 'S' + 'T' + 'A' + 'M' + 'P') + +#define TWS_FUNC_ID_ADV_RESET_SYNC \ + (((u8)('R' + 'C' + 'S' + 'P') << (3 * 8)) | \ + ((u8)('A' + 'D' + 'V') << (2 * 8)) | \ + ((u8)('R' + 'E' + 'S' + 'E' + 'T') << (1 * 8)) | \ + ((u8)('S' + 'Y' + 'N' + 'C') << (0 * 8))) +#endif +// --------------- + +enum { + APP_OPT_TWS_EVENT_SYNC_FUN_CMD, +}; + +enum { + APP_OPT_SYNC_CMD_APP_RESET_LED_UI, + APP_OPT_SYNC_CMD_MUSIC_INFO, + APP_OPT_SYNC_CMD_RCSP_AUTH_RES, + APP_OPT_SYNC_CMD_MUSIC_PLAYER_STATE, + APP_OPT_SYNC_CMD_MUSIC_PLAYER_TIEM_EN, +}; diff --git a/apps/soundbox/smartbox/smartbox_task.c b/apps/soundbox/smartbox/smartbox_task.c new file mode 100644 index 0000000..1670e62 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_task.c @@ -0,0 +1,131 @@ +#include "smartbox/smartbox_task.h" +#include "smartbox/smartbox.h" +#include "file_transfer.h" +#include "file_delete.h" +#include "dev_format.h" +#include "clock_cfg.h" +#include "app_task.h" + +#include "le_smartbox_module.h" + +#if (SMART_BOX_EN) +//这个模式主要是提供一个空模式, 处理一些需要占用时间不较长的交互处理, 处理做完之后退回到原来的模式 +struct __action_event { + u8 type; //1:手机端触发, 0:固件触发 + u8 OpCode_SN; + u8 action; +}; +static struct __action_event action_prepare = {0}; + +static void app_smartbox_task_get_ready(void) +{ + printf("%s\n", __FUNCTION__); + if (action_prepare.type) { + JL_CMD_response_send(JL_OPCODE_ACTION_PREPARE, JL_PRO_STATUS_SUCCESS, action_prepare.OpCode_SN, NULL, 0); + } +} + +static void app_smartbox_action_end_callback(void) +{ + if (app_get_curr_task() == APP_SMARTBOX_ACTION_TASK) { + printf("action end callback!!\n"); + app_task_switch_back(); + } +} + +static void app_smartbox_task_start(void) +{ + clock_add_set(SMARTBOX_ACTION_CLK); + app_smartbox_task_get_ready(); + //根据不同的场景, 做不同的处理, 例如:初始化不同的UI显示 + switch (action_prepare.action) { + case SMARTBOX_TASK_ACTION_FILE_TRANSFER: + file_transfer_init(app_smartbox_action_end_callback); + break; + case SMARTBOX_TASK_ACTION_FILE_DELETE: + file_delete_init(app_smartbox_action_end_callback); + break; + case SMARTBOX_TASK_ACTION_DEV_FORMAT: + dev_format_init(app_smartbox_action_end_callback); + break; + default: + break; + } +} + +static void app_smartbox_task_stop(void) +{ + switch (action_prepare.action) { + case SMARTBOX_TASK_ACTION_FILE_TRANSFER: + break; + case SMARTBOX_TASK_ACTION_FILE_DELETE: + break; + case SMARTBOX_TASK_ACTION_DEV_FORMAT: + break; + default: + break; + } + + clock_remove_set(SMARTBOX_ACTION_CLK); + printf("app_smartbox_task_stop\n"); +} + +static int app_smartbox_task_event_handle(struct sys_event *event) +{ + switch (action_prepare.action) { + case SMARTBOX_TASK_ACTION_FILE_TRANSFER: + break; + case SMARTBOX_TASK_ACTION_FILE_DELETE: + break; + case SMARTBOX_TASK_ACTION_DEV_FORMAT: + break; + default: + break; + } + return 0; +} + +void app_smartbox_task_prepare(u8 type, u8 action, u8 OpCode_SN) +{ + action_prepare.type = type; + action_prepare.action = action; + action_prepare.OpCode_SN = OpCode_SN; + //切换模式 + if (app_get_curr_task() != APP_SMARTBOX_ACTION_TASK) { + app_task_switch_to(APP_SMARTBOX_ACTION_TASK); + } else { + app_smartbox_task_get_ready(); + } +} + + +void app_smartbox_task(void) +{ + int msg[32]; + app_smartbox_task_start(); + while (1) { + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + if (app_smartbox_task_event_handle((struct sys_event *)(msg + 1)) == false) { + app_default_event_deal((struct sys_event *)(&msg[1])); + } + break; + default: + break; + } + + if (app_task_exitting()) { + app_smartbox_task_stop(); + return; + } + } +} +#else +void app_smartbox_task(void) +{ + +} +#endif//SMART_BOX_EN + diff --git a/apps/soundbox/smartbox/smartbox_update/rcsp_ch_loader_download.c b/apps/soundbox/smartbox/smartbox_update/rcsp_ch_loader_download.c new file mode 100644 index 0000000..c165037 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_update/rcsp_ch_loader_download.c @@ -0,0 +1,409 @@ +//#include "update_lib.h" +#include "app_config.h" +#include "update.h" +#include "uart.h" +#include "update_loader_download.h" +#include "system/fs/fs.h" +#include "smartbox_update.h" +#include "JL_rcsp_protocol.h" +#include "classic/tws_api.h" +#include "os/os_api.h" + +#include + +//#if (OTA_TWS_SAME_TIME_ENABLE && SMART_BOX_EN && USER_APP_EN) + +#include "smartbox_update_tws.h" + +#if TCFG_USER_TWS_ENABLE +#include "bt_tws.h" +#endif + +#if (SMART_BOX_EN) + +#define LOG_TAG "[RCSP-UPDATE]" +#define LOG_INFO_ENABLE +#define LOG_ERROR_ENABLE +#include "system/debug.h" + +typedef enum __DEVICE_REFRESH_FW_STATUS { + DEVICE_UPDATE_STA_SUCCESS = 0, //升级成功(default) + DEVICE_UPDATE_STA_VERIFY_ERR, //升级完校验代码出错(default) + DEVICE_UPDATE_STA_FAIL, //升级失败(default) + DEVICE_UPDATE_STA_KEY_ERR, //加密key不匹配 + DEVICE_UPDATE_STA_FILE_ERR, //升级文件出错 + DEVICE_UPDATE_STA_TYPE_ERR, //升级类型出错,仅code_type; + //DEVICE_UPDATE_STA_MAX_ERR, + DEVICE_UPDATE_STA_LOADER_DOWNLOAD_SUCC = 0x80, +} DEVICE_UPDATE_STA; + +typedef enum { + UPDATA_START = 0x00, + UPDATA_REV_DATA, + UPDATA_STOP, +} UPDATA_BIT_FLAG; + + +typedef struct _rcsp_update_param_t { + u32 state; + u32 read_len; + u32 need_rx_len; + u8 *read_buf; + void (*resume_hdl)(void *priv); + int (*sleep_hdl)(void *priv); + u32(*data_send_hdl)(void *priv, u32 offset, u16 len); + u32(*send_update_status_hdl)(void *priv, u8 state); + u32 file_offset; + u8 seek_type; +} rcsp_update_param_t; + +extern const int support_dual_bank_update_en; + +static rcsp_update_param_t rcsp_update_param; +#define __this (&rcsp_update_param) + +static u8 *bt_read_buf = NULL; +static u16 g_bt_read_len = 0; +static u32 rcsp_file_offset = 0; +static u8 rcsp_seek_type = 0; + +//NOTE:测试盒的定义和本sdk文件系统的seek_type定义不一样; +enum { + BT_SEEK_SET = 0x01, + BT_SEEK_CUR = 0x02, + + BT_SEEK_TYPE_UPDATE_LEN = 0x10, +}; + +void tws_api_auto_role_switch_disable(); +void tws_api_auto_role_switch_enable(); + +int rcsp_f_seek(void *fp, u8 type, u32 offset) +{ + if (type == SEEK_SET) { + __this->file_offset = offset; + __this->seek_type = BT_SEEK_SET; + } else if (type == SEEK_CUR) { + __this->file_offset += offset; + __this->seek_type = BT_SEEK_CUR; + } + + /* lib_printf("---------UPDATA_seek type %d, offsize %d----------\n", bt_seek_type, bt_file_offset); */ + return 0;//FR_OK; +} + +static u16 rcsp_f_stop(u8 err); + +#define RETRY_TIMES 3 +u8 get_rcsp_connect_status(); +u16 rcsp_f_read(void *fp, u8 *buff, u16 len) +{ + //printf("===rcsp_read:%x %x\n", __this->file_offset, len); + u8 retry_cnt = 0; + + __this->need_rx_len = len; + __this->state = UPDATA_REV_DATA; + __this->read_len = 0; + __this->read_buf = buff; + +#if((OTA_TWS_SAME_TIME_ENABLE && (SMART_BOX_EN))) + if ((tws_ota_control(OTA_TYPE_GET) == OTA_TWS) && + (tws_api_get_tws_state() & TWS_STA_SIBLING_DISCONNECTED)) { + //假如TWS一起升级,TWS断开了,返回失败 + r_printf("tws disconn, stop update"); + rcsp_f_stop(DEVICE_UPDATE_STA_FAIL); + return (u16) - 1; + } +#endif + +__RETRY: + if (!get_rcsp_connect_status()) { //如果已经断开连接直接返回-1 + return -1; + } + __this->data_send_hdl(fp, __this->file_offset, len); + + while (!((0 == __this->state) && (__this->read_len == len))) { + if (__this->sleep_hdl && get_rcsp_connect_status()) { + __this->sleep_hdl(NULL); + } else { + len = -1; + break; + } + + if (!((0 == __this->state) && (__this->read_len == len))) { + if (retry_cnt++ > RETRY_TIMES) { + len = (u16) - 1; + break; + } else { + goto __RETRY; + } + } + } + + if ((u16) - 1 != len) { + __this->file_offset += len; + } + + + return len; +} + +u16 rcsp_f_open(void) +{ + log_info(">>>rcsp_f_open\n"); + __this->file_offset = 0; + __this->seek_type = BT_SEEK_SET; + return 1; +} + +u16 rcsp_send_update_len(u32 update_len) +{ + /* while (0 == (bit(updata_start) & bt_updata_get_flag())); */ + /* bt_updata_clr_flag(updata_start); //clr flag */ + return 1; +} + +enum { + BT_UPDATE_OVER = 0, + BT_UPDATE_KEY_ERR, + BT_UPDATE_CONNECT_ERR, +}; + +static u8 update_result_handle(u8 err) +{ + u8 res = DEVICE_UPDATE_STA_LOADER_DOWNLOAD_SUCC; + +#if OTA_TWS_SAME_TIME_ENABLE + tws_api_auto_role_switch_enable(); +#endif + + if (err & UPDATE_RESULT_FLAG_BITMAP) { + switch (err & 0x7f) { + //升级文件错误 + case UPDATE_RESULT_FILE_SIZE_ERR: + case UPDATE_RESULT_LOADER_SIZE_ERR: + case UPDATE_RESULT_REMOTE_FILE_HEAD_ERR: + case UPDATE_RESULT_LOCAL_FILE_HEAD_ERR: + case UPDATE_RESULT_FILE_OPERATION_ERR: + case UPDATE_RESULT_NOT_FIND_TARGET_FILE_ERR: + case UPDATE_RESULT_PRODUCT_INFO_NOT_MATCH: + res = DEVICE_UPDATE_STA_FILE_ERR; + break; + //文件内容校验失败 + case UPDATE_RESULT_LOADER_VERIFY_ERR: + case UPDATE_RESULT_FLASH_DATA_VERIFY_ERR: + res = DEVICE_UPDATE_STA_VERIFY_ERR; + break; + + } + } else if (BT_UPDATE_OVER == err) { + if (support_dual_bank_update_en) { + res = DEVICE_UPDATE_STA_SUCCESS; + } else { + res = DEVICE_UPDATE_STA_LOADER_DOWNLOAD_SUCC; + } + } else if (BT_UPDATE_KEY_ERR == err) { + res = DEVICE_UPDATE_STA_KEY_ERR; + } else { + res = DEVICE_UPDATE_STA_FAIL; + } + + return res; +} + +static u16 rcsp_f_stop(u8 err) +{ + /* while (0 == (bit(updata_start) & bt_updata_get_flag())); */ + /* bt_updata_clr_flag(updata_start); //clr flag */ + + err = update_result_handle(err); + log_info(">>>rcsp_stop\n"); + __this->state = UPDATA_STOP; + + if (__this->data_send_hdl) { + __this->data_send_hdl(NULL, 0, 0); + } + + while (!(0 == __this->state)) { + if (__this->sleep_hdl && get_rcsp_connect_status()) { + if (__this->sleep_hdl(NULL) == OS_TIMEOUT) { + break; + } + } else { + break; + } + } + + if (__this->send_update_status_hdl) { + __this->send_update_status_hdl(NULL, err); + } + + return 1; +} + +#if((OTA_TWS_SAME_TIME_ENABLE && (SMART_BOX_EN))) +void db_update_notify_fail_to_phone() +{ + if (get_rcsp_connect_status()) { + rcsp_f_stop(DEVICE_UPDATE_STA_FAIL); + } +} +#endif + +__attribute__((weak)) +void user_change_ble_conn_param(u8 param_index) +{ + +} + +static int rcsp_notify_update_content_size(void *priv, u32 size) +{ + int err; + + u8 data[4]; + + WRITE_BIG_U32(data, size); + + user_change_ble_conn_param(0); + + log_info("send content_size:%x\n", size); + err = JL_CMD_send(JL_OPCODE_NOTIFY_UPDATE_CONENT_SIZE, data, sizeof(data), JL_NEED_RESPOND); + + return err; +} + +void rcsp_update_handle(u8 state, void *buf, int len) +{ + /* log_info("R"); */ + if (state != __this->state) { + log_error(">>>rcsp state err\n"); + return; + } + + switch (state) { + case UPDATA_REV_DATA: + if (__this->read_buf) { + memcpy(__this->read_buf, buf, len); + __this->read_len = len; + __this->state = 0; + } + break; + + case UPDATA_STOP: + __this->state = 0; + break; + } + + if (__this->resume_hdl) { + __this->resume_hdl(NULL); + } +} + +void rcsp_resume(void) +{ + if (__this->resume_hdl) { + __this->resume_hdl(NULL); + } +} + +static void rcsp_update_resume_hdl_register(void (*resume_hdl)(void *priv), void (*sleep_hdl)(void *priv)) +{ + __this->resume_hdl = resume_hdl; + __this->sleep_hdl = sleep_hdl; +} + +void rcsp_update_data_api_register(u32(*data_send_hdl)(void *priv, u32 offset, u16 len), u32(*send_update_status_hdl)(void *priv, u8 state)) +{ + __this->data_send_hdl = data_send_hdl; + __this->send_update_status_hdl = send_update_status_hdl; +} + +void rcsp_ch_update_init(void (*resume_hdl)(void *priv), int (*sleep_hdl)(void *priv)) +{ + log_info("------------rcsp_ch_update_init\n"); + + rcsp_update_resume_hdl_register(resume_hdl, sleep_hdl); + //register_receive_fw_update_block_handle(rcsp_updata_handle); +} + +const update_op_api_t rcsp_update_op = { + .ch_init = rcsp_ch_update_init, + .f_open = rcsp_f_open, + .f_read = rcsp_f_read, + .f_seek = rcsp_f_seek, + .f_stop = rcsp_f_stop, + .notify_update_content_size = rcsp_notify_update_content_size, +}; + +#if((OTA_TWS_SAME_TIME_ENABLE && (SMART_BOX_EN))) +const update_op_api_t rcsp_tws_update_op = { + .ch_init = rcsp_ch_update_init, + .f_open = rcsp_f_open, + .f_read = rcsp_f_read, + .f_seek = rcsp_f_seek, + .f_stop = rcsp_f_stop, + .notify_update_content_size = rcsp_notify_update_content_size, + + //for tws ota + .tws_ota_start = tws_ota_open, + .tws_ota_data_send = tws_ota_data_send_m_to_s, + .tws_ota_err = tws_ota_err_callback, + .enter_verfiy_hdl = tws_ota_enter_verify, + .exit_verify_hdl = tws_ota_exit_verify, + .update_boot_info_hdl = tws_ota_updata_boot_info_over, +}; +#endif + +extern void set_jl_update_flag(u8 flag); +static void rcsp_update_state_cbk(int type, u32 state, void *priv) +{ + update_ret_code_t *ret_code = (update_ret_code_t *)priv; + log_info("state:%x err:%x\n", ret_code->stu, ret_code->err_code); + switch (state) { + case UPDATE_CH_EXIT: + if (UPDATE_DUAL_BANK_IS_SUPPORT()) { + if ((0 == ret_code->stu) && (0 == ret_code->err_code)) { + set_jl_update_flag(1); + log_info(">>>rcsp update succ\n"); + update_result_set(UPDATA_SUCC); + + } else { + update_result_set(UPDATA_DEV_ERR); + log_info(">>>rcsp update succ\n"); + } + } else { + if ((0 == ret_code->stu) && (0 == ret_code->err_code)) { + set_jl_update_flag(1); + } + } + break; + } +} + +void rcsp_update_loader_download_init(int update_type, void (*result_cbk)(void *priv, u8 type, u8 cmd)) +{ +#if((OTA_TWS_SAME_TIME_ENABLE && (SMART_BOX_EN))) + tws_api_auto_role_switch_disable(); + if ((tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) && support_dual_bank_update_en) { //双备份才支持tws同步升级 + extern int tws_ota_init(void); + tws_ota_init(); + app_update_loader_downloader_init( + update_type, + result_cbk, + NULL, + &rcsp_tws_update_op); + } else +#endif + { + update_mode_info_t info = { + .type = update_type, + .state_cbk = rcsp_update_state_cbk, + .p_op_api = &rcsp_update_op, + .task_en = 1, + }; + app_active_update_task_init(&info); + } + +} + +#endif //(OTA_TWS_SAME_TIME_ENABLE && (SMART_BOX_EN)) diff --git a/apps/soundbox/smartbox/smartbox_update/smartbox_update.c b/apps/soundbox/smartbox/smartbox_update/smartbox_update.c new file mode 100644 index 0000000..86db412 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_update/smartbox_update.c @@ -0,0 +1,636 @@ +#include "app_config.h" +#include "smartbox_update.h" +#if RCSP_UPDATE_EN +//#include "msg.h" +#include "uart.h" +//#include "common/sys_timer.h" +#include "system/timer.h" +#include "update.h" +#include "custom_cfg.h" +//#include "irq_api.h" +#include "btstack/avctp_user.h" +#include "smartbox_misc_setting.h" +#include "smartbox_rcsp_manage.h" +#include "smartbox_bt_manage.h" +#include "update_loader_download.h" +#include "btstack_3th_protocol_user.h" +#include "le_smartbox_module.h" +#include "classic/tws_api.h" +#include "mic_effect.h" + +#if (SMART_BOX_EN) + +#define RCSP_DEBUG_EN + +#ifdef RCSP_DEBUG_EN +#define rcsp_putchar(x) putchar(x) +#define rcsp_printf printf +#define rcsp_printf_buf(x,len) printf_buf(x,len) +#else +#define rcsp_putchar(...) +#define rcsp_printf(...) +#define rcsp_printf_buf(...) +#endif + +#define DEV_UPDATE_FILE_INFO_OFFEST 0x00//0x40 +#define DEV_UPDATE_FILE_INFO_LEN 0x00//(0x10 + VER_INFO_EXT_COUNT * (VER_INFO_EXT_MAX_LEN + 1)) + +typedef enum { + UPDATA_START = 0x00, + UPDATA_REV_DATA, + UPDATA_STOP, +} UPDATA_BIT_FLAG; + +#if 0 +static update_file_id_t update_file_id_info = { + .ver[0] = 0xff, + .ver[1] = 0xff, +}; +#else +static update_file_ext_id_t update_file_id_info = { + .update_file_id_info.ver[0] = 0xff, + .update_file_id_info.ver[1] = 0xff, +}; +#endif + +extern const int support_dual_bank_update_en; +extern void ble_app_disconnect(void); +extern void updata_parm_set(UPDATA_TYPE up_type, void *priv, u32 len); +extern u8 check_le_pakcet_sent_finish_flag(void); + +static u8 update_flag = 0; +static u8 disconnect_flag = 0; + +static void smartbox_update_prepare(void) +{ + ///升级前可以选择关闭需要关闭的模块 + extern void smartbox_function_setting_stop(void); + smartbox_function_setting_stop(); + +#if (SOUNDCARD_ENABLE) + extern void soundcard_close(void); + soundcard_close(); + return ; +#endif + +#if (TCFG_MIC_EFFECT_ENABLE && (0 == SMARTBOX_REVERBERATION_SETTING)) + mic_effect_stop(); +#endif + +} + +static void smartbox_update_fail_and_resume(void) +{ +#if (TCFG_MIC_EFFECT_ENABLE) + mic_effect_start(); +#endif + +#if (SOUNDCARD_ENABLE) + extern void soundcard_start(void); + soundcard_start(); +#endif +} + +u8 get_jl_update_flag(void) +{ + printf("get_update_flag:%x\n", update_flag); + return update_flag; +} + +void set_jl_update_flag(u8 flag) +{ + update_flag = flag; + printf("update_flag:%x\n", update_flag); +} + +static u8 device_type = 0; +static void set_curr_update_type(u8 type) +{ + device_type = type; +} + +u8 get_curr_device_type(void) +{ + return device_type; +} + +typedef struct _update_mode_t { + u8 opcode; + u8 opcode_sn; + +} update_mode_t; + +static update_mode_t update_record_info; +u8 tws_need_update = 0; //标志耳机是否需要强制升级 + +static void JL_controller_save_curr_cmd_para(u8 OpCode, u8 OpCode_SN) +{ + update_record_info.opcode = OpCode; + update_record_info.opcode_sn = OpCode_SN; +} + +static void JL_controller_get_curr_cmd_para(u8 *OpCode, u8 *OpCode_SN) +{ + *OpCode = update_record_info.opcode; + *OpCode_SN = update_record_info.opcode_sn; +} + +static void (*fw_update_block_handle)(u8 state, u8 *buf, u16 len) = NULL; +static void register_receive_fw_update_block_handle(void (*handle)(u8 state, u8 *buf, u16 len)) +{ + fw_update_block_handle = handle; +} + +static u16 ble_discon_timeout; +static void ble_discon_timeout_handle(void *priv) +{ + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_UPDATE_START, NULL, 0); +} + +static u16 wait_response_timeout; +static void wait_response_and_disconn_ble(void *priv) +{ + rcsp_printf("W"); + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_DEV_DISCONNECT, NULL, 0); +} +extern u32 ex_cfg_fill_content_api(void); +static void rcsp_update_private_param_fill(UPDATA_PARM *p) +{ + u32 exif_addr; + + exif_addr = ex_cfg_fill_content_api(); + memcpy(p->parm_priv, (u8 *)&exif_addr, sizeof(exif_addr)); +} + +static void rcsp_update_before_jump_handle(int type) +{ + cpu_reset(); +} + +#define SMARTBOX_UPDATE_WAIT_SPP_DISCONN_TIME (1000) +static bool check_edr_is_disconnct(void); +static void wait_response_and_disconn_spp(void *priv) +{ + static u32 wait_time = 0; + if (check_edr_is_disconnct()) { + rcsp_printf("b"); + if (wait_time > SMARTBOX_UPDATE_WAIT_SPP_DISCONN_TIME) { + wait_time = 0; + user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL); + } else { + wait_time += 100; + } + sys_timeout_add(NULL, wait_response_and_disconn_spp, 100); + return; + } + + wait_time = 0; + if (RCSP_BLE == get_curr_device_type()) { + rcsp_printf("BLE_APP_UPDATE\n"); + update_mode_api_v2(BLE_APP_UPDATA, + rcsp_update_private_param_fill, + rcsp_update_before_jump_handle); + } else { + rcsp_printf("SPP_APP_UPDATA\n"); + update_mode_api_v2(SPP_APP_UPDATA, + rcsp_update_private_param_fill, + rcsp_update_before_jump_handle); + } +} + +int JL_rcsp_update_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len) +{ + int ret = 0; + u8 msg[4]; + rcsp_printf("%s\n", __FUNCTION__); + switch (OpCode) { + case JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET: + if (0 == len) { + msg[0] = OpCode; + msg[1] = OpCode_SN; + rcsp_printf("JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET\n"); + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, + MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET, + msg, + 2); + } else { + rcsp_printf("JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET ERR\n"); + } + break; + case JL_OPCODE_INQUIRE_DEVICE_IF_CAN_UPDATE: + rcsp_printf("JL_OPCODE_INQUIRE_DEVICE_IF_CAN_UPDATE:%x %x\n", len, data[0]); + if (len) { + set_curr_update_type(data[0]); + msg[0] = OpCode; + msg[1] = OpCode_SN; + msg[2] = 0x00; + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, + MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE, + msg, + 3); + } + break; + case JL_OPCODE_EXIT_UPDATE_MODE: + rcsp_printf("JL_OPCODE_EXIT_UPDATE_MODE\n"); + break; + case JL_OPCODE_ENTER_UPDATE_MODE: + rcsp_printf("JL_OPCODE_ENTER_UPDATE_MODE\n"); + msg[0] = OpCode; + msg[1] = OpCode_SN; + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, + MSG_JL_ENTER_UPDATE_MODE, + msg, + 2); + break; + case JL_OPCODE_SEND_FW_UPDATE_BLOCK: + rcsp_printf("JL_OPCODE_SEND_FW_UPDATE_BLOCK\n"); + break; + case JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS: + rcsp_printf("JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS\n"); + JL_controller_save_curr_cmd_para(OpCode, OpCode_SN); + if (fw_update_block_handle) { + fw_update_block_handle(UPDATA_STOP, NULL, 0); + } + break; + case JL_OPCODE_SET_DEVICE_REBOOT: + rcsp_printf("JL_OPCODE_SET_DEVICE_REBOOT\n"); + if (support_dual_bank_update_en) { + cpu_reset(); + } + break; + default: + ret = 1; + break; + } + return ret; +} + +static void JL_rcsp_resp_dev_update_file_info_offest(u8 OpCode, u8 OpCode_SN) +{ + u8 data[4 + 2]; + u16 update_file_info_offset = DEV_UPDATE_FILE_INFO_OFFEST; + u16 update_file_info_len = DEV_UPDATE_FILE_INFO_LEN; + WRITE_BIG_U32(data + 0, update_file_info_offset); + WRITE_BIG_U16(data + 4, update_file_info_len); + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, sizeof(data)); +} + +static void JL_resp_inquire_device_if_can_update(u8 OpCode, u8 OpCode_SN, u8 update_sta) +{ + u8 data[1]; + data[0] = update_sta; + JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, sizeof(data)); +} + +enum { + UPDATE_FLAG_OK, + UPDATE_FLAG_LOW_POWER, + UPDATE_FLAG_FW_INFO_ERR, + UPDATE_FLAG_FW_INFO_CONSISTENT, + UPDATE_FLAG_TWS_DISCONNECT, +}; + +static u8 judge_remote_version_can_update(void) +{ + //extern u16 ex_cfg_get_local_version_info(void); + u16 remote_file_ver = READ_BIG_U16(update_file_id_info.update_file_id_info.ver); + //u16 local_ver = ex_cfg_get_local_version_info(); + u16 local_ver = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG); + +#if (0 == VER_INFO_EXT_COUNT) + //extern u16 ex_cfg_get_local_pid_info(void); + //extern u16 ex_cfg_get_local_vid_info(void); + + //u16 local_pid = ex_cfg_get_local_pid_info(); + //u16 local_vid = ex_cfg_get_local_vid_info(); + u16 local_pid = get_vid_pid_ver_from_cfg_file(GET_PID_FROM_EX_CFG); + u16 local_vid = get_vid_pid_ver_from_cfg_file(GET_VID_FROM_EX_CFG); + + u16 remote_file_pid = READ_BIG_U16(update_file_id_info.update_file_id_info.pid); + u16 remote_file_vid = READ_BIG_U16(update_file_id_info.update_file_id_info.vid); + + if (remote_file_ver > local_ver || remote_file_pid != local_pid || remote_file_vid != local_vid) { + return UPDATE_FLAG_FW_INFO_ERR; + } +#else + //extern u32 ex_cfg_get_local_authkey_info(u8 * authkey_data[], u8 * authkey_len); + //extern u32 ex_cfg_get_local_procode_info(u8 * procode_data[], u8 * procode_len); + + u8 authkey_len = 0; + u8 *local_authkey_data = NULL; + get_authkey_procode_from_cfg_file(&local_authkey_data, &authkey_len, GET_AUTH_KEY_FROM_EX_CFG); + + u8 procode_len = 0; + u8 *local_procode_data = NULL; + get_authkey_procode_from_cfg_file(&local_procode_data, &procode_len, GET_PRO_CODE_FROM_EX_CFG); + + //ex_cfg_get_local_authkey_info(&local_authkey_data, &authkey_len); + //ex_cfg_get_local_procode_info(&local_procode_data, &procode_len); + + u8 *remote_authkey_data = update_file_id_info.ext; + u8 *remote_procode_data = update_file_id_info.ext + authkey_len + 1; + + if (remote_file_ver < local_ver + || 0 != memcmp(remote_authkey_data, local_authkey_data, authkey_len) + || 0 != memcmp(remote_procode_data, local_procode_data, procode_len)) { + return UPDATE_FLAG_FW_INFO_ERR; + } +#endif + + if (remote_file_ver == local_ver) { + rcsp_printf("remote_file_ver is %x, local_ver is %x, remote_file_ver is similar to local_ver\n", remote_file_ver, local_ver); + return UPDATE_FLAG_FW_INFO_CONSISTENT; + } + + return UPDATE_FLAG_OK; +} + +static bool check_edr_is_disconnct(void) +{ + if (get_curr_channel_state()) { + return TRUE; + } else { + return FALSE; + } +} + +static bool check_ble_all_packet_sent(void) +{ + if (check_le_pakcet_sent_finish_flag()) { + return TRUE; + } else { + return FALSE; + } +} + + +static u32 rcsp_update_data_read(void *priv, u32 offset_addr, u16 len) +{ + u32 err; + u8 data[4 + 2]; + WRITE_BIG_U32(data, offset_addr); + WRITE_BIG_U16(data + 4, len); + err = JL_CMD_send(JL_OPCODE_SEND_FW_UPDATE_BLOCK, data, sizeof(data), JL_NEED_RESPOND); + + return err; +} + +static JL_ERR JL_controller_resp_get_dev_refresh_fw_status(u8 OpCode, u8 OpCode_SN, u8 result) +{ + JL_ERR send_err = JL_ERR_NONE; + u8 data[1]; + + data[0] = result; //0:sucess 1:fail; + + send_err = JL_CMD_response_send(OpCode, JL_PRO_STATUS_SUCCESS, OpCode_SN, data, sizeof(data)); + + return send_err; +} + +static u32 rcsp_update_status_response(void *priv, u8 status) +{ + u8 OpCode; + u8 OpCode_SN; + + JL_ERR send_err = JL_ERR_NONE; + + JL_controller_get_curr_cmd_para(&OpCode, &OpCode_SN); + + //log_info("get cmd para:%x %x\n", OpCode, OpCode_SN); + + if (JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS == OpCode) { + send_err = JL_controller_resp_get_dev_refresh_fw_status(OpCode, OpCode_SN, status); + } + + return send_err; +} + + + +int JL_rcsp_update_cmd_receive_resp(void *priv, u8 OpCode, u8 status, u8 *data, u16 len) +{ + int ret = 0; + switch (OpCode) { + case JL_OPCODE_SEND_FW_UPDATE_BLOCK: + if (fw_update_block_handle) { + fw_update_block_handle(UPDATA_REV_DATA, data, len); + } + break; + default: + ret = 1; + break; + } + return ret; +} + +static void rcsp_loader_download_result_handle(void *priv, u8 type, u8 cmd) +{ + if (UPDATE_LOADER_OK == cmd) { + //JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP,MSG_JL_UPDATE_START,NULL,0); + set_jl_update_flag(1); + if (support_dual_bank_update_en) { + rcsp_printf(">>>rcsp update succ\n"); + update_result_set(UPDATA_SUCC); + } + } else { + rcsp_printf(">>>update loader err\n"); + smartbox_update_fail_and_resume(); + /* #if OTA_TWS_SAME_TIME_ENABLE */ + /* if((tws_ota_control(OTA_TYPE_GET) == OTA_TWS)) { */ + /* tws_ota_stop(OTA_STOP_UPDATE_OVER_ERR); */ + /* } */ + /* #endif */ + //rcsp_db_update_fail_deal(); + } +} + + + +extern void register_receive_fw_update_block_handle(void (*handle)(u8 state, u8 *buf, u16 len)); +extern void rcsp_update_data_api_register(u32(*data_send_hdl)(void *priv, u32 offset, u16 len), u32(*send_update_handl)(void *priv, u8 state)); +extern void rcsp_update_handle(void *buf, int len); +extern void bt_set_low_latency_mode(int enable); +extern void bt_adv_seq_change(void); +extern int bt_tws_poweroff(); +extern void bt_wait_phone_connect_control(u8 enable); +extern int tws_api_get_role(void); +int JL_rcsp_update_msg_deal(void *hdl, u8 event, u8 *msg) +{ + int ret = 0; + u16 remote_file_version; + u8 can_update_flag = UPDATE_FLAG_FW_INFO_ERR; + + printf("---%s --- %d %d\n", __func__, __LINE__, event); + switch (event) { + case MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET: + rcsp_printf("MSG_JL_GET_DEV_UPDATE_FILE_INFO_OFFSET\n"); + + /* extern void linein_mutex_stop(void *priv); */ + /* linein_mutex_stop(NULL); */ + /* extern void linein_mute(u8 mute); */ + /* linein_mute(1); */ + + JL_rcsp_resp_dev_update_file_info_offest((u8)msg[0], (u8)msg[1]); + break; + + case MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE: + rcsp_printf("MSG_JL_INQUIRE_DEVEICE_IF_CAN_UPDATE\n"); +#if 0 + remote_file_version = READ_BIG_U16(update_file_id_info.update_file_id_info.ver); + rcsp_printf("remote_file_ver:V%d.%d.%d.%d\n", + (remote_file_version & 0xf000) >> 12, + (remote_file_version & 0x0f00) >> 8, + (remote_file_version & 0x00f0) >> 4, + (remote_file_version & 0x000f)); + + if (0 == remote_file_version) { + can_update_flag = UPDATE_FLAG_OK; + } else { + can_update_flag = judge_remote_version_can_update(); + } + + if (UPDATE_FLAG_OK == can_update_flag) { + smartbox_update_prepare(); + set_jl_update_flag(1); + } +#else +#if (TCFG_USER_TWS_ENABLE && OTA_TWS_SAME_TIME_ENABLE) + int get_bt_tws_connect_status(); + if (get_bt_tws_connect_status() || (!support_dual_bank_update_en)) { //单备份返回成功 + can_update_flag = UPDATE_FLAG_OK; + } else { + can_update_flag = UPDATE_FLAG_TWS_DISCONNECT; + } +#else + can_update_flag = UPDATE_FLAG_OK; +#endif //endif OTA_TWS_SAME_TIME_ENABLE +#endif + //todo;judge voltage + JL_resp_inquire_device_if_can_update((u8)msg[0], (u8)msg[1], can_update_flag); + + if (UPDATE_FLAG_OK == can_update_flag) { + smartbox_update_prepare(); + } + + if (0 == support_dual_bank_update_en) { +#if (TCFG_USER_TWS_ENABLE == 1) + if (!tws_api_get_role()) { +#else + if (1) { +#endif + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_LOADER_DOWNLOAD_START, NULL, 0); + } else { + tws_need_update = 1; //置上该标志位APP重新连接的时候强制进入升级 + } + //bt_tws_poweroff(); //单备份升级断开tws + //bt_adv_seq_change(); + } + + break; + + case MSG_JL_DEV_DISCONNECT: + if (rcsp_send_list_is_empty() && check_ble_all_packet_sent()) { + rcsp_printf("MSG_JL_DEV_DISCONNECT\n"); + ble_app_disconnect(); + if (check_edr_is_disconnct()) { + puts("-need discon edr\n"); + user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL); + } + ble_discon_timeout = sys_timeout_add(NULL, ble_discon_timeout_handle, 1000); + } else { + wait_response_timeout = sys_timeout_add(NULL, wait_response_and_disconn_ble, 100); + } + break; + + case MSG_JL_LOADER_DOWNLOAD_START: + printf("---%s --- %d\n", __func__, __LINE__); + rcsp_update_data_api_register(rcsp_update_data_read, rcsp_update_status_response); + register_receive_fw_update_block_handle(rcsp_update_handle); + if (RCSP_BLE == get_curr_device_type()) { + rcsp_update_loader_download_init(BLE_APP_UPDATA, rcsp_loader_download_result_handle); + } else if (RCSP_SPP == get_curr_device_type()) { + rcsp_update_loader_download_init(SPP_APP_UPDATA, rcsp_loader_download_result_handle); + } + break; + + case MSG_JL_UPDATE_START: + sys_timeout_add(NULL, wait_response_and_disconn_spp, 100); + break; + + case MSG_JL_ENTER_UPDATE_MODE: + rcsp_printf("MSG_JL_ENTER_UPDATE_MODE:%x %x\n", msg[0], msg[1]); + bt_set_low_latency_mode(0); +#if TCFG_USER_TWS_ENABLE + if (support_dual_bank_update_en && !tws_api_get_role()) { +#else + if (support_dual_bank_update_en) { +#endif + u8 status = 0; + JL_CMD_response_send(msg[0], JL_PRO_STATUS_SUCCESS, msg[1], &status, 1); + rcsp_update_data_api_register(rcsp_update_data_read, rcsp_update_status_response); + register_receive_fw_update_block_handle(rcsp_update_handle); + rcsp_update_loader_download_init(DUAL_BANK_UPDATA, rcsp_loader_download_result_handle); + } + break; + + default: + ret = 1; + break; + } + return ret; +} + + +static u8 rcsp_update_flag = 0; +void set_rcsp_db_update_status(u8 value) +{ + rcsp_update_flag = value; +} + +u8 get_rcsp_db_update_status() +{ + return rcsp_update_flag; +} + +void rcsp_before_enter_db_update_mode() //进入双备份升级前 +{ + r_printf("%s", __func__); + rcsp_update_flag = 1; + void sys_auto_shut_down_disable(void); + if (get_total_connect_dev() == 0) { + sys_auto_shut_down_disable(); + } +#if TCFG_USER_TWS_ENABLE + int tws_api_get_role(void); + if (tws_api_get_role() == TWS_ROLE_SLAVE) { + return; + } +#endif + if (get_total_connect_dev()) { //断开蓝牙连接,断开之后不能让他重新开 + /* user_send_cmd_prepare(USER_CTRL_DISCONNECTION_HCI, 0, NULL); */ + } +#if TCFG_USER_TWS_ENABLE + extern void tws_cancle_all_noconn(); + /* tws_cancle_all_noconn() ; */ +#else + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL); +#endif +} + +extern void sys_auto_shut_down_enable(void); +void rcsp_db_update_fail_deal() //双备份升级失败处理 +{ + r_printf("%s", __func__); + if (rcsp_update_flag) { + rcsp_update_flag = 0; + if (get_total_connect_dev() == 0) { + sys_auto_shut_down_enable(); + } + } + /* cpu_reset(); //升级失败直接复位 */ +} + +#endif +#endif + diff --git a/apps/soundbox/smartbox/smartbox_update/smartbox_update.h b/apps/soundbox/smartbox/smartbox_update/smartbox_update.h new file mode 100644 index 0000000..4a97ab7 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_update/smartbox_update.h @@ -0,0 +1,27 @@ +#ifndef _SMARTBOX_UPDATE_H_ +#define _SMARTBOX_UPDATE_H_ + +//#include "rcsp_protocol.h" +//#include "rcsp_packet.h" +#include "typedef.h" + +#define JL_OPCODE_GET_DEVICE_UPDATE_FILE_INFO_OFFSET 0xe1 +#define JL_OPCODE_INQUIRE_DEVICE_IF_CAN_UPDATE 0xe2 +#define JL_OPCODE_ENTER_UPDATE_MODE 0xe3 +#define JL_OPCODE_EXIT_UPDATE_MODE 0xe4 +#define JL_OPCODE_SEND_FW_UPDATE_BLOCK 0xe5 +#define JL_OPCODE_GET_DEVICE_REFRESH_FW_STATUS 0xe6 +#define JL_OPCODE_SET_DEVICE_REBOOT 0xe7 +#define JL_OPCODE_NOTIFY_UPDATE_CONENT_SIZE 0xe8 + + +int JL_rcsp_update_cmd_resp(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len); +int JL_rcsp_update_msg_deal(void *hdl, u8 event, u8 *msg); + +int JL_rcsp_update_cmd_receive_resp(void *priv, u8 OpCode, u8 status, u8 *data, u16 len); +u8 get_jl_update_flag(void); +void set_jl_update_flag(u8 flag); +u8 get_curr_device_type(void); + +#endif + diff --git a/apps/soundbox/smartbox/smartbox_update/smartbox_update_tws.c b/apps/soundbox/smartbox/smartbox_update/smartbox_update_tws.c new file mode 100644 index 0000000..6889e2e --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_update/smartbox_update_tws.c @@ -0,0 +1,753 @@ +#include +#include +#include + +#include "generic/circular_buf.h" +#include "os/os_api.h" +#include "update_loader_download.h" +#include "system/task.h" +#include "system/timer.h" +#include "init.h" +#include "smartbox_update_tws.h" +#include "dual_bank_updata_api.h" +#include "bt_tws.h" +#include "app_config.h" +#include "btstack/avctp_user.h" +#include "update.h" +#include "app_main.h" + +#if (SMART_BOX_EN && OTA_TWS_SAME_TIME_ENABLE) + +//#define LOG_TAG_CONST EARPHONE +#define LOG_TAG "[UPDATE_TWS]" +#define log_errorOR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#define THIS_TASK_NAME "tws_ota" +#define SLAVE_REV_BUF_LEN 1024*2 + +enum { + TWS_UPDATE_START, + TWS_UPDATE_RESULT_EXCHANGE, + TWS_UPDATE_RESULT_EXCHANGE_RES, + TWS_UPDATE_OVER, + TWS_UPDATE_OVER_CONFIRM, + TWS_UPDATE_OVER_CONFIRM_REQ, + TWS_UPDATE_OVER_CONFIRM_RES, + TWS_UPDATE_VERIFY, +}; + +extern void sys_enter_soft_poweroff(void *priv); + +void db_update_notify_fail_to_phone(); + +struct __tws_ota_var { + OS_SEM master_sem; + OS_SEM slave_sem; + OS_SEM confirm_sem; + struct __tws_ota_para para; + u8 ota_type; + u8 ota_status; + u8 ota_remote_status; + u8 ota_result; + volatile u32 ota_data_len; + u16 ota_timer_id; + u8 ota_verify_cnt; + volatile u32 ota_confirm; + cbuffer_t cbuffer; + u8 *slave_r_buf; +}; +struct __tws_ota_var tws_ota_var; +#define __this (&tws_ota_var) + +void tws_ota_event_post(u32 type, u8 event) +{ + struct sys_event e; + e.type = SYS_BT_EVENT; + e.arg = (void *)type; + e.u.bt.event = event; + sys_event_notify(&e); +} + +u8 tws_ota_control(int type, ...) +{ + int ret = 0; + int role = 0; + int value = 0; + + va_list argptr; + va_start(argptr, type); + + switch (type) { + case OTA_TYPE_SET: + value = va_arg(argptr, int); + __this->ota_type = value; + break; + case OTA_TYPE_GET: + ret = __this->ota_type; + break; + case OTA_STATUS_SET: + value = va_arg(argptr, int); + __this->ota_status = value; + break; + case OTA_STATUS_GET: + ret = __this->ota_status; + break; + case OTA_REMOTE_STATUS_SET: + value = va_arg(argptr, int); + __this->ota_remote_status = value; + break; + case OTA_REMOTE_STATUS_GET: + ret = __this->ota_remote_status; + break; + case OTA_RESULT_SET: + value = va_arg(argptr, int); + role = va_arg(argptr, int); + if (value == 1) { + __this->ota_result |= BIT(role); + } else { + __this->ota_result &= ~BIT(role); + } + break; + case OTA_RESULT_GET: + ret = __this->ota_result; + break; + } + + va_end(argptr); + + return ret; +} + +int tws_ota_init(void) +{ + memset((u8 *)__this, 0, sizeof(struct __tws_ota_var)); + __this->ota_status = OTA_INIT; + __this->ota_type = OTA_TWS; + + if (a2dp_get_status() == BT_MUSIC_STATUS_STARTING) { + /* log_info("try pause a2dp music"); */ + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_PAUSE, 0, NULL); + } + return 0; +} + +#define TWS_FUNC_ID_OTA_SYNC TWS_FUNC_ID('O', 'T', 'A', 'S') +static void tws_ota_data_read_s_from_m(void *_data, u16 len, bool rx) +{ + if (rx && __this->ota_status == OTA_START && __this->slave_r_buf) { + /* r_log_info("Offset:%x r_len:%d\n",__this->ota_data_len,len); */ + /* put_buf(_data, len); */ + __this->ota_data_len += len; + if (cbuf_is_write_able(&(__this->cbuffer), len)) { + cbuf_write(&(__this->cbuffer), _data, len); + } else { + log_info("ota cbuf write err\n"); + } + os_sem_post(&__this->slave_sem); + } +} + +REGISTER_TWS_FUNC_STUB(app_ota_sync_stub) = { + .func_id = TWS_FUNC_ID_OTA_SYNC, + .func = tws_ota_data_read_s_from_m, +}; + +int tws_ota_data_send_m_to_s(u8 *buf, u16 len) +{ + if (!(tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED)) { + return 0; + } + + if (tws_api_get_role() == TWS_ROLE_SLAVE) { + return 0; + } + + int ret = tws_api_send_data_to_slave(buf, len, TWS_FUNC_ID_OTA_SYNC); + return ret; +} + +int tws_ota_err_callback(u8 reason) +{ + tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_UPDATE_ERR); + return 0; +} + +static void tws_ota_update_loop(void *priv) +{ + u32 total_len = 0; + u32 len = 0; + u8 *tmp_buf = NULL; + int ret = 0; + + u8 sniff_wait_exit_timeout = 30;//3s + + log_info("tws_ota_update_loop\n"); + + while (1) { + os_sem_pend(&__this->slave_sem, 0); + + if (sniff_wait_exit_timeout) { + //wait slave exit sniff + extern u8 btstcak_get_bt_mode(void); + while (btstcak_get_bt_mode() && sniff_wait_exit_timeout--) { + log_info("wait sniff exit \n"); + os_time_dly(10); + } + log_info(">>>>>>>sniff timeout:%d \n", sniff_wait_exit_timeout); + + if (!sniff_wait_exit_timeout) { + log_info(">>>>>>wait sniff exit timeout !!!! \n"); + } + sniff_wait_exit_timeout = 0; + dual_bank_passive_update_init(__this->para.fm_crc16, __this->para.fm_size, __this->para.max_pkt_len, NULL); + ret = dual_bank_update_allow_check(__this->para.fm_size); + if (ret) { + log_info("fm_size:%x can't update\n", __this->para.fm_size); + tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_UPDATE_ERR); + continue; + } + tws_api_sync_call_by_uuid(0xA2E22223, SYNC_CMD_START_UPDATE, 400); + continue; + } + + total_len = cbuf_get_data_size(&(__this->cbuffer)); + /* log_info("total_len : %d\n",total_len); */ + while (total_len) { + if (total_len > get_dual_bank_passive_update_max_buf()) { + len = get_dual_bank_passive_update_max_buf(); + } else { + len = total_len; + } + + if (!len) { + continue; + } + tmp_buf = malloc(len); + if (tmp_buf) { + if (cbuf_read(&(__this->cbuffer), tmp_buf, len) == len) { + putchar('D'); + dual_bank_update_write(tmp_buf, len, NULL); + } else { + log_error("read err\n"); + } + free(tmp_buf); + } else { + log_error("malloc err\n"); + } + total_len -= len; + } + } +} + +static void ota_finish_confirm(void *priv) +{ + log_info("ota_finish_confirm:%d\n", __this->ota_confirm); + if (!__this->ota_confirm) { + //ota tws confirm err,earse boot info + flash_update_clr_boot_info(CLEAR_APP_UPDATE_BANK); + /* ASSERT(0, "ota tws confirm err\n"); */ + } + tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_UPDATE_SUCC); + +} + +u16 tws_ota_enter_verify(void *priv) +{ + if (tws_api_get_tws_state() & TWS_STA_SIBLING_DISCONNECTED) { + log_info("tws_disconn in verify\n"); + db_update_notify_fail_to_phone(); + return -1; + } + tws_ota_send_data_to_sibling(TWS_UPDATE_VERIFY, NULL, 0); + os_sem_pend(&__this->master_sem, 1000); + //这里pend完,要做超时的准备 + if (__this->ota_status == OTA_VERIFY_ING) { + return 0; + } else { + db_update_notify_fail_to_phone(); + return -1; + } +} + +u16 tws_ota_exit_verify(u8 *res, u8 *up_flg) +{ + //not updata boot info in lib + *up_flg = 1; + + u8 tws_ota_result[2]; + u8 master_result = *res; + u8 result = 0; + tws_ota_control(OTA_STATUS_SET, OTA_VERIFY_END); + tws_ota_control(OTA_RESULT_SET, !master_result, TWS_ROLE_MASTER); +__RESTART: + if (tws_api_get_tws_state() & TWS_STA_SIBLING_DISCONNECTED) { + db_update_notify_fail_to_phone(); + return 0; + } + result = tws_ota_control(OTA_RESULT_GET); + tws_ota_result[0] = result; + tws_ota_result[1] = tws_ota_control(OTA_STATUS_GET); + tws_ota_send_data_to_sibling(TWS_UPDATE_RESULT_EXCHANGE, (u8 *)&tws_ota_result, 2); + + if ((result & BIT(TWS_ROLE_SLAVE)) && (result & BIT(TWS_ROLE_SLAVE))) { + log_info("tws already ota succ1\n"); + os_sem_set(&__this->master_sem, 0); + tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_UPDATE_OVER); + return 1; + } else if (__this->ota_remote_status == OTA_VERIFY_END || __this->ota_remote_status == OTA_OVER) { + tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_UPDATE_ERR); + return 0; + } else { + os_sem_pend(&__this->master_sem, 200); + goto __RESTART; + } + return 1; +} + +u16 tws_ota_updata_boot_info_over(void *priv) +{ + log_info("master update_burn_boot_info succ\n"); + if (tws_api_get_tws_state() & TWS_STA_SIBLING_DISCONNECTED) { + log_info("tws_disconn, ota open fail"); + db_update_notify_fail_to_phone(); + return -1; + } + + //等待从机更新完成 + log_info("1------pend in"); + os_sem_pend(&__this->confirm_sem, 300); + log_info("1------pend out"); + + log_info("-------mz01"); + if (__this->ota_confirm) { + log_info("-------mz02"); + os_sem_set(&__this->confirm_sem, 0); + tws_ota_send_data_to_sibling(TWS_UPDATE_OVER_CONFIRM_REQ, NULL, 0); + log_info("2------pend in"); + if (OS_TIMEOUT == os_sem_pend(&__this->confirm_sem, 300)) { + __this->ota_confirm = 0; + } + log_info("2------pend out"); + } + + if (!__this->ota_confirm) { + log_info("-------mz03"); + //ota tws confirm err,earse boot info + flash_update_clr_boot_info(CLEAR_APP_UPDATE_BANK); + /* ASSERT(0, "ota tws confirm err\n"); */ + return -1; + } + /* tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS,OTA_UPDATE_SUCC); //主机等手机发重启命令*/ + return 0; + +} + +int tws_ota_open(struct __tws_ota_para *para) +{ + int ret = 0; + log_info("tws_ota_open\n"); + + if (tws_api_get_tws_state() & TWS_STA_SIBLING_DISCONNECTED) { + log_info("tws_disconn, ota open fail"); + db_update_notify_fail_to_phone(); + return -1; + } + + os_sem_create(&__this->master_sem, 0); + os_sem_create(&__this->slave_sem, 0); + os_sem_create(&__this->confirm_sem, 0); + + if (tws_api_get_role() == TWS_ROLE_MASTER) { + extern void bt_check_exit_sniff(); + bt_check_exit_sniff(); + //master 发命令给slave启动升级 + + + log_info("master updata info: crc16:%x size:%x max_pkt_len:%d\n", para->fm_crc16, para->fm_size, para->max_pkt_len); + if (__this->ota_type == OTA_TWS) { + tws_ota_send_data_to_sibling(TWS_UPDATE_START, (u8 *)para, sizeof(struct __tws_ota_para)); + log_info("sem pend in ..."); + os_sem_pend(&__this->master_sem, 600); + log_info("sem pend out ..."); + //判断对耳状态 + if (__this->ota_status == OTA_START) { + log_info("slave has ready"); + ret = 0; + } else { + log_info("slave answer timeout"); + db_update_notify_fail_to_phone(); + ret = -1; + } + } + } else { + log_info("slave updata info: crc16:%x size:%x max_pkt_len:%d\n", para->fm_crc16, para->fm_size, para->max_pkt_len); + + /* tws_api_sync_call_by_uuid('T', SYNC_CMD_START_UPDATE, 100); */ + tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_START_UPDATE_READY); + } + return ret; +} + +int tws_ota_close(void) +{ + int ret = 0; + log_info("%s", __func__); + if (__this->slave_r_buf) { + free(__this->slave_r_buf); + __this->slave_r_buf = 0; + task_kill(THIS_TASK_NAME); + } + return ret; +} + +static void ota_verify_timeout(void *priv) +{ + log_info("ota_verify_timeout:%x %x\n", __this->para.fm_size, __this->ota_data_len); + if (__this->ota_data_len == __this->para.fm_size) { + /* tws_api_sync_call_by_uuid('T', SYNC_CMD_START_VERIFY, 100); */ + tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_START_VERIFY); + return; + } + + if (__this->ota_verify_cnt > 4) { + log_info("code len err\n"); + tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_UPDATE_ERR); + sys_timeout_del(__this->ota_timer_id); + __this->ota_timer_id = 0; + return; + } + + __this->ota_verify_cnt ++; + __this->ota_timer_id = 0; + __this->ota_timer_id = sys_timeout_add(NULL, ota_verify_timeout, 500); +} + +int tws_ota_get_data_from_sibling(u8 opcode, u8 *data, u8 len) +{ + u8 tws_ota_result[2]; + switch (opcode) { + //master->slave + case TWS_UPDATE_START: + log_info("TWS_AI_START_UPDATE:%d\n", opcode); + if (tws_api_get_role() == TWS_ROLE_SLAVE) { + if (__this->slave_r_buf) { + tws_ota_close(); + } + tws_ota_init(); + memcpy((u8 *) & (__this->para), data, len); + tws_ota_open(&(__this->para)); + } + break; + + //master->slave + case TWS_UPDATE_RESULT_EXCHANGE: + log_info("TWS_UPDATE_RESULT_EXCHANGE:%d %d\n", data[0], data[1]); + __this->ota_remote_status = data[1]; + tws_ota_control(OTA_RESULT_SET, (data[0] & BIT(TWS_ROLE_MASTER) ? 1 : 0), TWS_ROLE_MASTER); + + tws_ota_result[0] = __this->ota_result; + tws_ota_result[1] = __this->ota_status; + tws_ota_send_data_to_sibling(TWS_UPDATE_RESULT_EXCHANGE_RES, (u8 *)tws_ota_result, 2); + log_info("master ota result:%x %d\n", tws_ota_control(OTA_RESULT_GET), __this->ota_status); + break; + + //slave->master + case TWS_UPDATE_RESULT_EXCHANGE_RES: + log_info("TWS_UPDATE_RESULT_EXCHANGE_RES:%d %d\n", data[0], data[1]); + __this->ota_remote_status = data[1]; + tws_ota_control(OTA_RESULT_SET, (data[0] & BIT(TWS_ROLE_SLAVE) ? 1 : 0), TWS_ROLE_SLAVE); + log_info("slave ota result:%x %d\n", tws_ota_control(OTA_RESULT_GET), __this->ota_status); + + if (tws_ota_control(OTA_RESULT_GET) & BIT(TWS_ROLE_SLAVE)) { + os_sem_post(&__this->master_sem); + } + break; + + //master->slave + case TWS_UPDATE_VERIFY: + log_info("TWS_UPDATE_VERIFY\n"); + tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_START_VERIFY); + break; + + case TWS_UPDATE_OVER: + log_info("TWS_AI_UPDATE_OVER:%d\n", opcode); + __this->ota_status = OTA_OVER; + break; + + //slave to master + case TWS_UPDATE_OVER_CONFIRM: + log_info("TWS_UPDATE_OVER_CONFIRM\n"); + __this->ota_confirm = 1; + if (tws_api_get_role() == TWS_ROLE_MASTER) { + log_info("1------post"); + os_sem_post(&__this->confirm_sem); + } + break; + //master->slave + case TWS_UPDATE_OVER_CONFIRM_REQ: + log_info("TWS_UPDATE_OVER_CONFIRM_REQ\n"); + if (tws_api_get_role() == TWS_ROLE_SLAVE) { + __this->ota_confirm = 1; + tws_ota_send_data_to_sibling(TWS_UPDATE_OVER_CONFIRM_RES, NULL, 0); + log_info("2------post"); + os_sem_post(&__this->confirm_sem); + } + break; + //slave->master + case TWS_UPDATE_OVER_CONFIRM_RES: + log_info("TWS_UPDATE_OVER_CONFIRM_RES\n"); + if (tws_api_get_role() == TWS_ROLE_MASTER) { + log_info("3------post"); + os_sem_post(&__this->confirm_sem); + } + break; + } + return 0; +} + +void tws_ota_send_data_to_sibling(u8 opcode, u8 *data, u8 len) +{ + extern void tws_data_to_sibling_send(u8 opcode, u8 * data, u8 len); + tws_data_to_sibling_send(opcode, data, len); +} + + + +u8 dual_bank_update_burn_boot_info_callback(u8 ret) +{ + if (ret) { + log_info("update_burn_boot_info err\n"); + } else { + log_info("slave update_burn_boot_info succ\n"); + tws_ota_send_data_to_sibling(TWS_UPDATE_OVER_CONFIRM, NULL, 0); + + //not recive master confirm + log_info("3------pend in"); + os_sem_pend(&__this->confirm_sem, 300); + log_info("3------pend out"); + + if (!__this->ota_confirm) { + //ota tws confirm err,earse boot info + flash_update_clr_boot_info(CLEAR_APP_UPDATE_BANK); + /* ASSERT(0, "ota tws confirm err\n"); */ + return 0; + } + + //确保从机的回复命令送达到主机 + os_time_dly(50); + + tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS, OTA_UPDATE_SUCC); + return 0; + } + + return 1; +} + +//slave ota result +static sint32_t gma_ota_slave_result(int crc_res) +{ + u8 ret = crc_res; + + tws_ota_control(OTA_STATUS_SET, OTA_VERIFY_END); + + tws_ota_control(OTA_RESULT_SET, crc_res, TWS_ROLE_SLAVE); + + log_info("gma_ota_slave_result:%d %d\n", crc_res, tws_ota_control(OTA_STATUS_GET)); + return 0; +} + +int tws_ota_sync_cmd(int reason) +{ + int ret = 1; + + switch (reason) { + //slave request + case SYNC_CMD_START_UPDATE: + log_info("SYNC_CMD_START_UPDATE\n"); + + if (__this->ota_status != OTA_INIT) { + log_info("tws ota no init"); + break; + } + __this->ota_status = OTA_START; + __this->ota_data_len = 0; + __this->ota_remote_status = OTA_START; + if (tws_api_get_role() == TWS_ROLE_MASTER) { + os_sem_post(&__this->master_sem); + } else { + } + break; + + //slave request + case SYNC_CMD_START_VERIFY: + log_info("SYNC_CMD_START_VERIFY\n"); + __this->ota_status = OTA_VERIFY_ING; + __this->ota_remote_status = OTA_VERIFY_ING; + + if (tws_api_get_role() == TWS_ROLE_MASTER) { + os_sem_post(&__this->master_sem); + } else { + dual_bank_update_verify(NULL, NULL, gma_ota_slave_result); + } + break; + + //master request + case SYNC_CMD_UPDATE_OVER: + log_info("SYNC_CMD_UPDATE_OVER\n"); + + __this->ota_status = OTA_OVER; + __this->ota_remote_status = OTA_OVER; + if ((__this->ota_result & BIT(TWS_ROLE_MASTER)) && (__this->ota_result & BIT(TWS_ROLE_SLAVE))) { + log_info("OTA SUCCESS\n"); + //update boot info + if (tws_api_get_role() == TWS_ROLE_SLAVE) { + dual_bank_update_burn_boot_info(dual_bank_update_burn_boot_info_callback); + } + } else { + log_info("OTA ERR\n"); + /* tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS,OTA_UPDATE_SUCC); */ + } + break; + + //slave request + case SYNC_CMD_UPDATE_ERR: + log_info("SYNC_CMD_UPDATE_ERR\n"); + if (tws_api_get_role() == TWS_ROLE_MASTER) { + } else { + tws_ota_stop(OTA_STOP_UPDATE_OVER_ERR); + } + break; + + default: + ret = 0; + break; + } + return ret; +} + +void tws_ota_app_event_deal(u8 evevt) +{ + if (__this->ota_status == OTA_OVER) { + return; + } + + switch (evevt) { + case TWS_EVENT_CONNECTION_DETACH: + /* case TWS_EVENT_PHONE_LINK_DETACH: */ + case TWS_EVENT_REMOVE_PAIRS: + log_info("stop ota : %d --1\n", evevt); + tws_ota_stop(OTA_STOP_LINK_DISCONNECT); + break; + default: + break; + } +} + +void tws_ota_stop(u8 reason) +{ + log_info("%s", __func__); + + if (__this->ota_status != OTA_OVER) { + + //reconnect hfp when start err + if (reason == OTA_STOP_APP_DISCONNECT || reason == OTA_STOP_UPDATE_OVER_ERR) { + //在更新信息的时候,手机app断开 + + /* if(tws_api_get_role() == TWS_ROLE_MASTER) { */ + /* extern void user_post_key_msg(u8 user_msg); */ + /* user_post_key_msg(USER_TWS_OTA_RESUME); */ + /* } */ + } + + __this->ota_status = OTA_OVER; + if (__this->ota_timer_id) { + sys_timeout_del(__this->ota_timer_id); + __this->ota_timer_id = 0; + } + + tws_ota_close(); + dual_bank_passive_update_exit(NULL); + extern void rcsp_db_update_fail_deal(); //双备份升级失败处理 + rcsp_db_update_fail_deal(); + } +} + +int bt_ota_event_handler(struct bt_event *bt) +{ + int ret = 0; + switch (bt->event) { + case OTA_START_UPDATE: + log_info("OTA_START_UPDATE\n"); + tws_api_sync_call_by_uuid(0xA2E22223, SYNC_CMD_START_UPDATE, 400); + break; + case OTA_START_UPDATE_READY: + log_info("OTA_START_UPDATE_READY:%x %x %d\n", __this->para.fm_crc16, __this->para.fm_size, __this->para.max_pkt_len); + extern void rcsp_before_enter_db_update_mode(); + rcsp_before_enter_db_update_mode(); + if (__this->slave_r_buf) { + ASSERT(0, "tws_ota_update_loop already exit\n"); + } + task_create(tws_ota_update_loop, NULL, THIS_TASK_NAME); + __this->slave_r_buf = malloc(SLAVE_REV_BUF_LEN); + ASSERT(__this->slave_r_buf, "slave_r_buf malloc err\n"); + cbuf_init(&(__this->cbuffer), __this->slave_r_buf, SLAVE_REV_BUF_LEN); + + os_sem_post(&__this->slave_sem); + /* tws_ota_event_post(SYS_BT_OTA_EVENT_TYPE_STATUS,OTA_START_UPDATE); */ + break; + case OTA_START_VERIFY: + log_info("OTA_START_VERIFY\n"); + if (__this->ota_data_len == __this->para.fm_size) { + tws_api_sync_call_by_uuid(0xA2E22223, SYNC_CMD_START_VERIFY, 1000); + } else { + if (__this->ota_timer_id) { + sys_timeout_del(__this->ota_timer_id); + __this->ota_timer_id = 0; + } + __this->ota_timer_id = sys_timeout_add(NULL, ota_verify_timeout, 500); + } + break; + case OTA_UPDATE_OVER: + log_info("OTA_UPDATE_OVER\n"); + tws_api_sync_call_by_uuid(0xA2E22223, SYNC_CMD_UPDATE_OVER, 400); + break; + case OTA_UPDATE_ERR: + log_info("OTA_UPDATE_ERR\n"); + tws_api_sync_call_by_uuid(0xA2E22223, SYNC_CMD_UPDATE_ERR, 400); + break; + case OTA_UPDATE_SUCC: + log_info("OTA_UPDATE_SUCC\n"); + update_result_set(UPDATA_SUCC); + dual_bank_passive_update_exit(NULL); + + /* update_result_set(UPDATA_SUCC); */ + /* extern void cpu_reset(); */ + /* cpu_reset(); */ + //user_ctl.shutdown_need_adv = 0; + sys_enter_soft_poweroff((void *)1); + break; + default: + break; + } + + return 0; +} + +static void smartbox_tws_ota_sync_handler(int reason, int err) +{ + tws_ota_sync_cmd(reason); +} + +TWS_SYNC_CALL_REGISTER(smartbox_tws_ota_sync) = { + .uuid = 0xA2E22223, + .task_name = "app_core", + .func = smartbox_tws_ota_sync_handler, +}; + +#endif + diff --git a/apps/soundbox/smartbox/smartbox_update/smartbox_update_tws.h b/apps/soundbox/smartbox/smartbox_update/smartbox_update_tws.h new file mode 100644 index 0000000..b036032 --- /dev/null +++ b/apps/soundbox/smartbox/smartbox_update/smartbox_update_tws.h @@ -0,0 +1,92 @@ +#ifndef _SMARTBOX_TWS_OTA_H +#define _SMARTBOX_TWS_OTA_H + +#include "app_config.h" + +#if (OTA_TWS_SAME_TIME_ENABLE && SMART_BOX_EN) + +#define SYS_BT_OTA_EVENT_TYPE_STATUS (('O' << 24) | ('T' << 16) | ('A' << 8) | '\0') + +#include "system/event.h" +#include "update_loader_download.h" + +typedef int sint32_t; + +enum { + OTA_OVER = 0, + OTA_INIT, + OTA_START, + OTA_VERIFY_ING, + OTA_VERIFY_END, + OTA_SUCC, +}; + +enum { + OTA_SINGLE_EARPHONE, + OTA_TWS, +}; + +enum { + OTA_START_UPDATE = 0, + OTA_START_UPDATE_READY, + OTA_START_VERIFY, + OTA_UPDATE_OVER, + OTA_UPDATE_ERR, + OTA_UPDATE_SUCC, +}; + +enum { + OTA_TYPE_SET = 0, + OTA_TYPE_GET, + OTA_STATUS_SET, + OTA_STATUS_GET, + OTA_REMOTE_STATUS_SET, + OTA_REMOTE_STATUS_GET, + OTA_RESULT_SET, + OTA_RESULT_GET, +}; + + +enum { + OTA_STOP_APP_DISCONNECT, + OTA_STOP_LINK_DISCONNECT, + OTA_STOP_UPDATE_OVER_SUCC, + OTA_STOP_UPDATE_OVER_ERR, + OTA_STOP_PHONE, +}; + +enum { + SYNC_CMD_START_UPDATE, + SYNC_CMD_START_VERIFY, + SYNC_CMD_UPDATE_OVER, + SYNC_CMD_UPDATE_ERR, +}; + +int tws_ota_init(void); +int tws_ota_close(void); + +int tws_ota_open(struct __tws_ota_para *para); +void tws_ota_stop(u8 reason); + +u16 tws_ota_enter_verify(void *priv); +u16 tws_ota_exit_verify(u8 *res, u8 *up_flg); +u16 tws_ota_updata_boot_info_over(void *priv); + +int tws_ota_err_callback(u8 reason); + +int tws_ota_data_send_m_to_s(u8 *buf, u16 len); +int tws_ota_sync_cmd(int reason); +void tws_ota_app_event_deal(u8 evevt); +u8 dual_bank_update_burn_boot_info_callback(u8 ret); +int bt_ota_event_handler(struct bt_event *bt); +void tws_ota_event_post(u32 type, u8 event); + +u8 tws_ota_control(int type, ...); + +void tws_ota_send_data_to_sibling(u8 opcode, u8 *data, u8 len); +int tws_ota_get_data_from_sibling(u8 opcode, u8 *data, u8 len); + +#endif //(OTA_TWS_SAME_TIME_ENABLE && SMART_BOX_EN) + +#endif //_SMARTBOX_TWS_OTA_H + diff --git a/apps/soundbox/smartbox/switch_device.c b/apps/soundbox/smartbox/switch_device.c new file mode 100644 index 0000000..940aa14 --- /dev/null +++ b/apps/soundbox/smartbox/switch_device.c @@ -0,0 +1,44 @@ +#include "smartbox/config.h" +#include "smartbox/feature.h" +#include "btstack/avctp_user.h" +#include "smartbox/event.h" +#include "smartbox_rcsp_manage.h" +#include "smartbox_bt_manage.h" +#include "smartbox_update.h" + +#include "app_main.h" + +#if (SMART_BOX_EN) + +/* #define RCSP_DEBUG_EN */ + +#ifdef RCSP_DEBUG_EN +#define rcsp_putchar(x) putchar(x) +#define rcsp_printf printf +#define rcsp_printf_buf(x,len) printf_buf(x,len) +#else +#define rcsp_putchar(...) +#define rcsp_printf(...) +#define rcsp_printf_buf(...) +#endif + +void smartbox_switch_device(u8 *data) +{ +#if RCSP_UPDATE_EN + if (get_jl_update_flag()) { + if (RCSP_BLE == bt_3th_get_cur_bt_channel_sel()) { + rcsp_printf("BLE_ CON START DISCON\n"); + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_DEV_DISCONNECT, NULL, 0); + } else { + rcsp_printf("WAIT_FOR_SPP_DISCON\n"); + } + } else { + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_SWITCH_DEVICE, &data[0], 1); + } +#else + JL_rcsp_event_to_user(DEVICE_EVENT_FROM_RCSP, MSG_JL_SWITCH_DEVICE, &data[0], 1); +#endif +} +#endif//SMART_BOX_EN + + diff --git a/apps/soundbox/smartbox/tuya/tuya_demo.c b/apps/soundbox/smartbox/tuya/tuya_demo.c new file mode 100644 index 0000000..fc516c2 --- /dev/null +++ b/apps/soundbox/smartbox/tuya/tuya_demo.c @@ -0,0 +1,1223 @@ +/********************************************************************************************* + * Filename : tuya_demo.c + + * Description : + + * Author : + + * Email : zh-jieli.com + + * Last modifiled : 2017-01-17 11:14 + + * Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved. +*********************************************************************************************/ + +// ***************************************************************************** +/* EXAMPLE_START(le_counter): LE Peripheral - Heartbeat Counter over GATT + * + * @text All newer operating systems provide GATT Client functionality. + * The LE Counter examples demonstrates how to specify a minimal GATT Database + * with a custom GATT Service and a custom Characteristic that sends periodic + * notifications. + */ +// ***************************************************************************** +#include "system/app_core.h" +#include "system/includes.h" + +#include "app_config.h" +#include "app_action.h" + +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "user_cfg.h" +#include "vm.h" +#include "btcontroller_modules.h" +#include "bt_common.h" +#include "3th_profile_api.h" + +#include "le_common.h" + +#include "rcsp_bluetooth.h" +#include "JL_rcsp_api.h" +#include "custom_cfg.h" + +#include "tuya_demo.h" +#include "tuya_ble_api.h" + + + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_TUYA) + +//TRANS ANCS +#define TRANS_ANCS_EN 0 +#if TRANS_ANCS_EN +#include "btstack/btstack_event.h" +#endif + +#define TEST_SEND_HANDLE_VAL ATT_CHARACTERISTIC_ae02_01_VALUE_HANDLE +/* #define TEST_SEND_HANDLE_VAL ATT_CHARACTERISTIC_ae05_01_VALUE_HANDLE */ +#define EXT_ADV_MODE_EN 0 + +#define TEST_AUDIO_DATA_UPLOAD 0 //测试文件上传 + +#if 1//LE_DEBUG_PRINT_EN +extern void printf_buf(u8 *buf, u32 len); +/* #define log_info printf */ +#define log_info(x, ...) printf("[tuya_demo]" x " ", ## __VA_ARGS__) +#define log_info_hexdump printf_buf +#else +#define log_info(...) +#define log_info_hexdump(...) +#endif + + +/* #define LOG_TAG_CONST BT_BLE */ +/* #define LOG_TAG "[LE_S_DEMO]" */ +/* #define LOG_ERROR_ENABLE */ +/* #define LOG_DEBUG_ENABLE */ +/* #define LOG_INFO_ENABLE */ +/* #define LOG_DUMP_ENABLE */ +/* #define LOG_CLI_ENABLE */ +/* #include "debug.h" */ + +//------ +//ATT发送的包长, note: 20 <=need >= MTU + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x04) +#define ATT_LOCAL_MTU_SIZE (246) // +//ATT缓存的buffer大小, note: need >= 20,可修改 +#define ATT_SEND_CBUF_SIZE (246) // +#else +#define ATT_LOCAL_MTU_SIZE (23) // +//ATT缓存的buffer大小, note: need >= 20,可修改 +#define ATT_SEND_CBUF_SIZE (246) // +#endif + +//共配置的RAM +#define ATT_RAM_BUFSIZE (ATT_CTRL_BLOCK_SIZE + ATT_LOCAL_MTU_SIZE + ATT_SEND_CBUF_SIZE) //note: +static u8 att_ram_buffer[ATT_RAM_BUFSIZE] __attribute__((aligned(4))); +//--------------- + +/* + 打开流控使能后,确定使能接口 att_server_flow_enable 被调用 + 然后使用过程 通过接口 att_server_flow_hold 来控制流控开关 + 注意:流控只能控制对方使用带响应READ/WRITE等命令方式 + 例如:ATT_WRITE_REQUEST = 0x12 + */ +#define ATT_DATA_RECIEVT_FLOW 0//流控功能使能 + +//--------------- +// 广播周期 (unit:0.625ms) +#define ADV_INTERVAL_MIN (160*5) + +#define HOLD_LATENCY_CNT_MIN (3) //(0~0xffff) +#define HOLD_LATENCY_CNT_MAX (15) //(0~0xffff) +#define HOLD_LATENCY_CNT_ALL (0xffff) + +static volatile hci_con_handle_t con_handle; + +//加密设置 +/* static const uint8_t sm_min_key_size = 7; */ + +//连接参数更新请求设置 +//是否使能参数请求更新,0--disable, 1--enable +static const uint8_t connection_update_enable = 1; ///0--disable, 1--enable +//当前请求的参数表index +static uint8_t connection_update_cnt = 0; // + +//参数表 +static const struct conn_update_param_t connection_param_table[] = { + {16, 24, 10, 600},//11 + {12, 28, 10, 600},//3.7 + {8, 20, 10, 600}, + /* {12, 28, 4, 600},//3.7 */ + /* {12, 24, 30, 600},//3.05 */ +}; + +//共可用的参数组数 +#define CONN_PARAM_TABLE_CNT (sizeof(connection_param_table)/sizeof(struct conn_update_param_t)) + +#if (ATT_RAM_BUFSIZE < 64) +#error "adv_data & rsp_data buffer error!!!!!!!!!!!!" +#endif + +//用户可配对的,这是样机跟客户开发的app配对的秘钥 +/* const u8 link_key_data[16] = {0x06, 0x77, 0x5f, 0x87, 0x91, 0x8d, 0xd4, 0x23, 0x00, 0x5d, 0xf1, 0xd8, 0xcf, 0x0c, 0x14, 0x2b}; */ +#define EIR_TAG_STRING 0xd6, 0x05, 0x08, 0x00, 'J', 'L', 'A', 'I', 'S', 'D','K' +static const char user_tag_string[] = {EIR_TAG_STRING}; + +static u8 adv_data_len; +static u8 adv_data[ADV_RSP_PACKET_MAX];//max is 31 +static u8 scan_rsp_data_len; +static u8 scan_rsp_data[ADV_RSP_PACKET_MAX];//max is 31 + +/* #define adv_data &att_ram_buffer[0] */ +/* #define scan_rsp_data &att_ram_buffer[32] */ + +static char gap_device_name[BT_NAME_LEN_MAX] = "jl_ble_test"; +static u8 gap_device_name_len = 0; //名字长度,不包含结束符 +static u8 ble_work_state = 0; //ble 状态变化 +static u8 adv_ctrl_en; //广播控制 + +static u8 test_read_write_buf[4]; + +static void (*app_recieve_callback)(void *priv, void *buf, u16 len) = NULL; +static void (*app_ble_state_callback)(void *priv, ble_state_e state) = NULL; +static void (*ble_resume_send_wakeup)(void) = NULL; +static u32 channel_priv; + +static int app_send_user_data_check(u16 len); +int tuya_app_send_user_data_do(void *priv, u8 *data, u16 len); +static int app_send_user_data(u16 handle, u8 *data, u16 len, u8 handle_type); + +// Complete Local Name 默认的蓝牙名字 + +//------------------------------------------------------ +//广播参数设置 +static void advertisements_setup_init(); +static int set_adv_enable(void *priv, u32 en); +static int get_buffer_vaild_len(void *priv); +extern const char *bt_get_local_name(); +extern void clr_wdt(void); +extern void sys_auto_shut_down_disable(void); +extern void sys_auto_shut_down_enable(void); +extern u8 get_total_connect_dev(void); +extern u8 JL_tuya_ble_gatt_receive_data(u8 *p_data, u16 len); + +//------------------------------------------------------ +//NACS +#if TRANS_ANCS_EN +#define ANCS_SUBEVENT_CLIENT_NOTIFICATION 0xF1 +void ancs_client_init(void); +void ancs_client_register_callback(btstack_packet_handler_t callback); +const char *ancs_client_attribute_name_for_id(int id); +void ancs_set_notification_buffer(u8 *buffer, u16 buffer_size); + +//ancs info buffer +#define ANCS_INFO_BUFFER_SIZE (1024) +static u8 ancs_info_buffer[ANCS_INFO_BUFFER_SIZE]; +#endif + + +//----------------------------------------------------- +//创建tuya list node +struct list_node { + u16 len; + u8 *buf_data; + struct list_node *next; +}; + +typedef struct list_node list_single; + +list_single *plist = NULL; + +list_single *create_list_node(void) +{ + list_single *node = NULL; + node = (list_single *)malloc(sizeof(list_single)); + if (node == NULL) { + printf("malloc fail\n"); + } + memset(node, 0, sizeof(list_single)); + node->len = 0; + node->buf_data = NULL; + node->next = NULL; + + return node; +} +//列表尾插入 +u8 insert_tail_link_list(list_single *plist, u8 *buf_data, u16 len) +{ + list_single *p = plist; + list_single *pinsert_node = malloc(sizeof(list_single)); + if (NULL == pinsert_node) { + printf("malloc fail\n"); + } + pinsert_node->buf_data = malloc(len); + if (NULL == pinsert_node->buf_data) { + printf("malloc buf_data fair!\n"); + } + OS_ENTER_CRITICAL(); + memcpy(pinsert_node->buf_data, buf_data, len); + pinsert_node->len = len; + pinsert_node->next = NULL; + + while (p->next != NULL) { + p = p->next; + } + p->next = pinsert_node; + OS_EXIT_CRITICAL(); + + return 0; + +} + +u8 get_node_link_list(list_single *plist) +{ + list_single *pr, *p; + if (plist->next == NULL) { + return 1; + } + pr = plist->next; + p = pr->next; + JL_tuya_ble_gatt_receive_data(pr->buf_data, pr->len); + free(pr->buf_data); + free(pr); + plist->next = p; + return 0; + +} + +//------------------------------------------------------ + +static void send_request_connect_parameter(u8 table_index) +{ + struct conn_update_param_t *param = (void *)&connection_param_table[table_index];//static ram + + log_info("update_request:-%d-%d-%d-%d-\n", param->interval_min, param->interval_max, param->latency, param->timeout); + if (con_handle) { + ble_op_conn_param_request(con_handle, param); + } +} + +static void check_connetion_updata_deal(void) +{ + if (connection_update_enable) { + if (connection_update_cnt < CONN_PARAM_TABLE_CNT) { + send_request_connect_parameter(connection_update_cnt); + } + } +} + +static void connection_update_complete_success(u8 *packet) +{ + int con_handle, conn_interval, conn_latency, conn_timeout; + + con_handle = hci_subevent_le_connection_update_complete_get_connection_handle(packet); + conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet); + conn_latency = hci_subevent_le_connection_update_complete_get_conn_latency(packet); + conn_timeout = hci_subevent_le_connection_update_complete_get_supervision_timeout(packet); + + log_info("conn_interval = %d\n", conn_interval); + log_info("conn_latency = %d\n", conn_latency); + log_info("conn_timeout = %d\n", conn_timeout); +} + + +static void set_ble_work_state(ble_state_e state) +{ + if (state != ble_work_state) { + log_info("ble_work_st:%x->%x\n", ble_work_state, state); + ble_work_state = state; + if (app_ble_state_callback) { + app_ble_state_callback((void *)channel_priv, state); + } + } +} + +static ble_state_e get_ble_work_state(void) +{ + return ble_work_state; +} + +static void cbk_sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + sm_just_event_t *event = (void *)packet; + u32 tmp32; + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + case SM_EVENT_JUST_WORKS_REQUEST: + sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); + log_info("Just Works Confirmed.\n"); + break; + case SM_EVENT_PASSKEY_DISPLAY_NUMBER: + log_info_hexdump(packet, size); + memcpy(&tmp32, event->data, 4); + log_info("Passkey display: %06u.\n", tmp32); + break; + } + break; + } +} + + +static void can_send_now_wakeup(void) +{ + /* putchar('E'); */ + if (ble_resume_send_wakeup) { + ble_resume_send_wakeup(); + } +} + +static void ble_auto_shut_down_enable(u8 enable) +{ +#if TCFG_AUTO_SHUT_DOWN_TIME + if (enable) { + if (get_total_connect_dev() == 0) { //已经没有设备连接 + sys_auto_shut_down_enable(); + } + } else { + sys_auto_shut_down_disable(); + } +#endif +} + +const char *const phy_result[] = { + "None", + "1M", + "2M", + "Coded", +}; + +static void set_connection_data_length(u16 tx_octets, u16 tx_time) +{ + if (con_handle) { + ble_op_set_data_length(con_handle, tx_octets, tx_time); + } +} + +static void set_connection_data_phy(u8 tx_phy, u8 rx_phy) +{ + if (0 == con_handle) { + return; + } + + u8 all_phys = 0; + u16 phy_options = CONN_SET_PHY_OPTIONS_S8; + + ble_op_set_ext_phy(con_handle, all_phys, tx_phy, rx_phy, phy_options); +} + +static void server_profile_start(u16 con_handle) +{ +#if BT_FOR_APP_EN + set_app_connect_type(TYPE_BLE); +#endif + ble_op_att_send_init(con_handle, att_ram_buffer, ATT_RAM_BUFSIZE, ATT_LOCAL_MTU_SIZE); + set_ble_work_state(BLE_ST_CONNECT); + ble_auto_shut_down_enable(0); + + /* set_connection_data_phy(CONN_SET_CODED_PHY, CONN_SET_CODED_PHY); */ +} + +_WEAK_ +u8 ble_update_get_ready_jump_flag(void) +{ + return 0; +} +/* + * @section Packet Handler + * + * @text The packet handler is used to: + * - stop the counter after a disconnect + * - send a notification when the requested ATT_EVENT_CAN_SEND_NOW is received + */ + +/* LISTING_START(packetHandler): Packet Handler */ +static void cbk_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ + int mtu; + u32 tmp; + u8 status; + const char *attribute_name; + + switch (packet_type) { + case HCI_EVENT_PACKET: + switch (hci_event_packet_get_type(packet)) { + + /* case DAEMON_EVENT_HCI_PACKET_SENT: */ + /* break; */ + case ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE: + log_info("ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE\n"); + case ATT_EVENT_CAN_SEND_NOW: + can_send_now_wakeup(); + break; + + case HCI_EVENT_LE_META: + switch (hci_event_le_meta_get_subevent_code(packet)) { + case HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE: + status = hci_subevent_le_enhanced_connection_complete_get_status(packet); + if (status) { + log_info("LE_SLAVE CONNECTION FAIL!!! %0x\n", status); + set_ble_work_state(BLE_ST_DISCONN); + break; + } + con_handle = hci_subevent_le_enhanced_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE : %0x\n", con_handle); + log_info("conn_interval = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_interval(packet)); + log_info("conn_latency = %d\n", hci_subevent_le_enhanced_connection_complete_get_conn_latency(packet)); + log_info("conn_timeout = %d\n", hci_subevent_le_enhanced_connection_complete_get_supervision_timeout(packet)); + server_profile_start(con_handle); + break; + + case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: + con_handle = hci_subevent_le_connection_complete_get_connection_handle(packet); + log_info("HCI_SUBEVENT_LE_CONNECTION_COMPLETE: %0x\n", con_handle); + connection_update_complete_success(packet + 8); + server_profile_start(con_handle); + log_info("ble remote rssi= %d\n", ble_vendor_get_peer_rssi(con_handle)); + log_info("tuya_ble_connection_handler\n"); + tuya_ble_connected_handler(); + + break; + + case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: + printf("HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE"); + connection_update_complete_success(packet); + break; + + case HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE: + log_info("APP HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE\n"); + /* set_connection_data_phy(CONN_SET_CODED_PHY, CONN_SET_CODED_PHY); */ + break; + + case HCI_SUBEVENT_LE_PHY_UPDATE_COMPLETE: + log_info("APP HCI_SUBEVENT_LE_PHY_UPDATE %s\n", hci_event_le_meta_get_phy_update_complete_status(packet) ? "Fail" : "Succ"); + log_info("Tx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_tx_phy(packet)]); + log_info("Rx PHY: %s\n", phy_result[hci_event_le_meta_get_phy_update_complete_rx_phy(packet)]); + break; + } + break; + + case HCI_EVENT_DISCONNECTION_COMPLETE: + log_info("HCI_EVENT_DISCONNECTION_COMPLETE: %0x\n", packet[5]); + con_handle = 0; + ble_op_att_send_init(con_handle, 0, 0, 0); + set_ble_work_state(BLE_ST_DISCONN); + + + connection_update_cnt = 0; +#if BT_FOR_APP_EN + set_app_connect_type(TYPE_NULL); +#endif + ble_auto_shut_down_enable(1); + log_info("tuya_ble_disconnection_handler\n"); + tuya_ble_disconnected_handler(); + + extern void tuya_ble_adv_change(void); + tuya_ble_adv_change(); + break; + + case ATT_EVENT_MTU_EXCHANGE_COMPLETE: + mtu = att_event_mtu_exchange_complete_get_MTU(packet) - 3; + log_info("ATT MTU = %u\n", mtu); + ble_op_att_set_send_mtu(mtu); + /* set_connection_data_length(251, 2120); */ + break; + + case HCI_EVENT_VENDOR_REMOTE_TEST: + log_info("--- HCI_EVENT_VENDOR_REMOTE_TEST\n"); + break; + + case L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE: + tmp = little_endian_read_16(packet, 4); + log_info("-update_rsp: %02x\n", tmp); + if (tmp) { + connection_update_cnt++; + log_info("remoter reject!!!\n"); + check_connetion_updata_deal(); + } else { + connection_update_cnt = CONN_PARAM_TABLE_CNT; + } + break; + + case HCI_EVENT_ENCRYPTION_CHANGE: + log_info("HCI_EVENT_ENCRYPTION_CHANGE= %d\n", packet[2]); + break; + +#if TRANS_ANCS_EN + case HCI_EVENT_ANCS_META: + switch (hci_event_ancs_meta_get_subevent_code(packet)) { + case ANCS_SUBEVENT_CLIENT_NOTIFICATION: + printf("ANCS_SUBEVENT_CLIENT_NOTIFICATION \n"); + attribute_name = ancs_client_attribute_name_for_id(ancs_subevent_client_notification_get_attribute_id(packet)); + if (!attribute_name) { + printf("ancs unknow attribute_id :%d \n", ancs_subevent_client_notification_get_attribute_id(packet)); + break; + } else { + u16 attribute_strlen = little_endian_read_16(packet, 7); + u8 *attribute_str = (void *)little_endian_read_32(packet, 9); + printf("Notification: %s - %s \n", attribute_name, attribute_str); + } + break; + default: + break; + } + + break; +#endif + + } + break; + } +} + + +/* LISTING_END */ + +/* + * @section ATT Read + * + * @text The ATT Server handles all reads to constant data. For dynamic data like the custom characteristic, the registered + * att_read_callback is called. To handle long characteristics and long reads, the att_read_callback is first called + * with buffer == NULL, to request the total value length. Then it will be called again requesting a chunk of the value. + * See Listing attRead. + */ + +/* LISTING_END */ +/* + * @section ATT Write + * + * @text The only valid ATT write in this example is to the Client Characteristic Configuration, which configures notification + * and indication. If the ATT handle matches the client configuration handle, the new configuration value is stored and used + * in the heartbeat handler to decide if a new value should be sent. See Listing attWrite. + */ + +/* LISTING_START(attWrite): ATT Write */ +static int att_write_callback(hci_con_handle_t connection_handle, uint16_t att_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size) +{ + int result = 0; + u16 tmp16; + u8 *tmp_buf = NULL; + u16 handle = att_handle; + + //log_info("write_callback, handle= 0x%04x,size = %d\n", handle, buffer_size); + //put_buf(buffer, buffer_size); + + switch (handle) { +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x03) + case ATT_CHARACTERISTIC_2b10_01_CLIENT_CONFIGURATION_HANDLE: + set_ble_work_state(BLE_ST_NOTIFY_IDICATE); + check_connetion_updata_deal(); + printf("\n------write ccc:%04x,%02x\n", handle, buffer[0]); + att_set_ccc_config(handle, buffer[0]); + break; + + case ATT_CHARACTERISTIC_2b11_01_VALUE_HANDLE: + printf("TUYA msg receive, handle = 0x%x, size = %d\n", handle, buffer_size); + //put_buf(buffer, buffer_size); + //insert_tail_link_list(plist, buffer, buffer_size); + JL_tuya_ble_gatt_receive_data(buffer, buffer_size); + break; +#endif + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x04) + case ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_CLIENT_CONFIGURATION_HANDLE: + set_ble_work_state(BLE_ST_NOTIFY_IDICATE); + check_connetion_updata_deal(); + printf("\n------write ccc:%04x,%02x\n", handle, buffer[0]); + att_set_ccc_config(handle, buffer[0]); + break; + + case ATT_CHARACTERISTIC_00000001_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE: + printf("\nTUYA msg receive, handle = 0x%x, size = %d\n", handle, buffer_size); + //insert_tail_link_list(plist, buffer, buffer_size); + //put_buf(buffer, buffer_size); + JL_tuya_ble_gatt_receive_data(buffer, buffer_size); + break; + + case ATT_CHARACTERISTIC_00000003_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE: + printf("\nTUYA read msg, handle = 0x%x, size = %d\n", handle, buffer_size); + put_buf(buffer, buffer_size); + break; + +#endif + + default: + printf("\n\nunknow handle:%d\n\n", handle); + break; + } + + return 0; +} + +static int app_send_user_data(u16 handle, u8 *data, u16 len, u8 handle_type) +{ + u32 ret = APP_BLE_NO_ERROR; + + if (!con_handle) { + return APP_BLE_OPERATION_ERROR; + } + + if (!att_get_ccc_config(handle + 1)) { + log_info("fail,no write ccc!!!,%04x\n", handle + 1); + return APP_BLE_NO_WRITE_CCC; + } + + ret = ble_op_att_send_data(handle, data, len, handle_type); + if (ret == BLE_BUFFER_FULL) { + ret = APP_BLE_BUFF_FULL; + } + + if (ret) { + log_info("app_send_fail:%d !!!!!!\n", ret); + } + return ret; +} + +//------------------------------------------------------ +static int make_set_adv_data(void) +{ + u8 offset = 0; + u8 *buf = adv_data; + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x03) + u8 service_data[11] = {0x01, 0xA2, 0x00, 0x65, 0x36, 0x6A, 0x6C, 0x6C, 0x70, 0x79, 0x37}; + + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_FLAGS, 0x06, 1); + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_MORE_16BIT_SERVICE_UUIDS, 0xA201, 2); + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_SERVICE_DATA, (void *)service_data, 11); +#endif + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x04) + u8 service_data[22] = {0x50, 0XFD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_FLAGS, 0x06, 1); + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_MORE_16BIT_SERVICE_UUIDS, 0x50FD, 2); + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_SERVICE_DATA, (void *)service_data, 22); +#endif + + if (offset > ADV_RSP_PACKET_MAX) { + puts("***adv_data overflow!!!!!!\n"); + return -1; + } + log_info("adv_data(%d):", offset); + log_info_hexdump(buf, offset); + adv_data_len = offset; + ble_op_set_adv_data(offset, buf); + return 0; +} + +static int make_set_rsp_data(void) +{ + u8 offset = 0; + u8 *buf = scan_rsp_data; + + u8 name_len = gap_device_name_len; + u8 vaild_len = ADV_RSP_PACKET_MAX - (offset + 2); + if (name_len > vaild_len) { + name_len = vaild_len; + } + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x03) + u8 ble_specific_data[24] = {0xD0, 0x07, 0x00, 0x03, 0x00, 0x00, 0x01, 0x00, 0x38, 0xD1, 0x4B, 0xE7, 0xF3, 0x61, 0xB8, 0xB3, 0xFA, 0x4E, 0x8C, 0x70, 0xD5, 0xEB, 0x25, 0x7E}; + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME, 0x5954, 2); + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA, (void *)ble_specific_data, 24); +#endif + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x04) + u8 ble_specific_data[22] = {0xD0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + offset += make_eir_packet_val(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME, 0x5954, 2); + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA, (void *)ble_specific_data, 24); +#endif + + + if (offset > ADV_RSP_PACKET_MAX) { + puts("***rsp_data overflow!!!!!!\n"); + return -1; + } + + log_info("rsp_data(%d):", offset); + log_info_hexdump(buf, offset); + scan_rsp_data_len = offset; + ble_op_set_rsp_data(offset, buf); + return 0; +} + +//广播参数设置 +static void advertisements_setup_init() +{ + uint8_t adv_type = ADV_IND; + uint8_t adv_channel = ADV_CHANNEL_ALL; + int ret = 0; + + ble_op_set_adv_param(ADV_INTERVAL_MIN, adv_type, adv_channel); + + ret |= make_set_adv_data(); + ret |= make_set_rsp_data(); + + if (ret) { + puts("advertisements_setup_init fail !!!!!!\n"); + return; + } + +} + +#define PASSKEY_ENTER_ENABLE 0 //输入passkey使能,可修改passkey +//重设passkey回调函数,在这里可以重新设置passkey +//passkey为6个数字组成,十万位、万位。。。。个位 各表示一个数字 高位不够为0 +static void reset_passkey_cb(u32 *key) +{ +#if 1 + u32 newkey = rand32();//获取随机数 + + newkey &= 0xfffff; + if (newkey > 999999) { + newkey = newkey - 999999; //不能大于999999 + } + *key = newkey; //小于或等于六位数 + printf("set new_key= %06u\n", *key); +#else + *key = 123456; //for debug +#endif +} + +void ble_sm_setup_init(io_capability_t io_type, u8 auth_req, uint8_t min_key_size, u8 security_en) +{ + //setup SM: Display only + sm_init(); + sm_set_io_capabilities(io_type); + sm_set_authentication_requirements(auth_req); + sm_set_encryption_key_size_range(min_key_size, 16); + sm_set_request_security(security_en); + sm_event_callback_set(&cbk_sm_packet_handler); + + if (io_type == IO_CAPABILITY_DISPLAY_ONLY) { + reset_PK_cb_register(reset_passkey_cb); + } +} + + +void ble_profile_init(void) +{ + printf("TUYA ble profile init\n"); + le_device_db_init(); + +#if PASSKEY_ENTER_ENABLE + ble_sm_setup_init(IO_CAPABILITY_DISPLAY_ONLY, SM_AUTHREQ_MITM_PROTECTION, 7, TCFG_BLE_SECURITY_EN); +#else + /* ble_sm_setup_init(IO_CAPABILITY_NO_INPUT_NO_OUTPUT, SM_AUTHREQ_BONDING, 7, TCFG_BLE_SECURITY_EN); */ + ble_sm_setup_init(IO_CAPABILITY_NO_INPUT_NO_OUTPUT, SM_AUTHREQ_BONDING, 7, 0); +#endif + + /* setup ATT server */ + att_server_init(profile_data, NULL, att_write_callback); + att_server_register_packet_handler(cbk_packet_handler); + /* gatt_client_register_packet_handler(packet_cbk); */ + + // register for HCI events + hci_event_callback_set(&cbk_packet_handler); + /* ble_l2cap_register_packet_handler(packet_cbk); */ + /* sm_event_packet_handler_register(packet_cbk); */ + le_l2cap_register_packet_handler(&cbk_packet_handler); + +#if TRANS_ANCS_EN + //setup GATT client + gatt_client_init(); + + //setup ANCS clent + ancs_client_init(); + ancs_set_notification_buffer(ancs_info_buffer, sizeof(ancs_info_buffer)); + ancs_client_register_callback(&cbk_packet_handler); +#endif + + extern u16 ble_vendor_set_default_att_mtu(u16 mtu_size); + ble_vendor_set_default_att_mtu(ATT_LOCAL_MTU_SIZE); +} + +#if EXT_ADV_MODE_EN + + +#define EXT_ADV_NAME 'J', 'L', '_', 'E', 'X', 'T', '_', 'A', 'D', 'V' +/* #define EXT_ADV_NAME "JL_EXT_ADV" */ +#define BYTE_LEN(x...) sizeof((u8 []) {x}) +#define EXT_ADV_DATA \ + 0x02, 0x01, 0x06, \ + 0x03, 0x02, 0xF0, 0xFF, \ + BYTE_LEN(EXT_ADV_NAME) + 1, BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME, EXT_ADV_NAME + +struct ext_advertising_param { + u8 Advertising_Handle; + u16 Advertising_Event_Properties; + u8 Primary_Advertising_Interval_Min[3]; + u8 Primary_Advertising_Interval_Max[3]; + u8 Primary_Advertising_Channel_Map; + u8 Own_Address_Type; + u8 Peer_Address_Type; + u8 Peer_Address[6]; + u8 Advertising_Filter_Policy; + u8 Advertising_Tx_Power; + u8 Primary_Advertising_PHY; + u8 Secondary_Advertising_Max_Skip; + u8 Secondary_Advertising_PHY; + u8 Advertising_SID; + u8 Scan_Request_Notification_Enable; +} _GNU_PACKED_; + +struct ext_advertising_data { + u8 Advertising_Handle; + u8 Operation; + u8 Fragment_Preference; + u8 Advertising_Data_Length; + u8 Advertising_Data[BYTE_LEN(EXT_ADV_DATA)]; +} _GNU_PACKED_; + +struct ext_advertising_enable { + u8 Enable; + u8 Number_of_Sets; + u8 Advertising_Handle; + u16 Duration; + u8 Max_Extended_Advertising_Events; +} _GNU_PACKED_; + +const struct ext_advertising_param ext_adv_param = { + .Advertising_Handle = 0, + .Advertising_Event_Properties = 1, + .Primary_Advertising_Interval_Min = {30, 0, 0}, + .Primary_Advertising_Interval_Max = {30, 0, 0}, + .Primary_Advertising_Channel_Map = 7, + .Primary_Advertising_PHY = ADV_SET_1M_PHY, + .Secondary_Advertising_PHY = ADV_SET_1M_PHY, +}; + +const struct ext_advertising_data ext_adv_data = { + .Advertising_Handle = 0, + .Operation = 3, + .Fragment_Preference = 0, + .Advertising_Data_Length = BYTE_LEN(EXT_ADV_DATA), + .Advertising_Data = EXT_ADV_DATA, +}; + +const struct ext_advertising_enable ext_adv_enable = { + .Enable = 1, + .Number_of_Sets = 1, + .Advertising_Handle = 0, + .Duration = 0, + .Max_Extended_Advertising_Events = 0, +}; + +const struct ext_advertising_enable ext_adv_disable = { + .Enable = 0, + .Number_of_Sets = 1, + .Advertising_Handle = 0, + .Duration = 0, + .Max_Extended_Advertising_Events = 0, +}; + +#endif /* EXT_ADV_MODE_EN */ + +void tuya_set_adv_enable() +{ + if (con_handle) { + printf("connect is exist return\n"); + return; + } + + if (!adv_ctrl_en) { + printf("!adv_ctrl_en return\n"); + return; + } + ble_op_adv_enable(1); +} + +static int set_adv_enable(void *priv, u32 en) +{ + ble_state_e next_state, cur_state; + + if (!adv_ctrl_en) { + return APP_BLE_OPERATION_ERROR; + } + + if (con_handle) { + return APP_BLE_OPERATION_ERROR; + } + + if (en) { + next_state = BLE_ST_ADV; + } else { + next_state = BLE_ST_IDLE; + } + + cur_state = get_ble_work_state(); + switch (cur_state) { + case BLE_ST_ADV: + case BLE_ST_IDLE: + case BLE_ST_INIT_OK: + case BLE_ST_NULL: + case BLE_ST_DISCONN: + break; + default: + return APP_BLE_OPERATION_ERROR; + break; + } + + if (cur_state == next_state) { + return APP_BLE_NO_ERROR; + } + log_info("adv_en:%d\n", en); + set_ble_work_state(next_state); + +#if EXT_ADV_MODE_EN + if (en) { + ble_op_set_ext_adv_param(&ext_adv_param, sizeof(ext_adv_param)); + + log_info_hexdump(&ext_adv_data, sizeof(ext_adv_data)); + ble_op_set_ext_adv_data(&ext_adv_data, sizeof(ext_adv_data)); + + ble_op_set_ext_adv_enable(&ext_adv_enable, sizeof(ext_adv_enable)); + } else { + ble_op_set_ext_adv_enable(&ext_adv_disable, sizeof(ext_adv_disable)); + } +#else + if (en) { + advertisements_setup_init(); + } + ble_op_adv_enable(en); +#endif /* EXT_ADV_MODE_EN */ + + return APP_BLE_NO_ERROR; +} + +static int ble_disconnect(void *priv) +{ + if (con_handle) { + if (BLE_ST_SEND_DISCONN != get_ble_work_state()) { + log_info(">>>tuya ble send disconnect\n"); + set_ble_work_state(BLE_ST_SEND_DISCONN); + ble_op_disconnect(con_handle); + } else { + log_info(">>>tuya ble wait disconnect...\n"); + } + return APP_BLE_NO_ERROR; + } else { + return APP_BLE_OPERATION_ERROR; + } +} + + +static int get_buffer_vaild_len(void *priv) +{ + u32 vaild_len = 0; + ble_op_att_get_remain(&vaild_len); + return vaild_len; +} + +int tuya_app_send_user_data_do(void *priv, u8 *data, u16 len) +{ +#if PRINT_DMA_DATA_EN + if (len < 128) { + log_info("-le_tx(%d):"); + log_info_hexdump(data, len); + } else { + putchar('L'); + } +#endif + att_set_ccc_config(ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE + 1, ATT_OP_NOTIFY); + return app_send_user_data(ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE, data, len, ATT_OP_AUTO_READ_CCC); + + return 0; + //return app_send_user_data(ATT_CHARACTERISTIC_2b10_01_VALUE_HANDLE, data, len, ATT_OP_AUTO_READ_CCC); +} + +static int app_send_user_data_check(u16 len) +{ + u32 buf_space = get_buffer_vaild_len(0); + if (len <= buf_space) { + return 1; + } + return 0; +} + + +static int regiest_wakeup_send(void *priv, void *cbk) +{ + ble_resume_send_wakeup = cbk; + return APP_BLE_NO_ERROR; +} + +static int regiest_recieve_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_recieve_callback = cbk; + return APP_BLE_NO_ERROR; +} + +static int regiest_state_cbk(void *priv, void *cbk) +{ + channel_priv = (u32)priv; + app_ble_state_callback = cbk; + return APP_BLE_NO_ERROR; +} + +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ + + +u8 *ble_get_scan_rsp_ptr(u16 *len) +{ + if (len) { + *len = scan_rsp_data_len; + } + return scan_rsp_data; +} + +u8 *ble_get_adv_data_ptr(u16 *len) +{ + if (len) { + *len = adv_data_len; + } + return adv_data; +} + +u8 *ble_get_gatt_profile_data(u16 *len) +{ + *len = sizeof(profile_data); + return (u8 *)profile_data; +} + + +void bt_ble_adv_enable(u8 enable) +{ + set_adv_enable(0, enable); +} + +u16 bt_ble_is_connected(void) +{ + return con_handle; +} + +void ble_module_enable(u8 en) +{ + if (en) { + adv_ctrl_en = 1; + bt_ble_adv_enable(1); + } else { + if (con_handle) { + adv_ctrl_en = 0; + ble_disconnect(NULL); + } else { + bt_ble_adv_enable(0); + adv_ctrl_en = 0; + } + } +} + + +//流控使能 EN: 1-停止收数 or 0-继续收数 +int ble_trans_flow_enable(u8 en) +{ + int ret = -1; +#if ATT_DATA_RECIEVT_FLOW + if (con_handle) { + att_server_flow_hold(con_handle, en); + ret = 0; + } +#endif + log_info("ble_trans_flow_enable:%d,%d\n", en, ret); + return ret; +} + +//for test +static void timer_trans_flow_test(void) +{ + static u8 sw = 0; + if (con_handle) { + sw = !sw; + ble_trans_flow_enable(sw); + } +} + +static const char ble_ext_name[] = "(BLE)"; +void tuya_report_data_timer(void *priv) +{ + get_node_link_list(plist); +} + + +int tuya_app_send_user_data(u8 *data, u16 len) +{ + int ret = 0; + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x03) + att_set_ccc_config(ATT_CHARACTERISTIC_2b10_01_VALUE_HANDLE + 1, ATT_OP_NOTIFY); + ret = app_send_user_data(ATT_CHARACTERISTIC_2b10_01_VALUE_HANDLE, data, len, ATT_OP_NOTIFY); +#endif +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x04) + att_set_ccc_config(ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE + 1, ATT_OP_NOTIFY); + ret = app_send_user_data(ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE, data, len, ATT_OP_NOTIFY); +#endif + printf("tuya_send_user_data: %d, len = %d\n", ret, len); + put_buf(data, len); + return ret ; +} + +void bt_ble_init(void) +{ + log_info("***** ble_init******\n"); + char *name_p; + +#if DOUBLE_BT_SAME_NAME + u8 ext_name_len = 0; +#else + u8 ext_name_len = sizeof(ble_ext_name) - 1; +#endif + + name_p = bt_get_local_name(); + gap_device_name_len = strlen(name_p); + if (gap_device_name_len > BT_NAME_LEN_MAX - ext_name_len) { + gap_device_name_len = BT_NAME_LEN_MAX - ext_name_len; + } + + memcpy(gap_device_name, name_p, gap_device_name_len); + +#if DOUBLE_BT_SAME_NAME == 0 + //增加后缀,区分名字 + memcpy(&gap_device_name[gap_device_name_len], "(BLE)", ext_name_len); + gap_device_name_len += ext_name_len; +#endif + + log_info("ble name(%d): %s \n", gap_device_name_len, gap_device_name); + +#if ATT_DATA_RECIEVT_FLOW + log_info("att_server_flow_enable\n"); + att_server_flow_enable(1); + /* sys_timer_add(0, timer_trans_flow_test, 3000); */ +#endif + + set_ble_work_state(BLE_ST_INIT_OK); + ble_module_enable(1); + + plist = create_list_node(); + extern void tuya_ble_app_init(); + tuya_ble_app_init(); + sys_timer_add(NULL, tuya_report_data_timer, 100); +} + +void bt_ble_exit(void) +{ + log_info("***** ble_exit******\n"); + +} + + +void ble_app_disconnect(void) +{ + ble_disconnect(NULL); +} + +static const struct ble_server_operation_t mi_ble_operation = { + .adv_enable = set_adv_enable, + .disconnect = ble_disconnect, + .get_buffer_vaild = get_buffer_vaild_len, + .send_data = (void *)tuya_app_send_user_data_do, + .regist_wakeup_send = regiest_wakeup_send, + .regist_recieve_cbk = regiest_recieve_cbk, + .regist_state_cbk = regiest_state_cbk, +}; + +void ble_get_server_operation_table(struct ble_server_operation_t **interface_pt) +{ + *interface_pt = (void *)&mi_ble_operation; +} + +void ble_server_send_test_key_num(u8 key_num) +{ + ; +} + +#endif + + diff --git a/apps/soundbox/smartbox/tuya/tuya_demo.h b/apps/soundbox/smartbox/tuya/tuya_demo.h new file mode 100644 index 0000000..5d30a34 --- /dev/null +++ b/apps/soundbox/smartbox/tuya/tuya_demo.h @@ -0,0 +1,125 @@ +// binary representation +// attribute size in bytes (16), flags(16), handle (16), uuid (16/128), value(...) + +#ifndef _TUYA_DEMO_H +#define _TUYA_DEMO_H + +#include +#include "app_config.h" +#include "tuya_ble_internal_config.h" + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_TUYA) + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x03) +// +// gatt profile include file, generated by jieli gatt_inc_generator.exe +// + +const uint8_t profile_data[] = { + ////////////////////////////////////////////////////// + // + // 0x0001 PRIMARY_SERVICE 1800 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x18, + + /* CHARACTERISTIC, 2a00, READ | DYNAMIC, */ + // 0x0002 CHARACTERISTIC 2a00 READ | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x03, 0x00, 0x00, 0x2a, + // 0x0003 VALUE 2a00 READ | DYNAMIC + 0x08, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x2a, + + ////////////////////////////////////////////////////// + // + // 0x0004 PRIMARY_SERVICE 1910 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x28, 0x10, 0x19, + + /* CHARACTERISTIC, 2b10, NOTIFY | DYNAMIC, */ + // 0x0005 CHARACTERISTIC 2b10 NOTIFY | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x05, 0x00, 0x03, 0x28, 0x10, 0x06, 0x00, 0x10, 0x2b, + // 0x0006 VALUE 2b10 NOTIFY | DYNAMIC + 0x08, 0x00, 0x10, 0x01, 0x06, 0x00, 0x10, 0x2b, + // 0x0007 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x07, 0x00, 0x02, 0x29, 0x00, 0x00, + + /* CHARACTERISTIC, 2b11, WRITE | WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x0008 CHARACTERISTIC 2b11 WRITE | WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x08, 0x00, 0x03, 0x28, 0x0c, 0x09, 0x00, 0x11, 0x2b, + // 0x0009 VALUE 2b11 WRITE | WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x08, 0x00, 0x0c, 0x01, 0x09, 0x00, 0x11, 0x2b, + + // END + 0x00, 0x00, +}; +// +// characteristics <--> handles +// +#define ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE 0x0003 +#define ATT_CHARACTERISTIC_2b10_01_VALUE_HANDLE 0x0006 +#define ATT_CHARACTERISTIC_2b10_01_CLIENT_CONFIGURATION_HANDLE 0x0007 +#define ATT_CHARACTERISTIC_2b11_01_VALUE_HANDLE 0x0009 +#endif + +#if (TUYA_BLE_PROTOCOL_VERSION_HIGN == 0x04) +// +// gatt profile include file, generated by jieli gatt_inc_generator.exe +// + +const uint8_t profile_data[] = { + ////////////////////////////////////////////////////// + // + // 0x0001 PRIMARY_SERVICE 1800 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x28, 0x00, 0x18, + + /* CHARACTERISTIC, 2a00, READ | DYNAMIC, */ + // 0x0002 CHARACTERISTIC 2a00 READ | DYNAMIC + 0x0d, 0x00, 0x02, 0x00, 0x02, 0x00, 0x03, 0x28, 0x02, 0x03, 0x00, 0x00, 0x2a, + // 0x0003 VALUE 2a00 READ | DYNAMIC + 0x08, 0x00, 0x02, 0x01, 0x03, 0x00, 0x00, 0x2a, + + ////////////////////////////////////////////////////// + // + // 0x0004 PRIMARY_SERVICE FD50 + // + ////////////////////////////////////////////////////// + 0x0a, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x28, 0x50, 0xfd, + + /* CHARACTERISTIC, 00000001-0000-1001-8001-00805F9B07D0, WRITE_WITHOUT_RESPONSE | DYNAMIC, */ + // 0x0005 CHARACTERISTIC 00000001-0000-1001-8001-00805F9B07D0 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x1b, 0x00, 0x02, 0x00, 0x05, 0x00, 0x03, 0x28, 0x04, 0x06, 0x00, 0xd0, 0x07, 0x9b, 0x5f, 0x80, 0x00, 0x01, 0x80, 0x01, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + // 0x0006 VALUE 00000001-0000-1001-8001-00805F9B07D0 WRITE_WITHOUT_RESPONSE | DYNAMIC + 0x16, 0x00, 0x04, 0x03, 0x06, 0x00, 0xd0, 0x07, 0x9b, 0x5f, 0x80, 0x00, 0x01, 0x80, 0x01, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + + /* CHARACTERISTIC, 00000002-0000-1001-8001-00805F9B07D0, NOTIFY | DYNAMIC, */ + // 0x0007 CHARACTERISTIC 00000002-0000-1001-8001-00805F9B07D0 NOTIFY | DYNAMIC + 0x1b, 0x00, 0x02, 0x00, 0x07, 0x00, 0x03, 0x28, 0x10, 0x08, 0x00, 0xd0, 0x07, 0x9b, 0x5f, 0x80, 0x00, 0x01, 0x80, 0x01, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + // 0x0008 VALUE 00000002-0000-1001-8001-00805F9B07D0 NOTIFY | DYNAMIC + 0x16, 0x00, 0x10, 0x03, 0x08, 0x00, 0xd0, 0x07, 0x9b, 0x5f, 0x80, 0x00, 0x01, 0x80, 0x01, 0x10, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + // 0x0009 CLIENT_CHARACTERISTIC_CONFIGURATION + 0x0a, 0x00, 0x0a, 0x01, 0x09, 0x00, 0x02, 0x29, 0x00, 0x00, + + /* CHARACTERISTIC, 00000003-0000-1001-8001-00805F9B07D0, READ | DYNAMIC, */ + // 0x000a CHARACTERISTIC 00000003-0000-1001-8001-00805F9B07D0 READ | DYNAMIC + 0x1b, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x03, 0x28, 0x02, 0x0b, 0x00, 0xd0, 0x07, 0x9b, 0x5f, 0x80, 0x00, 0x01, 0x80, 0x01, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + // 0x000b VALUE 00000003-0000-1001-8001-00805F9B07D0 READ | DYNAMIC + 0x16, 0x00, 0x02, 0x03, 0x0b, 0x00, 0xd0, 0x07, 0x9b, 0x5f, 0x80, 0x00, 0x01, 0x80, 0x01, 0x10, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + + // END + 0x00, 0x00, +}; +// +// characteristics <--> handles +// +#define ATT_CHARACTERISTIC_2a00_01_VALUE_HANDLE 0x0003 +#define ATT_CHARACTERISTIC_00000001_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE 0x0006 +#define ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE 0x0008 +#define ATT_CHARACTERISTIC_00000002_0000_1001_8001_00805F9B07D0_01_CLIENT_CONFIGURATION_HANDLE 0x0009 +#define ATT_CHARACTERISTIC_00000003_0000_1001_8001_00805F9B07D0_01_VALUE_HANDLE 0x000b +#endif + +#endif +#endif diff --git a/apps/soundbox/soundcard/lamp.c b/apps/soundbox/soundcard/lamp.c new file mode 100644 index 0000000..7c7dcad --- /dev/null +++ b/apps/soundbox/soundcard/lamp.c @@ -0,0 +1,199 @@ +#include "soundcard/lamp.h" +#include "system/device/vm.h" +#include "asm/rtc.h" +#include "asm/power/p33.h" +#include "asm/gpio.h" +#include "soundcard/soundcard.h" +#include "system/timer.h" + +#if SOUNDCARD_ENABLE + +static u8 my_led_status = 0; +static u8 my_led_status_self = 0; //独立的LED +static u16 soundcard_power_timer = 0; +static void led_port_set_hz(u8 port) +{ + gpio_set_pull_down(port, 0); + gpio_set_pull_up(port, 0); + gpio_set_direction(port, 1); +} +void my_led_clear_all(void) +{ + led_port_set_hz(TCFG_MY_LED1_PORT); + led_port_set_hz(TCFG_MY_LED2_PORT); + led_port_set_hz(TCFG_MY_LED3_PORT); + led_port_set_hz(TCFG_MY_LED4_PORT); +} +static void __my_led_scan(void *param) +{ + static u8 cnt = 0; + my_led_clear_all(); + /* if (get_vm_statu()) { */ + /* return; */ + /* } */ + switch (cnt) { + case 0: + gpio_direction_output(TCFG_MY_LED1_PORT, 0); + if (my_led_status & UI_LED_ELECTRIC_SOUND) { + gpio_direction_output(TCFG_MY_LED2_PORT, 1); + } + if (my_led_status & UI_LED_PITCH_SOUND) { + gpio_direction_output(TCFG_MY_LED3_PORT, 1); + } + if (my_led_status & UI_LED_MAGIC_SOUND) { + gpio_direction_output(TCFG_MY_LED4_PORT, 1); + } + break; + case 1: + gpio_direction_output(TCFG_MY_LED2_PORT, 0); + if (my_led_status & UI_LED_BOOM_SOUND) { + gpio_direction_output(TCFG_MY_LED3_PORT, 1); + } + if (my_led_status & UI_LED_MIC_SOUND) { + gpio_direction_output(TCFG_MY_LED4_PORT, 1); + } + break; + case 2: + gpio_direction_output(TCFG_MY_LED4_PORT, 0); + if (my_led_status_self & UI_LED_SELF_DODGE_SOUND) { + gpio_direction_output(TCFG_MY_LED3_PORT, 1); + } + break; + default: + putchar('a'); + break; + } + cnt = (cnt >= 2) ? 0 : cnt + 1; +} + +static void __my_led2_scan(void *param) +{ + static u8 cnt = 0; + + if (my_led_status_self & UI_LED_SELF_RED) { + gpio_set_output_value(TCFG_MY_LED_RED_PORT, 1); + } else { + gpio_set_output_value(TCFG_MY_LED_RED_PORT, 0); + } + + if (my_led_status_self & UI_LED_SELF_BLUE_FLASH) { + if (cnt) { + gpio_set_output_value(TCFG_MY_LED_BLUE_PORT, 1); + } else { + gpio_set_output_value(TCFG_MY_LED_BLUE_PORT, 0); + } + } else { + gpio_set_output_value(TCFG_MY_LED_BLUE_PORT, 1); + } + + cnt = (cnt >= 1) ? 0 : cnt + 1; +} + +void soundcard_led_set(u8 led, u8 sw) +{ + //y_printf("%s:%d", __func__, led); + if (sw) { + my_led_status = led; + } else { + my_led_status = 0; + } +} + +void soundcard_led_self_set(u8 led, u8 sw) +{ + //y_printf("%s:%d", __func__, led); + + if (sw) { + my_led_status_self |= led; + } else { + my_led_status_self &= ~led; + } + +} + +void soundcard_led_mode(u8 mode, u8 sw) +{ + if (soundcard_power_timer) { + return ; + } + switch (mode) { + case SOUNDCARD_MODE_NORMAL: + soundcard_led_set(UI_LED_OFF, sw); + break; + case SOUNDCARD_MODE_ELECTRIC: + soundcard_led_set(UI_LED_ELECTRIC_SOUND, sw); + break; + case SOUNDCARD_MODE_PITCH: + soundcard_led_set(UI_LED_PITCH_SOUND, sw); + break; + case SOUNDCARD_MODE_MAGIC: + soundcard_led_set(UI_LED_MAGIC_SOUND, sw); + break; + case SOUNDCARD_MODE_BOOM: + soundcard_led_set(UI_LED_BOOM_SOUND, sw); + break; + case SOUNDCARD_MODE_SHOUTING_WHEAT: + soundcard_led_set(UI_LED_MIC_SOUND, sw); + break; + case SOUNDCARD_MODE_DODGE: + soundcard_led_self_set(UI_LED_SELF_DODGE_SOUND, sw); + break; + default: + break; + } +} + +void soundcard_led_all_off(void) +{ + soundcard_led_set(0, 0); + soundcard_led_self_set(BIT(0), 0); +} + +void soundcard_led_all_on(void) +{ + soundcard_led_set(0xff, 1); + soundcard_led_self_set(BIT(0), 1); +} + +static void soundcard_low_power_led_can(void *p) +{ + static u8 flag = 0; + flag = !flag; + if (flag) { + soundcard_led_all_on(); + } else { + soundcard_led_all_off(); + } +} + +void soundcard_low_power_led(u8 onoff) +{ + if (onoff) { + if (soundcard_power_timer == 0) { + soundcard_power_timer = sys_hi_timer_add(NULL, soundcard_low_power_led_can, 1000); + } + } else { + if (soundcard_power_timer) { + sys_hi_timer_del(soundcard_power_timer); + soundcard_led_all_off(); + soundcard_power_timer = 0; + } + } +} + +void soundcard_led_init(void) +{ + //y_printf("%s", __func__); + + my_led_clear_all(); + + gpio_set_direction(TCFG_MY_LED_BLUE_PORT, 0); + gpio_set_direction(TCFG_MY_LED_RED_PORT, 0); + soundcard_led_self_set(UI_LED_SELF_RED, 1); + soundcard_led_self_set(UI_LED_SELF_BLUE_FLASH, 1); + + sys_hi_timer_add(NULL, __my_led_scan, 4); //2ms + sys_hi_timer_add(NULL, __my_led2_scan, 500); //2ms +} + +#endif//SOUNDCARD_ENABLE diff --git a/apps/soundbox/soundcard/notice.c b/apps/soundbox/soundcard/notice.c new file mode 100644 index 0000000..ca11f3f --- /dev/null +++ b/apps/soundbox/soundcard/notice.c @@ -0,0 +1,135 @@ +#include "soundcard/notice.h" +#include "tone_player.h" +#include "audio_dec.h" + + +#if SOUNDCARD_ENABLE +static const char *electric_notice_tab[] = { + SDFILE_RES_ROOT_PATH"tone/AA.*", + SDFILE_RES_ROOT_PATH"tone/SA.*", + SDFILE_RES_ROOT_PATH"tone/BB.*", + //SDFILE_RES_ROOT_PATH"tone/SB.*", + SDFILE_RES_ROOT_PATH"tone/CC.*", + SDFILE_RES_ROOT_PATH"tone/SC.*", + SDFILE_RES_ROOT_PATH"tone/DD.*", + SDFILE_RES_ROOT_PATH"tone/SD.*", + SDFILE_RES_ROOT_PATH"tone/EE.*", + //SDFILE_RES_ROOT_PATH"tone/SE.*", + SDFILE_RES_ROOT_PATH"tone/FF.*", + SDFILE_RES_ROOT_PATH"tone/SF.*", + SDFILE_RES_ROOT_PATH"tone/GG.*", + SDFILE_RES_ROOT_PATH"tone/SG.*", +}; + +static const char *noise_tab[] = { + SDFILE_RES_ROOT_PATH"tone/huan_hu.*", + SDFILE_RES_ROOT_PATH"tone/gan_ga.*", + SDFILE_RES_ROOT_PATH"tone/qiang.*", + SDFILE_RES_ROOT_PATH"tone/bi_shi.*", + SDFILE_RES_ROOT_PATH"tone/kaichang.*", + SDFILE_RES_ROOT_PATH"tone/FeiWen.*", + SDFILE_RES_ROOT_PATH"tone/xiao.*", + SDFILE_RES_ROOT_PATH"tone/zhangshen.*", + SDFILE_RES_ROOT_PATH"tone/QiuFenXiang.*", + SDFILE_RES_ROOT_PATH"tone/memeda.*", + SDFILE_RES_ROOT_PATH"tone/zeilala.*", + SDFILE_RES_ROOT_PATH"tone/feicheng.*", +}; + + + + +struct tone_dec_handle *tone_hdl = NULL; +struct audio_stream_entry *tone_vol_entry = NULL; +static u8 soundcard_notice_mic_out_en = 1; + + +static void soundcard_notice_play_stream_resume(void *p) +{ + struct audio_dec_app_hdl *app_dec = p; + audio_decoder_resume(&app_dec->decoder); +} +static void soundcard_notice_end(void *priv, int data) +{ + printf("soundcard_notice_end\n"); +} + +void soundcard_notice_play_stream_handler(void *priv, int event, struct audio_dec_app_hdl *app_dec) +{ + u8 entry_cnt = 0; + switch (event) { + case AUDIO_DEC_APP_EVENT_START_INIT_OK: + entry_cnt = 0; + if (soundcard_notice_mic_out_en) { + audio_mixer_ch_set_aud_ch_out(&app_dec->mix_ch, 0, BIT(0) | BIT(2) | BIT(3)); + audio_mixer_ch_set_aud_ch_out(&app_dec->mix_ch, 1, BIT(1) | BIT(2) | BIT(3)); + } else { + audio_mixer_ch_set_aud_ch_out(&app_dec->mix_ch, 0, BIT(0)); + audio_mixer_ch_set_aud_ch_out(&app_dec->mix_ch, 1, BIT(1)); + } + + tone_vol_entry = sys_digvol_group_ch_open("tone_tone", -1, NULL); + + struct audio_stream_entry *entries[8] = {NULL}; + entries[entry_cnt++] = &app_dec->decoder.entry; +#if SYS_DIGVOL_GROUP_EN + entries[entry_cnt++] = tone_vol_entry; +#endif + entries[entry_cnt++] = &app_dec->mix_ch.entry; + app_dec->stream = audio_stream_open(app_dec, soundcard_notice_play_stream_resume); + audio_stream_add_list(app_dec->stream, entries, entry_cnt); + break; + + case AUDIO_DEC_APP_EVENT_DEC_CLOSE: +#if SYS_DIGVOL_GROUP_EN + if (tone_vol_entry) { + audio_stream_del_entry(tone_vol_entry); + sys_digvol_group_ch_close("tone_tone"); + } +#endif + break; + + } +} + +int soundcard_notice_play_by_path(char *name, u8 preemption, void (*evt_handler)(void *priv, int flag), void *evt_priv) +{ + static char *single_file[2] = {NULL}; + single_file[0] = name; + single_file[1] = NULL; + tone_dec_stop(&tone_hdl, 1, TONE_DEC_STOP_BY_OTHER_PLAY); + tone_hdl = tone_dec_create(); + if (tone_hdl == NULL) { + return -1; + } + struct tone_dec_list_handle *dec_list = tone_dec_list_create(tone_hdl, + (const char **) single_file, + preemption, + evt_handler, + NULL, + soundcard_notice_play_stream_handler, + NULL); + return tone_dec_list_add_play(tone_hdl, dec_list); +} + +void soundcard_make_notice_electric(u8 mode) +{ + if (mode >= (sizeof(electric_notice_tab) / sizeof(electric_notice_tab[0]))) { + return ; + } + soundcard_notice_mic_out_en = 0; + soundcard_notice_play_by_path(electric_notice_tab[mode], 0, soundcard_notice_end, 0); + /* tone_play_with_callback_by_name(electric_notice_tab[mode], 0, NULL, NULL); */ +} + +void soundcard_make_some_noise(u8 id) +{ + if (id >= (sizeof(noise_tab) / sizeof(noise_tab[0]))) { + return ; + } + soundcard_notice_mic_out_en = 1; + soundcard_notice_play_by_path(noise_tab[id], 0, soundcard_notice_end, 0); + /* tone_play_with_callback_by_name(noise_tab[id], 0, NULL, NULL); */ +} +#endif//SOUNDCARD_ENABLE + diff --git a/apps/soundbox/soundcard/peripheral.c b/apps/soundbox/soundcard/peripheral.c new file mode 100644 index 0000000..1f8dd2c --- /dev/null +++ b/apps/soundbox/soundcard/peripheral.c @@ -0,0 +1,180 @@ +#include "soundcard/peripheral.h" +#include "soundcard/soundcard.h" +#include "soundcard/lamp.h" +#include "asm/audio_linein.h" +#include "audio_dec.h" +#include "common/user_msg.h" +#include "os/os_api.h" +#include "app_task.h" +#include "asm/rtc.h" +#include "asm/power/p33.h" +#include "asm/gpio.h" +#include "key_event_deal.h" +#include "application/audio_output_dac.h" +#include "linein/linein.h" + + +#if SOUNDCARD_ENABLE +typedef enum __VDET_STATUS { + VDET_OFF = 0, + VDET_ON, + NULL_VDET, +} VDET_STATUS; + + +typedef struct __DEVICE_DET_VAR { + u8 pre_status; + u8 cur_status; + u8 status_cnt; + u8 original_status; +} DEVICE_DET_VAR; + +static DEVICE_DET_VAR g_mic1_var = {0}; +static DEVICE_DET_VAR g_mic2_var = {0}; +static DEVICE_DET_VAR g_aux0_var = {0}; + + +void soundcard_pa_init(void) +{ + gpio_set_direction(IO_PORTC_07, 0); + gpio_set_pull_down(IO_PORTC_07, 0); + gpio_set_pull_up(IO_PORTC_07, 1); + gpio_set_output_value(IO_PORTC_07, 0); +} + +void soundcard_pa_umute(void) +{ + printf("soundcard_pa_umute\n"); + gpio_set_output_value(IO_PORTC_07, 1); + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0) | BIT(1) | BIT(2) | BIT(3), 30, 1);//模拟音量范围0~30 +} + +void soundcard_pa_mute(void) +{ + gpio_set_output_value(IO_PORTC_07, 0); +} + +static VDET_STATUS soundcard_device_check(struct __DEVICE_DET_VAR *var, u8 st, u8 cnt) +{ + var->cur_status = st; + if (var->cur_status != var->pre_status) { + var->original_status = var->pre_status; + var->pre_status = var->cur_status; + var->status_cnt = 0; + } else { + if (var->status_cnt < cnt) { + var->status_cnt++; + if (var->status_cnt == cnt) { + if ((VDET_ON == var->cur_status) && (!var->original_status)) { + return VDET_ON; + } else if ((VDET_OFF == var->cur_status) && var->original_status) { + return VDET_OFF; + } + } + } + } + return NULL_VDET; +} + +static void soundcard_mic_check_detect(void) +{ + VDET_STATUS res; + + u32 check_value_cur = 0; + u8 st; + + check_value_cur = adc_get_value(AD_CH_PA6); + //y_printf("check_value_cur:%d\n",check_value_cur); + + if (check_value_cur > 923) { //2.975V + st = 0; + } else { + st = 1; + } + res = soundcard_device_check(&g_mic1_var, st, 20); + if (VDET_ON == res) { + y_printf("MIC1=============ON\n"); + app_task_put_key_msg(KEY_SOUNDCARD_EAR_MIC_STATUS_UPDATE, res); + } else if (VDET_OFF == res) { + y_printf("MIC1=============OFF\n"); + app_task_put_key_msg(KEY_SOUNDCARD_EAR_MIC_STATUS_UPDATE, res); + } + //y_printf(":%d %d %d\n",g_mic1_var.cur_status,g_mic1_var.pre_status,g_mic1_var.original_status); + + st = !rtc_port_pr_read(0); + res = soundcard_device_check(&g_mic2_var, st, 20); + if (VDET_ON == res) { + y_printf("MIC2=============ON\n"); + app_task_put_key_msg(KEY_SOUNDCARD_NORMAL_MIC_STATUS_UPDATE, res); + } else if (VDET_OFF == res) { + y_printf("MIC2=============OFF\n"); + app_task_put_key_msg(KEY_SOUNDCARD_NORMAL_MIC_STATUS_UPDATE, res); + } + + st = gpio_read(IO_PORTA_02); + res = soundcard_device_check(&g_aux0_var, st, 20); + if (VDET_ON == res) { + y_printf("aux0=============ON\n"); + app_task_put_key_msg(KEY_SOUNDCARD_AUX_STATUS_UPDATE, res); + } else if (VDET_OFF == res) { + y_printf("aux0=============OFF\n"); + app_task_put_key_msg(KEY_SOUNDCARD_AUX_STATUS_UPDATE, res); + } +} +static void soundcard_mic_detect_init(void) +{ + y_printf("%s", __func__); + adc_add_sample_ch(AD_CH_PA6); + gpio_set_die(IO_PORTA_06, 0); + gpio_set_pull_down(IO_PORTA_06, 0); + gpio_set_pull_up(IO_PORTA_06, 0); + gpio_direction_input(IO_PORTA_06); + + p33_tx_1byte(R3_OSL_CON, 0); + rtc_port_pr_die(0, 1); + rtc_port_pr_pu(0, 1); + rtc_port_pr_pd(0, 0); + rtc_port_pr_in(0); + + gpio_set_die(IO_PORTA_02, 1); + gpio_set_pull_down(IO_PORTA_02, 0); + gpio_set_pull_up(IO_PORTA_02, 1); + gpio_direction_input(IO_PORTA_02); + + rtc_port_pr_die(1, 1); + rtc_port_pr_out(1, 1); + + sys_hi_timer_add(NULL, soundcard_mic_check_detect, 10); +} + +void soundcard_ear_mic_mute(u8 mute) +{ + if (mute) { + rtc_port_pr_out(1, 1); + } else { + rtc_port_pr_out(1, 0); + } +} + + + +extern void slidekey_update(void); +static void soundcard_slider_key_update(void *p) +{ + slidekey_update(); +} + +void soundcard_peripheral_init(void) +{ + printf("%s", __func__); + soundcard_pa_init(); + soundcard_led_init(); + soundcard_mic_detect_init(); + soundcard_start(); + sys_timeout_add(NULL, soundcard_pa_umute, 2000); + sys_timeout_add(NULL, soundcard_slider_key_update, 5000);//防止一开始按键消息更新事件丢失导致的音量不正常 +} + +#endif//SOUNDCARD_ENABLE + + diff --git a/apps/soundbox/soundcard/soundcard.c b/apps/soundbox/soundcard/soundcard.c new file mode 100644 index 0000000..88eff35 --- /dev/null +++ b/apps/soundbox/soundcard/soundcard.c @@ -0,0 +1,675 @@ +#include "soundcard/soundcard.h" +#include "soundcard/lamp.h" +#include "soundcard/notice.h" +#include "soundcard/peripheral.h" +#include "audio_mic/mic_effect.h" +#include "key_event_deal.h" +#include "btstack/avctp_user.h" +#include "audio_dec.h" +#include "application/audio_output_dac.h" +#include "linein/linein.h" +#include "app_power_manage.h" +#include "app_task.h" + + +#if SOUNDCARD_ENABLE + + +struct __soundcard { + u8 mode; + u8 electric; + u8 pitch; + u8 mic_status; + u8 status; + + u16 mic_vol; + u16 reverb_wet_vol; + u16 high_sound_vol; + u16 low_sound_vol; + u16 rec_vol; + u16 music_vol; + u16 earphone_vol; + + u32 electric_mode_cancel_tick; + u16 a2dp_stop_timerout; +}; + + +enum { + MIC_TYPE_NORMAL = 0x0, + MIC_TYPE_EAR, +}; + + + +static const u32 electric_tab[] = { + A_MAJOR, + Ashop_MAJOR, + B_MAJOR, + C_MAJOR, + Cshop_MAJOR, + D_MAJOR, + Dshop_MAJOR, + E_MAJOR, + F_MAJOR, + Fshop_MAJOR, + G_MAJOR, + Gshop_MAJOR, +}; + +enum { + APP_PITCH_NONE = 0, + APP_PITCH_BOY, + APP_PITCH_GIRL, + APP_PITCH_KIDS, + APP_PITCH_MAGIC, + /* 电音 */ + APP_SOUNDCARD_MODE_ELECTRIC_A_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_Ashop_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_B_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_C_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_Cshop_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_D_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_Dshop_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_E_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_F_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_Fshop_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_G_MAJOR, + APP_SOUNDCARD_MODE_ELECTRIC_Gshop_MAJOR, + + APP_SOUNDCARD_MODE_BOOM, // 爆音 + APP_SOUNDCARD_MODE_SHOUTING_WHEAT, // 喊麦 + APP_SOUNDCARD_MODE_DODGE, // 闪避 +}; + +static const u16 pitch_tab[] = { + EFFECT_REVERB_MODE_GIRL_TO_BOY, + EFFECT_REVERB_MODE_BOY_TO_GIRL, + EFFECT_REVERB_MODE_KIDS, +}; + +struct __soundcard soundcard = { + .mode = SOUNDCARD_MODE_NORMAL, + .mic_vol = (u16) - 1, + .reverb_wet_vol = (u16) - 1, + .high_sound_vol = (u16) - 1, + .low_sound_vol = (u16) - 1, + .rec_vol = (u16) - 1, + .music_vol = (u16) - 1, + .earphone_vol = (u16) - 1, + .a2dp_stop_timerout = 0, + .status = 0, +}; + + + +#define __this (&soundcard) + + +extern void pc_rrrl_output_enable(u8 onoff); +extern u8 pc_rrrl_output_enable_status(void); + +static void soundcard_mic_status_update(void) +{ + if (__this->mic_status == 0) { + //没有mic在线 + //关闭ear mic + soundcard_ear_mic_mute(1); + //关闭混响 + mic_effect_pause(1); + return ; + } + + if (__this->mic_status & BIT(MIC_TYPE_NORMAL)) { + //普通mic在线 + //mute ear mic + soundcard_ear_mic_mute(1); + } else if (__this->mic_status & BIT(MIC_TYPE_EAR)) { + //ear mic在线 + //unmute ear mic + soundcard_ear_mic_mute(0); + } + //释放暂停状态 + mic_effect_pause(0); +} + + + +static void soundcard_change_mic_effect_mode(u16 mode) +{ + mic_effect_change_mode(mode); +} + +static u8 soundcard_electric_conversion(u32 value) +{ + for (u8 i = 0; i < sizeof(electric_tab) / sizeof(electric_tab[0]); i++) { + if (value == electric_tab[i]) { + return i; + } + } + return 0; +} + +static u8 get_soundcard_electric_conversion(u8 value) +{ + return value + APP_SOUNDCARD_MODE_ELECTRIC_A_MAJOR; +} + +static void soundcard_app_set_pitch_mode(u8 mode) +{ + switch (mode) { + case APP_PITCH_NONE: + __this->mode = SOUNDCARD_MODE_NORMAL; + soundcard_led_mode(SOUNDCARD_MODE_NORMAL, 1); + soundcard_change_mic_effect_mode(EFFECT_REVERB_MODE_NORMAL); + break; + case APP_PITCH_GIRL: + case APP_PITCH_BOY: + case APP_PITCH_KIDS: + __this->mode = SOUNDCARD_MODE_PITCH; + __this->pitch = mode - 1; + soundcard_led_mode(SOUNDCARD_MODE_PITCH, 1); + soundcard_change_mic_effect_mode(pitch_tab[__this->pitch]); + break; + case APP_SOUNDCARD_MODE_ELECTRIC_A_MAJOR: + __this->mode = SOUNDCARD_MODE_ELECTRIC; + __this->electric = soundcard_electric_conversion(A_MAJOR); + break; + case APP_SOUNDCARD_MODE_ELECTRIC_Ashop_MAJOR: + __this->mode = SOUNDCARD_MODE_ELECTRIC; + __this->electric = soundcard_electric_conversion(Ashop_MAJOR); + break; + case APP_SOUNDCARD_MODE_ELECTRIC_B_MAJOR: + __this->mode = SOUNDCARD_MODE_ELECTRIC; + __this->electric = soundcard_electric_conversion(B_MAJOR); + break; + case APP_SOUNDCARD_MODE_ELECTRIC_C_MAJOR: + __this->mode = SOUNDCARD_MODE_ELECTRIC; + __this->electric = soundcard_electric_conversion(C_MAJOR); + break; + case APP_SOUNDCARD_MODE_ELECTRIC_Cshop_MAJOR: + __this->mode = SOUNDCARD_MODE_ELECTRIC; + __this->electric = soundcard_electric_conversion(Cshop_MAJOR); + break; + case APP_SOUNDCARD_MODE_ELECTRIC_D_MAJOR: + __this->mode = SOUNDCARD_MODE_ELECTRIC; + __this->electric = soundcard_electric_conversion(D_MAJOR); + break; + case APP_SOUNDCARD_MODE_ELECTRIC_Dshop_MAJOR: + __this->mode = SOUNDCARD_MODE_ELECTRIC; + __this->electric = soundcard_electric_conversion(Dshop_MAJOR); + break; + case APP_SOUNDCARD_MODE_ELECTRIC_E_MAJOR: + __this->mode = SOUNDCARD_MODE_ELECTRIC; + __this->electric = soundcard_electric_conversion(E_MAJOR); + break; + case APP_SOUNDCARD_MODE_ELECTRIC_F_MAJOR: + __this->mode = SOUNDCARD_MODE_ELECTRIC; + __this->electric = soundcard_electric_conversion(F_MAJOR); + break; + case APP_SOUNDCARD_MODE_ELECTRIC_Fshop_MAJOR: + __this->mode = SOUNDCARD_MODE_ELECTRIC; + __this->electric = soundcard_electric_conversion(Fshop_MAJOR); + break; + case APP_SOUNDCARD_MODE_ELECTRIC_G_MAJOR: + __this->mode = SOUNDCARD_MODE_ELECTRIC; + __this->electric = soundcard_electric_conversion(G_MAJOR); + break; + case APP_SOUNDCARD_MODE_ELECTRIC_Gshop_MAJOR: + __this->mode = SOUNDCARD_MODE_ELECTRIC; + __this->electric = soundcard_electric_conversion(Gshop_MAJOR); + break; + } + + if (SOUNDCARD_MODE_ELECTRIC == __this->mode) { + soundcard_led_mode(SOUNDCARD_MODE_ELECTRIC, 1); + //play notice + soundcard_make_notice_electric(__this->electric); + //切换模式为电音模式,设置完需要手动配置电音的pitch参数,工具不可配 + soundcard_change_mic_effect_mode(EFFECT_REVERB_MODE_ELECTRIC); + PITCH_PARM_SET2 electric_parm = {0}; + //设置电音的大调级数 + electric_parm.formant_shift = electric_tab[__this->electric]; + //电音该参数固定为100 + electric_parm.pitch = 100; + //因为电音参数是固定的不是通过工具 + mic_effect_pitch_parm_fill(&electric_parm, 1, 0); + } +} + +static u8 soundcard_pitch_conversion(u8 value) +{ + u8 ret = 0; + switch (value) { + case EFFECT_REVERB_MODE_BOY_TO_GIRL: + ret = APP_PITCH_GIRL; + break; + case EFFECT_REVERB_MODE_GIRL_TO_BOY: + ret = APP_PITCH_BOY; + break; + case EFFECT_REVERB_MODE_KIDS: + ret = APP_PITCH_KIDS; + break; + } + return ret; +} + +u8 get_curr_soundcard_pitch(void) +{ + u8 ret = 0; + if (__this->mode == SOUNDCARD_MODE_PITCH) { + ret = soundcard_pitch_conversion(pitch_tab[__this->pitch]); + } + return ret; +} + +u8 get_curr_soundcard_pitch_by_value(void) +{ + u8 ret = 0; + if (!__this) { + return 0; + } + switch (__this->mode) { + case SOUNDCARD_MODE_NORMAL: + ret = APP_PITCH_NONE; + break; + case SOUNDCARD_MODE_PITCH: + ret = soundcard_pitch_conversion(pitch_tab[__this->pitch]); + break; + case SOUNDCARD_MODE_ELECTRIC: + ret = get_soundcard_electric_conversion(__this->electric); + break; + } + return ret; +} + +u8 curr_soundcard_mode_is_normal(void) +{ + return (SOUNDCARD_MODE_NORMAL == __this->mode); +} + +u8 get_curr_key_soundcard_pitch(void) +{ + return __this->pitch; +} + +u16 soundcard_get_mic_vol(void) +{ + return __this->mic_vol; +} + +u16 soundcard_get_reverb_wet_vol(void) +{ + return __this->reverb_wet_vol; +} + +u16 soundcard_get_low_sound_vol(void) +{ + return __this->low_sound_vol; +} + +u16 soundcard_get_high_sound_vol(void) +{ + return __this->high_sound_vol; +} + +u16 soundcard_get_rec_vol(void) +{ + return __this->rec_vol; +} + +u16 soundcard_get_music_vol(void) +{ + return __this->music_vol; +} + +u16 soundcard_get_earphone_vol(void) +{ + return __this->earphone_vol; +} + +void soundcard_event_deal(struct sys_event *event) +{ + struct key_event *key = &event->u.key; + int key_event = event->u.key.event; + int key_value = event->u.key.value; + u8 mic_status = 0; + + if (key_event == KEY_NULL) { + return ; + } + + if (__this->status == 0) { + return ; + } + + switch (key_event) { + //按键模式操作 + case KEY_SOUNDCARD_MODE_ELECTRIC: + log_i("KEY_SOUNDCARD_MODE_ELECTRIC\n"); + if (__this->mode != SOUNDCARD_MODE_ELECTRIC) { + __this->mode = SOUNDCARD_MODE_ELECTRIC; + __this->electric = 0; + } else { + __this->electric++; + if (__this->electric >= ARRAY_SIZE(electric_tab)) { + __this->electric = 0; + //__this->mode = SOUNDCARD_MODE_NORMAL; + //soundcard_led_mode(SOUNDCARD_MODE_NORMAL, 1); + //soundcard_change_mic_effect_mode(EFFECT_REVERB_MODE_NORMAL); + //break; + } + } + soundcard_led_mode(SOUNDCARD_MODE_ELECTRIC, 1); + //play notice + soundcard_make_notice_electric(__this->electric); + //切换模式为电音模式,设置完需要手动配置电音的pitch参数,工具不可配 + soundcard_change_mic_effect_mode(EFFECT_REVERB_MODE_ELECTRIC); + PITCH_PARM_SET2 electric_parm = {0}; + //设置电音的大调级数 + electric_parm.formant_shift = electric_tab[__this->electric]; + //电音该参数固定为100 + electric_parm.pitch = 100; + //因为电音参数是固定的不是通过工具 + mic_effect_pitch_parm_fill(&electric_parm, 1, 0); + break; + case KEY_SOUNDCARD_MODE_ELECTRIC_CANCEL: + if (__this->mode == SOUNDCARD_MODE_ELECTRIC) { + if (__this->electric_mode_cancel_tick == 0) { + __this->electric_mode_cancel_tick = timer_get_ms(); + break; + } + u32 cur_tick = timer_get_ms(); + if ((cur_tick - __this->electric_mode_cancel_tick) > 4000) { + __this->electric_mode_cancel_tick = timer_get_ms(); + break; + } else if ((cur_tick - __this->electric_mode_cancel_tick) > 3000) { + log_i("KEY_SOUNDCARD_MODE_ELECTRIC_CANCEL\n"); + __this->electric_mode_cancel_tick = 0; + __this->mode = SOUNDCARD_MODE_NORMAL; + soundcard_led_mode(SOUNDCARD_MODE_NORMAL, 1); + soundcard_change_mic_effect_mode(EFFECT_REVERB_MODE_NORMAL); + } + } + break; + case KEY_SOUNDCARD_MODE_PITCH: + log_i("KEY_SOUNDCARD_MODE_PITCH\n"); + if (__this->mode != SOUNDCARD_MODE_PITCH) { + __this->mode = SOUNDCARD_MODE_PITCH; + __this->pitch = 0; + } else { + __this->pitch++; + if (__this->pitch >= ARRAY_SIZE(pitch_tab)) { + __this->mode = SOUNDCARD_MODE_NORMAL; + soundcard_led_mode(SOUNDCARD_MODE_NORMAL, 1); + soundcard_change_mic_effect_mode(EFFECT_REVERB_MODE_NORMAL); + break; + } + } + soundcard_led_mode(SOUNDCARD_MODE_PITCH, 1); + soundcard_change_mic_effect_mode(pitch_tab[__this->pitch]); + break; + case KEY_SOUNDCARD_MODE_PITCH_BY_VALUE: + log_i("KEY_SOUNDCARD_MODE_PITCH_BY_VALUE, %d\n", key_value); + soundcard_app_set_pitch_mode(key_value); + break; + case KEY_SOUNDCARD_MODE_MAGIC: + log_i("KEY_SOUNDCARD_MODE_MAGIC\n"); + if (__this->mode != SOUNDCARD_MODE_MAGIC) { + __this->mode = SOUNDCARD_MODE_MAGIC; + soundcard_led_mode(SOUNDCARD_MODE_MAGIC, 1); + soundcard_change_mic_effect_mode(EFFECT_REVERB_MODE_MAGIC); + } else { + __this->mode = SOUNDCARD_MODE_NORMAL; + soundcard_led_mode(SOUNDCARD_MODE_NORMAL, 1); + soundcard_change_mic_effect_mode(EFFECT_REVERB_MODE_NORMAL); + } + break; + case KEY_SOUNDCARD_MODE_BOOM: + log_i("KEY_SOUNDCARD_MODE_BOOM\n"); + if (__this->mode != SOUNDCARD_MODE_BOOM) { + __this->mode = SOUNDCARD_MODE_BOOM; + soundcard_led_mode(SOUNDCARD_MODE_BOOM, 1); + soundcard_change_mic_effect_mode(EFFECT_REVERB_MODE_BOOM); + } else { + __this->mode = SOUNDCARD_MODE_NORMAL; + soundcard_led_mode(SOUNDCARD_MODE_NORMAL, 1); + soundcard_change_mic_effect_mode(EFFECT_REVERB_MODE_NORMAL); + } + break; + case KEY_SOUNDCARD_MODE_SHOUTING_WHEAT: + log_i("KEY_SOUNDCARD_MODE_SHOUTING_WHEAT\n"); + if (__this->mode != SOUNDCARD_MODE_SHOUTING_WHEAT) { + __this->mode = SOUNDCARD_MODE_SHOUTING_WHEAT; + soundcard_led_mode(SOUNDCARD_MODE_SHOUTING_WHEAT, 1); + soundcard_change_mic_effect_mode(EFFECT_REVERB_MODE_SHOUTING_WHEAT); + mic_effect_cal_coef(MIC_EQ_MODE_SHOUT_WHEAT, 1); + } else { + __this->mode = SOUNDCARD_MODE_NORMAL; + mic_effect_cal_coef(MIC_EQ_MODE_SHOUT_WHEAT, 0); + soundcard_led_mode(SOUNDCARD_MODE_NORMAL, 1); + soundcard_change_mic_effect_mode(EFFECT_REVERB_MODE_NORMAL); + } + break; + case KEY_SOUNDCARD_MODE_DODGE: +#if(TCFG_MIC_DODGE_EN) + mic_dodge_ctr(); + if (mic_dodge_get_status()) { + soundcard_led_mode(SOUNDCARD_MODE_DODGE, 1); + } else { + soundcard_led_mode(SOUNDCARD_MODE_DODGE, 0); + } +#endif + break; + + case KEY_SOUNDCARD_USB_MIC_MUTE_SWICH: + log_i("KEY_SOUNDCARD_USB_MIC_MUTE_SWICH\n"); + mem_stats(); + /* break; */ +#if (TCFG_PC_ENABLE) + if (pc_rrrl_output_enable_status()) { + printf("pc_rrrl_output_enable\n"); + pc_rrrl_output_enable(0); + } else { + printf("pc_rrrl_output_disable\n"); + pc_rrrl_output_enable(1); + } +#endif + /* if (mic_effect_get_status()) { */ + /* mic_effect_stop(); */ + /* } else { */ + /* mic_effect_start(); */ + /* } */ + break; + + //按键提示音响应处理 + case KEY_SOUNDCARD_MAKE_NOISE0: + case KEY_SOUNDCARD_MAKE_NOISE1: + case KEY_SOUNDCARD_MAKE_NOISE2: + case KEY_SOUNDCARD_MAKE_NOISE3: + case KEY_SOUNDCARD_MAKE_NOISE4: + case KEY_SOUNDCARD_MAKE_NOISE5: + case KEY_SOUNDCARD_MAKE_NOISE6: + case KEY_SOUNDCARD_MAKE_NOISE7: + case KEY_SOUNDCARD_MAKE_NOISE8: + case KEY_SOUNDCARD_MAKE_NOISE9: + case KEY_SOUNDCARD_MAKE_NOISE10: + case KEY_SOUNDCARD_MAKE_NOISE11: + log_i("make noise index = %d\n", key_event - KEY_SOUNDCARD_MAKE_NOISE0); + soundcard_make_some_noise(key_event - KEY_SOUNDCARD_MAKE_NOISE0); + break; + case KEY_SOUNDCARD_SLIDE_MIC: + log_i("slide MIC:%d\n", key_value); + __this->mic_vol = key_value; + mic_effect_set_dvol(key_value); + break; + case KEY_SOUNDCARD_SLIDE_WET_GAIN: + log_i("slide WET:%d\n", key_value); + __this->reverb_wet_vol = key_value; + key_value = key_value * 10; //key_value*300/30; + mic_effect_set_reverb_wet(key_value); + break; + case KEY_SOUNDCARD_SLIDE_HIGH_SOUND: + log_i("slide HIGH SOUND:%d\n", key_value); + __this->high_sound_vol = key_value; + mic_effect_cal_coef(MIC_EQ_MODE_HIGH_SOUND, key_value); + break; + case KEY_SOUNDCARD_SLIDE_LOW_SOUND: + log_i("slide LOW SOUND:%d\n", key_value); + __this->low_sound_vol = key_value; + mic_effect_cal_coef(MIC_EQ_MODE_LOW_SOUND, key_value); + break; + case KEY_SOUNDCARD_SLIDE_RECORD_VOL: + log_i("slide RECORD:%d\n", key_value); + __this->rec_vol = key_value; + //设置dac rr rl硬件数字音量 + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(2) | BIT(3), (u32)__this->rec_vol * (u32)16384 / (u32)30, 1); + break; + case KEY_SOUNDCARD_SLIDE_EARPHONE_VOL: + log_i("slide EARPHONE:%d\n", key_value); + __this->earphone_vol = key_value; + //设置dac fr fl硬件数字音量 + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0) | BIT(1), (u32)__this->earphone_vol * (u32)16384 / (u32)30, 1); + break; + case KEY_SOUNDCARD_SLIDE_MUSIC_VOL: + log_i("slide MUSIC:%d\n", key_value); + __this->music_vol = key_value; + audio_dig_vol_set(audio_dig_vol_group_hdl_get(sys_digvol_group, "music_a2dp"), AUDIO_DIG_VOL_ALL_CH, __this->music_vol); + audio_dig_vol_set(audio_dig_vol_group_hdl_get(sys_digvol_group, "music_linein"), AUDIO_DIG_VOL_ALL_CH, __this->music_vol); + audio_dig_vol_set(audio_dig_vol_group_hdl_get(sys_digvol_group, "music_pc"), AUDIO_DIG_VOL_ALL_CH, __this->music_vol); + break; + + case KEY_SOUNDCARD_NORMAL_MIC_STATUS_UPDATE: + if (key_value) { + __this->mic_status |= BIT(MIC_TYPE_NORMAL); + } else { + __this->mic_status &= ~BIT(MIC_TYPE_NORMAL); + } + soundcard_mic_status_update(); + break; + case KEY_SOUNDCARD_EAR_MIC_STATUS_UPDATE: + if (key_value) { + __this->mic_status |= BIT(MIC_TYPE_EAR); + } else { + __this->mic_status &= ~BIT(MIC_TYPE_EAR); + } + soundcard_mic_status_update(); + break; + + case KEY_SOUNDCARD_AUX_STATUS_UPDATE: + if (key_value) { + + } else { + + } + break; + default: + break; + } +} + +static void soundcard_change_mode_timerout(void *p) +{ + if (app_get_curr_task() == APP_PC_TASK) { + return ; + } + if (pc_app_check() == true) { + app_task_switch_to(APP_PC_TASK); + } +} + +static void soundcard_switch_pc_mode_start(u32 msec) +{ +#if (TCFG_PC_ENABLE) + if (__this->a2dp_stop_timerout) { + sys_timeout_del(__this->a2dp_stop_timerout); + } + __this->a2dp_stop_timerout = sys_timeout_add(NULL, soundcard_change_mode_timerout, msec); +#endif +} + +static void soundcard_switch_pc_mode_stop(void) +{ +#if (TCFG_PC_ENABLE) + if (__this->a2dp_stop_timerout) { + sys_timeout_del(__this->a2dp_stop_timerout); + __this->a2dp_stop_timerout = 0; + } +#endif +} + + + +void soundcard_bt_connect_status_event(struct bt_event *e) +{ + switch (e->event) { + case BT_STATUS_SECOND_CONNECTED: + case BT_STATUS_FIRST_CONNECTED: + soundcard_switch_pc_mode_start(5000); + soundcard_led_self_set(UI_LED_SELF_BLUE_FLASH, 0); + break; + case BT_STATUS_FIRST_DISCONNECT: + case BT_STATUS_SECOND_DISCONNECT: + soundcard_led_self_set(UI_LED_SELF_BLUE_FLASH, 1); + break; + case BT_STATUS_PHONE_INCOME: + break; + case BT_STATUS_PHONE_OUT: + break; + case BT_STATUS_PHONE_ACTIVE: + break; + case BT_STATUS_PHONE_HANGUP: + break; + case BT_STATUS_PHONE_NUMBER: + break; + case BT_STATUS_SCO_STATUS_CHANGE: + break; + case BT_STATUS_VOICE_RECOGNITION: + break; + case BT_STATUS_A2DP_MEDIA_START: + soundcard_switch_pc_mode_stop(); + break; + case BT_STATUS_INIT_OK: + soundcard_switch_pc_mode_start(5000); + break; + case BT_STATUS_A2DP_MEDIA_STOP: + soundcard_switch_pc_mode_start(2000); + break; + default: + break; + } +} + +void soundcard_power_event(struct device_event *dev) +{ +#if(TCFG_SYS_LVD_EN == 1) + switch (dev->event) { + case POWER_EVENT_POWER_NORMAL: + printf("POWER_EVENT_POWER_NORMAL\n"); + soundcard_low_power_led(0); + break; + case POWER_EVENT_POWER_WARNING: + printf("POWER_EVENT_POWER_WARNING\n"); + soundcard_low_power_led(1); + break; + } +#endif +} + +void soundcard_start(void) +{ + mic_effect_start(); + audio_mic_0dB_en(1); + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0) | BIT(1) | BIT(2) | BIT(3), 0, 1);//模拟音量范围0~30 + __this->status = 1; +} + +void soundcard_close(void) +{ + __this->status = 0; + mic_effect_stop(); +} + +#endif/*SOUNDCARD_ENABLE*/ + + diff --git a/apps/soundbox/task_manager/app_common.c b/apps/soundbox/task_manager/app_common.c new file mode 100644 index 0000000..3ba60fa --- /dev/null +++ b/apps/soundbox/task_manager/app_common.c @@ -0,0 +1,539 @@ +#include "common/app_common.h" +#include "app_task.h" +#include "app_main.h" +#include "key_event_deal.h" +#include "music/music.h" +#include "pc/pc.h" +#include "record/record.h" +#include "linein/linein.h" +#include "fm/fm.h" +#include "btstack/avctp_user.h" +#include "app_power_manage.h" +#include "app_chargestore.h" +#include "usb/otg.h" +#include "usb/host/usb_host.h" +#include +#include "bt/bt_tws.h" +#include "audio_config.h" +#include "common/power_off.h" +#include "common/user_msg.h" +#include "audio_config.h" +#include "audio_enc.h" +#include "ui/ui_api.h" +#include "fm_emitter/fm_emitter_manage.h" +#include "common/fm_emitter_led7_ui.h" +#if TCFG_CHARGE_ENABLE +#include "app_charge.h" +#endif +#include "dev_multiplex_api.h" +#include "chgbox_ctrl.h" +#include "device/chargebox.h" +#include "app_online_cfg.h" +#include "soundcard/soundcard.h" +#include "smartbox_bt_manage.h" +#include "bt.h" +#include "common/dev_status.h" +#include "tone_player.h" +#include "ui_manage.h" +#include "soundbox.h" +#include "bt_emitter.h" + +#define LOG_TAG_CONST APP_ACTION +#define LOG_TAG "[APP_ACTION]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +int JL_rcsp_event_handler(struct rcsp_event *rcsp); +int bt_background_event_handler(struct sys_event *event); +extern u32 timer_get_ms(void); +extern int alarm_sys_event_handler(struct sys_event *event); +extern void bt_tws_sync_volume(); + +static u32 input_number = 0; +static u16 input_number_timer = 0; +static void input_number_timeout(void *p) +{ + input_number_timer = 0; + printf("input_number = %d\n", input_number); + if (app_get_curr_task() == APP_MUSIC_TASK) { + app_task_put_key_msg(KEY_MUSIC_PLAYE_BY_DEV_FILENUM, (int)input_number); + } + input_number = 0; +} +static void input_number_deal(u32 num) +{ + input_number = input_number * 10 + num; + if (input_number > 9999) { + input_number = num; + } + printf("num = %d, input_number = %d, input_number_timer = %d\n", num, input_number, input_number_timer); + if (input_number_timer == 0) { + input_number_timer = sys_timeout_add(NULL, input_number_timeout, 1000); + } else { + sys_timer_modify(input_number_timer, 1000); + } + UI_SHOW_MENU(MENU_FILENUM, 4 * 1000, input_number, NULL); +} + + +int app_common_key_msg_deal(struct sys_event *event) +{ + int ret = false; + struct key_event *key = &event->u.key; + int key_event = event->u.key.event; + int key_value = event->u.key.value; + + if (key_event == KEY_NULL) { + return false; + } + + if (key_is_ui_takeover()) { + ui_key_msg_post(key_event); + return false; + } + +#if (TCFG_UI_ENABLE && TCFG_APP_FM_EMITTER_EN) + if (!ui_fm_emitter_common_key_msg(key_event)) { + return false; + } +#endif + + log_info("common_key_event:%d\n", key_event); + + if ((key_event != KEY_POWEROFF) && (key_event != KEY_POWEROFF_HOLD)) { + extern u8 goto_poweroff_first_flag; + goto_poweroff_first_flag = 0; + } + +#if (SMART_BOX_EN) + extern bool smartbox_key_event_filter_before(int key_event); + if (smartbox_key_event_filter_before(key_event)) { + return true; + } +#endif + + switch (key_event) { +#if TCFG_APP_BT_EN + +#if TCFG_USER_TWS_ENABLE + case KEY_TWS_CONN: + log_info(" KEY_TWS_CONN \n"); + bt_open_tws_conn(0); + break; + case KEY_TWS_DISCONN: + log_info(" KEY_TWS_DISCONN \n"); + bt_disconnect_tws_conn(); + break; + case KEY_TWS_REMOVE_PAIR: + log_info(" KEY_TWS_REMOVE_PAIR \n"); + bt_tws_remove_tws_pair(); + break; + case KEY_TWS_SEARCH_PAIR: + log_info(" KEY_TWS_SEARCH_PAIR \n"); + bt_tws_start_search_and_pair(); + break; + case KEY_TWS_SEARCH_REMOVE_PAIR: + log_info(" KEY_TWS_SEARCH_REMOVE_PAIR \n"); + bt_tws_search_or_remove_pair(); + break; +#endif + + case KEY_BT_DIRECT_INIT: + bt_direct_init(); + break; + case KEY_BT_DIRECT_CLOSE: + bt_direct_close(); + break; +#endif + + case KEY_POWEROFF: + case KEY_POWEROFF_HOLD: + power_off_deal(event, key_event - KEY_POWEROFF); + break; + + case KEY_IR_NUM_0: + case KEY_IR_NUM_1: + case KEY_IR_NUM_2: + case KEY_IR_NUM_3: + case KEY_IR_NUM_4: + case KEY_IR_NUM_5: + case KEY_IR_NUM_6: + case KEY_IR_NUM_7: + case KEY_IR_NUM_8: + case KEY_IR_NUM_9: + input_number_deal(key_event - KEY_IR_NUM_0); + break; + + case KEY_CHANGE_MODE: +#if (TCFG_DEC2TWS_ENABLE) + if (!key->init) { + break; + } +#endif +#if TWFG_APP_POWERON_IGNORE_DEV + if ((timer_get_ms() - app_var.start_time) > TWFG_APP_POWERON_IGNORE_DEV) +#endif//TWFG_APP_POWERON_IGNORE_DEV + + { + printf("KEY_CHANGE_MODE\n"); + app_task_switch_next(); + } + break; + + case KEY_VOL_UP: + log_info("COMMON KEY_VOL_UP\n"); + if (!tone_get_status()) { + app_audio_volume_up(1); + printf("common vol+: %d", app_audio_get_volume(APP_AUDIO_CURRENT_STATE)); + } + if (app_audio_get_volume(APP_AUDIO_CURRENT_STATE) == app_audio_get_max_volume()) { + if (tone_get_status() == 0) { +#if TCFG_MAX_VOL_PROMPT + tone_play_by_path(tone_table[IDEX_TONE_MAX_VOL], 0); +#endif + } + } + +#if (TCFG_DEC2TWS_ENABLE) + bt_tws_sync_volume(); +#endif + UI_SHOW_MENU(MENU_MAIN_VOL, 1000, app_audio_get_volume(APP_AUDIO_CURRENT_STATE), NULL); + break; + + case KEY_VOL_DOWN: + log_info("COMMON KEY_VOL_DOWN\n"); + app_audio_volume_down(1); + printf("common vol-: %d", app_audio_get_volume(APP_AUDIO_CURRENT_STATE)); +#if (TCFG_DEC2TWS_ENABLE) + bt_tws_sync_volume(); +#endif + UI_SHOW_MENU(MENU_MAIN_VOL, 1000, app_audio_get_volume(APP_AUDIO_CURRENT_STATE), NULL); + break; + + case KEY_EQ_MODE: +#if(TCFG_EQ_ENABLE == 1) + eq_mode_sw(); +#endif + break; +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) + + + case KEY_BT_EMITTER_RECEIVER_SW: + printf(" KEY_BT_EMITTER_RECEIVER_SW\n"); + bt_emitter_receiver_sw(); + break; + + case KEY_BT_EMITTER_PAUSE: + r_printf(" KEY_BT_EMITTER_PAUSE\n"); + bt_emitter_pp(0); + break; + + case KEY_BT_EMITTER_PLAY: + r_printf(" KEY_BT_EMITTER_PLAY\n"); + bt_emitter_pp(1); + break; + + case KEY_BT_EMITTER_SW: + printf("KEY_BT_EMITTER_SW\n"); + { + extern u8 bt_emitter_stu_sw(void); + if (bt_emitter_stu_sw()) { + printf("bt emitter start \n"); + } else { + printf("bt emitter stop \n"); + } + } + break; +#endif + + +#if (TCFG_CHARGE_BOX_ENABLE) + case KEY_BOX_POWER_CLICK: + case KEY_BOX_POWER_LONG: + case KEY_BOX_POWER_HOLD: + case KEY_BOX_POWER_UP: + case KEY_BOX_POWER_DOUBLE: + case KEY_BOX_POWER_THREE: + case KEY_BOX_POWER_FOUR: + case KEY_BOX_POWER_FIVE: + charge_box_key_event_handler(key_event); + break; +#endif +#if (TCFG_MIC_EFFECT_ENABLE) + case KEY_REVERB_SWITCH: + switch_mic_effect_mode(); + break; + case KEY_REVERB_OPEN: +#if TCFG_USER_TWS_ENABLE + if (!key->init) { + break; + } +#endif + if (mic_effect_get_status()) { + mic_effect_stop(); + } else { + mic_effect_start(); + } + ret = true; + break; +#endif + case KEY_ENC_START: +#if (RECORDER_MIX_EN) + if (recorder_mix_get_status()) { + printf("recorder_encode_stop\n"); + recorder_mix_stop(); + } else { + if (dev_manager_get_phy_logo(dev_manager_find_active(0))) { + printf("recorder_encode_start\n"); + recorder_mix_start(); + } + } +#endif/*RECORDER_MIX_EN*/ + break; + default: + ui_key_msg_post(key_event); + ui_simple_key_msg_post(key_event, key_value); +#if (SOUNDCARD_ENABLE) + soundcard_event_deal(event); +#endif + break; + + } +#if (SMART_BOX_EN) + extern int smartbox_common_key_event_deal(int key_event, int ret); + ret = smartbox_common_key_event_deal(key_event, ret); +#endif + return ret; +} + +int app_power_user_event_handler(struct device_event *dev) +{ +#if(TCFG_SYS_LVD_EN == 1) + switch (dev->event) { + case POWER_EVENT_POWER_WARNING: + ui_update_status(STATUS_LOWPOWER); + tone_play_by_path(tone_table[IDEX_TONE_LOW_POWER], 1); + /* return 0; */ + } +#if (SOUNDCARD_ENABLE) + soundcard_power_event(dev); +#endif +#endif + return app_power_event_handler(dev); +} + +static void app_common_device_event_handler(struct sys_event *event) +{ + int ret = 0; + const char *logo = NULL; + const char *usb_msg = NULL; + u8 app = 0xff ; + u8 alarm_flag = 0; + switch ((u32)event->arg) { +#if (TCFG_SOUNDBOX_TOOL_ENABLE || TCFG_ONLINE_ENABLE) + case DEVICE_EVENT_FROM_SOUNDBOX_TOOL: + extern int app_soundbox_tool_event_handler(struct soundbox_tool_event * soundbox_tool_dev); + app_soundbox_tool_event_handler(&event->u.soundbox_tool); + break; +#endif +#if TCFG_CHARGE_ENABLE + case DEVICE_EVENT_FROM_CHARGE: + app_charge_event_handler(&event->u.dev); + break; +#endif//TCFG_CHARGE_ENABLE + +#if (TCFG_ONLINE_ENABLE || TCFG_SOUNDBOX_TOOL_ENABLE) + case DEVICE_EVENT_FROM_CI_UART: + ci_data_rx_handler(CI_UART); + break; + +#if TCFG_USER_TWS_ENABLE + case DEVICE_EVENT_FROM_CI_TWS: + ci_data_rx_handler(CI_TWS); + break; +#endif//TCFG_USER_TWS_ENABLE +#endif//TCFG_ONLINE_ENABLE + + case DEVICE_EVENT_FROM_POWER: + app_power_user_event_handler(&event->u.dev); + break; + +#if TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE + case DEVICE_EVENT_CHARGE_STORE: + app_chargestore_event_handler(&event->u.chargestore); + break; +#endif//TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE + +#if(TCFG_CHARGE_BOX_ENABLE) + case DEVICE_EVENT_FROM_CHARGEBOX: + charge_box_ctrl_event_handler(&event->u.chargebox); + break; +#endif + + + case DEVICE_EVENT_FROM_OTG: + ///先分析OTG设备类型 + usb_msg = (const char *)event->u.dev.value; + if (usb_msg[0] == 's') { + ///是从机 +#if TCFG_PC_ENABLE + ret = pc_device_event_handler(event); + if (ret == true) { + app = APP_PC_TASK; + } +#endif + break; + } else if (usb_msg[0] == 'h') { + ///是主机, 统一于SD卡等响应主机处理,这里不break + } else { + log_e("unknow otg devcie !!!\n"); + break; + } + case DRIVER_EVENT_FROM_SD0: + case DRIVER_EVENT_FROM_SD1: + case DRIVER_EVENT_FROM_SD2: +#if TCFG_APP_MUSIC_EN + ret = dev_status_event_filter(event);///解码设备上下线, 设备挂载等处理 + if (ret == true) { + if (event->u.dev.event == DEVICE_EVENT_IN) { + ///设备上线, 非解码模式切换到解码模式播放 + if (app_get_curr_task() != APP_MUSIC_TASK) { + app = APP_MUSIC_TASK; + } + } + } +#endif + break; + +#if TCFG_APP_LINEIN_EN + case DEVICE_EVENT_FROM_LINEIN: + ret = linein_device_event_handler(event); + if (ret == true) { + app = APP_LINEIN_TASK; + } + break; +#endif//TCFG_APP_LINEIN_EN + +#if TCFG_APP_RTC_EN + case DEVICE_EVENT_FROM_ALM: + ret = alarm_sys_event_handler(event); + if (ret == true) { + alarm_flag = 1; + app = APP_RTC_TASK; + } + break; +#endif//TCFG_APP_RTC_EN + + default: + /* printf("unknow SYS_DEVICE_EVENT!!, %x\n", (u32)event->arg); */ + break; + } + +#if (SMART_BOX_EN) + extern void smartbox_update_dev_state(u32 event); + smartbox_update_dev_state((u32)event->arg); +#endif + + if (app != 0xff) { + if ((true != app_check_curr_task(APP_PC_TASK)) || alarm_flag) { + + //PC 不响应因为设备上线引发的模式切换 +#if TWFG_APP_POWERON_IGNORE_DEV + if ((timer_get_ms() - app_var.start_time) > TWFG_APP_POWERON_IGNORE_DEV) +#endif//TWFG_APP_POWERON_IGNORE_DEV + { +#if (TCFG_CHARGE_ENABLE && (!TCFG_CHARGE_POWERON_ENABLE)) + extern u8 get_charge_online_flag(void); + if (get_charge_online_flag()) { + + } else +#endif + { + + printf(">>>>>>>>>>>>>%s %d \n", __FUNCTION__, __LINE__); + app_task_switch_to(app); + } + } + } + } +} + + +///公共事件处理, 各自模式没有处理的事件, 会统一在这里处理 +void app_default_event_deal(struct sys_event *event) +{ + int ret; + SYS_EVENT_HANDLER_SPECIFIC(event); + switch (event->type) { + case SYS_DEVICE_EVENT: + /*默认公共设备事件处理*/ + /* printf(">>>>>>>>>>>>>%s %d \n", __FUNCTION__, __LINE__); */ + app_common_device_event_handler(event); + break; +#if TCFG_APP_BT_EN + case SYS_BT_EVENT: + if (true != app_check_curr_task(APP_BT_TASK)) { + /*默认公共BT事件处理*/ + bt_background_event_handler(event); + } + break; +#endif + case SYS_KEY_EVENT: + app_common_key_msg_deal(event); + break; + default: + printf("unknow event\n"); + break; + } +} + + +#if 0 +extern int key_event_remap(struct sys_event *e); +extern const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX]; +u8 app_common_key_var_2_event(u32 key_var) +{ + u8 key_event = 0; + u8 key_value = 0; + struct sys_event e = {0}; +#if TCFG_ADKEY_ENABLE + for (; key_value < KEY_AD_NUM_MAX; key_value++) { + for (key_event = 0; key_event < KEY_EVENT_MAX; key_event++) { + if (bt_key_ad_table[key_value][key_event] == key_var) { + e.type = SYS_KEY_EVENT; + e.u.key.type = KEY_DRIVER_TYPE_AD; + e.u.key.event = key_event; + e.u.key.value = key_value; + /* e.u.key.tmr = timer_get_ms(); */ + e.arg = (void *)DEVICE_EVENT_FROM_KEY; + /* printf("key2event:%d %d %d\n", key_var, key_value, key_event); */ + if (key_event_remap(&e)) { + sys_event_notify(&e); + return true; + } + } + } + } +#endif + return false; +} + +#else + +u8 app_common_key_var_2_event(u32 key_var) +{ + struct sys_event e = {0}; + e.type = SYS_KEY_EVENT; + e.u.key.type = KEY_DRIVER_TYPE_SOFTKEY; + e.u.key.event = key_var; + e.arg = (void *)DEVICE_EVENT_FROM_KEY; + sys_event_notify(&e); + return true; +} +#endif + diff --git a/apps/soundbox/task_manager/app_task_switch.c b/apps/soundbox/task_manager/app_task_switch.c new file mode 100644 index 0000000..e00b872 --- /dev/null +++ b/apps/soundbox/task_manager/app_task_switch.c @@ -0,0 +1,335 @@ +#include "app_config.h" +#include "app_task.h" +#include "app_msg.h" +#include "key_driver.h" +#include "key_event_deal.h" +#include "audio_recorder_mix.h" + +///模式配置表,这里可以配置切换模式的顺序,方案根据需求定义 +static const u8 app_task_list[] = { +#if TCFG_APP_BT_EN + APP_BT_TASK, +#endif +#if TCFG_APP_MUSIC_EN + APP_MUSIC_TASK, +#endif +#if TCFG_APP_FM_EN + APP_FM_TASK, +#endif +#if TCFG_APP_RECORD_EN + APP_RECORD_TASK, +#endif +#if TCFG_APP_LINEIN_EN + APP_LINEIN_TASK, +#endif +#if TCFG_APP_RTC_EN + APP_RTC_TASK, +#endif +#if TCFG_APP_SLEEP_EN + APP_SLEEP_TASK, +#endif +#if TCFG_APP_PC_EN + APP_PC_TASK, +#endif +#if TCFG_APP_SPDIF_EN + APP_SPDIF_TASK, +#endif +}; + +u8 app_prev_task = 0; +u8 app_curr_task = 0; +u8 app_next_task = 0; + +//*----------------------------------------------------------------------------*/ +/**@brief 模式按键映射处理 + @param e:按键事件 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ + +int app_key_event_remap(struct sys_event *e) +{ + struct key_event *key = &e->u.key; + int msg = KEY_NULL; + switch (key->type) { + case KEY_DRIVER_TYPE_IO: +#if TCFG_IOKEY_ENABLE + msg = iokey_event_to_msg(app_curr_task, key); +#endif + break; + case KEY_DRIVER_TYPE_AD: + case KEY_DRIVER_TYPE_RTCVDD_AD: +#if TCFG_ADKEY_ENABLE + msg = adkey_event_to_msg(app_curr_task, key); +#endif + break; + case KEY_DRIVER_TYPE_IR: +#if TCFG_IRKEY_ENABLE + msg = irkey_event_to_msg(app_curr_task, key); +#endif + break; + case KEY_DRIVER_TYPE_TOUCH: +#if TCFG_TOUCH_KEY_ENABLE + msg = touch_key_event_to_msg(app_curr_task, key); +#endif + break; + case KEY_DRIVER_TYPE_RDEC: +#if TCFG_RDEC_KEY_ENABLE + msg = rdec_key_event_to_msg(app_curr_task, key); +#endif + break; + + case KEY_DRIVER_TYPE_SOFTKEY: + msg = key->event; + break; + default: + break; + } + + if (msg == KEY_NULL) { + e->consumed = 1;//接管按键消息,app应用不会收到消息 + return FALSE; + } + + e->u.key.event = msg; + e->u.key.value = 0;// + return TRUE;//notify数据 +} +SYS_EVENT_HANDLER(SYS_KEY_EVENT, app_key_event_remap, 3); +//*----------------------------------------------------------------------------*/ +/**@brief 模式退出检查 + @param curr_task:当前模式 + @return TRUE可以退出, FALSE不可以退出 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int app_task_switch_exit_check(u8 curr_task) +{ + int ret = false; + switch (curr_task) { + case APP_BT_TASK: + ret = bt_app_exit_check(); + break; + default: + ret = TRUE; + break; + + } + return ret; +} +//*----------------------------------------------------------------------------*/ +/**@brief 模式进入检查 + @param app_task:目标模式 + @return TRUE可以进入, FALSE不可以进入 + @note 例如一些需要设备在线的任务(music/record/linein等), + 如果设备在线可以进入, 没有设备在线不进入可以在这里处理 +*/ +/*----------------------------------------------------------------------------*/ +static int app_task_switch_check(u8 app_task) +{ + int ret = false; + switch (app_task) { +#if TCFG_APP_MUSIC_EN + case APP_MUSIC_TASK: + ret = music_app_check(); + break; +#endif +#if TCFG_APP_LINEIN_EN + case APP_LINEIN_TASK: + ret = linein_app_check(); + break; +#endif +#if TCFG_APP_PC_EN + case APP_PC_TASK: + ret = pc_app_check(); + break; +#endif + case APP_FM_TASK: + ret = TRUE; + break; +#if TCFG_APP_RECORD_EN + case APP_RECORD_TASK: + ret = record_app_check(); + break; +#endif + default: + ret = TRUE; + break; + + } + return ret; +} +//*----------------------------------------------------------------------------*/ +/**@brief 切换到上一个模式 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void app_task_switch_prev() +{ + int i = 0; + int cur_index = 0; + + if (app_next_task) { + printf("app_task_switch_prev busy \n"); + } + + for (cur_index = 0; cur_index < ARRAY_SIZE(app_task_list); cur_index++) { + if (app_curr_task == app_task_list[cur_index]) {//遍历当前索引 + break; + } + } + + for (i = cur_index; ;) { //遍历一圈 + if (i-- == 0) { + i = ARRAY_SIZE(app_task_list) - 1; + } + if (i == cur_index) { + return; + } + if (app_task_switch_to(app_task_list[i])) { + return; + } + } +} +//*----------------------------------------------------------------------------*/ +/**@brief 切换到下一个模式 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void app_task_switch_next() +{ + int i = 0; + int cur_index = 0; + + if (app_next_task) { + printf("app_task_switch_next busy \n"); + } + + for (cur_index = 0; cur_index < ARRAY_SIZE(app_task_list); cur_index++) { + if (app_curr_task == app_task_list[cur_index]) {//遍历当前索引 + break; + } + } + + for (i = cur_index ;;) { //遍历一圈 + if (++i >= ARRAY_SIZE(app_task_list)) { + i = 0; + } + if (i == cur_index) { + return; + } + if (app_task_switch_to(app_task_list[i])) { + return; + } + } +} +//*----------------------------------------------------------------------------*/ +/**@brief 切换到指定模式 + @param app_task:指定模式 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int app_task_switch_to(u8 app_task) +{ + if (app_curr_task == app_task) { + return false; + } + + if (!app_task_switch_check(app_task)) { + return false; + } + + if (!app_task_switch_exit_check(app_curr_task)) { + return false; + } + + printf("cur --- %x \n", app_curr_task); + printf("new +++ %x \n", app_task); + + /* if(app_next_task) */ + /* printf("app_task_switch_to busy \n"); */ +#if (defined SMART_BOX_EN) && (SMART_BOX_EN) + extern void function_change_inform(u8 app_mode, u8 ret); + function_change_inform(app_task, TRUE); +#endif + +#if (RECORDER_MIX_EN) + recorder_mix_stop(); +#endif/*RECORDER_MIX_EN*/ + + app_prev_task = app_curr_task; + app_next_task = app_task; + app_task_put_usr_msg(APP_MSG_SWITCH_TASK, 0); + + return TRUE; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 跳回到原来的模式 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int app_task_switch_back() +{ + if (app_prev_task == 0) { + return -EINVAL; + } + return app_task_switch_to(app_prev_task); +} + +//*----------------------------------------------------------------------------*/ +/**@brief 模式切换退出检测 + @param + @return 1:响应退出模式, 0:不响应 + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 app_task_exitting()// +{ + struct sys_event clear_key_event = {.type = SYS_KEY_EVENT, .arg = (void *)DEVICE_EVENT_FROM_KEY}; + if (app_next_task != 0) { + app_curr_task = app_next_task; + app_next_task = 0; + sys_key_event_disable(); + sys_event_clear(&clear_key_event); + return 1; + } + return 0; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 获取当前模式 + @param + @return 当前模式id + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 app_get_curr_task() +{ + return app_curr_task; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 通过指定id检查是否是当前模式 + @param + @return true:是当前模式,false:不是当前模式 + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 app_check_curr_task(u8 app) +{ + if (app == app_curr_task) { + return true; + } + return false; +} + + diff --git a/apps/soundbox/task_manager/bt/bt.c b/apps/soundbox/task_manager/bt/bt.c new file mode 100644 index 0000000..1afa85e --- /dev/null +++ b/apps/soundbox/task_manager/bt/bt.c @@ -0,0 +1,1488 @@ + +/************************************************************* + 此文件函数主要是蓝牙模式各种状态处理 + + void app_bt_task() + bt模式主函数 + + static int bt_sys_event_handler(struct sys_event *event) + bt模式系统事件所有处理入口 + + static void bt_task_close(void) + bt模式退出 + + + void bt_function_select_init() + 蓝牙功能配置 + + void bredr_handle_register() + 蓝牙协议栈回调函数 + + static int bt_connction_status_event_handler(struct bt_event *bt) + 蓝牙状态事件处理函数 + + static int bt_hci_event_handler(struct bt_event *bt) + 蓝牙协议栈事件回调,app处理函数 + + static int bt_ai_event_handler(struct bt_event *bt) + 蓝牙ai事件处理函数 + + int bt_background_event_handler_filter(struct sys_event *event) + 蓝牙后台事件过滤处理 + int bt_background_event_handler(struct sys_event *event) + 蓝牙后台事件处理函数 + + int bt_key_event_handler(struct sys_event *event) + 蓝牙按键处理函数 + + avctp_user.h 有蓝牙支持的命令介绍 + +**************************************************************/ + + + +#include "system/includes.h" +#include "media/includes.h" + +#include "app_config.h" +#include "app_task.h" + +#include "btstack/avctp_user.h" +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "btstack/btstack_error.h" +#include "btctrler/btctrler_task.h" +#include "classic/hci_lmp.h" + +#include "bt/bt_tws.h" +#include "bt/bt_ble.h" +#include "bt/bt.h" +#include "bt/vol_sync.h" +#include "bt/bt_emitter.h" +#include "bt_common.h" +#include "aec_user.h" + +#include "math.h" +#include "spp_user.h" + + +#include "app_protocol_common.h" + +#include "app_chargestore.h" +#include "app_charge.h" +#include "app_main.h" +#include "app_power_manage.h" +#include "user_cfg.h" + +#include "asm/pwm_led.h" +#include "asm/timer.h" +#include "asm/hwi.h" +#include "cpu.h" + +#include "ui/ui_api.h" +#include "ui_manage.h" +#include "ui/ui_style.h" + +#include "key_event_deal.h" +#include "clock_cfg.h" +#include "gSensor/gSensor_manage.h" +#include "soundcard/soundcard.h" + +#include "audio_dec.h" +#include "tone_player.h" +#include "dac.h" +#include "soundbox.h" +#include "le_client_demo.h" +#include "tuya_multi/tuya_le_multi_common.h" +#include "multi_demo/le_multi_common.h" + + +#define LOG_TAG_CONST BT +#define LOG_TAG "[BT]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +#define LOG_DUMP_ENABLE +#define LOG_CLI_ENABLE +#include "debug.h" + + +#if TCFG_APP_BT_EN + +struct app_bt_opr app_bt_hdl = { + .exit_flag = 1, + .replay_tone_flag = 1, + .esco_dump_packet = ESCO_DUMP_PACKET_CALL, + .hid_mode = 0, + .wait_exit = 0, +}; + +#define __this (&app_bt_hdl) + +BT_USER_PRIV_VAR bt_user_priv_var; + +static u8 event_conn_complete = 0; + +void user_avrcp_status_callback(u8 *addr,u8 flag) +{ + //flag = 0 是暂停,1是播放 + put_buf(addr,6); + +} + +#if BT_EMITTER_TEST_ENABLE +u8 ag_at_cmd_all_by_user(u8 *packet, u16 size)//奇祥在用 +{ + /* ATCMD_CMD_CHUP: 挂断 14 */ + /* ATCMD_CMD_BLDN: 回拨 7 */ + /* ATCMD_CMD_ATD: 来电 2 */ + #if (!NORM_VERSION) + u8 rsp_buf[64] = {0}; + int rsp_len = 0; + put_buf(packet, size); + g_printf("[%d]>>>>>>>>>>>>>>>>>>>>---atcmd start------%s -- %d\n", size, packet, get_call_status()); + if (0 == strncmp("AT+BLDN", packet, 7)) + { + // g_printf(">>>>>>>>>>>>>>>>>+++++++%s\n", packet); + // at_serv_opr_t * at_opr = at_server_get_opr(); + // at_opr->rsp_hfreq_state(1); + // at_opr->rsp_hfp_incoming_state(1); + rsp_len = sprintf(rsp_buf, "\r\nOK\r\n"); + u8 ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); + log_i("[%s]: %d\n", __FUNCTION__, ret); + return 1; + }else if (0 == strncmp("AT+CHUP", packet, 7)) + { + // g_printf(">>>>>>>>>>>>>>>>>-------%s\n", packet); + // at_serv_opr_t * at_opr = at_server_get_opr(); + // at_opr->rsp_hfreq_state(0); + // at_opr->rsp_hfp_incoming_state(0); + rsp_len = sprintf(rsp_buf, "\r\nOK\r\n"); + u8 ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); + log_i("[%s]: %d\n", __FUNCTION__, ret); + return 1; + }else if (0 == strncmp("AT+ATD", packet, 6)) + { + // g_printf(">>>>>>>>>>>>>>>>>88888888%s\n", packet); + rsp_len = sprintf(rsp_buf, "\r\nOK\r\n"); + u8 ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); + log_i("[%s]: %d\n", __FUNCTION__, ret); + return 1; + } + else if (0 == strncmp("AT+CLCC", packet, 7)) + { + // g_printf(">>>>>>>>>>>>>>>>>555555%s\n", packet); + if (get_call_status() == BT_CALL_ACTIVE) + { + rsp_len = sprintf(rsp_buf, "\r\n+CLCC: 1,0,0,0,0,\" \",129\r\n"); + u8 ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); + log_i("[%s]: %d\n", __FUNCTION__, ret); + memset(rsp_buf, 0, sizeof(rsp_buf)); + rsp_len = sprintf(rsp_buf, "\r\nOK\r\n"); + ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); + log_i("[%s]: %d\n", __FUNCTION__, ret); + }else + { + rsp_len = sprintf(rsp_buf, "\r\nOK\r\n"); + u8 ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); + log_i("[%s]: %d\n", __FUNCTION__, ret); + } + return 1; + } + // else if(0 == strncmp("AT+BRSF=", packet, 8)) + // { + // line_inf + // printf("[%s]: %s\n"); + // rsp_len = sprintf(rsp_buf, "\r\n+BRSF: 2052\r\n"); + // int ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); + // log_i("[%s]: %d\n", rsp_buf, ret); + // memset(rsp_buf, 0, sizeof(rsp_buf)); + // rsp_len = sprintf(rsp_buf, "\r\nOK\r\n"); + // ret = user_send_at_cmd_prepare(rsp_buf, rsp_len); + // log_i("[%s]: %d\n", rsp_buf, ret); + // return 1; + // } + return 0; + + // const at_serv_opr_t * at_opr = at_server_get_opr(); + // for (size_t i = 0; i < size + 1; i++) + // { + // if (i == size) + // { + // at_opr->parse_cmd_hendle('\n', user_send_at_cmd_prepare); + // }else + // { + // at_opr->parse_cmd_hendle(packet[i], user_send_at_cmd_prepare); + // } + // } + // g_printf(">>>>>>>>>>>>>>>>>>>>>---atcmd end-----[%d]\n", at_opr->get_ignore_flag()); + + // return at_opr->get_ignore_flag(); + #else + g_printf("---atcmd-----[%d]\n", parse_atcmd_type); + + switch (parse_atcmd_type) + { + case 2:/* ATCMD_CMD_ATD: 来电 2 */ + { + // at_serv_opr_t * at_opr = at_server_get_opr(); + // at_opr->rsp_hfreq_state(0); + return 1; + } + break; + case 7:/* ATCMD_CMD_BLDN: 回拨 7 */ + { + at_serv_opr_t * at_opr = at_server_get_opr(); + at_opr->rsp_hfreq_state(1); + at_opr->rsp_hfp_incoming_state(1); + return 1; + } + break; + case 14:/* ATCMD_CMD_CHUP: 挂断 14 */ + { + at_serv_opr_t * at_opr = at_server_get_opr(); + at_opr->rsp_hfreq_state(0); + at_opr->rsp_hfp_incoming_state(0); + return 1; + } + break; + default: + break; + } + log_i("---------------no process cmd\n"); + return 0; + #endif +} + +#else +u8 ag_at_cmd_all_by_user(u8 *packet, u16 size) +{ + line_inf + put_buf(packet,size); + return 0; +} +#endif +u8 user_diy_atcmd_handle(u8 parse_atcmd_type) +{ + #if BT_EMITTER_TEST_ENABLE + /* ATCMD_CMD_CHUP: 挂断 14 */ + /* ATCMD_CMD_BLDN: 回拨 7 */ + /* ATCMD_CMD_ATD: 来电 2 */ + g_printf("---atcmd------%d\n", parse_atcmd_type); + + switch (parse_atcmd_type) + { + case 2:/* ATCMD_CMD_ATD: 来电 2 */ + { + return 1; + } + break; + case 7:/* ATCMD_CMD_BLDN: 回拨 7 */ + { + + return 1; + } + break; + case 14:/* ATCMD_CMD_CHUP: 挂断 14 */ + { + return 1; + } + break; + default: + break; + } + #endif + return 0; +} + +//接收数据 +int at_cmd_analysis_by_user(u8 *packet,u16 size) +{ + puts(packet); + printf("size == %d\n",size); + return 0; +} + + +void bt_event_status_start_connected(struct bt_event *bt) +{ + if(bt_user_priv_var.auto_connection_timer) { + sys_timeout_del(bt_user_priv_var.auto_connection_timer); + bt_user_priv_var.auto_connection_timer = 0; + } + bt_user_priv_var.auto_connection_counter = 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式变量初始化 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_var_init() +{ + memset((u8 *)&bt_user_priv_var, 0, sizeof(BT_USER_PRIV_VAR)); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式协议栈回调函数 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void bredr_handle_register() +{ +#if (USER_SUPPORT_PROFILE_SPP==1) +#if APP_ONLINE_DEBUG + extern void online_spp_init(void); + spp_data_deal_handle_register(user_spp_data_handler); + online_spp_init(); +#else + spp_data_deal_handle_register(spp_data_handler); +#endif +#endif + +#if BT_SUPPORT_MUSIC_VOL_SYNC + ///蓝牙音乐和通话音量同步 + music_vol_change_handle_register(bt_set_music_device_volume, phone_get_device_vol); +#endif + +#if BT_SUPPORT_DISPLAY_BAT + ///电量显示获取电量的接口 + get_battery_value_register(bt_get_battery_value); +#endif + + ///被测试盒链接上进入快速测试回调 + bt_fast_test_handle_register(bt_fast_test_api); + + ///样机进入dut被测试仪器链接上回调 + bt_dut_test_handle_register(bt_dut_api); + + ///获取远端设备蓝牙名字回调 + read_remote_name_handle_register(bt_read_remote_name); + + ////获取歌曲信息回调 + /* bt_music_info_handle_register(user_get_bt_music_info); */ + + BT_BREDR_HANDLE_REG(); +} + + +#if (TRANS_MULTI_BLE_EN || TUYA_MULTI_BLE_EN) && TRANS_MULTI_BLE_MASTER_NUMS +//指定搜索uuid +//指定搜索uuid +static const target_uuid_t jl_search_uuid_table[] = { + + // for uuid16 + // PRIMARY_SERVICE, ae30 + // CHARACTERISTIC, ae01, WRITE_WITHOUT_RESPONSE | DYNAMIC, + // CHARACTERISTIC, ae02, NOTIFY, + + { + .services_uuid16 = 0xae30, + .characteristic_uuid16 = 0xae01, + .opt_type = ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, + }, + + { + .services_uuid16 = 0xae30, + .characteristic_uuid16 = 0xae02, + .opt_type = ATT_PROPERTY_NOTIFY, + }, + + //for uuid128,sample + // PRIMARY_SERVICE, 0000F530-1212-EFDE-1523-785FEABCD123 + // CHARACTERISTIC, 0000F531-1212-EFDE-1523-785FEABCD123, NOTIFY, + // CHARACTERISTIC, 0000F532-1212-EFDE-1523-785FEABCD123, WRITE_WITHOUT_RESPONSE | DYNAMIC, + /* + { + .services_uuid16 = 0, + .services_uuid128 = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23} , + .characteristic_uuid16 = 0, + .characteristic_uuid128 = {0x00,0x00,0xF5,0x31 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}, + .opt_type = ATT_PROPERTY_NOTIFY, + }, + + { + .services_uuid16 = 0, + .services_uuid128 = {0x00,0x00,0xF5,0x30 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23} , + .characteristic_uuid16 = 0, + .characteristic_uuid128 = {0x00,0x00,0xF5,0x32 ,0x12,0x12 ,0xEF, 0xDE ,0x15,0x23 ,0x78,0x5F,0xEA ,0xBC,0xD1,0x23}, + .opt_type = ATT_PROPERTY_WRITE_WITHOUT_RESPONSE, + }, + */ + +}; + + +static void ble_report_data_deal(att_data_report_t *report_data, target_uuid_t *search_uuid) +{ + log_info("conn_handle:%04x,report_data:%02x,%02x,%d,len(%d)", report_data->conn_handle, report_data->packet_type, + report_data->value_handle, report_data->value_offset, report_data->blob_length); + + log_info_hexdump(report_data->blob, report_data->blob_length); + + /* if (search_uuid == NULL) { */ + /* log_info("not_match handle"); */ + /* return; */ + /* } */ + + switch (report_data->packet_type) { + case GATT_EVENT_NOTIFICATION: //notify + break; + + case GATT_EVENT_INDICATION://indicate + case GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT://read + break; + + case GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT://read long + break; + + default: + break; + } +} + +static struct ble_client_operation_t *ble_client_api; +static const u8 test_remoter_name1[] = "AC897N_MX(BLE)";// +/* static const u8 test_remoter_name2[] = "AC630N_HID567(BLE)";// */ +static u16 ble_client_write_handle; +static u16 ble_client_timer = 0; + +static const client_match_cfg_t match_dev01 = { + .create_conn_mode = BIT(CLI_CREAT_BY_NAME), + .compare_data_len = sizeof(test_remoter_name1) - 1, //去结束符 + .compare_data = test_remoter_name1, + .bonding_flag = 0, +}; + +/* static const client_match_cfg_t match_dev02 = { */ +/* .create_conn_mode = BIT(CLI_CREAT_BY_NAME), */ +/* .compare_data_len = sizeof(test_remoter_name2) - 1, //去结束符 */ +/* .compare_data = test_remoter_name2, */ +/* .bonding_flag = 1, */ +/* }; */ + +static void client_test_write(void) +{ + static u32 count = 0; + int i, ret = 0; + u16 tmp_handle; + + count++; + for (i = 0; i < TRANS_MULTI_BLE_MASTER_NUMS; i++) { + tmp_handle = mul_dev_get_conn_handle(i, MULTI_ROLE_CLIENT); + + if (tmp_handle && ble_client_write_handle) { + ret = ble_client_api->opt_comm_send_ext(tmp_handle, ble_client_write_handle, &count, 16, ATT_OP_WRITE_WITHOUT_RESPOND); + log_info("test_write:%04x,%d", tmp_handle, ret); + } + } + + /* int ret = ble_client_api->opt_comm_send(ble_client_write_handle, &count, 16, ATT_OP_WRITE_WITHOUT_RESPOND); */ + /* log_info("test_write:%x", ret); */ +} + + +static void client_event_callback(le_client_event_e event, u8 *packet, int size) +{ + switch (event) { + case CLI_EVENT_MATCH_DEV: { + client_match_cfg_t *match_dev = packet; + log_info("match_name:%s\n", match_dev->compare_data); + } + break; + + case CLI_EVENT_MATCH_UUID: { + opt_handle_t *opt_hdl = packet; + if (opt_hdl->search_uuid == &jl_search_uuid_table[0]) { + ble_client_write_handle = opt_hdl->value_handle; + log_info("match_uuid22\n"); + } + } + break; + + case CLI_EVENT_SEARCH_PROFILE_COMPLETE: + log_info("CLI_EVENT_SEARCH_PROFILE_COMPLETE\n"); + if ((!ble_client_timer) && ble_client_write_handle) { + log_info("test timer_add\n"); + ble_client_timer = sys_timer_add(0, client_test_write, 500); + } + break; + + case CLI_EVENT_CONNECTED: + break; + + case CLI_EVENT_DISCONNECT: + if (ble_client_timer && TRANS_MULTI_BLE_MASTER_NUMS == 1) { + sys_timeout_del(ble_client_timer); + ble_client_write_handle = 0; + ble_client_timer = 0; + } + break; + + default: + break; + } +} + + +static const client_conn_cfg_t client_conn_config = { + .match_dev_cfg[0] = &match_dev01, + .match_dev_cfg[1] = NULL, + .match_dev_cfg[2] = NULL, + /* .match_dev_cfg[1] = &match_dev02, */ + .report_data_callback = ble_report_data_deal, + /* .search_uuid_cnt = 0, //配置不搜索profile,加快回连速度 */ + .search_uuid_cnt = (sizeof(jl_search_uuid_table) / sizeof(target_uuid_t)), + .search_uuid_table = jl_search_uuid_table, + .security_en = 0, //支持加密使能,对应配置 config_le_sm_support_enable + .event_callback = client_event_callback, +}; + +static void ble_client_config_init(void) +{ + ble_client_api = ble_get_client_operation_table(); + ble_client_api->init_config(0, &client_conn_config); + /* client_clear_bonding_info();//for test */ +} + +#endif + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式协议栈功能配置 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +// int set_remove_esco_req_not_accepted_flag = 0; +void bt_function_select_init() +{ + // void __set_hfp_ag_res_hangup_flag(bool flag); + // __set_hfp_ag_res_hangup_flag(0); + set_idle_period_slot(1600); + ////设置协议栈支持设备数 + __set_user_ctrl_conn_num(TCFG_BD_NUM); + ////msbc功能使能 + __set_support_msbc_flag(1); + set_bt_version(0x09);//修改蓝牙版本 + + __set_sbc_cap_bitpool(30); + +#if TCFG_BT_SUPPORT_AAC + ////AAC功能使能 + __set_support_aac_flag(1); +#else + __set_support_aac_flag(0); +#endif + +#if BT_SUPPORT_DISPLAY_BAT + ////设置更新电池电量的时间间隔 + __bt_set_update_battery_time(60); +#else + __bt_set_update_battery_time(0); +#endif + + ////回连搜索时间长度设置,可使用该函数注册使用,ms单位,u16 + __set_page_timeout_value(8000); + + ////回连时超时参数设置。ms单位。做主机有效 + __set_super_timeout_value(8000); + +#if (TCFG_BD_NUM == 2) + ////设置开机回链的设备个数 + __set_auto_conn_device_num(2); +#endif + +#if (TCFG_SPI_LCD_ENABLE) +#if TCFG_USER_EMITTER_ENABLE//带有屏幕的方案根据UI选项连接 + ////设置开机回链的设备个数 + __set_auto_conn_device_num(10);//彩屏方案支持10个设备的连接 +#endif +#endif + +#if BT_SUPPORT_MUSIC_VOL_SYNC + ////设置音乐音量同步的表 + vol_sys_tab_init(); +#endif + + ////设置蓝牙是否跑后台 + __set_user_background_goback(BACKGROUND_GOBACK); // 后台链接是否跳回蓝牙 1:跳回 + + ////设置蓝牙加密的level + //io_capabilities ; /*0: Display only 1: Display YesNo 2: KeyboardOnly 3: NoInputNoOutput*/ + //authentication_requirements: 0:not protect 1 :protect + + __set_simple_pair_param(3, 0, 2);//__set_simple_pair_param(3, 0, 2); + +#if (USER_SUPPORT_PROFILE_PBAP==1) + ////设置蓝牙设备类型 + __change_hci_class_type(BD_CLASS_CAR_AUDIO); +#endif + __change_hci_class_type(BD_CLASS_SMART_PHONE_2); + +#if (TCFG_BT_SNIFF_ENABLE == 0) + void lmp_set_sniff_disable(void); + lmp_set_sniff_disable(); +#endif + + + /* + TX RX + AI800x PA13 PA12 + AC692x PA13 PA12 + AC693x PA8 PA9 + AC695x PA9 PA10 + AC696x PA9 PA10 + AC694x PB1 PB2 + AC697x PC2 PC3 + AC631x PA7 PA8 + + */ + ////设置蓝牙接收状态io输出,可以外接pa + /* bt_set_rxtx_status_enable(1); */ + +#if TCFG_USER_BLE_ENABLE + { + u8 tmp_ble_addr[6]; +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV \ + || TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_GMA) + /* bt_set_tx_power(9);//ble txpwer level:0~9 */ + memcpy(tmp_ble_addr, (void *)bt_get_mac_addr(), 6); +#else + lib_make_ble_address(tmp_ble_addr, (void *)bt_get_mac_addr()); +#endif // + le_controller_set_mac((void *)tmp_ble_addr); + printf("\n-----edr + ble 's address-----"); + printf_buf((void *)bt_get_mac_addr(), 6); + printf_buf((void *)tmp_ble_addr, 6); + } + +#if (TRANS_MULTI_BLE_EN || TUYA_MULTI_BLE_EN) && TRANS_MULTI_BLE_MASTER_NUMS + ble_client_config_init(); +#endif + + +#endif // TCFG_USER_BLE_ENABLE + +#if (CONFIG_BT_MODE != BT_NORMAL) + set_bt_enhanced_power_control(1); +#endif +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式协议栈对应状态处理函数 + @param bt:事件 + @return + @note 蓝牙初始化完成、链接、通话播歌等状态 +*/ +/*----------------------------------------------------------------------------*/ +static int bt_connction_status_event_handler(struct bt_event *bt) +{ + + log_debug("-----------------------bt_connction_status_event_handler %d", bt->event); + + if (bt_status_event_filter(bt) == false) { + return false; + } + + switch (bt->event) { + + case BT_STATUS_EXIT_OK: + log_info("BT_STATUS_EXIT_OK\n"); + break; + case BT_STATUS_INIT_OK: + log_info("BT_STATUS_INIT_OK\n"); + bt_status_init_ok(bt); +#if(TCFG_TEST_BOX_ENABLE || TCFG_CHARGESTORE_ENABLE) + chargestore_set_bt_init_ok(1); +#endif + break; + case BT_STATUS_START_CONNECTED: + log_info(" BT_STATUS_START_CONNECTED\n"); +#if CONFIG_TWS_DISCONN_NO_RECONN + extern u8 tws_detach_by_remove_key; + tws_detach_by_remove_key = 0; +#endif + if(bt_emitter_role_get() == BT_EMITTER_EN) { + bt_event_status_start_connected(bt); + } + break; + case BT_STATUS_ENCRY_COMPLETE: + log_info(" BT_STATUS_ENCRY_COMPLETE\n"); +#ifdef CONFIG_DEBUG_ENABLE + extern u8 *get_last_device_connect_linkkey(u16 *len); + u8 *test_linkkey; + u16 test_linkkey_len = 16; + test_linkkey = get_last_device_connect_linkkey(&test_linkkey_len); + if(test_linkkey){ + printf("test_linkkey================\n"); + put_buf(test_linkkey, test_linkkey_len); + } +#endif + break; + case BT_STATUS_SECOND_CONNECTED: + log_info(" BT_STATUS_SECOND_CONNECTED\n"); + clear_current_poweron_memory_search_index(0); + case BT_STATUS_FIRST_CONNECTED: + log_info("BT_STATUS_CONNECTED\n"); + bt_status_connect(bt); + break; + case BT_STATUS_FIRST_DISCONNECT: + case BT_STATUS_SECOND_DISCONNECT: + log_info(" BT_STATUS_SECOND_DISCONNECT\n"); + bt_status_disconnect(bt); + break; + case BT_STATUS_PHONE_INCOME: + log_info("BT_STATUS_PHONE_INCOME\n"); + bt_status_phone_income(bt); + break; + case BT_STATUS_PHONE_OUT: + log_info("BT_STATUS_PHONE_OUT\n"); + bt_status_phone_out(bt); + break; + case BT_STATUS_PHONE_ACTIVE: + log_info("BT_STATUS_PHONE_ACTIVE\n"); + bt_status_phone_active(bt); + break; + case BT_STATUS_PHONE_HANGUP: + log_info(" BT_STATUS_PHONE_HANGUP\n"); + bt_status_phone_hangup(bt); + break; + case BT_STATUS_PHONE_NUMBER: + log_info("BT_STATUS_PHONE_NUMBER\n"); + bt_status_phone_number(bt); + break; + case BT_STATUS_INBAND_RINGTONE: + log_info("BT_STATUS_INBAND_RINGTONE\n"); + bt_status_inband_ringtone(bt); + break; + case BT_STATUS_BEGIN_AUTO_CON: + log_info("BT_STATUS_BEGIN_AUTO_CON\n"); + break; + case BT_STATUS_A2DP_MEDIA_START: + log_info(" BT_STATUS_A2DP_MEDIA_START\n"); + bt_status_a2dp_media_start(bt); + break; + case BT_STATUS_A2DP_MEDIA_STOP: + log_info(" BT_STATUS_A2DP_MEDIA_STOP"); + bt_status_a2dp_media_stop(bt); + break; + case BT_STATUS_SCO_STATUS_CHANGE: + log_info(" BT_STATUS_SCO_STATUS_CHANGE"); + bt_status_sco_change(bt); + break; + case BT_STATUS_CALL_VOL_CHANGE: + log_info(" BT_STATUS_CALL_VOL_CHANGE "); + bt_status_call_vol_change(bt); + break; + case BT_STATUS_SNIFF_STATE_UPDATE: + log_info(" BT_STATUS_SNIFF_STATE_UPDATE \n"); //0退出SNIFF + bt_status_sniff_state_update(bt); + break; + case BT_STATUS_LAST_CALL_TYPE_CHANGE: + log_info("BT_STATUS_LAST_CALL_TYPE_CHANGE\n"); + bt_status_last_call_type_change(bt); + break; + case BT_STATUS_CONN_A2DP_CH: + bt_status_conn_a2dp_ch(bt); + /* break; */ + case BT_STATUS_CONN_HFP_CH: + bt_status_conn_hfp_ch(bt); + break; + case BT_STATUS_PHONE_MANUFACTURER: + log_info("BT_STATUS_PHONE_MANUFACTURER\n"); + bt_status_phone_menufactuer(bt); + break; + case BT_STATUS_VOICE_RECOGNITION: + log_info(" BT_STATUS_VOICE_RECOGNITION \n"); + bt_status_voice_recognition(bt); + break; + case BT_STATUS_AVRCP_INCOME_OPID: + log_info(" BT_STATUS_AVRCP_INCOME_OPID \n"); + bt_status_avrcp_income_opid(bt); + break; + case BT_STATUS_RECONN_OR_CONN: + log_info(" BT_STATUS_RECONN_OR_CONN \n"); + break; + default: + log_info(" BT STATUS DEFAULT\n"); + break; + } + return 0; +} + + + + + + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式协议栈事件 + @param bt:事件 + @return + @note 蓝牙底层事件,通过app层处理 +*/ +/*----------------------------------------------------------------------------*/ +static int bt_hci_event_handler(struct bt_event *bt) +{ + //对应原来的蓝牙连接上断开处理函数 ,bt->value=reason + log_debug("------------------------bt_hci_event_handler reason %x %x", bt->event, bt->value); + + if (bt_hci_event_filter(bt) == 0) { + return 0; + } + + switch (bt->event) { + case HCI_EVENT_INQUIRY_COMPLETE: + log_info(" HCI_EVENT_INQUIRY_COMPLETE \n"); + bt_hci_event_inquiry(bt); + break; + case HCI_EVENT_IO_CAPABILITY_REQUEST: + log_info(" HCI_EVENT_IO_CAPABILITY_REQUEST \n"); + clock_add_set(BT_CONN_CLK); + break; + case HCI_EVENT_USER_CONFIRMATION_REQUEST: + log_info(" HCI_EVENT_USER_CONFIRMATION_REQUEST %d \n", bt->value); + ///<可通过按键来确认是否配对 1:配对 0:取消 + bt_send_pair(1); + clock_remove_set(BT_CONN_CLK); + break; + case HCI_EVENT_USER_PASSKEY_REQUEST: + log_info(" HCI_EVENT_USER_PASSKEY_REQUEST \n"); + ///<可以开始输入6位passkey + break; + case HCI_EVENT_USER_PRESSKEY_NOTIFICATION: + log_info(" HCI_EVENT_USER_PRESSKEY_NOTIFICATION %x\n", bt->value); + ///<可用于显示输入passkey位置 value 0:start 1:enrer 2:earse 3:clear 4:complete + break; + case HCI_EVENT_PIN_CODE_REQUEST : + log_info("HCI_EVENT_PIN_CODE_REQUEST \n"); + bt_send_pair(1); + break; + case HCI_EVENT_VENDOR_NO_RECONN_ADDR : + log_info("HCI_EVENT_VENDOR_NO_RECONN_ADDR \n"); + bt_hci_event_disconnect(bt) ; + break; + case HCI_EVENT_DISCONNECTION_COMPLETE : + log_info("HCI_EVENT_DISCONNECTION_COMPLETE \n"); + bt_hci_event_disconnect(bt) ; + clock_remove_set(BT_CONN_CLK); + break; + case BTSTACK_EVENT_HCI_CONNECTIONS_DELETE: + case HCI_EVENT_CONNECTION_COMPLETE: + log_info(" HCI_EVENT_CONNECTION_COMPLETE \n"); + switch (bt->value) { + case ERROR_CODE_SUCCESS : + log_info("ERROR_CODE_SUCCESS \n"); + bt_hci_event_connection(bt); + break; + case ERROR_CODE_PIN_OR_KEY_MISSING: + log_info(" ERROR_CODE_PIN_OR_KEY_MISSING \n"); + bt_hci_event_linkkey_missing(bt); + case ERROR_CODE_SYNCHRONOUS_CONNECTION_LIMIT_TO_A_DEVICE_EXCEEDED : + case ERROR_CODE_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES: + case ERROR_CODE_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR: + case ERROR_CODE_CONNECTION_ACCEPT_TIMEOUT_EXCEEDED : + case ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION : + case ERROR_CODE_CONNECTION_TERMINATED_BY_LOCAL_HOST : + case ERROR_CODE_AUTHENTICATION_FAILURE : + case CUSTOM_BB_AUTO_CANCEL_PAGE: + bt_hci_event_disconnect(bt) ; + break; + case ERROR_CODE_PAGE_TIMEOUT: + log_info(" ERROR_CODE_PAGE_TIMEOUT \n"); + bt_hci_event_page_timeout(bt); + break; + case ERROR_CODE_CONNECTION_TIMEOUT: + log_info(" ERROR_CODE_CONNECTION_TIMEOUT \n"); + bt_hci_event_connection_timeout(bt); + break; + case ERROR_CODE_ACL_CONNECTION_ALREADY_EXISTS : + log_info("ERROR_CODE_ACL_CONNECTION_ALREADY_EXISTS \n"); + bt_hci_event_connection_exist(bt); + break; + default: + break; + } + break; + default: + break; + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙后台事件过滤处理 + @param event: 事件 + @return 0:不需要切换模式, 1:需要切换模式,2:通话导致需要切换 + @note +*/ +/*----------------------------------------------------------------------------*/ +int bt_background_event_handler_filter(struct sys_event *event) +{ + u8 ret = 0; +#if TCFG_BLUETOOTH_BACK_MODE + if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) { + log_info("bt con event: %d \n", event->u.bt.event); + switch (event->u.bt.event) { + // 需要切换蓝牙的命令 + case BT_STATUS_A2DP_MEDIA_START: + if (__this->sbc_packet_step != 0) { + /* log_info("sbc_packet_step : %d \n", __this->sbc_packet_step); */ + break; + } + + case BT_STATUS_FIRST_DISCONNECT: + case BT_STATUS_SECOND_DISCONNECT: + //关机导致的断开不可以回去蓝牙,否则后台关机会有问题 + if (app_var.goto_poweroff_flag) { + break; + } +#if BACKGROUND_GOBACK +#if USER_SUPPORT_DUAL_A2DP_SOURCE + /* ret = 1; */ +#else + ret = 1; +#endif + +#else + //判断断开的是sink设备,默认切换蓝牙 + if (event->u.bt.value) { + ret = 1; + } + if (ret == 0) { + bt_status_disconnect_background(&event->u.bt); + } +#endif + break; + + case BT_STATUS_SECOND_CONNECTED: + case BT_STATUS_FIRST_CONNECTED: +#if BACKGROUND_GOBACK +#if USER_SUPPORT_DUAL_A2DP_SOURCE + /* ret = 1; */ +#else + ret = 1; +#endif +#else + bt_status_connect_background(&event->u.bt); +#endif + break; + + case BT_STATUS_START_CONNECTED: +#if BACKGROUND_GOBACK +#if USER_SUPPORT_DUAL_A2DP_SOURCE + /* ret = 1; */ +#else + ret = 1; +#endif +#endif + if(bt_emitter_role_get() == BT_EMITTER_EN) { + bt_event_status_start_connected(&event->u.bt); + } + break; + + case BT_STATUS_ENCRY_COMPLETE: + break; + case BT_STATUS_SCO_STATUS_CHANGE: + ret = 1; + break; + case BT_STATUS_LAST_CALL_TYPE_CHANGE: + bt_status_last_call_type_change(&event->u.bt); + case BT_STATUS_VOICE_RECOGNITION: + case BT_STATUS_PHONE_INCOME: + case BT_STATUS_PHONE_NUMBER: + /* case BT_STATUS_PHONE_MANUFACTURER: */ + case BT_STATUS_PHONE_OUT: + case BT_STATUS_PHONE_ACTIVE: + /* case BT_STATUS_PHONE_HANGUP: */ + ret = 2; + break; + // 不需要处理的命令 + case BT_STATUS_INIT_OK: + bt_status_init_ok_background(&event->u.bt); + break; + case BT_STATUS_A2DP_MEDIA_STOP: + bt_drop_a2dp_frame_stop(); + case BT_STATUS_CALL_VOL_CHANGE: + break; + // 按原方式处理的命令 + default: + bt_connction_status_event_handler(&event->u.bt); + break; + } + } else if ((u32)event->arg == SYS_BT_EVENT_TYPE_HCI_STATUS) { + /* log_info("bt hci event: %d \n", event->u.bt.event); */ + switch (event->u.bt.event) { + case HCI_EVENT_IO_CAPABILITY_REQUEST: + clock_add_set(BT_CONN_CLK); +#if BACKGROUND_GOBACK +#if USER_SUPPORT_DUAL_A2DP_SOURCE + /* ret = 1; */ +#else + ret = 1; +#endif +#endif + break; + default: + bt_hci_event_handler(&event->u.bt); + break; + } + } +#if TCFG_USER_TWS_ENABLE + else if (((u32)event->arg == SYS_BT_EVENT_FROM_TWS)) { + /* log_info("bt tws event: %d \n", event->u.bt.event); */ + switch (event->u.bt.event) { + /* case TWS_EVENT_CONNECTED: */ + /* ret = 1; */ + /* break; */ + default: + bt_tws_connction_status_event_handler(&event->u.bt); +#if (TCFG_DEC2TWS_ENABLE) + localtws_bt_event_deal(&event->u.bt); +#endif + break; + } + } +#endif + else if ((u32)event->arg == SYS_EVENT_FROM_CTRLER) { + switch (event->u.bt.event) { + case BTCTRLER_EVENT_RESUME_REQ: + /*log_info("------- BTCTRLER_EVENT_RESUME_REQ \n"); */ + ret = 2; + break; + } + } +#endif + return ret; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙后台事件处理 + @param event: 事件 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +int bt_background_event_handler(struct sys_event *event) +{ + int ret = bt_background_event_handler_filter(event); + if (ret) { + if (false == app_check_curr_task(APP_BT_TASK)) { + __this->cmd_flag = 1; + if (ret == 2) { + __this->call_flag = 1; + } else { + __this->call_flag = 0; + } + app_task_switch_to(APP_BT_TASK); + sys_event_notify(event); + } + } + return 0; +} + + +//#if (USER_SUPPORT_PROFILE_HID==1) +////重写bt_get_hid_name +//const char * bt_get_hid_name() +//{ +// return "HID_USER"; +//} +//#endif + +extern int multi_spp_send_data(u8 local_cid, u8 rfcomm_cid, u8 *buf, u16 len); + int mutil_handle_data_deal(u8 local_id, u8 packet_type, u16 channel, u8 *packet, u16 size) + //该函数在底层是weak函数 + { + printf("local_id %d\n",local_id); + switch (packet_type) + { + case 1: + printf("connect\n"); + break; + case 2: + printf("disconnect\n"); + break; + case 7: + put_buf(packet, size); + multi_spp_send_data(local_id,0,packet,size); + break; + default: + break; + } + } +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式按键响应处理 + @param event: 按键 + @return 1:事件处理 0:事件无处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +int bt_key_event_handler(struct sys_event *event) +{ + int ret = true; + struct key_event *key = &event->u.key; + + if (bt_key_event_filter_before() == false) { + return false; + } + + int key_event = event->u.key.event; + int key_value = event->u.key.value; + + + log_debug("bt key_event:%d %d %d %d\n", key_event, key->value, key->event, key->init); + + if (bt_key_event_filter_after(key_event) == true) { + return true; + } + + switch (key_event) { + case KEY_HCI_DISCONNECT_CLEAR_VM: + printf("KEY_HCI_DISCONNECT_CLEAR_VM\n"); + user_send_cmd_prepare(USER_CTRL_DISCONNECTION_HCI,0,NULL); + user_send_cmd_prepare(USER_CTRL_DEL_ALL_REMOTE_INFO, 0, NULL);//清除配对信息 + break; + case KEY_TEST_1: + printf("KEY_TEST_1"); + user_emitter_cmd_prepare(USER_CTRL_HFP_CALL_LAST_NO, 0, NULL); + break; + case KEY_TEST_2: + printf("KEY_TEST_2"); + // user_emitter_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); + user_send_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); + break; + case KEY_TEST_3: + printf("KEY_TEST_3"); + user_emitter_cmd_prepare(USER_CTRL_HFP_CALL_ANSWER, 0, NULL); + break; + case KEY_TEST_4: + printf("KEY_TEST_4"); + bt_search_device(); + break; + case KEY_MUSIC_PP: + log_info(" KEY_MUSIC_PP \n"); + bt_key_music_pp(); + break; + case KEY_MUSIC_PREV: + log_info(" KEY_MUSIC_PREV \n"); + bt_key_music_prev(); + break; + case KEY_MUSIC_NEXT: + log_info(" KEY_MUSIC_NEXT \n"); + bt_key_music_next(); + break; + case KEY_VOL_UP: + log_info(" KEY_VOL_UP \n"); + bt_key_vol_up(); + break; + case KEY_VOL_DOWN: + log_info(" KEY_VOL_DOWN \n"); + bt_key_vol_down(); + break; + case KEY_CALL_LAST_NO: + log_info(" KEY_CALL_LAST_NO \n"); + bt_key_call_last_on(); + break; + case KEY_CALL_HANG_UP: + log_info(" KEY_CALL_HANG_UP \n"); + bt_key_call_hand_up(); + break; + case KEY_CALL_ANSWER: + log_info(" KEY_CALL_ANSWER \n"); + bt_key_call_answer(); + break; + case KEY_OPEN_SIRI: + log_info(" KEY_OPEN_SIRI \n"); + bt_key_call_siri(); + break; + case KEY_HID_CONTROL: + log_info(" KEY_HID_CONTROL \n"); + bt_key_hid_control(); + break; + case KEY_THIRD_CLICK: + log_info(" KEY_THIRD_CLICK \n"); + bt_key_third_click(event); + break; + case KEY_LOW_LANTECY: + log_info(" KEY_LOW_LANTECY \n"); + bt_key_low_lantecy(); + break; + case KEY_NULL: + log_info(" KEY_NULL \n"); + ret = false; +#if TCFG_USER_TWS_ENABLE + if ((u32)event->arg == KEY_EVENT_FROM_TWS) { + break; + } +#endif + break; + + case KEY_HID_MODE_SWITCH: +#if (USER_SUPPORT_PROFILE_HID==1) + __this->hid_mode = !__this->hid_mode; + printf("KEY_HID_TAKE_PICTURE, %d\n", __this->hid_mode); + user_change_profile_mode(__this->hid_mode);///HID设备名称, 默认蓝牙名称追加_HID + //如果要修改名称, 可以重写重写这个函数,上面有重写例子 + //const char *__attribute__((weak)) bt_get_hid_name() +#endif + break; + case KEY_HID_TAKE_PICTURE: + if (__this->hid_mode) { + printf("KEY_HID_TAKE_PICTURE\n"); + user_send_cmd_prepare(USER_CTRL_HID_BOTH, 0, NULL); + } + break; + +#if TCFG_USER_TWS_ENABLE + case KEY_CHANGE_MODE: +#if (TCFG_DEC2TWS_ENABLE) + ret = false; +#else + if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) { + if (tws_api_get_role() == TWS_ROLE_MASTER) { + bt_tws_api_push_cmd(SYNC_CMD_MODE_CHANGE, 400); + } + } else { + ret = false; + break; + } + +#endif + break; +#endif + + default: + ret = false; + break; + } +#if (SMART_BOX_EN) + extern int smartbox_bt_key_event_deal(int key_event, int ret); + ret = smartbox_bt_key_event_deal(key_event, ret); +#endif + return ret; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式协议栈状态事件、hci事件、对箱事件 + @param event: 事件 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +int bt_sys_event_office(struct sys_event *event) +{ + u8 ret = false; + if ((u32)event->arg == SYS_BT_EVENT_TYPE_CON_STATUS) { + bt_connction_status_event_handler(&event->u.bt); + } else if ((u32)event->arg == SYS_BT_EVENT_TYPE_HCI_STATUS) { + bt_hci_event_handler(&event->u.bt); + } else if ((u32)event->arg == SYS_BT_EVENT_FORM_SELF) { + bt_reverb_status_change(&event->u.bt); + } +#if TCFG_USER_TWS_ENABLE + else if (((u32)event->arg == SYS_BT_EVENT_FROM_TWS)) { + ret = bt_tws_connction_status_event_handler(&event->u.bt); + } +#endif + else if (((u32)event->arg == SYS_BT_EVENT_FROM_KEY)) { + switch (event->u.key.event) { + case KEY_CHANGE_MODE: + app_task_switch_next(); + break; + } + } + return ret; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式事件消息处理 + @param event: 事件 + @return 1:处理完成,消息不需要进入common处理 0:common defult处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int bt_sys_event_handler(struct sys_event *event) +{ + int ret = false; + switch (event->type) { + case SYS_KEY_EVENT: + ret = bt_key_event_handler(event); + break; + case SYS_BT_EVENT: + ret = bt_sys_event_office(event); + break; + case SYS_DEVICE_EVENT: +#if APP_ONLINE_DEBUG + if ((u32)event->arg == DEVICE_EVENT_ONLINE_DATA) { + //putchar('%'); + extern void app_online_event_handle(int evt_value); + app_online_event_handle(event->u.dev.value); + } +#endif /* #if TCFG_EARTCH_EVENT_HANDLE_ENABLE */ + break; + default: + return false; + } + // SYS_EVENT_HANDLER_SPECIFIC(event); + app_protocol_sys_event_handler(event); + return ret; +} + +//*----------------------------------------------------------------------------*/ +/**@brief BT 模式提示音播放结束处理 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void bt_tone_play_end_callback(void *priv, int flag) +{ + u32 index = (u32)priv; + + if (APP_BT_TASK != app_get_curr_task()) { + log_error("tone callback task out \n"); + return; + } + + switch (index) { + case IDEX_TONE_BT_MODE: + ///提示音播放结束, 启动播放器播放 + bt_task_start(); + break; + default: + break; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 + @param + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void app_bt_task() +{ + int res; + int msg[32]; + ui_update_status(STATUS_EXIT_LOWPOWER); + + bt_task_init();//初始化变量、时钟、显示(未进行协议栈初始化) + +#if TCFG_TONE2TWS_ENABLE + extern void tone2tws_bt_task_start(u8 tone_play); + tone2tws_bt_task_start(!__this->cmd_flag); +#endif + + extern u8 get_tws_background_connected_flag(); + if (!__this->cmd_flag && (!get_tws_background_connected_flag())) { //蓝牙后台拉回蓝牙模式不播放提示音 + tone_play_with_callback_by_name(tone_table[IDEX_TONE_BT_MODE], 1, bt_tone_play_end_callback, (void *)IDEX_TONE_BT_MODE); + //协议栈初始化在提示音结束进行 + } else { + //后台返回的情况没有播放提示音,需要在这里进行协议栈的resume + bt_task_start(); + } +#if TCFG_DEC2TWS_ENABLE + extern void set_tws_background_connected_flag(u8 flag); + if (get_tws_background_connected_flag()) { + int state = tws_api_get_tws_state(); + if (state & TWS_STA_SIBLING_CONNECTED) { + if (tws_api_get_role() == TWS_ROLE_MASTER) { + app_task_switch_back(); + } else { + set_tws_background_connected_flag(0); + } + } + } +#endif + + while (1) { + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + if (bt_sys_event_handler((struct sys_event *)(msg + 1)) == false) { + app_default_event_deal((struct sys_event *)(&msg[1])); + } + break; + default: + break; + } + + + +#if TCFG_BLUETOOTH_BACK_MODE + if (!__this->init_ok && !app_var.goto_poweroff_flag) { + //蓝牙后台方案必须要等待协议栈初始化完成 + continue; + } +#else + if (__this->init_start && (!__this->init_ok)) { //协议栈已经初始化 但没有初始化完成 + //需要等待初始化完成才可以走退出流程 + continue; + } +#endif + + if (app_task_exitting()) { + if (__this->init_start) { + bt_task_close(); + __this->wait_exit = 1; + } else { //蓝牙协议栈没有初始化,可以直接退出 + bt_task_close(); + return; + } + } + + if (__this->wait_exit) { //开始退出 + if (!__this->exiting) { ///等待蓝牙退出处理完成 + __this->wait_exit = 0; + return; + } + } + } +} + +u8 bt_app_exit_check() +{ + return bt_app_switch_exit_check(); +} + +#else +void app_bt_task() +{ + +} + +u8 bt_app_exit_check() +{ + return 1; +} + +int bt_background_event_handler_filter(struct sys_event *event) +{ + return 0; +} + + +u8 get_call_status() +{ + return BT_CALL_HANGUP; +} + +u32 bt_tws_master_slot_clk(void) +{ + return 0; +} + +#endif diff --git a/apps/soundbox/task_manager/bt/bt_ble.c b/apps/soundbox/task_manager/bt/bt_ble.c new file mode 100644 index 0000000..cf0c5bf --- /dev/null +++ b/apps/soundbox/task_manager/bt/bt_ble.c @@ -0,0 +1,822 @@ +#include "system/app_core.h" +#include "system/includes.h" + +#include "app_config.h" +#include "app_task.h" + +#include "btstack/btstack_task.h" +#include "user_cfg.h" +#include "vm.h" +#include "app_power_manage.h" +#include "btcontroller_modules.h" +#include "app_chargestore.h" +#include "btstack/avctp_user.h" +#include "bt_common.h" +#include "le_common.h" + + +#include "bt/bt_ble.h" + +#if TCFG_APP_BT_EN + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) + +#define LOG_TAG_CONST BT_BLE +#define LOG_TAG "[BT_BLE]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#if 0 +#define ble_puts printf +#define ble_printf printf +#define ble_put_buf printf_buf + +#else + +#define ble_puts log_info +#define ble_printf log_info +#define ble_put_buf log_debug_hexdump + +#endif + +#define BLE_TIMER_SET (100) + +//停留时间,可以自定义修改 +#define ADV_ST_CONN_HOLD_TIME (20000/BLE_TIMER_SET)//phone connect device +#define ADV_ST_RECONN_HOLD_TIME (20000/BLE_TIMER_SET)//device connect phone + +//以下时间不建议修改 +#define ADV_ST_DISMISS_HOLD_TIME (2000/BLE_TIMER_SET) +#define ADV_ST_PRE1_HOLD_TIME (200/BLE_TIMER_SET) +#define ADV_ST_FAST_DISMISS_HOLD_TIME (1500/BLE_TIMER_SET)//to fast display reconnect + +#define PHONE_ICON_ONE_BETA 0 //beta case,one ear case + +//0---default,inquiry,connect,reconnect +//1---only inquiry and first connect +#define PHONE_ICON_CTRL_MODE 0 // + + +#define PHONE_ICON_AUTO_DISMISS 1 //auto dismiss icon + +#if TCFG_CHARGESTORE_ENABLE +#define REFLASH_ICON_STATE 1 //auto reflash +#else +#define REFLASH_ICON_STATE 0 //not auto reflash,fixed +#endif + +static u32 ble_timer_handle = 0; +static u16 adv_st_count = 0; +static u8 dev_battery_level[3];//master,slave,box +static volatile u8 adv_control_enable;//master +static volatile u8 adv_st_mode; +static volatile u8 adv_st_next_mode; +static volatile u8 adv_enable = 0; +static u8 adv_data[ADV_RSP_PACKET_MAX]; +static u8 adv_data_len = 0; +static u8 rsp_data[ADV_RSP_PACKET_MAX]; +static u8 rsp_data_len = 0; +static u8 adv_rand; +static u8 adv_open_lock;//lock open 标记 + +//-------------------user_tag data start---------------------------------------------------------- +static u8 user_tag_data[19] = { + 0xd6, 0x05, + 0x01, 0x00, + 0x01, 0x00, + 0x00, //6 +}; + + +static const u8 user_pre1_tag_data[29] = { + 0xd6, 0x05, + 0x02, 0x00, + 0x02, 0x00, + 0x00, //6 +}; + +static const u8 user_pre2_tag_data[29] = { + 0xd6, 0x05, + 0x03, 0x00, + 0x03, 0x00, + 0x00, //6 +}; + +static const u8 user_conn_tag_data[29] = { + 0xd6, 0x05, + 0x04, 0x00, + 0x04, 0x00, + 0x00, //6 +}; + +static const u8 user_reconn_tag_data[29] = { + 0xd6, 0x05, + 0x05, 0x00, + 0x05, 0x00, + 0x00, //6 +}; + +//-----------------------data end------------------------------------------------------ + +extern const char *bt_get_local_name(); +static void adv_rand_init(void); +static u8 update_dev_battery_level(void); + +//------------------------------------------------------- + +const char ble_name_string[] = "693_ble"; +static int make_set_adv_data(u8 *info, u8 len) +{ + u8 offset = 0; + u8 *buf = (void *)adv_data; + u8 *tag_buf = (void *)info; + u8 tag_len = len; + /* + #if 0 //BLE广播使用EDR的蓝牙名字,防止连接时蓝牙名字变成693_ble蓝牙名字最多只能31-21=10字节。 + u8 *edr_name = bt_get_local_name(); + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME, (void *)edr_name, strlen(edr_name)); + #else + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_COMPLETE_LOCAL_NAME, (void *)ble_name_string, strlen(ble_name_string)); + #endif + */ + + offset += make_eir_packet_data(&buf[offset], offset, HCI_EIR_DATATYPE_MANUFACTURER_SPECIFIC_DATA, (void *)tag_buf, tag_len); + + if (offset > ADV_RSP_PACKET_MAX) { + ble_puts("***adv_data overflow!!!!!!\n"); + return -1; + } + ble_printf("ADV data(%d):", offset); + ble_put_buf(buf, offset); + adv_data_len = offset; + return 0; +} + +static int make_set_rsp_data(void) +{ + u8 offset = 0; + u8 *buf = (void *)rsp_data; + + if (offset > ADV_RSP_PACKET_MAX) { + ble_puts("***rsp_data overflow!!!!!!\n"); + return -1; + } + + ble_printf("RSP data(%d):,offset"); + ble_put_buf(buf, offset); + rsp_data_len = offset; + return 0; +} + +static void adv_setup_init(void) +{ + u8 adv_type = 3; + u8 adv_channel = 0x07; + u16 adv_interval; + + switch (adv_st_mode) { + case ADV_ST_INQUIRY: + case ADV_ST_DISMISS: + case ADV_ST_FAST_DISMISS: + //特殊状态,广播周期快 + adv_interval = 0x30; + break; + + case ADV_ST_CONN: + case ADV_ST_RECONN: + default: + if (get_total_connect_dev()) { + //连上手机,广播周期慢 + adv_interval = 0x60; + } else { + //未连上手机,广播周期快 + adv_interval = 0x30; + } + break; + } + + ble_printf("adv_interval=%d\n", adv_interval); + + ble_user_cmd_prepare(BLE_CMD_ADV_PARAM, 3, adv_interval, adv_type, adv_channel); + + ble_user_cmd_prepare(BLE_CMD_ADV_DATA, 2, adv_data_len, adv_data); + ble_user_cmd_prepare(BLE_CMD_RSP_DATA, 2, rsp_data_len, rsp_data); +} + +u8 bt_ble_get_adv_enable(void) +{ + return adv_enable; +} + +void bt_ble_adv_enable(u8 enable) +{ + if (adv_enable == enable) { + return; + } + adv_enable = enable; + + ble_printf("***** ble_adv_en:%d ******\n", enable); + if (enable) { + adv_setup_init(); + } + ble_user_cmd_prepare(BLE_CMD_ADV_ENABLE, 1, enable); +} + +//----------------------- +extern u8 get_charge_online_flag(void); +static u8 get_device_bat_percent(void) +{ +#if CONFIG_DISPLAY_DETAIL_BAT + u8 val = get_vbat_percent(); +#else + u8 val = get_self_battery_level() * 10 + 10; +#endif + + if (val > 100) { + val = 100; + } + val = (val | (get_charge_online_flag() << 7)); + /* printf("[%d]",val); */ + return val; +} + +static void reflash_adv_tag_data(const u8 *tag_data, u8 len, u8 spec_val) +{ + u8 tmp_tag_data[32]; + u8 tmp8; + + memcpy(tmp_tag_data, tag_data, len); + memcpy(&tmp_tag_data[14], dev_battery_level, 3); + +#if TCFG_CHARGESTORE_ENABLE + //位置14,15,16 对应 R,L,BOX + if (chargestore_get_earphone_pos() == 'L') { + //switch position + ble_puts("is L pos\n"); + tmp8 = tmp_tag_data[14]; + tmp_tag_data[14] = tmp_tag_data[15]; + tmp_tag_data[15] = tmp8; + } else { + ble_puts("is R pos\n"); + } +#endif + + if (spec_val != 0xff) { + tmp_tag_data[17] = spec_val; + if (spec_val != 9) { +#if TCFG_USER_TWS_ENABLE + /* memset(&tmp_tag_data[14],0xff,3); */ +#endif + } else { + memset(&tmp_tag_data[14], 0xFF, 3);//关闭广播的时候不显示电量 + } + } + + //--- +#if (!REFLASH_ICON_STATE) // + if (len == 29) { +#if TCFG_USER_TWS_ENABLE + //fixed do,start,固定分开显示电量,如不分开,可以屏蔽这段代码 + ble_puts("fixed two do\n"); + /* ble_put_buf(&tmp_tag_data[14],3); */ + if ((tmp_tag_data[14] != 0xff) + && (tmp_tag_data[15] != 0xff)) { + if ((tmp_tag_data[14]&BIT(7)) + && (tmp_tag_data[15]&BIT(7))) { + tmp_tag_data[15] &= 0x7f; + ble_puts("fixed c1\n"); + } else { + if (((tmp_tag_data[14]&BIT(7)) == 0) + && ((tmp_tag_data[15]&BIT(7)) == 0)) { + tmp_tag_data[14] |= BIT(7); + ble_puts("fixed c2\n"); + } + + } + + } + //fixed do,end +#endif + } +#endif + //--- + + bt_ble_adv_enable(0); + make_set_adv_data(tmp_tag_data, len); + bt_ble_adv_enable(1); +} + +static bool check_adv_open_lock(void) +{ + if (get_total_connect_dev()) { + //已连上手机 + adv_open_lock = 1; + } + return adv_open_lock; +} + +static void change_adv_st_mode(u8 mode) +{ + if (mode == adv_st_mode) { + return; + } + + ble_printf("ble_adv_st:old= %d,new= %d \n", adv_st_mode, mode); + + adv_st_mode = mode; + adv_st_count = 0; + + switch (mode) { + case ADV_ST_CONN: + check_adv_open_lock(); + reflash_adv_tag_data(user_conn_tag_data, sizeof(user_conn_tag_data), 0xff); + break; + + case ADV_ST_RECONN: + check_adv_open_lock(); + reflash_adv_tag_data(user_reconn_tag_data, sizeof(user_reconn_tag_data), 0xff); + break; + + case ADV_ST_DISMISS: + reflash_adv_tag_data(user_tag_data, sizeof(user_tag_data), 0x9); + break; + + case ADV_ST_INQUIRY: + reflash_adv_tag_data(user_tag_data, sizeof(user_tag_data), adv_rand); + break; + + case ADV_ST_PRE1: + reflash_adv_tag_data(user_pre1_tag_data, sizeof(user_pre1_tag_data), 0xff); + break; + + case ADV_ST_PRE2: + reflash_adv_tag_data(user_pre2_tag_data, sizeof(user_pre2_tag_data), 0xff); + break; + + case ADV_ST_FAST_DISMISS: + reflash_adv_tag_data(user_tag_data, sizeof(user_tag_data), 0x9); + break; + + case ADV_ST_END: + bt_ble_adv_enable(0); + break; + + default: + break; + } + +} + +static void check_dev_pos_changed(u8 cur_adv_mode) +{ +#if REFLASH_ICON_STATE + if (update_dev_battery_level()) { + ble_puts("---reflash_dev_state\n"); + /* adv_st_next_mode = cur_adv_mode; */ + /* change_adv_st_mode(ADV_ST_FAST_DISMISS); */ + + change_adv_st_mode(ADV_ST_END); + change_adv_st_mode(cur_adv_mode); + } +#endif +} + +static void bt_ble_timer_handler(void) +{ + u8 bat_percent; + + if (!adv_enable) { + return; + } + + adv_st_count++; + switch (adv_st_mode) { + case ADV_ST_PRE1: + if (adv_st_count > ADV_ST_PRE1_HOLD_TIME) { + change_adv_st_mode(ADV_ST_PRE2); + } + break; + + case ADV_ST_CONN: + if (adv_st_count > ADV_ST_CONN_HOLD_TIME) { +#if PHONE_ICON_AUTO_DISMISS + change_adv_st_mode(ADV_ST_DISMISS); +#else + change_adv_st_mode(ADV_ST_END); +#endif + } else { + check_dev_pos_changed(adv_st_mode); + } + break; + + case ADV_ST_RECONN: + if (adv_st_count > ADV_ST_RECONN_HOLD_TIME) { +#if PHONE_ICON_AUTO_DISMISS + change_adv_st_mode(ADV_ST_DISMISS); +#else + change_adv_st_mode(ADV_ST_END); +#endif + } else { + check_dev_pos_changed(adv_st_mode); + } + break; + + case ADV_ST_DISMISS: + if (adv_st_count > ADV_ST_DISMISS_HOLD_TIME) { + change_adv_st_mode(ADV_ST_END); + } + break; + + case ADV_ST_FAST_DISMISS: + if (adv_st_count > ADV_ST_FAST_DISMISS_HOLD_TIME) { + change_adv_st_mode(adv_st_next_mode); + } + break; + + case ADV_ST_INQUIRY: + check_dev_pos_changed(adv_st_mode); + break; + + case ADV_ST_NULL: + case ADV_ST_PRE2: + break; + + default: + break; + } + +} + +static void bt_ble_timer_init(void) +{ + ble_timer_handle = sys_timer_add(NULL, bt_ble_timer_handler, BLE_TIMER_SET); +} + + +extern const u8 *bt_get_mac_addr(); +extern const u8 *ble_get_mac_addr(void); +extern void swapX(const uint8_t *src, uint8_t *dst, int len); +void bt_ble_test_tag_do(void) +{ + ble_puts("bt_ble_test_tag_do\n"); + //初始化三个电量值 + memset(dev_battery_level, 0xff, sizeof(dev_battery_level)); + dev_battery_level[0] = get_device_bat_percent(); + swapX(bt_get_mac_addr(), &user_tag_data[7], 6); + ble_puts("\n------master address------\n"); + ble_put_buf(&user_tag_data[7], 6); + /* make_set_adv_data(user_tag_data, sizeof(user_tag_data)); */ +} + +void bt_ble_icon_set_comm_address(u8 *addr) +{ + swapX(addr, &user_tag_data[7], 6); + le_controller_set_mac(addr);//将ble广播地址改成公共地址 + + ble_puts("\n------reset master address------\n"); + ble_put_buf(&user_tag_data[7], 6); +} + +void bt_ble_icon_reset(void) +{ + ble_puts("bt_ble_icon_reset\n"); + if (!adv_control_enable) { + return; + } + //重置状态,允许再广播 + ble_puts("reset_do\n"); + adv_rand_init(); + adv_st_mode = ADV_ST_NULL; + adv_open_lock = 0; + bt_ble_adv_enable(0); +} + +u8 bt_ble_icon_get_adv_state(void) +{ + return adv_st_mode; +} + +//return change_flag +static u8 update_dev_battery_level(void) +{ + + u8 old_dev_battery[3]; + + memcpy(old_dev_battery, dev_battery_level, 3); + + //read bat_level + dev_battery_level[0] = get_device_bat_percent(); + + u8 sibling_bat_level = dev_battery_level[1]; + if (sibling_bat_level == 0xff) { + /* ble_puts("--update_bat_00\n"); */ + goto update_dev2; + } + + +#if TCFG_USER_TWS_ENABLE + sibling_bat_level = get_tws_sibling_bat_persent(); +#endif + +#if TCFG_CHARGESTORE_ENABLE + if (sibling_bat_level == 0xff) { + /* ble_puts("--update_bat_01\n"); */ + sibling_bat_level = chargestore_get_sibling_power_level(); + } +#endif + + if (sibling_bat_level == 0xff) { + /* ble_puts("--update_bat_02\n"); */ + dev_battery_level[1] = dev_battery_level[0]; + } else { + dev_battery_level[1] = sibling_bat_level; + } + +update_dev2: + if (((dev_battery_level[0] & BIT(7)) && (dev_battery_level[0] != 0xff)) + || ((dev_battery_level[1] & BIT(7)) && (dev_battery_level[1] != 0xff))) { + //earphone in charge +#if TCFG_CHARGESTORE_ENABLE + dev_battery_level[2] = chargestore_get_power_level(); +#else + dev_battery_level[2] = 0xff; +#endif + } else { + //all not in charge + dev_battery_level[2] = 0xff; + } + + u8 i; + u8 change_flag = 0; + + for (i = 0; i < 3; i++) { + if ((dev_battery_level[i]&BIT(7)) != (old_dev_battery[i]&BIT(7))) { + break; + } + + if ((dev_battery_level[i] == 0xff) && (old_dev_battery[i] != 0xff)) { + break; + } + + if ((dev_battery_level[i] != 0xff) && (old_dev_battery[i] == 0xff)) { + break; + } + + } + + if (i < 3) { + ble_puts("dev_pos_state have changed:"); + ble_put_buf(old_dev_battery, 3); + ble_put_buf(dev_battery_level, 3); + change_flag = 1; + } + return change_flag; +} + + + +//open 不同类型广播 +void bt_ble_icon_open(u8 type) +{ + ble_printf("bt_ble_icon_open: %d\n", type); + + if (!adv_control_enable) { + return; + } + + if (adv_open_lock) { + ble_puts("open_lock\n"); + return; + } + + ble_puts("open_do\n"); + + update_dev_battery_level(); + + switch (adv_st_mode) { + case ADV_ST_NULL: + +#if PHONE_ICON_ONE_BETA + if (type == ICON_TYPE_INQUIRY) { + change_adv_st_mode(ADV_ST_INQUIRY); + } else if (type == ICON_TYPE_CONNECTED || type == ICON_TYPE_RECONNECT) { + //record,and not display + change_adv_st_mode(ADV_ST_END); + } + break; +#endif + +#if (PHONE_ICON_CTRL_MODE == 1) + if (type == ICON_TYPE_INQUIRY) { + change_adv_st_mode(ADV_ST_INQUIRY); + } else if (type == ICON_TYPE_CONNECTED || type == ICON_TYPE_RECONNECT) { + //record,and not display + change_adv_st_mode(ADV_ST_END); + } + break; +#endif + + + if (type == ICON_TYPE_CONNECTED || type == ICON_TYPE_RECONNECT) { + change_adv_st_mode(ADV_ST_RECONN); + } else if (type == ICON_TYPE_PRE_DEV) { + change_adv_st_mode(ADV_ST_PRE1); + } else { + change_adv_st_mode(ADV_ST_INQUIRY); + } + break; + + case ADV_ST_INQUIRY: + +#if PHONE_ICON_ONE_BETA + if (type == ICON_TYPE_CONNECTED || type == ICON_TYPE_RECONNECT) { + change_adv_st_mode(ADV_ST_DISMISS); + } + break; +#endif + +#if (PHONE_ICON_CTRL_MODE == 1) + if (type == ICON_TYPE_CONNECTED || type == ICON_TYPE_RECONNECT) { + change_adv_st_mode(ADV_ST_DISMISS); + } + break; +#endif + + + switch (type) { + case ICON_TYPE_CONNECTED: +#if TCFG_USER_TWS_ENABLE + change_adv_st_mode(ADV_ST_CONN); +#else + change_adv_st_mode(ADV_ST_DISMISS); +#endif + break; + + case ICON_TYPE_RECONNECT: + change_adv_st_mode(ADV_ST_FAST_DISMISS); + adv_st_next_mode = ADV_ST_RECONN; + break; + + default: + break; + } + break; + + case ADV_ST_PRE1: + case ADV_ST_PRE2: + if (type == ICON_TYPE_INQUIRY) { + //开inquiry + change_adv_st_mode(ADV_ST_INQUIRY); + } else if (type == ICON_TYPE_CONNECTED) { + change_adv_st_mode(ADV_ST_CONN); + } else { + ; + } + break; + + + case ADV_ST_RECONN: + if (type == ICON_TYPE_INQUIRY) { + change_adv_st_mode(ADV_ST_FAST_DISMISS); + adv_st_next_mode = ADV_ST_INQUIRY; + } else if (type == ICON_TYPE_CONNECTED) { + change_adv_st_mode(ADV_ST_FAST_DISMISS); + adv_st_next_mode = ADV_ST_CONN; + } else { + ; + } + break; + + default: + break; + } +} + +//dismiss_flag +void bt_ble_icon_close(u8 dismiss_flag) +{ + ble_printf("bt_ble_close: %d\n", dismiss_flag); + + if ((!dismiss_flag) || (!adv_control_enable)) { + ble_puts("close_adv\n"); + change_adv_st_mode(ADV_ST_END); + return; + } + + switch (adv_st_mode) { + case ADV_ST_CONN: + case ADV_ST_RECONN: + case ADV_ST_INQUIRY: + case ADV_ST_PRE1: + case ADV_ST_PRE2: + case ADV_ST_FAST_DISMISS: + case ADV_ST_DISMISS: + case ADV_ST_END://也要做 + change_adv_st_mode(ADV_ST_DISMISS); + break; + + default: + break; + } +} + +//tws,need set en +extern bool get_tws_sibling_connect_state(void); +extern int tws_api_get_role(void); +void bt_ble_icon_slave_en(u8 en) +{ + ble_printf("------icon_slave_enable = %d------\n", en); + if (en) { + dev_battery_level[1] = 0xfc;//set flag + } else { + dev_battery_level[1] = 0xff; + } + +#if TCFG_USER_TWS_ENABLE + if (get_tws_sibling_connect_state()) { + if (tws_api_get_role()) { + //已配对连接过的从机,记录以后不允许再广播 + adv_open_lock = 1;//lock open 接口 + bt_ble_icon_close(0); + } + } +#endif +} + + +//tws,master need set en;使能ICON_OPEN 接口控制 +void bt_ble_set_control_en(u8 en) +{ + ble_printf("------adv_control_enable = %d------\n", en); + adv_control_enable = en;//set master flag +} +//----------------------- +static void adv_rand_init(void) +{ + int ret = syscfg_read(CFG_BLE_MODE_INFO, (u8 *)&adv_rand, 1); + if (!ret) { + adv_rand = (rand32() % 7) + 1; + } else { + adv_rand++; + } + + if (adv_rand > 7) { + adv_rand = 1; + } + syscfg_write(CFG_BLE_MODE_INFO, (u8 *)&adv_rand, 1); + ble_printf("------adv_rand = %d------\n", adv_rand); + +} + +extern void dut_le_hw_open(void); +extern void ble_bqb_test_thread_init(void); +__BANK_INIT_ENTRY +void bt_ble_init(void) +{ + ble_printf("***** ble_init******\n"); + adv_rand_init(); + +#if TCFG_USER_TWS_ENABLE + adv_control_enable = 0;//tws,default off +#else + adv_control_enable = 1;//one earphone,default on +#endif + adv_st_mode = ADV_ST_NULL; + adv_open_lock = 0; + bt_ble_test_tag_do(); + bt_ble_timer_init(); +} + +/* + void bt_ble_icon_set(u8 *info, u8 len) + { + ble_printf("***** ble_icon_set******\n"); + + bt_ble_adv_enable(0); + update_user_tag_data(info, len); + bt_ble_adv_enable(1); + } + */ + +void bt_ble_exit(void) +{ + ble_printf("***** ble_exit******\n"); + + bt_ble_adv_enable(0); + adv_st_mode = ADV_ST_NULL; + adv_control_enable = 0; + if (ble_timer_handle) { + sys_timeout_del(ble_timer_handle); + ble_timer_handle = 0;; + } +} + + +#endif +#endif + + diff --git a/apps/soundbox/task_manager/bt/bt_emitter.c b/apps/soundbox/task_manager/bt/bt_emitter.c new file mode 100644 index 0000000..f2d3729 --- /dev/null +++ b/apps/soundbox/task_manager/bt/bt_emitter.c @@ -0,0 +1,1662 @@ + +/************************************************************* + + 此文件函数主要是蓝牙发射器接口处理 + +1、关于AG对讲功能使用说明: + 发射器需要通过user_emitter_cmd_prepare接口来给接收器发送命令,例如: + (1)发射器主动发起通话 + user_emitter_cmd_prepare(USER_CTRL_HFP_CALL_LAST_NO, 0, NULL) + + (2)发射器主动关断通话 + user_emitter_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL) + + (3)接收器来电接听 + user_emitter_cmd_prepare(USER_CTRL_HFP_CALL_ANSWER, 0, NULL) + +**************************************************************/ + +#include "system/app_core.h" +#include "system/includes.h" + +#include "app_config.h" +#include "app_task.h" + +#include "btstack/btstack_task.h" +#include "btcontroller_modules.h" +#include "btstack/avctp_user.h" +#include "classic/hci_lmp.h" + +#include "bt/bt.h" +#include "bt/bt_emitter.h" +#include "user_cfg.h" +#include "vm.h" +#include "app_main.h" +#include "common/app_common.h" + +#include "key_event_deal.h" +#include "rcsp_bluetooth.h" + +#include "media/includes.h" +#include "audio_config.h" +#include "audio_digital_vol.h" +#include "audio_enc.h" +#include "audio_sbc_codec.h" +#include "media/file_decoder.h" + +#include "music/music_player.h" + +#if TCFG_APP_BT_EN + + + +#if TCFG_USER_EMITTER_ENABLE + +#define LOG_TAG_CONST BT +#define LOG_TAG "[BT]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +#define LOG_DUMP_ENABLE +#define LOG_CLI_ENABLE +#include "debug.h" + + +#define SEARCH_BD_ADDR_LIMITED 0 +#define SEARCH_BD_NAME_LIMITED 1 +#define SEARCH_CUSTOM_LIMITED 2 +#define SEARCH_NULL_LIMITED 3 + +#define SEARCH_LIMITED_MODE SEARCH_BD_NAME_LIMITED + +#define SEARCH_NAME_DEBUG 0 + +struct remote_name { + u16 crc; + u8 addr[6]; + u8 name[32]; +}; + +struct list_head inquiry_noname_list; + +struct inquiry_noname_remote { + struct list_head entry; + u8 match; + s8 rssi; + u8 addr[6]; + u32 class; +}; + + +extern int music_player_get_play_status(void); +extern int music_player_pp(void); +extern u16 get_emitter_curr_channel_state(); +static u8 read_name_start = 0; +static u8 bt_search_busy = 0; +static u8 search_spp_device = 0; +static u8 emitter_dac_mute_en = 0; +static u8 bt_emitter_start = 0; + +int edr_at_set_cod(int cod_data) +{ + u32 class_type = cod_data; + printf("set class type %d",class_type); + __change_hci_class_type(class_type); + lmp_hci_write_class_of_device(class_type); + return 0; +} + +void bt_emitter_audio_set_mute(u8 mute) +{ + emitter_dac_mute_en = !!mute; +} + +//接收数据: +int ag_at_cmd_analysis_by_user(u8 *packet,u16 len) +{ + puts(packet); + // const at_serv_opr_t * at_opr = at_server_get_opr(); + // for (size_t i = 0; i < len + 1; i++) + // { + // if (i == len) + // { + // at_opr->parse_cmd_hendle('\n', user_send_at_cmd_prepare); + // }else + // { + // at_opr->parse_cmd_hendle(packet[i], user_send_at_cmd_prepare); + // } + // } + if (0 == strncmp("AT+XEVENT=TALK,0", packet, 16)) + { + // g_printf(">>>>>>>>>>>>>>>>>555555%s\n", packet); + // at_serv_opr_t * at_opr = at_server_get_opr(); + // at_opr->rsp_hfreq_state(0); + }else if (0 == strncmp("AT+XEVENT=TALK,1", packet, 16)) + { + // g_printf(">>>>>>>>>>>>>>>>>5344333335%s\n", packet); + // at_serv_opr_t * at_opr = at_server_get_opr(); + // at_opr->rsp_hfreq_state(1); + } + + printf("lllllllllllsize == %d\n",len); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 音频数据清0 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_data_set_zero(struct audio_stream_entry *entry, struct audio_data_frame *data_buf) +{ + if (emitter_dac_mute_en) { + memset(data_buf->data, 0, data_buf->data_len); + } + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射发起搜索设备 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_search_device(void) +{ + if (!get_bt_init_status()) { + /* log_info("bt on init >>>>>>>>>>>>>>>>>>>>>>>\n"); */ + return; + } + if (bt_search_busy) { + /* log_info("bt_search_busy >>>>>>>>>>>>>>>>>>>>>>>\n"); */ + //return; + } + + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL); + + read_name_start = 0; + bt_search_busy = 1; + u8 inquiry_length = 20; // inquiry_length * 1.28s + user_send_cmd_prepare(USER_CTRL_SEARCH_DEVICE, 1, &inquiry_length); + /* log_info("bt_search_start >>>>>>>>>>>>>>>>>>>>>>>\n"); */ +} + + +void bt_search_spp_device() +{ + search_spp_device = 1; + set_start_search_spp_device(1); + bt_search_device(); +} + +u8 bt_search_status() +{ + return bt_search_busy; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射 提供按键切换发射器或者是音箱功能 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void emitter_connect_switch() +{ + if (get_emitter_curr_channel_state() != 0) { + user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL); + while (hci_standard_connect_check() != 0) { + //wait disconnect; + os_time_dly(10); + } + } else { + /* log_info("start connect vm addr\n"); */ + user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR_MANUALLY, 0, NULL); + } +} + +u8 bt_emitter_role_get() +{ + return bt_user_priv_var.emitter_or_receiver; +} + +void bt_emitter_stop_search_device() +{ + user_send_cmd_prepare(USER_CTRL_INQUIRY_CANCEL, 0, NULL); +} + + + +void emitter_bt_connect(u8 *mac) +{ + if (bt_user_priv_var.emitter_or_receiver != BT_EMITTER_EN) { + return ; + } + + while (hci_standard_connect_check() == 0x80) { + //wait profile connect ok; + if (get_emitter_curr_channel_state()) { + break; + } + os_time_dly(10); + } + + + ////断开链接 + if (get_emitter_curr_channel_state() != 0) { + user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL); + } else { + if (hci_standard_connect_check()) { + user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL); + user_send_cmd_prepare(USER_CTRL_CONNECTION_CANCEL, 0, NULL); + } + } + /* if there are some connected channel ,then disconnect*/ + while (hci_standard_connect_check() != 0) { + //wait disconnect; + os_time_dly(10); + } + r_f_printf("USER_CTRL_START_CONNEC_VIA_ADDR"); + user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR, 6, mac); +} + + +void bt_emitter_start_search_device() +{ + if (bt_user_priv_var.emitter_or_receiver != BT_EMITTER_EN) { + return ; + } + while (hci_standard_connect_check() == 0x80) { + //wait profile connect ok; + if (get_emitter_curr_channel_state()) { + break; + } + os_time_dly(10); + } + + ////断开链接 + if (get_emitter_curr_channel_state() != 0) { + user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL); + } else { + if (hci_standard_connect_check()) { + user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL); + user_send_cmd_prepare(USER_CTRL_CONNECTION_CANCEL, 0, NULL); + } + } + /* if there are some connected channel ,then disconnect*/ + while (hci_standard_connect_check() != 0) { + //wait disconnect; + os_time_dly(10); + } + + ////关闭可发现可链接 + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL); + ////切换样机状态 + bt_search_device(); + +} + +////回链耳机音箱 +u8 connect_last_sink_device_from_vm() +{ + bd_addr_t mac_addr; + u8 flag = 0; + flag = restore_remote_device_info_profile(&mac_addr, 1, get_remote_dev_info_index(), REMOTE_SINK); + if (flag) { + //connect last conn + printf("last source device addr from vm:"); + put_buf(mac_addr, 6); + user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR, 6, mac_addr); + } + //r_printf("connect last vm addr\n"); + return flag; +} + +////回链手机 +u8 connect_last_source_device_from_vm() +{ + bd_addr_t mac_addr; + u8 flag = 0; + flag = restore_remote_device_info_profile(&mac_addr, 1, get_remote_dev_info_index(), REMOTE_SOURCE); + if (flag) { + //connect last conn + printf("last source device addr from vm:"); + put_buf(mac_addr, 6); + user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR, 6, mac_addr); + } + //r_printf("connect last vm addr\n"); + return flag; +} + +static void ag_mode_auto_reconn_timer_callback(void *priv) +{ + printf("周期5秒自动重连\n"); + log_i(">>>>>>>>>>>>>>>>>>>>ag auto reconn device: %x\n", get_emitter_curr_channel_state()); + if ((0 == get_emitter_curr_channel_state())) + { + g_printf("connect vm mac addr"); + // emitter_bt_connect(config->ag_dev.addr); + // u32 ret = user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR, 6, config->ag_dev.addr); + // log_i("emitter conn ret: %d\n", ret); + user_disconn_for_poweroff(); + u8 ret = connect_last_device_from_vm(); + log_info("start connect device vm addr: %d\n", ret); + } else { + g_printf("do nothing!!!"); + } +} +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射 提供按键切换发射器或者是音箱功能 + @param 1:发射 0:接收 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void emitter_or_receiver_switch(u8 flag) +{ + /* log_info("===emitter_or_receiver_switch %d %x\n", flag, hci_standard_connect_check()); */ + /*如果上一次操作记录跟传进来的参数一致,则不操作*/ + if (bt_user_priv_var.emitter_or_receiver == flag) { + return ; + } + while (hci_standard_connect_check() == 0x80) { + //wait profile connect ok; + if (bt_user_priv_var.emitter_or_receiver == BT_EMITTER_EN) { ///蓝牙发射器 + r_printf("cur_ch:0x%x", get_emitter_curr_channel_state()); + if (get_emitter_curr_channel_state()) { + break; + } + } else { + r_printf("cur_ch:0x%x", get_curr_channel_state()); + if (get_curr_channel_state()) { + break; + } + } + os_time_dly(10); + } + + ////断开链接 + if ((get_curr_channel_state() != 0) || (get_emitter_curr_channel_state() != 0)) { + user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL); + } else { + if (hci_standard_connect_check()) { + user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL); + user_send_cmd_prepare(USER_CTRL_CONNECTION_CANCEL, 0, NULL); + } + } + /* if there are some connected channel ,then disconnect*/ + while (hci_standard_connect_check() != 0) { + //wait disconnect; + os_time_dly(10); + } + + /* g_printf("===wait to switch to mode %d\n", flag); */ + bt_user_priv_var.emitter_or_receiver = flag; + if (flag == BT_EMITTER_EN) { ///蓝牙发射器 + bredr_bulk_change(0); + ////关闭可发现可链接 + // user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); + // user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL); + //修改 BD_CLASS + user_send_cmd_prepare(USER_CTRL_INQUIRY_CANCEL, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL); + edr_at_set_cod(BD_CLASS_SMART_PHONE_2); + //修改 local addr + lmp_hci_write_local_address(bt_get_mac_addr()); + + ////切换样机状态 + __set_emitter_enable_flag(1); + a2dp_source_init(NULL, 0, 1); +#if (USER_SUPPORT_PROFILE_HFP_AG==1) + hfp_ag_buf_init(NULL, 0, 1); +#endif + ////开启搜索设备 + +#if !BT_EMITTER_TEST_ENABLE + os_time_dly(1); + u8 mac[6]; + u8 flag = 0; + flag = restore_remote_device_info_profile(&mac, 1, get_remote_dev_info_index(), REMOTE_SINK); + if (flag) { + //connect last conn + printf("last source device addr from vm:"); + put_buf(mac,6); + emitter_bt_connect(mac); + } + + // r_printf("connect last vm addr\n"); + // lmp_hci_write_local_address(mac); + // u8 ret = connect_last_device_from_vm(); +#else + os_time_dly(1); + /* 添加避免发射器切换成接收器之后还会回连之前的接收器的修改 */ + u8 mac[6]; + bt_get_vm_mac_addr(mac); + u8 temp; + for (u8 i = 0; i < 3; i++) + { + temp = mac[i]; + mac[i] = mac[5-i]; + mac[5-i] = temp; + } + put_buf(mac, 6); + lmp_hci_write_local_address(mac); + os_time_dly(1); + ////开启搜索设备 + if (emitter_get_vm_device()) { + log_info("start connect device vm addr\n"); + sys_timer_add(NULL, ag_mode_auto_reconn_timer_callback, 5000); + } else { + bt_search_device(); + } +#endif + + } else if (flag == BT_RECEIVER_EN) { ///蓝牙接收 + + //修改 BD_CLASS + user_send_cmd_prepare(USER_CTRL_INQUIRY_CANCEL, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL); + edr_at_set_cod(BD_CLASS_HEADPHONES); + //修改 local addr + u8 rec_mac_addr[6] = {0}; + memcpy(rec_mac_addr,bt_get_mac_addr(),6); + rec_mac_addr[0] += 1; + lmp_hci_write_local_address(rec_mac_addr); + bredr_bulk_change(1); + ////切换样机状态 + __set_emitter_enable_flag(0); + emitter_media_source(1, 0); + hci_cancel_inquiry(); + a2dp_source_init(NULL, 0, 0); +#if (USER_SUPPORT_PROFILE_HFP_AG==1) + hfp_ag_buf_init(NULL, 0, 0); +#endif + // __change_hci_class_type(BD_CLASS_HEADPHONES);//当为接收器模式的时候,部分手机会过滤掉搜索不到 + ////开启可发现可链接 + if (connect_last_device_from_vm()) { + log_info("start connect vm addr phone \n"); + } else { + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_ENABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); + } + } +} + + +void bt_emitter_receiver_sw() +{ + if (bt_user_priv_var.emitter_or_receiver != BT_EMITTER_EN) { + emitter_or_receiver_switch(BT_EMITTER_EN); + } else { + emitter_or_receiver_switch(BT_RECEIVER_EN); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射变量初始化 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_emitter_init() +{ + bt_emitter_start = 1; + INIT_LIST_HEAD(&inquiry_noname_list); + + lmp_set_sniff_establish_by_remote(1); + audio_sbc_enc_init(); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射搜索设备没有名字的设备,放进需要获取名字链表 + @param status : 获取成功 0:获取失败 + addr:设备地址 + name:设备名字 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void emitter_search_noname(u8 status, u8 *addr, u8 *name) +{ + struct inquiry_noname_remote *remote, *n; + if (!bt_emitter_start) { + return ; + } + + u8 res = 0; + local_irq_disable(); + if (status) { + list_for_each_entry_safe(remote, n, &inquiry_noname_list, entry) { + if (!memcmp(addr, remote->addr, 6)) { + list_del(&remote->entry); + free(remote); + } + } + goto __find_next; + } + list_for_each_entry_safe(remote, n, &inquiry_noname_list, entry) { + if (!memcmp(addr, remote->addr, 6)) { + res = emitter_search_result(name, strlen(name), addr, remote->class, remote->rssi); + if (res) { + read_name_start = 0; + remote->match = 1; + user_send_cmd_prepare(USER_CTRL_INQUIRY_CANCEL, 0, NULL); + local_irq_enable(); + return; + } + list_del(&remote->entry); + free(remote); + } + } + +__find_next: + + read_name_start = 0; + remote = NULL; + if (!list_empty(&inquiry_noname_list)) { + remote = list_first_entry(&inquiry_noname_list, struct inquiry_noname_remote, entry); + } + + local_irq_enable(); + if (remote) { + read_name_start = 1; + user_send_cmd_prepare(USER_CTRL_READ_REMOTE_NAME, 6, remote->addr); + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射停止搜索 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ + +void emitter_search_stop(u8 result) +{ + struct inquiry_noname_remote *remote, *n; + bt_search_busy = 0; + search_spp_device = 0; + set_start_search_spp_device(0); + u8 wait_connect_flag = 1; + if (!list_empty(&inquiry_noname_list)) { + user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL); + } + + if (!result) { + list_for_each_entry_safe(remote, n, &inquiry_noname_list, entry) { + if (remote->match) { + user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR, 6, remote->addr); + wait_connect_flag = 0; + } + list_del(&remote->entry); + free(remote); + } + } + read_name_start = 0; + if (wait_connect_flag) { + /* log_info("wait conenct\n"); */ +#if TCFG_SPI_LCD_ENABLE + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL); +#else + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); + if (!result) { + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); + } +#endif + + } +} + + +#if (SEARCH_LIMITED_MODE == SEARCH_BD_ADDR_LIMITED) +u8 bd_addr_filt[][6] = { + {0x8E, 0xA7, 0xCA, 0x0A, 0x5E, 0xC8}, /*S10_H*/ + {0xA7, 0xDD, 0x05, 0xDD, 0x1F, 0x00}, /*ST-001*/ + {0xE9, 0x73, 0x13, 0xC0, 0x1F, 0x00}, /*HBS 730*/ + {0x38, 0x7C, 0x78, 0x1C, 0xFC, 0x02}, /*Bluetooth*/ +}; +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射搜索通过地址过滤 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 search_bd_addr_filt(u8 *addr) +{ + u8 i; + log_info("bd_addr:"); + log_info_hexdump(addr, 6); + for (i = 0; i < (sizeof(bd_addr_filt) / sizeof(bd_addr_filt[0])); i++) { + if (memcmp(addr, bd_addr_filt[i], 6) == 0) { + /* printf("bd_addr match:%d\n", i); */ + return TRUE; + } + } + /*log_info("bd_addr not match\n"); */ + return FALSE; +} +#endif + + +#if 1//(SEARCH_LIMITED_MODE == SEARCH_BD_NAME_LIMITED) +#if (0) +u8 bd_name_filt[][32] = { + "BeMine", + "EDIFIER CSR8635",/*CSR*/ + "JL-BT-SDK",/*Realtek*/ + "I7-TWS",/*ZKLX*/ + "TWS-i7",/*ZKLX*/ + "I9",/*ZKLX*/ + "小米小钢炮蓝牙音箱",/*XiaoMi*/ + "小米蓝牙音箱",/*XiaoMi*/ + "XMFHZ02",/*XiaoMi*/ + "JBL GO 2", + "i7mini",/*JL tws AC690x*/ + "S08U", + "AI8006B_TWS00", + "S046",/*BK*/ + "AirPods", + "CSD-TWS-01", + "AC692X_wh", + "JBL GO 2", + "JBL Flip 4", + "BT Speaker", + "CSC608", + "QCY-QY19", + "Newmine", + "HT1+", + "S-35", + "T12-JL", + "Redmi AirDots_R", + "Redmi AirDots_L", + "AC69_Bluetooth", + "FlyPods 3", + "MNS", + "Jam Heavy Metal", + "Bluedio", + "HR-686", + "BT MUSIC", + "BW-USB-DONGLE", + "S530", + "XPDQ7", + "MICGEEK Q9S", + "S10_H", + "S10",/*JL AC690x*/ + "S11",/*JL AC460x*/ + "HBS-730", + "SPORT-S9", + "Q5", + "IAEB25", + "T5-JL", + "MS-808", + "LG HBS-730", + "NG-BT07" +}; +#else +u8 bd_name_filt[20][30] = { + "JBL Flip 4", + "JBL GO", + "JBL Go 4", + "D Quad BT", + "Peltor WS5", + "Newmine M18", + "EDIFIER K歌精灵Q3C", + "MPBT-H03", + "JBL PartyBox Encore", + "KLIM Lynx", + "AirPods", + "AirPods Pro", + "AirPods Pro -Find My", + "ATH-CK150BT", + "YDBEP-560", + "UGREEN HiTune T6", + "H3", + "NDZ-03-GA", + "SOAIY SK2", + + // "JLab JBuds Lux ANC", +}; +#endif + +u8 bd_spp_name_filt[20][30] = { + "AC69_BT_SDK", +}; + +extern const char *bt_get_emitter_connect_name(); +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射搜索通过名字过滤 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 search_bd_name_filt(char *data, u8 len, u32 dev_class, char rssi) +{ + char bd_name[64] = {0}; + u8 i; + char *targe_name = NULL; + char char_a = 0, char_b = 0; + + if ((len > (sizeof(bd_name))) || (len == 0)) { + //printf("bd_name_len error:%d\n", len); + return FALSE; + } + + memset(bd_name, 0, sizeof(bd_name)); + memcpy(bd_name, data, len); + r_printf("name:%s,len:%d,class %x ,rssi %d\n", bd_name, len, dev_class, rssi); +#if SEARCH_NAME_DEBUG + extern char *get_edr_name(void); + printf("tar name:%s,len:%d\n", get_edr_name(), strlen(get_edr_name())); + targe_name = (char *)get_edr_name(); +#if 1 +//不区分大小写 + for (i = 0; i < len; i++) { + char_a = bd_name[i]; + char_b = targe_name[i]; + if ('A' <= char_a && char_a <= 'Z') { + char_a += 32; //转换成小写 + } + if ('A' <= char_b && char_b <= 'Z') { + char_b += 32; //转换成小写 + } + //printf("{%d-%d}",char_a,char_b); + if (char_a != char_b) { + return FALSE; + } + } + log_info("\n*****find dev ok******\n"); + return TRUE; +#else +//区分大小写 + if (memcmp(data, bt_get_emitter_connect_name(), len) == 0) { + log_info("\n*****find dev ok******\n"); + return TRUE; + } + return FALSE; +#endif + +#else + if (search_spp_device) { + for (i = 0; i < (sizeof(bd_spp_name_filt) / sizeof(bd_spp_name_filt[0])); i++) { + if (memcmp(data, bd_spp_name_filt[i], len) == 0) { + puts("\n*****find dev ok******\n"); + return TRUE; + } + } + } else { + for (i = 0; i < (sizeof(bd_name_filt) / sizeof(bd_name_filt[0])); i++) { + if (memcmp(data, bd_name_filt[i], len) == 0) { + puts("\n*****find dev ok******\n"); + return TRUE; + } + } + } + return FALSE; +#endif + +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射搜索结果回调处理 + @param name : 设备名字 + name_len: 设备名字长度 + addr: 设备地址 + dev_class: 设备类型 + rssi: 设备信号强度 + @return 无 + @note + 蓝牙设备搜索结果,可以做名字/地址过滤,也可以保存搜到的所有设备 + 在选择一个进行连接,获取其他你想要的操作。 + 返回TRUE,表示搜到指定的想要的设备,搜索结束,直接连接当前设备 + 返回FALSE,则继续搜索,直到搜索完成或者超时 +*/ +/*----------------------------------------------------------------------------*/ +u8 emitter_search_result(char *name, u8 name_len, u8 *addr, u32 dev_class, char rssi) +{ +#if (SEARCH_LIMITED_MODE == SEARCH_BD_NAME_LIMITED) + g_printf("--emitter_search_result--\n"); + g_printf("---name:%s,len:%d,class %x ,rssi %d\n", name, name_len, dev_class, rssi); + put_buf(addr,6); + #if 1 + if (name == NULL) { + struct inquiry_noname_remote *remote = malloc(sizeof(struct inquiry_noname_remote)); + remote->match = 0; + remote->class = dev_class; + remote->rssi = rssi; + memcpy(remote->addr, addr, 6); + local_irq_disable(); + list_add_tail(&remote->entry, &inquiry_noname_list); + local_irq_enable(); + if (read_name_start == 0) { + read_name_start = 1; + user_send_cmd_prepare(USER_CTRL_READ_REMOTE_NAME, 6, addr); + } + } + #endif +#endif + /* #if (RCSP_BTMATE_EN) */ + /* rcsp_msg_post(RCSP_MSG_BT_SCAN, 5, dev_class, addr, rssi, name, name_len); */ + /* #endif */ +#if (SMART_BOX_EN) + extern void smartbox_command_send_bt_scan_result(char *name, u8 name_len, u8 * addr, u32 dev_class, char rssi); + smartbox_command_send_bt_scan_result(name, name_len, addr, dev_class, rssi); +#endif + +#if TCFG_SPI_LCD_ENABLE + /* void bt_menu_list_add(u8 * name, u8 * mac, u8 rssi); */ + /* bt_menu_list_add(name, addr, rssi); */ + log_info("name:%s,len:%d,class %x ,rssi %d\n", name, name_len, dev_class, rssi); + return false; +#endif + + +#if (SEARCH_LIMITED_MODE == SEARCH_BD_NAME_LIMITED) + return search_bd_name_filt(name, name_len, dev_class, rssi); +#endif + +#if (SEARCH_LIMITED_MODE == SEARCH_BD_ADDR_LIMITED) + return search_bd_addr_filt(addr); +#endif + +#if (SEARCH_LIMITED_MODE == SEARCH_CUSTOM_LIMITED) + /*以下为搜索结果自定义处理*/ + char bt_name[63] = {0}; + u8 len; + if (name_len == 0) { + log_info("No_eir\n"); + } else { + len = (name_len > 63) ? 63 : name_len; + /* display bd_name */ + memcpy(bt_name, name, len); + log_info("name:%s,len:%d,class %x ,rssi %d\n", bt_name, name_len, dev_class, rssi); + } + + /* display bd_addr */ + log_debug_hexdump(addr, 6); + + /* You can connect the specified bd_addr by below api */ + //user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR,6,addr); + + return FALSE; +#endif + +#if (SEARCH_LIMITED_MODE == SEARCH_NULL_LIMITED) + /*没有指定限制,则搜到什么就连接什么*/ + return TRUE; +#endif +} + +typedef enum { + AVCTP_OPID_VOLUME_UP = 0x41, + AVCTP_OPID_VOLUME_DOWN = 0x42, + AVCTP_OPID_MUTE = 0x43, + AVCTP_OPID_PLAY = 0x44, + AVCTP_OPID_STOP = 0x45, + AVCTP_OPID_PAUSE = 0x46, + AVCTP_OPID_NEXT = 0x4B, + AVCTP_OPID_PREV = 0x4C, +} AVCTP_CMD_TYPE; + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射接收到设备按键消息 + @param cmd:按键命令 + @return 无 + @note + 发射器收到接收器发过来的控制命令处理 + 根据实际需求可以在收到控制命令之后做相应的处理 + 蓝牙库里面定义的是weak函数,直接再定义一个同名可获取信息 +*/ +/*----------------------------------------------------------------------------*/ +void emitter_rx_avctp_opid_deal(u8 cmd, u8 id) +{ + log_debug("avctp_rx_cmd:%x\n", cmd); + switch (cmd) { + case AVCTP_OPID_NEXT: + log_info("AVCTP_OPID_NEXT\n"); + app_task_put_key_msg(KEY_MUSIC_NEXT, 0); + break; + case AVCTP_OPID_PREV: + log_info("AVCTP_OPID_PREV\n"); + app_task_put_key_msg(KEY_MUSIC_PREV, 0); + break; + case AVCTP_OPID_PAUSE: + case AVCTP_OPID_STOP: + log_info("AVCTP_OPID_PAUSE\n"); + /* bt_emitter_pp(0); */ + app_task_put_key_msg(KEY_MUSIC_PP, 0); + break; + case AVCTP_OPID_PLAY: + /* bt_emitter_pp(1); */ + app_task_put_key_msg(KEY_MUSIC_PP, 0); + log_info("AVCTP_OPID_PP\n"); + break; + case AVCTP_OPID_VOLUME_UP: + log_info("AVCTP_OPID_VOLUME_UP\n"); + app_task_put_key_msg(KEY_VOL_UP, 0); + break; + case AVCTP_OPID_VOLUME_DOWN: + log_info("AVCTP_OPID_VOLUME_DOWN\n"); + app_task_put_key_msg(KEY_VOL_DOWN, 0); + break; + default: + break; + } + return ; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射接收设备同步音量 + @param vol:接收到设备同步音量 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void emitter_rx_vol_change(u8 vol) +{ + if (vol < 10) { + user_emitter_cmd_prepare(USER_CTRL_AVCTP_OPID_SEND_VOL, 0, NULL); + } + y_printf("vol_change:%d \n", vol); +} + +typedef struct _EMITTER_INFO { + volatile u8 role; + u8 media_source; + u8 source_record;/*统计当前有多少设备可用*/ + u8 reserve; +} EMITTER_INFO_T; + +EMITTER_INFO_T emitter_info = { + .role = 0/*EMITTER_ROLE_SLAVE*/, +}; + +void emitter_info_init(void) +{ + emitter_info.media_source = 0; + emitter_info.source_record = 0; +} + +void emitter_open(u8 source) +{ + int err; + emitter_info.source_record |= source; + if (emitter_info.media_source == source) { + return; + } + emitter_info.media_source = source; + printf("emitter_open"); + err = __emitter_send_media_toggle(NULL, 1); + if(!err) { + printf("emitter send succeed"); + } else { + printf("emitter send failed"); + } +} + +void emitter_close(u8 source) +{ + if (music_player_get_play_status() == FILE_DEC_STATUS_PLAY) { + music_player_pp(); + } + int err; + printf("emitter_close"); + emitter_info.source_record &= ~source; + if (emitter_info.media_source == source) { + emitter_info.media_source = 0/*EMITTER_SOURCE_NULL*/; + err = __emitter_send_media_toggle(NULL, 0); + if(!err) { + printf("emitter send succeed"); + } else { + printf("emitter send failed"); + } + //emitter_media_source_next(); + } + while (bt_emitter_stu_get()) { + os_time_dly(2); + putchar('K'); + } +} +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射接收设备同步音量 + @param source: 高级音频角色 1:source 0:sink + en:关闭source + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void emitter_media_source(u8 source, u8 en) +{ + int err = 0; + if (en) { + emitter_info.source_record |= source; + emitter_info.media_source = source; + err = __emitter_send_media_toggle(NULL, 1); + if(!err) { + printf("emitter send succeed set 1"); + user_emitter_cmd_prepare(USER_CTRL_AVCTP_OPID_SEND_VOL, 0, NULL); + } else { + printf("emitter send failed set 1"); + } + } else { + emitter_info.source_record &= ~source; + if (emitter_info.media_source == source) { + emitter_info.media_source = 0/*EMITTER_SOURCE_NULL*/; + err = __emitter_send_media_toggle(NULL, 0); + if(!err) { + printf("emitter send succeed set 0"); + } else { + printf("emitter send failed set 0"); + } + } + } + log_info("en : %d current source: %x-%x\n", en,source, emitter_info.source_record); +} +#endif + + +u8 bt_emitter_stu_get(void) +{ + return audio_sbc_enc_is_work();//bt_emitter_on; +} + +u8 bt_emitter_stu_set(u8 *addr, u8 on) +{ + if (bt_user_priv_var.emitter_or_receiver != BT_EMITTER_EN) { + return 0; + } + if (!(get_emitter_curr_channel_state() & A2DP_SRC_CH) && !(get_emitter_curr_channel_state() & A2DP_CH)) { + emitter_media_source(1, 0); + return 0; + } + printf("total con dev:%d ", get_total_connect_dev()); + if (on && (get_total_connect_dev() == 0)) { + on = 0; + } + emitter_media_source(1, on); + return on; +} + +u8 __bt_emitter_pp(u8 pp) +{ + if(!get_bt_init_status() || (!bt_user_priv_var.bt_a2dp_con_flag)) { + return 0; + } + + return bt_emitter_stu_set(NULL, pp); +} + +u8 bt_emitter_pp(u8 pp) +{ + if(!get_bt_init_status() || (!bt_user_priv_var.bt_a2dp_con_flag)) { + return 0; + } + printf("---bt_emitter_pp [%d],cur_profile_channel = 0x%x\n",pp,get_emitter_curr_channel_state()); + if (bt_user_priv_var.emitter_or_receiver != BT_EMITTER_EN) { + return 0; + } + if (get_total_connect_dev() == 0) { + //如果没有连接就启动一下搜索 + bt_search_device(); + return 0; + } + if (!(get_emitter_curr_channel_state() & A2DP_SRC_CH) && !(get_emitter_curr_channel_state() & A2DP_CH)) { + return 0; + } + return bt_emitter_stu_set(NULL, pp); +} + + +u8 bt_emitter_stu_sw(void) +{ + return bt_emitter_pp(!bt_emitter_stu_get()); +} + + + +////////////////////////////////////////////////////////////////////// +// mic +#define ESCO_ADC_BUF_NUM 2 +#define ESCO_ADC_IRQ_POINTS 256 +#define ESCO_ADC_BUFS_SIZE (ESCO_ADC_BUF_NUM * ESCO_ADC_IRQ_POINTS) + +#include "audio_dec.h" +#include "clock_cfg.h" +#include "media/pcm_decoder.h" + +#define BT_EMITTER_PCM_BUF_LEN (3*1024) + +struct bt_emitter_mic_dec_hdl { + struct audio_stream *stream; // 音频流 + struct pcm_decoder pcm_dec; // pcm解码句柄 + struct audio_res_wait wait; // 资源等待句柄 + struct audio_mixer_ch mix_ch; // 叠加句柄 + u32 id; // 唯一标识符,随机值 + u32 start : 1; // 正在解码 + u32 mic_start : 1; + struct audio_adc_output_hdl adc_output; + struct adc_mic_ch mic_ch; + s16 adc_buf[ESCO_ADC_BUFS_SIZE]; //align 4Bytes + u8 pcm_buf[BT_EMITTER_PCM_BUF_LEN]; + cbuffer_t cbuf; + u32 lost; + u32 cbuf_use_max; + u8 skip_cnt; //用来丢掉刚开mic时的前几包异常数据 +}; + +static struct bt_emitter_mic_dec_hdl *bt_emitter_mic_dec = NULL; + +extern struct audio_adc_hdl adc_hdl; + + +static void adc_mic_output_handler(void *priv, s16 *data, int len) +{ + struct bt_emitter_mic_dec_hdl *dec = bt_emitter_mic_dec; + if (!dec || !dec->start) { + return ; + } + if (dec->skip_cnt) { + dec->skip_cnt--; + memset(data, 0, len); + } + + int wlen = cbuf_write(&dec->cbuf, data, len); + if (wlen != len) { + dec->lost++; + } + u32 max = cbuf_get_data_len(&dec->cbuf); + if (dec->cbuf_use_max < max) { + dec->cbuf_use_max = max; + } + audio_decoder_resume(&dec->pcm_dec.decoder); +} + +static int bt_emitter_mic_dec_read(void *hdl, void *data, int len) +{ + struct bt_emitter_mic_dec_hdl *dec = hdl; + return cbuf_read(&dec->cbuf, data, len); +} + +static int bt_emitter_mic_dec_size(void *hdl) +{ + struct bt_emitter_mic_dec_hdl *dec = hdl; + return cbuf_get_data_size(&dec->cbuf); +} +static int bt_emitter_mic_dec_total(void *hdl) +{ + struct bt_emitter_mic_dec_hdl *dec = hdl; + return dec->cbuf.total_len; +} + +static void bt_emitter_mic_dec_relaese() +{ + if (bt_emitter_mic_dec) { + audio_decoder_task_del_wait(&decode_task, &bt_emitter_mic_dec->wait); + clock_remove(AUDIO_CODING_PCM); + local_irq_disable(); + free(bt_emitter_mic_dec); + bt_emitter_mic_dec = NULL; + local_irq_enable(); + } +} + +static void bt_emitter_mic_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ + switch (argv[0]) { + case AUDIO_DEC_EVENT_END: + if (!bt_emitter_mic_dec) { + log_i("bt_emitter_mic_dec handle err "); + break; + } + if (bt_emitter_mic_dec->id != argv[1]) { + log_w("bt_emitter_mic_dec id err : 0x%x, 0x%x \n", bt_emitter_mic_dec->id, argv[1]); + break; + } + bt_emitter_mic_close(); + break; + } +} + +static void bt_emitter_mic_dec_out_stream_resume(void *p) +{ + struct bt_emitter_mic_dec_hdl *dec = p; + audio_decoder_resume(&dec->pcm_dec.decoder); +} + +int bt_emitter_mic_dec_start() +{ + int err; + struct bt_emitter_mic_dec_hdl *dec = bt_emitter_mic_dec; + struct audio_mixer *p_mixer = &mixer; + + if (!bt_emitter_mic_dec) { + return -EINVAL; + } + + err = pcm_decoder_open(&dec->pcm_dec, &decode_task); + if (err) { + goto __err1; + } + + bt_emitter_set_vol(app_var.music_volume); + audio_sbc_enc_reset_buf(1); + + // 打开mic驱动 + audio_adc_mic_open(&dec->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl); + audio_adc_mic_set_sample_rate(&dec->mic_ch, dec->pcm_dec.sample_rate); + audio_adc_mic_set_gain(&dec->mic_ch, app_var.aec_mic_gain); + audio_adc_mic_set_buffs(&dec->mic_ch, dec->adc_buf, + ESCO_ADC_IRQ_POINTS * 2, ESCO_ADC_BUF_NUM); + dec->adc_output.handler = adc_mic_output_handler; + audio_adc_add_output_handler(&adc_hdl, &dec->adc_output); + + cbuf_init(&dec->cbuf, dec->pcm_buf, sizeof(dec->pcm_buf)); + + audio_adc_mic_start(&dec->mic_ch); + dec->mic_start = 1; + + dec->skip_cnt = 30; + + pcm_decoder_set_event_handler(&dec->pcm_dec, bt_emitter_mic_dec_event_handler, dec->id); + pcm_decoder_set_read_data(&dec->pcm_dec, bt_emitter_mic_dec_read, dec); + + // 设置叠加功能 + audio_mixer_ch_open_head(&dec->mix_ch, p_mixer); + struct audio_mixer_ch_sync_info info = {0}; + info.priv = dec; + info.get_total = bt_emitter_mic_dec_total; + info.get_size = bt_emitter_mic_dec_size; + audio_mixer_ch_set_sync(&dec->mix_ch, &info, 1, 1); + + // 数据流串联 + struct audio_stream_entry *entries[8] = {NULL}; + u8 entry_cnt = 0; + entries[entry_cnt++] = &dec->pcm_dec.decoder.entry; + entries[entry_cnt++] = &dec->mix_ch.entry; + dec->stream = audio_stream_open(dec, bt_emitter_mic_dec_out_stream_resume); + audio_stream_add_list(dec->stream, entries, entry_cnt); + + + audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); + + dec->start = 1; + err = audio_decoder_start(&dec->pcm_dec.decoder); + if (err) { + goto __err3; + } + clock_set_cur(); + return 0; +__err3: + dec->start = 0; + if (dec->mic_start) { + audio_adc_mic_close(&dec->mic_ch); + audio_adc_del_output_handler(&adc_hdl, &dec->adc_output); + dec->mic_start = 0; + } + audio_mixer_ch_close(&dec->mix_ch); + if (dec->stream) { + audio_stream_close(dec->stream); + dec->stream = NULL; + } + pcm_decoder_close(&dec->pcm_dec); +__err1: + bt_emitter_mic_dec_relaese(); + return err; +} + +static void __bt_emitter_mic_dec_close(void) +{ + if (bt_emitter_mic_dec && bt_emitter_mic_dec->start) { + bt_emitter_mic_dec->start = 0; + + pcm_decoder_close(&bt_emitter_mic_dec->pcm_dec); + + bt_emitter_mic_dec->mic_start = 0; + audio_adc_mic_close(&bt_emitter_mic_dec->mic_ch); + audio_adc_del_output_handler(&adc_hdl, &bt_emitter_mic_dec->adc_output); + + audio_mixer_ch_close(&bt_emitter_mic_dec->mix_ch); + + if (bt_emitter_mic_dec->stream) { + audio_stream_close(bt_emitter_mic_dec->stream); + bt_emitter_mic_dec->stream = NULL; + } + } +} + +static int bt_emitter_mic_wait_res_handler(struct audio_res_wait *wait, int event) +{ + int err = 0; + log_i("bt_emitter_mic_wait_res_handler, event:%d\n", event); + if (event == AUDIO_RES_GET) { + // 启动解码 + err = bt_emitter_mic_dec_start(); + } else if (event == AUDIO_RES_PUT) { + // 被打断 + __bt_emitter_mic_dec_close(); + } + + return err; +} + +void bt_emitter_mic_close(void) +{ + if (!bt_emitter_mic_dec) { + return; + } + + __bt_emitter_mic_dec_close(); + bt_emitter_mic_dec_relaese(); + clock_set_cur(); + log_i("bt_emitter_mic dec close \n\n "); +} + +int bt_emitter_mic_open(void) +{ + if (bt_user_priv_var.emitter_or_receiver != BT_EMITTER_EN) { + return 0; + } + bt_emitter_mic_close(); + + int err; + struct bt_emitter_mic_dec_hdl *dec; + dec = zalloc(sizeof(*dec)); + if (!dec) { + return -ENOMEM; + } + bt_emitter_mic_dec = dec; + + dec->id = rand32(); + dec->pcm_dec.ch_num = 1; + dec->pcm_dec.output_ch_num = audio_sbc_enc_get_channel_num(); + dec->pcm_dec.sample_rate = audio_sbc_enc_get_rate(); + if (dec->pcm_dec.output_ch_num == 2) { + dec->pcm_dec.output_ch_type = AUDIO_CH_LR; + } else { + dec->pcm_dec.output_ch_type = AUDIO_CH_DIFF; + } + + dec->wait.priority = 2; + dec->wait.preemption = 1; + dec->wait.handler = bt_emitter_mic_wait_res_handler; + clock_add(AUDIO_CODING_PCM); + + err = audio_decoder_task_add_wait(&decode_task, &dec->wait); + return err; +} + + + + + +void audio_sbc_enc_open_exit(void) +{ + if (app_check_curr_task(APP_BT_TASK) == true) { + bt_emitter_mic_open(); + } +} +void audio_sbc_enc_close_enter(void) +{ + bt_emitter_mic_close(); +} +//pin code 轮询功能 +const char pin_code_list[10][4] = { + {'0', '0', '0', '0'}, + {'1', '2', '3', '4'}, + {'8', '8', '8', '8'}, + {'1', '3', '1', '4'}, + {'4', '3', '2', '1'}, + {'1', '1', '1', '1'}, + {'2', '2', '2', '2'}, + {'3', '3', '3', '3'}, + {'5', '6', '7', '8'}, + {'5', '5', '5', '5'} +}; + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射链接pincode 轮询 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +const char *bt_get_emitter_pin_code(u8 flag) +{ + static u8 index_flag = 0; + int pincode_num = sizeof(pin_code_list) / sizeof(pin_code_list[0]); + if (flag == 1) { + //reset index + index_flag = 0; + } else if (flag == 2) { + //查询是否要开始继续回连尝试pin code。 + if (index_flag >= pincode_num) { + //之前已经遍历完了 + return NULL; + } else { + index_flag++; //准备使用下一个 + } + } else { + log_debug("get pin code index %d\n", index_flag); + } + return &pin_code_list[index_flag][0]; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射链接保存远端设备名字 + @param addr:远端设备地址 + name:远端设备名字 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void emitter_save_remote_name(u8 *addr, u8 *name) +{ + struct remote_name remote_n; + u16 id = CFG_REMOTE_DN_00; + + while (1) { + syscfg_read(id, &remote_n, sizeof(struct remote_name)); + if (remote_n.crc == CRC16((u8 *)&remote_n.addr, sizeof(struct remote_name) - 2)) { + if (!memcmp(addr, remote_n.addr, 6)) { + return; + } + } else { + break; + } + id++; + if (id >= 20) { + break; + } + } + memset(&remote_n, 0, sizeof(struct remote_name)); + memcpy(remote_n.addr, addr, 6); + memcpy(remote_n.name, name, strlen(name)); + + remote_n.crc = CRC16((u8 *)&remote_n.addr, sizeof(struct remote_name) - 2); + + syscfg_write(id, &remote_n, sizeof(struct remote_name)); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射通过地址来获取设备名字 + @param addr:远端设备地址 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 *emitter_get_remote_name(u8 *addr) +{ + struct remote_name remote_n; + u16 id = CFG_REMOTE_DN_00; + while (1) { + syscfg_read(id, &remote_n, sizeof(struct remote_name)); + if (remote_n.crc == CRC16((u8 *)&remote_n.addr, sizeof(struct remote_name) - 2)) { + if (!memcmp(addr, remote_n.addr, 6)) { + return &remote_n.name; + } + } else { + break; + } + id++; + if (id >= 20) { + break; + } + } + return NULL; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射通过地址来删除vm的设备名字 + @param addr:远端设备地址 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void emitter_delete_remote_name(u8 *addr) +{ + struct remote_name remote_n; + u16 id = CFG_REMOTE_DN_00; + while (1) { + syscfg_read(id, &remote_n, sizeof(struct remote_name)); + if (remote_n.crc == CRC16((u8 *)&remote_n.addr, sizeof(struct remote_name) - 2)) { + if (!memcmp(addr, remote_n.addr, 6)) { + memset(&remote_n, 0xff, sizeof(struct remote_name)); + syscfg_write(id, &remote_n, sizeof(struct remote_name)); + return; + } + } + id++; + } +} + + +#define BD_ADDR_LEN 6 +typedef uint8_t bd_addr_t[BD_ADDR_LEN]; +static bd_addr_t remote_addr[20]; +extern u8 restore_remote_device_info_opt(bd_addr_t *mac_addr, u8 conn_device_num, u8 id); + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙发射获取vm设备记忆 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +int emitter_get_vm_device() +{ + memset(remote_addr, 0, sizeof(remote_addr)); + u8 flag = restore_remote_device_info_opt(&remote_addr, 20, get_remote_dev_info_index()); + for (u8 i = 0; i < 20; i++) { + line_inf + log_debug_hexdump(remote_addr[i], 6); + } + return flag; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙 开关ag_a2dp + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bredr_ag_a2dp_open_and_close() +{ + if (get_emitter_curr_channel_state() & A2DP_SRC_CH) { + puts("start to disconnect a2dp "); + user_emitter_cmd_prepare(USER_CTRL_DISCONN_A2DP, 0, NULL); + } else { + puts("start to connect a2dp "); + user_emitter_cmd_prepare(USER_CTRL_CONN_A2DP, 0, NULL); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙 开关ag_hfp + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bredr_ag_hfp_open_and_close() +{ + if (get_emitter_curr_channel_state() & HFP_AG_CH) { + puts("start to disconnect HFP "); + user_emitter_cmd_prepare(USER_CTRL_HFP_DISCONNECT, 0, NULL); + } else { + puts("start to connect HFP "); + user_emitter_cmd_prepare(USER_CTRL_HFP_CMD_BEGIN, 0, NULL); + } +} + +int emitter_disconnect_device() +{ + int ret = 0; + line_inf + ret = emitter_get_vm_device(); + os_time_dly(5); + user_emitter_cmd_prepare(USER_CTRL_DISCONNECTION_HCI, 0, NULL);//断开所有连接 + user_emitter_cmd_prepare(USER_CTRL_DEL_ALL_REMOTE_INFO, 0, NULL);//清除配对信息 + os_time_dly(5); + if(get_emitter_curr_channel_state() == 0x00){ + printf("disconnect_ok\n"); + } + + + if(ret) { + ret = delete_last_device_from_vm(); + if(ret) { + printf("delete_last_device_from_vm success\n"); + } + } + return ret; +} + +int emitter_connect_device() +{ + u8 con_mac_addr[6] = {0}; + memcpy(con_mac_addr,remote_addr[0],6); + put_buf(con_mac_addr,6); + user_send_cmd_prepare(USER_CTRL_INQUIRY_CANCEL, 0, NULL); + user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL); + user_send_cmd_prepare(USER_CTRL_CONNECTION_CANCEL, 0, NULL); + os_time_dly(5); + emitter_bt_connect(con_mac_addr); + g_printf("connect mac addr"); +} + +#else + +void emitter_media_source(u8 source, u8 en) +{ + +} +void emitter_or_receiver_switch(u8 flag) +{ +} + +u8 bt_search_status() +{ + return 0; +} + +#endif + + +#endif + diff --git a/apps/soundbox/task_manager/bt/bt_event_fun.c b/apps/soundbox/task_manager/bt/bt_event_fun.c new file mode 100644 index 0000000..fbe4b4c --- /dev/null +++ b/apps/soundbox/task_manager/bt/bt_event_fun.c @@ -0,0 +1,2362 @@ + + +#include "system/includes.h" +#include "media/includes.h" + +#include "app_config.h" +#include "app_task.h" + +#include "btstack/avctp_user.h" +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "btstack/btstack_error.h" +#include "btctrler/btctrler_task.h" +#include "classic/hci_lmp.h" + +#include "bt/bt_tws.h" +#include "bt/bt_ble.h" +#include "bt/bt.h" +#include "bt/vol_sync.h" +#include "bt/bt_emitter.h" +#include "bt_common.h" +#include "aec_user.h" +#include "soundbox.h" + +#include "math.h" +#include "spp_user.h" + + +#include "app_chargestore.h" +#include "app_charge.h" +#include "app_main.h" +#include "app_power_manage.h" +#include "user_cfg.h" + +#include "asm/pwm_led.h" +#include "asm/timer.h" +#include "asm/hwi.h" +#include "cpu.h" + +#include "ui/ui_api.h" +#include "ui_manage.h" +#include "ui/ui_style.h" + +#include "key_event_deal.h" +#include "clock_cfg.h" +#include "gSensor/gSensor_manage.h" +#include "soundcard/soundcard.h" + +#include "audio_dec.h" +#include "tone_player.h" +#include "dac.h" +#include "audio_recorder_mix.h" + +#define LOG_TAG_CONST BT +#define LOG_TAG "[BT]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +#define LOG_DUMP_ENABLE +#define LOG_CLI_ENABLE +#include "debug.h" + +#if TCFG_APP_BT_EN + +#define __this (&app_bt_hdl) + +static int bt_switch_back_timer = 0; +extern BT_USER_PRIV_VAR bt_user_priv_var; +/************************************************************* + 此文件函数主要是蓝牙模式各种状态处理 + + 蓝牙播歌通话各种状态处理 + + 蓝牙协议栈事件处理 +**************************************************************/ + +u8 get_bt_init_status() +{ + return __this->init_ok; +} + +u8 get_bt_back_flag() +{ + return __this->bt_back_flag; +} + +void set_bt_back_flag(u8 flag) +{ + __this->bt_back_flag = flag; +} + + +void clr_tws_local_back_role(void) +{ + __this->tws_local_back_role = 0; +} + + +void bt_reverb_status_change(struct bt_event *bt) +{ +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式切换等待解码停止 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static int bt_switch_back(void *p) +{ + if (!__this->call_flag) { + return 0; + } + + if (bt_switch_back_timer) { + sys_timeout_del(bt_switch_back_timer); + bt_switch_back_timer = 0; + } + + if (bt_must_work()) { + bt_switch_back_timer = sys_timeout_add(NULL, bt_switch_back, 500); + return 0; + } + + if (bt_phone_dec_is_running()) { + bt_switch_back_timer = sys_timeout_add(NULL, bt_switch_back, 500); + return 0; + } + /* __this->call_flag = 0; */ + __this->bt_back_flag = 2; + app_task_switch_back(); + return 0; +} + +u8 get_a2dp_start_flag() +{ + return __this->a2dp_start_flag; +} + + +u8 bt_sco_state(void) +{ + return bt_user_priv_var.phone_call_dec_begin; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙eir信息追加数据 + @param + @return + @note 注释掉add_data_2_eir函数就不追加数据 + 追加数据不可以超150byte +*/ +/*----------------------------------------------------------------------------*/ +u8 const eir_more_data_uuid[] = { + 0x0F, 0x03, 0x00, 0x12, 0x1F, 0x11, 0x2F, + 0x11, 0x0A, 0x11, 0x0C, 0x11, 0x32, 0x11, 0x01, 0x18 +}; + +/* u8 add_data_2_eir(u8 *eir) +{ + u8 len = sizeof(eir_more_data_uuid); + memcpy(eir,eir_more_data_uuid,len); + + return len; +} */ + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙电话本获取回调函数 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void phonebook_packet_handler(u8 type, const u8 *name, const u8 *number, const u8 *date) +{ + static u16 number_cnt = 0; + log_debug("NO.%d:", number_cnt); + number_cnt++; + log_debug("type:%d ", type); + if (type == 0xff) { + number_cnt = 0; + } + if (name) { + log_debug(" NAME:%s ", name); + } + if (number) { + log_debug("number:%s ", number); + } + if (date) { + log_debug("date:%s ", date); + } + /* putchar('\n'); */ +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式led状态更新 + @param + @return status : 蓝牙状态 + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_set_led_status(u8 status) +{ + static u8 bt_status = STATUS_BT_INIT_OK; + + u8 app = app_get_curr_task(); + if (status) { + bt_status = status; + } + if (app == APP_BT_TASK) { //蓝牙模式或者state_machine + pwm_led_mode_set(PWM_LED_ALL_OFF); + ui_update_status(bt_status); + } +} + + +/************************************************************* + 开关可发现可连接的函数接口 +**************************************************************/ +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙可发现可连接使能 + @param enable 1:开启 0:关闭 + @return + @note 函数根据状态开启,开启tws后该函数不起作用 + 1拖2的时候会限制开启 +*/ +/*----------------------------------------------------------------------------*/ +void bt_wait_phone_connect_control(u8 enable) +{ +#if TCFG_USER_TWS_ENABLE + return; +#endif + + if (enable && app_var.goto_poweroff_flag && (__this->exiting)) { + return; + } + + if (enable) { + log_debug("is_1t2_connection:%d \t total_conn_dev:%d\n", is_1t2_connection(), get_total_connect_dev()); + if (is_1t2_connection()) { + /*达到最大连接数,可发现(0)可连接(0)*/ + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL); + } else { + if (get_total_connect_dev() == 1) { + /*支持连接2台,只连接一台的情况下,可发现(0)可连接(1)*/ + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); + } else { + /*可发现(1)可连接(1)*/ + BT_STATE_SET_PAGE_SCAN_ENABLE(); + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_ENABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); + } + } + } else { + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙可发现可连接\回链轮询使能 + @param p 1:开启轮询 0:不开启轮询,只开启可发现可连接 + @return + @note auto_connection_counter:回链设备的总时间 +*/ +/*----------------------------------------------------------------------------*/ +int bt_wait_connect_and_phone_connect_switch(void *p) +{ + int ret = 0; + int timeout = 0; + s32 wait_timeout; + + if (__this->exiting) { + return 0; + } + + log_debug("connect_switch: %d, %d\n", (int)p, bt_user_priv_var.auto_connection_counter); + + if (bt_user_priv_var.auto_connection_timer) { + sys_timeout_del(bt_user_priv_var.auto_connection_timer); + bt_user_priv_var.auto_connection_timer = 0; + } + + if (bt_user_priv_var.auto_connection_counter <= 0) { + bt_user_priv_var.auto_connection_timer = 0; + bt_user_priv_var.auto_connection_counter = 0; + + + BT_STATE_CANCEL_PAGE_SCAN(); + + user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL); + if (get_current_poweron_memory_search_index(NULL)) { + bt_init_ok_search_index(); + return bt_wait_connect_and_phone_connect_switch(0); + } else { + bt_wait_phone_connect_control(1); + return 0; + } + } + /* log_info(">>>phone_connect_switch=%d\n",bt_user_priv_var.auto_connection_counter ); */ + if ((int)p == 0) { //// 根据地址回链 + if (bt_user_priv_var.auto_connection_counter) { + timeout = 6000; ////设置回链6s + bt_wait_phone_connect_control(0); + user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR, 6, bt_user_priv_var.auto_connection_addr); + ret = 1; + bt_user_priv_var.auto_connection_counter -= timeout ; + } + } else { + timeout = 2000; ////设置开始被发现被连接2s + user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL); + bt_wait_phone_connect_control(1); + } + /* if (bt_user_priv_var.auto_connection_counter) { */ + /* bt_user_priv_var.auto_connection_counter -= timeout ; */ + /* #<{(| log_info("do=%d\n", bt_user_priv_var.auto_connection_counter); |)}># */ + /* } */ + bt_user_priv_var.auto_connection_timer = sys_timeout_add((void *)(!(int)p), + bt_wait_connect_and_phone_connect_switch, timeout); + + return ret; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙关闭可发现可连接 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_close_page_scan(void *p) +{ + /* log_info(">>>%s\n", __func__); */ + bt_wait_phone_connect_control(0); + sys_timer_del(app_var.auto_stop_page_scan_timer); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙通话时候设置不让系统进入idle状态,不让系统进powerdown + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static u8 check_phone_income_idle(void) +{ + if (bt_user_priv_var.phone_ring_flag) { + return 0; + } + return 1; +} +REGISTER_LP_TARGET(phone_incom_lp_target) = { + .name = "phone_check", + .is_idle = check_phone_income_idle, +}; + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙连接配置,提供app层用户可以输入配对鉴定key + @param key :配对需要输入的数字 + @return + @note 配对需要输入6位数字的时候,按照顺序从左到右一个个输入 +*/ +/*----------------------------------------------------------------------------*/ +void bt_send_keypress(u8 key) +{ + user_send_cmd_prepare(USER_CTRL_KEYPRESS, 1, &key); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙连接配置,提供app层用户可以输入确定或者否定 + @param en 0:否定 1:确定 + @return + @note 在连接过程中类似手机弹出 确定和否定 按键,可以供用户界面设置 +*/ +/*----------------------------------------------------------------------------*/ +void bt_send_pair(u8 en) +{ + user_send_cmd_prepare(USER_CTRL_PAIR, 1, &en); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙获取vm连接记录信息 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_init_ok_search_index(void) +{ + if (!bt_user_priv_var.auto_connection_counter && get_current_poweron_memory_search_index(bt_user_priv_var.auto_connection_addr)) { + /* log_info("bt_wait_connect_and_phone_connect_switch\n"); */ + clear_current_poweron_memory_search_index(1); + bt_user_priv_var.auto_connection_counter = POWERON_AUTO_CONN_TIME * 1000; //8000ms + BT_STATE_GET_CONNECT_MAC_ADDR(); + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙获取样机当前电量 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int bt_get_battery_value() +{ + //取消默认蓝牙定时发送电量给手机,需要更新电量给手机使用USER_CTRL_HFP_CMD_UPDATE_BATTARY命令 + /*电量协议的是0-9个等级,请比例换算*/ + return get_cur_battery_level(); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙spp 协议数据 回调 + @param packet_type:数据类型 + ch : + packet :数据缓存 + size :数据长度 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void spp_data_handler(u8 packet_type, u16 ch, u8 *packet, u16 size) +{ + switch (packet_type) { + case 1: + log_debug("spp connect\n"); + break; + case 2: + log_debug("spp disconnect\n"); + break; + case 7: + //log_info("spp_rx:"); + //put_buf(packet,size); +#if AEC_DEBUG_ONLINE + aec_debug_online(packet, size); +#endif + break; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙音乐同步,设置音量 + @param volume : 设置音量 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_set_music_device_volume(int volume) +{ +#if (SMART_BOX_EN) + extern bool smartbox_set_device_volume(int volume); + if (smartbox_set_device_volume(volume)) { + return; + } +#endif + + if (true == app_check_curr_task(APP_BT_TASK)) { + set_music_device_volume(volume); + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙通话音量同步,设置音量 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void phone_sync_vol(void *priv) +{ + log_debug("phone_sync_vol\n"); + bt_user_priv_var.phone_vol = 14; + user_send_cmd_prepare(USER_CTRL_HFP_CALL_SET_VOLUME, 1, &bt_user_priv_var.phone_vol); + user_send_cmd_prepare(USER_CTRL_HFP_CALL_VOLUME_UP, 0, NULL); + bt_user_priv_var.phone_vol = 15; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙获取在连接设备名字回调 + @param status : 1:获取失败 0:获取成功 + addr : 配对设备地址 + name :配对设备名字 + @return + @note 需要连接上设备后发起USER_CTRL_READ_REMOTE_NAME + 命令来 +*/ +/*----------------------------------------------------------------------------*/ +void bt_read_remote_name(u8 status, u8 *addr, u8 *name) +{ + if (status) { + log_debug("remote_name fail \n"); + } else { + log_debug("remote_name : %s \n", name); + } + + log_debug_hexdump(addr, 6); + +#if TCFG_USER_EMITTER_ENABLE + emitter_search_noname(status, addr, name); +#endif +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙歌词信息获取回调 + @param + @return + @note + const u8 more_avctp_cmd_support = 1;置上1 + 需要在void bredr_handle_register()注册回调函数 + 要动态获取播放时间的,可以发送USER_CTRL_AVCTP_OPID_GET_PLAY_TIME命令就可以了 + 要半秒或者1秒获取就做个定时发这个命令 +*/ +/*----------------------------------------------------------------------------*/ +void user_get_bt_music_info(u8 type, u32 time, u8 *info, u16 len) +{ + //profile define type: 1-title 2-artist name 3-album names 4-track number 5-total number of tracks 6-genre 7-playing time + //JL define 0x10-total time , 0x11 current play position + u8 min, sec; + //printf("type %d\n", type ); + if ((info != NULL) && (len != 0)) { + log_debug(" %s \n", info); + } + if (time != 0) { + min = time / 1000 / 60; + sec = time / 1000 - (min * 60); + log_debug(" time %d %d\n ", min, sec); + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙通话开始丢包数 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +#if ESCO_DUMP_PACKET_ADJUST +u8 get_esco_packet_dump(void) +{ + //log_info("esco_dump_packet:%d\n", esco_dump_packet); + return __this->esco_dump_packet; +} +#endif + + + + + + +/************************************************************* + 蓝牙丢高级音频数据 +**************************************************************/ +static u32 bt_timer = 0; +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙丢音频数据包 + @param + @return + @note 如果在播放提示音等打断高级音频解码的话,导致蓝牙底层数据满了, + 太久没有接收手机数据会导致手机断开链接 +*/ +/*----------------------------------------------------------------------------*/ +static void bt_a2dp_drop_frame(void *p) +{ + int len; + u8 *frame; + /* putchar('@'); */ + +#if TCFG_DEC2TWS_ENABLE + if (tone_get_status() || localtws_dec_is_open()) { +#else + if (tone_get_status()) { +#endif + bt_timer = sys_timeout_add(NULL, bt_a2dp_drop_frame, 100); + __a2dp_drop_frame(NULL); + } else { + local_irq_disable(); + bt_timer = 0; + local_irq_enable(); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙启动音频数据包 + @param + @return + @note 如果在播放提示音等打断高级音频解码的话,导致蓝牙底层数据满了, + 太久没有接收手机数据会导致手机断开链接 +*/ +/*----------------------------------------------------------------------------*/ +void bt_drop_a2dp_frame_start(void) +{ + log_debug("bt_drop_frame_start %d\n", bt_timer); + local_irq_disable(); + if (bt_timer == 0) { + bt_timer = sys_timeout_add(NULL, bt_a2dp_drop_frame, 100); + } + local_irq_enable(); + +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙停止音频数据包 + @param + @return + @note 如果在播放提示音等打断高级音频解码的话,导致蓝牙底层数据满了, + 太久没有接收手机数据会导致手机断开链接 +*/ +/*----------------------------------------------------------------------------*/ +void bt_drop_a2dp_frame_stop() +{ + log_debug("bt_drop_frame_stop %d\n", bt_timer); + local_irq_disable(); + if (bt_timer) { + sys_timeout_del(bt_timer); + bt_timer = 0; + } + extern void bt_stop_a2dp_slience_detect(); + bt_stop_a2dp_slience_detect(); + local_irq_enable(); +} + + + + + +/************************************************************* + 蓝牙模式app层检测空闲是否可以进入sniff模式 +**************************************************************/ +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙退出sniff模式 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_check_exit_sniff() +{ + sys_timeout_del(__this->exit_sniff_timer); + __this->exit_sniff_timer = 0; + +#if TCFG_USER_TWS_ENABLE + if (tws_api_get_role() == TWS_ROLE_SLAVE) { + return; + } +#endif + user_send_cmd_prepare(USER_CTRL_ALL_SNIFF_EXIT, 0, NULL); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙检测是否空闲,空闲就发起sniff + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_check_enter_sniff() +{ + struct sniff_ctrl_config_t sniff_ctrl_config; + u8 addr[12]; + u8 conn_cnt = 0; + u8 i = 0; + /*putchar('H');*/ + conn_cnt = bt_api_enter_sniff_status_check(SNIFF_CNT_TIME, addr); + + ASSERT(conn_cnt <= 2); + + for (i = 0; i < conn_cnt; i++) { + log_debug("-----USER SEND SNIFF IN %d %d\n", i, conn_cnt); + sniff_ctrl_config.sniff_max_interval = SNIFF_MAX_INTERVALSLOT; + sniff_ctrl_config.sniff_mix_interval = SNIFF_MIN_INTERVALSLOT; + sniff_ctrl_config.sniff_attemp = SNIFF_ATTEMPT_SLOT; + sniff_ctrl_config.sniff_timeout = SNIFF_TIMEOUT_SLOT; + memcpy(sniff_ctrl_config.sniff_addr, addr + i * 6, 6); +#if TCFG_USER_TWS_ENABLE + if (tws_api_get_role() == TWS_ROLE_SLAVE) { + return; + } +#endif + user_send_cmd_prepare(USER_CTRL_SNIFF_IN, sizeof(struct sniff_ctrl_config_t), (u8 *)&sniff_ctrl_config); + } +} + +bool bt_is_sniff_close(void) +{ +#if TCFG_BT_SNIFF_ENABLE + return (bt_user_priv_var.sniff_timer == 0); +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙启动 检测空闲 发起sniff + @param enable : 1 启动 0:关闭 + addr:要和对应设备进入sniff 状态的地址 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void sys_auto_sniff_controle(u8 enable, u8 *addr) +{ +#if (TCFG_BT_SNIFF_ENABLE == 0) + return; +#endif + + if (addr) { + if (bt_api_conn_mode_check(enable, addr) == 0) { + log_debug("sniff ctr not change\n"); + return; + } + } + + if (enable) { + if (get_total_connect_dev() == 0) { + return; + } + + if (addr) { + log_debug("sniff cmd timer init\n"); + user_cmd_timer_init(); + } + + if (bt_user_priv_var.sniff_timer == 0) { + log_debug("check_sniff_enable\n"); + bt_user_priv_var.sniff_timer = sys_timer_add(NULL, bt_check_enter_sniff, 1000); + } + } else { + if (get_total_connect_dev() > 0) { + return; + } + if (addr) { + log_debug("sniff cmd timer remove\n"); + remove_user_cmd_timer(); + } + + if (bt_user_priv_var.sniff_timer) { + log_info("check_sniff_disable\n"); + sys_timeout_del(bt_user_priv_var.sniff_timer); + bt_user_priv_var.sniff_timer = 0; + + if (__this->exit_sniff_timer == 0) { + /* exit_sniff_timer = sys_timer_add(NULL, bt_check_exit_sniff, 5000); */ + } + } + } +} + +void soft_poweroff_mode(u8 mode) +{ + __this->force_poweroff = mode; +} + +/************************************************************* + 蓝牙模式关机处理 + **************************************************************/ +/*----------------------------------------------------------------------------*/ +/**@brief 软关机蓝牙模式处理 + @param + @return + @note 断开蓝牙链接\关闭所有状态 +*/ +/*----------------------------------------------------------------------------*/ +void sys_enter_soft_poweroff(void *priv) +{ + int detach_phone = 1; + struct sys_event clear_key_event = {.type = SYS_KEY_EVENT, .arg = "key"}; + + log_info("%s", __func__); + + bt_user_priv_var.emitter_or_receiver = 0; + if (app_var.goto_poweroff_flag) { + return; + } + +#if TCFG_BLUETOOTH_BACK_MODE + if (__this->exit_flag == 1 && __this->init_ok == 1) { + __this->cmd_flag = 1; + app_task_switch_to(APP_BT_TASK); + } +#endif + + ui_update_status(STATUS_POWEROFF); + + app_var.goto_poweroff_flag = 1; + app_var.goto_poweroff_cnt = 0; + + +#if 0 + sys_key_event_disable(); + sys_event_clear(&clear_key_event); + sys_auto_shut_down_disable(); + sys_auto_sniff_controle(0, NULL); + + BT_STATE_ENTER_SOFT_POWEROFF(); + + +#if TCFG_CHARGESTORE_ENABLE + if (chargestore_get_earphone_online() != 2) +#else + if (1) +#endif + { +#if TCFG_USER_TWS_ENABLE + detach_phone = bt_tws_poweroff(); +#endif + } + + /* log_debug("detach_phone = %d\n", detach_phone); */ + + if (detach_phone) { + user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL); + } +#endif + + if (app_var.wait_exit_timer == 0) { + app_var.wait_exit_timer = sys_timer_add(priv, wait_exit_btstack_flag, 50); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 自动关机开关 + @param + @return + @note 开启后,如果一段时间内没有连接等操作就会进入关机 +*/ +/*----------------------------------------------------------------------------*/ +void sys_auto_shut_down_enable(void) +{ + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_TRANS_DATA) + extern u16 bt_ble_is_connected(void); + if (bt_ble_is_connected()) { + return; + } +#endif + + +#if TCFG_AUTO_SHUT_DOWN_TIME + log_debug("sys_auto_shut_down_enable\n"); + + if (app_var.auto_shut_down_timer == 0) { + + u8 app = app_get_curr_task(); + if (app == APP_BT_TASK) { + app_var.auto_shut_down_timer = sys_timeout_add(NULL, sys_enter_soft_poweroff, (app_var.auto_off_time * 1000)); + } else { + /* log_debug("cur_app:%s, return", app->name); */ + } + } else {//在切换到蓝牙任务APP_STA_START中,current_app为空 + sys_auto_shut_down_disable(); + app_var.auto_shut_down_timer = sys_timeout_add(NULL, sys_enter_soft_poweroff, (app_var.auto_off_time * 1000)); + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭自动关机 + @param + @return + @note 链接上设备后会调用关闭 +*/ +/*----------------------------------------------------------------------------*/ +void sys_auto_shut_down_disable(void) +{ +#if TCFG_AUTO_SHUT_DOWN_TIME + log_debug("sys_auto_shut_down_disable\n"); + if (app_var.auto_shut_down_timer) { + sys_timeout_del(app_var.auto_shut_down_timer); + app_var.auto_shut_down_timer = 0; + } +#endif +} + + +/************************************************************* + 蓝牙模式提示音播放 +**************************************************************/ +static const u32 num0_9[] = { + (u32)TONE_NUM_0, + (u32)TONE_NUM_1, + (u32)TONE_NUM_2, + (u32)TONE_NUM_3, + (u32)TONE_NUM_4, + (u32)TONE_NUM_5, + (u32)TONE_NUM_6, + (u32)TONE_NUM_7, + (u32)TONE_NUM_8, + (u32)TONE_NUM_9, +} ; + + + +static void number_to_play_list(char *num, u32 *lst) +{ + u8 i = 0; + + if (num) { + for (; i < strlen(num); i++) { + lst[i] = num0_9[num[i] - '0'] ; + } + } + lst[i++] = (u32)TONE_REPEAT_BEGIN(-1); + lst[i++] = (u32)TONE_RING; + lst[i++] = (u32)TONE_REPEAT_END(); + lst[i++] = (u32)NULL; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙来电报号 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void phone_num_play_timer(void *priv) +{ + char *len_lst[34]; + + if (get_call_status() == BT_CALL_HANGUP) { + /* log_debug("hangup,--phone num play return\n"); */ + return; + } + log_info("%s\n", __FUNCTION__); + + if (bt_user_priv_var.phone_num_flag) { + tone_play_stop(); + number_to_play_list((char *)(bt_user_priv_var.income_phone_num), len_lst); + tone_file_list_play(len_lst, 1); + } else { + /*电话号码还没有获取到,定时查询*/ + bt_user_priv_var.phone_timer_id = sys_timeout_add(NULL, phone_num_play_timer, 200); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙来电报号启动 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void phone_num_play_start(void) +{ + /* check if support inband ringtone */ + if (!bt_user_priv_var.inband_ringtone) { + bt_user_priv_var.phone_num_flag = 0; + bt_user_priv_var.phone_timer_id = sys_timeout_add(NULL, phone_num_play_timer, 500); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙来电铃声播放 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 phone_ring_play_start(void) +{ + char *len_lst[34]; + + if (get_call_status() == BT_CALL_HANGUP) { + /* log_debug("hangup,--phone ring play return\n"); */ + return 0; + } + log_info("%s\n", __FUNCTION__); + /* check if support inband ringtone */ + if (!bt_user_priv_var.inband_ringtone) { + tone_play_stop(); + number_to_play_list(NULL, len_lst); + tone_file_list_play(len_lst, 1); + return 1; + } + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙提示音播放统一接口 + @param index:提示音序号 + preemption:是否打断/1:打断、0:不打断 + priv : + @return 播放是否成功 + @note + 蓝牙模式播放提示音接口,防止提示音播放时候打开 a2dp 解码不及时, + 导致底层 a2dp buff 阻塞,手机超时断开蓝牙. +*/ +/*----------------------------------------------------------------------------*/ +int bt_tone_play_index(u8 index, u8 preemption, void *priv) +{ + bt_drop_a2dp_frame_start(); + return tone_play_with_callback_by_name(tone_table[index], preemption, NULL, priv); +} + +__attribute__((weak)) +int earphone_a2dp_codec_get_low_latency_mode() +{ + return 0; +} + +__attribute__((weak)) +void earphone_a2dp_codec_set_low_latency_mode(int enable) +{ + return; +} + +int bt_get_low_latency_mode() +{ + return earphone_a2dp_codec_get_low_latency_mode(); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 低电处理 + @param + @return + @note 电量高的做主机,电量低的做从机 +*/ +/*----------------------------------------------------------------------------*/ +void bt_set_low_latency_mode(int enable) +{ +#if TCFG_USER_TWS_ENABLE + if (tws_api_get_role() == TWS_ROLE_MASTER) { + if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) { + if (enable) { + bt_tws_api_push_cmd(SYNC_CMD_LOW_LATENCY_ENABLE, 300); + } else { + bt_tws_api_push_cmd(SYNC_CMD_LOW_LATENCY_DISABLE, 300); + } + } else { + earphone_a2dp_codec_set_low_latency_mode(enable); + } + } +#else + earphone_a2dp_codec_set_low_latency_mode(enable); +#endif +} + + + +/************************************************************* + 蓝牙模式协议栈状态事件处理 +**************************************************************/ +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 事件过滤 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 bt_status_event_filter(struct bt_event *bt) +{ + if (__this->init_ok && app_var.goto_poweroff_flag) { + if (bt->event != BT_STATUS_A2DP_MEDIA_STOP) { + return false; + } + } + +#if (RECORDER_MIX_EN) + recorder_mix_bt_status_event(bt); +#endif//RECORDER_MIX_EN + +#if SOUNDCARD_ENABLE + soundcard_bt_connect_status_event(bt); +#endif//SOUNDCARD_ENABLE + + UI_MSG_POST("bt_status:event=%4", bt->event); + return true; +} + +void bt_status_init_ok(struct bt_event *bt) +{ + __this->init_ok = 1; + if (__this->init_ok_time == 0) { + __this->init_ok_time = timer_get_ms(); + __this->auto_exit_limit_time = POWERON_AUTO_CONN_TIME * 1000; + /* tone_dec_wait_stop(3000); */ + } +#if TCFG_USER_BLE_ENABLE + if (BT_MODE_IS(BT_BQB)) { + ble_bqb_test_thread_init(); + } else { + bt_ble_init(); + } +#endif + +#if TCFG_USER_EMITTER_ENABLE + ////发射器设置回调等 + void bt_emitter_init() ; + bt_emitter_init(); + extern u8 emitter_search_result(char *name, u8 name_len, u8 * addr, u32 dev_class, char rssi); + inquiry_result_handle_register(emitter_search_result); + extern void emitter_or_receiver_switch(u8 flag); + emitter_or_receiver_switch(BT_EMITTER_EN); + return; +#endif + + + + bt_init_ok_search_index(); + bt_set_led_status(STATUS_BT_INIT_OK); +#if TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE + chargestore_set_bt_init_ok(1); +#endif + + +#if ((CONFIG_BT_MODE == BT_BQB)||(CONFIG_BT_MODE == BT_PER)) + bt_wait_phone_connect_control(1); +#else +#if TCFG_USER_TWS_ENABLE + bt_tws_poweron(); +#else + +#if BT_EMITTER_TEST_ENABLE + +#else + bt_wait_connect_and_phone_connect_switch(0); +#endif + +#endif +#endif +} + +void bt_status_init_ok_background(struct bt_event *bt) +{ + __this->init_ok = 1; + +#if TCFG_USER_BLE_ENABLE + if (BT_MODE_IS(BT_BQB)) { + ble_bqb_test_thread_init(); + } else { + bt_ble_init(); + } +#endif + +#if TCFG_USER_EMITTER_ENABLE + ////发射器设置回调等 + void bt_emitter_init() ; + bt_emitter_init(); + extern u8 emitter_search_result(char *name, u8 name_len, u8 * addr, u32 dev_class, char rssi); + inquiry_result_handle_register(emitter_search_result); + + extern void emitter_or_receiver_switch(u8 flag); + emitter_or_receiver_switch(BT_EMITTER_EN); + + /* bt_user_priv_var.emitter_or_receiver = BT_EMITTER_EN; */ + return; +#endif +} +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 设备连接上状态 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_connect(struct bt_event *bt) +{ + + sys_auto_sniff_controle(1, NULL); + sys_auto_shut_down_disable(); +#if SMART_BOX_EN + memcpy(__this->last_connecting_addr, bt->args, 6); + extern void smartbox_update_bt_emitter_connect_state(u8 state, u8 * addr); + smartbox_update_bt_emitter_connect_state(1, __this->last_connecting_addr); +#endif + + + + /* UI_MSG_POST("bt_status:n=%4", 1); */ + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) + { + u8 connet_type; + if (get_auto_connect_state(bt->args)) { + connet_type = ICON_TYPE_RECONNECT; + } else { + connet_type = ICON_TYPE_CONNECTED; + } + +#if TCFG_USER_TWS_ENABLE + if (tws_api_get_role() == TWS_ROLE_MASTER) { + bt_ble_icon_open(connet_type); + } else { + //maybe slave already open + bt_ble_icon_close(0); + } + +#else + bt_ble_icon_open(connet_type); +#endif + } +#endif + + +#if (TCFG_BD_NUM == 2) + if (get_current_poweron_memory_search_index(NULL) == 0) { +#if USER_SUPPORT_DUAL_A2DP_SOURCE + extern void bt_emitter_dev_search(); + bt_emitter_dev_search(); +#else + bt_wait_phone_connect_control(1); +#endif + + } +#endif + +#if TCFG_USER_TWS_ENABLE + if (!get_bt_tws_connect_status()) { //如果对耳还未连接就连上手机,要切换闪灯状态 + bt_set_led_status(STATUS_BT_CONN); + } + + if (bt_tws_phone_connected()) { + return ; + } +#else + bt_set_led_status(STATUS_BT_CONN); //单台在此处设置连接状态,对耳的连接状态需要同步,在bt_tws.c中去设置 +#if (TCFG_AUTO_STOP_PAGE_SCAN_TIME && TCFG_BD_NUM == 2) + if (get_total_connect_dev() == 1) { //当前有一台连接上了 + if (app_var.auto_stop_page_scan_timer == 0) { + app_var.auto_stop_page_scan_timer = sys_timeout_add(NULL, bt_close_page_scan, (TCFG_AUTO_STOP_PAGE_SCAN_TIME * 1000)); //2 + } + } else { + if (app_var.auto_stop_page_scan_timer) { + sys_timeout_del(app_var.auto_stop_page_scan_timer); + app_var.auto_stop_page_scan_timer = 0; + } + } +#endif //endif AUTO_STOP_PAGE_SCAN_TIME +#endif + /* log_debug("tone status:%d\n", tone_get_status()); */ + if (get_call_status() == BT_CALL_HANGUP) { + bt_tone_play_index(IDEX_TONE_BT_CONN, 1, NULL); + } +} + +void bt_status_connect_background(struct bt_event *bt) +{ + sys_auto_sniff_controle(1, NULL); + sys_auto_shut_down_disable(); + +#if SMART_BOX_EN + memcpy(__this->last_connecting_addr, bt->args, 6); + extern void smartbox_update_bt_emitter_connect_state(u8 state, u8 * addr); + smartbox_update_bt_emitter_connect_state(1, __this->last_connecting_addr); +#endif + + static u8 mac_addr[6]; + memcpy(mac_addr, bt->args, 6); + UI_MSG_POST("bt_connect_info:mac=%4", mac_addr); + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) + { + u8 connet_type; + if (get_auto_connect_state(bt->args)) { + connet_type = ICON_TYPE_RECONNECT; + } else { + connet_type = ICON_TYPE_CONNECTED; + } + +#if TCFG_USER_TWS_ENABLE + if (tws_api_get_role() == TWS_ROLE_MASTER) { + bt_ble_icon_open(connet_type); + } else { + //maybe slave already open + bt_ble_icon_close(0); + } + +#else + bt_ble_icon_open(connet_type); +#endif + } +#endif + + +#if (TCFG_BD_NUM == 2) + if ((get_total_connect_dev() == 1) && bt->value) { //当前有一台连接上了,并且连接的是sink设备 + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); + } + /* if (get_current_poweron_memory_search_index(NULL) == 0) { */ + /* bt_wait_phone_connect_control(1); */ + /* } */ +#endif + +#if TCFG_USER_TWS_ENABLE + if (!get_bt_tws_connect_status()) { //如果对耳还未连接就连上手机,要切换闪灯状态 + bt_set_led_status(STATUS_BT_CONN); + } + + if (bt_tws_phone_connected()) { + return ; + } +#else + bt_set_led_status(STATUS_BT_CONN); //单台在此处设置连接状态,对耳的连接状态需要同步,在bt_tws.c中去设置 +#if (TCFG_AUTO_STOP_PAGE_SCAN_TIME && TCFG_BD_NUM == 2) + if ((get_total_connect_dev() == 1) && bt->value) { //当前有一台连接上了,并且连接的是sink设备 + if (app_var.auto_stop_page_scan_timer == 0) { + app_var.auto_stop_page_scan_timer = sys_timeout_add(NULL, bt_close_page_scan, (TCFG_AUTO_STOP_PAGE_SCAN_TIME * 1000)); //2 + } + } else { + if (app_var.auto_stop_page_scan_timer) { + sys_timeout_del(app_var.auto_stop_page_scan_timer); + app_var.auto_stop_page_scan_timer = 0; + } + } +#endif //endif AUTO_STOP_PAGE_SCAN_TIME +#endif +} +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 设备断开连接 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_disconnect(struct bt_event *bt) +{ + sys_auto_sniff_controle(0, NULL); + __this->call_flag = 0; + /* log_info("BT_STATUS_DISCONNECT\n"); */ +#if (SMART_BOX_EN) + smartbox_update_bt_emitter_connect_state(0, __this->last_connecting_addr); +#endif + /* UI_MSG_POST("bt_status:n=%4", 0); */ +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) +#if USER_SUPPORT_DUAL_A2DP_SOURCE + bt_emitter_stu_set(bt->args, 0); +#else + bt_emitter_stu_set(NULL, 0); +#endif + +#endif + + bt_set_led_status(STATUS_BT_DISCONN); +#if(TCFG_BD_NUM == 2) //对耳在bt_tws同步播放提示音 + if (!app_var.goto_poweroff_flag) { /*关机不播断开提示音*/ + if (!__this->ignore_discon_tone) { + tone_play_by_path(tone_table[IDEX_TONE_BT_DISCONN], 1); + } + } +#else +#if TCFG_USER_TWS_ENABLE + if (!get_bt_tws_connect_status()) +#endif + { + if (!app_var.goto_poweroff_flag) { /*关机不播断开提示音*/ + if (!__this->ignore_discon_tone) { + bt_tone_play_index(IDEX_TONE_BT_DISCONN, 1, NULL); + } + } + } +#endif + +#if TCFG_USER_TWS_ENABLE + STATUS *p_led = get_led_config(); + if (get_bt_tws_connect_status()) { +#if TCFG_CHARGESTORE_ENABLE + chargestore_set_phone_disconnect(); +#endif + if (tws_api_get_role() == TWS_ROLE_MASTER) { + bt_tws_api_push_cmd(SYNC_CMD_LED_PHONE_DISCONN_STATUS, 400); + } + } else { + //断开手机时,如果对耳未连接,要把LED时钟切到RC(因为单台会进SNIFF) + if (!app_var.goto_poweroff_flag) { /*关机时不改UI*/ + pwm_led_clk_set(PWM_LED_CLK_RC32K); + bt_set_led_status(STATUS_BT_DISCONN); + } + } + __this->tws_local_back_role = 0; +#else + if (get_total_connect_dev() == 0) { //已经没有设备连接 + if (!app_var.goto_poweroff_flag) { /*关机时不改UI*/ + bt_set_led_status(STATUS_BT_DISCONN); + } + sys_auto_shut_down_enable(); + } +#endif +#if TCFG_USER_EMITTER_ENABLE + bt_user_priv_var.bt_a2dp_con_flag = 0; +#endif + +} + +void bt_status_disconnect_background(struct bt_event *bt) +{ + sys_auto_sniff_controle(0, NULL); + __this->call_flag = 0; + /* log_info("BT_STATUS_DISCONNECT\n"); */ +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) + if (bt->value) { + emitter_close(1); + } +#endif + +#if TCFG_USER_TWS_ENABLE + if (tws_api_get_role() == TWS_ROLE_MASTER) { + bt_tws_api_push_cmd(SYNC_CMD_LED_PHONE_DISCONN_STATUS, 400); + } + __this->tws_local_back_role = 0; +#endif +} +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 手机来电 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_phone_income(struct bt_event *bt) +{ + __this->esco_dump_packet = ESCO_DUMP_PACKET_CALL; + ui_update_status(STATUS_PHONE_INCOME); + u8 tmp_bd_addr[6]; + memcpy(tmp_bd_addr, bt->args, 6); + if (bt_switch_back_timer) { + sys_timeout_del(bt_switch_back_timer); + bt_switch_back_timer = 0; + } + /* + *(1)1t2有一台通话的时候,另一台如果来电不要提示 + *(2)1t2两台同时来电,现来的题示,后来的不播 + */ + if ((check_esco_state_via_addr(tmp_bd_addr) != BD_ESCO_BUSY_OTHER) && (bt_user_priv_var.phone_ring_flag == 0)) { +#if BT_INBAND_RINGTONE + extern u8 get_device_inband_ringtone_flag(void); + bt_user_priv_var.inband_ringtone = get_device_inband_ringtone_flag(); +#else + bt_user_priv_var.inband_ringtone = 0 ; + lmp_private_esco_suspend_resume(3); +#endif + + bt_user_priv_var.phone_ring_flag = 1; + bt_user_priv_var.phone_income_flag = 1; + +#if TCFG_USER_TWS_ENABLE +#if BT_SYNC_PHONE_RING + if (!bt_tws_sync_phone_num(NULL)) +#else + if (tws_api_get_role() == TWS_ROLE_MASTER) +#endif +#endif + { +#if BT_PHONE_NUMBER + phone_num_play_start(); +#else + phone_ring_play_start(); +#endif + + } + user_send_cmd_prepare(USER_CTRL_HFP_CALL_CURRENT, 0, NULL); //发命令获取电话号码 + } else { + /* log_debug("SCO busy now:%d,%d\n", check_esco_state_via_addr(tmp_bd_addr), bt_user_priv_var.phone_ring_flag); */ + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 手机打出电话 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_phone_out(struct bt_event *bt) +{ + if (bt_switch_back_timer) { + sys_timeout_del(bt_switch_back_timer); + bt_switch_back_timer = 0; + } + lmp_private_esco_suspend_resume(4); + __this->esco_dump_packet = ESCO_DUMP_PACKET_CALL; + ui_update_status(STATUS_PHONE_OUT); + bt_user_priv_var.phone_income_flag = 0; + user_send_cmd_prepare(USER_CTRL_HFP_CALL_CURRENT, 0, NULL); //发命令获取电话号码 + #if BT_EMITTER_TEST_ENABLE + user_emitter_cmd_prepare(USER_CTRL_HFP_CALL_ANSWER, 0, NULL); + #endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 手机接通电话 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_phone_active(struct bt_event *bt) +{ + ui_update_status(STATUS_PHONE_ACTIV); + if (bt_user_priv_var.phone_call_dec_begin) { + /* log_debug("call_active,dump_packet clear\n"); */ + __this->esco_dump_packet = ESCO_DUMP_PACKET_DEFAULT; + } + if (bt_user_priv_var.phone_ring_flag) { + bt_user_priv_var.phone_ring_flag = 0; + tone_play_stop(); + if (bt_user_priv_var.phone_timer_id) { + sys_timeout_del(bt_user_priv_var.phone_timer_id); + bt_user_priv_var.phone_timer_id = 0; + } + } + lmp_private_esco_suspend_resume(4); + bt_user_priv_var.phone_income_flag = 0; + bt_user_priv_var.phone_num_flag = 0; + bt_user_priv_var.phone_con_sync_num_ring = 0; + bt_user_priv_var.phone_con_sync_ring = 0; + bt_user_priv_var.phone_vol = 15; + /* log_debug("phone_active:%d\n", app_var.call_volume); */ +#ifdef PHONE_CALL_DEFAULT_MAX_VOL + bt_user_priv_var.set_call_vol_flag |= BIT(1); + if ((BIT(1) | BIT(2)) == bt_user_priv_var.set_call_vol_flag) { + app_audio_set_volume(APP_AUDIO_STATE_CALL, 15, 1); + sys_timeout_add(NULL, phone_sync_vol, 1200); + } +#else + app_audio_set_volume(APP_AUDIO_STATE_CALL, app_var.call_volume, 1); +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 手机挂断电话 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_phone_hangup(struct bt_event *bt) +{ + __this->esco_dump_packet = ESCO_DUMP_PACKET_CALL; + /* log_info("phone_handup\n"); */ + if (bt_user_priv_var.phone_ring_flag) { + bt_user_priv_var.phone_ring_flag = 0; + tone_play_stop(); + if (bt_user_priv_var.phone_timer_id) { + sys_timeout_del(bt_user_priv_var.phone_timer_id); + bt_user_priv_var.phone_timer_id = 0; + } + } + lmp_private_esco_suspend_resume(4); + bt_user_priv_var.phone_num_flag = 0; + bt_user_priv_var.phone_con_sync_num_ring = 0; + bt_user_priv_var.phone_con_sync_ring = 0; + __this->call_back_flag &= ~BIT(0); + if ((__this->call_back_flag == 0) && __this->call_flag) { + if (bt_switch_back_timer == 0) { + r_printf("timerout_add:bt_switch_back_timer"); + bt_switch_back_timer = sys_timeout_add(NULL, bt_switch_back, 500); + } + } + if (get_call_status() == BT_CALL_HANGUP) { + //call handup + bt_user_priv_var.set_call_vol_flag = 0; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 手机来电号码 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_phone_number(struct bt_event *bt) +{ + u8 *phone_number = NULL; + phone_number = (u8 *)bt->value; + //put_buf(phone_number, strlen((const char *)phone_number)); + if (bt_user_priv_var.phone_num_flag == 1) { + return ; + } + bt_user_priv_var.income_phone_len = 0; + memset(bt_user_priv_var.income_phone_num, '\0', sizeof(bt_user_priv_var.income_phone_num)); + for (int i = 0; i < strlen((const char *)phone_number); i++) { + if (phone_number[i] >= '0' && phone_number[i] <= '9') { + //过滤,只有数字才能报号 + bt_user_priv_var.income_phone_num[bt_user_priv_var.income_phone_len++] = phone_number[i]; + if (bt_user_priv_var.income_phone_len >= sizeof(bt_user_priv_var.income_phone_num)) { + return; /*buffer 空间不够,后面不要了*/ + } + } + } + if (bt_user_priv_var.income_phone_len > 0) { + bt_user_priv_var.phone_num_flag = 1; + } else { + log_debug("PHONE_NUMBER len err\n"); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 手机来电铃声 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_inband_ringtone(struct bt_event *bt) +{ + +#if BT_INBAND_RINGTONE + bt_user_priv_var.inband_ringtone = bt->value; +#else + bt_user_priv_var.inband_ringtone = 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙停止正在播放的模式提示音 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +#if (TCFG_DEC2TWS_ENABLE) +void bt_mode_stop_other_mode_tone(void) +{ + log_i("bt_mode_stop_other_mode_tone \n"); +#if (TCFG_APP_MUSIC_EN) + tone_play_stop_by_path(tone_table[IDEX_TONE_MUSIC]); + tone_play_stop_by_path(tone_table[IDEX_TONE_SD]); + tone_play_stop_by_path(tone_table[IDEX_TONE_UDISK]); +#endif +#if (TCFG_APP_LINEIN_EN) + tone_play_stop_by_path(tone_table[IDEX_TONE_LINEIN]); +#endif +#if (TCFG_APP_FM_EN) + tone_play_stop_by_path(tone_table[IDEX_TONE_FM]); +#endif +#if (TCFG_APP_PC_EN) + tone_play_stop_by_path(tone_table[IDEX_TONE_PC]); +#endif +#if (TCFG_APP_RTC_EN) + tone_play_stop_by_path(tone_table[IDEX_TONE_RTC]); +#endif +#if (TCFG_APP_RECORD_EN) + tone_play_stop_by_path(tone_table[IDEX_TONE_RECORD]); +#endif +} +#endif + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 手机高级音频开始播放 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_a2dp_media_start(struct bt_event *bt) +{ + + __this->call_flag = 0; + __this->a2dp_start_flag = 1; +#if (TCFG_DEC2TWS_ENABLE) + bt_drop_a2dp_frame_stop(); + a2dp_media_clear_packet_before_seqn(0); + + if (bt_media_is_running()) { + log_debug("is_a2dp_dec_open break\n"); + return ; + } + if (localtws_dec_is_open()) { + // 先发命令再关闭解码,减少tws两边结束的时间差异 + bt_a2dp_drop_frame(NULL); + tws_user_sync_box(TWS_BOX_NOTICE_A2DP_BACK_TO_BT_MODE, 0); + os_time_dly(2); + localtws_dec_close(1); + } + // 停止其他模式提示音 + bt_mode_stop_other_mode_tone(); +#endif + a2dp_dec_open(bt->value); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 手机高级音频停止播放 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_a2dp_media_stop(struct bt_event *bt) +{ + __this->a2dp_start_flag = 0; + bt_drop_a2dp_frame_stop(); + a2dp_dec_close(); + +#if (TCFG_DEC2TWS_ENABLE) + if (is_tws_active_device()) { + return ; + } +#endif +#if TCFG_USER_TWS_ENABLE + if (get_bt_tws_connect_status()) { + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 手机通话链路切换 + @param + @return + @note 手机音频切换、微信等都会有这个状态 +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_sco_change(struct bt_event *bt) +{ + void mem_stats(void); + mem_stats(); + /* log_info(" BT_STATUS_SCO_STATUS_CHANGE len:%d ,type:%d", (bt->value >> 16), (bt->value & 0x0000ffff)); */ + if (bt->value != 0xff) { +#ifdef PHONE_CALL_DEFAULT_MAX_VOL + bt_user_priv_var.set_call_vol_flag |= BIT(2); + if ((BIT(1) | BIT(2)) == bt_user_priv_var.set_call_vol_flag) { + /* app_audio_set_volume(APP_AUDIO_STATE_CALL, app_var.aec_dac_gain, 1); */ + app_audio_set_volume(APP_AUDIO_STATE_CALL, 15, 1); + sys_timeout_add(NULL, phone_sync_vol, 1200); + } + /* log_debug("--test printfjjj --%x\n", bt_user_priv_var.set_call_vol_flag); */ +#endif + log_info("<<<<<<<<<<call_back_flag |= BIT(1); + + app_reset_vddiom_lev(VDDIOM_VOL_32V); + +#if 0 //debug + void mic_capless_feedback_toggle(u8 toggle); + mic_capless_feedback_toggle(0); +#endif + +#if PHONE_CALL_USE_LDO15 + if ((get_chip_version() & 0xff) <= 0x04) { //F版芯片以下的,通话需要使用LDO模式 + power_set_mode(PWR_LDO15); + } +#endif + +#if (TCFG_DEC2TWS_ENABLE) + if (localtws_dec_close(1)) { + bt_a2dp_drop_frame(NULL); + } + // 停止其他模式提示音 + bt_mode_stop_other_mode_tone(); +#endif + +#if TCFG_USER_TWS_ENABLE +#if TCFG_USER_ESCO_SLAVE_MUTE + if (tws_api_get_role() == TWS_ROLE_SLAVE) { + esco_dec_open(&bt->value, 1); + } else +#endif +#endif + { + esco_dec_open(&bt->value, 0); + } + bt_user_priv_var.phone_call_dec_begin = 1; + if (get_call_status() == BT_CALL_ACTIVE) { + log_debug("dec_begin,dump_packet clear\n"); + __this->esco_dump_packet = ESCO_DUMP_PACKET_DEFAULT; + } +#if TCFG_USER_TWS_ENABLE + tws_page_scan_deal_by_esco(1); +#endif +#if (RECORDER_MIX_EN) + recorder_mix_call_status_change(1); +#endif/*RECORDER_MIX_EN*/ + } else { + log_info("<<<<<<<<<<call_back_flag &= ~BIT(1); + + app_reset_vddiom_lev(VDDIOM_VOL_34V); + + bt_user_priv_var.set_call_vol_flag &= ~BIT(2); + bt_user_priv_var.phone_call_dec_begin = 0; + __this->esco_dump_packet = ESCO_DUMP_PACKET_CALL; + esco_dec_close(); +#if (RECORDER_MIX_EN) + recorder_mix_call_status_change(0); +#endif/*RECORDER_MIX_EN*/ +#if TCFG_USER_TWS_ENABLE + tws_page_scan_deal_by_esco(0); +#endif +#if PHONE_CALL_USE_LDO15 + if ((get_chip_version() & 0xff) <= 0x04) { //F版芯片以下的,通话需要使用LDO模式 + power_set_mode(TCFG_LOWPOWER_POWER_SEL); + } +#endif + +#if (TCFG_DEC2TWS_ENABLE) + if (is_tws_active_device()) { + return ; + } +#endif + if ((__this->call_back_flag == 0) && __this->call_flag) { + if (bt_switch_back_timer == 0) { + g_printf("timerout_add:bt_switch_back_timer"); + bt_switch_back_timer = sys_timeout_add(NULL, bt_switch_back, 500); + } + } + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 手机通话过程中设置音量产生状态 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_call_vol_change(struct bt_event *bt) +{ + + u8 volume = bt->value; //app_audio_get_max_volume() * bt->value / 15; + u8 call_status = get_call_status(); + bt_user_priv_var.phone_vol = bt->value; + if ((call_status == BT_CALL_ACTIVE) || (call_status == BT_CALL_OUTGOING) || app_var.siri_stu) { + app_audio_set_volume(APP_AUDIO_STATE_CALL, volume, 1); + } else if (call_status != BT_CALL_HANGUP) { + /*只保存,不设置到dac*/ + app_var.call_volume = volume; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 样机和链接设备进入sniff模式后返回来的状态 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_sniff_state_update(struct bt_event *bt) +{ + + if (bt->value == 0) { +#if (TCFG_USER_TWS_ENABLE == 1) + pwm_led_clk_set(PWM_LED_CLK_BTOSC_24M); +#endif + sys_auto_sniff_controle(1, bt->args); + } else { +#if (TCFG_USER_TWS_ENABLE == 1) + pwm_led_clk_set(PWM_LED_CLK_RC32K); +#endif + sys_auto_sniff_controle(0, bt->args); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 最后拨打电话类型 + @param + @return + @note 只区分打入和打出 +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_last_call_type_change(struct bt_event *bt) +{ + __this->call_back_flag |= BIT(0); + bt_user_priv_var.last_call_type = bt->value; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 高级音频链接上 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_conn_a2dp_ch(struct bt_event *bt) +{ + printf("------bt_status_conn_a2dp_ch------\n"); +#if TCFG_USER_EMITTER_ENABLE + if (bt_user_priv_var.emitter_or_receiver == BT_EMITTER_EN) { + /* extern int music_player_get_play_status(void); */ + /* if (bt->value && (music_player_get_play_status() == FILE_DEC_STATUS_PLAY)) { */ + /* emitter_open(1); */ + /* } */ + bt_user_priv_var.bt_a2dp_con_flag = 1; + emitter_info_init(); + +#if USER_SUPPORT_DUAL_A2DP_SOURCE + int err = 0; + if (get_total_connect_dev() == 2) { + err = __emitter_send_media_toggle(bt->args, 1); + } else { + app_task_put_key_msg(KEY_BT_EMITTER_SW, 0); + } +#else + // app_task_put_key_msg(KEY_BT_EMITTER_SW, 0); + bt_emitter_pp(1); +#endif + + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 手机音频链接上 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 tar_mac_addr[6] = {0}; +void bt_conn_spp_ch(void *priv) +{ + line_inf + printf("get_emitter_curr_channel_state() = %x",get_emitter_curr_channel_state()); + put_buf(tar_mac_addr,6); + if(get_emitter_curr_channel_state() & SPP_CH || get_emitter_curr_channel_state() == 0) { + return; + } else { + user_send_cmd_prepare(USER_CTRL_START_CONNEC_SPP_VIA_ADDR, 6, tar_mac_addr); + sys_timeout_add(NULL,bt_conn_spp_ch,1000); + } + return; +} + + +void bt_status_conn_hfp_ch(struct bt_event *bt) +{ + #if BT_EMITTER_TEST_ENABLE + memcpy(tar_mac_addr , bt->args , 6); + sys_timeout_add(NULL, bt_conn_spp_ch, 1000); + r_f_printf("bt_status_conn_hfp_ch------------"); + #endif +#if !TCFG_USER_EMITTER_ENABLE + if ((!is_1t2_connection()) && (get_current_poweron_memory_search_index(NULL))) { //回连下一个device + if (get_esco_coder_busy_flag()) { + clear_current_poweron_memory_search_index(0); + } else { + user_send_cmd_prepare(USER_CTRL_START_CONNECTION, 0, NULL); + } + } +#endif +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 获取手机厂商 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_phone_menufactuer(struct bt_event *bt) +{ + extern const u8 hid_conn_depend_on_dev_company; + app_var.remote_dev_company = bt->value; + if (hid_conn_depend_on_dev_company) { + if (bt->value) { + //user_send_cmd_prepare(USER_CTRL_HID_CONN, 0, NULL); + } else { + user_send_cmd_prepare(USER_CTRL_HID_DISCONNECT, 0, NULL); + } + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 语音识别 + @param + @return + @note bt->value 0-siri关闭状态 , + 1-siri开启状态 , + 2-手动打开siri成功状态. + 3-安卓手机上选择语音识别软件状态 +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_voice_recognition(struct bt_event *bt) +{ + __this->esco_dump_packet = ESCO_DUMP_PACKET_DEFAULT; + /* put_buf(bt, sizeof(struct bt_event)); */ + printf("bt value = %d",bt->value); + app_var.siri_stu = bt->value; + if (__this->call_flag && ((app_var.siri_stu == 0) || (app_var.siri_stu == 3))) { + if (bt_switch_back_timer == 0) { + bt_switch_back_timer = sys_timeout_add(NULL, bt_switch_back, 500); + } + } +//#if (RECORDER_MIX_EN) +// if (app_var.siri_stu) { +// recorder_mix_stop(); +// } +//#endif/*RECORDER_MIX_EN*/ +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙status 接收远端设备发过来的avrcp命令 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_status_avrcp_income_opid(struct bt_event *bt) +{ + +#define AVC_VOLUME_UP 0x41 +#define AVC_VOLUME_DOWN 0x42 + log_debug("BT_STATUS_AVRCP_INCOME_OPID:%d\n", bt->value); + if (bt->value == AVC_VOLUME_UP) { + + } + if (bt->value == AVC_VOLUME_DOWN) { + + } +} + + + +/************************************************************* + 蓝牙模式协议栈事件事件处理 +**************************************************************/ +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙event 蓝牙协议栈事件过滤 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 bt_hci_event_filter(struct bt_event *bt) +{ + if (bt->event == HCI_EVENT_VENDOR_REMOTE_TEST) { + if (0 == bt->value) { + set_remote_test_flag(0); + /* log_debug("clear_test_box_flag"); */ + return 0; + } else { + +#if TCFG_USER_BLE_ENABLE + //1:edr con;2:ble con; + if (1 == bt->value) { + extern void ble_module_enable(u8 enable); + /* bt_ble_adv_enable(0); */ + ble_module_enable(0); + } +#endif + +#if TCFG_USER_TWS_ENABLE + bt_tws_poweroff(); +#endif + } + } + + if ((bt->event != HCI_EVENT_CONNECTION_COMPLETE) || + ((bt->event == HCI_EVENT_CONNECTION_COMPLETE) && (bt->value != ERROR_CODE_SUCCESS))) { +#if TCFG_TEST_BOX_ENABLE + if (chargestore_get_testbox_status()) { + if (get_remote_test_flag()) { + chargestore_clear_connect_status(); + } + //return 0; + } +#endif + if (get_remote_test_flag() \ + && !(HCI_EVENT_DISCONNECTION_COMPLETE == bt->event) \ + && !(HCI_EVENT_VENDOR_REMOTE_TEST == bt->event) \ + && !get_total_connect_dev()) { + log_info("cpu reset\n"); + cpu_reset(); + } + } + if (__this->bt_close_bredr) { + return 0; + } + +#if CONFIG_TWS_DISCONN_NO_RECONN + extern u8 tws_detach_by_remove_key; + if (tws_detach_by_remove_key) { + return 0; + } +#endif + + + return 1; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙event 搜索结束 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_hci_event_inquiry(struct bt_event *bt) +{ +#if TCFG_USER_EMITTER_ENABLE + if (bt_user_priv_var.emitter_or_receiver == BT_EMITTER_EN) { + extern void emitter_search_stop(u8 result); + emitter_search_stop(bt->value); + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙event 链接成功 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_hci_event_connection(struct bt_event *bt) +{ + /* log_debug("tws_conn_state=%d\n", bt_user_priv_var.tws_conn_state); */ + +#if TCFG_USER_TWS_ENABLE + bt_tws_hci_event_connect(); +#ifndef CONFIG_NEW_BREDR_ENABLE + tws_try_connect_disable(); +#endif +#else + if (bt_user_priv_var.auto_connection_timer) { + sys_timeout_del(bt_user_priv_var.auto_connection_timer); + bt_user_priv_var.auto_connection_timer = 0; + } + bt_user_priv_var.auto_connection_counter = 0; + bt_wait_phone_connect_control(0); + user_send_cmd_prepare(USER_CTRL_ALL_SNIFF_EXIT, 0, NULL); +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙event 链接断开 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_hci_event_disconnect(struct bt_event *bt) +{ + u8 local_addr[6]; + if (app_var.goto_poweroff_flag || __this->exiting) { + return; + } + + if (get_total_connect_dev() == 0) { //已经没有设备连接 + sys_auto_shut_down_enable(); + } + + +#if TCFG_TEST_BOX_ENABLE + if (chargestore_get_testbox_status()) { + /* log_info("<<<<<<<<<<<<<<<<>>>>>>>>>>>>\n"); */ + bt_get_vm_mac_addr(local_addr); + //log_info("local_adr\n"); + //put_buf(local_addr,6); + lmp_hci_write_local_address(local_addr); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); + return; + } +#endif + +#if (TCFG_AUTO_STOP_PAGE_SCAN_TIME && TCFG_BD_NUM == 2) + if (get_total_connect_dev() == 1) { //当前有一台连接上了 + if (app_var.auto_stop_page_scan_timer == 0) { + app_var.auto_stop_page_scan_timer = sys_timeout_add(NULL, bt_close_page_scan, (TCFG_AUTO_STOP_PAGE_SCAN_TIME * 1000)); //2 + } + } else { + if (app_var.auto_stop_page_scan_timer) { + sys_timeout_del(app_var.auto_stop_page_scan_timer); + app_var.auto_stop_page_scan_timer = 0; + } + } +#endif //endif AUTO_STOP_PAGE_SCAN_TIME + +#if (TCFG_BD_NUM == 2) + if ((bt->value == ERROR_CODE_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR) || + (bt->value == ERROR_CODE_CONNECTION_ACCEPT_TIMEOUT_EXCEEDED)) { + /* + *连接接受超时 + *如果支持1t2,可以选择继续回连下一台,除非已经回连完毕 + */ + if (get_current_poweron_memory_search_index(NULL)) { + user_send_cmd_prepare(USER_CTRL_START_CONNECTION, 0, NULL); + return; + } + } +#endif + +#if TCFG_USER_TWS_ENABLE + /* bt_tws_phone_disconnected(); */ + if (bt->value == ERROR_CODE_CONNECTION_TIMEOUT) { + bt_tws_phone_connect_timeout(); + } else { + bt_tws_phone_disconnected(); + } +#else + if (bt_user_priv_var.emitter_or_receiver != BT_EMITTER_EN) { + bt_wait_phone_connect_control(1); + } else { +#if (TCFG_SPI_LCD_ENABLE) + //彩屏方案又ui 控制 + /* if (bt_search_status()) { */ + /* return; */ + /* } */ + + u8 search_index = 0; + search_index = get_current_poweron_memory_search_index(NULL); + + if (search_index) { + /* log_debug(">>>>>>>>> search_index =%d \n", search_index); */ + user_send_cmd_prepare(USER_CTRL_START_CONNECTION, 0, NULL); + return; + } + + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); +#else + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); +#endif + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙event 链接link key 错误 + @param + @return + @note 可能是取消配对 +*/ +/*----------------------------------------------------------------------------*/ +void bt_hci_event_linkkey_missing(struct bt_event *bt) +{ +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) +#if (CONFIG_NO_DISPLAY_BUTTON_ICON && TCFG_CHARGESTORE_ENABLE) + //已取消配对了 + if (bt_ble_icon_get_adv_state() == ADV_ST_RECONN) { + //切换广播 + /* log_info("switch_INQ\n"); */ + bt_ble_icon_open(ICON_TYPE_INQUIRY); + } +#endif +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙event 回链超时 + @param + @return + @note 回链超时内没有连接上设备 +*/ +/*----------------------------------------------------------------------------*/ +void bt_hci_event_page_timeout(struct bt_event *bt) +{ + log_info("-----------HCI_EVENT_PAGE_TIMEOUT conuter %d", bt_user_priv_var.auto_connection_counter); +#if TCFG_USER_TWS_ENABLE + bt_tws_phone_page_timeout(); +#else + /* if (!bt_user_priv_var.auto_connection_counter) { */ + if (bt_user_priv_var.auto_connection_timer) { + sys_timer_del(bt_user_priv_var.auto_connection_timer); + bt_user_priv_var.auto_connection_timer = 0; + } + +#if (TCFG_BD_NUM == 2) + if (get_current_poweron_memory_search_index(NULL)) { + user_send_cmd_prepare(USER_CTRL_START_CONNECTION, 0, NULL); + return; + } +#endif + if (bt_user_priv_var.emitter_or_receiver != BT_EMITTER_EN) { + bt_wait_phone_connect_control(1); + } else { + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙event 链接超时 + @param + @return + @note 链接超时,设备拿远导致的超时等 +*/ +/*----------------------------------------------------------------------------*/ +void bt_hci_event_connection_timeout(struct bt_event *bt) +{ + if (!get_remote_test_flag() && !get_esco_busy_flag()) { + bt_user_priv_var.auto_connection_counter = (TIMEOUT_CONN_TIME * 1000); + memcpy(bt_user_priv_var.auto_connection_addr, bt->args, 6); +#if TCFG_USER_TWS_ENABLE + bt_tws_phone_connect_timeout(); +#else + +#if ((CONFIG_BT_MODE == BT_BQB)||(CONFIG_BT_MODE == BT_PER)) + bt_wait_phone_connect_control(1); +#else + user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL); + bt_wait_connect_and_phone_connect_switch(0); +#endif + //user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR, 6, bt->args); +#endif + } else { +#if TCFG_USER_TWS_ENABLE + bt_tws_phone_disconnected(); +#else + bt_wait_phone_connect_control(1); +#endif + } + +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙event 链接已经存在 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_hci_event_connection_exist(struct bt_event *bt) +{ + if (!get_remote_test_flag() && !get_esco_busy_flag()) { + bt_user_priv_var.auto_connection_counter = (8 * 1000); + memcpy(bt_user_priv_var.auto_connection_addr, bt->args, 6); +#if TCFG_USER_TWS_ENABLE + bt_tws_phone_connect_timeout(); +#else + if (bt_user_priv_var.auto_connection_timer) { + sys_timer_del(bt_user_priv_var.auto_connection_timer); + bt_user_priv_var.auto_connection_timer = 0; + } + bt_wait_connect_and_phone_connect_switch(0); +#endif + } else { +#if TCFG_USER_TWS_ENABLE + bt_tws_phone_disconnected(); +#else + bt_wait_phone_connect_control(1); +#endif + } +} + +u8 is_call_now() +{ + if (get_call_status() != BT_CALL_HANGUP) { + return 1; + } + + return 0; +} +#else + +void sys_enter_soft_poweroff(void *priv) +{ + if (priv == NULL) { + app_task_switch_to(APP_POWEROFF_TASK); + } else if (priv == (void *)1) { + log_info("cpu_reset!!!\n"); + cpu_reset(); + } +} + + +#endif diff --git a/apps/soundbox/task_manager/bt/bt_key_fun.c b/apps/soundbox/task_manager/bt/bt_key_fun.c new file mode 100644 index 0000000..5d2ee56 --- /dev/null +++ b/apps/soundbox/task_manager/bt/bt_key_fun.c @@ -0,0 +1,728 @@ + +/************************************************************* + + 此文件函数主要是蓝牙模式按键处理 + + +**************************************************************/ +#include "system/includes.h" +#include "media/includes.h" + +#include "app_config.h" +#include "app_task.h" + +#include "btstack/avctp_user.h" +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "btstack/btstack_error.h" +#include "btctrler/btctrler_task.h" +#include "classic/hci_lmp.h" + +#include "bt/bt_tws.h" +#include "bt/bt_ble.h" +#include "bt/bt.h" +#include "bt/vol_sync.h" +#include "bt/bt_emitter.h" +#include "bt_common.h" +#include "aec_user.h" + +#include "math.h" +#include "spp_user.h" + + +#include "app_chargestore.h" +#include "app_charge.h" +#include "app_main.h" +#include "app_power_manage.h" +#include "user_cfg.h" + +#include "asm/pwm_led.h" +#include "asm/timer.h" +#include "asm/hwi.h" +#include "cpu.h" + +#include "ui/ui_api.h" +#include "ui_manage.h" +#include "ui/ui_style.h" + +#include "key_event_deal.h" +#include "clock_cfg.h" +#include "gSensor/gSensor_manage.h" +#include "soundcard/soundcard.h" + +#include "audio_dec.h" +#include "tone_player.h" +#include "dac.h" + + +#define __this (&app_bt_hdl) + +#define LOG_TAG_CONST BT +#define LOG_TAG "[BT]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +#define LOG_DUMP_ENABLE +#define LOG_CLI_ENABLE +#include "debug.h" + +#if TCFG_APP_BT_EN + +#if TCFG_USER_TWS_ENABLE +static void max_tone_timer(void *priv) +{ + if (!tone_get_status()) { + __this->max_tone_timer_hdl = 0; + __this->replay_tone_flag = 1; + } else { + __this->max_tone_timer_hdl = sys_timeout_add(NULL, max_tone_timer, TWS_SYNC_TIME_DO + 100); + } +} +#endif + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式获取按键事件前的过滤 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 bt_key_event_filter_before() +{ +#if TCFG_APP_FM_EMITTER_EN +#if TCFG_UI_ENABLE + if (ui_get_app_menu(GRT_CUR_MENU) == MENU_FM_SET_FRE) { + return false; + } +#endif +#endif + + if (key_is_ui_takeover()) { + return false; + } + return true; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式获取按键事件后的过滤 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 bt_key_event_filter_after(int key_event) +{ + +#if (TCFG_DEC2TWS_ENABLE) + u8 is_tws_all_in_bt(); + if ((key_event != KEY_POWEROFF) && \ + (key_event != KEY_POWEROFF_HOLD) && \ + (key_event != KEY_CHANGE_MODE) && \ + (key_event != KEY_REVERB_OPEN)) { + if (!is_tws_all_in_bt()) { + return true; + } + } +#endif + return false; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 tws 区分左右耳加音量 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void volume_up(void) +{ + u8 test_box_vol_up = 0x41; + s8 cur_vol = 0; + u8 call_status = get_call_status(); + + if (tone_get_status()) { + if (get_call_status() == BT_CALL_INCOMING) { + app_audio_volume_up(1); + } + return; + } + + /*打电话出去彩铃要可以调音量大小*/ + if ((call_status == BT_CALL_ACTIVE) || (call_status == BT_CALL_OUTGOING)) { + cur_vol = app_audio_get_volume(APP_AUDIO_STATE_CALL); + } else { + cur_vol = app_audio_get_volume(APP_AUDIO_STATE_MUSIC); + } + if (get_remote_test_flag()) { + user_send_cmd_prepare(USER_CTRL_TEST_KEY, 1, &test_box_vol_up); //音量加 + } + + if (cur_vol >= app_audio_get_max_volume()) { +#if TCFG_USER_TWS_ENABLE + if (get_tws_sibling_connect_state()) { + if (tws_api_get_role() == TWS_ROLE_MASTER && __this->replay_tone_flag) { + __this->replay_tone_flag = 0; //防止提示音被打断标志 + tws_api_sync_call_by_uuid('T', SYNC_CMD_MAX_VOL, TWS_SYNC_TIME_DO); + __this->max_tone_timer_hdl = sys_timeout_add(NULL, max_tone_timer, TWS_SYNC_TIME_DO + 100); //同步在TWS_SYNC_TIME_DO之后才会播放提示音,所以timer需要在这个时间之后才去检测提示音状态 + } + } else +#endif + { +#if TCFG_MAX_VOL_PROMPT + tone_play_by_path(tone_table[IDEX_TONE_MAX_VOL], 0); +#endif + } + + if (get_call_status() != BT_CALL_HANGUP) { + /*本地音量最大,如果手机音量还没最大,继续加,以防显示不同步*/ + if (bt_user_priv_var.phone_vol < 15) { + #if TCFG_USER_EMITTER_ENABLE + if(bt_user_priv_var.emitter_or_receiver == BT_EMITTER_EN) { + if (get_emitter_curr_channel_state() & HID_CH) { + user_send_cmd_prepare(USER_CTRL_HID_VOL_UP, 0, NULL); //使用HID调音量 + } else { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_VOLUME_UP, 0, NULL); + } + } else if(bt_user_priv_var.emitter_or_receiver == BT_RECEIVER_EN) { + if (get_curr_channel_state() & HID_CH) { + user_send_cmd_prepare(USER_CTRL_HID_VOL_UP, 0, NULL); //使用HID调音量 + } else { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_VOLUME_UP, 0, NULL); + } + } + #else + if (get_curr_channel_state() & HID_CH) { + user_send_cmd_prepare(USER_CTRL_HID_VOL_UP, 0, NULL); //使用HID调音量 + } else { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_VOLUME_UP, 0, NULL); + } + #endif + } + return; + } +#if BT_SUPPORT_MUSIC_VOL_SYNC +#if (TCFG_DEC2TWS_ENABLE) + if (!is_tws_all_in_bt()) { + log_debug(">>>>>>>tws is not all in bt mode !!!\n"); + } else +#endif + { + opid_play_vol_sync_fun(&app_var.music_volume, 1); + user_send_cmd_prepare(USER_CTRL_CMD_SYNC_VOL_INC, 0, NULL); + } +#endif/*BT_SUPPORT_MUSIC_VOL_SYNC*/ + return; + } + +#if BT_SUPPORT_MUSIC_VOL_SYNC +#if (TCFG_BD_NUM == 2) + if ((APP_AUDIO_STATE_MUSIC == app_audio_get_state()) || (a2dp_get_status() == BT_MUSIC_STATUS_STARTING)) { +#else + if (APP_AUDIO_STATE_MUSIC == app_audio_get_state()) { +#endif + opid_play_vol_sync_fun(&app_var.music_volume, 1); + app_audio_set_volume(APP_AUDIO_STATE_MUSIC, app_var.music_volume, 1); + } else { + app_audio_volume_up(1); + } +#else + app_audio_volume_up(1); +#endif/*BT_SUPPORT_MUSIC_VOL_SYNC*/ + log_info("vol+: %d", app_audio_get_volume(APP_AUDIO_CURRENT_STATE)); + if (get_call_status() != BT_CALL_HANGUP) { + #if TCFG_USER_EMITTER_ENABLE + if(bt_user_priv_var.emitter_or_receiver == BT_EMITTER_EN) { + if (get_emitter_curr_channel_state() & HID_CH) { + user_send_cmd_prepare(USER_CTRL_HID_VOL_UP, 0, NULL); //使用HID调音量 + } else { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_VOLUME_UP, 0, NULL); + } + } else if(bt_user_priv_var.emitter_or_receiver == BT_RECEIVER_EN) { + if (get_curr_channel_state() & HID_CH) { + user_send_cmd_prepare(USER_CTRL_HID_VOL_UP, 0, NULL); //使用HID调音量 + } else { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_VOLUME_UP, 0, NULL); + } + } + #else + if (get_curr_channel_state() & HID_CH) { + user_send_cmd_prepare(USER_CTRL_HID_VOL_UP, 0, NULL); //使用HID调音量 + } else { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_VOLUME_UP, 0, NULL); + } + #endif + } else { +#if BT_SUPPORT_MUSIC_VOL_SYNC +#if (TCFG_DEC2TWS_ENABLE) + if (!is_tws_all_in_bt()) { + log_debug(">>>>>>>tws is not all in bt mode !!!\n"); + } else +#endif + { + /* opid_play_vol_sync_fun(&app_var.music_volume, 0); */ + +#if TCFG_USER_TWS_ENABLE + user_send_cmd_prepare(USER_CTRL_CMD_SYNC_VOL_INC, 0, NULL); //使用HID调音量 + //user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_SEND_VOL, 0, NULL); +#else + user_send_cmd_prepare(USER_CTRL_CMD_SYNC_VOL_INC, 0, NULL); +#endif/*TCFG_USER_TWS_ENABLE*/ + } +#endif/*BT_SUPPORT_MUSIC_VOL_SYNC*/ + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 tws 区分左右耳减音量 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void volume_down(void) +{ + u8 test_box_vol_down = 0x42; + + if (tone_get_status()) { + if (get_call_status() == BT_CALL_INCOMING) { + app_audio_volume_down(1); + } + return; + } + if (get_remote_test_flag()) { + user_send_cmd_prepare(USER_CTRL_TEST_KEY, 1, &test_box_vol_down); //音量减 + } + + if (app_audio_get_volume(APP_AUDIO_CURRENT_STATE) <= 0) { + if (get_call_status() != BT_CALL_HANGUP) { + /* + *本地音量最小,如果手机音量还没最小,继续减 + *注意:有些手机通话最小音量是1(GREE G0245D) + */ + if (bt_user_priv_var.phone_vol > 1) { + #if TCFG_USER_EMITTER_ENABLE + if(bt_user_priv_var.emitter_or_receiver == BT_EMITTER_EN) { + if (get_emitter_curr_channel_state() & HID_CH) { + user_send_cmd_prepare(USER_CTRL_HID_VOL_DOWN, 0, NULL); //使用HID调音量 + } else { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_VOLUME_DOWN, 0, NULL); + } + } else if(bt_user_priv_var.emitter_or_receiver == BT_RECEIVER_EN) { + if (get_curr_channel_state() & HID_CH) { + user_send_cmd_prepare(USER_CTRL_HID_VOL_DOWN, 0, NULL); //使用HID调音量 + } else { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_VOLUME_DOWN, 0, NULL); + } + } + #else + if (get_curr_channel_state() & HID_CH) { + user_send_cmd_prepare(USER_CTRL_HID_VOL_DOWN, 0, NULL); //使用HID调音量 + } else { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_VOLUME_DOWN, 0, NULL); + } + #endif + } + return; + } +#if BT_SUPPORT_MUSIC_VOL_SYNC +#if (TCFG_DEC2TWS_ENABLE) + if (!is_tws_all_in_bt()) { + log_debug(">>>>>>>tws is not all in bt mode !!!\n"); + } else +#endif + { + opid_play_vol_sync_fun(&app_var.music_volume, 0); + user_send_cmd_prepare(USER_CTRL_CMD_SYNC_VOL_DEC, 0, NULL); + } +#endif + return; + } + +#if BT_SUPPORT_MUSIC_VOL_SYNC +#if (TCFG_BD_NUM == 2) + if ((APP_AUDIO_STATE_MUSIC == app_audio_get_state()) || (a2dp_get_status() == BT_MUSIC_STATUS_STARTING)) { +#else + if (APP_AUDIO_STATE_MUSIC == app_audio_get_state()) { +#endif + opid_play_vol_sync_fun(&app_var.music_volume, 0); + app_audio_set_volume(APP_AUDIO_STATE_MUSIC, app_var.music_volume, 1); + } else { + app_audio_volume_down(1); + } +#else + app_audio_volume_down(1); +#endif/*BT_SUPPORT_MUSIC_VOL_SYNC*/ + log_info("vol-: %d", app_audio_get_volume(APP_AUDIO_CURRENT_STATE)); + if (get_call_status() != BT_CALL_HANGUP) { + #if TCFG_USER_EMITTER_ENABLE + if(bt_user_priv_var.emitter_or_receiver == BT_EMITTER_EN) { + if (get_emitter_curr_channel_state() & HID_CH) { + user_send_cmd_prepare(USER_CTRL_HID_VOL_DOWN, 0, NULL); //使用HID调音量 + } else { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_VOLUME_DOWN, 0, NULL); + } + } else if(bt_user_priv_var.emitter_or_receiver == BT_RECEIVER_EN) { + if (get_curr_channel_state() & HID_CH) { + user_send_cmd_prepare(USER_CTRL_HID_VOL_DOWN, 0, NULL); //使用HID调音量 + } else { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_VOLUME_DOWN, 0, NULL); + } + } + #else + if (get_curr_channel_state() & HID_CH) { + user_send_cmd_prepare(USER_CTRL_HID_VOL_DOWN, 0, NULL); //使用HID调音量 + } else { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_VOLUME_DOWN, 0, NULL); + } + #endif + } else { +#if BT_SUPPORT_MUSIC_VOL_SYNC +#if (TCFG_DEC2TWS_ENABLE) + if (!is_tws_all_in_bt()) { + log_debug(">>>>>>>tws is not all in bt mode !!!\n"); + } else +#endif + { + /* opid_play_vol_sync_fun(&app_var.music_volume, 0); */ + if (app_audio_get_volume(APP_AUDIO_CURRENT_STATE) == 0) { + app_audio_volume_down(0); + } + +#if TCFG_USER_TWS_ENABLE + user_send_cmd_prepare(USER_CTRL_CMD_SYNC_VOL_DEC, 0, NULL); + //user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_SEND_VOL, 0, NULL); +#else + user_send_cmd_prepare(USER_CTRL_CMD_SYNC_VOL_DEC, 0, NULL); +#endif + } +#endif + } +} + + + +#if ONE_KEY_CTL_DIFF_FUNC +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 tws 左右耳区分按键功能 + @param + @return + @note 左耳:下一曲、音量加 + 右耳:上一曲、音量减 +*/ +/*----------------------------------------------------------------------------*/ +static void lr_diff_otp_deal(u8 opt, char channel) +{ + /* log_info("lr_diff_otp_deal:%d", opt); */ + switch (opt) { + case ONE_KEY_CTL_NEXT_PREV: + if (channel == 'L') { + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_NEXT, 0, NULL); + } else if (channel == 'R') { + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_PREV, 0, NULL); + } else { + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_NEXT, 0, NULL); + } + break; + case ONE_KEY_CTL_VOL_UP_DOWN: + if (channel == 'L') { + volume_up(); + } else if (channel == 'R') { + volume_down(); + } + break; + default: + break; + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 tws 左右耳区分按键功能 + @param + @return + @note 左耳:下一曲、音量加 + 右耳:上一曲、音量减 +*/ +/*----------------------------------------------------------------------------*/ +void key_tws_lr_diff_deal(struct sys_event *event, u8 opt) +{ + u8 channel = 'U'; + if (get_bt_tws_connect_status()) { + channel = tws_api_get_local_channel(); + if ('L' == channel) { + channel = (u32)event->arg == KEY_EVENT_FROM_TWS ? 'R' : 'L'; + } else { + channel = (u32)event->arg == KEY_EVENT_FROM_TWS ? 'L' : 'R'; + } + } + lr_diff_otp_deal(opt, channel); +} +#else +void key_tws_lr_diff_deal(struct sys_event *event, u8 opt) +{ +} +#endif + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式切换设备类型 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +#if (USER_SUPPORT_PROFILE_HID==1) +void user_change_profile_mode(u8 flag) +{ + user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL); + while (hci_standard_connect_check() != 0) { + //wait disconnect; + os_time_dly(10); + } + __bt_set_hid_independent_flag(flag); + if (flag) { + __change_hci_class_type(0x002570); + } else { + __change_hci_class_type(BD_CLASS_WEARABLE_HEADSET); + } + user_send_cmd_prepare(USER_CTRL_CMD_CHANGE_PROFILE_MODE, 0, NULL); + if (connect_last_device_from_vm()) { + /* log_debug("start connect vm addr phone \n"); */ + } else { + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_ENABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); + } +} +#endif + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 pp 按键处理 + @param + @return + @note 播放音乐、通话接听挂断 +*/ +/*----------------------------------------------------------------------------*/ +void bt_key_music_pp() +{ + if ((get_call_status() == BT_CALL_OUTGOING) || + (get_call_status() == BT_CALL_ALERT)) { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); + } else if (get_call_status() == BT_CALL_INCOMING) { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_ANSWER, 0, NULL); + } else if (get_call_status() == BT_CALL_ACTIVE) { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); + } else { + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_PLAY, 0, NULL); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 prev 按键处理 + @param + @return + @note 播放音乐上一曲 +*/ +/*----------------------------------------------------------------------------*/ +void bt_key_music_prev() +{ + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_PREV, 0, NULL); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 next 按键处理 + @param + @return + @note 播放音乐下一曲 +*/ +/*----------------------------------------------------------------------------*/ +void bt_key_music_next() +{ +#ifdef CONFIG_BOARD_AC6933B_LIGHTING + if (get_call_status() == BT_CALL_INCOMING) { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); + break; + } +#endif + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_NEXT, 0, NULL); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 vol up 按键处理 + @param + @return + @note 加音量 +*/ +/*----------------------------------------------------------------------------*/ +void bt_key_vol_up() +{ + + u8 vol; + if (get_call_status() == BT_CALL_ACTIVE && bt_sco_state() == 0) { + return; + } + volume_up(); + vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + UI_SHOW_MENU(MENU_MAIN_VOL, 1000, vol, NULL); + UI_MSG_POST("music_vol:vol=%4", vol); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 vol down 按键处理 + @param + @return + @note 减音量 +*/ +/*----------------------------------------------------------------------------*/ +void bt_key_vol_down() +{ + u8 vol; + if (get_call_status() == BT_CALL_ACTIVE && bt_sco_state() == 0) { + return; + } + volume_down(); + vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + UI_SHOW_MENU(MENU_MAIN_VOL, 1000, vol, NULL); + UI_MSG_POST("music_vol:vol=%4", vol); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 回拨最后一个号码 来电拒听 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_key_call_last_on() +{ + if (get_call_status() == BT_CALL_INCOMING) { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); + return; + } + + if ((get_call_status() == BT_CALL_ACTIVE) || + (get_call_status() == BT_CALL_OUTGOING) || + (get_call_status() == BT_CALL_ALERT) || + (get_call_status() == BT_CALL_INCOMING)) { + return;//通话过程不允许回拨 + } + + if (bt_user_priv_var.last_call_type == BT_STATUS_PHONE_INCOME) { + user_send_cmd_prepare(USER_CTRL_DIAL_NUMBER, bt_user_priv_var.income_phone_len, + bt_user_priv_var.income_phone_num); + } else { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_LAST_NO, 0, NULL); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 通话挂断 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_key_call_hand_up() +{ + user_send_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_key_call_answer() +{ + +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 siri开启 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_key_call_siri() +{ + user_send_cmd_prepare(USER_CTRL_HFP_GET_SIRI_OPEN, 0, NULL); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 hid 发起拍照命令 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_key_hid_control() +{ + /* log_info("get_curr_channel_state:%x\n", get_curr_channel_state()); */ + #if TCFG_USER_EMITTER_ENABLE + if(bt_user_priv_var.emitter_or_receiver == BT_EMITTER_EN) { + if (get_emitter_curr_channel_state() & HID_CH) { + log_info("KEY_HID_CONTROL\n"); + user_send_cmd_prepare(USER_CTRL_HID_IOS, 0, NULL); + } + } else if(bt_user_priv_var.emitter_or_receiver == BT_RECEIVER_EN) { + if (get_curr_channel_state() & HID_CH) { + log_info("KEY_HID_CONTROL\n"); + user_send_cmd_prepare(USER_CTRL_HID_IOS, 0, NULL); + } + } + #else + if (get_curr_channel_state() & HID_CH) { + log_info("KEY_HID_CONTROL\n"); + user_send_cmd_prepare(USER_CTRL_HID_IOS, 0, NULL); + } + #endif +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 tws 分开左右耳的按键功能 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_key_third_click(struct sys_event *event) +{ + key_tws_lr_diff_deal(event, ONE_KEY_CTL_NEXT_PREV); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 低电处理 + @param + @return + @note 电量高的做主机,电量低的做从机 +**/ +/*----------------------------------------------------------------------------*/ +void bt_key_low_lantecy() +{ + bt_set_low_latency_mode(!bt_get_low_latency_mode()); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式 混响按键不处理 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 bt_key_reverb_open() +{ + if ((get_call_status() == BT_CALL_ACTIVE) || + (get_call_status() == BT_CALL_OUTGOING) || + (get_call_status() == BT_CALL_ALERT) || + (get_call_status() == BT_CALL_INCOMING)) { + //通话过程不允许开/关混响 + return 1; + } + return 0; +} +#endif diff --git a/apps/soundbox/task_manager/bt/bt_product_test.c b/apps/soundbox/task_manager/bt/bt_product_test.c new file mode 100644 index 0000000..8179aa3 --- /dev/null +++ b/apps/soundbox/task_manager/bt/bt_product_test.c @@ -0,0 +1,426 @@ + + +#include "system/includes.h" +#include "media/includes.h" + +#include "app_config.h" +#include "app_task.h" + +#include "btstack/avctp_user.h" +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "btstack/btstack_error.h" +#include "btctrler/btctrler_task.h" +#include "classic/hci_lmp.h" + +#include "bt/bt_tws.h" +#include "bt/bt_ble.h" +#include "bt/bt.h" +#include "bt/vol_sync.h" +#include "bt/bt_emitter.h" +#include "bt_common.h" +#include "aec_user.h" + +#include "math.h" +#include "spp_user.h" + + +#include "app_chargestore.h" +#include "app_charge.h" +#include "app_main.h" +#include "app_power_manage.h" +#include "user_cfg.h" + +#include "asm/pwm_led.h" +#include "asm/timer.h" +#include "asm/hwi.h" +#include "cpu.h" + +#include "ui/ui_api.h" +#include "ui_manage.h" +#include "ui/ui_style.h" + +#include "key_event_deal.h" +#include "clock_cfg.h" +#include "gSensor/gSensor_manage.h" +#include "soundcard/soundcard.h" + +#include "audio_dec.h" +#include "tone_player.h" +#include "dac.h" +#define LOG_TAG_CONST BT +#define LOG_TAG "[BT]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +#define LOG_DUMP_ENABLE +#define LOG_CLI_ENABLE +#include "debug.h" + +#if TCFG_APP_BT_EN +#define __this (&app_bt_hdl) + +/************************************************************* + + 此文件函数主要是蓝牙量产测试的函数处理 + +**************************************************************/ + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙快速测试 + @param + @return + @note 样机和蓝牙测试盒链接开启快速测试,开启mic扩音功能, + 按键就播放按键音来检测硬件是否焊接正常 +*/ +/*----------------------------------------------------------------------------*/ +void bt_fast_test_api(void) +{ + log_info("------------bt_fast_test_api---------\n"); + //进入快速测试模式,用户根据此标志判断测试,如测试按键-开按键音 、测试mic-开扩音 、关闭蓝牙进入powerdown、关闭可发现可连接 + bt_user_priv_var.fast_test_mode = 1; +#ifdef AUDIO_MIC_TEST + mic_test_start(); +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式样机被测试仪链接上的回调函数,把其他状态关闭 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_dut_api(u8 value) +{ + log_info("bt in dut \n"); + sys_auto_shut_down_disable(); +#if TCFG_USER_TWS_ENABLE + extern void tws_cancle_all_noconn(); + tws_cancle_all_noconn() ; +#else + sys_timer_del(app_var.auto_stop_page_scan_timer); + extern void bredr_close_all_scan(); + bredr_close_all_scan(); +#endif + + if (bt_user_priv_var.auto_connection_timer) { + sys_timeout_del(bt_user_priv_var.auto_connection_timer); + bt_user_priv_var.auto_connection_timer = 0; + } + +#if TCFG_USER_BLE_ENABLE + extern void ble_module_enable(u8 enable); + /* bt_ble_adv_enable(0); */ + ble_module_enable(0); +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式进入定频状态 + @param + @return + @note 量产的时候可以通过按键等来触发进入定频状态,这时候蓝牙会在一个通道里 + 发送信号,可以通过设置下面变量来设置定频的频点 + const int config_bredr_fcc_fix_fre = 0; +*/ +/*----------------------------------------------------------------------------*/ +void bt_fix_fre_api(u8 fre) +{ + log_info("bt in fix fre \n"); + bt_dut_api(0); + + bit_clr_ie(IRQ_BREDR_IDX); + bit_clr_ie(IRQ_BT_CLKN_IDX); + + bredr_fcc_init(BT_FRE, fre); + +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式进入定频测试接收发射 + @param mode :0 测试发射 1:测试接收 + mac_addr:测试设置的地址 + fre:定频的频点 0=2402 1=2403 + packet_type:数据包类型 + + #define DH1_1 0 + #define DH3_1 1 + #define DH5_1 2 + #define DH1_2 3 + #define DH3_2 4 + #define DH5_2 5 + + payload:数据包内容 0x0000 0x0055 0x00aa 0x00ff + 0xffff:prbs9 + @return + @note 量产的时候通过串口,发送设置的参数,设置发送接收的参数 + + 关闭定频接收发射测试 + void link_fix_txrx_disable(); + + 更新接收结果 + void bt_updata_fix_rx_result() + +struct link_fix_rx_result { + u32 rx_err_b; //接收到err bit + u32 rx_sum_b; //接收到正确bit + u32 rx_perr_p; //接收到crc 错误 包数 + u32 rx_herr_p; //接收到crc 以外其他错误包数 + u32 rx_invail_p; //接收到crc错误bit太多的包数,丢弃不统计到err bit中 +}; + +*/ + +/*----------------------------------------------------------------------------*/ +void bt_fix_txrx_api(u8 mode, u8 *mac_addr, u8 fre, u8 packet_type, u16 payload) +{ + bt_dut_api(0); + local_irq_disable(); + link_fix_txrx_disable(); + if (mode) { + link_fix_rx_enable(mac_addr, fre, packet_type, 0xffff); + } else { + link_fix_tx_enable(mac_addr, fre, packet_type, 0xffff); + } + local_irq_enable(); +} + + +void bt_updata_fix_rx_result() +{ + struct link_fix_rx_result fix_rx_result; + link_fix_rx_update_result(&fix_rx_result); + printf("err_b:%d sum_b:%d perr:%d herr_b:%d invaile:%d \n", + fix_rx_result.rx_err_b, + fix_rx_result.rx_sum_b, + fix_rx_result.rx_perr_p, + fix_rx_result.rx_herr_p, + fix_rx_result.rx_invail_p + ); +} + + +extern void ble_fix_fre_api(); +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙量产串口控制处理 + @param + @return + @note 下面是蓝牙通过串口来控制进行量产测试的简单例子demo + 命令格式可以查看<<杰理蓝牙串口量产控制.pdf>>文档命令、 + 客户可以按照需求自行添加修改 + 需要把uart_bt_product.c 里面代码流程开启或者自己调试串口发送接收 + + +*/ +/*----------------------------------------------------------------------------*/ + +#if 0 +#include"asm/uart_dev.h" +#define UART_HEAD 0x12345678 + + +#define GET_BT_ADDR 0x01 //获取小机蓝牙地址 +#define SET_BT_ADDR 0x02 //设置小机蓝牙地址 +#define SET_DUT 0x03 //设置小机进入dut模式,可以被仪器链接测试性能 +#define SET_BREDR_FRE 0x04 //设置小机进入bredr定频 +#define SET_BLE_FRE 0x05 //设置小机进入ble定频 +#define SAVE_OFFSET 0x06 //更新并且保存小机频偏,确定测试的频偏没有问题可以保存 +#define UPDATA_OFFSET 0x07 //更新小机频偏 +#define SET_RESET 0x08 //小机复位 + + +static uart_bus_t *product_uart_bus; +void set_bt_uart_bus(uart_bus_t *uart_bus) +{ + product_uart_bus = uart_bus; +} + +u16 bt_product_checksum(u8 *data, u16 len) +{ + u16 sum = 0; + u16 i ; + for (i = 0; i < len; i++) { + sum += data[i]; + } + return sum; +} + +void bt_product_get_addr(u8 cmd, u8 *addr) +{ + u16 sum = 0; + u8 return_data[20]; + + return_data[0] = (u8)(UART_HEAD >> 24); + return_data[1] = (u8)(UART_HEAD >> 16); + return_data[2] = (u8)(UART_HEAD >> 8); + return_data[3] = (u8)UART_HEAD; + + return_data[4] = 7; //len + return_data[5] = cmd; //cmd + + memcpy(&return_data[6], addr, 6); + sum = bt_product_checksum(return_data, 11); + + return_data[12] = sum >> 8; + return_data[13] = sum; + + if (product_uart_bus) { + product_uart_bus->write(return_data, 14); + } +} + +void bt_product_set_addr(u8 cmd, u8 *addr) +{ + u16 sum = 0; + u8 return_data[20]; + + /* put_buf(addr,6); */ + +////从新设置地址,然后要从新开启搜索发现等 + bt_update_mac_addr(addr); +#if TCFG_USER_TWS_ENABLE + extern void tws_cancle_all_noconn(); + tws_cancle_all_noconn() ; +#else + sys_timer_del(app_var.auto_stop_page_scan_timer); + extern void bredr_close_all_scan(); + bredr_close_all_scan(); +#endif + +#if TCFG_USER_BLE_ENABLE + bt_ble_adv_enable(0); +#endif + lmp_hci_write_local_address(addr); + + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_ENABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); + + return_data[0] = (u8)(UART_HEAD >> 24); + return_data[1] = (u8)(UART_HEAD >> 16); + return_data[2] = (u8)(UART_HEAD >> 8); + return_data[3] = (u8)UART_HEAD; + + return_data[4] = 1; //len + return_data[5] = cmd; //cmd + + sum = bt_product_checksum(return_data, 6); + return_data[6] = sum >> 8; + return_data[7] = sum; + + //// 更新协议栈 地址 + if (product_uart_bus) { + product_uart_bus->write(return_data, 8); + } +} + +void bt_product_save_offset(u8 cmd, u8 *data) +{ + u32 offset = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; + u16 sum = 0; + u8 return_data[20]; + + printf("%d \n", offset); + + bt_osc_offset_ext_save(offset); + + return_data[0] = (u8)(UART_HEAD >> 24); + return_data[1] = (u8)(UART_HEAD >> 16); + return_data[2] = (u8)(UART_HEAD >> 8); + return_data[3] = (u8)UART_HEAD; + + return_data[4] = 1; //len + return_data[5] = cmd; //cmd + + sum = bt_product_checksum(return_data, 6); + return_data[6] = sum >> 8; + return_data[7] = sum; + + if (product_uart_bus) { + product_uart_bus->write(return_data, 8); + } +} + + +void bt_product_updata_offset(u8 cmd, u8 *data) +{ + u32 offset = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; + u16 sum = 0; + u8 return_data[20]; + + printf("%d \n", offset); + + bt_osc_offset_ext_updata(offset); + + return_data[0] = (u8)(UART_HEAD >> 24); + return_data[1] = (u8)(UART_HEAD >> 16); + return_data[2] = (u8)(UART_HEAD >> 8); + return_data[3] = (u8)UART_HEAD; + + return_data[4] = 1; //len + return_data[5] = cmd; //cmd + + sum = bt_product_checksum(return_data, 6); + return_data[6] = sum >> 8; + return_data[7] = sum; + + if (product_uart_bus) { + product_uart_bus->write(return_data, 8); + } +} + +void bt_product_test_uart(u8 *data, u8 len) +{ + u32 head = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3]; + + /* y_printf(" head %x \n",head); */ + + if (head != UART_HEAD) { + return; + } + + u8 param_len = data[4]; + u8 cmd = data[5]; + u16 checksum = data[4 + 1 + param_len] << 8 | data[4 + 1 + param_len + 1]; + u16 checksum1 = bt_product_checksum(data, 4 + 1 + param_len); + + /* y_printf(" param_len=%d cmd=%x %x %x\n",param_len,cmd,checksum,checksum1); */ + + switch (cmd) { + case GET_BT_ADDR: + printf(" GET_BT_ADDR \n"); + bt_product_get_addr(cmd, bt_get_mac_addr()); + break; + case SET_BT_ADDR: + printf(" SET_BT_ADDR \n"); + bt_product_set_addr(cmd, &data[6]); + break; + case SET_DUT: + printf(" SET_DUT \n"); + bredr_set_dut_enble(1, 0); + break; + case SET_BREDR_FRE: + printf(" SET_BREDR_FRE \n"); + bt_fix_fre_api(0); + break; + case SET_BLE_FRE: + printf(" SET_BLE_FRE \n"); + ble_fix_fre_api(); + break; + case SAVE_OFFSET: + printf(" SET_OFFSET \n"); + bt_product_save_offset(cmd, &data[6]); + break; + case UPDATA_OFFSET: + printf(" UPDATA_OFFSET \n"); + bt_product_updata_offset(cmd, &data[6]); + break; + case SET_RESET: + printf(" SET_RESET \n"); + cpu_reset(); + break; + } +} +#endif +#endif diff --git a/apps/soundbox/task_manager/bt/bt_switch_fun.c b/apps/soundbox/task_manager/bt/bt_switch_fun.c new file mode 100644 index 0000000..d43d898 --- /dev/null +++ b/apps/soundbox/task_manager/bt/bt_switch_fun.c @@ -0,0 +1,1122 @@ + +#include "system/includes.h" +#include "media/includes.h" + +#include "app_config.h" +#include "app_task.h" + +#include "btstack/avctp_user.h" +#include "btstack/btstack_task.h" +#include "btstack/bluetooth.h" +#include "btstack/btstack_error.h" +#include "btctrler/btctrler_task.h" +#include "classic/hci_lmp.h" + +#include "bt/bt_tws.h" +#include "bt/bt_ble.h" +#include "bt/bt.h" +#include "bt/vol_sync.h" +#include "bt/bt_emitter.h" +#include "bt_common.h" +#include "aec_user.h" +#include "soundbox.h" + +#include "math.h" +#include "spp_user.h" + + +#include "app_chargestore.h" +#include "app_charge.h" +#include "app_main.h" +#include "app_power_manage.h" +#include "user_cfg.h" + +#include "asm/pwm_led.h" +#include "asm/timer.h" +#include "asm/hwi.h" +#include "cpu.h" + +#include "ui/ui_api.h" +#include "ui_manage.h" +#include "ui/ui_style.h" + +#include "key_event_deal.h" +#include "clock_cfg.h" +#include "gSensor/gSensor_manage.h" +#include "soundcard/soundcard.h" + +#include "audio_dec.h" +#include "tone_player.h" +#include "dac.h" + + +#define LOG_TAG_CONST BT +#define LOG_TAG "[BT]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +#define LOG_DUMP_ENABLE +#define LOG_CLI_ENABLE +#include "debug.h" + +#if TCFG_APP_BT_EN +#define __this (&app_bt_hdl) + +extern void bt_start_a2dp_slience_detect(int ingore_packet_num) ; +extern void bt_drop_a2dp_frame_start(void); + +/************************************************************* + + 此文件函数主要是蓝牙模式创建,模式退出和进去 + + 后台、非后台的处理 + + +**************************************************************/ + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式关机退出道idle模式 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void wait_exit_btstack_flag(void *priv) +{ + sys_timer_del(app_var.wait_exit_timer); + app_var.wait_exit_timer = 0; + if (priv == NULL) { + app_task_switch_to(APP_POWEROFF_TASK); + } else if (priv == (void *)1) { + log_info("cpu_reset!!!\n"); + cpu_reset(); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式后台回来蓝牙模式恢复 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void bt_resume_deal(void) +{ + sys_key_event_enable(); + sys_auto_sniff_controle(1, NULL); + if (get_call_status() != BT_CALL_HANGUP) { + log_debug("background return by call"); + return; + } + bt_set_led_status(0); + if (get_total_connect_dev() == 0) { + sys_auto_shut_down_enable(); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 判断蓝牙通话是否在运行 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int bt_must_work(void) +{ + if ((app_var.siri_stu) && (app_var.siri_stu != 3)) { + // siri不退出 + return true; + } + + if ((get_call_status() == BT_CALL_OUTGOING) + || (get_call_status() == BT_CALL_ALERT) + || (get_call_status() == BT_CALL_INCOMING) + || (get_call_status() == BT_CALL_ACTIVE) + ) { + // 通话不退出 + return true; + } + return false; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 后台的时候判断有音频需要播放歌曲 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void a2dp_media_packet_play_start(void *p) +{ + __this->back_mode_systime = 0; + if ((__this->exit_flag == 0) || (__this->sbc_packet_step == 2)) { + log_debug(" a2dp back \n"); +#if (TCFG_DEC2TWS_ENABLE) + /* tws_user_sync_box(TWS_BOX_A2DP_BACK_TO_BT_MODE_START, __this->a2dp_decoder_type); */ + __this->tws_local_to_bt_mode = 1; + localtws_set_wait_a2dp_start(1); +#endif + app_task_switch_to(APP_BT_TASK); + struct sys_event event; + event.type = SYS_BT_EVENT; + event.arg = (void *)SYS_BT_EVENT_TYPE_CON_STATUS; + event.u.bt.event = BT_STATUS_A2DP_MEDIA_START; + event.u.bt.value = __this->a2dp_decoder_type; + sys_event_notify(&event); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式发起播放命令 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static int a2dp_media_packet_cmd_pp(void *p) +{ + if ((__this->exit_flag == 1) && (__this->sbc_packet_step == 1)) { + /* log_info("send pp "); */ + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_PLAY, 0, NULL); + } + return 0; +} + + +u8 bt_get_exit_flag() +{ + return __this->exit_flag; +} + +extern int a2dp_media_clear_packet_before_seqn(u16 seqn_number); +extern void *a2dp_media_fetch_packet(int *len, void *prev_packet); +static u16 slience_timer; +u16 clear_to_seqn; +void a2dp_slience_detect(void *p) +{ + int ingore_packet_num = (int)p; + int role = tws_api_get_role(); + int len; + + u8 *packet = a2dp_media_fetch_packet(&len, NULL); + if (!packet) { + return; + } + if (role == TWS_ROLE_MASTER) { + if (packet) { + u16 seqn = (packet[2] << 8) | packet[3]; + if (clear_to_seqn == 0) { + clear_to_seqn = seqn + ingore_packet_num; + g_printf("clear_to_seqn=%d\n", clear_to_seqn); + if (clear_to_seqn == 0) { + clear_to_seqn = 1; + } + a2dp_media_clear_packet_before_seqn(clear_to_seqn); + } + } + } + if (clear_to_seqn) { + bt_drop_a2dp_frame_start(); + __a2dp_drop_frame(NULL); + } + +} +void bt_start_a2dp_slience_detect(int ingore_packet_num) +{ + clear_to_seqn = 0; + if (slience_timer) { + sys_timer_del(slience_timer); + } + r_printf("bt_start_a2dp_slience_detect=%d", ingore_packet_num); + a2dp_slience_detect((void *)ingore_packet_num); + if (clear_to_seqn == 0) { + slience_timer = sys_timer_add((void *)ingore_packet_num, a2dp_slience_detect, 40); + } +} +void bt_stop_a2dp_slience_detect() +{ + if (slience_timer) { + sys_timer_del(slience_timer); + slience_timer = 0; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief tws后台回蓝牙模式 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void tws_local_back_to_bt_mode(u8 mode, u8 value) +{ + /* log_info("rx_tws_local_back_to_bt_mode=%d\n", mode); */ +#if (TCFG_DEC2TWS_ENABLE) + if (mode == TWS_BOX_NOTICE_A2DP_BACK_TO_BT_MODE) { + if (__this->tws_local_back_role == 1) { + localtws_set_wait_a2dp_start(1); + __this->tws_local_back_role = 0; + if (__this->back_mode_systime == 0) { + __this->cmd_flag = 1; + __this->back_mode_systime = sys_timeout_add(NULL, a2dp_media_packet_play_start, 1); + } + /* r_printf("tws_local_back_role ==role_new back mode_switch=%d\n", __this->back_mode_systime); */ + } + } else if (mode == TWS_BOX_A2DP_BACK_TO_BT_MODE_START) { + __this->tws_local_back_role = 0; + struct sys_event event; + event.type = SYS_BT_EVENT; + event.arg = (void *)SYS_BT_EVENT_TYPE_CON_STATUS; + event.u.bt.event = BT_STATUS_A2DP_MEDIA_START; + event.u.bt.value = value; + sys_event_notify(&event); + } else if (mode == TWS_BOX_EXIT_BT) { + __this->a2dp_start_flag = 0; + if (value == TWS_UNACTIVE_DEIVCE) { + __this->tws_local_back_role = 2; + if (tws_api_get_role() == TWS_ROLE_MASTER) { + log_debug("\n ----- master pause ------- \n"); + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_PAUSE, 0, NULL); + } + if (a2dp_dec_close()) { + bt_start_a2dp_slience_detect(300); + bt_drop_a2dp_frame_start(); + __a2dp_drop_frame(NULL); + } + if (bt_get_exit_flag()) { + __this->cmd_flag = 2; + } + /* __this->tws_local_back_role = 2; */ + /* log_debug("__this->cmd_flag=0x%x,%d\n", __this->tws_local_back_role, __this->cmd_flag); */ + app_task_switch_to(APP_BT_TASK); + } else { + __this->exiting = 0; + } + } else if (mode == TWS_BOX_ENTER_BT) { + __this->tws_local_back_role = 0; + if (!localtws_dec_close(1)) { + tws_api_local_media_trans_clear(); + } + } +#endif + +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 后台模式下sbc丢包加能量检测, 返回-INVALUE表示要丢掉此包数据 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int a2dp_media_packet_user_handler(u8 *data, u16 size) +{ + if ((get_call_status() != BT_CALL_HANGUP) || bt_phone_dec_is_running() || (__this->call_flag)) { + if (get_call_status() != BT_CALL_HANGUP) { + /* puts("call!=hangup"); */ + } + return -EINVAL; + } + + if (__this->tws_local_back_role == 2) { + /* putchar('$'); */ + return -EINVAL; + } + + if (app_var.goto_poweroff_flag) { + return -EINVAL; + } + + +#if TCFG_USER_TWS_ENABLE + if (is_tws_going_poweroff()) { + return -EINVAL; + } +#endif + + local_irq_disable(); + if (__this->exit_flag == 0) { + if ((!bt_media_is_running()) && (__this->sbc_packet_lose_cnt)) { + __this->sbc_packet_lose_cnt++; + if (__this->sbc_packet_lose_cnt > 10) { + __this->sbc_packet_lose_cnt = 0; + __this->cmd_flag = 0; + __this->sbc_packet_step = 0; + local_irq_enable(); + __this->a2dp_decoder_type = a2dp_media_packet_codec_type(data); + /* log_info("sbc lose over %d", __this->a2dp_decoder_type); */ + if (__this->back_mode_systime == 0) { + __this->back_mode_systime = sys_timeout_add(NULL, a2dp_media_packet_play_start, 1); + } + return 0; + } + } else { + __this->sbc_packet_lose_cnt = 0; + } + local_irq_enable(); + return 0; + } + u32 media_type = a2dp_media_packet_codec_type(data); + u32 cur_time = timer_get_ms(); + int energy = 0; + if (media_type == 0/* A2DP_CODEC_SBC */) {//后台返回蓝牙 + energy = sbc_energy_check(data, size); + } else { + if (a2dp_get_status() == BT_MUSIC_STATUS_STARTING) { + energy = 2000; + //其它格式不方便做能量检测。简易判断,该标志成立就直接认为是有效声音 + } + } + /* log_info("sbc_filter: %d ", energy); */ + if (__this->sbc_packet_step == 1) { + // 退出 + if ((cur_time > __this->no_sbc_packet_to) || ((cur_time > __this->sbc_packet_filter_to))) { + // 转换为后台模式 + log_debug("goto back mode \n"); + __this->sbc_packet_step = 2; + __this->no_sbc_packet_to = cur_time; + __this->sbc_packet_filter_to = cur_time + SBC_FILTER_TIME_MS; + __this->a2dp_decoder_type = a2dp_media_packet_codec_type(data); + } else { + // 还在退出 + /* log_info("exit,, "); */ + __this->no_sbc_packet_to = cur_time + NO_SBC_TIME_MS; + if (energy > 1000) { + __this->sbc_packet_filter_to = cur_time + SBC_ZERO_TIME_MS; + __this->sbc_packet_valid_cnt ++; + if (__this->sbc_packet_valid_cnt > __this->sbc_packet_valid_cnt_max) { + __this->sbc_packet_valid_cnt = 0; + if (__this->sbc_packet_valid_cnt_max < 80) { + __this->sbc_packet_valid_cnt_max += 20; + } else { + log_debug("goto back mode0 \n"); + __this->sbc_packet_step = 2; + __this->no_sbc_packet_to = cur_time; + __this->sbc_packet_filter_to = cur_time + SBC_FILTER_TIME_MS; + } + ///在退出的时候已经发送暂停 + /* sys_timeout_add(NULL, a2dp_media_packet_cmd_pp, 1); */ + } + } else { + __this->sbc_packet_valid_cnt = 0; + } + } + } else if (__this->sbc_packet_step == 2) { + // 后台 + if (cur_time >= __this->no_sbc_packet_to) { + // 新的开始 + if (energy > 1000) { + log_debug("new back mode \n"); +#if 0 // 超时太短,容易误触发返回蓝牙模式 + if (__this->tws_local_back_role) { + /* puts("tws_new_back_mode\n"); */ + __this->no_sbc_packet_to = cur_time + NO_SBC_TIME_MS * 2; + __this->sbc_packet_filter_to = cur_time + SBC_FILTER_TIME_MS / 4; + } else +#endif + { + __this->no_sbc_packet_to = cur_time + NO_SBC_TIME_MS; + __this->sbc_packet_filter_to = cur_time + SBC_FILTER_TIME_MS; + } + } else { + /* log_info("energy limit \n"); */ + } + } else { + /* log_info("bkm:%d, ", __this->sbc_packet_filter_to - cur_time); */ + if (__this->tws_local_back_role) { + __this->no_sbc_packet_to = cur_time + NO_SBC_TIME_MS * 2; + } else { + __this->no_sbc_packet_to = cur_time + NO_SBC_TIME_MS; + } + if (cur_time > __this->sbc_packet_filter_to) { + //过滤时间耗完 + __this->no_sbc_packet_to = cur_time; + if (energy > 1000) { + log_debug("start back mode \n"); + __this->cmd_flag = 1; + __this->tws_local_back_role = 0; + local_irq_enable(); + __this->a2dp_decoder_type = a2dp_media_packet_codec_type(data); + if (__this->back_mode_systime == 0) { + __this->back_mode_systime = sys_timeout_add(NULL, a2dp_media_packet_play_start, 1); + } + return -EINVAL; + } + } + } + } else { + local_irq_enable(); + return 0; + } + local_irq_enable(); + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙非后台模式退出蓝牙等待蓝牙状态可以退出 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void bt_no_background_exit_check(void *priv) +{ + if (bt_user_priv_var.auto_connection_timer) { + sys_timeout_del(bt_user_priv_var.auto_connection_timer); + bt_user_priv_var.auto_connection_timer = 0; + } + + if (__this->init_ok == 0) { + /* putchar('#'); */ + return; + } + + if (bt_audio_is_running()) { + /* putchar('$'); */ + return; + } + +#if TCFG_USER_BLE_ENABLE + bt_ble_exit(); +#endif + btstack_exit(); + log_info("bt_exit_check ok\n"); + __this->exit_flag = 1; + sys_timer_del(__this->timer); + __this->init_ok = 0; + __this->init_start = 0; + __this->timer = 0; + __this->exiting = 0; + set_stack_exiting(0); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙后台模式退出蓝牙 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static u8 bt_background_exit() +{ + u8 suepend_rx_bulk = 1; + __this->cmd_flag = 0; + __this->call_flag = 0; + + u32 cur_time = timer_get_ms(); + local_irq_disable(); + __this->exit_flag = 1; + __this->sbc_packet_step = 1; + __this->sbc_packet_valid_cnt = 0; + __this->sbc_packet_valid_cnt_max = 2; + __this->no_sbc_packet_to = cur_time + NO_SBC_TIME_MS; + __this->sbc_packet_filter_to = cur_time + SBC_ZERO_TIME_MS; + local_irq_enable(); + +#if (TCFG_DEC2TWS_ENABLE) + int state = tws_api_get_tws_state(); + suepend_rx_bulk = 0; + __this->tws_local_back_role = 0; + if (state & TWS_STA_SIBLING_CONNECTED) { + __this->tws_local_back_role = 1; + tws_api_sync_call_by_uuid('D', SYNC_CMD_BOX_INIT_EXIT_BT, 0);// delay不宜太长,避免两边结束时间差异大 + localtws_dec_close(1); + } else { + user_set_tws_box_mode(1); + } + /* r_printf("__this->tws_local_back_role=0x%x\n", __this->tws_local_back_role); */ +#endif + if (a2dp_dec_close()) { + bt_start_a2dp_slience_detect(300); + } + extern int btctrler_suspend(u8 suepend_rx_bulk); + btctrler_suspend(suepend_rx_bulk); + extern int bredr_suspend(); + bredr_suspend(); + +#if (TCFG_DEC2TWS_ENABLE) + if (state & TWS_STA_SIBLING_CONNECTED) { + __this->exiting = 1; + return -EINVAL; + } +#endif + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙后台模式关机,蓝牙关闭所有状态 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static u8 bt_background_poweroff_exit() +{ + __this->exiting = 1; + set_stack_exiting(1); + + +#if TCFG_USER_TWS_ENABLE + bt_tws_poweroff(); +#endif + + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL); + user_send_cmd_prepare(USER_CTRL_CONNECTION_CANCEL, 0, NULL); + user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL); + + if (__this->exit_flag) { + __this->sbc_packet_step = 0; + __this->no_sbc_packet_to = 0; + __this->sbc_packet_filter_to = 0; + __this->sbc_packet_lose_cnt = 1; + } + + if (__this->timer == 0) { + __this->tmr_cnt = 0; + __this->timer = sys_timer_add(NULL, bt_no_background_exit_check, 10); + /* printf("set exit timer\n"); */ + } + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙非后台模式退出模式 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static u8 bt_nobackground_exit() +{ + if (!__this->init_start) { + return -EINVAL; + } + + __this->exiting = 1; + set_stack_exiting(1); + __a2dp_drop_frame(NULL);//临时解决非后台退出杂音问题 +#if TCFG_USER_TWS_ENABLE + bt_tws_poweroff(); +#endif + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL); + user_send_cmd_prepare(USER_CTRL_CONNECTION_CANCEL, 0, NULL); + user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL); + + if (__this->timer == 0) { + __this->tmr_cnt = 0; + __this->timer = sys_timer_add(NULL, bt_no_background_exit_check, 10); + printf("set exit timer\n"); + } + + return -EINVAL; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙通话检测 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void esco_check_state(void *priv) +{ + /* if (bt_sco_state()) { */ + if (true == bt_phone_dec_is_running()) { + sys_timeout_add(NULL, esco_check_state, 20); + } else { +#if (TCFG_DEC2TWS_ENABLE) + extern bool get_tws_sibling_connect_state(void); + if (get_tws_sibling_connect_state()) { + if (tws_api_get_role() == TWS_ROLE_MASTER) { + bt_tws_api_push_cmd(SYNC_CMD_POWER_OFF_TOGETHER, TWS_SYNC_TIME_DO); + } + } else +#endif + { + sys_enter_soft_poweroff(NULL); + } + } +} + + +u8 bt_app_switch_exit_check() +{ + if ((get_call_status() == BT_CALL_OUTGOING) + || (get_call_status() == BT_CALL_ALERT) + || (get_call_status() == BT_CALL_INCOMING) + || (get_call_status() == BT_CALL_ACTIVE) + ) { + // 通话不退出 + return 0; + } + + if (__this->exit_flag) { + // 正在退出就不用重新设置 + // 避免快速调用两次导致发了两次pp,结束不了解码 + log_debug("exit flag "); +#if TCFG_BLUETOOTH_BACK_MODE + if ((app_var.goto_poweroff_flag == 0) && (__this->exiting == 1)) { + return 0; + } else { + return 1; + } +#else + return 1; +#endif + } + +#if PHONE_CALL_FORCE_POWEROFF + if (true == bt_phone_dec_is_running()) { + log_debug("bt_phone_dec_is_running"); + if (app_var.goto_poweroff_flag) { + user_send_cmd_prepare(USER_CTRL_DISCONN_SCO, 0, NULL); + sys_timeout_add(NULL, esco_check_state, 20); + } + app_var.goto_poweroff_flag = 0; + return 0; + } +#else + + if (__this->force_poweroff) { + if (true == bt_must_work()) { + user_send_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); + sys_timeout_add(NULL, esco_check_state, 20); + app_var.goto_poweroff_flag = 0; + return 0; + } + if (true == bt_phone_dec_is_running()) { + user_send_cmd_prepare(USER_CTRL_DISCONN_SCO, 0, NULL); + sys_timeout_add(NULL, esco_check_state, 20); + app_var.goto_poweroff_flag = 0; + return 0; + } + __this->force_poweroff = 0; + } + + if (true == bt_must_work()) { + log_debug("bt_must_work"); + app_var.goto_poweroff_flag = 0; + return 0; + } + + if (true == bt_phone_dec_is_running()) { + log_debug("bt_phone_dec_is_running"); + app_var.goto_poweroff_flag = 0; + return 0; + } + +#endif + return 1; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙退出模式 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int bt_app_exit(void) +{ + struct sys_event clear_key_event = {.type = SYS_KEY_EVENT, .arg = "key"}; + + log_info("bt_app_exit"); + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) + bt_emitter_mic_close(); +#endif + + __this->ignore_discon_tone = 1; + bt_drop_a2dp_frame_stop(); +#if (TCFG_BLUETOOTH_BACK_MODE == 0) + extern void app_protocol_exit(int handler_id); + app_protocol_exit(0); +#endif + /* __a2dp_drop_frame(NULL); */ + sys_key_event_disable(); + sys_event_clear(&clear_key_event); + sys_auto_shut_down_disable(); + tone_play_stop(); + UI_HIDE_CURR_WINDOW(); +#if TCFG_BLUETOOTH_BACK_MODE + if (app_var.goto_poweroff_flag == 0) { + return bt_background_exit(); + } else { + return bt_background_poweroff_exit(); + } +#else + return bt_nobackground_exit(); +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙后台进入模式初始化 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_background_init() +{ + if (__this->back_mode_systime) { + sys_timeout_del(__this->back_mode_systime); + __this->back_mode_systime = 0; + /* log_debug("__this->init_ok clear back_mode_systime\n"); */ + } +#if (TCFG_DEC2TWS_ENABLE) + int state = tws_api_get_tws_state(); + if (state & TWS_STA_SIBLING_CONNECTED) { + if (__this->cmd_flag != 2) { + if (__this->tws_local_to_bt_mode) { + tws_user_sync_box(TWS_BOX_A2DP_BACK_TO_BT_MODE_START, __this->a2dp_decoder_type); + } + log_debug("tx_SYNC_CMD_BOX_ENTER_BT\n"); + tws_api_sync_call_by_uuid('D', SYNC_CMD_BOX_ENTER_BT, 10); + } + } else { + /* user_set_tws_box_mode(2); */ + user_set_tws_box_mode(0); + } + __this->tws_local_to_bt_mode = 0; +#endif + local_irq_disable(); + __this->sbc_packet_step = 0; + __this->no_sbc_packet_to = 0; + __this->sbc_packet_filter_to = 0; + __this->sbc_packet_lose_cnt = 1; + __this->tws_local_back_role = 0; + local_irq_enable(); + extern void bredr_resume();//background resume + bredr_resume(); + void btctrler_resume(); + btctrler_resume(); + + bt_resume_deal(); + __this->cmd_flag = 0; + UI_SHOW_MENU(MENU_BT, 1000, 0, NULL); + +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙进入模式初始化(时钟和显示部分和变量) + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_task_init() +{ + clock_idle(BT_IDLE_CLOCK); + u32 sys_clk = clk_get("sys"); + bt_pll_para(TCFG_CLOCK_OSC_HZ, sys_clk, 0, 0); + + __this->ignore_discon_tone = 0; + __this->exiting = 0; + __this->wait_exit = 0; + __this->force_poweroff = 0 ; + __this->init_start = 0;//蓝牙协议栈已经开始初始化标志位 + + UI_SHOW_WINDOW(ID_WINDOW_BT); + UI_SHOW_MENU(MENU_BT, 1000, 0, NULL); + +#if TCFG_BLUETOOTH_BACK_MODE + if (__this->init_ok) { + __this->init_start = 1;//蓝牙协议栈已经开始初始化标志位 + /* 按键消息使能 */ + sys_key_event_enable();//第一次需要蓝牙初始化成功才开按键 不然会没有蓝牙后台 + } +#else + sys_key_event_enable(); +#endif + +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙进入模式 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_task_start() +{ + if (__this->exit_flag == 0) { + return; + } + + __this->exit_flag = 0; + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) + if (bt_emitter_stu_get() == true) { + bt_emitter_mic_open(); + } +#endif + +#if TCFG_BLUETOOTH_BACK_MODE + if (__this->init_ok) { + bt_background_init(); + return; + } +#else + /*注释掉app_var.goto_poweroff_flag = 0; + *为了防止关机过程中运行至此处时关机标志 + *被清0导致不能正常关机的情况*/ + /* app_var.goto_poweroff_flag = 0; */ +#endif + bt_function_select_init(); + bredr_handle_register(); + btstack_init(); +#if TCFG_USER_TWS_ENABLE + tws_profile_init(); +#endif + + BT_STATE_INIT(); + + __this->init_start = 1;//蓝牙协议栈已经开始初始化 + + sys_auto_shut_down_enable(); + sys_auto_sniff_controle(1, NULL); + +#if TCFG_BLUETOOTH_BACK_MODE + sys_key_event_enable();//蓝牙带后台情况第一次开按键需要在协议栈初始化之后 +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙模式退出 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_task_close() +{ + tone_play_stop(); + if (__this->timer) { + sys_timer_del(__this->timer); + __this->timer = 0; + } + sys_auto_shut_down_disable(); + __this->auto_exit_limit_time = (u32) - 1; + bt_app_exit(); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙直接开关 + @param + @return + @note 如果想后台开机不需要进蓝牙,可以在poweron模式 + 直接调用这个函数初始化蓝牙 +*/ +/*----------------------------------------------------------------------------*/ + +void bt_direct_init() +{ +#if TCFG_BLUETOOTH_BACK_MODE + if (__this->bt_direct_init) { + return; + } + log_info(" bt_direct_init \n"); + + u32 sys_clk = clk_get("sys"); + bt_pll_para(TCFG_CLOCK_OSC_HZ, sys_clk, 0, 0); + + __this->ignore_discon_tone = 0; + __this->bt_direct_init = 1; + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) + if (bt_emitter_stu_get() == true) { + bt_emitter_mic_open(); + } +#endif + bt_function_select_init(); + bredr_handle_register(); + btstack_init(); +#if TCFG_USER_TWS_ENABLE + tws_profile_init(); +#endif + + BT_STATE_INIT(); + + /* 按键消息使能 */ + sys_key_event_enable(); + sys_auto_shut_down_enable(); + sys_auto_sniff_controle(1, NULL); +#endif +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙 退出蓝牙等待蓝牙状态可以退出 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_direct_close_check(void *priv) +{ +#if TCFG_BLUETOOTH_BACK_MODE + if (bt_user_priv_var.auto_connection_timer) { + sys_timeout_del(bt_user_priv_var.auto_connection_timer); + bt_user_priv_var.auto_connection_timer = 0; + } + + if (__this->init_ok == 0) { + /* putchar('#'); */ + return; + } + + if (bt_audio_is_running()) { + /* putchar('$'); */ + return; + } + +#if TCFG_USER_BLE_ENABLE + bt_ble_exit(); +#endif +#if TCFG_USER_TWS_ENABLE + bt_tws_poweroff(); +#endif + btstack_exit(); + log_info(" bt_direct_close_check ok\n"); + sys_timer_del(__this->timer); + __this->init_ok = 0; + __this->init_start = 0; + __this->timer = 0; + __this->bt_direct_init = 0; + set_stack_exiting(0); +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙后台直接关闭 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_direct_close(void) +{ +#if TCFG_BLUETOOTH_BACK_MODE + if (__this->init_ok == 0) { + /* putchar('#'); */ + return; + } + + log_info(" bt_direct_close"); + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) + bt_emitter_mic_close(); +#endif + + __this->ignore_discon_tone = 1; + sys_auto_shut_down_disable(); + + set_stack_exiting(1); + __a2dp_drop_frame(NULL);//临时解决非后台退出杂音问题 + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL); + user_send_cmd_prepare(USER_CTRL_CONNECTION_CANCEL, 0, NULL); + user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL); + + if (__this->timer == 0) { + __this->tmr_cnt = 0; + __this->timer = sys_timer_add(NULL, bt_direct_close_check, 10); + printf("set exit timer\n"); + } + +#endif +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙 关闭bredr + @param + @return + @note 主要把bredr 运行状态都关闭即可 +*/ +/*----------------------------------------------------------------------------*/ +void bt_close_bredr() +{ + __this->bt_close_bredr = 1; + if (bt_user_priv_var.auto_connection_timer) { + sys_timeout_del(bt_user_priv_var.auto_connection_timer); + bt_user_priv_var.auto_connection_timer = 0; + } + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_DISABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL); + user_send_cmd_prepare(USER_CTRL_CONNECTION_CANCEL, 0, NULL); + user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL); + user_send_cmd_prepare(USER_CTRL_INQUIRY_CANCEL, 0, NULL); + +#if TCFG_USER_TWS_ENABLE + tws_cancle_all_noconn(); +#endif + sys_auto_sniff_controle(0, NULL); + btctrler_task_close_bredr(); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙 开启bredr + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_init_bredr() +{ + __this->bt_close_bredr = 0; + btctrler_task_init_bredr(); + bt_wait_phone_connect_control(1); + sys_auto_sniff_controle(1, NULL); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙 开关a2dp + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bredr_a2dp_open_and_close() +{ + if (get_curr_channel_state() & A2DP_CH) { + puts("start to disconnect a2dp "); + user_send_cmd_prepare(USER_CTRL_DISCONN_A2DP, 0, NULL); + } else { + puts("start to connect a2dp "); + user_send_cmd_prepare(USER_CTRL_CONN_A2DP, 0, NULL); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙 开关hfp + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void bredr_hfp_open_and_close() +{ + if (get_curr_channel_state() & HFP_CH) { + user_send_cmd_prepare(USER_CTRL_HFP_DISCONNECT, 0, NULL); + } else { + user_send_cmd_prepare(USER_CTRL_HFP_CMD_BEGIN, 0, NULL); + } +} + +u8 bt_get_task_state() +{ + return __this->exiting; +} + +#endif diff --git a/apps/soundbox/task_manager/bt/bt_tws.c b/apps/soundbox/task_manager/bt/bt_tws.c new file mode 100644 index 0000000..ea18f0a --- /dev/null +++ b/apps/soundbox/task_manager/bt/bt_tws.c @@ -0,0 +1,3011 @@ + +/************************************************************* + + 此文件函数主要是蓝牙tws 功能处理 + + +tws已有配对,启动链接,对方要在被链接状态 +int bt_open_tws_conn(u16 timeout) + +tws已经连接上,只断开tws链接 +void bt_disconnect_tws_conn() + +tws链接上,取消tws配对信息,并且断开链接 +void bt_tws_remove_tws_pair() + +tws发起搜索链接,对方要在被链接状态 +int bt_tws_start_search_and_pair() + +tws 回链手机、tws被搜索链接、被手机搜索链接、tws链接等状态切换 +客户可以在这个函数里面根据自己链接需求修改 +static void connect_and_connectable_switch(void *_sw) + +客户的链接需求可以根据各种情况来处理 +根据 gtws.state 状态来判断需要做那种操作 + + +**************************************************************/ + + + +#include "system/includes.h" +#include "media/includes.h" +#include "device/vm.h" +#include "tone_player.h" + +#include "app_config.h" +#include "app_task.h" + +#include "user_cfg.h" + +#include "btcontroller_config.h" +#include "btstack/avctp_user.h" +#include "btstack/btstack_task.h" +#include "classic/hci_lmp.h" + +#include "bt/bt_tws.h" +#include "classic/tws_pair.h" +#include "bt/bt_ble.h" +#include "bt/bt.h" + + +#include "asm/pwm_led.h" +#include "asm/charge.h" +#include "app_charge.h" +#include "ui_manage.h" + +#include "app_chargestore.h" +#include "app_online_cfg.h" +#include "app_main.h" +#include "app_power_manage.h" +#include "audio_config.h" + +#include "audio_dec.h" +#include "tone_player.h" + +#include "bt_common.h" +#include "soundbox.h" + +#if TCFG_APP_BT_EN + + +#ifdef CONFIG_NEW_BREDR_ENABLE +#define CONFIG_NEW_QUICK_CONN +#endif + + +#if TCFG_USER_TWS_ENABLE + +#define LOG_TAG_CONST BT_TWS +#define LOG_TAG "[BT-TWS]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +#define BT_TWS_UNPAIRED 0x0001 +#define BT_TWS_PAIRED 0x0002 +#define BT_TWS_WAIT_SIBLING_SEARCH 0x0004 +#define BT_TWS_SEARCH_SIBLING 0x0008 +#define BT_TWS_CONNECT_SIBLING 0x0010 +#define BT_TWS_SIBLING_CONNECTED 0x0020 +#define BT_TWS_PHONE_CONNECTED 0x0040 +#define BT_TWS_POWER_ON 0x0080 +#define BT_TWS_TIMEOUT 0x0100 +#define BT_TWS_AUDIO_PLAYING 0x0200 + + +struct tws_user_var { + u8 addr[6]; + u16 state; + s16 auto_pair_timeout; //tws 自动连接时间 + int pair_timer; //tws 链接时间 + u32 connect_time; // 回链手机时间计时 + u8 device_role; //tws 记录那个是active device 活动设备,音源控制端 + u8 bt_task; ///标志对箱在bt task情况,BIT(0):local BIT(1):remote +}; + +struct tws_user_var gtws; + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) +typedef struct { + u8 miss_flag: 1; + u8 exchange_bat: 2; + u8 poweron_flag: 1; + u8 reserver: 4; +} icon_ctl_t; +static icon_ctl_t ble_icon_contrl; +#endif + + +static u32 local_us_time = 0; +static u32 local_instant_us_time = 0; +static u8 poweroff_sametime_flag = 0; +static u16 poweroff_sametime_timer_id = 0; +static u8 tws_wair_pair_time = 0; + +static u8 tws_going_poweroff = 0; + + +#if CONFIG_TWS_DISCONN_NO_RECONN +u8 tws_detach_by_remove_key = 0; +#endif + + +///记录tws是否在蓝牙模式 +#define TWS_LOCAL_IN_BT() (gtws.bt_task |=BIT(0)) +#define TWS_LOCAL_OUT_BT() (gtws.bt_task &=~BIT(0)) +#define TWS_REMOTE_IN_BT() (gtws.bt_task |=BIT(1)) +#define TWS_REMOTE_OUT_BT() (gtws.bt_task &=~BIT(1)) + +static void connect_and_connectable_switch(void *_sw); +static void search_and_connectable_switch(void *_sw); +static void bt_tws_connect_sibling(int timeout); + +u8 is_tws_going_poweroff() +{ + return tws_going_poweroff; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 判断tws是否都在蓝牙模式 + @param 无 + @return 1:在蓝牙模式 0:不在蓝牙模式 + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 is_tws_all_in_bt() +{ +#if (TCFG_DEC2TWS_ENABLE) + int state = tws_api_get_tws_state(); + if (state & TWS_STA_SIBLING_CONNECTED) { + if ((gtws.bt_task & 0x03) == 0x03) { + return 1; + } + return 0; + } +#endif + return 1; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 判断tws是否为活动端 + @param 无 + @return 1:活动端 0:非活动端 + @note 音源输入端为活动端 +*/ +/*----------------------------------------------------------------------------*/ +u8 is_tws_active_device(void) +{ + /* log_info("\n ------ tws device ------ %x \n",gtws.device_role); */ + int state = tws_api_get_tws_state(); + if (state & TWS_STA_SIBLING_CONNECTED) { + if (gtws.device_role == TWS_ACTIVE_DEIVCE) { + return 1; + } + return 0; + } + return 1; +} + +u8 tws_network_audio_was_started(void) +{ + if (gtws.state & BT_TWS_AUDIO_PLAYING) { + return 1; + } + + return 0; +} + +void tws_network_local_audio_start(void) +{ + gtws.state &= ~BT_TWS_AUDIO_PLAYING; +} + +bool get_tws_sibling_connect_state(void) +{ + if (tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED) { + return TRUE; + } + /* if (gtws.state & BT_TWS_SIBLING_CONNECTED) { */ + /* return TRUE; */ + /* } */ + return FALSE; +} + + +bool get_tws_phone_connect_state(void) +{ + if (gtws.state & BT_TWS_PHONE_CONNECTED) { + return TRUE; + } + return FALSE; +} + +#if CONFIG_TWS_POWEROFF_SAME_TIME +enum { + FROM_HOST_POWEROFF_CNT_ENOUGH = 1, + FROM_TWS_POWEROFF_CNT_ENOUGH, + POWEROFF_CNT_ENOUGH, +}; + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 同时关机 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void poweroff_sametime_timer(void *priv) +{ + log_info("poweroff_sametime_timer\n"); + int state = tws_api_get_tws_state(); + if (!(state & TWS_STA_SIBLING_CONNECTED)) { + sys_enter_soft_poweroff(NULL); + return; + } + if (priv == NULL || poweroff_sametime_flag == POWEROFF_CNT_ENOUGH) { + poweroff_sametime_timer_id = sys_timeout_add((void *)1, poweroff_sametime_timer, 500); + } else { + poweroff_sametime_timer_id = 0; + } +} + +static void poweroff_sametime_timer_init(void) +{ + if (poweroff_sametime_timer_id) { + return; + } + + poweroff_sametime_timer_id = sys_timeout_add(NULL, poweroff_sametime_timer, 500); +} +#endif + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 同步执行发送命令函数 + @param cmd:命令 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tws_sync_call_fun(int cmd) +{ + struct sys_event event; + + event.type = SYS_BT_EVENT; + event.arg = (void *)SYS_BT_EVENT_FROM_TWS; + + event.u.bt.event = TWS_EVENT_SYNC_FUN_CMD; + event.u.bt.args[0] = 0; + event.u.bt.args[1] = 0; + event.u.bt.args[2] = cmd; + sys_event_notify(&event); +} + +TWS_SYNC_CALL_REGISTER(tws_tone_sync) = { + .uuid = 'T', + .func = tws_sync_call_fun, +}; + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 同步执行发送命令函数,可区分发起段 + @param cmd:命令 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tws_sync_call_tranid_fun(int cmd) +{ + struct sys_event event; + + event.type = SYS_BT_EVENT; + event.arg = (void *)SYS_BT_EVENT_FROM_TWS; + + event.u.bt.event = TWS_EVENT_SYNC_FUN_TRANID; + event.u.bt.args[0] = 0; + event.u.bt.args[1] = 0; + event.u.bt.args[2] = cmd; + + sys_event_notify(&event); +} + +TWS_SYNC_CALL_REGISTER(tws_tranid_sync) = { + .uuid = 'D', + .func = tws_sync_call_tranid_fun, +}; + +u32 get_local_us_time(u32 *instant_time) +{ + *instant_time = local_instant_us_time; + return local_us_time; +} + +int bt_tws_api_push_cmd(int priv, int delay_ms) +{ + return tws_api_sync_call_by_uuid('T', priv, delay_ms); +} + +u16 tws_host_get_battery_voltage() +{ + return get_vbat_level(); +} + +int tws_host_channel_match(char remote_channel) +{ + /*r_printf("tws_host_channel_match: %c, %c\n", remote_channel, + bt_tws_get_local_channel());*/ + +#if (CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_MASTER_AS_LEFT) + return 1; +#endif + if (remote_channel != bt_tws_get_local_channel() || remote_channel == 'U') { + return 1; + } +#if CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_LEFT_START_PAIR || \ + CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_RIGHT_START_PAIR + if (gtws.state & BT_TWS_SEARCH_SIBLING) { + return 1; + } +#endif + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 获取本地左右声道值 + @param 无 + @return channel + @note +*/ +/*----------------------------------------------------------------------------*/ +char tws_host_get_local_channel() +{ + char channel; + +#if (CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_RIGHT_START_PAIR) + if (gtws.state & BT_TWS_SEARCH_SIBLING) { + return 'R'; + } +#elif (CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_LEFT_START_PAIR) + if (gtws.state & BT_TWS_SEARCH_SIBLING) { + return 'L'; + } +#endif + channel = bt_tws_get_local_channel(); + if (channel != 'R') { + channel = 'L'; + } + /*y_printf("tws_host_get_local_channel: %c\n", channel);*/ + + return channel; +} + + +/* + * + * */ +u8 auto_pair_code[6] = {0x34, 0x66, 0x33, 0x87, 0x09, 0x42}; + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 设置自动回连的识别码 6个byte + @param 无 + @return 配对码 + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 *tws_set_auto_pair_code(void) +{ + u16 code = bt_get_tws_device_indicate(NULL); + auto_pair_code[0] = code >> 8; + auto_pair_code[1] = code & 0xff; + return auto_pair_code; +} +#if CONFIG_TWS_PAIR_MODE == CONFIG_TWS_PAIR_BY_FAST_CONN +u8 tws_auto_pair_enable = 1; +#else +u8 tws_auto_pair_enable = 0; +#endif + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 读取vm记忆里面的远端设备 + @param 无 + @return 0:没有找到 -ENOENT:读取成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static u8 tws_get_sibling_addr(u8 *addr) +{ + u8 all_ff[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + int len = syscfg_read(CFG_TWS_REMOTE_ADDR, addr, 6); + if (len != 6 || !memcmp(addr, all_ff, 6)) { + return -ENOENT; + } + return 0; +} + +void lmp_hci_write_local_address(const u8 *addr); + +/* + * 获取左右耳信息 + * 'L': 左耳 + * 'R': 右耳 + * 'U': 未知 + */ +char bt_tws_get_local_channel() +{ + char channel = 'U'; + + syscfg_read(CFG_TWS_CHANNEL, &channel, 1); + + return channel; +} + +int get_bt_tws_connect_status() +{ + if (gtws.state & BT_TWS_SIBLING_CONNECTED) { + return 1; + } + + return 0; +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 来电同步播放铃声 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void tws_sync_phone_num_play_wait(void *priv) +{ + log_debug("tws_sync_phone_num_play_wait\n"); + if (bt_user_priv_var.phone_con_sync_num_ring) { + return; + } + if (bt_user_priv_var.phone_num_flag) { + if (tws_api_get_role() == TWS_ROLE_SLAVE) { + tws_api_sync_call_by_uuid('T', SYNC_CMD_PHONE_NUM_TONE, TWS_SYNC_TIME_DO * 2); + } else { //从机超时还没获取到 + phone_ring_play_start(); + } + } else { + /*电话号码还没有获取到,定时查询*/ + if (bt_user_priv_var.get_phone_num_timecnt > 300) { + bt_user_priv_var.get_phone_num_timecnt = 0; + tws_api_sync_call_by_uuid('T', SYNC_CMD_PHONE_SYNC_NUM_RING_TONE, TWS_SYNC_TIME_DO); + } else { + bt_user_priv_var.phone_timer_id = sys_timeout_add(NULL, tws_sync_phone_num_play_wait, 10); + } + } + bt_user_priv_var.get_phone_num_timecnt++; + +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 来电同步报号 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +int bt_tws_sync_phone_num(void *priv) +{ + int state = tws_api_get_tws_state(); + if ((state & TWS_STA_SIBLING_CONNECTED) && (state & TWS_STA_PHONE_CONNECTED)) { + log_debug("bt_tws_sync_phone_num\n"); +#if BT_PHONE_NUMBER + bt_user_priv_var.get_phone_num_timecnt = 0; + if (tws_api_get_role() == TWS_ROLE_SLAVE && bt_user_priv_var.phone_con_sync_num_ring) { //从机同步播来电ring,不在发起sync_play + /* log_debug("phone_con_sync_num_ring_ing return\n"); */ + return 1; + } +#endif + if (tws_api_get_role() == TWS_ROLE_SLAVE || bt_user_priv_var.phone_con_sync_num_ring) { + + if (!(state & TWS_STA_MONITOR_START)) { + /* log_debug(" not monitor ring_tone\n"); */ + /* tws_api_sync_call_by_uuid('T', SYNC_CMD_PHONE_RING_TONE, TWS_SYNC_TIME_DO * 5); */ + bt_user_priv_var.phone_timer_id = sys_timeout_add(NULL, (void (*)(void *priv))bt_tws_sync_phone_num, 10); + return 1; + } +#if BT_PHONE_NUMBER + if (bt_user_priv_var.phone_con_sync_num_ring) { + /* log_debug("<<<<<<<<<< 0) { + timeout = 4000 + (rand32() % 4 + 1) * 500; + bt_user_priv_var.auto_connection_counter -= timeout ; + + bt_close_tws_wait_pair(); + bt_close_phone_wait_pair(); + bt_close_tws_conn(); + + /* tws_api_cancle_wait_pair(); + tws_api_cancle_create_connection(); */ + + user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR, 6, + bt_user_priv_var.auto_connection_addr); + } else { + bt_user_priv_var.auto_connection_counter = 0; + + BT_STATE_CANCEL_PAGE_SCAN(); + + if (gtws.state & BT_TWS_POWER_ON) { + /* + * 开机回连,获取下一个设备地址 + */ + if (get_current_poweron_memory_search_index(NULL)) { + bt_init_ok_search_index(); + goto __again ; + } + gtws.state &= ~BT_TWS_POWER_ON; + } + } + + return timeout; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 开启tws被发现链接的状态 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static u32 tws_wait_pair_and_wait_conn(u8 sw) +{ + int timeout = 0; + if (tws_remote_state_check()) { + timeout = 1000 + (rand32() % 4 + 1) * 500; + } else { + timeout = 2000 + (rand32() % 4 + 1) * 500; + } + + /* user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL); */ + extern void bredr_close_all_scan(); + bredr_close_all_scan(); + if (sw) { + bt_open_tws_wait_pair_all_way(); + } else { + bt_open_tws_wait_pair(); + bt_open_tws_wait_conn(0); + } + + if (sw != 2) { + bt_open_phone_wait_pair(); + } + + BT_STATE_SET_PAGE_SCAN_ENABLE(); + + return timeout; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 开启tws 链接 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static u32 tws_creat_connection() +{ + int timeout = 0; + if (tws_remote_state_check()) { + timeout = 4000; + } else { + timeout = 1000 + (rand32() % 4 + 1) * 500; + } + tws_remote_state_clear(); + bt_open_tws_conn(0); + return timeout; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 自动连接 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static u32 tws_pari_by_auto() +{ + int timeout = 0; +#if CONFIG_TWS_PAIR_MODE == CONFIG_TWS_PAIR_BY_AUTO + timeout = 2000 + (rand32() % 4 + 1) * 500; + tws_auto_pair_enable = 1; + tws_le_acc_generation_init(); + tws_api_create_connection(0); +#endif + return timeout; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 被手机发现链接、tws被搜索链接、tws已配对链接状态切换 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void connect_and_connectable_switch(void *_sw) +{ + int timeout = 0; + int sw = (int)_sw; + + gtws.pair_timer = 0; + + + +#if CONFIG_TWS_DISCONN_NO_RECONN + if (tws_detach_by_remove_key) { + return; + } +#endif + + + + log_info("switch: %d, state = %x, %d\n", sw, gtws.state, + bt_user_priv_var.auto_connection_counter); + +#if CONFIG_TWS_PAIR_MODE == CONFIG_TWS_PAIR_BY_AUTO + if (tws_auto_pair_enable == 1) { + tws_auto_pair_enable = 0; + tws_le_acc_generation_init(); + } +#endif + + /* if (tws_remote_state_check()) { + if (sw == 0) { + sw = 1; + } else if (sw == 3) { + sw = 2; + } + } */ + + + if (sw == 0) { //判断是否需要回链手机 + timeout = tws_page_phone(); + if (!timeout) { /// 不需要回链手机 + sw = 1; + } + } + + if (sw == 1) { + timeout = tws_wait_pair_and_wait_conn(1); + } else if (sw == 2) { + timeout = tws_creat_connection(); + } else if (sw == 3) { + timeout = tws_pari_by_auto(); + } + + /// 如果tws 没有配对信息 + int end_sw = 3; + if (gtws.state & BT_TWS_UNPAIRED) { + end_sw = 1; +#if CONFIG_TWS_PAIR_MODE == CONFIG_TWS_PAIR_BY_AUTO + end_sw = 3; +#endif + } else if (gtws.state & BT_TWS_PAIRED) { + /* //// 如果通过按键断开tws后不需要tws马上回链, */ + /* end_sw = 1; */ + + // 如果通过tws断开后需要tws马上回链, + end_sw = 2; +#ifdef CONFIG_TWS_AUTO_PAIR_WITHOUT_UNPAIR + end_sw = 3; +#endif + } + + if (++sw > end_sw) { + sw = 0; + } + + /* r_printf("++ %d \n",sw); */ + + gtws.pair_timer = sys_timeout_add((void *)sw, connect_and_connectable_switch, timeout); + +} + + +#if CONFIG_TWS_DISCONN_NO_RECONN +static void connect_and_connectable_switch_by_noreconn(void *_sw) +{ + int timeout = 0; + int sw = (int)_sw; + + gtws.pair_timer = 0; + + + if (tws_detach_by_remove_key == 0) { + return; + } + + bt_close_tws_wait_pair(); + + + if (sw == 0) { + bt_tws_wait_sibling_connect(0); + timeout = 2000 + ((rand32() % 10) * 200); + } else if (sw == 1) { + + //bt_open_phone_wait_pair(); + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_ENABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); + + timeout = 3000 + ((rand32() % 10) * 200); + } + + if (++sw > 1) { + sw = 0; + } + + //printf("++ %d \n",sw); + + gtws.pair_timer = sys_timeout_add((void *)sw, connect_and_connectable_switch_by_noreconn, timeout); + +} +#endif + + + +#if CONFIG_TWS_PAIR_BY_BOTH_SIDES +static int tws_search_both_side() +{ + int timeout = 0; +__again: + if (bt_user_priv_var.auto_connection_counter > 0) { + timeout = 4000 + (rand32() % 4 + 1) * 500; + bt_user_priv_var.auto_connection_counter -= timeout ; + + bt_close_tws_wait_pair(); + bt_close_phone_wait_pair(); + bt_close_tws_conn(); + + /* tws_api_cancle_wait_pair(); + tws_api_cancle_create_connection(); */ + + user_send_cmd_prepare(USER_CTRL_START_CONNEC_VIA_ADDR, 6, + bt_user_priv_var.auto_connection_addr); + } else { + bt_user_priv_var.auto_connection_counter = 0; + + BT_STATE_CANCEL_PAGE_SCAN(); + + if (gtws.state & BT_TWS_POWER_ON) { + /* + * 开机回连,获取下一个设备地址 + */ + if (get_current_poweron_memory_search_index(NULL)) { + bt_init_ok_search_index(); + goto __again ; + } + gtws.state &= ~BT_TWS_POWER_ON; + } + } + + return timeout; +} + +void tws_remote_search_working(void) +{ + tws_wair_pair_time = 5000; +} + +static void search_and_connectable_switch(void *_sw) +{ + int timeout = 0; + int sw = (int)_sw; + + bt_tws_close_search_and_pair(); + + if (sw == 0) { + timeout = tws_wait_pair_and_wait_conn(2); + } else if (sw == 1) { + + printf("search cnt %d\n", bt_user_priv_var.search_counter); + + if ((tws_wair_pair_time) && (bt_user_priv_var.search_counter > 0)) { + printf("here11\n"); + timeout = 5000; + tws_wait_pair_and_wait_conn(2); + } else { + if (bt_user_priv_var.search_counter > 0) { + printf("here22\n"); + tws_api_search_sibling_by_code(bt_get_tws_device_indicate(NULL), 15000); + timeout = 1000 + (rand32() % 4 + 1) * 500; + + } else { + printf("here33\n"); + tws_api_search_sibling_by_code(bt_get_tws_device_indicate(NULL), 2000); + return; + } + } + bt_user_priv_var.search_counter--; + } + + tws_wair_pair_time = 0; + + if (++sw > 1) { + sw = 0; + } + + r_printf("++ search sw %d \n", sw); + + gtws.pair_timer = sys_timeout_add((void *)sw, search_and_connectable_switch, timeout); + +} +#endif +#endif + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 自动配对状态定时切换函数 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void __bt_tws_auto_pair_switch(void *priv) +{ + u32 timeout; + int sw = (int)priv; + + gtws.pair_timer = 0; + + log_debug("bt_tws_auto_pair: %d, %d\n", gtws.auto_pair_timeout, bt_user_priv_var.auto_connection_counter); + + if (gtws.auto_pair_timeout < 0 && bt_user_priv_var.auto_connection_counter > 0) { + gtws.auto_pair_timeout = 4000; + timeout = bt_tws_connect_phone(); + } else { + + timeout = 1000 + ((rand32() % 10) * 200); + + gtws.auto_pair_timeout -= timeout; + + if (sw == 0) { + tws_api_wait_pair_by_code(bt_get_tws_device_indicate(NULL), bt_get_local_name(), 0); + } else if (sw == 1) { + bt_tws_search_and_pair(); + } + + if (++sw > 1) { + sw = 0; + } + } + + gtws.pair_timer = sys_timeout_add((void *)sw, __bt_tws_auto_pair_switch, timeout); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 自动配对状态定时切换函数 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void bt_tws_auto_pair_switch(int timeout) +{ + bt_tws_delete_pair_timer(); + + gtws.auto_pair_timeout = timeout; + __bt_tws_auto_pair_switch(NULL); +} + +void __set_sbc_cap_bitpool(u8 sbc_cap_bitpoola); + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws tws链接配对码 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static u8 set_channel_by_code_or_res(void) +{ + u8 count = 0; + char channel = 0; + char last_channel = 0; +#if (CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_EXTERN_UP_AS_LEFT) + gpio_set_direction(CONFIG_TWS_CHANNEL_CHECK_IO, 1); + gpio_set_pull_down(CONFIG_TWS_CHANNEL_CHECK_IO, 1); + gpio_set_die(CONFIG_TWS_CHANNEL_CHECK_IO, 1); + for (int i = 0; i < 5; i++) { + os_time_dly(2); + if (gpio_read(CONFIG_TWS_CHANNEL_CHECK_IO)) { + count++; + } + } + channel = (count >= 3) ? 'L' : 'R'; +#elif (CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_EXTERN_DOWN_AS_LEFT) + gpio_set_direction(CONFIG_TWS_CHANNEL_CHECK_IO, 1); + gpio_set_die(CONFIG_TWS_CHANNEL_CHECK_IO, 1); + gpio_set_pull_up(CONFIG_TWS_CHANNEL_CHECK_IO, 1); + for (int i = 0; i < 5; i++) { + os_time_dly(2); + if (gpio_read(CONFIG_TWS_CHANNEL_CHECK_IO)) { + count++; + } + } + channel = (count >= 3) ? 'R' : 'L'; +#elif (CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_AS_LEFT_CHANNEL) + channel = 'L'; +#elif (CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_AS_RIGHT_CHANNEL) + channel = 'R'; +#elif (CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_SECECT_BY_CHARGESTORE) + syscfg_read(CFG_CHARGESTORE_TWS_CHANNEL, &channel, 1); +#endif + +#if CONFIG_TWS_SECECT_CHARGESTORE_PRIO + syscfg_read(CFG_CHARGESTORE_TWS_CHANNEL, &channel, 1); +#endif + + if (channel) { + syscfg_read(CFG_TWS_CHANNEL, &last_channel, 1); + if (channel != last_channel) { + syscfg_write(CFG_TWS_CHANNEL, &channel, 1); + } + tws_api_set_local_channel(channel); + return 1; + } + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws tws初始化 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +__BANK_INIT_ENTRY +int bt_tws_poweron() +{ + int err; + u8 addr[6]; + char channel; + + +#if CONFIG_TWS_DISCONN_NO_RECONN + tws_detach_by_remove_key = 0; +#endif + + + + gtws.state = BT_TWS_POWER_ON; + gtws.connect_time = 0; + gtws.device_role = TWS_ACTIVE_DEIVCE; + TWS_LOCAL_IN_BT(); + +#if CONFIG_TWS_PAIR_BY_BOTH_SIDES + bt_set_pair_code_en(0); +#endif + +#if CONFIG_TWS_USE_COMMMON_ADDR + tws_api_common_addr_en(1); +#else + tws_api_common_addr_en(0); + tws_api_auto_role_switch_disable(); +#endif + +#if CONFIG_TWS_PAIR_ALL_WAY + tws_api_pair_all_way(1); +#endif + + /* __set_sbc_cap_bitpool(38); */ + + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) + memset(&ble_icon_contrl, 0, sizeof(icon_ctl_t)); + ble_icon_contrl.poweron_flag = 1; +#endif + +#if (TCFG_DEC2TWS_ENABLE) + tws_api_auto_role_switch_disable(); +#endif + + + err = tws_get_sibling_addr(addr); + if (err == 0) { + /* + * 获取到对方地址, 开始连接 + */ + log_info("\n ---------have tws info----------\n"); + gtws.state |= BT_TWS_PAIRED; + + BT_STATE_TWS_INIT(1); + + tws_api_set_sibling_addr(addr); + if (set_channel_by_code_or_res() == 0) { + channel = bt_tws_get_local_channel(); + tws_api_set_local_channel(channel); + } + +#if TCFG_TEST_BOX_ENABLE + if (chargestore_get_testbox_status()) { + } else +#endif + { +#ifdef CONFIG_NEW_QUICK_CONN + if (bt_tws_get_local_channel() == 'L') { + syscfg_read(CFG_TWS_LOCAL_ADDR, addr, 6); + } + tws_api_set_quick_connect_addr(addr); +#endif + ////<有tws配对信息,开启tws链接 + bt_tws_connect_sibling(CONFIG_TWS_CONNECT_SIBLING_TIMEOUT); + } + + } else { + log_info("\n ---------no tws info----------\n"); + + BT_STATE_TWS_INIT(0); + + + gtws.state |= BT_TWS_UNPAIRED; + if (set_channel_by_code_or_res() == 0) { + tws_api_set_local_channel('U'); + } +#if TCFG_TEST_BOX_ENABLE + if (chargestore_get_testbox_status()) { + } else +#endif + { + +#if CONFIG_TWS_PAIR_MODE == CONFIG_TWS_PAIR_BY_AUTO + /* + * 未配对, 开始自动配对 + */ +#ifdef CONFIG_NEW_BREDR_ENABLE + tws_api_set_quick_connect_addr(tws_set_auto_pair_code()); +#else + tws_auto_pair_enable = 1; + tws_le_acc_generation_init(); +#endif + bt_tws_connect_sibling(6); + +#else + /* + * 未配对, 等待发起配对 + */ + bt_tws_connect_and_connectable_switch(); +#endif + } + } + +#ifndef CONFIG_NEW_BREDR_ENABLE + tws_remote_state_clear(); +#endif + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 手机开始连接 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_tws_hci_event_connect() +{ + log_info("bt_tws_hci_event_connect: %x\n", gtws.state); + + gtws.state &= ~BT_TWS_POWER_ON; + + bt_user_priv_var.auto_connection_counter = 0; + + bt_tws_delete_pair_timer(); + sys_auto_shut_down_disable(); + +#ifndef CONFIG_NEW_BREDR_ENABLE + tws_remote_state_clear(); +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 手机链接上 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +int bt_tws_phone_connected() +{ + int state; + + log_info("bt_tws_phone_connected: %x\n", gtws.state); + +#if TCFG_TEST_BOX_ENABLE + if (chargestore_get_testbox_status()) { + return 1; + } +#endif + + gtws.state |= BT_TWS_PHONE_CONNECTED; + + //// tws 没有配对过 + if (gtws.state & BT_TWS_UNPAIRED) { +#if (CONFIG_TWS_PAIR_ALL_WAY == 1) + +#if CONFIG_TWS_USE_COMMMON_ADDR + +#else + if (get_call_status() == BT_CALL_HANGUP) { ///不在通话状态,开启tws 被搜索链接状态 + bt_open_tws_wait_pair(); + } +#endif +#endif + return 0; + } + + if (!(gtws.state & BT_TWS_SIBLING_CONNECTED)) { ///tws 已经配对,但是没哟链接,开启被链接 + bt_tws_wait_sibling_connect(0); + return 0; + } + + /* + * 获取tws状态,如果正在播歌或打电话则返回1,不播连接成功提示音 + */ + + if (tws_api_get_role() == TWS_ROLE_MASTER) { + bt_tws_api_push_cmd(SYNC_CMD_LED_PHONE_CONN_STATUS, TWS_SYNC_TIME_DO - 500); //此时手机已经连接上,同步PHONE_CONN状态 + + /* bt_tws_sync_volume(); */ + state = tws_api_get_tws_state(); + if (state & (TWS_STA_SBC_OPEN | TWS_STA_ESCO_OPEN) || + (get_call_status() != BT_CALL_HANGUP)) { + return 1; + } + + /* log_info("[SYNC] TONE SYNC"); */ + bt_tws_api_push_cmd(SYNC_CMD_PHONE_CONN_TONE, TWS_SYNC_TIME_DO); + } + + return 1; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 手机断开链接 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_tws_phone_disconnected() +{ + gtws.state &= ~BT_TWS_PHONE_CONNECTED; + + y_printf("**** bt_tws_phone_disconnected: %x\n", gtws.state); + + sys_auto_shut_down_enable(); + + bt_user_priv_var.auto_connection_counter = 0; + if (!(gtws.state & BT_TWS_SIBLING_CONNECTED)) { + bt_tws_connect_and_connectable_switch(); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 回链手机超时 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_tws_phone_page_timeout() +{ + log_info("bt_tws_phone_page_timeout: %x\n", gtws.state); + + bt_tws_phone_disconnected(); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 链接手机超时 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_tws_phone_connect_timeout() +{ + log_debug("bt_tws_phone_connect_timeout: %x, %d\n", gtws.state, gtws.pair_timer); + + gtws.state &= ~BT_TWS_PHONE_CONNECTED; + + /* + * 跟手机超时断开,如果对耳未连接则优先连接对耳 + */ + if (gtws.state & (BT_TWS_UNPAIRED | BT_TWS_SIBLING_CONNECTED)) { + bt_tws_connect_and_connectable_switch(); + } else { + bt_tws_connect_sibling(CONFIG_TWS_CONNECT_SIBLING_TIMEOUT); + } +} + +void bt_get_vm_mac_addr(u8 *addr); + +void bt_page_scan_for_test() +{ + u8 local_addr[6]; + + int state = tws_api_get_tws_state(); + + /* log_info("\n\n\n\n -------------bt test page scan\n"); */ + + bt_tws_delete_pair_timer(); + + bt_close_phone_wait_pair(); + bt_close_tws_wait_pair(); + bt_close_tws_conn(); + + user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL); + + tws_api_detach(TWS_DETACH_BY_POWEROFF); + + user_send_cmd_prepare(USER_CTRL_POWER_OFF, 0, NULL); + + if (0 == get_total_connect_dev()) { + /* log_info("<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>\n"); */ + bt_get_vm_mac_addr(local_addr); + //log_info("local_adr\n"); + //put_buf(local_addr,6); + lmp_hci_write_local_address(local_addr); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); + } + + gtws.state = 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 关机 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +int bt_tws_poweroff() +{ + log_info("bt_tws_poweroff\n"); + + bt_tws_delete_pair_timer(); + + bt_close_phone_wait_pair(); + bt_close_tws_wait_pair(); + bt_close_tws_conn(); + + user_send_cmd_prepare(USER_CTRL_PAGE_CANCEL, 0, NULL); + + tws_api_detach(TWS_DETACH_BY_POWEROFF); + + tws_profile_exit(); + + if (tws_api_get_tws_state() & TWS_STA_SIBLING_DISCONNECTED) { + return 1; + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 通话过程中tws开启被链接 或者链接 + @param esco_flag 1:开始通话 0:结束通话 + @return 无 + @note 开始通话的时候要把tws等待链接的状态关闭,通话结束后在开启 +*/ +/*----------------------------------------------------------------------------*/ +extern int tws_api_cancle_wait_pair_internal(); +void tws_page_scan_deal_by_esco(u8 esco_flag) +{ + if (gtws.state & BT_TWS_UNPAIRED) { ///tws 没配对 +#if (CONFIG_TWS_PAIR_ALL_WAY == 1) + if (esco_flag) { + bt_tws_delete_pair_timer(); + bt_close_tws_wait_pair(); + } else { + bt_open_tws_wait_pair(); + + } +#endif + return; + } + + + if (esco_flag) { + bt_tws_delete_pair_timer(); + gtws.state &= ~BT_TWS_CONNECT_SIBLING; + bt_close_tws_conn(); + tws_api_connect_in_esco(); + /* log_debug("close scan\n"); */ + } + + if (!esco_flag && !(gtws.state & BT_TWS_SIBLING_CONNECTED)) { + /* log_debug("open scan22\n"); */ + tws_api_cancle_connect_in_esco(); + bt_open_tws_conn(0); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 解除配对,清掉对方地址信息和本地声道信息 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void bt_tws_remove_pairs() +{ + u8 mac_addr[6]; + char channel = 'U'; + char tws_channel = 0; + int role = 0; + +#if (CONFIG_TWS_USE_COMMMON_ADDR == 0) + syscfg_write(VM_TWS_ROLE, &role, 1); +#endif + + memset(mac_addr, 0xFF, 6); + syscfg_write(CFG_TWS_COMMON_ADDR, mac_addr, 6); + syscfg_write(CFG_TWS_REMOTE_ADDR, mac_addr, 6); +#if CONFIG_TWS_USE_COMMMON_ADDR + bt_reset_and_get_mac_addr(mac_addr); + delete_last_device_from_vm(); +#else + syscfg_read(CFG_BT_MAC_ADDR, mac_addr, 6); +#endif + + + lmp_hci_write_local_address(mac_addr); + +#if (CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_LEFT_START_PAIR) ||\ + (CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_RIGHT_START_PAIR) ||\ + (CONFIG_TWS_CHANNEL_SELECT == CONFIG_TWS_MASTER_AS_LEFT) + +#if CONFIG_TWS_SECECT_CHARGESTORE_PRIO + syscfg_read(CFG_CHARGESTORE_TWS_CHANNEL, &tws_channel, 1); +#endif + if ((tws_channel != 'L') && (tws_channel != 'R')) { + syscfg_write(CFG_TWS_CHANNEL, &channel, 1); + tws_api_set_local_channel(channel); + } +#endif + + tws_api_clear_connect_aa(); + ////取消配对后开启tws被搜索链接和被手机搜索链接 + bt_tws_wait_pair_and_phone_connect(); +} + +#if TCFG_ADSP_UART_ENABLE +extern void adsp_deal_sibling_uart_command(u8 type, u8 cmd); +void tws_sync_uart_command(u8 type, u8 cmd) +{ + struct tws_sync_info_t sync_adsp_uart_command; + sync_adsp_uart_command.type = TWS_SYNC_ADSP_UART_CMD; + sync_adsp_uart_command.u.adsp_cmd[0] = type; + sync_adsp_uart_command.u.adsp_cmd[1] = cmd; + tws_api_send_data_to_sibling((u8 *)&sync_adsp_uart_command, sizeof(sync_adsp_uart_command)); +} +#endif + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws tws音量同步 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void bt_tws_vol_sync(void *_data, u16 len, bool rx) +{ + if (rx) { + u8 *data = (u8 *)_data; + app_audio_set_volume(APP_AUDIO_STATE_MUSIC, data[0], 1); + app_audio_set_volume(APP_AUDIO_STATE_CALL, data[1], 1); + log_debug("---- bt_tws_sync_volume %d %d \n", data[0], data[1]); + log_debug("vol: %d", app_audio_get_volume(APP_AUDIO_CURRENT_STATE)); + } + +} + + +REGISTER_TWS_FUNC_STUB(app_vol_sync_stub) = { + .func_id = TWS_FUNC_ID_VOL_SYNC, + .func = bt_tws_vol_sync, +}; + +void bt_tws_sync_volume() +{ + u8 data[2]; + + data[0] = app_audio_get_volume(APP_AUDIO_STATE_MUSIC); + data[1] = app_audio_get_volume(APP_AUDIO_STATE_CALL); + + log_debug("---- tx bt_tws_sync_volume %d %d \n", data[0], data[1]); + + tws_api_send_data_to_sibling(data, 2, TWS_FUNC_ID_VOL_SYNC); +} + +void send_bt_event2local(u8 value) +{ + struct sys_event event; + event.type = SYS_BT_EVENT; + event.arg = (void *)SYS_BT_EVENT_FORM_SELF; + event.u.bt.event = 0; + event.u.bt.value = value; + sys_event_notify(&event); +} + +static void bt_tws_reverb_state_sync(void *_data, u16 len, bool rx) +{ + if (rx) { + u8 *data = (u8 *)_data; + app_var.reverb_status = data[0]; + extern void send_bt_event2local(u8 value); + send_bt_event2local(app_var.reverb_status); + /* log_debug("----rx bt_tws_reverb_state_sync %d \n", data[0]); */ + } + +} + +REGISTER_TWS_FUNC_STUB(reverb_sync_stub) = { + .func_id = TWS_FUNC_ID_REVERB_SYNC, + .func = bt_tws_reverb_state_sync, +}; + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws tws同步同步开启混响 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void bt_tws_sync_reverb_state(u8 status) +{ + u8 data[1]; + + app_var.reverb_status = status; + data[0] = app_var.reverb_status; + tws_api_send_data_to_sibling(data, 1, TWS_FUNC_ID_REVERB_SYNC); +} + +void tws_conn_auto_test(void *p) +{ + cpu_reset(); +} + +extern u32 audio_bt_time_read(u16 *bt_phase, s32 *bt_bitoff); + +static void bt_tws_box_sync(void *_data, u16 len, bool rx) +{ +#if (TCFG_DEC2TWS_ENABLE) + if (rx) { + u8 *data = (u8 *)_data; + if (data[0] == TWS_BOX_NOTICE_A2DP_BACK_TO_BT_MODE + || data[0] == TWS_BOX_A2DP_BACK_TO_BT_MODE_START) { + tws_local_back_to_bt_mode(data[0], data[1]); + /* u32 bt_tmr = 0; */ + /* memcpy(&bt_tmr, &data[2], 4); */ + /* a2dp_dec_output_set_start_bt_time(bt_tmr); */ + } + } +#endif +} + +REGISTER_TWS_FUNC_STUB(app_box_sync_stub) = { + .func_id = TWS_FUNC_ID_BOX_SYNC, + .func = bt_tws_box_sync, +}; + + +void tws_user_sync_box(u8 cmd, u8 value) +{ +#if (TCFG_DEC2TWS_ENABLE) + u8 data[6]; + data[0] = cmd; + data[1] = value; + u32 bt_tmr = audio_bt_time_read(NULL, NULL) + 1000; + memcpy(&data[2], &bt_tmr, 4); + tws_api_send_data_to_sibling(data, sizeof(data), TWS_FUNC_ID_BOX_SYNC); + /* if (cmd == TWS_BOX_NOTICE_A2DP_BACK_TO_BT_MODE */ + /* || cmd == TWS_BOX_A2DP_BACK_TO_BT_MODE_START) { */ + /* a2dp_dec_output_set_start_bt_time(bt_tmr); */ + /* } */ +#else + u8 data[2]; + + data[0] = cmd; + data[1] = value; + tws_api_send_data_to_sibling(data, 2, TWS_FUNC_ID_BOX_SYNC); +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 手机链接上 local tws设置 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tws_local_connected(u8 state, u8 role) +{ + //state&TWS_STA_LOCAL_TWS_OPEN 对方是否开启local_tws + log_info("tws_conn_state=0x%x\n", state); + + u8 cur_task = app_check_curr_task(APP_BT_TASK); + + if (cur_task) { + TWS_LOCAL_IN_BT(); + } else { + TWS_LOCAL_OUT_BT(); + } + + if (state & TWS_STA_LOCAL_TWS_OPEN) { + TWS_REMOTE_OUT_BT(); + } else { + TWS_REMOTE_IN_BT(); + } + + + if (state & TWS_STA_LOCAL_TWS_OPEN) { +#if (TCFG_DEC2TWS_ENABLE) + user_set_tws_box_mode(1); +#endif + clear_current_poweron_memory_search_index(0); + bt_user_priv_var.auto_connection_counter = 0; + if (!cur_task) { + gtws.device_role = TWS_ACTIVE_DEIVCE; + log_debug("\n ------ tws active device 0 ------ \n"); + } else { + gtws.device_role = TWS_UNACTIVE_DEIVCE; + log_debug("\n ------ tws unactive device0 ------ \n"); + } + } else if (!cur_task) { + clear_current_poweron_memory_search_index(0); + bt_user_priv_var.auto_connection_counter = 0; + gtws.device_role = TWS_ACTIVE_DEIVCE; + log_debug("\n ------ tws active device 1 ------ \n"); + } else { + if (role == TWS_ROLE_MASTER) { + gtws.device_role = TWS_ACTIVE_DEIVCE; + log_debug("\n ------ tws active device 2 ------ \n"); + } else { + gtws.device_role = TWS_UNACTIVE_DEIVCE; + log_debug("\n ------ tws unactive device2 ------ \n"); + } + + } +} + +static void tws_connect_ble_adv(u8 phone_link_connection) +{ +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) + bt_ble_icon_slave_en(1); + if (tws_api_get_role() == TWS_ROLE_MASTER) { + //master enable + log_debug("master do icon_open\n"); + bt_ble_set_control_en(1); + + if (phone_link_connection) { + bt_ble_icon_open(ICON_TYPE_RECONNECT); + } else { +#if (TCFG_CHARGESTORE_ENABLE && !CONFIG_NO_DISPLAY_BUTTON_ICON) + bt_ble_icon_open(ICON_TYPE_RECONNECT); +#else + if (ble_icon_contrl.poweron_flag) { //上电标记 + if (bt_user_priv_var.auto_connection_counter > 0) { + //有回连手机动作 + /* g_printf("ICON_TYPE_RECONNECT"); */ + /* bt_ble_icon_open(ICON_TYPE_RECONNECT); //没按键配对的话,等回连成功的时候才显示电量。如果在这里显示,手机取消配对后耳机开机,会显示出按键的界面*/ + } else { + //没有回连,设可连接 + /* g_printf("ICON_TYPE_INQUIRY"); */ + bt_ble_icon_open(ICON_TYPE_INQUIRY); + } + + } +#endif + } + } else { + //slave disable + bt_ble_set_control_en(0); + } + ble_icon_contrl.poweron_flag = 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws tws链接上 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void tws_event_connected(struct bt_event *evt) +{ + u8 addr[4][6]; + int state; + int pair_suss = 0; + int role = evt->args[0]; + int phone_link_connection = evt->args[1]; + int reason = evt->args[2]; + char channel = 0; + log_info("----- tws_event_pair_suss: %x\n", gtws.state); + + clr_tws_local_back_role(); + + +#if CONFIG_TWS_DISCONN_NO_RECONN + tws_detach_by_remove_key = 0; +#endif + + +#if CONFIG_TWS_PAIR_BY_BOTH_SIDES + bt_set_pair_code_en(0); +#endif + +#if (CONFIG_TWS_USE_COMMMON_ADDR == 0) + lmp_hci_write_local_address(bt_get_mac_addr()); +#endif + + + syscfg_read(CFG_TWS_REMOTE_ADDR, addr[0], 6); + syscfg_read(CFG_TWS_COMMON_ADDR, addr[1], 6); + tws_api_get_sibling_addr(addr[2]); + tws_api_get_local_addr(addr[3]); + + /* + * 记录对方地址 + */ + if (memcmp(addr[0], addr[2], 6)) { + syscfg_write(CFG_TWS_REMOTE_ADDR, addr[2], 6); + pair_suss = 1; + log_info("rec tws addr\n"); + } + if (memcmp(addr[1], addr[3], 6)) { + syscfg_write(CFG_TWS_COMMON_ADDR, addr[3], 6); + pair_suss = 1; + log_info("rec comm addr\n"); + } + +#if (CONFIG_TWS_USE_COMMMON_ADDR == 0) + syscfg_write(VM_TWS_ROLE, &role, 1); +#endif + + if (pair_suss) { + + gtws.state = BT_TWS_PAIRED; + +#if CONFIG_TWS_USE_COMMMON_ADDR + extern void bt_update_mac_addr(u8 * addr); + bt_update_mac_addr((void *)addr[3]); +#endif + } + + /* + * 记录左右声道 + */ + channel = tws_api_get_local_channel(); + if (channel != bt_tws_get_local_channel()) { + syscfg_write(CFG_TWS_CHANNEL, &channel, 1); + } + log_debug("tws_local_channel: %c\n", channel); + + BT_STATE_TWS_CONNECTED(pair_suss, addr[3]); + +#if CONFIG_TWS_PAIR_MODE == CONFIG_TWS_PAIR_BY_AUTO + if (tws_auto_pair_enable) { + tws_auto_pair_enable = 0; + tws_le_acc_generation_init(); + } +#endif + +#ifdef CONFIG_NEW_BREDR_ENABLE + if (channel == 'L') { + syscfg_read(CFG_TWS_LOCAL_ADDR, addr[2], 6); + } + tws_api_set_quick_connect_addr(addr[2]); +#else + tws_api_set_connect_aa(channel); + tws_remote_state_clear(); +#endif + if (reason & (TWS_STA_ESCO_OPEN | TWS_STA_SBC_OPEN)) { + if (role == TWS_ROLE_SLAVE) { + gtws.state |= BT_TWS_AUDIO_PLAYING; + } + } + + if (!phone_link_connection || + (reason & (TWS_STA_ESCO_OPEN | TWS_STA_SBC_OPEN))) { + pwm_led_clk_set(PWM_LED_CLK_BTOSC_24M); + } + /* + * TWS连接成功, 主机尝试回连手机 + */ + if (gtws.connect_time) { + if (role == TWS_ROLE_MASTER) { + bt_user_priv_var.auto_connection_counter = gtws.connect_time; + } + gtws.connect_time = 0; + } + + gtws.state &= ~BT_TWS_TIMEOUT; + gtws.state |= BT_TWS_SIBLING_CONNECTED; + + state = evt->args[2]; + if (role == TWS_ROLE_MASTER) { + if (!phone_link_connection) { //!(gtws.state & TWS_STA_PHONE_CONNECTED)) { //还没连上手机 + log_info("[SYNC] LED SYNC"); + bt_tws_api_push_cmd(SYNC_CMD_LED_TWS_CONN_STATUS, TWS_SYNC_TIME_DO - 500); + } else { + bt_tws_api_push_cmd(SYNC_CMD_LED_PHONE_CONN_STATUS, TWS_SYNC_TIME_DO - 500); + } + if (bt_get_exit_flag() || ((get_call_status() == BT_CALL_HANGUP) && !(state & TWS_STA_SBC_OPEN))) { //通话状态不播提示音 + log_info("[SYNC] TONE SYNC"); + bt_tws_api_push_cmd(SYNC_CMD_TWS_CONN_TONE, TWS_SYNC_TIME_DO / 2); + } +#if BT_SYNC_PHONE_RING + if (get_call_status() == BT_CALL_INCOMING) { + if (bt_user_priv_var.phone_ring_flag && !bt_user_priv_var.inband_ringtone) { + log_debug("<<<<<<<<args[0]; + int phone_link_connection = evt->args[1]; + int reason = evt->args[2]; +#if TCFG_TEST_BOX_ENABLE + if (chargestore_get_testbox_status()) { + return; + } +#endif + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) + bt_ble_icon_slave_en(0); +#endif + + clr_tws_local_back_role(); + + if (gtws.state & BT_TWS_UNPAIRED) { + /* + * 配对超时 + */ +#if CONFIG_TWS_PAIR_BY_BOTH_SIDES + bt_set_pair_code_en(0); +#endif + + + gtws.state &= ~BT_TWS_SEARCH_SIBLING; +#if CONFIG_TWS_PAIR_MODE == CONFIG_TWS_PAIR_BY_CLICK + tws_api_set_local_channel(bt_tws_get_local_channel()); + lmp_hci_write_local_address(gtws.addr); +#endif + bt_tws_connect_and_connectable_switch(); + } else { + if (phone_link_connection) { ///如果手机连接上,就开启等待链接 + bt_tws_wait_sibling_connect(0); + } else { + if (gtws.state & BT_TWS_TIMEOUT) { + gtws.state &= ~BT_TWS_TIMEOUT; + gtws.connect_time = bt_user_priv_var.auto_connection_counter; + bt_user_priv_var.auto_connection_counter = 0; + } + bt_tws_connect_and_connectable_switch(); + } + } + +#if (CONFIG_TWS_USE_COMMMON_ADDR == 0) + u8 mac_addr[6]; + syscfg_read(CFG_BT_MAC_ADDR, mac_addr, 6); + lmp_hci_write_local_address(mac_addr); +#endif + +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 断开链接 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void tws_event_connection_detach(struct bt_event *evt) +{ + u8 mac_addr[6]; + int role = evt->args[0]; + int phone_link_connection = evt->args[1]; + int reason = evt->args[2]; + + clr_tws_local_back_role(); + +#if (TCFG_DEC2TWS_ENABLE) + if (app_check_curr_task(APP_BT_TASK)) { + //tws断开时清除local_tws标志,防止tws重新配对后状态错误 + user_set_tws_box_mode(0); + // close localtws dec + localtws_dec_close(0); + } +#endif + + gtws.device_role = TWS_ACTIVE_DEIVCE; + app_power_set_tws_sibling_bat_level(0xff, 0xff); + +#if TCFG_CHARGESTORE_ENABLE + chargestore_set_sibling_chg_lev(0xff); +#endif + + if ((!a2dp_get_status()) && (get_call_status() == BT_CALL_HANGUP)) { //如果当前正在播歌,切回RC会导致下次从机开机回连后灯状态不同步 + pwm_led_clk_set((!TCFG_LOWPOWER_BTOSC_DISABLE) ? PWM_LED_CLK_RC32K : PWM_LED_CLK_BTOSC_24M); + //pwm_led_clk_set(PWM_LED_CLK_RC32K); + } + +#if TCFG_TEST_BOX_ENABLE + if (chargestore_get_testbox_status()) { + return; + } +#endif + + if (phone_link_connection) { + ui_update_status(STATUS_BT_CONN); + extern void power_event_to_user(u8 event); + power_event_to_user(POWER_EVENT_POWER_CHANGE); + user_send_cmd_prepare(USER_CTRL_HFP_CMD_UPDATE_BATTARY, 0, NULL); //对耳断开后如果手机还连着,主动推一次电量给手机 + } else { + ui_update_status(STATUS_BT_TWS_DISCONN); + } + + if ((gtws.state & BT_TWS_SIBLING_CONNECTED) && (!app_var.goto_poweroff_flag)) { +#if CONFIG_TWS_POWEROFF_SAME_TIME + extern u8 poweroff_sametime_flag; + if (!app_var.goto_poweroff_flag && !poweroff_sametime_flag && !phone_link_connection && (reason != TWS_DETACH_BY_REMOVE_PAIRS)) { /*关机不播断开提示音*/ + tone_play_by_path(tone_table[IDEX_TONE_TWS_DISCONN], 1); + } +#else + if (!app_var.goto_poweroff_flag && !phone_link_connection && (reason != TWS_DETACH_BY_REMOVE_PAIRS)) { + tone_play_by_path(tone_table[IDEX_TONE_TWS_DISCONN], 1); + } +#endif + gtws.state &= ~BT_TWS_SIBLING_CONNECTED; + +#if (CONFIG_TWS_USE_COMMMON_ADDR == 0) + syscfg_read(CFG_BT_MAC_ADDR, mac_addr, 6); + lmp_hci_write_local_address(mac_addr); +#endif + } + + if (reason == TWS_DETACH_BY_REMOVE_PAIRS) { + gtws.state = BT_TWS_UNPAIRED; + log_debug("<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>\n"); + + if (!phone_link_connection) { + bt_open_tws_wait_pair(); + } else { +#if (CONFIG_TWS_PAIR_ALL_WAY == 1) + bt_open_tws_wait_pair(); +#endif + } + + return; + } + + if (get_esco_coder_busy_flag()) { + tws_api_connect_in_esco(); + return; + } + + //非测试盒在仓测试,直连蓝牙 + if (reason == TWS_DETACH_BY_TESTBOX_CON) { + log_debug(">>>>>>>>>>>>>>>>TWS_DETACH_BY_TESTBOX_CON<<<<<<<<<<<<<<<<<<<\n"); + gtws.state &= ~BT_TWS_PAIRED; + gtws.state |= BT_TWS_UNPAIRED; + //syscfg_read(CFG_BT_MAC_ADDR, mac_addr, 6); + if (!phone_link_connection) { +#if CONFIG_TWS_USE_COMMMON_ADDR + get_random_number(mac_addr, 6); + lmp_hci_write_local_address(mac_addr); +#endif + + bt_tws_wait_pair_and_phone_connect(); + } + return; + } + + +#if CONFIG_TWS_DISCONN_NO_RECONN + if (reason == TWS_DETACH_BY_REMOVE_NO_RECONN) { + tws_detach_by_remove_key = 1; + if ((tws_api_get_tws_state() & TWS_STA_PHONE_CONNECTED)) { + bt_tws_wait_sibling_connect(0); + } else { + connect_and_connectable_switch_by_noreconn(0); + } + + return; + } +#endif + + + + + if (phone_link_connection) { + bt_tws_wait_sibling_connect(0); + } else { + if (reason == TWS_DETACH_BY_SUPER_TIMEOUT) { + if (role == TWS_ROLE_SLAVE) { + gtws.state |= BT_TWS_TIMEOUT; + gtws.connect_time = bt_user_priv_var.auto_connection_counter; + bt_user_priv_var.auto_connection_counter = 0; + } + bt_tws_connect_sibling(6); + } else { + bt_tws_connect_and_connectable_switch(); + } + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 手机断开链接 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void tws_event_phone_link_detach(struct bt_event *evt) +{ + + int reason = evt->args[2]; +#if TCFG_TEST_BOX_ENABLE + if (chargestore_get_testbox_status()) { + break; + } +#endif + + sys_auto_shut_down_enable(); + + if ((reason != 0x08) && (reason != 0x0b)) { + bt_user_priv_var.auto_connection_counter = 0; + } else { + if (reason == 0x0b) { + bt_user_priv_var.auto_connection_counter = (8 * 1000); + } + } + + +#if (TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV) + if (reason == 0x0b) { + //CONNECTION ALREADY EXISTS + ble_icon_contrl.miss_flag = 1; + } else { + ble_icon_contrl.miss_flag = 0; + } +#endif + + bt_tws_connect_and_connectable_switch(); + + +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws tws 清除配对信息 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void tws_event_remove_pairs(struct bt_event *evt) +{ + tone_play_by_path(tone_table[IDEX_TONE_TWS_DISCONN], 1); + bt_tws_remove_pairs(); + app_power_set_tws_sibling_bat_level(0xff, 0xff); +#if TCFG_CHARGESTORE_ENABLE + chargestore_set_sibling_chg_lev(0xff); +#endif + pwm_led_clk_set((!TCFG_LOWPOWER_BTOSC_DISABLE) ? PWM_LED_CLK_RC32K : PWM_LED_CLK_BTOSC_24M); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 拨号 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tws_event_cmd_phone_num_tone() +{ + if (bt_user_priv_var.phone_con_sync_num_ring) { + return; + } + if (tws_api_get_role() == TWS_ROLE_SLAVE) { + if (bt_user_priv_var.phone_timer_id) { + sys_timeout_del(bt_user_priv_var.phone_timer_id); + bt_user_priv_var.phone_timer_id = 0; + } + } + if (bt_user_priv_var.phone_ring_flag) { + phone_num_play_timer(NULL); + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 铃声 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tws_event_cmd_phone_ring_tone() +{ + if (bt_user_priv_var.phone_ring_flag) { + if (bt_user_priv_var.phone_con_sync_ring) { + if (phone_ring_play_start()) { + bt_user_priv_var.phone_con_sync_ring = 0; + if (tws_api_get_role() == TWS_ROLE_MASTER) { + //播完一声来电铃声之后,关闭aec、msbc_dec之后再次同步播来电铃声 + /* bt_tws_api_push_cmd(SYNC_CMD_PHONE_RING_TONE, TWS_SYNC_TIME_DO * 2 + 400); */ + } + } + } else { + phone_ring_play_start(); + } + } +} + + +static void tws_event_cmd_sync_num_ring_tone() +{ + if (bt_user_priv_var.phone_ring_flag) { + if (phone_ring_play_start()) { + if (tws_api_get_role() == TWS_ROLE_MASTER) { + //播完一声来电铃声之后,关闭aec、msbc_dec之后再次同步播来电铃声 + bt_user_priv_var.phone_con_sync_ring = 0; + /* bt_tws_api_push_cmd(SYNC_CMD_PHONE_RING_TONE, TWS_SYNC_TIME_DO * 2 + 400); */ + } + bt_user_priv_var.phone_con_sync_num_ring = 1; + + } + } +} + +static void tws_event_cmd_led_tws_conn_status() +{ + pwm_led_mode_set(PWM_LED_ALL_OFF); + ui_update_status(STATUS_BT_TWS_CONN); +} + +static void tws_event_cmd_led_phone_conn_status() +{ + pwm_led_mode_set(PWM_LED_ALL_OFF); + ui_update_status(STATUS_BT_CONN); +} + +static void tws_event_cmd_led_phone_disconn_status() +{ + ui_update_status(STATUS_BT_TWS_CONN); + if (!app_var.goto_poweroff_flag) { /*关机不播断开提示音*/ + /* tone_play(TONE_DISCONN); */ + if (is_tws_all_in_bt()) { + tone_play_by_path(tone_table[IDEX_TONE_BT_DISCONN], 1); + } + } +} + +static void tws_event_cmd_max_vol() +{ + +#if TCFG_MAX_VOL_PROMPT + tone_play_by_path(tone_table[IDEX_TONE_MAX_VOL], 0); +#endif +} + +static void tws_event_cmd_earphone_charge_start() +{ + if (a2dp_get_status() != BT_MUSIC_STATUS_STARTING) { + /* g_printf("TWS MUSIC PLAY"); */ + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_PLAY, 0, NULL); + } +} + +static void tws_event_cmd_irsensor_event_near() +{ + if (a2dp_get_status() != BT_MUSIC_STATUS_STARTING) { + /* g_printf("TWS MUSIC PLAY"); */ + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_PLAY, 0, NULL); + } +} + + +static void tws_event_cmd_irsensor_event_far() +{ + if (a2dp_get_status() == BT_MUSIC_STATUS_STARTING) { + /* r_printf("STOP...\n"); */ + user_send_cmd_prepare(USER_CTRL_AVCTP_OPID_PAUSE, 0, NULL); + } +} + + +void tws_event_cmd_mode_change(void) +{ + if (get_bt_init_status() && (bt_get_task_state() == 0)) { +#if TWFG_APP_POWERON_IGNORE_DEV + if ((timer_get_ms() - app_var.start_time) > TWFG_APP_POWERON_IGNORE_DEV) +#endif//TWFG_APP_POWERON_IGNORE_DEV + + { + printf("KEY_CHANGE_MODE\n"); + app_task_switch_next(); + } + } +} + +extern void sys_enter_soft_poweroff(void *priv); +static void tws_poweroff_same_time_tone_end(void *priv, int flag) +{ + //提示音结束, 才进入关机流程 + u32 index = (u32)priv; + switch (index) { + case IDEX_TONE_POWER_OFF: + ///提示音播放结束, 启动播放器播放 + sys_enter_soft_poweroff(NULL); + break; + default: + printf("%s callback err!!!!!!\n", __FUNCTION__); + break; + } +} + +static void tws_poweroff_same_time_deal(void) +{ + ///先播放提示音, 保证同时播放 + + tws_going_poweroff = 1; + + int ret = tone_play_with_callback_by_name(tone_table[IDEX_TONE_POWER_OFF], 1, + tws_poweroff_same_time_tone_end, (void *)IDEX_TONE_POWER_OFF); + if (ret) { + sys_enter_soft_poweroff(NULL); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws 主从同步调用函数处理 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tws_event_sync_fun_cmd(struct bt_event *evt) +{ + int reason = evt->args[2]; + switch (reason) { + case SYNC_CMD_TWS_CONN_TONE: + tone_play_by_path(tone_table[IDEX_TONE_TWS_CONN], 1); + break; + case SYNC_CMD_PHONE_CONN_TONE: + tone_play_by_path(tone_table[IDEX_TONE_BT_CONN], 1); + break; + case SYNC_CMD_PHONE_NUM_TONE: + tws_event_cmd_phone_num_tone(); + break; + case SYNC_CMD_PHONE_RING_TONE: + tws_event_cmd_phone_ring_tone(); + break; + case SYNC_CMD_PHONE_SYNC_NUM_RING_TONE: + tws_event_cmd_sync_num_ring_tone(); + break; + + case SYNC_CMD_LED_TWS_CONN_STATUS: + tws_event_cmd_led_tws_conn_status(); + break; + case SYNC_CMD_LED_PHONE_CONN_STATUS: + tws_event_cmd_led_phone_conn_status(); + break; + case SYNC_CMD_LED_PHONE_DISCONN_STATUS: + tws_event_cmd_led_phone_disconn_status(); + break; + + case SYNC_CMD_POWER_OFF_TOGETHER: + //sys_enter_soft_poweroff(NULL); + tws_poweroff_same_time_deal(); + break; + case SYNC_CMD_MAX_VOL: + tws_event_cmd_max_vol(); + break; + + case SYNC_CMD_MODE_BT : + case SYNC_CMD_MODE_MUSIC : + case SYNC_CMD_MODE_LINEIN: + case SYNC_CMD_MODE_FM: + case SYNC_CMD_MODE_PC: + case SYNC_CMD_MODE_ENC: + case SYNC_CMD_MODE_RTC: + case SYNC_CMD_MODE_SPDIF: +#if (TCFG_TONE2TWS_ENABLE) + /* app_mode_tone_play_by_tws(reason); */ +#endif + break; + + case SYNC_CMD_LOW_LATENCY_ENABLE: + earphone_a2dp_codec_set_low_latency_mode(1); + break; + case SYNC_CMD_LOW_LATENCY_DISABLE: + earphone_a2dp_codec_set_low_latency_mode(0); + break; + case SYNC_CMD_EARPHONE_CHAREG_START: + tws_event_cmd_earphone_charge_start() ; + break; + case SYNC_CMD_IRSENSOR_EVENT_NEAR: + tws_event_cmd_irsensor_event_near() ; + break; + case SYNC_CMD_IRSENSOR_EVENT_FAR: + tws_event_cmd_irsensor_event_far() ; + break; + + case SYNC_CMD_MODE_CHANGE: + tws_event_cmd_mode_change(); + break; + default : + break; + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws tws本地解码状态设置 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tws_event_sync_fun_tranid(struct bt_event *evt) +{ + int reason = evt->args[2]; + if (reason == SYNC_CMD_BOX_EXIT_BT) { +#if (TCFG_DEC2TWS_ENABLE) + user_set_tws_box_mode(1); +#endif + log_debug("\n ------ TWS_UNACTIVE_DEIVCE \n"); + TWS_LOCAL_IN_BT(); + TWS_REMOTE_OUT_BT(); + gtws.device_role = TWS_UNACTIVE_DEIVCE; + tws_local_back_to_bt_mode(TWS_BOX_EXIT_BT, gtws.device_role); + } else if (reason == SYNC_CMD_BOX_INIT_EXIT_BT) { + TWS_LOCAL_OUT_BT(); + TWS_REMOTE_IN_BT(); +#if (TCFG_DEC2TWS_ENABLE) + user_set_tws_box_mode(2); +#endif + log_debug("\n ------ TWS_ACTIVE_DEIVCE \n"); + gtws.device_role = TWS_ACTIVE_DEIVCE; + tws_local_back_to_bt_mode(TWS_BOX_EXIT_BT, gtws.device_role); + } else if (reason == SYNC_CMD_BOX_ENTER_BT) { + log_debug("---- SYNC_CMD_BOX_ENTER_BT"); + TWS_LOCAL_IN_BT(); + TWS_REMOTE_IN_BT(); +#if (TCFG_DEC2TWS_ENABLE) + user_set_tws_box_mode(0); +#endif + tws_local_back_to_bt_mode(TWS_BOX_ENTER_BT, gtws.device_role); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws tws本地解码启动 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tws_event_local_media_start(struct bt_event *evt) +{ + if (false == app_check_curr_task(APP_BT_TASK)) { + /* log_debug("is not bt mode \n"); */ + return; + } + if (a2dp_dec_close()) { + /* tws_api_local_media_trans_clear(); */ + } + localtws_dec_open(evt->value); +} + + +static void tws_event_local_media_stop(struct bt_event *evt) +{ + if (false == app_check_curr_task(APP_BT_TASK)) { + /* log_debug("is not bt mode \n"); */ + return; + } + if (localtws_dec_close(0)) { + } +} + + +static void tws_event_role_switch(struct bt_event *evt) +{ + int role = evt->args[0]; + if (role == TWS_ROLE_MASTER) { + + } else { + + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws tws通话音量同步 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tws_event_esco_add_connect(struct bt_event *evt) +{ + int role = evt->args[0]; + if (role == TWS_ROLE_MASTER) { + bt_tws_sync_volume(); + } +} + +#if (CONFIG_TWS_USE_COMMMON_ADDR == 0) +int tws_host_get_local_role() +{ + int role = 0; + + if (syscfg_read(VM_TWS_ROLE, &role, 1) == 1) { + if (role == TWS_ROLE_SLAVE) { + + + //printf("\n\n\nrole is slave\n\n\n"); + + return TWS_ROLE_SLAVE; + } + } + return TWS_ROLE_MASTER; +} +#endif + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙tws tws事件状态处理函数 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +int bt_tws_connction_status_event_handler(struct bt_event *evt) +{ + u8 ret = 0; + u8 addr[4][6]; + int state; + int pair_suss = 0; + int role = evt->args[0]; + int phone_link_connection = evt->args[1]; + int reason = evt->args[2]; + u16 random_num = 0; + char channel = 0; + u8 mac_addr[6]; + + log_info("tws-user: role= %d, phone_link_connection %d, reason=%d,event= %d\n", + role, phone_link_connection, reason, evt->event); + + switch (evt->event) { + case TWS_EVENT_CONNECTED: + log_info(" TWS_EVENT_CONNECTED \n"); + tws_event_connected(evt); + ret = 1; + break; + case TWS_EVENT_SEARCH_TIMEOUT: + log_info(" TWS_EVENT_SEARCH_TIMEOUT \n"); + tws_event_search_timeout(evt); + ret = 1; + break; + case TWS_EVENT_CONNECTION_TIMEOUT: + log_info(" TWS_EVENT_CONNECTION_TIMEOUT \n"); + tws_event_connection_timeout(evt); + ret = 1; + break; + case TWS_EVENT_CONNECTION_DETACH: + log_info(" TWS_EVENT_CONNECTION_DETACH \n"); + tws_event_connection_detach(evt); + ret = 1; + break; + case TWS_EVENT_PHONE_LINK_DETACH: + log_info(" TWS_EVENT_PHONE_LINK_DETACH \n"); + tws_event_phone_link_detach(evt); + ret = 1; + break; + case TWS_EVENT_REMOVE_PAIRS: + log_info(" TWS_EVENT_REMOVE_PAIRS \n"); + tws_event_remove_pairs(evt); + ret = 1; + break; + case TWS_EVENT_SYNC_FUN_CMD: + log_info(" TWS_EVENT_SYNC_FUN_CMD \n"); + tws_event_sync_fun_cmd(evt); + ret = 1; + break; + case TWS_EVENT_SYNC_FUN_TRANID: + log_info(" TWS_EVENT_SYNC_FUN_TRANID \n"); + tws_event_sync_fun_tranid(evt); + ret = 1; + break; +#if (TCFG_DEC2TWS_ENABLE) + case TWS_EVENT_LOCAL_MEDIA_START: + log_info(" TWS_EVENT_LOCAL_MEDIA_START \n"); + tws_event_local_media_start(evt); + ret = 1; + break; + case TWS_EVENT_LOCAL_MEDIA_STOP: + log_info(" TWS_EVENT_LOCAL_MEDIA_STOP \n"); + tws_event_local_media_stop(evt); + ret = 1; + break; +#endif + case TWS_EVENT_ROLE_SWITCH: + log_info(" TWS_EVENT_ROLE_SWITCH \n"); + tws_event_role_switch(evt); + ret = 1; + break; + case TWS_EVENT_ESCO_ADD_CONNECT: + log_info(" TWS_EVENT_ESCO_ADD_CONNECT \n"); + tws_event_esco_add_connect(evt); + ret = 1; + break; + } + return ret; +} + + +#endif +#endif diff --git a/apps/soundbox/task_manager/bt/vol_sync.c b/apps/soundbox/task_manager/bt/vol_sync.c new file mode 100644 index 0000000..dc31bd9 --- /dev/null +++ b/apps/soundbox/task_manager/bt/vol_sync.c @@ -0,0 +1,170 @@ +#include "typedef.h" +#include "app_main.h" +#include "app_config.h" +#include "bt/vol_sync.h" +#include "tone_player.h" + +#if TCFG_APP_BT_EN + +u8 vol_sys_tab[17] = {0, 2, 3, 4, 6, 8, 10, 11, 12, 14, 16, 18, 19, 20, 22, 23, 25}; +const u8 vol_sync_tab[17] = {0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, 127}; + +extern u8 get_max_sys_vol(void); +extern bool get_esco_busy_flag(void); + +void vol_sys_tab_init(void) +{ +#if BT_SUPPORT_MUSIC_VOL_SYNC + +#if 1 + u8 i = 0; + u8 max_vol = get_max_sys_vol(); + for (i = 0; i < 17; i++) { + vol_sys_tab[i] = i * max_vol / 16; + } +#else + u8 i = 0; + u8 max_vol = get_max_sys_vol(); + vol_sys_tab[0] = 0; + + //最大音量<16,补最大值 + if (max_vol <= 16) { + for (i = 1; i <= max_vol; i++) { + vol_sys_tab[i] = i; + } + for (; i < 17; i++) { + vol_sys_tab[i] = max_vol; + } + } else { + u8 j = max_vol - 16; + u8 k = 1; + for (i = 1; i <= max_vol; i++) { + /* g_printf("i=%d j=%d k=%d",i,j,k); */ + if (i % 2) { + } else { + j--; + if (max_vol - j > k) { + continue; + } + } + + if (k < 17) { + vol_sys_tab[k] = i; + } + k++; + } + + vol_sys_tab[16] = max_vol; + } + +#endif +#if 1 + for (i = 0; i < 17; i++) { + g_printf("[%d]:%d ", i, vol_sys_tab[i]); + } +#endif +#endif //BT_SUPPORT_MUSIC_VOL_SYNC +} + +//注册给库的回调函数,用户手机设置设备音量 +void set_music_device_volume(int volume) +{ +#if BT_SUPPORT_MUSIC_VOL_SYNC + s16 music_volume; + +#if (TCFG_DEC2TWS_ENABLE) + extern u8 get_a2dp_start_flag(); + extern u8 is_tws_all_in_bt(); + if (!is_tws_all_in_bt() && !get_a2dp_start_flag()) { //get_a2dp_start_flag为了防止后台模式时手机播放音乐回到蓝牙模式后音量同步被过滤掉 + return; + } +#endif + + //音量同步最大是127,请计数比例 + if (volume > 127) { + /*log_info("vol %d invalid\n", volume);*/ +#if TCFG_VOL_RESET_WHEN_NO_SUPPORT_VOL_SYNC + /*不支持音量同步的设备,默认设置到最大值,可以根据实际需要进行修改。 + 注意如果不是最大值,设备又没有按键可以调音量到最大,则输出也就达不到最大*/ + music_volume = get_max_sys_vol(); + log_i("unsupport vol_sync,reset vol:%d\n", music_volume); + app_audio_set_volume(APP_AUDIO_STATE_MUSIC, music_volume, 1); +#endif + return; + } + if (tone_get_status() || get_esco_busy_flag()) { + log_i("It's not smart to sync a2dp vol now\n"); + app_var.music_volume = vol_sys_tab[(volume + 1) / 8]; + return; + } + /* s16 music_volume = (volume * get_max_sys_vol() / 127); */ + + music_volume = vol_sys_tab[(volume + 1) / 8]; + app_var.opid_play_vol_sync = vol_sync_tab[(volume + 1) / 8]; + + app_audio_set_volume(APP_AUDIO_STATE_MUSIC, music_volume, 1); + +#endif +} + +//注册给库的回调函数,用于手机获取当前设备音量 +int phone_get_device_vol(void) +{ + //音量同步最大是127,请计数比例 +#if 0 + return (app_var.sys_vol_l * get_max_sys_vol() / 127) ; +#else + return app_var.opid_play_vol_sync; +#endif +} + + +void opid_play_vol_sync_fun(u8 *vol, u8 mode) +{ +#if BT_SUPPORT_MUSIC_VOL_SYNC + u8 i = 0; + vol_sys_tab[16] = get_max_sys_vol(); + + if (*vol == 0) { + if (mode) { + *vol = vol_sys_tab[1]; + app_var.opid_play_vol_sync = vol_sync_tab[1]; + } else { + *vol = vol_sys_tab[0]; + app_var.opid_play_vol_sync = vol_sync_tab[0]; + } + } else if (*vol >= get_max_sys_vol()) { + if (mode) { + *vol = vol_sys_tab[16]; + app_var.opid_play_vol_sync = vol_sync_tab[16]; + } else { + *vol = vol_sys_tab[15]; + app_var.opid_play_vol_sync = vol_sync_tab[15]; + } + } else { + for (i = 0; i < sizeof(vol_sys_tab); i++) { + if (*vol == vol_sys_tab[i]) { + if (mode) { + app_var.opid_play_vol_sync = vol_sync_tab[i + 1]; + *vol = vol_sys_tab[i + 1]; + } else { + app_var.opid_play_vol_sync = vol_sync_tab[i - 1]; + *vol = vol_sys_tab[i - 1]; + } + break; + } else if (*vol < vol_sys_tab[i]) { + if (mode) { + *vol = vol_sys_tab[i + 1]; + app_var.opid_play_vol_sync = vol_sync_tab[i]; + } else { + *vol = vol_sys_tab[i - 1]; + app_var.opid_play_vol_sync = vol_sync_tab[i - 1]; + } + break; + } + } + } +#endif +} + +#endif diff --git a/apps/soundbox/task_manager/fm/fm.c b/apps/soundbox/task_manager/fm/fm.c new file mode 100644 index 0000000..b89f590 --- /dev/null +++ b/apps/soundbox/task_manager/fm/fm.c @@ -0,0 +1,273 @@ +#include "media/includes.h" +#include "system/includes.h" +#include "app_config.h" +#include "app_task.h" +#include "app_action.h" +#include "tone_player.h" +#include "app_main.h" +#include "ui_manage.h" +#include "vm.h" +#include "key_event_deal.h" +#include "asm/pwm_led.h" +#include "user_cfg.h" +#include "ui/ui_api.h" +#include "clock_cfg.h" +#include "includes.h" +#include "fm/fm_api.h" +#include "fm/fm_manage.h" +#include "fm/fm_rw.h" + +#define LOG_TAG_CONST APP_FM +#define LOG_TAG "[APP_FM]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +/************************************************************* + 此文件函数主要是fm模式按键处理和事件处理 + + void app_fm_task() + fm模式主函数 + + static int fm_event_handler(struct sys_event *event) + fm系统事件所有处理入口 + + static void fm_app_unint(void) + fm模式退出 + +**************************************************************/ + + + +#if TCFG_APP_FM_EN +static u8 fm_idle_flag = 1; +//*----------------------------------------------------------------------------*/ +/**@brief fm按键消息入口 + @param 无 + @return 1、消息已经处理,不需要发送到common 0、消息发送到common处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int fm_key_event_opr(struct sys_event *event) +{ + int ret = true; + struct key_event *key = &event->u.key; + + int key_event = event->u.key.event; + int key_value = event->u.key.value;// + + r_printf("key value:%d, event:%d \n", key->value, key->event); + +#if (TCFG_SPI_LCD_ENABLE) + extern int key_is_ui_takeover(); + if (key_is_ui_takeover()) { + return false; + } +#endif + + switch (key_event) { + case KEY_TEST_DEMO_0: + log_info("KEY_TEST_DEMO_0 = %d \n", key_value); + app_task_put_key_msg(KEY_TEST_DEMO_1, 5678); //test demo + break; + case KEY_TEST_DEMO_1: + log_info("KEY_TEST_DEMO_1 = %d \n", key_value); //test demo + break; + + case KEY_MUSIC_PP://暂停播放 + /* app_task_put_key_msg(KEY_TEST_DEMO_0,1234); //test demo// */ + fm_volume_pp(); + break; + case KEY_FM_SCAN_ALL://全自动搜台 + case KEY_FM_SCAN_ALL_DOWN://全自动搜台 + case KEY_FM_SCAN_ALL_UP://全自动搜台 + fm_scan_all(); + break; + case KEY_FM_SCAN_DOWN: + fm_scan_down();//半自动搜台 + break; + case KEY_FM_SCAN_UP: + fm_scan_up();//半自动搜台 + break; + case KEY_FM_PREV_STATION://下一台 + fm_prev_station(); + break; + case KEY_FM_NEXT_STATION: + fm_next_station(); + break; + case KEY_FM_PREV_FREQ://下一个频率 + fm_prev_freq(); + break; + case KEY_FM_NEXT_FREQ: + fm_next_freq(); + break; + case KEY_VOL_UP: + fm_volume_up(); + break; + case KEY_VOL_DOWN: + fm_volume_down(); + break; + + default: + ret = false; + break; + } +#if (SMART_BOX_EN) + extern void smartbot_fm_msg_deal(int msg); + smartbot_fm_msg_deal(key_event); +#endif + + return ret; +} + + + +//*----------------------------------------------------------------------------*/ +/**@brief fm 模式活跃状态 所有消息入口 + @param 无 + @return 1、当前消息已经处理,不需要发送comomon 0、当前消息不是fm处理的,发送到common统一处理 + @note +*/ +/*----------------------------------------------------------------------------*/ + +static int fm_event_handler(struct sys_event *event) +{ + int err = 0; + switch (event->type) { + case SYS_KEY_EVENT: + return fm_key_event_opr(event); + break; + + case SYS_DEVICE_EVENT: + if ((u32)event->arg == DEVICE_EVENT_FROM_FM) { + if (event->u.dev.event == DEVICE_EVENT_IN) { + log_info("fm online \n"); + } else if (event->u.dev.event == DEVICE_EVENT_OUT) { + log_info("fm offline \n"); + app_task_switch_next(); + } + return true; + } + return false; + + default: + return false; + } +} + +static void fm_app_init(void) +{ + fm_idle_flag = 0; + sys_key_event_enable(); + ui_update_status(STATUS_FM_MODE); + clock_idle(FM_IDLE_CLOCK); + fm_manage_init();// + fm_api_init();//设置频率信息 +} + + +static void fm_app_start(void) +{ + fm_manage_start();//收音出声 +} + +static void fm_app_uninit(void) +{ + fm_api_release(); + fm_manage_close(); + /* tone_play_stop(); */ + tone_play_stop_by_path(tone_table[IDEX_TONE_FM]); + fm_idle_flag = 1; +} + + +static void fm_tone_play_end_callback(void *priv, int flag) +{ + u32 index = (u32)priv; + + if (APP_FM_TASK != app_get_curr_task()) { + log_error("tone callback task out \n"); + return; + } + + switch (index) { + case IDEX_TONE_FM: + ///提示音播放结束, 启动播放器播放 + fm_app_start(); + break; + default: + break; + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief fm主任务 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void app_fm_task() +{ + int msg[32]; + fm_app_init(); +#if TCFG_DEC2TWS_ENABLE + extern void set_tws_background_connected_flag(u8 flag); + extern u8 get_tws_background_connected_flag(); + if (get_tws_background_connected_flag()) { //不播放提示音 + fm_app_start(); + set_tws_background_connected_flag(0); + } else +#endif + { + tone_play_with_callback_by_name(tone_table[IDEX_TONE_FM], 1, fm_tone_play_end_callback, (void *)IDEX_TONE_FM); + } +// if (err) { +// ///提示音播放失败,直接启动播放 +// fm_app_start(); +// } + + while (1) { + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + if (fm_event_handler((struct sys_event *)(&msg[1])) == false) { + app_default_event_deal((struct sys_event *)(&msg[1])); //由common统一处理 + } + break; + default: + break; + } + + if (app_task_exitting()) { + fm_app_uninit(); + return; + } + } +} + +static u8 fm_idle_query(void) +{ + return fm_idle_flag; +} +REGISTER_LP_TARGET(fm_lp_target) = { + .name = "fm", + .is_idle = fm_idle_query, +}; + +#else + + +void app_fm_task() +{ + +} + + +#endif + + diff --git a/apps/soundbox/task_manager/fm/fm_api.c b/apps/soundbox/task_manager/fm/fm_api.c new file mode 100644 index 0000000..0dec753 --- /dev/null +++ b/apps/soundbox/task_manager/fm/fm_api.c @@ -0,0 +1,700 @@ +#include "system/includes.h" +#include "media/includes.h" +#include "app_config.h" +#include "app_task.h" +#include "tone_player.h" +#include "app_main.h" +#include "ui_manage.h" +#include "vm.h" +#include "key_event_deal.h" +#include "asm/pwm_led.h" +#include "user_cfg.h" +#include "fm/fm.h" +#include "fm/fm_manage.h" +#include "fm/fm_rw.h" +#include "ui/ui_api.h" +#include "clock_cfg.h" +#include "includes.h" +#include "fm/fm_api.h" +#include "bt/bt_tws.h" +#include "ui/ui_style.h" +#include "audio_dec/audio_dec_fm.h" +#include "fm/fm_inside/fm_inside.h" + +#define LOG_TAG_CONST APP_FM +#define LOG_TAG "[APP_FM]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + + +#if TCFG_APP_FM_EN + +#define TCFG_FM_SC_REVERB_ENABLE 1//搜索过程关闭混响 + +/************************************************************* + 此文件函数主要是fm模式 实现函数 + + + + 任务内初始化: + fm_api_init 主要申请空间、读取vm信息操作 + + 释放资源: + fm_api_release + + 注意:在逻辑操作上,sdk大部分是使用了虚拟频点,即(1,、2、3、4)代替了8750、8760、8770等真实的频率 + 转换规则:真实 = REAL_FREQ(虚拟) + 虚拟 = VIRTUAL_FREQ(真实) +**************************************************************/ + + +struct fm_opr { + void *dev; + u8 volume: 7; + u8 fm_dev_mute : 1; + u8 scan_flag;//搜索标志位,客户增加了自己了搜索标志位也要对应增加 + u16 fm_freq_cur; // 这是虚拟频率,从1计算 real_freq = fm_freq_cur + 874 + u16 fm_freq_channel_cur;//当前的台号,从1计算 + u16 fm_total_channel;//总共台数 + s16 scan_fre;//搜索过程的虚拟频率,因为--会少于0,使用带符号 + u16 fm_freq_temp; // 这是虚拟频率,从1计算 real_freq = fm_freq_cur + 874,用来做记录 +}; + +#define SCANE_ALL (0x01) +#define SEMI_SCANE_DOWN (0x02)//半自动搜索标志位 +#define SEMI_SCANE_UP (0x03) + + +static struct fm_opr *fm_hdl = NULL; +#define __this (fm_hdl) +extern void fm_dec_pause_out(u8 pause); +/*----------------------------------------------------------------------------*/ +/**@brief fm 的 mute 操作 + @param 1: mute 0:解mute + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void fm_app_mute(u8 mute) +{ + if (!__this) { + return; + } + if (mute) { + if (!__this->fm_dev_mute) { + fm_manage_mute(1); + __this->fm_dev_mute = 1; + } + } else { + if (__this->fm_dev_mute) { + fm_manage_mute(0); + __this->fm_dev_mute = 0; + } + } + /* fm_dec_pause_out(mute); */ +} + + +/*----------------------------------------------------------------------------*/ +/**@brief fm 获取vm 保存信息 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ + +static void fm_read_info_init(void) +{ + FM_INFO fm_info = {0}; + + fm_vm_check();//校验mask,不符合mask进行清0 + fm_read_info(&fm_info);//获取vm信息 + + __this->fm_freq_cur = fm_info.curFreq;//上一次的保存的频率(虚拟频率) + printf("__this->fm_freq_cur = 0x%x\n", __this->fm_freq_cur); + __this->fm_freq_channel_cur = fm_info.curChanel;//上一次保存的频道 + printf("__this->fm_freq_channel_cur = 0x%x\n", __this->fm_freq_channel_cur); + __this->fm_total_channel = fm_info.total_chanel;//总台数 + printf("__this->fm_total_channel = 0x%x\n", __this->fm_total_channel); + + if (__this->fm_freq_cur == 0 && __this->fm_freq_channel_cur && __this->fm_total_channel) { + __this->fm_freq_cur = get_fre_via_channel(__this->fm_freq_channel_cur);//上次记录操作是频道,则获取频道对应的频率 + fm_manage_set_fre(REAL_FREQ(__this->fm_freq_cur)); + } else { + fm_manage_set_fre(REAL_FREQ(__this->fm_freq_cur));//上次记录操作的是频率 + } + +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief fm ui 更新 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void __fm_ui_reflash_main()//刷新主页 +{ + UI_REFLASH_WINDOW(true); + UI_MSG_POST("fm_fre", NULL); +} + +static void __fm_ui_show_station()//显示台号 +{ + UI_SHOW_MENU(MENU_FM_STATION, 1000, __this->fm_total_channel, NULL); + /* ui_menu_reflash(true); */ + UI_MSG_POST("fm_fre", NULL); +} + +static void __fm_ui_cur_station()//显示当前台号 +{ + UI_SHOW_MENU(MENU_FM_STATION, 1000, __this->fm_freq_channel_cur, NULL); + /* ui_menu_reflash(true); */ + UI_MSG_POST("fm_fre", NULL); +} +/*----------------------------------------------------------------------------*/ +/**@brief fm 搜台完毕开混响 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void __fm_reverb_resume() +{ +#if ((TCFG_MIC_EFFECT_ENABLE) &&(TCFG_FM_SC_REVERB_ENABLE)) + mic_effect_pause(0); +#endif +} +/*----------------------------------------------------------------------------*/ +/**@brief fm 搜台前关混响 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void __fm_reverb_pause() +{ +#if ((TCFG_MIC_EFFECT_ENABLE) &&(TCFG_FM_SC_REVERB_ENABLE)) + mic_effect_pause(1); +#endif +} + + +/*----------------------------------------------------------------------------*/ +/**@brief fm 下一个台 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void __set_fm_station() +{ + fm_app_mute(1); + __this->fm_freq_cur = get_fre_via_channel(__this->fm_freq_channel_cur); + fm_manage_set_fre(REAL_FREQ(__this->fm_freq_cur)); + fm_last_ch_save(__this->fm_freq_channel_cur); + fm_app_mute(0); +} + +static void __set_fm_frq() +{ + fm_app_mute(1); + fm_manage_set_fre(REAL_FREQ(__this->fm_freq_cur)); + fm_last_freq_save(REAL_FREQ(__this->fm_freq_cur)); + fm_app_mute(0); +} + + + +static void __fm_scan_all(void) +{ + if ((!__this) || (__this->scan_flag != SCANE_ALL)) { + return; + } + + if (__this->scan_fre > VIRTUAL_FREQ(REAL_FREQ_MAX)) { + __this->scan_fre = VIRTUAL_FREQ(REAL_FREQ_MIN); + //搜索完毕跑这里 + fm_app_mute(1); + + ///////////////////////////////////// + //这里设置搜索完毕的默认台号 + if (__this->fm_freq_channel_cur) { //搜索到台就自动跳转1第一台 + __this->fm_freq_cur = get_fre_via_channel(1); + __this->fm_freq_channel_cur = 1; + } else { + __this->fm_freq_cur = 1; //搜索不了就默认第一个 + } + /////////////////////////// + fm_manage_set_fre(REAL_FREQ(__this->fm_freq_cur)); + __this->scan_flag = 0; + fm_app_mute(0); + __fm_ui_reflash_main(); + __fm_reverb_resume(); + return; + } + + fm_app_mute(1); + + if (fm_manage_set_fre(REAL_FREQ(__this->scan_fre))) { + __this->fm_freq_cur = __this->scan_fre; + __this->fm_total_channel++; + __this->fm_freq_channel_cur = __this->fm_total_channel;//++; + save_fm_point(REAL_FREQ(__this->scan_fre)); + sys_timeout_add(NULL, __fm_scan_all, 1500); //播放一秒 + __fm_ui_show_station(); + fm_app_mute(0); + } else { + __this->fm_freq_cur = __this->scan_fre; + sys_timeout_add(NULL, __fm_scan_all, 20); + + __fm_ui_reflash_main(); + } + __this->scan_fre++; + +} + + +static void __fm_semi_scan(void)//半自动收台 +{ + if ((!__this) || (__this->scan_flag != SEMI_SCANE_UP && __this->scan_flag != SEMI_SCANE_DOWN)) { + return; + } + + + if (__this->scan_flag == SEMI_SCANE_DOWN) { + __this->scan_fre++; + } else { + __this->scan_fre--; + } + + if (__this->scan_fre > VIRTUAL_FREQ(REAL_FREQ_MAX)) { + __this->scan_fre = VIRTUAL_FREQ(REAL_FREQ_MIN); +#if TCFG_FM_INSIDE_ENABLE + save_scan_freq_org(REAL_FREQ(__this->scan_fre) * 10); +#endif + } + + if (__this->scan_fre < VIRTUAL_FREQ(REAL_FREQ_MIN)) { + __this->scan_fre = VIRTUAL_FREQ(REAL_FREQ_MAX); +#if TCFG_FM_INSIDE_ENABLE + save_scan_freq_org(REAL_FREQ(__this->scan_fre) * 10); +#endif + } + + + if (__this->scan_fre == __this->fm_freq_temp) { + fm_app_mute(1); + __this->fm_freq_cur = __this->fm_freq_temp; + fm_manage_set_fre(REAL_FREQ(__this->fm_freq_cur)); + fm_app_mute(0); + __this->scan_flag = 0; + __fm_ui_reflash_main(); + __fm_reverb_resume(); + return; + } + + fm_app_mute(1); + + if (fm_manage_set_fre(REAL_FREQ(__this->scan_fre))) { + __this->fm_freq_cur = __this->scan_fre; + save_fm_point(REAL_FREQ(__this->scan_fre));//保存当前频点 + __this->fm_freq_channel_cur = get_channel_via_fre(REAL_FREQ(__this->scan_fre));//获取当前台号 + __this->fm_total_channel = get_total_mem_channel();//获取新的总台数 + fm_app_mute(0); + __fm_ui_show_station(); + __fm_reverb_resume(); + __this->scan_flag = 0; + return; + } else { + __fm_ui_reflash_main(); + __this->fm_freq_cur = __this->scan_fre; //影响半自动搜台结束条件,先进行注释,app问题要重新解决 + sys_timeout_add(NULL, __fm_semi_scan, 20); + } + +} + + + + + +void fm_delete_freq() +{ + if (!__this || __this->scan_flag) { + return; + } + delete_fm_point(__this->fm_freq_cur); +} + + + + + +void fm_scan_up()//半自动收台 +{ + log_info("KEY_FM_SCAN_UP\n"); + if (!__this || __this->scan_flag) { + return; + } + __this->scan_fre = __this->fm_freq_cur; + __this->scan_flag = SEMI_SCANE_UP; + __this->fm_freq_temp = __this->fm_freq_cur; + __fm_reverb_pause(); + fm_app_mute(1); + +#if TCFG_FM_INSIDE_ENABLE + fm_inside_trim(REAL_FREQ(__this->scan_fre) * 10); +#endif + sys_timeout_add(NULL, __fm_semi_scan, 20); +} + + + +void fm_scan_down()//半自动收台 +{ + log_info("KEY_FM_SCAN_DOWN\n"); + if (!__this || __this->scan_flag) { + return; + } + __this->scan_fre = __this->fm_freq_cur; + __this->scan_flag = SEMI_SCANE_DOWN; + __this->fm_freq_temp = __this->fm_freq_cur; + + __fm_reverb_pause(); + fm_app_mute(1); + +#if TCFG_FM_INSIDE_ENABLE + fm_inside_trim(REAL_FREQ(__this->scan_fre) * 10); +#endif + + sys_timeout_add(NULL, __fm_semi_scan, 20); + +} + +void fm_scan_stop(void) +{ + if (__this && __this->scan_flag) { + __this->scan_flag = 0; + os_time_dly(1); + __set_fm_station(); + __fm_reverb_resume(); + } +} + +void fm_scan_all() +{ + log_info("KEY_FM_SCAN_ALL\n"); + if (!__this) { + return; + } + + if (__this->scan_flag) { + fm_scan_stop(); + return; + } + + clear_all_fm_point(); + + __this->fm_freq_cur = 1;; + __this->fm_total_channel = 0; + __this->fm_freq_channel_cur = 0; + + __this->scan_fre = VIRTUAL_FREQ(REAL_FREQ_MIN); + __this->scan_flag = SCANE_ALL; + + __fm_reverb_pause(); + fm_app_mute(1); + +#if TCFG_FM_INSIDE_ENABLE + fm_inside_trim(REAL_FREQ(__this->scan_fre) * 10); +#endif + sys_timeout_add(NULL, __fm_scan_all, 20); +} + +void fm_volume_pp(void) +{ + log_info("KEY_MUSIC_PP\n"); + if (!__this || __this->scan_flag) { + return ; + } + if (__this->fm_dev_mute == 0) { + fm_app_mute(1); + } else { + fm_app_mute(0); + } +} + + +void fm_prev_freq() +{ + log_info("KEY_FM_PREV_FREQ\n"); + if (!__this || __this->scan_flag) { + return; + } + + if (__this->fm_freq_cur <= VIRTUAL_FREQ(REAL_FREQ_MIN)) { + __this->fm_freq_cur = VIRTUAL_FREQ(REAL_FREQ_MAX); + } else { + __this->fm_freq_cur -= 1; + } + __set_fm_frq(); + __fm_ui_reflash_main(); +} + +void fm_next_freq() +{ + log_info("KEY_FM_NEXT_FREQ\n"); + if (!__this || __this->scan_flag) { + return; + } + if (__this->fm_freq_cur >= VIRTUAL_FREQ(REAL_FREQ_MAX)) { + __this->fm_freq_cur = VIRTUAL_FREQ(REAL_FREQ_MIN); + } else { + __this->fm_freq_cur += 1; + } + __set_fm_frq(); + __fm_ui_reflash_main(); + +} + +void fm_volume_up() +{ + u8 vol = 0; + log_info("KEY_VOL_UP\n"); + if (!__this || __this->scan_flag) { + return; + } + + app_audio_volume_up(1); + log_info("fm vol+: %d", app_audio_get_volume(APP_AUDIO_CURRENT_STATE)); + +#if (TCFG_DEC2TWS_ENABLE) + bt_tws_sync_volume(); +#endif + + vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + UI_SHOW_MENU(MENU_MAIN_VOL, 1000, vol, NULL); + +} + +void fm_volume_down() +{ + u8 vol = 0; + log_info("KEY_VOL_DOWN\n"); + if (!__this || __this->scan_flag) { + return; + } + app_audio_volume_down(1); + log_info("fm vol-: %d", app_audio_get_volume(APP_AUDIO_CURRENT_STATE)); + +#if (TCFG_DEC2TWS_ENABLE) + bt_tws_sync_volume(); +#endif + + vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + UI_SHOW_MENU(MENU_MAIN_VOL, 1000, vol, NULL); + +} + + +void fm_prev_station() +{ + log_info("KEY_FM_PREV_STATION\n"); + + if (!__this || __this->scan_flag || (!__this->fm_total_channel)) { + return; + } + + if (__this->fm_freq_channel_cur <= 1) { + __this->fm_freq_channel_cur = __this->fm_total_channel; + } else { + __this->fm_freq_channel_cur -= 1; + } + __set_fm_station(); + __fm_ui_cur_station(); +} + + +void fm_next_station() +{ + log_info("KEY_FM_NEXT_STATION\n"); + if (!__this || __this->scan_flag || (!__this->fm_total_channel)) { + return; + } + + + if (__this->fm_freq_channel_cur >= __this->fm_total_channel) { + __this->fm_freq_channel_cur = 1; + } else { + __this->fm_freq_channel_cur += 1; + } + + __set_fm_station(); + __fm_ui_cur_station(); +} + +/*----------------------------------------------------------------------------*/ +/**@brief fm 入口初始化 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void fm_api_init() +{ + fm_hdl = (struct fm_opr *)malloc(sizeof(struct fm_opr)); + memset(fm_hdl, 0x00, sizeof(struct fm_opr)); + if (fm_hdl == NULL) { + puts("fm_state_machine fm_hdl malloc err !\n"); + } + __this->fm_dev_mute = 0; + fm_app_mute(1); + fm_read_info_init(); + os_time_dly(1); + fm_app_mute(0); + UI_SHOW_WINDOW(ID_WINDOW_FM); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief fm 任务资源释放 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ + + +void fm_api_release() +{ + int err = 0; + if (!__this) { + return; + } + + if (__this->scan_flag) { + __this->scan_flag = 0; + __fm_reverb_resume(); + } + + if (__this != NULL) { + free(__this); + __this = NULL; + } + UI_HIDE_CURR_WINDOW(); +} + +u8 fm_get_scan_flag(void) +{ + return __this->scan_flag; +} + +u8 fm_get_fm_dev_mute(void) +{ + return __this->fm_dev_mute; +} + +u8 fm_get_cur_channel(void) +{ + if (!__this) { + return 0; + } + + return (u8)__this->fm_freq_channel_cur; +} + +u16 fm_get_cur_fre(void) +{ + if (!__this) { + return 0; + } + if (__this->fm_freq_cur > 1080) { + __this->fm_freq_cur /= 10; + } + return (__this->fm_freq_cur % 874) + 874; +} + +u8 fm_get_mode(void) +{ + u32 freq_min = REAL_FREQ_MIN / VIRTUAL_FREQ_STEP; + if (freq_min < 875) { + return 1; + } else { + return 0; + } +} + +void fm_sel_station(u8 channel) +{ + if (!__this) { + return; + } + + if (channel > __this->fm_total_channel) { + printf("channel sel err!\n"); + return; + } + __this->fm_freq_channel_cur = channel; + __set_fm_station(); +} + +u8 fm_set_fre(u16 fre) +{ + if (!__this) { + return -1; + } + + if ((fre < REAL_FREQ_MIN) || (fre > REAL_FREQ_MAX)) { + return -1; + } + __this->fm_freq_cur = VIRTUAL_FREQ(fre); + __set_fm_frq(); + return 0; +} + +u8 get_fm_scan_status(void) +{ + return __this->scan_flag; +} + +//FM发射模式下扫描强台,避开强台发射 +//在最低优先级的线程运行、关闭解调、关闭FM解码 +void txmode_fm_inside_freq_scan(void) +{ + u16 scan_cnt = 0; + fm_vm_check(); + fm_inside_init(NULL);//初始化FM模块 + save_scan_freq_org(REAL_FREQ_MIN * 10); //搜台的起始频点 + for (scan_cnt = 1; scan_cnt <= MAX_CHANNEL; scan_cnt++) { + wdt_clear();//搜台时间较长,每次切频点要清看门狗 + if (fm_inside_set_fre(NULL, REAL_FREQ(scan_cnt))) { //真 判为有台 + save_fm_point(REAL_FREQ(scan_cnt));//保存频点到VM + + //REAL_FREQ(scan_cnt) * 10 ---->87.5M对应87500 + printf("get_freq = %d\n", REAL_FREQ(scan_cnt) * 10); + } + } + fm_inside_powerdown(NULL);//关闭FM模块 +} + +//FM发射模式下获取扫描到的强台 +//REAL_FREQ(get_fre_via_channel(freq_channel)) * 10 ---->87.5M对应87500 +void txmode_fm_inside_freq_get(void) +{ + u16 freq_channel = 0; + FM_INFO info; + fm_vm_check(); + fm_read_info(&info);//读取扫完台的信息 + for (freq_channel = 1; freq_channel < info.total_chanel; freq_channel++) { + printf("freq_channel_%d : %dKHz\n", freq_channel, + REAL_FREQ(get_fre_via_channel(freq_channel)) * 10); + } +} +#endif diff --git a/apps/soundbox/task_manager/fm/fm_rw.c b/apps/soundbox/task_manager/fm/fm_rw.c new file mode 100644 index 0000000..dbc246b --- /dev/null +++ b/apps/soundbox/task_manager/fm/fm_rw.c @@ -0,0 +1,286 @@ +#include "system/includes.h" +#include "syscfg_id.h" +#include "fm/fm.h" +#include "fm/fm_manage.h" +#include "fm/fm_rw.h" +#if TCFG_APP_FM_EN + + +/************************************************************* + 此文件函数主要是fm模式vm 保存 消息api + + 注意:在逻辑操作上,sdk大部分是使用了虚拟频点,即(1,、2、3、4)代替了8750、8760、8770等真实的频率 + 转换规则:真实 = REAL_FREQ(虚拟) + 虚拟 = VIRTUAL_FREQ(真实) +**************************************************************/ + + + + +#define FM_USE_MALLOC_VM 1//使用静态变量优化vm访问 + +#if FM_USE_MALLOC_VM +FM_INFO *__this_fm_info = NULL; +#endif + +/*----------------------------------------------------------------------------*/ +/*@brief 获取一个byte中有几个位被置一 + @param byte :所传进去的byte + @return 被置一位数 + @note u8 get_total_mem_channel(void) + */ +/*----------------------------------------------------------------------------*/ +static u8 __my_get_one_count(u8 byte) +{ + u8 count = 0 ; + while (byte) { + count++ ; + byte &= (byte - 1) ; + } + return count ; +} +/*----------------------------------------------------------------------------*/ +/**@brief 获取全部记录的频道 + @param 无 + @return 频道总数 + @note u8 get_total_mem_channel(void) + */ +/*----------------------------------------------------------------------------*/ +u16 get_total_mem_channel(void) +{ + FM_INFO fm_info = {0}; + fm_read_info(&fm_info); + return fm_info.total_chanel; +} +/*----------------------------------------------------------------------------*/ +/**@brief 根据频点偏移量获取频道 + @param 输入真实频点 + @return 频道 + @note u8 get_channel_via_fre(u8 fre) + + */ +/*----------------------------------------------------------------------------*/ +u16 get_channel_via_fre(u16 fre) +{ + FM_INFO fm_info = {0}; + u16 i, k; + u16 total = 0; + fre = VIRTUAL_FREQ(fre);//fre - 874; + fm_read_info(&fm_info); + for (i = 0; i < (MEM_FM_LEN); i++) { + for (k = 0; k < 8; k++) { + if (fm_info.dat[i] & (BIT(k))) { + total++; + if (fre == (i * 8 + k)) { + return total; //return fre index + } + } + } + } + return 0x00;//fm_mode_var->wFreChannel; //find none +} + +/*----------------------------------------------------------------------------*/ +/**@brief 通过频道获取频点 + @param channel:频道 + @return 有效的频点偏移量 + @note u8 get_fre_via_channle(u8 channel) + */ +/*----------------------------------------------------------------------------*/ +u16 get_fre_via_channel(u16 channel) +{ + FM_INFO fm_info = {0}; + u16 i, k; + u16 total = 0; + + fm_read_info(&fm_info); + + for (i = 0; i < (MEM_FM_LEN); i++) { + for (k = 0; k < 8; k++) { + if (fm_info.dat[i] & (BIT(k))) { + total++; + if (total == channel) { + return i * 8 + k; //fre = MIN_FRE + return val + } + } + } + } + + return 0; //find none +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 从vm清除所有频点信息 + @param 无 + @return 无 + @note void clear_all_fm_point(void) + */ +/*----------------------------------------------------------------------------*/ +void clear_all_fm_point(void) +{ + FM_INFO fm_info = {0}; + fm_info.mask = FM_VM_MASK; + fm_info.curFreq = 1; + fm_info.curChanel = 0; + fm_info.total_chanel = 0; + fm_save_info(&fm_info); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 根据频点偏移量保存到相应的频点位变量到vm + @param fre:真实频点 + @return 无 + @note void save_fm_point(u8 fre) + */ +/*----------------------------------------------------------------------------*/ +void save_fm_point(u16 fre)//1-206 +{ + FM_INFO fm_info = {0}; + u16 i, k; + u16 total = 0; + fm_read_info(&fm_info); + fre = VIRTUAL_FREQ(fre);//fre - 874; + /* fre = fre - 874; */ + i = fre / 8; + k = fre % 8; + + fm_info.dat[i] |= BIT(k); + fm_info.curFreq = fre; + + for (i = 0; i < (MEM_FM_LEN); i++) { + total += __my_get_one_count(fm_info.dat[i]); + } + + total = total > MAX_CHANNEL ? MAX_CHANNEL : total; + fm_info.total_chanel = total; + + fm_save_info(&fm_info); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 删除频道 + @param 虚拟频点 + @return 无 + @note void delete_fm_point(u8 fre) + */ +/*----------------------------------------------------------------------------*/ +void delete_fm_point(u16 fre) +{ + u16 i, k; + FM_INFO fm_info = {0}; + fm_read_info(&fm_info); + i = fre / 8; + k = fre % 8; + if (fm_info.dat[i] & BIT(k)) { + fm_info.dat[i] &= (~BIT(k)); + fm_info.total_chanel--; + fm_save_info(&fm_info); + } +} +/*----------------------------------------------------------------------------*/ +/**@brief 最近一次操作记录 + @param 无 + @return 无 + @note u8 ch_save(void) + */ +/*----------------------------------------------------------------------------*/ +void fm_last_ch_save(u16 channel) +{ + FM_INFO fm_info = {0}; + fm_read_info(&fm_info); + fm_info.curFreq = 0; + fm_info.curChanel = channel; + fm_save_info(&fm_info); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 最近一次操作记录 + @param 真实频点 + @return 无 + @note u8 ch_save(void) + */ +/*----------------------------------------------------------------------------*/ +void fm_last_freq_save(u16 freq) +{ + FM_INFO fm_info = {0}; + fm_read_info(&fm_info); + fm_info.curChanel = 0; + freq = VIRTUAL_FREQ(freq);//fre - 874; + fm_info.curFreq = freq;// - 874; + fm_save_info(&fm_info); +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief 保存信息到fm_buf + @param 无 + @return 无 + @note void fm_save_info() + */ +/*----------------------------------------------------------------------------*/ +void fm_save_info(FM_INFO *info) +{ +#if FM_USE_MALLOC_VM + if (__this_fm_info) { + memcpy(__this_fm_info, info, sizeof(FM_INFO)); + } +#endif + syscfg_write(VM_FM_INFO, info, sizeof(FM_INFO)); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 从vm读取信息 + @param 无 + @return 无 + @note void fm_read_info() + */ +/*----------------------------------------------------------------------------*/ +void fm_read_info(FM_INFO *info) +{ + +#if FM_USE_MALLOC_VM + if (__this_fm_info) { + memcpy(info, __this_fm_info, sizeof(FM_INFO)); + return; + } +#endif + + if (sizeof(FM_INFO) != syscfg_read(VM_FM_INFO, info, sizeof(FM_INFO))) { + r_printf("fm_info is null xx\n"); + memset(info, 0x00, sizeof(FM_INFO)); + } + +#if FM_USE_MALLOC_VM + if (!__this_fm_info) { + __this_fm_info = zalloc(sizeof(FM_INFO)); + memcpy(__this_fm_info, info, sizeof(FM_INFO)); + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 检查vm信息 + @param 无 + @return 无 + @note void fm_read_info() + */ +/*----------------------------------------------------------------------------*/ +void fm_vm_check(void) +{ + FM_INFO fm_info = {0}; + fm_read_info(&fm_info); + if (fm_info.mask != FM_VM_MASK) { + fm_info.mask = FM_VM_MASK; + fm_info.curFreq = 1; + fm_info.curChanel = 0; + fm_info.total_chanel = 0; + fm_save_info(&fm_info); + } +} + + + +#endif + diff --git a/apps/soundbox/task_manager/idle/idle.c b/apps/soundbox/task_manager/idle/idle.c new file mode 100644 index 0000000..6c23539 --- /dev/null +++ b/apps/soundbox/task_manager/idle/idle.c @@ -0,0 +1,513 @@ + +/************************************************************* + 此文件函数主要是idle模式按键处理和事件处理 + + void app_idle_task() + idle模式主函数 + + static int idle_sys_event_handler(struct sys_event *event) + idle模式系统事件所有处理入口 + + static void idle_task_close(void) + idle模式退出 + + 该模式只是作为系统空跑的,可以做家关机,把没有用的模块关闭 + +**************************************************************/ +#include "system/includes.h" +#include "media/includes.h" +#include "app_config.h" +#include "app_task.h" +#include "tone_player.h" +#include "asm/charge.h" +#include "app_charge.h" +#include "app_main.h" +#include "ui_manage.h" +#include "vm.h" +#include "app_chargestore.h" +#include "user_cfg.h" +#include "ui/ui_api.h" +#include "key_event_deal.h" + +#define LOG_TAG_CONST APP_IDLE +#define LOG_TAG "[APP_IDLE]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +static int timer_printf_1sec = 0; +static u8 is_idle_flag = 0; +static u8 goto_poweron_cnt = 0; +static u8 goto_poweron_flag = 0; + +extern u8 get_power_on_status(void); + +static void idle_key_poweron_deal(u8 step); +static void idle_app_open_module(); + +#define POWER_ON_CNT 10 +/// idle 是否关闭不用的模块,减少功耗 +#define LOW_POWER_IN_IDLE 0 + + +#if LOW_POWER_IN_IDLE +///*----------------------------------------------------------------------------*/ +/**@brief 下面处理是为了关闭不需要用的模块,减少系统功耗 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +#include "usb/otg.h" +#include "usb/host/usb_host.h" +#include "asm/power/p33.h" +struct timer_hdl { + u32 ticks; + int index; + int prd; + u32 fine_cnt; + void *power_ctrl; + struct list_head head; +}; + +static struct timer_hdl hdl; +static u8 suspend_flag = 0; + +#define __this (&hdl) + +static const u32 timer_div[] = { + /*0000*/ 1, + /*0001*/ 4, + /*0010*/ 16, + /*0011*/ 64, + /*0100*/ 2, + /*0101*/ 8, + /*0110*/ 32, + /*0111*/ 128, + /*1000*/ 256, + /*1001*/ 4 * 256, + /*1010*/ 16 * 256, + /*1011*/ 64 * 256, + /*1100*/ 2 * 256, + /*1101*/ 8 * 256, + /*1110*/ 32 * 256, + /*1111*/ 128 * 256, +}; + +#define APP_TIMER_CLK clk_get("timer") +#define MAX_TIME_CNT 0x7fff +#define MIN_TIME_CNT 0x100 + +#define TIMER_UNIT_MS 2 +#define MAX_TIMER_PERIOD_MS (1000/TIMER_UNIT_MS) + +extern void adc_scan(void *priv); +___interrupt +static void idle_timer2_isr() +{ + static u32 cnt = 0; + JL_TIMER2->CON |= BIT(14); + + ++cnt; + if ((cnt % 5) == 0) { + } + + if (cnt == 500) { + cnt = 0; + } + /* adc_scan(NULL); */ +} + +static int idle_timer2_init() +{ + u32 prd_cnt; + u8 index; + + for (index = 0; index < (sizeof(timer_div) / sizeof(timer_div[0])); index++) { + prd_cnt = TIMER_UNIT_MS * (APP_TIMER_CLK / 1000) / timer_div[index]; + if (prd_cnt > MIN_TIME_CNT && prd_cnt < MAX_TIME_CNT) { + break; + } + } + __this->index = index; + __this->prd = prd_cnt; + + JL_TIMER2->CNT = 0; + JL_TIMER2->PRD = prd_cnt; //2ms + request_irq(IRQ_TIME2_IDX, 3, idle_timer2_isr, 0); + JL_TIMER2->CON = (index << 4) | BIT(0) | BIT(3); + + log_info("PRD : 0x%x / %d", JL_TIMER2->PRD, clk_get("timer")); + + return 0; +} + +static void idle_timer2_uninit() +{ + JL_TIMER2->CON &= ~(BIT(1) | BIT(0)); +} + +static void idle_timer1_open() +{ + JL_TIMER1->CON |= BIT(0); +} + +static void idle_timer1_close() +{ + JL_TIMER1->CON &= ~(BIT(1) | BIT(0)); +} + +u32 regs_buf[11] = {0}; +void resume_some_peripheral() +{ + u32 *regs_ptr = regs_buf; + + if (!suspend_flag) { + return; + } + + clk_set("sys", 24 * 1000000L); + + JL_ANA->DAA_CON0 = *regs_ptr++ ; + JL_ANA->DAA_CON1 = *regs_ptr++ ; + JL_ANA->DAA_CON2 = *regs_ptr++ ; + JL_ANA->DAA_CON3 = *regs_ptr++ ; + JL_ANA->DAA_CON7 = *regs_ptr++ ; + + JL_ANA->ADA_CON0 = *regs_ptr++ ; + JL_ANA->ADA_CON1 = *regs_ptr++ ; + JL_ANA->ADA_CON2 = *regs_ptr++ ; + JL_ANA->ADA_CON3 = *regs_ptr++ ; + JL_ANA->ADA_CON4 = *regs_ptr++ ; + + suspend_flag = 0; +} + +void suspend_some_peripheral() +{ + u32 *regs_ptr = regs_buf; + + if (suspend_flag) { + return; + } + + clk_set("sys", 6 * 1000000L); + SYSVDD_VOL_SEL(SYSVDD_VOL_SEL_102V); + VDC13_VOL_SEL(VDC13_VOL_SEL_105V); + + *regs_ptr++ = JL_ANA->DAA_CON0; + *regs_ptr++ = JL_ANA->DAA_CON1; + *regs_ptr++ = JL_ANA->DAA_CON2; + *regs_ptr++ = JL_ANA->DAA_CON3; + *regs_ptr++ = JL_ANA->DAA_CON7; + + *regs_ptr++ = JL_ANA->ADA_CON0; + *regs_ptr++ = JL_ANA->ADA_CON1; + *regs_ptr++ = JL_ANA->ADA_CON2; + *regs_ptr++ = JL_ANA->ADA_CON3; + *regs_ptr++ = JL_ANA->ADA_CON4; + + JL_ANA->DAA_CON0 = 0; + JL_ANA->DAA_CON1 = 0; + JL_ANA->DAA_CON2 = 0; + JL_ANA->DAA_CON3 = 0; + JL_ANA->DAA_CON7 = 0; + + JL_ANA->ADA_CON0 = 0; + JL_ANA->ADA_CON1 = 0; + JL_ANA->ADA_CON2 = 0; + JL_ANA->ADA_CON3 = 0; + JL_ANA->ADA_CON4 = 0; + + suspend_flag = 1; +} + +static u8 is_idle_query(void) +{ + return is_idle_flag; +} +#if 0 +REGISTER_LP_TARGET(idle_lp_target) = { + .name = "not_idle", + .is_idle = is_idle_query, +}; +#endif + +#endif + +static void idle_key_poweron_deal(u8 step) +{ + switch (step) { + case 0: + goto_poweron_cnt = 0; + goto_poweron_flag = 1; + break; + case 1: + log_info("poweron flag:%d cnt:%d\n", goto_poweron_flag, goto_poweron_cnt); + if (goto_poweron_flag) { + goto_poweron_cnt++; + if (goto_poweron_cnt >= POWER_ON_CNT) { + goto_poweron_cnt = 0; + goto_poweron_flag = 0; + app_var.goto_poweroff_flag = 0; +#if LOW_POWER_IN_IDLE + idle_app_open_module(); +#endif + +#if TWFG_APP_POWERON_IGNORE_DEV + app_task_switch_to(APP_POWERON_TASK); +#endif + } + } + break; + } +} + +#if (TWFG_APP_POWERON_IGNORE_DEV == 0) +static u16 ignore_dev_timeout = 0; +static void poweron_task_switch_to_bt(void *priv) //超时还没有设备挂载,则切到蓝牙模式 +{ + app_task_switch_to(APP_BT_TASK); +} +#endif + +//*----------------------------------------------------------------------------*/ +/**@brief idle 按键消息入口 + @param 无 + @return 1、消息已经处理,不需要发送到common 0、消息发送到common处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int idle_key_event_opr(struct sys_event *event) +{ + int ret = false; + int key_event = event->u.key.event; + int key_value = event->u.key.value; + + log_info("key_event:%d \n", key_event); + + switch (key_event) { + case KEY_POWER_ON: + case KEY_POWER_ON_HOLD: + idle_key_poweron_deal(key_event - KEY_POWER_ON); + ret = true; + break; + } + return ret; +} + +//*----------------------------------------------------------------------------*/ +/**@brief idle 模式活跃状态 所有消息入口 + @param 无 + @return 1、当前消息已经处理,不需要发送comomon 0、当前消息不是idle处理的,发送到common统一处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +extern int app_common_otg_devcie_event(struct sys_event *event); +static int idle_sys_event_handler(struct sys_event *event) +{ + switch (event->type) { + case SYS_KEY_EVENT: + return idle_key_event_opr(event); + + case SYS_BT_EVENT: + /* return 0; */ + return true; + case SYS_DEVICE_EVENT: +#if TCFG_CHARGESTORE_ENABLE || TCFG_TEST_BOX_ENABLE + if ((u32)event->arg == DEVICE_EVENT_CHARGE_STORE) { + app_chargestore_event_handler(&event->u.chargestore); + } +#endif + return 0; + default: + return true; + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief idle 退出 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void idle_task_close() +{ + UI_HIDE_CURR_WINDOW(); +} + +//*----------------------------------------------------------------------------*/ +/**@brief idle 重新打开需要的模块 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void idle_app_open_module() +{ +#if LOW_POWER_IN_IDLE + is_idle_flag = 0; +#if (TCFG_LOWPOWER_LOWPOWER_SEL == 0) + resume_some_peripheral(); +#endif + +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + extern void sdx_dev_detect_timer_add(); + sdx_dev_detect_timer_add(); +#endif + +#if (TCFG_PC_ENABLE || TCFG_UDISK_ENABLE) + extern void usb_detect_timer_add(); + usb_detect_timer_add(); +#endif + +#if TCFG_LINEIN_ENABLE + extern void linein_detect_timer_add(); + linein_detect_timer_add(); +#endif + if (timer_printf_1sec) { + sys_timer_del(timer_printf_1sec); + } +#endif //LOW_POWER_IN_IDLE +} + +//*----------------------------------------------------------------------------*/ +/**@brief idle 关闭不需要的模块 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void idle_app_close_module() +{ +#if LOW_POWER_IN_IDLE + int ret = false; + is_idle_flag = 1; + +#if (TCFG_SD0_ENABLE || TCFG_SD1_ENABLE) + extern void sdx_dev_detect_timer_del(); + sdx_dev_detect_timer_del(); +#endif + +#if (((TCFG_PC_ENABLE) && (!TCFG_USB_PORT_CHARGE)) || ((TCFG_UDISK_ENABLE) && (!TCFG_PC_ENABLE))) + extern void usb_detect_timer_del(); + extern u32 usb_otg_online(const usb_dev usb_id); + /* extern int usb_mount_offline(usb_dev usb_id); */ + extern void usb_pause(); + extern int dev_manager_del(char *logo); + usb_detect_timer_del(); + os_time_dly((TCFG_OTG_DET_INTERVAL + 9) / 10); + if (usb_otg_online(0) == HOST_MODE) { +#if TCFG_UDISK_ENABLE + dev_manager_del("udisk0"); + usb_host_unmount(0); + usb_h_sie_close(0); + + /* + 经过测试发现,有相当一部分在DP/DM设成高阻状态下U盘的电流仍维持在 + 20 ~ 30mA,需要把DP设成上拉,DM设成下拉,这些U盘的电流才能降到2mA + 以下。即有部分U盘需要主机维持在空闲时J状态才能进入suspend。 + */ + usb_iomode(1); + gpio_set_die(IO_PORT_DP, 1); + gpio_set_pull_up(IO_PORT_DP, 1); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + + gpio_set_die(IO_PORT_DM, 1); + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 1); + gpio_set_direction(IO_PORT_DM, 1); + + /* usb_mount_offline(0); */ +#endif + } else if (usb_otg_online(0) == SLAVE_MODE) { +#if TCFG_PC_ENABLE + usb_pause(); + + usb_iomode(1); + gpio_set_die(IO_PORT_DP, 0); + gpio_set_pull_up(IO_PORT_DP, 0); + gpio_set_pull_down(IO_PORT_DP, 0); + gpio_set_direction(IO_PORT_DP, 1); + + gpio_set_die(IO_PORT_DM, 0); + gpio_set_pull_up(IO_PORT_DM, 0); + gpio_set_pull_down(IO_PORT_DM, 0); + gpio_set_direction(IO_PORT_DM, 1); +#endif + } +#endif + +#if TCFG_LINEIN_ENABLE + extern void linein_detect_timer_del(); + linein_detect_timer_del(); +#endif + +#if (TCFG_LOWPOWER_LOWPOWER_SEL == 0) + suspend_some_peripheral(); +#endif +#endif +} +//*----------------------------------------------------------------------------*/ +/**@brief idle 启动 + @param 无 + @return + @note 关闭SD卡 、 usb 、假关机还是软关机 +*/ +/*----------------------------------------------------------------------------*/ +static void idle_app_start() +{ +#if LOW_POWER_IN_IDLE + idle_app_close_module(); +#endif + + UI_SHOW_WINDOW(ID_WINDOW_IDLE); + +#if (TCFG_CHARGE_ENABLE && !TCFG_CHARGE_POWERON_ENABLE) + +#else + sys_key_event_enable(); +#endif +} + + +//*----------------------------------------------------------------------------*/ +/**@brief idle 主任务 + @param 无 + @return 无 + @note + */ +/*----------------------------------------------------------------------------*/ +void app_idle_task() +{ + int res; + int msg[32]; + + idle_app_start(); + + while (1) { + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + if (idle_sys_event_handler((struct sys_event *)(&msg[1])) == false) { + app_default_event_deal((struct sys_event *)(&msg[1])); //由common统一处理 + } + break; + default: + break; + } + + if (app_task_exitting()) { + idle_task_close(); + return; + } + } +} + diff --git a/apps/soundbox/task_manager/linein/linein.c b/apps/soundbox/task_manager/linein/linein.c new file mode 100644 index 0000000..733f8dc --- /dev/null +++ b/apps/soundbox/task_manager/linein/linein.c @@ -0,0 +1,370 @@ + +/************************************************************* + 此文件函数主要是linein模式按键处理和事件处理 + + void app_linein_task() + linein模式主函数 + + static int linein_sys_event_handler(struct sys_event *event) + linein模式系统事件所有处理入口 + + static void linein_task_close(void) + linein模式退出 + +**************************************************************/ + + +#include "system/app_core.h" +#include "system/includes.h" +#include "server/server_core.h" + +#include "app_config.h" +#include "app_task.h" + +#include "media/includes.h" +#include "tone_player.h" +#include "audio_dec_linein.h" + +#include "asm/audio_linein.h" +#include "asm/pwm_led.h" +#include "asm/charge.h" + +#include "app_charge.h" +#include "app_main.h" +#include "app_online_cfg.h" +#include "app_power_manage.h" + +#include "app_chargestore.h" +#include "gSensor/gSensor_manage.h" +#include "ui_manage.h" +#include "vm.h" + +#include "linein/linein_dev.h" +#include "linein/linein.h" + +#include "key_event_deal.h" +#include "user_cfg.h" +#include "ui/ui_api.h" +#include "fm_emitter/fm_emitter_manage.h" +#include "clock_cfg.h" + +#include "bt.h" +#include "bt_tws.h" + + +#if TCFG_APP_LINEIN_EN + +#define LOG_TAG_CONST APP_LINEIN +#define LOG_TAG "[APP_LINEIN]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +static u8 linein_last_onoff = (u8) - 1; +static u8 linein_bt_back_flag = 0; +static u8 linein_idle_flag = 1; + +///*----------------------------------------------------------------------------*/ +/**@brief 当前出于非linein 模式时候linein的在common消息处理 + @param 无 + @return 1:需要切换回linein 模式 0:无 + @note +*/ +/*----------------------------------------------------------------------------*/ +int linein_device_event_handler(struct sys_event *event) +{ + if ((u32)event->arg == DEVICE_EVENT_FROM_LINEIN) { + if (event->u.dev.event == DEVICE_EVENT_IN) { + log_info("linein online \n"); + return true; + } else if (event->u.dev.event == DEVICE_EVENT_OUT) { + log_info("linein offline \n"); + } + } + return false; +} + + +static int linein_key_event_filter_before() +{ +#if TCFG_UI_ENABLE +#if (TCFG_APP_FM_EMITTER_EN == ENABLE_THIS_MOUDLE) + if (ui_get_app_menu(GRT_CUR_MENU) == MENU_FM_SET_FRE) { + return false; + } +#endif +#endif + return TRUE; +} + + +//*----------------------------------------------------------------------------*/ +/**@brief linein 按键消息入口 + @param 无 + @return 1、消息已经处理,不需要发送到common 0、消息发送到common处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int linein_key_msg_deal(struct sys_event *event) +{ + int ret = true; + int err = 0; + u8 vol; + int key_event = event->u.key.event; + int key_value = event->u.key.value;// + + if (linein_key_event_filter_before() == false) { + return false; + } + + log_info("key_event:%d \n", key_event); +#if (SMART_BOX_EN) + extern bool smartbox_key_event_filter_before(int key_event); + if (smartbox_key_event_filter_before(key_event)) { + return true; + } +#endif + + switch (key_event) { + case KEY_LINEIN_START: + linein_start(); + linein_last_onoff = 1; + UI_REFLASH_WINDOW(true);//刷新主页并且支持打断显示 + break; + case KEY_TEST_DEMO_0: + log_info("KEY_TEST_DEMO_0 = %d \n", key_value); + app_task_put_key_msg(KEY_TEST_DEMO_1, 5678); //test demo + break; + case KEY_TEST_DEMO_1: + log_info("KEY_TEST_DEMO_1 = %d \n", key_value); //test demo + break; + + case KEY_MUSIC_PP: + log_info("KEY_MUSIC_PP\n"); + /* app_task_put_key_msg(KEY_TEST_DEMO_0,1234); //test demo// */ + linein_last_onoff = linein_volume_pp(); + linein_last_onoff ? ui_update_status(STATUS_LINEIN_PLAY)\ + : ui_update_status(STATUS_LINEIN_PAUSE); + break; + case KEY_VOL_UP: + log_info(" KEY_VOL_UP\n"); + linein_key_vol_up(); + break; + + case KEY_VOL_DOWN: + log_info(" KEY_VOL_DOWN\n"); + linein_key_vol_down(); + break; + + default: + ret = false; + break; + } +#if (SMART_BOX_EN) + extern void smartbox_linein_msg_deal(int msg, u8 ret); + smartbox_linein_msg_deal(key_event, ret); +#endif + + return ret; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 音乐播放结束回调函数 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void line_tone_play_end_callback(void *priv, int flag) +{ + u32 index = (u32)priv; + + if (APP_LINEIN_TASK != app_get_curr_task()) { + log_error("tone callback task out \n"); + return; + } + + switch (index) { + case IDEX_TONE_LINEIN: + ///提示音播放结束, 启动播放器播放 + app_task_put_key_msg(KEY_LINEIN_START, 0); + break; + default: + break; + } +} + + +//*----------------------------------------------------------------------------*/ +/**@brief linein 入口 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void linein_app_init(void) +{ + linein_idle_flag = 0; + UI_SHOW_WINDOW(ID_WINDOW_LINEIN);//打开ui主页 + UI_SHOW_MENU(MENU_AUX, 0, 0, NULL); + sys_key_event_enable();//开启按键 + ui_update_status(STATUS_LINEIN_MODE); + clock_idle(LINEIN_IDLE_CLOCK); + +} + +//*----------------------------------------------------------------------------*/ +/**@brief linein 退出 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ + +static void linein_task_close(void) +{ + UI_HIDE_CURR_WINDOW(); + linein_stop(); + /* tone_play_stop(); */ + tone_play_stop_by_path(tone_table[IDEX_TONE_LINEIN]); + linein_idle_flag = 1; +} + + +//*----------------------------------------------------------------------------*/ +/**@brief linein 模式活跃状态 所有消息入口 + @param 无 + @return 1、当前消息已经处理,不需要发送comomon 0、当前消息不是linein处理的,发送到common统一处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int linein_sys_event_handler(struct sys_event *event) +{ + int ret = TRUE; + switch (event->type) { + case SYS_KEY_EVENT: + return linein_key_msg_deal(event); + break; + case SYS_DEVICE_EVENT: + if ((u32)event->arg == DEVICE_EVENT_FROM_LINEIN) { + if (event->u.dev.event == DEVICE_EVENT_IN) { + log_info("linein online \n"); + } else if (event->u.dev.event == DEVICE_EVENT_OUT) { + log_info("linein offline \n"); + app_task_switch_next(); + } + return true; + } + return false; + break; + default: + return false; + } + return false; +} + + +//*----------------------------------------------------------------------------*/ +/**@brief linein 在线检测 切换模式判断使用 + @param 无 + @return 1 linein设备在线 0 设备不在线 + @note +*/ +/*----------------------------------------------------------------------------*/ +int linein_app_check(void) +{ + if (linein_is_online()) { + return true; + } + return false; +} + +//*----------------------------------------------------------------------------*/ +/**@brief linein 主任务 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void app_linein_task() +{ + int res; + int err = 0; + int msg[32]; + +#if TCFG_APP_BT_EN + linein_bt_back_flag = get_bt_back_flag();//从蓝牙后台返回标志 + set_bt_back_flag(0); +#else + linein_bt_back_flag = 0; +#endif + log_info("linein_bt_back_flag == %d linein_last_onoff = %d\n", \ + linein_bt_back_flag, linein_last_onoff); + + linein_app_init();//初始化时钟和开启ui + +#if TCFG_DEC2TWS_ENABLE + extern void set_tws_background_connected_flag(u8 flag); + extern u8 get_tws_background_connected_flag(); + if (get_tws_background_connected_flag()) { //不播放提示音 + app_task_put_key_msg(KEY_LINEIN_START, 0); + set_tws_background_connected_flag(0); + } else +#endif + { + err = tone_play_with_callback_by_name(tone_table[IDEX_TONE_LINEIN], 1, + line_tone_play_end_callback, (void *)IDEX_TONE_LINEIN); + } +// if (err) { // +// ///提示音播放失败,直接推送KEY_MUSIC_PLAYER_START启动播放 +// app_task_put_key_msg(KEY_LINEIN_START, 0); +// } + + while (1) { + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + if (linein_sys_event_handler((struct sys_event *)(&msg[1])) == false) { + app_default_event_deal((struct sys_event *)(&msg[1])); //由common统一处理 + } + break; + default: + break; + } + + if (app_task_exitting()) { + linein_task_close(); + return; + } + } +} + +static u8 linein_idle_query(void) +{ + return linein_idle_flag; +} +REGISTER_LP_TARGET(linein_lp_target) = { + .name = "linein", + .is_idle = linein_idle_query, +}; + +#else + +int linein_app_check(void) +{ + return false; +} + +void app_linein_task() +{ + +} + +#endif + + diff --git a/apps/soundbox/task_manager/linein/linein_api.c b/apps/soundbox/task_manager/linein/linein_api.c new file mode 100644 index 0000000..0a2e733 --- /dev/null +++ b/apps/soundbox/task_manager/linein/linein_api.c @@ -0,0 +1,393 @@ +#include "system/includes.h" +#include "app_config.h" +#include "app_task.h" +#include "media/includes.h" +#include "tone_player.h" +#include "audio_dec_linein.h" +#include "asm/audio_linein.h" +#include "app_main.h" +#include "ui_manage.h" +#include "vm.h" +#include "linein/linein_dev.h" +#include "linein/linein.h" +#include "key_event_deal.h" +#include "user_cfg.h" +#include "ui/ui_api.h" +#include "fm_emitter/fm_emitter_manage.h" +#include "clock_cfg.h" +#include "bt.h" +#include "bt_tws.h" +#ifndef CONFIG_MEDIA_NEW_ENABLE +#include "application/audio_output_dac.h" +#endif + +/************************************************************* + 此文件函数主要是linein实现api +**************************************************************/ + + +#if TCFG_APP_LINEIN_EN + +#define LOG_TAG_CONST APP_LINEIN +#define LOG_TAG "[APP_LINEIN]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +struct linein_opr { + void *rec_dev; + u8 volume : 7; + u8 onoff : 1; + u8 audio_state; /*判断linein模式使用模拟音量还是数字音量*/ +}; +static struct linein_opr linein_hdl = {0}; +#define __this (&linein_hdl) + + +/**@brief linein 音量设置函数 + @param 需要设置的音量 + @return + @note 在linein 情况下针对了某些情景进行了处理,设置音量需要使用独立接口 +*/ +/*----------------------------------------------------------------------------*/ +int linein_volume_set(u8 vol) +{ + if (TCFG_LINEIN_LR_CH == AUDIO_LIN_DACL_CH) { + app_audio_output_ch_analog_gain_set(BIT(0), 0); + /* app_audio_output_ch_analog_gain_set(BIT(1), vol); */ + } else if (TCFG_LINEIN_LR_CH == AUDIO_LIN_DACR_CH) { + app_audio_output_ch_analog_gain_set(BIT(1), 0); + /* app_audio_output_ch_analog_gain_set(BIT(0), vol); */ + } + app_audio_set_volume(__this->audio_state, vol, 1); + log_info("linein vol: %d", __this->volume); + __this->volume = vol; + +#if (TCFG_DEC2TWS_ENABLE) + bt_tws_sync_volume(); +#endif + +#if (TCFG_LINEIN_INPUT_WAY != LINEIN_INPUT_WAY_ADC) + if (__this->volume) { + audio_linein_mute(0); + } else { + audio_linein_mute(1); + } +#endif + + return true; +} + + + + +/*----------------------------------------------------------------------------*/ +/**@brief linein 使用模拟直通方式 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static inline void __linein_way_analog_start() +{ + app_audio_state_switch(__this->audio_state, get_max_sys_vol());// + app_audio_set_volume(__this->audio_state, __this->volume, 1); + if (!app_audio_get_volume(__this->audio_state)) { + audio_linein_mute(1); //模拟输出时候,dac为0也有数据 + } + + if (TCFG_LINEIN_LR_CH & (BIT(0) | BIT(1))) { + audio_linein0_open(TCFG_LINEIN_LR_CH, 1); + } else if (TCFG_LINEIN_LR_CH & (BIT(2) | BIT(3))) { + audio_linein1_open(TCFG_LINEIN_LR_CH, 1); + } else if (TCFG_LINEIN_LR_CH & (BIT(4) | BIT(5))) { + audio_linein2_open(TCFG_LINEIN_LR_CH, 1); + } + + if (TCFG_LINEIN_LR_CH != AUDIO_LIN0_LR && TCFG_LINEIN_LR_CH != AUDIO_LIN1_LR && TCFG_LINEIN_LR_CH != AUDIO_LIN2_LR) { + audio_linein_ch_combine(1, 1); + } + + audio_linein_gain(1); // high gain + if (app_audio_get_volume(__this->audio_state)) { + audio_linein_mute(0); + app_audio_set_volume(__this->audio_state, app_audio_get_volume(__this->audio_state), 1);//防止无法调整 + } + //模拟输出时候,dac为0也有数据 +} + +/*----------------------------------------------------------------------------*/ +/**@brief linein 使用dac IO输入方式 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static inline void __linein_way_dac_analog_start() +{ + app_audio_state_switch(__this->audio_state, get_max_sys_vol()); + + app_audio_set_volume(__this->audio_state, __this->volume, 1); + + + if ((TCFG_LINEIN_LR_CH == AUDIO_LIN_DACL_CH) \ + || (TCFG_LINEIN_LR_CH == AUDIO_LIN_DACR_CH)) { + audio_linein_via_dac_open(TCFG_LINEIN_LR_CH, 1); + } else { + ASSERT(0, "linein ch err\n"); + } + linein_volume_set(app_audio_get_volume(__this->audio_state)); + +} + +/*----------------------------------------------------------------------------*/ +/**@brief linein 使用采集adc输入方式 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static inline void __linein_way_adc_start() +{ + +#if (TCFG_LINEIN_MULTIPLEX_WITH_FM && (defined(CONFIG_CPU_BR25))) + linein_dec_open(AUDIO_LIN1R_CH, 44100); //696X 系列FM 与 LINEIN复用脚,绑定选择AUDIO_LIN1R_CH +#elif ((TCFG_LINEIN_LR_CH & AUDIO_LIN1R_CH ) && (defined(CONFIG_CPU_BR25))) //FM 与 LINEIN 复用未使能,不可选择AUDIO_LIN1R_CH + log_e("FM is not multiplexed with linein. channel selection err\n"); + ASSERT(0, "err\n"); +#else + printf("linein_dec_open\n"); + linein_dec_open(TCFG_LINEIN_LR_CH, 44100); +#endif + +} + +///*----------------------------------------------------------------------------*/ +/**@brief linein 设置硬件 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +int linein_start(void) +{ + if (__this->onoff == 1) { + log_info("linein is aleady start\n"); + return true; + } + +#if (TCFG_LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ADC) + __linein_way_adc_start(); + __this->audio_state = APP_AUDIO_STATE_MUSIC; +#elif (TCFG_LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ANALOG) + __this->volume = app_audio_get_volume(__this->audio_state); + log_info("current sys vol:%d\n", __this->volume); + __this->audio_state = APP_AUDIO_STATE_LINEIN; + __linein_way_analog_start(); + audio_dac_vol_mute_lock(1); +#ifndef CONFIG_MEDIA_NEW_ENABLE +#if AUDIO_OUTPUT_AUTOMUTE + extern void mix_out_automute_skip(u8 skip); + mix_out_automute_skip(1); +#endif // #if AUDIO_OUTPUT_AUTOMUTE +#endif + +#elif (TCFG_LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_DAC) + __this->volume = app_audio_get_volume(__this->audio_state); + log_info("current sys vol:%d\n", __this->volume); + __this->audio_state = APP_AUDIO_STATE_LINEIN; + + __linein_way_dac_analog_start(); + audio_dac_vol_mute_lock(1); +#ifndef CONFIG_MEDIA_NEW_ENABLE +#if AUDIO_OUTPUT_AUTOMUTE + extern void mix_out_automute_skip(u8 skip); + mix_out_automute_skip(1); +#endif // #if AUDIO_OUTPUT_AUTOMUTE +#endif + +#endif + __this->volume = app_audio_get_volume(__this->audio_state); + __this->onoff = 1; + UI_REFLASH_WINDOW(false);//刷新主页并且支持打断显示 + return true; +} + + + + +/*----------------------------------------------------------------------------*/ +/**@brief linein stop + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void linein_stop(void) +{ + + if (__this->onoff == 0) { + log_info("linein is aleady stop\n"); + return; + } +#if (TCFG_LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ADC) + linein_dec_close(); +#elif (TCFG_LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ANALOG) + + if (TCFG_LINEIN_LR_CH & (BIT(0) | BIT(1))) { + audio_linein0_close(TCFG_LINEIN_LR_CH, 0); + } else if (TCFG_LINEIN_LR_CH & (BIT(2) | BIT(3))) { + audio_linein1_close(TCFG_LINEIN_LR_CH, 0); + } else if (TCFG_LINEIN_LR_CH & (BIT(4) | BIT(5))) { + audio_linein2_close(TCFG_LINEIN_LR_CH, 0); + } + audio_dac_vol_mute_lock(0); +#ifndef CONFIG_MEDIA_NEW_ENABLE +#if AUDIO_OUTPUT_AUTOMUTE + extern void mix_out_automute_skip(u8 skip); + mix_out_automute_skip(0); +#endif // #if AUDIO_OUTPUT_AUTOMUTE +#endif + +#elif (TCFG_LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_DAC) + audio_linein_via_dac_close(TCFG_LINEIN_LR_CH, 0); + audio_dac_vol_mute_lock(0); +#ifndef CONFIG_MEDIA_NEW_ENABLE +#if AUDIO_OUTPUT_AUTOMUTE + extern void mix_out_automute_skip(u8 skip); + mix_out_automute_skip(0); +#endif // #if AUDIO_OUTPUT_AUTOMUTE +#endif + +#endif + app_audio_set_volume(APP_AUDIO_STATE_MUSIC, __this->volume, 1); + __this->onoff = 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief linein start stop 播放暂停切换 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ + +int linein_volume_pp(void) +{ + if (__this->onoff) { + linein_stop(); + } else { + linein_start(); + } + log_info("pp:%d \n", __this->onoff); + UI_REFLASH_WINDOW(true); + return __this->onoff; +} + + + + + + + +/**@brief 获取linein 播放状态 + @param 无 + @return 1:当前正在打开 0:当前正在关闭 + @note +*/ +/*----------------------------------------------------------------------------*/ + +u8 linein_get_status(void) +{ + return __this->onoff; +} + + + + +/* + @note 在linein 情况下针对了某些情景进行了处理,设置音量需要使用独立接口 +*/ + +void linein_tone_play_callback(void *priv, int flag) //模拟linein用数字音量调节播提示音要用这个回调 +{ + linein_volume_pp(); + +} + + +void linein_tone_play(u8 index, u8 preemption) +{ + if (preemption) { //抢断播放 + linein_volume_pp(); + + tone_play_index_with_callback(index, preemption, linein_tone_play_callback, NULL); + } + + else { + tone_play_index_with_callback(index, preemption, NULL, NULL); + } + + + + +} + + + + + + + + +void linein_key_vol_up() +{ + u8 vol; + if (__this->volume < get_max_sys_vol()) { + __this->volume ++; + linein_volume_set(__this->volume); + } else { + linein_volume_set(__this->volume); + if (tone_get_status() == 0) { + /* tone_play(TONE_MAX_VOL); */ +#if TCFG_MAX_VOL_PROMPT + tone_play_by_path(tone_table[IDEX_TONE_MAX_VOL], 0); +#endif + } + } + vol = __this->volume; + UI_SHOW_MENU(MENU_MAIN_VOL, 1000, vol, NULL); + log_info("vol+:%d\n", __this->volume); +} + + + +/* + @note 在linein 情况下针对了某些情景进行了处理,设置音量需要使用独立接口 +*/ +void linein_key_vol_down() +{ + u8 vol; + if (__this->volume) { + __this->volume --; + linein_volume_set(__this->volume); + } + vol = __this->volume; + UI_SHOW_MENU(MENU_MAIN_VOL, 1000, vol, NULL); + log_info("vol-:%d\n", __this->volume); +} + + + + + + + + + + +#endif diff --git a/apps/soundbox/task_manager/linein/linein_dev.c b/apps/soundbox/task_manager/linein/linein_dev.c new file mode 100644 index 0000000..854a1f4 --- /dev/null +++ b/apps/soundbox/task_manager/linein/linein_dev.c @@ -0,0 +1,355 @@ + +/************************************************************* + 此文件函数主要是linein 插入检测 + + 支持和sd卡 io复用检测 + + + +**************************************************************/ +#include "app_config.h" +#include "system/event.h" +#include "system/init.h" +#include "system/timer.h" +#include "asm/power_interface.h" +#include "asm/adc_api.h" +#include "linein/linein.h" +#include "linein/linein_dev.h" +#include "gpio.h" +#include "asm/sdmmc.h" + + +#if TCFG_APP_LINEIN_EN + +#define LINEIN_STU_HOLD 0 +#define LINEIN_STU_ON 1 +#define LINEIN_STU_OFF 2 + +#define LINEIN_DETECT_CNT 3//滤波计算 + + +#define LOG_TAG_CONST APP_LINEIN +#define LOG_TAG "[APP_LINEIN_DEV]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +struct linein_dev_opr { + struct linein_dev_data *dev; + u8 cnt;//滤波计算 + u8 stu;//当前状态 + u16 timer;//定时器句柄 + u8 online: 1; //是否在线 + u8 active: 1; //进入sniff的判断标志 + u8 init: 1; //初始化完成标志 + u8 step: 3; //检测阶段 +}; +static struct linein_dev_opr linein_dev_hdl = {0}; +#define __this (&linein_dev_hdl) + +/*----------------------------------------------------------------------------*/ +/*@brief 获取linein是否在线 + @param + @return 1:在线 0:不在线 + @note app通过这个接口判断linein是否在线 + */ +/*----------------------------------------------------------------------------*/ +u8 linein_is_online(void) +{ +#if ((defined TCFG_LINEIN_DETECT_ENABLE) && (TCFG_LINEIN_DETECT_ENABLE == 0)) + return 1; +#else + return __this->online; +#endif//TCFG_LINEIN_DETECT_ENABLE + +} + +/*----------------------------------------------------------------------------*/ +/*@brief 设置inein是否在线 + @param 1:在线 0:不在线 + @return null + @note 检测驱动通过这个接口判断linein是否在线 + */ +/*----------------------------------------------------------------------------*/ +void linein_set_online(u8 online) +{ + __this->online = !!online; +} + +/*----------------------------------------------------------------------------*/ +/*@brief 发布设备上下线消息 + @param 上下线消息 + */ +/*----------------------------------------------------------------------------*/ +void linein_event_notify(u8 arg) +{ + struct sys_event event = {0}; + event.arg = (void *)DEVICE_EVENT_FROM_LINEIN; + event.type = SYS_DEVICE_EVENT; + + if (arg == DEVICE_EVENT_IN) { + event.u.dev.event = DEVICE_EVENT_IN; + } else if (arg == DEVICE_EVENT_OUT) { + event.u.dev.event = DEVICE_EVENT_OUT; + } else { + return ; + } + sys_event_notify(&event); +} + + +/*----------------------------------------------------------------------------*/ +/*@brief 检测前使能io + @param null + @return null + @note 检测驱动检测前使能io ,检测完成后设为高阻 可以节约功耗 + (io检测、sd复用ad检测动态使用,单独ad检测不动态修改) + */ +/*----------------------------------------------------------------------------*/ +static void linein_io_start(void) +{ + /* printf("<<dev; + if (__this->init) { + return ; + } + __this->init = 1; + if (linein_dev->down) { + gpio_set_pull_down(linein_dev->port, 1); + } else { + gpio_set_pull_down(linein_dev->port, 0); + } + if (linein_dev->up) { + gpio_set_pull_up(linein_dev->port, 1); + } else { + gpio_set_pull_up(linein_dev->port, 0); + } + if (linein_dev->ad_channel == (u8)NO_CONFIG_PORT) { + gpio_set_die(linein_dev->port, 1); + } else { + gpio_set_die(linein_dev->port, 0); + } + gpio_set_hd(linein_dev->port, 0); + gpio_set_hd0(linein_dev->port, 0); + gpio_direction_input(linein_dev->port); +} + +/*----------------------------------------------------------------------------*/ +/*@brief 检测完成关闭使能io + @param null + @return null + @note 检测驱动检测前使能io ,检测完成后设为高阻 可以节约功耗 + (io检测、sd复用ad检测动态使用,单独ad检测不动态修改) + */ +/*----------------------------------------------------------------------------*/ +static void linein_io_stop(void) +{ + /* printf("<<dev; + if (!__this->init) { + return ; + } + __this->init = 0; + gpio_direction_input(linein_dev->port); + gpio_set_pull_up(linein_dev->port, 0); + gpio_set_pull_down(linein_dev->port, 0); + gpio_set_hd(linein_dev->port, 0); + gpio_set_hd0(linein_dev->port, 0); + gpio_set_die(linein_dev->port, 0); +} + +/*----------------------------------------------------------------------------*/ +/*@brief 检测是否在线 + @param 驱动句柄 + @return 1:有设备插入 0:没有设备插入 + @note 检测驱动检测前使能io ,检测完成后设为高阻 可以节约功耗 + (io检测、sd复用ad检测动态使用,单独ad检测不动态修改) + */ +/*----------------------------------------------------------------------------*/ +static int linein_sample_detect(void *arg) +{ + struct linein_dev_data *linein_dev = (struct linein_dev_data *)arg; + u8 cur_stu; + + if (linein_dev->ad_channel == (u8)NO_CONFIG_PORT) { + linein_io_start(); + cur_stu = gpio_read(linein_dev->port) ? false : true; + linein_io_stop(); + if (!linein_dev->up) { + cur_stu = !cur_stu; + } + } else { + cur_stu = adc_get_value(linein_dev->ad_channel) > linein_dev->ad_vol ? false : true; + /* printf("<%d> ", adc_get_value(linein_dev->ad_channel)); */ + } + /* putchar('A' + cur_stu); */ + return cur_stu; +} + +/*----------------------------------------------------------------------------*/ +/*@brief sd cmd 复用检测是否在线 + @param 驱动句柄 + @return 1:有设备插入 0:没有设备插入 + @note 检测驱动检测前使能io ,检测完成后设为高阻 可以节约功耗 + (io检测、sd复用ad检测动态使用,单独ad检测不动态修改) + */ +/*----------------------------------------------------------------------------*/ +static int linein_sample_mult_sd(void *arg) +{ + struct linein_dev_data *linein_dev = (struct linein_dev_data *)arg; + linein_io_start(); + u16 ad_value = 0; + u8 cur_stu; + if (linein_dev->ad_channel == (u8)NO_CONFIG_PORT) { + cur_stu = gpio_read(linein_dev->port) ? false : true; + } else { + adc_enter_occupy_mode(linein_dev->ad_channel); + if (adc_occupy_run()) { + ad_value = adc_get_occupy_value(); + cur_stu = ad_value > linein_dev->ad_vol ? false : true; + /* printf("\n<%d>\n", ad_value); */ + } else { + cur_stu = __this->stu; + } + adc_exit_occupy_mode(); + } + + /* putchar('A'+cur_stu); */ + /* putchar(cur_stu); */ + linein_io_stop(); + return cur_stu; +} + + +/*----------------------------------------------------------------------------*/ +/*@brief 注册的定时器回调检测函数 + @param 驱动句柄 + @return null + @note 定时进行检测 + */ +/*----------------------------------------------------------------------------*/ +static void linein_detect(void *arg) +{ + int cur_stu; + struct sys_event event = {0}; +#if ((TCFG_LINEIN_MULTIPLEX_WITH_SD == ENABLE)) + if (sd_io_suspend(TCFG_LINEIN_SD_PORT, 0) == 0) {//判断sd 看是否空闲 + cur_stu = linein_sample_mult_sd(arg); + sd_io_resume(TCFG_LINEIN_SD_PORT, 0);//使用完,回复sd + } else { + return; + } +#else + if (__this->step == 0) { + __this->step = 1; + sys_timer_modify(__this->timer, 10);//猜测是检测状态变化的时候改变定时器回调时间 + return ; + } + cur_stu = linein_sample_detect(arg); + if (!__this->active) { + __this->step = 0; + sys_timer_modify(__this->timer, 500);//猜测是检测状态不变化的时候改变定时器回调时间 + } +#endif + + if (cur_stu != __this->stu) { + __this->stu = cur_stu; + __this->cnt = 0; + __this->active = 1; + } else { + __this->cnt ++; + } + + if (__this->cnt < LINEIN_DETECT_CNT) {//滤波计算 + return; + } + + __this->active = 0;//检测一次完成 + + + /* putchar(cur_stu); */ + + if ((linein_is_online()) && (!__this->stu)) { + linein_set_online(false); + linein_event_notify(DEVICE_EVENT_OUT);//发布下线消息 + } else if ((!linein_is_online()) && (__this->stu)) { + linein_set_online(true); + linein_event_notify(DEVICE_EVENT_IN);//发布上线消息 + } + return; +} + +void linein_detect_timer_add() +{ + if (!__this || !(__this->dev)) { + return; + } + if (__this->timer == 0) { + __this->timer = sys_timer_add(__this->dev, linein_detect, 25); + } +} +void linein_detect_timer_del() +{ + if (__this && __this->timer) { + sys_timer_del(__this->timer); + __this->timer = 0; + } +} + +static int linein_driver_init(const struct dev_node *node, void *arg) +{ + struct linein_dev_data *linein_dev = (struct linein_dev_data *)arg; + if (!linein_dev->enable) { + linein_set_online(true); + return 0; + } +#if ((defined TCFG_LINEIN_DETECT_ENABLE) && (TCFG_LINEIN_DETECT_ENABLE == 0)) + linein_set_online(true);//没有配置detcct 默认在线 + return 0; +#endif + + if (linein_dev->port == (u8)NO_CONFIG_PORT) { + linein_set_online(true);//配置的io 不在范围 ,默认在线 + return 0; + } + linein_set_online(false); + +#if (!(TCFG_LINEIN_MULTIPLEX_WITH_SD))//复用情况和io检测仅在使用的时候配置io + if (linein_dev->ad_channel != (u8)NO_CONFIG_PORT) { + linein_io_start();//初始化io + adc_add_sample_ch(linein_dev->ad_channel); + } +#endif + + __this->dev = linein_dev; + __this->timer = sys_timer_add(arg, linein_detect, 50); + return 0; +} + +const struct device_operations linein_dev_ops = { + .init = linein_driver_init, +}; + + +/*----------------------------------------------------------------------------*/ +/*@brief 注册的定功耗检测函数 + @param + @return null + @note 用于防止检测一次未完成进入了低功耗 + */ +/*----------------------------------------------------------------------------*/ +static u8 linein_dev_idle_query(void) +{ + return !__this->active; +} + +REGISTER_LP_TARGET(linein_dev_lp_target) = { + .name = "linein_dev", + .is_idle = linein_dev_idle_query, +}; + +#endif + diff --git a/apps/soundbox/task_manager/music/music.c b/apps/soundbox/task_manager/music/music.c new file mode 100644 index 0000000..04e5dda --- /dev/null +++ b/apps/soundbox/task_manager/music/music.c @@ -0,0 +1,1075 @@ +#include "music/music.h" +#include "music_player.h" +#include "system/includes.h" +#include "app_config.h" +#include "app_task.h" +#include "app_main.h" +#include "clock_cfg.h" +#include "app_action.h" +#include "breakpoint.h" +#include "key_event_deal.h" +#include "tone_player.h" +#include "dev_multiplex_api.h" +#include "ui/ui_api.h" +#include "bt/bt.h" +#include "smartbox/smartbox.h" +#include "ui_manage.h" +#include "audio_dec.h" +#include "common/dev_status.h" +#include "clock_cfg.h" +#include "system/fs/fs.h" +#include "user_api/app_status_api.h" + +/************************************************************* + 此文件函数主要是music模式按键处理和事件处理 + + void app_music_task() + music模式主函数 + + static int music_sys_event_handler(struct sys_event *event) + music模式系统事件所有处理入口 + + static void music_task_close(void) + music模式退出 + +**************************************************************/ + +#define LOG_TAG_CONST APP_MUSIC +#define LOG_TAG "[APP_MUSIC]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#if TCFG_APP_MUSIC_EN + +static u8 music_idle_flag = 1; + +///模式参数结构体 +struct __music_task_parm { + u8 type; + int val; +}; + +///music模式控制结构体 +struct __music { + struct __music_task_parm task_parm; + u16 file_err_counter;//错误文件统计 + u8 file_play_direct;//0:下一曲, 1:上一曲 + u8 scandisk_break;//扫描设备打断标志 + char device_tone_dev[16]; +#if SD_BAUD_RATE_CHANGE_WHEN_SCAN + u32 old_speed; +#endif +}; +struct __music music_hdl; +#define __this (&music_hdl) + +static struct __breakpoint *breakpoint = NULL; + + +static void music_player_play_start(void); + +///设备提示音使能 +#define MUSIC_DEVICE_TONE_EN 0 +#if (MUSIC_DEVICE_TONE_EN) +struct __dev_tone { + char *logo; + char *phy_logo; + char *tone_path; + u16 index; +}; + +enum { + ///0x1000起始为了不要跟提示音的IDEX_TONE_重叠了 + DEVICE_INDEX_UDISK = 0x1000, + DEVICE_INDEX_UDISK_REC, + DEVICE_INDEX_SD0, + DEVICE_INDEX_SD0_REC, + DEVICE_INDEX_SD1, + DEVICE_INDEX_SD1_REC, +}; +const struct __dev_tone device_tone[] = { + {"udisk0", "udisk0", TONE_RES_ROOT_PATH"tone/udisk.*", DEVICE_INDEX_UDISK} , + {"udisk0_rec", "udisk0", TONE_RES_ROOT_PATH"tone/udisk.*", DEVICE_INDEX_UDISK_REC} , + {"sd0", "sd0", TONE_RES_ROOT_PATH"tone/sd.*", DEVICE_INDEX_SD0} , + {"sd0_rec", "sd0", TONE_RES_ROOT_PATH"tone/sd.*", DEVICE_INDEX_SD0_REC} , + {"sd1", "sd1", TONE_RES_ROOT_PATH"tone/sd.*", DEVICE_INDEX_SD1} , + {"sd1_rec", "sd1", TONE_RES_ROOT_PATH"tone/sd.*", DEVICE_INDEX_SD1_REC} , +}; +static void music_tone_play_end_callback(void *priv, int flag); +int music_device_tone_play(char *logo) +{ + if (logo == NULL) { + return false; + } + printf("__this->device_tone_dev = %s, logo =%s\n", __this->device_tone_dev, logo); + char *phy_logo = dev_manager_get_phy_logo(dev_manager_find_spec(logo, 0)); + if (phy_logo && (strcmp(__this->device_tone_dev, phy_logo) == 0)) { + log_i("[%s, %d]the same phy dev, no need device tone!!\n", logo, __LINE__); + return false; + } + for (int i = 0; i < ARRAY_SIZE(device_tone); i++) { + if (strcmp(device_tone[i].logo, logo) == 0) { + log_i("[%s, %d]device_tone play \n", logo, __LINE__); + memset(__this->device_tone_dev, 0, sizeof(__this->device_tone_dev)); + memcpy(__this->device_tone_dev, device_tone[i].phy_logo, strlen(device_tone[i].phy_logo)); + tone_play_with_callback_by_name(device_tone[i].tone_path, 1, music_tone_play_end_callback, (void *)device_tone[i].index); + return true; + } + } + log_i("[%s, %d]device_tone play \n", logo, __LINE__); + return false; +} +#endif + + + +#if TCFG_LFN_EN +static u8 music_file_name[128] = {0}; //长文件名 +u16 music_file_name_len = 0; +#else +static u8 music_file_name[12 + 1] = {0}; //8.3+\0 +u16 music_file_name_len = 0; +#endif + +const char *music_file_get_cur_name(int *len, int *is_unicode) +{ + if (music_file_name[0] == '\\' && music_file_name[1] == 'U') { + *is_unicode = 1 ; + *len = music_file_name_len - 2; + return (const char *)(music_file_name + 2); + } + *is_unicode = 0 ; + *len = music_file_name_len; + return (const char *)music_file_name; +} + + +static void music_set_dev_sync_mode(char *logo, u8 mode) +{ + if (logo) { + struct imount *mount_hdl = NULL; + u8 async_mode = mode; + + if ((!memcmp(logo, "udisk0", strlen("udisk0"))) + || (!memcmp(logo, "udisk0_rec", strlen("udisk0_rec")))) { + struct file_dec_hdl *dec = get_file_dec_hdl(); + if (dec) { + mount_hdl = dev_manager_get_mount_hdl(dev_manager_find_spec(logo, 0)); + if (mount_hdl) { + if (dec->file_dec.decoder.dec_ops->coding_type == AUDIO_CODING_APE + || dec->file_dec.decoder.dec_ops->coding_type == AUDIO_CODING_FLAC + || dec->file_dec.decoder.dec_ops->coding_type == AUDIO_CODING_DTS + || dec->file_dec.decoder.dec_ops->coding_type == AUDIO_CODING_WAV) { + ///指定解码格式开启该功能 + dev_ioctl(mount_hdl->dev.fd, IOCTL_SET_ASYNC_MODE, (u32)async_mode); + } else { + ///不指定的解码格式不开启 + async_mode = 0; + dev_ioctl(mount_hdl->dev.fd, IOCTL_SET_ASYNC_MODE, (u32)async_mode); + } + printf("udisk, set usb ASYNC = %d\n", async_mode); + } + } + } else { + //不是udisk, 如果udisk在线, 将udisk设置成非AYSNC_MODE + mount_hdl = dev_manager_get_mount_hdl(dev_manager_find_spec("udisk0", 0)); + if (mount_hdl) { + async_mode = 0; + printf("not udisk, set usb ASYNC = 0\n"); + dev_ioctl(mount_hdl->dev.fd, IOCTL_SET_ASYNC_MODE, (u32)async_mode); + } + } + } +} + +u16 music_playing_time_timer_id = 0; +void music_playing_show(void *priv) +{ + int sencond = file_dec_get_cur_time(); + printf("sec = %d \n", sencond); +} + +//*----------------------------------------------------------------------------*/ +/**@brief music 解码成功回调 + @param priv:私有参数, parm:暂时未用 + @return + @note 此处可以做一些用户操作, 如断点保存, 显示, 获取播放信息等 +*/ +/*----------------------------------------------------------------------------*/ +static void music_player_play_success(void *priv, int parm) +{ + char *logo = music_player_get_dev_cur(); + + //使能usb预读功能 + music_set_dev_sync_mode(logo, 1); + + log_i("\n\n----------------music_player_play_success----------------------\n"); + log_i("cur dev = %s\n", logo); + log_i("total dev = %d\n", dev_manager_get_total(1)); + log_i("cur filenum = %d\n", music_player_get_file_cur()); + log_i("totol filenum = %d\n", music_player_get_file_total()); + log_i("totol time = %d\n", music_player_get_dec_total_time()); + log_i("sclust = %d\n", music_player_get_file_sclust()); + log_i("dir_cur = %d\n", music_player_get_dir_cur()); + log_i("dir_total = %d\n", music_player_get_dir_total()); + log_i("file indir = %d\n", music_player_get_fileindir_number()); + music_file_name_len = fget_name(music_player_get_file_hdl(), music_file_name, sizeof(music_file_name)); + int unicode = 0; + if ((music_file_name[0] == '\\') && (music_file_name[1] == 'U')) { + unicode = 1; + music_file_name_len -= 2; + log_i("cur file = %s, len = %d, unicode = %d\n", music_file_name + 2, music_file_name_len, unicode); + } else { + log_i("cur file = %s, len = %d, unicode = %d\n", music_file_name, music_file_name_len, unicode); + } + log_i("\n"); + + + + ///save breakpoint, 只保存文件信息 + if (music_player_get_playing_breakpoint(breakpoint, 0) == true) { + breakpoint_vm_write(breakpoint, logo); + } + + int analaz = music_player_lrc_analy_start(); + ///show ui + UI_SHOW_MENU(MENU_FILENUM, 1000, music_player_get_file_cur(), NULL); + UI_MSG_POST("music_start:show_lyric=%4:dev=%4:filenum=%4:total_filenum=%4", !analaz, logo, music_player_get_file_cur(), music_player_get_file_total()); + ///smartbox info update + SMARTBOX_UPDATE(MUSIC_FUNCTION_MASK,BIT(MUSIC_INFO_ATTR_STATUS) | BIT(MUSIC_INFO_ATTR_FILE_NAME) | BIT(MUSIC_INFO_ATTR_FILE_PLAY_MODE)); + + if(!music_playing_time_timer_id) { + music_playing_time_timer_id = sys_timer_add(NULL, music_playing_show, 500); + } +} +//*----------------------------------------------------------------------------*/ +/**@brief music 解码结束回调处理 + @param + @return + @note 此处统一将错误通过消息的方式发出, 在key msg中统一响应 +*/ +/*----------------------------------------------------------------------------*/ +static void music_player_play_end(void *priv, int parm) +{ + log_i("music_player_play_end\n"); + ///这里推出消息, 目的是在music主流程switch case统一入口 + app_task_put_key_msg(KEY_MUSIC_PLAYER_END, parm); + if(music_playing_time_timer_id) { + sys_timer_del(music_playing_time_timer_id); + music_playing_time_timer_id = 0; + } +} +//*----------------------------------------------------------------------------*/ +/**@brief music 解码错误回调 + @param + @return + @note 此处统一将错误通过消息的方式发出, 在key msg中统一响应 +*/ +/*----------------------------------------------------------------------------*/ +static void music_player_decode_err(void *priv, int parm) +{ + log_i("music_player_decode_err\n"); + ///这里推出消息, 目的是在music主流程switch case统一入口 + app_task_put_key_msg(KEY_MUSIC_PLAYER_DEC_ERR, parm); +} +//*----------------------------------------------------------------------------*/ +/**@brief music 播放器扫盘打断接口 + @param + @return 1:打断当前扫描,0:正常扫描 + @note 设备扫描耗时长的情况下, 此接口提供打断机制 +*/ +/*----------------------------------------------------------------------------*/ +static int music_player_scandisk_break(void) +{ + ///注意: + ///需要break fsn的事件, 请在这里拦截, + ///需要结合MUSIC_PLAYER_ERR_FSCAN错误,做相应的处理 + int msg[32] = {0}; + struct sys_event *event = NULL; + char *logo = NULL; + char *evt_logo = NULL; + app_task_get_msg(msg, ARRAY_SIZE(msg), 0); + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + event = (struct sys_event *)(&msg[1]); + switch (event->type) { + case SYS_DEVICE_EVENT: + switch ((u32)event->arg) { + case DRIVER_EVENT_FROM_SD0: + case DRIVER_EVENT_FROM_SD1: + case DRIVER_EVENT_FROM_SD2: + evt_logo = (char *)event->u.dev.value; + case DEVICE_EVENT_FROM_OTG: + if ((u32)event->arg == DEVICE_EVENT_FROM_OTG) { + evt_logo = (char *)"udisk0"; + } + ///设备上下线底层推出的设备逻辑盘符是跟跟音乐设备一致的(音乐/录音设备, 详细看接口注释) + int str_len = 0; + logo = music_player_get_phy_dev(&str_len); + ///响应设备插拔打断 + if (event->u.dev.event == DEVICE_EVENT_OUT) { + log_i("__func__ = %s logo=%s evt_logo=%s %d\n", __FUNCTION__, logo, evt_logo, str_len); + if (logo && (0 == memcmp(logo, evt_logo, str_len))) { + ///相同的设备才响应 + __this->scandisk_break = 1; + } + } else { + ///响应新设备上线 + __this->scandisk_break = 1; + } + if (__this->scandisk_break == 0) { + log_i("__func__ = %s DEVICE_EVENT_OUT TODO\n", __FUNCTION__); + dev_status_event_filter(event); + log_i("__func__ = %s DEVICE_EVENT_OUT OK\n", __FUNCTION__); + } + break; + } + break; + case SYS_BT_EVENT: + if (bt_background_event_handler_filter(event)) { + __this->scandisk_break = 1; + } + break; + case SYS_KEY_EVENT: + switch (event->u.key.event) { + case KEY_CHANGE_MODE: + ///响应切换模式事件 + __this->scandisk_break = 1; + break; + //其他按键case 在这里增加 + } + ///因为TWS转发sys_event_notify需要用原始的按键序号, 未经过按键表处理, 所以这里要特殊处理 + if (__this->scandisk_break) { + app_task_put_key_msg(event->u.key.event, (int)event->u.key.value); + printf("key break scan!!"); + return 1; + } + break; + } + break; + } + if (__this->scandisk_break) { + ///查询到需要打断的事件, 返回1, 并且重新推送一次该事件,跑主循环处理流程 + sys_event_notify(event); + printf("scandisk_break!!!!!!\n"); + return 1; + } else { + return 0; + } +} + +static const struct __player_cb music_player_callback = { + .start = music_player_play_success, + .end = music_player_play_end, + .err = music_player_decode_err, +// .fsn_break = music_player_scandisk_break, +}; + +static void scan_enter(struct __dev *dev) +{ +#if SD_BAUD_RATE_CHANGE_WHEN_SCAN + struct imount *mount_hdl = dev_manager_get_mount_hdl(dev); + if (mount_hdl) { + if ((!memcmp(dev_manager_get_logo(dev), "sd0", strlen("sd0"))) + || (!memcmp(dev_manager_get_logo(dev), "sd1", strlen("sd1")))) { + dev_ioctl(mount_hdl->dev.fd, IOCTL_GET_SPEED, (u32)&__this->old_speed); //获取sd速度 + if (SD_BAUD_RATE_CHANGE_WHEN_SCAN > __this->old_speed) { //设定速度大于获取的才加速 + dev_ioctl(mount_hdl->dev.fd, IOCTL_SET_SPEED, SD_BAUD_RATE_CHANGE_WHEN_SCAN); + } + } + } +#endif + clock_add_set(SCAN_DISK_CLK); +} + +static void scan_exit(struct __dev *dev) +{ +#ifdef SD_BAUD_RATE_CHANGE_WHEN_SCAN + struct imount *mount_hdl = dev_manager_get_mount_hdl(dev); + if (mount_hdl) { + if ((!memcmp(dev_manager_get_logo(dev), "sd0", strlen("sd0"))) + || (!memcmp(dev_manager_get_logo(dev), "sd1", strlen("sd1")))) { + if (SD_BAUD_RATE_CHANGE_WHEN_SCAN > __this->old_speed) { + dev_ioctl(mount_hdl->dev.fd, IOCTL_SET_SPEED, __this->old_speed);//恢复原速 + } + } + } +#endif + clock_remove_set(SCAN_DISK_CLK); +} + +static const struct __scan_callback scan_cb = { + .enter = scan_enter, + .exit = scan_exit, + .scan_break = music_player_scandisk_break, +}; + +//*----------------------------------------------------------------------------*/ +/**@brief music 模式提示音播放结束处理 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void music_tone_play_end_callback(void *priv, int flag) +{ + u32 index = (u32)priv; + char *logo = NULL; + + if (APP_MUSIC_TASK != app_get_curr_task()) { + log_error("tone callback task out \n"); + return; + } + + switch (index) { + case IDEX_TONE_MUSIC: + ///提示音播放结束, 启动播放器播 + music_player_play_start(); + break; +#if (MUSIC_DEVICE_TONE_EN) + case DEVICE_INDEX_UDISK: + case DEVICE_INDEX_UDISK_REC: + case DEVICE_INDEX_SD0: + case DEVICE_INDEX_SD0_REC: + case DEVICE_INDEX_SD1: + case DEVICE_INDEX_SD1_REC: + for (int i = 0; i < ARRAY_SIZE(device_tone); i++) { + if (index == device_tone[i].index) { + logo = device_tone[i].logo; + break; + } + } + app_task_put_key_msg(KEY_MUSIC_DEVICE_TONE_END, (int)logo); + break; +#endif + default: + break; + } +} + + +//*----------------------------------------------------------------------------*/ +/**@brief music 模式解码错误处理 + @param err:错误码,详细错误码描述请看MUSIC_PLAYER错误码表枚举 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void music_player_err_deal(int err) +{ + u16 msg = KEY_NULL; + char *logo = NULL; + if (err != MUSIC_PLAYER_ERR_NULL && err != MUSIC_PLAYER_ERR_DECODE_FAIL) { + __this->file_err_counter = 0;///清除错误文件累计 + } + + if (err != MUSIC_PLAYER_ERR_NULL && err != MUSIC_PLAYER_SUCC) { + log_e("music player err = %d\n", err); + } + + switch (err) { + case MUSIC_PLAYER_SUCC: + __this->file_err_counter = 0; + break; + case MUSIC_PLAYER_ERR_NULL: + break; + case MUSIC_PLAYER_ERR_POINT: + case MUSIC_PLAYER_ERR_NO_RAM: + msg = KEY_MUSIC_PLAYER_QUIT;//退出音乐模式 + break; + case MUSIC_PLAYER_ERR_DECODE_FAIL: + if (__this->file_err_counter >= music_player_get_file_total()) { + __this->file_err_counter = 0; + dev_manager_set_valid_by_logo(music_player_get_dev_cur(), 0);///将设备设置为无效设备 + if (dev_manager_get_total(1) == 0) {//参数为1 :获取所有有效设备 参数0:获取所有设备 + msg = KEY_MUSIC_PLAYER_QUIT;//没有设备了,退出音乐模式 + } else { + msg = KEY_MUSIC_AUTO_NEXT_DEV;///所有文件都是错误的, 切换到下一个设备 + } + } else { + __this->file_err_counter ++; + if (__this->file_play_direct == 0) { + msg = KEY_MUSIC_NEXT;//播放下一曲 + } else { + msg = KEY_MUSIC_PREV;//播放上一曲 + } + } + break; + case MUSIC_PLAYER_ERR_DEV_NOFOUND: + log_e("MUSIC_PLAYER_ERR_DEV_NOFOUND \n"); + if (dev_manager_get_total(1) == 0) {//参数为1 :获取所有有效设备 参数0:获取所有设备 + msg = KEY_MUSIC_PLAYER_QUIT;///没有设备在线, 退出音乐模式 + } else { + msg = KEY_MUSIC_PLAYER_START;///没有找到指定设备, 播放之前的活动设备 + } + break; + + case MUSIC_PLAYER_ERR_FSCAN: + ///需要结合music_player_scandisk_break中处理的标志位处理 + if (__this->scandisk_break) { + __this->scandisk_break = 0; + ///此处不做任何处理, 打断的事件已经重发, 由重发事件执行后续处理 + break; + } + case MUSIC_PLAYER_ERR_DEV_READ: + case MUSIC_PLAYER_ERR_DEV_OFFLINE: + log_e("MUSIC_PLAYER_ERR_DEV_OFFLINE \n"); + logo = music_player_get_dev_cur(); + if (dev_manager_online_check_by_logo(logo, 1)) { + ///如果错误失败在线, 并且是播放过程中产生的,先记录下断点 + if (music_player_get_playing_breakpoint(breakpoint, 1) == true) { + music_player_stop(0);//先停止,防止下一步操作VM卡顿 + breakpoint_vm_write(breakpoint, logo); + } + if (err == MUSIC_PLAYER_ERR_FSCAN) { + dev_manager_set_valid_by_logo(logo, 0);///将设备设置为无效设备 + } else { + //针对读错误, 因为时间推到应用层有延时导致下一个模式判断不正常, 此处需要将设备卸载 + dev_manager_unmount(logo); + } + } + if (dev_manager_get_total(1) == 0) { + app_status_handler(APP_STATUS_MUSIC_QUIT); + msg = KEY_MUSIC_PLAYER_QUIT;///没有设备在线, 退出音乐模式 + } else { + msg = KEY_MUSIC_AUTO_NEXT_DEV;///切换设备 + } + break; + case MUSIC_PLAYER_ERR_FILE_NOFOUND: + ///查找文件有扫盘的可能,也需要结合music_player_scandisk_break中处理的标志位处理 + if (__this->scandisk_break) { + __this->scandisk_break = 0; + ///此处不做任何处理, 打断的事件已经重发, 由重发事件执行后续处理 + break; + } + case MUSIC_PLAYER_ERR_PARM: + logo = music_player_get_dev_cur(); + if (dev_manager_online_check_by_logo(logo, 1)) { + if (music_player_get_file_total()) { + msg = KEY_MUSIC_PLAYER_PLAY_FIRST;///有文件,播放第一个文件 + break; + } + } + + if (dev_manager_get_total(1) == 0) { + msg = KEY_MUSIC_PLAYER_QUIT;//没有设备了,退出音乐模式 + } else { + msg = KEY_MUSIC_AUTO_NEXT_DEV; + } + break; + case MUSIC_PLAYER_ERR_FILE_READ://文件读错误 + msg = KEY_MUSIC_NEXT;//播放下一曲 + break; + } + if (msg != KEY_NULL) { + app_task_put_key_msg(msg, 0); + } +} +//*----------------------------------------------------------------------------*/ +/**@brief music 按键消息入口 + @param 无 + @return 1、消息已经处理,common不再处理 0、消息发送到common处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int music_key_event_opr(struct sys_event *event) +{ + int ret = true; + int err = MUSIC_PLAYER_ERR_NULL; + u8 vol, auto_next_dev; + int mode ; + char *logo = NULL; + + int msg[2]; + msg[0] = event->u.key.event; + msg[1] = event->u.key.value;// + static int msg_demo = 0; + + log_i("music task msg = %d\n", msg[0]); + + switch (msg[0]) { + case KEY_MUSIC_DEVICE_TONE_END: +#if (MUSIC_DEVICE_TONE_EN) + logo = (char *)msg[1]; + log_i("KEY_MUSIC_DEVICE_TONE_END %s\n", logo); + if (logo) { + if (true == breakpoint_vm_read(breakpoint, logo)) { + err = music_player_play_by_breakpoint(logo, breakpoint); + } else { + err = music_player_play_first_file(logo); + } + } + break; +#endif + case KEY_MUSIC_PLAYER_START: + log_i("KEY_MUSIC_PLAYER_START !!\n"); + app_status_handler(APP_STATUS_MUSIC_PLAY); + ///断点播放活动设备 + logo = dev_manager_get_logo(dev_manager_find_active(1)); + if (music_player_get_play_status() == FILE_DEC_STATUS_PLAY) { + if (music_player_get_dev_cur() && logo) { + ///播放的设备跟当前活动的设备是同一个设备,不处理 + if (0 == strcmp(logo, music_player_get_dev_cur())) { + log_w("the same dev!!\n"); + break; + } + } + } +#if (MUSIC_DEVICE_TONE_EN) + if (music_device_tone_play(logo) == true) { + break; + } +#endif + if (true == breakpoint_vm_read(breakpoint, logo)) { + err = music_player_play_by_breakpoint(logo, breakpoint); + } else { + err = music_player_play_first_file(logo); + } + break; + ///播放器退出处理 + case KEY_MUSIC_PLAYER_QUIT: + log_i("KEY_MUSIC_PLAYER_QUIT !!\n"); + app_task_switch_next(); + break; + ///结束消息处理 + case KEY_MUSIC_PLAYER_END: + log_i("KEY_MUSIC_PLAYER_END\n"); + err = music_player_end_deal(msg[1]); + break; + //播放器解码错误处理 + case KEY_MUSIC_PLAYER_DEC_ERR: + err = music_player_decode_err_deal(msg[1]); + break; + ///播放执行类消息 + case KEY_MUSIC_PP: + log_i("KEY_MUSIC_PP\n"); + logo = music_player_get_dev_cur(); + if (music_player_get_play_status() == FILE_DEC_STATUS_PLAY) { + music_set_dev_sync_mode(logo, 0); + } else { + music_set_dev_sync_mode(logo, 1); + + } + err = music_player_pp(); + if (music_player_get_play_status() == FILE_DEC_STATUS_PLAY) { + app_status_handler(APP_STATUS_MUSIC_PLAY); + ui_update_status(STATUS_MUSIC_PLAY); + } else { + app_status_handler(APP_STATUS_MUSIC_PP); + ui_update_status(STATUS_MUSIC_PAUSE); + /* tone_play_by_path(tone_table[IDEX_TONE_MAX_VOL],1); */ + } + printf("=============================================%d\n", music_player_get_play_status()); + break; + case KEY_MUSIC_PLAYER_AUTO_NEXT: + log_i("KEY_MUSIC_PLAYER_AUTO_NEXT\n"); + err = music_player_play_auto_next(); + break; + case KEY_MUSIC_PLAYER_PLAY_FIRST: + log_i("KEY_MUSIC_PLAYER_PLAY_FIRST\n"); + err = music_player_play_first_file(NULL); + break; + case KEY_MUSIC_PREV: + log_i("KEY_MUSIC_PREV\n"); + app_status_handler(APP_STATUS_MUSIC_FFR); + __this->file_play_direct = 1; + err = music_player_play_prev(); + break; + case KEY_MUSIC_NEXT: + log_i("KEY_MUSIC_NEXT\n"); + app_status_handler(APP_STATUS_MUSIC_FFR); + __this->file_play_direct = 0; + err = music_player_play_next(); + break; + case KEY_MUSIC_PLAYE_PREV_FOLDER: + log_i("KEY_MUSIC_PLAYE_PREV_FOLDER\n"); + err = music_player_play_folder_prev(); + break; + case KEY_MUSIC_PLAYE_NEXT_FOLDER: + log_i("KEY_MUSIC_PLAYE_NEXT_FOLDER\n"); + err = music_player_play_folder_next(); + break; + + case KEY_MUSIC_AUTO_NEXT_DEV: + case KEY_MUSIC_CHANGE_DEV: + log_i("KEY_MUSIC_CHANGE_DEV\n"); + auto_next_dev = ((msg[0] == KEY_MUSIC_AUTO_NEXT_DEV) ? 1 : 0); + logo = music_player_get_dev_next(auto_next_dev); + printf("next dev = %s\n", logo); + if (logo == NULL) { ///找不到下一个设备,不响应设备切换 + break; + } + ///切换设备前先保存一下上一个设备的断点信息,包括文件和解码信息 + if (music_player_get_playing_breakpoint(breakpoint, 1) == true) { + music_player_stop(0);//先停止,防止下一步操作VM卡顿 + breakpoint_vm_write(breakpoint, music_player_get_dev_cur()); + } +#if (MUSIC_DEVICE_TONE_EN) + if (music_device_tone_play(logo) == true) { + break; + } +#endif + if (true == breakpoint_vm_read(breakpoint, logo)) { + err = music_player_play_by_breakpoint(logo, breakpoint); + } else { + err = music_player_play_first_file(logo); + } + break; + case KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH: + log_i("KEY_MUSIC_PLAYE_REC_FOLDER_SWITCH\n"); +#if (TCFG_RECORD_FOLDER_DEV_ENABLE) + ///尝试保存断点 + if (music_player_get_playing_breakpoint(breakpoint, 1) == true) { + breakpoint_vm_write(breakpoint, music_player_get_dev_cur()); + } + if (true == breakpoint_vm_read(breakpoint, music_player_get_cur_music_dev())) { + err = music_player_play_record_folder(NULL, breakpoint); + } else { + err = music_player_play_record_folder(NULL, NULL); + } +#endif//TCFG_RECORD_FOLDER_DEV_ENABLE + break; + case KEY_MUSIC_PLAYE_BY_DEV_FILENUM: + log_i("KEY_MUSIC_PLAYE_BY_DEV_FILENUM, file_number = %d\n", msg[1]); + logo = dev_manager_get_logo(dev_manager_find_active(1)); + err = music_player_play_by_number(logo, msg[1]); + break; + case KEY_MUSIC_PLAYE_BY_DEV_SCLUST: + log_i("KEY_MUSIC_PLAYE_BY_DEV_SCLUST\n"); + logo = dev_manager_get_logo(dev_manager_find_active(1)); + err = music_player_play_by_sclust(logo, msg[1]); + break; + case KEY_MUSIC_PLAYE_BY_DEV_PATH: + log_i("KEY_MUSIC_PLAYE_BY_DEV_PATH\n"); + err = music_player_play_by_path((char *)"udisk0", "/sin.wav");///this is a demo + break; + + + ///非播放执行类消息 + case KEY_MUSIC_FF: + log_i("KEY_MUSIC_FF\n"); + app_status_handler(APP_STATUS_MUSIC_FFR); + music_player_ff(3); + break; + case KEY_MUSIC_FR: + log_i("KEY_MUSIC_FR\n"); + app_status_handler(APP_STATUS_MUSIC_FFR); + music_player_fr(3); + break; + case KEY_MUSIC_CHANGE_REPEAT: + log_i("KEY_MUSIC_CHANGE_REPEAT\n"); + mode = music_player_change_repeat_mode(); + if (mode > 0) { + UI_SHOW_MENU(MENU_MUSIC_REPEATMODE, 1000, mode, NULL); + } + break; + case KEY_MUSIC_DELETE_FILE: + log_i("KEY_MUSIC_DELETE_FILE\n"); + err = music_player_delete_playing_file(); + break; + case KEY_MUSIC_PLAYER_AB_REPEAT_SWITCH: + file_dec_ab_repeat_switch(); + break; + + default: + ret = false; + break; + } + + + ///错误处理 + music_player_err_deal(err); + ///smartbox info update + SMARTBOX_UPDATE(MUSIC_FUNCTION_MASK, + BIT(MUSIC_INFO_ATTR_STATUS) | BIT(MUSIC_INFO_ATTR_FILE_PLAY_MODE)); + + return ret; +} + + +//*----------------------------------------------------------------------------*/ +/**@brief music 设备事件响应接口 + @param 无 + @return 1、当前消息已经处理,comomon不再做处理 0、common统一处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int music_sys_event_handler(struct sys_event *event) +{ + int err = 0; + char *logo = NULL; + char *evt_logo = NULL; + switch (event->type) { + case SYS_KEY_EVENT: + return music_key_event_opr(event); + case SYS_DEVICE_EVENT: + switch ((u32)event->arg) { + case DRIVER_EVENT_FROM_SD0: + case DRIVER_EVENT_FROM_SD1: + case DRIVER_EVENT_FROM_SD2: + evt_logo = (char *)event->u.dev.value; + case DEVICE_EVENT_FROM_OTG: + if ((u32)event->arg == DEVICE_EVENT_FROM_OTG) { + evt_logo = (char *)"udisk0"; + } + int str_len = 0; + logo = music_player_get_phy_dev(&str_len); + log_i("evt_logo =%s, logo = %s len =%d\n", evt_logo, logo, str_len); + if (event->u.dev.event == DEVICE_EVENT_OUT) { + if (logo == NULL) { + break; + } + if (logo && (0 == memcmp(logo, evt_logo, str_len))) { + ///相同的设备才响应 + if (music_player_get_playing_breakpoint(breakpoint, 1) == true) { + breakpoint_vm_write(breakpoint, logo); + } + memset(__this->device_tone_dev, 0, sizeof(__this->device_tone_dev)); + ///停止解码,防止设备掉线后还继续使用 + music_player_stop(1); + ///重新选择活动设备播放 + app_task_put_key_msg(KEY_MUSIC_PLAYER_START, 0);//卸载了设备再执行 + log_i("KEY_MUSIC_PLAYER_START AFTER UMOUNT\n"); + } + } else { +#if (MUSIC_DEV_ONLINE_START_AFTER_MOUNT_EN == 0) + music_task_dev_online_start(); +#endif + } + break; + default://switch((u32)event->arg) + break; + } + break;//SYS_DEVICE_EVENT + default://switch (event->type) + break; + } + + return false; +} + +//*----------------------------------------------------------------------------*/ +/**@brief music 模式切换前参数设置 + @param type:播放方式,暂时支持: + MUSIC_TASK_START_BY_NORMAL:首次播放按照正常断点播放 + MUSIC_TASK_START_BY_SCLUST:首次播放按照簇号播放 + val:播放参数 + @return + @note 首次播放执行参考music_player_play_start接口 +*/ +/*----------------------------------------------------------------------------*/ +void music_task_set_parm(u8 type, int val) +{ + __this->task_parm.type = type; + __this->task_parm.val = val; +} +//*----------------------------------------------------------------------------*/ +/**@brief music 模式首次播放 + @param 无 + @return + @note 切换到音乐模式前可以通过接口music_task_set_parm设置参数, + 进入音乐模式后会按照对应参数播放 +*/ +/*----------------------------------------------------------------------------*/ +static void music_player_play_start(void) +{ + switch (__this->task_parm.type) { + case MUSIC_TASK_START_BY_NORMAL: + log_i("MUSIC_TASK_START_BY_NORMAL\n"); + app_task_put_key_msg(KEY_MUSIC_PLAYER_START, 0); + break; + case MUSIC_TASK_START_BY_SCLUST: + log_i("MUSIC_TASK_START_BY_SCLUST\n"); + app_task_put_key_msg(KEY_MUSIC_PLAYE_BY_DEV_SCLUST, __this->task_parm.val); + break; + default: + log_i("other MUSIC_TASK_START!!!\n"); + break; + } + ///提示音播放失败,直接推送KEY_MUSIC_PLAYER_START启动播放 +} + + +//*----------------------------------------------------------------------------*/ +/**@brief music 模式新设备上线处理 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void music_task_dev_online_start(void) +{ + u8 save = 0; + char *logo = music_player_get_dev_cur(); + if (logo && breakpoint) { + ///新设备上线, 先记录当前设备断点, 然后播放活动设备 + if (music_player_get_playing_breakpoint(breakpoint, 1) == true) { + save = 1; + //这里不要直接记忆断点, 解码停了之后再记忆 + //breakpoint_vm_write(breakpoint, logo); + } + } + ///停止解码,播放新活动设备 + music_player_stop(1); + if (save && breakpoint) { + breakpoint_vm_write(breakpoint, logo); + } + app_task_put_key_msg(KEY_MUSIC_PLAYER_START, 0); + log_i("KEY_MUSIC_PLAYER_START AFTER MOUNT\n"); + //先挂载了设备再执行 +} + +//*----------------------------------------------------------------------------*/ +/**@brief music 模式初始化处理 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void music_task_start() +{ + printf("music task start!!!!!\n"); + music_idle_flag = 0; + ui_update_status(STATUS_MUSIC_MODE); + +#if (TCFG_LRC_LYRICS_ENABLE) + extern int lrc_init(void); + lrc_init(); +#endif + + ///显示初始化 + UI_SHOW_WINDOW(ID_WINDOW_MUSIC); + UI_SHOW_MENU(MENU_WAIT, 0, 0, NULL); + ///时钟初始化 + clock_idle(MUSIC_IDLE_CLOCK); + ///按键使能 + sys_key_event_enable(); + + + ///播放器初始化 + struct __player_parm parm = {0}; + parm.cb = &music_player_callback; + parm.scan_cb = &scan_cb; + music_player_creat(NULL, &parm); + ///获取断点句柄, 后面所有断点读/写都需要用到 + breakpoint = breakpoint_handle_creat(); + ///初始化一些参数 + __this->file_err_counter = 0; + __this->file_play_direct = 0; + __this->scandisk_break = 0; + memset(__this->device_tone_dev, 0, sizeof(__this->device_tone_dev)); +} +//*----------------------------------------------------------------------------*/ +/**@brief music 模式退出处理 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void music_task_close() +{ + UI_HIDE_CURR_WINDOW(); + tone_play_stop_by_path(tone_table[IDEX_TONE_MUSIC]);//停止播放提示音 + char *logo = music_player_get_dev_cur(); + if (music_player_get_playing_breakpoint(breakpoint, 1) == true) { + breakpoint_vm_write(breakpoint, logo); + } + + music_set_dev_sync_mode(logo, 0); + + breakpoint_handle_destroy(&breakpoint); + music_player_destroy(); +#if (TCFG_LRC_LYRICS_ENABLE) + extern void lrc_exit(void); + lrc_exit(); +#endif + memset(__this, 0, sizeof(struct __music)); + music_idle_flag = 1; +} +//*----------------------------------------------------------------------------*/ +/**@brief music 在线检测 切换模式判断使用 + @param 无 + @return 1 设备在线 0 设备不在线 + @note +*/ +/*----------------------------------------------------------------------------*/ +int music_app_check(void) +{ + if (dev_manager_get_total(1)) { + return true; + } + return false; +} + +//*----------------------------------------------------------------------------*/ +/**@brief music 主任务 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void app_music_task() +{ + int res; + int msg[32]; + music_task_start(); + +#if (MUSIC_DEVICE_TONE_EN) + music_player_play_start(); +#else +#if TCFG_DEC2TWS_ENABLE + extern void set_tws_background_connected_flag(u8 flag); + extern u8 get_tws_background_connected_flag(); + if (get_tws_background_connected_flag()) { //不播放提示音 + music_player_play_start(); + set_tws_background_connected_flag(0); + } else +#endif + { + tone_play_with_callback_by_name(tone_table[IDEX_TONE_MUSIC], 1, music_tone_play_end_callback, (void *)IDEX_TONE_MUSIC); + } +#endif + + + while (1) { + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + if (music_sys_event_handler((struct sys_event *)(&msg[1])) == false) { + app_default_event_deal((struct sys_event *)(&msg[1])); + } + break; + default: + break; + } + if (app_task_exitting()) { + music_task_close(); + return; + } + } +} + +static u8 music_idle_query(void) +{ + return music_idle_flag; +} +REGISTER_LP_TARGET(music_lp_target) = { + .name = "music", + .is_idle = music_idle_query, +}; + +#else + +void app_music_task() +{ + +} + +#endif + + + diff --git a/apps/soundbox/task_manager/pc/pc.c b/apps/soundbox/task_manager/pc/pc.c new file mode 100644 index 0000000..8bfc676 --- /dev/null +++ b/apps/soundbox/task_manager/pc/pc.c @@ -0,0 +1,418 @@ + +/************************************************************* + 此文件函数主要是pc模式按键处理和事件处理 + + void app_pc_task() + pc模式主函数 + + static int pc_sys_event_handler(struct sys_event *event) + pc模式系统事件所有处理入口 + + static void pc_task_close() + pc模式退出 + + +**************************************************************/ + +#include "system/app_core.h" +#include "system/includes.h" +#include "server/server_core.h" +#include "media/includes.h" +#include "app_config.h" +#include "app_task.h" +#include "tone_player.h" +#include "asm/charge.h" +#include "asm/usb.h" +#include "app_charge.h" +#include "app_main.h" +#include "app_online_cfg.h" +#include "app_power_manage.h" +#include "ui_manage.h" +#include "app_chargestore.h" +#include "key_event_deal.h" +#include "os/os_api.h" +#include "usb/usb_config.h" +#include "usb/device/usb_stack.h" +#include "usb/device/hid.h" +#include "usb/device/msd.h" +#include "uac_stream.h" +#include "pc/pc.h" +#include "user_cfg.h" +#include "device/sdmmc.h" +#include "pc/usb_msd.h" +#include "ui/ui_api.h" +#include "clock_cfg.h" +#include "dev_multiplex_api.h" +#include "usb/otg.h" +#include "bt_tws.h" +#include "clock_cfg.h" +#include "user_api/app_status_api.h" + + +#if TCFG_APP_PC_EN + +#define LOG_TAG_CONST APP_PC +#define LOG_TAG "[APP_PC]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +struct pc_opr { + u8 volume; + u8 onoff : 1; +}; + +static struct pc_opr pc_hdl = {0}; +#define __this (&pc_hdl) +static u8 pc_idle_flag = 1; + + + +static void pc_start() +{ + if (__this->onoff) { + log_info("PC is start "); + return ; + } + __this->onoff = 1; + log_info("App Start - PC"); + + app_status_handler(APP_STATUS_PC); +#if TCFG_USB_CDC_BACKGROUND_RUN + usb_stop(); +#endif + +#if TCFG_PC_ENABLE + usb_start(); +#endif +} + +static void pc_stop() +{ + if (!__this->onoff) { + log_info("PC is stop "); + return ; + } + __this->onoff = 0; + + log_info("App Stop - PC"); +#if TCFG_PC_ENABLE + usb_stop(); +#endif + +#if TCFG_USB_CDC_BACKGROUND_RUN + usb_cdc_background_run(); +#endif +} + +static void pc_hold() +{ + if (!__this->onoff) { + log_info("PC is hold"); + return ; + } + __this->onoff = 0; + + log_info("App Hold- PC"); +#if TCFG_PC_ENABLE + usb_pause(); +#endif + +#if TCFG_USB_CDC_BACKGROUND_RUN + usb_cdc_background_run(); +#endif +} + + + +//*----------------------------------------------------------------------------*/ +/**@brief pc 按键消息入口 + @param 无 + @return 1、消息已经处理,不需要发送到common 0、消息发送到common处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int pc_key_event_opr(struct sys_event *event) +{ + int ret = true; + int err = 0; + + int key_event = event->u.key.event; + int key_value = event->u.key.value; + + log_debug("key value:%d, event:%d \n", key_value, key_event); + + switch (key_event) { +#if TCFG_USB_SLAVE_HID_ENABLE + case KEY_MUSIC_PP: + log_info("KEY_MUSIC_PP\n"); + hid_key_handler(0, USB_AUDIO_PP); + break; + case KEY_MUSIC_PREV: + log_info("KEY_MUSIC_PREV\n"); + hid_key_handler(0, USB_AUDIO_PREFILE); + break; + case KEY_MUSIC_NEXT: + log_info("KEY_MUSIC_NEXT\n"); + hid_key_handler(0, USB_AUDIO_NEXTFILE); + break; + case KEY_VOL_UP: + log_info("pc KEY_VOL_UP\n"); + hid_key_handler(0, USB_AUDIO_VOLUP); + printf(">>>pc vol+: %d", app_audio_get_volume(APP_AUDIO_CURRENT_STATE)); + break; + case KEY_VOL_DOWN: + log_info("pc KEY_VOL_DOWN\n"); + hid_key_handler(0, USB_AUDIO_VOLDOWN); + printf(">>>pc vol-: %d", app_audio_get_volume(APP_AUDIO_CURRENT_STATE)); + break; +#endif + default: + ret = false; + break; + } + + return ret; +} + +//*----------------------------------------------------------------------------*/ +/**@brief pc 入口 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void pc_task_start(void) +{ +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + pc_dm_multiplex_init(); +#endif + + __this->volume = app_audio_get_volume(APP_AUDIO_STATE_MUSIC); + + pc_start(); +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + usb_otg_resume(0); +#endif +} + +//*----------------------------------------------------------------------------*/ +/**@brief pc 关闭 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void pc_app_uninit(void) +{ + if (pc_app_check() == false) { + pc_stop(); + } else { +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + usb_otg_suspend(0, 0); +#endif + pc_hold(); + } + + /* tone_play_stop(); */ + tone_play_stop_by_path(tone_table[IDEX_TONE_PC]);//停止播放提示音 +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + pc_dm_multiplex_exit(); +#endif + +#if (TCFG_DEV_MANAGER_ENABLE) + dev_manager_list_check_mount(); +#endif/*TCFG_DEV_MANAGER_ENABLE*/ + + UI_HIDE_CURR_WINDOW(); +} + + +#if ((defined TCFG_PC_BACKMODE_ENABLE) && (TCFG_PC_BACKMODE_ENABLE)) +bool pc_backmode_check(struct sys_event *event) +{ + switch (event->type) { + case SYS_DEVICE_EVENT: + if ((u32)event->arg == DEVICE_EVENT_FROM_OTG) { + const char *usb_msg = (const char *)event->u.dev.value; + if (usb_msg[0] == 's') { + if (event->u.dev.event == DEVICE_EVENT_IN) { + pc_task_start(); + } else if (event->u.dev.event == DEVICE_EVENT_OUT) { + pc_app_uninit(); + } + return true; + } + } + break; + } + return false; +} +#endif//TCFG_PC_BACKMODE_ENABLE + +//*----------------------------------------------------------------------------*/ +/**@brief pc模式 退出 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void pc_task_close() +{ + pc_app_uninit(); + app_audio_set_volume(APP_AUDIO_STATE_MUSIC, __this->volume, 1); +#if (TCFG_DEC2TWS_ENABLE) + bt_tws_sync_volume(); +#endif + pc_idle_flag = 1; +} + +//*----------------------------------------------------------------------------*/ +/**@brief pc 模式活跃状态 所有消息入口 + @param 无 + @return 1、当前消息已经处理,不需要发送comomon 0、当前消息不是linein处理的,发送到common统一处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int pc_sys_event_handler(struct sys_event *event) +{ + switch (event->type) { + case SYS_KEY_EVENT: + return pc_key_event_opr(event); + + case SYS_DEVICE_EVENT: +#if TCFG_PC_ENABLE + if (pc_device_event_handler(event) == 2) { + /* pc_stop(); */ + app_task_switch_next(); + } +#endif + return false; + + default: + return false; + } + return false; +} + +//*----------------------------------------------------------------------------*/ +/**@brief pc 在线检测 切换模式判断使用 + @param 无 + @return 1 linein设备在线 0 设备不在线 + @note +*/ +/*----------------------------------------------------------------------------*/ +int pc_app_check(void) +{ +#if ((defined TCFG_PC_BACKMODE_ENABLE) && (TCFG_PC_BACKMODE_ENABLE)) + return false; +#endif//TCFG_PC_BACKMODE_ENABLE + + u32 r = usb_otg_online(0); + log_info("pc_app_check %d", r); + if ((r == SLAVE_MODE) || + (r == SLAVE_MODE_WAIT_CONFIRMATION)) { + return true; + } + return false; +} +//*----------------------------------------------------------------------------*/ +/**@brief PC 模式提示音播放结束处理 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void pc_tone_play_end_callback(void *priv, int flag) +{ + u32 index = (u32)priv; + + if (APP_PC_TASK != app_get_curr_task()) { + log_error("tone callback task out \n"); + return; + } + + switch (index) { + case IDEX_TONE_PC: + ///提示音播放结束, 启动播放器播放 + pc_task_start(); + break; + default: + break; + } +} + +void pc_app_init() +{ + /* 按键消息使能 */ + pc_idle_flag = 0; + sys_key_event_enable(); + + clock_idle(PC_IDLE_CLOCK); + + UI_SHOW_WINDOW(ID_WINDOW_PC); + UI_SHOW_MENU(MENU_PC, 1000, 0, NULL); + ui_update_status(STATUS_PC_MODE); + __this->volume = app_audio_get_volume(APP_AUDIO_STATE_MUSIC);//记录下当前音量 +} +//*----------------------------------------------------------------------------*/ +/**@brief pc 主任务 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void app_pc_task() +{ + int res; + int msg[32]; + + pc_app_init(); + + tone_play_with_callback_by_name(tone_table[IDEX_TONE_PC], 1, pc_tone_play_end_callback, (void *)IDEX_TONE_PC); + + while (1) { + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + if (pc_sys_event_handler((struct sys_event *)(msg + 1)) == false) { + app_default_event_deal((struct sys_event *)(&msg[1])); + } + break; + default: + break; + } + + if (app_task_exitting()) { + pc_task_close(); + return; + } + } +} + +static u8 pc_idle_query(void) +{ + return pc_idle_flag; +} +REGISTER_LP_TARGET(pc_lp_target) = { + .name = "pc", + .is_idle = pc_idle_query, +}; + +#else + +int pc_app_check(void) +{ + return false; +} + +void app_pc_task() +{ + +} +#endif diff --git a/apps/soundbox/task_manager/power_off/power_off.c b/apps/soundbox/task_manager/power_off/power_off.c new file mode 100644 index 0000000..295bf89 --- /dev/null +++ b/apps/soundbox/task_manager/power_off/power_off.c @@ -0,0 +1,295 @@ + +/************************************************************* + 此文件函数主 poweroff 关机流程 + + 如果蓝牙模式有开启,就会等待蓝牙流程关闭完成才会进入软关机 + + power_set_soft_poweroff(); + 软关机 + + +**************************************************************/ + + +#include "common/power_off.h" +#include "bt_tws.h" +#include +#include "app_config.h" +#include "app_task.h" +#include "system/includes.h" +#include "media/includes.h" +#include "app_power_manage.h" +#include "app_chargestore.h" +#include "btstack/avctp_user.h" +#include "app_main.h" +#include "ui/ui_api.h" +#include "ui_manage.h" +#include "tone_player.h" +#include "user_cfg.h" +#include "bt_tws.h" +#include "bt.h" + +#define LOG_TAG_CONST APP_ACTION +#define LOG_TAG "[APP_ACTION]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +#define POWER_OFF_CNT 10 + +static u8 goto_poweroff_cnt = 0; +u8 goto_poweroff_first_flag = 0; +static u8 goto_poweroff_flag = 0; +static u8 power_off_tone_play_flag = 0; + +//*----------------------------------------------------------------------------*/ +/**@brief poweroff 长按等待 关闭蓝牙 + @param 无 + @return 无 + @note + */ +/*----------------------------------------------------------------------------*/ +void power_off_deal(struct sys_event *event, u8 step) +{ + switch (step) { + case 0: + case 1: + if (goto_poweroff_first_flag == 0) { + goto_poweroff_first_flag = 1; + goto_poweroff_cnt = 0; + goto_poweroff_flag = 0; + +#if TCFG_APP_BT_EN + if ((BT_STATUS_CONNECTING == get_bt_connect_status()) || + (BT_STATUS_TAKEING_PHONE == get_bt_connect_status()) || + (BT_STATUS_PLAYING_MUSIC == get_bt_connect_status())) { + /* if (get_call_status() != BT_CALL_HANGUP) { + log_info("call hangup\n"); + user_send_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); + goto_poweroff_first_flag = 0; + goto_poweroff_flag = 0; + break; + } */ + if ((get_call_status() == BT_CALL_INCOMING) || + (get_call_status() == BT_CALL_OUTGOING)) { + log_info("key call reject\n"); + /* user_send_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); */ + goto_poweroff_first_flag = 0; + goto_poweroff_flag = 0; + break; + } else if (get_call_status() == BT_CALL_ACTIVE) { + log_info("key call hangup\n"); + /* user_send_cmd_prepare(USER_CTRL_HFP_CALL_HANGUP, 0, NULL); */ + goto_poweroff_first_flag = 0; + goto_poweroff_flag = 0; + break; + } + } + +#if (TCFG_USER_TWS_ENABLE && CONFIG_TWS_POWEROFF_SAME_TIME == 0) + if ((u32)event->arg == KEY_EVENT_FROM_TWS) { + goto_poweroff_first_flag = 0; + break; + } +#endif + user_send_cmd_prepare(USER_CTRL_ALL_SNIFF_EXIT, 0, NULL); +#endif + goto_poweroff_flag = 1; + break; + } + +#if (TCFG_USER_TWS_ENABLE && CONFIG_TWS_POWEROFF_SAME_TIME == 0) + if ((u32)event->arg == KEY_EVENT_FROM_TWS) { + break; + } +#endif + log_info("poweroff flag:%d cnt:%d\n", goto_poweroff_flag, goto_poweroff_cnt); + + if (goto_poweroff_flag) { + goto_poweroff_cnt++; + +#if CONFIG_TWS_POWEROFF_SAME_TIME + if (goto_poweroff_cnt == POWER_OFF_CNT) { + if (get_tws_sibling_connect_state()) { + if ((u32)event->arg != KEY_EVENT_FROM_TWS) { + tws_api_sync_call_by_uuid('T', SYNC_CMD_POWER_OFF_TOGETHER, TWS_SYNC_TIME_DO); + } + } else { + power_off_tone_play_flag = 1; + sys_enter_soft_poweroff(NULL); + } + } +#else + if (goto_poweroff_cnt >= POWER_OFF_CNT) { + goto_poweroff_cnt = 0; +#if TCFG_APP_BT_EN + sys_enter_soft_poweroff(NULL); +#else + app_var.goto_poweroff_flag = 1; + app_task_switch_to(APP_POWEROFF_TASK); +#endif + } +#endif //CONFIG_TWS_POWEROFF_SAME_TIME + + } + break; + } +} + + +//*----------------------------------------------------------------------------*/ +/**@brief poweroff 流程消息事件处理 + @param 无 + @return 无 + @note 只处理提示音消息 + */ +/*----------------------------------------------------------------------------*/ +static int poweroff_sys_event_handler(struct sys_event *event) +{ + switch (event->type) { + case SYS_KEY_EVENT: + return true; + case SYS_BT_EVENT: + return true; + case SYS_DEVICE_EVENT: + return true; + default: + return true; + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief poweroff 等待关机显示完毕 + @param 无 + @return 无 + @note */ +/*----------------------------------------------------------------------------*/ +static inline void poweroff_wait_ui() +{ +#if TCFG_UI_ENABLE + u8 count = 0; +__retry: + if (UI_GET_WINDOW_ID() != ID_WINDOW_POWER_OFF) { + os_time_dly(10);//增加延时防止没有关显示 + if (count < 3) { + goto __retry; + } + count++; + } + UI_HIDE_CURR_WINDOW(); +#if TCFG_SPI_LCD_ENABLE + extern void ui_backlight_close(void); + ui_backlight_close(); +#endif +#endif +} + +static void poweroff_done(void) +{ + poweroff_wait_ui();//等待关机显示完毕 + while (get_ui_busy_status()) { + } +#if (TCFG_CHARGE_ENABLE && TCFG_CHARGE_POWERON_ENABLE) + extern u8 get_charge_online_flag(void); + if (get_charge_online_flag()) { + cpu_reset(); + } else { + power_set_soft_poweroff(); + } +#else + power_set_soft_poweroff(); +#endif +} + + + +void poweroff_tone_end(void *priv, int flag) +{ + if (app_var.goto_poweroff_flag) { + log_info("audio_play_event_end,enter soft poweroff"); + poweroff_done(); + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief poweroff 流程启动 + @param 无 + @return 无 + @note + */ +/*----------------------------------------------------------------------------*/ +static void poweroff_app_start() +{ + int ret = false; + app_var.goto_poweroff_flag = 1; + if (app_var.goto_poweroff_flag) { + UI_SHOW_WINDOW(ID_WINDOW_POWER_OFF); + syscfg_write(CFG_MUSIC_VOL, &app_var.music_volume, 1); + os_taskq_flush(); + +#if (CONFIG_TWS_POWEROFF_SAME_TIME) + if (power_off_tone_play_flag == 0) { + //不在这里播放提示音 + poweroff_done(); + } else +#endif/*CONFIG_TWS_POWEROFF_SAME_TIME*/ + { + ret = tone_play_with_callback_by_name(tone_table[IDEX_TONE_POWER_OFF], 1, + poweroff_tone_end, (void *)IDEX_TONE_POWER_OFF); + if (ret) { + y_printf("power_off tone play err,enter soft poweroff"); + poweroff_done(); + } + } + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief poweroff 主任务 + @param 无 + @return 无 + @note + */ +/*----------------------------------------------------------------------------*/ +void app_poweroff_task() +{ + int res; + int msg[32]; + poweroff_app_start(); + while (1) { + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + if (poweroff_sys_event_handler((struct sys_event *)(&msg[1])) == false) { + app_default_event_deal((struct sys_event *)(&msg[1])); //由common统一处理 + } + break; + default: + break; + } + + /* if (app_task_exitting()) { + poweroff_task_close(); + return; + } */ + } +} + +extern void sdx_dev_entry_lowpower(const char *sdx_name); +u8 poweroff_entry_cbfun(void) +{ +#if TCFG_SD0_ENABLE + sdx_dev_entry_lowpower("sd0"); +#endif +#if TCFG_SD1_ENABLE + sdx_dev_entry_lowpower("sd1"); +#endif + return 0; +} + + diff --git a/apps/soundbox/task_manager/power_on/power_on.c b/apps/soundbox/task_manager/power_on/power_on.c new file mode 100644 index 0000000..24399cd --- /dev/null +++ b/apps/soundbox/task_manager/power_on/power_on.c @@ -0,0 +1,160 @@ +#include "system/includes.h" +#include "media/includes.h" +#include "app_config.h" +#include "tone_player.h" +#include "asm/charge.h" +#include "app_charge.h" +#include "app_main.h" +#include "ui_manage.h" +#include "vm.h" +#include "app_chargestore.h" +#include "user_cfg.h" +#include "ui/ui_api.h" +#include "app_task.h" +#include "key_event_deal.h" + + +#define LOG_TAG_CONST APP_IDLE +#define LOG_TAG "[APP_IDLE]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +static void lcd_ui_power_on_timeout(void *p) +{ +#if (TCFG_SPI_LCD_ENABLE) + /* sys_key_event_enable(); */ + /* logo_time = timer_get_ms(); */ + /* while (timer_get_ms() - logo_time <= 2 * 1000) { //显示开机logo */ + /* os_time_dly(10); */ + /* } */ + + UI_HIDE_WINDOW(ID_WINDOW_POWER_ON); + UI_SHOW_WINDOW(ID_WINDOW_MAIN); +#if TCFG_APP_BT_EN + app_task_switch_to(APP_BT_TASK); +#else + app_task_switch_to(APP_MUSIC_TASK); +#endif +#endif + +} + +static void lcd_ui_power_on() +{ +#if (TCFG_SPI_LCD_ENABLE) + int logo_time = 0; + UI_SHOW_WINDOW(ID_WINDOW_POWER_ON); + sys_timeout_add(NULL, lcd_ui_power_on_timeout, 1000); +#endif +} + +static int power_on_init(void) +{ + ///有些需要在开机提示完成之后再初始化的东西, 可以在这里初始化 +#if (TCFG_SPI_LCD_ENABLE) + lcd_ui_power_on();//由ui决定切换的模式 + return 0; +#endif + +#if TCFG_APP_BT_EN + app_task_switch_to(APP_BT_TASK); +#else + +#if TCFG_USB_APPLE_DOCK_EN //苹果iap协议使用pc模式 + app_task_switch_to(APP_PC_TASK); +#else + app_task_switch_to(APP_SLEEP_TASK); + /* app_task_switch_to(APP_PC_TASK); */ + /* app_task_switch_to(APP_MUSIC_TASK); */ + /* app_task_switch_to(APP_IDLE_TASK); */ + /* app_task_switch_to(APP_LINEIN_TASK);//如果带检测,设备不在线,则不跳转 */ +#endif + +#endif + + return 0; +} + +static int power_on_unint(void) +{ + + tone_play_stop(); + UI_HIDE_CURR_WINDOW(); + return 0; +} + + + + + + +static int poweron_sys_event_handler(struct sys_event *event) +{ + switch (event->type) { + case SYS_KEY_EVENT: + break; + case SYS_BT_EVENT: + break; + case SYS_DEVICE_EVENT: + break; + default: + return false; + } + return false; +} + + +static void tone_play_end_callback(void *priv, int flag) +{ + int index = (int)priv; + + if (APP_POWERON_TASK != app_get_curr_task()) { + log_error("tone callback task out \n"); + return; + } + + switch (index) { + case IDEX_TONE_POWER_ON: + power_on_init(); + break; + } +} + + +void app_poweron_task() +{ + int msg[32]; + + UI_SHOW_MENU(MENU_POWER_UP, 0, 0, NULL); + + int err = tone_play_with_callback_by_name(tone_table[IDEX_TONE_POWER_ON], 1, tone_play_end_callback, (void *)IDEX_TONE_POWER_ON); + /* if (err) { //提示音没有,播放失败,直接init流程 */ + /* power_on_init(); */ + /* } */ + + + while (1) { + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + if (poweron_sys_event_handler((struct sys_event *)(msg + 1)) == false) { + app_default_event_deal((struct sys_event *)(&msg[1])); //由common统一处理 + } + break; + default: + break; + } + + if (app_task_exitting()) { + power_on_unint(); + return; + } + } + +} + diff --git a/apps/soundbox/task_manager/record/record.c b/apps/soundbox/task_manager/record/record.c new file mode 100644 index 0000000..ea0d1dc --- /dev/null +++ b/apps/soundbox/task_manager/record/record.c @@ -0,0 +1,347 @@ + +/************************************************************* + 此文件函数主要是record模式按键处理和事件处理 + + void app_record_task() + record模式主函数 + + static int record_sys_event_handler(struct sys_event *event) + record模式系统事件所有处理入口 + + static void record_task_close(void) + record模式退出 + +**************************************************************/ +#include "system/app_core.h" +#include "system/includes.h" +#include "server/server_core.h" +#include "media/includes.h" +#include "app_config.h" +#include "app_task.h" +#include "tone_player.h" +#include "asm/charge.h" +#include "app_charge.h" +#include "app_main.h" +#include "app_online_cfg.h" +#include "app_power_manage.h" +#include "gSensor/gSensor_manage.h" +#include "ui_manage.h" +#include "vm.h" +#include "app_chargestore.h" +#include "key_event_deal.h" +#include "asm/pwm_led.h" +#include "user_cfg.h" +#include "record/record.h" +#include "audio_enc.h" +#include "audio_dec.h" +#include "ui/ui_api.h" +#include "fm_emitter/fm_emitter_manage.h" +#include "clock_cfg.h" +#include "dev_manager.h" + +#if TCFG_APP_RECORD_EN + +#define LOG_TAG_CONST APP_RECORD +#define LOG_TAG "[APP_RECORD]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +//*----------------------------------------------------------------------------*/ +/**@brief mic录音启动 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void record_mic_start(void) +{ + struct record_file_fmt fmt = {0}; + /* char logo[] = {"sd0"}; */ //可以指定设备 + char folder[] = {REC_FOLDER_NAME}; //录音文件夹名称 + char filename[] = {"AC69****"}; //录音文件名,不需要加后缀,录音接口会根据编码格式添加后缀 + +#if (TCFG_NOR_REC) + char logo[] = {"rec_nor"}; //外挂flash录音 +#elif (FLASH_INSIDE_REC_ENABLE) + char logo[] = {"rec_sdfile"}; //内置flash录音 +#else + char *logo = dev_manager_get_phy_logo(dev_manager_find_active(0));//普通设备录音,获取最后活动设备 +#endif + + fmt.dev = logo; + fmt.folder = folder; + fmt.filename = filename; +#if (RECORDER_MIX_EN) + //如果开了混合录音这里获取编码类型是为了使得保存的录音文件格式一致,主要指针对695 + fmt.coding_type = recorder_mix_get_coding_type(); +#else + fmt.coding_type = AUDIO_CODING_MP3; //编码格式:AUDIO_CODING_WAV, AUDIO_CODING_MP3 +#endif/*RECORDER_MIX_EN*/ + fmt.channel = 1; //声道数: 1:单声道 2:双声道 + fmt.cut_head_time = 300; //录音文件去头时间,单位ms + fmt.cut_tail_time = 300; //录音文件去尾时间,单位ms + fmt.limit_size = 3000; //录音文件大小最小限制, 单位byte + fmt.gain = 8; +#if (TCFG_MIC_EFFECT_ENABLE) + fmt.sample_rate = MIC_EFFECT_SAMPLERATE; //采样率:8000,16000,32000,44100 + /* fmt.source = ENCODE_SOURCE_MIX; //录音输入源 */ +#else + fmt.sample_rate = 44100; //采样率:8000,16000,32000,44100 +#endif//TCFG_MIC_EFFECT_ENABLE + + fmt.source = ENCODE_SOURCE_MIC; //录音输入源 + fmt.err_callback = NULL; + int ret = recorder_encode_start(&fmt); + if (ret) { + log_e("record_mic_start fail !!, dev = %s\n", logo); + } else { + log_i("record_mic_start succ !!, dev = %s\n", logo); + } +} +//*----------------------------------------------------------------------------*/ +/**@brief mic 录音停止 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void record_mic_stop(void) +{ + recorder_encode_stop(); +} +//*----------------------------------------------------------------------------*/ +/**@brief mic 录音与回放切换 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void record_key_pp() +{ + if (recorder_is_encoding()) { + log_i("mic record stop && replay\n"); + record_mic_stop(); + record_file_play(); + } else { + record_file_close(); + record_mic_start(); + log_i("mic record start\n"); + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief 录音模式提示音结束处理 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void record_tone_play_end_callback(void *priv, int flag) +{ + u32 index = (u32)priv; + if (APP_RECORD_TASK != app_get_curr_task()) { + log_e("tone callback task out \n"); + return; + } + switch (index == IDEX_TONE_RECORD) { + case IDEX_TONE_RECORD: + log_i("IDEX_TONE_RECORD end\n"); + break; + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief record 按键消息入口 + @param 无 + @return 1、消息已经处理,不需要发送到common 0、消息发送到common处理 + @note + */ +/*----------------------------------------------------------------------------*/ +static int record_key_event_opr(struct sys_event *event) +{ + int ret = false; + int err = 0; + +#if TCFG_APP_FM_EMITTER_EN +#if TCFG_UI_ENABLE + if (ui_get_app_menu(GRT_CUR_MENU) == MENU_FM_SET_FRE) { + return ret; + } + +#endif +#endif + int key_event = event->u.key.event; + int key_value = event->u.key.value;// + + log_i("key_event:%d \n", key_event); + switch (key_event) { + case KEY_ENC_START: + log_i(" KEY_ENC_START \n"); + record_key_pp(); + return true; + +#if 0//(TCFG_MIC_EFFECT_ENABLE) + case KEY_REVERB_OPEN: + log_i("record mode ignore mic_effect!!\n"); + ret = true; + break; +#endif + + default: + break; + } + + return ret; +} +//*----------------------------------------------------------------------------*/ +/**@brief record 模式初始化 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void record_task_start(void) +{ + UI_SHOW_WINDOW(ID_WINDOW_REC); + sys_key_event_enable(); + ui_update_status(STATUS_RECORD_MODE); + + clock_idle(REC_IDLE_CLOCK); +} + + +//*----------------------------------------------------------------------------*/ +/**@brief record 退出 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ + +static void record_task_close() +{ + UI_HIDE_CURR_WINDOW(); + //停止播放模式提示音 + tone_play_stop_by_path(tone_table[IDEX_TONE_RECORD]); + ///停止mic录音 + record_mic_stop(); + ///停止回放 + record_file_close(); +} + +//*----------------------------------------------------------------------------*/ +/**@brief record 模式活跃状态 所有消息入口 + @param 无 + @return 1、当前消息已经处理,不需要发送comomon + 0、当前消息不是linein处理的,发送到common统一处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int record_sys_event_handler(struct sys_event *event) +{ + const char *logo = NULL; + int err = 0; + switch (event->type) { + case SYS_KEY_EVENT: + return record_key_event_opr(event); + case SYS_DEVICE_EVENT: + ///所有设备相关的事件不能返回true, 必须给留给公共处理的地方响应设备上下线 + switch ((u32)event->arg) { + case DRIVER_EVENT_FROM_SD0: + case DRIVER_EVENT_FROM_SD1: + case DRIVER_EVENT_FROM_SD2: + logo = (char *)event->u.dev.value; + case DEVICE_EVENT_FROM_OTG: + if ((u32)event->arg == DEVICE_EVENT_FROM_OTG) { + logo = (char *)"udisk0"; + } + + if (event->u.dev.event == DEVICE_EVENT_IN) { + } else if (event->u.dev.event == DEVICE_EVENT_OUT) { + //判断是否是正在录音的设备掉线 + recorder_device_offline_check(logo); + } + break;//DEVICE_EVENT_FROM_USB_HOST + }//switch((u32)event->arg) + break;//SYS_DEVICE_EVENT + default: + break;; + }//switch (event->type) + + return false; +} + +//*----------------------------------------------------------------------------*/ +/**@brief record 在线检测 切换模式判断使用 + @param 无 + @return 1 设备在线 0 设备不在线 + @note +*/ +/*----------------------------------------------------------------------------*/ +int record_app_check(void) +{ +#if 0//(TCFG_MIC_EFFECT_ENABLE) + if (mic_effect_get_status()) { + log_i("mic_effect working!!\n"); + return false; + } +#endif + if (dev_manager_get_total(0)) { + return true; + } + return false; +} + +//*----------------------------------------------------------------------------*/ +/**@brief record 主任务 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void app_record_task() +{ + int res; + int msg[32]; + record_task_start(); + tone_play_with_callback_by_name(tone_table[IDEX_TONE_RECORD], 1, record_tone_play_end_callback, (void *)IDEX_TONE_RECORD); + + while (1) { + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + if (record_sys_event_handler((struct sys_event *)(&msg[1])) == false) { + app_default_event_deal((struct sys_event *)(&msg[1])); //由common统一处理 + } + break; + default: + break; + } + + if (app_task_exitting()) { + record_task_close(); + return; + } + } +} + +#else + +int record_app_check(void) +{ + return false; +} + +void app_record_task() +{ + +} + +#endif + diff --git a/apps/soundbox/task_manager/rtc/alarm_api.c b/apps/soundbox/task_manager/rtc/alarm_api.c new file mode 100644 index 0000000..073ca0a --- /dev/null +++ b/apps/soundbox/task_manager/rtc/alarm_api.c @@ -0,0 +1,921 @@ +#include "system/includes.h" +#include "rtc/alarm.h" +#include "common/app_common.h" +#include "system/timer.h" +#include "app_main.h" +#include "tone_player.h" +#include "app_task.h" + +#if TCFG_APP_RTC_EN +#ifdef RTC_ALM_EN +/* #define ALARM_DEBUG_EN */ +#ifdef ALARM_DEBUG_EN +#define alarm_printf printf +#define alarm_putchar putchar +#define alarm_printf_buf put_buf +#else +#define alarm_printf(...) +#define alarm_putchar(...) +#define alarm_printf_buf(...) +#endif + +#define PRINT_FUN() alarm_printf("func : %s\n", __FUNCTION__) +#define PRINT_FUN_RETURN_INFO() alarm_printf("func : %s, line : %d.\n", __FUNCTION__, __LINE__) + +/************************************************************* + 此文件函数主要是rtc闹钟的实现代码 + 用户可以不主要关心实现,专心留意api调用 + 常用的api 有: + +u8 alarm_add(PT_ALARM p, u8 index); +增加闹钟 + +void alarm_delete(u8 index); +删除闹钟 + +void rtc_update_time_api(struct sys_time *time) +更新时间api(更新了时间必须调用该接口) + +u8 alarm_active_flag_get(void); +闹钟到达的标志 + +u8 alarm_get_info(PT_ALARM p, u8 index) +获取闹钟信息 + +u8 alarm_get_active_index(void); +获取当前激活使能的闹钟(可以理解为下一个会响的闹钟) + + +u8 alarm_get_total(void) +获取当前已经设备的闹钟数(包括关闭的闹钟) + + +void rtc_calculate_next_few_day(struct sys_time *data_time,u8 days) +获取今天星期几 + + +void alarm_name_set(u8 *p, u8 index, u8 len) +设置闹钟名字 + + +u8 alarm_name_get(u8 *p, u8 index) +获取闹钟名字 +**************************************************************/ + + + +static volatile u8 g_alarm_active_flag = 0; +static volatile u8 alarm_cur_active = 0;//当前在响的闹钟 + + + +typedef struct __alarm_map__ { + u32 mask: 16; +u32 map : + ((M_MAX_ALARM_NUMS + 7) / 8 * 8); //存储了闹钟数目信息(闹钟数) +u32 map_sw : + ((M_MAX_ALARM_NUMS + 7) / 8 * 8); //存储闹钟的使能开关(闹钟开关) +u32 active_map : + ((M_MAX_ALARM_NUMS + 7) / 8 * 8); //存储最后激活闹钟 +} T_ALARM_MAP, *PT_ALARM_MAP; + + +/* volatile u8 g_alarm_ring_max_cnt = 100; */ + +static T_ALARM alarm_tab[M_MAX_ALARM_NUMS] = {0}; +static u8 alarm_name[M_MAX_ALARM_NAME_LEN] = {0}; + +#define RTC_MASK (0x55aa+M_MAX_ALARM_NAME_LEN) + +static void *dev_handle; + +T_ALARM_MAP alarm_map = {0}; + + + +/*----------------------------------------------------------------------------*/ +/* debug 函数代码 */ +/*----------------------------------------------------------------------------*/ + + +void alarm_vm_puts_info(PT_ALARM p) +{ + alarm_printf("index : %d\n", p->index); + alarm_printf("mode: %d\n", p->mode); + alarm_printf("sw: %d\n", p->sw); + /* alarm_puts_time(&(p->time)); */ +} + +void alarm_puts_time(struct sys_time *pTime) +{ + u8 week = 0; + +#if 1 + alarm_printf("alarm_time : %d-%d-%d,%d:%d:%d\n", pTime->year, pTime->month, pTime->day, pTime->hour, pTime->min, pTime->sec); + week = rtc_calculate_week_val(pTime); +#endif + alarm_printf("alarm week : %d\n", week); +} + +/*----------------------------------------------------------------------------*/ +/* rtc 硬化相关代码*/ +/*----------------------------------------------------------------------------*/ +void *is_sys_time_online() +{ + return dev_handle; +} + + +static void get_sys_time(struct sys_time *time)//获取时间 +{ + if (!dev_handle) { + return ; + } + dev_ioctl(dev_handle, IOCTL_GET_SYS_TIME, (u32)time); +} + +static void set_sys_time(struct sys_time *time)//设置时间 +{ + if (!dev_handle) { + return ; + } + dev_ioctl(dev_handle, IOCTL_SET_SYS_TIME, (u32)time); +} + +void alarm_hw_set_sw(u8 sw)//闹钟开关 +{ + /* printf("alarm sw : %d\n", sw); */ + if (!dev_handle) { + return ; + } + dev_ioctl(dev_handle, IOCTL_SET_ALARM_ENABLE, !!sw); +} + +void alarm_hw_write_time(struct sys_time *time, u8 sw)//写闹钟寄存器 +{ + if (!dev_handle) { + return ; + } + alarm_printf("alarm_time : %d-%d-%d,%d:%d:%d\n", time->year, time->month, time->day, time->hour, time->min, time->sec); + + alarm_hw_set_sw(0); + dev_ioctl(dev_handle, IOCTL_SET_ALARM, (u32)time); + alarm_hw_set_sw(sw); +} + + + + +/*----------------------------------------------------------------------------*/ +/* vm读写操作部分代码 */ +/*----------------------------------------------------------------------------*/ + +static void alarm_vm_reset() +{ + int i = 0; + int ret = 0; + T_ALARM_MAP map_temp = {0}; + memset(&map_temp, 0x0, sizeof(T_ALARM_MAP)); + map_temp.mask = RTC_MASK; + ret = syscfg_write(VM_ALARM_MASK, (u8 *)&map_temp, sizeof(T_ALARM_MAP)); + if (ret != sizeof(T_ALARM_MAP)) { + PRINT_FUN_RETURN_INFO(); + return; + } + + for (i = 0; i < M_MAX_ALARM_NUMS; i++) { + T_ALARM_VM tmp = {0}; + tmp.head = RTC_MASK; + tmp.alarm.index = i; + ret = syscfg_write(VM_ALARM_0 + i, &tmp, sizeof(T_ALARM_VM)); + if (ret != sizeof(T_ALARM_VM)) { + alarm_printf("The %d alarm write vm err!\n", index); + return; + } + } + +} + +//写闹钟map表 +static void alarm_vm_write_mask(PT_ALARM_MAP map) +{ + int ret = 0; + PRINT_FUN(); + T_ALARM_MAP map_temp = {0}; + memcpy(&map_temp, map, sizeof(T_ALARM_MAP)); + if (map_temp.mask != RTC_MASK) { + memset(&map_temp, 0x0, sizeof(T_ALARM_MAP)); + map_temp.mask = RTC_MASK; + } + + ret = syscfg_write(VM_ALARM_MASK, (u8 *)&map_temp, sizeof(T_ALARM_MAP)); + if (ret != sizeof(T_ALARM_MAP)) { + PRINT_FUN_RETURN_INFO(); + return; + } +} + +//获取闹钟所有信息 +static void alarm_vm_read_info(PT_ALARM_MAP map) +{ + PRINT_FUN(); + T_ALARM_VM tmp; + int ret = 0; + u8 i; + + ret = syscfg_read(VM_ALARM_MASK, (u8 *)map, sizeof(T_ALARM_MAP)); + if (ret != sizeof(T_ALARM_MAP) || map->mask != RTC_MASK) { + PRINT_FUN_RETURN_INFO(); + memset(map, 0, sizeof(T_ALARM_MAP)); + map->mask = RTC_MASK; + alarm_vm_reset(); + return; + } + + for (i = 0; i < M_MAX_ALARM_NUMS; i++) { + if ((map->map) & BIT(i)) { + ret = syscfg_read(VM_ALARM_0 + i, &tmp, sizeof(T_ALARM_VM)); + if (ret != sizeof(T_ALARM_VM) || tmp.head != RTC_MASK) { + alarm_printf("can't find the %d alarm from vm.\n", i); + memset(&(alarm_tab[i]), 0x00, sizeof(T_ALARM)); + continue; + } + + printf("vm info : index=%d, sw=%d, mode=%d, h=%d, m=%d, name_len=%d\n", tmp.alarm.index, tmp.alarm.sw, tmp.alarm.mode, \ + tmp.alarm.time.hour, tmp.alarm.time.min, tmp.alarm.name_len); + memcpy(&alarm_tab[i], &(tmp.alarm), sizeof(T_ALARM)); + if (alarm_tab[i].sw) { + map->map_sw |= BIT(i); + } else { + map->map_sw &= ~(BIT(i)); + } + } + } +} + + +//更新闹钟信息 +static void alarm_vm_write_info_by_index(PT_ALARM_MAP map, u8 index) +{ + PRINT_FUN(); + s32 ret = 0; + T_ALARM_VM tmp; + tmp.head = RTC_MASK; + memcpy(&(tmp.alarm), &alarm_tab[index], sizeof(T_ALARM)); + tmp.alarm.index = index; + ret = syscfg_write(VM_ALARM_0 + index, &tmp, sizeof(T_ALARM_VM)); + if (ret != sizeof(T_ALARM_VM)) { + alarm_printf("The %d alarm write vm err!\n", index); + return; + } + + alarm_printf("vm info : index=%d, sw=%d, mode=%d, h=%d, m=%d, name_len=%d\n", tmp.alarm.index, tmp.alarm.sw, tmp.alarm.mode, \ + tmp.alarm.time.hour, tmp.alarm.time.min, tmp.alarm.name_len); + alarm_vm_write_mask(map); + return; +} + + +/*----------------------------------------------------------------------------*/ +/*闹钟名字部分代码 */ +/*----------------------------------------------------------------------------*/ +static void alarm_vm_write_name(u8 *p, u8 index) +{ + PRINT_FUN(); + + s32 ret = 0; + + ret = syscfg_write(VM_ALARM_NAME_0 + index, p, sizeof(alarm_name)); + if (ret < 0) { + PRINT_FUN_RETURN_INFO(); + return; + } + + return; +} + +static void alarm_vm_read_name(u8 *p, u8 index) +{ + PRINT_FUN(); + + s32 ret = 0; + + ret = syscfg_read(VM_ALARM_NAME_0 + index, p, sizeof(alarm_name)); + if (ret < 0) { + PRINT_FUN_RETURN_INFO(); + return; + } + + return; +} + +void alarm_name_clear(void) +{ + PRINT_FUN(); + memset(alarm_name, 0x00, sizeof(alarm_name)); + return; +} + + +void alarm_name_set(u8 *p, u8 index, u8 len) +{ + PRINT_FUN(); + + if (index > M_MAX_ALARM_INDEX) { + PRINT_FUN_RETURN_INFO(); + alarm_printf("alarm is full!\n"); + return; + } + + + if ((len == 0) || (len > sizeof(alarm_name))) { + PRINT_FUN_RETURN_INFO(); + return; + } + + alarm_name_clear(); + + alarm_printf("alarm name len : %d\n", len); + alarm_printf_buf(p, len); + + memcpy(alarm_name, p, len); + alarm_vm_write_name(alarm_name, index); + + return; +} + +u8 alarm_name_get(u8 *p, u8 index) +{ + PRINT_FUN(); + + u8 name_len = 0; + + if (index > M_MAX_ALARM_INDEX) { + PRINT_FUN_RETURN_INFO(); + return 0; + } + + alarm_vm_read_name(alarm_name, index); + + name_len = alarm_tab[index].name_len; + memcpy(p, alarm_name, name_len); + + alarm_printf("alarm name len : %d\n", name_len); + alarm_printf_buf(alarm_name, name_len); + + return name_len; +} + + + +/*----------------------------------------------------------------------------*/ +/*工具函数部分代码 */ +/*----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------*/ +/**@brief 月份换算为月天数 + @param month,year + @return 月份天数 + @note +*/ +/*----------------------------------------------------------------------------*/ +u16 month_for_day(u8 month, u16 year) +{ + extern u16 month_to_day(u16 year, u8 month); + return month_to_day(year, month); +} + + + + +/*----------------------------------------------------------------------------*/ +/**@brief 计算未来几天的日期 days要小于29,防止跨两个月 + @param data_time--计算日期 + @return none + @note +*/ +/*----------------------------------------------------------------------------*/ +void rtc_calculate_next_few_day(struct sys_time *data_time, u8 days) +{ + if (!days || days >= 29) { + return; + } + u16 tmp16 = month_for_day(data_time->month, data_time->year); + data_time->day += days; + if (data_time->day > tmp16) { + data_time->month++; + data_time->day -= tmp16; + if (data_time->month > 12) { + data_time->month = 1; + data_time->year++; + } + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 日期转换为星期 + @param data_time--日期 + @return 星期 + @note +*/ +/*----------------------------------------------------------------------------*/ +//蔡勒(Zeller)公式:w=y+[y/4]+[c/4]-2c+[26x(m+1)/10]+d-1 +u8 rtc_calculate_week_val(struct sys_time *data_time) +{ + struct sys_time t_time; + u32 century, val, year; + + memcpy(&t_time, data_time, sizeof(struct sys_time)); + if (t_time.month < 3) { + t_time.month = t_time.month + 12; + t_time.year--; + } + year = t_time.year % 100; + century = t_time.year / 100; + val = year + (year / 4) + (century / 4) + (26 * (t_time.month + 1) / 10) + t_time.day; + val = val - century * 2 - 1; + + return (u8)(val % 7); +} + + +static int __alarm_cmp_time_num(u32 num1, u32 num2) +{ + int ret = -2; + + if (num1 > num2) { + ret = 1; + } else if (num1 == num2) { + ret = 0; + } else if (num1 < num2) { + ret = -1; + } + + return ret; +} + +/* + * 函数功能 :比较两个闹钟的时间 + * 函数形参 :time1 - 闹钟1;time2 - 闹钟2 + * 返回值 :0-两闹钟相等;1-闹钟1时间比对比闹钟2要晚;-1-闹钟1比对比闹钟2早 -2-比较出错 + * 备注 :无 + * + * */ +static int alarm_cmp_time_member(struct sys_time *time1, struct sys_time *time2, TIME_MEMBER_ENUM type) +{ + switch (type) { + case TIME_MEMBER_YEAR: + return __alarm_cmp_time_num(time1->year, time2->year); + case TIME_MEMBER_MONTH: + return __alarm_cmp_time_num(time1->month, time2->month); + case TIME_MEMBER_DAY: + return __alarm_cmp_time_num(time1->day, time2->day); + case TIME_MEMBER_HOUR: + return __alarm_cmp_time_num(time1->hour, time2->hour); + case TIME_MEMBER_MIN: + return __alarm_cmp_time_num(time1->min, time2->min); + case TIME_MEMBER_SEC: + return __alarm_cmp_time_num(time1->sec, time2->sec); + + default: + return -2; + } + + return -2; +} + +/* + * 函数功能 :比较两个闹钟的时间 + * 函数形参 :time1 - 闹钟1;time2 - 闹钟2 + * 返回值 :0-两闹钟相等;1-闹钟1时间比对比闹钟2要晚;-1-闹钟1比对比闹钟2早 -2-比较出错 + * 备注 :无 + * + * */ +static int alarm_cmp_time(struct sys_time *time1, struct sys_time *time2) +{ + u8 i; + int ret = 0; + + for (i = 0; i < TIME_MEMBER_MAX; i++) { + ret = alarm_cmp_time_member(time1, time2, i); + if (ret != 0) { + break; + } + } + + return ret; +} + + + + +/*----------------------------------------------------------------------------*/ +/*核心部分代码 */ +/*----------------------------------------------------------------------------*/ + + + +/* +** 函数功能 :根据闹钟的模式计算出实际时间 +** 函数形参 :pTime-闹钟时间结构体;week-当下星期; mode-闹钟模式 +** 返回值 :void +** 备注 :无 +*/ + +static void __alarm_calc_time_by_week_mode(struct sys_time *pTime, u8 mode) +{ + PRINT_FUN(); + u8 i = 0; + u8 alarm_week = 0; + u8 tmp_mode = 0; + alarm_week = rtc_calculate_week_val(pTime);//alarm_week 可以理解为最近可以设置的闹钟(忽略week) + if (alarm_week == 0) { + alarm_week = 7; //星期天写成7,方便对比计算 + } + + //查找当前可以设置闹钟日期最近的日期 + for (i = 1; i < 8; i++) { + if (mode & BIT(i)) { + if (i >= alarm_week) { + tmp_mode = i; + break; + } + } + } + + if (i >= 8) {//翻越了星期的 + for (i = 1; i < 8; i++) { + if (mode & BIT(i)) { + tmp_mode = i; + break; + } + } + } + + if ((tmp_mode >= 1) && (tmp_mode < 8)) { + if (tmp_mode > alarm_week) { + alarm_printf("***a***\n"); + //没有翻越星期 + rtc_calculate_next_few_day(pTime, tmp_mode - alarm_week); + } else if (tmp_mode < alarm_week) { + //翻越了星期 + alarm_printf("***b***\n"); + rtc_calculate_next_few_day(pTime, 7 - (alarm_week - tmp_mode)); + } + } + return; +} + + + + + + +/* +** 函数功能 :根据闹钟的时、分计算出它具体的时间(年、月、日、时、分、秒) +** 函数形参 :带有时、分和闹钟模式的时间结构体 +** 返回值 :void +** 备注 :无 +*/ +static void alarm_calc_real_time_by_index(struct sys_time *cTime, u8 index) +{ + struct sys_time tmp = {0}; + PT_ALARM pAlarm_tab; + + if (index > M_MAX_ALARM_INDEX) { + PRINT_FUN_RETURN_INFO(); + return; + } + + pAlarm_tab = &(alarm_tab[index]); + struct sys_time *pTime = &(pAlarm_tab->time); + + if (pAlarm_tab->mode > M_MAX_ALARM_MODE) { + PRINT_FUN_RETURN_INFO(); + return; + } + u32 c_tmp = ((cTime->hour & 0x1f) << 12) | ((cTime->min & 0x3f) << 6) | (cTime->sec & 0x3f); + u32 p_tmp = ((pTime->hour & 0x1f) << 12) | ((pTime->min & 0x3f) << 6) | (pTime->sec & 0x3f); + + if (p_tmp > c_tmp) { //时间未到 + + PRINT_FUN_RETURN_INFO(); + pTime->year = cTime->year; + pTime->month = cTime->month; + pTime->day = cTime->day; + pTime->sec = 0; + } else { + PRINT_FUN_RETURN_INFO(); + memcpy(&tmp, cTime, sizeof(struct sys_time)); + rtc_calculate_next_few_day(&tmp, 1); + pTime->year = tmp.year; + pTime->month = tmp.month; + pTime->day = tmp.day; + pTime->sec = 0; + + } + + if ((pAlarm_tab->mode != E_ALARM_MODE_ONCE) && (pAlarm_tab->mode != E_ALARM_MODE_EVERY_DAY)) { + __alarm_calc_time_by_week_mode(pTime, pAlarm_tab->mode); + } + alarm_puts_time(pTime); +} + +static void __alarm_get_the_earliest(void) +{ + PRINT_FUN(); + int ret = 0; + u8 index = 0; + u8 i = 0; + + struct sys_time *pTmp = NULL; + alarm_map.active_map = 0 ; + for (i = 0; i < M_MAX_ALARM_NUMS; i++) { + if (alarm_map.map_sw & BIT(i)) { + alarm_map.active_map |= BIT(i) ; + pTmp = &(alarm_tab[i].time); + index = i; + break; + } + } + + + if (i >= M_MAX_ALARM_NUMS) { + alarm_printf("***no alarm***\n"); + alarm_hw_set_sw(0); + return; + } + for (i = index + 1; i < M_MAX_ALARM_NUMS; i++) { + if (alarm_map.map_sw & BIT(i)) { + ret = alarm_cmp_time(pTmp, &(alarm_tab[i].time)); + if (0 == ret) { + alarm_map.active_map |= BIT(i); + alarm_printf("***A***\n"); + } else if (1 == ret) { + alarm_printf("***B***\n"); + pTmp = &(alarm_tab[i].time); + index = i; + alarm_map.active_map = 0; + alarm_map.active_map |= BIT(i); + } + } + } + /* alarm_puts_time(pTmp); */ + /* printf("find the %dth alarm, the save alarm : %x\n", index, alarm_map.active_map); */ + alarm_hw_write_time(pTmp, alarm_tab[index].sw); + return; +} + + +static void __alarm_update_all_time(struct sys_time *cTIME) +{ + PRINT_FUN(); + u8 i = 0; + for (i = 0; i < M_MAX_ALARM_NUMS; i++) { + if (alarm_map.map_sw & BIT(i)) { + alarm_calc_real_time_by_index(cTIME, i); + } + } + + return; +} + + +static void alarm_update() +{ + PRINT_FUN(); + struct sys_time current_time = {0}; + + if (!is_sys_time_online()) { + return ; + } + + get_sys_time(¤t_time); + local_irq_disable(); + __alarm_update_all_time(¤t_time); + local_irq_enable(); + __alarm_get_the_earliest(); +} + + +u8 alarm_get_active_index(void) +{ + return alarm_cur_active; +} + +u8 alarm_get_info(PT_ALARM p, u8 index) +{ + u8 ret = E_SUCCESS; + + local_irq_disable(); + if (alarm_map.map & BIT(index)) { + p->index = alarm_tab[index].index; + p->sw = alarm_tab[index].sw; + p->mode = alarm_tab[index].mode; + p->time.hour = alarm_tab[index].time.hour; + p->time.min = alarm_tab[index].time.min; + p->name_len = alarm_tab[index].name_len; + } else { + memset(p, 0x0, sizeof(T_ALARM)); + ret = E_FAILURE; + } + local_irq_enable(); + return ret; +} + +u8 alarm_get_total(void) +{ + PRINT_FUN(); + + u8 total = 0; + u8 i = 0; + + local_irq_disable(); + for (i = 0; i < M_MAX_ALARM_NUMS; i++) { + if (alarm_map.map & BIT(i)) { + total++; + } + } + local_irq_enable(); + alarm_printf("total %d alarm\n", total); + + return total; +} + + + + + + +void rtc_update_time_api(struct sys_time *time) +{ + if (!is_sys_time_online()) { + return ; + } + set_sys_time(time); + local_irq_disable(); + __alarm_update_all_time(time); + local_irq_enable(); + __alarm_get_the_earliest(); + alarm_vm_write_mask(&alarm_map); +} + + +void alarm_update_info_after_isr(void) +{ + PRINT_FUN(); + struct sys_time time = {0}; + + if (!is_sys_time_online()) { + return ; + } + + get_sys_time(&time); + u8 i = 0; + printf("alarm_map.active_map =%x\n", alarm_map.active_map); + local_irq_disable(); + alarm_cur_active = alarm_map.active_map; + for (i = 0; i < M_MAX_ALARM_NUMS; i++) { + if (alarm_map.active_map & BIT(i)) { + if (alarm_tab[i].mode != 0) { + //闹钟不只响一次 + //计算一次闹钟的时间 + alarm_calc_real_time_by_index(&time, i); + } else { + //闹钟只响一次 + alarm_map.map_sw &= ~BIT(i); + alarm_tab[i].sw = 0; + alarm_vm_write_info_by_index(&alarm_map, i); + } + } + } + local_irq_enable(); + __alarm_get_the_earliest(); + alarm_vm_write_mask(&alarm_map); +} + + +u8 alarm_add(PT_ALARM p, u8 index) +{ + + struct sys_time current_time = {0}; + PRINT_FUN(); + u8 ret = E_SUCCESS; + + if (!is_sys_time_online()) { + return E_FAILURE; + } + + if (index > M_MAX_ALARM_INDEX) { + PRINT_FUN_RETURN_INFO(); + alarm_printf("alarm is full!\n"); + return E_FAILURE; + } + + if (p->mode > M_MAX_ALARM_MODE) { + PRINT_FUN_RETURN_INFO(); + alarm_printf("alarm's mode is error"); + return E_FAILURE; + } + + + local_irq_disable(); + alarm_map.map |= BIT(index); + if (0 == p->sw) { + alarm_printf("close the %dth alarm!\n", p->index); + alarm_map.map_sw &= ~BIT(p->index); + } else if (1 == p->sw) { + alarm_printf("set the %dth alarm!\n", p->index); + alarm_map.map_sw |= BIT(p->index); + } + alarm_tab[index].index = p->index; + alarm_tab[index].sw = p->sw; + alarm_tab[index].mode = p->mode; + alarm_tab[index].time.hour = p->time.hour; + alarm_tab[index].time.min = p->time.min; + alarm_tab[index].name_len = p->name_len; + + get_sys_time(¤t_time); + alarm_calc_real_time_by_index(¤t_time, index);//根据当前时间和闹钟模式计算出最新闹钟时间 + local_irq_enable(); + __alarm_get_the_earliest(); + alarm_vm_write_info_by_index(&alarm_map, index); + return ret; +} + +void alarm_delete(u8 index) +{ + PRINT_FUN(); + if (index > M_MAX_ALARM_INDEX) { + PRINT_FUN_RETURN_INFO(); + alarm_printf("alarm is full!\n"); + return; + } + alarm_printf("delete the %dth alarm!\n", index); + + local_irq_disable(); + alarm_map.map &= ~BIT(index); + alarm_map.map_sw &= ~BIT(index); + alarm_tab[index].sw = 0; + local_irq_enable(); + __alarm_get_the_earliest(); + alarm_vm_write_info_by_index(&alarm_map, index); + return; +} + + +void alarm_active_flag_set(u8 flag) +{ + g_alarm_active_flag = flag; + + return; +} + +u8 alarm_active_flag_get(void) +{ + return g_alarm_active_flag; +} + +static void alarm_check(void *priv) +{ + extern APP_VAR app_var; + extern u32 timer_get_ms(void); + if ((timer_get_ms() - app_var.start_time) > 3000) { + struct sys_event e; + e.type = SYS_DEVICE_EVENT; + e.arg = (void *)DEVICE_EVENT_FROM_ALM; + e.u.dev.event = DEVICE_EVENT_IN; + e.u.dev.value = 0; + sys_event_notify(&e); + } else { + sys_timeout_add(NULL, alarm_check, 100); + } +} + +void alarm_init() +{ + u8 i = 0; + if (dev_handle) { + return ; + } + dev_handle = dev_open("rtc", NULL); + if (!dev_handle) { + ASSERT(0, "%s %d \n", __func__, __LINE__); + } + + alarm_vm_read_info(&alarm_map); + + if (!alarm_active_flag_get()) { //判断是否闹钟在响 + alarm_update();//开机重新写入闹钟寄存器信息 + } else { + sys_timeout_add(NULL, alarm_check, 100); + } + + + /* register_sys_event_handler(SYS_ALL_EVENT, 1, NULL, alarm_event_handler); */ +} + +#endif //end of RTC_ALM_EN +#endif + + diff --git a/apps/soundbox/task_manager/rtc/alarm_user.c b/apps/soundbox/task_manager/rtc/alarm_user.c new file mode 100644 index 0000000..a21274f --- /dev/null +++ b/apps/soundbox/task_manager/rtc/alarm_user.c @@ -0,0 +1,166 @@ +#include "system/includes.h" +#include "rtc/alarm.h" +#include "common/app_common.h" +#include "system/timer.h" +#include "app_main.h" +#include "tone_player.h" +#include "app_task.h" + + +#if TCFG_APP_RTC_EN + +#define ALARM_RING_MAX 50 +volatile u16 g_alarm_ring_cnt = 0; +static u16 g_ring_playing_timer = 0; + +/************************************************************* + 此文件函数主要是用户主要修改的文件 + +void set_rtc_default_time(struct sys_time *t) +设置默认时间的函数 + +void alm_wakeup_isr(void) +闹钟到达的函数 + +void alarm_event_handler(struct sys_event *event, void *priv) +监听按键消息接口,应用于随意按键停止闹钟 + + +int alarm_sys_event_handler(struct sys_event *event) +闹钟到达响应接口 + +void alarm_ring_start() +闹钟铃声播放接口 + + +void alarm_stop(void) +闹钟铃声停止播放接口 +**************************************************************/ + + + + +void set_rtc_default_time(struct sys_time *t) +{ + t->year = 2019; + t->month = 5; + t->day = 5; + t->hour = 18; + t->min = 18; + t->sec = 18; +} + + +__attribute__((weak)) +u8 rtc_app_alarm_ring_play(u8 alarm_state) +{ + return 0; +} + + +void alm_wakeup_isr(void) +{ + if (!is_sys_time_online()) { + alarm_active_flag_set(true); + } else { + alarm_active_flag_set(true); + struct sys_event e; + e.type = SYS_DEVICE_EVENT; + e.arg = (void *)DEVICE_EVENT_FROM_ALM; + e.u.dev.event = DEVICE_EVENT_IN; + e.u.dev.value = 0; + sys_event_notify(&e); + } +} + +void alarm_ring_cnt_clear(void) +{ + g_alarm_ring_cnt = 0; +} + +void alarm_stop(void) +{ + printf("ALARM_STOP !!!\n"); + alarm_active_flag_set(0); + alarm_ring_cnt_clear(); + rtc_app_alarm_ring_play(0); +} + +void alarm_play_timer_del(void) +{ + if (g_ring_playing_timer) { + sys_timeout_del(g_ring_playing_timer); + g_ring_playing_timer = 0; + } +} + +static void __alarm_ring_play(void *p) +{ + if (g_alarm_ring_cnt > 0) { + u8 app = app_get_curr_task(); + if (app != APP_RTC_TASK) { + alarm_stop(); + printf("...not in rtc task\n"); + return; + } + + if (!tone_get_status()) { + if (!rtc_app_alarm_ring_play(1)) { + tone_play_by_path(tone_table[IDEX_TONE_NORMAL], 0); + g_alarm_ring_cnt--; + } + } + g_ring_playing_timer = sys_timeout_add(NULL, __alarm_ring_play, 500); + } else { + alarm_stop(); + } +} + +void alarm_ring_start() +{ + if (g_alarm_ring_cnt == 0) { + g_alarm_ring_cnt = ALARM_RING_MAX; + sys_timeout_add(NULL, __alarm_ring_play, 500); + } +} + +void alarm_event_handler(struct sys_event *event, void *priv) +{ + switch (event->type) { + case SYS_KEY_EVENT: + if (alarm_active_flag_get()) { + alarm_stop(); + event->consumed = 1;//接管按键消息,app应用不会收到消息 + } + break; + default: + break; + } +} + +SYS_EVENT_HANDLER(SYS_KEY_EVENT, alarm_event_handler, 2); + + + +int alarm_sys_event_handler(struct sys_event *event) +{ + struct application *cur; + if ((u32)event->arg == DEVICE_EVENT_FROM_ALM) { + if (event->u.dev.event == DEVICE_EVENT_IN) { + printf("alarm_sys_event_handler\n"); + alarm_update_info_after_isr(); + + u8 app = app_get_curr_task(); + if (app == APP_RTC_TASK) { + alarm_ring_start(); + return false; + } + return true; + } + } + + return false; +} + +#endif + diff --git a/apps/soundbox/task_manager/rtc/rtc.c b/apps/soundbox/task_manager/rtc/rtc.c new file mode 100644 index 0000000..c44882d --- /dev/null +++ b/apps/soundbox/task_manager/rtc/rtc.c @@ -0,0 +1,707 @@ +#include "app_config.h" +#include "key_event_deal.h" +#include "system/includes.h" +#include "tone_player.h" +#include "app_task.h" +#include "tone_player.h" +#include "media/includes.h" +#include "system/sys_time.h" +#include "ui/ui_api.h" +#include "rtc/alarm.h" +#include "rtc/rtc_ui.h" +#include "clock_cfg.h" +#include "ui/ui_style.h" +#include "ui_manage.h" + +/************************************************************* + 此文件函数主要是rtc模式按键处理和事件处理 + +**************************************************************/ + + +#if TCFG_APP_RTC_EN + + + +#define LOG_TAG_CONST APP_RTC +#define LOG_TAG "[APP_RTC]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + + +#define RTC_SET_MODE 0x55 +#define ALM_SET_MODE 0xAA + +#define RTC_POS_DEFAULT RTC_POS_YEAR +#define RTC_ALM_POS_DEFAULT ALM_POS_HOUR +#define RTC_MODE_DEFAULT RTC_SET_MODE + +#define MAX_YEAR 2099 +#define MIN_YEAR 2000 + +enum { + RTC_POS_NULL = 0, + RTC_POS_YEAR, + RTC_POS_MONTH, + RTC_POS_DAY, + RTC_POS_HOUR, + RTC_POS_MIN, + /* RTC_POS_SEC, */ + RTC_POS_MAX, + ALM_POS_HOUR, + ALM_POS_MIN, + ALM_POS_ENABLE, + ALM_POS_MAX, +}; + +struct rtc_opr { + void *dev_handle; + u8 rtc_set_mode; + u8 rtc_pos; + u8 alm_enable; + u8 alm_num; + struct sys_time set_time; +}; + +static struct rtc_opr *__this = NULL; + + + +const char *alm_string[] = {" AL ", " ON ", " OFF"}; +const char *alm_select[] = {"AL-1", "AL-2", "AL-3", "AL-4", "AL-5"}; + + + + +static void ui_set_rtc_timeout(u8 menu) +{ + if (!__this) { + return ; + } + __this->rtc_set_mode = RTC_SET_MODE; + __this->rtc_pos = RTC_POS_NULL; +} + +struct ui_rtc_display *__attribute__((weak)) rtc_ui_get_display_buf() +{ + return NULL; +} + + + +//*----------------------------------------------------------------------------*/ +/**@brief rtc 闹钟设置 \ 时间设置转换 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void set_rtc_sw() +{ + if ((!__this) || (!__this->dev_handle)) { + return; + } + + + struct ui_rtc_display *rtc = rtc_ui_get_display_buf(); + if (!rtc) { + return; + } + switch (__this->rtc_set_mode) { + case RTC_SET_MODE: + __this->rtc_set_mode = ALM_SET_MODE; + __this->rtc_pos = RTC_POS_NULL; + __this->alm_num = 0; + rtc->rtc_menu = UI_RTC_ACTION_STRING_SET; + rtc->str = alm_select[__this->alm_num]; + UI_SHOW_MENU(MENU_RTC_SET, 10 * 1000, 0, ui_set_rtc_timeout); + break; + + case ALM_SET_MODE: + __this->alm_num++; + __this->rtc_pos = RTC_POS_NULL; + if (__this->alm_num >= sizeof(alm_select) / sizeof(alm_select[0])) { + __this->rtc_set_mode = RTC_SET_MODE; + __this->alm_num = 0; + UI_REFLASH_WINDOW(true); + break; + } + rtc->rtc_menu = UI_RTC_ACTION_STRING_SET; + rtc->str = alm_select[__this->alm_num]; + UI_SHOW_MENU(MENU_RTC_SET, 10 * 1000, 0, ui_set_rtc_timeout); + break; + + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief rtc 设置调整时钟的位置 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void set_rtc_pos() +{ + T_ALARM alarm = {0}; + if ((!__this) || (!__this->dev_handle)) { + return; + } + + struct ui_rtc_display *rtc = rtc_ui_get_display_buf(); + + if (!rtc) { + return; + } + + switch (__this->rtc_set_mode) { + case RTC_SET_MODE: + + if (__this->rtc_pos == RTC_POS_NULL) { + __this->rtc_pos = RTC_POS_DEFAULT; + dev_ioctl(__this->dev_handle, IOCTL_GET_SYS_TIME, (u32)&__this->set_time); + } else { + __this->rtc_pos++; + if (__this->rtc_pos == RTC_POS_MAX) { + __this->rtc_pos = RTC_POS_NULL; + rtc_update_time_api(&__this->set_time); + UI_REFLASH_WINDOW(true); + break; + } + } + + rtc->rtc_menu = UI_RTC_ACTION_YEAR_SET + (__this->rtc_pos - RTC_POS_YEAR); + + rtc->time.Year = __this->set_time.year; + rtc->time.Month = __this->set_time.month; + rtc->time.Day = __this->set_time.day; + rtc->time.Hour = __this->set_time.hour; + rtc->time.Min = __this->set_time.min; + rtc->time.Sec = __this->set_time.sec; + + UI_SHOW_MENU(MENU_RTC_SET, 10 * 1000, 0, ui_set_rtc_timeout); + break; + + case ALM_SET_MODE: + if (__this->rtc_pos == RTC_POS_NULL) { + __this->rtc_pos = RTC_ALM_POS_DEFAULT; + if (alarm_get_info(&alarm, __this->alm_num) != 0) { + log_error("alarm_get_info \n"); + } + + __this->set_time.hour = alarm.time.hour; + __this->set_time.min = alarm.time.min; + __this->alm_enable = alarm.sw; + + } else { + __this->rtc_pos++; + if (__this->rtc_pos == ALM_POS_MAX) { + __this->rtc_pos = RTC_POS_NULL; + alarm.time.hour = __this->set_time.hour; + alarm.time.min = __this->set_time.min; + alarm.time.sec = 0; + alarm.sw = __this->alm_enable; + alarm.index = __this->alm_num; + alarm.mode = 0; + alarm_add(&alarm, __this->alm_num); + __this->alm_num++; + if (__this->alm_num >= sizeof(alm_select) / sizeof(alm_select[0])) { + __this->rtc_set_mode = RTC_SET_MODE; + __this->alm_num = 0; + UI_REFLASH_WINDOW(true); + } else { + rtc->rtc_menu = UI_RTC_ACTION_STRING_SET; + rtc->str = alm_select[__this->alm_num]; + UI_SHOW_MENU(MENU_RTC_SET, 10 * 1000, 0, ui_set_rtc_timeout); + } + + break; + } + } + + if (ALM_POS_ENABLE == __this->rtc_pos) { + rtc->rtc_menu = UI_RTC_ACTION_STRING_SET; + if (__this->alm_enable) { + rtc->str = " ON "; + } else { + rtc->str = " OFF"; + } + } else { + rtc->rtc_menu = UI_RTC_ACTION_HOUR_SET + (__this->rtc_pos - ALM_POS_HOUR); + rtc->time.Year = __this->set_time.year; + rtc->time.Month = __this->set_time.month; + rtc->time.Day = __this->set_time.day; + rtc->time.Hour = __this->set_time.hour; + rtc->time.Min = __this->set_time.min; + rtc->time.Sec = __this->set_time.sec; + } + + UI_SHOW_MENU(MENU_RTC_SET, 10 * 1000, 0, ui_set_rtc_timeout); + break; + + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief rtc 调整时钟 加时间 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void set_rtc_up() +{ + + if ((!__this) || (!__this->dev_handle)) { + return; + } + + struct ui_rtc_display *rtc = rtc_ui_get_display_buf(); + + if (!rtc) { + return; + } + + if (__this->rtc_pos == RTC_POS_NULL) { + return ; + } + + + switch (__this->rtc_set_mode) { + case RTC_SET_MODE: + switch (__this->rtc_pos) { + case RTC_POS_YEAR: + __this->set_time.year++; + if (__this->set_time.year > MAX_YEAR) { + __this->set_time.year = MIN_YEAR; + } + break; + case RTC_POS_MONTH: + if (++__this->set_time.month > 12) { + __this->set_time.month = 1; + } + break; + case RTC_POS_DAY: + if (++__this->set_time.day > month_for_day(__this->set_time.month, __this->set_time.year)) { + __this->set_time.day = 1; + } + break; + case RTC_POS_HOUR: + if (++__this->set_time.hour >= 24) { + __this->set_time.hour = 0; + } + break; + + case RTC_POS_MIN: + if (++__this->set_time.min >= 60) { + __this->set_time.min = 0; + } + + break; + /* case RTC_POS_SEC: */ + + /* break; */ + } + + + rtc->rtc_menu = UI_RTC_ACTION_YEAR_SET + (__this->rtc_pos - RTC_POS_YEAR); + rtc->time.Year = __this->set_time.year; + rtc->time.Month = __this->set_time.month; + rtc->time.Day = __this->set_time.day; + rtc->time.Hour = __this->set_time.hour; + rtc->time.Min = __this->set_time.min; + rtc->time.Sec = __this->set_time.sec; + UI_SHOW_MENU(MENU_RTC_SET, 10 * 1000, 0, ui_set_rtc_timeout); + break; + case ALM_SET_MODE: + + switch (__this->rtc_pos) { + case ALM_POS_HOUR: + if (++__this->set_time.hour >= 24) { + __this->set_time.hour = 0; + } + break; + + case ALM_POS_MIN: + if (++__this->set_time.min >= 60) { + __this->set_time.min = 0; + } + break; + case ALM_POS_ENABLE: + __this->alm_enable = !__this->alm_enable; + break; + } + + if (ALM_POS_ENABLE == __this->rtc_pos) { + rtc->rtc_menu = UI_RTC_ACTION_STRING_SET; + if (__this->alm_enable) { + rtc->str = " ON "; + } else { + rtc->str = " OFF"; + } + } else { + rtc->rtc_menu = UI_RTC_ACTION_HOUR_SET + (__this->rtc_pos - ALM_POS_HOUR); + rtc->time.Year = __this->set_time.year; + rtc->time.Month = __this->set_time.month; + rtc->time.Day = __this->set_time.day; + rtc->time.Hour = __this->set_time.hour; + rtc->time.Min = __this->set_time.min; + rtc->time.Sec = __this->set_time.sec; + } + + UI_SHOW_MENU(MENU_RTC_SET, 10 * 1000, 0, ui_set_rtc_timeout); + break; + + default: + break; + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief rtc 调整时钟 减时间 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void set_rtc_down() +{ + + if ((!__this) || (!__this->dev_handle)) { + return; + } + struct ui_rtc_display *rtc = rtc_ui_get_display_buf(); + + if (!rtc) { + return; + } + + if (__this->rtc_pos == RTC_POS_NULL) { + return ; + } + + switch (__this->rtc_set_mode) { + case RTC_SET_MODE: + switch (__this->rtc_pos) { + case RTC_POS_YEAR: + __this->set_time.year--; + if (__this->set_time.year < MIN_YEAR) { + __this->set_time.year = MAX_YEAR; + } + break; + case RTC_POS_MONTH: + + if (__this->set_time.month == 1) { + __this->set_time.month = 12; + } else { + __this->set_time.month--; + } + + break; + case RTC_POS_DAY: + + if (__this->set_time.day == 1) { + __this->set_time.day = month_for_day(__this->set_time.month, __this->set_time.year); + } else { + __this->set_time.day --; + } + + break; + case RTC_POS_HOUR: + if (__this->set_time.hour == 0) { + __this->set_time.hour = 23; + } else { + __this->set_time.hour--; + } + break; + case RTC_POS_MIN: + if (__this->set_time.min == 0) { + __this->set_time.min = 59; + } else { + __this->set_time.min--; + } + break; + } + + rtc->rtc_menu = UI_RTC_ACTION_YEAR_SET + (__this->rtc_pos - RTC_POS_YEAR); + rtc->time.Year = __this->set_time.year; + rtc->time.Month = __this->set_time.month; + rtc->time.Day = __this->set_time.day; + rtc->time.Hour = __this->set_time.hour; + rtc->time.Min = __this->set_time.min; + rtc->time.Sec = __this->set_time.sec; + UI_SHOW_MENU(MENU_RTC_SET, 10 * 1000, 0, ui_set_rtc_timeout); + break; + + case ALM_SET_MODE: + switch (__this->rtc_pos) { + case ALM_POS_HOUR: + if (__this->set_time.hour == 0) { + __this->set_time.hour = 23; + } else { + __this->set_time.hour--; + } + break; + + case ALM_POS_MIN: + if (__this->set_time.min == 0) { + __this->set_time.min = 59; + } else { + __this->set_time.min--; + } + break; + + case ALM_POS_ENABLE: + __this->alm_enable = !__this->alm_enable; + break; + } + + if (ALM_POS_ENABLE == __this->rtc_pos) { + rtc->rtc_menu = UI_RTC_ACTION_STRING_SET; + if (__this->alm_enable) { + rtc->str = " ON "; + } else { + rtc->str = " OFF"; + } + } else { + rtc->rtc_menu = UI_RTC_ACTION_HOUR_SET + (__this->rtc_pos - ALM_POS_HOUR); + rtc->time.Year = __this->set_time.year; + rtc->time.Month = __this->set_time.month; + rtc->time.Day = __this->set_time.day; + rtc->time.Hour = __this->set_time.hour; + rtc->time.Min = __this->set_time.min; + rtc->time.Sec = __this->set_time.sec; + } + UI_SHOW_MENU(MENU_RTC_SET, 10 * 1000, 0, ui_set_rtc_timeout); + + break; + + default: + + break; + } + + + +} + +static void rtc_app_init() +{ + if (!__this) { + __this = zalloc(sizeof(struct rtc_opr)); + ASSERT(__this, "%s %di \n", __func__, __LINE__); + __this->dev_handle = dev_open("rtc", NULL); + if (!__this->dev_handle) { + ASSERT(0, "%s %d \n", __func__, __LINE__); + } + } + __this->rtc_set_mode = RTC_SET_MODE; + __this->rtc_pos = RTC_POS_NULL; + + ui_update_status(STATUS_RTC_MODE); + clock_idle(RTC_IDLE_CLOCK); + UI_SHOW_WINDOW(ID_WINDOW_CLOCK); + sys_key_event_enable(); + +} + + +//*----------------------------------------------------------------------------*/ +/**@brief rtc 退出 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void rtc_task_close() +{ +#if SMART_BOX_EN + extern void smartbox_rtc_mode_exit(void); + smartbox_rtc_mode_exit(); +#endif + UI_HIDE_CURR_WINDOW(); + if (__this) { + if (__this->dev_handle) { + dev_close(__this->dev_handle); + __this->dev_handle = NULL; + } + free(__this); + __this = NULL; + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief rtc 按键消息入口 + @param 无 + @return 1、消息已经处理,不需要发送到common 0、消息发送到common处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int rtc_key_event_opr(struct sys_event *event) +{ + int ret = true; + int err = 0; + +#if (TCFG_SPI_LCD_ENABLE) + extern int key_is_ui_takeover(); + if (key_is_ui_takeover()) { + return false; + } +#endif + + int key_event = event->u.key.event; + int key_value = event->u.key.value;// + + log_info("key_event:%d \n", key_event); + + if (__this && __this->dev_handle) { + switch (key_event) { + case KEY_RTC_UP: + log_info("KEY_RTC_UP \n"); + set_rtc_up(); + break; + + case KEY_RTC_DOWN: + log_info("KEY_RTC_DOWN \n"); + set_rtc_down(); + break; + + case KEY_RTC_SW: + log_info("KEY_RTC_SW \n"); + set_rtc_sw(); + break; + + case KEY_RTC_SW_POS: + log_info("KEY_RTC_SW_POS \n"); + set_rtc_pos(); + break; + + default : + ret = false; + break; + } + } + return ret; +} + + +//*----------------------------------------------------------------------------*/ +/**@brief rtc 按键消息入口 + @param 无 + @return 1、消息已经处理,不需要发送到common 0、消息发送到common处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int rtc_sys_event_handler(struct sys_event *event) +{ + switch (event->type) { + case SYS_KEY_EVENT: + return rtc_key_event_opr(event); + case SYS_DEVICE_EVENT: + return false; + default: + return false; + } + return false; +} + + +//*----------------------------------------------------------------------------*/ +/**@brief rtc 启动 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void rtc_task_start() +{ + rtc_app_init(); + if (alarm_active_flag_get()) { + alarm_ring_start(); + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief rtc 模式提示音播放结束处理 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void rtc_tone_play_end_callback(void *priv, int flag) +{ + u32 index = (u32)priv; + + if (APP_RTC_TASK != app_get_curr_task()) { + log_error("tone callback task out \n"); + return; + } + + switch (index) { + case IDEX_TONE_RTC: + ///提示音播放结束, 启动播放器播放 + break; + default: + break; + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief rtc 主任务 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void app_rtc_task() +{ + int res; + int msg[32]; +#if (SMART_BOX_EN) + extern u8 smartbox_rtc_ring_tone(void); + if (smartbox_rtc_ring_tone()) { + tone_play_with_callback_by_name(tone_table[IDEX_TONE_RTC], 1, rtc_tone_play_end_callback, (void *)IDEX_TONE_RTC); + } +#else + tone_play_with_callback_by_name(tone_table[IDEX_TONE_RTC], 1, rtc_tone_play_end_callback, (void *)IDEX_TONE_RTC); +#endif + rtc_task_start(); + + while (1) { + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + if (rtc_sys_event_handler((struct sys_event *)(&msg[1])) == false) { + app_default_event_deal((struct sys_event *)(&msg[1])); //由common统一处理 + } + break; + default: + break; + } + + if (app_task_exitting()) { + rtc_task_close(); + return; + } + } +} + +#else + + +void app_rtc_task() +{ + +} + +#endif + + + + diff --git a/apps/soundbox/task_manager/rtc/virtual_rtc.c b/apps/soundbox/task_manager/rtc/virtual_rtc.c new file mode 100644 index 0000000..a4c590c --- /dev/null +++ b/apps/soundbox/task_manager/rtc/virtual_rtc.c @@ -0,0 +1,205 @@ +#include "app_config.h" +#include "rtc/alarm.h" +#include "app_action.h" +#include "system/includes.h" +#include "clock_cfg.h" +#include "ioctl_cmds.h" +#include "system/sys_time.h" + +#if (TCFG_APP_RTC_EN && TCFG_USE_VIRTUAL_RTC) + + +/************************************************************* + 此文件函数主要是虚拟rtc设备的实现 + 应用于不外挂晶振的场景,用户可以忽略实现, + 最后的应用的接口与挂晶振的接口一致 +**************************************************************/ + + +#define WRITE_ALARM BIT(1) +#define READ_ALARM BIT(5) + +#define WRITE_RTC BIT(0) +#define READ_RTC BIT(4) + +#define MAX_YEAR 2099 +#define MIN_YEAR 2000 + + +typedef struct _RTC_SIMULATE_VAR { + struct device device; + struct sys_time sys_simulate_time; + struct sys_time sys_alarm_time; + /* OS_MUTEX mutex; */ +} RTC_SIMULATE_VAR; + +#define __this (&rtc_smulate_var) +static RTC_SIMULATE_VAR rtc_smulate_var = {0}; + +static u8 g_alarm_flag = 0; + + +__attribute__((weak))void alm_wakeup_isr(void); +__attribute__((weak)) void set_rtc_default_time(struct sys_time *t); + +static u8 is_the_same_time(struct sys_time *time1, struct sys_time *time2) +{ + return (time1->year == time2->year && + time1->month == time2->month && + time1->day == time2->day && + time1->hour == time2->hour && + time1->min == time2->min && + time1->sec == time2->sec); +} + + +static int rtc_simulate_init(const struct dev_node *node, void *arg) +{ + /* os_mutex_create(&__this->mutex); */ + + if (set_rtc_default_time) { + set_rtc_default_time(&__this->sys_simulate_time); + } else { + __this->sys_simulate_time.year = 2020; + __this->sys_simulate_time.month = 1; + __this->sys_simulate_time.day = 1; + __this->sys_simulate_time.hour = 0; + __this->sys_simulate_time.min = 0; + __this->sys_simulate_time.sec = 0; + } + printf("rtc_simulate_init: %d-%d-%d %d:%d:%d\n", + __this->sys_simulate_time.year, + __this->sys_simulate_time.month, + __this->sys_simulate_time.day, + __this->sys_simulate_time.hour, + __this->sys_simulate_time.min, + __this->sys_simulate_time.sec); + return 0; +} + +static int rtc_simulate_open(const char *name, struct device **device, void *arg) +{ + *device = &__this->device; + + return 0; +} + +static void write_alarm(struct sys_time *alarm_time) +{ + local_irq_disable(); + memcpy(&__this->sys_alarm_time, alarm_time, sizeof(struct sys_time)); + local_irq_enable(); +} + +static void write_sys_time(struct sys_time *curr_time) +{ + local_irq_disable(); + memcpy(&__this->sys_simulate_time, curr_time, sizeof(struct sys_time)); + local_irq_enable(); +} + +static void read_sys_time(struct sys_time *curr_time) +{ + local_irq_disable(); + memcpy(curr_time, &__this->sys_simulate_time, sizeof(struct sys_time)); + local_irq_enable(); +} + +static void set_alarm_ctrl(u8 set_alarm) +{ + g_alarm_flag = set_alarm; +} + +static int rtc_simulate_ioctl(struct device *device, u32 cmd, u32 arg) +{ + int err = 0; + switch (cmd) { + case IOCTL_SET_ALARM: + write_alarm((struct sys_time *)arg); + break; + case IOCTL_SET_ALARM_ENABLE: + if (arg) { + set_alarm_ctrl(1); + } else { + set_alarm_ctrl(0); + } + break; + case IOCTL_GET_SYS_TIME: + read_sys_time((struct sys_time *)arg); + break; + case IOCTL_SET_SYS_TIME: + write_sys_time((struct sys_time *)arg); + break; + } + return err; +} + +void set_virtual_rtc_tick(u64 actual_ns) +{ +#if (defined(TCFG_USE_VIRTUAL_RTC) && (TCFG_USE_VIRTUAL_RTC)) + struct sys_time temp_time; + static u64 sum_nsec = 0; + static u8 cal_flag = 0; + + sum_nsec += actual_ns; + if (sum_nsec >= 1000000000) { + sum_nsec -= 1000000000; + cal_flag = 1; + } + + if (cal_flag) { + cal_flag = 0; + read_sys_time(&temp_time); + if (++temp_time.sec >= 60) { + temp_time.sec = 0; + if (++temp_time.min >= 60) { + temp_time.min = 0; + if (++temp_time.hour >= 24) { + temp_time.hour = 0; + if (++temp_time.day > month_for_day(temp_time.month, temp_time.year)) { + temp_time.day = 1; + if (++temp_time.month > 12) { + temp_time.month = 1; + if (++temp_time.year > MAX_YEAR) { + temp_time.year = MIN_YEAR; + } + } + } + } + } + } + write_sys_time(&temp_time); + /* + printf("rtc_sys_time: %d-%d-%d %d:%d:%d\n", + temp_time.year, + temp_time.month, + temp_time.day, + temp_time.hour, + temp_time.min, + temp_time.sec); + */ + + local_irq_disable(); + if (g_alarm_flag && is_the_same_time(&__this->sys_alarm_time, &__this->sys_simulate_time)) { + local_irq_enable(); + if (alm_wakeup_isr) { + alm_wakeup_isr(); + } + } else { + local_irq_enable(); + } + + } +#endif +} + + +const struct device_operations rtc_simulate_ops = { + .init = rtc_simulate_init, + .open = rtc_simulate_open, + .ioctl = rtc_simulate_ioctl, + .read = NULL, + .write = NULL, +}; + +#endif diff --git a/apps/soundbox/task_manager/sleep/sleep.c b/apps/soundbox/task_manager/sleep/sleep.c new file mode 100644 index 0000000..a905492 --- /dev/null +++ b/apps/soundbox/task_manager/sleep/sleep.c @@ -0,0 +1,225 @@ +#include "system/app_core.h" +#include "system/includes.h" +#include "server/server_core.h" +#include "media/includes.h" +#include "app_config.h" +#include "app_task.h" +#include "tone_player.h" +#include "asm/charge.h" +#include "app_charge.h" +#include "app_main.h" +#include "app_online_cfg.h" +#include "app_power_manage.h" +#include "gSensor/gSensor_manage.h" +#include "ui_manage.h" +#include "vm.h" +#include "app_chargestore.h" +#include "key_event_deal.h" +#include "asm/pwm_led.h" +#include "user_cfg.h" +#include "sleep/sleep.h" +#include "ui/ui_api.h" +#include "clock_cfg.h" +#include "dev_manager.h" +#include "user_api/app_status_api.h" + +#if TCFG_APP_SLEEP_EN + + +static u16 power_off_timer = 0; +static u16 led_blink_timer1 = 0; +static u16 led_blink_timer2 = 0; +static u16 power_on_timer = 0; + +extern void app_status_handler(enum APP_STATUS status); + +//*----------------------------------------------------------------------------*/ +/**@brief sleep 按键消息入口 + @param 无 + @return 1、消息已经处理,不需要发送到common 0、消息发送到common处理 + @note + */ +/*----------------------------------------------------------------------------*/ +static int sleep_key_event_opr(struct sys_event *event) +{ + int ret = false; + int err = 0; + + int key_event = event->u.key.event; + int key_value = event->u.key.value;// + + log_i("key_event:%d \n", key_event); + switch (key_event) { + default: + break; + } + + return ret; +} + + +//*----------------------------------------------------------------------------*/ +/**@brief sleep 软关机处理 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void sleep_power_off() +{ + if (get_charge_online_flag() == 0) { + app_var.goto_poweroff_flag = 1; + app_task_switch_to(APP_POWEROFF_TASK); + } else { + app_task_switch_to(APP_IDLE_TASK); + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief sleep 关机闪灯处理 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void poweroff_led_blink1() +{ + app_status_handler(APP_STATUS_POWER_OFF); +} + +static void poweroff_led_blink2() +{ + app_status_handler(APP_STATUS_POWER_CLOSE); +} + +//*----------------------------------------------------------------------------*/ +/**@brief sleep 开机闪灯处理 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void poweron_led_blink() +{ + app_status_handler(APP_STATUS_POWER_ON); + +} + +//*----------------------------------------------------------------------------*/ +/**@brief sleep 模式初始化 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void sleep_task_start(void) +{ + sys_key_event_enable(); + + clock_idle(REC_IDLE_CLOCK); + power_off_timer = sys_timeout_add(NULL, sleep_power_off, 30000); + led_blink_timer1 = sys_timeout_add(NULL, poweroff_led_blink1, 28000); + led_blink_timer2 = sys_timeout_add(NULL, poweroff_led_blink2, 29500); + power_on_timer = sys_timeout_add(NULL, poweron_led_blink, 500); +} + + +//*----------------------------------------------------------------------------*/ +/**@brief sleep 退出 + @param 无 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ + +static void sleep_task_close() +{ + sys_timeout_del(power_off_timer); + sys_timeout_del(led_blink_timer1); + sys_timeout_del(led_blink_timer2); + return; +} + +//*----------------------------------------------------------------------------*/ +/**@brief sleep 模式活跃状态 所有消息入口 + @param 无 + @return 1、当前消息已经处理,不需要发送comomon + 0、当前消息不是linein处理的,发送到common统一处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int sleep_sys_event_handler(struct sys_event *event) +{ + const char *logo = NULL; + int err = 0; + switch (event->type) { + case SYS_KEY_EVENT: + return 1; + case SYS_DEVICE_EVENT: + ///所有设备相关的事件不能返回true, 必须给留给公共处理的地方响应设备上下线 + switch ((u32)event->arg) { + case DRIVER_EVENT_FROM_SD0: + case DRIVER_EVENT_FROM_SD1: + case DRIVER_EVENT_FROM_SD2: + logo = (char *)event->u.dev.value; + case DEVICE_EVENT_FROM_OTG: + if ((u32)event->arg == DEVICE_EVENT_FROM_OTG) { + logo = (char *)"udisk0"; + } + + if (event->u.dev.event == DEVICE_EVENT_IN) { + } else if (event->u.dev.event == DEVICE_EVENT_OUT) { + } + break;//DEVICE_EVENT_FROM_USB_HOST + }//switch((u32)event->arg) + break;//SYS_DEVICE_EVENT + default: + break;; + }//switch (event->type) + + return false; +} + + +//*----------------------------------------------------------------------------*/ +/**@brief sleep 主任务 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void app_sleep_task() +{ + int res; + int msg[32]; + sleep_task_start(); + + while (1) { + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + if (sleep_sys_event_handler((struct sys_event *)(&msg[1])) == false) { + app_default_event_deal((struct sys_event *)(&msg[1])); //由common统一处理 + } + break; + default: + break; + } + + if (app_task_exitting()) { + sleep_task_close(); + return; + } + } +} + +#else + + +void app_sleep_task() +{ + +} + +#endif diff --git a/apps/soundbox/task_manager/spdif/hdmi_cec_drv.c b/apps/soundbox/task_manager/spdif/hdmi_cec_drv.c new file mode 100644 index 0000000..f630c68 --- /dev/null +++ b/apps/soundbox/task_manager/spdif/hdmi_cec_drv.c @@ -0,0 +1,723 @@ +#include "spdif/hdmi_cec.h" +#include "spdif/hdmi_cec_api.h" +#include "app_config.h" +#include "asm/clock.h" +#include "app_config.h" +#include "gpio.h" +#include "system/timer.h" +#if ((TCFG_SPDIF_ENABLE) && (TCFG_HDMI_ARC_ENABLE)) + +//#pragma const_seg(".HDMI_const") +//#pragma code_seg(".HDMI_code") + + +static void cec_set_wait_time(u32 us); + +static void cec_set_line_state(const u8 state) +{ + gpio_direction_output(TCFG_HDMI_CEC_PORT, state); +} + +static u32 cec_get_line_state() +{ + return gpio_read(TCFG_HDMI_CEC_PORT); +} + +static u8 CEC_Version_cmd[3] = {0x00, CEC_VERSION, 0x04}; //0x04 :1.3a ???? +static u8 Report_Power_Status_Cmd[3] = {0x00, 0x90, 0x00}; //0x00:ON ; 0x01:OFF +static u8 Standby_Cmd[2] = {0x00, STANDBY}; + +static u8 PollingMessage_cmd[1] = {0x55}; +static u8 Report_Physical_Add_Cmd1[7] = {0x5F, REPORT_PHYSICAL_ADDRESS, 0x20, 0x00, 0x05}; +static u8 Report_Physical_Add_Cmd[7] = {0x5F, REPORT_PHYSICAL_ADDRESS, 0x10, 0x00, 0x05}; + +static u8 Device_Vendor_Id_Cmd[5] = {0x5f, DEVICE_VENDOR_ID, 0x45, 0x58, 0x50}; +static u8 Set_System_Audio_Mode_cmd[] = {0x50, SET_SYSTEM_AUDIO_MODE, 0x01}; +static u8 Broadcast_System_Audio_Mode_cmd[] = {0x5F, SET_SYSTEM_AUDIO_MODE, 0x01}; +static u8 Set_Osd_Name_cmd[] = {0x50, CECOP_SET_OSD_NAME, 0x41, 0x75, 0x64, 0x69, 0x6f, 0x20, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d}; //["Audio System"] + +static u8 System_Audio_Mode_Status_cmd[] = {0x50, CECOP_SYSTEM_AUDIO_MODE_STATUS, 0x01}; +//static u8 Report_Audio_Status_cmd[] = {0x50, CECOP_REPORT_AUDIO_STATUS, 0xB2};// bit7 off/on bit6-0 volume +static u8 Report_Audio_Status_cmd[] = {0x50, CECOP_REPORT_AUDIO_STATUS, 0x32}; + +static u8 Report_Power_Status_cmd[] = {0x50, CECOP_REPORT_POWER_STATUS, 0x00};// 0:on 1 standby 2: S2O 3: o2s + +static u8 Terminate_Arc_cmd[2] = {0x50, CECOP_ARC_TERMINATE}; +static u8 Initiate_Arc_cmd[2] = {0x50, INITIATE_ARC}; +static u8 Report_Short_Audio_Desc_cmd[8] = {0x50, REPORT_SHORT_AUDIO_DESCRIPTOR, 0x15, 0x17, 0x50, 0x3E, 0x06, 0xC0}; //AC-3 6Ch (48 44 32k) 640kbps/ DTS 7Ch (48 44K) 1536kbps + +static u8 Give_Tuner_Device_Status_cmd[3] = {0x50, CECOP_GIVE_TUNER_DEVICE_STATUS, 0x01}; +static u8 Feature_Abort_cmd[3] = {0x50, CECOP_FEATURE_ABORT, 0x00}; + +#define CEC_IDLE 0 +#define CEC_TX 1 +#define CEC_RX 2 + +static u8 cec_work_mode; +static s8 cec_state; +static u16 high_period_time; +enum { + CEC_SUCC, + NAK_HEAD, + NAK_DATA, +}; + +struct cec_msg_frame { + u8 *msg; + u8 msg_len; + u8 tx_count; + u8 ack; + u8 broadcast; +}; + +static struct cec_msg_frame cec_frame; + +struct hdmi_arc_t { + u8 msg_count; + u8 state; + u8 logic_addr; + u8 rx_count; + u8 rx_msg; + u8 idle_time; + u16 time_id; + u8 cec_ok; + + u8 msg[17]; + +}; + +static struct hdmi_arc_t arc_devcie; +#define __this (&arc_devcie) + +typedef enum { + CEC_XMIT_STARTBIT, + CEC_XMIT_BIT7, + CEC_XMIT_BIT6, + CEC_XMIT_BIT5, + CEC_XMIT_BIT4, + CEC_XMIT_BIT3, + CEC_XMIT_BIT2, + CEC_XMIT_BIT1, + CEC_XMIT_BIT0, + CEC_XMIT_BIT_EOM, + CEC_XMIT_BIT_ACK, + CEC_XMIT_ACK_PU, + CEC_XMIT_CHECK_ACK, + CEC_XMIT_ACK_END, + + CEC_WAIT_IDLE, + CEC_RECEIVE, + CEC_CONTINUE_BIT, +} CEC_XMIT_STATE ; + +static void cec_start_bit() +{ + cec_state = CEC_XMIT_STARTBIT; + gpio_direction_output(TCFG_HDMI_CEC_PORT, 0); + gpio_set_pull_down(TCFG_HDMI_CEC_PORT, 0); + + const u16 low_time = 3700; + const u16 high_time = 4500 - low_time; + cec_set_wait_time(low_time); + high_period_time = high_time; + +} +static void cec_logic_bit0() +{ + const u16 low_time = 1500; + const u16 high_time = 2400 - low_time; + cec_set_wait_time(low_time); + cec_set_line_state(0); + high_period_time = high_time; +} +static void cec_logic_bit1() +{ + const u16 low_time = 600; + const u16 high_time = 2400 - low_time; + cec_set_wait_time(low_time); + cec_set_line_state(0); + high_period_time = high_time; +} +static void cec_end_bit() +{ + const u16 low_time = 600; + cec_set_line_state(0); + cec_set_wait_time(low_time); +} +static void cec_ack_bit() +{ + const u16 low_time = 1500; + const u16 high_time = 1800 - low_time; + cec_set_wait_time(low_time); + cec_set_line_state(0); + high_period_time = high_time; +} +static void transmit_complete(u32 state) +{ + gpio_set_direction(TCFG_HDMI_CEC_PORT, 1); + cec_work_mode = CEC_IDLE; + cec_frame.ack = state; + cec_state = CEC_RECEIVE; +} +static void tx_bit_isr() +{ + if (high_period_time) { + cec_set_line_state(1); + cec_set_wait_time(high_period_time); + high_period_time = 0; + cec_state++; + return; + } + switch (cec_state) { + case CEC_WAIT_IDLE: + cec_start_bit(); + break; + + case CEC_XMIT_STARTBIT: + break; + + case CEC_XMIT_ACK_END: + if (cec_frame.ack) { + cec_set_line_state(1); + if (cec_frame.tx_count == cec_frame.msg_len) { + transmit_complete(CEC_SUCC); + break; + } else { + cec_state = CEC_XMIT_BIT7; + } + } else { + if (cec_frame.tx_count == 1) { + transmit_complete(NAK_HEAD); + } else { + transmit_complete(NAK_DATA); + } + break; + } + case CEC_XMIT_BIT7 ... CEC_XMIT_BIT0: + if (cec_frame.msg[cec_frame.tx_count] & BIT(7 - (cec_state - CEC_XMIT_BIT7))) { + cec_logic_bit1(); + } else { + cec_logic_bit0(); + } + break; + + case CEC_XMIT_BIT_EOM: + cec_frame.tx_count++; + if (cec_frame.tx_count == cec_frame.msg_len) { + cec_logic_bit1(); + } else { + cec_logic_bit0(); + } + break; + + case CEC_XMIT_BIT_ACK: + cec_state++; + cec_end_bit(); + break; + + case CEC_XMIT_ACK_PU: + gpio_set_direction(TCFG_HDMI_CEC_PORT, 1); + cec_set_wait_time(1000 - 600); + cec_state++; + break; + + case CEC_XMIT_CHECK_ACK: + cec_frame.ack = cec_frame.broadcast ? 1 : !cec_get_line_state(); + cec_state++; + cec_set_wait_time(2400 - 1000); + break; + } + +} + +#define CAP_DIV 64 +#define CAP_CLK 24000000 +#define CEC_TMR JL_TIMER2 +#define CEC_TMR_IDX IRQ_TIME2_IDX + +#define CAP_RISING_EDGE 0b10 +#define CAP_FALLING_EDGE 0b11 +static void change_capture_mode(u32 mode) +{ + CEC_TMR->PRD = 0; + CEC_TMR->CNT = 0; + CEC_TMR->CON = ((0b0011 << 4) | BIT(3)); + CEC_TMR->CON |= mode; +} +static u16 get_captrue_time() +{ + return CEC_TMR->PRD; +} +//New initiator wants to send a frame wait time +#define _ms *1//000 +#define CEC_NEW_FRAME_WAIT_TIME (5*(2.4 _ms))//(5*(2.4 _ms)) +#define CEC_RETRANSMIT_FRAME (3*(2.4 _ms)) + +static void cec_set_wait_time(u32 us) +{ + /* us = 3700; */ + CEC_TMR->CON = BIT(14); + u32 clk = clk_get("timer") / 320000; + /* printf("clk %d %d %d", clk, us, us / 100 * clk); */ + CEC_TMR->CON = ((0b0110 << 4) | BIT(3)); + CEC_TMR->CNT = 0; + CEC_TMR->PRD = us / 100 * clk; + CEC_TMR->CON |= BIT(0); +} +static u32 cec_bit_time_check(u16 t, u16 min, u16 max) +{ + const u16 _min = min * (CAP_CLK / 1000000) / CAP_DIV; + const u16 _max = max * (CAP_CLK / 1000000) / CAP_DIV; + if ((t > _min) && (t < _max)) { + return 1; + } else { + return 0; + } +} +static s8 cec_get_bit_value(const u16 low_time, const u16 high_time) +{ + if (cec_bit_time_check(low_time + high_time, 2050, 2750)) { + if (cec_bit_time_check(low_time, 400, 800)) { + return 1; + } else if (cec_bit_time_check(low_time, 1300, 1700)) { + return 0; + } + } + return -1; +} + +static void cec_cmd_response(); +static void rx_bit_isr() +{ + static u16 low_time = 0; + static u16 high_time = 0; + static u16 eom = 0; + static u8 follower = 0; + u32 mode = CEC_TMR->CON & 0x3; + CEC_TMR->CON = 0; + + if (high_period_time) { + cec_set_line_state(1); + cec_set_wait_time(high_period_time); + high_period_time = 0; + cec_state = CEC_XMIT_ACK_END; + return; + } + + if (cec_state == CEC_XMIT_ACK_END) { + gpio_set_direction(TCFG_HDMI_CEC_PORT, 1); + __this->rx_count ++; + if (eom) { + __this->rx_msg = 1; + u16 ttmp; + ttmp = usr_timeout_add(NULL, cec_cmd_response, CEC_NEW_FRAME_WAIT_TIME, 0); +// printf("****ttmp = 0x%x\n", ttmp); + } else { + cec_state = CEC_CONTINUE_BIT; + } + + change_capture_mode(CAP_FALLING_EDGE); + return; + } + + u16 time = get_captrue_time(); + + if (mode == CAP_RISING_EDGE) { + low_time = time; + time = 0; + mode = CAP_FALLING_EDGE; + } else { + mode = CAP_RISING_EDGE; + } + + change_capture_mode(mode); + + if (time == 0) { + return; + } + + if (cec_state == CEC_RECEIVE) { + cec_state = CEC_XMIT_STARTBIT; + low_time = 0; + high_time = 0; + return; + } + + s8 bit; + + high_time = time; + + switch (cec_state) { + case CEC_XMIT_STARTBIT: + if (low_time && high_time) { + if (cec_bit_time_check(low_time, 3500, 3900) && + cec_bit_time_check(low_time + high_time, 4300, 4700)) { + cec_state ++; + } + } + + follower = 0; + __this->rx_count = 0; + low_time = 0; + high_time = 0; + break; + + case CEC_CONTINUE_BIT: + cec_state = CEC_XMIT_BIT7; + break; + + case CEC_XMIT_BIT7 ... CEC_XMIT_BIT0: + bit = cec_get_bit_value(low_time, high_time); + if (bit == 0) { + __this->msg[__this->rx_count] &= ~BIT(7 - (cec_state - CEC_XMIT_BIT7)); +// cec_state++; + } else if (bit == 1) { + __this->msg[__this->rx_count] |= BIT(7 - (cec_state - CEC_XMIT_BIT7)); +// cec_state++; + } else if (bit == -1) { //error bit + cec_state = CEC_XMIT_STARTBIT; + } + cec_state++; + break; + + case CEC_XMIT_BIT_EOM: + cec_state++; + bit = cec_get_bit_value(low_time, high_time); + if (bit == 0) { + eom = 0; + } else if (bit == 1) { + eom = 1; + } else if (bit == -1) { //error bit + cec_state = CEC_XMIT_STARTBIT; + } + if (__this->rx_count == 0) { //head block + follower = __this->msg[0] & 0xf; + } + + if (follower == __this->logic_addr) { + cec_ack_bit();//send ack + } else { + /* printf(" %d %d %d", __this->rx_count, follower, __this->logic_addr); */ + __this->rx_count = 0; + } + break; + + case CEC_XMIT_BIT_ACK: + cec_state = CEC_XMIT_BIT7; + break; + } + +} +#define TIME_PRD 30 +___interrupt +static void cec_timer_isr() +{ + CEC_TMR->CON |= BIT(14); + + if (cec_work_mode == CEC_TX) { + tx_bit_isr(); + if (cec_work_mode == CEC_IDLE) { + change_capture_mode(CAP_FALLING_EDGE); + } + } else { + + if (__this->idle_time < (150 / TIME_PRD)) { + __this->idle_time = 150 / TIME_PRD; + } + + rx_bit_isr(); + } + +} + + +u32 cec_transmit_frame(unsigned char *buffer, int count) +{ + if (cec_work_mode != CEC_IDLE) { + return 1; + } + __this->idle_time = 1; + cec_work_mode = CEC_TX; + CEC_TMR->CON = BIT(14); + cec_frame.ack = -1; + cec_frame.msg = buffer; + cec_frame.msg_len = count; + cec_frame.tx_count = 0; + cec_frame.broadcast = 0; + + if ((buffer[0] & 0xf) == CEC_LOGADDR_UNREGORBC) { + cec_frame.broadcast = 1; + } + + if ((buffer[0] & 0xf) == __this->logic_addr) { + cec_frame.broadcast = 1; + } + + gpio_set_direction(TCFG_HDMI_CEC_PORT, 1); + if (cec_get_line_state()) { + /* g_printf("start"); */ + cec_start_bit(); + } else { + /* g_printf("wait idle"); */ + high_period_time = 0; + cec_state = CEC_WAIT_IDLE; + change_capture_mode(CAP_RISING_EDGE); + } + + return 0; +} +typedef enum { + ARC_STATUS_REQ_ADD, + ARC_STATUS_WAIT_ONLINE, + ARC_STATUS_REPORT_ADD, + ARC_STATUS_STB, + ARC_STATUS_INIT, + ARC_STATUS_REQ_INIT, + ARC_STATUS_INIT_SUCCESS, + ARC_STATUS_TERMINATE, + ARC_STATUS_REQ_TERMINATE, + ARC_STATUS_REPORT_TERMINATE, +} ARC_STATUS; + +static void decode_cec_command() +{ + printf("CEC command "); + put_buf(__this->msg, __this->rx_count); + u8 intiator = __this->msg[0] >> 4; + switch (__this->msg[1]) { + case CECOP_FEATURE_ABORT: + printf("__this->state < ARC_STATUS_INIT=0x%x\n", __this->state); + if (__this->state <= ARC_STATUS_INIT) { +// putchar('2'); + __this->cec_ok = 0; + __this->state = ARC_STATUS_REQ_ADD; + } + break; + case CECOP_GIVE_PHYSICAL_ADDRESS: + cec_transmit_frame(Report_Physical_Add_Cmd, 5); + break; + case CECOP_GIVE_DEVICE_VENDOR_ID: + cec_transmit_frame(Device_Vendor_Id_Cmd, 5); + break; + case GET_CEC_VERSION: + CEC_Version_cmd[0] = intiator; + cec_transmit_frame(CEC_Version_cmd, 3); + break; + case CECOP_ARC_REPORT_INITIATED: + __this->idle_time = 500 / TIME_PRD; + break; + + case CECOP_SET_STREAM_PATH: + break; + case CECOP_GIVE_OSD_NAME: + cec_transmit_frame(Set_Osd_Name_cmd, 14); + break; + + case CECOP_REQUEST_SHORT_AUDIO: + __this->cec_ok = 1; + cec_transmit_frame(Report_Short_Audio_Desc_cmd, sizeof(Report_Short_Audio_Desc_cmd)); + __this->idle_time = 3500 / TIME_PRD; + break; + + case CECOP_SYSTEM_AUDIO_MODE_REQUEST: +// cec_transmit_frame(Set_System_Audio_Mode_cmd, sizeof(Set_System_Audio_Mode_cmd)); + cec_transmit_frame(Broadcast_System_Audio_Mode_cmd, sizeof(Set_System_Audio_Mode_cmd)); + break; + case CECOP_GIVE_AUDIO_STATUS: + cec_transmit_frame(Report_Audio_Status_cmd, sizeof(Report_Audio_Status_cmd)); + break; + + case CECOP_GIVE_SYSTEM_AUDIO_MODE_STATUS: + cec_transmit_frame(System_Audio_Mode_Status_cmd, sizeof(System_Audio_Mode_Status_cmd)); + break; + case CECOP_TUNER_DEVICE_STATUS: + cec_transmit_frame(Give_Tuner_Device_Status_cmd, sizeof(Give_Tuner_Device_Status_cmd) / sizeof(Give_Tuner_Device_Status_cmd[0])); + break; + case CECOP_GIVE_DEVICE_POWER_STATUS: + cec_transmit_frame(Report_Power_Status_cmd, sizeof(Report_Power_Status_cmd)); + break; + case CECOP_ARC_REQUEST_INITIATION: + cec_transmit_frame(Initiate_Arc_cmd, 2); + __this->state = ARC_STATUS_INIT; + __this->idle_time = 3500 / TIME_PRD; + break; + + default: + printf("CEC command "); + put_buf(__this->msg, __this->rx_count); + break; + } +} +static void cec_cmd_response() +{ + if (__this->rx_count > 1) { + decode_cec_command(); + } + +// putchar('1'); + if (__this->idle_time < (150 / TIME_PRD)) { + __this->idle_time = 150 / TIME_PRD; + } + + if (cec_work_mode == CEC_IDLE) { + cec_state = CEC_RECEIVE; + } + if (__this->msg_count != 0) { + __this->msg_count = 0xff; + } + __this->rx_msg = 0; +} +static void cec_timer_loop() +{ + if (__this->rx_msg) { + return; + } + + if (cec_work_mode) { + return; + } + + if (__this->idle_time) { + __this->idle_time--; + return; + } + + if (__this->msg_count && cec_frame.ack != CEC_SUCC) { + __this->msg_count = 0; + r_printf("send cec msg nak %d", cec_frame.ack); + } else { + } + + printf("[%d]", __this->state); + switch (__this->state) { + + case ARC_STATUS_REQ_ADD: + if (__this->msg_count == 0xff) { + __this->state = ARC_STATUS_REPORT_ADD; + __this->msg_count = 0; + break; + } + __this->cec_ok = 0; + cec_transmit_frame(PollingMessage_cmd, 1); + __this->msg_count ++; + + if (__this->msg_count == 2) { + __this->idle_time = 50 / TIME_PRD; + } + if (__this->msg_count > 3) { + __this->state = ARC_STATUS_REPORT_ADD; + __this->idle_time = 50 / TIME_PRD; + __this->msg_count = 0; + } + break; + + case ARC_STATUS_REPORT_ADD: + __this->logic_addr = 5; + if (__this->msg_count == 0xff) { + __this->state = ARC_STATUS_WAIT_ONLINE; + __this->msg_count = 0; + break; + } +// __this->cec_ok=1; + cec_transmit_frame(Report_Physical_Add_Cmd1, 5); + __this->msg_count ++; + if (__this->msg_count > 1) { + __this->state = ARC_STATUS_WAIT_ONLINE; + __this->msg_count = 0; + } + break; + + case ARC_STATUS_WAIT_ONLINE: + if (__this->msg_count == 0xff) { + __this->state = ARC_STATUS_STB; + __this->msg_count = 0; + break; + } + cec_transmit_frame(Device_Vendor_Id_Cmd, 5); + __this->msg_count ++; + if (__this->msg_count > 1) { + __this->state = ARC_STATUS_STB; + __this->msg_count = 0; + } + break; + + case ARC_STATUS_STB: + if (__this->msg_count == 0xff) { + __this->state = ARC_STATUS_INIT; + __this->msg_count = 0; + break; + } + __this->cec_ok = 1; +// cec_transmit_frame(Set_System_Audio_Mode_cmd, 3); + cec_transmit_frame(Broadcast_System_Audio_Mode_cmd, 3); + __this->msg_count ++; + __this->idle_time = 300 / TIME_PRD; + if (__this->msg_count > 1) { + __this->state = ARC_STATUS_INIT; + } + break; + + case ARC_STATUS_INIT: + if (__this->cec_ok) { + break; + } + cec_transmit_frame(Initiate_Arc_cmd, 2); + __this->idle_time = 3500 / TIME_PRD; + break; + } +} + +void hdmi_cec_init(void) +{ + memset(__this, 0, sizeof(*__this)); + + __this->logic_addr = 5; + cec_state = CEC_RECEIVE; + cec_work_mode = CEC_IDLE; + __this->cec_ok = 0; + + //port + gpio_set_die(TCFG_HDMI_CEC_PORT, 1); + gpio_set_direction(TCFG_HDMI_CEC_PORT, 1); + gpio_set_pull_up(TCFG_HDMI_CEC_PORT, 1); + gpio_set_pull_down(TCFG_HDMI_CEC_PORT, 0); + + u32 clk = clk_get("timer"); + printf("clk %d %d", clk, CAP_CLK); + +#if CEC_TMR_IDX == IRQ_TIME2_IDX + //capture input channel + printf("TCFG_HDMI_CEC_PORT:[%d]", TCFG_HDMI_CEC_PORT); + JL_IOMAP->CON1 |= BIT(30); + JL_IOMAP->CON2 &= ~(0x7F << 16); + JL_IOMAP->CON2 |= (TCFG_HDMI_CEC_PORT << 16); + + CEC_TMR->CON = BIT(14); +#else +#error "please config time input channle" +#endif + change_capture_mode(CAP_FALLING_EDGE); + request_irq(CEC_TMR_IDX, 2, cec_timer_isr, 0); + __this->time_id = sys_timer_add(NULL, cec_timer_loop, TIME_PRD); + g_printf("add timer %x", __this->time_id); +} + +void hdmi_cec_close(void) +{ + CEC_TMR->CON = BIT(14); + __this->cec_ok = 0; + + gpio_set_direction(TCFG_HDMI_CEC_PORT, 1); + gpio_set_pull_up(TCFG_HDMI_CEC_PORT, 0); + gpio_set_die(TCFG_HDMI_CEC_PORT, 0); + + g_printf("del timer %x", __this->time_id); + if (__this->time_id) { + sys_timer_del(__this->time_id); + __this->time_id = 0; + } + +} + +#endif + diff --git a/apps/soundbox/task_manager/spdif/spdif.c b/apps/soundbox/task_manager/spdif/spdif.c new file mode 100644 index 0000000..041a776 --- /dev/null +++ b/apps/soundbox/task_manager/spdif/spdif.c @@ -0,0 +1,233 @@ + +/************************************************************* + 此文件函数主要是spdif模式按键处理和事件处理 + + void app_spdif_task() + spdif模式主函数 + + static int spdif_sys_event_handler(struct sys_event *event) + spdif模式系统事件所有处理入口 + + static void spdif_task_close(void) + spdif模式退出 + +**************************************************************/ + + +#include "app_config.h" +#include "key_event_deal.h" +#include "system/includes.h" +#include "tone_player.h" +#include "app_task.h" +#include "tone_player.h" +#include "media/includes.h" +#include "asm/audio_spdif.h" +#include "clock_cfg.h" + +#include "ui/ui_api.h" +#include "ui_manage.h" + + +#if TCFG_APP_SPDIF_EN + +extern struct audio_spdif_hdl spdif_slave_hdl; +/* #define LOG_TAG_CONST APP_SPDIF */ +#define LOG_TAG "[APP_SPDIF]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + + +static u8 source = 0; + +///*----------------------------------------------------------------------------*/ +/**@brief spdif 硬件设置 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void spdif_open(void) +{ +#if TCFG_SPDIF_OUTPUT_ENABLE + spdif_slave_hdl.output_port = SPDIF_OUT_PORT_A;//PB11 +#endif + spdif_slave_hdl.input_port = SPDIF_IN_PORT_A;//PA9 + source = 0; + audio_spdif_slave_open(&spdif_slave_hdl); + + audio_spdif_slave_start(&spdif_slave_hdl); +#if TCFG_HDMI_ARC_ENABLE + extern void hdmi_cec_init(void); + hdmi_cec_init(); +#endif +} + + +///*----------------------------------------------------------------------------*/ +/**@brief spdif 模式初始化 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void spdif_app_init(void) +{ + extern void spdif_dec_init(void); + spdif_dec_init(); + ui_update_status(STATUS_SPDIF_MODE); + clock_idle(SPDIF_IDLE_CLOCK); + UI_SHOW_WINDOW(ID_WINDOW_SPDIF); + sys_key_event_enable(); + spdif_open(); +} + + +//*----------------------------------------------------------------------------*/ +/**@brief spdif 模式退出 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void spdif_task_close(void) +{ + UI_HIDE_CURR_WINDOW(); + audio_spdif_slave_close(&spdif_slave_hdl); + log_info("APP_SPDIF_STOP1\n"); + extern void spdif_dec_close(void); + spdif_dec_close(); +#if TCFG_HDMI_ARC_ENABLE + extern void hdmi_cec_close(void); + hdmi_cec_close(); +#endif +} + +//*----------------------------------------------------------------------------*/ +/**@brief spdif 输入io口设置 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void switch_spdif_input_port(void) +{ + source++; + if (source > 2) { + source = 0; + } + printf("\n--func=%s\n", __FUNCTION__); + switch (source) { + case 0: + audio_spdif_slave_switch_port(&spdif_slave_hdl, SPDIF_IN_PORT_A); + break; + case 1: + audio_spdif_slave_switch_port(&spdif_slave_hdl, SPDIF_IN_PORT_C); + break; + case 2: + audio_spdif_slave_switch_port(&spdif_slave_hdl, SPDIF_IN_PORT_D); + break; + default: + break; + } +} + +//*----------------------------------------------------------------------------*/ +/**@brief spdif 按键消息入口 + @param 无 + @return 1、消息已经处理,不需要发送到common 0、消息发送到common处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int spdif_key_event_opr(struct sys_event *event) +{ + int ret = true; + int err = 0; + + int key_event = event->u.key.event; + int key_value = event->u.key.value;// + + log_info("key_event:%d \n", key_event); + + switch (key_event) { + case KEY_SPDIF_SW_SOURCE: + log_info("KEY_SPDIF_SW_SOURCE \n"); + switch_spdif_input_port(); + break; + default : + ret = false; + break; + } + return ret; +} + +//*----------------------------------------------------------------------------*/ +/**@brief spdif 模式活跃状态 所有消息入口 + @param 无 + @return 1、当前消息已经处理,不需要发送comomon 0、当前消息不是linein处理的,发送到common统一处理 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int spdif_sys_event_handler(struct sys_event *event) +{ + switch (event->type) { + case SYS_KEY_EVENT: + return spdif_key_event_opr(event); + case SYS_DEVICE_EVENT: + return false; + default: + return false; + } + return false; +} + + +//*----------------------------------------------------------------------------*/ +/**@brief spdif 主任务 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void app_spdif_task() +{ + + int res; + int msg[32]; + spdif_app_init(); + while (1) { + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + if (spdif_sys_event_handler((struct sys_event *)(&msg[1])) == false) { + app_default_event_deal((struct sys_event *)(&msg[1])); //由common统一处理 + } + break; + default: + break; + } + + if (app_task_exitting()) { + spdif_task_close(); + return; + } + } +} + +#else + + +void app_spdif_task() +{ + +} + + + + +#endif diff --git a/apps/soundbox/task_manager/task_key.c b/apps/soundbox/task_manager/task_key.c new file mode 100644 index 0000000..d3a9bd1 --- /dev/null +++ b/apps/soundbox/task_manager/task_key.c @@ -0,0 +1,266 @@ +#include "key_event_deal.h" +#include "key_driver.h" +#include "app_config.h" +#include "board_config.h" +#include "app_task.h" + +//ad key +extern const u16 bt_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 music_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 fm_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 record_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 linein_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 rtc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 pc_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 spdif_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 idle_key_ad_table[KEY_AD_NUM_MAX][KEY_EVENT_MAX]; +/*********************************************************** + * adkey table 映射管理 + ***********************************************************/ +typedef const u16(*type_key_ad_table)[KEY_EVENT_MAX]; +static const type_key_ad_table ad_table[APP_TASK_MAX_INDEX] = { +#if TCFG_APP_BT_EN + [APP_BT_TASK] = bt_key_ad_table, +#endif +#if TCFG_APP_MUSIC_EN + [APP_MUSIC_TASK] = music_key_ad_table, +#endif +#if TCFG_APP_FM_EN + [APP_FM_TASK] = fm_key_ad_table, +#endif +#if TCFG_APP_RECORD_EN + [APP_RECORD_TASK] = record_key_ad_table, +#endif +#if TCFG_APP_LINEIN_EN + [APP_LINEIN_TASK] = linein_key_ad_table, +#endif +#if TCFG_APP_RTC_EN + [APP_RTC_TASK] = rtc_key_ad_table, +#endif +#if TCFG_APP_PC_EN + [APP_PC_TASK] = pc_key_ad_table, +#endif +#if TCFG_APP_SPDIF_EN + [APP_SPDIF_TASK] = spdif_key_ad_table, +#endif + [APP_IDLE_TASK] = idle_key_ad_table, +}; + +u16 adkey_event_to_msg(u8 cur_task, struct key_event *key) +{ + if (ad_table[cur_task] == NULL) { + return KEY_NULL; + } + + type_key_ad_table cur_task_ad_table = ad_table[cur_task]; + return cur_task_ad_table[key->value][key->event]; +} + +//io key +extern const u16 bt_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 music_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 fm_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 record_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 linein_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 rtc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 pc_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 spdif_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 idle_key_io_table[KEY_IO_NUM_MAX][KEY_EVENT_MAX]; +/*********************************************************** + * iokey table 映射管理 + ***********************************************************/ +typedef const u16(*type_key_io_table)[KEY_EVENT_MAX]; +static const type_key_io_table io_table[APP_TASK_MAX_INDEX] = { +#if TCFG_APP_BT_EN + [APP_BT_TASK] = bt_key_io_table, +#endif +#if TCFG_APP_MUSIC_EN + [APP_MUSIC_TASK] = music_key_io_table, +#endif +#if TCFG_APP_FM_EN + [APP_FM_TASK] = fm_key_io_table, +#endif +#if TCFG_APP_RECORD_EN + [APP_RECORD_TASK] = record_key_io_table, +#endif +#if TCFG_APP_LINEIN_EN + [APP_LINEIN_TASK] = linein_key_io_table, +#endif +#if TCFG_APP_RTC_EN + [APP_RTC_TASK] = rtc_key_io_table, +#endif +#if TCFG_APP_PC_EN + [APP_PC_TASK] = pc_key_io_table, +#endif +#if TCFG_APP_SPDIF_EN + [APP_SPDIF_TASK] = spdif_key_io_table, +#endif + [APP_IDLE_TASK] = idle_key_io_table, +}; + +u16 iokey_event_to_msg(u8 cur_task, struct key_event *key) +{ + if (io_table[cur_task] == NULL) { + return KEY_NULL; + } + + type_key_io_table cur_task_io_table = io_table[cur_task]; + return cur_task_io_table[key->value][key->event]; +} + +//ir key +extern const u16 bt_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 music_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 fm_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 record_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 linein_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 rtc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 pc_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 spdif_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 idle_key_ir_table[KEY_IR_NUM_MAX][KEY_EVENT_MAX]; +/*********************************************************** + * irkey table 映射管理 + ***********************************************************/ +typedef const u16(*type_key_ir_table)[KEY_EVENT_MAX]; +static const type_key_ir_table ir_table[APP_TASK_MAX_INDEX] = { +#if TCFG_APP_BT_EN + [APP_BT_TASK] = bt_key_ir_table, +#endif +#if TCFG_APP_MUSIC_EN + [APP_MUSIC_TASK] = music_key_ir_table, +#endif +#if TCFG_APP_FM_EN + [APP_FM_TASK] = fm_key_ir_table, +#endif +#if TCFG_APP_RECORD_EN + [APP_RECORD_TASK] = record_key_ir_table, +#endif +#if TCFG_APP_LINEIN_EN + [APP_LINEIN_TASK] = linein_key_ir_table, +#endif +#if TCFG_APP_RTC_EN + [APP_RTC_TASK] = rtc_key_ir_table, +#endif +#if TCFG_APP_PC_EN + [APP_PC_TASK] = pc_key_ir_table, +#endif +#if TCFG_APP_SPDIF_EN + [APP_SPDIF_TASK] = spdif_key_ir_table, +#endif + [APP_IDLE_TASK] = idle_key_ir_table, +}; + +u16 irkey_event_to_msg(u8 cur_task, struct key_event *key) +{ + if (ir_table[cur_task] == NULL) { + return KEY_NULL; + } + + type_key_ir_table cur_task_ir_table = ir_table[cur_task]; + return cur_task_ir_table[key->value][key->event]; +} + +//rdec key +extern const u16 bt_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 music_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 fm_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 record_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 linein_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 rtc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 pc_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 spdif_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 idle_key_rdec_table[KEY_RDEC_NUM_MAX][KEY_EVENT_MAX]; + +/*********************************************************** + * rdec_key table 映射管理 + ***********************************************************/ +typedef const u16(*type_key_rdec_table)[KEY_EVENT_MAX]; +static const type_key_rdec_table rdec_table[APP_TASK_MAX_INDEX] = { +#if TCFG_APP_BT_EN + [APP_BT_TASK] = bt_key_rdec_table, +#endif +#if TCFG_APP_MUSIC_EN + [APP_MUSIC_TASK] = music_key_rdec_table, +#endif +#if TCFG_APP_FM_EN + [APP_FM_TASK] = fm_key_rdec_table, +#endif +#if TCFG_APP_RECORD_EN + [APP_RECORD_TASK] = record_key_rdec_table, +#endif +#if TCFG_APP_LINEIN_EN + [APP_LINEIN_TASK] = linein_key_rdec_table, +#endif +#if TCFG_APP_RTC_EN + [APP_RTC_TASK] = rtc_key_rdec_table, +#endif +#if TCFG_APP_PC_EN + [APP_PC_TASK] = pc_key_rdec_table, +#endif +#if TCFG_APP_SPDIF_EN + [APP_SPDIF_TASK] = spdif_key_rdec_table, +#endif + [APP_IDLE_TASK] = idle_key_rdec_table, +}; + +u16 rdec_key_event_to_msg(u8 cur_task, struct key_event *key) +{ + if (rdec_table[cur_task] == NULL) { + return KEY_NULL; + } + + type_key_rdec_table cur_task_rdec_table = rdec_table[cur_task]; + return cur_task_rdec_table[key->value][key->event]; +} + +//touch key +extern const u16 bt_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 music_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 fm_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 record_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 linein_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 rtc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 pc_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 spdif_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX]; +extern const u16 idle_key_touch_table[KEY_TOUCH_NUM_MAX][KEY_EVENT_MAX]; +/*********************************************************** + * touch_key table 映射管理 + ***********************************************************/ +typedef const u16(*type_key_touch_table)[KEY_EVENT_MAX]; +static const type_key_touch_table touch_table[APP_TASK_MAX_INDEX] = { +#if TCFG_APP_BT_EN + [APP_BT_TASK] = bt_key_touch_table, +#endif +#if TCFG_APP_MUSIC_EN + [APP_MUSIC_TASK] = music_key_touch_table, +#endif +#if TCFG_APP_FM_EN + [APP_FM_TASK] = fm_key_touch_table, +#endif +#if TCFG_APP_RECORD_EN + [APP_RECORD_TASK] = record_key_touch_table, +#endif +#if TCFG_APP_LINEIN_EN + [APP_LINEIN_TASK] = linein_key_touch_table, +#endif +#if TCFG_APP_RTC_EN + [APP_RTC_TASK] = rtc_key_touch_table, +#endif +#if TCFG_APP_PC_EN + [APP_PC_TASK] = pc_key_touch_table, +#endif +#if TCFG_APP_SPDIF_EN + [APP_SPDIF_TASK] = spdif_key_touch_table, +#endif + [APP_IDLE_TASK] = idle_key_touch_table, +}; + +u16 touch_key_event_to_msg(u8 cur_task, struct key_event *key) +{ + if (touch_table[cur_task] == NULL) { + return KEY_NULL; + } + + type_key_touch_table cur_task_touch_table = touch_table[cur_task]; + return cur_task_touch_table[key->value][key->event]; +} diff --git a/apps/soundbox/third_party_profile/ancs_client_demo/ancs_client_demo.c b/apps/soundbox/third_party_profile/ancs_client_demo/ancs_client_demo.c new file mode 100644 index 0000000..08f46e8 --- /dev/null +++ b/apps/soundbox/third_party_profile/ancs_client_demo/ancs_client_demo.c @@ -0,0 +1,188 @@ +#include "app_config.h" + +#include "btstack/avctp_user.h" +#include "btstack/btstack_task.h" +#include "bt_tws.h" +#include "app_main.h" +#include "event.h" +#include "3th_profile_api.h" +#include "spp_user.h" + +#if ANCS_CLIENT_EN + +#define LOG_TAG "[ANCS_CLIENT_DEMO]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +void ble_app_disconnect(void); +void bt_ble_adv_enable(u8 enable); + +int ancs_data_bt_state_set_page_scan_enable() +{ + return 0; +} + +int ancs_data_bt_state_get_connect_mac_addr() +{ + return 0; +} + +int ancs_data_bt_state_cancel_page_scan() +{ + return 0; +} + +int ancs_data_bt_state_tws_init(int paired) +{ + return 0; +} + +int ancs_data_bt_state_tws_connected(int first_pair, u8 *comm_addr) +{ + if (first_pair) { + extern void ble_module_enable(u8 en); + extern void bt_update_mac_addr(u8 * addr); + extern void lib_make_ble_address(u8 * ble_address, u8 * edr_address); + /* bt_ble_adv_enable(0); */ + u8 tmp_ble_addr[6] = {0}; + lib_make_ble_address(tmp_ble_addr, comm_addr); + le_controller_set_mac(tmp_ble_addr);//将ble广播地址改成公共地址 + bt_update_mac_addr(comm_addr); + /* bt_ble_adv_enable(1); */ + + + /*新的连接,公共地址改变了,要重新将新的地址广播出去*/ + if (tws_api_get_role() == TWS_ROLE_MASTER) { + printf("\nNew Connect Master!!!\n\n"); + ble_app_disconnect(); + bt_ble_adv_enable(0); + bt_ble_adv_enable(1); + } else { + printf("\nConnect Slave!!!\n\n"); + /*从机ble关掉*/ + ble_app_disconnect(); + bt_ble_adv_enable(0); + } + } + + return 0; +} + +int ancs_data_bt_state_enter_soft_poweroff() +{ + extern void bt_ble_exit(void); + bt_ble_exit(); + return 0; +} + +int ancs_data_bt_status_event_handler(struct bt_event *bt) +{ + return 0; +} + + +int ancs_data_hci_event_handler(struct bt_event *bt) +{ + + return 0; +} + +void ancs_data_bt_tws_event_handler(struct bt_event *bt) +{ + int role = bt->args[0]; + int phone_link_connection = bt->args[1]; + int reason = bt->args[2]; + + switch (bt->event) { + case TWS_EVENT_CONNECTED: + //bt_ble_adv_enable(1); + if (tws_api_get_role() == TWS_ROLE_SLAVE) { + //master enable + printf("\nConnect Slave!!!\n\n"); + /*从机ble关掉*/ + ble_app_disconnect(); + bt_ble_adv_enable(0); + } + + break; + case TWS_EVENT_PHONE_LINK_DETACH: + /* + * 跟手机的链路LMP层已完全断开, 只有tws在连接状态才会收到此事件 + */ + break; + case TWS_EVENT_CONNECTION_DETACH: + /* + * TWS连接断开 + */ + if (app_var.goto_poweroff_flag) { + break; + } + if (get_app_connect_type() == 0) { + printf("\ntws detach to open ble~~~\n\n"); + bt_ble_adv_enable(1); + } + set_ble_connect_type(TYPE_NULL); + + break; + case TWS_EVENT_SYNC_FUN_CMD: + break; + case TWS_EVENT_ROLE_SWITCH: + break; + } + +#if OTA_TWS_SAME_TIME_ENABLE + tws_ota_app_event_deal(bt->event); +#endif +} + +int ancs_data_sys_event_handler_specific(struct sys_event *event) +{ + return 0; +} + +int user_spp_state_specific(u8 packet_type) +{ + + switch (packet_type) { + case 1: + ble_app_disconnect(); + bt_ble_adv_enable(0); + set_app_connect_type(TYPE_SPP); + break; + case 2: + + set_app_connect_type(TYPE_NULL); + +#if TCFG_USER_TWS_ENABLE + if (!(tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED)) { + ble_module_enable(1); + } else { + if (tws_api_get_role() == TWS_ROLE_MASTER) { + ble_module_enable(1); + } + } +#else + ble_module_enable(1); +#endif + + break; + } + return 0; +} + + +int ancs_data_bt_state_init() +{ + + return 0; +} + + + + + +#endif diff --git a/apps/soundbox/third_party_profile/app_protocol_deal.c b/apps/soundbox/third_party_profile/app_protocol_deal.c new file mode 100644 index 0000000..fd26a07 --- /dev/null +++ b/apps/soundbox/third_party_profile/app_protocol_deal.c @@ -0,0 +1,100 @@ +#include +#include +#include + +#include "app_protocol_api.h" +#include "tone_player.h" +#include "clock_cfg.h" +#include "key_event_deal.h" +#include "bt.h" +#include "app_config.h" +#include "app_main.h" + +#if AI_APP_PROTOCOL + +#if 1 +#define APP_PROTOCOL_LOG printf +#define APP_PROTOCOL_DUMP put_buf +#else +#define APP_PROTOCOL_LOG(...) +#define APP_PROTOCOL_DUMP(...) +#endif + + +int get_bt_tws_connect_status(); + +void mic_rec_clock_set(void) +{ + clock_add_set(AI_SPEECH_CLK); +} + +void mic_rec_clock_recover(void) +{ + clock_remove_set(AI_SPEECH_CLK); +} + +static void tone_play_in_app_core(int index) +{ + tone_play_with_callback_by_name(app_protocol_get_tone(index), 1, app_speech_tone_play_end_callback, (void *)index); +} + +void app_protocol_tone_play(int index, int tws_sync) +{ + if (app_var.goto_poweroff_flag) { + APP_PROTOCOL_LOG("shutdown don't play tone:%d\n", index); + return; + } +#if TCFG_APP_BT_EN + if (app_bt_hdl.ignore_discon_tone) { +#if (TCFG_BLUETOOTH_BACK_MODE == 0) + APP_PROTOCOL_LOG("ingore discon tone:%d\n", index); + return; +#endif + } +#endif +#if TCFG_USER_TWS_ENABLE + if (tws_sync && get_bt_tws_connect_status()) { + APP_PROTOCOL_LOG("tws_sync play index:%d\n", index); + app_protocol_tws_sync_send(APP_PROTOCOL_SYNC_TONE, index); + return; + } +#endif +#if TCFG_APP_BT_EN + bt_drop_a2dp_frame_start(); //蓝牙播提示音,丢A2DP数据防止a2dp buf阻塞 +#endif + if (strcmp(os_current_task(), "app_core")) { + APP_PROTOCOL_LOG("tone play in app core index:%d\n", index); + app_protocol_post_app_core_callback((int)tone_play_in_app_core, (void *)index); //提示音放到app_core播放 + } else { + APP_PROTOCOL_LOG("tone play index:%d\n", index); + tone_play_with_callback_by_name(app_protocol_get_tone(index), 1, app_speech_tone_play_end_callback, (void *)index); + } +} + +extern u8 get_call_status(); +int app_protocol_key_event_handler(struct sys_event *event) +{ + int ret = false; + struct key_event *key = &event->u.key; + int key_event = event->u.key.event; + switch (key_event) { +#if APP_PROTOCOL_SPEECH_EN + case KEY_SEND_SPEECH_START: + if (get_call_status() != 5) { + printf("phone is using, no speech allow\n"); + return ret; + } + APP_PROTOCOL_LOG("KEY_SEND_SPEECH_START \n"); + app_protocol_start_speech_by_key(event); + break; + case KEY_SEND_SPEECH_STOP: + APP_PROTOCOL_LOG("KEY_SEND_SPEECH_STOP \n"); + app_protocol_stop_speech_by_key(); + break; +#endif + } + return ret; +} + +#endif + diff --git a/apps/soundbox/third_party_profile/trans_data_demo/trans_data_demo.c b/apps/soundbox/third_party_profile/trans_data_demo/trans_data_demo.c new file mode 100644 index 0000000..17303ac --- /dev/null +++ b/apps/soundbox/third_party_profile/trans_data_demo/trans_data_demo.c @@ -0,0 +1,195 @@ +#include "app_config.h" + +#include "btstack/avctp_user.h" +#include "btstack/btstack_task.h" +#include "bt_tws.h" +#include "app_main.h" +#include "event.h" +#include "spp_trans_data.h" +#include "3th_profile_api.h" +#include "spp_user.h" +#include "bt_common.h" + +#if TRANS_DATA_EN + +#define LOG_TAG "[TRANS_DATA]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +int trans_data_bt_state_set_page_scan_enable() +{ + return 0; +} + +int trans_data_bt_state_get_connect_mac_addr() +{ + return 0; +} + +int trans_data_bt_state_cancel_page_scan() +{ + return 0; +} + +int trans_data_bt_state_tws_init(int paired) +{ + return 0; +} + +int trans_data_bt_state_tws_connected(int first_pair, u8 *comm_addr) +{ + if (first_pair) { + extern void ble_module_enable(u8 en); + extern void bt_update_mac_addr(u8 * addr); + extern void lib_make_ble_address(u8 * ble_address, u8 * edr_address); + /* bt_ble_adv_enable(0); */ + u8 tmp_ble_addr[6] = {0}; + lib_make_ble_address(tmp_ble_addr, comm_addr); + le_controller_set_mac(tmp_ble_addr);//将ble广播地址改成公共地址 + bt_update_mac_addr(comm_addr); + /* bt_ble_adv_enable(1); */ + + + /*新的连接,公共地址改变了,要重新将新的地址广播出去*/ + if (tws_api_get_role() == TWS_ROLE_MASTER) { + printf("\nNew Connect Master!!!\n\n"); + ble_app_disconnect(); + bt_ble_adv_enable(0); + bt_ble_adv_enable(1); + } else { + printf("\nConnect Slave!!!\n\n"); + /*从机ble关掉*/ + ble_app_disconnect(); + bt_ble_adv_enable(0); + } + } + + return 0; +} + +void gma_app_bredr_handle_reg(void) +{ + spp_data_deal_handle_register(user_spp_data_handler); +} + +int trans_data_bt_state_enter_soft_poweroff() +{ + extern void bt_ble_exit(void); + bt_ble_exit(); + return 0; +} + +int trans_data_bt_status_event_handler(struct bt_event *bt) +{ + return 0; +} + + +int trans_data_hci_event_handler(struct bt_event *bt) +{ + + return 0; +} + +void trans_data_bt_tws_event_handler(struct bt_event *bt) +{ + int role = bt->args[0]; + int phone_link_connection = bt->args[1]; + int reason = bt->args[2]; + + switch (bt->event) { + case TWS_EVENT_CONNECTED: + //bt_ble_adv_enable(1); + if (tws_api_get_role() == TWS_ROLE_SLAVE) { + //master enable + printf("\nConnect Slave!!!\n\n"); + /*从机ble关掉*/ + ble_app_disconnect(); + bt_ble_adv_enable(0); + } + + break; + case TWS_EVENT_PHONE_LINK_DETACH: + /* + * 跟手机的链路LMP层已完全断开, 只有tws在连接状态才会收到此事件 + */ + break; + case TWS_EVENT_CONNECTION_DETACH: + /* + * TWS连接断开 + */ + if (app_var.goto_poweroff_flag) { + break; + } + if (get_app_connect_type() == 0) { + printf("\ntws detach to open ble~~~\n\n"); + bt_ble_adv_enable(1); + } + set_ble_connect_type(TYPE_NULL); + + break; + case TWS_EVENT_SYNC_FUN_CMD: + break; + case TWS_EVENT_ROLE_SWITCH: + break; + } + +#if OTA_TWS_SAME_TIME_ENABLE + tws_ota_app_event_deal(bt->event); +#endif +} + +int trans_data_sys_event_handler_specific(struct sys_event *event) +{ + return 0; +} + +int user_spp_state_specific(u8 packet_type) +{ + + switch (packet_type) { + case 1: + ble_app_disconnect(); + bt_ble_adv_enable(0); + set_app_connect_type(TYPE_SPP); + break; + case 2: + + set_app_connect_type(TYPE_NULL); + +#if TCFG_USER_TWS_ENABLE + if (!(tws_api_get_tws_state() & TWS_STA_SIBLING_CONNECTED)) { + ble_module_enable(1); + } else { + if (tws_api_get_role() == TWS_ROLE_MASTER) { + ble_module_enable(1); + } + } +#else + ble_module_enable(1); +#endif + + break; + } + return 0; +} + + +int trans_data_bt_state_init() +{ + transport_spp_init(); + spp_data_deal_handle_register(user_spp_data_handler); + + return 0; +} + + + + + +#endif diff --git a/apps/soundbox/ui/color_led/color_led_app.c b/apps/soundbox/ui/color_led/color_led_app.c new file mode 100644 index 0000000..b5c6765 --- /dev/null +++ b/apps/soundbox/ui/color_led/color_led_app.c @@ -0,0 +1,333 @@ +#include "system/includes.h" +#include "app_config.h" +#include "user_cfg.h" +#include "color_led_app.h" +#include "color_led_table.h" +#include "music_player.h" + +#if TCFG_COLORLED_ENABLE +#define LOG_TAG_CONST COLOR_LED +#define LOG_TAG "[COLOR_LED]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#if AUDIO_OUTPUT_AUTOMUTE +static void audio_dac_energy_scan(void *priv); +static u8 color_led_dac_energy_to_fre(int energy); +int audio_dac_energy_get(void); + +#define TWINKLE_MUSIC_TIME 500 +#endif + +typedef struct { + u8 cur_mode; + u32 cur_color; + int cur_fremode; + u32 music_twinkle_timer_hdl; + u32 colorful_twinkle_pause_color; +} color_led_app_t; +static color_led_app_t color_led_app; +#define __this (&color_led_app) + +#define CPU_ENTER_CRITICAL() local_irq_disable() +#define CPU_EXIT_CRITICAL() local_irq_enable() +static color_cell_t color_table_space[4]; +COLOR_TABLE_REGISTER(color_table_space); + +static void led_select(u32 led_io) +{ +// log_info("led_io:%x",led_io); +} + +static void colorful_twinkle_color_cb(u32 color) +{ + if (color == COLOR_BLACK) { + return; + } + + __this->colorful_twinkle_pause_color = color; +// log_info("led_io:%x",led_io); +} +static void color_led_colorful_twinkle_deal(u8 fre_mode) +{ + switch (fre_mode) { + case TWINKLE_SLOW: + COLOR_LED_SET(color_table_colorful_twinkle_slow, colorful_twinkle_color_cb); + log_info("colorful twinkle scale slow \n"); + break; + case TWINKLE_MID: + COLOR_LED_SET(color_table_colorful_twinkle_mid, colorful_twinkle_color_cb); + log_info("colorful twinkle scale middle \n"); + break; + case TWINKLE_FAST: + COLOR_LED_SET(color_table_colorful_twinkle_fast, colorful_twinkle_color_cb); + log_info("colorful twinkle scale fast \n"); + break; + case TWINKLE_FOLLOW_MUSIC: +#if AUDIO_OUTPUT_AUTOMUTE + __this->cur_mode = COLOR_LED_MODE_COLORFUL_TWINKLE; + __this->cur_fremode = (-1); + __this->music_twinkle_timer_hdl = sys_hi_timer_add(__this, audio_dac_energy_scan, TWINKLE_MUSIC_TIME); + return; +#endif + break; + case TWINKLE_PAUSE: + if (__this->colorful_twinkle_pause_color == 0) { + __this->colorful_twinkle_pause_color = COLOR_GREEN; + } + CPU_ENTER_CRITICAL(); + memcpy((u8 *)color_table_space, (u8 *)color_table_light_base, color_table_light_base_size * sizeof(color_cell_t)); + color_table_space[0].show_time = 0; + color_table_space[0].type_action.color.color = __this->colorful_twinkle_pause_color; + COLOR_LED_SET(color_table_space, led_select); + CPU_EXIT_CRITICAL(); + log_info("colorful twinkle scale pause \n"); + return; + break; + default: + break; + } +} + +static void color_led_color_twinkle_deal(u8 fre_mode, u32 color) +{ + if (sizeof(color_table_space) < color_table_twinkle_base_size * sizeof(color_cell_t)) { + log_info("space no enough \n"); + return; + } + + u32 fre = 0; + switch (fre_mode) { + case TWINKLE_SLOW: + fre = TWINKLE_SLOW_FRE; + log_info("twinkle scale slow \n"); + break; + case TWINKLE_MID: + fre = TWINKLE_MID_FRE; + log_info("twinkle scale middle \n"); + break; + case TWINKLE_FAST: + fre = TWINKLE_FAST_FRE; + log_info("twinkle scale fast \n"); + break; + + case TWINKLE_FOLLOW_MUSIC: +#if AUDIO_OUTPUT_AUTOMUTE + __this->cur_mode = COLOR_LED_MODE_TWINKLE; + __this->cur_color = color; + __this->cur_fremode = (-1); + __this->music_twinkle_timer_hdl = sys_hi_timer_add(__this, audio_dac_energy_scan, TWINKLE_MUSIC_TIME); + return; +#endif + break; + case TWINKLE_PAUSE: + fre = 0; + log_info("twinkle scale pause \n"); + break; + default: + fre = TWINKLE_SLOW_FRE; + break; + } + + CPU_ENTER_CRITICAL(); + memcpy((u8 *)color_table_space, (u8 *)color_table_twinkle_base, color_table_twinkle_base_size * sizeof(color_cell_t)); + color_table_space[0].show_time = fre; + color_table_space[0].type_action.color.color = color; + color_table_space[1].show_time = fre; + COLOR_LED_SET(color_table_space, led_select); + CPU_EXIT_CRITICAL(); + +} + +static void color_led_color_light_deal(u32 color) +{ + if (sizeof(color_table_space) < color_table_light_base_size * sizeof(color_cell_t)) { + log_info("space no enough \n"); + return; + } + + CPU_ENTER_CRITICAL(); + memcpy((u8 *)color_table_space, (u8 *)color_table_light_base, color_table_light_base_size * sizeof(color_cell_t)); + color_table_space[0].show_time = 0; + color_table_space[0].type_action.color.color = color; + COLOR_LED_SET(color_table_space, led_select); + CPU_EXIT_CRITICAL(); + +} + +static void color_led_follow_music_deal(u8 fre_mode) +{ + switch (fre_mode) { + case TWINKLE_SLOW: + COLOR_LED_SET(color_table_green_breath, led_select); + log_info("colorful twinkle scale slow \n"); + break; + case TWINKLE_MID: + COLOR_LED_SET(color_table_blue_breath, led_select); + log_info("colorful twinkle scale middle \n"); + break; + case TWINKLE_FAST: + COLOR_LED_SET(color_table_red_breath, led_select); + log_info("colorful twinkle scale fast \n"); + break; + case TWINKLE_FOLLOW_MUSIC: +#if AUDIO_OUTPUT_AUTOMUTE + __this->cur_mode = COLOR_LED_MODE_FOLLOW_MUSIC; + __this->cur_fremode = (-1); + __this->music_twinkle_timer_hdl = sys_hi_timer_add(__this, audio_dac_energy_scan, TWINKLE_MUSIC_TIME); + return; +#endif + break; + case TWINKLE_PAUSE: + COLOR_LED_SET(color_table_green_breath, led_select); + log_info("colorful twinkle scale pause \n"); + break; + default: + break; + } +} +int color_led_set_api(u8 mode, u8 fre_mode, u32 color) +{ + if (__this->music_twinkle_timer_hdl) { + sys_hi_timer_del(__this->music_twinkle_timer_hdl); + __this->music_twinkle_timer_hdl = 0; + } + + switch (mode) { + case COLOR_LED_MODE_SUNSET: + COLOR_LED_SET(color_table_sunset, led_select); + break; + case COLOR_LED_MODE_NICE_EMOTION: + COLOR_LED_SET(color_table_nice_emotion, led_select); + break; + case COLOR_LED_MODE_BLUE_BREATH: + COLOR_LED_SET(color_table_blue_breath, led_select); + break; + case COLOR_LED_MODE_GREEN_BREATH: + COLOR_LED_SET(color_table_green_breath, led_select); + break; + case COLOR_LED_MODE_RED_BREATH: + COLOR_LED_SET(color_table_red_breath, led_select); + break; + case COLOR_LED_MODE_WANDERFUL_BREATH: + COLOR_LED_SET(color_table_wonderful_breath, led_select); + break; + case COLOR_LED_MODE_NIGHTLIGNT: + COLOR_LED_SET(color_table_nightlight, led_select); + break; + case COLOR_LED_MODE_CANDLELIGHT: + COLOR_LED_SET(color_table_candlelight, led_select); + break; + case COLOR_LED_MODE_HEARTBEAT: + COLOR_LED_SET(color_table_heartbeat, led_select); + break; + case COLOR_LED_MODE_RAINBOW: + COLOR_LED_SET(color_table_rainbow, led_select); + break; + case COLOR_LED_MODE_COLORFUL_TWINKLE: + color_led_colorful_twinkle_deal(fre_mode); + break; + case COLOR_LED_MODE_TWINKLE: + color_led_color_twinkle_deal(fre_mode, color); + break; + case COLOR_LED_MODE_LIGHT: + color_led_color_light_deal(color); + break; + case COLOR_LED_MODE_FOLLOW_MUSIC: + color_led_follow_music_deal(TWINKLE_FOLLOW_MUSIC); + break; + case COLOR_LED_MODE_STAGE: + COLOR_LED_SET(color_table_stage, led_select); + break; + default: + return (-1); + break; + + } + + return 0; +} + +#if AUDIO_OUTPUT_AUTOMUTE +static u8 color_led_dac_energy_to_fremode(int energy) +{ + if (energy < 0) { + energy = 0; + } + + switch (energy) { + case 0: + return TWINKLE_PAUSE; + break; + case 1 ... TWINKLE_SLOW_THRESHOLD: + return TWINKLE_SLOW; + break; + case (TWINKLE_SLOW_THRESHOLD+1) ... TWINKLE_MID_THRESHOLD: + return TWINKLE_MID; + break; + default: + return TWINKLE_FAST; + break; + } + return 1; +} + +static void audio_dac_energy_scan(void *priv) +{ + color_led_app_t *hdl = priv; + if (hdl == NULL) { + return; + } + int energy = audio_dac_energy_get(); + if (energy < 0) { + putchar('e'); + energy = 0; + } +// printf("energy:%d \n",energy); + u8 fre_mode = color_led_dac_energy_to_fremode(energy); + if (fre_mode == hdl->cur_fremode) { + return; + } + hdl->cur_fremode = fre_mode; + + switch (hdl->cur_mode) { + case COLOR_LED_MODE_COLORFUL_TWINKLE: + color_led_colorful_twinkle_deal(hdl->cur_fremode); + break; + case COLOR_LED_MODE_TWINKLE: + color_led_color_twinkle_deal(hdl->cur_fremode, hdl->cur_color); + break; + case COLOR_LED_MODE_FOLLOW_MUSIC: + color_led_follow_music_deal(hdl->cur_fremode); + break; + default: + return; + break; + + } +} +#endif + +void color_led_init(void *data) +{ + log_info("color_led_init \n"); + const colorled_platform_data *cfg_data = (const colorled_platform_data *)data; + COLOR_LED_IO_SET(cfg_data); + +// color_led_set_api(COLOR_LED_MODE_LIGHT, TWINKLE_SLOW, 0x00ff0000); +} +#else +void color_led_init(void *data) +{ + +} + +int color_led_set_api(u8 mode, u8 fre_mode, u32 color) +{ + return 0; +} +#endif diff --git a/apps/soundbox/ui/color_led/color_led_table.c b/apps/soundbox/ui/color_led/color_led_table.c new file mode 100644 index 0000000..41e1165 --- /dev/null +++ b/apps/soundbox/ui/color_led/color_led_table.c @@ -0,0 +1,240 @@ +#include "system/includes.h" +#include "app_config.h" +#include "user_cfg.h" +#include "color_led_app.h" +#include "color_led_table.h" + +const color_cell_t color_table_demo1[] = { + COLOR_TYPE_COLOR_INIT(0, 300, COLOR_RED), + COLOR_TYPE_BREATH_INIT(0, 0, 0x00003000, BREATH_RGB_SEL(0, GREEN_EN, 0), BREATH_RGB_DIR_UP(0, 0, 0), 10, 1, 0x10, 0xff), + + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_demo1); + +/*stage*/ +const color_cell_t color_table_stage[] = { + COLOR_TYPE_COLOR_INIT(0, 300, COLOR_RED), + COLOR_TYPE_BREATH_MEASURE_BY_STEP_INIT(0, 0xef, 0x00003000, BREATH_RGB_SEL(0, GREEN_EN, 0), BREATH_RGB_DIR_UP(0, 0, 0), 5, 1, 0x10, 0xff), + COLOR_TYPE_BREATH_MEASURE_BY_STEP_INIT(0, 0xef, 0x00300000, BREATH_RGB_SEL(BLUE_EN, 0, 0), BREATH_RGB_DIR_UP(0, 0, 0), 5, 1, 0x10, 0xff), + COLOR_TYPE_COLOR_INIT(0, TWINKLE_FAST_FRE, COLOR_RED), + COLOR_TYPE_COLOR_INIT(0, TWINKLE_FAST_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(0, TWINKLE_FAST_FRE, COLOR_ORANGE), + COLOR_TYPE_COLOR_INIT(0, TWINKLE_FAST_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(0, TWINKLE_FAST_FRE, COLOR_YELLOW), + COLOR_TYPE_COLOR_INIT(0, TWINKLE_FAST_FRE, COLOR_BLACK), + COLOR_TYPE_BREATH_MEASURE_BY_STEP_INIT(0, 0xff, 0x000000ff, BREATH_RGB_SEL(RED_EN, GREEN_EN, 0), BREATH_RGB_DIR_UP(0, GREEN_EN, 0), 20, 1, 0x00, 0xff), + COLOR_TYPE_COLOR_INIT(0, TWINKLE_FAST_FRE, COLOR_GREEN), + COLOR_TYPE_COLOR_INIT(0, TWINKLE_FAST_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(0, TWINKLE_FAST_FRE, COLOR_CYAN), + COLOR_TYPE_COLOR_INIT(0, TWINKLE_FAST_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(0, TWINKLE_FAST_FRE, COLOR_BLUE), + COLOR_TYPE_COLOR_INIT(0, TWINKLE_FAST_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(0, TWINKLE_FAST_FRE, COLOR_PURPLE), + COLOR_TYPE_COLOR_INIT(0, TWINKLE_FAST_FRE, COLOR_BLACK), + + COLOR_TYPE_BREATH_INIT(0, 2000, 0x0aa3030, BREATH_RGB_SEL(RED_EN, GREEN_EN, BLUE_EN), BREATH_RGB_DIR_UP(RED_EN, 0, 0), 20, 1, 0x10, 0xff), + COLOR_TYPE_LOOP_INIT(0/*back to step zero*/, 0xffffffff), + + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_stage); + +/*light*/ +const color_cell_t color_table_light_base[] = { + COLOR_TYPE_COLOR_INIT(0, 0, COLOR_RED), + + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_light_base); + +/*colorful twinkle base*/ +const color_cell_t color_table_twinkle_base[] = { + COLOR_TYPE_COLOR_INIT(0, TWINKLE_SLOW_FRE, COLOR_RED), + COLOR_TYPE_COLOR_INIT(0, TWINKLE_SLOW_FRE, COLOR_BLACK), + + COLOR_TYPE_LOOP_INIT(0/*back to step zero*/, 0xffffffff), + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_twinkle_base); + +/*colorful twinkle slow*/ +const color_cell_t color_table_colorful_twinkle_slow[] = { + COLOR_TYPE_COLOR_INIT(COLOR_RED , TWINKLE_SLOW_FRE, COLOR_RED), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_SLOW_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_ORANGE , TWINKLE_SLOW_FRE, COLOR_ORANGE), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_SLOW_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_YELLOW , TWINKLE_SLOW_FRE, COLOR_YELLOW), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_SLOW_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_GREEN , TWINKLE_SLOW_FRE, COLOR_GREEN), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_SLOW_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_CYAN , TWINKLE_SLOW_FRE, COLOR_CYAN), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_SLOW_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_BLUE , TWINKLE_SLOW_FRE, COLOR_BLUE), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_SLOW_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_PURPLE , TWINKLE_SLOW_FRE, COLOR_PURPLE), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_SLOW_FRE, COLOR_BLACK), + + COLOR_TYPE_LOOP_INIT(0/*back to step zero*/, 0xffffffff), + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_colorful_twinkle_slow); + +/*colorful twinkle middle*/ +const color_cell_t color_table_colorful_twinkle_mid[] = { + COLOR_TYPE_COLOR_INIT(COLOR_RED , TWINKLE_MID_FRE, COLOR_RED), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_MID_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_ORANGE , TWINKLE_MID_FRE, COLOR_ORANGE), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_MID_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_YELLOW , TWINKLE_MID_FRE, COLOR_YELLOW), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_MID_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_GREEN , TWINKLE_MID_FRE, COLOR_GREEN), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_MID_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_CYAN , TWINKLE_MID_FRE, COLOR_CYAN), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_MID_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_BLUE , TWINKLE_MID_FRE, COLOR_BLUE), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_MID_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_PURPLE , TWINKLE_MID_FRE, COLOR_PURPLE), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_MID_FRE, COLOR_BLACK), + + COLOR_TYPE_LOOP_INIT(0/*back to step zero*/, 0xffffffff), + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_colorful_twinkle_mid); + +/*colorful twinkle fast*/ +const color_cell_t color_table_colorful_twinkle_fast[] = { + COLOR_TYPE_COLOR_INIT(COLOR_RED , TWINKLE_FAST_FRE, COLOR_RED), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_FAST_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_ORANGE , TWINKLE_FAST_FRE, COLOR_ORANGE), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_FAST_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_YELLOW , TWINKLE_FAST_FRE, COLOR_YELLOW), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_FAST_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_GREEN , TWINKLE_FAST_FRE, COLOR_GREEN), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_FAST_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_CYAN , TWINKLE_FAST_FRE, COLOR_CYAN), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_FAST_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_BLUE , TWINKLE_FAST_FRE, COLOR_BLUE), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_FAST_FRE, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(COLOR_PURPLE , TWINKLE_FAST_FRE, COLOR_PURPLE), + COLOR_TYPE_COLOR_INIT(COLOR_BLACK , TWINKLE_FAST_FRE, COLOR_BLACK), + + COLOR_TYPE_LOOP_INIT(0/*back to step zero*/, 0xffffffff), + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_colorful_twinkle_fast); +/*colorful twinkle pause*/ +const color_cell_t color_table_colorful_twinkle_pause[] = { + COLOR_TYPE_COLOR_INIT(0, 0, COLOR_GREEN), + + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_colorful_twinkle_pause); + +/*nice emotion*/ +const color_cell_t color_table_sunset[] = { + COLOR_TYPE_BREATH_MEASURE_BY_STEP_INIT(0, 0x90, 0x00009999, BREATH_RGB_SEL(RED_EN, GREEN_EN, 0), BREATH_RGB_DIR_UP(0, 0, 0), 100, 1, 0x00, 0xff), + COLOR_TYPE_COLOR_INIT(0, 2000, COLOR_BLACK), + COLOR_TYPE_LOOP_INIT(0/*back to step zero*/, 0xffffffff), + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_sunset); + +/*nice emotion*/ +const color_cell_t color_table_nice_emotion[] = { + COLOR_TYPE_BREATH_MEASURE_BY_STEP_INIT(0, 0x50, 0x0000ff00, BREATH_RGB_SEL(RED_EN, GREEN_EN, 0), BREATH_RGB_DIR_UP(RED_EN, 0, 0), 100, 1, 0x00, 0xff), + COLOR_TYPE_BREATH_MEASURE_BY_STEP_INIT(0, 0x50, 0x0000af50, BREATH_RGB_SEL(RED_EN, GREEN_EN, 0), BREATH_RGB_DIR_UP(0, GREEN_EN, 0), 100, 1, 0x00, 0xff), + COLOR_TYPE_BREATH_MEASURE_BY_STEP_INIT(0, 0x50, 0x0000ff00, BREATH_RGB_SEL(0, GREEN_EN, BLUE_EN), BREATH_RGB_DIR_UP(0, 0, BLUE_EN), 100, 1, 0x00, 0xff), + COLOR_TYPE_BREATH_MEASURE_BY_STEP_INIT(0, 0x50, 0x0050af00, BREATH_RGB_SEL(0, GREEN_EN, BLUE_EN), BREATH_RGB_DIR_UP(0, GREEN_EN, 0), 100, 1, 0x00, 0xff), + + COLOR_TYPE_BREATH_MEASURE_BY_STEP_INIT(0, 0x50, 0x0000ff00, BREATH_RGB_SEL(RED_EN, GREEN_EN, BLUE_EN), BREATH_RGB_DIR_UP(RED_EN, 0, BLUE_EN), 100, 1, 0x00, 0xff), + COLOR_TYPE_BREATH_MEASURE_BY_STEP_INIT(0, 0x50, 0x0050af50, BREATH_RGB_SEL(RED_EN, GREEN_EN, BLUE_EN), BREATH_RGB_DIR_UP(0, GREEN_EN, 0), 100, 1, 0x00, 0xff), + + COLOR_TYPE_LOOP_INIT(0/*back to step zero*/, 0xffffffff), + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_nice_emotion); + +/*blue breath*/ +const color_cell_t color_table_blue_breath[] = { + COLOR_TYPE_BREATH_INIT(0, 0, 0x00300000, BREATH_RGB_SEL(0, 0, BLUE_EN), BREATH_RGB_DIR_UP(0, 0, 0), 20, 1, 0x10, 0xff), + COLOR_TYPE_LOOP_INIT(0/*back to step zero*/, 0xffffffff), + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_blue_breath); + +/*green breath*/ +const color_cell_t color_table_green_breath[] = { + COLOR_TYPE_BREATH_INIT(0, 0, 0x00003000, BREATH_RGB_SEL(0, GREEN_EN, 0), BREATH_RGB_DIR_UP(0, 0, 0), 20, 1, 0x10, 0xff), + COLOR_TYPE_LOOP_INIT(0/*back to step zero*/, 0xffffffff), + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_green_breath); + +/*red breath*/ +const color_cell_t color_table_red_breath[] = { + COLOR_TYPE_BREATH_INIT(0, 0, 0x00000030, BREATH_RGB_SEL(RED_EN, 0, 0), BREATH_RGB_DIR_UP(0, 0, 0), 20, 1, 0x10, 0xff), + COLOR_TYPE_LOOP_INIT(0/*back to step zero*/, 0xffffffff), + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_red_breath); + +/*wonderful breath*/ +const color_cell_t color_table_wonderful_breath[] = { + COLOR_TYPE_BREATH_MEASURE_BY_STEP_INIT(0, 0xff, 0x000000ff, BREATH_RGB_SEL(RED_EN, GREEN_EN, 0), BREATH_RGB_DIR_UP(0, GREEN_EN, 0), 20, 1, 0x00, 0xff), + COLOR_TYPE_BREATH_MEASURE_BY_STEP_INIT(0, 0xff, 0x0000ff00, BREATH_RGB_SEL(0, GREEN_EN, BLUE_EN), BREATH_RGB_DIR_UP(0, 0, BLUE_EN), 20, 1, 0x00, 0xff), + COLOR_TYPE_BREATH_MEASURE_BY_STEP_INIT(0, 0xff, 0x00ff0000, BREATH_RGB_SEL(RED_EN, 0, BLUE_EN), BREATH_RGB_DIR_UP(RED_EN, 0, 0), 20, 1, 0x00, 0xff), + COLOR_TYPE_LOOP_INIT(0/*back to step zero*/, 0xffffffff), + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_wonderful_breath); + +/*night light*/ +const color_cell_t color_table_nightlight[] = { + COLOR_TYPE_COLOR_INIT(0, 0, COLOR_WHITE), + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_nightlight); + +/*candle light*/ +const color_cell_t color_table_candlelight[] = { + COLOR_TYPE_BREATH_INIT(0, 0, COLOR_YELLOW, BREATH_RGB_SEL(RED_EN, GREEN_EN, 0), BREATH_RGB_DIR_UP(RED_EN, 0, 0), 10000, 1, 0xf0, 0xff), + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_candlelight); + +/*heart beat*/ +const color_cell_t color_table_heartbeat[] = { + COLOR_TYPE_COLOR_INIT(0, 1000, COLOR_RED - 0x60), + COLOR_TYPE_COLOR_INIT(0, 2000, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(0, 900, COLOR_RED - 0x50), + COLOR_TYPE_COLOR_INIT(0, 1500, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(0, 800, COLOR_RED - 0x40), + COLOR_TYPE_COLOR_INIT(0, 1200, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(0, 700, COLOR_RED - 0x30), + COLOR_TYPE_COLOR_INIT(0, 800, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(0, 600, COLOR_RED - 0x20), + COLOR_TYPE_COLOR_INIT(0, 700, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(0, 500, COLOR_RED), + COLOR_TYPE_COLOR_INIT(0, 500, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(0, 600, COLOR_RED - 0x20), + COLOR_TYPE_COLOR_INIT(0, 700, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(0, 700, COLOR_RED - 0x30), + COLOR_TYPE_COLOR_INIT(0, 800, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(0, 800, COLOR_RED - 0x40), + COLOR_TYPE_COLOR_INIT(0, 1200, COLOR_BLACK), + COLOR_TYPE_COLOR_INIT(0, 900, COLOR_RED - 0x50), + COLOR_TYPE_COLOR_INIT(0, 1500, COLOR_BLACK), + + COLOR_TYPE_LOOP_INIT(0/*back to step zero*/, 0xffffffff), + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_heartbeat); + +/*rain bow*/ +const color_cell_t color_table_rainbow[] = { + COLOR_TYPE_BREATH_INIT(0, 0, 0x0aa3030, BREATH_RGB_SEL(RED_EN, GREEN_EN, BLUE_EN), BREATH_RGB_DIR_UP(RED_EN, 0, 0), 2000, 1, 0x10, 0xff), + COLOR_END(), +}; +COLOR_TABLE_REGISTER(color_table_rainbow); + diff --git a/apps/soundbox/ui/color_led/driver/color_led.c b/apps/soundbox/ui/color_led/driver/color_led.c new file mode 100644 index 0000000..1f22ce2 --- /dev/null +++ b/apps/soundbox/ui/color_led/driver/color_led.c @@ -0,0 +1,310 @@ +#include "system/includes.h" +#include "app_config.h" +#include "user_cfg.h" +#include "color_led_app.h" + +#if TCFG_COLORLED_ENABLE +#define LOG_TAG_CONST COLOR_LED +#define LOG_TAG "[COLOR_LED]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#define CPU_ENTER_CRITICAL() local_irq_disable() +#define CPU_EXIT_CRITICAL() local_irq_enable() +typedef struct { + const color_cell_t *begin; + const color_cell_t *cur; + const color_cell_t *loop; + void (*led_select)(u32 led_io); + u32 next_step_timer; + u32 loop_cnt; + u32 total_step; + u32 pwm_loop_timer; + u32 pwm_cur_color; + u32 breath_step_cnt; + u8 pwm_step_dir : 3; +} color_led_control_t; + +static color_led_control_t color_led_hdl; +#define __this (&color_led_hdl) + +static void color_led_timer(void *priv); +static void pwm_loop(void *priv); +static int color_led_active(const color_cell_t *color, color_led_control_t *hdl) +{ + if ((hdl == NULL) || (color == NULL)) { + return (-1); + } + const color_cell_t *active_color = NULL; + + CPU_ENTER_CRITICAL(); + hdl->cur = color; + CPU_EXIT_CRITICAL(); + switch (hdl->cur->type) { + case COLOR_TYPE_SET: + if (hdl->led_select) { + hdl->led_select(hdl->cur->led_io); + } + + COLOR_SET(hdl->cur->type_action.color.color); + if (hdl->cur->show_time) { + hdl->next_step_timer = sys_hi_timeout_add(hdl, color_led_timer, hdl->cur->show_time); + } + break; + case COLOR_TYPE_LOOP: + if (hdl->loop != color) { + /*load new loop*/ + hdl->loop = color; + hdl->loop_cnt = color->type_action.loop.loop_num; + } + + if (hdl->loop_cnt == 0) { + /*loop end*/ + active_color = ++(hdl->cur); + color_led_active(active_color, hdl); + break; + } + + if (hdl->total_step < hdl->loop->type_action.loop.back_step) { + log_info("!!!back_step bigger than the number of elements of table \n"); + break; + } + + active_color = hdl->begin + hdl->loop->type_action.loop.back_step; + hdl->loop_cnt--; + CPU_ENTER_CRITICAL(); + if (active_color->type == COLOR_TYPE_PWM) { + hdl->breath_step_cnt = 0; + hdl->pwm_step_dir = active_color->type_action.pwm_color.start_direction; + hdl->pwm_cur_color = active_color->type_action.pwm_color.start_color; + } + CPU_EXIT_CRITICAL(); + color_led_active(active_color, hdl); + break; + case COLOR_TYPE_PWM: + if (hdl->led_select) { + hdl->led_select(hdl->cur->led_io); + } + + COLOR_SET(hdl->pwm_cur_color); + if (hdl->cur->show_time && (!hdl->cur->type_action.pwm_color.display_time_by_step)) { + hdl->next_step_timer = sys_hi_timeout_add(hdl, color_led_timer, hdl->cur->show_time); + } + + //register pwm loop + if (hdl->cur->type_action.pwm_color.color_sel && hdl->cur->type_action.pwm_color.step_time) { + hdl->pwm_loop_timer = sys_hi_timeout_add(hdl, pwm_loop, hdl->cur->type_action.pwm_color.step_time); + } + + break; + default: + break; + } + + return 0; +} + +static void color_led_timer(void *priv) +{ + color_led_control_t *hdl = (color_led_control_t *)priv; + if (hdl == NULL) { + return; + } + + //del pwm loop + if (hdl->pwm_loop_timer) { + sys_hi_timer_del(hdl->pwm_loop_timer); + hdl->pwm_loop_timer = 0; + } + + hdl->next_step_timer = 0; + + /*to next step*/ + const color_cell_t *active_color = ++(hdl->cur); + CPU_ENTER_CRITICAL(); + if (hdl->cur->type == COLOR_TYPE_PWM) { + hdl->breath_step_cnt = 0; + hdl->pwm_step_dir = hdl->cur->type_action.pwm_color.start_direction; + hdl->pwm_cur_color = hdl->cur->type_action.pwm_color.start_color; + } + CPU_EXIT_CRITICAL(); + color_led_active(active_color, hdl); +} + +static void pwm_loop(void *priv) +{ +#define RED_COLOR_SET(red_color,color) ((red_color & 0x000000ff) + (color & 0xffffff00)) +#define GREE_COLOR_SET(gree_color,color) ((gree_color & 0x0000ff00) + (color & 0xffff00ff)) +#define BLUE_COLOR_SET(blue_color,color) ((blue_color & 0x00ff0000) + (color & 0xff00ffff)) +#define COLOR_LED_BREATH_DATA_IS_LEGAL(color,floor,ceil) ((color>=floor) && (color<=ceil)) + color_led_control_t *hdl = (color_led_control_t *)priv; + if (hdl == NULL) { + return; + } + + hdl->breath_step_cnt ++; + + if (hdl->cur->type_action.pwm_color.color_sel & BIT(0)) { + //set red value + u8 dir = hdl->pwm_step_dir & BIT(0);/*0:down 1:up*/ + u32 color = hdl->pwm_cur_color; + color &= 0x000000ff; + if (!COLOR_LED_BREATH_DATA_IS_LEGAL(color, \ + hdl->cur->type_action.pwm_color.flood, hdl->cur->type_action.pwm_color.ceil)) { + log_info("!!!data illegal color:%x floor:%x ceil:%x \n", color, \ + hdl->cur->type_action.pwm_color.flood, hdl->cur->type_action.pwm_color.ceil); + return; + } + + if (dir == 0) { + if ((color - hdl->cur->type_action.pwm_color.flood) > hdl->cur->type_action.pwm_color.step) { + color -= hdl->cur->type_action.pwm_color.step; + } else { + color = hdl->cur->type_action.pwm_color.flood; + //down to up + hdl->pwm_step_dir ^= BIT(0); + } + } else { + if ((color + hdl->cur->type_action.pwm_color.step) >= hdl->cur->type_action.pwm_color.ceil) { + color = hdl->cur->type_action.pwm_color.ceil; + //up to down + hdl->pwm_step_dir ^= BIT(0); + } else { + color += hdl->cur->type_action.pwm_color.step; + } + } + + hdl->pwm_cur_color = RED_COLOR_SET(color, hdl->pwm_cur_color); + } + + if (hdl->cur->type_action.pwm_color.color_sel & BIT(1)) { + //set gree value + u8 dir = hdl->pwm_step_dir & BIT(1);/*0:down 1:up*/ + u32 color = hdl->pwm_cur_color; + color &= 0x0000ff00; + color >>= 8; + if (!COLOR_LED_BREATH_DATA_IS_LEGAL(color, \ + hdl->cur->type_action.pwm_color.flood, hdl->cur->type_action.pwm_color.ceil)) { + log_info("!!!data illegal color:%x floor:%x ceil:%x \n", color, \ + hdl->cur->type_action.pwm_color.flood, hdl->cur->type_action.pwm_color.ceil); + return; + } + + if (dir == 0) { + if ((color - hdl->cur->type_action.pwm_color.flood) > hdl->cur->type_action.pwm_color.step) { + color -= hdl->cur->type_action.pwm_color.step; + } else { + color = hdl->cur->type_action.pwm_color.flood; + //down to up + hdl->pwm_step_dir ^= BIT(1); + } + } else { + if ((color + hdl->cur->type_action.pwm_color.step) >= hdl->cur->type_action.pwm_color.ceil) { + color = hdl->cur->type_action.pwm_color.ceil; + //up to down + hdl->pwm_step_dir ^= BIT(1); + } else { + color += hdl->cur->type_action.pwm_color.step; + } + } + color <<= 8; + + hdl->pwm_cur_color = GREE_COLOR_SET(color, hdl->pwm_cur_color); + } + + if (hdl->cur->type_action.pwm_color.color_sel & BIT(2)) { + //set gree value + u8 dir = hdl->pwm_step_dir & BIT(2);/*0:down 1:up*/ + u32 color = hdl->pwm_cur_color; + color &= 0x00ff0000; + color >>= 16; + if (!COLOR_LED_BREATH_DATA_IS_LEGAL(color, \ + hdl->cur->type_action.pwm_color.flood, hdl->cur->type_action.pwm_color.ceil)) { + log_info("!!!data illegal color:%x floor:%x ceil:%x \n", color, \ + hdl->cur->type_action.pwm_color.flood, hdl->cur->type_action.pwm_color.ceil); + return; + } + + if (dir == 0) { + if ((color - hdl->cur->type_action.pwm_color.flood) > hdl->cur->type_action.pwm_color.step) { + color -= hdl->cur->type_action.pwm_color.step; + } else { + color = hdl->cur->type_action.pwm_color.flood; + //down to up + hdl->pwm_step_dir ^= BIT(2); + } + } else { + if ((color + hdl->cur->type_action.pwm_color.step) >= hdl->cur->type_action.pwm_color.ceil) { + color = hdl->cur->type_action.pwm_color.ceil; + //up to down + hdl->pwm_step_dir ^= BIT(2); + } else { + color += hdl->cur->type_action.pwm_color.step; + } + } + color <<= 16; + + hdl->pwm_cur_color = BLUE_COLOR_SET(color, hdl->pwm_cur_color); + } + + //log_info("color:%x \n",hdl->pwm_cur_color); + COLOR_SET(hdl->pwm_cur_color); + if (hdl->cur->type_action.pwm_color.color_sel && hdl->cur->type_action.pwm_color.step_time) { + hdl->pwm_loop_timer = sys_hi_timeout_add(hdl, pwm_loop, hdl->cur->type_action.pwm_color.step_time); + } + + if (hdl->cur->type_action.pwm_color.display_time_by_step && \ + (hdl->breath_step_cnt == hdl->cur->type_action.pwm_color.display_time_by_step)) { + color_led_timer(hdl); + } +} + +static void color_led_close(color_led_control_t *hdl) +{ + if (hdl == NULL) { + return; + } + if (hdl->next_step_timer) { + sys_hi_timer_del(hdl->next_step_timer); + hdl->next_step_timer = 0; + } + if (hdl->pwm_loop_timer) { + sys_hi_timer_del(hdl->pwm_loop_timer); + hdl->pwm_loop_timer = 0; + } + + COLOR_SET(COLOR_BLACK); +} + +int color_led_set(const color_cell_t table[], u32 numberofmembers, void (*led_select)(u32 led_io)) +{ + if (table == NULL) { + return (-1); + } + + color_led_control_t *hdl = __this; + color_led_close(hdl); + CPU_ENTER_CRITICAL(); + hdl->begin = table; + hdl->cur = table; + hdl->loop = NULL; + hdl->total_step = numberofmembers; + hdl->loop_cnt = 0; + hdl->led_select = led_select; + if (hdl->cur->type == COLOR_TYPE_PWM) { + hdl->breath_step_cnt = 0; + hdl->pwm_step_dir = hdl->cur->type_action.pwm_color.start_direction; + hdl->pwm_cur_color = hdl->cur->type_action.pwm_color.start_color; + } + CPU_EXIT_CRITICAL(); + + color_led_active(hdl->cur, hdl); + return 0; +} + +#endif + diff --git a/apps/soundbox/ui/color_led/driver/color_led_driver.c b/apps/soundbox/ui/color_led/driver/color_led_driver.c new file mode 100644 index 0000000..5e8565a --- /dev/null +++ b/apps/soundbox/ui/color_led/driver/color_led_driver.c @@ -0,0 +1,114 @@ +#include "system/includes.h" +#include "app_config.h" +#include "user_cfg.h" +#include "color_led_driver.h" + +#define LOG_TAG_CONST COLOR_LED +#define LOG_TAG "[COLOR_LED]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#if TCFG_COLORLED_ENABLE +int timer_pwm_init(JL_TIMER_TypeDef *JL_TIMERx, u32 fre, u32 duty, u32 port, int output_ch); +void set_timer_pwm_duty(JL_TIMER_TypeDef *JL_TIMERx, u32 fre, u32 duty); +#define PWM_FRE (0XFF*0XFF) + +#define BYTE(data,n) ((data>>(n*8)) & 0x000000ff) +static const colorled_platform_data *color_led_cfg_data = NULL; +#define __this (color_led_cfg_data) +#define PWM_DETY_SET(timer_hdl,duty) set_timer_pwm_duty(timer_hdl,PWM_FRE,duty*0xff) + +void __color_led_normal_mode_io_set(const colorled_platform_data *cfg_data) +{ + u8 pin[3] = {cfg_data->pin_red.pin, cfg_data->pin_gree.pin, cfg_data->pin_blue.pin}; + + for (int i = 0; i < sizeof(pin); i++) { + gpio_set_die(pin[i], 1); + gpio_set_pull_up(pin[i], 0); + gpio_set_pull_down(pin[i], 0); + gpio_set_direction(pin[i], 0); + } +} + +/* + * BYTE3(reserved) BYTE2(BLUE) BYTE1(GREE) BYTE0(RED) + * */ +void __color_normal_mode_set(u32 color) +{ + //log_info("color:%8x %d %d %d \n", color,(BYTE(color,0)!=0),(BYTE(color,1)!=0),(BYTE(color,2)!=0)); + + { + //RED + gpio_direction_output(__this->pin_red.pin, (BYTE(color, 0) != 0)); + } + + { + //GREE + gpio_direction_output(__this->pin_gree.pin, (BYTE(color, 1) != 0)); + } + + { + ///BLUE + gpio_direction_output(__this->pin_blue.pin, (BYTE(color, 2) != 0)); + } +} + +void __color_led_pwm_mode_io_set(const colorled_platform_data *cfg_data) +{ + + if (timer_pwm_init(__this->pin_red.timer_hdl, PWM_FRE, 0, __this->pin_red.pin, __this->pin_red.output_ch) == (-1)) { + ASSERT(0, "!!!warning : pwm not support io,please select others or used output channel mode \n"); + } + if (timer_pwm_init(__this->pin_gree.timer_hdl, PWM_FRE, 0, __this->pin_gree.pin, __this->pin_gree.output_ch) == (-1)) { + ASSERT(0, "!!!warning : pwm not support io,please select others or used output channel mode \n"); + } + if (timer_pwm_init(__this->pin_blue.timer_hdl, PWM_FRE, 0, __this->pin_blue.pin, __this->pin_blue.output_ch) == (-1)) { + ASSERT(0, "!!!warning : pwm not support io,please select others or used output channel mode \n"); + } +} + +void __color_pwm_mode_set(u32 color) +{ +// log_info("color:%8x \n", color); + PWM_DETY_SET(__this->pin_red.timer_hdl, (BYTE(color, 0))); + PWM_DETY_SET(__this->pin_gree.timer_hdl, (BYTE(color, 1))); + PWM_DETY_SET(__this->pin_blue.timer_hdl, (BYTE(color, 2))); +} +#endif + +void __color_led_io_set(const colorled_platform_data *cfg_data) +{ +#if TCFG_COLORLED_ENABLE + color_led_cfg_data = cfg_data; + + switch (__this->work_mode) { + case COLOR_LED_MODE_NORNAL: + __color_led_normal_mode_io_set(__this); + break; + case COLOR_LED_MODE_PWM: + __color_led_pwm_mode_io_set(__this); + break; + default: + break; + } +#endif +} +void __color_set(u32 color) +{ +#if TCFG_COLORLED_ENABLE + switch (__this->work_mode) { + case COLOR_LED_MODE_NORNAL: + __color_normal_mode_set(color); + break; + case COLOR_LED_MODE_PWM: + __color_pwm_mode_set(color); + break; + default: + break; + } +#endif +} diff --git a/apps/soundbox/ui/lcd/STYLE_02/bt_action.c b/apps/soundbox/ui/lcd/STYLE_02/bt_action.c new file mode 100644 index 0000000..b881247 --- /dev/null +++ b/apps/soundbox/ui/lcd/STYLE_02/bt_action.c @@ -0,0 +1,527 @@ +#include "ui/ui.h" +#include "app_config.h" +#include "ui/ui_api.h" +#include "app_task.h" +#include "system/timer.h" +#include "key_event_deal.h" +#include "audio_config.h" +#include "jiffies.h" +#include "btstack/avctp_user.h" +#include "app_power_manage.h" +#include "asm/charge.h" +#ifndef CONFIG_MEDIA_NEW_ENABLE +#include "media/audio_eq_drc_apply.h" +#else +#include "audio_eq.h" +#endif + + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX)) + +#define STYLE_NAME JL + +REGISTER_UI_STYLE(STYLE_NAME) + +extern void key_ui_takeover(u8 on); +extern u8 bt_sco_state(void); +extern void power_off_deal(struct sys_event *event, u8 step); +static int music_vol_handler(const char *type, u32 arg); + +static int bt_status_handler(const char *type, u32 arg) +{ + if (ui_get_disp_status_by_id(BT_MENU_LAYOUT) == true) { + return -1; + } + + if (ui_get_disp_status_by_id(BT_VOL_LAYOUT) == true) { + return -1; + } + + if (type && (!strcmp(type, "event"))) { + switch (arg) { + case BT_STATUS_SECOND_CONNECTED: + case BT_STATUS_FIRST_CONNECTED: + printf("%s %d\n", __func__, __LINE__); + ui_pic_show_image_by_id(BT_STATUS_PIC, 1); + ui_text_show_index_by_id(BT_STATUS_TEXT, 1); + break; + case BT_STATUS_FIRST_DISCONNECT: + case BT_STATUS_SECOND_DISCONNECT: + printf("%s %d\n", __func__, __LINE__); + ui_pic_show_image_by_id(BT_STATUS_PIC, 0); + ui_text_show_index_by_id(BT_STATUS_TEXT, 0); + break; + case BT_STATUS_A2DP_MEDIA_START: + printf("%s %d\n", __func__, __LINE__); + ui_pic_show_image_by_id(BT_STATUS_PIC, 1); + ui_text_show_index_by_id(BT_STATUS_TEXT, 2); + break; + case BT_STATUS_A2DP_MEDIA_STOP: + printf("%s %d\n", __func__, __LINE__); + ui_pic_show_image_by_id(BT_STATUS_PIC, 1); + ui_text_show_index_by_id(BT_STATUS_TEXT, 1); + break; + + } + } + return 0; +} + + + + +/************************************************************ + 窗口app与ui的消息交互注册 app可以发生消息到ui进行显示 + ************************************************************/ + +static const struct uimsg_handl ui_msg_handler[] = { + { "bt_status", bt_status_handler }, /* 设置音量 */ + { "music_vol", music_vol_handler }, /* 显示音量 */ + { NULL, NULL}, /* 必须以此结尾! */ +}; + + + + +/************************************************************ + 蓝牙主页窗口控件 + 可以在这个窗口注册各个布局需要用的资源 + ************************************************************/ + + +static int bt_mode_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct window *window = (struct window *)ctr; + static int bt_status_timer = 0; + switch (e) { + case ON_CHANGE_INIT: + puts("\n***!!!!!!!!!!!! >>>>>>>>>>>>>>>>>>bt_mode_onchange***\n"); + ui_register_msg_handler(ID_WINDOW_BT, ui_msg_handler);//注册消息交互的回调 + /* + * 注册APP消息响应 + */ + break; + case ON_CHANGE_RELEASE: + + if (bt_status_timer) { + sys_timeout_del(bt_status_timer); + bt_status_timer = 0; + } + break; + default: + return false; + } + return false; +} + + + +REGISTER_UI_EVENT_HANDLER(ID_WINDOW_BT) +.onchange = bt_mode_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + + +static void bt_status_check(void *p) +{ + u8 status = get_bt_connect_status(); + u8 eq_mode = 0; + if (status == BT_STATUS_WAITINT_CONN) { + ui_pic_show_image_by_id(BT_STATUS_PIC, 0); + ui_text_show_index_by_id(BT_STATUS_TEXT, 0); + } else if (status == BT_STATUS_PLAYING_MUSIC) { + ui_pic_show_image_by_id(BT_STATUS_PIC, 1); + ui_text_show_index_by_id(BT_STATUS_TEXT, 2); + } else { + ui_pic_show_image_by_id(BT_STATUS_PIC, 1); + ui_text_show_index_by_id(BT_STATUS_TEXT, 1); + } +#if TCFG_EQ_ENABLE + eq_mode = eq_mode_get_cur(); + ui_pic_show_image_by_id(BT_EQ, eq_mode); +#endif +} + +static int bt_layout_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct layout *layout = (struct layout *)ctr; + switch (e) { + case ON_CHANGE_INIT: + break; + + case ON_CHANGE_FIRST_SHOW: + ui_set_call(bt_status_check, 0); + break; + + case ON_CHANGE_SHOW_POST: + //有显示动作 + break; + + case ON_CHANGE_RELEASE: + break; + default: + return FALSE; + } + return FALSE; +} + + + +static int bt_layout_onkey(void *ctr, struct element_key_event *e) +{ + printf("bt_layout_onkey %d\n", e->value); + switch (e->value) { + case KEY_MENU: + if (ui_get_disp_status_by_id(BT_MENU_LAYOUT) <= 0) { + printf("BT_MENU_LAYOUT\n"); + ui_show(BT_MENU_LAYOUT); + } + break; + case KEY_UP: + r_printf("BT_MUSIC_PREV\n"); + app_task_put_key_msg(KEY_MUSIC_PREV, 0); + break; + case KEY_DOWN: + r_printf("BT_MUSIC_NEXT\n"); + app_task_put_key_msg(KEY_MUSIC_NEXT, 0); + break; + case KEY_VOLUME_INC: + case KEY_VOLUME_DEC: + if (ui_get_disp_status_by_id(BT_VOL_LAYOUT) <= 0) { + ui_show(BT_VOL_LAYOUT); + } + break; + case KEY_OK: + r_printf("BT_MUSIC_PP\n"); + app_task_put_key_msg(KEY_MUSIC_PP, 0); + break; + case KEY_MODE: + ui_hide_main(ID_WINDOW_BT); + ui_show_main(ID_WINDOW_SYS); + break; + case KEY_POWER_START: + case KEY_POWER: + power_off_deal(NULL, e->value - KEY_POWER_START); + break; + default: + return false; + break; + } + return TRUE; +} + + + + +REGISTER_UI_EVENT_HANDLER(BT_LAYOUT) +.onchange = bt_layout_onchange, + .onkey = bt_layout_onkey, + .ontouch = NULL, +}; + + +static u16 bt_timer = 0; +static void bt_vol_timeout(void *p) +{ + int id = (int)(p); + if (ui_get_disp_status_by_id(id) == TRUE) { + ui_hide(id); + } + bt_timer = 0; +} + +static int music_vol_handler(const char *type, u32 arg) +{ + struct unumber num; + if (type && (!strcmp(type, "vol"))) { + if (ui_get_disp_status_by_id(BT_VOL_LAYOUT) == TRUE) { + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = arg; + ui_number_update_by_id(BT_VOL_NUM, &num); + } + } + return 0; +} + + + +static void vol_init(int id) +{ + struct unumber num; + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + ui_number_update_by_id(BT_VOL_NUM, &num); +} + +static int bt_vol_layout_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct layout *layout = (struct layout *)ctr; + switch (e) { + case ON_CHANGE_INIT: + if (!bt_timer) { + bt_timer = sys_timeout_add((void *)layout->elm.id, bt_vol_timeout, 3000); + } + layout_on_focus(layout);//设置焦点在本布局(如果布局下还有列表,焦点会最后显示出的列表这里,防止焦点不在,可以把焦点控制在本布局) + break; + + case ON_CHANGE_FIRST_SHOW: + ui_set_call(vol_init, 0); + break; + + case ON_CHANGE_SHOW_POST: + //有显示动作 + break; + + case ON_CHANGE_RELEASE: + if (bt_timer) { + sys_timeout_del(bt_timer); + bt_timer = 0; + } + layout_lose_focus(layout);//失去本焦点 + break; + default: + return FALSE; + } + return FALSE; +} + + + + +static int bt_vol_layout_onkey(void *ctr, struct element_key_event *e) +{ + printf("bt_vol_layout_onkey %d\n", e->value); + + if (bt_timer) { + sys_timer_modify(bt_timer, 3000); + } + + switch (e->value) { + case KEY_MENU: + break; + case KEY_UP: + case KEY_VOLUME_INC: + app_task_put_key_msg(KEY_VOL_UP, 0); + break; + case KEY_DOWN: + case KEY_VOLUME_DEC: + app_task_put_key_msg(KEY_VOL_DOWN, 0); + break; + default: + return false; + break; + } + return true; +} + + + +REGISTER_UI_EVENT_HANDLER(BT_VOL_LAYOUT) +.onchange = bt_vol_layout_onchange, + .onkey = bt_vol_layout_onkey, + .ontouch = NULL, +}; + + + +static int bt_menu_list_onkey(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + int sel_item = 0; + printf("ui key %s %d\n", __FUNCTION__, e->value); + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + switch (sel_item) { + case 0: + ui_show(BT_MENU_EQ_LAYOUT); + break; + case 1: + ui_hide(BT_MENU_LAYOUT); + break; + } + break; + default: + return false; + } + return TRUE; +} + + + +REGISTER_UI_EVENT_HANDLER(BT_MENU_LIST) +.onchange = NULL, + .onkey = bt_menu_list_onkey, + .ontouch = NULL, +}; + + + +static int bt_eq_menu_list_onkey(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + int sel_item = 0; + printf("ui key %s %d\n", __FUNCTION__, e->value); + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + switch (sel_item) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: +#if TCFG_EQ_ENABLE + eq_mode_set(sel_item); + ui_pic_show_image_by_id(BT_EQ, sel_item); +#endif + case 6: + ui_hide(BT_MENU_EQ_LAYOUT); + break; + } + break; + default: + return false; + } + return TRUE; +} + + +static const int eq_mode_pic[] = { + BT_EQ_NORMAL_PIC, + BT_EQ_ROCK_PIC, + BT_EQ_POP_PIC, + BT_EQ_CLASSIC_PIC, + BT_EQ_JAZZ_PIC, + BT_EQ_COUNTRY_PIC, +}; + + +#if TCFG_EQ_ENABLE +static int eq_pic_common_onchange(void *_ctrl, enum element_change_event event, void *arg) +{ + struct ui_pic *pic = (struct ui_pic *)_ctrl; + switch (event) { + case ON_CHANGE_INIT: + if (pic->elm.id == eq_mode_pic[eq_mode_get_cur() % 6]) { + ui_pic_set_image_index(pic, 1); + } + break; + case ON_CHANGE_SHOW_POST: + break; + default: + return FALSE; + } + return FALSE; +} + +REGISTER_UI_EVENT_HANDLER(BT_EQ_NORMAL_PIC) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(BT_EQ_ROCK_PIC) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(BT_EQ_POP_PIC) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(BT_EQ_CLASSIC_PIC) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(BT_EQ_JAZZ_PIC) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(BT_EQ_COUNTRY_PIC) +.onchange = eq_pic_common_onchange, +}; + +#endif + + + + +static int bt_eq_menu_list_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + int list = 0; + switch (e) { + case ON_CHANGE_INIT: + printf("ON_CHANGE_INIT %d \n", grid->avail_item_num); + break; + } + return false; +} + + + +REGISTER_UI_EVENT_HANDLER(BT_EQ_MENU_LIST) +.onchange = bt_eq_menu_list_onchange, + .onkey = bt_eq_menu_list_onkey, + .ontouch = NULL, +}; + +/************************************************************ + 电池控件事件 + ************************************************************/ + +static void battery_timer(void *priv) +{ + int incharge = 0;//充电标志 + int id = (int)(priv); + static u8 percent = 0; + static u8 percent_last = 0; + if (1 || get_charge_online_flag()) { //充电时候图标动态效果 + if (percent > get_vbat_percent()) { + percent = 0; + } + ui_battery_set_level_by_id(id, percent, incharge); //充电标志,ui可以显示不一样的图标 + percent += 20; + } else { + + percent = get_vbat_percent(); + if (percent != percent_last) { + ui_battery_set_level_by_id(id, percent, incharge); //充电标志,ui可以显示不一样的图标,需要工具设置 + percent_last = percent; + } + + } +} + +static int battery_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_battery *battery = (struct ui_battery *)ctr; + static u32 timer = 0; + int incharge = 0;//充电标志 + + switch (e) { + case ON_CHANGE_INIT: + ui_battery_set_level(battery, get_vbat_percent(), incharge); + if (!timer) { + timer = sys_timer_add((void *)battery->elm.id, battery_timer, 1 * 1000); //传入的id就是BT_BAT + } + break; + case ON_CHANGE_FIRST_SHOW: + break; + case ON_CHANGE_RELEASE: + if (timer) { + sys_timer_del(timer); + timer = 0; + } + break; + default: + return false; + } + return false; +} +REGISTER_UI_EVENT_HANDLER(BT_BAT) +.onchange = battery_onchange, + .ontouch = NULL, +}; + + + +#endif diff --git a/apps/soundbox/ui/lcd/STYLE_02/clock_action.c b/apps/soundbox/ui/lcd/STYLE_02/clock_action.c new file mode 100644 index 0000000..859cd73 --- /dev/null +++ b/apps/soundbox/ui/lcd/STYLE_02/clock_action.c @@ -0,0 +1,1381 @@ +#include "ui/ui.h" +#include "app_config.h" +#include "ui/ui_style.h" +#include "ui/ui_api.h" +#include "app_task.h" +#include "system/timer.h" +#include "key_event_deal.h" +#include "audio_config.h" +#include "jiffies.h" +#include "system/timer.h" +#include "system/includes.h" +#include "rtc/alarm.h" +#include "app_power_manage.h" +#include "asm/charge.h" +#ifndef CONFIG_MEDIA_NEW_ENABLE +#include "media/audio_eq_drc_apply.h" +#else +#include "audio_eq.h" +#endif + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX)) +#if (TCFG_APP_RTC_EN) + +#define STYLE_NAME JL + +extern int ui_hide_main(int id); +extern int ui_show_main(int id); +extern void key_ui_takeover(u8 on); +extern void power_off_deal(struct sys_event *event, u8 step); + +struct rtc_ui_opr { + void *dev_handle; + int timer; +}; + +static struct rtc_ui_opr *__this = NULL; + + +/* static int test_timer =0; */ + +/************************************************************ + 电池控件事件 + ************************************************************/ + +static void battery_timer(void *priv) +{ + int incharge = 0;//充电标志 + int id = (int)(priv); + static u8 percent = 0; + static u8 percent_last = 0; + if (1 || get_charge_online_flag()) { //充电时候图标动态效果 + if (percent > get_vbat_percent()) { + percent = 0; + } + ui_battery_set_level_by_id(id, percent, incharge); //充电标志,ui可以显示不一样的图标 + percent += 20; + } else { + + percent = get_vbat_percent(); + if (percent != percent_last) { + ui_battery_set_level_by_id(id, percent, incharge); //充电标志,ui可以显示不一样的图标,需要工具设置 + percent_last = percent; + } + + } +} + +static int battery_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_battery *battery = (struct ui_battery *)ctr; + static u32 timer = 0; + int incharge = 0;//充电标志 + + switch (e) { + case ON_CHANGE_INIT: + ui_battery_set_level(battery, get_vbat_percent(), incharge); + if (!timer) { + timer = sys_timer_add((void *)battery->elm.id, battery_timer, 1 * 1000); //传入的id就是BT_BAT + } + break; + case ON_CHANGE_FIRST_SHOW: + break; + case ON_CHANGE_RELEASE: + if (timer) { + sys_timer_del(timer); + timer = 0; + } + break; + default: + return false; + } + return false; +} +REGISTER_UI_EVENT_HANDLER(CLOCK_BAT) +.onchange = battery_onchange, + .ontouch = NULL, +}; + + + + +static void timer_add_update(void *p) +{ + struct utime time_r; + struct sys_time current_time; + dev_ioctl(__this->dev_handle, IOCTL_GET_SYS_TIME, (u32)¤t_time); + + time_r.year = current_time.year;//, jiffies /1 %3000; + time_r.month = current_time.month;//jiffies /2 %12; + time_r.day = current_time.day;//jiffies /3 %30; + + time_r.hour = current_time.hour;//jiffies /4 % 60; + time_r.min = current_time.min;//jiffies /5 %60; + time_r.sec = current_time.sec;//jiffies /6 %60; + + if (ui_get_disp_status_by_id(CLOCK_TIME_YMD) > 0) { + ui_time_update_by_id(CLOCK_TIME_YMD, &time_r); + } + + if (ui_get_disp_status_by_id(CLOCK_TIME_HMS) > 0) { + ui_time_update_by_id(CLOCK_TIME_HMS, &time_r); + } +} + + +/************************************************************ + 时钟主页窗口控件 + ************************************************************/ +static int clock_mode_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct window *window = (struct window *)ctr; + switch (e) { + case ON_CHANGE_INIT: + puts("\n***clock_mode_onchange***\n"); + /* key_ui_takeover(1); */ + + if (!__this) { + __this = zalloc(sizeof(struct rtc_ui_opr)); + } + __this->dev_handle = dev_open("rtc", NULL); + + if (!__this->dev_handle) { + free(__this); + __this = NULL; + break; + } + + if (!__this->timer) { + __this->timer = sys_timer_add(NULL, timer_add_update, 500); + } + + + /* + * 注册APP消息响应 + */ + break; + case ON_CHANGE_RELEASE: + + if (__this && __this->timer) { + sys_timer_del(__this->timer); + __this->timer = 0; + } + + if (__this && __this->dev_handle) { + dev_close(__this->dev_handle); + __this->dev_handle = 0; + } + + if (__this) { + free(__this); + __this = NULL; + } + + break; + default: + return false; + } + return false; +} + + + +REGISTER_UI_EVENT_HANDLER(ID_WINDOW_CLOCK) +.onchange = clock_mode_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + + + + + +/************************************************************ + 时钟显示界面的布局控件 + ************************************************************/ + + +static int clock_layout_onchange(void *ctr, enum element_change_event e, void *arg) +{ + switch (e) { + case ON_CHANGE_INIT: + break; + } + return false; +} + + +static int clock_layout_onkey(void *ctr, struct element_key_event *e) +{ + printf("clock_layout_onkey %d\n", e->value); + switch (e->value) { + case KEY_MENU: + if (ui_get_disp_status_by_id(CLOCK_MENU_LAYOUT) <= 0) { + printf("CLOCK_MENU_LAYOUT\n"); + ui_show(CLOCK_MENU_LAYOUT); + } + break; + case KEY_UP: + case KEY_DOWN: + break; + case KEY_VOLUME_INC: + case KEY_VOLUME_DEC: + if (ui_get_disp_status_by_id(CLOCK_VOL_LAYOUT) <= 0) { + ui_hide(CLOCK_LAYOUT); + ui_show(CLOCK_VOL_LAYOUT); + } + break; + case KEY_MODE: + ui_hide_curr_main(); + ui_show_main(ID_WINDOW_SYS); + break; + case KEY_POWER_START: + case KEY_POWER: + power_off_deal(NULL, e->value - KEY_POWER_START); + break; + default: + return false; + break; + } + return false; +} + + + + +REGISTER_UI_EVENT_HANDLER(CLOCK_LAYOUT) +.onchange = clock_layout_onchange, + .onkey = clock_layout_onkey, + .ontouch = NULL, +}; + + + + +/************************************************************ + 时钟显示菜单的列表控件 + ************************************************************/ +static int clock_menu_list_onkey(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + int sel_item = 0; + printf("ui key %s %d\n", __FUNCTION__, e->value); + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + switch (sel_item) { + case 0: + ui_show(CLOCK_TIME_SET_LAYOUT); + break; + case 1: + ui_show(CLOCK_ALM_SET_LAYOUT); + break; + case 2: + ui_hide(CLOCK_MENU_LAYOUT); + break; + } + break; + default: + return false; + } + return TRUE; +} + + + +REGISTER_UI_EVENT_HANDLER(CLOCK_MENU_LIST) +.onchange = NULL, + .onkey = clock_menu_list_onkey, + .ontouch = NULL, +}; + + + +/************************************************************ + 时钟音量设置布局控件 + ************************************************************/ +static u16 vol_timer = 0; +static void clock_vol_lay_timeout(void *p) +{ + int id = (int)(p); + if (ui_get_disp_status_by_id(id) == TRUE) { + ui_hide(id); + ui_show(CLOCK_LAYOUT); + } + vol_timer = 0; +} + + +static void vol_init(int id) +{ + struct unumber num; + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + ui_number_update_by_id(CLOCK_VOL_NUM, &num); +} + +static int clock_vol_layout_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct layout *layout = (struct layout *)ctr; + switch (e) { + case ON_CHANGE_INIT: + if (!vol_timer) { + vol_timer = sys_timer_add((void *)layout->elm.id, clock_vol_lay_timeout, 3000); + } + break; + + case ON_CHANGE_FIRST_SHOW: + ui_set_call(vol_init, 0); + /* ui_number_update_by_id(CLOCK_VOL_NUM,&num); */ + break; + + case ON_CHANGE_SHOW_POST: + break; + + case ON_CHANGE_RELEASE: + if (vol_timer) { + sys_timeout_del(vol_timer); + vol_timer = 0; + } + break; + default: + return FALSE; + } + return FALSE; +} + + +static int clock_vol_layout_onkey(void *ctr, struct element_key_event *e) +{ + printf("clock_vol_layout_onkey %d\n", e->value); + struct unumber num; + u8 vol; + + if (vol_timer) { + sys_timer_modify(vol_timer, 3000); + } + + + switch (e->value) { + case KEY_MENU: + break; + + case KEY_UP: + case KEY_VOLUME_INC: + app_audio_volume_up(1); + vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = vol; + ui_number_update_by_id(CLOCK_VOL_NUM, &num); + break; + case KEY_DOWN: + case KEY_VOLUME_DEC: + app_audio_volume_down(1); + vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = vol; + ui_number_update_by_id(CLOCK_VOL_NUM, &num); + break; + default: + return false; + break; + } + return true; +} + + + + +REGISTER_UI_EVENT_HANDLER(CLOCK_VOL_LAYOUT) +.onchange = clock_vol_layout_onchange, + .onkey = clock_vol_layout_onkey, + .ontouch = NULL, +}; + +/***************************** 时间显示控件初始化 ************************************/ +static int clock_timer_show_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_time *time = (struct ui_time *)ctr; + struct sys_time current_time; + + switch (e) { + case ON_CHANGE_INIT: + dev_ioctl(__this->dev_handle, IOCTL_GET_SYS_TIME, (u32)¤t_time); + time->year = current_time.year; + time->month = current_time.month; + time->day = current_time.day; + time->hour = current_time.hour; + time->min = current_time.min; + time->sec = current_time.sec; + break; + default: + return FALSE; + } + return FALSE; +} +REGISTER_UI_EVENT_HANDLER(CLOCK_TIME_YMD) +.onchange = clock_timer_show_onchange, + .onkey = NULL, + .ontouch = NULL, +}; +REGISTER_UI_EVENT_HANDLER(CLOCK_TIME_HMS) +.onchange = clock_timer_show_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + + + + +/***************************** 日期时间设置 ************************************/ +struct time_setting { + const char *mark; + u32 time_id; + u16 time_value; +}; +static struct time_setting time_set_table[] = { + {"year", CLOCK_TIMER_YEAR, 0}, + {"month", CLOCK_TIMER_MONTH, 0}, + {"day", CLOCK_TIMER_DAY, 0}, + {"hour", CLOCK_TIMER_HOUR, 0}, + {"min", CLOCK_TIMER_MINUTE, 0}, + {"sec", CLOCK_TIMER_SECOND, 0}, +}; +enum sw_dir { /* 切换方向 */ + DIR_NEXT = 1, + DIR_PREV, + DIR_SET, +}; +enum set_mod { /* 加减时间方向 */ + MOD_ADD = 1, + MOD_DEC, + MOD_SET, +}; + +static void get_sys_time(struct sys_time *time) +{ + void *fd = dev_open("rtc", NULL); + if (!fd) { + memset(time, 0, sizeof(*time)); + return; + } + dev_ioctl(fd, IOCTL_GET_SYS_TIME, (u32)time); + /* printf("get_sys_time : %d-%d-%d,%d:%d:%d\n", time->year, time->month, time->day, time->hour, time->min, time->sec); */ + dev_close(fd); +} +static u16 time_set_p = 0xff; /* time_set_table的当前设置指针 */ +static u8 __time_search_by_mark(const char *mark) +{ + u16 p = 0; + u16 table_sum = sizeof(time_set_table) / sizeof(struct time_setting); + while (p < table_sum) { + if (!strcmp(mark, time_set_table[p].mark)) { + return p; + } + p++; + } + return -1; +} +static u8 __time_set_switch(enum sw_dir dir, const char *mark) +{ + u16 table_sum; + u16 prev_set_p = time_set_p; + u8 p; + printf("__time_set_switch dir: %d\n", dir); + table_sum = sizeof(time_set_table) / sizeof(struct time_setting); + ASSERT(dir == DIR_NEXT || dir == DIR_PREV || dir == DIR_SET); + switch (dir) { + case DIR_NEXT: + if (time_set_p >= (table_sum - 1)) { + time_set_p = 0; + } else { + time_set_p++; + } + break; + case DIR_PREV: + if (time_set_p >= (table_sum - 1)) { + time_set_p = 0; + } + + + if (time_set_p == 0) { + time_set_p = (table_sum - 1); + } else { + time_set_p--; + } + break; + case DIR_SET: + p = __time_search_by_mark(mark); + if (p == (u8) - 1) { + return -1; + } + time_set_p = p; + + break; + } + if (prev_set_p != 0xff) { + ui_no_highlight_element_by_id(time_set_table[prev_set_p].time_id); + } + + ui_highlight_element_by_id(time_set_table[time_set_p].time_id); + printf("__time_set_switch ok.\n"); + return 0; +} +static u8 __time_set_reset(void) +{ + struct sys_time time; + + time_set_p = 0xff; + /* + * 此处应该读取系统RTC时间 + */ + get_sys_time(&time); + + time_set_table[0].time_value = time.year; + time_set_table[1].time_value = time.month; + time_set_table[2].time_value = time.day; + time_set_table[3].time_value = time.hour; + time_set_table[4].time_value = time.min; + time_set_table[5].time_value = time.sec; + + return 0; +} +const u16 leap_month_table[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; +static u8 __is_leap_year(u16 year) +{ + return (((year % 4) == 0 && (year % 100) != 0) || ((year % 400) == 0)); +} +static u8 __time_update_show(u8 pos) /* 更新单个时间控件的时间 */ +{ + struct utime t; + t.year = time_set_table[0].time_value; + t.month = time_set_table[1].time_value; + t.day = time_set_table[2].time_value; + t.hour = time_set_table[3].time_value; + t.min = time_set_table[4].time_value; + t.sec = time_set_table[5].time_value; + ui_time_update_by_id(time_set_table[pos].time_id, &t); + return 0; +} +static u8 __time_set_value(enum set_mod mod, u16 value) +{ + + enum set_mod need_check = 0; + u16 year, month, day; + ASSERT(mod == MOD_ADD || mod == MOD_DEC || mod == MOD_SET); + switch (mod) { + case MOD_ADD: + switch (time_set_p) { + case 0: /* year */ + value = time_set_table[time_set_p].time_value + 1; + if (value >= 2100) { + value = 2099; + } + need_check = MOD_ADD; + break; + case 1: /* month */ + value = time_set_table[time_set_p].time_value + 1; + if (value > 12) { + value = 1; + } + need_check = MOD_ADD; + break; + case 2: /* day */ + month = time_set_table[1].time_value; + ASSERT(month >= 1 && month <= 12); + value = time_set_table[time_set_p].time_value + 1; + if (value > leap_month_table[month - 1]) { + value = 1; + } + need_check = MOD_ADD; + break; + case 3: /* hour */ + value = time_set_table[time_set_p].time_value + 1; + if (value > 23) { + value = 0; + } + break; + case 4: /* min */ + value = time_set_table[time_set_p].time_value + 1; + if (value > 59) { + value = 0; + } + break; + case 5: /* sec */ + value = time_set_table[time_set_p].time_value + 1; + if (value > 59) { + value = 0; + } + break; + default: + /* ASSERT(0, "mod_add time_set_p:%d err!", time_set_p); */ + return 0; + break; + } + break; + case MOD_DEC: + switch (time_set_p) { + case 0: /* year */ + value = time_set_table[time_set_p].time_value - 1; + if (value <= 2000) { + value = 2001; + } + need_check = MOD_DEC; + break; + case 1: /* month */ + value = time_set_table[time_set_p].time_value; + if (value == 1) { + value = 12; + } else { + value--; + } + need_check = MOD_DEC; + break; + case 2: /* day */ + value = time_set_table[time_set_p].time_value; + if (value == 1) { + month = time_set_table[1].time_value; + ASSERT(month >= 1 && month <= 12); + value = leap_month_table[month - 1]; + } else { + value--; + } + need_check = MOD_DEC; + break; + case 3: /* hour */ + value = time_set_table[time_set_p].time_value; + if (value == 0) { + value = 23; + } else { + value--; + } + break; + case 4: /* min */ + value = time_set_table[time_set_p].time_value; + if (value == 0) { + value = 59; + } else { + value--; + } + break; + case 5: /* sec */ + value = time_set_table[time_set_p].time_value; + if (value == 0) { + value = 59; + } else { + value--; + } + break; + default: + /* ASSERT(0, "mod_dec time_set_p:%d err!", time_set_p); */ + + return 0; + break; + } + break; + case MOD_SET: + switch (time_set_p) { + case 0: /* year */ + need_check = MOD_SET; + break; + case 1: /* month */ + ASSERT(value >= 1 && value <= 12); + need_check = MOD_SET; + break; + case 2: /* day */ + need_check = MOD_SET; + break; + case 3: /* hour */ + ASSERT(value >= 0 && value <= 23); + break; + case 4: /* min */ + ASSERT(value >= 0 && value <= 59); + break; + case 5: /* sec */ + ASSERT(value >= 0 && value <= 59); + break; + default: + /* ASSERT(0, "mod_set time_set_p:%d err!", time_set_p); */ + + return 0; + break; + } + break; + } + time_set_table[time_set_p].time_value = value; + + if (need_check) { + year = time_set_table[0].time_value; + month = time_set_table[1].time_value; + day = time_set_table[2].time_value; + if (month == 2 && !__is_leap_year(year)) { + if (day >= 29) { + if (need_check == MOD_ADD) { + day = 1; + } else if (need_check == MOD_DEC) { + day = 28; + } else { + day = 28; + } + time_set_table[2].time_value = day; + __time_update_show(2); /* 调整day数值显示 */ + } + + } else { + if (day > leap_month_table[month - 1]) { + day = leap_month_table[month - 1]; + time_set_table[2].time_value = day; + __time_update_show(2); /* 调整day数值显示 */ + } + } + } + __time_update_show(time_set_p); /* 更新当前位数值显示 */ + + return 0; +} +static int __time_get(struct sys_time *t) +{ + t->year = time_set_table[0].time_value; + t->month = time_set_table[1].time_value; + t->day = time_set_table[2].time_value; + t->hour = time_set_table[3].time_value; + t->min = time_set_table[4].time_value; + t->sec = time_set_table[5].time_value; + return 0; +} + + +extern void rtc_update_time_api(struct sys_time *time); +static int menu_sys_time_set() +{ + struct sys_time t; + + __time_get(&t); + + rtc_update_time_api(&t); + return 0; +} + + + +/************************************************************ + 时钟置布局控件 + ************************************************************/ +//是时钟初始化消息入口 +static void __time_set_switch_init(int id) +{ + __time_set_switch(DIR_SET, "year");//设置默认高亮的选项,可以是year day + /* __time_set_switch(DIR_SET, NULL); */ +} + + +static int time_layout_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct layout *layout = (struct layout *)ctr; + switch (e) { + case ON_CHANGE_INIT: + puts("time_layout_onchange onfocus.\n"); + layout_on_focus(layout);//设置焦点在本布局(如果布局下还有列表,焦点会最后显示出的列表这里,防止焦点不在,可以把焦点控制在本布局) + __time_set_reset();//初始化一些信息 + break; + case ON_CHANGE_RELEASE: + puts("time_layout_onchange losefocus.\n"); + layout_lose_focus(layout);//失去本焦点 + break; + case ON_CHANGE_FIRST_SHOW: + puts("time_layout_onchange ON_CHANGE_FIRST_SHOW.\n"); + ui_set_call(__time_set_switch_init, 0); + + break; + default: + break; + } + return FALSE; +} + +//是时钟消息入口,控制设置显示的选项和加减 +static int time_layout_onkey(void *ctr, struct element_key_event *e) +{ + + switch (e->value) { + case KEY_OK: + puts("time_layout_onkey KEY_OK.\n"); + __time_set_switch(DIR_NEXT, NULL);//切换选项 + + break; + case KEY_VOLUME_DEC: + case KEY_DOWN: + __time_set_value(MOD_ADD, 0); + + break; + case KEY_VOLUME_INC: + case KEY_UP: + __time_set_value(MOD_DEC, 0); + + break; + case KEY_MODE: + case KEY_MENU: + menu_sys_time_set();//保存设置 + ui_hide(CLOCK_TIME_SET_LAYOUT);//退出当前布局 + break; + default: + return false; + break; + } + + return true; +} + +REGISTER_UI_EVENT_HANDLER(CLOCK_TIME_SET_LAYOUT) +.onchange = time_layout_onchange, + .onkey = time_layout_onkey, + .ontouch = NULL, +}; + + + +//如果不对控件进行初始化,默认显示0的,因此需要对控件进行初始先 +/***************************** 系统时间各个数字动作 ************************************/ +static int clock_timer_sys_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_time *time = (struct ui_time *)ctr; + switch (e) { + case ON_CHANGE_INIT: + puts("timer_sys_onchange .\n"); + time->year = time_set_table[0].time_value; + time->month = time_set_table[1].time_value; + time->day = time_set_table[2].time_value; + time->hour = time_set_table[3].time_value; + time->min = time_set_table[4].time_value; + time->sec = time_set_table[5].time_value; + break; +#if 0 + case ON_CHANGE_SHOW_POST: + printf("~~~~~~~~~~~~%x\n", time->text.elm.id); + if (time->text.elm.highlight) { + printf("~~~~~~~~~~~~%x\n", time->text.elm.id); + /* ui_invert_element_by_id(time->text.elm.id); */ + } + break; +#endif + default: + return FALSE; + } + return FALSE; +} +REGISTER_UI_EVENT_HANDLER(CLOCK_TIMER_YEAR) +.onchange = clock_timer_sys_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +REGISTER_UI_EVENT_HANDLER(CLOCK_TIMER_MONTH) +.onchange = clock_timer_sys_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +REGISTER_UI_EVENT_HANDLER(CLOCK_TIMER_DAY) +.onchange = clock_timer_sys_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +REGISTER_UI_EVENT_HANDLER(CLOCK_TIMER_HOUR) +.onchange = clock_timer_sys_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +REGISTER_UI_EVENT_HANDLER(CLOCK_TIMER_MINUTE) +.onchange = clock_timer_sys_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +REGISTER_UI_EVENT_HANDLER(CLOCK_TIMER_SECOND) +.onchange = clock_timer_sys_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + + + +/***************************** 闹钟日期时间设置 ************************************/ + +static const int alm_rep_list[] = { + ALM_SUN, + ALM_MON, + ALM_TUE, + ALM_WED, + ALM_THU, + ALM_FRI, + ALM_SAT, +}; + + +struct alm_data_rep { + int rep_set; + int mask; +}; + +static struct time_setting alm_set_table[] = { + {"hour", ALM_H, 0}, + {"min", ALM_M, 0}, + {"rep", 0, 0}, + {"sw", ALM_SW, 0}, +}; + + +struct alm_data_rep alm_rep[] = { + {E_ALARM_MODE_ONCE, 0}, + //只响应一次 + {E_ALARM_MODE_EVERY_DAY, 0xff}, + //每天 + { + E_ALARM_MODE_EVERY_MONDAY | E_ALARM_MODE_EVERY_TUESDAY | \ + E_ALARM_MODE_EVERY_WEDNESDAY | E_ALARM_MODE_EVERY_THURSDAY | \ + E_ALARM_MODE_EVERY_FRIDAY, BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) + }, + //工作日 + + {E_ALARM_MODE_EVERY_SUNDAY, BIT(0)}, + {E_ALARM_MODE_EVERY_MONDAY, BIT(1)}, + {E_ALARM_MODE_EVERY_TUESDAY, BIT(2)}, + {E_ALARM_MODE_EVERY_WEDNESDAY, BIT(3)}, + {E_ALARM_MODE_EVERY_THURSDAY, BIT(4)}, + {E_ALARM_MODE_EVERY_FRIDAY, BIT(5)}, + {E_ALARM_MODE_EVERY_SATURDAY, BIT(6)}, + //独立日 +}; + + + +static u16 alm_set_p = 0xff; /* time_set_table的当前设置指针 */ + +static u8 __alm_search_by_mark(const char *mark) +{ + u16 p = 0; + u16 table_sum = sizeof(alm_set_table) / sizeof(struct time_setting); + while (p < table_sum) { + if (!strcmp(mark, alm_set_table[p].mark)) { + return p; + } + p++; + } + return -1; +} + +static u8 __alm_set_switch(enum sw_dir dir, const char *mark) +{ + u16 table_sum; + u16 prev_set_p = alm_set_p; + u8 p; + printf("__time_set_switch dir: %d\n", dir); + table_sum = sizeof(alm_set_table) / sizeof(struct time_setting); + ASSERT(dir == DIR_NEXT || dir == DIR_PREV || dir == DIR_SET); + switch (dir) { + case DIR_NEXT: + if (alm_set_p >= (table_sum - 1)) { + alm_set_p = 0; + } else { + alm_set_p++; + } + break; + case DIR_PREV: + if (alm_set_p >= (table_sum - 1)) { + alm_set_p = 0; + } + + if (alm_set_p == 0) { + alm_set_p = (table_sum - 1); + } else { + alm_set_p--; + } + break; + case DIR_SET: + p = __alm_search_by_mark(mark); + if (p == (u8) - 1) { + return -1; + } + alm_set_p = p; + break; + } + + if (prev_set_p != 0xff && alm_set_table[prev_set_p].time_id) { + ui_no_highlight_element_by_id(alm_set_table[prev_set_p].time_id); + } + + + if (alm_set_table[alm_set_p].time_id) { + ui_highlight_element_by_id(alm_set_table[alm_set_p].time_id); + } + + printf("__time_set_switch ok.\n"); + return 0; +} + +static u8 __alm_set_reset(void) +{ + T_ALARM alarm; + alm_set_p = 0xff; + alarm_get_info(&alarm, 0); + alm_set_table[0].time_value = alarm.time.hour; + alm_set_table[1].time_value = alarm.time.min; + + for (int i = 0; i < sizeof(alm_rep) / sizeof(alm_rep[0]); i++) { + if (alm_rep[i].rep_set == alarm.mode) { + alm_set_table[2].time_value = i; + break; + } + } + + alm_set_table[3].time_value = alarm.sw; + return 0; +} + +static u8 __alm_update_show(u8 pos) /* 更新单个时间控件的时间 */ +{ + struct utime t; + t.hour = alm_set_table[0].time_value; + t.min = alm_set_table[1].time_value; + int rep_set = alm_set_table[2].time_value; + int sw = alm_set_table[3].time_value; + + if (pos == 2) { // + for (int i = 0; i < sizeof(alm_rep_list) / sizeof(alm_rep_list[0]); i++) { + if (BIT(i) & alm_rep[rep_set].mask) { + ui_highlight_element_by_id(alm_rep_list[i]); + } else { + ui_no_highlight_element_by_id(alm_rep_list[i]); + } + } + return 0; + } + + if (pos == 3) { //开关 + if (sw) { + ui_text_show_index_by_id(alm_set_table[pos].time_id, 1); + } else { + ui_text_show_index_by_id(alm_set_table[pos].time_id, 0); + } + + return 0; + } + + ui_time_update_by_id(alm_set_table[pos].time_id, &t); + return 0; +} + +static u8 __alm_set_value(enum set_mod mod, u16 value) +{ + enum set_mod need_check = 0; + u16 year, month, day; + ASSERT(mod == MOD_ADD || mod == MOD_DEC || mod == MOD_SET); + switch (mod) { + case MOD_ADD: + switch (alm_set_p) { + case 0: /* hour */ + value = alm_set_table[alm_set_p].time_value + 1; + if (value > 23) { + value = 0; + } + break; + case 1: /* min */ + value = alm_set_table[alm_set_p].time_value + 1; + if (value > 59) { + value = 0; + } + break; + case 2: /* rep */ + value = alm_set_table[alm_set_p].time_value + 1; + if (value >= sizeof(alm_rep) / sizeof(alm_rep[0])) { + value = 0; + } + break; + case 3: /* sw */ + value = !alm_set_table[alm_set_p].time_value; + break; + default: + /* ASSERT(0, "mod_add time_set_p:%d err!", time_set_p); */ + return 0; + break; + } + break; + case MOD_DEC: + switch (alm_set_p) { + case 0: /* hour */ + value = alm_set_table[alm_set_p].time_value; + if (value == 0) { + value = 23; + } else { + value--; + } + break; + case 1: /* min */ + value = alm_set_table[alm_set_p].time_value; + if (value == 0) { + value = 59; + } else { + value--; + } + break; + case 2://rep + value = alm_set_table[alm_set_p].time_value; + if (value == 0) { + value = sizeof(alm_rep) / sizeof(alm_rep[0]) - 1; + } else { + value--; + } + break; + case 3: /* sw */ + value = !alm_set_table[alm_set_p].time_value; + break; + default: + /* ASSERT(0, "mod_dec time_set_p:%d err!", time_set_p); */ + return 0; + break; + } + break; + case MOD_SET: + switch (alm_set_p) { + case 0: /* hour */ + ASSERT(value >= 0 && value <= 23); + break; + case 1: /* min */ + ASSERT(value >= 0 && value <= 59); + break; + default: + /* ASSERT(0, "mod_set time_set_p:%d err!", time_set_p); */ + return 0; + break; + } + break; + } + + alm_set_table[alm_set_p].time_value = value; + + __alm_update_show(alm_set_p); /* 更新当前位数值显示 */ + + return 0; +} + + +static int menu_sys_alm_set() +{ + u8 index = 0; + T_ALARM alarm; + alarm.time.hour = alm_set_table[0].time_value ; + alarm.time.min = alm_set_table[1].time_value; + alarm.mode = alm_rep[alm_set_table[2].time_value].rep_set; + alarm.sw = alm_set_table[3].time_value; + alarm.index = index; + alarm_add(&alarm, index); + return 0; +} + + +static void __alm_set_switch_init(int id) +{ + __alm_set_switch(DIR_SET, NULL); +} + +static int alm_layout_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct layout *layout = (struct layout *)ctr; + switch (e) { + case ON_CHANGE_INIT: + puts("time_layout_onchange onfocus.\n"); + layout_on_focus(layout); + __alm_set_reset(); + break; + case ON_CHANGE_RELEASE: + puts("time_layout_onchange losefocus.\n"); + layout_lose_focus(layout); + break; + case ON_CHANGE_FIRST_SHOW: + puts("time_layout_onchange ON_CHANGE_FIRST_SHOW.\n"); + ui_set_call(__time_set_switch_init, 0); + + break; + default: + break; + } + return FALSE; +} +static int alm_layout_onkey(void *ctr, struct element_key_event *e) +{ + + switch (e->value) { + case KEY_OK: + puts("time_layout_onkey KEY_OK.\n"); + __alm_set_switch(DIR_NEXT, NULL); + + break; + case KEY_DOWN: + __alm_set_value(MOD_ADD, 0); + + break; + case KEY_UP: + __alm_set_value(MOD_DEC, 0); + + break; + case KEY_MODE: + case KEY_MENU: + menu_sys_alm_set(); + ui_hide(CLOCK_ALM_SET_LAYOUT); + break; + default: + return false; + break; + } + + return true; +} + +REGISTER_UI_EVENT_HANDLER(CLOCK_ALM_SET_LAYOUT) +.onchange = alm_layout_onchange, + .onkey = alm_layout_onkey, + .ontouch = NULL, +}; + + + +/***************************** 闹钟各个数字动作 ************************************/ +static int alm_timer_sys_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_time *time = (struct ui_time *)ctr; + switch (e) { + case ON_CHANGE_INIT: + puts("timer_sys_onchange .\n"); + time->hour = alm_set_table[0].time_value; + time->min = alm_set_table[1].time_value; + break; + case ON_CHANGE_SHOW_POST: +#if 0 + printf("~~~~~~~~~~~~%x\n", time->text.elm.id); + if (time->text.elm.highlight) { + printf("~~~~~~~~~~~~%x\n", time->text.elm.id); + /* ui_invert_element_by_id(time->text.elm.id); */ + } +#endif + break; + default: + return FALSE; + } + return FALSE; +} + +REGISTER_UI_EVENT_HANDLER(ALM_H) +.onchange = alm_timer_sys_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +REGISTER_UI_EVENT_HANDLER(ALM_M) +.onchange = alm_timer_sys_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + +static int alm_timer_rep_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_text *text = (struct ui_text *)ctr; + switch (e) { + case ON_CHANGE_INIT: + for (int i = 0; i < sizeof(alm_rep_list) / sizeof(alm_rep_list[0]); i++) { + if (text->elm.id == alm_rep_list[i]) { + if (BIT(i) & alm_rep[alm_set_table[2].time_value].mask) { + ui_highlight_element(&text->elm); + /* text->elm.highlight = 1; */ + } + break; + } + } + break; + case ON_CHANGE_SHOW_POST: + break; + default: + return FALSE; + } + return FALSE; +} + +REGISTER_UI_EVENT_HANDLER(ALM_SUN) +.onchange = alm_timer_rep_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +REGISTER_UI_EVENT_HANDLER(ALM_MON) +.onchange = alm_timer_rep_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +REGISTER_UI_EVENT_HANDLER(ALM_TUE) +.onchange = alm_timer_rep_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +REGISTER_UI_EVENT_HANDLER(ALM_WED) +.onchange = alm_timer_rep_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + +REGISTER_UI_EVENT_HANDLER(ALM_THU) +.onchange = alm_timer_rep_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +REGISTER_UI_EVENT_HANDLER(ALM_FRI) +.onchange = alm_timer_rep_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +REGISTER_UI_EVENT_HANDLER(ALM_SAT) +.onchange = alm_timer_rep_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +static int alm_timer_sw_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_text *text = (struct ui_text *)ctr; + switch (e) { + case ON_CHANGE_INIT: + if (alm_set_table[3].time_value) { + ui_text_set_index(text, 1); + } else { + ui_text_set_index(text, 0); + } + break; + case ON_CHANGE_SHOW_POST: + break; + default: + return FALSE; + } + return FALSE; +} + + +REGISTER_UI_EVENT_HANDLER(ALM_SW) +.onchange = alm_timer_sw_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +#endif //#if (TCFG_APP_RTC_EN) +#endif diff --git a/apps/soundbox/ui/lcd/STYLE_02/file_brower.c b/apps/soundbox/ui/lcd/STYLE_02/file_brower.c new file mode 100644 index 0000000..bf15181 --- /dev/null +++ b/apps/soundbox/ui/lcd/STYLE_02/file_brower.c @@ -0,0 +1,371 @@ +#include "ui/ui.h" +#include "app_config.h" +#include "ui/ui_api.h" +#include "system/timer.h" +#include "key_event_deal.h" +#include "audio_config.h" +#include "jiffies.h" +#include "app_power_manage.h" +#include "asm/charge.h" +#include "audio_dec_file.h" +#include "music/music_player.h" +#ifndef CONFIG_MEDIA_NEW_ENABLE +#include "media/audio_eq_drc_apply.h" +#else +#include "audio_eq.h" +#endif + + + + + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX)) + +#define STYLE_NAME JL//必须要 + +extern int ui_hide_main(int id); +extern int ui_show_main(int id); +extern void key_ui_takeover(u8 on); + + +//文件浏览部分 + +#define TEXT_NAME_LEN (128) +#define TEXT_SHORT_NAME_LEN (13)//8.3+1 +#define TEXT_PAGE (4) +struct text_name_t { + u16 len; + u8 unicode; + u8 fname[TEXT_NAME_LEN]; + u8 fsname[TEXT_SHORT_NAME_LEN]; + int index; +}; + + + +struct grid_set_info { + int flist_index; //文件列表首项所指的索引 + int open_index; //所打开的文件所指的索引(未) + int cur_total; + const char *disk_name[4]; + u8 in_scan;//是否在盘内 + u8 disk_total; + FILE *file; + struct vfscan *fs; + struct text_name_t text_list[TEXT_PAGE]; + struct vfs_attr attr[TEXT_PAGE]; +#if (TCFG_LFN_EN) + u8 lfn_buf[512]; +#endif//TCFG_LFN_EN + +}; + +static struct grid_set_info *handler = NULL; +#define __this (handler) +#define sizeof_this (sizeof(struct grid_set_info)) + +static u32 LAYOUT_FNAME_LIST_ID[] = { + FILE_LAYOUT_0, + FILE_LAYOUT_1, + FILE_LAYOUT_2, + FILE_LAYOUT_3, +}; + +static u32 TEXT_FNAME_ID[] = { + FILE_BROWSE_TEXT_0, + FILE_BROWSE_TEXT_1, + FILE_BROWSE_TEXT_2, + FILE_BROWSE_TEXT_3, +}; + +static u32 PIC_FNAME_ID[] = { + FILE_BROWSE_PIC_0, + FILE_BROWSE_PIC_1, + FILE_BROWSE_PIC_2, + FILE_BROWSE_PIC_3, +}; + + + + +static int __get_ui_max_num() +{ + return sizeof(TEXT_FNAME_ID) / sizeof(TEXT_FNAME_ID[0]); +} + +static const u8 MUSIC_SCAN_PARAM[] = "-t" + "MP1MP2MP3" + " -sn -d" + ; + + +static int file_select_enter(int from_index) +{ + + int one_page_num = sizeof(TEXT_FNAME_ID) / sizeof(TEXT_FNAME_ID[0]); + int i = 0; + i = from_index % one_page_num; + if (__this->attr[i].attr == F_ATTR_DIR) { //判断是不是文件夹文件属性 + if (!from_index) { + __this->fs = fscan_exitdir(__this->fs); + } else { + __this->fs = fscan_enterdir(__this->fs, __this->text_list[i].fsname); + } + + if (!__this->fs) { + ui_hide(MUSIC_FILE_LAYOUT); + ui_hide(MUSIC_MENU_LAYOUT); + return false; + } + + + __this->cur_total = __this->fs->file_number + 1; + return TRUE; + } else { + /* if (!strcmp(cur->name, APP_NAME_MUSIC)) {//当前在目标app内,则只要显示出目标页面即可 */ + app_task_put_key_msg(KEY_MUSIC_PLAYE_BY_DEV_SCLUST, __this->attr[i].sclust); + /* music_play_file_by_dev_sclust(__this->dev->logo, __this->attr[i].sclust);///this is a demo */ + ui_hide(MUSIC_FILE_LAYOUT); + ui_hide(MUSIC_MENU_LAYOUT); + /* } */ + } + return false; +} + +static int file_list_flush(int from_index) +{ + FILE *f = NULL; + int one_page_num = sizeof(TEXT_FNAME_ID) / sizeof(TEXT_FNAME_ID[0]); + int i = 0; + int end_index = from_index + one_page_num; + char *name_buf = NULL; + + for (i = 0; i < sizeof(TEXT_FNAME_ID) / sizeof(TEXT_FNAME_ID[0]); i++) { + memset(__this->text_list[i].fname, 0, TEXT_NAME_LEN); + __this->text_list[i].len = 0; + } + +__find: + i = from_index % one_page_num; + if (from_index == 0) { + sprintf(__this->text_list[i].fname, "%s", ".."); + sprintf(__this->text_list[i].fsname, "%s", ".."); + __this->attr[i].attr = F_ATTR_DIR; + __this->text_list[i].unicode = 0; + __this->text_list[i].len = strlen(__this->text_list[i].fname); + } else { + f = fselect(__this->fs, FSEL_BY_NUMBER, from_index); + } + + if (f) { + name_buf = malloc(TEXT_NAME_LEN); + __this->text_list[i].len = fget_name(f, name_buf, TEXT_NAME_LEN); + if (name_buf[0] == '\\' && name_buf[1] == 'U') { + __this->text_list[i].len -= 2; + __this->text_list[i].unicode = 1; + memcpy(__this->text_list[i].fname, name_buf + 2, TEXT_NAME_LEN - 2); + } else { + __this->text_list[i].unicode = 0; + memcpy(__this->text_list[i].fname, name_buf, TEXT_NAME_LEN); + } + free(name_buf); + name_buf = NULL; + printf("\n--func=%s, line=%d\n", __FUNCTION__, __LINE__); + printf("flush [%d]=%s\n", i, __this->text_list[i].fname); + fget_attrs(f, &__this->attr[i]); + if (__this->attr[i].attr == F_ATTR_DIR) { //判断是不是文件夹文件属性,文件夹需要获取短文件名 + fget_name(f, __this->text_list[i].fsname, TEXT_SHORT_NAME_LEN); + } + fclose(f); + f = NULL; + } + + from_index++; + if (from_index < __this->cur_total && from_index < end_index) { + goto __find; + } + + + for (i = 0; i < sizeof(TEXT_FNAME_ID) / sizeof(TEXT_FNAME_ID[0]); i++) { + if (__this->text_list[i].len) { + if (__this->text_list[i].unicode) { + ui_text_set_textw_by_id(TEXT_FNAME_ID[i], __this->text_list[i].fname, __this->text_list[i].len, FONT_ENDIAN_SMALL, FONT_DEFAULT | FONT_HIGHLIGHT_SCROLL); + } else { + ui_text_set_text_by_id(TEXT_FNAME_ID[i], __this->text_list[i].fname, __this->text_list[i].len, FONT_DEFAULT); + } + if (__this->attr[i].attr == F_ATTR_DIR) { + ui_pic_show_image_by_id(PIC_FNAME_ID[i], 1); + } else { + ui_pic_show_image_by_id(PIC_FNAME_ID[i], 0); + } + if (ui_get_disp_status_by_id(PIC_FNAME_ID[i]) != true) { + ui_show(PIC_FNAME_ID[i]); + } + } else { + ui_text_set_text_by_id(TEXT_FNAME_ID[i], __this->text_list[i].fname, __this->text_list[i].len, FONT_DEFAULT); + if (ui_get_disp_status_by_id(PIC_FNAME_ID[i]) == true) { + ui_hide(PIC_FNAME_ID[i]); + } + } + + } + return 0; +} + + +static int file_browse_enter_onchane(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + int fnum = 0; + + switch (e) { + case ON_CHANGE_INIT: + if (!__this) { + __this = zalloc(sizeof_this); + } + + if (!__this->fs) { + if (!dev_manager_get_total(1)) { + break; + } + + void *dev = dev_manager_find_active(1); + if (!dev) { + break; + } + __this->fs = fscan(dev_manager_get_root_path(dev), MUSIC_SCAN_PARAM, 9); +#if (TCFG_LFN_EN) + if (__this->fs) { + fset_lfn_buf(__this->fs, __this->lfn_buf); + } +#endif + printf(">>> file number=%d \n", __this->fs->file_number); + fnum = (__this->fs->file_number + 1 > __get_ui_max_num()) ? __get_ui_max_num() : __this->fs->file_number + 1; + __this->cur_total = __this->fs->file_number + 1; + } + break; + case ON_CHANGE_RELEASE: + if (__this->fs) { + fscan_release(__this->fs); + __this->fs = NULL; + } + + if (__this) { + free(__this); + __this = NULL; + } + + break; + case ON_CHANGE_FIRST_SHOW: + if (__this->open_index) { + //从回放返回文件列表时 + ui_set_call(file_list_flush, __this->flist_index); + } else { + ui_set_call(file_list_flush, 0); + /* file_list_flush(0); */ + //刚进去文件列表时 + __this->flist_index = 0; + } + break; + default: + return false; + } + return false; +} + +static int file_browse_onkey(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + sel_item = ui_grid_cur_item(grid); + switch (e->value) { + case KEY_OK: + if (file_select_enter(__this->flist_index)) { + ui_no_highlight_element_by_id(LAYOUT_FNAME_LIST_ID[sel_item]); + __this->flist_index = 0; + file_list_flush(__this->flist_index); + ui_grid_set_item(grid, 0); + ui_highlight_element_by_id(LAYOUT_FNAME_LIST_ID[0]); + } + + + break; + case KEY_DOWN: + + sel_item++; + + __this->flist_index += 1; + + if (sel_item >= __this->cur_total || __this->flist_index >= __this->cur_total) { + //大于文件数 + ui_no_highlight_element_by_id(LAYOUT_FNAME_LIST_ID[sel_item - 1]); + __this->flist_index = 0; + file_list_flush(__this->flist_index); + ui_grid_set_item(grid, 0); + ui_highlight_element_by_id(LAYOUT_FNAME_LIST_ID[0]); + ui_vslider_set_persent_by_id(MUSIC_FILE_SLIDER, (__this->flist_index + 1) * 100 / __this->cur_total); + return TRUE; + } + ui_vslider_set_persent_by_id(MUSIC_FILE_SLIDER, (__this->flist_index + 1) * 100 / __this->cur_total); + if (sel_item >= TEXT_PAGE) { + ui_no_highlight_element_by_id(LAYOUT_FNAME_LIST_ID[sel_item - 1]); + file_list_flush(__this->flist_index); + ui_grid_set_item(grid, 0); + ui_highlight_element_by_id(LAYOUT_FNAME_LIST_ID[0]); + return true; //不返回到首项 + } + + return FALSE; + + break; + case KEY_UP: + if (sel_item == 0) { + __this->flist_index = __this->flist_index ? __this->flist_index - 1 : __this->cur_total - 1; + ui_no_highlight_element_by_id(LAYOUT_FNAME_LIST_ID[sel_item]); + file_list_flush(__this->flist_index / TEXT_PAGE * TEXT_PAGE); + ui_grid_set_item(grid, __this->flist_index % TEXT_PAGE); + ui_highlight_element_by_id(LAYOUT_FNAME_LIST_ID[__this->flist_index % TEXT_PAGE]); + ui_vslider_set_persent_by_id(MUSIC_FILE_SLIDER, (__this->flist_index + 1) * 100 / __this->cur_total); + return true; //不跳转到最后一项 + } + __this->flist_index--; + ui_vslider_set_persent_by_id(MUSIC_FILE_SLIDER, (__this->flist_index + 1) * 100 / __this->cur_total); + return FALSE; + break; + + default: + return false; + } + return false; +} + +REGISTER_UI_EVENT_HANDLER(MUSIC_FILE_BROWSE) +.onchange = file_browse_enter_onchane, + .onkey = file_browse_onkey, + .ontouch = NULL, +}; + + + + + + + + + + + + + + + + + + + + + + + +#endif diff --git a/apps/soundbox/ui/lcd/STYLE_02/fm_action.c b/apps/soundbox/ui/lcd/STYLE_02/fm_action.c new file mode 100644 index 0000000..fdb2e71 --- /dev/null +++ b/apps/soundbox/ui/lcd/STYLE_02/fm_action.c @@ -0,0 +1,478 @@ +#include "ui/ui.h" +#include "app_config.h" +#include "ui/ui_style.h" +#include "ui/ui_api.h" +#include "app_task.h" +#include "system/timer.h" +#include "key_event_deal.h" +#include "audio_config.h" +#include "jiffies.h" +#include "fm/fm_api.h" +#include "fm/fm_rw.h" +#include "app_power_manage.h" +#include "asm/charge.h" +#ifndef CONFIG_MEDIA_NEW_ENABLE +#include "media/audio_eq_drc_apply.h" +#else +#include "audio_eq.h" +#endif + + + + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX)) +#if (TCFG_APP_FM_EN) + +#define STYLE_NAME JL + +extern int ui_hide_main(int id); +extern int ui_show_main(int id); +extern void key_ui_takeover(u8 on); +extern int fm_server_msg_post(int msg); +extern void fm_volume_up(); +extern void fm_volume_down(); +extern void power_off_deal(struct sys_event *event, u8 step); + +extern u8 fm_get_cur_channel(void); + +static int fm_fre_handler(const char *type, u32 arg) +{ + printf(">>%s\n", __FUNCTION__); + u16 fre = fm_manage_get_fre();//8750 + + struct unumber num; + num.type = TYPE_NUM; + num.numbs = 2; + num.number[0] = fm_get_cur_channel(); + num.number[1] = get_total_mem_channel(); + ui_number_update_by_id(FM_CH, &num); + + num.numbs = 2; + num.number[0] = fre / 100 % 1000; + num.number[1] = fre / 10 % 10; + ui_number_update_by_id(FM_FREQ, &num); + //显示进度图标是从87开始 + ui_slider_set_persent_by_id(FM_SLIDER, (fre - 8700) * 100 / (REAL_FREQ_MAX - 8700)); + + return 0; +} + +static const struct uimsg_handl ui_msg_handler[] = { + { "fm_fre", fm_fre_handler }, /* 设置fm频率显示*/ + { NULL, NULL}, /* 必须以此结尾! */ +}; + + +static int fm_mode_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct window *window = (struct window *)ctr; + switch (e) { + case ON_CHANGE_INIT: + puts("\n***fm_mode_onchange***\n"); + /* key_ui_takeover(1); */ + ui_register_msg_handler(ID_WINDOW_FM, ui_msg_handler); + /* + * 注册APP消息响应 + */ + break; + case ON_CHANGE_RELEASE: + /* + * 要隐藏一下系统菜单页面,防止在系统菜单插入USB进入USB页面 + */ + break; + default: + return false; + } + return false; +} + + + +REGISTER_UI_EVENT_HANDLER(ID_WINDOW_FM) +.onchange = fm_mode_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + + +static void fm_layout_init(int id) +{ + u16 fre = fm_manage_get_fre();//8750 + + struct unumber num; + num.type = TYPE_NUM; + num.numbs = 2; + num.number[0] = fm_get_cur_channel(); + num.number[1] = get_total_mem_channel(); + ui_number_update_by_id(FM_CH, &num); + + num.numbs = 2; + num.number[0] = fre / 100 % 1000; + num.number[1] = fre / 10 % 10; + ui_number_update_by_id(FM_FREQ, &num); + //显示进度图标是从87开始 + ui_slider_set_persent_by_id(FM_SLIDER, (fre - 8700) * 100 / (REAL_FREQ_MAX - 8700)); +} + +static int fm_layout_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct layout *layout = (struct layout *)ctr; + switch (e) { + case ON_CHANGE_INIT: + layout_on_focus(layout); + ui_set_call(fm_layout_init, 0); + break; + case ON_CHANGE_RELEASE: + layout_lose_focus(layout); + break; + case ON_CHANGE_FIRST_SHOW: + break; + default: + break; + } + return FALSE; +} + + +static void fm_vol_timeout(void *p); +static int fm_layout_onkey(void *ctr, struct element_key_event *e) +{ + printf("fm_layout_onkey %d\n", e->value); + switch (e->value) { + case KEY_MENU: + if (ui_get_disp_status_by_id(FM_MENU_LAYOUT) <= 0) { + printf("FM_MENU_LAYOUT\n"); + ui_show(FM_MENU_LAYOUT); + } + break; + case KEY_UP: + app_task_put_key_msg(KEY_FM_PREV_FREQ, 0); + break; + case KEY_DOWN: + app_task_put_key_msg(KEY_FM_NEXT_FREQ, 0); + break; + case KEY_VOLUME_INC: + case KEY_VOLUME_DEC: + if (ui_get_disp_status_by_id(FM_VOL_LAYOUT) <= 0) { + ui_show(FM_VOL_LAYOUT); + } + break; + case KEY_MODE: + ui_hide_curr_main(); + ui_show_main(ID_WINDOW_SYS); + break; + case KEY_POWER_START: + case KEY_POWER: + power_off_deal(NULL, e->value - KEY_POWER_START); + break; + default: + return false; + break; + } + return true; +} + + + + +REGISTER_UI_EVENT_HANDLER(FM_LAYOUT) +.onchange = fm_layout_onchange, + .onkey = fm_layout_onkey, + .ontouch = NULL, +}; + + + + +static int fm_menu_list_onkey(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + int sel_item = 0; + printf("ui key %s %d\n", __FUNCTION__, e->value); + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + switch (sel_item) { + case 0: + app_task_put_key_msg(KEY_FM_SCAN_ALL, 0); + ui_hide(FM_MENU_LAYOUT); + break; + case 1: + /* fm_server_msg_post(FM_DEL_FREQ); */ + ui_hide(FM_MENU_LAYOUT); + break; + case 2: + ui_hide(FM_MENU_LAYOUT); + break; + } + break; + default: + return false; + } + return false; +} + + + +REGISTER_UI_EVENT_HANDLER(FM_MENU_LIST) +.onchange = NULL, + .onkey = fm_menu_list_onkey, + .ontouch = NULL, +}; + + + +static u16 fm_timer = 0; +static void fm_vol_timeout(void *p) +{ + int id = (int)(p); + if (ui_get_disp_status_by_id(id) == TRUE) { + ui_hide(id); + } + fm_timer = 0; +} + + +static int fm_vol_layout_onkey(void *ctr, struct element_key_event *e) +{ + printf("bt_vol_layout_onkey %d\n", e->value); + struct unumber num; + u8 vol; + + if (fm_timer) { + sys_timer_modify(fm_timer, 3000); + } + + switch (e->value) { + case KEY_MENU: + break; + case KEY_UP: + case KEY_VOLUME_INC: + fm_volume_up(); + vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = vol; + ui_number_update_by_id(FM_VOL_NUM, &num); + break; + case KEY_DOWN: + case KEY_VOLUME_DEC: + fm_volume_down(); + vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = vol; + ui_number_update_by_id(FM_VOL_NUM, &num); + break; + default: + return false; + break; + } + return true; +} + + +static void vol_init(int id) +{ + struct unumber num; + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + ui_number_update_by_id(FM_VOL_NUM, &num); +} + + + +static int fm_vol_layout_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct layout *layout = (struct layout *)ctr; + struct unumber num; + u8 vol; + switch (e) { + case ON_CHANGE_INIT: + layout_on_focus(layout); + if (!fm_timer) { + fm_timer = sys_timeout_add((void *)FM_VOL_LAYOUT, fm_vol_timeout, 3000); + } + + break; + case ON_CHANGE_RELEASE: + layout_lose_focus(layout); + if (fm_timer) { + sys_timeout_del(fm_timer); + fm_timer = 0; + } + break; + case ON_CHANGE_FIRST_SHOW: + ui_set_call(vol_init, 0); + break; + default: + break; + } + return FALSE; +} + + +REGISTER_UI_EVENT_HANDLER(FM_VOL_LAYOUT) +.onchange = fm_vol_layout_onchange, + .onkey = fm_vol_layout_onkey, + .ontouch = NULL, +}; + + +/************************************************************ + fm模式控件初始化 + ************************************************************/ + + +static int fm_slider_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_slider *slider = (struct ui_slider *)ctr; + u16 fre = 0; + switch (e) { + case ON_CHANGE_INIT: + fre = fm_manage_get_fre();//8750 + slider->persent = VIRTUAL_FREQ(fre) * 100 / MAX_CHANNEL; + break; + default: + return FALSE; + } + return FALSE; +} + + + +REGISTER_UI_EVENT_HANDLER(FM_SLIDER) +.onchange = fm_slider_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + +static int fm_vol_num_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_number *num = (struct ui_number *)ctr; + switch (e) { + case ON_CHANGE_INIT: + num->nums = 1; + num->number[0] = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + break; + default: + return FALSE; + } + return FALSE; +} +REGISTER_UI_EVENT_HANDLER(FM_VOL_NUM) +.onchange = fm_vol_num_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +static int fm_ch_num_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_number *num = (struct ui_number *)ctr; + switch (e) { + case ON_CHANGE_INIT: + num->nums = 2; + num->number[0] = fm_get_cur_channel(); + num->number[1] = get_total_mem_channel(); + break; + default: + return FALSE; + } + return FALSE; +} + + + +REGISTER_UI_EVENT_HANDLER(FM_CH) +.onchange = fm_ch_num_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + +static int fm_freq_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_number *num = (struct ui_number *)ctr; + u16 fre = 0; + switch (e) { + case ON_CHANGE_INIT: + fre = fm_manage_get_fre();//8750 + num->nums = 2; + num->number[0] = fre / 100 % 1000; + num->number[1] = fre / 10 % 10; + break; + default: + return FALSE; + } + return FALSE; +} + + + +REGISTER_UI_EVENT_HANDLER(FM_FREQ) +.onchange = fm_freq_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +static void battery_timer(void *priv) +{ + int incharge = 0;//充电标志 + int id = (int)(priv); + static u8 percent = 0; + static u8 percent_last = 0; + if (get_charge_online_flag()) { //充电时候图标动态效果 + if (percent > get_vbat_percent()) { + percent = 0; + } + ui_battery_set_level_by_id(id, percent, incharge); //充电标志,ui可以显示不一样的图标 + percent += 20; + } else { + + percent = get_vbat_percent(); + if (percent != percent_last) { + ui_battery_set_level_by_id(id, percent, incharge); //充电标志,ui可以显示不一样的图标,需要工具设置 + percent_last = percent; + } + + } +} + +static int battery_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_battery *battery = (struct ui_battery *)ctr; + static u32 timer = 0; + int incharge = 0;//充电标志 + + switch (e) { + case ON_CHANGE_INIT: + ui_battery_set_level(battery, get_vbat_percent(), incharge); + if (!timer) { + timer = sys_timer_add((void *)battery->elm.id, battery_timer, 1 * 1000); //传入的id就是BT_BAT + } + break; + case ON_CHANGE_FIRST_SHOW: + break; + case ON_CHANGE_RELEASE: + if (timer) { + sys_timer_del(timer); + timer = 0; + } + break; + default: + return false; + } + return false; +} +REGISTER_UI_EVENT_HANDLER(FM_BAT) +.onchange = battery_onchange, + .ontouch = NULL, +}; + + + +#endif //#if (TCFG_APP_FM_EN) +#endif diff --git a/apps/soundbox/ui/lcd/STYLE_02/linein_action.c b/apps/soundbox/ui/lcd/STYLE_02/linein_action.c new file mode 100644 index 0000000..4dcb6a8 --- /dev/null +++ b/apps/soundbox/ui/lcd/STYLE_02/linein_action.c @@ -0,0 +1,425 @@ +#include "ui/ui.h" +#include "app_config.h" +#include "ui/ui_style.h" +#include "ui/ui_api.h" +#include "audio_config.h" +#include "audio_enc/audio_enc.h" +#include "app_power_manage.h" +#include "app_task.h" +#include "key_event_deal.h" +#include "linein/linein.h" +#include "asm/charge.h" +#ifndef CONFIG_MEDIA_NEW_ENABLE +#include "media/audio_eq_drc_apply.h" +#else +#include "audio_eq.h" +#endif + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX)) +#define STYLE_NAME JL + +extern int ui_hide_main(int id); +extern int ui_show_main(int id); +extern void key_ui_takeover(u8 on); +extern void power_off_deal(struct sys_event *event, u8 step); + +/************************************************************ + linein模式主页窗口控件 +************************************************************/ +static int linein_mode_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct window *window = (struct window *)ctr; + switch (e) { + case ON_CHANGE_INIT: + puts("\n***linein_mode_onchange***\n"); + /* key_ui_takeover(1); */ + break; + case ON_CHANGE_RELEASE: + puts("\n***linein_mode_release***\n"); + break; + default: + return false; + } + return false; +} + + +REGISTER_UI_EVENT_HANDLER(ID_WINDOW_LINEIN) +.onchange = linein_mode_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +/************************************************************ + linein模式布局控件按键事件 + ************************************************************/ +static void linein_ui_first_show() +{ + u8 eq_mode = 0; + ui_pic_show_image_by_id(LINE_IN_PIC, 0); + ui_text_show_index_by_id(LINE_IN_TEXT, 0); + ui_no_highlight_element_by_id(LINE_IN_STATUS); +#if TCFG_EQ_ENABLE + eq_mode = eq_mode_get_cur(); + ui_pic_show_image_by_id(LINE_IN_EQ, eq_mode); +#endif +} + +static int linein_layout_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_text *text = (struct ui_text *)ctr; + switch (e) { + case ON_CHANGE_INIT: + break; + case ON_CHANGE_SHOW_PROBE: + break; + case ON_CHANGE_FIRST_SHOW: + ui_set_call(linein_ui_first_show, 0); + break; + default: + return FALSE; + } + return FALSE; +} + +static int linein_layout_onkey(void *ctr, struct element_key_event *e) +{ + printf("record_layout_onkey %d\n", e->value); + switch (e->value) { + case KEY_MENU: + ui_show(LINE_IN_MENU_LAYOUT); + break; + case KEY_OK: + app_task_put_key_msg(KEY_MUSIC_PP, 0); + if (linein_get_status()) { //显示暂停开始图标 + ui_highlight_element_by_id(LINE_IN_STATUS); + } else { + ui_no_highlight_element_by_id(LINE_IN_STATUS); + } + break; + case KEY_UP: + break; + case KEY_DOWN: + break; + case KEY_VOLUME_INC: + case KEY_VOLUME_DEC: + ui_show(LINE_IN_VOL_LAYOUT); + break; + case KEY_MODE: + UI_HIDE_CURR_WINDOW(); + ui_show_main(ID_WINDOW_SYS); + break; + case KEY_POWER_START: + case KEY_POWER: + power_off_deal(NULL, e->value - KEY_POWER_START); + break; + default: + return false; + break; + } + return false; +} + +REGISTER_UI_EVENT_HANDLER(LINE_IN_LAYOUT) +.onchange = linein_layout_onchange, + .onkey = linein_layout_onkey, + .ontouch = NULL, +}; + +/************************************************************ + LINEIN模式主菜单列表按键事件 + ************************************************************/ + +static int linein_enter_callback(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + switch (sel_item) { + case 0: + ui_show(LINE_IN_EQ_LAYOUT); + break; + case 1: + ui_hide(LINE_IN_MENU_LAYOUT); + break; + default: + break; + } + break; + default: + return false; + } + return TRUE; +} + +REGISTER_UI_EVENT_HANDLER(LINE_IN_MENU_LIST) +.onchange = NULL, + .onkey = linein_enter_callback, + .ontouch = NULL, +}; + +/************************************************************ + LINEIN模式eq菜单列表按键事件 + ************************************************************/ + +static const int eq_mode_pic[] = { + LINE_IN_EQ_NORMAL_PIC, + LINE_IN_EQ_ROCK_PIC, + LINE_IN_EQ_POP_PIC, + LINE_IN_EQ_CLASSIC_PIC, + LINE_IN_EQ_JAZZ_PIC, + LINE_IN_EQ_COUNTRY_PIC, +}; + +#if TCFG_EQ_ENABLE +static int eq_pic_common_onchange(void *_ctrl, enum element_change_event event, void *arg) +{ + struct ui_pic *pic = (struct ui_pic *)_ctrl; + switch (event) { + case ON_CHANGE_INIT: + if (pic->elm.id == eq_mode_pic[eq_mode_get_cur() % 6]) { + ui_pic_set_image_index(pic, 1); + } + break; + case ON_CHANGE_SHOW_POST: + break; + default: + return FALSE; + } + return FALSE; +} + +REGISTER_UI_EVENT_HANDLER(LINE_IN_EQ_NORMAL_PIC) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(LINE_IN_EQ_ROCK_PIC) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(LINE_IN_EQ_POP_PIC) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(LINE_IN_EQ_CLASSIC_PIC) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(LINE_IN_EQ_JAZZ_PIC) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(LINE_IN_EQ_COUNTRY_PIC) +.onchange = eq_pic_common_onchange, +}; +#endif + +static int linein_eq_menu_list_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + int list = 0; + switch (e) { + case ON_CHANGE_INIT: + printf("ON_CHANGE_INIT %d \n", grid->avail_item_num); + break; + } + return false; +} + +static int linein_eq_callback(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + switch (sel_item) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: +#if TCFG_EQ_ENABLE + eq_mode_set(sel_item); + ui_pic_show_image_by_id(LINE_IN_EQ, sel_item); +#endif + case 6: + ui_hide(LINE_IN_EQ_LAYOUT); + break; + } + break; + default: + return false; + } + return TRUE; +} + + +REGISTER_UI_EVENT_HANDLER(LINE_IN_EQ_MENU_LIST) +.onchange = linein_eq_menu_list_onchange, + .onkey = linein_eq_callback, + .ontouch = NULL, +}; + +/************************************************************ + 音量设置布局控件 + ************************************************************/ +static u16 vol_timer = 0; +static void linein_vol_lay_timeout(void *p) +{ + int id = (int)(p); + if (ui_get_disp_status_by_id(id) == TRUE) { + ui_hide(id); + //ui_show(CLOCK_LAYOUT); + } + vol_timer = 0; +} + +static void vol_init(int id) +{ + struct unumber num; + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + ui_number_update_by_id(LINE_IN_VOL_NUM, &num); +} + +static int linein_vol_layout_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct layout *layout = (struct layout *)ctr; + switch (e) { + case ON_CHANGE_INIT: + if (!vol_timer) { + vol_timer = sys_timer_add((void *)layout->elm.id, linein_vol_lay_timeout, 3000); + } + break; + + case ON_CHANGE_FIRST_SHOW: + ui_set_call(vol_init, 0); + /* ui_number_update_by_id(CLOCK_VOL_NUM,&num); */ + break; + + case ON_CHANGE_SHOW_POST: + break; + + case ON_CHANGE_RELEASE: + if (vol_timer) { + sys_timeout_del(vol_timer); + vol_timer = 0; + } + break; + default: + return FALSE; + } + return FALSE; +} + + +static int linein_vol_layout_onkey(void *ctr, struct element_key_event *e) +{ + printf("clock_vol_layout_onkey %d\n", e->value); + struct unumber num; + u8 vol; + + if (vol_timer) { + sys_timer_modify(vol_timer, 3000); + } + + switch (e->value) { + case KEY_MENU: + break; + + case KEY_UP: + case KEY_VOLUME_INC: + linein_key_vol_up(); + //app_audio_volume_up(1); + vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = vol; + ui_number_update_by_id(LINE_IN_VOL_NUM, &num); + break; + case KEY_DOWN: + case KEY_VOLUME_DEC: + linein_key_vol_down(); + // app_audio_volume_down(1); + vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = vol; + ui_number_update_by_id(LINE_IN_VOL_NUM, &num); + break; + default: + return false; + break; + } + return true; +} + +REGISTER_UI_EVENT_HANDLER(LINE_IN_VOL_LAYOUT) +.onchange = linein_vol_layout_onchange, + .onkey = linein_vol_layout_onkey, + .ontouch = NULL, +}; + + + +/************************************************************ + 电池控件事件 + ************************************************************/ + +static void battery_timer(void *priv) +{ + int incharge = 0;//充电标志 + int id = (int)(priv); + static u8 percent = 0; + static u8 percent_last = 0; + if (1 || get_charge_online_flag()) { //充电时候图标动态效果,get_charge_online_flag()在内置充电的时候获取是否正在充电,外置充电根据电路来编写接口 + if (percent > get_vbat_percent()) { + percent = 0; + } + ui_battery_set_level_by_id(id, percent, incharge); //充电标志,ui可以显示不一样的图标 + percent += 20; + } else { + + percent = get_vbat_percent(); + if (percent != percent_last) { + ui_battery_set_level_by_id(id, percent, incharge); //充电标志,ui可以显示不一样的图标,需要工具设置 + percent_last = percent; + } + + } +} + +static int battery_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_battery *battery = (struct ui_battery *)ctr; + static u32 timer = 0; + int incharge = 0;//充电标志 + + switch (e) { + case ON_CHANGE_INIT: + ui_battery_set_level(battery, get_vbat_percent(), incharge); + if (!timer) { + timer = sys_timer_add((void *)battery->elm.id, battery_timer, 1 * 1000); //传入的id就是BT_BAT + } + break; + case ON_CHANGE_FIRST_SHOW: + break; + case ON_CHANGE_RELEASE: + if (timer) { + sys_timer_del(timer); + timer = 0; + } + break; + default: + return false; + } + return false; +} +REGISTER_UI_EVENT_HANDLER(LINE_IN_BAT) +.onchange = battery_onchange, + .ontouch = NULL, +}; + +#endif diff --git a/apps/soundbox/ui/lcd/STYLE_02/music_action.c b/apps/soundbox/ui/lcd/STYLE_02/music_action.c new file mode 100644 index 0000000..df5daf6 --- /dev/null +++ b/apps/soundbox/ui/lcd/STYLE_02/music_action.c @@ -0,0 +1,787 @@ +#include "ui/ui.h" +#include "app_config.h" +#include "ui/ui_style.h" +#include "ui/ui_api.h" +#include "app_task.h" +#include "system/timer.h" +#include "key_event_deal.h" +#include "audio_config.h" +#include "jiffies.h" +#include "app_power_manage.h" +#include "asm/charge.h" +#include "../lyrics_api.h" +#include "audio_dec_file.h" +#include "music/music_player.h" +#ifndef CONFIG_MEDIA_NEW_ENABLE +#include "media/audio_eq_drc_apply.h" +#else +#include "audio_eq.h" +#endif + + + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX)) + +#define STYLE_NAME JL + +extern int ui_hide_main(int id); +extern int ui_show_main(int id); +extern void key_ui_takeover(u8 on); +extern void power_off_deal(struct sys_event *event, u8 step); +extern const char *music_file_get_cur_name(int *len, int *is_unicode); + +typedef struct _MUSIC_UI_VAR { + u8 start: 1; + u8 menu: 1; + u8 eq_mode: 3; + u8 cycle_mode: 3; + u8 disp_lrc; + int timer; + int total_time; + int file_total; + int cur_num; +} MUSIC_UI_VAR; + + +static MUSIC_UI_VAR *__this = NULL; +static u8 enter_music_mode = 0; +static u16 disp_time = 0; + +static int music_start(const char *type, u32 arg) +{ + const char *file_name; + printf("__FUNCTION__ =%s type =%s %d\n", __FUNCTION__, type, arg); + struct unumber num; + struct utime time_r; + + if (!__this) { + return 0; + } + + if (type && !strcmp(type, "show_lyric")) { + if (arg) { + /* ui_hide(MUSIC_FILE);//不显示歌名 */ + /* ui_show(MUSIC_LYRICS);//显示歌词 */ + } else { + /* ui_hide(MUSIC_LYRICS);//不显示歌词 */ + /* ui_show(MUSIC_FILE);//显示歌名 */ + int len = 0; + int is_unicode = 0; + file_name = music_file_get_cur_name(&len, &is_unicode); + if (len && file_name) { + printf("is_unicode = %d\n", is_unicode); + put_buf(file_name, len); + if (is_unicode) { + ui_text_set_text_by_id(LRC_TEXT_ID_SEC, "", 16, FONT_DEFAULT); + ui_text_set_textw_by_id(MUSIC_FILE, file_name, len, FONT_ENDIAN_SMALL, FONT_DEFAULT | FONT_SHOW_SCROLL); + } else { + ui_text_set_text_by_id(LRC_TEXT_ID_SEC, "", 16, FONT_DEFAULT); + ui_text_set_text_by_id(MUSIC_FILE, file_name, len, FONT_DEFAULT); + } + + } + } + return 0; + } + + + if (type && !strcmp(type, "dev")) { + if (arg && (!strncmp((char *)arg, "udisk", 5))) { + ui_pic_show_image_by_id(MUSIC_DEV, 1); //显示udik + } else { + ui_pic_show_image_by_id(MUSIC_DEV, 2); //显示sd + } + return 0; + } + + + if (type && !strcmp(type, "filenum")) { + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = arg; + ui_number_update_by_id(MUSIC_CUR_NUM, &num); + return 0; + } + + + if (type && !strcmp(type, "total_filenum")) { + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = arg; + ui_number_update_by_id(MUSIC_TOTAL_NUM, &num); + return 0; + } + + return 0; +} + +static const struct uimsg_handl ui_msg_handler[] = { + { "music_start", music_start }, /* */ + { NULL, NULL}, /* 必须以此结尾! */ +}; + + + + +static void music_check_add(void *ptr); + +/************************************************************ + 音乐模式主页窗口控件 + ************************************************************/ + + +static int music_mode_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct window *window = (struct window *)ctr; + static int bt_status_timer = 0; + switch (e) { + case ON_CHANGE_INIT: + puts("\n***music_mode_onchange***\n"); + enter_music_mode = 1; + /* key_ui_takeover(1); */ + if (!__this) { + __this = zalloc(sizeof(MUSIC_UI_VAR)); + } + ui_register_msg_handler(ID_WINDOW_MUSIC, ui_msg_handler); + /* + * 注册APP消息响应 + */ + if (!__this->timer) { + __this->timer = sys_timer_add(NULL, music_check_add, 500); + } + disp_time = 0; + break; + case ON_CHANGE_RELEASE: + + if (__this->timer) { + sys_timer_del(__this->timer); + } + + if (__this) { + free(__this); + __this = NULL; + } + break; + default: + return false; + } + return false; +} + + + +REGISTER_UI_EVENT_HANDLER(ID_WINDOW_MUSIC) +.onchange = music_mode_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + + + +/* extern void test_browser(); */ +/************************************************************ + 音乐模式布局控件按键事件 + ************************************************************/ + +static void music_layout_init(int id) +{ +#if (defined(TCFG_LRC_LYRICS_ENABLE) && (TCFG_LRC_LYRICS_ENABLE)) +#else +#endif +} + +static int music_layout_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_text *text = (struct ui_text *)ctr; + switch (e) { + case ON_CHANGE_INIT: + /* ui_text_set_text_attrs(text, NULL, 0, FONT_ENCODE_UTF8, 0, FONT_DEFAULT); */ + break; + case ON_CHANGE_SHOW_PROBE: + break; + case ON_CHANGE_FIRST_SHOW: + ui_set_call(music_layout_init, 0); + break; + default: + return FALSE; + } + return FALSE; +} + +static int music_layout_onkey(void *ctr, struct element_key_event *e) +{ + printf("music_layout_onkey %d\n", e->value); + char *logo = music_player_get_dev_cur(); + switch (e->value) { + case KEY_MENU: + ui_show(MUSIC_MENU_LAYOUT); + break; + case KEY_OK: + /* music_play_file_pp(); */ + app_task_put_key_msg(KEY_MUSIC_PP, 0); + break; + case KEY_UP: + /* music_play_file_prev(); */ + app_task_put_key_msg(KEY_MUSIC_PREV, 0); + break; + case KEY_DOWN: + app_task_put_key_msg(KEY_MUSIC_NEXT, 0); + /* music_play_file_next(); */ + break; + case KEY_VOLUME_INC: + /* app_audio_volume_up(1); */ + /* break; */ + case KEY_VOLUME_DEC: + /* app_audio_volume_down(1); */ + ui_show(MUSIC_VOL_LAYOUT); + break; + case KEY_MODE: + UI_HIDE_CURR_WINDOW(); + ui_show_main(ID_WINDOW_SYS); + break; + case KEY_POWER_START: + case KEY_POWER: + power_off_deal(NULL, e->value - KEY_POWER_START); + break; + default: + return false; + break; + } + return false; +} + +REGISTER_UI_EVENT_HANDLER(MUSIC_LAYOUT) +.onchange = music_layout_onchange, + .onkey = music_layout_onkey, + .ontouch = NULL, +}; + +void music_player_disp_status() +{ + if (__this) { + __this->disp_lrc = 1; + ui_hide(MUSIC_START); +// ui_show(MUSIC_FILE); + // ui_show(MUSIC_LYRICS); + } +} +/************************************************************ + 音乐模式的定时器 + ************************************************************/ +static void music_check_add(void *ptr) +{ + int sencond; + struct utime time_r; + char *logo = music_player_get_dev_cur(); + + if (!__this) { + return; + } + +#if TCFG_EQ_ENABLE + if (eq_mode_get_cur() != __this->eq_mode) { + __this->eq_mode = eq_mode_get_cur(); + ui_pic_show_image_by_id(MUSIC_EQ, __this->eq_mode); + } +#endif + + if (music_player_get_repeat_mode() != __this->cycle_mode) { + __this->cycle_mode = music_player_get_repeat_mode(); + ui_pic_show_image_by_id(MUSIC_MLOOP, __this->cycle_mode); + } + + + if (true == file_dec_is_play()) { + if (!__this->start) { + ui_pic_show_image_by_id(MUSIC_START, 0); + if (!disp_time) { + disp_time = sys_timeout_add(NULL, music_player_disp_status, 200); + } + sencond = file_dec_get_total_time(); + time_r.hour = sencond / 60 / 60; + time_r.min = sencond / 60 % 60; + time_r.sec = sencond % 60; + ui_time_update_by_id(MUSIC_TOTAL_TIME, &time_r); + __this->total_time = sencond; + __this->start = 1; + } + sencond = file_dec_get_total_time(); + if (sencond != __this->total_time) { + time_r.hour = sencond / 60 / 60; + time_r.min = sencond / 60 % 60; + time_r.sec = sencond % 60; + ui_time_update_by_id(MUSIC_TOTAL_TIME, &time_r); + __this->total_time = sencond; + } + sencond = file_dec_get_cur_time(); + /* printf("sec = %d \n", sencond); */ + time_r.hour = sencond / 60 / 60; + time_r.min = sencond / 60 % 60; + time_r.sec = sencond % 60; + ui_time_update_by_id(MUSIC_CUR_TIME, &time_r); + if (__this->disp_lrc == 1) { +#if (defined(TCFG_LRC_LYRICS_ENABLE) && (TCFG_LRC_LYRICS_ENABLE)) + if (lrc_show_api(MUSIC_FILE, file_dec_get_cur_time(), 0)) { + if (enter_music_mode == 1) { + UI_MSG_POST("music_start:dev=%4:filenum=%4:total_filenum=%4", logo, music_player_get_file_cur(), music_player_get_file_total()); + enter_music_mode = 0; + } + } else { + if (enter_music_mode == 1) { + UI_MSG_POST("music_start:show_lyric=%4:dev=%4:filenum=%4:total_filenum=%4", 0, logo, music_player_get_file_cur(), music_player_get_file_total()); + enter_music_mode = 0; + } + } +#endif + } + } else if (file_dec_is_pause()) { + if (__this->start) { + if (disp_time) { + sys_timeout_del(disp_time); + disp_time = 0; + // ui_hide(MUSIC_FILE); + // ui_hide(MUSIC_LYRICS); + ui_pic_show_image_by_id(MUSIC_START, 1); + } + __this->start = 0; + __this->disp_lrc = 0; + } + } else { + if (__this->start) { + if (disp_time) { + sys_timeout_del(disp_time); + disp_time = 0; + // ui_hide(MUSIC_FILE); + // ui_hide(MUSIC_LYRICS); + ui_pic_show_image_by_id(MUSIC_START, 1); + } + __this->start = 0; + __this->disp_lrc = 0; + } + } +} + +/************************************************************ + 音乐模式的一些控件初始化事件 + ************************************************************/ + +static int play_timer_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_time *timer = (struct ui_time *)ctr; + int sencond = 0; + switch (e) { + case ON_CHANGE_INIT: + + if (timer->text.elm.id == MUSIC_CUR_TIME) { + sencond = file_dec_get_cur_time(); + } else if (timer->text.elm.id == MUSIC_TOTAL_TIME) { + sencond = file_dec_get_total_time(); + } + + timer->hour = sencond / 60 / 60; + if (true == file_dec_is_play()) { + timer->min = sencond / 60 % 60; + timer->sec = sencond % 60; + } else { + timer->min = sencond / 60 % 60; + timer->sec = sencond % 60; + } + break; + default: + return FALSE; + } + return FALSE; +} + +REGISTER_UI_EVENT_HANDLER(MUSIC_TOTAL_TIME) +.onchange = play_timer_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +REGISTER_UI_EVENT_HANDLER(MUSIC_CUR_TIME) +.onchange = play_timer_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + + + + + +/************************************************************ + 音乐模式主菜单列表按键事件 + ************************************************************/ + +static int music_enter_callback(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + switch (sel_item) { + case 0: + ui_show(MUSIC_EQ_LAYOUT); + break; + case 1: + ui_show(MUSIC_CYCLE_LAYOUT); + break; + case 2: + ui_show(MUSIC_FILE_LAYOUT); + break; + case 3: + ui_hide(MUSIC_MENU_LAYOUT); + break; + } + break; + default: + return false; + } + return TRUE; +} + + +REGISTER_UI_EVENT_HANDLER(MUSIC_MENU_LIST) +.onchange = NULL, + .onkey = music_enter_callback, + .ontouch = NULL, +}; + + + + + +/************************************************************ + 音乐模式eq菜单列表按键事件 + ************************************************************/ + +static const int eq_mode_pic[] = { + MUSIC_2, + MUSIC_8, + MUSIC_12, + MUSIC_14, + MUSIC_16, + MUSIC_18, +}; + + + +#if TCFG_EQ_ENABLE +static int eq_pic_common_onchange(void *_ctrl, enum element_change_event event, void *arg) +{ + struct ui_pic *pic = (struct ui_pic *)_ctrl; + switch (event) { + case ON_CHANGE_INIT: + if (pic->elm.id == eq_mode_pic[eq_mode_get_cur() % 6]) { + ui_pic_set_image_index(pic, 1); + } + break; + case ON_CHANGE_SHOW_POST: + break; + default: + return FALSE; + } + return FALSE; +} + +REGISTER_UI_EVENT_HANDLER(MUSIC_2) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(MUSIC_8) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(MUSIC_12) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(MUSIC_14) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(MUSIC_16) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(MUSIC_18) +.onchange = eq_pic_common_onchange, +}; +#endif + +static int music_eq_menu_list_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + int list = 0; + switch (e) { + case ON_CHANGE_INIT: + printf("ON_CHANGE_INIT %d \n", grid->avail_item_num); + break; + } + return false; +} + +static int music_eq_callback(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + switch (sel_item) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: +#if TCFG_EQ_ENABLE + eq_mode_set(sel_item); +#endif + case 6: + ui_hide(MUSIC_EQ_LAYOUT); + break; + } + break; + default: + return false; + } + return TRUE; +} + + +REGISTER_UI_EVENT_HANDLER(MUSIC_EQ_LIST) +.onchange = music_eq_menu_list_onchange, + .onkey = music_eq_callback, + .ontouch = NULL, +}; + + + + +/************************************************************ + 音乐模式循环菜单列表按键事件 + ************************************************************/ + +static const int cycle_mode_pic[] = { + MUSIC_29, + MUSIC_32, + MUSIC_35, + MUSIC_38, + MUSIC_41, +}; + + +static int music_cycle_menu_list_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + int list = 0; + switch (e) { + case ON_CHANGE_INIT: + printf("ON_CHANGE_INIT %d \n", grid->avail_item_num); + int id = cycle_mode_pic[music_player_get_repeat_mode() % 5]; + printf("id = %x \n", id); + ui_pic_show_image_by_id(id, 1); + break; + } + return false; +} + +static int music_cycle_callback(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + switch (sel_item) { + case 0: + case 1: + case 2: + case 3: + case 4: + music_player_set_repeat_mode(sel_item); + case 5: + ui_hide(MUSIC_CYCLE_LAYOUT); + break; + } + break; + default: + return false; + } + return TRUE; +} + + +REGISTER_UI_EVENT_HANDLER(MUSIC_CYCLE_LIST) +.onchange = music_cycle_menu_list_onchange, + .onkey = music_cycle_callback, + .ontouch = NULL, +}; + + + +/************************************************************ + 电池控件事件 + ************************************************************/ + +static void battery_timer(void *priv) +{ + int incharge = 0;//充电标志 + int id = (int)(priv); + static u8 percent = 0; + static u8 percent_last = 0; + if (1 || get_charge_online_flag()) { //充电时候图标动态效果 + if (percent > get_vbat_percent()) { + percent = 0; + } + ui_battery_set_level_by_id(id, percent, incharge); //充电标志,ui可以显示不一样的图标 + percent += 20; + } else { + + percent = get_vbat_percent(); + if (percent != percent_last) { + ui_battery_set_level_by_id(id, percent, incharge); //充电标志,ui可以显示不一样的图标,需要工具设置 + percent_last = percent; + } + + } +} + + +static int battery_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_battery *battery = (struct ui_battery *)ctr; + static u32 timer = 0; + int incharge = 0;//充电标志 + + switch (e) { + case ON_CHANGE_INIT: + ui_battery_set_level(battery, get_vbat_percent(), incharge); + if (!timer) { + timer = sys_timer_add((void *)battery->elm.id, battery_timer, 1 * 1000); //传入的id就是BT_BAT + } + break; + case ON_CHANGE_FIRST_SHOW: + break; + case ON_CHANGE_RELEASE: + if (timer) { + sys_timer_del(timer); + timer = 0; + } + break; + default: + return false; + } + return false; +} +REGISTER_UI_EVENT_HANDLER(MUSIC_BAT) +.onchange = battery_onchange, + .ontouch = NULL, +}; + +/************************************************************ + 音乐模式音量布局事件 + ************************************************************/ + +static u16 music_timer = 0; +static void music_vol_timeout(void *p) +{ + int id = (int)(p); + if (ui_get_disp_status_by_id(id) == TRUE) { + ui_hide(id); + } + music_timer = 0; +} + +static void vol_init(int id) +{ + struct unumber num; + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + ui_number_update_by_id(MUSIC_VOL_NUM, &num); +} + + +static int music_vol_layout_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct layout *layout = (struct layout *)ctr; + struct unumber num; + switch (e) { + case ON_CHANGE_INIT: + if (!music_timer) { + music_timer = sys_timeout_add((void *)layout->elm.id, music_vol_timeout, 3000); + } + break; + + case ON_CHANGE_FIRST_SHOW://布局第一次显示,可以对布局内的一些控件进行初始化 + ui_set_call(vol_init, 0); + break; + case ON_CHANGE_SHOW_POST: + //有显示动作 + break; + + case ON_CHANGE_RELEASE: + if (music_timer) { + sys_timeout_del(music_timer); + music_timer = 0; + } + break; + default: + return FALSE; + } + return FALSE; +} + + +static int music_vol_layout_onkey(void *ctr, struct element_key_event *e) +{ + printf("music_vol_layout_onkey %d\n", e->value); + struct unumber num; + u8 vol; + + if (music_timer) { + sys_timer_modify(music_timer, 3000); + } + + switch (e->value) { + case KEY_MENU: + break; + case KEY_UP: + case KEY_VOLUME_INC: + app_audio_volume_up(1); + vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = vol; + ui_number_update_by_id(MUSIC_VOL_NUM, &num); + break; + case KEY_DOWN: + case KEY_VOLUME_DEC: + app_audio_volume_down(1); + vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = vol; + ui_number_update_by_id(MUSIC_VOL_NUM, &num); + break; + default: + return false; + break; + } + return true; +} + + + +REGISTER_UI_EVENT_HANDLER(MUSIC_VOL_LAYOUT) +.onchange = music_vol_layout_onchange, + .onkey = music_vol_layout_onkey, + .ontouch = NULL, +}; + + + +#endif diff --git a/apps/soundbox/ui/lcd/STYLE_02/record_action.c b/apps/soundbox/ui/lcd/STYLE_02/record_action.c new file mode 100644 index 0000000..33c9d4f --- /dev/null +++ b/apps/soundbox/ui/lcd/STYLE_02/record_action.c @@ -0,0 +1,614 @@ +#include "ui/ui.h" +#include "app_config.h" +#include "ui/ui_style.h" +#include "ui/ui_api.h" +#include "app_task.h" +#include "system/timer.h" +#include "key_event_deal.h" +#include "asm/charge.h" +#include "record/record.h" +#include "encode/encode_write.h" +#include "audio_config.h" +#include "audio_enc/audio_enc.h" +#include "app_power_manage.h" +#include "audio_dec/audio_dec_file.h" +#include "audio_enc/audio_enc.h" +#ifndef CONFIG_MEDIA_NEW_ENABLE +#include "media/audio_eq_drc_apply.h" +#else +#include "audio_eq.h" +#endif + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX)) + +#define STYLE_NAME JL + +extern int ui_hide_main(int id); +extern int ui_show_main(int id); +extern void key_ui_takeover(u8 on); +extern void power_off_deal(struct sys_event *event, u8 step); + +extern const char *music_file_get_cur_name(int *len, int *is_unicode); + +typedef struct _RECORD_UI_OPR { + u8 start: 1; + u8 menu: 1; + u8 rec_play: 1; + u8 eq_mode : 3; + int timer; + int cur_num; + u32 second; +} RECORD_UI_OPR; + +static RECORD_UI_OPR *__this = NULL; +char path[64] = {0};//用于获取录音文件的路径 + +/************************************************************ + 获取录音文件的名字 +************************************************************/ +char *rec_get_filename() +{ + char *name = path; + int ret, len; + memset(path, 0, 64); + ret = last_enc_file_path_get(path); + if (ret) { + return NULL; + } + len = strlen(path); + + while (len--) { + if (*name++ == '.') { + name -= 9; + break; + } + } + if (len <= 0) { + return NULL; + } + len = strlen(name) + 1; + printf("\n--func=%s, line=%d,record_action--len:%d,name:%s\n", __FUNCTION__, __LINE__, len, name); + return name; +} +/************************************************************ + 录音模式UI消息处理函数 +************************************************************/ +static int record_start(const char *type, u32 arg) +{ + const char *file_name = NULL; + int len = 0; + printf("__FUNCTION__ =%s type =%s %d\n", __FUNCTION__, type, arg); + + if (type && !strcmp(type, "first_show")) { + if (arg) { + ui_text_set_text_by_id(REC_FILE_NAME, "------", 6, FONT_DEFAULT); + } + return 0; + } + + if (type && !strcmp(type, "show_filename")) { + file_name = rec_get_filename(); + len = strlen(file_name) + 1; + if (len && file_name) { + printf("\n--func=%s, line=%d,len:%d,file_name:%s\n", __FUNCTION__, __LINE__, len, file_name); + ui_text_set_text_by_id(REC_FILE_NAME, file_name, len, FONT_DEFAULT); + } + return 0; + } + + if (type && !strcmp(type, "dev")) { + if (arg && (!strncmp((char *)arg, "udisk", 5))) { + ui_pic_show_image_by_id(REC_DEV, 0); //显示udik + } else { + ui_pic_show_image_by_id(REC_DEV, 1); //显示sd + } + return 0; + } + + return 0; +} + +static const struct uimsg_handl ui_msg_handler[] = { + { "record_start", record_start }, /* */ + { NULL, NULL}, /* 必须以此结尾! */ +}; + +static void record_check_add(void *ptr); +/************************************************************ + 录音模式主页窗口控件 +************************************************************/ +static int record_mode_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct window *window = (struct window *)ctr; + switch (e) { + case ON_CHANGE_INIT: + puts("\n***record_mode_onchange***\n"); + /* key_ui_takeover(1); */ + if (!__this) { + __this = zalloc(sizeof(RECORD_UI_OPR)); + } + ui_register_msg_handler(ID_WINDOW_REC, ui_msg_handler); + /* + * 注册APP消息响应 + */ + UI_MSG_POST("record_start:first_show=%1", 1); //录音模式上电显示空白路径 + if (!__this->timer) { + __this->timer = sys_timer_add(NULL, record_check_add, 500); + } + break; + case ON_CHANGE_RELEASE: + puts("\n***record_mode_release***\n"); + if (__this->timer) { + sys_timer_del(__this->timer); + } + if (__this) { + free(__this); + __this = NULL; + } + break; + default: + return false; + } + return false; +} + + +REGISTER_UI_EVENT_HANDLER(ID_WINDOW_REC) +.onchange = record_mode_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + +/* extern void test_browser(); */ +/************************************************************ + 录音模式布局控件按键事件 + ************************************************************/ +static void record_layout_init(int id) +{ + ; +} + +static int record_layout_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_text *text = (struct ui_text *)ctr; + switch (e) { + case ON_CHANGE_INIT: + break; + case ON_CHANGE_SHOW_PROBE: + break; + case ON_CHANGE_FIRST_SHOW: + break; + default: + return FALSE; + } + return FALSE; +} + +static int record_layout_onkey(void *ctr, struct element_key_event *e) +{ + printf("record_layout_onkey %d\n", e->value); + switch (e->value) { + case KEY_MENU: + ui_show(REC_MENU_LAYOUT); + break; + case KEY_OK: + /* music_play_file_pp(); */ + break; + case KEY_ENC: + app_task_put_key_msg(KEY_ENC_START, 0); + break; + case KEY_UP: + break; + case KEY_DOWN: + break; + case KEY_VOLUME_INC: + case KEY_VOLUME_DEC: + ui_show(REC_VOL_LAYOUT); + break; + case KEY_MODE: + UI_HIDE_CURR_WINDOW(); + ui_show_main(ID_WINDOW_SYS); + break; + case KEY_POWER_START: + case KEY_POWER: + power_off_deal(NULL, e->value - KEY_POWER_START); + break; + default: + return false; + break; + } + return false; +} + +REGISTER_UI_EVENT_HANDLER(REC_LAYOUT) +.onchange = record_layout_onchange, + .onkey = record_layout_onkey, + .ontouch = NULL, +}; + + +/************************************************************ + 录音模式的定时器 + ************************************************************/ +static void record_check_add(void *ptr) +{ + struct utime time_r; + char *logo = dev_manager_get_phy_logo(dev_manager_find_active(0));//最后活动设备 + + if (!__this) { + return; + } + +#if TCFG_EQ_ENABLE + if (eq_mode_get_cur() != __this->eq_mode) { + __this->eq_mode = eq_mode_get_cur(); + ui_pic_show_image_by_id(REC_EQ, __this->eq_mode); + } +#endif + + if (true == recorder_is_encoding()) { //正在录音 + if (!__this->start) { //刚开始进行录音或者总系统设置出来后显示录音盘符,名字,正在录音文本以及播放标志 + ui_highlight_element_by_id(REC_START); + ui_text_show_index_by_id(REC_TEXT, 1); + UI_MSG_POST("record_start:show_filename=%2:dev=%2", 1, logo); + __this->start = 1; + __this->second = 0; + } + + if (__this->start == 1) { //显示录音时间 + __this->second = recorder_get_encoding_time(); + } + time_r.hour = __this->second / 60 / 60; + time_r.min = __this->second / 60 % 60; + time_r.sec = __this->second % 60; + ui_time_update_by_id(REC_TIME, &time_r); + } else {//录音回放,回放结束以及还没开始录音处理 + if (__this->start == 1 || (file_dec_is_play() && !__this->rec_play)) { //回放时显示录音盘符,名字,正在录音文本以及播放标志,从系统设置菜单返回也跑这里 + ui_highlight_element_by_id(REC_START); + ui_text_show_index_by_id(REC_TEXT, 1); + UI_MSG_POST("record_start:show_filename=%2:dev=%2", 1, logo); + __this->start = 0; + __this->second = 0; + __this->rec_play = 1; + ui_text_show_index_by_id(REC_TEXT, 2); + } + if (__this->rec_play == 1) { //正在回放 + __this->second = file_dec_get_cur_time(); + if (file_dec_is_stop()) { //回放结束 + __this->rec_play = 0; + __this->second = 0; + } + time_r.hour = __this->second / 60 / 60; + time_r.min = __this->second / 60 % 60; + time_r.sec = __this->second % 60; + ui_time_update_by_id(REC_TIME, &time_r); + } else { //回放结束或者还没开始录音处理 + ui_text_show_index_by_id(REC_TEXT, 0); + ui_no_highlight_element_by_id(REC_START); + } + } +} + +/************************************************************ + 录音模式的一些控件初始化事件 + ************************************************************/ + +static int record_timer_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_time *timer = (struct ui_time *)ctr; + int sencond = 0; + switch (e) { + case ON_CHANGE_INIT: + timer->hour = sencond / 60 / 60; + timer->min = sencond / 60 % 60; + timer->sec = sencond % 60; + break; + default: + return FALSE; + } + return FALSE; +} + +REGISTER_UI_EVENT_HANDLER(REC_TIME) +.onchange = record_timer_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +/************************************************************ + 录音模式主菜单列表按键事件 + ************************************************************/ +static int record_enter_callback(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + switch (sel_item) { + case 0: + ui_show(REC_EQ_LAYOUT); + break; + case 1: + ui_hide(REC_MENU_LAYOUT); + break; + default: + break; + } + break; + default: + return false; + } + return TRUE; +} + +REGISTER_UI_EVENT_HANDLER(REC_MENU_LIST) +.onchange = NULL, + .onkey = record_enter_callback, + .ontouch = NULL, +}; + +/************************************************************ + 录音模式eq菜单列表按键事件 + ************************************************************/ + +static const int eq_mode_pic[] = { + REC_EQ_NORMAL_PIC, + REC_EQ_ROCK_PIC, + REC_EQ_POP_PIC, + REC_EQ_CLASSIC_PIC, + REC_EQ_JAZZ_PIC, + REC_EQ_COUNTRY_PIC, +}; + +#if TCFG_EQ_ENABLE +static int eq_pic_common_onchange(void *_ctrl, enum element_change_event event, void *arg) +{ + struct ui_pic *pic = (struct ui_pic *)_ctrl; + switch (event) { + case ON_CHANGE_INIT: + if (pic->elm.id == eq_mode_pic[eq_mode_get_cur() % 6]) { + ui_pic_set_image_index(pic, 1); + } + break; + case ON_CHANGE_SHOW_POST: + break; + default: + return FALSE; + } + return FALSE; +} + +REGISTER_UI_EVENT_HANDLER(REC_EQ_NORMAL_PIC) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(REC_EQ_ROCK_PIC) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(REC_EQ_POP_PIC) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(REC_EQ_CLASSIC_PIC) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(REC_EQ_JAZZ_PIC) +.onchange = eq_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(REC_EQ_COUNTRY_PIC) +.onchange = eq_pic_common_onchange, +}; +#endif + +static int record_eq_menu_list_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + int list = 0; + switch (e) { + case ON_CHANGE_INIT: + printf("ON_CHANGE_INIT %d \n", grid->avail_item_num); + break; + } + return false; +} + +static int record_eq_callback(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + switch (sel_item) { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: +#if TCFG_EQ_ENABLE + eq_mode_set(sel_item); +#endif + case 6: + ui_hide(REC_EQ_LAYOUT); + break; + } + break; + default: + return false; + } + return TRUE; +} + + +REGISTER_UI_EVENT_HANDLER(REC_EQ_MENU_LIST) +.onchange = record_eq_menu_list_onchange, + .onkey = record_eq_callback, + .ontouch = NULL, +}; + + + +/************************************************************ + 音量设置布局控件 + ************************************************************/ +static u16 vol_timer = 0; +static void record_vol_lay_timeout(void *p) +{ + int id = (int)(p); + if (ui_get_disp_status_by_id(id) == TRUE) { + ui_hide(id); + //ui_show(CLOCK_LAYOUT); + } + vol_timer = 0; +} + + +static void vol_init(int id) +{ + struct unumber num; + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + ui_number_update_by_id(REC_VOL_NUM, &num); +} + +static int record_vol_layout_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct layout *layout = (struct layout *)ctr; + switch (e) { + case ON_CHANGE_INIT: + if (!vol_timer) { + vol_timer = sys_timer_add((void *)layout->elm.id, record_vol_lay_timeout, 3000); + } + break; + + case ON_CHANGE_FIRST_SHOW: + ui_set_call(vol_init, 0); + /* ui_number_update_by_id(CLOCK_VOL_NUM,&num); */ + break; + + case ON_CHANGE_SHOW_POST: + break; + + case ON_CHANGE_RELEASE: + if (vol_timer) { + sys_timeout_del(vol_timer); + vol_timer = 0; + } + break; + default: + return FALSE; + } + return FALSE; +} + + +static int record_vol_layout_onkey(void *ctr, struct element_key_event *e) +{ + printf("clock_vol_layout_onkey %d\n", e->value); + struct unumber num; + u8 vol; + + if (vol_timer) { + sys_timer_modify(vol_timer, 3000); + } + + + switch (e->value) { + case KEY_MENU: + break; + + case KEY_UP: + case KEY_VOLUME_INC: + app_audio_volume_up(1); + vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = vol; + ui_number_update_by_id(REC_VOL_NUM, &num); + break; + case KEY_DOWN: + case KEY_VOLUME_DEC: + app_audio_volume_down(1); + vol = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + num.type = TYPE_NUM; + num.numbs = 1; + num.number[0] = vol; + ui_number_update_by_id(REC_VOL_NUM, &num); + break; + default: + return false; + break; + } + return true; +} + +REGISTER_UI_EVENT_HANDLER(REC_VOL_LAYOUT) +.onchange = record_vol_layout_onchange, + .onkey = record_vol_layout_onkey, + .ontouch = NULL, +}; + +/************************************************************ + 电池控件事件 + ************************************************************/ + +static void battery_timer(void *priv) +{ + int incharge = 0;//充电标志 + int id = (int)(priv); + static u8 percent = 0; + static u8 percent_last = 0; + if (1 || get_charge_online_flag()) { //充电时候图标动态效果 get_charge_online_flag()在内置充电的时候获取是否正在充电,外置充电根据电路来编写接口 + if (percent > get_vbat_percent()) { + percent = 0; + } + ui_battery_set_level_by_id(id, percent, incharge); //充电标志,ui可以显示不一样的图标 + percent += 20; + } else { + + percent = get_vbat_percent(); + if (percent != percent_last) { + ui_battery_set_level_by_id(id, percent, incharge); //充电标志,ui可以显示不一样的图标,需要工具设置 + percent_last = percent; + } + + } +} + +static int battery_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_battery *battery = (struct ui_battery *)ctr; + static u32 timer = 0; + int incharge = 0;//充电标志 + + switch (e) { + case ON_CHANGE_INIT: + ui_battery_set_level(battery, get_vbat_percent(), incharge); + if (!timer) { + timer = sys_timer_add((void *)battery->elm.id, battery_timer, 1 * 1000); //传入的id就是BT_BAT + } + break; + case ON_CHANGE_FIRST_SHOW: + break; + case ON_CHANGE_RELEASE: + if (timer) { + sys_timer_del(timer); + timer = 0; + } + break; + default: + return false; + } + return false; +} + +REGISTER_UI_EVENT_HANDLER(REC_BAT) +.onchange = battery_onchange, + .ontouch = NULL, +}; + +#endif diff --git a/apps/soundbox/ui/lcd/STYLE_02/system_action.c b/apps/soundbox/ui/lcd/STYLE_02/system_action.c new file mode 100644 index 0000000..50b94f0 --- /dev/null +++ b/apps/soundbox/ui/lcd/STYLE_02/system_action.c @@ -0,0 +1,776 @@ +#include "ui/ui.h" +#include "app_config.h" +#include "ui/ui_style.h" +#include "ui/ui_api.h" +#include "app_task.h" +#include "system/timer.h" +#include "font/language_list.h" +#include "res/resfile.h" +#include "app_power_manage.h" +#include "asm/charge.h" +#include "../ui_sys_param_api.h" +#include "update/update.h" +#include "dev_manager/dev_manager.h" + + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX)) + +#define STYLE_NAME JL +REGISTER_UI_STYLE(STYLE_NAME) + +extern int ui_hide_main(int id); +extern int ui_show_main(int id); +extern void key_ui_takeover(u8 on); +extern u16 dev_update_check(char *logo); +/************************************************************ + 电池控件事件 + ************************************************************/ + +static void battery_timer(void *priv) +{ + int incharge = 0;//充电标志 + int id = (int)(priv); + static u8 percent = 0; + static u8 percent_last = 0; + if (get_charge_online_flag()) { //充电时候图标动态效果 + if (percent > get_vbat_percent()) { + percent = 0; + } + ui_battery_set_level_by_id(id, percent, incharge); //充电标志,ui可以显示不一样的图标 + percent += 20; + } else { + + percent = get_vbat_percent(); + if (percent != percent_last) { + ui_battery_set_level_by_id(id, percent, incharge); //充电标志,ui可以显示不一样的图标,需要工具设置 + percent_last = percent; + } + + } +} + +static int battery_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct ui_battery *battery = (struct ui_battery *)ctr; + static u32 timer = 0; + int incharge = 0;//充电标志 + + switch (e) { + case ON_CHANGE_INIT: + ui_battery_set_level(battery, get_vbat_percent(), incharge); + if (!timer) { + timer = sys_timer_add((void *)battery->elm.id, battery_timer, 1 * 1000); //传入的id就是BT_BAT + } + break; + case ON_CHANGE_FIRST_SHOW: + break; + case ON_CHANGE_RELEASE: + if (timer) { + sys_timer_del(timer); + timer = 0; + } + break; + default: + return false; + } + return false; +} +REGISTER_UI_EVENT_HANDLER(SYSTEM_BAT) +.onchange = battery_onchange, + .ontouch = NULL, +}; + + + + + +/************************************************************ + 系统设置 + ************************************************************/ + + +static int sys_mode_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct window *window = (struct window *)ctr; + static int bt_status_timer = 0; + switch (e) { + case ON_CHANGE_INIT: + puts("\n***sys_mode_onchange***\n"); + /* key_ui_takeover(1); */ + /* ui_register_msg_handler(ID_WINDOW_BT, ui_msg_handler); */ + /* + * 注册APP消息响应 + */ + break; + case ON_CHANGE_RELEASE: + + break; + default: + return false; + } + return false; +} + + +REGISTER_UI_EVENT_HANDLER(ID_WINDOW_SYS) +.onchange = sys_mode_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +static int common_layout_onchange(void *ctr, enum element_change_event e, void *arg) +{ + struct layout *layout = (struct layout *)ctr; + switch (e) { + case ON_CHANGE_INIT: + layout_on_focus(layout); + break; + case ON_CHANGE_RELEASE: + layout_lose_focus(layout); + break; + default: + break; + } + return FALSE; +} + + +/************************************************************ + 系统设置入口 + ************************************************************/ +static int system_enter_callback(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + switch (sel_item) { + case 0: + ui_show(SYSTEM_M_LAYOUT); + break; + case 1: + ui_show(SYS_LANGUAGE); + break; + case 2: + r_printf("UI sys_enter_soft_poweroff\n"); + ui_show(SYS_POWEROFF); + break; + case 3: + ui_show(SYS_BACKLIGHT); + break; + case 4: + UI_HIDE_CURR_WINDOW(); + ui_show_main(-1);//显示上一个页面 + break; + } + break; + default: + return false; + } + return TRUE; +} + + +REGISTER_UI_EVENT_HANDLER(SYSTEM_SET_LIST) +.onchange = NULL, + .onkey = system_enter_callback, + .ontouch = NULL, +}; + + +/************************************************************ + 系统菜单 + ************************************************************/ + + +REGISTER_UI_EVENT_HANDLER(SYSTEM_M_LAYOUT) +.onchange = common_layout_onchange, + .onkey = NULL, + .ontouch = NULL, +}; +static void system_update_timeout() +{ + ui_hide(SYSTEM_UPDATE); +} + +static int system_menu_callback(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + u16 update_status = 0; + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + + switch (sel_item) { + case 0: + ui_show(SYS_MSG_LAYOUT); + return TRUE; + break; + case 1: + set_sys_info_reset();//只重置了背光时间,背光亮度,以及自动关机时间 + set_backlight_time(0);//重置之后需要再设置背光时间为0,避免按按键后在app_key_event中响应背光时间为0事件导致立即关背光 + ui_hide(SYSTEM_M_LAYOUT); + break; + case 2://分别去查找SD卡,U盘中是否有升级文件 + if (dev_manager_online_check_by_logo("sd0", 0) && update_status != UPDATA_READY) { + update_status = dev_update_check("sd0"); + } + if (dev_manager_online_check_by_logo("sd1", 0) && update_status != UPDATA_READY) { + update_status = dev_update_check("sd1"); + } + if (dev_manager_online_check_by_logo("udisk0", 0) && update_status != UPDATA_READY) { + update_status = dev_update_check("udisk0"); + } + if (update_status != UPDATA_READY) { + ui_show(SYSTEM_UPDATE); + sys_timeout_add(NULL, system_update_timeout, 2000); + } + break; + default: + ui_hide(SYSTEM_M_LAYOUT); + break; + } + + break; + default: + return false; + } + return TRUE; +} + + +REGISTER_UI_EVENT_HANDLER(SYSTEM_M_LIST) +.onchange = NULL, + .onkey = system_menu_callback, + .ontouch = NULL, +}; + + + +/************************************************************ + 系统信息 +************************************************************/ +/* + * 版本号 + */ +#define VERSION_LOG "20200522" +#define SPACE_LOG "1024 MB" + +static int version_ascii_onchange(void *ctr, enum element_change_event e, void *arg) +{ + int index; + struct ui_text *text = (struct ui_text *)ctr; + struct ui_text_attrs *text_attrs = &(text->attrs); + u8 vol; + switch (e) { + case ON_CHANGE_INIT: + text_attrs->str = VERSION_LOG; + break; + case ON_CHANGE_RELEASE: + break; + default: + break; + } + return false; +} + +REGISTER_UI_EVENT_HANDLER(SYSTEM_31) +.onchange = version_ascii_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + +static int space_ascii_onchange(void *ctr, enum element_change_event e, void *arg) +{ + int index; + struct ui_text *text = (struct ui_text *)ctr; + struct ui_text_attrs *text_attrs = &(text->attrs); + u8 vol; + switch (e) { + case ON_CHANGE_INIT: + text_attrs->str = SPACE_LOG; + break; + case ON_CHANGE_RELEASE: + break; + default: + break; + } + return false; +} + +REGISTER_UI_EVENT_HANDLER(SYSTEM_35) +.onchange = space_ascii_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + +static int system_info_menu_enter_callback(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + switch (e->value) { + case KEY_OK: + ui_hide(SYS_MSG_LAYOUT); + return false; + } + return TRUE; +} + +REGISTER_UI_EVENT_HANDLER(SYS_MSG_INFO_LIST) +.onchange = NULL, + .onkey = system_info_menu_enter_callback, + .ontouch = NULL, +}; + + + +/************************************************************ + 语言设置 + ************************************************************/ + +/* + * system语言设置 + */ +static const u8 table_system_language[] = { + Chinese_Simplified, /* 简体中文 */ + Chinese_Traditional, /* 繁体中文 */ + English, /* 英文 */ +}; + + +static const int language_pic[] = { + SYSTEM_47, + SYSTEM_49, + SYSTEM_51, +}; + + + + +static int language_pic_common_onchange(void *_ctrl, enum element_change_event event, void *arg) +{ + struct ui_pic *pic = (struct ui_pic *)_ctrl; + int i = 0; + switch (event) { + case ON_CHANGE_INIT: + for (i = 0; i < sizeof(language_pic) / sizeof(language_pic[0]); i++) { + if (ui_language_get() == table_system_language[i]) { + if (pic->elm.id == language_pic[i]) { + ui_pic_set_image_index(pic, 1); + break; + } + + } + } + break; + case ON_CHANGE_SHOW_POST: + break; + default: + return FALSE; + } + return FALSE; +} + +REGISTER_UI_EVENT_HANDLER(SYSTEM_47) +.onchange = language_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(SYSTEM_49) +.onchange = language_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(SYSTEM_51) +.onchange = language_pic_common_onchange, +}; + + +static int language_enter_callback(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + if (sel_item >= 0 && sel_item < sizeof(table_system_language) / sizeof(table_system_language[0])) { + ui_language_set(table_system_language[sel_item]); + ui_hide(SYS_LANGUAGE); + } else { + ui_hide(SYS_LANGUAGE); + } + + return false; + default: + return false; + } + return TRUE; +} +REGISTER_UI_EVENT_HANDLER(SYS_LANGUAGE_LIST) +.onchange = NULL, + .onkey = language_enter_callback, + .ontouch = NULL, +}; + + + +REGISTER_UI_EVENT_HANDLER(SYS_LANGUAGE) +.onchange = common_layout_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + + + +/************************************************************ + 背光设置 + ************************************************************/ + +static int backlight_menu_enter_callback(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + switch (sel_item) { + case 0: + ui_show(SYS_BACKLIGHT_TIME); + break; + case 1: + ui_show(SYS_BACKLIGHT_VALUE); + break; + case 2: + ui_hide(SYS_BACKLIGHT); + break; + + } + return false; + } + return false; +} + +REGISTER_UI_EVENT_HANDLER(SYS_BACKLIGHT_LIST) +.onchange = NULL, + .onkey = backlight_menu_enter_callback, + .ontouch = NULL, +}; + + +REGISTER_UI_EVENT_HANDLER(SYS_BACKLIGHT) +.onchange = common_layout_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + +/* + * system屏幕保护设置 + */ + + +static const int backlight_time_pic[] = { + SYSTEM_7, + SYSTEM_11, + SYSTEM_16, + SYSTEM_18, + SYSTEM_20, +}; + + +static int backlight_time_pic_common_onchange(void *_ctrl, enum element_change_event event, void *arg) +{ + struct ui_pic *pic = (struct ui_pic *)_ctrl; + switch (event) { + case ON_CHANGE_INIT: + if (pic->elm.id == backlight_time_pic[get_backlight_time_item() % 5]) { + ui_pic_set_image_index(pic, 1); + } + break; + case ON_CHANGE_SHOW_POST: + break; + default: + return FALSE; + } + return FALSE; +} + +REGISTER_UI_EVENT_HANDLER(SYSTEM_7) +.onchange = backlight_time_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(SYSTEM_11) +.onchange = backlight_time_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(SYSTEM_16) +.onchange = backlight_time_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(SYSTEM_18) +.onchange = backlight_time_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(SYSTEM_20) +.onchange = backlight_time_pic_common_onchange, +}; + + + +static int backlight_menu_time_callback(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + set_backlight_time(sel_item); + ui_hide(SYS_BACKLIGHT_TIME); + return false; + } + return false; +} + +REGISTER_UI_EVENT_HANDLER(SYS_BACKLIGHT_TIME_LIST) +.onchange = NULL, + .onkey = backlight_menu_time_callback, + .ontouch = NULL, +}; + +REGISTER_UI_EVENT_HANDLER(SYS_BACKLIGHT_TIME) +.onchange = common_layout_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + + + +/* + * system屏幕亮度设置 + */ + + +static const int backlight_value_pic[] = { + SYSTEM_13, + SYSTEM_25, + SYSTEM_27, +}; + + +static int backlight_value_pic_common_onchange(void *_ctrl, enum element_change_event event, void *arg) +{ + struct ui_pic *pic = (struct ui_pic *)_ctrl; + switch (event) { + case ON_CHANGE_INIT: + if (pic->elm.id == backlight_value_pic[get_backlight_brightness_item() % 3]) { + ui_pic_set_image_index(pic, 1); + } + break; + case ON_CHANGE_SHOW_POST: + break; + default: + return FALSE; + } + return FALSE; +} + +REGISTER_UI_EVENT_HANDLER(SYSTEM_13) +.onchange = backlight_value_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(SYSTEM_25) +.onchange = backlight_value_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(SYSTEM_27) +.onchange = backlight_value_pic_common_onchange, +}; + + +static int backlight_menu_value_callback(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + set_backlight_brightness(sel_item); + ui_hide(SYS_BACKLIGHT_VALUE); + return false; + } + return false; +} + +REGISTER_UI_EVENT_HANDLER(SYS_BACKLIGHT_VALUE_LIST) +.onchange = NULL, + .onkey = backlight_menu_value_callback, + .ontouch = NULL, +}; + +REGISTER_UI_EVENT_HANDLER(SYS_BACKLIGHT_VALUE) +.onchange = common_layout_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + + + +/************************************************************ + 系统关机设置 + ************************************************************/ + + +static const int power_off_pic[] = { + SYSTEM_29, + SYSTEM_37, + SYSTEM_39, + SYSTEM_41, + SYSTEM_43, +}; + + +static int poweroff_pic_common_onchange(void *_ctrl, enum element_change_event event, void *arg) +{ + struct ui_pic *pic = (struct ui_pic *)_ctrl; + switch (event) { + case ON_CHANGE_INIT: + if (pic->elm.id == power_off_pic[get_cur_auto_power_time() % 5]) { + ui_pic_set_image_index(pic, 1); + } + break; + case ON_CHANGE_SHOW_POST: + break; + default: + return FALSE; + } + return FALSE; +} + +REGISTER_UI_EVENT_HANDLER(SYSTEM_29) +.onchange = poweroff_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(SYSTEM_37) +.onchange = poweroff_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(SYSTEM_39) +.onchange = poweroff_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(SYSTEM_41) +.onchange = poweroff_pic_common_onchange, +}; +REGISTER_UI_EVENT_HANDLER(SYSTEM_43) +.onchange = poweroff_pic_common_onchange, +}; + + + + + + +/* + * system自动关机设置 + */ +static int power_menu_enter_callback(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + switch (sel_item) { + case 0: + case 1: + case 2: + case 3: + case 4: + set_auto_poweroff_timer(sel_item); + case 5: + ui_hide(SYS_POWEROFF); + break; + + } + return false; + default: + return false; + } + return TRUE; +} + +REGISTER_UI_EVENT_HANDLER(SYS_POWEROFF_LIST) +.onchange = NULL, + .onkey = power_menu_enter_callback, + .ontouch = NULL, +}; + +REGISTER_UI_EVENT_HANDLER(SYS_POWEROFF) +.onchange = common_layout_onchange, + .onkey = NULL, + .ontouch = NULL, +}; + + +#if 0 +struct grid_setting { + int id; + int parent_id; + void (*handler)(void *hd, int args, int index); +}; + + +static const struct grid_setting grid_function_table[] = { + { SYSTEM_MENU_LIST, 0, system_enter_callback}, + { LANGUAGE_MENU_LIST, 0, language_enter_callback}, + { POWER_MENU_LIST, 0, power_menu_enter_callback}, + { BACK_MENU_LIST, NULL}, + { 0, NULL}, //必须要要0结束 +}; + +static const struct grid_setting grid_function_table_1[] = { + { SYS_BACKLIGHT_0, SYS_BACKLIGHT, backlight_menu_enter_callback}, + { SYS_BACKLIGHT_1, SYS_BACKLIGHT, backlight_menu_enter_callback}, + { SYS_BACKLIGHT_2, SYS_BACKLIGHT, backlight_menu_enter_callback}, + { 0, NULL}, //必须要要0结束 +}; + + + +static void ui_list_callback_common(const struct grid_setting *table, int id, int key, int index) +{ + if (!table) { + return; + } + for (; table->id; table++) { + if (table->id == id) { + if (table->handler) { + table->handler(table, key, index); + } + break; + } + } +} + +static int ui_list_onkey_common(void *ctr, struct element_key_event *e) +{ + struct ui_grid *grid = (struct ui_grid *)ctr; + printf("ui key %s %d\n", __FUNCTION__, e->value); + int sel_item; + switch (e->value) { + case KEY_OK: + sel_item = ui_grid_cur_item(grid); + if (sel_item >= 0) { + ui_list_callback_common(grid_function_table, grid->item[sel_item].elm.id, e->value, sel_item); + } + break; + default: + return false; + } + return TRUE; +} + +#endif +#endif //TCFG_SPI_LCD_ENABLE + diff --git a/apps/soundbox/ui/lcd/lyrics_api.c b/apps/soundbox/ui/lcd/lyrics_api.c new file mode 100644 index 0000000..2b2b18c --- /dev/null +++ b/apps/soundbox/ui/lcd/lyrics_api.c @@ -0,0 +1,251 @@ +#include "lyrics_api.h" +#include "ui/lyrics.h" +#include "system/fs/fs.h" +#include "app_config.h" +#include "ui/ui_style.h" + +#if (TCFG_LRC_LYRICS_ENABLE) + + +static u8 *lrc_info_buf = NULL; //[2324] __attribute__((aligned(4))); +static volatile u8 lrc_analysis_flag = 0; + +static LRC_FILE_IO lrc_file_io = { + .seek = fseek, + .read = fread, +}; + + +static OS_MUTEX mutex; + +/*----------------------------------------------------------------------------*/ +/**@brief 配置翻屏的速度 + @param lrc_len--当前歌词长度,time_gap-与下一条歌词的间隔, + @param *roll_speed - 翻屏的速度 500ms unit + @return + @note + */ +/*----------------------------------------------------------------------------*/ +void lrc_roll_speed_ctrl(u8 lrc_len, u32 time_gap, u8 *roll_speed) +{ + ///翻页滚动速度控制 + ///printf("speed = %d,%d",lrc_len,time_gap); + ///DVcTxt1_11 显示长度为32 bytes + if (lrc_len > (LRC_DISPLAY_TEXT_LEN * 2)) { + *roll_speed = ((time_gap + 2) / 3) << 1; + } else if (lrc_len > LRC_DISPLAY_TEXT_LEN) { + *roll_speed = time_gap; + } else { + *roll_speed = 250; ///never load new page + } + +} + +/*----------------------------------------------------------------------------*/ +/**@brief 清空显示区域 + @param + @return + @note + */ +/*----------------------------------------------------------------------------*/ +void clr_lrc_disp_buff(void) +{ + /* lcd_clear_area_rect(4, 8, 0, 128); */ +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 歌词模块初始化 + @param + @return 0--成功,非0 失败 + @note + */ +/*----------------------------------------------------------------------------*/ +int lrc_init(void) +{ + LRC_CFG t_lrc_cfg; + t_lrc_cfg.once_read_len = ONCE_READ_LENGTH; + t_lrc_cfg.once_disp_len = ONCE_DIS_LENGTH; + t_lrc_cfg.label_temp_buf_len = LABEL_TEMP_BUF_LEN; + t_lrc_cfg.roll_speed_ctrl_cb = lrc_roll_speed_ctrl; + t_lrc_cfg.clr_lrc_disp_cb = NULL;//clr_lrc_disp_buff; + /* t_lrc_cfg.lrc_text_id = LRC_DISPLAY_TEXT_ID; */ + t_lrc_cfg.read_next_lrc_flag = 0; + t_lrc_cfg.enable_save_lable_to_flash = LRC_ENABLE_SAVE_LABEL_TO_FLASH; + + u32 need_buf_size = LRC_SIZEOF_ALIN(sizeof(LRC_INFO), 4) + + LRC_SIZEOF_ALIN(sizeof(LABEL_INFO), 4) + + LRC_SIZEOF_ALIN(sizeof(SORTING_INFO), 4) + + LRC_SIZEOF_ALIN(t_lrc_cfg.once_disp_len, 4) + + LRC_SIZEOF_ALIN(t_lrc_cfg.label_temp_buf_len, 4) + + LRC_SIZEOF_ALIN(t_lrc_cfg.once_read_len, 4); + printf("---lrc need_buf_size=%d---\n", need_buf_size); + /* ASSERT(sizeof(lrc_info_buf) >= need_buf_size); */ + if (!lrc_info_buf) { + lrc_info_buf = zalloc(need_buf_size); + } + + /* memset(lrc_info_buf, 0, sizeof(lrc_info_buf)); */ + + os_mutex_create(&mutex); + + return lrc_param_init(&t_lrc_cfg, lrc_info_buf); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 歌词模块退出 + @param + @return + @note + + */ +/*----------------------------------------------------------------------------*/ +void lrc_exit(void) +{ + os_mutex_pend(&mutex, 0); + lrc_destroy(); + if (lrc_info_buf) { + free(lrc_info_buf); + lrc_info_buf = NULL; + } + os_mutex_post(&mutex); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 搜索歌词,解析 + @param + @return 0--成功,非0 失败 + @note + */ +/*----------------------------------------------------------------------------*/ +int lrc_find(FILE *file, FILE **newFile, void *ext_name) +{ + u32 find_lrc_flag; + + find_lrc_flag = fget_file_byname_indir(file, newFile, ext_name); + + if (find_lrc_flag) { + puts("\ncan't find lrc------\n"); + return -1; + } + + return 0; +} + +void lrc_set_analysis_flag(u8 flag) +{ + if (!lrc_info_buf) { + return; + } + os_mutex_pend(&mutex, 0); + lrc_analysis_flag = flag; + os_mutex_post(&mutex); +} + +bool lrc_show_api(int text_id, u16 dbtime_s, u8 btime_100ms) +{ + bool ret = 0; + if (!lrc_info_buf) { + return false; + } + os_mutex_pend(&mutex, 0); + if (lrc_analysis_flag == 1) { + ret = lrc_show(text_id, dbtime_s, btime_100ms); + os_mutex_post(&mutex); + return ret ; + } else { + os_mutex_post(&mutex); + return false; + } +} + +bool lrc_get_api(u16 dbtime_s, u8 btime_100ms) +{ + bool ret = 0; + os_mutex_pend(&mutex, 0); + if (lrc_analysis_flag == 1) { + ret = lrc_get(dbtime_s, btime_100ms); + return ret ; + os_mutex_post(&mutex); + return ret; + } else { + os_mutex_post(&mutex); + return false; + } +} + +bool lrc_analysis_api(FILE *file, FILE **newFile) +{ + void *ext_name = "LRC"; + LRC_FILE_IO *p_lrc_file_io = &lrc_file_io; + if (!lrc_info_buf) { + return false; + } + os_mutex_pend(&mutex, 0); + if (*newFile) { + fclose(*newFile); + *newFile = NULL; + } + + if (0 == lrc_find(file, newFile, ext_name)) { + if (false == lrc_analysis(*newFile, p_lrc_file_io)) { + printf("lrc analazy err \n"); + os_mutex_post(&mutex); + return false; + } else { + printf("lrc analazy succ \n"); + os_mutex_post(&mutex); + return true; + } + } else { + printf("lrc_find err\n"); + os_mutex_post(&mutex); + return false; + } +} +/*----------------------------------------------------------------------------*/ +/**@brief 歌词显示,默认显示两行 + @param lrc_show_flag:滚动显示标志 lrc_update:显示下一条歌词内容标志 + @return true--成功 + @note 可以根据xi需要修改该函数的实现方法 + */ +/*----------------------------------------------------------------------------*/ +bool lrc_ui_show(int text_id, u8 encode_type, u8 *buf, int len, u8 lrc_show_flag, u8 lrc_update) +{ +#if(CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX) + static int disp_len = 0; + static u8 lrc_showbytes = 0; + static u8 offset = 0; + if (lrc_update) { + disp_len = len; + lrc_showbytes = 0; + offset = 0; + ui_text_set_text_by_id(LRC_TEXT_ID_SEC, "", 16, FONT_DEFAULT); + } + if (lrc_show_flag == 1) { + if (LRC_UTF16_S == encode_type) { + lrc_showbytes = ui_text_set_textw_by_id(LRC_TEXT_ID_FIR, buf + offset, disp_len, FONT_ENDIAN_SMALL, FONT_DEFAULT); + } else if (LRC_UTF16_B == encode_type) { + lrc_showbytes = ui_text_set_textw_by_id(LRC_TEXT_ID_FIR, buf + offset, disp_len, FONT_ENDIAN_BIG, FONT_DEFAULT); + } else if (LRC_UTF8 == encode_type) { + lrc_showbytes = ui_text_set_textw_by_id(LRC_TEXT_ID_FIR, buf + offset, disp_len, FONT_ENDIAN_SMALL, FONT_DEFAULT | FONT_SHOW_MULTI_LINE); + } else { + lrc_showbytes = ui_text_set_text_by_id(LRC_TEXT_ID_FIR, buf + offset, disp_len, FONT_DEFAULT); + } + offset += lrc_showbytes; + if (LRC_UTF16_S == encode_type) { + lrc_showbytes = ui_text_set_textw_by_id(LRC_TEXT_ID_SEC, buf + offset, disp_len, FONT_ENDIAN_SMALL, FONT_DEFAULT); + } else if (LRC_UTF16_B == encode_type) { + lrc_showbytes = ui_text_set_textw_by_id(LRC_TEXT_ID_SEC, buf + offset, disp_len, FONT_ENDIAN_BIG, FONT_DEFAULT); + } else if (LRC_UTF8 == encode_type) { + lrc_showbytes = ui_text_set_textw_by_id(LRC_TEXT_ID_SEC, buf + offset, disp_len, FONT_ENDIAN_SMALL, FONT_DEFAULT | FONT_SHOW_MULTI_LINE); + } else { + lrc_showbytes = ui_text_set_text_by_id(LRC_TEXT_ID_SEC, buf + offset, disp_len, FONT_DEFAULT); + } + } +#endif + return true; +} + +#endif //TCFG_LRC_LYRICS_ENABLE + diff --git a/apps/soundbox/ui/lcd/lyrics_api.h b/apps/soundbox/ui/lcd/lyrics_api.h new file mode 100644 index 0000000..75df7cd --- /dev/null +++ b/apps/soundbox/ui/lcd/lyrics_api.h @@ -0,0 +1,40 @@ +#ifndef __LYRICS_API_H__ +#define __LYRICS_API_H__ + +#include "ui/lyrics.h" +#include "ui/ui.h" + +///<保存歌词时间标签到flash, 可以解决较长歌词文件不兼容问题,要使能该功能,需要做以下几点: +//1、配置isd_tools.cfg文件(参考vm区间分配, LRIF_LEN 默认设置为64K) +// LRIF_ADDR=AUTO; +// LRIF_LEN=0x10000; +// LRIF_OPT=1; +//2、使能LRC_ENABLE_SAVE_LABEL_TO_FLASH +//3、配置时间标签临时缓存buf大小LABEL_TEMP_BUF_LEN(2048表示可以解释最长包含1024个时间标签的歌词文件) +//注意:如果flash空间不够, 只能不是能LRC_ENABLE_SAVE_LABEL_TO_FLASH,但是不兼容长歌词文件 +#define LRC_ENABLE_SAVE_LABEL_TO_FLASH 1 //是否使能保存歌词时间标签到flash, 1:保存, 0:不保存 + + +//宏定义区 +#define LRC_DISPLAY_TEXT_ID DVcTxt1_11 +#define LRC_DISPLAY_TEXT_LEN 32 + +#define ONCE_READ_LENGTH ALIGN_4BYTE(128) ///<涉及内存对齐问题,值最好是4的倍数(最大允许值为255) +#define ONCE_DIS_LENGTH ALIGN_4BYTE(64) ///显示歌词的缓存长度 +#define LABEL_TEMP_BUF_LEN ALIGN_4BYTE(2048) ///暂用2K缓存时间标签 + + +#if(CONFIG_UI_STYLE == STYLE_JL_SOUNDBOX) +#define LRC_TEXT_ID_FIR MUSIC_FILE //根据实际文本框的ID号修改 +#define LRC_TEXT_ID_SEC MUSIC_LYRICS //根据实际文本框的ID号修改 +#endif + +extern int lrc_init(void); +extern void lrc_exit(void); +extern int lrc_find(FILE *file, FILE **newFile, void *ext_name); +extern bool lrc_analysis_api(FILE *file, FILE **newFile); +extern void lrc_set_analysis_flag(u8 flag); +extern bool lrc_show_api(int text_id, u16 dbtime_s, u8 btime_100ms); +extern bool lrc_get_api(u16 dbtime_s, u8 btime_100ms); + +#endif//__LYRICS_API_H__ diff --git a/apps/soundbox/ui/lcd/ui_sys_param_api.c b/apps/soundbox/ui/lcd/ui_sys_param_api.c new file mode 100644 index 0000000..424974f --- /dev/null +++ b/apps/soundbox/ui/lcd/ui_sys_param_api.c @@ -0,0 +1,278 @@ +#include "ui/ui.h" +#include "app_config.h" +#include "ui/ui_style.h" +#include "ui/ui_api.h" +#include "app_action.h" +#include "system/timer.h" +#include "font/language_list.h" +#include "res/resfile.h" +#include "syscfg_id.h" + +#if (TCFG_UI_ENABLE && TCFG_SPI_LCD_ENABLE) +#include "ui/ui_sys_param.h" + +struct SYS_INFO { + u32 version_log; //版本日期 + u32 space_log; //内存大小 +}; + +struct UI_DISPLAY { + u16 backlight_time; //背光时间 + u16 backlight_brightness; //背光亮度 +}; + +typedef struct _UI_SYS_PARAM { + u16 cur_auto_close_time; //当前设置的关机时间 + struct SYS_INFO sys_infomation; //系统信息 + struct UI_DISPLAY display; //显示信息 +} UI_SYS_PARAM; + +//背光亮度 +static const char table_system_lcd_value[] = { + 30, + 60, + 80, + 100, +}; + +//背光时间 +static const u16 table_system_lcd_protect[] = { + 0, + 10, + 15, + 30, + 60, +}; + +//自动关机时间 +static const u16 table_system_auto_close[] = { + 0, + 15 * 60, + 30 * 60, + 60 * 60, + 120 * 60, + 180 * 60, +}; + +static UI_SYS_PARAM sys_param; +volatile static int system_auto_close_timer; //自动关机定时器 +volatile static int system_backlight_timer; //背光时间 +#define __this (&sys_param) + +extern void sys_enter_soft_poweroff(void *priv); +void auto_power_off_timer_close(void); +//*********************************************************************************// +// 配置开始 // +//*********************************************************************************// +static void sys_ui_backlight_close() +{ + printf("\n<<<<%s >>>>> \n", __FUNCTION__); + system_backlight_timer = 0; + ui_backlight_close(); +} + +void set_sys_param_default(void) +{ + __this->display.backlight_time = 0; + __this->display.backlight_brightness = 0; + __this->cur_auto_close_time = 0; + auto_power_off_timer_close(); +} + +void sys_param_write2vm(void) +{ + syscfg_write(CFG_UI_SYS_INFO, __this, sizeof(UI_SYS_PARAM)); +} + +void sys_param_init(void) +{ + int ret = 0; + r_printf("sys_param_init\n"); + ret = syscfg_read(CFG_UI_SYS_INFO, __this, sizeof(UI_SYS_PARAM)); + if (ret != sizeof(UI_SYS_PARAM)) { + r_printf("sys_param read err\n"); + memset(__this, 0, sizeof(UI_SYS_PARAM)); //暂时默认都为0; + set_sys_param_default(); + sys_param_write2vm(); + } + if (__this->cur_auto_close_time && (!system_auto_close_timer)) { + //每次重新开机把上次设置的自动关机时间设置进去 + system_auto_close_timer = sys_s_hi_timerout_add(NULL, sys_enter_soft_poweroff, (table_system_auto_close[__this->cur_auto_close_time ] * 1000)); + } + + if (__this->display.backlight_time && (!system_backlight_timer)) { + system_backlight_timer = sys_s_hi_timerout_add(NULL, sys_ui_backlight_close, (table_system_lcd_protect[ __this->display.backlight_time] * 1000)); + } + +} + +//*********************************************************************************// +// 系统信息配置 // +//*********************************************************************************// +void set_version_log(u32 log) +{ + __this->sys_infomation.version_log = log; +} + +u32 get_version_log(void) +{ + return __this->sys_infomation.version_log; +} + +void set_space_log(u32 log) +{ + __this->sys_infomation.space_log = log; +} + +u32 get_space_log(void) +{ + return __this->sys_infomation.space_log; +} + +//*********************************************************************************// +// 自动关机配置 // +//*********************************************************************************// +void set_auto_poweroff_timer(int sel_item) +{ + int time = table_system_auto_close[sel_item]; + __this->cur_auto_close_time = sel_item; + + if (time == 0) { + auto_power_off_timer_close(); + sys_param_write2vm(); + return; + } + + if (system_auto_close_timer) { + sys_s_hi_timer_modify(system_auto_close_timer, time * 1000); + } else { + system_auto_close_timer = sys_s_hi_timerout_add(NULL, sys_enter_soft_poweroff, (time * 1000)); + } + sys_param_write2vm(); +} + +void auto_power_off_timer_close(void) +{ + if (system_auto_close_timer) { + sys_s_hi_timeout_del(system_auto_close_timer); + system_auto_close_timer = 0; + } +} + +u16 get_cur_auto_power_time(void) +{ + return __this->cur_auto_close_time; +} + +//*********************************************************************************// +// 背光配置 // +//*********************************************************************************// +void set_backlight_time(u16 time) +{ + /* __this->display.backlight_time = table_system_lcd_protect[time]; */ + + + if (time >= sizeof(table_system_lcd_protect) / sizeof(table_system_lcd_protect[0])) { + return; + } + __this->display.backlight_time = time; + + if (system_backlight_timer) { + time = table_system_lcd_protect[__this->display.backlight_time]; + sys_s_hi_timer_modify(system_backlight_timer, time * 1000); + } + + if (__this->display.backlight_time && (!system_backlight_timer)) { + + system_backlight_timer = sys_s_hi_timerout_add(NULL, sys_ui_backlight_close, (table_system_lcd_protect[ __this->display.backlight_time] * 1000)); + } + + if (!__this->display.backlight_time && system_backlight_timer) { + sys_s_hi_timeout_del(system_backlight_timer); + system_backlight_timer = 0; + } + + + sys_param_write2vm(); +} + +u16 get_backlight_time_item(void) +{ + return __this->display.backlight_time; +} + +u16 get_backlight_time(void) +{ + return table_system_lcd_protect[__this->display.backlight_time]; +} + + +void set_backlight_brightness(u16 brightness) +{ + /* __this->display.backlight_brightness = table_system_lcd_value[brightness]; */ + if (brightness >= sizeof(table_system_lcd_value) / sizeof(table_system_lcd_value[0])) { + return; + } + + __this->display.backlight_brightness = brightness; + sys_param_write2vm(); +} + + + +u16 get_backlight_brightness_item(void) +{ + return __this->display.backlight_brightness; +} + +u16 get_backlight_brightness(void) +{ + return table_system_lcd_value[__this->display.backlight_brightness]; +} + +//*********************************************************************************// +// 其他配置 // +//*********************************************************************************// +void set_sys_info_reset(void) +{ + set_sys_param_default(); + sys_param_write2vm(); +} + + + +extern int lcd_backlight_status(); + +static int app_key_event(struct sys_event *e) +{ + struct key_event *key = &e->u.key; + int time; + + if (system_auto_close_timer) { + time = table_system_auto_close[__this->cur_auto_close_time ]; + sys_s_hi_timer_modify(system_auto_close_timer, time * 1000); + } + + + if (system_backlight_timer) { + time = table_system_lcd_protect[__this->display.backlight_time]; + sys_s_hi_timer_modify(system_backlight_timer, time * 1000); + } + + + + if (!lcd_backlight_status()) { + e->consumed = 1;//接管按键消息,app应用不会收到消息 + if (__this->display.backlight_time && (!system_backlight_timer)) { + system_backlight_timer = sys_s_hi_timerout_add(NULL, sys_ui_backlight_close, (table_system_lcd_protect[ __this->display.backlight_time] * 1000)); + ui_backlight_open(); + } + return TRUE; + } + + return FALSE; +} + +SYS_EVENT_HANDLER(SYS_KEY_EVENT, app_key_event, 2); + +#endif //TCFG_SPI_LCD_ENABLE diff --git a/apps/soundbox/ui/lcd/ui_sys_param_api.h b/apps/soundbox/ui/lcd/ui_sys_param_api.h new file mode 100644 index 0000000..f11a955 --- /dev/null +++ b/apps/soundbox/ui/lcd/ui_sys_param_api.h @@ -0,0 +1,25 @@ +#ifndef _SYS_PARAM_API_H_ +#define _SYS_PARAM_API_H_ + +void sys_param_init(void); +void sys_param_write2vm(void); + +void set_version_log(u32 log); +u32 get_version_log(void); +void set_space_log(u32 log); +u32 get_space_log(void); + +void set_auto_poweroff_timer(int sel_item); +void auto_power_off_timer_close(void); +u16 get_cur_auto_power_time(void); + +void set_backlight_time(u16 time); +u16 get_backlight_time(void); +u16 get_backlight_time_item(void); +void set_backlight_brightness(u16 brightness); +u16 get_backlight_brightness(void); +u16 get_backlight_brightness_item(void); + +void set_sys_info_reset(void); +#endif /* _SYS_PARAM_API_H_ */ + diff --git a/apps/soundbox/ui/lcd_simple/my_demo.c b/apps/soundbox/ui/lcd_simple/my_demo.c new file mode 100644 index 0000000..48277f9 --- /dev/null +++ b/apps/soundbox/ui/lcd_simple/my_demo.c @@ -0,0 +1,311 @@ +#include "ui/ui.h" +#include "app_config.h" +#include "ui/ui_api.h" +#include "app_task.h" +#include "system/timer.h" +#include "key_event_deal.h" +#include "audio_config.h" +#include "jiffies.h" +#include "ui/ui_simple/ui_res.h" +#include "ui/lcd_simple/ui.h" +#include "app_msg.h" +#include "ui/lcd_simple/ui_mainmenu.h" + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_UI_SIMPLE)) + +////FM任务下菜单//// +MENULIST FM_Main; //FM任务主菜单 +MENULIST FM_Seek; +////FM任务下菜单ID//// +const u16 FM_Main_ItemString[8] = +{fmenu16, sreplay1, fmenu1, fmenu15, fmenu2, fmenu3, fm_vol, mstop5}; + +const u16 FM_Seek_ItemString[3] = +{fm_manual, fmautoload, fm_switch}; + +static void DEMO_MenuInit(void) +{ + FM_Main.ItemSum = 8; + FM_Main.ActiveItemNum = 1; //菜单选中时的图标ID + FM_Main.IconID[0] = ACTIVE; //菜单选中时的图标ID + FM_Main.IconID[1] = UNACTIVE; //菜单未选中时的图标ID + FM_Main.TitleID = 0;//vstopm1; //菜单的标题字符串ID号,0代表无标题 + FM_Main.ItemString = FM_Main_ItemString; + + FM_Seek.ItemSum = 3; + FM_Seek.ActiveItemNum = 1; //菜单选中时的图标ID + FM_Seek.IconID[0] = ACTIVE; //菜单选中时的图标ID + FM_Seek.IconID[1] = UNACTIVE; //菜单未选中时的图标ID + FM_Seek.TitleID = 0;//vstopm1; //菜单的标题字符串ID号,0代表无标题 + FM_Seek.ItemString = FM_Seek_ItemString; +} + +static void UI_MenuSelectOn(uint8 showitemnum) +{ + TurnPixelReverse_Rect(MENUICONWIDTH, showitemnum * 2, SCR_WIDTH - SCROLLBARWIDTH - 1, showitemnum * 2 + 1); + ResShowPic(ACTIVE, 0, showitemnum * 16); +} + +static u8 volume_adjust(u8 mode) +{ + static u8 test = 0; + if (mode == UI_SLIDER_INC) { + test ++; + } + + if (mode == UI_SLIDER_DEC) { + if (test) { + test--; + } + } + printf(">>>>%s %d %d<<<<\n", __func__, __LINE__, test); + return test; +} + +static void UpdateMenu(MENULIST *Mlist) +{ + u8 i; + static u8 itembegin; + if (Mlist->TitleID > 0) { + itembegin = 1; + } else { + itembegin = 0; + } + + if (CurrentScreenNum < NeedScreenSumViaItem - 1) { + for (i = itembegin; i < MENUITEMSUMPERSCR; i++) { + ResShowPic(Mlist->IconID[1], 0, i * MENUITEMHEIGHT); + ResShowMultiString(MENUICONWIDTH, i * MENUITEMHEIGHT, Mlist->ItemString[(i - itembegin) + (CurrentScreenNum * (MENUITEMSUMPERSCR - itembegin))]); + } + } else { //到达最后一屏,只显示剩下的菜单项目 + for (i = itembegin; i < LaseScreenRemainMenuItem + itembegin; i++) { + ResShowPic(Mlist->IconID[1], 0, i * MENUITEMHEIGHT); + ResShowMultiString(MENUICONWIDTH, i * MENUITEMHEIGHT, Mlist->ItemString[(i - itembegin) + (CurrentScreenNum * (MENUITEMSUMPERSCR - itembegin))]); + } + } +} + +static u8 SetFMArrow(uint8 Start_x, uint8 Start_y) +{ + uint8 FMArrowPixelBuf[7] = {0x10, 0x30, 0x5F, 0x81, 0x5F, 0x30, 0x10}; + uint8 x; + + if ((Start_x > SCR_WIDTH - 7) || (Start_y > LCDPAGE)) { + return false; + } + + for (x = Start_x; x < Start_x + 7; x++) { + LCDBuff[Start_y][x] = FMArrowPixelBuf[x - Start_x]; + } + return true; +} + +//菜单// +static u8 DEMO_UI_MenuList(MENULIST *Mlist) +{ + uint8 autoruntime = MENUWAITTIME; + uint8 i = 0; + uint8 minusbase; + int msg[16]; + bool redraw = true; + + memset(&LCDBuff[0][0], 0x00, (SCR_HEIGHT / 8)*SCR_WIDTH); + + if (Mlist->TitleID > 0) { //有菜单标题 菜单项目数为3 + minusbase = (Mlist->ActiveItemNum + (MENUITEMSUMPERSCR - 1) - 1) / (MENUITEMSUMPERSCR - 1) - 1; + MenuItemSelectOnNum = Mlist->ActiveItemNum - minusbase * (MENUITEMSUMPERSCR - 1); + NeedScreenSumViaItem = (Mlist->ItemSum + (MENUITEMSUMPERSCR - 1) - 1) / (MENUITEMSUMPERSCR - 1); + LaseScreenRemainMenuItem = Mlist->ItemSum % (MENUITEMSUMPERSCR - 1); + if (LaseScreenRemainMenuItem == 0) { + LaseScreenRemainMenuItem = (MENUITEMSUMPERSCR - 1); + } + CurrentScreenNum = (Mlist->ActiveItemNum - 1) / (MENUITEMSUMPERSCR - 1); + ResShowMultiString(0, 0, Mlist->TitleID); //显示菜单图标 + + UpdateMenu(Mlist); + } else { //没有菜单标题 菜单项目数为4 + MenuItemSelectOnNum = (Mlist->ActiveItemNum - 1) % (MENUITEMSUMPERSCR); //当前屏的活动菜单 + NeedScreenSumViaItem = (Mlist->ItemSum + MENUITEMSUMPERSCR - 1) / MENUITEMSUMPERSCR; //需要分几屏显示 + LaseScreenRemainMenuItem = Mlist->ItemSum % MENUITEMSUMPERSCR; + + if (LaseScreenRemainMenuItem == 0) { + LaseScreenRemainMenuItem = (MENUITEMSUMPERSCR); + } + + CurrentScreenNum = (Mlist->ActiveItemNum - 1) / MENUITEMSUMPERSCR; + + UpdateMenu(Mlist); + } + UI_MenuSelectOn(MenuItemSelectOnNum); + + while (1) { + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + printf("%s demo key = %d value = %x\n", __func__, msg[1], msg[2]); + switch (msg[1]) { + case KEY_OK: + return Mlist->ItemString[Mlist->ActiveItemNum - 1]; + break; + case KEY_MENU: + break; + case KEY_DOWN: + autoruntime = MENUWAITTIME; + Mlist->ActiveItemNum -= 1; + if ((Mlist->ActiveItemNum <= 0) && (Mlist->TitleID > 0)) { + Mlist->ActiveItemNum = Mlist->ItemSum; + CurrentScreenNum = NeedScreenSumViaItem - 1; + MenuItemSelectOnNum = LaseScreenRemainMenuItem + 1; + } else if ((Mlist->ActiveItemNum <= 0) && (Mlist->TitleID <= 0)) { + Mlist->ActiveItemNum = Mlist->ItemSum; + CurrentScreenNum = NeedScreenSumViaItem - 1; + MenuItemSelectOnNum = LaseScreenRemainMenuItem; + } + + MenuItemSelectOnNum -= 1; + if ((MenuItemSelectOnNum <= 0) && (Mlist->TitleID > 0)) { + MenuItemSelectOnNum = 3; + CurrentScreenNum -= 1; + if (CurrentScreenNum < 0) { + CurrentScreenNum = 0; + } + } else if ((MenuItemSelectOnNum < 0) && (Mlist->TitleID <= 0)) { + MenuItemSelectOnNum = 3; + CurrentScreenNum -= 1; + if (CurrentScreenNum < 0) { + CurrentScreenNum = 0; + } + } + redraw = true; + + break; + case KEY_UP: + autoruntime = MENUWAITTIME; + Mlist->ActiveItemNum += 1; + if ((Mlist->ActiveItemNum > Mlist->ItemSum) && (Mlist->TitleID > 0)) { + Mlist->ActiveItemNum = 1; + CurrentScreenNum = 0; + MenuItemSelectOnNum = 0; + } else if ((Mlist->ActiveItemNum > Mlist->ItemSum) && (Mlist->TitleID <= 0)) { + Mlist->ActiveItemNum = 1; + CurrentScreenNum = 0; + MenuItemSelectOnNum = -1; + } + + + MenuItemSelectOnNum += 1; + if ((MenuItemSelectOnNum > 3) && (Mlist->TitleID > 0)) { + MenuItemSelectOnNum = 1; + CurrentScreenNum += 1; + if (CurrentScreenNum >= NeedScreenSumViaItem) { + CurrentScreenNum = 0; + } + } else if ((MenuItemSelectOnNum > 3) && (Mlist->TitleID <= 0)) { + MenuItemSelectOnNum = 0; + CurrentScreenNum += 1; + if (CurrentScreenNum >= NeedScreenSumViaItem) { + CurrentScreenNum = 0; + } + } + redraw = true; + + case MSG_HALF_SECOND: + autoruntime--; + if (!autoruntime) { + return mstop5; + } + break; + + default: + return 0xff; + break; + } + break; + } + + if (redraw) { + redraw = false; + memset(&LCDBuff[0][0], 0x00, (SCR_HEIGHT / 8)*SCR_WIDTH); + if (Mlist->TitleID > 0) { //有菜单标题 菜单项目数为3 + ResShowMultiString(0, 0, Mlist->TitleID); + UpdateMenu(Mlist); + } else { //没有菜单标题 菜单项目数为4 + UpdateMenu(Mlist); + } + UI_MenuSelectOn(MenuItemSelectOnNum); + + SetScrollBar(SCR_WIDTH - SCROLLBARWIDTH); //滚动条 + //滑动块设置 + if (Mlist->ItemSum == 8) { + SetSlideBlock(SCR_WIDTH - SCROLLBARWIDTH + 1, Mlist->ActiveItemNum - 1); + } else if (Mlist->ItemSum < 8) { + if (Mlist->ActiveItemNum == 1) { + SetSlideBlock(SCR_WIDTH - SCROLLBARWIDTH + 1, 0); + } else if (Mlist->ActiveItemNum == Mlist->ItemSum) { + SetSlideBlock(SCR_WIDTH - SCROLLBARWIDTH + 1, 7); + } else if (Mlist->ItemSum <= 4) { + SetSlideBlock(SCR_WIDTH - SCROLLBARWIDTH + 1, Mlist->ActiveItemNum * 2 - 1); + } else if (Mlist->ItemSum == 5 && Mlist->ActiveItemNum == 2) { + SetSlideBlock(SCR_WIDTH - SCROLLBARWIDTH + 1, 2); + } else { + SetSlideBlock(SCR_WIDTH - SCROLLBARWIDTH + 1, 8 * Mlist->ActiveItemNum / Mlist->ItemSum); + } + } else if (Mlist->ItemSum > 8) { + if (Mlist->ActiveItemNum == 1) { + SetSlideBlock(SCR_WIDTH - SCROLLBARWIDTH + 1, 0); + } + if (Mlist->ActiveItemNum == Mlist->ItemSum) { + SetSlideBlock(SCR_WIDTH - SCROLLBARWIDTH + 1, 7); + } else { + SetSlideBlock(SCR_WIDTH - SCROLLBARWIDTH + 1, 8 * Mlist->ActiveItemNum / Mlist->ItemSum); + } + } + draw_lcd(0, LCDPAGE); + } + + } +} + + + + + + + +void demo_simple_ui_mode() +{ + int msg[16]; + DEMO_MenuInit(); + while (1) { + app_task_get_msg(msg, ARRAY_SIZE(msg), 1); + switch (msg[0]) { + case APP_MSG_SYS_EVENT: + printf("ui %s key = %d value = %x\n", __func__, msg[1], msg[2]); + switch (msg[1]) { + case KEY_OK: + UI_mainmenu(APP_FM_TASK); + DEMO_UI_MenuList(&FM_Main); + DEMO_UI_MenuList(&FM_Seek); + /* UI_mainmenu(APP_RECORD_TASK); */ + ui_simple_key_msg_post(KEY_OK, 0); + break; + case KEY_MENU: + break; + case KEY_DOWN: + break; + case KEY_UP: + break; + default: + break; + } + break; + } + } +} + + + + + + +#endif diff --git a/apps/soundbox/ui/led/pwm_led_api.c b/apps/soundbox/ui/led/pwm_led_api.c new file mode 100644 index 0000000..ca60ea1 --- /dev/null +++ b/apps/soundbox/ui/led/pwm_led_api.c @@ -0,0 +1,637 @@ +#include "ui_manage.h" +#include "asm/pwm_led.h" +#include "system/includes.h" +#include "app_config.h" +#include "user_cfg.h" + +#if TCFG_PWMLED_ENABLE + +#define LOG_TAG_CONST UI +#define LOG_TAG "[UI]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#define UI_MANAGE_BUF 8 + +static bool ui_status_read_alloc(void); +static u8 ui_status_pop(u8 *status); +static void ui_status_manager_init(void); +static u32 ui_status_push(u8 status); +static int ui_normal_status_deal(u8 *status, u8 *power_status, u8 ui_mg_para); +static int ui_charging_deal(u8 *status, u8 *power_status, u8 ui_mg_para); +static int ui_power_off_deal(u8 *status, u8 *power_status, u8 ui_mg_para); +static void ui_manage_scan(void *priv); +extern const pwm_led_breathe_para pwm_led_breathe_para_table[]; +extern const pwm_led_double_flash_para pwm_led_double_flash_para_table[]; +extern const pwm_led_one_flash_para pwm_led_one_flash_para_table[]; +extern const pwm_led_on_para pwm_led_on_para_table[]; +static int led_remap_status_get(u8 status); + +typedef struct _ui_var { + u8 ui_init_flag; + u8 other_status; + u8 power_status; + u8 current_status; + volatile u8 ui_flash_cnt; + volatile u32 ui_flash_fre; + cbuffer_t ui_cbuf; + u8 ui_buf[UI_MANAGE_BUF]; + int sys_ui_timer; +} ui_var; + +enum { + UI_MG_CALL_USER = 1, + UI_MG_CALL_LED_FLASH = 2, +}; + +static ui_var sys_ui_var = {.power_status = STATUS_NORMAL_POWER}; + +/* + * display:显示的模式,PWM_LED_ALL_OFF ~ PWM_LED_MODE_END.*注意显示的模式是系统固定的,不能用户自己增加模式 + * + * para_sel:同一个模式下面,用户可以根据para_sel值来选择不同的参数值,进而实现不同的效果控制 + * 示例: + if (para_sel == 1) + {可以通过para_sel*来选择不同的参数 + para.on = on_para[0]; + } + else + { + para.on = on_para[1]; + } +*/ +void ui_mode_set(u8 display, u8 para_sel) +{ + pwm_led_para para = {0}; + + if (display == PWM_LED_NULL) { + return; + } + + + switch (display) { + case PWM_LED_ALL_OFF: + case PWM_LED0_OFF: + case PWM_LED1_OFF: + break; + +//灯常亮 + case PWM_LED0_ON: + if (para_sel == 1) { + para.on = pwm_led_on_para_table[3]; + } else { + para.on = pwm_led_on_para_table[0]; + } + break; + case PWM_LED1_ON: + para.on = pwm_led_on_para_table[1]; + break; + case PWM_LED_ALL_ON: + para.on = pwm_led_on_para_table[2]; + break; + +//单灯单闪 + case PWM_LED0_SLOW_FLASH: + para.one_flash = pwm_led_one_flash_para_table[0]; + break; + case PWM_LED1_SLOW_FLASH: + para.one_flash = pwm_led_one_flash_para_table[1]; + break; + case PWM_LED0_FAST_FLASH: + para.one_flash = pwm_led_one_flash_para_table[2]; + break; + case PWM_LED1_FAST_FLASH: + para.one_flash = pwm_led_one_flash_para_table[3]; + break; + case PWM_LED0_ONE_FLASH_5S: + para.one_flash = pwm_led_one_flash_para_table[4]; + break; + case PWM_LED1_ONE_FLASH_5S: + para.one_flash = pwm_led_one_flash_para_table[5]; + break; +//双灯互闪 + case PWM_LED0_LED1_FAST_FLASH: + para.one_flash = pwm_led_one_flash_para_table[6]; + break; + case PWM_LED0_LED1_SLOW_FLASH: + para.one_flash = pwm_led_one_flash_para_table[7]; + break; + +//单灯双闪 + case PWM_LED0_DOUBLE_FLASH_5S: + para.double_flash = pwm_led_double_flash_para_table[0]; + break; + case PWM_LED1_DOUBLE_FLASH_5S: + para.double_flash = pwm_led_double_flash_para_table[1]; + break; + +//呼吸模式 + case PWM_LED0_BREATHE: + para.breathe = pwm_led_breathe_para_table[0]; + break; + case PWM_LED1_BREATHE: + para.breathe = pwm_led_breathe_para_table[1]; + break; + case PWM_LED0_LED1_BREATHE: + para.breathe = pwm_led_breathe_para_table[2]; + break; + + default: + log_error("pwm led para not match:%d \n", display); + return; + break; + } + + pwm_led_mode_set_with_para(display, para); +} + +void ui_user_mode_set(u8 status, u8 display, u8 para_sel) +{ + int ret = led_remap_status_get(status); + if (ret != (-1)) { + display = (u8)ret; + } + + ui_mode_set(display, para_sel); +} + +static bool ui_status_fetch(u8 *status, u8 *power_status) +{ + bool ret = false; + if (ui_status_pop(&sys_ui_var.current_status)) { + if (sys_ui_var.current_status >= STATUS_CHARGE_START && sys_ui_var.current_status <= STATUS_NORMAL_POWER) { + ///充电模式优先处理 + *power_status = sys_ui_var.current_status; + } else { + *status = sys_ui_var.current_status; + } + + ret = true; + } + + return ret; +} + +/***********************led flash three ******************************/ +#define IS_LED_FLASH_PROCESSING(ui_mg_para) (ui_mg_para == UI_MG_CALL_LED_FLASH) +static void ui_led_flash_register_next_process(void) +{ + sys_ui_var.sys_ui_timer = 0; + if (sys_ui_var.ui_flash_cnt) { + sys_ui_var.ui_flash_cnt --; + sys_ui_var.sys_ui_timer = sys_hi_timeout_add((void *)UI_MG_CALL_LED_FLASH, ui_manage_scan, sys_ui_var.ui_flash_fre); + } +} + +/***********************ui process manage ******************************/ +static void ui_manage_scan(void *priv) +{ + u8 ui_mg_para = (u8)priv; + log_info("ui_flash_cnt:%d cur_ui_status:%d ui_mg_para:%d \n", \ + sys_ui_var.ui_flash_cnt, sys_ui_var.current_status, ui_mg_para); + + if (!IS_LED_FLASH_PROCESSING(ui_mg_para)) { //有特殊的闪烁状态等当前状态执行完再进入下一个状态 + ui_status_fetch(&(sys_ui_var.other_status), &(sys_ui_var.power_status)); + } + + ///step one处理STATUS_POWEROFF + if (ui_power_off_deal(&(sys_ui_var.other_status), &(sys_ui_var.power_status), ui_mg_para) != (-1)) { + log_info("*STATUS_POWEROFF*\n"); + goto _ui_status_deal_end; + } + + //step two处理power status + if (ui_charging_deal(&(sys_ui_var.other_status), &(sys_ui_var.power_status), ui_mg_para) != (-1)) { + log_info("*STATUS_CHARGING*\n"); + goto _ui_status_deal_end; + } + + //last step 处理normal status + if (ui_normal_status_deal(&(sys_ui_var.other_status), &(sys_ui_var.power_status), ui_mg_para) != (-1)) { + goto _ui_status_deal_end; + } + +_ui_status_deal_end: + + if (!IS_LED_FLASH_PROCESSING(ui_mg_para)) { //有特殊的闪烁状态等当前状态执行完再进入下一个状态 + if (ui_status_read_alloc() == true) { + ///cmd pool还有命令,启动一下命令处理 + log_info("*FETCH NEXT CMD*\n"); + sys_ui_var.sys_ui_timer = sys_hi_timeout_add((void *)UI_MG_CALL_USER, ui_manage_scan, 10); + } + } + + ui_led_flash_register_next_process(); + return; + +} + +static int ui_power_off_deal(u8 *status, u8 *power_status, u8 ui_mg_para) +{ + int ret = -1; + + switch (*status) { + case STATUS_POWEROFF: + log_info("[STATUS_POWEROFF]\n"); + ///init ui_flash_cnt + if (ui_mg_para == UI_MG_CALL_USER) { + sys_ui_var.ui_flash_cnt = 7; + sys_ui_var.ui_flash_fre = 300; + } + + if (sys_ui_var.ui_flash_cnt) { + if (sys_ui_var.ui_flash_cnt % 2) { + ui_user_mode_set(STATUS_POWEROFF, PWM_LED1_OFF, 0); + } else { + ui_user_mode_set(STATUS_POWEROFF, PWM_LED1_ON, 0); + } + } + ret = 0; + break; + default: + break; + } + + return ret; +} + +static int ui_charging_deal(u8 *status, u8 *power_status, u8 ui_mg_para) +{ +#define IS_CHARGING_MODE_STATUS() ((*power_status) != STATUS_NORMAL_POWER) + int ret = -1; + + if (IS_CHARGING_MODE_STATUS()) { + switch (*power_status) { + case STATUS_LOWPOWER: + log_info("[STATUS_LOWPOWER]\n"); + ui_user_mode_set(STATUS_LOWPOWER, PWM_LED1_SLOW_FLASH, 0); + break; + + case STATUS_CHARGE_START: + log_info("[STATUS_CHARGE_START]\n"); + ui_user_mode_set(STATUS_CHARGE_START, PWM_LED1_ON, 0); + break; + + case STATUS_CHARGE_FULL: + log_info("[STATUS_CHARGE_FULL]\n"); + ui_user_mode_set(STATUS_CHARGE_FULL, PWM_LED0_ON, 0); + break; + + case STATUS_CHARGE_ERR: + log_info("[STATUS_CHARGE_ERR]\n"); + ui_user_mode_set(STATUS_CHARGE_ERR, PWM_LED0_ON, 0); + ui_user_mode_set(STATUS_CHARGE_ERR, PWM_LED1_ON, 0); + break; + + case STATUS_CHARGE_CLOSE: + log_info("[STATUS_CHARGE_CLOSE]\n"); + ui_user_mode_set(STATUS_CHARGE_CLOSE, PWM_LED0_OFF, 0); + ui_user_mode_set(STATUS_CHARGE_CLOSE, PWM_LED1_OFF, 0); + break; + + case STATUS_CHARGE_LDO5V_OFF: + log_info("[STATUS_CHARGE_LDO5V_OFF]\n"); + case STATUS_EXIT_LOWPOWER: + case STATUS_NORMAL_POWER: + //ui_user_mode_set(STATUS_NORMAL_POWER,PWM_LED0_OFF,0); + //ui_user_mode_set(STATUS_NORMAL_POWER,PWM_LED1_OFF,0); + *power_status = STATUS_NORMAL_POWER; + break; + + default: + break; + } + + ret = 0; + } + + return ret; +} + +static int ui_normal_status_deal(u8 *status, u8 *power_status, u8 ui_mg_para) +{ + int ret = -1; + + ret = 0; + switch (*status) { + case STATUS_DEMO_MODE: + log_info("[STATUS_DEMO_MODE]\n"); + ui_user_mode_set(STATUS_DEMO_MODE, PWM_LED0_ON, 1); + break; + + case STATUS_POWERON: + log_info("[STATUS_POWERON]\n"); + ui_user_mode_set(STATUS_POWERON, PWM_LED0_ON, 0); + break; + case STATUS_POWEROFF: + log_info("[STATUS_POWEROFF]\n"); + ///init ui_flash_cnt + if (ui_mg_para == UI_MG_CALL_USER) { + sys_ui_var.ui_flash_cnt = 7; + sys_ui_var.ui_flash_fre = 300; + } + + if (sys_ui_var.ui_flash_cnt) { + if (sys_ui_var.ui_flash_cnt % 2) { + ui_user_mode_set(STATUS_POWEROFF, PWM_LED1_OFF, 0); + } else { + ui_user_mode_set(STATUS_POWEROFF, PWM_LED1_ON, 0); + } + } + break; + + case STATUS_BT_INIT_OK: + log_info("[STATUS_BT_INIT_OK]\n"); + ui_user_mode_set(STATUS_BT_INIT_OK, PWM_LED0_LED1_SLOW_FLASH, 0); + break; + + case STATUS_BT_SLAVE_CONN_MASTER: + ui_user_mode_set(STATUS_BT_SLAVE_CONN_MASTER, PWM_LED1_SLOW_FLASH, 0); + break; + + case STATUS_BT_CONN: + log_info("[STATUS_BT_CONN]\n"); + ui_user_mode_set(STATUS_BT_CONN, PWM_LED0_ONE_FLASH_5S, 0); + break; + + case STATUS_BT_MASTER_CONN_ONE: + log_info("[STATUS_BT_MASTER_CONN_ONE]\n"); + ui_user_mode_set(STATUS_BT_MASTER_CONN_ONE, PWM_LED0_LED1_SLOW_FLASH, 0); + break; + + case STATUS_BT_DISCONN: + log_info("[STATUS_BT_DISCONN]\n"); + ui_user_mode_set(STATUS_BT_DISCONN, PWM_LED0_LED1_FAST_FLASH, 0); + break; + + case STATUS_PHONE_INCOME: + log_info("[STATUS_PHONE_INCOME]\n"); + ui_user_mode_set(STATUS_PHONE_INCOME, PWM_LED_NULL, 0); + break; + + case STATUS_PHONE_OUT: + log_info("[STATUS_PHONE_OUT]\n"); + ui_user_mode_set(STATUS_PHONE_OUT, PWM_LED_NULL, 0); + break; + + case STATUS_PHONE_ACTIV: + log_info("[STATUS_PHONE_ACTIV]\n"); + ui_user_mode_set(STATUS_PHONE_ACTIV, PWM_LED_NULL, 0); + break; + + case STATUS_POWERON_LOWPOWER: + log_info("[STATUS_POWERON_LOWPOWER]\n"); + ui_user_mode_set(STATUS_POWERON_LOWPOWER, PWM_LED1_SLOW_FLASH, 0); + break; + + case STATUS_BT_TWS_CONN: + log_info("[STATUS_BT_TWS_CONN]\n"); + ui_user_mode_set(STATUS_BT_TWS_CONN, PWM_LED0_LED1_FAST_FLASH, 0); + break; + case STATUS_BT_TWS_DISCONN: + log_info("[STATUS_BT_TWS_DISCONN]\n"); + ui_user_mode_set(STATUS_BT_TWS_DISCONN, PWM_LED0_LED1_SLOW_FLASH, 0); + break; + case STATUS_MUSIC_MODE: + log_info("[STATUS_MUSIC_MODE]\n"); + ui_user_mode_set(STATUS_MUSIC_MODE, PWM_LED0_SLOW_FLASH, 0); + break; + case STATUS_MUSIC_PLAY: + log_info("[STATUS_MUSIC_PLAY]\n"); + ui_user_mode_set(STATUS_MUSIC_PLAY, PWM_LED0_SLOW_FLASH, 0); + break; + case STATUS_MUSIC_PAUSE: + log_info("[STATUS_MUSIC_PAUSE]\n"); + ui_user_mode_set(STATUS_MUSIC_PAUSE, PWM_LED0_ON, 0); + break; + case STATUS_LINEIN_MODE: + log_info("[STATUS_LINEIN_MODE]\n"); + ui_user_mode_set(STATUS_LINEIN_MODE, PWM_LED0_SLOW_FLASH, 0); + break; + case STATUS_LINEIN_PLAY: + log_info("[STATUS_LINEIN_PLAY]\n"); + ui_user_mode_set(STATUS_LINEIN_PLAY, PWM_LED0_SLOW_FLASH, 0); + break; + case STATUS_LINEIN_PAUSE: + log_info("[STATUS_LINEIN_PAUSE]\n"); + ui_user_mode_set(STATUS_LINEIN_PAUSE, PWM_LED0_ON, 0); + break; + case STATUS_PC_MODE: + log_info("[STATUS_PC_MODE]\n"); + ui_user_mode_set(STATUS_PC_MODE, PWM_LED0_SLOW_FLASH, 0); + break; + case STATUS_PC_PLAY: + log_info("[STATUS_PC_PLAY]\n"); + ui_user_mode_set(STATUS_PC_PLAY, PWM_LED0_SLOW_FLASH, 0); + break; + case STATUS_PC_PAUSE: + log_info("[STATUS_PC_PAUSE]\n"); + ui_user_mode_set(STATUS_PC_PAUSE, PWM_LED0_ON, 0); + break; + case STATUS_FM_MODE: + log_info("[STATUS_FM_MODE]\n"); + ui_user_mode_set(STATUS_FM_MODE, PWM_LED0_SLOW_FLASH, 0); + break; + case STATUS_RECORD_MODE: + log_info("[STATUS_RECORD_MODE]\n"); + ui_user_mode_set(STATUS_RECORD_MODE, PWM_LED0_SLOW_FLASH, 0); + break; + case STATUS_SPDIF_MODE: + log_info("[STATUS_SPDIF_MODE]\n"); + ui_user_mode_set(STATUS_SPDIF_MODE, PWM_LED0_SLOW_FLASH, 0); + break; + case STATUS_RTC_MODE: + log_info("[STATUS_RTC_MODE]\n"); + ui_user_mode_set(STATUS_RTC_MODE, PWM_LED0_SLOW_FLASH, 0); + break; + + default: + ret = -1; + break; + } + + return ret; +} + +int ui_manage_init(void) +{ + if (!sys_ui_var.ui_init_flag) { + ui_status_manager_init(); + sys_ui_var.ui_init_flag = 1; + } + return 0; +} + +void ui_update_status(u8 status) +{ + int ui_mg_para = UI_MG_CALL_USER; + if (!sys_ui_var.ui_init_flag) { //更新UI状态之前需先初始化ui_cbuf + ui_manage_init(); + } + log_info("update ui status :%d", status); + + ui_status_push(status); + + ui_manage_scan((void *)ui_mg_para); +} + +/***********************ui flag******************************/ +u8 get_ui_busy_status() +{ + return sys_ui_var.ui_flash_cnt; +} + +u8 adv_get_led_status(void) +{ + return sys_ui_var.other_status; +} + +/***********************ui remap led status******************************/ +static LED_REMAP_STATUS led_remap_t = {PWM_LED_NULL}; +void *led_get_remap_t(void) +{ + return &led_remap_t; +} + +static void led_remap_init(void) +{ + memset(&led_remap_t, PWM_LED_NULL, sizeof(LED_REMAP_STATUS)); +} + +static int led_remap_status_get(u8 status) +{ + LED_REMAP_STATUS *p_led = led_get_remap_t(); + u8 led_user_status = PWM_LED_NULL; + switch (status) { + case STATUS_LOWPOWER: + led_user_status = p_led->lowpower; + break; + case STATUS_CHARGE_START: + led_user_status = p_led->charge_start; + break; + case STATUS_CHARGE_FULL: + led_user_status = p_led->charge_full; + break; + case STATUS_POWERON: + led_user_status = p_led->power_on; + break; + case STATUS_POWEROFF: + led_user_status = p_led->power_off; + break; + case STATUS_BT_INIT_OK: + led_user_status = p_led->bt_init_ok; + break; + case STATUS_BT_CONN: + led_user_status = p_led->bt_connect_ok; + break; + case STATUS_BT_DISCONN: + led_user_status = p_led->bt_disconnect; + break; + case STATUS_PHONE_INCOME: + led_user_status = p_led->phone_in; + break; + case STATUS_PHONE_OUT: + led_user_status = p_led->phone_out; + break; + case STATUS_PHONE_ACTIV: + led_user_status = p_led->phone_activ; + break; + case STATUS_POWERON_LOWPOWER: + led_user_status = p_led->lowpower; + break; + case STATUS_BT_TWS_CONN: + led_user_status = p_led->tws_connect_ok; + break; + case STATUS_BT_TWS_DISCONN: + led_user_status = p_led->tws_disconnect; + break; + case STATUS_MUSIC_MODE: + case STATUS_MUSIC_PLAY: + led_user_status = p_led->music_play; + break; + case STATUS_MUSIC_PAUSE: + led_user_status = p_led->music_pause; + break; + case STATUS_LINEIN_MODE: + case STATUS_LINEIN_PLAY: + led_user_status = p_led->linein_play; + break; + case STATUS_LINEIN_PAUSE: + led_user_status = p_led->linein_mute; + break; + } + + if (led_user_status == PWM_LED_NULL) { + return (-1); + } + + log_info("led remap index:%d \n", led_user_status); + + return led_user_status; +} + +/***********************ui command manage******************************/ +static void ui_status_manager_init(void) +{ + cbuf_init(&(sys_ui_var.ui_cbuf), &(sys_ui_var.ui_buf), UI_MANAGE_BUF); +} + +static u8 ui_status_pop(u8 *status) +{ + return cbuf_read(&(sys_ui_var.ui_cbuf), status, 1); +} + +static u32 ui_status_push(u8 status) +{ + return cbuf_write(&(sys_ui_var.ui_cbuf), &status, 1); +} + +static bool ui_status_read_alloc(void) +{ + u32 len = 0; + cbuf_read_alloc(&(sys_ui_var.ui_cbuf), &len); + return (len > 0); +} + +void ui_pwm_led_init(const struct led_platform_data *user_data) +{ + led_remap_init(); + ui_manage_init(); + pwm_led_init(user_data); +} +#else +int ui_manage_init(void) +{ + return 0; +} + +void ui_update_status(u8 status) +{ + u8 status_para = status; +} +u8 get_ui_busy_status() +{ + return 0; +} + +u8 adv_get_led_status(void) +{ + return 0; +} + +void ui_pwm_led_init(const struct led_platform_data *user_data) +{ + const struct led_platform_data *user_data_para = user_data; +} + +static LED_REMAP_STATUS led_remap_t = {PWM_LED_NULL}; +void *led_get_remap_t(void) +{ + return &led_remap_t; +} + +#endif diff --git a/apps/soundbox/ui/led/pwm_led_para_table.c b/apps/soundbox/ui/led/pwm_led_para_table.c new file mode 100644 index 0000000..257ac21 --- /dev/null +++ b/apps/soundbox/ui/led/pwm_led_para_table.c @@ -0,0 +1,86 @@ +#include "ui_manage.h" +#include "asm/pwm_led.h" +#include "system/includes.h" +#include "app_config.h" +#include "user_cfg.h" + +#if TCFG_PWMLED_ENABLE + +#define CFG_LED0_LIGHT 100 //10 ~ 500, 值越大, (红灯)亮度越高 +#define CFG_LED1_LIGHT 100 //10 ~ 500, 值越大, (蓝灯)亮度越高 + +#define CFG_SINGLE_FAST_FLASH_FREQ 500 //LED单独快闪速度, ms闪烁一次(100 ~ 1000) +#define CFG_SINGLE_FAST_LIGHT_TIME 100 //单灯快闪灯亮持续时间, 单位ms + +#define CFG_SINGLE_SLOW_FLASH_FREQ 2000 //LED单独慢闪速度, ms闪烁一次(1000 ~ 20000) +#define CFG_SINGLE_SLOW_LIGHT_TIME 100 //单灯慢闪灯亮持续时间, 单位ms + +#define CFG_DOUBLE_FAST_FLASH_FREQ 500 //LED交替快闪速度, ms闪烁一次(100 ~ 1000) +#define CFG_DOUBLE_SLOW_FLASH_FREQ 2000 //LED交替慢闪速度, ms闪烁一次(1000 ~ 20000) + +/***************** LED0/LED1单独每隔5S单闪时, 可供调节参数 ********************/ +#define CFG_LED_5S_FLASH_LIGHT_TIME 100 //LED 5S 闪烁时灯亮持续时间, 单位ms + +/***************** 呼吸模式配置参数, 可供调节参数 ********************/ +#define CFG_LED_BREATH_TIME 1000 //呼吸时间灭->亮->灭, 单位ms +#define CFG_LED0_BREATH_BRIGHT 300 //呼吸亮度, 范围: 0 ~ 500 +#define CFG_LED1_BREATH_BRIGHT 300 //呼吸亮度, 范围: 0 ~ 500 +#define CFG_LED_BREATH_BLINK_TIME 1000 //灭灯延时, 单位ms + +const pwm_led_on_para pwm_led_on_para_table[] = { + /* + u16 led0_bright;//led0_bright, LED0亮度: 0 ~ 500 + u16 led1_bright;//led1_bright, LED1亮度: 0 ~ 500 + */ + {CFG_LED0_LIGHT, CFG_LED1_LIGHT},//PWM_LED0_ON 蓝亮 + {CFG_LED0_LIGHT, CFG_LED1_LIGHT},//PWM_LED1_ON 红亮 + {CFG_LED0_LIGHT, CFG_LED1_LIGHT},//PWM_LED_ALL_ON 全亮 + {300, 100},//demo para +}; + +const pwm_led_one_flash_para pwm_led_one_flash_para_table[] = { + /* + u16 led0_bright;//led0_bright: led0亮度(0 ~ 500), + u16 led1_bright;//led1_bright: led1亮度(0 ~ 500), + u32 period;//period: 闪灯周期(ms), 多少ms闪一下(100 ~ 20000), 100ms - 20S, + u32 start_light_time;//start_light_time: 在周期中开始亮灯的时间, -1: 周期最后亮灯, 默认填-1即可, + u32 light_time;//light_time: 灯亮持续时间, + */ + {CFG_LED0_LIGHT, CFG_LED1_LIGHT, CFG_SINGLE_SLOW_FLASH_FREQ, -1, CFG_SINGLE_SLOW_LIGHT_TIME},//PWM_LED0_SLOW_FLASH 蓝慢闪 + {CFG_LED0_LIGHT, CFG_LED1_LIGHT, CFG_SINGLE_SLOW_FLASH_FREQ, -1, CFG_SINGLE_SLOW_LIGHT_TIME},//PWM_LED1_SLOW_FLASH 红慢闪 + {CFG_LED0_LIGHT, CFG_LED1_LIGHT, CFG_SINGLE_FAST_FLASH_FREQ, -1, CFG_SINGLE_FAST_LIGHT_TIME},//PWM_LED0_FAST_FLASH 蓝快闪 + {CFG_LED0_LIGHT, CFG_LED1_LIGHT, CFG_SINGLE_FAST_FLASH_FREQ, -1, CFG_SINGLE_FAST_LIGHT_TIME},//PWM_LED1_FAST_FLASH 红快闪 + {CFG_LED0_LIGHT, CFG_LED1_LIGHT, 5000, 10, CFG_LED_5S_FLASH_LIGHT_TIME},//PWM_LED0_ONE_FLASH_5S 蓝灯5秒连闪1下 + {CFG_LED0_LIGHT, CFG_LED1_LIGHT, 5000, 10, CFG_LED_5S_FLASH_LIGHT_TIME},//PWM_LED1_ONE_FLASH_5S 红灯5秒闪1下 + {CFG_LED0_LIGHT, CFG_LED1_LIGHT, CFG_DOUBLE_FAST_FLASH_FREQ, -1, -1},//PWM_LED0_LED1_FAST_FLASH 红蓝交替闪(快闪) + {CFG_LED0_LIGHT, CFG_LED1_LIGHT, CFG_DOUBLE_SLOW_FLASH_FREQ, -1, -1},//PWM_LED0_LED1_SLOW_FLASH 红蓝交替闪(慢闪) +}; + +const pwm_led_double_flash_para pwm_led_double_flash_para_table[] = { + /* + u16 led0_bright;//led0_bright: led0亮度, + u16 led1_bright;//led1_bright: led1亮度, + u32 period;//period: 闪灯周期(ms), 多少ms闪一下 + u32 first_light_time;//first_light_time: 第一次亮灯持续时间, + u32 gap_time;//gap_time: 两次亮灯时间间隔, + u32 second_light_time;//second_light_time: 第二次亮灯持续时间, + */ + {CFG_LED0_LIGHT, CFG_LED1_LIGHT, 5000, 100, 200, 100}, //PWM_LED0_DOUBLE_FLASH_5S 蓝灯5秒连闪两下 + {CFG_LED0_LIGHT, CFG_LED1_LIGHT, 5000, 100, 200, 100}, //PWM_LED1_DOUBLE_FLASH_5S 红灯5秒连闪两下 +}; + +const pwm_led_breathe_para pwm_led_breathe_para_table[] = { + /* + u16 breathe_time;//breathe_time: 呼吸周期(灭->最亮->灭), 设置范围: 500ms以上; + u16 led0_bright;//led0_bright: led0呼吸到最亮的亮度(0 ~ 500); + u16 led1_bright;//led1_bright: led1呼吸到最亮的亮度(0 ~ 500); + u32 led0_light_delay_time;//led0_light_delay_time: led0最高亮度延时(0 ~ 100ms); + u32 led1_light_delay_time;//led1_light_delay_time: led1最高亮度延时(0 ~ 100ms); + u32 led_blink_delay_time;//led_blink_delay_time: led0和led1灭灯延时(0 ~ 20000ms), 0 ~ 20S; + */ + {CFG_LED_BREATH_TIME, CFG_LED0_BREATH_BRIGHT, CFG_LED1_BREATH_BRIGHT, 0, 0, CFG_LED_BREATH_BLINK_TIME},//PWM_LED0_BREATHE 蓝灯呼吸灯模式 + {CFG_LED_BREATH_TIME, CFG_LED0_BREATH_BRIGHT, CFG_LED1_BREATH_BRIGHT, 0, 0, CFG_LED_BREATH_BLINK_TIME},//PWM_LED1_BREATHE 红灯呼吸灯模式 + {CFG_LED_BREATH_TIME, CFG_LED0_BREATH_BRIGHT, CFG_LED1_BREATH_BRIGHT, 0, 0, CFG_LED_BREATH_BLINK_TIME},//PWM_LED0_LED1_BREATHE 红蓝交替呼吸灯模式 +}; + +#endif diff --git a/apps/soundbox/ui/led7/ui_bt.c b/apps/soundbox/ui/led7/ui_bt.c new file mode 100644 index 0000000..e902e05 --- /dev/null +++ b/apps/soundbox/ui/led7/ui_bt.c @@ -0,0 +1,145 @@ +#include "includes.h" +#include "ui/ui_api.h" +#include "fm_emitter/fm_emitter_manage.h" +#include "btstack/avctp_user.h" + +#if (TCFG_APP_BT_EN) + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_LED7)) + +static void led7_show_bt(void *hd) +{ + + LCD_API *dis = (LCD_API *)hd; + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string((u8 *)" bt"); + dis->lock(0); +} + +static void led7_show_call(void *hd) +{ + LCD_API *dis = (LCD_API *)hd; + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string((u8 *)" CAL"); + dis->lock(0); +} + + + +static void led7_fm_show_freq(void *hd, void *private, u32 arg) +{ + u8 bcd_number[5] = {0}; + LCD_API *dis = (LCD_API *)hd; + u16 freq = 0; + freq = arg; + + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + itoa4(freq, (u8 *)bcd_number); + if (freq > 999 && freq <= 1999) { + bcd_number[0] = '1'; + } else { + bcd_number[0] = ' '; + } + dis->show_string(bcd_number); + dis->show_icon(LED7_DOT); + dis->lock(0); +} + + +static void led7_show_wait(void *hd) +{ + LCD_API *dis = (LCD_API *)hd; + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string((u8 *)" Lod"); + dis->lock(0); +} + + + +static void *ui_open_bt(void *hd) +{ + void *private = NULL; + ui_set_auto_reflash(500);//设置主页500ms自动刷新 + return private; +} + +static void ui_close_bt(void *hd, void *private) +{ + LCD_API *dis = (LCD_API *)hd; + if (!dis) { + return; + } + if (private) { + free(private); + } +} + +static void ui_bt_main(void *hd, void *private) //主界面显示 +{ + if (!hd) { + return; + } + +#if TCFG_APP_FM_EMITTER_EN + + if (BT_STATUS_TAKEING_PHONE == get_bt_connect_status()) { + led7_show_call(hd); + } else { + u16 fre = fm_emitter_manage_get_fre(); + if (fre != 0) { + led7_fm_show_freq(hd, private, fre); + } else { + led7_show_wait(hd); + } + } +#else + if (BT_STATUS_TAKEING_PHONE == get_bt_connect_status()) { + led7_show_call(hd); + } else { + led7_show_bt(hd); + } +#endif +} + + +static int ui_bt_user(void *hd, void *private, u8 menu, u32 arg)//子界面显示 //返回true不继续传递 ,返回false由common统一处理 +{ + int ret = true; + LCD_API *dis = (LCD_API *)hd; + if (!hd) { + return false; + } + + switch (menu) { + case MENU_BT: + led7_show_bt(hd); + break; + + default: + ret = false; + } + + return ret; + +} + +const struct ui_dis_api bt_main = { + .ui = UI_BT_MENU_MAIN, + .open = ui_open_bt, + .ui_main = ui_bt_main, + .ui_user = ui_bt_user, + .close = ui_close_bt, +}; + + + +#endif +#endif diff --git a/apps/soundbox/ui/led7/ui_common.c b/apps/soundbox/ui/led7/ui_common.c new file mode 100644 index 0000000..2efbbbe --- /dev/null +++ b/apps/soundbox/ui/led7/ui_common.c @@ -0,0 +1,140 @@ +#include "includes.h" +#include "ui/ui_api.h" +#include "fm_emitter/fm_emitter_manage.h" + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_LED7)) +static void led7_show_hi(void *hd) +{ + LCD_API *dis = (LCD_API *)hd; + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string((u8 *)" HI"); + dis->lock(0); +} + +static void led7_show_volume(void *hd, u8 vol) +{ + LCD_API *dis = (LCD_API *)hd; + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_char(' '); + dis->show_char('V'); + dis->show_number(vol / 10); + dis->show_number(vol % 10); + dis->lock(0); +} + +static void led7_show_wait(void *hd) +{ + LCD_API *dis = (LCD_API *)hd; + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string((u8 *)" Lod"); + dis->lock(0); +} + +static void led7_show_bt(void *hd) +{ + + LCD_API *dis = (LCD_API *)hd; + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string((u8 *)" bt"); + dis->lock(0); +} + +#if TCFG_APP_FM_EMITTER_EN +static void led7_fm_ir_set_freq(void *hd, u16 freq) +{ + + LCD_API *dis = (LCD_API *)hd; + u8 bcd_number[5] = {0}; ///<换算结果显示缓存 + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + sprintf((char *)bcd_number, "%4d", freq); + /* itoa4(freq,bcd_number); */ + if (freq > 1080) { + dis->show_string((u8 *)" Err"); + } else if (freq >= 875) { + dis->show_string(bcd_number); + /* os_time_dly(100); */ + fm_emitter_manage_set_fre(freq); + UI_REFLASH_WINDOW(TRUE);//设置回主页 + } else { + dis->FlashChar(BIT(0) | BIT(1) | BIT(2) | BIT(3)); //设置闪烁 + dis->show_string(bcd_number); + } + dis->lock(0); + +} +#endif + + +static void led7_fm_set_freq(void *hd, u32 arg) +{ + u8 bcd_number[5] = {0}; + LCD_API *dis = (LCD_API *)hd; + u16 freq = 0; + freq = arg; + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->FlashChar(BIT(0) | BIT(1) | BIT(2) | BIT(3)); //设置闪烁 + itoa4(freq, (u8 *)bcd_number); + if (freq > 999 && freq <= 1999) { + bcd_number[0] = '1'; + } else { + bcd_number[0] = ' '; + } + dis->show_string(bcd_number); + dis->show_icon(LED7_DOT); + dis->lock(0); +} + + + +void ui_common(void *hd, void *private, u8 menu, u32 arg)//公共显示 +{ + + u16 fre = 0; + + if (!hd) { + return; + } + + switch (menu) { + case MENU_POWER_UP: + led7_show_hi(hd); + break; + case MENU_MAIN_VOL: + led7_show_volume(hd, arg & 0xff); + break; + case MENU_WAIT: + led7_show_wait(hd); + break; + case MENU_BT: + led7_show_bt(hd); + break; + case MENU_IR_FM_SET_FRE: +#if TCFG_APP_FM_EMITTER_EN + led7_fm_ir_set_freq(hd, arg); +#endif + break; + case MENU_FM_SET_FRE: + +#if TCFG_APP_FM_EMITTER_EN + fre = fm_emitter_manage_get_fre(); + led7_fm_set_freq(hd, arg); +#endif + break; + default: + break; + } +} + +#endif diff --git a/apps/soundbox/ui/led7/ui_fm.c b/apps/soundbox/ui/led7/ui_fm.c new file mode 100644 index 0000000..c1b642e --- /dev/null +++ b/apps/soundbox/ui/led7/ui_fm.c @@ -0,0 +1,129 @@ +#include "ui/ui_api.h" +#include "fm/fm_manage.h" + +#if TCFG_APP_FM_EN +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_LED7)) +void ui_fm_temp_finsh(u8 menu)//子菜单被打断或者显示超时 +{ + switch (menu) { + default: + break; + } +} + +static void led7_show_fm(void *hd) +{ + + + LCD_API *dis = (LCD_API *)hd; + + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string((u8 *)" FM"); + dis->lock(0); +} + + +static void led7_fm_show_freq(void *hd, u32 arg) +{ + u8 bcd_number[5] = {0}; + LCD_API *dis = (LCD_API *)hd; + u16 freq = arg; + + if (freq > 1080 && freq <= 1080 * 10) { + freq = freq / 10; + } + + + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + itoa4(freq, (u8 *)bcd_number); + if (freq > 999 && freq <= 1999) { + bcd_number[0] = '1'; + } else { + bcd_number[0] = ' '; + } + dis->show_string(bcd_number); + dis->show_icon(LED7_DOT); + dis->show_icon(LED7_FM); + dis->lock(0); +} + +static void led7_fm_show_station(void *hd, u32 arg) +{ + u8 bcd_number[5] = {0}; + LCD_API *dis = (LCD_API *)hd; + u16 freq = arg; + + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + sprintf((char *)bcd_number, "P%03d", arg); + dis->show_string(bcd_number); + dis->lock(0); +} + + +static void *ui_open_fm(void *hd) +{ + return NULL; +} + +static void ui_close_fm(void *hd, void *private) +{ + LCD_API *dis = (LCD_API *)hd; + if (!dis) { + return ; + } + if (private) { + free(private); + } +} + +static void ui_fm_main(void *hd, void *private) //主界面显示 +{ + if (!hd) { + return; + } + u16 fre = fm_manage_get_fre(); + if (fre != 0) { + led7_fm_show_freq(hd, fre); + } +} + + +static int ui_fm_user(void *hd, void *private, u8 menu, u32 arg)//子界面显示 //返回true不继续传递 ,返回false由common统一处理 +{ + int ret = true; + LCD_API *dis = (LCD_API *)hd; + if (!dis) { + return false; + } + + switch (menu) { + case MENU_FM_STATION: + led7_fm_show_station(hd, arg); + break; + default: + ret = false; + } + + return ret; + +} + + + +const struct ui_dis_api fm_main = { + .ui = UI_FM_MENU_MAIN, + .open = ui_open_fm, + .ui_main = ui_fm_main, + .ui_user = ui_fm_user, + .close = ui_close_fm, +}; + + +#endif +#endif diff --git a/apps/soundbox/ui/led7/ui_fm_emitter.c b/apps/soundbox/ui/led7/ui_fm_emitter.c new file mode 100644 index 0000000..6b25e7c --- /dev/null +++ b/apps/soundbox/ui/led7/ui_fm_emitter.c @@ -0,0 +1,138 @@ +#include "app_config.h" +#include "key_event_deal.h" +#include "common/fm_emitter_led7_ui.h" +#include "ui/ui_api.h" +#include "fm_emitter/fm_emitter_manage.h" + +#if (TCFG_UI_ENABLE && TCFG_APP_FM_EMITTER_EN) + +#define LOG_TAG_CONST APP_ACTION +#define LOG_TAG "[APP_ACTION]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + + +void fm_emitter_enter_ui_menu(void) +{ + u16 tmp_fmtx_fre; + tmp_fmtx_fre = fm_emitter_manage_get_fre(); + + if (ui_get_app_menu(GRT_CUR_MENU) == MENU_FM_SET_FRE) { + UI_REFLASH_WINDOW(true);//刷新主页 + printf("fm menu exit !\n"); + } else if (ui_get_app_menu(GRT_CUR_MENU) == MENU_MAIN) { + printf("fm menu in !\n"); + UI_SHOW_MENU(MENU_FM_SET_FRE, 10000, tmp_fmtx_fre, NULL); + } else { + printf("fm menu ui not ready %d!\n", __LINE__); + } +} + +void fm_emitter_enter_ui_next_fre(void) +{ + u16 tmp_fmtx_fre; + tmp_fmtx_fre = fm_emitter_manage_get_fre(); + if (tmp_fmtx_fre < 1080) { + tmp_fmtx_fre++; + } else { + tmp_fmtx_fre = 875; + } + UI_SHOW_MENU(MENU_FM_SET_FRE, 10000, tmp_fmtx_fre, NULL); + fm_emitter_manage_set_fre(tmp_fmtx_fre); +} + +void fm_emitter_enter_ui_prev_fre(void) +{ + u16 tmp_fmtx_fre; + tmp_fmtx_fre = fm_emitter_manage_get_fre(); + if (tmp_fmtx_fre > 875) { + tmp_fmtx_fre--; + } else { + tmp_fmtx_fre = 1080; + } +#if TCFG_UI_ENABLE + UI_SHOW_MENU(MENU_FM_SET_FRE, 10000, tmp_fmtx_fre, NULL); + fm_emitter_manage_set_fre(tmp_fmtx_fre); +#endif +} + + +static u16 fre_num_tmp = 0; +static void set_fm_fre_timeout(u8 menu) +{ + if (menu == MENU_IR_FM_SET_FRE) { + fre_num_tmp = 0; + /* printf("set_fm_fre_timeout\n"); */ + } +} + +void fm_emitter_fre_set_by_number(u8 num) +{ + fre_num_tmp = fre_num_tmp * 10 + num; +#if TCFG_UI_ENABLE + /* printf("fre_num_tmp =%d \n",fre_num_tmp); */ + UI_SHOW_MENU(MENU_IR_FM_SET_FRE, 4 * 1000, fre_num_tmp, set_fm_fre_timeout); +#endif + if (fre_num_tmp > 875) { + fre_num_tmp = 0; + } +} + +int ui_fm_emitter_common_key_msg(int key_event) +{ + u8 ret = 0; + switch (key_event) { + case KEY_IR_NUM_0: + case KEY_IR_NUM_1: + case KEY_IR_NUM_2: + case KEY_IR_NUM_3: + case KEY_IR_NUM_4: + case KEY_IR_NUM_5: + case KEY_IR_NUM_6: + case KEY_IR_NUM_7: + case KEY_IR_NUM_8: + case KEY_IR_NUM_9: + fm_emitter_fre_set_by_number(key_event - KEY_IR_NUM_0); + break; + + case KEY_FM_EMITTER_MENU: + fm_emitter_enter_ui_menu(); + break; + case KEY_FM_EMITTER_NEXT_FREQ: + fm_emitter_enter_ui_next_fre(); + break; + case KEY_FM_EMITTER_PERV_FREQ: + fm_emitter_enter_ui_prev_fre(); + break; + + /* case KEY_VOL_UP: */ + /* log_info("COMMON KEY_VOL_UP\n"); */ + /* if (ui_get_app_menu(GRT_CUR_MENU) == MENU_FM_SET_FRE) { */ + /* fm_emitter_enter_ui_next_fre(); */ + /* ret = 1; */ + /* } */ + /* break; */ + + /* case KEY_VOL_DOWN: */ + /* log_info("COMMON KEY_VOL_DOWN\n"); */ + /* if (ui_get_app_menu(GRT_CUR_MENU) == MENU_FM_SET_FRE) { */ + /* fm_emitter_enter_ui_prev_fre(); */ + /* ret = 1; */ + /* } */ + /* break; */ + default: + ret = 1; + break; + } + return ret; +} + +#endif //(TCFG_UI_ENABLE && TCFG_APP_FM_EMITTER_EN) + + + diff --git a/apps/soundbox/ui/led7/ui_idle.c b/apps/soundbox/ui/led7/ui_idle.c new file mode 100644 index 0000000..5f299b6 --- /dev/null +++ b/apps/soundbox/ui/led7/ui_idle.c @@ -0,0 +1,26 @@ +#include "includes.h" +#include "ui/ui_api.h" + +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_LED7)) +static void ui_idle_main(void *hd, void *private) //主界面显示 +{ + if (!hd) { + return; + } + LCD_API *dis = (LCD_API *)hd;//清显示 + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->clear_icon(0xffff); + dis->lock(0); +} + + +const struct ui_dis_api idle_main = { + .ui = UI_IDLE_MENU_MAIN, + .open = NULL, + .ui_main = ui_idle_main, + .ui_user = NULL, + .close = NULL, +}; +#endif diff --git a/apps/soundbox/ui/led7/ui_linein.c b/apps/soundbox/ui/led7/ui_linein.c new file mode 100644 index 0000000..235fc92 --- /dev/null +++ b/apps/soundbox/ui/led7/ui_linein.c @@ -0,0 +1,141 @@ +#include "system/includes.h" +#include "ui/ui_api.h" +#include "fm_emitter/fm_emitter_manage.h" + +#if TCFG_APP_LINEIN_EN +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_LED7)) + +void ui_linein_temp_finsh(u8 menu)//子菜单被打断或者显示超时 +{ + switch (menu) { + default: + break; + } +} + +static void led7_show_aux(void *hd) +{ + + LCD_API *dis = (LCD_API *)hd; + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string((u8 *)" AUX"); + dis->lock(0); +} + + +static void led7_fm_show_freq(void *hd, u32 arg) +{ + u8 bcd_number[5] = {0}; + LCD_API *dis = (LCD_API *)hd; + u16 freq = 0; + freq = arg; + + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + itoa4(freq, (u8 *)bcd_number); + if (freq > 999 && freq <= 1999) { + bcd_number[0] = '1'; + } else { + bcd_number[0] = ' '; + } + dis->show_string(bcd_number); + dis->show_icon(LED7_DOT); + dis->lock(0); +} + +static void led7_show_pause(void *hd) +{ + LCD_API *dis = (LCD_API *)hd; + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string((u8 *)" PAU"); + dis->lock(0); +} + +static void *ui_open_linein(void *hd) +{ + /* ui_set_auto_reflash(500);//设置主页500ms自动刷新 */ + return NULL; +} + +static void ui_close_linein(void *hd, void *private) +{ + LCD_API *dis = (LCD_API *)hd; + if (!dis) { + return ; + } + if (private) { + free(private); + } +} + +static void ui_linein_main(void *hd, void *private) //主界面显示 +{ + if (!hd) { + return; + } + +#if TCFG_APP_FM_EMITTER_EN + extern u8 linein_get_status(void); + if (linein_get_status()) { + u16 fre = fm_emitter_manage_get_fre(); + if (fre != 0) { + led7_fm_show_freq(hd, fre); + } else { + printf("ui get fmtx fre err !\n"); + } + } else { + led7_show_pause(hd); + } +#else + extern u8 linein_get_status(void); + if (linein_get_status()) { + led7_show_aux(hd); + } else { + led7_show_pause(hd); + } +#endif +} + + +static int ui_linein_user(void *hd, void *private, u8 menu, u32 arg)//子界面显示 //返回true不继续传递 ,返回false由common统一处理 +{ + int ret = true; + LCD_API *dis = (LCD_API *)hd; + if (!dis) { + return false; + } + switch (menu) { + case MENU_AUX: + led7_show_aux(hd); + break; + default: + ret = false; + break; + } + + return ret; + +} + + + +const struct ui_dis_api linein_main = { + .ui = UI_AUX_MENU_MAIN, + .open = ui_open_linein, + .ui_main = ui_linein_main, + .ui_user = ui_linein_user, + .close = ui_close_linein, +}; + + + + + + +#endif +#endif diff --git a/apps/soundbox/ui/led7/ui_music.c b/apps/soundbox/ui/led7/ui_music.c new file mode 100644 index 0000000..6c7c53f --- /dev/null +++ b/apps/soundbox/ui/led7/ui_music.c @@ -0,0 +1,236 @@ +#include "ui/ui_api.h" +#include "music/music_ui.h" +#include "fm_emitter/fm_emitter_manage.h" +#include "audio_dec.h" +#include "audio_dec_file.h" +#include "music/music_player.h" + +#if TCFG_APP_MUSIC_EN +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_LED7)) +/* UI_DIS_VAR *ui_get_dis_var()//获取存储模式参数的结构体 */ +/* { */ +/* return ui_dis_var; */ +/* } */ + + +void ui_music_temp_finsh(u8 menu)//子菜单被打断或者显示超时 +{ + switch (menu) { + default: + break; + } +} + +static void ui_led7_show_music_time(void *hd, int sencond) +{ + LCD_API *dis = (LCD_API *)hd; + u8 tmp_buf[5] = {0}; + u8 min = 0; + min = sencond / 60 % 60; + sencond = sencond % 60; + + itoa2(min, (u8 *)&tmp_buf[0]); + itoa2(sencond, (u8 *)&tmp_buf[2]); + + + dis->lock(1); + /* dis->clear(); */ + dis->setXY(0, 0); + dis->clear_icon(0xffff); + dis->show_string(tmp_buf); + dis->flash_icon(LED7_2POINT); + dis->show_icon(LED7_PLAY); + dis->show_icon(LED7_MP3); + dis->lock(0); + +} + + +static void led7_show_filenumber(void *hd, u16 file_num) +{ + LCD_API *dis = (LCD_API *)hd; + u8 bcd_number[5] = {0}; ///<换算结果显示缓存 + itoa4(file_num, (u8 *)bcd_number); + + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); +#if TCFG_UI_LED1888_ENABLE //UI使用LED1888 + if (file_num > 999 && file_num <= 1999) { + bcd_number[0] = '1'; + } else { + bcd_number[0] = ' '; + } +#endif + dis->show_string(bcd_number); + dis->lock(0); +} + + +static void led7_show_pause(void *hd) +{ + LCD_API *dis = (LCD_API *)hd; + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string((u8 *)" PAU"); + dis->show_icon(LED7_PAUSE); + dis->lock(0); +} + +static void led7_show_repeat_mode(void *hd, u32 val) +{ + if (!val) { + return ; + } + u8 mode = (u8)val - 1; + + const u8 playmodestr[][5] = { + " ALL", + " ONE", + "Fold", + " rAn", + }; + + if (mode >= sizeof(playmodestr) / sizeof(playmodestr[0])) { + printf("rpt mode display err !!\n"); + return ; + } + + LCD_API *dis = (LCD_API *)hd; + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string((u8 *)playmodestr[mode]); + dis->lock(0); +} + + +static void led7_fm_show_freq(void *hd, u32 arg) +{ + u8 bcd_number[5] = {0}; + LCD_API *dis = (LCD_API *)hd; + u16 freq = 0; + freq = arg; + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + itoa4(freq, (u8 *)bcd_number); + if (freq > 999 && freq <= 1999) { + bcd_number[0] = '1'; + } else { + bcd_number[0] = ' '; + } + dis->show_string(bcd_number); + dis->show_icon(LED7_DOT); + dis->lock(0); +} + +static void *ui_open_music(void *hd) +{ + MUSIC_DIS_VAR *ui_music = NULL; + /* ui_music = (MUSIC_DIS_VAR *)malloc(sizeof(MUSIC_DIS_VAR)); */ + /* if (ui_music == NULL) { */ + /* return NULL; */ + /* } */ + ui_set_auto_reflash(500);//设置主页500ms自动刷新 + return ui_music; +} + +static void ui_close_music(void *hd, void *private) +{ + MUSIC_DIS_VAR *ui_music = (MUSIC_DIS_VAR *)private; + LCD_API *dis = (LCD_API *)hd; + if (!dis) { + return ; + } + + if (ui_music) { + free(ui_music); + } +} + +static void led7_show_music_dev(void *hd) +{ + LCD_API *dis = (LCD_API *)hd; + char *dev = NULL; + /* char *music_play_get_cur_dev(void); */ + /* char *dev = music_play_get_cur_dev(); */ + dev = music_player_get_dev_cur(); + if (dev) { + if (!memcmp(dev, "udisk", 5)) { + dis->show_icon(LED7_USB); + } else { + dis->show_icon(LED7_SD); + } + } +} + +static void ui_music_main(void *hd, void *private) //主界面显示 +{ + if (!hd) { + return; + } + MUSIC_DIS_VAR *ui_music = (MUSIC_DIS_VAR *)private; +#if TCFG_APP_FM_EMITTER_EN + if (true == file_dec_is_pause()) { + led7_show_pause(hd); + } else { + u16 fre = fm_emitter_manage_get_fre(); + if (fre != 0) { + led7_fm_show_freq(hd, fre); + } + } +#else + if (true == file_dec_is_play()) { + int sencond = file_dec_get_cur_time(); + ui_led7_show_music_time(hd, sencond); + led7_show_music_dev(hd); + printf("sec = %d \n", sencond); + } else if (file_dec_is_pause()) { + led7_show_pause(hd); + } else { + printf("!!! %s %d\n", __FUNCTION__, __LINE__); + + } + +#endif +} + + +static int ui_music_user(void *hd, void *private, u8 menu, u32 arg)//子界面显示 //返回true不继续传递 ,返回false由common统一处理 +{ + int ret = true; + LCD_API *dis = (LCD_API *)hd; + MUSIC_DIS_VAR *ui_music = (MUSIC_DIS_VAR *)private; + if (!dis) { + return false; + } + switch (menu) { + case MENU_FILENUM: + led7_show_filenumber(hd, arg); + break; + case MENU_MUSIC_REPEATMODE: + led7_show_repeat_mode(hd, arg); + break; + default: + ret = false; + break; + } + + return ret; + +} + + + +const struct ui_dis_api music_main = { + .ui = UI_MUSIC_MENU_MAIN, + .open = ui_open_music, + .ui_main = ui_music_main, + .ui_user = ui_music_user, + .close = ui_close_music, +}; + +#endif +#endif diff --git a/apps/soundbox/ui/led7/ui_pc.c b/apps/soundbox/ui/led7/ui_pc.c new file mode 100644 index 0000000..8ca6c52 --- /dev/null +++ b/apps/soundbox/ui/led7/ui_pc.c @@ -0,0 +1,96 @@ +#include "ui/ui_api.h" +#include "system/includes.h" + +#if TCFG_APP_PC_EN +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_LED7)) +void ui_pc_temp_finsh(u8 menu)//子菜单被打断或者显示超时 +{ + switch (menu) { + default: + break; + } +} + +static void led7_show_pc(void *hd) +{ + LCD_API *dis = (LCD_API *)hd; + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string((u8 *)" PC"); + dis->show_icon(LED7_USB); + dis->lock(0); +} + + + + +static void *ui_open_pc(void *hd) +{ + /* ui_set_auto_reflash(500);//设置主页500ms自动刷新 */ + return NULL; +} + +static void ui_close_pc(void *hd, void *private) +{ + LCD_API *dis = (LCD_API *)hd; + if (!dis) { + return ; + } + + if (private) { + free(private); + } +} + +static void ui_pc_main(void *hd, void *private) //主界面显示 +{ + if (!hd) { + return; + } + led7_show_pc(hd); +} + + +static int ui_pc_user(void *hd, void *private, u8 menu, u32 arg)//子界面显示 //返回true不继续传递 ,返回false由common统一处理 +{ + int ret = true; + LCD_API *dis = (LCD_API *)hd; + if (!dis) { + return false; + } + switch (menu) { + default: + ret = false; + break; + } + + return ret; + +} + + + + +const struct ui_dis_api pc_main = { + .ui = UI_PC_MENU_MAIN, + .open = ui_open_pc, + .ui_main = ui_pc_main, + .ui_user = ui_pc_user, + .close = ui_close_pc, +}; + + + + + + + + + + + + + +#endif +#endif diff --git a/apps/soundbox/ui/led7/ui_record.c b/apps/soundbox/ui/led7/ui_record.c new file mode 100644 index 0000000..17c271b --- /dev/null +++ b/apps/soundbox/ui/led7/ui_record.c @@ -0,0 +1,147 @@ +#include "ui/ui_api.h" +#include "fm_emitter/fm_emitter_manage.h" +#include "audio_enc/audio_enc.h" + +#if TCFG_APP_RECORD_EN +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_LED7)) + +void ui_record_temp_finsh(u8 menu)//子菜单被打断或者显示超时 +{ + switch (menu) { + default: + break; + } +} + +static void led7_show_record(void *hd) +{ + LCD_API *dis = (LCD_API *)hd; + + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string((u8 *)" REC"); + dis->lock(0); +} + +static void led_show_record_time(void *hd, int time) +{ + LCD_API *dis = (LCD_API *)hd; + u8 tmp_buf[5] = {0}; + + u8 Min = (u8)(time / 60 % 60); + u8 Sec = (u8)(time % 60); + printf("rec Min = %d, Sec = %d\n", Min, Sec); + + itoa2(Min, (u8 *)&tmp_buf[0]); + itoa2(Sec, (u8 *)&tmp_buf[2]); + + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string(tmp_buf); + dis->show_icon(LED7_2POINT); + dis->lock(0); +} + + +#if TCFG_APP_FM_EMITTER_EN +static void led7_fm_show_freq(void *hd, u32 arg) +{ + u8 bcd_number[5] = {0}; + LCD_API *dis = (LCD_API *)hd; + u16 freq = 0; + if (arg) { + freq = arg; + fmtx_freq = arg; + } else { + freq = fmtx_freq; + } + + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + itoa4(freq, (u8 *)bcd_number); + if (freq > 999 && freq <= 1999) { + bcd_number[0] = '1'; + } else { + bcd_number[0] = ' '; + } + dis->show_string(bcd_number); + dis->show_icon(LED7_DOT); + dis->lock(0); +} +#endif//TCFG_APP_FM_EMITTER_EN + +static void *ui_open_record(void *hd) +{ + ui_set_auto_reflash(500); + return NULL; +} + +static void ui_close_record(void *hd, void *private) +{ + LCD_API *dis = (LCD_API *)hd; + if (!dis) { + return ; + } + if (private) { + free(private); + } +} + +static void ui_record_main(void *hd, void *private) //主界面显示 +{ + /* printf("=====================\n"); */ + if (!hd) { + return; + } + +#if TCFG_APP_FM_EMITTER_EN + u16 fre = fm_emitter_manage_get_fre(); + if (fre != 0) { + led7_fm_show_freq(hd, fre); + } +#else + if (recorder_is_encoding()) { + int time = recorder_get_encoding_time(); + led_show_record_time(hd, time); + } else { + led7_show_record(hd); + } +#endif +} + + +static int ui_record_user(void *hd, void *private, u8 menu, u32 arg)//子界面显示 //返回true不继续传递 ,返回false由common统一处理 +{ + int ret = true; + LCD_API *dis = (LCD_API *)hd; + if (!dis) { + return false; + } + switch (menu) { + case MENU_RECORD: + led7_show_record(hd); + break; + default: + ret = false; + break; + } + + return ret; + +} + + + +const struct ui_dis_api record_main = { + .ui = UI_RECORD_MENU_MAIN, + .open = ui_open_record, + .ui_main = ui_record_main, + .ui_user = ui_record_user, + .close = ui_close_record, +}; + +#endif +#endif//(TCFG_UI_ENABLE && TCFG_APP_RECORD_EN) diff --git a/apps/soundbox/ui/led7/ui_rtc.c b/apps/soundbox/ui/led7/ui_rtc.c new file mode 100644 index 0000000..bb0f3c1 --- /dev/null +++ b/apps/soundbox/ui/led7/ui_rtc.c @@ -0,0 +1,288 @@ +#include "ui/ui_api.h" +#include "system/includes.h" +#include "system/sys_time.h" +#include "rtc/rtc_ui.h" + +#if TCFG_APP_RTC_EN +#if (TCFG_UI_ENABLE&&(CONFIG_UI_STYLE == STYLE_JL_LED7)) + +struct rtc_ui_opr { + void *dev_handle; + struct ui_rtc_display ui_rtc; +}; + +static struct rtc_ui_opr *__this = NULL; + +void ui_rtc_temp_finsh(u8 menu)//子菜单被打断或者显示超时 +{ + switch (menu) { + default: + break; + } +} + +static void ui_led7_show_year(void *hd, u16 Year) +{ + + LCD_API *dis = (LCD_API *)hd; + u8 tmp_buf[5] = {0}; + itoa4(Year, (u8 *)&tmp_buf[0]); + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string(tmp_buf); + dis->lock(0); +} + +static void led7_show_rtc_string(void *hd, const char *buf) +{ + LCD_API *dis = (LCD_API *)hd; + + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string((u8 *)buf); + dis->lock(0); +} + + +static void led7_flash_char(void *hd, u8 index) +{ + LCD_API *dis = (LCD_API *)hd; + dis->FlashChar(BIT(index)); +} + +static void led7_rtc_flash_icon(void *hd, u32 icon) +{ + LCD_API *dis = (LCD_API *)hd; + dis->flash_icon(icon); +} + + +static void ui_led7_show_curtime(void *hd, u8 Hour, u8 Min) +{ + LCD_API *dis = (LCD_API *)hd; + u8 tmp_buf[5] = {0}; + itoa2(Hour, (u8 *)&tmp_buf[0]); + itoa2(Min, (u8 *)&tmp_buf[2]); + + dis->lock(1); + dis->setXY(0, 0); + dis->Clear_FlashChar(BIT(0) | BIT(1) | BIT(2) | BIT(3)); + dis->show_string(tmp_buf); + dis->flash_icon(LED7_2POINT); + dis->lock(0); +} + + +static void ui_led7_show_RTC_time(void *hd, u8 Hour, u8 Min) +{ + LCD_API *dis = (LCD_API *)hd; + u8 tmp_buf[5] = {0}; + itoa2(Hour, (u8 *)&tmp_buf[0]); + itoa2(Min, (u8 *)&tmp_buf[2]); + + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string(tmp_buf); + dis->show_icon(LED7_2POINT); + dis->lock(0); +} + +static void ui_led7_show_date(void *hd, u16 Year, u8 Month, u8 Day) +{ + + LCD_API *dis = (LCD_API *)hd; + u8 tmp_buf[5] = {0}; + itoa2(Month, (u8 *)&tmp_buf[0]); + itoa2(Day, (u8 *)&tmp_buf[2]); + + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->show_string(tmp_buf); + dis->lock(0); +} + + + +static int ui_led7_show_RTC_user(void *hd, struct ui_rtc_display *rtc) +{ + int ret = true; + if (rtc == NULL) { + return false; + } + + switch (rtc->rtc_menu) { + + /* case UI_RTC_ACTION_SHOW_TIME: */ + /* ui_led7_show_RTC_time(hd,rtc->time.Hour, rtc->time.Min); */ + /* break; */ + + case UI_RTC_ACTION_SHOW_DATE: + ui_led7_show_date(hd, rtc->time.Year, rtc->time.Month, rtc->time.Day); + break; + + case UI_RTC_ACTION_YEAR_SET: + ui_led7_show_year(hd, rtc->time.Year); + led7_flash_char(hd, 0); + led7_flash_char(hd, 1); + led7_flash_char(hd, 2); + led7_flash_char(hd, 3); + break; + + case UI_RTC_ACTION_MONTH_SET: + ui_led7_show_date(hd, rtc->time.Year, rtc->time.Month, rtc->time.Day); + led7_flash_char(hd, 0); + led7_flash_char(hd, 1); + break; + + case UI_RTC_ACTION_DAY_SET: + ui_led7_show_date(hd, rtc->time.Year, rtc->time.Month, rtc->time.Day); + led7_flash_char(hd, 2); + led7_flash_char(hd, 3); + break; + + case UI_RTC_ACTION_HOUR_SET: + ui_led7_show_RTC_time(hd, rtc->time.Hour, rtc->time.Min); + led7_flash_char(hd, 0); + led7_flash_char(hd, 1); + break; + + case UI_RTC_ACTION_MINUTE_SET: + ui_led7_show_RTC_time(hd, rtc->time.Hour, rtc->time.Min); + led7_flash_char(hd, 2); + led7_flash_char(hd, 3); + break; + + case UI_RTC_ACTION_STRING_SET: + led7_show_rtc_string(hd, rtc->str); + break; + + default: + ret = false; + break; + } + + return ret; +} + + + + +struct ui_rtc_display *rtc_ui_get_display_buf() +{ + if (__this) { + return &(__this->ui_rtc); + } else { + return NULL; + } +} + + + +static void *ui_open_rtc(void *hd) +{ + + struct sys_time current_time; + if (!__this) { + __this = zalloc(sizeof(struct rtc_ui_opr)); + } + __this->dev_handle = dev_open("rtc", NULL); + + if (!__this->dev_handle) { + free(__this); + __this = NULL; + return NULL; + } + + ui_set_auto_reflash(500);//设置主页500ms自动刷新 + dev_ioctl(__this->dev_handle, IOCTL_GET_SYS_TIME, (u32)¤t_time); + printf("rtc_read_sys_time: %d-%d-%d %d:%d:%d\n", + current_time.year, + current_time.month, + current_time.day, + current_time.hour, + current_time.min, + current_time.sec); + + + if (hd) { + LCD_API *dis = (LCD_API *)hd; + dis->lock(1); + dis->clear(); + dis->setXY(0, 0); + dis->lock(0); + } + return NULL; +} + + +static void ui_close_rtc(void *hd, void *private) +{ + LCD_API *dis = (LCD_API *)hd; + if (!dis) { + return; + } + if (__this) { + free(__this); + __this = NULL; + } +} + +static void ui_rtc_main(void *hd, void *private) //主界面显示 +{ + if (!hd) { + return; + } + struct sys_time current_time; + dev_ioctl(__this->dev_handle, IOCTL_GET_SYS_TIME, (u32)¤t_time); +#if 1 + printf("rtc_read_sys_time: %d-%d-%d %d:%d:%d\n", + current_time.year, + current_time.month, + current_time.day, + current_time.hour, + current_time.min, + current_time.sec); +#endif + ui_led7_show_curtime(hd, current_time.hour, current_time.min); +} + + +static int ui_rtc_user(void *hd, void *private, u8 menu, u32 arg)//子界面显示 //返回true不继续传递 ,返回false由common统一处理 +{ + int ret = true; + LCD_API *dis = (LCD_API *)hd; + if (!dis) { + return false; + } + switch (menu) { + + case MENU_ALM_SET: + case MENU_RTC_SET: + ui_led7_show_RTC_user(hd, &(__this->ui_rtc)); + break; + default: + ret = false; + break; + } + + return ret; + +} + + + +const struct ui_dis_api rtc_main = { + .ui = UI_RTC_MENU_MAIN, + .open = ui_open_rtc, + .ui_main = ui_rtc_main, + .ui_user = ui_rtc_user, + .close = ui_close_rtc, +}; + + +#endif +#endif diff --git a/apps/soundbox/user_api/app_pwmled_api.c b/apps/soundbox/user_api/app_pwmled_api.c new file mode 100644 index 0000000..e72b9a6 --- /dev/null +++ b/apps/soundbox/user_api/app_pwmled_api.c @@ -0,0 +1,233 @@ +#include "generic/gpio.h" +#include "asm/includes.h" +#include "asm/pwm_led.h" +#include "system/timer.h" +#include "board_config.h" + +#ifdef CONFIG_BOARD_AC696X_DEMO +//注意事项: +//1.使用该模块需确认 TCFG_PWMLED_ENABLE 和 UI中的pwm_led 都处于DISABLE状态 +//2.进入蓝牙模式时需要在蓝牙初始化完成后(BT_STATUS_INIT_OK)再设置灯效,蓝牙初始化过程会影响pwm_led模块 +//3.一个pwm周期内最多只能进行4次IO口反转,能够实现双闪动作,如果需要进行更多的闪动则需要配合PWM的中断来实现 +// +// +//=============周期灯======================================================================================================================================== +// +// __第一次反转后状态保持时间__ __第三次反转后状态保持时间__ +// holdtime1_ms | holdtime2_ms | holdtime3_ms | holdtime4_ms | cycle_ms减去所有hondtime +//高亮灯:__初始状态保持时间__| |__第二次反转后状态保持时间__| |___最后电平持续时间,持续到周期结束_______ +//低亮灯:_____________________ ______________________________ ___________________________________________ +// | | | | +// |__________________________| |__________________________| +// |<---------------------------------------------整个PWM亮灭周期(中断周期):cycle_ms--------------------------------------------------------------->| +// +//1.PMW周期从灭灯开始,高亮灯初始电平为低,低亮灯初始电平为高 +// +//=========================================================================================================================================================== +//struct pwm_cycle_pattern{ +// u32 cycle_ms; //PWM产生的一个亮灭周期,单位ms +// u32 holdtime1_ms; //初始状态保持时间,等于0时接近于PWM周期从亮灯开始 +// u32 holdtime2_ms; //第一次反转后状态保持时间,等于0时关闭 +// u32 holdtime3_ms; //第二次反转后状态保持时间,等于0时关闭 +// u32 holdtime4_ms; //第三次反转后状态保持时间,等于0时关闭 +// u16 led_L_bright; //低电平灯亮度设置 +// u16 led_H_bright; //高电平灯亮度设置 +// u8 led_type; //LED类型 0:低亮 1:高亮 +// u8 shift_duty; //每隔shift_duty个周期后输出电平取反,亮度设置不变,也就是说当前灯的图案会切换到两外一个灯上,用于周期变色处理,等于0时功能关闭 +//}; +//=============呼吸灯======================================================================================================================================== +// +// _最高亮度保持时间__ __ +// __| led_H_holdtime |__ __| +// breathe_interval __| |__ breathe_interval __| +//高亮灯:____________呼吸间隔________| breathe_time |____________呼吸间隔________| +// |<----------呼吸时间----------->| +// |<---PWM周期(中断周期) = breathe_interval + breathe_time---->| +// +//低亮灯: +// +//=========================================================================================================================================================== +//struct pwm_breathe_pattern{ +// u32 breathe_interval; //呼吸间隔,LED处于灭灯状态,PWM初始化后经过一个呼吸间隔后才开始第一次呼吸动作。 +// u16 breathe_time; //呼吸时间(灭->最亮->灭), 设置范围: 500ms以上; +// u32 led_L_holdtime; //低电平灯最高亮度保持时间,呼吸时间-保持时间=渐变时间 (0 ~ 100ms); +// u32 led_H_holdtime; //高电平灯最高亮度保持时间,呼吸时间-保持时间=渐变时间 (0 ~ 100ms); +// u16 led_L_bright; //低电平灯呼吸到最亮的亮度设置(0 ~ 500); +// u16 led_H_bright; //高电平灯呼吸到最亮的亮度设置(0 ~ 500); +// u8 led_type; //LED类型 1:高亮 0:低亮 +// u8 shift_duty; //每隔shift_duty个周期后输出电平取反,亮度设置不变,也就是说当前灯的呼吸效果会切换到两外一个灯上,用于周期变色处理,等于0时功能关闭 +//}; + + +extern void pwm_cycle_pattern_init(struct pwm_cycle_pattern *pattern); +extern void pwm_breathe_pattern_init(struct pwm_breathe_pattern *pattern); +extern void pwmled_pwm_init(); +extern void led_pwm_clear_pending(); +extern void led_pwm_isr_en(u8 en); +extern void led_pin_set_enable(u8 gpio); +extern void led_pin_set_disable(u8 disable_pin); + +extern void pwm_ledL_off_Nms(int off_ms); +extern void pwm_ledL_four_flash_test(); + +volatile u8 pwm_isr_state; +volatile u32 pwm_isr_cnt; + +enum { + four_flash_cnt = 0, + four_flash_interval, + change_PWM_IO, +}; +//=========================================================================================================================================================== +//pwm周期中断函数 +// +//=========================================================================================================================================================== +___interrupt +void pwm_cycle_isr_func() +{ + led_pwm_clear_pending(); + switch (pwm_isr_state) { + case four_flash_cnt: + pwm_isr_cnt++; + if (pwm_isr_cnt == 4) { + pwm_ledL_off_Nms(2000);//闪动4次之后切换到灭灯周期 + } + break; + case four_flash_interval: + pwm_ledL_four_flash_test();//灭灯周期结束后切换到4闪周期 + break; + case change_PWM_IO: + pwm_isr_cnt++; + if (pwm_isr_cnt == 2) { //进行PWM IO口切换动作 + led_pin_set_disable(IO_PORTA_00); + led_pin_set_enable(IO_PORTA_01); + } else if (pwm_isr_cnt >= 4) { + pwm_isr_cnt = 0; + led_pin_set_disable(IO_PORTA_01); + led_pin_set_enable(IO_PORTA_00); + } + break; + default: + break; + } +} +//=========================================================================================================================================================== +//高亮灯,每隔1秒进行一次双闪示例 +// +// __第一次反转后状态保持时间__ __第三次反转后状态保持时间__ +// holdtime1_ms | holdtime2_ms | holdtime3_ms | holdtime4_ms | cycle_ms减去所有hondtime +//高亮灯:__初始状态保持时间__| |__第二次反转后状态保持时间__| |___最后电平持续时间,持续到周期结束_______ +// |<---------------------------------------------整个PWM亮灭周期(中断周期):cycle_ms--------------------------------------------------------------->| +// +// +//=========================================================================================================================================================== +void pwm_ledH_double_flash_test() +{ + struct pwm_cycle_pattern pattern = {0}; + pattern.cycle_ms = 1000; //每隔1秒进行一次动作,需要设置PWM周期为1000ms + pattern.holdtime1_ms = 10; //设置初始灭灯状态的保持时间,主要作用是产生PWM中断之后能在灭灯状态下进行相关设置,时间到则IO反转进入亮灯状态。 + pattern.holdtime2_ms = 100; //设置第一次亮灯保持时间,时间到则IO反转进入灭灯状态。 + pattern.holdtime3_ms = 100; //设置第一次灭灯保持时间,即两次亮灯的时间间隔,时间到则IO反转进入亮灯状态。 + pattern.holdtime4_ms = 100; //设置第二次亮灯保持时间,时间到则IO反转进入灭灯状态并持续要周期结束。 + pattern.led_L_bright = 0; //只操作高亮灯时,低亮灯亮度设置为0。 + pattern.led_H_bright = 500; //设置高亮灯的亮度。 + pattern.led_type = 1; //设置亮灯类型:0:低亮 1:高亮 2:两灯跳变效果 + pattern.shift_duty = 0; //关闭周期取反功能 + + pwm_cycle_pattern_init(&pattern); //根据配置好的pwm周期图案进行初始话并启动PWM_LED模块 + led_pwm_isr_en(0); //关闭pwm中断 +} +//=========================================================================================================================================================== +//PMW周期图案加周期中断实现低亮灯周期4闪例子 +// +//低亮灯:___holdtime1_ms______ ____ +// | | +// |____holdtime1_ms:200ms____| +// |<--整个PWM亮灭周期(中断周期):cycle_ms:400ms->| +// +//实现方法: +// 1.画出单闪的PWM图案和一个灭灯的PWM图案 +// 2.使能PWM中断计算4次pwm单闪后切换到灭灯PWM周期 +// 3.灭灯PWM周期结束后再切换到4个单闪周期 +//=========================================================================================================================================================== +void pwm_ledL_off_Nms(int off_ms) +{ + struct pwm_cycle_pattern pattern = {0}; + pattern.cycle_ms = off_ms; //设置灭灯时间,时间到产生pwm中断 + pattern.holdtime1_ms = 0; + pattern.holdtime2_ms = 0; + pattern.holdtime3_ms = 0; + pattern.holdtime4_ms = 0; + pattern.led_L_bright = 0; + pattern.led_H_bright = 0; + pattern.led_type = 0; + pattern.shift_duty = 0; + + pwm_cycle_pattern_init(&pattern); + pwm_isr_state = four_flash_interval;//设置灭灯周期结束后进行闪动切换处理 + pwm_isr_cnt = 0; + led_pwm_isr_en(1); +} + +void pwm_ledL_four_flash_test() +{ + struct pwm_cycle_pattern pattern = {0}; + pattern.cycle_ms = 400; //设置4闪过程中的亮灭周期,每闪动一次周期是400ms + pattern.holdtime1_ms = 10; //设置周期开始时灭灯保持时间 + pattern.holdtime2_ms = 200; //设置每个闪动周期的亮灯时间200ms + pattern.holdtime3_ms = 0; // + pattern.holdtime4_ms = 0; // + pattern.led_L_bright = 500; //设置低亮灯亮度 + pattern.led_H_bright = 0; // + pattern.led_type = 0; // + pattern.shift_duty = 0; // + + pwm_cycle_pattern_init(&pattern); //根据配置好的pwm周期图案进行初始话并启动PWM_LED模块 + pwm_isr_state = four_flash_cnt; //设置pwm中断时进行4闪的计数处理 + pwm_isr_cnt = 0; + led_pwm_isr_en(1); //使能pwm中断 +} +//=========================================================================================================================================================== +//PWM呼吸图案加周期中断处理,实现两个IO口推4灯轮流呼吸例子 +// +// _最高亮度保持时间__ __ +// __| led_H_holdtime |__ __| +// breathe_interval __| |__ breathe_interval __| +//高亮灯:____________呼吸间隔________| breathe_time |____________呼吸间隔________| +// |<----------呼吸时间----------->| +// |<---PWM周期(中断周期) = breathe_interval + breathe_time---->| +// +//实现方法: +// 1.画出单个灯的呼吸图案 +// 2.打开双灯模式和设置状态周期互换实现第二个灯的切换 +// 3.产生两次PWM中断后切换IO口,进行第三和第四个灯的呼吸效果 +//=========================================================================================================================================================== +void pwm_four_led_breathe_test() +{ + struct pwm_breathe_pattern pattern = {0}; + pattern.breathe_interval = 1000; //设置呼吸间隔为1000ms,实现每次灭灯间隔1s后进行一次呼吸动作。 + pattern.breathe_time = 2000; //设置呼吸时间为2000ms,2秒内实现 灭->最亮->灭 + pattern.led_H_bright = 500; //设置呼吸时间内高亮灯最高亮度 + pattern.led_H_holdtime = 100; //设置呼吸时间内高亮灯最高亮度维持时 + pattern.led_L_bright = 500; //设置呼吸时间内低亮灯最高亮度 + pattern.led_L_holdtime = 100; //设置呼吸时间内低亮灯最高亮度维持时 + pattern.led_type = 2; //推双灯模式 + pattern.shift_duty = 1; //每个周期进行双灯状态互换 + + pwm_breathe_pattern_init(&pattern); + pwm_isr_state = change_PWM_IO; + pwm_isr_cnt = 0; + led_pwm_isr_en(1); +} +//=========================================================================================================================================================== +//pwm初始化函数,用户使用该API时需要在 app_main() 调用该函数进行模块初始化 +// +//=========================================================================================================================================================== +void app_pwmled_init() +{ + request_irq(IRQ_PWM_LED_IDX, 1, pwm_cycle_isr_func, 0); //初始化PWM中断函数 + led_pin_set_enable(IO_PORTA_00); //初始化PWM IO口 + pwmled_pwm_init(); //初始化PWM模块 +} + +#endif diff --git a/apps/soundbox/user_api/app_record_api.c b/apps/soundbox/user_api/app_record_api.c new file mode 100644 index 0000000..5db0a0a --- /dev/null +++ b/apps/soundbox/user_api/app_record_api.c @@ -0,0 +1,88 @@ +#include "generic/gpio.h" +#include "asm/includes.h" +#include "system/timer.h" +#include "board_config.h" +#include "record/record.h" +#include "dev_manager.h" +#include "media/audio_base.h" +#include "audio_enc.h" +#include "tone_player.h" +#include "audio_dec.h" +#include "clock_cfg.h" +#ifdef CONFIG_BOARD_AC696X_DEMO +#include "effect_reg.h" + + +//*----------------------------------------------------------------------------*/ +/**@brief 用户自定义录音输入例子 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +u16 rec_test_timer = 0; +FILE *pcm_file = NULL; +/*---调用recorder_userdata_to_enc将数据输入到编码器-----------------------------*/ +void rec_userinput_sun() +{ + char data2[512]; + fread(pcm_file, data2, 512); + recorder_userdata_to_enc((s16 *)data2, 512); +} +/*--关闭pcm文件,关闭定时器---------------------------------------------------*/ +void rec_userinput_del() +{ + if (pcm_file) { + fclose(pcm_file); + pcm_file = NULL; + } + if (rec_test_timer) { + sys_timer_del(rec_test_timer); + rec_test_timer = 0; + } +} +/*---打开pcm文件,启动一个定时器将pcm数据发给编码器---------------------------*/ +void rec_userinput_init() +{ + pcm_file = fopen(SDFILE_RES_ROOT_PATH"sine.pcm", "r"); + if (pcm_file == NULL) { + printf("sine.pcm open err\n"); + return; + } + rec_test_timer = sys_timer_add(NULL, rec_userinput_sun, 100); +} +//*----------------------------------------------------------------------------*/ +/**@brief 文件录音接口 + @param + @return + @note 1. +*/ +/*----------------------------------------------------------------------------*/ +void record_file_start(void) +{ + struct record_file_fmt fmt = {0}; + //char *logo = dev_manager_get_logo(dev_manager_find_active(0));//录音设备 + char logo[] = {"sd0"}; + char folder[] = {"JL_REC"}; //录音文件夹名称 + char filename[] = {"REC_TEST"}; //录音文件名,不需要加后缀,录音接口会根据编码格式添加后缀 + + fmt.dev = logo; + fmt.folder = folder; + fmt.filename = filename; + fmt.coding_type = AUDIO_CODING_MP3; //编码格式:AUDIO_CODING_WAV, AUDIO_CODING_MP3 + fmt.channel = 1; //声道数: 1:单声道 2:双声道 + fmt.sample_rate = 16000; //采样率:8000,16000,32000,44100 + fmt.cut_head_time = 300; //录音文件去头时间,单位ms + fmt.cut_tail_time = 300; //录音文件去尾时间,单位ms + fmt.limit_size = 3000; //录音文件大小最小限制, 单位byte + fmt.gain = 8; + fmt.source = ENCODE_SOURCE_MIC; //录音输入源:ENCODE_SOURCE_MIC, ENCODE_SOURCE_LINE0_LR, ENCODE_SOURCE_USER + + int ret = recorder_encode_start(&fmt); + + if (fmt.source == ENCODE_SOURCE_USER) { + rec_userinput_init();//初始化自定义录音源 + } +} + +#endif diff --git a/apps/soundbox/user_api/app_special_play_api.c b/apps/soundbox/user_api/app_special_play_api.c new file mode 100644 index 0000000..f2c75c1 --- /dev/null +++ b/apps/soundbox/user_api/app_special_play_api.c @@ -0,0 +1,215 @@ +#include "generic/gpio.h" +#include "asm/includes.h" +#include "system/timer.h" +#include "board_config.h" +#include "record/record.h" +#include "dev_manager.h" +#include "media/audio_base.h" +#include "audio_enc.h" +#include "tone_player.h" +#include "audio_dec.h" +#include "clock_cfg.h" +#ifdef CONFIG_BOARD_AC696X_DEMO +#include "effect_reg.h" + +extern void *file_eq_drc_open(u16 sample_rate, u8 ch_num); +extern void file_eq_drc_close(struct audio_eq_drc *eq_drc); + +/*----------------------------------------------------------------------------*/ +/**@brief 叠加播放需要添加的函数 + @param + @return + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +#define OVERLAY_PLAY 0 //叠加播放 +#define INTERRUPT_PLAY 1 //打断之前所有提示音再进行播放 + +struct tone_dec_handle *tone_dec_lev1 = NULL; +struct tone_dec_handle *tone_dec_lev2 = NULL; + +struct audio_eq_drc *record_eq_drc_lev1 = NULL; +struct audio_eq_drc *record_eq_drc_lev2 = NULL; +ECHO_API_STRUCT *record_play_echo_hdl_lev1 = NULL; +ECHO_API_STRUCT *record_play_echo_hdl_lev2 = NULL; +s_pitch_hdl *record_play_pitch_hdl_lev1 = NULL; +s_pitch_hdl *record_play_pitch_hdl_lev2 = NULL; + +/**************************************************************************************************************** +效果配置说明: +1.EFFECT_PITCH_SHIFT 移频,变调不变速,init_parm.shiftv调节有效,init_parm.formant_shift调节无效 +2.EFFECT_VOICECHANGE_KIN0 变声,可以调节不同的 init_parm.shiftv 跟 init_parm.formant_shift ,调出更多的声音效果 +3.EFFECT_VOICECHANGE_KIN1 变声,同EFFECT_VOICECHANGE_KIN0类似的,但是2者由于运算的不同,会有区别。 +4.EFFECT_ROBORT 机器音效果,类似 喜马拉雅那样的 +5.EFFECT_AUTOTUNE 电音效果 +****************************************************************************************************************/ +const PITCH_SHIFT_PARM record_play_pitch_parm = { + .sr = 16000L, //input audio samplerate + .shiftv = 100, //pitch rate: <8192(pitch up), >8192(pitch down) + .effect_v = EFFECT_AUTOTUNE, + .formant_shift = 100, +}; + +const ECHO_PARM_SET record_echo_parm = { + .delay = 200, //回声的延时时间 0-300ms + .decayval = 50, // 0-70% + .direct_sound_enable = 1, //直达声使能 0/1 + .filt_enable = 1, //发散滤波器使能 +}; + +static void record_play_stream_resume(void *p) +{ + struct audio_dec_app_hdl *app_dec = p; + audio_decoder_resume(&app_dec->decoder); +} + +void record_play_stream_handler_lev1(void *priv, int event, struct audio_dec_app_hdl *app_dec) +{ + switch (event) { + case AUDIO_DEC_APP_EVENT_START_INIT_OK: { + u8 entry_cnt = 0; + struct audio_stream_entry *entries[8] = {NULL}; + entries[entry_cnt++] = &app_dec->decoder.entry; + { + clock_add_set(REVERB_CLK); + //打开pitch和添加处理入口 + //record_play_pitch_hdl_lev1 = open_pitch((PITCH_SHIFT_PARM *)&record_play_pitch_parm); + //entries[entry_cnt++] = &record_play_pitch_hdl_lev1->entry; + + //打开echo和添加处理入口 + //record_play_echo_hdl_lev1 = open_echo((ECHO_PARM_SET *)&record_echo_parm, 16000); + //entries[entry_cnt++] = &record_play_echo_hdl_lev1->entry; + + //打开EQ和添加处理入口 + //record_eq_drc_lev1 = file_eq_drc_open(16000, 1); + //entries[entry_cnt++] = &record_eq_drc_lev1->entry; + } + entries[entry_cnt++] = &app_dec->mix_ch.entry; + app_dec->stream = audio_stream_open(app_dec, record_play_stream_resume); + audio_stream_add_list(app_dec->stream, entries, entry_cnt); + break; + } + case AUDIO_DEC_APP_EVENT_DEC_CLOSE: + //如果打开了pitch则删除pitch处理入口和关闭pitch + if (record_play_pitch_hdl_lev1) { + audio_stream_del_entry(&record_play_pitch_hdl_lev1->entry); + close_pitch(record_play_pitch_hdl_lev1); + record_play_pitch_hdl_lev1 = NULL; + } + //如果打开了echo则删除echo处理入口和关闭echo + if (record_play_echo_hdl_lev1) { + audio_stream_del_entry(&record_play_echo_hdl_lev1->entry); + close_echo(record_play_echo_hdl_lev1); + record_play_echo_hdl_lev1 = NULL; + } + //如果打开了EQ则删除EQ处理入口和关闭EQ + if (record_eq_drc_lev1) { + file_eq_drc_close(record_eq_drc_lev1); + record_eq_drc_lev1 = NULL; + } + break; + } +} + +void record_play_stream_handler_lev2(void *priv, int event, struct audio_dec_app_hdl *app_dec) +{ + switch (event) { + case AUDIO_DEC_APP_EVENT_START_INIT_OK: + printf("AUDIO_DEC_APP_EVENT_START_INIT_OK\n"); + struct audio_stream_entry *entries[8] = {NULL}; + u8 entry_cnt = 0; + entries[entry_cnt++] = &app_dec->decoder.entry; + { + clock_add_set(REVERB_CLK); + //打开pitch和添加处理入口 + //record_play_pitch_hdl_lev2 = open_pitch((PITCH_SHIFT_PARM *)&record_play_pitch_parm); + //entries[entry_cnt++] = &record_play_pitch_hdl_lev2->entry; + + //打开echo和添加处理入口 + //record_play_echo_hdl_lev2 = open_echo((ECHO_PARM_SET *)&record_echo_parm, 16000); + //entries[entry_cnt++] = &record_play_echo_hdl_lev2->entry; + + } + entries[entry_cnt++] = &app_dec->mix_ch.entry; + app_dec->stream = audio_stream_open(app_dec, record_play_stream_resume); + audio_stream_add_list(app_dec->stream, entries, entry_cnt); + break; + case AUDIO_DEC_APP_EVENT_DEC_CLOSE: + //如果打开了pitch则删除pitch处理入口和关闭pitch + if (record_play_pitch_hdl_lev2) { + audio_stream_del_entry(&record_play_pitch_hdl_lev2->entry); + close_pitch(record_play_pitch_hdl_lev2); + record_play_pitch_hdl_lev2 = NULL; + } + //如果打开了echo则删除echo处理入口和关闭echo + if (record_play_echo_hdl_lev2) { + audio_stream_del_entry(&record_play_echo_hdl_lev2->entry); + close_echo(record_play_echo_hdl_lev2); + record_play_echo_hdl_lev2 = NULL; + } + //如果打开了EQ则删除EQ处理入口和关闭EQ + if (record_eq_drc_lev2) { + file_eq_drc_close(record_eq_drc_lev2); + record_eq_drc_lev2 = NULL; + } + + break; + } +} + +int record_play_with_callback_by_path_lev1(char *name, u8 preemption, void (*evt_handler)(void *priv, int flag), void *evt_priv) +{ + static char *single_file[2] = {NULL}; + single_file[0] = name; + single_file[1] = NULL; + printf("record_play_with_callback_by_path_lev1\n"); + tone_dec_stop(&tone_dec_lev1, 1, TONE_DEC_STOP_BY_OTHER_PLAY); + tone_dec_lev1 = tone_dec_create(); + if (tone_dec_lev1 == NULL) { + return -1; + } + struct tone_dec_list_handle *dec_list = tone_dec_list_create(tone_dec_lev1, (const char **) single_file, preemption, evt_handler, NULL, record_play_stream_handler_lev1, NULL); + return tone_dec_list_add_play(tone_dec_lev1, dec_list); +} + +int record_play_with_callback_by_path_lev2(char *name, u8 preemption, void (*evt_handler)(void *priv, int flag), void *evt_priv) +{ + static char *single_file[2] = {NULL}; + single_file[0] = name; + single_file[1] = NULL; + printf("record_play_with_callback_by_path_lev2 \n"); + tone_dec_stop(&tone_dec_lev2, 1, TONE_DEC_STOP_BY_OTHER_PLAY); + tone_dec_lev2 = tone_dec_create(); + if (tone_dec_lev2 == NULL) { + return -1; + } + struct tone_dec_list_handle *dec_list = tone_dec_list_create(tone_dec_lev2, (const char **)single_file, preemption, evt_handler, NULL, record_play_stream_handler_lev2, NULL); + return tone_dec_list_add_play(tone_dec_lev2, dec_list); +} + +void record_play_end_callback_lev1(void *priv, int data) +{ + printf("record_play_end_callback_lev1\n"); +} +void record_play_end_callback_lev2(void *priv, int data) +{ + printf("record_play_end_callback_lev2\n"); +} +void record_file_replay_lev1() +{ + char path[64] = {0}; + char filepath[] = {"/JL_REC/REC_TEST.MP3"}; + sprintf(path, "%s%s%s%s", "storage/", "sd0", "/C", filepath); + record_play_with_callback_by_path_lev1(path, INTERRUPT_PLAY, record_play_end_callback_lev1, 0); +} + +void record_file_replay_lev2() +{ + char path[64] = {0}; + char filepath[] = {"/JL_REC/REC_TEST.WAV"}; + sprintf(path, "%s%s%s%s", "storage/", "sd0", "/C", filepath); + record_play_with_callback_by_path_lev2(path, OVERLAY_PLAY, record_play_end_callback_lev2, 0); +} + +#endif diff --git a/apps/soundbox/user_api/app_status_api.c b/apps/soundbox/user_api/app_status_api.c new file mode 100644 index 0000000..c4b4d2f --- /dev/null +++ b/apps/soundbox/user_api/app_status_api.c @@ -0,0 +1,63 @@ +#include "user_api/app_status_api.h" +#include "system/event.h" +#include "app_config.h" +extern void app_status_6083_handler(enum APP_STATUS status); + +void app_status_handler(enum APP_STATUS status)//必须在对应板级定义对应处理接口 +{ +#ifdef CONFIG_BOARD_AC6083A + app_status_6083_handler(status); +#endif + return; +} + +void app_status_bt_event(struct bt_event *e) +{ + switch (e->event) { + case BT_STATUS_SECOND_CONNECTED: + app_status_handler(APP_STATUS_BT_SECOND_CONNECTED); + break; + case BT_STATUS_FIRST_CONNECTED: + app_status_handler(APP_STATUS_BT_SECOND_DISCONNECT); + break; + case BT_STATUS_FIRST_DISCONNECT: + app_status_handler(APP_STATUS_BT_FIRST_DISCONNECT); + break; + case BT_STATUS_SECOND_DISCONNECT: + app_status_handler(APP_STATUS_BT_SECOND_DISCONNECT); + break; + case BT_STATUS_PHONE_INCOME: + app_status_handler(APP_STATUS_BT_PHONE_INCOME); + break; + case BT_STATUS_PHONE_OUT: + app_status_handler(APP_STATUS_BT_PHONE_OUT); + break; + case BT_STATUS_PHONE_ACTIVE: + app_status_handler(APP_STATUS_BT_PHONE_ACTIVE); + break; + case BT_STATUS_PHONE_HANGUP: + app_status_handler(APP_STATUS_BT_PHONE_HANGUP); + break; + case BT_STATUS_PHONE_NUMBER: + app_status_handler(APP_STATUS_BT_PHONE_NUMBER); + break; + case BT_STATUS_SCO_STATUS_CHANGE: + app_status_handler(APP_STATUS_BT_SCO_STATUS_CHANGE); + break; + case BT_STATUS_VOICE_RECOGNITION: + app_status_handler(APP_STATUS_BT_VOICE_RECOGNITION); + break; + case BT_STATUS_A2DP_MEDIA_START: + app_status_handler(APP_STATUS_BT_A2DP_MEDIA_START); + break; + case BT_STATUS_INIT_OK: + app_status_handler(APP_STATUS_BT_INIT_OK); + break; + case BT_STATUS_A2DP_MEDIA_STOP: + app_status_handler(APP_STATUS_BT_A2DP_MEDIA_STOP); + break; + default: + break; + } +} + diff --git a/apps/soundbox/user_api/dev_multiplex_api.c b/apps/soundbox/user_api/dev_multiplex_api.c new file mode 100644 index 0000000..ec570ca --- /dev/null +++ b/apps/soundbox/user_api/dev_multiplex_api.c @@ -0,0 +1,406 @@ +#include "includes.h" +#include "app_config.h" +#include "dev_multiplex_api.h" +#include "usb/otg.h" +#include "dev_manager.h" +#include "music/music_player.h" + + +#define LOG_TAG_CONST APP_ACTION +#define LOG_TAG "[APP_ACTION]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + + +extern u8 sd_io_suspend(u8 sdx, u8 sd_io); +extern u8 sd_io_resume(u8 sdx, u8 sd_io); + +static u8 msg_notify_enable = 0xff; + + +static u8 sd_first_online = 0; +static u16 resume = 0; + +#define USB_ACTIVE 0x1 +#define SD_ACTIVE 0x2 + +#define MULT_IO_IDLE (0) +#define MULT_IO_ACTIVE (BIT(0)) +#define MULT_IO_SUSPEND (BIT(1)) + +#define USB_RESET_DELAY 20 + +struct mult_io { + u8 sd_status: 3; + u8 usb_status: 3; + u8 active: 2; +}; + +struct mult_io mult_flag = {0}; + + +/*----------------------------------------------------------------------------*/ +/**@brief 库的调用函数 重载了库驱动 如果返回真则可以发送sd卡的上下线消息 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + +int sd_notify_enable(int sd_id) +{ + return msg_notify_enable & BIT(sd_id); +} + +#endif + +/*----------------------------------------------------------------------------*/ +/**@brief 设置是否 sd卡可以推上下线消息 + @param 1:可以推 0:不推 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void set_sd_notify_enable(int sd_id, u8 en) +{ + if (en) { + msg_notify_enable |= BIT(sd_id); + } else { + msg_notify_enable &= ~BIT(sd_id); + } +} + + + +void mult_sdio_resume_clean() +{ +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + if (resume) { + sd_io_resume(TCFG_DM_MULTIPLEX_WITH_SD_PORT, 2);//sd_data0 io 状态会被还原 + resume = 0; + } +#endif +} + + +void mult_sdio_resume() +{ +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + if (resume) { + resume--; + if (!resume) { + sd_io_resume(TCFG_DM_MULTIPLEX_WITH_SD_PORT, 2);//sd_data0 io 状态会被还原 + } + } +#endif +} + +int mult_sdio_suspend() +{ +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + if (resume) { + printf("%s resume count = %d\n", __FUNCTION__, resume); + return 0; + } +__try_t: + if (sd_io_suspend(TCFG_DM_MULTIPLEX_WITH_SD_PORT, 2)) { + os_time_dly(1); + printf("wait %s\n", __FUNCTION__); + goto __try_t; + } + resume++; + //配置绑定的sd_data0 io 为高阻 + gpio_set_direction(TCFG_USB_SD_MULTIPLEX_IO, 1); + gpio_set_pull_up(TCFG_USB_SD_MULTIPLEX_IO, 0); + gpio_set_pull_down(TCFG_USB_SD_MULTIPLEX_IO, 0); + gpio_set_die(TCFG_USB_SD_MULTIPLEX_IO, 0); + +#endif + return 0; +} + + + +void mult_usb_suspend(usb_dev id) +{ +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + if (id != (usb_dev) - 1 && usb_otg_online(id) == HOST_MODE) { + printf("mult_usb_suspend\n"); + usb_otg_io_suspend(id); + } +#endif +} + + + +int mult_usb_resume(usb_dev id, u8 mount, u32 delay) +{ + int err = -1; +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + if (id != (usb_dev) - 1 && usb_otg_online(id) == HOST_MODE) { + usb_otg_io_resume(id); + /* + * 有一部分U盘在DM和SD DAT0复用时,插入U盘或者模式切到播U盘, + * 需要把DPDM拉低一段时间,让U盘自己认为插入了主机 + */ + if (delay) { + usb_otg_suspend(id, 0); + os_time_dly(delay); + usb_otg_resume(id); + } + + if (mount) { + if (dev_manager_online_check_by_logo("udisk0", 0)) { + dev_manager_unmount("udisk0"); + } + if (usb_host_remount(id, MOUNT_RETRY, MOUNT_RESET, MOUNT_TIMEOUT, 0)) { + log_error("udisk remount fail\n"); + } else { + err = dev_manager_mount("udisk0"); + return err; + } + } else { + err = 0; + } + } +#endif + return err; +} + + + + +int dev_sd_change_usb() +{ +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + if ((mult_flag.sd_status == MULT_IO_ACTIVE) || + (mult_flag.usb_status == MULT_IO_SUSPEND)) { + printf("sd_change_usb start \n"); + mult_sdio_suspend(); + mult_flag.sd_status = MULT_IO_SUSPEND; + mult_usb_resume(g_usb_id, 1, USB_RESET_DELAY); + mult_flag.usb_status = MULT_IO_ACTIVE; + mult_flag.active = USB_ACTIVE; + printf("sd_change_usb finsh \n"); + } +#endif + return 0; +} + + +int dev_usb_change_sd() +{ + +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + if ((mult_flag.usb_status == MULT_IO_ACTIVE) || + (mult_flag.sd_status == MULT_IO_SUSPEND)) { + printf("dev_usb_change_sd start \n"); + mult_usb_suspend(g_usb_id); + os_time_dly(1);// + mult_flag.usb_status = MULT_IO_SUSPEND; + mult_sdio_resume(); + mult_flag.sd_status = MULT_IO_ACTIVE; + mult_flag.active = SD_ACTIVE; + printf("dev_usb_change_sd finsh \n"); + } + return 0; +#endif + return true; +} + + +int mult_sd_online_mount_before(int sd_dev, usb_dev usb_id) +{ +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + if (TCFG_DM_MULTIPLEX_WITH_SD_PORT != sd_dev) { + return 0; + } + sd_first_online = 1; + music_player_stop(1);//停止解码 + if (mult_flag.active == USB_ACTIVE) { + mult_usb_suspend(g_usb_id); + } + mult_sdio_resume_clean(); + mult_flag.usb_status = MULT_IO_SUSPEND; + mult_flag.sd_status = MULT_IO_ACTIVE; + mult_flag.active = SD_ACTIVE; +#endif + return 0; +} + + +int mult_sd_online_mount_after(int sd_dev, usb_dev usb_id, int err) +{ + int ret = 0; +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + if (TCFG_DM_MULTIPLEX_WITH_SD_PORT != sd_dev) { + return 0; + } + + if (err) { + mult_flag.sd_status = MULT_IO_SUSPEND; + mult_sdio_suspend(); + mult_usb_resume(usb_id, 1, USB_RESET_DELAY); + mult_flag.usb_status = MULT_IO_ACTIVE; + mult_flag.active = USB_ACTIVE; + } +#endif + return ret; +} + +int mult_sd_offline_before(void *logo, usb_dev usb_id) +{ + int ret = 0 ; + /* u8 dev_logo[16]; */ +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + int str_len = 0; + if (!sd_first_online) { //没有收到过上线消息不处理下线 + return 0; + } + if ((TCFG_DM_MULTIPLEX_WITH_SD_PORT == 0) && strcmp("sd0", logo)) { + return 0; + } + if ((TCFG_DM_MULTIPLEX_WITH_SD_PORT == 1) && strcmp("sd1", logo)) { + return 0; + } + printf("MULT_SD_OFFLINE_BEFORE\n"); + if (mult_flag.active == SD_ACTIVE) { + const char *cur_logo = music_player_get_phy_dev(&str_len); + +#if (TCFG_DM_MULTIPLEX_WITH_SD_PORT == 0) + if (cur_logo && (0 == strncmp(cur_logo, "sd0", str_len))) { + printf("SD0 STOP FIRST !!!"); + music_player_stop(1);//停止解码 + } + +#else + if (cur_logo && (0 == strncmp(cur_logo, "sd1", str_len))) { + printf("SD1 STOP FIRST !!!"); + music_player_stop(1);//停止解码 + } +#endif + + if (dev_manager_check_by_logo(logo)) { + dev_manager_del(logo); + } + /* sprintf(dev_logo, "%s%s", logo, "_rec"); */ + /* if (dev_manager_check_by_logo(dev_logo)) { */ + /* dev_manager_del(dev_logo); */ + /* } */ + mult_flag.sd_status = MULT_IO_IDLE; + mult_sdio_suspend(); + mult_usb_resume(usb_id, 1, USB_RESET_DELAY); + mult_flag.usb_status = MULT_IO_ACTIVE; + mult_flag.active = USB_ACTIVE; + + } else if (mult_flag.active == USB_ACTIVE) { + if (dev_manager_check_by_logo(logo)) { + dev_manager_del(logo); + } + /* sprintf(dev_logo, "%s%s", logo, "_rec"); */ + /* if (dev_manager_check_by_logo(dev_logo)) { */ + /* dev_manager_del(dev_logo); */ + /* } */ + mult_sdio_resume(); + mult_flag.sd_status = MULT_IO_SUSPEND; + } +#endif + return ret; +} + +int mult_usb_mount_before(usb_dev usb_id) +{ + u32 reset_delay = 0;; +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + music_player_stop(1);//停止解码 + if (mult_flag.active == SD_ACTIVE) { + mult_sdio_suspend(); + reset_delay = USB_RESET_DELAY; + } + mult_usb_resume(usb_id, 0, reset_delay); + mult_flag.sd_status = MULT_IO_SUSPEND; + mult_flag.usb_status = MULT_IO_ACTIVE; + mult_flag.active = USB_ACTIVE; +#endif + return 0; +} + + + + +int mult_usb_online_mount_after(usb_dev usb_id, int err) +{ + int ret = 0; +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + if (err) { + mult_flag.usb_status = MULT_IO_SUSPEND; + mult_usb_suspend(usb_id); + mult_sdio_resume(); + mult_flag.sd_status = MULT_IO_ACTIVE; + mult_flag.active = SD_ACTIVE; + } +#endif + return ret; +} + +int mult_usb_mount_offline(usb_dev usb_id) +{ +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + mult_usb_suspend(usb_id); + mult_sdio_resume(); + mult_flag.usb_status = MULT_IO_SUSPEND; + if (mult_flag.active == USB_ACTIVE) { + mult_flag.sd_status = MULT_IO_SUSPEND; + mult_flag.active = 0; + } else { + mult_flag.sd_status = MULT_IO_ACTIVE; + mult_flag.active = SD_ACTIVE; + + } +#endif + return 0; + +} + + + + + +///*----------------------------------------------------------------------------*/ +/**@brief pc模式 usb和sd卡 io 复用初始化 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void pc_dm_multiplex_init() +{ +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + mult_sdio_suspend();//supend sd卡总线 + set_sd_notify_enable(TCFG_DM_MULTIPLEX_WITH_SD_PORT, 0); //sd卡不允许发出上下线消息 + gpio_set_die(TCFG_USB_SD_MULTIPLEX_IO, 1); + gpio_direction_output(TCFG_USB_SD_MULTIPLEX_IO, 0); + os_time_dly(2); + gpio_set_direction(TCFG_USB_SD_MULTIPLEX_IO, 1); + gpio_set_pull_up(TCFG_USB_SD_MULTIPLEX_IO, 0); + gpio_set_pull_down(TCFG_USB_SD_MULTIPLEX_IO, 0); + gpio_set_die(TCFG_USB_SD_MULTIPLEX_IO, 0); +#endif +} + + +void pc_dm_multiplex_exit() +{ +#if TCFG_USB_DM_MULTIPLEX_WITH_SD_DAT0 + mult_sdio_resume();//resume sd卡总线 + usb_otg_resume(0); + set_sd_notify_enable(TCFG_DM_MULTIPLEX_WITH_SD_PORT, 1); //sd卡允许发出上下线消息 +#endif +} + + diff --git a/apps/soundbox/user_api/product_info_api.c b/apps/soundbox/user_api/product_info_api.c new file mode 100644 index 0000000..36d2db8 --- /dev/null +++ b/apps/soundbox/user_api/product_info_api.c @@ -0,0 +1,114 @@ +#include "product_info_api.h" +#include "syscfg_id.h" +#include "vm.h" +#include "app_config.h" +#include "typedef.h" +#include "system/includes.h" + +#define PRODUCT_INFO_API_EN 0 //默认不开启 + +#if (PRODUCT_INFO_API_EN) +struct __product_info_head { + s16 crc; + u16 len; + const u8 data[]; +} __attribute__((packed)); + +typedef enum _FLASH_ERASER { + CHIP_ERASER = 0, + BLOCK_ERASER, + SECTOR_ERASER, + PAGE_ERASER, +} FLASH_ERASER; + +//*----------------------------------------------------------------------------*/ +/**@brief 获取产品信息地址偏移 + @param + @return 返回产品信息地址偏移 + @note 产品信息是在芯片烧写的时候, 使用1拖2或者1拖8进行烧录的 +*/ +/*----------------------------------------------------------------------------*/ +static u32 product_info_get_ptr(void) +{ + u32 flash_capacity = sdfile_get_disk_capacity(); + u32 addr = flash_capacity - 256 + 80; + printf("flash capacity:%x \n", flash_capacity); + return sdfile_flash_addr2cpu_addr(addr); +} + +//*----------------------------------------------------------------------------*/ +/**@brief 产品信息检查 + @param para:产品信息位置偏移 + @return + @note 产品信息是在芯片烧写的时候, 使用1拖2或者1拖8进行烧录的 +*/ +/*----------------------------------------------------------------------------*/ +static int product_info_check(const u8 *para) +{ + struct __product_info_head *head; + + //fill head + head = (struct __product_info_head *)para; + if (head->len >= 0xff) { + printf("product info len err!!\n"); + return -1; + } + + ///crc check + u8 *crc_data = (u8 *)(para + sizeof(((struct __product_info_head *)0)->crc)); + u32 crc_len = sizeof(struct __product_info_head) + - sizeof(((struct __product_info_head *)0)->crc)/*head crc*/ + + (head->len)/*content crc,include end character '\0'*/; + s16 crc_sum = 0; + + crc_sum = CRC16(crc_data, crc_len); + + if (crc_sum != head->crc) { + ("product info crc error !!! %x %x \n", (u32)crc_sum, (u32)head->crc); + return -1; + } + + return 0; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 获取产品信息接口 + @param buf:外部传进来的缓存, len:缓存长度 + @return + @note 产品信息是在芯片烧写的时候, 使用1拖2或者1拖8进行烧录的 +*/ +/*----------------------------------------------------------------------------*/ +int product_info_prase(u8 *buf, u16 len) +{ + //产品信息内容建议不要超过128 + u8 *data_ptr = (u8 *)product_info_get_ptr(); + int ret = product_info_check((const u8 *)data_ptr); + if (ret) { + return -1; + } + + struct __product_info_head *head = (struct __product_info_head *)data_ptr; + if (len < head->len) { + printf("prase buf not enough\n"); + return -1; + } + + memcpy(buf, data_ptr + sizeof(struct __product_info_head), head->len); + return 0; +} + +//测试代码 +#if 0 +void product_info_debug(void) +{ + printf("product_info_debug \n"); + u8 tst_data[128] = {0}; + product_info_prase(tst_data, sizeof(tst_data)); + printf("tst_data = %s\n", tst_data); + put_buf(tst_data, 256); + //针对获出来的数据结合方案需求进行解析 +} +#endif + +#endif//PRODUCT_INFO_API_EN + diff --git a/apps/soundbox/version.c b/apps/soundbox/version.c new file mode 100644 index 0000000..676d188 --- /dev/null +++ b/apps/soundbox/version.c @@ -0,0 +1,32 @@ +#include "system/includes.h" +#include "generic/log.h" + +extern char __VERSION_BEGIN[]; +extern char __VERSION_END[]; + +_INLINE_ +int app_version_check() +{ + /*lib_version_check();*/ + + char *version; + + puts("=================Version===============\n"); + for (version = __VERSION_BEGIN; version < __VERSION_END;) { + version += 4; + printf("%s\n", version); + version += strlen(version) + 1; + } + puts("=======================================\n"); + + /*#ifdef CONFIG_FATFS_ENBALE + VERSION_CHECK(fatfs, FATFS_VERSION); + #endif + + #ifdef SDFILE_VERSION + VERSION_CHECK(sdfile, SDFILE_VERSION); + #endif*/ + return 0; +} + + diff --git a/cpu/br23/adc_api.c b/cpu/br23/adc_api.c new file mode 100644 index 0000000..2a739c8 --- /dev/null +++ b/cpu/br23/adc_api.c @@ -0,0 +1,696 @@ +#include "typedef.h" +#include "asm/clock.h" +#include "asm/adc_api.h" +#include "timer.h" +#include "init.h" +#include "asm/efuse.h" +#include "irq.h" +#include "asm/power/p33.h" +#include "asm/power_interface.h" + +u32 adc_sample(u32 ch); +static volatile u16 _adc_res; +static volatile u16 cur_ch_value; +static u8 cur_ch = 0; +struct adc_info_t { + u32 ch; + u16 value; +}; + +extern u8 is_lcd_on(); +#define ENABLE_OCCUPY_MODE 1 + +static struct adc_info_t adc_queue[ADC_MAX_CH + ENABLE_OCCUPY_MODE]; + +static u16 vbg_adc_value; +/* static u16 vbat_adc_value; */ + +#define ADC_SRC_CLK clk_get("adc") + +/*config adc clk according to sys_clk*/ +static const u32 sys2adc_clk_info[] = { + 128000000L, + 96000000L, + 72000000L, + 48000000L, + 24000000L, + 12000000L, + 6000000L, + 1000000L, +}; + +u32 adc_add_sample_ch(u32 ch) +{ + u32 i = 0; + for (i = 0; i < ADC_MAX_CH; i++) { + /* printf("%s() %d %x %x\n", __func__, i, ch, adc_queue[i].ch); */ + if (adc_queue[i].ch == ch) { + break; + } else if (adc_queue[i].ch == -1) { + adc_queue[i].ch = ch; + adc_queue[i].value = 1; + printf("add sample ch %x\n", ch); + break; + } + } + return i; +} +u32 adc_remove_sample_ch(u32 ch) +{ + u32 i = 0; + for (i = 0; i < ADC_MAX_CH; i++) { + if (adc_queue[i].ch == ch) { + adc_queue[i].ch = -1; + break; + } + } + return i; +} +static u32 adc_get_next_ch(u32 cur_ch) +{ + for (int i = cur_ch + 1; i < ADC_MAX_CH; i++) { + if (adc_queue[i].ch != -1) { + return i; + } + } + return 0; +} +#define vbat_value_array_size 16 +static u16 vbat_value_array[vbat_value_array_size]; +static void vbat_value_push(u16 vbat_value) +{ + static u32 pos = 0; + vbat_value_array[pos] = vbat_value; + pos++; + if (pos == vbat_value_array_size) { + pos = 0; + } +} +static u16 vbat_value_avg(void) +{ + u32 i, sum = 0; + for (i = 0; i < vbat_value_array_size; i++) { + sum += vbat_value_array[i]; + } + return sum / vbat_value_array_size; +} +u32 adc_get_value(u32 ch) +{ + if (ch == AD_CH_VBAT) { + return vbat_value_avg(); + } + + if (ch == AD_CH_LDOREF) { + return vbg_adc_value; + } + + for (int i = 0; i < ADC_MAX_CH; i++) { + if (adc_queue[i].ch == ch) { + return adc_queue[i].value; + } + } + return 0; +} + +#define CENTER 1168 +#define TRIM_MV 3.2f +u32 adc_value_to_voltage(u32 adc_vbg, u32 adc_ch_val) +{ + u32 adc_res = adc_ch_val; + u32 adc_trim = get_vbg_trim(); + u32 tmp, tmp1; + + tmp1 = adc_trim & 0x1f; + tmp = (adc_trim & BIT(5)) ? CENTER - tmp1 * TRIM_MV : CENTER + tmp1 * TRIM_MV; + adc_res = adc_res * tmp / adc_vbg; + return adc_res; +} + + +u32 adc_get_voltage(u32 ch) +{ +#ifdef CONFIG_FPGA_ENABLE + return 1000; +#endif + +#define CENTER 1168 + u32 adc_vbg = adc_get_value(AD_CH_LDOREF); + u32 adc_res = adc_get_value(ch); + + + u32 adc_trim = get_vbg_trim(); + u32 tmp, tmp1; + + tmp1 = adc_trim & 0x1f; + tmp = (adc_trim & BIT(5)) ? CENTER - tmp1 * 3.2 : CENTER + tmp1 * 3.2; + adc_res = adc_res * tmp / adc_vbg; + + + /* printf("\n\n vbg %d\n", adc_get_value(AD_CH_LDOREF)); */ + /* printf("%x VBAT:%d %d mv\n\n", adc_trim, */ + /* adc_get_value(AD_CH_VBAT), adc_res * 4); */ + return adc_res; +} + +u32 adc_check_vbat_lowpower() +{ + return 0; + /* u32 vbat = adc_get_value(AD_CH_VBAT); */ + /* return __builtin_abs(vbat - 255) < 5; */ +} +void adc_audio_ch_select(u32 ch) +{ + u8 tmp_ch = 0b1110011; + if ((ch == 2) || (ch == 3)) { + + tmp_ch |= BIT(ch); + } else { + + tmp_ch &= ~BIT(ch); + } + SFR(JL_ANA->ADA_CON3, 24, 7, tmp_ch); +} + +void adc_pll_detect_en(u32 ch) +{ + JL_CLOCK->PLL_CON1 |= BIT(18);//pll + SFR(JL_CLOCK->PLL_CON1, 16, 2, ch); +} + +void adc_fm_detect_en(u32 ch) +{ + + JL_ANA->WLA_CON25 |= (BIT(19));//fm + SFR(JL_ANA->WLA_CON25, 21, 3, ch); +} + +void adc_bt_detect_en(u32 ch) +{ + + JL_ANA->WLA_CON4 |= (BIT(6));//bt +} + +void adc_close() +{ + JL_ADC->CON = 0; + JL_ADC->CON = 0; +} +void adc_suspend() +{ + JL_ADC->CON &= ~BIT(4); +} +void adc_resume() +{ + JL_ADC->CON |= BIT(4); +} + +void adc_enter_occupy_mode(u32 ch) +{ + if (JL_ADC->CON & BIT(4)) { + return; + } + adc_queue[ADC_MAX_CH].ch = ch; + cur_ch_value = adc_sample(ch); +} +void adc_exit_occupy_mode() +{ + adc_queue[ADC_MAX_CH].ch = -1; +} +u32 adc_occupy_run() +{ + if (adc_queue[ADC_MAX_CH].ch != -1) { + while (1) { + asm volatile("idle");//wait isr + if (_adc_res != (u16) - 1) { + break; + } + } + if (_adc_res == 0) { + _adc_res ++; + } + adc_queue[ADC_MAX_CH].value = _adc_res; + _adc_res = cur_ch_value; + return adc_queue[ADC_MAX_CH].value; + } + return 0; +} +u32 adc_get_occupy_value() +{ + if (adc_queue[ADC_MAX_CH].ch != -1) { + return adc_queue[ADC_MAX_CH].value; + } + return 0; +} +u32 get_adc_div(u32 src_clk) +{ + u32 adc_clk; + u32 adc_clk_idx; + u32 cnt; + adc_clk = src_clk; + cnt = ARRAY_SIZE(sys2adc_clk_info); + for (adc_clk_idx = 0; adc_clk_idx < cnt; adc_clk_idx ++) { + if (adc_clk > sys2adc_clk_info[adc_clk_idx]) { + break; + } + } + + if (adc_clk_idx < cnt) { + adc_clk_idx = cnt - adc_clk_idx; + } else { + adc_clk_idx = cnt - 1; + } + return adc_clk_idx; +} + +u8 __attribute__((weak)) adc_io_reuse_enter(u32 ch) +{ + return 0; +} + +u8 __attribute__((weak)) adc_io_reuse_exit(u32 ch) +{ + return 0; +} + +static void adc_ch_mux_select(u32 mux_ch) +{ +#if 1 + //先把所有复用通道都关了 + P33_CON_SET(P3_ANA_CON4, 0, 1, 0);//pmu + SFR(JL_ANA->ADA_CON3, 24, 7, 0b1110011);//audio + JL_CLOCK->PLL_CON1 &= ~BIT(18);//pll + JL_ANA->WLA_CON25 &= ~(BIT(19));//fm + JL_ANA->WLA_CON4 &= ~(BIT(6));//bt +#endif + + if ((mux_ch & 0xfffff) == AD_OF_PMU) { + adc_pmu_detect_en(1); + adc_pmu_ch_select(mux_ch >> 20); + } else if ((mux_ch & 0xfffff) == AD_OF_AUDIO) { + adc_audio_ch_select(mux_ch >> 20); + } else if ((mux_ch & 0xfffff) == AD_OF_PLL) { + adc_pll_detect_en(mux_ch >> 20); + } else if ((mux_ch & 0xfffff) == AD_OF_FM) { + adc_fm_detect_en(mux_ch >> 20); + } else if ((mux_ch & 0xfffff) == AD_OF_BT) { + adc_bt_detect_en(mux_ch >> 20); + } +} + +___interrupt +static void adc_isr() +{ + _adc_res = JL_ADC->RES; + + u32 ch; + ch = (JL_ADC->CON & 0xf00) >> 8; + adc_io_reuse_exit(ch); + + adc_pmu_ch_select(AD_CH_WVDD >> 20); + local_irq_disable(); + JL_ADC->CON = BIT(6); + JL_ADC->CON = 0; + local_irq_enable(); +} + + +u32 adc_sample(u32 ch) +{ + const u32 tmp_adc_res = _adc_res; + _adc_res = (u16) - 1; + + if (adc_io_reuse_enter(ch)) { + _adc_res = adc_get_value(ch); + return tmp_adc_res; + } + + u32 adc_con = 0; + SFR(adc_con, 0, 3, 0b110);//div 96 + + adc_con |= (0xf << 12); //启动延时控制,实际启动延时为此数值*8个ADC时钟 + adc_con |= (adc_queue[0].ch & 0xf) << 8; + adc_con |= BIT(3); + adc_con |= BIT(6); + adc_con |= BIT(5);//ie + + SFR(adc_con, 8, 4, ch & 0xf); + + if ((ch & 0xffff) == AD_CH_MUX) { + adc_ch_mux_select(ch); + } + + JL_ADC->CON = adc_con; + JL_ADC->CON |= BIT(4);//en + JL_ADC->CON |= BIT(6);//kistart + + return tmp_adc_res; +} + + +#define VBG_VBAT_SCAN_CNT 10000 +void adc_scan(void *priv) +{ + static u16 vbg_vbat_cnt = VBG_VBAT_SCAN_CNT; + static u16 vbg_vbat_step = 0; + static u16 old_adc_res; + static u16 tmp_vbg_adc_value; + +// printf("%s() %x\n",__func__,JL_ADC->CON); + if (adc_queue[ADC_MAX_CH].ch != -1) {//occupy mode + return; + } + + if (JL_ADC->CON & BIT(4)) { + return ; + } + + /* if (!(JL_ADC->CON & BIT(4))) { //adc disable */ + /* return; */ + /* } */ + + vbg_vbat_cnt ++; + if (vbg_vbat_cnt > VBG_VBAT_SCAN_CNT) { + if (vbg_vbat_step == 0) { + vbg_vbat_step = 1; + old_adc_res = _adc_res; + adc_sample(AD_CH_LDOREF); + return; + } else if (vbg_vbat_step == 1) { + vbg_vbat_step = 2; + tmp_vbg_adc_value = adc_sample(AD_CH_VBAT); + //printf("vbg = %d\n", tmp_vbg_adc_value); + return; + } else if (vbg_vbat_step == 2) { + vbg_vbat_step = 0; + vbat_value_push(_adc_res); + vbg_adc_value = tmp_vbg_adc_value; + //printf("vbg = %d vbat = %d\n", vbg_adc_value, vbat_adc_value); + _adc_res = old_adc_res; + vbg_vbat_cnt = 0; + } + } + + u8 next_ch; + + next_ch = adc_get_next_ch(cur_ch); + + adc_queue[cur_ch].value = adc_sample(adc_queue[next_ch].ch); + + cur_ch = next_ch; +} + +//获取当前采集ad的通道总数 +u8 get_cur_total_ad_ch(void) +{ + u8 total_ch = 0; + u8 i = 0; + while (i < ADC_MAX_CH) { + if (adc_queue[i].ch != -1) { + total_ch++; + } + /* printf("i:%d,ch:%x\n",i,adc_queue[i].ch); */ + i++; + } + /* printf("total_ch:%d\n",total_ch); */ + return total_ch; +} + +void _adc_init(u32 sys_lvd_en) +{ + memset(adc_queue, 0xff, sizeof(adc_queue)); + + JL_ADC->CON = 0; + JL_ADC->CON = 0; + + adc_pmu_detect_en(1); + + u32 i; + adc_sample(AD_CH_VBAT); + for (i = 0; i < vbat_value_array_size; i++) { + while (!(JL_ADC->CON & BIT(7))); + vbat_value_array[i] = JL_ADC->RES; + JL_ADC->CON |= BIT(6); + } + printf("vbat_adc_value = %d\n", vbat_value_avg()); + + vbg_adc_value = 0; + adc_sample(AD_CH_LDOREF); + for (i = 0; i < 10; i++) { + while (!(JL_ADC->CON & BIT(7))); + vbg_adc_value += JL_ADC->RES; + JL_ADC->CON |= BIT(6); + } + vbg_adc_value /= 10; + printf("vbg_adc_value = %d\n", vbg_adc_value); + + _adc_res = 1; + + request_irq(IRQ_SARADC_IDX, 0, adc_isr, 0); + + sys_s_hi_timer_add(NULL, adc_scan, 2); //2ms + + /* void adc_test(); */ + /* sys_s_hi_timer_add(NULL, adc_test, 1000); //2ms */ +} +static u8 wvdd_lev = 0; +static u32 get_wvdd_voltage() +{ + u32 vbg_value = 0; + u32 wvdd_value = 0; + + adc_pmu_detect_en(1); + adc_sample(AD_CH_LDOREF); + for (int i = 0; i < 10; i++) { + while (!(JL_ADC->CON & BIT(7))) { //wait pending + } + + vbg_value += JL_ADC->RES; + JL_ADC->CON |= BIT(6); + } + + adc_sample(AD_CH_WVDD); + for (int i = 0; i < 10; i++) { + while (!(JL_ADC->CON & BIT(7))) { //wait pending + } + + wvdd_value += JL_ADC->RES; + JL_ADC->CON |= BIT(6); + } + +#define CENTER 1168 + u32 adc_vbg = vbg_value / 10; + u32 adc_res = wvdd_value / 10; + + + u32 adc_trim = get_vbg_trim(); + u32 tmp, tmp1; + + tmp1 = adc_trim & 0x1f; + tmp = (adc_trim & BIT(5)) ? CENTER - tmp1 * 3.2 : CENTER + tmp1 * 3.2; + adc_res = adc_res * tmp / adc_vbg; + /* printf("adc_res %d mv vbg:%d wvdd:%d %x\n", adc_res, vbg_value / 10, wvdd_value / 10,adc_trim); */ + return adc_res; +} + + +static void wvdd_trim() +{ + wvdd_lev = 0; + P33_CON_SET(P3_WLDO06_AUTO, 0, 3, wvdd_lev); + WLDO06_EN(1); + delay(2000);//1ms + do { + P33_CON_SET(P3_WLDO06_AUTO, 0, 3, wvdd_lev); + delay(2000);//1ms * n + if (get_wvdd_voltage() > 700) { + break; + } + wvdd_lev ++; + } while (wvdd_lev < 8); + WLDO06_EN(0); + + printf("wvdd_lev: %d\n", wvdd_lev); + + power_set_wvdd(wvdd_lev); +} +void vddiom_trim() +{ + u32 vbg_value = 0; + + adc_pmu_detect_en(1); + adc_sample(AD_CH_LDOREF); + for (int i = 0; i < 10; i++) { + while (!(JL_ADC->CON & BIT(7))) { //wait pending + } + + vbg_value += JL_ADC->RES; + JL_ADC->CON |= BIT(6); + } + + vbg_value /= 10; + + u32 vbg_trim = get_vbg_trim(); + u32 vbg_vol; + + u32 tmp1 = vbg_trim & 0x1f; + vbg_vol = (vbg_trim & BIT(5)) ? CENTER - tmp1 * 3.2 : CENTER + tmp1 * 3.2; + u32 vddio_vol = vbg_vol * 1023 / vbg_value; + printf("vddio_vol %d (mv) %d %x\n", vddio_vol, vbg_value, vbg_trim); + if (vddio_vol < 3400) { + VDDIOM_VOL_SEL(VDDIOM_VOL_36V); + } +} +#define _ABS(x) ((x) >= 0 ? (x) : (-(x))) +void vddiom_trim_all_range() +{ + u32 vbg_value = 0; + + adc_pmu_detect_en(1); + adc_sample(AD_CH_LDOREF); + for (int i = 0; i < 10; i++) { + while (!(JL_ADC->CON & BIT(7))) { //wait pending + } + + vbg_value += JL_ADC->RES; + JL_ADC->CON |= BIT(6); + } + + vbg_value /= 10; + + u32 vbg_trim = get_vbg_trim(); + u32 vbg_vol; + + u32 tmp1 = vbg_trim & 0x1f; + vbg_vol = (vbg_trim & BIT(5)) ? CENTER - tmp1 * 3.2 : CENTER + tmp1 * 3.2; + u32 vddio_vol = vbg_vol * 1023 / vbg_value; + printf("vddio_vol %d (mv), vbg_vol %d (mv) %d %x\n", vddio_vol, vbg_vol, vbg_value, vbg_trim); + + //if (vddio_vol < 3400) { + // VDDIOM_VOL_SEL(VDDIOM_VOL_36V); + //} + u32 vddiom_lev = GET_VDDIOM_VOL(); + u32 vddiom_ref = (vddiom_lev - VDDIOM_VOL_22V) * 200 + 2200; + int vddiom_diff = 32767; + u32 vbg_value_trim; + u32 vddiom_lev_trim = vddiom_lev; + printf("vddiom_lev %d, vddiom_ref %d\n", vddiom_lev, vddiom_ref); + + u32 vddiow_lev_bak = GET_VDDIOW_VOL(); + u32 vddiow_ref = 0; + VDDIOW_VOL_SEL(VDDIOW_VOL_21V); + switch (vddiow_lev_bak) { + case VDDIOW_VOL_21V: + vddiow_ref = 2100; + break; + case VDDIOW_VOL_24V: + vddiow_ref = 2400; + break; + case VDDIOW_VOL_28V: + vddiow_ref = 2800; + break; + case VDDIOW_VOL_32V: + vddiow_ref = 3200; + break; + } + printf("vddiow_lev %d, vddiow_ref %d\n", vddiow_lev_bak, vddiow_ref); + + for (int lev = VDDIOM_VOL_36V; vddiom_lev > 1 && lev >= vddiom_lev - 2; lev--) { + VDDIOM_VOL_SEL(lev); + delay(5000); //设完电压等级后要等电压稳定再采样 + vbg_value = 0; + adc_sample(AD_CH_LDOREF); + for (int i = 0; i < 10; i++) { + while (!(JL_ADC->CON & BIT(7))) { //wait pending + } + vbg_value += JL_ADC->RES; + JL_ADC->CON |= BIT(6); + } + vbg_value /= 10; + vddio_vol = vbg_vol * 1023 / vbg_value; + if (_ABS(vddiom_diff) > _ABS((int)vddio_vol - (int)vddiom_ref)) { + vddiom_diff = (int)vddio_vol - (int)vddiom_ref; + vbg_value_trim = vbg_value; + vddiom_lev_trim = lev; + } + } + vddio_vol = vddiom_ref + vddiom_diff; + VDDIOM_VOL_SEL(vddiom_lev_trim); + printf("trim: vddio_vol %d (mv), vddiom_lev %d, vddiom_diff %d, vbg_value %d\n", vddio_vol, vddiom_lev_trim, vddiom_diff, vbg_value_trim); + + u32 temp = (vddiom_lev_trim - VDDIOM_VOL_22V) * 200 + 2200; + if (temp < vddiow_ref + 200) { //vddiom需要比vddiow高200mV + if (temp >= 3200 + 200) { + VDDIOW_VOL_SEL(VDDIOW_VOL_32V); + } else if (temp >= 2800 + 200) { + VDDIOW_VOL_SEL(VDDIOW_VOL_28V); + } else if (temp >= 2400 + 200) { + VDDIOW_VOL_SEL(VDDIOW_VOL_24V); + } else { + VDDIOW_VOL_SEL(VDDIOW_VOL_21V); + } + printf("trim: vddiow lev %d to %d\n", vddiow_lev_bak, GET_VDDIOW_VOL()); + } else { + VDDIOW_VOL_SEL(vddiow_lev_bak); + } +} +void adc_init() +{ + JL_ANA->WLA_CON25 &= ~(BIT(19)); //fm + JL_ANA->WLA_CON4 &= ~(BIT(6));//bt + + //audio + JL_ANA->ADA_CON3 |= BIT(24);//F_VOUTL_TEST_EN_11v + JL_ANA->ADA_CON3 |= BIT(25);//F_VOUTR_TEST_EN_11v + JL_ANA->ADA_CON3 &= ~BIT(26); + JL_ANA->ADA_CON3 &= ~BIT(27); + JL_ANA->ADA_CON3 |= BIT(28);//DACVDD_TEST_EN_11v + JL_ANA->ADA_CON3 |= BIT(29);//R_VOUTL_TEST_EN_11v + JL_ANA->ADA_CON3 |= BIT(30);//R_VOUTR_TEST_EN_11v + + JL_CLOCK->PLL_CON1 &= ~BIT(18); //pll + + //trim wvdd + if (JL_SYSTEM->CHIP_ID & 0xf < 0x2) { + if (GET_VDDIOM_VOL() == VDDIOM_VOL_34V) { + vddiom_trim(); + if (is_lcd_on()) { + ASSERT(0, "lcd power_down must run vddio_trim_30v"); + } + } + } + + wvdd_trim(); + if (is_lcd_on()) { + /*lcd_driver : power_down use vddiow, trim vddiow=vddiom*/ + /*参数为vddio和vbat是否绑定在一起*/ + check_pmu_voltage(0); + } + _adc_init(1); + +} +//late_initcall(adc_init); + +void adc_test() +{ + + /* printf("\n\n%s() chip_id :%x\n", __func__, get_chip_id()); */ + /* printf("%s() vbg trim:%x\n", __func__, get_vbg_trim()); */ + /* printf("%s() vbat trim:%x\n", __func__, get_vbat_trim()); */ + + /* printf("\n\nWLA_CON0 %x\n", JL_ANA->WLA_CON0); */ + /* printf("WLA_CON9 %x\n", JL_ANA->WLA_CON9); */ + /* printf("WLA_CON10 %x\n", JL_ANA->WLA_CON10); */ + /* printf("WLA_CON21 %x\n", JL_ANA->WLA_CON21); */ + /* */ + /* printf("ADA_CON %x\n", JL_ANA->ADA_CON3); */ + /* printf("PLL_CON1 %x\n", JL_CLOCK->PLL_CON1); */ + + printf("\n%s() VBAT:%d %d mv\n\n", __func__, + adc_get_value(AD_CH_VBAT), adc_get_voltage(AD_CH_VBAT) * 4); + +} +void adc_vbg_init() +{ + return ; +} +//__initcall(adc_vbg_init); diff --git a/cpu/br23/app_timer.c b/cpu/br23/app_timer.c new file mode 100644 index 0000000..36a701f --- /dev/null +++ b/cpu/br23/app_timer.c @@ -0,0 +1,142 @@ + +#include "includes.h" +#include "app_config.h" +#include "asm/cpu.h" +#include "asm/irq.h" +#include "asm/clock.h" +#include "system/timer.h" +#include "system/init.h" +#include "gpio.h" + +/* #define LOG_TAG_CONST TMR */ +/* #define LOG_TAG "[USER_TMR]" */ +/* #define LOG_INFO_ENABLE */ +/* #define LOG_DUMP_ENABLE */ +/* #define LOG_ERROR_ENABLE */ +/* #define LOG_DEBUG_ENABLE */ +#include "debug.h" +/* +注意 + +timer1 现在定义优先级为6 ,关总中断不关闭该优先级, +该中断里面使用函数 const 变量都必须定义在ram,否则会跑飞 + + + + * + */ + +//注意:改定时器会被低功耗使用到,使用时需要关闭低功耗 + +#if (TCFG_UI_LED1888_ENABLE || TCFG_UI_LED7_ENABLE) +#define TCFG_USER_TIMER_ENABLE +#endif + +#ifdef TCFG_USER_TIMER_ENABLE + + +struct timer_hdl { + int index; + int prd; +}; + +static struct timer_hdl hdl; + +#define __this (&hdl) + +static const u32 timer_div[] = { + /*0000*/ 1, + /*0001*/ 4, + /*0010*/ 16, + /*0011*/ 64, + /*0100*/ 2, + /*0101*/ 8, + /*0110*/ 32, + /*0111*/ 128, + /*1000*/ 256, + /*1001*/ 4 * 256, + /*1010*/ 16 * 256, + /*1011*/ 64 * 256, + /*1100*/ 2 * 256, + /*1101*/ 8 * 256, + /*1110*/ 32 * 256, + /*1111*/ 128 * 256, +}; + +#define APP_TIMER_CLK clk_get("timer") +#define MAX_TIME_CNT 0x7fff +#define MIN_TIME_CNT 0x100 + + +#define TIMER_CON JL_TIMER2->CON +#define TIMER_CNT JL_TIMER2->CNT +#define TIMER_PRD JL_TIMER2->PRD +#define TIMER_VETOR IRQ_TIME2_IDX + +#define TIMER_UNIT_MS 2 //1ms起一次中断 +#define MAX_TIMER_PERIOD_MS (1000/TIMER_UNIT_MS) + +/*-----------------------------------------------------------*/ + +static volatile u32 delay_cnt = 0; + +extern void sputchar(char c); + + +void (*timer_led_scan)(void *param); + +void app_timer_led_scan(void (*led_scan)(void *)) +{ + timer_led_scan = led_scan; +} + +/////下面函数调用的使用函数都必须放在ram +___interrupt +AT_VOLATILE_RAM_CODE +static void timer2_isr() +{ + static u32 cnt1 = 0; + + TIMER_CON |= BIT(14); + + ++cnt1; + + if (timer_led_scan) { + timer_led_scan(NULL); + } + + if (cnt1 == 500) { //500ms + /* sputchar('!'); */ + cnt1 = 0; + } +} + +int timer2_init() +{ + u32 prd_cnt; + u8 index; + + printf("------------%s :%d", __func__, __LINE__); + + for (index = 0; index < (sizeof(timer_div) / sizeof(timer_div[0])); index++) { + prd_cnt = TIMER_UNIT_MS * (APP_TIMER_CLK / 1000) / timer_div[index]; + if (prd_cnt > MIN_TIME_CNT && prd_cnt < MAX_TIME_CNT) { + break; + } + } + __this->index = index; + __this->prd = prd_cnt; + + TIMER_CNT = 0; + TIMER_PRD = prd_cnt; //1ms + request_irq(TIMER_VETOR, 1, timer2_isr, 0); + TIMER_CON = (index << 4) | BIT(0) | BIT(3); + + printf("PRD : 0x%x / %d", TIMER_PRD, clk_get("timer")); + + return 0; +} +__initcall(timer2_init); + +#endif + diff --git a/cpu/br23/audio_common/app_audio.c b/cpu/br23/audio_common/app_audio.c new file mode 100644 index 0000000..4b769d2 --- /dev/null +++ b/cpu/br23/audio_common/app_audio.c @@ -0,0 +1,1770 @@ +#include "system/includes.h" +#include "media/includes.h" + +#include "app_config.h" +#include "app_action.h" +#include "app_main.h" + +#include "audio_config.h" +#include "audio_digital_vol.h" +#include "audio_link.h" +#include "application/audio_output_dac.h" +#include "application/audio_dig_vol.h" + +#include "update.h" + +#if defined(AUDIO_OUTPUT_WAY) && (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) +#include "fm_emitter/fm_emitter_manage.h" +#endif +#if (defined(AUDIO_OUTPUT_WAY) && AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) +extern void bt_emitter_set_vol(u8 vol); +#endif + +extern void set_user_audio_digital_vol(u8 vol); + +#define LOG_TAG "[APP_AUDIO]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +#define DEFAULT_DIGTAL_VOLUME 16384 + +struct app_audio_config { + u8 state; + u8 prev_state; + u8 mute_when_vol_zero; + volatile u8 fade_gain_l; + volatile u8 fade_gain_r; + volatile u8 fade_gain_rl; + volatile u8 fade_gain_rr; + volatile s16 fade_dgain_l; + volatile s16 fade_dgain_r; + volatile s16 fade_dgain_rl; + volatile s16 fade_dgain_rr; + volatile s16 fade_dgain_step_l; + volatile s16 fade_dgain_step_r; + volatile s16 fade_dgain_step_rl; + volatile s16 fade_dgain_step_rr; + volatile int fade_timer; + volatile int save_vol_timer; + volatile u8 save_vol_cnt; + /* s16 digital_volume; */ + s16 digital_volume_fl; + s16 digital_volume_fr; + s16 digital_volume_rl; + s16 digital_volume_rr; + atomic_t ref; + s16 max_volume[APP_AUDIO_MAX_STATE]; +}; +static const char *audio_state[] = { + "idle", + "music", + "call", + "tone", + "linein", + "err", +}; + +static struct app_audio_config app_audio_cfg = {0}; + +#define __this (&app_audio_cfg) +extern struct audio_dac_hdl dac_hdl; +extern struct audio_dac_channel default_dac; +extern struct dac_platform_data dac_data; +struct audio_dac_hdl dac_hdl; +extern struct audio_adc_hdl adc_hdl; +OS_SEM dac_sem; + +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) +#define BNUM 2 +#else +#define BNUM 1 +#endif + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) +s16 dac_buff[4 * 1024 * BNUM] SEC(.dac_buff); +#elif AUDIO_OUTPUT_INCLUDE_DAC +s16 dac_buff[4 * 1024 * BNUM] SEC(.dac_buff); +#endif + +/*关闭audio相关模块使能*/ +void audio_disable_all(void) +{ + //DAC:DACEN + JL_AUDIO->DAC_CON &= ~BIT(4); + //ADC:ADCEN + JL_AUDIO->ADC_CON &= ~BIT(4); + //EQ: + JL_EQ->CON0 &= ~BIT(0); + //FFT: + JL_FFT->CON = BIT(1);//置1强制关闭模块,不管是否已经运算完成 +} + +REGISTER_UPDATE_TARGET(audio_update_target) = { + .name = "audio", + .driver_close = audio_disable_all, +}; + +/* + ************************************************************* + * + * audio volume save + * + ************************************************************* + */ + +static void app_audio_volume_save_do(void *priv) +{ + //log_info("app_audio_volume_save_do %d\n", __this->save_vol_cnt); + local_irq_disable(); + if (++__this->save_vol_cnt >= 5) { + sys_timer_del(__this->save_vol_timer); + __this->save_vol_timer = 0; + __this->save_vol_cnt = 0; + local_irq_enable(); + log_info("VOL_SAVE\n"); + syscfg_write(CFG_MUSIC_VOL, &app_var.music_volume, 1); + return; + } + local_irq_enable(); +} + +static void app_audio_volume_change(void) +{ + local_irq_disable(); + __this->save_vol_cnt = 0; + if (__this->save_vol_timer == 0) { + __this->save_vol_timer = sys_timer_add(NULL, app_audio_volume_save_do, 1000);//要使用软件定时器 中断里不能操作vm + } + local_irq_enable(); +} + + +static int audio_vol_set(u8 gain_l, u8 gain_r, u8 gain_rl, u8 gain_rr, u8 fade) +{ +#if (AUDIO_VOL_MANUAL) + return 0; +#endif + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) + return 0; +#endif + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) + extern void *iis_digvol_last; + if (iis_digvol_last) { + audio_dig_vol_set(iis_digvol_last, AUDIO_DIG_VOL_ALL_CH, gain_l); + } +#endif + +#if (TCFG_APP_FM_EMITTER_EN) + extern void *fmtx_digvol_last; + audio_dig_vol_set(fmtx_digvol_last, AUDIO_DIG_VOL_ALL_CH, gain_l); +#endif + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) + bt_emitter_set_vol(gain_l); +#endif + /* r_printf("dac_fade_begin:0x%x\n", __this->fade_timer); */ + local_irq_disable(); + __this->fade_gain_l = gain_l; + __this->fade_gain_r = gain_r; + __this->fade_gain_rl = gain_rl; + __this->fade_gain_rr = gain_rr; + +#if AUDIO_OUTPUT_INCLUDE_DAC + +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_MONO_L) + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0), gain_l, fade); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0), gain_l ? DEFAULT_DIGTAL_VOLUME : 0, fade); +#elif (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_MONO_R) + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(1), gain_r, fade); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0), gain_r ? DEFAULT_DIGTAL_VOLUME : 0, fade); +#else + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0), gain_l, fade); + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(1), gain_r, fade); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0), gain_l ? DEFAULT_DIGTAL_VOLUME : 0, fade); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(1), gain_r ? DEFAULT_DIGTAL_VOLUME : 0, fade); +#endif + +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) \ + || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(2), gain_rl, fade); + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(3), gain_rr, fade); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(2), gain_rl ? DEFAULT_DIGTAL_VOLUME : 0, fade); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(3), gain_rr ? DEFAULT_DIGTAL_VOLUME : 0, fade); +#endif + +#endif // AUDIO_OUTPUT_INCLUDE_DAC + + local_irq_enable(); + + return 0; +} + +#if (SYS_VOL_TYPE == 2) + +#define DGAIN_SET_MAX_STEP (300) +#define DGAIN_SET_MIN_STEP (30) + +static unsigned short combined_vol_list[31][2] = { + { 0, 0}, //0: None + { 0, 16384}, // 1:-41.21 db + { 2, 14105}, // 2:-39.79 db + { 3, 14273}, // 3:-38.37 db + { 4, 14409}, // 4:-36.94 db + { 5, 14473}, // 5:-35.52 db + { 6, 14619}, // 6:-34.10 db + { 7, 14727}, // 7:-32.68 db + { 8, 14840}, // 8:-31.26 db + { 9, 15010}, // 9:-29.84 db + {10, 15182}, // 10:-28.42 db + {11, 15333}, // 11:-27.00 db + {12, 15450}, // 12:-25.58 db + {13, 15652}, // 13:-24.16 db + {14, 15826}, // 14:-22.73 db + {15, 15890}, // 15:-21.31 db + {16, 15294}, // 16:-19.89 db + {17, 15357}, // 17:-18.47 db + {18, 15455}, // 18:-17.05 db + {19, 15569}, // 19:-15.63 db + {20, 15668}, // 20:-14.21 db + {21, 15790}, // 21:-12.79 db + {22, 15857}, // 22:-11.37 db + {23, 15877}, // 23:-9.95 db + {24, 15949}, // 24:-8.53 db + {25, 15998}, // 25:-7.11 db + {26, 16070}, // 26:-5.68 db + {27, 16152}, // 27:-4.26 db + {28, 16245}, // 28:-2.84 db + {29, 16301}, // 29:-1.42 db + {30, 16384}, // 30:0.00 db +}; +static unsigned short call_combined_vol_list[16][2] = { + { 0, 0}, //0: None + { 0, 16384}, // 1:-41.21 db + { 2, 15343}, // 2:-39.05 db + { 4, 14475}, // 3:-36.90 db + { 5, 15817}, // 4:-34.75 db + { 7, 14865}, // 5:-32.60 db + { 8, 16294}, // 6:-30.45 db + {10, 15396}, // 7:-28.30 db + {12, 14472}, // 8:-26.14 db + {13, 15949}, // 9:-23.99 db + {15, 14953}, // 10:-21.84 db + {16, 15656}, // 11:-19.69 db + {18, 14612}, // 12:-17.54 db + {19, 16013}, // 13:-15.39 db + {21, 14998}, // 14:-13.23 db + {22, 16384}, // 15:-11.08 db +}; + +static int audio_combined_vol_set(u8 gain_l, u8 gain_r, u8 gain_rl, u8 gain_rr, u8 fade) +{ +#if TCFG_APP_FM_EMITTER_EN + return 0; +#endif + u8 target_again_l = 0; + u8 target_again_r = 0; + u8 target_again_rl = 0; + u8 target_again_rr = 0; + u16 target_dgain_l = 0; + u16 target_dgain_r = 0; + u16 target_dgain_rl = 0; + u16 target_dgain_rr = 0; + + if (__this->state == APP_AUDIO_STATE_CALL) { + target_again_l = call_combined_vol_list[gain_l][0]; + target_again_r = call_combined_vol_list[gain_r][0]; + target_again_rl = call_combined_vol_list[gain_rl][0]; + target_again_rr = call_combined_vol_list[gain_rr][0]; + target_dgain_l = call_combined_vol_list[gain_l][1]; + target_dgain_r = call_combined_vol_list[gain_r][1]; + target_dgain_rl = call_combined_vol_list[gain_rl][1]; + target_dgain_rr = call_combined_vol_list[gain_rr][1]; + } else { + target_again_l = combined_vol_list[gain_l][0]; + target_again_r = combined_vol_list[gain_r][0]; + target_again_rl = combined_vol_list[gain_rl][0]; + target_again_rr = combined_vol_list[gain_rr][0]; + target_dgain_l = combined_vol_list[gain_l][1]; + target_dgain_r = combined_vol_list[gain_r][1]; + target_dgain_rl = combined_vol_list[gain_rl][1]; + target_dgain_rr = combined_vol_list[gain_rr][1]; + } + + r_printf("dac_fade_begin:0x%x\n", __this->fade_timer); + + local_irq_disable(); + + __this->fade_gain_l = target_again_l; + __this->fade_gain_r = target_again_r; + __this->fade_gain_rl = target_again_rl; + __this->fade_gain_rr = target_again_rr; + __this->fade_dgain_l = target_dgain_l; + __this->fade_dgain_r = target_dgain_r; + __this->fade_dgain_rl = target_dgain_rl; + __this->fade_dgain_rr = target_dgain_rr; + + +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_MONO_L) + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0), __this->fade_gain_l, fade); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0), __this->fade_dgain_l, fade); +#elif (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_MONO_R) + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(1), __this->fade_gain_r, fade); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0), __this->fade_dgain_r, fade); +#else + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0), __this->fade_gain_l, fade); + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(1), __this->fade_gain_r, fade); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0), __this->fade_dgain_l, fade); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(1), __this->fade_dgain_r, fade); +#endif + +#if ((TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) \ + || (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF)) + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(2), __this->fade_gain_rl, fade); + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(3), __this->fade_gain_rr, fade); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(2), __this->fade_dgain_rl, fade); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(3), __this->fade_dgain_rr, fade); +#endif + + local_irq_enable(); + + return 0; +} + +#endif // (SYS_VOL_TYPE == 2) + + + + + +static void set_audio_device_volume(u8 type, s16 vol) +{ +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) + fm_emitter_manage_set_vol(vol); +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) + audio_dac_set_analog_vol_support4way(&dac_hdl, vol, vol, vol, vol); +#else + audio_dac_set_analog_vol(&dac_hdl, vol); +#endif +#endif +} + +static int get_audio_device_volume(u8 vol_type) +{ +#if 0 + void *dev; + struct audio_volume volume; + int vol; + + volume.type = vol_type; + dev = dev_open("audio", (void *)"play0"); + if (dev) { + dev_ioctl(dev, IOCTL_GET_VOLUME, (u32)&volume); + dev_close(dev); + return volume.value; + } else { + log_info("no audio dev\n"); + return -1; + } +#endif + return 0; +} + +void volume_up_down_direct(s8 value) +{ +#if 0 + s16 volume; + volume = get_audio_device_volume(AUDIO_SYS_VOL); + volume += value; + if (volume < 0) { + volume = 0; + } + set_audio_device_volume(AUDIO_SYS_VOL, volume); +#endif +} + +void audio_set_hw_digital_vol_fl(s16 fl) +{ + __this->digital_volume_fl = fl * 16384 / get_max_sys_vol(); + audio_dac_set_L_digital_vol(&dac_hdl, __this->digital_volume_fl); +} +void audio_set_hw_digital_vol_fr(s16 fr) +{ + __this->digital_volume_fr = fr * 16384 / get_max_sys_vol(); + audio_dac_set_R_digital_vol(&dac_hdl, __this->digital_volume_fr); +} +void audio_set_hw_digital_vol_rl(s16 rl) +{ + __this->digital_volume_rl = rl * 16384 / get_max_sys_vol(); + audio_dac_set_RL_digital_vol(&dac_hdl, __this->digital_volume_rl); +} +void audio_set_hw_digital_vol_rr(s16 rr) +{ + __this->digital_volume_rr = rr * 16384 / get_max_sys_vol(); + audio_dac_set_RR_digital_vol(&dac_hdl, __this->digital_volume_rr); +} + +void audio_set_hw_digital_vol_default(u8 fl, u8 fr, u8 rl, u8 rr) +{ + __this->digital_volume_fl = fl; + __this->digital_volume_fr = fr; + __this->digital_volume_rl = rl; + __this->digital_volume_rr = rr; +} + + + +void audio_fade_in_fade_out(u8 left_gain, u8 right_gain, u8 fade) +{ +#if (SYS_VOL_TYPE == 2) + audio_combined_vol_set(left_gain, right_gain, left_gain, right_gain, fade); +#else + audio_vol_set(left_gain, right_gain, left_gain, right_gain, fade); +#endif +} + +extern char *music_dig_logo[]; + +extern void *sys_digvol_group; + +void app_audio_set_volume(u8 state, s8 volume, u8 fade) +{ + char *digvol_type = NULL ; + switch (state) { + case APP_AUDIO_STATE_IDLE: + case APP_AUDIO_STATE_MUSIC: + case APP_AUDIO_STATE_LINEIN: +#if SYS_DIGVOL_GROUP_EN + digvol_type = "music_type"; +#endif + app_var.music_volume = volume; + if (app_var.music_volume > get_max_sys_vol()) { + app_var.music_volume = get_max_sys_vol(); + } + volume = app_var.music_volume; + + break; + case APP_AUDIO_STATE_CALL: +#if SYS_DIGVOL_GROUP_EN + digvol_type = "call_esco"; +#endif + + app_var.call_volume = volume; + if (app_var.call_volume > 15) { + app_var.call_volume = 15; + } + volume = app_var.aec_dac_gain * app_var.call_volume / 15; +#if TCFG_CALL_USE_DIGITAL_VOLUME + audio_digital_vol_set(volume); + return; +#endif + break; + case APP_AUDIO_STATE_WTONE: +#if SYS_DIGVOL_GROUP_EN + digvol_type = "tone_tone"; +#endif + + +#if (TONE_MODE_DEFAULE_VOLUME != 0) + app_var.wtone_volume = TONE_MODE_DEFAULE_VOLUME; + volume = app_var.wtone_volume; + break; +#endif +#if (APP_AUDIO_STATE_WTONE_BY_MUSIC == 1) + app_var.wtone_volume = app_var.music_volume; + if (app_var.wtone_volume < 5) { + app_var.wtone_volume = 5; + } +#else + app_var.wtone_volume = volume; +#endif + if (app_var.wtone_volume > get_max_sys_vol()) { + app_var.wtone_volume = get_max_sys_vol(); + } + volume = app_var.wtone_volume; + break; + default: + return; + } + + if (state == __this->state) { +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) + fm_emitter_manage_set_vol(volume); +#else +#if defined (VOL_TYPE_DIGGROUP) && defined (SYS_DIGVOL_GROUP_EN) + if (state == APP_AUDIO_STATE_LINEIN) { + //printf("linein analog vol:%d\n",volume); + audio_fade_in_fade_out(volume, volume, fade); + return; + } + + if (SYS_VOL_TYPE == VOL_TYPE_DIGGROUP && SYS_DIGVOL_GROUP_EN) { + if (sys_digvol_group == NULL) { + /* printf("the sys_digvol_group is NULL\n-------------------------------------------------------------"); */ + return; + } + if (strcmp(digvol_type, "music_type") == 0) { + for (int i = 0; music_dig_logo[i] != "NULL"; i++) { + /* printf("%s\n", music_dig_logo[i]); */ + if (audio_dig_vol_group_hdl_get(sys_digvol_group, music_dig_logo[i]) == NULL) { + continue; + } + + + audio_dig_vol_set(audio_dig_vol_group_hdl_get(sys_digvol_group, music_dig_logo[i]), AUDIO_DIG_VOL_ALL_CH, volume); + } + } else { + if (audio_dig_vol_group_hdl_get(sys_digvol_group, digvol_type) == NULL) { + return; + } + + + audio_dig_vol_set(audio_dig_vol_group_hdl_get(sys_digvol_group, digvol_type), AUDIO_DIG_VOL_ALL_CH, volume); + } + } + + else { + audio_fade_in_fade_out(volume, volume, fade); + } + +#else + audio_fade_in_fade_out(volume, volume, fade); +#endif //vol_type_diggroup + +#endif //audio_output_way + + } + app_audio_volume_change(); +} + +void app_audio_volume_init(void) +{ + app_audio_set_volume(APP_AUDIO_STATE_MUSIC, app_var.music_volume, 1); +} + +s8 app_audio_get_volume(u8 state) +{ + s8 volume = 0; + switch (state) { + case APP_AUDIO_STATE_IDLE: + case APP_AUDIO_STATE_MUSIC: + case APP_AUDIO_STATE_LINEIN: + volume = app_var.music_volume; + break; + case APP_AUDIO_STATE_CALL: + volume = app_var.call_volume; + break; + case APP_AUDIO_STATE_WTONE: +#if (TONE_MODE_DEFAULE_VOLUME != 0) + app_var.wtone_volume = TONE_MODE_DEFAULE_VOLUME; + volume = app_var.wtone_volume; + break; +#endif +#if (APP_AUDIO_STATE_WTONE_BY_MUSIC == 1) + app_var.wtone_volume = app_var.music_volume; + volume = app_var.music_volume; + break; +#else + volume = app_var.wtone_volume; + /* if (!volume) { */ + /* volume = app_var.music_volume; */ + /* } */ + break; +#endif + case APP_AUDIO_CURRENT_STATE: + volume = app_audio_get_volume(__this->state); + break; + default: + break; + } + /* printf("app_audio_get_volume %d %d\n", state, volume); */ + return volume; +} + + +static const char *audio_mute_string[] = { + "mute_default", + "unmute_default", + "mute_L", + "unmute_L", + "mute_R", + "unmute_R", +}; + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) +#define AUDIO_MUTE_FADE 0 +#define AUDIO_UMMUTE_FADE 0 +#else +#define AUDIO_MUTE_FADE 1 +#define AUDIO_UMMUTE_FADE 1 +#endif + +void app_audio_mute(u8 value) +{ + u8 volume = 0; + /* printf("audio_mute:%s", audio_mute_string[value]); */ + switch (value) { + case AUDIO_MUTE_DEFAULT: + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) + fm_emitter_manage_set_vol(0); +#else + audio_dac_vol_mute(1, 1); +#endif + break; + case AUDIO_UNMUTE_DEFAULT: +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) + volume = app_audio_get_volume(APP_AUDIO_CURRENT_STATE); + fm_emitter_manage_set_vol(volume); +#else + audio_dac_vol_mute(0, 1); +#endif + break; + } +} + + +void app_audio_volume_up(u8 value) +{ + s16 volume = 0; + switch (__this->state) { + case APP_AUDIO_STATE_IDLE: + case APP_AUDIO_STATE_MUSIC: + case APP_AUDIO_STATE_LINEIN: + app_var.music_volume += value; + if (app_var.music_volume > get_max_sys_vol()) { + app_var.music_volume = get_max_sys_vol(); + } + volume = app_var.music_volume; + break; + case APP_AUDIO_STATE_CALL: + app_var.call_volume += value; + if (app_var.call_volume > 15) { + app_var.call_volume = 15; + } + volume = app_var.call_volume; +#if TCFG_CALL_USE_DIGITAL_VOLUME + audio_digital_vol_set(volume); + return; +#endif + break; + case APP_AUDIO_STATE_WTONE: +#if (TONE_MODE_DEFAULE_VOLUME != 0) + app_var.wtone_volume = TONE_MODE_DEFAULE_VOLUME; + volume = app_var.wtone_volume; + break; +#endif +#if (APP_AUDIO_STATE_WTONE_BY_MUSIC == 1) + app_var.wtone_volume = app_var.music_volume; +#endif + app_var.wtone_volume += value; + if (app_var.wtone_volume > get_max_sys_vol()) { + app_var.wtone_volume = get_max_sys_vol(); + } + volume = app_var.wtone_volume; +#if (APP_AUDIO_STATE_WTONE_BY_MUSIC == 1) + app_var.music_volume = app_var.wtone_volume; +#endif + break; + default: + return; + } + + app_audio_set_volume(__this->state, volume, 1); +} + +void app_audio_volume_down(u8 value) +{ + s16 volume = 0; + switch (__this->state) { + case APP_AUDIO_STATE_IDLE: + case APP_AUDIO_STATE_MUSIC: + case APP_AUDIO_STATE_LINEIN: + app_var.music_volume -= value; + if (app_var.music_volume < 0) { + app_var.music_volume = 0; + } + volume = app_var.music_volume; + break; + case APP_AUDIO_STATE_CALL: + app_var.call_volume -= value; + if (app_var.call_volume < 0) { + app_var.call_volume = 0; + } + volume = app_var.call_volume; +#if TCFG_CALL_USE_DIGITAL_VOLUME + audio_digital_vol_set(volume); + return; +#endif + break; + case APP_AUDIO_STATE_WTONE: +#if (TONE_MODE_DEFAULE_VOLUME != 0) + app_var.wtone_volume = TONE_MODE_DEFAULE_VOLUME; + volume = app_var.wtone_volume; + break; +#endif +#if (APP_AUDIO_STATE_WTONE_BY_MUSIC == 1) + app_var.wtone_volume = app_var.music_volume; +#endif + app_var.wtone_volume -= value; + if (app_var.wtone_volume < 0) { + app_var.wtone_volume = 0; + } + volume = app_var.wtone_volume; +#if (APP_AUDIO_STATE_WTONE_BY_MUSIC == 1) + app_var.music_volume = app_var.wtone_volume; +#endif + break; + default: + return; + } + + app_audio_set_volume(__this->state, volume, 1); +} + +void app_audio_state_switch(u8 state, s16 max_volume) +{ + r_printf("audio state old:%s,new:%s,vol:%d\n", audio_state[__this->state], audio_state[state], max_volume); + + __this->prev_state = __this->state; + __this->state = state; +#if TCFG_CALL_USE_DIGITAL_VOLUME + if (__this->state == APP_AUDIO_STATE_CALL) { + audio_digital_vol_open(max_volume, max_volume, 4); + /*调数字音量的时候,模拟音量定最大*/ + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0) | BIT(1), max_volume, 1); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0) | BIT(1), DEFAULT_DIGTAL_VOLUME, 1); + } +#else + +#if (SYS_VOL_TYPE ==VOL_TYPE_DIGGROUP) + u8 dac_connect_mode = app_audio_output_mode_get(); + switch (dac_connect_mode) { + case DAC_OUTPUT_MONO_L : + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0), MAX_ANA_VOL, 1); + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(1), 0, 1); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0) | BIT(1), 16384, 1); + break; + case DAC_OUTPUT_MONO_R : + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(1), MAX_ANA_VOL, 1); + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0), 0, 1); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0) | BIT(1), 16384, 1); + break; + case DAC_OUTPUT_LR: + case DAC_OUTPUT_MONO_LR_DIFF: + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0) | BIT(1), MAX_ANA_VOL, 1); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0) | BIT(1), 16384, 1); + break; + default : + audio_dac_vol_set(TYPE_DAC_AGAIN, BIT(0) | BIT(1) | BIT(2) | BIT(3), MAX_ANA_VOL, 1); + audio_dac_vol_set(TYPE_DAC_DGAIN, BIT(0) | BIT(1) | BIT(2) | BIT(3), 16384, 1); + } +#endif + app_audio_set_volume(__this->state, app_audio_get_volume(__this->state), 1); + +#endif + + /*限制最大音量*/ +#if (SYS_VOL_TYPE == 0) +#elif (SYS_VOL_TYPE == 3) +#else + __this->digital_volume_fl = DEFAULT_DIGTAL_VOLUME; + __this->digital_volume_fr = __this->digital_volume_fl; + __this->digital_volume_rl = __this->digital_volume_fl; + __this->digital_volume_rr = __this->digital_volume_fl; +#endif + __this->max_volume[state] = max_volume; + +#if (SYS_VOL_TYPE == 2) + if (__this->state == APP_AUDIO_STATE_CALL) { + __this->max_volume[state] = 15; + } +#endif +} + + + +void app_audio_state_exit(u8 state) +{ +#if TCFG_CALL_USE_DIGITAL_VOLUME + if (__this->state == APP_AUDIO_STATE_CALL) { + audio_digital_vol_close(); + } +#endif + + r_printf("audio state now:%s,prev:%s\n", audio_state[__this->state], audio_state[__this->prev_state]); + if (state == __this->state) { + __this->state = __this->prev_state; + __this->prev_state = APP_AUDIO_STATE_IDLE; + } else if (state == __this->prev_state) { + __this->prev_state = APP_AUDIO_STATE_IDLE; + } + app_audio_set_volume(__this->state, app_audio_get_volume(__this->state), 1); +} +u8 app_audio_get_state(void) +{ + return __this->state; +} + +s16 app_audio_get_max_volume(void) +{ + if (__this->state == APP_AUDIO_STATE_IDLE) { + return get_max_sys_vol(); + } + return __this->max_volume[__this->state]; +} + +void app_audio_set_mix_volume(u8 front_volume, u8 back_volume) +{ + /*set_audio_device_volume(AUDIO_MIX_FRONT_VOL, front_volume); + set_audio_device_volume(AUDIO_MIX_BACK_VOL, back_volume);*/ +} + +void dac_power_on(void) +{ + log_info(">>>dac_power_on:%d", __this->ref.counter); + if (atomic_inc_return(&__this->ref) == 1) { + audio_dac_open(&dac_hdl); + } +} + +void dac_sniff_power_off(void) +{ + audio_dac_close(&dac_hdl); +} + +void dac_power_off(void) +{ + /* log_info(">>>dac_power_off:%d", __this->ref.counter); */ + /* if (atomic_dec_return(&__this->ref)) { */ + /* return; */ + /* } */ +#if 1 + app_audio_mute(AUDIO_MUTE_DEFAULT); + if (dac_hdl.vol_l || dac_hdl.vol_r) { + u8 fade_time = dac_hdl.vol_l * 2 / 10 + 1; + os_time_dly(fade_time); + printf("fade_time:%d ms", fade_time); + } +#endif + audio_dac_close(&dac_hdl); +} + +//#define LADC_CAPLESS_INFO_DEBUG +#ifdef LADC_CAPLESS_INFO_DEBUG +/* + * adcdso:正负1000之内 + * dacr32(正常范围:稳定在正负28000之内) + */ +void ladc_capless_info(s16 adcdso, s32 dacr32, s32 pout, s32 tmps8) +{ + printf("[%d, %d, %d, %d]\n", adcdso, dacr32, pout, tmps8); +} +#endif + +static void mic_capless_feedback_toggle(u8 toggle); + +#define LADC_CAPLESS_ADJUST_SAVE +#ifdef LADC_CAPLESS_ADJUST_SAVE +#define DIFF_RANGE 50 +#define CFG_DIFF_RANGE 200 +#define CHECK_INTERVAL 7 +#define DACR32_DEFAULT 32767 + +#define MIC_CAPLESS_ADJUST_BUD_DEFAULT 0 +#define MIC_CAPLESS_ADJUST_BUD 100 +/*不支持自动校准,使用快速收敛*/ +#if TCFG_MC_BIAS_AUTO_ADJUST +u8 mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD_DEFAULT; +#else +u8 mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD; +#endif + +s16 read_capless_DTB(void) +{ + s16 dacr32 = 32767; + int ret = syscfg_read(CFG_DAC_DTB, &dacr32, 2); + printf("cfg DAC_DTB:%d,ret = %d\n", dacr32, ret); + /*没有记忆值,使用默认值*/ + if (ret != 2) { + /*没有收敛值的时候,使用快速收敛*/ + //printf("DAC_DTB NULL,use fast feedback"); + mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD; + /* + *未初始化状态,返回默认收敛值。可以通过修改默认收敛值,使其 + *接近最终收敛值,来加快预收敛时间。比如最终收敛值是-2500,则 + *可以把默认收敛值设置成-2000左右,因为不同的样机稍微有点小差 + *异,所以这个值不用那么精确,只要差不多就行了。 + */ + return 32767; + } + return dacr32; +} + +s16 read_vm_capless_DTB(void) +{ + s16 vm_dacr32 = 32767; + int ret = syscfg_read(CFG_DAC_DTB, &vm_dacr32, 2); + printf("vm DAC_DTB:%d,ret = %d\n", vm_dacr32, ret); + if (ret != 2) { + return DACR32_DEFAULT; + } + return vm_dacr32; +} + +s16 save_dacr32 = DACR32_DEFAULT; +static u8 adjust_complete = 0; +static u16 dtb_step_limit = 0; /*dtb收敛步进限制*/ +void save_capless_DTB() +{ + s16 diff; + //printf("save_capless_DTB\n"); + if ((save_dacr32 != DACR32_DEFAULT) && adjust_complete) { + /*比较是否需要更新配置*/ + s16 cfg_dacr32 = read_vm_capless_DTB(); + adjust_complete = 0; + diff = save_dacr32 - cfg_dacr32; + if ((cfg_dacr32 == DACR32_DEFAULT) || ((diff < -CFG_DIFF_RANGE) || (diff > CFG_DIFF_RANGE))) { + log_info("dacr32 write:%d\n", save_dacr32); + syscfg_write(CFG_DAC_DTB, &save_dacr32, 2); + + /* s16 tmp_dacr32; + syscfg_read(CFG_DAC_DTB,&tmp_dacr32,2); + printf("dacr32 read:%d\n",tmp_dacr32); */ + } else { + log_info("dacr32 need't update:%d,diff:%d\n", save_dacr32, diff); + } + } else { + log_info("dacr32 adjust uncomplete:%d,complete:%d\n", save_dacr32, adjust_complete); + } +} + +void ladc_capless_adjust_post(s32 dacr32, u8 begin) +{ + static s32 last_dacr32 = 0; + static u8 check_cnt = 0; + + s32 dacr32_diff; + + /*adjust_begin,clear*/ + if (begin) { + printf("dtb_step_limit = %d\n", dtb_step_limit); + last_dacr32 = 0; + adjust_complete = 0; + check_cnt = 0; + save_dacr32 = DACR32_DEFAULT; + return; + } + +#if TCFG_MC_CONVERGE_TRACE + printf("<%d>", dacr32); +#endif/*TCFG_MC_CONVERGE_TRACE*/ + if (adjust_complete == 0) { + if (++check_cnt > CHECK_INTERVAL) { + check_cnt = 0; + dacr32_diff = dacr32 - last_dacr32; + //printf("[capless:%d-%d-%d]",dacr32,last_dacr32,dacr32_diff); + last_dacr32 = dacr32; + if (adjust_complete == 0) { + save_dacr32 = dacr32; + } + /*调整稳定*/ + if ((dacr32_diff > -DIFF_RANGE) && (dacr32_diff < DIFF_RANGE)) { + log_info("adjust_OK:%d\n", dacr32); + adjust_complete = 1; +#if TCFG_MC_BIAS_AUTO_ADJUST + mic_capless_feedback_toggle(0); +#endif + } + } + } +} +#endif + + +#if 0 +/* + *写到dac buf的数据接口 + */ +void audio_write_data_hook(void *data, u32 len) +{ + +} +#endif + +/* + *dac快速校准 + */ +//#define DAC_TRIM_FAST_EN +#ifdef DAC_TRIM_FAST_EN +u8 dac_trim_fast_en() +{ + return 1; +} +#endif + +/* + *自定义dac上电延时时间,具体延时多久应通过示波器测量 + */ +#if 1 +void dac_power_on_delay() +{ +#if TCFG_MC_BIAS_AUTO_ADJUST + void mic_capless_auto_adjust_init(); + mic_capless_auto_adjust_init(); +#endif + os_time_dly(50); +} +#endif + +/* + *capless模式一开始不要的数据包数量 + */ +u16 get_ladc_capless_dump_num(void) +{ + return 10; +} + +/* + *mic省电容模式自动收敛 + */ +u8 mic_capless_feedback_sw = 0; +static u8 audio_mc_idle_query(void) +{ + return (mic_capless_feedback_sw ? 0 : 1); +} +REGISTER_LP_TARGET(audio_mc_device_lp_target) = { + .name = "audio_mc_device", + .is_idle = audio_mc_idle_query, +}; + +/*快调慢调边界*/ +u16 get_ladc_capless_bud(void) +{ + //printf("mc_bud:%d",mic_capless_adjust_bud); + return mic_capless_adjust_bud; +} + +extern int audio_adc_mic_init(u16 sr); +extern void audio_adc_mic_exit(void); +int audio_mic_capless_feedback_control(u8 en, u16 sr) +{ + int ret = 0; + if (en) { + ret = audio_adc_mic_init(sr); + } else { + audio_adc_mic_exit(); + } + return ret; +} + +OS_SEM mc_sem; +/*收敛的前提是偏置电压合法*/ +static void mic_capless_feedback_toggle(u8 toggle) +{ + int ret = 0; + log_info("mic_capless_feedback_toggle:%d-%d\n", mic_capless_feedback_sw, toggle); + if (toggle && (mic_capless_feedback_sw == 0)) { + mic_capless_feedback_sw = 1; + ret = audio_mic_capless_feedback_control(1, 32000); + if (ret == 0) { + mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD; + } + os_sem_create(&mc_sem, 0); + } else if (mic_capless_feedback_sw) { + os_sem_post(&mc_sem); + mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD_DEFAULT; + } else { + log_info("Nothing to do\n"); + } +} + +extern struct adc_platform_data adc_data; + +#if TCFG_MC_BIAS_AUTO_ADJUST +static const u8 mic_bias_tab[] = {0, 20, 12, 28, 4, 18, 10, 26, 2, 22, 14, 30, 17, 21, 6, 25, 29, 27, 31, 5, 3, 7}; +extern void delay_2ms(int cnt); +extern void wdt_clear(void); +extern void mic_analog_init(u8 mic_ldo_vsel, u8 mic_bias); +extern void mic_analog_close(struct adc_platform_data *pd); +void mic_capless_auto_adjust_init() +{ + if (adc_data.mic_capless == 0) { + return; + } + log_info("mic_capless_bias_adjust_init:%d-%d\n", adc_data.mic_ldo_vsel, adc_data.mic_bias_res); + mic_analog_init(adc_data.mic_ldo_vsel, adc_data.mic_bias_res); +} + +void mic_capless_auto_adjust_exit() +{ + if (adc_data.mic_capless == 0) { + return; + } + log_info("mic_capless_bias_adjust_exit\n"); + mic_analog_close(&adc_data); +} + +/*AC695x系列只支持高压模式*/ +#define MIC_BIAS_HIGH_UPPER_LIMIT 190 /*高压上限:1.90v*/ +#define MIC_BIAS_HIGH_LOWER_LIMIT 140 /*高压下限:1.40v*/ + +#define ADC_MIC_IO IO_PORTC_06 +#define ADC_MIC_CH AD_CH_PC6 +#define MIC_BIAS_RSEL(x) SFR(JL_ANA->ADA_CON2, 21, 5, x) +#define MIC_LDO_SEL(x) SFR(JL_ANA->ADA_CON2, 16, 2, x) + + +/* + *return -1:非省电容模式 + *return -2:校准失败 + *return 0:默认值合法,不用校准 + *return 1:默认值非法,启动校准 + */ +s8 mic_capless_auto_adjust(void) +{ + u16 mic_bias_val = 0; + u8 mic_bias_idx = adc_data.mic_bias_res; + u8 mic_bias_compare = 0; + u16 bias_upper_limit = MIC_BIAS_HIGH_UPPER_LIMIT; + u16 bias_lower_limit = MIC_BIAS_HIGH_LOWER_LIMIT; + s8 ret = 0; + u8 err_cnt = 0; + u8 mic_ldo_idx = 0; + + //printf("mic_capless_bias_adjust:%d\n",adc_data.mic_capless); + + if (adc_data.mic_capless == 0) { + return -1; + } + + log_info("mic_bias idx:%d,rsel:%d\n", mic_bias_idx, mic_bias_tab[mic_bias_idx]); + + /*采样MIC_port(PC6)的偏置电压值*/ + JL_PORTC->DIE &= ~BIT(6); + JL_PORTC->DIR |= BIT(6); + JL_PORTC->PU &= ~BIT(6); + JL_PORTC->PD &= ~BIT(6); + adc_add_sample_ch(ADC_MIC_CH); + +#if 0 + /* + *调试使用 + *如果mic的偏置电压mic_bias_val稳定,则表示延时足够,否则加大延时知道电压值稳定 + */ + while (1) { + wdt_clear(); + MIC_BIAS_RSEL(mic_bias_tab[mic_bias_idx]); + delay_2ms(50);//延时等待偏置电压稳定 + mic_bias_val = adc_get_voltage(ADC_MIC_CH) / 10; + log_info("mic_bias_val:%d,idx:%d,rsel:%d\n", mic_bias_val, mic_bias_idx, mic_bias_tab[mic_bias_idx]); + } +#endif + + while (1) { + wdt_clear(); + MIC_BIAS_RSEL(mic_bias_tab[mic_bias_idx]); + delay_2ms(50); + + mic_bias_val = adc_get_voltage(ADC_MIC_CH) / 10; + log_info("mic_bias_val:%d,idx:%d,rsel:%d\n", mic_bias_val, mic_bias_idx, mic_bias_tab[mic_bias_idx]); + + if (mic_bias_val < bias_lower_limit) { + /*电压偏小,调小内部上拉偏置*/ + mic_bias_compare |= BIT(0); + mic_bias_idx++; + if (mic_bias_idx >= sizeof(mic_bias_tab)) { + log_error("mic_bias_auto_adjust faild 0\n"); + /*校准失败,使用快速收敛*/ + //mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD; + ret = -2; + //break; + } + } else if (mic_bias_val > bias_upper_limit) { + /*电压偏大,调大内部上拉偏置*/ + mic_bias_compare |= BIT(1); + if (mic_bias_idx) { + mic_bias_idx--; + } else { + log_error("mic_bias_auto_adjust faild 1\n"); + /*校准失败,使用快速收敛*/ + //mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD; + ret = -2; + //break; + } + } else { + if (mic_bias_compare) { + /*超出范围,调整过的值,保存*/ + adc_data.mic_bias_res = mic_bias_idx; + log_info("mic_bias_adjust ok,idx:%d,rsel:%d\n", mic_bias_idx, mic_bias_tab[mic_bias_idx]); + /*记住校准过的值*/ + ret = syscfg_write(CFG_MC_BIAS, &adc_data.mic_bias_res, 1); + log_info("mic_bias_adjust save ret = %d\n", ret); + ret = 1; + } + + /*原本的MICLDO档位不合适,保存新的MICLDO档位*/ + if (err_cnt) { + adc_data.mic_ldo_vsel = mic_ldo_idx; + log_info("mic_ldo_vsel fix:%d\n", adc_data.mic_ldo_vsel); + //log_info("mic_bias:%d,idx:%d\n",adc_data.mic_bias_res,mic_bias_idx); + ret = syscfg_write(CFG_MIC_LDO_VSEL, &mic_ldo_idx, 1); + log_info("mic_ldo_vsel save ret = %d\n", ret); + ret = 1; + } + log_info("mic_bias valid:%d,idx:%d,res:%d\n", mic_bias_val, mic_bias_idx, mic_bias_tab[mic_bias_idx]); + break; + } + + /* + *当前MICLDO分不出合适的偏置电压 + * 选择1、修改MICLDO档位,重新校准 + * 选择2、直接退出,跳出自动校准 + */ + if ((mic_bias_compare == (BIT(0) | BIT(1))) || (ret == -2)) { + log_info("mic_bias_trim err,adjust micldo vsel\n"); + ret = 0; +#if 1 /*选择1*/ + /*从0开始遍历查询*/ + if (err_cnt) { + mic_ldo_idx++; + } + err_cnt++; + /*跳过默认的ldo电压档*/ + if (mic_ldo_idx == adc_data.mic_ldo_vsel) { + mic_ldo_idx++; + } + /*遍历结束,没有合适的MICLDO电压档*/ + if (mic_ldo_idx > 3) { + log_info("mic_bias_adjust tomeout\n"); + mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD; + ret = -3; + break; + } + log_info("mic_ldo_idx:%d", mic_ldo_idx); + MIC_LDO_SEL(mic_ldo_idx); + /*修改MICLDO电压档,等待电压稳定*/ + os_time_dly(20); + /*复位偏置电阻档位*/ + mic_bias_idx = adc_data.mic_bias_res; + /*复位校准标志位*/ + mic_bias_compare = 0; +#else /*选择2*/ + log_info("mic_bias_trim err,break loop\n"); + mic_capless_adjust_bud = MIC_CAPLESS_ADJUST_BUD; + ret = -3; + break; +#endif + } + } + mic_capless_auto_adjust_exit(); + return ret; +} +#endif + +/* + *检查mic偏置是否需要校准,以下情况需要重新校准: + *1、power on reset + *2、vm被擦除 + *3、每次开机都校准 + */ +extern u8 power_reset_src; +u8 mc_bias_adjust_check() +{ +#if(TCFG_MC_BIAS_AUTO_ADJUST == MC_BIAS_ADJUST_ALWAYS) + return 1; +#elif (TCFG_MC_BIAS_AUTO_ADJUST == MC_BIAS_ADJUST_ONE) + return 0; +#endif + u8 por_flag = 0; + int ret = syscfg_read(CFG_POR_FLAG, &por_flag, 1); + if (ret == 1) { + if (por_flag == 0xA5) { + log_info("power on reset 1"); + por_flag = 0; + ret = syscfg_write(CFG_POR_FLAG, &por_flag, 1); + return 1; + } + } + if (power_reset_src & BIT(0)) { + log_info("power on reset 2"); + return 1; + } + if (read_vm_capless_DTB() == DACR32_DEFAULT) { + log_info("vm format"); + return 1; + } + + return 0; +} + +#if TCFG_MC_DTB_STEP_LIMIT +/*获取省电容mic收敛信息配置*/ +int get_mc_dtb_step_limit(void) +{ + return dtb_step_limit; +} +#endif /*TCFG_MC_DTB_STEP_LIMIT*/ + +/* + *pos = 1:dac trim begin + *pos = 2:dac trim end + *pos = 3:dac已经trim过(开机) + *pos = 4:dac已经读取过变量(过程) + *pos = 5:dac已经trim过(开机,dac模块初始化) + */ +extern void audio_dac2micbias_en(struct audio_dac_hdl *dac, u8 en); +void _audio_dac_trim_hook(u8 pos) +{ +#if TCFG_MC_BIAS_AUTO_ADJUST + int ret = 0; + log_info("dac_trim_hook:%d\n", pos); + if ((adc_data.mic_capless == 0) || (pos == 0xFF)) { + return; + } + + if (pos == 1) { + ret = mic_capless_auto_adjust(); + if (ret >= 0) { + mic_capless_feedback_toggle(1); + } else { + /*校准出错的时候不做预收敛*/ + log_info("auto_adjust err:%d\n", ret); + } + return; + } else if (pos == 2) { + if (mic_capless_feedback_sw) { + ret = os_sem_pend(&mc_sem, 250); + audio_mic_capless_feedback_control(0, 16000); + if (ret == OS_TIMEOUT) { + log_info("mc_trim1 timeout!\n"); + } else { + dtb_step_limit = TCFG_MC_DTB_STEP_LIMIT; + } + } else { + log_info("auto_feedback disable"); + } + } else if (pos == 5) { + if (mc_bias_adjust_check()) { + //printf("MC_BIAS_ADJUST..."); + void mic_capless_auto_adjust_init(); + mic_capless_auto_adjust_init(); + os_time_dly(25); + ret = mic_capless_auto_adjust(); + /* + *预收敛条件: + *1、开机检查发现mic的偏置非法,则校准回来,同时重新收敛,比如中途更换mic头的情况 + *2、收敛值丢失(vm被擦除),重新收敛一次(前提是校准成功) + */ + if ((ret == 1) || ((ret == 0) && (read_vm_capless_DTB() == DACR32_DEFAULT))) { + audio_dac2micbias_en(&dac_hdl, 1); + mic_capless_feedback_toggle(1); + ret = os_sem_pend(&mc_sem, 250); + audio_mic_capless_feedback_control(0, 16000); + audio_dac2micbias_en(&dac_hdl, 0); + if (ret == OS_TIMEOUT) { + log_info("mc_trim2 timeout!\n"); + } else { + dtb_step_limit = TCFG_MC_DTB_STEP_LIMIT; + } + } else { + log_info("auto_adjust err:%d\n", ret); + if (ret == 0) { + dtb_step_limit = TCFG_MC_DTB_STEP_LIMIT; + } + } + } else { + log_info("MC_BIAS_OK...\n"); + dtb_step_limit = TCFG_MC_DTB_STEP_LIMIT; + } + } + mic_capless_feedback_sw = 0; +#endif/*TCFG_MC_BIAS_AUTO_ADJUST*/ +} + + + +////////////////////////////////// audio_output_api ////////////////////////////////////////////// +#if 1 + +void _audio_dac_irq_hook(void) +{ + /* putbyte('d'); */ + extern struct audio_stream_dac_out *dac_last; + audio_stream_resume(&dac_last->entry); +} + +void _audio_adc_irq_hook(void) +{ + /* putbyte('a'); */ + extern struct audio_adc_hdl adc_hdl; + audio_adc_irq_handler(&adc_hdl); +} + + + +/******************************************************* +* Function name : app_audio_output_init +* Description : 音频输出设备初始化 +* Return : None +********************* -HB ******************************/ +void app_audio_output_init(void) +{ +#if (AUDIO_OUTPUT_INCLUDE_DAC|| TCFG_AUDIO_ADC_ENABLE) + audio_dac_init(&dac_hdl, &dac_data); +#endif + +#if AUDIO_OUTPUT_INCLUDE_DAC // AUDIO_OUTPUT_ONLY_DAC + s16 dacr32 = read_capless_DTB(); + + audio_dac_set_capless_DTB(&dac_hdl, dacr32); + + audio_dac_set_buff(&dac_hdl, dac_buff, sizeof(dac_buff)); + + struct audio_dac_trim dac_trim = {0}; + int len = syscfg_read(CFG_DAC_TRIM_INFO, (void *)&dac_trim, sizeof(dac_trim)); + if (len != sizeof(dac_trim) || dac_trim.left == 0 || dac_trim.right == 0) { + audio_dac_do_trim(&dac_hdl, &dac_trim, 0); + syscfg_write(CFG_DAC_TRIM_INFO, (void *)&dac_trim, sizeof(dac_trim)); + } else { + _audio_dac_trim_hook(5); + } + + audio_dac_set_trim_value(&dac_hdl, &dac_trim); + audio_dac_set_delay_time(&dac_hdl, 30, 50); +#endif +} + +/******************************************************* +* Function name : app_audio_output_sync_buff_init +* Description : 设置音频输出设备同步功能 buf +* Parameter : +* @sync_buff buf 起始地址 +* @len buf 长度 +* Return : None +********************* -HB ******************************/ +void app_audio_output_sync_buff_init(void *sync_buff, int len) +{ +#if AUDIO_OUTPUT_INCLUDE_DAC + /*音频同步DA端buffer设置*/ + /*audio_dac_set_sync_buff(&dac_hdl, sync_buff, len);*/ +#endif +} + + +/******************************************************* +* Function name : app_audio_output_samplerate_select +* Description : 将输入采样率与输出采样率进行匹配对比 +* Parameter : +* @sample_rate 输入采样率 +* @high: 0 - 低一级采样率,1 - 高一级采样率 +* Return : 匹配后的采样率 +********************* -HB ******************************/ +int app_audio_output_samplerate_select(u32 sample_rate, u8 high) +{ + return audio_dac_sample_rate_select(&dac_hdl, sample_rate, high); +} + +/******************************************************* +* Function name : app_audio_output_samplerate_set +* Description : 设置音频输出设备的采样率 +* Parameter : +* @sample_rate 采样率 +* Return : 0 success, other fail +********************* -HB ******************************/ +int app_audio_output_samplerate_set(int sample_rate) +{ +#if AUDIO_OUTPUT_INCLUDE_DAC + return audio_dac_set_sample_rate(&dac_hdl, sample_rate); +#endif + return 0; +} + +/******************************************************* +* Function name : app_audio_output_samplerate_get +* Description : 获取音频输出设备的采样率 +* Return : 音频输出设备的采样率 +********************* -HB ******************************/ +int app_audio_output_samplerate_get(void) +{ +#if AUDIO_OUTPUT_INCLUDE_DAC + return audio_dac_get_sample_rate(&dac_hdl); +#endif + return 0; +} + +/******************************************************* +* Function name : app_audio_output_mode_get +* Description : 获取当前硬件输出模式 +* Return : 输出模式 +********************* -HB ******************************/ +int app_audio_output_mode_get(void) +{ +#if AUDIO_OUTPUT_INCLUDE_DAC + return audio_dac_get_pd_output(&dac_hdl); +#endif + return 0; +} + +/******************************************************* +* Function name : app_audio_output_mode_set +* Description : 设置当前硬件输出模式 +* Return : 0 success, other fail +********************* -HB ******************************/ +int app_audio_output_mode_set(u8 output) +{ +#if AUDIO_OUTPUT_INCLUDE_DAC + return audio_dac_set_pd_output(&dac_hdl, output); +#endif + return 0; +} + +/******************************************************* +* Function name : app_audio_output_channel_get +* Description : 获取音频输出设备输出通道数 +* Return : 通道数 +********************* -HB ******************************/ +int app_audio_output_channel_get(void) +{ +#if AUDIO_OUTPUT_INCLUDE_DAC + return audio_dac_get_channel(&dac_hdl); +#endif + return 0; +} + +/******************************************************* +* Function name : app_audio_output_channel_set +* Description : 设置音频输出设备输出通道数 +* Parameter : +* @channel 通道数 +* Return : 0 success, other fail +********************* -HB ******************************/ +int app_audio_output_channel_set(u8 channel) +{ +#if AUDIO_OUTPUT_INCLUDE_DAC + return audio_dac_set_channel(&dac_hdl, channel); +#endif + return 0; +} + +#if AUDIO_OUTPUT_DAC_AND_IIS +static u16 dac_remain_len = 0; +static u16 iis_remain_len = 0; +#endif +/******************************************************* +* Function name : app_audio_output_write +* Description : 向音频输出设备写入需要输出的音频数据 +* Parameter : +* @buf 写入音频数据的起始地址 +* @len 写入音频数据的长度 +* Return : 成功写入的长度 +********************* -HB ******************************/ +int app_audio_output_write(void *buf, int len) +{ +#if 0 +#if AUDIO_OUTPUT_ONLY_DAC + return audio_dac_write(&default_dac, buf, len); +#elif AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM + return fm_emitter_cbuf_write(buf, len); +#elif AUDIO_OUTPUT_DAC_AND_IIS + int wlen1 = 0; + int wlen2 = 0; + static u8 output_order = 0; + if (dac_remain_len) { + wlen1 = audio_dac_write(&default_dac, buf, dac_remain_len); + dac_remain_len -= wlen1; + return wlen1; + } + + if (iis_remain_len) { + wlen2 = audio_link_write_stereodata(buf, iis_remain_len, TCFG_IIS_OUTPUT_PORT); + iis_remain_len -= wlen2; + return wlen2; + } + + if (output_order) { //调换输出顺序做输出均衡 + wlen2 = audio_link_write_stereodata(buf, len, TCFG_IIS_OUTPUT_PORT); + wlen1 = audio_dac_write(&default_dac, buf, len); + } else { + wlen1 = audio_dac_write(&default_dac, buf, len); + wlen2 = audio_link_write_stereodata(buf, len, TCFG_IIS_OUTPUT_PORT); + } + if (wlen1 == wlen2) { + return wlen1; + } else { + if (wlen1 > wlen2) { + output_order = 0; + iis_remain_len = wlen1 - wlen2; + return wlen2; + } else { + output_order = 1; + dac_remain_len = wlen2 - wlen1; + return wlen1; + } + } +#endif +#endif + return len; +} + + +/******************************************************* +* Function name : app_audio_output_start +* Description : 音频输出设备输出打开 +* Return : 0 success, other fail +********************* -HB ******************************/ +int app_audio_output_start(void) +{ +#if AUDIO_OUTPUT_INCLUDE_DAC + audio_dac_start(&dac_hdl); +#endif + +#if AUDIO_OUTPUT_DAC_AND_IIS + dac_remain_len = 0; + iis_remain_len = 0; +#endif + return 0; +} + +/******************************************************* +* Function name : app_audio_output_stop +* Description : 音频输出设备输出停止 +* Return : 0 success, other fail +********************* -HB ******************************/ +int app_audio_output_stop(void) +{ +#if AUDIO_OUTPUT_INCLUDE_DAC + + return audio_dac_channel_stop(&default_dac); + +#endif + return 0; +} + +/******************************************************* +* Function name : app_audio_output_reset +* Description : 音频输出设备重启 +* Parameter : +* @msecs 重启时间 ms +* Return : 0 success, other fail +********************* -HB ******************************/ +int app_audio_output_reset(u32 msecs) +{ +#if AUDIO_OUTPUT_INCLUDE_DAC + audio_dac_sound_reset(&dac_hdl, msecs); +#endif + return 0; +} + +/******************************************************* +* Function name : app_audio_output_get_cur_buf_points +* Description : 获取当前音频输出buf还可以输出的点数 +* Parameter : +* Return : 还可以输出的点数 +********************* -HB ******************************/ +int app_audio_output_get_cur_buf_points(void) +{ +#if AUDIO_OUTPUT_INCLUDE_DAC + /*return audio_dac_buf_pcm_number(&dac_hdl) >> PCM_PHASE_BIT;*/ +#endif + return 0; +} + +int app_audio_output_ch_analog_gain_set(u8 ch, u8 again) +{ +#if AUDIO_OUTPUT_INCLUDE_DAC + return audio_dac_ch_analog_gain_set(&dac_hdl, ch, again); +#endif + return 0; +} + +int app_audio_output_state_get(void) +{ +#if AUDIO_OUTPUT_INCLUDE_DAC + return audio_dac_get_status(&dac_hdl); +#endif + return 0; +} + +void app_audio_output_ch_mute(u8 ch, u8 mute) +{ +#if AUDIO_OUTPUT_INCLUDE_DAC + audio_dac_ch_mute(&dac_hdl, ch, mute); +#endif +} + +int audio_output_buf_time(void) +{ +#if AUDIO_OUTPUT_INCLUDE_DAC + return audio_dac_data_time(&dac_hdl); +#endif + return 0; +} + +int audio_output_dev_is_working(void) +{ +#if 0 +#if AUDIO_OUTPUT_ONLY_DAC + return audio_dac_is_working(&dac_hdl); +#endif +#if AUDIO_OUTPUT_DAC_AND_IIS + return audio_dac_is_working(&dac_hdl) && audio_iis_is_working(&iis_hdl); +#endif +#endif + return 1; + +} + +int audio_output_sync_start(void) +{ + + return 0; +} + +int audio_output_sync_stop(void) +{ + return 0; +} + +#endif + +void audio_adda_dump(void) //打印所有的dac,adc寄存器 +{ + printf("DAC_VL0:%x", JL_AUDIO->DAC_VL0); + printf("DAC_TM0:%x", JL_AUDIO->DAC_TM0); + printf("DAC_DTB:%x", JL_AUDIO->DAC_DTB); + printf("DAC_CON:%x", JL_AUDIO->DAC_CON); + printf("ADC_CON:%x", JL_AUDIO->ADC_CON); + printf("DAC RES: DA0:0x%x DA1:0x%x DA2:0x%x DA3:0x%x ,ADC RES:ADA0:0X%x ADA1:0X%x ADA2:0X%x ADA3:0X%x\n", \ + JL_ANA->DAA_CON0, JL_ANA->DAA_CON1, JL_ANA->DAA_CON2, JL_ANA->DAA_CON3, \ + JL_ANA->ADA_CON0, JL_ANA->ADA_CON1, JL_ANA->ADA_CON2, JL_ANA->ADA_CON3); +} + +void audio_adda_gain_dump(void)//打印所有adc,dac的增益 +{ + u8 dac_again_fl = JL_ANA->DAA_CON1 & 0x1F; + u8 dac_again_fr = (JL_ANA->DAA_CON1 >> 5) & 0x1F; + u8 dac_again_rl = (JL_ANA->DAA_CON1 >> 10) & 0x1F; + u8 dac_again_rr = (JL_ANA->DAA_CON1 >> 15) & 0x1F; + + + u32 dac_dgain_fl = JL_AUDIO->DAC_VL0 & 0xFFFF; + u32 dac_dgain_fr = (JL_AUDIO->DAC_VL0 >> 16) & 0xFFFF; + u32 dac_dgain_rl = JL_AUDIO->DAC_VL1 & 0xFFFF; + u32 dac_dgain_rr = (JL_AUDIO->DAC_VL1 >> 16) & 0xFFFF; + + + u8 mic0_gain = (JL_ANA->ADA_CON0 >> 8) & 0x1F; + u8 mic0_db = (JL_ANA->ADA_CON4 >> 29) & 0x1; //0db还是6db + + u8 linein_r_gain = (JL_ANA->ADA_CON0 >> 4) & 0xF; + u8 linein_l_gain = JL_ANA->ADA_CON0 & 0xF; + printf("MIC_G:%d,MIC_0_6:%d, linein_gain:%d,%d,DAC_AG:%d,%d,%d,%d,DAC_DG:%d,%d,%d,%d\n", mic0_gain, mic0_db, linein_l_gain, linein_r_gain, dac_again_fl, dac_again_fr, dac_again_rl, dac_again_rr, dac_dgain_fl, dac_dgain_fr, dac_dgain_rl, dac_dgain_rr); + +} + diff --git a/cpu/br23/audio_common/audio_fmtx.c b/cpu/br23/audio_common/audio_fmtx.c new file mode 100644 index 0000000..f656e23 --- /dev/null +++ b/cpu/br23/audio_common/audio_fmtx.c @@ -0,0 +1,264 @@ +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "app_config.h" +#include "circular_buf.h" +#include "audio_fmtx.h" +#include "fm_emitter/fm_emitter_manage.h" + +#if (TCFG_APP_FM_EMITTER_EN) + +#define FMTX_DEBUG_ENABLE 1 +#if FMTX_DEBUG_ENABLE +#define fmtx_debug printf +#else +#define fmtx_debug(...) +#endif + +#define FMTX_TX_BUF_LEN (4*1024) +struct _fmtx_output { + u32 in_sample_rate; + u32 out_sample_rate; + cbuffer_t cbuf; + u8 buf[FMTX_TX_BUF_LEN]; + struct audio_src_handle *hw_src; + struct audio_stream_entry entry; + int sr_cal_timer; + u32 points_total; + u32 cnt_total; + u8 ch : 4; + u8 flag : 1; + u8 need_resume : 1; +} *fmtx_output_hdl = NULL; + +static u32 fmtx_srI_last = 0; + + +static int audio_stream_fmtx_data_handler(struct audio_stream_entry *entry, struct audio_data_frame *in, struct audio_data_frame *out) + +{ + + if (fmtx_srI_last != in->sample_rate) { + fmtx_debug("in:%d ---%d\n", fmtx_srI_last, in->sample_rate); + audio_fmtx_output_set_srI(in->sample_rate); + } + + u32 len = audio_fmtx_output_write(in->data, in->data_len); + if (len != in->data_len) { + local_irq_disable(); + fmtx_output_hdl->need_resume = 1; + local_irq_enable(); + } + return len; +} + +static void audio_stream_fmtx_data_clear(struct audio_stream_entry *entry) +{ + cbuf_clear(&(fmtx_output_hdl->cbuf)); + fmtx_debug("fmtx clear\n"); +} + +static void audio_fmtx_src_irq_cb(void *hdl) +{ + if (fmtx_output_hdl) { + audio_stream_resume(&(fmtx_output_hdl->entry)); + } +} + +int audio_fmtx_src_output_handler(void *parm, s16 *data, int len) +{ + int wlen = fmtx_output_hdl->cbuf.total_len - fmtx_output_hdl->cbuf.data_len; + if (wlen > len) { + wlen = len; + } + wlen = cbuf_write(&(fmtx_output_hdl->cbuf), data, wlen); + if (wlen != len) { + local_irq_disable(); + fmtx_output_hdl->need_resume = 1; + local_irq_enable(); + } + return wlen; +} + +s16 ref_temp_buf[256]; +int audio_fmtx_output_write(s16 *data, u32 len) +{ + u32 wlen = 0; + if (fmtx_output_hdl) { + if (fmtx_output_hdl->hw_src) { + wlen = audio_src_resample_write(fmtx_output_hdl->hw_src, data, len); + if (bt_phone_dec_is_running()) { + for (int i = 0; i < (len >> 2); i++) { + ref_temp_buf[i] = data[2 * i] / 2 + data[2 * i + 1] / 2; + } + if (wlen) { + audio_aec_refbuf(ref_temp_buf, wlen / 2); + } + } + + } else { + wlen = fmtx_output_hdl->cbuf.total_len - fmtx_output_hdl->cbuf.data_len; + if (wlen > len) { + wlen = len; + } + wlen = cbuf_write(&(fmtx_output_hdl->cbuf), data, len); + } + if (wlen != len) { + local_irq_disable(); + fmtx_output_hdl->need_resume = 1; + local_irq_enable(); + } + } + return wlen; +} +void audio_fmtx_tx_isr(s16 *data, u32 len) +{ + u32 wlen = 0; + u32 rlen = 0; + if (fmtx_output_hdl) { + local_irq_disable(); + if (fmtx_output_hdl->need_resume) { + fmtx_output_hdl->need_resume = 0; + local_irq_enable(); + audio_stream_resume(&(fmtx_output_hdl->entry)); + } else { + local_irq_enable(); + } + + + fmtx_output_hdl->points_total += len >> 2; + + rlen = cbuf_get_data_len(&(fmtx_output_hdl->cbuf)); + if ((fmtx_output_hdl->flag == 0) && (rlen < (FMTX_TX_BUF_LEN / 2))) { + memset(data, 0x00, len); + return; + } + fmtx_output_hdl->flag = 1; + + if (rlen >= len) { + wlen = cbuf_read(&(fmtx_output_hdl->cbuf), data, len); + } else { + fmtx_debug("fmtx end\n"); + wlen = cbuf_read(&(fmtx_output_hdl->cbuf), data, rlen); + memset((u8 *)data + rlen, 0x00, len - rlen); + fmtx_output_hdl->flag = 0; + } + } +} + +void audio_fmtx_sr_cal_timer(void *param) +{ + if (fmtx_output_hdl) { + if (fmtx_output_hdl->cnt_total == 0) { + fmtx_output_hdl->points_total = fmtx_output_hdl->out_sample_rate * 1000; + fmtx_output_hdl->cnt_total = 999; + } + fmtx_output_hdl->cnt_total++; + fmtx_output_hdl->out_sample_rate = fmtx_output_hdl->points_total / fmtx_output_hdl->cnt_total; + + if ((fmtx_output_hdl->points_total > 0xFFF00000) \ + && ((fmtx_output_hdl->cnt_total % 2) == 0)) { + fmtx_output_hdl->points_total >>= 1; + fmtx_output_hdl->cnt_total >>= 1; + } + + + if (fmtx_output_hdl->hw_src && fmtx_output_hdl->out_sample_rate) { + /* fmtx_debug("fmtx cal:%d > %d\n", \ */ + /* fmtx_output_hdl->in_sample_rate, \ */ + /* fmtx_output_hdl->out_sample_rate); */ + audio_hw_src_set_rate(fmtx_output_hdl->hw_src, \ + fmtx_output_hdl->in_sample_rate, \ + fmtx_output_hdl->out_sample_rate); + } + } +} + +void audio_fmtx_output_set_srI(u32 sample_rate) +{ + fmtx_debug("audio_fmtx_output_set_srI %d\n", sample_rate); + fmtx_srI_last = sample_rate; + if (fmtx_output_hdl) { + fmtx_output_hdl->points_total = 0; + fmtx_output_hdl->cnt_total = 0; + fmtx_output_hdl->in_sample_rate = sample_rate; + if (fmtx_output_hdl->hw_src) { + fmtx_debug("fmtx set:%d > %d\n", \ + fmtx_output_hdl->in_sample_rate, \ + fmtx_output_hdl->out_sample_rate); + audio_hw_src_set_rate(fmtx_output_hdl->hw_src, \ + fmtx_output_hdl->in_sample_rate, \ + fmtx_output_hdl->out_sample_rate); + } + } +} + +void *audio_fmtx_output_start(u16 fre) +{ + if (fmtx_output_hdl == NULL) { + fmtx_debug("audio_fmtx_output_start\n"); + mem_stats(); + fmtx_output_hdl = zalloc(sizeof(struct _fmtx_output)); + if (fmtx_output_hdl == NULL) { + fmtx_debug("audio_fmtx_output_start malloc err !\n"); + return NULL; + } + /* clk_set("sys", 96 * 1000000L); */ + /* clk_set_en(0); */ + cbuf_init(&(fmtx_output_hdl->cbuf), fmtx_output_hdl->buf, FMTX_TX_BUF_LEN); + + fm_emitter_manage_init(fre, audio_fmtx_tx_isr); + fm_emitter_manage_start(); + + fmtx_output_hdl->in_sample_rate = fmtx_srI_last; + fmtx_output_hdl->out_sample_rate = 41667; + fmtx_output_hdl->sr_cal_timer = sys_s_hi_timer_add(NULL, audio_fmtx_sr_cal_timer, 1000); + + fmtx_output_hdl->hw_src = zalloc(sizeof(struct audio_src_handle)); + if (fmtx_output_hdl->hw_src) { + audio_hw_src_open(fmtx_output_hdl->hw_src, 2, SRC_TYPE_RESAMPLE); + audio_hw_src_set_rate(fmtx_output_hdl->hw_src, \ + fmtx_output_hdl->in_sample_rate, \ + fmtx_output_hdl->out_sample_rate); + fmtx_debug("audio fmtx rate:%d -> %d\n", \ + fmtx_output_hdl->in_sample_rate, \ + fmtx_output_hdl->out_sample_rate); + audio_src_set_output_handler(fmtx_output_hdl->hw_src, NULL, audio_fmtx_src_output_handler); + audio_src_set_rise_irq_handler(fmtx_output_hdl->hw_src, NULL, audio_fmtx_src_irq_cb); + } else { + fmtx_debug("hw_src malloc err ==============\n"); + } + + fmtx_output_hdl->entry.data_handler = audio_stream_fmtx_data_handler; + fmtx_output_hdl->entry.data_clear = audio_stream_fmtx_data_clear; + /* mem_stats(); */ + return (&(fmtx_output_hdl->entry)); + } + return NULL; +} + +void audio_fmtx_output_stop() +{ + fmtx_debug("audio_fmtx_output_stop\n"); + if (fmtx_output_hdl) { + fm_emitter_manage_stop(); + + if (fmtx_output_hdl->sr_cal_timer) { + sys_s_hi_timer_del(fmtx_output_hdl->sr_cal_timer); + } + + if (fmtx_output_hdl->hw_src) { + audio_hw_src_stop(fmtx_output_hdl->hw_src); + audio_hw_src_close(fmtx_output_hdl->hw_src); + free(fmtx_output_hdl->hw_src); + fmtx_output_hdl->hw_src = NULL; + } + + free(fmtx_output_hdl); + fmtx_output_hdl = NULL; + /* clk_set_en(1); */ + } +} + +#endif + diff --git a/cpu/br23/audio_common/audio_fmtx.h b/cpu/br23/audio_common/audio_fmtx.h new file mode 100644 index 0000000..fed67cd --- /dev/null +++ b/cpu/br23/audio_common/audio_fmtx.h @@ -0,0 +1,16 @@ +#ifndef _AUDIO_FMTX_H_ +#define _AUDIO_FMTX_H_ + + + +extern void *audio_fmtx_output_start(u16 fre); +extern void audio_fmtx_output_stop(); +extern int audio_fmtx_output_write(s16 *data, u32 len); +extern void audio_fmtx_output_set_srI(u32 sample_rate); + + + + + +#endif + diff --git a/cpu/br23/audio_common/audio_iis.c b/cpu/br23/audio_common/audio_iis.c new file mode 100644 index 0000000..2ce8e9d --- /dev/null +++ b/cpu/br23/audio_common/audio_iis.c @@ -0,0 +1,462 @@ +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "app_config.h" +#include "circular_buf.h" +#include "audio_iis.h" + +#define IIS_DEBUG_ENABLE 1 +#if IIS_DEBUG_ENABLE +#define iis_debug y_printf +#else +#define iis_debug(...) +#endif + +#if (TCFG_IIS_ENABLE && TCFG_IIS_OUTPUT_EN) + +#define IIS_RESAMPLE_USE_BUF_SIZE 1 + +#define IIS_TX_BUF_LEN (4*1024) +struct _iis_output { + u32 in_sample_rate; + u32 out_sample_rate; + cbuffer_t cbuf; + u8 buf[IIS_TX_BUF_LEN]; + struct audio_src_handle *hw_src; + struct audio_stream_entry entry; +#if (IIS_RESAMPLE_USE_BUF_SIZE) + int resample_dir; +#else + int sr_cal_timer; + u32 points_total; + u16 cnt_total; +#endif + u8 ch : 4; + u8 flag : 1; + u8 need_resume : 1; +} *iis_output_hdl = NULL; + +static u32 iis_srI_last = 0; + +struct audio_sample_sync *iis_samp_sync = NULL; +int iis_samp_sync_step = 0; + +static void audio_stream_iis_src_open(void); +static void audio_stream_iis_src_close(void); + +static int audio_stream_iis_data_handler(struct audio_stream_entry *entry, struct audio_data_frame *in, struct audio_data_frame *out) + +{ + if (iis_srI_last != in->sample_rate) { + iis_debug("in:%d ---%d\n", iis_srI_last, in->sample_rate); + audio_iis_output_set_srI(in->sample_rate); + } + +#if (IIS_RESAMPLE_USE_BUF_SIZE) + if (iis_output_hdl->hw_src) { + u32 sample_rate = TCFG_IIS_OUTPUT_SR; + u32 buf_size = cbuf_get_data_len(&(iis_output_hdl->cbuf)); + if (buf_size >= (IIS_TX_BUF_LEN * 3 / 4)) { + /* putchar('-'); */ + sample_rate = TCFG_IIS_OUTPUT_SR - (TCFG_IIS_OUTPUT_SR * 5 / 10000); + if (iis_output_hdl->resample_dir >= 0) { + iis_output_hdl->resample_dir = -1; + } else { + iis_output_hdl->resample_dir --; + int resr = (iis_output_hdl->resample_dir >> 3); + if (resr < -10) { + resr = -10; + } + sample_rate += (resr * (TCFG_IIS_OUTPUT_SR * 5 / 10000)); + /* put_u16hex(sample_rate); */ + } + } else if (buf_size <= (IIS_TX_BUF_LEN / 4)) { + /* putchar('+'); */ + sample_rate = TCFG_IIS_OUTPUT_SR + (TCFG_IIS_OUTPUT_SR * 5 / 10000); + if (iis_output_hdl->resample_dir <= 0) { + iis_output_hdl->resample_dir = 1; + } else { + iis_output_hdl->resample_dir ++; + int resr = (iis_output_hdl->resample_dir >> 3); + if (resr > 10) { + resr = 10; + } + sample_rate += (resr * (TCFG_IIS_OUTPUT_SR * 5 / 10000)); + /* put_u16hex(sample_rate); */ + } + } else { + iis_output_hdl->resample_dir = 0; + /* putchar('='); */ + } + if (sample_rate != TCFG_IIS_OUTPUT_SR) { + iis_output_hdl->out_sample_rate = sample_rate; + audio_hw_src_set_rate(iis_output_hdl->hw_src, \ + iis_output_hdl->in_sample_rate, \ + iis_output_hdl->out_sample_rate); + } + } +#endif + + u32 len = audio_iis_output_sync_write(in->data, in->data_len, in->data_sync); + if (len != in->data_len) { + local_irq_disable(); + iis_output_hdl->need_resume = 1; + local_irq_enable(); + } + return len; +} + +static void audio_stream_iis_data_clear(struct audio_stream_entry *entry) +{ +#if (IIS_RESAMPLE_USE_BUF_SIZE) + if (iis_output_hdl->hw_src) { + // 开关一次src,避免src中残留数据 + audio_stream_iis_src_close(); + iis_output_hdl->out_sample_rate = TCFG_IIS_OUTPUT_SR; + iis_output_hdl->resample_dir = 0; + audio_stream_iis_src_open(); + } +#endif + if (iis_samp_sync && iis_samp_sync_step == 2) { + iis_samp_sync_step = 1; + } + + cbuf_clear(&(iis_output_hdl->cbuf)); + iis_debug("iis clear\n"); +} + +static void audio_iis_src_irq_cb(void *hdl) +{ + if (iis_output_hdl) { + audio_stream_resume(&(iis_output_hdl->entry)); + } +} + +int audio_iis_src_output_handler(void *parm, s16 *data, int len) +{ + int wlen = iis_output_hdl->cbuf.total_len - iis_output_hdl->cbuf.data_len; + if (wlen > len) { + wlen = len; + } + wlen = cbuf_write(&(iis_output_hdl->cbuf), data, wlen); + if (wlen != len) { + local_irq_disable(); + iis_output_hdl->need_resume = 1; + local_irq_enable(); + } + return wlen; +} + +int audio_iis_output_sync_write(s16 *data, u32 len, u8 data_sync) +{ + u32 wlen = 0; + + if (data_sync) { + if (len && iis_samp_sync && iis_samp_sync_step == 1 && iis_output_hdl) { + iis_samp_sync_step = 2; + audio_sample_sync_output_begin(iis_samp_sync, 0, iis_output_hdl->in_sample_rate); + } + } else { + if (iis_samp_sync_step == 2) { + iis_samp_sync_step = 1; + if (iis_samp_sync) { + audio_sample_sync_stop(iis_samp_sync); + } else { + iis_samp_sync_step = 0; + } + } + } + + if (len) { + wlen = audio_iis_output_write(data, len); + } + + return wlen; +} + + +int audio_iis_output_write(s16 *data, u32 len) +{ + u32 wlen = 0; + if (iis_output_hdl) { + if (iis_output_hdl->hw_src) { + wlen = audio_src_resample_write(iis_output_hdl->hw_src, data, len); + } else { + wlen = iis_output_hdl->cbuf.total_len - iis_output_hdl->cbuf.data_len; + if (wlen > len) { + wlen = len; + } + wlen = cbuf_write(&(iis_output_hdl->cbuf), data, len); + } + if (wlen != len) { + local_irq_disable(); + iis_output_hdl->need_resume = 1; + local_irq_enable(); + } + } + return wlen; +} + +void audio_iis_tx_isr(u8 idx, s16 *data, u32 len) +{ + u32 wlen = 0; + u32 rlen = 0; + if (iis_output_hdl) { + if (iis_samp_sync && iis_samp_sync_step == 2) { + audio_irq_update_sample_sync_position(iis_samp_sync, (len >> 1) / 2); + } + local_irq_disable(); + if (iis_output_hdl->need_resume) { + iis_output_hdl->need_resume = 0; + local_irq_enable(); + audio_stream_resume(&(iis_output_hdl->entry)); + } else { + local_irq_enable(); + } + + +#if (!IIS_RESAMPLE_USE_BUF_SIZE) + iis_output_hdl->points_total += len >> 2; +#endif + + rlen = cbuf_get_data_len(&(iis_output_hdl->cbuf)); + if ((iis_output_hdl->flag == 0) && (rlen < (IIS_TX_BUF_LEN / 2))) { + memset(data, 0x00, len); + return; + } + iis_output_hdl->flag = 1; + + if (rlen >= len) { + wlen = cbuf_read(&(iis_output_hdl->cbuf), data, len); + } else { + iis_debug("iis end\n"); + wlen = cbuf_read(&(iis_output_hdl->cbuf), data, rlen); + memset((u8 *)data + rlen, 0x00, len - rlen); + iis_output_hdl->flag = 0; + } + + } +} + +#if (!IIS_RESAMPLE_USE_BUF_SIZE) +void audio_iis_sr_cal_timer(void *param) +{ + if (iis_output_hdl) { + if (iis_output_hdl->cnt_total == 0) { + iis_output_hdl->points_total = iis_output_hdl->out_sample_rate; + } + iis_output_hdl->cnt_total++; + if (iis_output_hdl->cnt_total == 0) { + iis_output_hdl->cnt_total++; + } + iis_output_hdl->out_sample_rate = iis_output_hdl->points_total / iis_output_hdl->cnt_total; + + if ((iis_output_hdl->points_total > 0xFFF00000) \ + && ((iis_output_hdl->cnt_total % 2) == 0)) { + iis_output_hdl->points_total >>= 1; + iis_output_hdl->cnt_total >>= 1; + } + + + if (iis_output_hdl->hw_src && iis_output_hdl->out_sample_rate) { + /* iis_debug("iis cal:%d > %d\n", \ */ + /* iis_output_hdl->in_sample_rate, \ */ + /* iis_output_hdl->out_sample_rate); */ + audio_hw_src_set_rate(iis_output_hdl->hw_src, \ + iis_output_hdl->in_sample_rate, \ + iis_output_hdl->out_sample_rate); + } + } +} +#endif /* (!IIS_RESAMPLE_USE_BUF_SIZE) */ + +void audio_iis_output_set_srI(u32 sample_rate) +{ + iis_debug("audio_iis_output_set_srI %d\n", sample_rate); + iis_srI_last = sample_rate; + if (iis_output_hdl) { + /* iis_output_hdl->points_total = 0; */ + /* iis_output_hdl->cnt_total = 0; */ + iis_output_hdl->in_sample_rate = sample_rate; + if (iis_output_hdl->hw_src) { + iis_debug("iis set:%d > %d\n", \ + iis_output_hdl->in_sample_rate, \ + iis_output_hdl->out_sample_rate); + audio_hw_src_set_rate(iis_output_hdl->hw_src, \ + iis_output_hdl->in_sample_rate, \ + iis_output_hdl->out_sample_rate); + } + } +} + +static void audio_stream_iis_src_open(void) +{ + if (iis_output_hdl->hw_src) { + return ; + } + iis_output_hdl->hw_src = zalloc(sizeof(struct audio_src_handle)); + if (iis_output_hdl->hw_src) { + audio_hw_src_open(iis_output_hdl->hw_src, 2, SRC_TYPE_RESAMPLE); + audio_hw_src_set_rate(iis_output_hdl->hw_src, \ + iis_output_hdl->in_sample_rate, \ + iis_output_hdl->out_sample_rate); + iis_debug("audio iis rate:%d -> %d\n", \ + iis_output_hdl->in_sample_rate, \ + iis_output_hdl->out_sample_rate); + audio_src_set_output_handler(iis_output_hdl->hw_src, NULL, audio_iis_src_output_handler); + audio_src_set_rise_irq_handler(iis_output_hdl->hw_src, NULL, audio_iis_src_irq_cb); + } else { + iis_debug("hw_src malloc err ==============\n"); + } +} + +static void audio_stream_iis_src_close(void) +{ + if (iis_output_hdl->hw_src) { + audio_hw_src_stop(iis_output_hdl->hw_src); + audio_hw_src_close(iis_output_hdl->hw_src); + free(iis_output_hdl->hw_src); + iis_output_hdl->hw_src = NULL; + } +} + +void *audio_iis_output_start(ALINK_PORT port, u8 ch) +{ + if (iis_output_hdl == NULL) { + iis_debug("audio_iis_output_start\n"); + mem_stats(); + iis_output_hdl = zalloc(sizeof(struct _iis_output)); + if (iis_output_hdl == NULL) { + iis_debug("audio_iis_output_start malloc err !\n"); + return NULL; + } + /* clk_set("sys", 96 * 1000000L); */ + /* clk_set_en(0); */ + cbuf_init(&(iis_output_hdl->cbuf), iis_output_hdl->buf, IIS_TX_BUF_LEN); + iis_output_hdl->in_sample_rate = iis_srI_last; + iis_output_hdl->out_sample_rate = TCFG_IIS_OUTPUT_SR; + iis_output_hdl->ch = ch; + +#if (!IIS_RESAMPLE_USE_BUF_SIZE) + iis_output_hdl->sr_cal_timer = sys_hi_timer_add(NULL, audio_iis_sr_cal_timer, 1000); +#endif + + /* audio_stream_iis_src_open(); */ + + audio_link_init(port); + alink_channel_init(port, ch, ALINK_DIR_TX, audio_iis_tx_isr); + + iis_output_hdl->entry.data_handler = audio_stream_iis_data_handler; + iis_output_hdl->entry.data_clear = audio_stream_iis_data_clear; + /* mem_stats(); */ + return (&(iis_output_hdl->entry)); + } + return NULL; +} + +void audio_iis_output_stop(ALINK_PORT port) +{ + iis_debug("audio_iis_output_stop\n"); + if (iis_output_hdl) { + alink_channel_close(port, iis_output_hdl->ch); + audio_link_uninit(port); + +#if (!IIS_RESAMPLE_USE_BUF_SIZE) + if (iis_output_hdl->sr_cal_timer) { + sys_hi_timer_del(iis_output_hdl->sr_cal_timer); + } +#endif + + audio_stream_iis_src_close(); + + free(iis_output_hdl); + iis_output_hdl = NULL; + /* clk_set_en(1); */ + } +} + +static int audio_iis_channel_sync_state_query(void *priv) +{ + int state = SAMPLE_SYNC_DEVICE_IDLE; + + if (iis_output_hdl) { + state = SAMPLE_SYNC_DEVICE_START; + } + + return state; +} + +static int audio_iis_channel_buf_samples(void *_ch) +{ + if (!iis_output_hdl) { + return 0; + } + + /* int timeout = (1000000 / iis_output_hdl->in_sample_rate + 1) * (clk_get("sys") / 1000000); */ + int pcm_num = iis_output_hdl->cbuf.data_len / 2 / 2; + + return pcm_num << PCM_PHASE_BIT; +} + + +int audio_iis_channel_sync_enable(struct audio_sample_sync *samp_sync) +{ + if (!samp_sync) { + return -EINVAL; + } + + iis_samp_sync = samp_sync; + iis_samp_sync_step = 1; + + struct sample_sync_device_ops device; + device.data_len = audio_iis_channel_buf_samples; + device.state_query = audio_iis_channel_sync_state_query; + + audio_sample_sync_set_device(iis_samp_sync, NULL, &device); + + return 0; +} + +int audio_iis_channel_sync_disable(struct audio_sample_sync *samp_sync) +{ + if (samp_sync == iis_samp_sync) { + iis_samp_sync = NULL; + } + return 0; +} +#endif //(TCFG_IIS_ENABLE && TCFG_IIS_OUTPUT_EN) + + + + + +#if (TCFG_IIS_ENABLE && TCFG_IIS_INPUT_EN) + +u8 iis_input_state = 0; + +void audio_iis_input_start(ALINK_PORT port, u8 ch, void (*handle)(u8 ch, s16 *buf, u32 len)) +{ + if (iis_input_state == 0) { + audio_link_init(port); + alink_channel_init(port, ch, ALINK_DIR_RX, handle); + iis_input_state = 1; + } +} + + +void audio_iis_input_stop(ALINK_PORT port, u8 ch) +{ + if (iis_input_state) { + alink_channel_close(port, ch); + audio_link_uninit(port); + iis_input_state = 0; + } +} + + + +#endif //(TCFG_IIS_ENABLE && TCFG_IIS_INPUT_EN) + + + + diff --git a/cpu/br23/audio_common/audio_iis.h b/cpu/br23/audio_common/audio_iis.h new file mode 100644 index 0000000..bdf84a8 --- /dev/null +++ b/cpu/br23/audio_common/audio_iis.h @@ -0,0 +1,18 @@ +#ifndef _AUDIO_IIS_H_ +#define _AUDIO_IIS_H_ + +#include "audio_link.h" + +extern void *audio_iis_output_start(ALINK_PORT port, u8 ch); +extern void audio_iis_output_stop(ALINK_PORT port); +extern int audio_iis_output_write(s16 *data, u32 len); +extern void audio_iis_output_set_srI(u32 sample_rate); +extern int audio_iis_output_sync_write(s16 *data, u32 len, u8 data_sync); +extern int audio_iis_channel_sync_enable(struct audio_sample_sync *samp_sync); +extern int audio_iis_channel_sync_disable(struct audio_sample_sync *samp_sync); + +extern void audio_iis_input_start(ALINK_PORT port, u8 ch, void (*handle)(u8 ch, s16 *buf, u32 len)); +extern void audio_iis_input_stop(ALINK_PORT port, u8 ch); + +#endif + diff --git a/cpu/br23/audio_common/audio_link.c b/cpu/br23/audio_common/audio_link.c new file mode 100644 index 0000000..ef8510d --- /dev/null +++ b/cpu/br23/audio_common/audio_link.c @@ -0,0 +1,799 @@ +/***************************************************************** + >file name : lib/media/cpu/br22/audio_link.c + >author : + >create time : Fri 7 Dec 2018 14:59:12 PM CST + *****************************************************************/ +#include "includes.h" +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "app_config.h" +#include "asm/clock.h" +#include "asm/iis.h" +#include "audio_link.h" + +#if TCFG_IIS_ENABLE + +#define ALINK_TEST_ENABLE + +#define ALINK_DEBUG_INFO +#ifdef ALINK_DEBUG_INFO +#define alink_printf printf +#else +#define alink_printf(...) +#endif + +static u32 *ALNK0_BUF_ADR[] = { + (u32 *)(&(JL_ALNK0->ADR0)), + (u32 *)(&(JL_ALNK0->ADR1)), + (u32 *)(&(JL_ALNK0->ADR2)), + (u32 *)(&(JL_ALNK0->ADR3)), +}; + +static u32 *ALNK1_BUF_ADR[] = { + (u32 *)(&(JL_ALNK1->ADR0)), + (u32 *)(&(JL_ALNK1->ADR1)), + (u32 *)(&(JL_ALNK1->ADR2)), + (u32 *)(&(JL_ALNK1->ADR3)), +}; + +enum { + IIS_IO_MCLK = 0u, + IIS_IO_SCLK , + IIS_IO_LRCK , + IIS_IO_CH0 , + IIS_IO_CH1 , + IIS_IO_CH2 , + IIS_IO_CH3 , +}; + +enum { + MCLK_11M2896K = 0, + MCLK_12M288K +}; + +enum { + MCLK_EXTERNAL = 0u, + MCLK_SYS_CLK , + MCLK_OSC_CLK , + MCLK_PLL_CLK , +}; + +enum { + MCLK_DIV_1 = 0u, + MCLK_DIV_2 , + MCLK_DIV_4 , + MCLK_DIV_8 , + MCLK_DIV_16 , +}; + +enum { + MCLK_LRDIV_EX = 0u, + MCLK_LRDIV_64FS , + MCLK_LRDIV_128FS , + MCLK_LRDIV_192FS , + MCLK_LRDIV_256FS , + MCLK_LRDIV_384FS , + MCLK_LRDIV_512FS , + MCLK_LRDIV_768FS , +}; + +static const u8 alink0_IOS_portA[] = { + IO_PORTA_08, IO_PORTA_02, IO_PORTA_03, IO_PORTA_04, IO_PORTA_05, IO_PORTA_06, IO_PORTA_07, +}; +static const u8 alink0_IOS_portB[] = { + IO_PORTA_15, IO_PORTA_09, IO_PORTA_10, IO_PORTA_11, IO_PORTA_12, IO_PORTA_13, IO_PORTA_14, +}; +static const u8 alink1_IOS_portA[] = { + IO_PORTB_00, IO_PORTC_00, IO_PORTC_01, IO_PORTC_02, IO_PORTC_03, IO_PORTC_04, IO_PORTC_05, +}; + +static u8 alink0_IOS_port[7] = {0}; +static u8 alink1_IOS_port[7] = {0}; + +ALINK_PARM *p_alink0_parm; +ALINK_PARM *p_alink1_parm; + +//================================================== +enum alnk_clock { + ALINK_CLOCK_12M288K, + ALINK_CLOCK_11M2896K, +}; +static void audio_link_clock_sel(u8 module, enum alnk_clock clk) +{ + switch (clk) { + case ALINK_CLOCK_12M288K: + if (module) { + SFR(JL_CLOCK->CLK_CON2, 10, 4, 5); //160/13 + } else { + SFR(JL_CLOCK->CLK_CON2, 6, 4, 5); //160/13 + } + break; + case ALINK_CLOCK_11M2896K: + if (module) { + SFR(JL_CLOCK->CLK_CON2, 10, 4, 0); //192/17 + } else { + SFR(JL_CLOCK->CLK_CON2, 6, 4, 0); //192/17 + } + break; + default: + break; + } +} + +//================================================== +static void alink_clk_io_in_init(u8 gpio) +{ + gpio_set_direction(gpio, 1); + gpio_set_pull_down(gpio, 0); + gpio_set_pull_up(gpio, 1); + gpio_set_die(gpio, 1); +} + + +static void *alink_addr(u8 module, u8 ch) +{ + u8 *buf_addr = NULL; //can be used + u32 buf_index = 0; + + u8 index_table[4] = {12, 13, 14, 15}; + u8 bit_index = index_table[ch]; + buf_index = (ALINK_SEL(module, CON0) & BIT(bit_index)) ? 0 : 1; + if (module) { + buf_addr = (u8 *)(p_alink1_parm->ch_cfg[ch].buf); + buf_addr = buf_addr + ((p_alink1_parm->dma_len / 2) * buf_index); + } else { + buf_addr = (u8 *)(p_alink0_parm->ch_cfg[ch].buf); + buf_addr = buf_addr + ((p_alink0_parm->dma_len / 2) * buf_index); + } + return buf_addr; +} + +___interrupt +static void alink0_isr(void) +{ + u16 reg; + s16 *buf_addr = NULL ; + u8 ch = 0; + + reg = JL_ALNK0->CON2; + + //channel 0 + if (reg & BIT(4)) { + ch = 0; + ALINK_CLR_CH0_PND(0); + buf_addr = alink_addr(0, ALINK_CH0); + goto __isr_cb; + } + //channel 1 + if (reg & BIT(5)) { + ch = 1; + ALINK_CLR_CH1_PND(0); + buf_addr = alink_addr(0, ALINK_CH1); + goto __isr_cb; + } + //channel 2 + if (reg & BIT(6)) { + ch = 2; + ALINK_CLR_CH2_PND(0); + buf_addr = alink_addr(0, ALINK_CH2); + goto __isr_cb; + } + //channel 3 + if (reg & BIT(7)) { + ch = 3; + ALINK_CLR_CH3_PND(0); + buf_addr = alink_addr(0, ALINK_CH3); + goto __isr_cb; + } + +__isr_cb: + if (p_alink0_parm->ch_cfg[ch].isr_cb) { + p_alink0_parm->ch_cfg[ch].isr_cb(ch, buf_addr, p_alink0_parm->dma_len / 2); + } +} + +___interrupt +static void alink1_isr(void) +{ + u16 reg; + s16 *buf_addr = NULL ; + u8 ch = 0; + + reg = JL_ALNK1->CON2; + + //channel 0 + if (reg & BIT(4)) { + ch = 0; + ALINK_CLR_CH0_PND(1); + buf_addr = alink_addr(1, ALINK_CH0); + goto __isr_cb; + } + //channel 1 + if (reg & BIT(5)) { + ch = 1; + ALINK_CLR_CH1_PND(1); + buf_addr = alink_addr(1, ALINK_CH1); + goto __isr_cb; + } + //channel 2 + if (reg & BIT(6)) { + ch = 2; + ALINK_CLR_CH2_PND(1); + buf_addr = alink_addr(1, ALINK_CH2); + goto __isr_cb; + } + //channel 3 + if (reg & BIT(7)) { + ch = 3; + ALINK_CLR_CH3_PND(1); + buf_addr = alink_addr(1, ALINK_CH3); + goto __isr_cb; + } + +__isr_cb: + if (p_alink1_parm->ch_cfg[ch].isr_cb) { + p_alink1_parm->ch_cfg[ch].isr_cb(ch, buf_addr, p_alink1_parm->dma_len / 2); + } +} + +static void alink_sr(ALINK_PORT port, u32 rate) +{ + u8 module = ALINK_PORT_TO_MODULE(port); + + alink_printf("ALINK_SR = %d\n", rate); + switch (rate) { + case ALINK_SR_48000: + /*12.288Mhz 256fs*/ + audio_link_clock_sel(module, ALINK_CLOCK_12M288K); + ALINK_MDIV(module, MCLK_DIV_1); + ALINK_LRDIV(module, MCLK_LRDIV_256FS); + break ; + + case ALINK_SR_44100: + /*11.289Mhz 256fs*/ + audio_link_clock_sel(module, ALINK_CLOCK_11M2896K); + ALINK_MDIV(module, MCLK_DIV_1); + ALINK_LRDIV(module, MCLK_LRDIV_256FS); + break ; + + case ALINK_SR_32000: + /*12.288Mhz 384fs*/ + audio_link_clock_sel(module, ALINK_CLOCK_12M288K); + ALINK_MDIV(module, MCLK_DIV_1); + ALINK_LRDIV(module, MCLK_LRDIV_384FS); + break ; + + case ALINK_SR_24000: + /*12.288Mhz 512fs*/ + audio_link_clock_sel(module, ALINK_CLOCK_12M288K); + ALINK_MDIV(module, MCLK_DIV_2); + ALINK_LRDIV(module, MCLK_LRDIV_256FS); + break ; + + case ALINK_SR_22050: + /*11.289Mhz 512fs*/ + audio_link_clock_sel(module, ALINK_CLOCK_11M2896K); + ALINK_MDIV(module, MCLK_DIV_2); + ALINK_LRDIV(module, MCLK_LRDIV_256FS); + break ; + + case ALINK_SR_16000: + /*12.288/2Mhz 384fs*/ + audio_link_clock_sel(module, ALINK_CLOCK_12M288K); + ALINK_MDIV(module, MCLK_DIV_2); + ALINK_LRDIV(module, MCLK_LRDIV_384FS); + break ; + + case ALINK_SR_12000: + /*12.288/2Mhz 512fs*/ + audio_link_clock_sel(module, ALINK_CLOCK_12M288K); + ALINK_MDIV(module, MCLK_DIV_4); + ALINK_LRDIV(module, MCLK_LRDIV_256FS); + break ; + + case ALINK_SR_11025: + /*11.289/2Mhz 512fs*/ + audio_link_clock_sel(module, ALINK_CLOCK_11M2896K); + ALINK_MDIV(module, MCLK_DIV_4); + ALINK_LRDIV(module, MCLK_LRDIV_256FS); + break ; + + case ALINK_SR_8000: + /*12.288/4Mhz 384fs*/ + audio_link_clock_sel(module, ALINK_CLOCK_12M288K); + ALINK_MDIV(module, MCLK_DIV_4); + ALINK_LRDIV(module, MCLK_LRDIV_384FS); + break ; + + default: + //44100 + /*11.289Mhz 256fs*/ + audio_link_clock_sel(module, ALINK_CLOCK_11M2896K); + ALINK_MDIV(module, MCLK_DIV_1); + ALINK_LRDIV(module, MCLK_LRDIV_256FS); + break; + } + if (module) { + if (p_alink1_parm->role == ALINK_ROLE_SLAVE) { + ALINK_LRDIV(module, MCLK_LRDIV_EX); + } + } else { + if (p_alink0_parm->role == ALINK_ROLE_SLAVE) { + ALINK_LRDIV(module, MCLK_LRDIV_EX); + } + } +} + + +void alink_channel_init(ALINK_PORT port, u8 ch_idx, u8 dir, void (*handle)(u8 ch, s16 *buf, u32 len)) +{ + u8 module = ALINK_PORT_TO_MODULE(port); + if (module) { + if (!p_alink1_parm->ch_cfg[ch_idx].enable) { + return; + } + p_alink1_parm->ch_cfg[ch_idx].dir = dir; + p_alink1_parm->ch_cfg[ch_idx].isr_cb = handle; + p_alink1_parm->ch_cfg[ch_idx].buf = malloc(p_alink1_parm->dma_len); + memset(p_alink1_parm->ch_cfg[ch_idx].buf, 0xFF, p_alink1_parm->dma_len); + u32 *buf_addr; + //===================================// + // ALNK工作模式 // + //===================================// + if (p_alink1_parm->mode > ALINK_MD_IIS_RALIGN) { + ALINK_CHx_MODE_SEL(1, (p_alink1_parm->mode - ALINK_MD_IIS_RALIGN), ch_idx); + } else { + ALINK_CHx_MODE_SEL(1, p_alink1_parm->mode, ch_idx); + } + //===================================// + // ALNK CH DMA BUF // + //===================================// + buf_addr = ALNK1_BUF_ADR[ch_idx]; + *buf_addr = (u32)(p_alink1_parm->ch_cfg[ch_idx].buf); + //===================================// + // ALNK CH DAT IO INIT // + //===================================// + if (p_alink1_parm->ch_cfg[ch_idx].dir == ALINK_DIR_RX) { + gpio_set_direction(alink1_IOS_port[IIS_IO_CH0 + ch_idx], 1); + gpio_set_pull_down(alink1_IOS_port[IIS_IO_CH0 + ch_idx], 0); + gpio_set_pull_up(alink1_IOS_port[IIS_IO_CH0 + ch_idx], 1); + gpio_set_die(alink1_IOS_port[IIS_IO_CH0 + ch_idx], 1); + ALINK_CHx_DIR_RX_MODE(1, ch_idx); + } else { + gpio_direction_output(alink1_IOS_port[IIS_IO_CH0 + ch_idx], 1); + ALINK_CHx_DIR_TX_MODE(1, ch_idx); + } + } else { + if (!p_alink0_parm->ch_cfg[ch_idx].enable) { + return; + } + p_alink0_parm->ch_cfg[ch_idx].dir = dir; + p_alink0_parm->ch_cfg[ch_idx].isr_cb = handle; + p_alink0_parm->ch_cfg[ch_idx].buf = malloc(p_alink0_parm->dma_len); + memset(p_alink0_parm->ch_cfg[ch_idx].buf, 0xFF, p_alink0_parm->dma_len); + u32 *buf_addr; + //===================================// + // ALNK工作模式 // + //===================================// + if (p_alink0_parm->mode > ALINK_MD_IIS_RALIGN) { + ALINK_CHx_MODE_SEL(0, (p_alink0_parm->mode - ALINK_MD_IIS_RALIGN), ch_idx); + } else { + ALINK_CHx_MODE_SEL(0, p_alink0_parm->mode, ch_idx); + } + //===================================// + // ALNK CH DMA BUF // + //===================================// + buf_addr = ALNK0_BUF_ADR[ch_idx]; + *buf_addr = (u32)(p_alink0_parm->ch_cfg[ch_idx].buf); + //===================================// + // ALNK CH DAT IO INIT // + //===================================// + if (p_alink0_parm->ch_cfg[ch_idx].dir == ALINK_DIR_RX) { + gpio_set_direction(alink0_IOS_port[IIS_IO_CH0 + ch_idx], 1); + gpio_set_pull_down(alink0_IOS_port[IIS_IO_CH0 + ch_idx], 0); + gpio_set_pull_up(alink0_IOS_port[IIS_IO_CH0 + ch_idx], 1); + gpio_set_die(alink0_IOS_port[IIS_IO_CH0 + ch_idx], 1); + ALINK_CHx_DIR_RX_MODE(0, ch_idx); + } else { + gpio_direction_output(alink0_IOS_port[IIS_IO_CH0 + ch_idx], 1); + ALINK_CHx_DIR_TX_MODE(0, ch_idx); + } + } +} + +static void alink_info_dump(ALINK_PORT port) +{ + u8 module = ALINK_PORT_TO_MODULE(port); + alink_printf("JL_ALNK0->CON0 = 0x%x", ALINK_SEL(module, CON0)); + alink_printf("JL_ALNK0->CON1 = 0x%x", ALINK_SEL(module, CON1)); + alink_printf("JL_ALNK0->CON2 = 0x%x", ALINK_SEL(module, CON2)); + alink_printf("JL_ALNK0->CON3 = 0x%x", ALINK_SEL(module, CON3)); + alink_printf("JL_ALNK0->LEN = 0x%x", ALINK_SEL(module, LEN)); + alink_printf("JL_ALNK0->ADR0 = 0x%x", ALINK_SEL(module, ADR0)); + alink_printf("JL_ALNK0->ADR1 = 0x%x", ALINK_SEL(module, ADR1)); + alink_printf("JL_ALNK0->ADR2 = 0x%x", ALINK_SEL(module, ADR2)); + alink_printf("JL_ALNK0->ADR3 = 0x%x", ALINK_SEL(module, ADR3)); + alink_printf("JL_CLOCK->CLK_CON2 = 0x%x", JL_CLOCK->CLK_CON2); +} + +int alink_init(ALINK_PARM *parm) +{ + if (parm == NULL) { + return -1; + } + u8 module = ALINK_PORT_TO_MODULE(parm->port_select); + if (module) { + p_alink1_parm = parm; + } else { + p_alink0_parm = parm; + } + switch (parm->port_select) { + case ALINK0_PORTA: + for (int i = 0; i < 7; i++) { + alink0_IOS_port[i] = alink0_IOS_portA[i]; + } + JL_IOMAP->CON0 &= ~BIT(11); + r_printf("iis0_portA init\n"); + request_irq(IRQ_ALINK0_IDX, 3, alink0_isr, 0); + break; + case ALINK0_PORTB: + for (int i = 0; i < 7; i++) { + alink0_IOS_port[i] = alink0_IOS_portB[i]; + } + JL_IOMAP->CON0 |= BIT(11); + r_printf("iis0_portB init\n"); + request_irq(IRQ_ALINK0_IDX, 3, alink0_isr, 0); + break; + case ALINK1_PORTA: + for (int i = 0; i < 7; i++) { + alink1_IOS_port[i] = alink1_IOS_portA[i]; + } + r_printf("iis1_portA init\n"); + request_irq(IRQ_ALINK1_IDX, 3, alink1_isr, 0); + break; + } + ALINK_MSRC(module, MCLK_PLL_CLK); /*MCLK source*/ + + //===================================// + // 输出时钟配置 // + //===================================// + if (parm->role == ALINK_ROLE_MASTER) { + //主机输出时钟 + if (module) { + gpio_direction_output(alink1_IOS_port[IIS_IO_MCLK], 1); + gpio_direction_output(alink1_IOS_port[IIS_IO_LRCK], 1); + gpio_direction_output(alink1_IOS_port[IIS_IO_SCLK], 1); + } else { + gpio_direction_output(alink0_IOS_port[IIS_IO_MCLK], 1); + gpio_direction_output(alink0_IOS_port[IIS_IO_LRCK], 1); + gpio_direction_output(alink0_IOS_port[IIS_IO_SCLK], 1); + + } + ALINK_MOE(module, 1); /*MCLK output to IO*/ + ALINK_SOE(module, 1); /*SCLK/LRCK output to IO*/ + } else { + //从机输入时钟 + if (module) { + alink_clk_io_in_init(alink1_IOS_port[IIS_IO_MCLK]); + alink_clk_io_in_init(alink1_IOS_port[IIS_IO_LRCK]); + alink_clk_io_in_init(alink1_IOS_port[IIS_IO_SCLK]); + } else { + alink_clk_io_in_init(alink0_IOS_port[IIS_IO_MCLK]); + alink_clk_io_in_init(alink0_IOS_port[IIS_IO_LRCK]); + alink_clk_io_in_init(alink0_IOS_port[IIS_IO_SCLK]); + } + ALINK_MOE(module, 0); /*MCLK input to IO*/ + ALINK_SOE(module, 0); /*SCLK/LRCK output to IO*/ + } + //===================================// + // 基本模式/扩展模式 // + //===================================// + ALINK_DSPE(module, parm->mode >> 2); + + //===================================// + // 数据位宽16/32bit // + //===================================// + //注意: 配置了24bit, 一定要选ALINK_FRAME_64SCLK, 因为sclk32 x 2才会有24bit; + if (parm->bitwide == ALINK_LEN_24BIT) { + ASSERT(parm->sclk_per_frame == ALINK_FRAME_64SCLK); + ALINK_24BIT_MODE(module); + //一个点需要4bytes, LR = 2, 双buf = 2 + ALINK_SEL(module, LEN) = parm->dma_len / 8; //点数 + } else { + ALINK_16BIT_MODE(module); + //一个点需要2bytes, LR = 2, 双buf = 2 + ALINK_SEL(module, LEN) = parm->dma_len / 8; //点数 + } + //===================================// + // 时钟边沿选择 // + //===================================// + if (parm->clk_mode == ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE) { + SCLKINV(module, 0); + } else { + SCLKINV(module, 1); + } + //===================================// + // 每帧数据sclk个数 // + //===================================// + if (parm->sclk_per_frame == ALINK_FRAME_64SCLK) { + F32_EN(module, 0); + } else { + F32_EN(module, 1); + } + //===================================// + // 设置数据采样率 // + //===================================// + alink_sr(parm->port_select, parm->sample_rate); + + return 0; +} + +void alink_channel_close(ALINK_PORT port, u8 ch_idx) +{ + u8 module = ALINK_PORT_TO_MODULE(port); + if (module) { + gpio_set_pull_up(alink1_IOS_port[IIS_IO_CH0 + ch_idx], 0); + gpio_set_pull_down(alink1_IOS_port[IIS_IO_CH0 + ch_idx], 0); + gpio_set_direction(alink1_IOS_port[IIS_IO_CH0 + ch_idx], 1); + gpio_set_die(alink1_IOS_port[IIS_IO_CH0 + ch_idx], 0); + ALINK_CHx_CLOSE(module, 1, ch_idx); + if (p_alink1_parm->ch_cfg[ch_idx].buf) { + free(p_alink1_parm->ch_cfg[ch_idx].buf); + p_alink1_parm->ch_cfg[ch_idx].buf = NULL; + } + } else { + gpio_set_pull_up(alink0_IOS_port[IIS_IO_CH0 + ch_idx], 0); + gpio_set_pull_down(alink0_IOS_port[IIS_IO_CH0 + ch_idx], 0); + gpio_set_direction(alink0_IOS_port[IIS_IO_CH0 + ch_idx], 1); + gpio_set_die(alink0_IOS_port[IIS_IO_CH0 + ch_idx], 0); + ALINK_CHx_CLOSE(module, 1, ch_idx); + if (p_alink0_parm->ch_cfg[ch_idx].buf) { + free(p_alink0_parm->ch_cfg[ch_idx].buf); + p_alink0_parm->ch_cfg[ch_idx].buf = NULL; + } + } +} + + +int alink_start(ALINK_PORT port) +{ + u8 module = ALINK_PORT_TO_MODULE(port); + if (module) { + if (p_alink1_parm) { + ALINK_EN(module, 1); + return 0; + } + } else { + if (p_alink0_parm) { + ALINK_EN(module, 1); + return 0; + } + } + return -1; +} + +void alink_uninit(ALINK_PORT port) +{ + u8 module = ALINK_PORT_TO_MODULE(port); + if (module) { + ALINK_EN(module, 0); + for (int i = 0; i < 4; i++) { + if (p_alink1_parm->ch_cfg[i].buf) { + alink_channel_close(port, i); + } + } + p_alink1_parm = NULL; + } else { + ALINK_EN(module, 0); + for (int i = 0; i < 4; i++) { + if (p_alink0_parm->ch_cfg[i].buf) { + alink_channel_close(port, i); + } + } + p_alink0_parm = NULL; + } +} + +int alink_sr_set(ALINK_PORT port, u16 sr) +{ + u8 module = ALINK_PORT_TO_MODULE(port); + if (module) { + if (p_alink1_parm) { + ALINK_EN(module, 0); + alink_sr(port, sr); + ALINK_EN(module, 1); + return 0; + } else { + return -1; + } + } else { + if (p_alink0_parm) { + ALINK_EN(module, 0); + alink_sr(port, sr); + ALINK_EN(module, 1); + return 0; + } else { + return -1; + } + } +} + +extern ALINK_PARM alink0_param; +extern ALINK_PARM alink1_param; +static u8 alink0_init_cnt = 0; +static u8 alink1_init_cnt = 0; +void audio_link_init(ALINK_PORT port) +{ + u8 module = ALINK_PORT_TO_MODULE(port); + if (module) { + if (alink1_init_cnt == 0) { + alink_init(&alink1_param); + alink_start(port); + } + alink1_init_cnt++; + } else { + if (alink0_init_cnt == 0) { + alink_init(&alink0_param); + alink_start(port); + } + alink0_init_cnt++; + } +} + +void audio_link_uninit(ALINK_PORT port) +{ + u8 module = ALINK_PORT_TO_MODULE(port); + if (module) { + alink1_init_cnt--; + if (alink1_init_cnt == 0) { + alink_uninit(port); + } + } else { + alink0_init_cnt--; + if (alink0_init_cnt == 0) { + alink_uninit(port); + } + } +} + +//===============================================// +// for APP use demo // +//===============================================// + +#ifdef ALINK_TEST_ENABLE + +short const tsin_441k[441] = { + 0x0000, 0x122d, 0x23fb, 0x350f, 0x450f, 0x53aa, 0x6092, 0x6b85, 0x744b, 0x7ab5, 0x7ea2, 0x7fff, 0x7ec3, 0x7af6, 0x74ab, 0x6c03, + 0x612a, 0x545a, 0x45d4, 0x35e3, 0x24db, 0x1314, 0x00e9, 0xeeba, 0xdce5, 0xcbc6, 0xbbb6, 0xad08, 0xa008, 0x94fa, 0x8c18, 0x858f, + 0x8181, 0x8003, 0x811d, 0x84ca, 0x8af5, 0x9380, 0x9e3e, 0xaaf7, 0xb969, 0xc94a, 0xda46, 0xec06, 0xfe2d, 0x105e, 0x223a, 0x3365, + 0x4385, 0x5246, 0x5f5d, 0x6a85, 0x7384, 0x7a2d, 0x7e5b, 0x7ffa, 0x7f01, 0x7b75, 0x7568, 0x6cfb, 0x6258, 0x55b7, 0x4759, 0x3789, + 0x2699, 0x14e1, 0x02bc, 0xf089, 0xdea7, 0xcd71, 0xbd42, 0xae6d, 0xa13f, 0x95fd, 0x8ce1, 0x861a, 0x81cb, 0x800b, 0x80e3, 0x844e, + 0x8a3c, 0x928c, 0x9d13, 0xa99c, 0xb7e6, 0xc7a5, 0xd889, 0xea39, 0xfc5a, 0x0e8f, 0x2077, 0x31b8, 0x41f6, 0x50de, 0x5e23, 0x697f, + 0x72b8, 0x799e, 0x7e0d, 0x7fee, 0x7f37, 0x7bed, 0x761f, 0x6ded, 0x6380, 0x570f, 0x48db, 0x392c, 0x2855, 0x16ad, 0x048f, 0xf259, + 0xe06b, 0xcf20, 0xbed2, 0xafd7, 0xa27c, 0x9705, 0x8db0, 0x86ab, 0x821c, 0x801a, 0x80b0, 0x83da, 0x8988, 0x919c, 0x9bee, 0xa846, + 0xb666, 0xc603, 0xd6ce, 0xe86e, 0xfa88, 0x0cbf, 0x1eb3, 0x3008, 0x4064, 0x4f73, 0x5ce4, 0x6874, 0x71e6, 0x790a, 0x7db9, 0x7fdc, + 0x7f68, 0x7c5e, 0x76d0, 0x6ed9, 0x64a3, 0x5863, 0x4a59, 0x3acc, 0x2a0f, 0x1878, 0x0661, 0xf42a, 0xe230, 0xd0d0, 0xc066, 0xb145, + 0xa3bd, 0x9813, 0x8e85, 0x8743, 0x8274, 0x8030, 0x8083, 0x836b, 0x88da, 0x90b3, 0x9acd, 0xa6f5, 0xb4ea, 0xc465, 0xd515, 0xe6a3, + 0xf8b6, 0x0aee, 0x1ced, 0x2e56, 0x3ecf, 0x4e02, 0x5ba1, 0x6764, 0x710e, 0x786f, 0x7d5e, 0x7fc3, 0x7f91, 0x7cc9, 0x777a, 0x6fc0, + 0x65c1, 0x59b3, 0x4bd3, 0x3c6a, 0x2bc7, 0x1a41, 0x0833, 0xf5fb, 0xe3f6, 0xd283, 0xc1fc, 0xb2b7, 0xa503, 0x9926, 0x8f60, 0x87e1, + 0x82d2, 0x804c, 0x805d, 0x8303, 0x8833, 0x8fcf, 0x99b2, 0xa5a8, 0xb372, 0xc2c9, 0xd35e, 0xe4da, 0xf6e4, 0x091c, 0x1b26, 0x2ca2, + 0x3d37, 0x4c8e, 0x5a58, 0x664e, 0x7031, 0x77cd, 0x7cfd, 0x7fa3, 0x7fb4, 0x7d2e, 0x781f, 0x70a0, 0x66da, 0x5afd, 0x4d49, 0x3e04, + 0x2d7d, 0x1c0a, 0x0a05, 0xf7cd, 0xe5bf, 0xd439, 0xc396, 0xb42d, 0xa64d, 0x9a3f, 0x9040, 0x8886, 0x8337, 0x806f, 0x803d, 0x82a2, + 0x8791, 0x8ef2, 0x989c, 0xa45f, 0xb1fe, 0xc131, 0xd1aa, 0xe313, 0xf512, 0x074a, 0x195d, 0x2aeb, 0x3b9b, 0x4b16, 0x590b, 0x6533, + 0x6f4d, 0x7726, 0x7c95, 0x7f7d, 0x7fd0, 0x7d8c, 0x78bd, 0x717b, 0x67ed, 0x5c43, 0x4ebb, 0x3f9a, 0x2f30, 0x1dd0, 0x0bd6, 0xf99f, + 0xe788, 0xd5f1, 0xc534, 0xb5a7, 0xa79d, 0x9b5d, 0x9127, 0x8930, 0x83a2, 0x8098, 0x8024, 0x8247, 0x86f6, 0x8e1a, 0x978c, 0xa31c, + 0xb08d, 0xbf9c, 0xcff8, 0xe14d, 0xf341, 0x0578, 0x1792, 0x2932, 0x39fd, 0x499a, 0x57ba, 0x6412, 0x6e64, 0x7678, 0x7c26, 0x7f50, + 0x7fe6, 0x7de4, 0x7955, 0x7250, 0x68fb, 0x5d84, 0x5029, 0x412e, 0x30e0, 0x1f95, 0x0da7, 0xfb71, 0xe953, 0xd7ab, 0xc6d4, 0xb725, + 0xa8f1, 0x9c80, 0x9213, 0x89e1, 0x8413, 0x80c9, 0x8012, 0x81f3, 0x8662, 0x8d48, 0x9681, 0xa1dd, 0xaf22, 0xbe0a, 0xce48, 0xdf89, + 0xf171, 0x03a6, 0x15c7, 0x2777, 0x385b, 0x481a, 0x5664, 0x62ed, 0x6d74, 0x75c4, 0x7bb2, 0x7f1d, 0x7ff5, 0x7e35, 0x79e6, 0x731f, + 0x6a03, 0x5ec1, 0x5193, 0x42be, 0x328f, 0x2159, 0x0f77, 0xfd44, 0xeb1f, 0xd967, 0xc877, 0xb8a7, 0xaa49, 0x9da8, 0x9305, 0x8a98, + 0x848b, 0x80ff, 0x8006, 0x81a5, 0x85d3, 0x8c7c, 0x957b, 0xa0a3, 0xadba, 0xbc7b, 0xcc9b, 0xddc6, 0xefa2, 0x01d3, 0x13fa, 0x25ba, + 0x36b6, 0x4697, 0x5509, 0x61c2, 0x6c80, 0x750b, 0x7b36, 0x7ee3, 0x7ffd, 0x7e7f, 0x7a71, 0x73e8, 0x6b06, 0x5ff8, 0x52f8, 0x444a, + 0x343a, 0x231b, 0x1146, 0xff17, 0xecec, 0xdb25, 0xca1d, 0xba2c, 0xaba6, 0x9ed6, 0x93fd, 0x8b55, 0x850a, 0x813d, 0x8001, 0x815e, + 0x854b, 0x8bb5, 0x947b, 0x9f6e, 0xac56, 0xbaf1, 0xcaf1, 0xdc05, 0xedd3 +}; +static u16 tx_s_cnt = 0; +int get_sine_data(u16 *s_cnt, s16 *data, u16 points, u8 ch) +{ + while (points--) { + if (*s_cnt >= 441) { + *s_cnt = 0; + } + *data++ = tsin_441k[*s_cnt]; + if (ch == 2) { + *data++ = tsin_441k[*s_cnt]; + } + (*s_cnt)++; + } + return 0; +} + +u32 data_buf[2][ALNK_BUF_POINTS_NUM * 2] __attribute__((aligned(4))); + +void handle_tx(u8 ch, void *buf, u16 len) +{ + get_sine_data(&tx_s_cnt, buf, len / 2 / 2, 2); + /* put_buf(buf, 32); */ +#if 0 + s16 *data_tx = (s16 *)buf; + s16 *data = (s16 *)data_buf; + for (int i = 0; i < len / sizeof(s16) ; i++) { + /* data_tx[i] = data[i]; */ + data_tx[i] = 0x5a5a; + } +#endif +} + +void handle_rx(u8 ch, void *buf, u16 len) +{ + /* put_buf(buf, 32); */ +#if 0 + s16 *data_rx = (s16 *)buf; + s16 *data_b = (s16 *)data_buf; + for (int i = 0; i < len / sizeof(s16) ; i++) { + data_b[i] = data_rx[i]; + } +#endif +} + +ALINK_PARM test_alink0 = { + /* .port_select = ALINK0_PORTA, //MCLK:PA8 SCLK:PA2 LRCK:PA3 CH0:PA4 CH1:PA5 CH2:PA6 CH3:PA7 */ + .port_select = ALINK0_PORTB, //MCLK:PA15 SCLK:PA9 LRCK:PA10 CH0:PA11 CH1:PA12 CH2:PA13 CH3:PA14 + /* .port_select = ALINK1_PORTA, //MCLK:PB0 SCLK:PC0 LRCK:PC1 CH0:PC2 CH1:PC3 CH2:PC4 CH3:PC5 */ + .ch_cfg[0].enable = 1, + .ch_cfg[1].enable = 1, + .mode = ALINK_MD_IIS, + /* .role = ALINK_ROLE_SLAVE, */ + .role = ALINK_ROLE_MASTER, + .clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE, + .bitwide = ALINK_LEN_16BIT, + .sclk_per_frame = ALINK_FRAME_64SCLK, + /* .sclk_per_frame = ALINK_FRAME_32SCLK, */ + .dma_len = ALNK_BUF_POINTS_NUM * 2 * 2 * 2, + .sample_rate = 44100, +}; + +ALINK_PARM test_alink1 = { + /* .port_select = ALINK0_PORTA, //MCLK:PA8 SCLK:PA2 LRCK:PA3 CH0:PA4 CH1:PA5 CH2:PA6 CH3:PA7 */ + /* .port_select = ALINK0_PORTB, //MCLK:PA15 SCLK:PA9 LRCK:PA10 CH0:PA11 CH1:PA12 CH2:PA13 CH3:PA14 */ + .port_select = ALINK1_PORTA, //MCLK:PB0 SCLK:PC0 LRCK:PC1 CH0:PC2 CH1:PC3 CH2:PC4 CH3:PC5 + .ch_cfg[0].enable = 1, + .ch_cfg[1].enable = 1, + .mode = ALINK_MD_IIS, + /* .role = ALINK_ROLE_SLAVE, */ + .role = ALINK_ROLE_MASTER, + .clk_mode = ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE, + .bitwide = ALINK_LEN_16BIT, + .sclk_per_frame = ALINK_FRAME_64SCLK, + /* .sclk_per_frame = ALINK_FRAME_32SCLK, */ + .dma_len = ALNK_BUF_POINTS_NUM * 2 * 2 * 2, + .sample_rate = 44100, +}; + + +void audio_link_test(void) +{ +#if 0 + alink_init(&test_alink0); + /* alink_channel_init(ALINK1_PORTA, 0, ALINK_DIR_RX, handle_rx); */ + alink_channel_init(ALINK0_PORTB, 1, ALINK_DIR_TX, handle_tx); + alink_start(ALINK0_PORTB); + alink_info_dump(ALINK0_PORTB); +#endif + +#if 0 + alink_init(&test_alink1); + /* alink_channel_init(ALINK1_PORTA, 0, ALINK_DIR_RX, handle_rx); */ + alink_channel_init(ALINK1_PORTA, 1, ALINK_DIR_TX, handle_tx); + alink_start(ALINK1_PORTA); + alink_info_dump(ALINK1_PORTA); +#endif +} + + +#endif + + +#endif + diff --git a/cpu/br23/audio_common/audio_link.h b/cpu/br23/audio_common/audio_link.h new file mode 100644 index 0000000..ba5a989 --- /dev/null +++ b/cpu/br23/audio_common/audio_link.h @@ -0,0 +1,101 @@ +#ifndef _AUDIO_LINK_H_ +#define _AUDIO_LINK_H_ + +//ch_num +#define ALINK_CH0 0 +#define ALINK_CH1 1 +#define ALINK_CH2 2 +#define ALINK_CH3 3 + +#define ALNK_BUF_POINTS_NUM 128 + +typedef enum { + ALINK0_PORTA, //MCLK:PA8 SCLK:PA2 LRCK:PA3 CH0:PA4 CH1:PA5 CH2:PA6 CH3:PA7 + ALINK0_PORTB, //MCLK:PA15 SCLK:PA9 LRCK:PA10 CH0:PA11 CH1:PA12 CH2:PA13 CH3:PA14 + ALINK1_PORTA, //MCLK:PB0 SCLK:PC0 LRCK:PC1 CH0:PC2 CH1:PC3 CH2:PC4 CH3:PC5 +} ALINK_PORT; + +//ch_dir +typedef enum { + ALINK_DIR_TX = 0u, + ALINK_DIR_RX , +} ALINK_DIR; + +typedef enum { + ALINK_LEN_16BIT = 0u, + ALINK_LEN_24BIT , //ALINK_FRAME_MODE需要选择: ALINK_FRAME_64SCLK +} ALINK_DATA_WIDTH; + +//ch_mode +typedef enum { + ALINK_MD_NONE = 0u, + ALINK_MD_IIS , + ALINK_MD_IIS_LALIGN , + ALINK_MD_IIS_RALIGN , + ALINK_MD_DSP0 , + ALINK_MD_DSP1 , +} ALINK_MODE; + +//ch_mode +typedef enum { + ALINK_ROLE_MASTER, //主机 + ALINK_ROLE_SLAVE, //从机 +} ALINK_ROLE; + +typedef enum { + ALINK_CLK_FALL_UPDATE_RAISE_SAMPLE, //下降沿更新数据, 上升沿采样数据 + ALINK_CLK_RAISE_UPDATE_FALL_SAMPLE, //上降沿更新数据, 下升沿采样数据 +} ALINK_CLK_MODE; + +typedef enum { + ALINK_FRAME_32SCLK, //32 sclk/frame + ALINK_FRAME_64SCLK, //64 sclk/frame +} ALINK_FRAME_MODE; + +typedef enum { + ALINK_SR_48000 = 48000, + ALINK_SR_44100 = 44100, + ALINK_SR_32000 = 32000, + ALINK_SR_24000 = 24000, + ALINK_SR_22050 = 22050, + ALINK_SR_16000 = 16000, + ALINK_SR_12000 = 12000, + ALINK_SR_11025 = 11025, + ALINK_SR_8000 = 8000, +} ALINK_SR; + +struct alnk_ch_cfg { + u8 enable; + ALINK_DIR dir; //通道传输数据方向: Tx, Rx + void *buf; //dma buf地址 + void (*isr_cb)(u8 ch, s16 *buf, u32 len); +}; + +//===================================// +//多个通道使用需要注意: +//1.数据位宽需要保持一致 +//2.buf长度相同 +//===================================// +typedef struct _ALINK_PARM { + u8 port_select; + struct alnk_ch_cfg ch_cfg[4]; //通道内部配置 + ALINK_MODE mode; //IIS, left, right, dsp0, dsp1 + ALINK_ROLE role; //主机/从机 + ALINK_CLK_MODE clk_mode; //更新和采样边沿 + ALINK_DATA_WIDTH bitwide; //数据位宽16/32bit + ALINK_FRAME_MODE sclk_per_frame; //32/64 sclk/frame + u16 dma_len; //buf长度: byte + ALINK_SR sample_rate; //采样率 +} ALINK_PARM; + +int alink_init(ALINK_PARM *parm); //iis 初始化 +int alink_start(ALINK_PORT port); //iis 开启 +void alink_channel_init(ALINK_PORT port, u8 ch_idx, u8 dir, void (*handle)(u8 ch, s16 *buf, u32 len)); //iis 打开通道 +void alink_channel_close(ALINK_PORT port, u8 ch_idx); //iis 关闭通道 +int alink_sr_set(ALINK_PORT port, u16 sr); //iis 设置采样率 +void alink_uninit(ALINK_PORT port); //iis 退出 + +void audio_link_init(ALINK_PORT port); +void audio_link_uninit(ALINK_PORT port); + +#endif diff --git a/cpu/br23/audio_config.h b/cpu/br23/audio_config.h new file mode 100644 index 0000000..34f3d21 --- /dev/null +++ b/cpu/br23/audio_config.h @@ -0,0 +1,190 @@ +#ifndef _AUDIO_CONFIG_H_ +#define _AUDIO_CONFIG_H_ + +#include "generic/typedef.h" +#include "board_config.h" + +#if(defined(CONFIG_MIXER_CYCLIC)&&(SOUNDCARD_ENABLE)) +#define AUDIO_MIXER_LEN (128 * 2 * 2 * 6) +#else +#define AUDIO_MIXER_LEN (128 * 2 * 2) +#endif + +#if (SOUNDCARD_ENABLE) +#define AUDIO_SYNTHESIS_LEN (AUDIO_MIXER_LEN * 4) +#else +#define AUDIO_SYNTHESIS_LEN (AUDIO_MIXER_LEN * 2) +#endif + +/*解码任务cpu占用率跟踪*/ +#define TCFG_AUDIO_DECODER_OCCUPY_TRACE 1 + +#if BT_SUPPORT_MUSIC_VOL_SYNC +#define TCFG_MAX_VOL_PROMPT 0 +#else +#define TCFG_MAX_VOL_PROMPT 1 +#endif + +/* + *该配置适用于没有音量按键的产品,防止打开音量同步之后 + *连接支持音量同步的设备,将音量调小过后,连接不支持音 + *量同步的设备,音量没有恢复,导致音量小的问题 + *默认是没有音量同步的,将音量设置到最大值,可以在vol_sync.c + *该宏里面修改相应的设置。 + */ +#define TCFG_VOL_RESET_WHEN_NO_SUPPORT_VOL_SYNC 0 //不支持音量同步的设备默认最大音量 + +/* + *省电容mic偏置电压自动调整(因为校准需要时间,所以有不同的方式) + *1、烧完程序(完全更新,包括配置区)开机校准一次 + *2、上电复位的时候都校准,即断电重新上电就会校准是否有偏差(默认) + *3、每次开机都校准,不管有没有断过电,即校准流程每次都跑 + */ +#define MC_BIAS_ADJUST_DISABLE 0 //省电容mic偏置校准关闭 +#define MC_BIAS_ADJUST_ONE 1 //省电容mic偏置只校准一次(跟dac trim一样) +#define MC_BIAS_ADJUST_POWER_ON 2 //省电容mic偏置每次上电复位都校准(Power_On_Reset) +#define MC_BIAS_ADJUST_ALWAYS 3 //省电容mic偏置每次开机都校准(包括上电复位和其他复位) +#if TCFG_MIC_CAPLESS_ENABLE +#define TCFG_MC_BIAS_AUTO_ADJUST MC_BIAS_ADJUST_POWER_ON +#else +#define TCFG_MC_BIAS_AUTO_ADJUST MC_BIAS_ADJUST_DISABLE +#endif/*TCFG_MIC_CAPLESS_ENABLE*/ +#define TCFG_MC_CONVERGE_TRACE 0 //省电容mic收敛值跟踪 +/* + *省电容mic收敛步进限制 + *0:自适应步进调整, >0:收敛步进最大值 + *注:当mic的模拟增益或者数字增益很大的时候,mic_capless模式收敛过程, + *变化的电压放大后,可能会听到哒哒声,这个时候就可以限制住这个收敛步进 + *让收敛平缓进行(前提是预收敛成功的情况下) + */ +#define TCFG_MC_DTB_STEP_LIMIT 15 //最大收敛步进值 + +#if TCFG_USER_BLE_ENABLE +#define TCFG_AEC_SIMPLEX 0 //通话单工模式配置 +#else +#define TCFG_AEC_SIMPLEX 0 //通话单工模式配置 +#endif + +#define TCFG_ESCO_PLC 1 //通话丢包修复 +#define TCFG_DIG_PHASE_INVERTER_EN 1 //数字反相器,用来矫正DAC的输出相位 +#define TCFG_AUDIO_CONFIG_TRACE 0 //音频模块配置跟踪查看 + +#define TCFG_ESCO_LIMITER 0 //通话近端底噪/限幅器 + +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_MONO_LR_DIFF || \ + TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF) +#define MAX_ANA_VOL (21) +#else +#define MAX_ANA_VOL (28) +#endif/*TCFG_AUDIO_DAC_CONNECT_MODE*/ + +#define MAX_COM_VOL (22) // 具体数值应小于联合音量等级的数组大小 (combined_vol_list) +#define MAX_DIG_VOL (100) + +#define MAX_DIG_GR_VOL (30)//数字音量组的最大值 + +#if ((SYS_VOL_TYPE == VOL_TYPE_DIGITAL) || (SYS_VOL_TYPE == VOL_TYPE_DIGITAL_HW)) +#define SYS_MAX_VOL MAX_DIG_VOL +#elif (SYS_VOL_TYPE == VOL_TYPE_ANALOG) +#define SYS_MAX_VOL MAX_ANA_VOL +#elif (SYS_VOL_TYPE == VOL_TYPE_AD) +#define SYS_MAX_VOL MAX_COM_VOL +#elif (SYS_VOL_TYPE == VOL_TYPE_DIGGROUP) +#define SYS_MAX_VOL MAX_DIG_GR_VOL +#else +#error "SYS_VOL_TYPE define error" +#endif + + +#define SYS_DEFAULT_VOL 0//SYS_MAX_VOL //(SYS_MAX_VOL/2) +#define SYS_DEFAULT_TONE_VOL 18 //(SYS_MAX_VOL) +#define SYS_DEFAULT_SIN_VOL 17 + +#define APP_AUDIO_STATE_IDLE 0 +#define APP_AUDIO_STATE_MUSIC 1 +#define APP_AUDIO_STATE_CALL 2 +#define APP_AUDIO_STATE_WTONE 3 +#define APP_AUDIO_STATE_LINEIN 4 +#define APP_AUDIO_CURRENT_STATE 5 + +#define APP_AUDIO_MAX_STATE (APP_AUDIO_CURRENT_STATE + 1) + +#ifdef TCFG_IIS_ENABLE +#define AUDIO_OUTPUT_ONLY_IIS \ + (TCFG_IIS_ENABLE && TCFG_IIS_OUTPUT_EN && AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) + +#define AUDIO_OUTPUT_DAC_AND_IIS \ + (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC_IIS && TCFG_IIS_ENABLE && TCFG_IIS_OUTPUT_EN) +#else +#define AUDIO_OUTPUT_ONLY_IIS 0 + +#define AUDIO_OUTPUT_DAC_AND_IIS (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC_IIS) + +#endif + +#define AUDIO_OUTPUT_INCLUDE_IIS (AUDIO_OUTPUT_ONLY_IIS || AUDIO_OUTPUT_DAC_AND_IIS) + +#define AUDIO_OUTPUT_ONLY_DAC (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC) +#define AUDIO_OUTPUT_INCLUDE_DAC ((AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC) \ + || (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) \ + || (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DONGLE) \ + || (AUDIO_OUTPUT_DAC_AND_IIS)) + + +u8 get_max_sys_vol(void); +u8 get_tone_vol(void); + +void app_audio_output_init(void); +void app_audio_output_sync_buff_init(void *sync_buff, int len); +int app_audio_output_channel_set(u8 output); +int app_audio_output_channel_get(void); +int app_audio_output_mode_set(u8 output); +int app_audio_output_mode_get(void); +int app_audio_output_write(void *buf, int len); +int app_audio_output_samplerate_select(u32 sample_rate, u8 high); +int app_audio_output_samplerate_set(int sample_rate); +int app_audio_output_samplerate_get(void); +int app_audio_output_start(void); +int app_audio_output_stop(void); +int app_audio_output_reset(u32 msecs); +int app_audio_output_state_get(void); +int app_audio_output_get_cur_buf_points(void); +void app_audio_output_ch_mute(u8 ch, u8 mute); +int app_audio_output_ch_analog_gain_set(u8 ch, u8 again); +s8 app_audio_get_volume(u8 state); +void app_audio_set_volume(u8 state, s8 volume, u8 fade); +void app_audio_volume_up(u8 value); +void app_audio_volume_down(u8 value); +void app_audio_state_switch(u8 state, s16 max_volume); +void app_audio_mute(u8 value); +s16 app_audio_get_max_volume(void); +void app_audio_state_switch(u8 state, s16 max_volume); +void app_audio_state_exit(u8 state); +u8 app_audio_get_state(void); +void volume_up_down_direct(s8 value); +void app_audio_set_mix_volume(u8 front_volume, u8 back_volume); +void app_audio_volume_init(void); +void app_audio_set_digital_volume(s16 volume); +void dac_trim_hook(u8 pos); + +int audio_output_buf_time(void); +int audio_output_dev_is_working(void); +int audio_output_sync_start(void); +int audio_output_sync_stop(void); + +void app_set_sys_vol(s16 vol_l, s16 vol_r); +void app_set_max_vol(s16 vol); + +u32 phone_call_eq_open(); +int eq_mode_sw(); +int mic_test_start(); +int mic_test_stop(); + +void dac_power_on(void); +void dac_power_off(void); + +/*打印audio模块的数字模拟增益:DAC/ADC*/ +void audio_gain_dump(); +void audio_adda_dump(void); //打印所有的dac,adc寄存器 + +#endif/*_AUDIO_CONFIG_H_*/ diff --git a/cpu/br23/audio_dec/audio_dec.c b/cpu/br23/audio_dec/audio_dec.c new file mode 100644 index 0000000..167789f --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec.c @@ -0,0 +1,1217 @@ +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "classic/tws_api.h" +#include "classic/hci_lmp.h" +#include "effectrs_sync.h" +#include "media/audio_eq_drc_apply.h" +#include "app_config.h" +#include "audio_config.h" +#include "audio_enc.h" +#include "audio_dec.h" +#include "app_main.h" +#include "audio_digital_vol.h" +/* #include "fm_emitter/fm_emitter_manage.h" */ +/* #include "asm/audio_spdif.h" */ +#include "clock_cfg.h" +#include "btstack/avctp_user.h" +#include "application/audio_output_dac.h" +#include "application/audio_energy_detect.h" +#include "application/audio_dig_vol.h" +#include "media/audio_equalloudness_eq.h" +#include "audio_spectrum.h" +#include "application/audio_vocal_remove.h" +#include "audio_effect/audio_sound_track_2_p_x.h" +#include "audio_utils.h" + +#if TCFG_USER_TWS_ENABLE +#include "bt_tws.h" +#endif + +#ifndef CONFIG_LITE_AUDIO +#include "aec_user.h" +#include "encode/encode_write.h" +#include "common/Resample_api.h" +#include "audio_link.h" +#include "audio_common/audio_iis.h" +#include "audio_fmtx.h" +#include "audio_sbc_codec.h" +#endif /*CONFIG_LITE_AUDIO*/ + +#if (AUDIO_OUTPUT_INCLUDE_IIS) +void *iis_digvol_last = NULL; +void *iis_digvol_last_entry = NULL; +struct audio_stream_entry *iis_last_entry = NULL; +#endif + +#if AUDIO_OUTPUT_AUTOMUTE +void *mix_out_automute_hdl = NULL; +void *mix_out_automute_entry = NULL; +extern void mix_out_automute_open(); +extern void mix_out_automute_close(); +#endif + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) +void *bt_digvol_last = NULL; +void *bt_digvol_last_entry = NULL; +#endif + +#if (TCFG_APP_FM_EMITTER_EN) +void *fmtx_digvol_last = NULL; +void *fmtx_digvol_last_entry = NULL; +struct audio_stream_entry *fmtx_last_entry = NULL; +#endif + +#define AUDIO_CODEC_SUPPORT_SYNC 1 // 同步 + +#if (RECORDER_MIX_EN) +#define MAX_SRC_NUMBER 5 // 最大支持src个数 +#else +#define MAX_SRC_NUMBER 3 // 最大支持src个数 +#endif/*RECORDER_MIX_EN*/ + +#define AUDIO_DECODE_TASK_WAKEUP_TIME 0 // 解码定时唤醒 // ms + +////////////////////////////////////////////////////////////////////////////// + +struct audio_decoder_task decode_task = {0}; +struct audio_mixer mixer = {0}; +/*struct audio_stream_dac_out *dac_last = NULL;*/ + +#if TCFG_MIXER_CYCLIC_TASK_EN +struct audio_mixer_task mixer_task = {0}; +#endif + +#if TCFG_DEC2TWS_TASK_ENABLE +struct audio_decoder_task localtws_decode_task = {0}; +#endif + +static u8 audio_dec_inited = 0; + +#if AUDIO_EQUALLOUDNESS_CONFIG +loudness_hdl *loudness; +#endif + +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) +#if !TCFG_EQ_DIVIDE_ENABLE +struct channel_switch *mix_ch_switch = NULL;//声道变换 +#endif +#endif + +u8 audio_src_hw_filt[SRC_FILT_POINTS * SRC_CHI * 2 * MAX_SRC_NUMBER] ALIGNED(4); /*SRC的滤波器必须4个byte对齐*/ +s16 mix_buff[AUDIO_MIXER_LEN / 2] SEC(.dec_mix_buff); +#if (RECORDER_MIX_EN) +struct audio_mixer recorder_mixer = {0}; +s16 recorder_mix_buff[AUDIO_MIXER_LEN / 2] SEC(.dec_mix_buff); +#endif/*RECORDER_MIX_EN*/ + + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC) +#if AUDIO_CODEC_SUPPORT_SYNC +s16 dac_sync_buff[256]; +#endif +#endif + +#if AUDIO_VOCAL_REMOVE_EN +vocal_remove_hdl *mix_vocal_remove_hdl = NULL; +void *vocal_remove_open(u8 ch_num); +struct channel_switch *vocal_remove_mix_ch_switch = NULL;//声道变换,单声道时,先让解码出立体声,做完人声消除,再变单声道 +#endif + + +extern const int config_mixer_en; + +#define AUDIO_DEC_MIXER_EN config_mixer_en + +////////////////////////////////////////////////////////////////////////////// + +#if AUDIO_SPECTRUM_CONFIG +extern spectrum_fft_hdl *spec_hdl; +#endif + + +#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) &&SOUND_TRACK_2_P_X_CH_CONFIG +static float bass_gain = 0; +//低音调节测试例子 +void sound_track_bass_vol_test_demo(u8 up_down) +{ + if (up_down) { + bass_gain++; + } else { + bass_gain--; + } + if (bass_gain > 6) { + bass_gain = 6; + tone_play_by_path(TONE_NORMAL, 0); //播放一段正弦波 + } + if (bass_gain < -6) { + bass_gain = -6; + tone_play_by_path(TONE_NORMAL, 0); //播放一段正弦波 + } + //printf("=====bass gain %d\n", (int)bass_gain); + low_bass_set_global_gain(bass_gain, bass_gain); +} + +#endif/*defined(SOUND_TRACK_2_P_X_CH_CONFIG) &&SOUND_TRACK_2_P_X_CH_CONFIG*/ + +////////////////////////////////////////////////////////////////////////////// +struct _audio_phase_inver_hdl { + struct audio_stream_entry entry; // 音频流入口 +} audio_phase_inver_hdl; + +static void audio_phase_inver_output_data_process_len(struct audio_stream_entry *entry, int len) +{ +} + +static int audio_phase_inver_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + struct _audio_phase_inver_hdl *hdl = container_of(entry, struct _audio_phase_inver_hdl, entry); + out->data = in->data; + out->data_len = in->data_len; + if (in->data_len - in->offset > 0) { + digital_phase_inverter_s16(in->data + in->offset / 2, in->data_len - in->offset); + } + return in->data_len; +} + +////////////////////////////////////////////////////////////////////////////// + + + + + +/*----------------------------------------------------------------------------*/ +/**@brief 获取dac能量值 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_dac_energy_get(void) +{ +#if AUDIO_OUTPUT_AUTOMUTE + int audio_energy_detect_energy_get(void *_hdl, u8 ch); + if (mix_out_automute_hdl) { + return audio_energy_detect_energy_get(mix_out_automute_hdl, BIT(0)); + } + + return (-1); +#else + return 0; +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 激活所有解码 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_resume_all_decoder(void) +{ + audio_decoder_resume_all(&decode_task); +#if TCFG_DEC2TWS_TASK_ENABLE + audio_decoder_resume_all(&localtws_decode_task); +#endif +} + + +#if AUDIO_DECODE_TASK_WAKEUP_TIME +#include "timer.h" +/*----------------------------------------------------------------------------*/ +/**@brief 解码定时处理 + @param *priv: 私有参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void audio_decoder_wakeup_timer(void *priv) +{ + //putchar('k'); + struct audio_decoder_task *task = priv; + audio_decoder_resume_all(task); +} +/*----------------------------------------------------------------------------*/ +/**@brief 添加一个解码预处理 + @param *task: 解码任务 + @return 0: ok + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +int audio_decoder_task_add_probe(struct audio_decoder_task *task) +{ + if (task->wakeup_timer == 0) { + task->wakeup_timer = sys_hi_timer_add(task, audio_decoder_wakeup_timer, AUDIO_DECODE_TASK_WAKEUP_TIME); + log_i("audio_decoder_task_add_probe:%d\n", task->wakeup_timer); + } + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief 删除一个解码预处理 + @param *task: 解码任务 + @return 0: ok + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +int audio_decoder_task_del_probe(struct audio_decoder_task *task) +{ + log_i("audio_decoder_task_del_probe\n"); + if (audio_decoder_task_wait_state(task) > 0) { + /*解码任务列表还有任务*/ + return 0; + } + if (task->wakeup_timer) { + log_i("audio_decoder_task_del_probe:%d\n", task->wakeup_timer); + sys_hi_timer_del(task->wakeup_timer); + task->wakeup_timer = 0; + } + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief 重定义唤醒时间 + @param msecs: 唤醒时间ms + @return 0: ok + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_decoder_wakeup_modify(int msecs) +{ + if (decode_task.wakeup_timer) { + sys_hi_timer_modify(decode_task.wakeup_timer, msecs); + } + + return 0; +} +#endif/*AUDIO_DECODE_TASK_WAKEUP_TIME*/ + +/*----------------------------------------------------------------------------*/ +/**@brief 各模式主解码open + @param state: 参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_mode_main_dec_open(u32 state) +{ +#if 0 + // 等待提示音解码完 + tone_dec_wait_stop(200); + // 等待当前dac中的数据输出完 + os_time_dly(audio_output_buf_time() / 10 + 1); +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 获取输出默认采样率 + @param + @return 0: 采样率可变 + @return 非0: 固定采样率 + @note +*/ +/*----------------------------------------------------------------------------*/ +u32 audio_output_nor_rate(void) +{ +#if (TCFG_IIS_ENABLE && TCFG_IIS_OUTPUT_EN) + /* return 0; */ + return TCFG_IIS_OUTPUT_SR; +#endif +#if TCFG_SPDIF_ENABLE + return 44100; +#endif + +#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) &&SOUND_TRACK_2_P_X_CH_CONFIG + return 44100; +#endif + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC) + +#if (TCFG_MIC_EFFECT_ENABLE) + return TCFG_REVERB_SAMPLERATE_DEFUAL; +#endif + /* return app_audio_output_samplerate_select(input_rate, 1); */ +#elif (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) + +#elif (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) + return 41667; +#else + return 44100; +#endif + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 获取输出采样率 + @param input_rate: 输入采样率 + @return 输出采样率 + @note +*/ +/*----------------------------------------------------------------------------*/ +u32 audio_output_rate(int input_rate) +{ + u32 out_rate = audio_output_nor_rate(); + if (out_rate) { + return out_rate; + } + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) + if ((bt_user_priv_var.emitter_or_receiver == BT_EMITTER_EN) && (!bt_phone_dec_is_running()) + && (!bt_media_is_running())) { + y_printf("+++ \n"); + return audio_sbc_enc_get_rate(); + } +#elif (AUDIO_OUTPUT_WAY_DONGLE && AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DONGLE) + return DONGLE_OUTPUT_SAMPLE_RATE; +#endif + +#if (TCFG_MIC_EFFECT_ENABLE) + if (input_rate > 48000) { + return 48000; + } +#endif + //y_printf("+++ 11 \n"); + return app_audio_output_samplerate_select(input_rate, 1); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 获取输出通道数 + @param + @return 输出通道数 + @note +*/ +/*----------------------------------------------------------------------------*/ +u32 audio_output_channel_num(void) +{ +#if ((AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC) || (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT)) + /*根据DAC输出的方式选择输出的声道*/ + u8 dac_connect_mode = app_audio_output_mode_get(); + if (dac_connect_mode == DAC_OUTPUT_LR || dac_connect_mode == DAC_OUTPUT_DUAL_LR_DIFF) { + return 2; + } else if (dac_connect_mode == DAC_OUTPUT_FRONT_LR_REAR_LR) { + return 2; + } else { +#if AUDIO_VOCAL_REMOVE_EN + return 2; +#endif + return 1; + } +#elif (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) + return 2; +#else + return 2; +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 获取输出通道类型 + @param + @return 输出通道类型 + @note +*/ +/*----------------------------------------------------------------------------*/ +u32 audio_output_channel_type(void) +{ +#if ((AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC) || (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT)) + /*根据DAC输出的方式选择输出的声道*/ + u8 dac_connect_mode = app_audio_output_mode_get(); + if (dac_connect_mode == DAC_OUTPUT_LR || dac_connect_mode == DAC_OUTPUT_DUAL_LR_DIFF) { + return AUDIO_CH_LR; + } else if (dac_connect_mode == DAC_OUTPUT_FRONT_LR_REAR_LR) { + return AUDIO_CH_LR; + } else if (dac_connect_mode == DAC_OUTPUT_MONO_L) { + return AUDIO_CH_DIFF; //要输出左右合成的单声道数据选这个 + /* return AUDIO_CH_L; */ //只要输出左声道的数据选这个 + } else if (dac_connect_mode == DAC_OUTPUT_MONO_R) { + + return AUDIO_CH_DIFF; //要输出左右合成的单声道数据选这个 + + /* return AUDIO_CH_R; */ //只要输出右声道的数据选这个 + + } else { + return AUDIO_CH_DIFF; + } +#elif (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) + return AUDIO_CH_LR; +#else + return AUDIO_CH_LR; +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 设置输出音量状态 + @param state: 输出音量状态 + @return 0: ok + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_output_set_start_volume(u8 state) +{ + s16 vol_max = get_max_sys_vol(); + if (state == APP_AUDIO_STATE_CALL) { + vol_max = app_var.aec_dac_gain; + } + app_audio_state_switch(state, vol_max); + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 开始音频输出 + @param sample_rate: 输出采样率 + @param reset_rate: 更新输出采样率 + @return 0: ok + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 audio_output_flag = 0; +int audio_output_start(u32 sample_rate, u8 reset_rate) +{ + if (reset_rate) { + app_audio_output_samplerate_set(sample_rate); + } + + if (audio_output_flag) { + return 0; + } + + audio_output_flag = 1; + app_audio_output_start(); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭音频输出 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_output_stop(void) +{ + audio_output_flag = 0; + + app_audio_output_stop(); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 打开一个变采样通道 + @param *priv: output回调私有句柄 + @param *output_handler: 变采样输出回调 + @param *channel: 声道数 + @param *input_sample_rate: 输入采样率 + @param *output_sample_rate: 输出采样率 + @return 变采样句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +struct audio_src_handle *audio_hw_resample_open(void *priv, + int (*output_handler)(void *, void *, int), + u8 channel, + u16 input_sample_rate, + u16 output_sample_rate) +{ + struct audio_src_handle *hdl; + hdl = zalloc(sizeof(struct audio_src_handle)); + if (hdl) { + audio_hw_src_open(hdl, channel, SRC_TYPE_RESAMPLE); + audio_hw_src_set_rate(hdl, input_sample_rate, output_sample_rate); + audio_src_set_output_handler(hdl, priv, output_handler); + } + + return hdl; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭变采样 + @param *hdl: 变采样句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_hw_resample_close(struct audio_src_handle *hdl) +{ + if (hdl) { + audio_hw_src_stop(hdl); + audio_hw_src_close(hdl); + free(hdl); + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief mixer事件处理 + @param *mixer: 句柄 + @param event: 事件 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void mixer_event_handler(struct audio_mixer *mixer, int event) +{ + switch (event) { + case MIXER_EVENT_OPEN: + if (audio_mixer_get_ch_num(mixer) >= 1) { + clock_add_set(DEC_MIX_CLK); + } + break; + case MIXER_EVENT_CLOSE: + if (audio_mixer_get_ch_num(mixer) == 0) { + clock_remove_set(DEC_MIX_CLK); + } + if (config_mixer_en) { + os_mutex_pend(&mixer->mutex, 0); + if (audio_mixer_get_active_ch_num(mixer) == 0) { + /*输出通道可以进行stop处理*/ + audio_mixer_output_stop(mixer); + //通道关闭时,清掉节点记录的偏移,防止下个解码打开时,mix之后的同步节点断言 + audio_stream_clear_from(&mixer->entry); + } + os_mutex_post(&mixer->mutex); + } + break; + case MIXER_EVENT_SR_CHANGE: +#if 0 + y_printf("sr change:%d \n", mixer->sample_rate); +#endif + break; + } + +} +/*----------------------------------------------------------------------------*/ +/**@brief 检测mixer采样率支持 + @param *mixer: 句柄 + @param sr: 采样率 + @return 支持的采样率 + @note +*/ +/*----------------------------------------------------------------------------*/ +static u32 audio_mixer_check_sr(struct audio_mixer *mixer, u32 sr) +{ + return audio_output_rate(sr);; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 获取系统软件数字音量 + @param 无 + @return 返回系统软件数字音量值 + @note 改回调由用户实现 +*/ +/*----------------------------------------------------------------------------*/ +int vol_get_test() +{ + u8 vol = 0; + /* vol = audio_dig_vol_get(digvol_last, AUDIO_DIG_VOL_ALL_CH); */ + return vol; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 重新设置mixer采样率 + @param sr: 采样率 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_mixer_reset_sample_rate(u8 flag, u32 sr) +{ + if (flag) { + audio_mixer_set_sample_rate(&mixer, MIXER_SR_SPEC, sr); + } else { + audio_mixer_set_sample_rate(&mixer, MIXER_SR_FIRST, sr); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief audio解码任务cpu跟踪回调 + @param idle_total 跟踪周期内的空闲时间统计 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_dec_occupy_trace_hdl(void *priv, u32 idle_total) +{ + struct audio_decoder_occupy *occupy = priv; + if (idle_total < occupy->idle_expect) { + if (occupy->pend_time) { + os_time_dly(occupy->pend_time); + } + } + return 0; +} + + +extern void audio_adda_gain_dump(void);//打印所有adc,dac的增益 +/*音频配置实时跟踪,可以用来查看ADC/DAC增益,或者其他寄存器配置*/ +static void audio_config_trace(void *priv) +{ + printf(">>Audio_Config_Trace:\n"); + audio_adda_gain_dump(); + //audio_adda_dump(); + //mem_stats(); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 音频解码初始化 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +extern struct audio_dac_hdl dac_hdl; +struct audio_dac_channel default_dac = {0}; +int audio_dec_init() +{ + int err; + + printf("audio_dec_init\n"); + + + // 创建解码任务 + err = audio_decoder_task_create(&decode_task, "audio_dec"); + +#if TCFG_AUDIO_DECODER_OCCUPY_TRACE + decode_task.occupy.pend_time = 1; + decode_task.occupy.idle_expect = 4; + decode_task.occupy.trace_period = 200; + //decode_task.occupy.trace_hdl = audio_dec_occupy_trace_hdl; +#endif/*TCFG_AUDIO_DECODER_OCCUPY_TRACE*/ + +#if TCFG_AUDIO_DEC_OUT_TASK + audio_decoder_out_task_create(&decode_task, "audio_out"); +#endif + +#if TCFG_DEC2TWS_TASK_ENABLE + // 创建本地转发解码任务 + audio_decoder_task_create(&localtws_decode_task, "local_dec"); +#endif + + // 初始化音频输出 + app_audio_output_init(); + +#if TCFG_KEY_TONE_EN + // 按键音初始化 + audio_key_tone_init(); +#endif + +#if SYS_DIGVOL_GROUP_EN + // 数字通道初始化 + sys_digvol_group_open(); +#endif // SYS_DIGVOL_GROUP_EN + + /*硬件SRC模块滤波器buffer设置,可根据最大使用数量设置整体buffer*/ + audio_src_base_filt_init(audio_src_hw_filt, sizeof(audio_src_hw_filt)); + + if (!AUDIO_DEC_MIXER_EN) { +#if AUDIO_OUTPUT_INCLUDE_DAC + // 创建dac通道 + audio_dac_new_channel(&dac_hdl, &default_dac); + struct audio_dac_channel_attr attr; + audio_dac_channel_get_attr(&default_dac, &attr); + attr.delay_time = 50; + attr.protect_time = 8; + attr.write_mode = WRITE_MODE_BLOCK; + audio_dac_channel_set_attr(&default_dac, &attr); +#endif + goto __mixer_init_end; + } + + // 初始化mixer + audio_mixer_open(&mixer); + // 使能mixer事件回调 + audio_mixer_set_event_handler(&mixer, mixer_event_handler); + // 使能mixer采样率检测 + audio_mixer_set_check_sr_handler(&mixer, audio_mixer_check_sr); + if (config_mixer_en) { + /*初始化mix_buf的长度*/ + audio_mixer_set_output_buf(&mixer, mix_buff, sizeof(mix_buff)); +#ifdef CONFIG_MIXER_CYCLIC +#define MIXER_MIN_LEN (128*4*2) + // 设置mixer最小输出长度 + audio_mixer_set_min_len(&mixer, sizeof(mix_buff) < (MIXER_MIN_LEN * 2) ? (sizeof(mix_buff) / 2) : MIXER_MIN_LEN); +#if (SOUNDCARD_ENABLE) + // 关闭直通输出 + audio_mixer_set_direct_out(&mixer, 0); +#endif +#endif + } + // 获取音频输出声道数 + u8 ch_num = audio_output_channel_num(); +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) +#if TCFG_EQ_DIVIDE_ENABLE /* || defined (CONFIG_MIXER_CYCLIC) */ + ch_num = 4; +#endif +#endif + // 设置mixer输出声道数 + audio_mixer_set_channel_num(&mixer, ch_num); + // 检测音频输出采样率是否为固定输出 + u32 sr = audio_output_nor_rate(); + if (sr) { + // 固定采样率输出 + audio_mixer_set_sample_rate(&mixer, MIXER_SR_SPEC, sr); + } + +#ifdef CONFIG_MIXER_CYCLIC +#if TCFG_MIXER_CYCLIC_TASK_EN + // mixer使用单独task输出 + audio_mixer_task_init(&mixer_task, "mix_out"); + audio_mixer_task_ch_open(&mixer, &mixer_task); +#endif +#endif + + struct audio_stream_entry *entries[8] = {NULL}; + +#if defined(TCFG_EQ_DIVIDE_ENABLE)&&(!TCFG_EQ_DIVIDE_ENABLE)// && (!defined(CONFIG_MIXER_CYCLIC)) + + if (ch_num <= 2) { +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) + mix_ch_switch = channel_switch_open(AUDIO_CH_QUAD, AUDIO_SYNTHESIS_LEN / 2); +#endif + } +#endif + +#if AUDIO_OUTPUT_AUTOMUTE + // 自动mute + mix_out_automute_open(); +#endif + +#if AUDIO_SPECTRUM_CONFIG + //频响能量值获取接口 + spec_hdl = spectrum_open_demo(sr, ch_num); +#endif + +#if AUDIO_EQUALLOUDNESS_CONFIG + if (ch_num != 4) { + loudness_open_parm parm = {0}; + parm.sr = sr; + parm.ch_num = ch_num; + parm.threadhold_vol = LOUDNESS_THREADHOLD_VOL; + parm.vol_cb = vol_get_test; + loudness = audio_equal_loudness_open(&parm);//不支持四声道 + } +#endif + +#if AUDIO_VOCAL_REMOVE_EN + mix_vocal_remove_hdl = vocal_remove_open(ch_num); + + u8 dac_connect_mode = app_audio_output_mode_get(); + if ((dac_connect_mode == DAC_OUTPUT_MONO_L) + || (dac_connect_mode == DAC_OUTPUT_MONO_R) + || (dac_connect_mode == DAC_OUTPUT_MONO_LR_DIFF)) { + vocal_remove_mix_ch_switch = channel_switch_open(AUDIO_CH_DIFF, 512); + } +#endif + + + // 数据流串联。可以在mixer和last中间添加其他的数据流,比如eq等 + u8 entry_cnt = 0; + entries[entry_cnt++] = &mixer.entry; + +#if TCFG_DIG_PHASE_INVERTER_EN + audio_phase_inver_hdl.entry.data_process_len = audio_phase_inver_output_data_process_len; + audio_phase_inver_hdl.entry.data_handler = audio_phase_inver_data_handler; + entries[entry_cnt++] = &(audio_phase_inver_hdl.entry); +#endif/*TCFG_DIG_PHASE_INVERTER_EN*/ + +#if AUDIO_EQUALLOUDNESS_CONFIG + if (loudness) { + entries[entry_cnt++] = &loudness->loudness->entry; + } +#endif + +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) +#if !TCFG_EQ_DIVIDE_ENABLE + if (mix_ch_switch) { + entries[entry_cnt++] = &mix_ch_switch->entry; + } +#endif +#endif + +#if AUDIO_SPECTRUM_CONFIG + if (spec_hdl) { + entries[entry_cnt++] = &spec_hdl->entry; + } +#endif + +#if AUDIO_VOCAL_REMOVE_EN + if (mix_vocal_remove_hdl) { + entries[entry_cnt++] = &mix_vocal_remove_hdl->entry; + } + if (vocal_remove_mix_ch_switch) { + entries[entry_cnt++] = &vocal_remove_mix_ch_switch->entry; + } +#endif + + +#if AUDIO_OUTPUT_AUTOMUTE + entries[entry_cnt++] = mix_out_automute_entry; +#endif + +#if AUDIO_OUTPUT_INCLUDE_DAC + // 创建dac通道 + audio_dac_new_channel(&dac_hdl, &default_dac); + struct audio_dac_channel_attr attr; + audio_dac_channel_get_attr(&default_dac, &attr); + attr.delay_time = 50; + attr.protect_time = 8; + attr.write_mode = WRITE_MODE_BLOCK; + audio_dac_channel_set_attr(&default_dac, &attr); + entries[entry_cnt++] = &default_dac.entry; + /*entries[entry_cnt++] = &dac_hdl.entry;*/ +#endif /*AUDIO_OUTPUT_INCLUDE_DAC*/ + + // 创建数据流,把所有节点连接起来 + mixer.stream = audio_stream_open(&mixer, audio_mixer_stream_resume); + audio_stream_add_list(mixer.stream, entries, entry_cnt); + +#if (!AUDIO_OUTPUT_INCLUDE_DAC) + entry_cnt++; +#endif + + +#if (AUDIO_OUTPUT_INCLUDE_IIS) + audio_dig_vol_param iis_digvol_last_param = { + .vol_start = app_var.music_volume, + .vol_max = SYS_MAX_VOL, + .ch_total = 2, + .fade_en = 1, + .fade_points_step = 5, + .fade_gain_step = 10, + .vol_list = NULL, + }; + iis_digvol_last = audio_dig_vol_open(&iis_digvol_last_param); + iis_digvol_last_entry = audio_dig_vol_entry_get(iis_digvol_last); + + iis_last_entry = audio_iis_output_start(TCFG_IIS_OUTPUT_PORT, TCFG_IIS_OUTPUT_DATAPORT_SEL); + struct audio_stream_entry *iis_entries_start = entries[entry_cnt - 2]; + entry_cnt = 0; + entries[entry_cnt++] = iis_entries_start; + entries[entry_cnt++] = iis_digvol_last_entry; + entries[entry_cnt++] = iis_last_entry; + for (int i = 0; i < entry_cnt - 1; i++) { + audio_stream_add_entry(entries[i], entries[i + 1]); + } +#endif + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) + // 蓝牙发射。从倒数第二个节点分流 + extern int audio_data_set_zero(struct audio_stream_entry * entry, struct audio_data_frame * data_buf); + default_dac.entry.prob_handler = audio_data_set_zero; + audio_dig_vol_param bt_digvol_last_param = { + .vol_start = app_var.music_volume, + .vol_max = SYS_MAX_VOL, + .ch_total = 2, + .fade_en = 1, + .fade_points_step = 5, + .fade_gain_step = 10, + .vol_list = NULL, + }; + bt_digvol_last = audio_dig_vol_open(&bt_digvol_last_param); + bt_digvol_last_entry = audio_dig_vol_entry_get(bt_digvol_last); + audio_stream_add_entry(entries[entry_cnt - 2], bt_digvol_last_entry); + + audio_sbc_emitter_init(); + audio_stream_add_entry(bt_digvol_last_entry, &sbc_emitter.entry); +#endif + +#if (TCFG_APP_FM_EMITTER_EN) + // fm发射。从倒数第二个节点分流 + audio_dig_vol_param fmtx_digvol_last_param = { + .vol_start = app_var.music_volume, + .vol_max = SYS_MAX_VOL, + .ch_total = 2, + .fade_en = 1, + .fade_points_step = 5, + .fade_gain_step = 10, + .vol_list = NULL, + }; + fmtx_digvol_last = audio_dig_vol_open(&fmtx_digvol_last_param); + fmtx_digvol_last_entry = audio_dig_vol_entry_get(fmtx_digvol_last); + + fmtx_last_entry = audio_fmtx_output_start(0); + struct audio_stream_entry *fmtx_entries_start = entries[entry_cnt - 2]; + entry_cnt = 0; + entries[entry_cnt++] = fmtx_entries_start; + entries[entry_cnt++] = fmtx_digvol_last_entry; + entries[entry_cnt++] = fmtx_last_entry; + for (int i = 0; i < entry_cnt - 1; i++) { + audio_stream_add_entry(entries[i], entries[i + 1]); + } +#endif + +__mixer_init_end: + +#if (RECORDER_MIX_EN) + // 录音 + recorder_mix_init(&recorder_mixer, recorder_mix_buff, sizeof(recorder_mix_buff)); +#endif//RECORDER_MIX_EN + + + // 音频音量初始化 + app_audio_volume_init(); + audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); + +#if TCFG_IIS_ENABLE + // iis音频 + /* audio_link_init(); */ + /* #if TCFG_IIS_OUTPUT_EN */ + /* audio_link_open(TCFG_IIS_OUTPUT_PORT, ALINK_DIR_TX); */ + /* #endif */ +#endif + +#if TCFG_SPDIF_ENABLE + // spdif音频 + spdif_init(); +#endif + + audio_dec_inited = 1; +#if (TCFG_MIC_EFFECT_ENABLE && TCFG_MIC_EFFECT_START_DIR) + mic_effect_start(); +#endif + +#if TCFG_AUDIO_CONFIG_TRACE + sys_timer_add(NULL, audio_config_trace, 3000); +#endif/*TCFG_AUDIO_CONFIG_TRACE*/ + + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 音频解码初始化判断 + @param + @return 1: 还没初始化 + @return 0: 已经初始化 + @note +*/ +/*----------------------------------------------------------------------------*/ +static u8 audio_dec_init_complete() +{ + /*不支持Audio功能,返回idle*/ +#if (defined TCFG_AUDIO_ENABLE && (TCFG_AUDIO_ENABLE == 0)) + return 1; +#endif/*TCFG_AUDIO_ENABLE*/ + + if (!audio_dec_inited) { + return 0; + } + + return 1; +} +REGISTER_LP_TARGET(audio_dec_init_lp_target) = { + .name = "audio_dec_init", + .is_idle = audio_dec_init_complete, +}; + + + +#if AUDIO_OUTPUT_AUTOMUTE + +void audio_mix_out_automute_mute(u8 mute) +{ + printf(">>>>>>>>>>>>>>>>>>>> %s\n", mute ? ("MUTE") : ("UNMUTE")); +} + +/* #define AUDIO_E_DET_UNMUTE (0x00) */ +/* #define AUDIO_E_DET_MUTE (0x01) */ +void mix_out_automute_handler(u8 event, u8 ch) +{ + printf(">>>> ch:%d %s\n", ch, event ? ("MUTE") : ("UNMUTE")); + if (ch == app_audio_output_channel_get()) { + audio_mix_out_automute_mute(event); + } else { +#if DAC_AUTO_HIGH_Z_EN + app_audio_output_ch_mute(BIT(ch), event); +#endif + } +} + +void mix_out_automute_skip(u8 skip) +{ + u8 mute = !skip; + if (mix_out_automute_hdl) { + audio_energy_detect_skip(mix_out_automute_hdl, 0xFFFF, skip); + audio_mix_out_automute_mute(mute); + } +} + +void mix_out_automute_open() +{ + if (mix_out_automute_hdl) { + printf("mix_out_automute is already open !\n"); + return; + } + audio_energy_detect_param e_det_param = {0}; + e_det_param.mute_energy = 5; + e_det_param.unmute_energy = 10; + e_det_param.mute_time_ms = 1000; + e_det_param.unmute_time_ms = 50; + e_det_param.count_cycle_ms = 10; + e_det_param.sample_rate = 44100; + e_det_param.event_handler = mix_out_automute_handler; +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) + e_det_param.ch_total = 4; +#else + e_det_param.ch_total = app_audio_output_channel_get(); +#endif + e_det_param.dcc = 1; + mix_out_automute_hdl = audio_energy_detect_open(&e_det_param); + mix_out_automute_entry = audio_energy_detect_entry_get(mix_out_automute_hdl); +} + +void mix_out_automute_close() +{ + if (mix_out_automute_hdl) { + audio_energy_detect_close(mix_out_automute_hdl); + } +} +#endif //#if AUDIO_OUTPUT_AUTOMUTE + + +/***************************************************************************** + * + * 数字音量分组管理 + * + ****************************************************************************/ + +#if SYS_DIGVOL_GROUP_EN + +char *music_dig_logo[] = { + + "music_a2dp", + "music_file", + "music_fm", + "music_linein", + "music_pc", + "NULL" + +}; + +void *sys_digvol_group = NULL; + +int sys_digvol_group_open(void) +{ + if (sys_digvol_group == NULL) { + sys_digvol_group = audio_dig_vol_group_open(); + return 0; + } + return -1; +} + +int sys_digvol_group_close(void) +{ + if (sys_digvol_group != NULL) { + return audio_dig_vol_group_close(sys_digvol_group); + } + return -1; +} + +// 根据每个解码通道的logo来决定启动时候的数字音量等级 +u16 __attribute__((weak)) get_ch_digvol_start(char *logo) +{ +#if 0 + if (!strcmp(logo, "music_a2dp")) { + return 100; + } else if (!strcmp(logo, "music_fm")) { + return 100; + } +#endif + return get_max_sys_vol(); +} + + +/******************************************************* +* Function name : sys_digvol_group_ch_open +* Description : 解码通道数字音量打开且加入分组管理 +* Parameter : +* @logo 解码通道的标识 +* @vol_start 解码通道数字音量启动等级, 传 -1 时会调用 get_ch_digvol_start 获取 +* Return : digvol audio stream entry +*******************************************************/ +void *sys_digvol_group_ch_open(char *logo, int vol_start, audio_dig_vol_param *parm) +{ + if (sys_digvol_group == NULL || logo == NULL) { + return NULL; + } + if (vol_start == -1) { + vol_start = get_ch_digvol_start(logo); + } + audio_dig_vol_param temp_digvol_param = { + .vol_start = vol_start, + .vol_max = get_max_sys_vol(), + .ch_total = 2, + .fade_en = 1, + .fade_points_step = 5, + .fade_gain_step = 10, + .vol_list = NULL, + }; + if (parm == NULL) { + parm = &temp_digvol_param; + } + void *digvol_hdl = audio_dig_vol_open(parm); + if (digvol_hdl) { + audio_dig_vol_group_add(sys_digvol_group, digvol_hdl, logo); + return audio_dig_vol_entry_get(digvol_hdl); + } + return NULL; +} + +int sys_digvol_group_ch_close(char *logo) +{ + if (sys_digvol_group == NULL || logo == NULL) { + return -1; + } + void *hdl = audio_dig_vol_group_hdl_get(sys_digvol_group, logo); + + if (hdl != NULL) { + void *entry = audio_dig_vol_entry_get(hdl); + if (entry != NULL) { + audio_stream_del_entry(entry); + } + + } + + + audio_dig_vol_close(audio_dig_vol_group_hdl_get(sys_digvol_group, logo)); + audio_dig_vol_group_del(sys_digvol_group, logo); + return 0; +} + +#endif // SYS_DIGVOL_GROUP_EN + + +#if AUDIO_VOCAL_REMOVE_EN +/*----------------------------------------------------------------------------*/ +/**@brief 人声消除打开例子 + @param ch_num:通道个数 + @return 句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +void *vocal_remove_open(u8 ch_num) +{ + vocal_remove_hdl *hdl = NULL; + vocal_remove_open_parm parm = {0}; + parm.channel = ch_num; + hdl = audio_vocal_remove_open(&parm); + return hdl; +} +/*----------------------------------------------------------------------------*/ +/**@brief 人声消除关闭例子 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void vocal_remove_close() +{ + if (mix_vocal_remove_hdl) { + audio_vocal_remove_close(mix_vocal_remove_hdl); + mix_vocal_remove_hdl = NULL; + } +} + +#endif + + diff --git a/cpu/br23/audio_dec/audio_dec.h b/cpu/br23/audio_dec/audio_dec.h new file mode 100644 index 0000000..2ddf2a8 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec.h @@ -0,0 +1,125 @@ + +#ifndef _AUDIO_DEC_H_ +#define _AUDIO_DEC_H_ + +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "asm/audio_src.h" +#include "audio_digital_vol.h" +#include "media/audio_eq_drc_apply.h" +#include "application/audio_vocal_tract_synthesis.h" +#include "application/audio_dig_vol.h" +#include "audio_effect/audio_eq_drc_demo.h" +#include "audio_effect/audio_gain_process_demo.h" +#include "audio_effect/audio_sound_track_2_p_x.h" +#include "media/effects_adj.h" +#include "media/convert_data.h" +#include "stream/stream_entry.h" +#include "audio_effect/audio_vbass_demo.h" +#include "audio_effect/audio_surround_demo.h" +#include "audio_effect/audio_eff_default_parm.h" + +#ifndef RB16 +#define RB16(b) (u16)(((u8 *)b)[0] << 8 | (((u8 *)b))[1]) +#endif + +extern struct audio_decoder_task decode_task; +extern struct audio_mixer mixer; +extern struct audio_mixer recorder_mixer; + +u32 audio_output_rate(int input_rate); +u32 audio_output_channel_num(void); +u32 audio_output_channel_type(void); +int audio_output_set_start_volume(u8 state); + +int audio_output_start(u32 sample_rate, u8 reset_rate); +void audio_output_stop(void); + +struct audio_src_handle *audio_hw_resample_open(void *priv, int (*output_handler)(void *, void *, int), + u8 channel, u16 input_sample_rate, u16 output_sample_rate); +void audio_hw_resample_close(struct audio_src_handle *hdl); + +void audio_resume_all_decoder(void); + +u32 audio_output_nor_rate(void); + +enum { + AUDIO_MODE_MAIN_STATE_DEC_A2DP = 1, + AUDIO_MODE_MAIN_STATE_DEC_ESCO, + AUDIO_MODE_MAIN_STATE_DEC_FILE, + AUDIO_MODE_MAIN_STATE_DEC_FM, + AUDIO_MODE_MAIN_STATE_DEC_LINEIN, + AUDIO_MODE_MAIN_STATE_DEC_PC, + AUDIO_MODE_MAIN_STATE_DEC_SPDIF, + AUDIO_MODE_MAIN_STATE_DEC_LOCALTWS, + + AUDIO_MODE_MAIN_STATE_DEC_MASK = 0xff, +}; + +enum { + KARAOKE_SPK_OST,//原声 + KARAOKE_SPK_DBB,//重低音 + KARAOKE_SPK_SURROUND,//全景环绕 + KARAOKE_SPK_3D,//3d环绕 + KARAOKE_SPK_FLOW_VOICE,//流动人声 + KARAOKE_SPK_KING,//王者荣耀 + KARAOKE_SPK_WAR,//刺激战场 + KARAOKE_SPK_MAX, +}; + +void audio_mode_main_dec_open(u32 state); + +////////////////////////////////////////////////////////////////////////////// + +// 音频解码初始化 +int audio_dec_init(); + +void mix_out_high_bass(u32 cmd, struct high_bass *hb); +// mix out后 是否做高低音处理 +// 切换频响计算 +void spectrum_switch_demo(u8 en); + +////////////////////////////////////////////////////////////////////////////// +static inline void audio_pcm_mono_to_dual(s16 *dual_pcm, s16 *mono_pcm, int points) +{ + s16 *mono = mono_pcm; + int i = 0; + u8 j = 0; + + for (i = 0; i < points; i++, mono++) { + *dual_pcm++ = *mono; + *dual_pcm++ = *mono; + } +} + + +////////////////////////////////////////////////////////////////////////////// + +extern void *sys_digvol_group; +// 数字通道初始化 +extern int sys_digvol_group_open(void); +// 数字通道关闭 +extern int sys_digvol_group_close(void); +// 打开一个数字通道 +extern void *sys_digvol_group_ch_open(char *logo, int vol_start, audio_dig_vol_param *parm); +// 关闭一个数字通道 +extern int sys_digvol_group_ch_close(char *logo); + + + +#include "audio_dec_bt.h" +#include "audio_dec_file.h" +#ifndef CONFIG_LITE_AUDIO +#include "audio_dec_fm.h" +#endif/*CONFIG_LITE_AUDIO*/ +#include "audio_dec_linein.h" +#include "audio_dec_pc.h" +#include "audio_dec_spdif.h" +#include "audio_dec_record.h" +#include "audio_dec_tone.h" + +#include "localtws/localtws.h" + +#endif + diff --git a/cpu/br23/audio_dec/audio_dec_board_cfg.h b/cpu/br23/audio_dec/audio_dec_board_cfg.h new file mode 100644 index 0000000..5fe82a4 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_board_cfg.h @@ -0,0 +1,28 @@ +#ifndef _AUDIO_DEC_BOARD_CONFIG_H_ +#define _AUDIO_DEC_BOARD_CONFIG_H_ + +#include "system/includes.h" +#include "app_config.h" + +struct dec_board_param +{ + const char *name; + u8 d_vol_en; + u16 d_vol_fade_step; + u8 (*d_vol_max)(void); + u8 (*d_vol_cur)(void); + u8 voice_cut_en;//人声消除 使能 + ///other dec param... +}; + +#define REGISTER_DEC_BOARD_PARAM(p) \ + struct dec_board_param p sec(.dec_board_param_mem) + +extern struct dec_board_param dec_board_param_mem_begin[]; +extern struct dec_board_param dec_board_param_mem_end[]; + +#define list_for_each_dec_board_param(p) \ + for (p = dec_board_param_mem_begin; p < dec_board_param_mem_end; p++) + +#endif//_AUDIO_DEC_BOARD_CONFIG_H_ + diff --git a/cpu/br23/audio_dec/audio_dec_bt.c b/cpu/br23/audio_dec/audio_dec_bt.c new file mode 100644 index 0000000..68d18c2 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_bt.c @@ -0,0 +1,1812 @@ +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "media/a2dp_decoder.h" +#include "media/esco_decoder.h" +#include "classic/tws_api.h" +#include "app_config.h" +#include "audio_config.h" +#include "audio_dec.h" +#include "audio_digital_vol.h" +#include "clock_cfg.h" +#include "btstack/a2dp_media_codec.h" +#include "media/audio_eq_drc_apply.h" +#include "media/audio_equalloudness.h" +#include "media/audio_vbass.h" +#include "aec_user.h" +#include "audio_enc.h" +#include "bt_tws.h" +#include "media/convert_data.h" +#include "audio_effect/audio_dynamic_eq_demo.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" + +#if TCFG_ESCO_PLC +#include "PLC.h" +#define PLC_FRAME_LEN 60 +#endif/*TCFG_ESCO_PLC*/ + + + +#ifdef TCFG_ESCO_NOISEGATE +/*小于CONST_NOISE_GATE的当成噪声处理,防止清0近端声音*/ +#define LIMITER_NOISE_GATE -55000 /*-12000 = -12dB,放大1000倍,(-30000参考)*/ +/*低于噪声门限阈值的增益 */ +#define LIMITER_NOISE_GAIN (0 << 30) /*(0~1)*2^30*/ + +#endif //TCFG_ESCO_NOISEGATE + +#define ESCO_DRC_EN 0 //通话下行增加限幅器处理,默认关闭,need en TCFG_DRC_ENABLE + +#if (!TCFG_DRC_ENABLE || !TCFG_PHONE_EQ_ENABLE) +#undef ESCO_DRC_EN 0 +#define ESCO_DRC_EN 0 +#endif + + + +#define TCFG_ESCO_USE_SPEC_MIX_LEN 0 + +extern const int CONFIG_A2DP_DELAY_TIME; + +extern const int config_mixer_en; + +#define AUDIO_DEC_BT_MIXER_EN config_mixer_en + + + +/* + * 解码输出变双声道。不打开的时候使用mixer中的声道转换。 + * mixer中的声道转换是通用型的,支持任意转换,但效率没有单独的单声道转双声道的好 + */ +#define ESCO_DEC_OUT_DUAL 1 + + +////////////////////////////////////////////////////////////////////////////// + + +struct a2dp_dec_hdl { + struct a2dp_decoder dec; // a2dp解码句柄 + struct audio_res_wait wait; // 资源等待句柄 + struct audio_mixer_ch mix_ch; // 叠加句柄 +#if (RECORDER_MIX_EN) + struct audio_mixer_ch rec_mix_ch; // 叠加句柄 +#endif//RECORDER_MIX_EN + + struct audio_stream *stream; // 音频流 + +#if AUDIO_SURROUND_CONFIG + surround_hdl *surround; //环绕音效句柄 +#endif + +#if AUDIO_VBASS_CONFIG + struct aud_gain_process *vbass_prev_gain; + vbass_hdl *vbass; //虚拟低音句柄 +#endif + struct audio_eq *high_bass; + struct audio_drc *hb_drc;//高低音后的drc + struct convert_data *hb_convert; + + struct audio_eq *eq; //eq drc句柄 + struct audio_drc *drc; // drc句柄 + struct convert_data *convert; + struct audio_eq *eq2; //eq drc句柄 + struct dynamic_eq_hdl *dy_eq; + struct convert_data *convert2; + struct aud_gain_process *gain; + + + struct audio_wireless_sync *sync; + +#if TCFG_EQ_DIVIDE_ENABLE + struct audio_eq *eq_rl_rr; //eq drc句柄 + struct audio_drc *drc_rl_rr; // drc句柄 + struct convert_data *convert_rl_rr; + struct __stream_entry *rl_rr_mix;//双声道相加除2处理 + struct aud_gain_process *gain_rl_rr; + + struct audio_vocal_tract vocal_tract;//声道合并目标句柄 + struct audio_vocal_tract_ch synthesis_ch_fl_fr;//声道合并句柄 + struct audio_vocal_tract_ch synthesis_ch_rl_rr;//声道合并句柄 + struct channel_switch *ch_switch;//声道变换 +#endif + + + u8 closing; + u8 preempted; + u8 slience; + int slience_time; + u32 slience_end_time; + struct audio_stream_entry *slience_entry; +}; + +struct esco_dec_hdl { + struct esco_decoder dec; // esco解码句柄 + struct audio_res_wait wait; // 资源等待句柄 + struct audio_mixer_ch mix_ch; // 叠加句柄 +#if (RECORDER_MIX_EN) + struct audio_mixer_ch rec_mix_ch; // 叠加句柄 +#endif//RECORDER_MIX_EN + + struct audio_stream *stream; // 音频流 + + struct audio_eq *eq; //eq drc句柄 + struct audio_drc *drc; // drc句柄 + struct convert_data *convert;//32转16bit + + struct channel_switch *ch_switch;//声道变换 + + u32 tws_mute_en : 1; // 静音 + u32 remain : 1; // 未输出完成 + +#if TCFG_ESCO_PLC + void *plc; // 丢包修护 +#endif + + +#ifdef TCFG_ESCO_NOISEGATE + void *noisegate; // 噪声抑制 +#endif + struct audio_wireless_sync *sync; +}; + + +////////////////////////////////////////////////////////////////////////////// + +struct a2dp_dec_hdl *bt_a2dp_dec = NULL; +struct esco_dec_hdl *bt_esco_dec = NULL; + +static u8 a2dp_suspend = 0; +static u16 drop_a2dp_timer = 0; + +extern s16 mix_buff[]; +extern s16 recorder_mix_buff[]; + +extern struct audio_dac_hdl dac_hdl; +extern struct audio_dac_channel default_dac; + +////////////////////////////////////////////////////////////////////////////// + +struct audio_wireless_sync *a2dp_output_sync_open(int sample_rate, int output_sample_rate, u8 channel); +void a2dp_output_sync_close(struct audio_wireless_sync *a2dp_sync); +struct audio_wireless_sync *esco_output_sync_open(int sample_rate, int output_sample_rate, u8 channels); +void esco_output_sync_close(struct audio_wireless_sync *esco_sync); + +extern int lmp_private_esco_suspend_resume(int flag); + + + +static void bt_dec_stream_run_stop(struct audio_decoder *decoder) +{ +#if AUDIO_DAC_MULTI_CHANNEL_ENABLE + struct audio_data_frame frame = {0}; + struct audio_data_frame output = {0}; + frame.stop = 1; + frame.channel = audio_output_channel_num(); + frame.sample_rate = app_audio_output_samplerate_get(); + /* audio_stream_run(&default_dac.entry, &frame); */ + default_dac.entry.data_handler(&default_dac.entry, &frame, &output); + audio_stream_del_entry(&default_dac.entry); +#else /*AUDIO_DAC_MULTI_CHANNEL_ENABLE*/ + audio_dac_stop(&dac_hdl); +#endif /*AUDIO_DAC_MULTI_CHANNEL_ENABLE*/ +} + +static int audio_dec_slience_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + out->data = in->data; + out->data_len = in->data_len; + + if (in->offset == 0) { + if (bt_a2dp_dec->slience == 0) { + bt_a2dp_dec->slience_end_time = jiffies + msecs_to_jiffies(bt_a2dp_dec->slience_time); + memset(in->data, 0, in->data_len); + bt_a2dp_dec->slience = 1; + } else if (bt_a2dp_dec->slience == 1) { + if (time_after(jiffies, bt_a2dp_dec->slience_end_time)) { + bt_a2dp_dec->slience = 2; + } + memset(in->data, 0, in->data_len); + } + } + return in->data_len; +} + +static void audio_dec_slience_process_len(struct audio_stream_entry *entry, int len) +{ + +} + +static struct audio_stream_entry *audio_dec_slience_stream_entry(struct a2dp_dec_hdl *dec, int time) +{ + struct audio_stream_entry *entry = zalloc(sizeof(struct audio_stream_entry)); + entry->data_handler = audio_dec_slience_data_handler; + entry->data_process_len = audio_dec_slience_process_len; + dec->slience = 0; + dec->slience_entry = entry; + dec->slience_time = time; + + return entry; +} + +static void audio_dec_slience_entry_free(struct a2dp_dec_hdl *dec) +{ + if (dec->slience_entry) { + audio_stream_del_entry(dec->slience_entry); + free(dec->slience_entry); + dec->slience_entry = NULL; + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief a2dp解码close + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void a2dp_audio_res_close(void) +{ + if (bt_a2dp_dec->dec.start == 0) { + log_i("bt_a2dp_dec->dec.start == 0"); + return ; + } + + if (!bt_a2dp_dec->closing) { + bt_a2dp_dec->preempted = 1; + } + bt_a2dp_dec->dec.start = 0; + a2dp_decoder_close(&bt_a2dp_dec->dec); +#if AUDIO_SURROUND_CONFIG + surround_close_demo(bt_a2dp_dec->surround); +#endif + +#if AUDIO_VBASS_CONFIG + audio_gain_close_demo(bt_a2dp_dec->vbass_prev_gain); + audio_vbass_close_demo(bt_a2dp_dec->vbass); +#endif + high_bass_eq_close(bt_a2dp_dec->high_bass); + high_bass_drc_close(bt_a2dp_dec->hb_drc); + convet_data_close(bt_a2dp_dec->hb_convert); +#if TCFG_EQ_ENABLE &&TCFG_BT_MUSIC_EQ_ENABLE + music_eq_close(bt_a2dp_dec->eq); +#if TCFG_DRC_ENABLE && TCFG_BT_MUSIC_DRC_ENABLE + music_drc_close(bt_a2dp_dec->drc); +#endif + convet_data_close(bt_a2dp_dec->convert); + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + music_eq2_close(bt_a2dp_dec->eq2); + audio_dynamic_eq_ctrl_close(bt_a2dp_dec->dy_eq); + convet_data_close(bt_a2dp_dec->convert2); +#endif + audio_gain_close_demo(bt_a2dp_dec->gain); +#endif + +#if TCFG_EQ_DIVIDE_ENABLE + music_eq_rl_rr_close(bt_a2dp_dec->eq_rl_rr); + music_drc_rl_rr_close(bt_a2dp_dec->drc_rl_rr); + convet_data_close(bt_a2dp_dec->convert_rl_rr); +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + stream_entry_close(&bt_a2dp_dec->rl_rr_mix); +#endif + audio_gain_close_demo(bt_a2dp_dec->gain_rl_rr); + + audio_vocal_tract_synthesis_close(&bt_a2dp_dec->synthesis_ch_fl_fr); + audio_vocal_tract_synthesis_close(&bt_a2dp_dec->synthesis_ch_rl_rr); + audio_vocal_tract_close(&bt_a2dp_dec->vocal_tract); + channel_switch_close(&bt_a2dp_dec->ch_switch); +#endif + a2dp_output_sync_close(bt_a2dp_dec->sync); + bt_a2dp_dec->sync = NULL; + if (AUDIO_DEC_BT_MIXER_EN) { + audio_mixer_ch_close(&bt_a2dp_dec->mix_ch); + } else { + default_dac.entry.prob_handler = NULL; + bt_dec_stream_run_stop(&bt_a2dp_dec->dec.decoder); + } + + audio_dec_slience_entry_free(bt_a2dp_dec); + + + +#if (RECORDER_MIX_EN) + audio_mixer_ch_close(&bt_a2dp_dec->rec_mix_ch); +#endif//RECORDER_MIX_EN + +#if SYS_DIGVOL_GROUP_EN + sys_digvol_group_ch_close("music_a2dp"); +#endif // SYS_DIGVOL_GROUP_EN + + + + // 先关闭各个节点,最后才close数据流 + if (bt_a2dp_dec->stream) { + audio_stream_close(bt_a2dp_dec->stream); + bt_a2dp_dec->stream = NULL; + } + + app_audio_state_exit(APP_AUDIO_STATE_MUSIC); +} + +/*----------------------------------------------------------------------------*/ +/**@brief a2dp解码释放 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void a2dp_dec_release() +{ + audio_decoder_task_del_wait(&decode_task, &bt_a2dp_dec->wait); + a2dp_drop_frame_stop(); + + if (bt_a2dp_dec->dec.coding_type == AUDIO_CODING_SBC) { + clock_remove(DEC_SBC_CLK); + } else if (bt_a2dp_dec->dec.coding_type == AUDIO_CODING_AAC) { + clock_remove(DEC_AAC_CLK); + } + + local_irq_disable(); + free(bt_a2dp_dec); + bt_a2dp_dec = NULL; + local_irq_enable(); +} + +/*----------------------------------------------------------------------------*/ +/**@brief a2dp解码事件返回 + @param *decoder: 解码器句柄 + @param argc: 参数个数 + @param *argv: 参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void a2dp_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ + switch (argv[0]) { + case AUDIO_DEC_EVENT_END: + log_i("AUDIO_DEC_EVENT_END\n"); + a2dp_dec_close(); + break; + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief a2dp解码数据流激活 + @param *p: 私有句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void a2dp_dec_out_stream_resume(void *p) +{ + struct a2dp_dec_hdl *dec = (struct a2dp_dec_hdl *)p; + + audio_decoder_resume(&dec->dec.decoder); +} + +/*----------------------------------------------------------------------------*/ +/**@brief a2dp接受回调 + @param + @return + @note 蓝牙库里面接受到了a2dp音频 +*/ +/*----------------------------------------------------------------------------*/ +void a2dp_rx_notice_to_decode(void) +{ + if (bt_a2dp_dec && bt_a2dp_dec->dec.start) { + a2dp_decoder_resume_from_bluetooth(&bt_a2dp_dec->dec); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief a2dp解码输出到dac时的预处理 + @param *entry: 数据流节点 + @param *in: 输入数据 + @return + @note 应用在没有使用mixer情况下传输sync标志 +*/ +/*----------------------------------------------------------------------------*/ +static int a2dp_to_dac_probe_handler(struct audio_stream_entry *entry, struct audio_data_frame *in) +{ + if (!in->stop/* && in->data_len*/) { + if (bt_a2dp_dec->sync) { + in->data_sync = 1; + } + } + + return 0; +} + +#if 0 +// 解码输出数据流节点数据处理回调示例 +static int demo_decoder_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + struct audio_decoder *decoder = container_of(entry, struct audio_decoder, entry); + // 自定义数据处理 + // ... + put_buf(in->data, 16); + // 输出到数据流示例。 + // 如果不使用audio_stream流程,输出后,需要把实际输出长度更新到decoder->process_len + decoder->process_len = 0; + audio_stream_run(&decoder->entry, in); + int wlen = decoder->process_len; + return wlen; +} +#endif + +#if 0 +// 数据流预处理回调示例 +static int demo_stream_mix_prob_handler(struct audio_stream_entry *entry, struct audio_data_frame *in) +{ + // 该函数中如果返回负数,数据流将截止运行,解码会被挂起 + // 对数据进行处理,如打印一下数据 + /* put_buf(in->data, in->data_len); */ + put_buf(in->data, 16); + /* memset(in->data, 0, in->data_len); */ + return 0; +} +#endif + +#if 0 +// 保存原来的数据流数据处理 +static void *demo_data_handler_save; +// 数据流data_handler处理 +static int demo_new_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + // 对数据进行处理 + put_buf(in->data, 8); + // 调用原来的接口输出,这里就可以保存一下是否输出完,就可以做比较多的处理了 + int wlen = ((int (*)(struct audio_stream_entry *, struct audio_data_frame *, struct audio_data_frame *))demo_data_handler_save)(entry, in, out); + return wlen; +} +#endif + +/*----------------------------------------------------------------------------*/ +/**@brief 开始a2dp解码 + @param + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int a2dp_dec_start(void) +{ + int err; + struct audio_fmt *fmt; + struct a2dp_dec_hdl *dec = bt_a2dp_dec; + u8 ch_num = 0; + u8 ch_type = 0; + + if (!bt_a2dp_dec) { + return -EINVAL; + } + + log_i("a2dp_dec_start: in\n"); + + // 打开a2dp解码 + err = a2dp_decoder_open(&dec->dec, &decode_task); + if (err) { + goto __err1; + } + // 使能事件回调 + audio_decoder_set_event_handler(&dec->dec.decoder, a2dp_dec_event_handler, 0); + + // 获取解码格式 + err = audio_decoder_get_fmt(&dec->dec.decoder, &fmt); + if (err) { + goto __err2; + } + + // 设置输出声道数和声道类型 + ch_num = audio_output_channel_num(); + ch_type = audio_output_channel_type(); + a2dp_decoder_set_output_channel(&dec->dec, ch_num, ch_type); + + if (AUDIO_DEC_BT_MIXER_EN) { + audio_mode_main_dec_open(AUDIO_MODE_MAIN_STATE_DEC_A2DP); + // 配置mixer通道参数 + audio_mixer_ch_open_head(&dec->mix_ch, &mixer); // 挂载到mixer最前面 +#if (SOUNDCARD_ENABLE) + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 0, BIT(0) | BIT(2) | BIT(3)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 1, BIT(1) | BIT(2) | BIT(3)); +#endif/*SOUNDCARD_ENABLE*/ + audio_mixer_ch_set_src(&dec->mix_ch, 1, 0); + audio_mixer_ch_set_no_wait(&dec->mix_ch, 1, 20); // 超时自动丢数 + audio_mixer_ch_sample_sync_enable(&dec->mix_ch, 1); // 标志为sync通道 + audio_mixer_ch_set_sample_rate(&dec->mix_ch, fmt->sample_rate); + } + +#if (RECORDER_MIX_EN) + audio_mixer_ch_open_head(&dec->rec_mix_ch, &recorder_mixer); // 挂载到mixer最前面 + audio_mixer_ch_set_src(&dec->rec_mix_ch, 1, 0); + audio_mixer_ch_set_no_wait(&dec->rec_mix_ch, 1, 10); // 超时自动丢数 + /* audio_mixer_ch_sample_sync_enable(&dec->rec_mix_ch, 1); */ +#endif//RECORDER_MIX_EN + +#if AUDIO_SURROUND_CONFIG + //环绕音效 + dec->surround = surround_open_demo(AEID_MUSIC_SURROUND, ch_type); +#endif + +#if AUDIO_VBASS_CONFIG + dec->vbass_prev_gain = audio_gain_open_demo(AEID_MUSIC_VBASS_PREV_GAIN, ch_num); + //虚拟低音 + dec->vbass = audio_vbass_open_demo(AEID_MUSIC_VBASS, fmt->sample_rate, ch_num); +#endif + + + dec->high_bass = high_bass_eq_open(fmt->sample_rate, ch_num); + dec->hb_drc = high_bass_drc_open(fmt->sample_rate, ch_num); + if (dec->hb_drc && dec->hb_drc->run32bit) { + dec->hb_convert = convet_data_open(0, 512); + } +#if TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE + dec->eq = music_eq_open(fmt->sample_rate, ch_num);// eq +#if TCFG_DRC_ENABLE && TCFG_BT_MUSIC_DRC_ENABLE + dec->drc = music_drc_open(fmt->sample_rate, ch_num);//drc +#endif/*TCFG_BT_MUSIC_DRC_ENABLE*/ + if (dec->eq && dec->eq->out_32bit) { + dec->convert = convet_data_open(0, 512); + } + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + dec->eq2 = music_eq2_open(fmt->sample_rate, ch_num);// eq + dec->dy_eq = audio_dynamic_eq_ctrl_open(fmt->sample_rate, ch_num);//动态eq + dec->convert2 = convet_data_open(0, 512); +#endif/*TCFG_DYNAMIC_EQ_ENABLE*/ + + dec->gain = audio_gain_open_demo(AEID_MUSIC_GAIN, ch_num); +#endif/*TCFG_BT_MUSIC_EQ_ENABLE*/ + + +#if TCFG_EQ_DIVIDE_ENABLE + dec->eq_rl_rr = music_eq_rl_rr_open(fmt->sample_rate, ch_num);// eq +#if TCFG_DRC_ENABLE && TCFG_BT_MUSIC_DRC_ENABLE + dec->drc_rl_rr = music_drc_rl_rr_open(fmt->sample_rate, ch_num);//drc +#endif + if (dec->eq_rl_rr && dec->eq_rl_rr->out_32bit) { + dec->convert_rl_rr = convet_data_open(0, 512); + } + +#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) && SOUND_TRACK_2_P_X_CH_CONFIG +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + dec->rl_rr_mix = stream_entry_open(NULL, stream_rl_rr_mix_data_handler, 0); +#endif +#endif + dec->gain_rl_rr = audio_gain_open_demo(AEID_MUSIC_RL_GAIN, ch_num); + if (dec->eq_rl_rr) { + audio_vocal_tract_open(&dec->vocal_tract, AUDIO_SYNTHESIS_LEN); + { + u8 entry_cnt = 0; + struct audio_stream_entry *entries[8] = {NULL}; + entries[entry_cnt++] = &dec->vocal_tract.entry; + if (AUDIO_DEC_BT_MIXER_EN) { + entries[entry_cnt++] = &dec->mix_ch.entry; + } else { + entries[entry_cnt++] = &default_dac.entry; + } + + dec->vocal_tract.stream = audio_stream_open(&dec->vocal_tract, audio_vocal_tract_stream_resume); + audio_stream_add_list(dec->vocal_tract.stream, entries, entry_cnt); + } + audio_vocal_tract_synthesis_open(&dec->synthesis_ch_fl_fr, &dec->vocal_tract, FL_FR); + audio_vocal_tract_synthesis_open(&dec->synthesis_ch_rl_rr, &dec->vocal_tract, RL_RR); + } else { + dec->ch_switch = channel_switch_open(AUDIO_CH_QUAD, AUDIO_SYNTHESIS_LEN / 2); + } + +#ifdef CONFIG_MIXER_CYCLIC + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 0, BIT(0)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 1, BIT(1)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 2, BIT(2)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 3, BIT(3)); +#endif +#endif + + + + + // sync初始化 + if (AUDIO_DEC_BT_MIXER_EN) { + dec->sync = a2dp_output_sync_open(fmt->sample_rate, audio_mixer_get_sample_rate(&mixer), ch_num); + } else { + dec->sync = a2dp_output_sync_open(fmt->sample_rate, fmt->sample_rate, ch_num); + } + + /*使能同步,配置延时时间*/ + a2dp_decoder_stream_sync_enable(&dec->dec, dec->sync->context, fmt->sample_rate, CONFIG_A2DP_DELAY_TIME); + +#if 0 + // 获取解码输出数据示例 + // 可以重新实现data_handler,在data_handler中再调用数据流输出 + // 或者可以查看紧接着dec->dec.decoder.entry之后的数据流预处理数据 + dec->dec.decoder.entry.data_handler = demo_decoder_data_handler; +#endif +#if 0 + // 获取节点数据示例1 + // 获取传入数据流节点中的数据仅需实现prob_handler接口就可以了 + // 该方式仅用于查看节点数据,或者做一些清零之类的简单动作 + // 这里以获取传入mix节点的数据为例 + dec->mix_ch.entry.prob_handler = demo_stream_mix_prob_handler; +#endif +#if 0 + // 获取节点数据示例2 + // 可以用变量保存原来的数据处理接口,然后重新赋值新的数据处理 + // 这里以获取mix节点的数据为例 + demo_data_handler_save = (void *)dec->mix_ch.entry.data_handler; + dec->mix_ch.entry.data_handler = demo_new_data_handler; +#endif + + // 数据流串联 + struct audio_stream_entry *entries[32] = {NULL}; + u8 entry_cnt = 0; + u8 rl_rr_entry_start = 0; + entries[entry_cnt++] = &dec->dec.decoder.entry; + if (dec->sync) { + entries[entry_cnt++] = dec->sync->entry; + entries[entry_cnt++] = dec->sync->resample_entry; + } + +#if AUDIO_SURROUND_CONFIG + if (dec->surround) { + entries[entry_cnt++] = &dec->surround->entry; + } +#endif + +#if AUDIO_VBASS_CONFIG + if (dec->vbass_prev_gain) { + entries[entry_cnt++] = &dec->vbass_prev_gain->entry; + } + if (dec->vbass) { + entries[entry_cnt++] = &dec->vbass->entry; + } +#endif + if (dec->high_bass) { //高低音 + entries[entry_cnt++] = &dec->high_bass->entry; + } + if (dec->hb_drc) { //高低音后drc + entries[entry_cnt++] = &dec->hb_drc->entry; + if (dec->hb_convert) { + entries[entry_cnt++] = &dec->hb_convert->entry; + } + } + + rl_rr_entry_start = entry_cnt - 1;//记录eq的上一个节点 +#if TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE + if (dec->eq) { + entries[entry_cnt++] = &dec->eq->entry; + if (dec->drc) { + entries[entry_cnt++] = &dec->drc->entry; + } + if (dec->convert) { + entries[entry_cnt++] = &dec->convert->entry; + } +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + if (dec->eq2) { + entries[entry_cnt++] = &dec->eq2->entry; + } + if (dec->dy_eq && dec->dy_eq->dy_eq) { + entries[entry_cnt++] = &dec->dy_eq->dy_eq->entry; + } + if (dec->convert2) { + entries[entry_cnt++] = &dec->convert2->entry; + } +#endif + if (dec->gain) { + entries[entry_cnt++] = &dec->gain->entry; + } + } +#endif + + +#if SYS_DIGVOL_GROUP_EN + void *dvol_entry = sys_digvol_group_ch_open("music_a2dp", -1, NULL); + entries[entry_cnt++] = dvol_entry; +#endif // SYS_DIGVOL_GROUP_EN + +#if TCFG_USER_TWS_ENABLE + if (dec->preempted) { + dec->preempted = 0; + entries[entry_cnt++] = audio_dec_slience_stream_entry(dec, 700); + } +#endif +#if TCFG_EQ_DIVIDE_ENABLE + if (dec->eq_rl_rr) { + entries[entry_cnt++] = &dec->synthesis_ch_fl_fr.entry;//四声道eq独立时,该节点后不接节点 + } else { + if (dec->ch_switch) { + entries[entry_cnt++] = &dec->ch_switch->entry; + } + if (AUDIO_DEC_BT_MIXER_EN) { + entries[entry_cnt++] = &dec->mix_ch.entry; + } else { + entries[entry_cnt++] = &default_dac.entry; + } + } +#else + if (AUDIO_DEC_BT_MIXER_EN) { + entries[entry_cnt++] = &dec->mix_ch.entry; + } else { + default_dac.entry.prob_handler = a2dp_to_dac_probe_handler; + entries[entry_cnt++] = &default_dac.entry; + } +#endif + + // 创建数据流,把所有节点连接起来 + dec->stream = audio_stream_open(dec, a2dp_dec_out_stream_resume); + audio_stream_add_list(dec->stream, entries, entry_cnt); + +#if (RECORDER_MIX_EN) + audio_stream_add_entry(entries[entry_cnt - 2], &dec->rec_mix_ch.entry); +#endif//RECORDER_MIX_EN + +#if TCFG_EQ_DIVIDE_ENABLE + struct audio_stream_entry *rl_rr_entries[16] = {NULL}; + entry_cnt = 0; + if (dec->eq_rl_rr) { //接在eq_drc的上一个节点 + rl_rr_entries[entry_cnt++] = entries[rl_rr_entry_start]; + rl_rr_entries[entry_cnt++] = &dec->eq_rl_rr->entry; + if (dec->drc_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->drc_rl_rr->entry; + } + if (dec->convert_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->convert_rl_rr->entry; + } +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + if (dec->rl_rr_mix) { + rl_rr_entries[entry_cnt++] = &dec->rl_rr_mix->entry; + } +#endif + if (dec->gain_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->gain_rl_rr->entry; + } + + rl_rr_entries[entry_cnt++] = &dec->synthesis_ch_rl_rr.entry;//必须是最后一个 + for (int i = 0; i < (entry_cnt - 1); i++) { + audio_stream_add_entry(rl_rr_entries[i], rl_rr_entries[i + 1]); + } + } +#endif + + // 设置音频输出类型 + audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); + + log_i("dec->ch:%d, fmt->channel:%d\n", dec->dec.ch, fmt->channel); + + // 关闭丢数 + a2dp_drop_frame_stop(); +#if TCFG_USER_TWS_ENABLE + if (tws_network_audio_was_started()) { + /*a2dp播放中副机加入*/ + tws_network_local_audio_start(); + a2dp_decoder_join_tws(&dec->dec); + } +#endif + + // 开始解码 + dec->dec.start = 1; + err = audio_decoder_start(&dec->dec.decoder); + if (err) { + goto __err3; + } + + clock_set_cur(); + + return 0; + +__err3: + dec->dec.start = 0; + +#if AUDIO_SURROUND_CONFIG + surround_close_demo(dec->surround); +#endif + + +#if AUDIO_VBASS_CONFIG + audio_gain_close_demo(dec->vbass_prev_gain); + audio_vbass_close_demo(dec->vbass); +#endif + high_bass_eq_close(dec->high_bass); + high_bass_drc_close(dec->hb_drc); + convet_data_close(dec->hb_convert); +#if TCFG_EQ_ENABLE && TCFG_BT_MUSIC_EQ_ENABLE + music_eq_close(dec->eq); +#if TCFG_DRC_ENABLE && TCFG_BT_MUSIC_DRC_ENABLE + music_drc_close(dec->drc); +#endif + convet_data_close(dec->convert); + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + music_eq2_close(dec->eq2); + audio_dynamic_eq_ctrl_close(dec->dy_eq); + convet_data_close(dec->convert2); +#endif + audio_gain_close_demo(dec->gain); +#endif + +#if TCFG_EQ_DIVIDE_ENABLE + music_eq_rl_rr_close(dec->eq_rl_rr); + music_drc_rl_rr_close(dec->drc_rl_rr); + convet_data_close(dec->convert_rl_rr); +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + stream_entry_close(&dec->rl_rr_mix); +#endif + audio_gain_close_demo(dec->gain_rl_rr); + + audio_vocal_tract_synthesis_close(&dec->synthesis_ch_fl_fr); + audio_vocal_tract_synthesis_close(&dec->synthesis_ch_rl_rr); + audio_vocal_tract_close(&dec->vocal_tract); + channel_switch_close(&dec->ch_switch); +#endif + + + + if (AUDIO_DEC_BT_MIXER_EN) { + audio_mixer_ch_close(&dec->mix_ch); + } else { + bt_dec_stream_run_stop(&dec->dec.decoder); + } +#if (RECORDER_MIX_EN) + audio_mixer_ch_close(&dec->rec_mix_ch); +#endif//RECORDER_MIX_EN + + if (dec->sync) { + a2dp_output_sync_close(dec->sync); + dec->sync = NULL; + } +#if SYS_DIGVOL_GROUP_EN + sys_digvol_group_ch_close("music_a2dp"); +#endif // SYS_DIGVOL_GROUP_EN + + + // 先关闭各个节点,最后才close数据流 + if (dec->stream) { + audio_stream_close(dec->stream); + dec->stream = NULL; + } + +__err2: + a2dp_decoder_close(&dec->dec); +__err1: + a2dp_dec_release(); + + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief a2dp解码资源等待 + @param *wait: 句柄 + @param event: 事件 + @return 0:成功 + @note 用于多解码打断处理 +*/ +/*----------------------------------------------------------------------------*/ +static int a2dp_wait_res_handler(struct audio_res_wait *wait, int event) +{ + int err = 0; + + log_i("a2dp_wait_res_handler: %d\n", event); + + if (event == AUDIO_RES_GET) { + err = a2dp_dec_start(); + } else if (event == AUDIO_RES_PUT) { + if (bt_a2dp_dec->dec.start) { + a2dp_audio_res_close(); + a2dp_drop_frame_start(); + } + } + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 打开a2dp解码 + @param media_type: 媒体类型 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int a2dp_dec_open(int media_type) +{ + struct a2dp_dec_hdl *dec; + + if (bt_a2dp_dec) { + return 0; + } + + log_i("a2dp_dec_open: %d\n", media_type); + + if (a2dp_suspend) { +#if (TCFG_USER_TWS_ENABLE) + if (tws_api_get_role() == TWS_ROLE_MASTER) +#endif//TCFG_USER_TWS_ENABLE + { + if (drop_a2dp_timer == 0) { + drop_a2dp_timer = sys_timer_add(NULL, + a2dp_media_clear_packet_before_seqn, 100); + } + } + return 0; + } + + dec = zalloc(sizeof(*dec)); + if (!dec) { + return -ENOMEM; + } + + switch (media_type) { + case A2DP_CODEC_SBC: + log_i("a2dp_media_type:SBC"); + dec->dec.coding_type = AUDIO_CODING_SBC; + clock_add(DEC_SBC_CLK); + break; + case A2DP_CODEC_MPEG24: + log_i("a2dp_media_type:AAC"); + dec->dec.coding_type = AUDIO_CODING_AAC; + clock_add(DEC_AAC_CLK); + break; + default: + log_i("a2dp_media_type unsupoport:%d", media_type); + free(dec); + return -EINVAL; + } + + bt_a2dp_dec = dec; + dec->wait.priority = 1; // 解码优先级 + dec->wait.preemption = 0; // 不使能直接抢断解码 + dec->wait.snatch_same_prio = 1; // 可抢断同优先级解码 +#if SOUNDCARD_ENABLE + dec->wait.protect = 1; +#endif + dec->wait.handler = a2dp_wait_res_handler; + audio_decoder_task_add_wait(&decode_task, &dec->wait); + + if (bt_a2dp_dec && (bt_a2dp_dec->dec.start == 0)) { + a2dp_drop_frame_start(); + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭a2dp解码 + @param + @return 0: 没有a2dp解码 + @return 1: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int a2dp_dec_close(void) +{ + if (drop_a2dp_timer) { + sys_timer_del(drop_a2dp_timer); + drop_a2dp_timer = 0; + } + if (!bt_a2dp_dec) { + return 0; + } + bt_a2dp_dec->closing = 1; + + if (bt_a2dp_dec->dec.start) { + a2dp_audio_res_close(); + } + a2dp_dec_release();/*free bt_a2dp_dec*/ + clock_set_cur(); + log_i("a2dp_dec_close: exit\n"); + return 1; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief a2dp挂起 + @param *p: 私有参数 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int a2dp_tws_dec_suspend(void *p) +{ + r_printf("a2dp_tws_dec_suspend\n"); + /*mem_stats();*/ + + if (a2dp_suspend) { + return -EINVAL; + } + a2dp_suspend = 1; + + if (bt_a2dp_dec) { + a2dp_dec_close(); + a2dp_media_clear_packet_before_seqn(0); +#if (TCFG_USER_TWS_ENABLE) + if (tws_api_get_role() == 0) +#endif//TCFG_USER_TWS_ENABLE + { + drop_a2dp_timer = sys_timer_add(NULL, a2dp_media_clear_packet_before_seqn, 100); + } + } + + int err = audio_decoder_fmt_lock(&decode_task, AUDIO_CODING_AAC); + if (err) { + log_e("AAC_dec_lock_faild\n"); + } + + return err; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief a2dp挂起激活 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void a2dp_tws_dec_resume(void) +{ + r_printf("a2dp_tws_dec_resume\n"); + + if (a2dp_suspend) { + a2dp_suspend = 0; + + if (drop_a2dp_timer) { + sys_timer_del(drop_a2dp_timer); + drop_a2dp_timer = 0; + } + + audio_decoder_fmt_unlock(&decode_task, AUDIO_CODING_AAC); + + int type = a2dp_media_get_codec_type(); + printf("codec_type: %d\n", type); + if (type >= 0) { +#if (TCFG_USER_TWS_ENABLE) + if (tws_api_get_role() == 0) +#endif//TCFG_USER_TWS_ENABLE + { + a2dp_media_clear_packet_before_seqn(0); + } + /* a2dp_resume_time = jiffies + msecs_to_jiffies(80); */ + a2dp_dec_open(type); + } + } +} + +#if TCFG_ESCO_PLC +/*----------------------------------------------------------------------------*/ +/**@brief esco丢包修护初始化 + @param + @return 丢包修护句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void *esco_plc_init(void) +{ + void *plc = malloc(PLC_query()); /*buf_size:1040*/ + //plc = zalloc_mux(PLC_query()); + log_i("PLC_buf:0x%x,size:%d\n", (int)plc, PLC_query()); + if (!plc) { + return NULL; + } + int err = PLC_init(plc); + if (err) { + log_i("PLC_init err:%d", err); + free(plc); + plc = NULL; + } + return plc; +} +/*----------------------------------------------------------------------------*/ +/**@brief esco丢包修护关闭 + @param *plc: 丢包修护句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void esco_plc_close(void *plc) +{ + free(plc); +} +/*----------------------------------------------------------------------------*/ +/**@brief esco丢包修护运行 + @param *data: 数据 + @param len: 数据长度 + @param repair: 修护标记 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void esco_plc_run(s16 *data, u16 len, u8 repair) +{ + u16 repair_point, tmp_point; + s16 *p_in, *p_out; + p_in = data; + p_out = data; + tmp_point = len / 2; + +#if 0 //debug + static u16 repair_cnt = 0; + if (repair) { + repair_cnt++; + y_printf("[E%d]", repair_cnt); + } else { + repair_cnt = 0; + } + //log_i("[%d]",point); +#endif/*debug*/ + + while (tmp_point) { + repair_point = (tmp_point > PLC_FRAME_LEN) ? PLC_FRAME_LEN : tmp_point; + tmp_point = tmp_point - repair_point; + PLC_run(p_in, p_out, repair_point, repair); + p_in += repair_point; + p_out += repair_point; + } +} +#endif + + + + +/*----------------------------------------------------------------------------*/ +/**@brief esco解码输出数据处理 + @param *entry: 数据流入口 + @param *in: 输入数据 + @param *out: 输出数据 + @return 处理了多长数据 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int esco_dec_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + struct audio_decoder *decoder = container_of(entry, struct audio_decoder, entry); + struct esco_decoder *esco_dec = container_of(decoder, struct esco_decoder, decoder); + struct esco_dec_hdl *dec = container_of(esco_dec, struct esco_dec_hdl, dec); + + if (dec->remain == 0) { + if (dec->tws_mute_en) { + memset(in->data, 0, in->data_len); + } + +#if TCFG_ESCO_PLC + if (dec->plc && out && out->data) { + esco_plc_run(in->data, in->data_len, *(u8 *)out->data); + } +#endif/*TCFG_ESCO_PLC*/ +#ifdef TCFG_ESCO_NOISEGATE + if (dec->noisegate) { + run_noisegate(dec->noisegate, in->data, in->data, in->data_len); + } +#endif /*TCFG_ESCO_NOISEGATE*/ + + } + + out->no_subsequent = 1; + + struct audio_data_frame out_frame; + memcpy(&out_frame, in, sizeof(struct audio_data_frame)); + audio_stream_run(&decoder->entry, &out_frame); + int wlen = decoder->process_len; + /* int wlen = esco_decoder_output_handler(&dec->dec, in); */ + + + if (in->data_len != wlen) { + dec->remain = 1; + } else { + dec->remain = 0; + } + return wlen; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief esco解码释放 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void esco_dec_release() +{ + audio_decoder_task_del_wait(&decode_task, &bt_esco_dec->wait); + + if (bt_esco_dec->dec.coding_type == AUDIO_CODING_MSBC) { + clock_remove(DEC_MSBC_CLK); + } else if (bt_esco_dec->dec.coding_type == AUDIO_CODING_CVSD) { + clock_remove(DEC_CVSD_CLK); + } + + local_irq_disable(); + free(bt_esco_dec); + bt_esco_dec = NULL; + local_irq_enable(); +} + +/*----------------------------------------------------------------------------*/ +/**@brief esco解码事件返回 + @param *decoder: 解码器句柄 + @param argc: 参数个数 + @param *argv: 参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void esco_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ + switch (argv[0]) { + case AUDIO_DEC_EVENT_END: + log_i("AUDIO_DEC_EVENT_END\n"); + esco_dec_close(); + break; + } +} + +static int esco_to_dac_probe_handler(struct audio_stream_entry *entry, struct audio_data_frame *in) +{ + if (!in->stop) { + if (bt_esco_dec->sync) { + in->data_sync = 1; + } + } + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief esco解码close + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +extern void audio_aec_ref_src_close(); +static void esco_audio_res_close(void) +{ + /* + *先关闭aec,里面有复用到enc的buff,再关闭enc, + *如果没有buf复用,则没有先后顺序要求。 + */ + if (!bt_esco_dec->dec.start) { + return ; + } + bt_esco_dec->dec.start = 0; + bt_esco_dec->dec.enc_start = 0; +#if (TCFG_IIS_ENABLE && TCFG_IIS_OUTPUT_EN) + audio_aec_ref_src_close(); +#endif //(TCFG_IIS_ENABLE && TCFG_IIS_OUTPUT_EN) + audio_aec_close(); + esco_enc_close(); + esco_decoder_close(&bt_esco_dec->dec); +#if TCFG_EQ_ENABLE &&TCFG_PHONE_EQ_ENABLE + esco_eq_close(bt_esco_dec->eq); +#if TCFG_DRC_ENABLE && ESCO_DRC_EN + esco_drc_close(bt_esco_dec->drc); +#endif + convet_data_close(bt_esco_dec->convert); +#endif + + spectrum_switch_demo(1);//打开频谱计算 + channel_switch_close(&bt_esco_dec->ch_switch); + esco_output_sync_close(bt_esco_dec->sync); + bt_esco_dec->sync = NULL; + if (AUDIO_DEC_BT_MIXER_EN) { + audio_mixer_ch_close(&bt_esco_dec->mix_ch); + } else { + default_dac.entry.prob_handler = NULL; + bt_dec_stream_run_stop(&bt_esco_dec->dec.decoder); + } +#if (RECORDER_MIX_EN) + audio_mixer_ch_close(&bt_esco_dec->rec_mix_ch); +#endif//RECORDER_MIX_EN + + +#if TCFG_ESCO_PLC + if (bt_esco_dec->plc) { + esco_plc_close(bt_esco_dec->plc); + bt_esco_dec->plc = NULL; + } +#endif/*TCFG_ESCO_PLC*/ + + + +#if TCFG_ESCO_NOISEGATE + if (bt_esco_dec->noisegate) { + close_noisegate(bt_esco_dec->noisegate); + bt_esco_dec->noisegate = NULL; + } +#endif /*TCFG_ESCO_NOISEGATE*/ + +#if SYS_DIGVOL_GROUP_EN + sys_digvol_group_ch_close("call_esco"); +#endif // SYS_DIGVOL_GROUP_EN + + + // 先关闭各个节点,最后才close数据流 + if (bt_esco_dec->stream) { + audio_stream_close(bt_esco_dec->stream); + bt_esco_dec->stream = NULL; + } + +#if TCFG_ESCO_USE_SPEC_MIX_LEN + /*恢复mix_buf的长度*/ + audio_mixer_set_output_buf(&mixer, mix_buff, AUDIO_MIXER_LEN); +#endif /*TCFG_ESCO_USE_SPEC_MIX_LEN*/ + app_audio_state_exit(APP_AUDIO_STATE_CALL); + bt_esco_dec->dec.start = 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief esco解码数据流激活 + @param *p: 私有句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void esco_dec_out_stream_resume(void *p) +{ + struct esco_dec_hdl *dec = (struct esco_dec_hdl *)p; + + /* audio_decoder_resume(&dec->dec.decoder); */ +} + +/*----------------------------------------------------------------------------*/ +/**@brief esco接受回调 + @param + @return + @note 蓝牙库里面接受到了esco音频 +*/ +/*----------------------------------------------------------------------------*/ +void esco_rx_notice_to_decode(void) +{ + if (bt_esco_dec && bt_esco_dec->dec.start) { + audio_decoder_resume(&bt_esco_dec->dec.decoder); + /* if (bt_esco_dec->dec.wait_resume) { */ + /* bt_esco_dec->dec.wait_resume = 0; */ + /* audio_decoder_resume(&bt_esco_dec->dec.decoder); */ + /* } */ + } +} + +void audio_aec_ref_src_get_output_rate(u16 *input_rate, u16 *output_rate) +{ + if (bt_esco_dec->sync) { + audio_wireless_sync_get_rate(bt_esco_dec->sync->context, input_rate, output_rate); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 开始esco解码 + @param + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +extern void audio_aec_ref_src_open(); +static int esco_dec_start() +{ + int err; + struct esco_dec_hdl *dec = bt_esco_dec; + + if (!bt_esco_dec) { + return -EINVAL; + } + // 打开esco解码 + err = esco_decoder_open(&dec->dec, &decode_task); + if (err) { + goto __err1; + } + // 使能事件回调 + audio_decoder_set_event_handler(&dec->dec.decoder, esco_dec_event_handler, 0); + +#if TCFG_ESCO_USE_SPEC_MIX_LEN + /* + *(1)bt_esco_dec输出是120或者240,所以通话的时候,修改mix_buff的长度,提高效率 + *(2)其他大部分时候解码输出是512的倍数,通话结束,恢复mix_buff的长度,提高效率 + */ + audio_mixer_set_output_buf(&mixer, mix_buff, AUDIO_MIXER_LEN / 240 * 240); +#endif /*TCFG_ESCO_USE_SPEC_MIX_LEN*/ + + if (AUDIO_DEC_BT_MIXER_EN) { + audio_mode_main_dec_open(AUDIO_MODE_MAIN_STATE_DEC_ESCO); + // 配置mixer通道参数 + audio_mixer_ch_open_head(&dec->mix_ch, &mixer); // 挂载到mixer最前面 + audio_mixer_ch_set_src(&dec->mix_ch, 1, 0); + audio_mixer_ch_set_no_wait(&dec->mix_ch, 1, 10); // 超时自动丢数 + audio_mixer_ch_sample_sync_enable(&dec->mix_ch, 1); + audio_mixer_ch_set_sample_rate(&dec->mix_ch, dec->dec.sample_rate); + } + +#if (RECORDER_MIX_EN) + audio_mixer_ch_open_head(&dec->rec_mix_ch, &recorder_mixer); // 挂载到mixer最前面 + audio_mixer_ch_set_src(&dec->rec_mix_ch, 1, 0); + audio_mixer_ch_set_no_wait(&dec->rec_mix_ch, 1, 10); // 超时自动丢数 + audio_mixer_ch_sample_sync_enable(&dec->rec_mix_ch, 1); + audio_mixer_ch_set_sample_rate(&dec->mix_ch, dec->dec.sample_rate); + /* audio_mixer_ch_set_sample_rate(&dec->rec_mix_ch, dec->dec.sample_rate); */ + printf("[%s], dec->dec.sample_rate = %d\n", __FUNCTION__, dec->dec.sample_rate); +#endif//RECORDER_MIX_EN + + // eq、drc音效 +#if TCFG_EQ_ENABLE && TCFG_PHONE_EQ_ENABLE + u8 bit_wide = 0; + if (ESCO_DRC_EN) { + bit_wide = 1; + } + dec->eq = esco_eq_open(dec->dec.sample_rate, dec->dec.ch_num, bit_wide);// eq +#if TCFG_DRC_ENABLE && ESCO_DRC_EN + dec->drc = esco_drc_open(dec->dec.sample_rate, dec->dec.ch_num, bit_wide);//drc + if (bit_wide) { + dec->convert = convet_data_open(0, 512); + } +#endif/*TCFG_BT_MUSIC_DRC_ENABLE*/ +#endif + + spectrum_switch_demo(0);//关闭频谱计算 +#ifdef CONFIG_MIXER_CYCLIC +#if ESCO_DEC_OUT_DUAL + if (dec->dec.out_ch_num == 2) { + // 单独的单变双 + dec->ch_switch = channel_switch_open(AUDIO_CH_LR, (120 + 5) * 2 * 2); + } else +#endif /* #if ESCO_DEC_OUT_DUAL */ + { + // mixer_cyclic 中自带声道处理 + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 0, BIT(0) | BIT(1) | BIT(2) | BIT(3)); +#if (RECORDER_MIX_EN) + audio_mixer_ch_set_aud_ch_out(&dec->rec_mix_ch, 0, BIT(0) | BIT(1) | BIT(2) | BIT(3)); +#endif + } + +#else + if (dec->dec.ch_num != dec->dec.out_ch_num) { + u8 out_ch_type = AUDIO_CH_DIFF; + if (dec->dec.out_ch_num == 4) { + out_ch_type = AUDIO_CH_QUAD; + } else if (dec->dec.out_ch_num == 2) { + out_ch_type = AUDIO_CH_LR; + } + dec->ch_switch = channel_switch_open(out_ch_type, AUDIO_SYNTHESIS_LEN / 2); + } +#endif + + dec->dec.decoder.entry.data_handler = esco_dec_data_handler; + + // sync初始化 + if (AUDIO_DEC_BT_MIXER_EN) { + dec->sync = esco_output_sync_open(dec->dec.sample_rate, audio_mixer_get_sample_rate(&mixer), dec->dec.ch_num); + } else { + dec->sync = esco_output_sync_open(dec->dec.sample_rate, dec->dec.sample_rate, dec->dec.ch_num); + + } + /*使能同步,配置延时时间*/ + esco_decoder_stream_sync_enable(&dec->dec, dec->sync->context, dec->dec.sample_rate, 25); + // 数据流串联 + struct audio_stream_entry *entries[16] = {NULL}; + u8 entry_cnt = 0; + entries[entry_cnt++] = &dec->dec.decoder.entry; + if (dec->sync) { + entries[entry_cnt++] = dec->sync->entry; + } +#if TCFG_EQ_ENABLE && TCFG_PHONE_EQ_ENABLE + if (dec->eq) { + entries[entry_cnt++] = &dec->eq->entry; + if (dec->drc) { + entries[entry_cnt++] = &dec->drc->entry; + } + if (dec->convert) { + entries[entry_cnt++] = &dec->convert->entry; + } + } +#endif + if (dec->sync) { + entries[entry_cnt++] = dec->sync->resample_entry; + } + +#if SYS_DIGVOL_GROUP_EN + void *dvol_entry = sys_digvol_group_ch_open("call_esco", -1, NULL); + entries[entry_cnt++] = dvol_entry; +#endif // SYS_DIGVOL_GROUP_EN + + if (dec->ch_switch) { + entries[entry_cnt++] = &dec->ch_switch->entry; + } + + if (AUDIO_DEC_BT_MIXER_EN) { + entries[entry_cnt++] = &dec->mix_ch.entry; + } else { + default_dac.entry.prob_handler = esco_to_dac_probe_handler; + entries[entry_cnt++] = &default_dac.entry; + } + // 创建数据流,把所有节点连接起来 + dec->stream = audio_stream_open(dec, esco_dec_out_stream_resume); + audio_stream_add_list(dec->stream, entries, entry_cnt); + +#if (RECORDER_MIX_EN) + audio_stream_add_entry(entries[entry_cnt - 2], &dec->rec_mix_ch.entry); +#endif//RECORDER_MIX_EN + // 设置音频输出类型 + audio_output_set_start_volume(APP_AUDIO_STATE_CALL); + +#if TCFG_ESCO_PLC + // 丢包修护 + dec->plc = esco_plc_init(); +#endif + + + +#if TCFG_ESCO_NOISEGATE + NOISEGATE_PARM esco_noisegate_parm = { + .attackTime = 300, + .releaseTime = 5, + .threshold = LIMITER_NOISE_GATE, + .low_th_gain = LIMITER_NOISE_GAIN, + .sampleRate = dec->dec.sample_rate, + .channel = 1, + }; + dec->noisegate = open_noisegate(&esco_noisegate_parm, 0, 0); +#endif /*TCFG_ESCO_NOISEGATE*/ + +#if TCFG_USER_TWS_ENABLE + if (tws_network_audio_was_started()) { + tws_network_local_audio_start(); + esco_decoder_join_tws(&dec->dec); + } +#endif + lmp_private_esco_suspend_resume(2); + // 开始解码 + dec->dec.start = 1; + err = audio_decoder_start(&dec->dec.decoder); + if (err) { + goto __err3; + } + dec->dec.frame_get = 0; + + err = audio_aec_init(dec->dec.sample_rate); +#if (TCFG_IIS_ENABLE && TCFG_IIS_OUTPUT_EN) + audio_aec_ref_src_open(); +#endif //(TCFG_IIS_ENABLE && TCFG_IIS_OUTPUT_EN) + if (err) { + log_i("audio_aec_init failed:%d", err); + //goto __err3; + } + err = esco_enc_open(dec->dec.coding_type, dec->dec.esco_len); + if (err) { + log_i("audio_enc_open failed:%d", err); + goto __err3; + } + dec->dec.enc_start = 1; + + clock_set_cur(); + return 0; + +__err3: + dec->dec.start = 0; +#if TCFG_EQ_ENABLE &&TCFG_PHONE_EQ_ENABLE + esco_eq_close(dec->eq); +#if TCFG_DRC_ENABLE && ESCO_DRC_EN + esco_drc_close(dec->drc); +#endif + convet_data_close(dec->convert); +#endif + + spectrum_switch_demo(1);//打开频谱计算 + channel_switch_close(&dec->ch_switch); + if (AUDIO_DEC_BT_MIXER_EN) { + audio_mixer_ch_close(&dec->mix_ch); + } else { + bt_dec_stream_run_stop(&dec->dec.decoder); + } +#if (RECORDER_MIX_EN) + audio_mixer_ch_close(&dec->rec_mix_ch); +#endif//RECORDER_MIX_EN + + if (dec->sync) { + esco_output_sync_close(dec->sync); + dec->sync = NULL; + } +#if SYS_DIGVOL_GROUP_EN + sys_digvol_group_ch_close("call_esco"); +#endif // SYS_DIGVOL_GROUP_EN + + + if (dec->stream) { + audio_stream_close(dec->stream); + dec->stream = NULL; + } + +__err2: + esco_decoder_close(&dec->dec); +__err1: + esco_dec_release(); + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief esco解码资源等待 + @param *wait: 句柄 + @param event: 事件 + @return 0:成功 + @note 用于多解码打断处理 +*/ +/*----------------------------------------------------------------------------*/ +static int esco_wait_res_handler(struct audio_res_wait *wait, int event) +{ + int err = 0; + log_d("esco_wait_res_handler %d\n", event); + if (event == AUDIO_RES_GET) { + err = esco_dec_start(); + } else if (event == AUDIO_RES_PUT) { + if (bt_esco_dec->dec.start) { + lmp_private_esco_suspend_resume(1); + esco_audio_res_close(); + } + } + + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 打开esco解码 + @param *param: 媒体信息 + @param mutw: 静音 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int esco_dec_open(void *param, u8 mute) +{ + int err; + struct esco_dec_hdl *dec; + u32 esco_param = *(u32 *)param; + int esco_len = esco_param >> 16; + int codec_type = esco_param & 0x000000ff; + + log_i("esco_dec_open, type=%d,len=%d\n", codec_type, esco_len); + + dec = zalloc(sizeof(*dec)); + if (!dec) { + return -ENOMEM; + } + +#if TCFG_DEC2TWS_ENABLE + localtws_media_disable(); +#endif + + bt_esco_dec = dec; + + dec->tws_mute_en = mute; + dec->dec.esco_len = esco_len; +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) + +#if !TCFG_EQ_DIVIDE_ENABLE + dec->dec.out_ch_num = 2; +#else + dec->dec.out_ch_num = 4; +#endif +#else + dec->dec.out_ch_num = audio_output_channel_num(); +#endif + + printf("dec->dec.out_ch_num %d\n", dec->dec.out_ch_num); + if (codec_type == 3) { + dec->dec.coding_type = AUDIO_CODING_MSBC; + dec->dec.sample_rate = 16000; + dec->dec.ch_num = 1; + clock_add(DEC_MSBC_CLK); + } else if (codec_type == 2) { + dec->dec.coding_type = AUDIO_CODING_CVSD; + dec->dec.sample_rate = 8000; + dec->dec.ch_num = 1; + clock_add(DEC_CVSD_CLK); + } + + dec->wait.priority = 2; // 解码优先级 + dec->wait.preemption = 0; // 不使能直接抢断解码 + dec->wait.snatch_same_prio = 1; // 可抢断同优先级解码 + dec->wait.handler = esco_wait_res_handler; + err = audio_decoder_task_add_wait(&decode_task, &dec->wait); + if (bt_esco_dec && (bt_esco_dec->dec.start == 0)) { + lmp_private_esco_suspend_resume(1); + } + +#if AUDIO_OUTPUT_AUTOMUTE + extern void mix_out_automute_skip(u8 skip); + mix_out_automute_skip(1); +#endif + + return err; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭esco解码 + @param : + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void esco_dec_close() +{ + if (!bt_esco_dec) { + return; + } + + esco_audio_res_close(); + esco_dec_release(); + + log_i("esco_dec_close: exit\n"); +#if AUDIO_OUTPUT_AUTOMUTE + extern void mix_out_automute_skip(u8 skip); + mix_out_automute_skip(0); +#endif + clock_set_cur(); +#if TCFG_DEC2TWS_ENABLE + localtws_media_enable(); +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙音频正在运行 + @param + @return 1: 正在运行 + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 bt_audio_is_running(void) +{ + return (bt_a2dp_dec || bt_esco_dec); +} +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙播放正在运行 + @param + @return 1: 正在运行 + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 bt_media_is_running(void) +{ + return bt_a2dp_dec != NULL; +} +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙电话正在运行 + @param + @return 1: 正在运行 + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 bt_phone_dec_is_running() +{ + return bt_esco_dec != NULL; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 蓝牙解码idle判断 + @param + @return 1: idle + @return 0: busy + @note +*/ +/*----------------------------------------------------------------------------*/ +static u8 bt_dec_idle_query() +{ + if (bt_audio_is_running()) { + return 0; + } + + return 1; +} +REGISTER_LP_TARGET(bt_dec_lp_target) = { + .name = "bt_dec", + .is_idle = bt_dec_idle_query, +}; + + diff --git a/cpu/br23/audio_dec/audio_dec_bt.h b/cpu/br23/audio_dec/audio_dec_bt.h new file mode 100644 index 0000000..d96d0d9 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_bt.h @@ -0,0 +1,31 @@ + +#ifndef _AUDIO_DEC_BT_H_ +#define _AUDIO_DEC_BT_H_ + +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "media/audio_decoder.h" + +// a2dp或者esco正在播放 +u8 bt_audio_is_running(void); +// a2dp正在播放 +u8 bt_media_is_running(void); +// esco正在播放 +u8 bt_phone_dec_is_running();; + +// 打开a2dp解码 +int a2dp_dec_open(int media_type); +// 关闭a2dp解码 +int a2dp_dec_close(); + +// 打开esco解码 +int esco_dec_open(void *, u8); +// 关闭esco解码 +void esco_dec_close(); + +// a2dp传输中止 +void __a2dp_drop_frame(void *p); + +#endif + diff --git a/cpu/br23/audio_dec/audio_dec_file.c b/cpu/br23/audio_dec/audio_dec_file.c new file mode 100644 index 0000000..1631a75 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_file.c @@ -0,0 +1,1541 @@ +/* + **************************************************************** + *File : audio_dec_file.c + *Note : + * + **************************************************************** + */ +////////////////////////////////////////////////////////////////////////////// +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "effectrs_sync.h" +#include "app_config.h" +#include "audio_config.h" +#include "audio_dec.h" +#include "app_config.h" +#include "app_main.h" +#include "classic/tws_api.h" + +#include "music/music_decrypt.h" +#include "music/music_id3.h" +/* #include "pitchshifter/pitchshifter_api.h" */ +/* #include "mono2stereo/reverb_mono2stero_api.h" */ +#include "audio_enc.h" +#include "clock_cfg.h" +#include "media/audio_voice_changer.h" +#include "media/audio_eq_drc_apply.h" +#include "audio_base.h" +#include "channel_switch.h" +#include "media/convert_data.h" +#include "audio_effect/audio_dynamic_eq_demo.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" +#include "avctp_user.h" + +#if TCFG_APP_MUSIC_EN + + +#define FILE_DEC_PICK_EN 1 // 本地解码拆包转发 + +#if (!TCFG_DEC2TWS_ENABLE) +#undef FILE_DEC_PICK_EN +#define FILE_DEC_PICK_EN 0 +#endif + +#ifndef BREAKPOINT_DATA_LEN +#define BREAKPOINT_DATA_LEN 32 +#endif + +const int FILE_DEC_ONCE_OUT_NUM = ((512 * 4) * 2); // 一次最多输出长度。避免多解码叠加时卡住其他解码太长时间 + +// 文件解码输出使用单独任务 +#if TCFG_AUDIO_DEC_OUT_TASK +#define FILE_DEC_USE_OUT_TASK 1 +#else +#define FILE_DEC_USE_OUT_TASK 0 +#endif + +#define CHECK_SR_WHEN_DECODING 0 //每次run都检测采样率 +////////////////////////////////////////////////////////////////////////////// + +struct dec_type { + u32 type; // 解码类型 + u32 clk; // 解码时钟 +}; + +const struct dec_type dec_clk_tb[] = { + {AUDIO_CODING_MP3, DEC_MP3_CLK}, + {AUDIO_CODING_WAV, DEC_WAV_CLK}, + {AUDIO_CODING_G729, DEC_G729_CLK}, + {AUDIO_CODING_G726, DEC_G726_CLK}, + {AUDIO_CODING_PCM, DEC_PCM_CLK}, + {AUDIO_CODING_MTY, DEC_MTY_CLK}, + {AUDIO_CODING_WMA, DEC_WMA_CLK}, + + {AUDIO_CODING_APE, DEC_APE_CLK}, + {AUDIO_CODING_FLAC, DEC_FLAC_CLK}, + {AUDIO_CODING_DTS, DEC_DTS_CLK}, + {AUDIO_CODING_M4A, DEC_M4A_CLK}, + {AUDIO_CODING_ALAC, DEC_ALAC_CLK}, + {AUDIO_CODING_MIDI, DEC_MIDI_CLK}, + + {AUDIO_CODING_MP3 | AUDIO_CODING_STU_PICK, DEC_MP3PICK_CLK}, + {AUDIO_CODING_WMA | AUDIO_CODING_STU_PICK, DEC_WMAPICK_CLK}, + {AUDIO_CODING_M4A | AUDIO_CODING_STU_PICK, DEC_M4APICK_CLK}, +}; + +////////////////////////////////////////////////////////////////////////////// + +struct file_dec_hdl *file_dec = NULL; // 文件解码句柄 +u8 file_dec_start_pause = 0; // 启动解码后但不马上开始播放 + + +////////////////////////////////////////////////////////////////////////////// + + +extern void put_u16hex(u16 dat); + +extern int tws_api_get_tws_state(); +extern void local_tws_sync_no_check_data_buf(u8 no_check); + +int file_dec_repeat_set(u8 repeat_num); + + +////////////////////////////////////////////////////////////////////////////// +/*----------------------------------------------------------------------------*/ +/**@brief 获取文件解码hdl + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void *get_file_dec_hdl() +{ + return file_dec; +} +/*----------------------------------------------------------------------------*/ +/**@brief 解码时钟添加 + @param type: 解码类型 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void dec_clock_add(u32 type) +{ + int i = 0; + for (i = 0; i < ARRAY_SIZE(dec_clk_tb); i++) { + if (type == dec_clk_tb[i].type) { + clock_add(dec_clk_tb[i].clk); + return; + } + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 解码时钟移除 + @param type: 解码类型 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void dec_clock_remove(u32 type) +{ + int i = 0; + for (i = 0; i < ARRAY_SIZE(dec_clk_tb); i++) { + if (type == dec_clk_tb[i].type) { + clock_remove(dec_clk_tb[i].clk); + return; + } + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 读取文件数据 + @param *decoder: 解码器句柄 + @param *buf: 数据 + @param len: 数据长度 + @return >=0:读到的数据长度 + @return <0:错误 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int file_fread(struct audio_decoder *decoder, void *buf, u32 len) +{ + struct file_decoder *file_dec = container_of(decoder, struct file_decoder, decoder); + struct file_dec_hdl *dec = container_of(file_dec, struct file_dec_hdl, file_dec); + int rlen; +#if TCFG_DEC_DECRYPT_ENABLE + // 解密读取 + u32 addr; + addr = fpos(dec->file); + rlen = fread(dec->file, buf, len); + if (rlen && (rlen <= len)) { + // read后进行解密 + cryptanalysis_buff(&dec->mply_cipher, buf, addr, rlen); + } +#else + rlen = fread(dec->file, buf, len); +#endif + if (rlen > len) { + // putchar('r'); + if (rlen == (-1)) { + //file err + dec->read_err = 1; + } else { + //dis err + dec->read_err = 2; + } + rlen = 0; + } else { + // putchar('R'); + dec->read_err = 0; + } + return rlen; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 文件指针定位 + @param *decoder: 解码器句柄 + @param offset: 定位偏移 + @param seek_mode: 定位类型 + @return 0:成功 + @return 非0:错误 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int file_fseek(struct audio_decoder *decoder, u32 offset, int seek_mode) +{ + struct file_decoder *file_dec = container_of(decoder, struct file_decoder, decoder); + struct file_dec_hdl *dec = container_of(file_dec, struct file_dec_hdl, file_dec); + return fseek(dec->file, offset, seek_mode); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 读取文件长度 + @param *decoder: 解码器句柄 + @return 文件长度 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int file_flen(struct audio_decoder *decoder) +{ + struct file_decoder *file_dec = container_of(decoder, struct file_decoder, decoder); + struct file_dec_hdl *dec = container_of(file_dec, struct file_dec_hdl, file_dec); + int len = 0; + len = flen(dec->file); + return len; +} + +// 先检查完file_input中定义的类型,最后检查file_input_coding_more定义的数据类型 +static const u32 file_input_coding_more[] = { +#if TCFG_DEC_WAV_ENABLE + AUDIO_CODING_WAV, +#endif + +#if TCFG_DEC_MP3_ENABLE + AUDIO_CODING_MP3, +#endif + 0, +}; + +static const struct audio_dec_input file_input = { + .coding_type = 0 +#if TCFG_DEC_WMA_ENABLE + | AUDIO_CODING_WMA +#endif + /* #if TCFG_DEC_WAV_ENABLE */ + /* | AUDIO_CODING_WAV */ + /* #endif */ +#if TCFG_DEC_FLAC_ENABLE + | AUDIO_CODING_FLAC +#endif +#if TCFG_DEC_APE_ENABLE + | AUDIO_CODING_APE +#endif +#if TCFG_DEC_M4A_ENABLE + | AUDIO_CODING_M4A +#endif +#if TCFG_DEC_ALAC_ENABLE + | AUDIO_CODING_ALAC +#endif +#if TCFG_DEC_AMR_ENABLE + | AUDIO_CODING_AMR +#endif +#if TCFG_DEC_DTS_ENABLE + | AUDIO_CODING_DTS +#endif +#if TCFG_DEC_G726_ENABLE + | AUDIO_CODING_G726 +#endif +#if TCFG_DEC_MIDI_ENABLE + | AUDIO_CODING_MIDI +#endif + , + .p_more_coding_type = (u32 *)file_input_coding_more, + .data_type = AUDIO_INPUT_FILE, + .ops = { + .file = { + .fread = file_fread, + .fseek = file_fseek, + .flen = file_flen, + } + } +}; + +/*----------------------------------------------------------------------------*/ +/**@brief 文件解码释放 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void file_dec_release(void) +{ + struct file_dec_hdl *dec = file_dec; + +#if TCFG_DEC_ID3_V1_ENABLE + if (dec->p_mp3_id3_v1) { + id3_obj_post(&dec->p_mp3_id3_v1); + } +#endif +#if TCFG_DEC_ID3_V2_ENABLE + if (dec->p_mp3_id3_v2) { + id3_obj_post(&dec->p_mp3_id3_v2); + } +#endif + + audio_decoder_task_del_wait(&decode_task, &dec->wait); + + if (dec->file_dec.decoder.fmt.coding_type) { + dec_clock_remove(dec->file_dec.decoder.fmt.coding_type); + } + + local_irq_disable(); + if (file_dec->dec_bp) { + free(file_dec->dec_bp); + file_dec->dec_bp = NULL; + } + free(file_dec); + file_dec = NULL; + local_irq_enable(); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 文件解码事件处理 + @param *decoder: 解码器句柄 + @param argc: 参数个数 + @param *argv: 参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void file_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ + switch (argv[0]) { + case AUDIO_DEC_EVENT_END: + log_i("AUDIO_DEC_EVENT_END\n"); + if (!file_dec) { + log_i("file_dec handle err "); + break; + } + + if (file_dec->id != argv[1]) { + log_w("file_dec id err : 0x%x, 0x%x \n", file_dec->id, argv[1]); + break; + } + + // 有回调,让上层close,避免close后上层读不到断点等 + if (file_dec->evt_cb) { + /* file_dec->evt_cb(file_dec->evt_priv, argc, argv); */ + int msg[2]; + msg[0] = argv[0]; + msg[1] = file_dec->read_err; + /* log_i("read err0:%d ", file_dec->read_err); */ + file_dec->evt_cb(file_dec->evt_priv, 2, msg); + } else { + file_dec_close(); + } + //audio_decoder_resume_all(&decode_task); + break; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 文件解码数据流激活 + @param *p: 私有句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void file_dec_out_stream_resume(void *p) +{ + struct file_dec_hdl *dec = p; +#if FILE_DEC_USE_OUT_TASK + if (dec->file_dec.dec_no_out_sound == 0) { + audio_decoder_resume_out_task(&dec->file_dec.decoder); + return ; + } +#endif + audio_decoder_resume(&dec->file_dec.decoder); +} + + +#if CHECK_SR_WHEN_DECODING +/*----------------------------------------------------------------------------*/ +/**@brief 文件解码预处理 + @param *decoder: 解码器句柄 + @return 0:成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int file_decoder_probe_handler_app(struct audio_decoder *decoder) +{ + struct file_decoder *dec = container_of(decoder, struct file_decoder, decoder); + dec->once_out_cnt = 0; + struct audio_fmt fmt = {0}; + audio_decoder_get_fmt_info(&dec->decoder, &fmt); + if (fmt.sample_rate) { + dec->decoder.fmt.sample_rate = fmt.sample_rate; + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 文件解码后处理 + @param *decoder: 解码器句柄 + @return 0:成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int file_decoder_post_handler_app(struct audio_decoder *decoder) +{ + struct file_decoder *dec = container_of(decoder, struct file_decoder, decoder); + if (dec->status) { + dec->dec_cur_time = audio_decoder_get_play_time(&dec->decoder); + } + if (FILE_DEC_ONCE_OUT_NUM && (dec->once_out_cnt >= FILE_DEC_ONCE_OUT_NUM)) { + audio_decoder_resume(&dec->decoder); + return 0; + } + return 0; +} + +//mp3特殊处理 +static const struct audio_dec_handler file_decoder_handler_app = { + .dec_probe = file_decoder_probe_handler_app, + .dec_post = file_decoder_post_handler_app, +}; +#endif +/*----------------------------------------------------------------------------*/ +/**@brief 文件解码开始 + @param + @return 0:成功 + @return 非0:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int file_dec_start(void) +{ + int err; + struct file_dec_hdl *dec = file_dec; + struct audio_mixer *p_mixer = &mixer; + u8 pcm_enc_flag = 0; + + if (!dec) { + return -EINVAL; + } + + log_i("file_dec_start: in\n"); + +#if FILE_DEC_PICK_EN + if (localtws_check_enable() == true) { + // 使用拆包方式传输 + err = file_decoder_open(&dec->file_dec, &file_input, &decode_task, + dec->bp, 1); + if (err == 0) { + dec->pick_flag = 1; + dec->file_dec.dec_no_out_sound = 1; + // 同步不需要检查buf变化 + local_tws_sync_no_check_data_buf(1); + // 打开localtws推送 + localtws_push_open(); + // 启动localtws功能 + localtws_start(&dec->file_dec.decoder.fmt); + // 关闭资源等待。最终会在localtws解码处等待 + audio_decoder_task_del_wait(&decode_task, &dec->wait); + goto __open_ok; + } + } +#endif + + // 打开file解码器 + err = file_decoder_open(&dec->file_dec, &file_input, &decode_task, + dec->bp, 0); + if (err) { + goto __err1; + } + +__open_ok: +#if CHECK_SR_WHEN_DECODING + if (dec->file_dec.decoder.dec_ops->coding_type == AUDIO_CODING_MP3) { + audio_decoder_set_handler(&dec->file_dec.decoder, &file_decoder_handler_app); //注册 解码时检测采样率 + } +#endif + + file_decoder_set_event_handler(&dec->file_dec, file_dec_event_handler, dec->id); + + // 获取id3 + if (dec->file_dec.decoder.dec_ops->coding_type == AUDIO_CODING_MP3) { +#if TCFG_DEC_ID3_V1_ENABLE + if (dec->p_mp3_id3_v1) { + id3_obj_post(&dec->p_mp3_id3_v1); + } + dec->p_mp3_id3_v1 = id3_v1_obj_get(dec->file); +#endif +#if TCFG_DEC_ID3_V2_ENABLE + if (dec->p_mp3_id3_v2) { + id3_obj_post(&dec->p_mp3_id3_v2); + } + dec->p_mp3_id3_v2 = id3_v2_obj_get(dec->file); +#endif + } + + +#if TCFG_PCM_ENC2TWS_ENABLE + if (dec->file_dec.dec_no_out_sound == 0) { + // 没有拆包的情况下,尝试使用sbc等编码转发 + struct audio_fmt enc_f; + memcpy(&enc_f, &dec->file_dec.decoder.fmt, sizeof(struct audio_fmt)); + enc_f.coding_type = AUDIO_CODING_SBC; + enc_f.channel = 2;//dec->file_dec.output_ch_num; // 使用双声道输出,localtws在解码时才变成对应声道 + int ret = localtws_enc_api_open(&enc_f, 0); + if (ret == true) { + dec->file_dec.dec_no_out_sound = 1; + // 重定向mixer + p_mixer = &g_localtws.mixer; + // 关闭资源等待。最终会在localtws解码处等待 + audio_decoder_task_del_wait(&decode_task, &dec->wait); + if (dec->file_dec.output_ch_num != enc_f.channel) { + dec->file_dec.output_ch_num = dec->file_dec.decoder.fmt.channel = enc_f.channel; + if (enc_f.channel == 2) { + dec->file_dec.output_ch_type = AUDIO_CH_LR; + } else { + dec->file_dec.output_ch_type = AUDIO_CH_DIFF; + } + } + // 重新设置解码输出声道 + file_decoder_set_output_channel(&dec->file_dec); + } + } +#endif + +#if TCFG_SPEED_PITCH_ENABLE + static PS69_CONTEXT_CONF pitch_param; + pitch_param.pitchV = 32768;//32767 是原始音调 >32768是音调变高,《32768 音调变低,建议范围20000 - 50000 + pitch_param.speedV = 40;//>80变快,<80 变慢,建议范围30-130 + pitch_param.sr = dec->file_dec.sample_rate ; + pitch_param.chn = dec->file_dec.output_ch_num ; + dec->p_pitchspeed_hdl = open_pitchspeed(&pitch_param, NULL); +#endif + if (!dec->file_dec.dec_no_out_sound) { + audio_mode_main_dec_open(AUDIO_MODE_MAIN_STATE_DEC_FILE); + } + // 设置叠加功能 + audio_mixer_ch_open_head(&dec->mix_ch, p_mixer); + audio_mixer_ch_set_src(&dec->mix_ch, 1, 0); + +#if FILE_DEC_USE_OUT_TASK + if (dec->file_dec.dec_no_out_sound == 0) { + audio_decoder_out_task_ch_enable(&dec->file_dec.decoder, 1024); + } +#endif + + dec_clock_add(dec->file_dec.decoder.dec_ops->coding_type); + + + if (dec->stream_handler && (dec->pick_flag == 0)) { + dec->stream_handler(dec->stream_priv, FILE_DEC_STREAM_OPEN, dec); + goto __stream_set_end; + } +#if AUDIO_SURROUND_CONFIG + dec->surround = surround_open_demo(AEID_MUSIC_SURROUND, dec->file_dec.output_ch_type); +#endif + +#if AUDIO_VBASS_CONFIG + dec->vbass_prev_gain = audio_gain_open_demo(AEID_MUSIC_VBASS_PREV_GAIN, dec->file_dec.output_ch_num); + //虚拟低音 + dec->vbass = audio_vbass_open_demo(AEID_MUSIC_VBASS, dec->file_dec.sample_rate, dec->file_dec.output_ch_num); +#endif + + dec->high_bass = high_bass_eq_open(dec->file_dec.sample_rate, dec->file_dec.output_ch_num); + dec->hb_drc = high_bass_drc_open(dec->file_dec.sample_rate, dec->file_dec.output_ch_num); + if (dec->hb_drc && dec->hb_drc->run32bit) { + dec->hb_convert = convet_data_open(0, 512); + } + +#if TCFG_EQ_ENABLE && TCFG_MUSIC_MODE_EQ_ENABLE + dec->eq = music_eq_open(dec->file_dec.sample_rate, dec->file_dec.output_ch_num);// eq +#if TCFG_DRC_ENABLE && TCFG_MUSIC_MODE_DRC_ENABLE + dec->drc = music_drc_open(dec->file_dec.sample_rate, dec->file_dec.output_ch_num);//drc +#endif/*TCFG_MUSIC_MODE_DRC_ENABLE*/ + if (dec->eq && dec->eq->out_32bit) { + dec->convert = convet_data_open(0, 512); + } + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + dec->eq2 = music_eq2_open(dec->file_dec.sample_rate, dec->file_dec.output_ch_num);// eq + dec->dy_eq = audio_dynamic_eq_ctrl_open(dec->file_dec.sample_rate, dec->file_dec.output_ch_num);//动态eq + dec->convert2 = convet_data_open(0, 512); +#endif/*TCFG_DYNAMIC_EQ_ENABLE*/ + dec->gain = audio_gain_open_demo(AEID_MUSIC_GAIN, dec->file_dec.output_ch_num); +#endif/*TCFG_MUSIC_MODE_EQ_ENABLE*/ + +#if TCFG_EQ_DIVIDE_ENABLE + dec->eq_rl_rr = music_eq_rl_rr_open(dec->file_dec.sample_rate, dec->file_dec.output_ch_num);// eq +#if TCFG_DRC_ENABLE && TCFG_BT_MUSIC_DRC_ENABLE + dec->drc_rl_rr = music_drc_rl_rr_open(dec->file_dec.sample_rate, dec->file_dec.output_ch_num);//drc +#endif + if (dec->eq_rl_rr && dec->eq_rl_rr->out_32bit) { + dec->convert_rl_rr = convet_data_open(0, 512); + } +#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) && SOUND_TRACK_2_P_X_CH_CONFIG +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + dec->rl_rr_mix = stream_entry_open(NULL, stream_rl_rr_mix_data_handler, 0); +#endif +#endif + dec->gain_rl_rr = audio_gain_open_demo(AEID_MUSIC_RL_GAIN, dec->file_dec.output_ch_num); + + if (dec->eq_rl_rr) { + audio_vocal_tract_open(&dec->vocal_tract, AUDIO_SYNTHESIS_LEN); + { + u8 entry_cnt = 0; + struct audio_stream_entry *entries[8] = {NULL}; + entries[entry_cnt++] = &dec->vocal_tract.entry; + entries[entry_cnt++] = &dec->mix_ch.entry; + dec->vocal_tract.stream = audio_stream_open(&dec->vocal_tract, audio_vocal_tract_stream_resume); + audio_stream_add_list(dec->vocal_tract.stream, entries, entry_cnt); + } + audio_vocal_tract_synthesis_open(&dec->synthesis_ch_fl_fr, &dec->vocal_tract, FL_FR); + audio_vocal_tract_synthesis_open(&dec->synthesis_ch_rl_rr, &dec->vocal_tract, RL_RR); + } else { + dec->ch_switch = channel_switch_open(AUDIO_CH_QUAD, AUDIO_SYNTHESIS_LEN / 2); + } +#ifdef CONFIG_MIXER_CYCLIC + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 0, BIT(0)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 1, BIT(1)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 2, BIT(2)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 3, BIT(3)); +#endif + +#endif + + + + // 数据流串联 + struct audio_stream_entry *entries[16] = {NULL}; + u8 entry_cnt = 0; + u8 rl_rr_entry_start = 0; + entries[entry_cnt++] = &dec->file_dec.decoder.entry; +#if FILE_DEC_PICK_EN + if (dec->pick_flag) { + // 拆包直接输出到localtws推送,中间不经过任何处理 + entries[entry_cnt++] = &g_localtws.push.entry; + } else +#endif + { +#if TCFG_SPEED_PITCH_ENABLE + if (dec->p_pitchspeed_hdl) { + entries[entry_cnt++] = &dec->p_pitchspeed_hdl->entry; + } +#endif +#if AUDIO_SURROUND_CONFIG + if (dec->surround) { + entries[entry_cnt++] = &dec->surround->entry; + } +#endif + +#if AUDIO_VBASS_CONFIG + if (dec->vbass_prev_gain) { + entries[entry_cnt++] = &dec->vbass_prev_gain->entry; + } + if (dec->vbass) { + entries[entry_cnt++] = &dec->vbass->entry; + } +#endif + + if (dec->high_bass) { //高低音 + entries[entry_cnt++] = &dec->high_bass->entry; + } + if (dec->hb_drc) { //高低音后drc + entries[entry_cnt++] = &dec->hb_drc->entry; + if (dec->hb_convert) { + entries[entry_cnt++] = &dec->hb_convert->entry; + } + } + + rl_rr_entry_start = entry_cnt - 1;//记录eq的上一个节点 +#if TCFG_EQ_ENABLE && TCFG_MUSIC_MODE_EQ_ENABLE + + if (dec->eq) { + entries[entry_cnt++] = &dec->eq->entry; + if (dec->drc) { + entries[entry_cnt++] = &dec->drc->entry; + } + if (dec->convert) { + entries[entry_cnt++] = &dec->convert->entry; + } +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + if (dec->eq2) { + entries[entry_cnt++] = &dec->eq2->entry; + } + if (dec->dy_eq && dec->dy_eq->dy_eq) { + entries[entry_cnt++] = &dec->dy_eq->dy_eq->entry; + } + if (dec->convert2) { + entries[entry_cnt++] = &dec->convert2->entry; + } +#endif + if (dec->gain) { + entries[entry_cnt++] = &dec->gain->entry; + } + } +#endif + + + +#if SYS_DIGVOL_GROUP_EN + void *dvol_entry = sys_digvol_group_ch_open("music_file", -1, NULL); + entries[entry_cnt++] = dvol_entry; +#endif // SYS_DIGVOL_GROUP_EN + +#if TCFG_EQ_DIVIDE_ENABLE + if (dec->eq_rl_rr) { + entries[entry_cnt++] = &dec->synthesis_ch_fl_fr.entry;//四声道eq独立时,该节点后不接节点 + } else { + if (dec->ch_switch) { + entries[entry_cnt++] = &dec->ch_switch->entry; + } + entries[entry_cnt++] = &dec->mix_ch.entry; + } +#else + entries[entry_cnt++] = &dec->mix_ch.entry; +#endif + } + // 创建数据流,把所有节点连接起来 + dec->stream = audio_stream_open(dec, file_dec_out_stream_resume); + audio_stream_add_list(dec->stream, entries, entry_cnt); + +#if TCFG_EQ_DIVIDE_ENABLE + struct audio_stream_entry *rl_rr_entries[16] = {NULL}; + entry_cnt = 0; + if (dec->eq_rl_rr) { //接在eq_drc的上一个节点 + rl_rr_entries[entry_cnt++] = entries[rl_rr_entry_start]; + rl_rr_entries[entry_cnt++] = &dec->eq_rl_rr->entry; + if (dec->drc_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->drc_rl_rr->entry; + } + if (dec->convert_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->convert_rl_rr->entry; + } +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + if (dec->rl_rr_mix) { + rl_rr_entries[entry_cnt++] = &dec->rl_rr_mix->entry; + } +#endif + if (dec->gain_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->gain_rl_rr->entry; + } + + rl_rr_entries[entry_cnt++] = &dec->synthesis_ch_rl_rr.entry;//必须是最后一个 + for (int i = 0; i < (entry_cnt - 1); i++) { + audio_stream_add_entry(rl_rr_entries[i], rl_rr_entries[i + 1]); + } + } +#endif + +__stream_set_end: + log_i("total_time : %d \n", dec->file_dec.dec_total_time); + +#if FILE_DEC_REPEAT_EN + // 无缝循环播放 + file_dec_repeat_set(3); +#endif + +#if FILE_DEC_DEST_PLAY + // 跳到指定位置播放 + file_dec_set_start_play(3 * 1000); + /* u32 file_dec_dest_test_cb(void *priv); */ + /* file_dec_set_start_dest_play(2000, 4000, file_dec_dest_test_cb, dec); */ +#endif + + // 设置音频输出音量 + audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); + + // 文件打开就暂停 + if (file_dec_start_pause) { + log_i("file_dec_start_pause\n"); + file_dec_start_pause = 0; + dec->file_dec.status = FILE_DEC_STATUS_PAUSE; + return 0; + } + + // 设置时钟 + clock_set_cur(); + + // 开始解码 + dec->file_dec.status = FILE_DEC_STATUS_PLAY; + if (dec->evt_cb) { + int msg[2]; + msg[0] = AUDIO_DEC_EVENT_START; + dec->evt_cb(dec->evt_priv, 2, msg); + } + + + err = audio_decoder_start(&dec->file_dec.decoder); + if (err) { + goto __err3; + } + __bt_emitter_pp(1); + return 0; + +__err3: + dec->file_dec.status = 0; +#if TCFG_SPEED_PITCH_ENABLE + if (dec->p_pitchspeed_hdl) { + close_pitchspeed(dec->p_pitchspeed_hdl); + } +#endif + +#if AUDIO_SURROUND_CONFIG + surround_close_demo(dec->surround); +#endif + + +#if AUDIO_VBASS_CONFIG + audio_gain_close_demo(dec->vbass_prev_gain); + audio_vbass_close_demo(dec->vbass); +#endif + + high_bass_eq_close(dec->high_bass); + high_bass_drc_close(dec->hb_drc); + convet_data_close(dec->hb_convert); + +#if TCFG_EQ_ENABLE && TCFG_MUSIC_MODE_EQ_ENABLE + music_eq_close(dec->eq); +#if TCFG_DRC_ENABLE && TCFG_MUSIC_MODE_DRC_ENABLE + music_drc_close(dec->drc); +#endif + convet_data_close(dec->convert); +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + music_eq2_close(dec->eq2); + audio_dynamic_eq_ctrl_close(dec->dy_eq); + convet_data_close(dec->convert2); +#endif + audio_gain_close_demo(dec->gain); +#endif + +#if TCFG_EQ_DIVIDE_ENABLE + music_eq_rl_rr_close(dec->eq_rl_rr); + music_drc_rl_rr_close(dec->drc_rl_rr); + convet_data_close(dec->convert_rl_rr); +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + stream_entry_close(&dec->rl_rr_mix); +#endif + audio_gain_close_demo(dec->gain_rl_rr); + + audio_vocal_tract_synthesis_close(&dec->synthesis_ch_fl_fr); + audio_vocal_tract_synthesis_close(&dec->synthesis_ch_rl_rr); + audio_vocal_tract_close(&dec->vocal_tract); + channel_switch_close(&dec->ch_switch); +#endif + + + audio_mixer_ch_close(&dec->mix_ch); +#if TCFG_PCM_ENC2TWS_ENABLE + if (file_dec->file_dec.dec_no_out_sound) { + file_dec->file_dec.dec_no_out_sound = 0; + localtws_enc_api_close(); + } +#endif + if (dec->stream_handler) { + dec->stream_handler(dec->stream_priv, FILE_DEC_STREAM_CLOSE, dec); + } + +#if SYS_DIGVOL_GROUP_EN + sys_digvol_group_ch_close("music_file"); +#endif // SYS_DIGVOL_GROUP_EN + + + if (dec->stream) { + audio_stream_close(dec->stream); + dec->stream = NULL; + } + + file_decoder_close(&dec->file_dec); +__err1: + if (dec->evt_cb && (dec->wait_add == 0)) { + int msg[2]; + msg[0] = AUDIO_DEC_EVENT_ERR; + dec->evt_cb(dec->evt_priv, 2, msg); + } + file_dec_release(); + // 设置时钟 + clock_set_cur(); + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 文件解码资源等待 + @param *wait: 句柄 + @param event: 事件 + @return 0:成功 + @note 用于多解码打断处理。被打断时仅暂停解码 +*/ +/*----------------------------------------------------------------------------*/ +static int file_wait_res_handler(struct audio_res_wait *wait, int event) +{ + int err = 0; + + log_i("file_wait_res_handler, event:%d, status:%d ", event, file_dec->file_dec.status); + if (event == AUDIO_RES_GET) { + // 启动解码 + if (file_dec->file_dec.status == 0) { + err = file_dec_start(); + } else if (file_dec->file_dec.tmp_pause) { + file_dec->file_dec.tmp_pause = 0; + + audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); + if (file_dec->file_dec.status == FILE_DEC_STATUS_PLAY) { + err = audio_decoder_start(&file_dec->file_dec.decoder); + if (!file_dec->pick_flag) { + audio_mixer_ch_pause(&file_dec->mix_ch, 0); + } + } + __bt_emitter_pp(1); + } + } else if (event == AUDIO_RES_PUT) { + // 被打断 + if (file_dec->file_dec.status) { + if (file_dec->file_dec.status == FILE_DEC_STATUS_PLAY || \ + file_dec->file_dec.status == FILE_DEC_STATUS_PAUSE) { + if (!file_dec->pick_flag) { + audio_mixer_ch_pause(&file_dec->mix_ch, 1); + } + err = audio_decoder_pause(&file_dec->file_dec.decoder); + /* os_time_dly(2); */ + /* audio_output_stop(); */ + + } + file_dec->file_dec.tmp_pause = 1; + __bt_emitter_pp(0); + } + } + + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief file解码pp处理 + @param play: 1-播放。0-暂停 + @return + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +static void file_dec_pp_ctrl(u8 play) +{ + if (!file_dec) { + return ; + } + if (play) { + // 播放前处理 +#if (!TCFG_MIC_EFFECT_ENABLE) + clock_pause_play(0); +#endif/*TCFG_MIC_EFFECT_ENABLE*/ + if (!file_dec->pick_flag) { + audio_mixer_ch_pause(&file_dec->mix_ch, 0); + } +#if TCFG_DEC2TWS_ENABLE + if (file_dec->file_dec.dec_no_out_sound) { + localtws_decoder_pause(0); + } +#endif + __bt_emitter_pp(1); + } else { + // 暂停后处理 +#if TCFG_DEC2TWS_ENABLE + if (file_dec->file_dec.dec_no_out_sound) { + localtws_decoder_pause(1); + } +#endif + if (!file_dec->pick_flag) { + audio_mixer_ch_pause(&file_dec->mix_ch, 1); + //audio_decoder_resume_all(&decode_task); + } + if (audio_mixer_get_active_ch_num(&mixer) == 0) { +#if (!TCFG_MIC_EFFECT_ENABLE) + clock_pause_play(1); +#endif/*TCFG_MIC_EFFECT_ENABLE*/ + } + __bt_emitter_pp(0); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 创建一个文件解码 + @param *priv: 事件回调私有参数 + @param *handler: 事件回调句柄 + @return 0:成功 + @return 非0:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int file_dec_create(void *priv, void (*handler)(void *, int argc, int *argv)) +{ + struct file_dec_hdl *dec; + if (file_dec) { + file_dec_close(); + } + + dec = zalloc(sizeof(*dec)); + if (!dec) { + return -ENOMEM; + } + + file_dec = dec; + file_dec->evt_cb = handler; + file_dec->evt_priv = priv; + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 设置解码数据流设置回调接口 + @param *dec: 解码句柄 + @param *stream_handler: 数据流设置回调 + @param *stream_priv: 数据流设置回调私有句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void file_dec_set_stream_set_hdl(struct file_dec_hdl *dec, + void (*stream_handler)(void *priv, int event, struct file_dec_hdl *), + void *stream_priv) +{ + if (dec) { + dec->stream_handler = stream_handler; + dec->stream_priv = stream_priv; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 打开文件解码 + @param *file: 文件句柄 + @param *bp: 断点信息 + @return 0:成功 + @return 非0:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int file_dec_open(void *file, struct audio_dec_breakpoint *bp) +{ + int err; + struct file_dec_hdl *dec = file_dec; + + log_i("file_dec_open: in, 0x%x, bp:0x%x \n", file, bp); + + if ((!dec) || (!file)) { + return -EPERM; + } + dec->file = file; + dec->bp = bp; + dec->id = rand32(); + + dec->file_dec.ch_type = AUDIO_CH_MAX; + dec->file_dec.output_ch_num = audio_output_channel_num(); + dec->file_dec.output_ch_type = audio_output_channel_type(); + +#if TCFG_DEC_DECRYPT_ENABLE + cipher_init(&dec->mply_cipher, TCFG_DEC_DECRYPT_KEY); + cipher_check_decode_file(&dec->mply_cipher, file); +#endif + +#if TCFG_DEC2TWS_ENABLE + // 设置localtws重播接口 + localtws_globle_set_dec_restart(file_dec_push_restart); +#endif + + dec->wait.priority = 1; + dec->wait.preemption = 0; + dec->wait.snatch_same_prio = 1; + dec->wait.handler = file_wait_res_handler; + dec->wait_add = 1; + dec->wait.protect = 1; + err = audio_decoder_task_add_wait(&decode_task, &dec->wait); + if (file_dec) { + file_dec->wait_add = 0; + } + + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭文件解码 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void file_dec_close(void) +{ + if (!file_dec) { + return; + } + + if (file_dec->file_dec.status) { + if (file_dec->file_dec.dec_no_out_sound == 0) { + audio_mixer_ch_try_fadeout(&file_dec->mix_ch, 50); + } + file_dec->file_dec.status = 0; + audio_mixer_ch_pause(&file_dec->mix_ch, 1); + file_decoder_close(&file_dec->file_dec); +#if TCFG_SPEED_PITCH_ENABLE + if (file_dec->p_pitchspeed_hdl) { + close_pitchspeed(file_dec->p_pitchspeed_hdl); + } +#endif +#if AUDIO_SURROUND_CONFIG + surround_close_demo(file_dec->surround); +#endif + +#if AUDIO_VBASS_CONFIG + audio_gain_close_demo(file_dec->vbass_prev_gain); + audio_vbass_close_demo(file_dec->vbass); +#endif + + high_bass_eq_close(file_dec->high_bass); + high_bass_drc_close(file_dec->hb_drc); + convet_data_close(file_dec->hb_convert); + +#if TCFG_EQ_ENABLE && TCFG_MUSIC_MODE_EQ_ENABLE + music_eq_close(file_dec->eq); +#if TCFG_DRC_ENABLE && TCFG_MUSIC_MODE_DRC_ENABLE + music_drc_close(file_dec->drc); +#endif + convet_data_close(file_dec->convert); + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + music_eq2_close(file_dec->eq2); + audio_dynamic_eq_ctrl_close(file_dec->dy_eq); + convet_data_close(file_dec->convert2); +#endif + audio_gain_close_demo(file_dec->gain); +#endif + +#if TCFG_EQ_DIVIDE_ENABLE + music_eq_rl_rr_close(file_dec->eq_rl_rr); + music_drc_rl_rr_close(file_dec->drc_rl_rr); + convet_data_close(file_dec->convert_rl_rr); +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + stream_entry_close(&file_dec->rl_rr_mix); +#endif + audio_gain_close_demo(file_dec->gain_rl_rr); + + audio_vocal_tract_synthesis_close(&file_dec->synthesis_ch_fl_fr); + audio_vocal_tract_synthesis_close(&file_dec->synthesis_ch_rl_rr); + audio_vocal_tract_close(&file_dec->vocal_tract); + channel_switch_close(&file_dec->ch_switch); +#endif + + audio_mixer_ch_close(&file_dec->mix_ch); +#if TCFG_PCM_ENC2TWS_ENABLE + if (file_dec->file_dec.dec_no_out_sound) { + file_dec->file_dec.dec_no_out_sound = 0; + localtws_enc_api_close(); + } +#endif + if (file_dec->stream_handler) { + file_dec->stream_handler(file_dec->stream_priv, FILE_DEC_STREAM_CLOSE, file_dec); + } +#if SYS_DIGVOL_GROUP_EN + sys_digvol_group_ch_close("music_file"); +#endif // SYS_DIGVOL_GROUP_EN + + + // 先关闭各个节点,最后才close数据流 + if (file_dec->stream) { + audio_stream_close(file_dec->stream); + file_dec->stream = NULL; + } + + } + + file_dec_release(); + + clock_set_cur(); + __bt_emitter_pp(0); + log_i("file_dec_close: exit\n"); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 获取file_dec句柄 + @param + @return file_dec句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +struct file_decoder *file_dec_get_file_decoder_hdl(void) +{ + if (file_dec) { + return &file_dec->file_dec; + } + return NULL; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 获取file_dec状态 + @param + @return 解码状态 + @note +*/ +/*----------------------------------------------------------------------------*/ +int file_dec_get_status(void) +{ + struct file_decoder *dec = file_dec_get_file_decoder_hdl(); + if (dec) { + return dec->status; + } + return FILE_DEC_STATUS_STOP; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 文件解码重新开始 + @param id: 文件解码id + @return 0:成功 + @return 非0:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int file_dec_restart(int id) +{ + if ((!file_dec) || (id != file_dec->id)) { + return -1; + } + if (file_dec->bp == NULL) { + if (file_dec->dec_bp == NULL) { + file_dec->dec_bp = zalloc(sizeof(struct audio_dec_breakpoint) + BREAKPOINT_DATA_LEN); + ASSERT(file_dec->dec_bp); + file_dec->dec_bp->data_len = BREAKPOINT_DATA_LEN; + } + file_dec->bp = file_dec->dec_bp; + } + if (file_dec->file_dec.status && file_dec->bp) { + audio_decoder_get_breakpoint(&file_dec->file_dec.decoder, file_dec->bp); + } + + void *file = file_dec->file; + void *bp = file_dec->bp; + void *evt_cb = file_dec->evt_cb; + void *evt_priv = file_dec->evt_priv; + int err; + void *dec_bp = file_dec->dec_bp; // 先保存一下,避免close被释放 + file_dec->dec_bp = NULL; + + file_dec_close(); + err = file_dec_create(evt_priv, evt_cb); + if (!err) { + file_dec->dec_bp = dec_bp; // 还原回去 + err = file_dec_open(file, bp); + } else { + if (dec_bp) { + free(dec_bp); // 失败,释放 + } + } + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 推送文件解码重新开始命令 + @param + @return true:成功 + @return false:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int file_dec_push_restart(void) +{ + if (!file_dec) { + return false; + } + int argv[3]; + argv[0] = (int)file_dec_restart; + argv[1] = 1; + argv[2] = (int)file_dec->id; + os_taskq_post_type(os_current_task(), Q_CALLBACK, ARRAY_SIZE(argv), argv); + return true; +} + +#if FILE_DEC_DEST_PLAY +static u32 file_dec_dest_test_cb(void *priv) +{ + struct file_dec_hdl *dec = priv; + static u8 cnt = 0; + if (cnt < 3) { + cnt ++; + printf("file_dec_dest_test_cb"); + struct audio_dest_time_play_param param = {0}; + param.start_time = 20 * 1000; + param.dest_time = 30 * 1000; + param.callback_func = file_dec_dest_test_cb; + param.callback_priv = dec; + audio_decoder_ioctrl(&dec->file_dec.decoder, AUDIO_IOCTRL_CMD_SET_DEST_PLAYPOS, ¶m); + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 跳到指定位置开始播放,播放到目标时间后回调 + @param start_time: 要跳转过去播放的起始时间 + @param dest_time: 要跳转过去播放的目标时间 + @param *cb: 到达目标时间后回调 + @param *cb_priv: 回调参数 + @return true:成功 + @return false:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int file_dec_set_start_dest_play(u32 start_time, u32 dest_time, u32(*cb)(void *), void *cb_priv) +{ + struct file_dec_hdl *dec = file_dec; + if (!dec || !dec->file_dec.decoder.dec_ops) { + return false; + } + switch (dec->file_dec.decoder.dec_ops->coding_type) { + case AUDIO_CODING_MP3: { + struct audio_dest_time_play_param param = {0}; + param.start_time = start_time; + param.dest_time = dest_time; + param.callback_func = cb; + param.callback_priv = cb_priv; + audio_decoder_ioctrl(&dec->file_dec.decoder, AUDIO_IOCTRL_CMD_SET_DEST_PLAYPOS, ¶m); + } + return true; + } + return false; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 跳到指定位置开始播放 + @param start_time: 要跳转过去播放的起始时间 + @return true:成功 + @return false:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int file_dec_set_start_play(u32 start_time) +{ + return file_dec_set_start_dest_play(start_time, 0x7fffffff, NULL, NULL); +} +#endif + +#if FILE_DEC_REPEAT_EN +/*----------------------------------------------------------------------------*/ +/**@brief 循环播放回调接口 + @param *priv: 私有参数 + @return 0:循环播放 + @return 非0:结束循环 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int file_dec_repeat_cb(void *priv) +{ + struct file_dec_hdl *dec = priv; + y_printf("file_dec_repeat_cb\n"); + if (dec->repeat_num) { + dec->repeat_num--; + } else { + y_printf("file_dec_repeat_cb end\n"); + return -1; + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 设置循环播放次数 + @param repeat_num: 循环次数 + @return true:成功 + @return false:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int file_dec_repeat_set(u8 repeat_num) +{ + struct file_dec_hdl *dec = file_dec; + if (!dec || !dec->file_dec.decoder.dec_ops) { + return false; + } + switch (dec->file_dec.decoder.dec_ops->coding_type) { + case AUDIO_CODING_MP3: + case AUDIO_CODING_WAV: { + dec->repeat_num = repeat_num; + struct audio_repeat_mode_param rep = {0}; + rep.flag = 1; //使能 + rep.headcut_frame = 2; //依据需求砍掉前面几帧,仅mp3格式有效 + rep.tailcut_frame = 2; //依据需求砍掉后面几帧,仅mp3格式有效 + rep.repeat_callback = file_dec_repeat_cb; + rep.callback_priv = dec; + rep.repair_buf = &dec->repair_buf; + audio_decoder_ioctrl(&dec->file_dec.decoder, AUDIO_IOCTRL_CMD_REPEAT_PLAY, &rep); + } + return true; + } + return false; +} +#endif + + +#if FILE_DEC_AB_REPEAT_EN + +#define AUDIO_AB_REPEAT_CODING_TYPE (AUDIO_CODING_MP3 | AUDIO_CODING_WMA | AUDIO_CODING_WAV | AUDIO_CODING_FLAC | AUDIO_CODING_APE | AUDIO_CODING_DTS) + +enum { + AB_REPEAT_STA_NON = 0, + AB_REPEAT_STA_ASTA, + AB_REPEAT_STA_BSTA, +}; + +/*----------------------------------------------------------------------------*/ +/**@brief 设置AB点复读命令 + @param ab_cmd: 命令 + @param ab_mode: 参数 + @return true:成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int file_dec_ab_repeat_set(int ab_cmd, int ab_mode) +{ + struct file_dec_hdl *dec = file_dec; + if (!dec || !dec->file_dec.decoder.dec_ops) { + return false; + } + y_printf("ab repat, cmd:0x%x, mode:%d \n", ab_cmd, ab_mode); + struct audio_ab_repeat_mode_param rpt = {0}; + rpt.value = ab_mode; + audio_decoder_ioctrl(&dec->file_dec.decoder, ab_cmd, &rpt); + return true; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 检查是否可以AB点复读 + @param + @return true:成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int file_dec_ab_probe_check(void) +{ + struct file_dec_hdl *dec = file_dec; + if (!dec || !dec->file_dec.decoder.dec_ops) { + return false; + } + if (false == file_decoder_is_play(&dec->file_dec)) { + return false; + } + if (dec->file_dec.decoder.dec_ops->coding_type & AUDIO_CODING_STU_PICK) { + return false; + } + if (!(dec->file_dec.decoder.dec_ops->coding_type & AUDIO_AB_REPEAT_CODING_TYPE)) { + return false; + } + return true; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 切换AB点复读状态 + @param + @return true:成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int file_dec_ab_repeat_switch(void) +{ + struct file_dec_hdl *dec = file_dec; + if (false == file_dec_ab_probe_check()) { + return false; + } + switch (dec->ab_repeat_status) { + case AB_REPEAT_STA_NON: + if (file_dec_ab_repeat_set(AUDIO_IOCTRL_CMD_SET_BREAKPOINT_A, 0)) { + dec->ab_repeat_status = AB_REPEAT_STA_ASTA; + } + break; + case AB_REPEAT_STA_ASTA: + if (file_dec_ab_repeat_set(AUDIO_IOCTRL_CMD_SET_BREAKPOINT_B, 0)) { + dec->ab_repeat_status = AB_REPEAT_STA_BSTA; + } + break; + case AB_REPEAT_STA_BSTA: + if (file_dec_ab_repeat_set(AUDIO_IOCTRL_CMD_SET_BREAKPOINT_MODE, AB_REPEAT_MODE_CUR)) { + dec->ab_repeat_status = AB_REPEAT_STA_NON; + } + break; + } + printf("file_dec_ab_repeat_switch = %d\n", dec->ab_repeat_status); + return true; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭AB点复读 + @param + @return true:成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int file_dec_ab_repeat_close(void) +{ + struct file_dec_hdl *dec = file_dec; + if (false == file_dec_ab_probe_check()) { + return false; + } + + if (dec->ab_repeat_status == AB_REPEAT_STA_NON) { + return true; + } + + if (dec->ab_repeat_status == AB_REPEAT_STA_ASTA) { + switch (dec->file_dec.decoder.dec_ops->coding_type) { + case AUDIO_CODING_FLAC: + case AUDIO_CODING_DTS: + case AUDIO_CODING_APE: + file_dec_ab_repeat_set(AUDIO_IOCTRL_CMD_SET_BREAKPOINT_B, 0); + break; + } + } + + file_dec_ab_repeat_set(AUDIO_IOCTRL_CMD_SET_BREAKPOINT_MODE, AB_REPEAT_MODE_CUR); + dec->ab_repeat_status = AB_REPEAT_STA_NON; + return true; +} + +#endif /*FILE_DEC_AB_REPEAT_EN*/ + +#endif /*TCFG_APP_MUSIC_EN*/ + + +/*----------------------------------------------------------------------------*/ +/**@brief file decoder pp处理 + @param *dec: file解码句柄 + @param play: 1-播放。0-暂停 + @return + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +void file_decoder_pp_ctrl(struct file_decoder *dec, u8 play) +{ +#if TCFG_APP_MUSIC_EN + if (file_dec && (&file_dec->file_dec == dec)) { + file_dec_pp_ctrl(play); + } +#endif /*TCFG_APP_MUSIC_EN*/ +} + diff --git a/cpu/br23/audio_dec/audio_dec_file.h b/cpu/br23/audio_dec/audio_dec_file.h new file mode 100644 index 0000000..c926947 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_file.h @@ -0,0 +1,166 @@ + +#ifndef _AUDIO_DEC_FILE_H_ +#define _AUDIO_DEC_FILE_H_ + +#include "asm/includes.h" +#include "media/includes.h" +#include "media/file_decoder.h" +#include "system/includes.h" +#include "media/audio_decoder.h" +#include "app_config.h" +#include "music/music_decrypt.h" +#include "music/music_id3.h" +#include "application/audio_vocal_tract_synthesis.h" +#include "application/audio_pitchspeed.h" +#include "media/audio_surround.h" +#include "media/audio_vbass.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_dynamic_eq_demo.h" +#include "audio_effect/audio_eff_default_parm.h" + + +#define FILE_DEC_REPEAT_EN 0 // 无缝循环播放 + +#define FILE_DEC_AB_REPEAT_EN 1 // AB点复读 + +#define FILE_DEC_DEST_PLAY 0 // 指定时间播放 + +enum { + FILE_DEC_STREAM_CLOSE = 0, + FILE_DEC_STREAM_OPEN, +}; + +struct file_dec_hdl { + struct audio_stream *stream; // 音频流 + struct file_decoder file_dec; // file解码句柄 + struct audio_res_wait wait; // 资源等待句柄 + struct audio_mixer_ch mix_ch; // 叠加句柄 + +#if AUDIO_SURROUND_CONFIG + surround_hdl *surround; //环绕音效句柄 +#endif + +#if AUDIO_VBASS_CONFIG + struct aud_gain_process *vbass_prev_gain; + vbass_hdl *vbass; //虚拟低音句柄 +#endif + + struct audio_eq *high_bass; + struct audio_drc *hb_drc;//高低音后的drc + struct convert_data *hb_convert; + + struct audio_eq *eq; //eq drc句柄 + struct audio_drc *drc; // drc句柄 + struct convert_data *convert; + struct audio_eq *eq2; //eq drc句柄 + struct dynamic_eq_hdl *dy_eq; + struct convert_data *convert2; + struct aud_gain_process *gain; + + + + struct audio_dec_breakpoint *dec_bp; // 断点 + s_pitchspeed_hdl *p_pitchspeed_hdl; // 变速变调句柄 +#if defined(TCFG_EQ_DIVIDE_ENABLE) && TCFG_EQ_DIVIDE_ENABLE + struct audio_eq *eq_rl_rr; //eq drc句柄 + struct audio_drc *drc_rl_rr; // drc句柄 + struct convert_data *convert_rl_rr; + struct __stream_entry *rl_rr_mix;//双声道相加除2处理 + struct aud_gain_process *gain_rl_rr; + + struct audio_vocal_tract vocal_tract;//声道合并目标句柄 + struct audio_vocal_tract_ch synthesis_ch_fl_fr;//声道合并句柄 + struct audio_vocal_tract_ch synthesis_ch_rl_rr;//声道合并句柄 + struct channel_switch *ch_switch;//声道变换 +#endif + + + u32 id; // 唯一标识符,随机值 + void *file; // 文件句柄 + u32 pick_flag : 1; // 挑出数据帧发送(如MP3等)。不是输出pcm,后级不能接任何音效处理等 + u32 pcm_enc_flag : 1; // pcm压缩成数据帧发送(如WAV等) + u32 read_err : 2; // 读数出错 0:no err, 1:fat err, 2:disk err + u32 ab_repeat_status : 3; // AB复读状态 + u32 wait_add : 1; // 是否马上得到执行 + +#if TCFG_DEC_DECRYPT_ENABLE + CIPHER mply_cipher; // 解密播放 +#endif +#if TCFG_DEC_ID3_V1_ENABLE + MP3_ID3_OBJ *p_mp3_id3_v1; // id3_v1信息 +#endif +#if TCFG_DEC_ID3_V2_ENABLE + MP3_ID3_OBJ *p_mp3_id3_v2; // id3_v2信息 +#endif + +#if FILE_DEC_REPEAT_EN + u8 repeat_num; // 无缝循环次数 + struct fixphase_repair_obj repair_buf; // 无缝循环句柄 +#endif + + struct audio_dec_breakpoint *bp; // 断点信息 + + void *evt_priv; // 事件回调私有参数 + void (*evt_cb)(void *, int argc, int *argv); // 事件回调句柄 + + void (*stream_handler)(void *priv, int event, struct file_dec_hdl *); // 数据流设置回调 + void *stream_priv; // 数据流设置回调私有句柄 + +}; + + + +struct file_decoder *file_dec_get_file_decoder_hdl(void); + +#define file_dec_is_stop() file_decoder_is_stop(file_dec_get_file_decoder_hdl()) +#define file_dec_is_play() file_decoder_is_play(file_dec_get_file_decoder_hdl()) +#define file_dec_is_pause() file_decoder_is_pause(file_dec_get_file_decoder_hdl()) +#define file_dec_pp() file_decoder_pp(file_dec_get_file_decoder_hdl()) +#define file_dec_FF(x) file_decoder_FF(file_dec_get_file_decoder_hdl(),x) +#define file_dec_FR(x) file_decoder_FR(file_dec_get_file_decoder_hdl(),x) +#define file_dec_get_breakpoint(x) file_decoder_get_breakpoint(file_dec_get_file_decoder_hdl(),x) +#define file_dec_get_total_time() file_decoder_get_total_time(file_dec_get_file_decoder_hdl()) +#define file_dec_get_cur_time() file_decoder_get_cur_time(file_dec_get_file_decoder_hdl()) +#define file_dec_get_decoder_type() file_decoder_get_decoder_type(file_dec_get_file_decoder_hdl()) + +// 创建一个文件解码 +int file_dec_create(void *priv, void (*handler)(void *, int argc, int *argv)); +// 打开文件解码 +int file_dec_open(void *file, struct audio_dec_breakpoint *bp); +// 关闭文件解码 +void file_dec_close(); + +// 文件解码重新开始 +int file_dec_restart(int id); +// 推送文件解码重新开始命令 +int file_dec_push_restart(void); +// 获取file_dec状态 +int file_dec_get_status(void); + +// 设置解码数据流设置回调接口 +void file_dec_set_stream_set_hdl(struct file_dec_hdl *dec, + void (*stream_handler)(void *priv, int event, struct file_dec_hdl *), + void *stream_priv); + +// 获取文件解码hdl +void *get_file_dec_hdl(); + +#if (FILE_DEC_AB_REPEAT_EN) +int file_dec_ab_repeat_switch(void); +int file_dec_ab_repeat_close(void); +#else +#define file_dec_ab_repeat_switch() +#define file_dec_ab_repeat_close() +#endif/*FILE_DEC_AB_REPEAT_EN*/ + +#if (FILE_DEC_DEST_PLAY) +int file_dec_set_start_play(u32 start_time); +int file_dec_set_start_dest_play(u32 start_time, u32 dest_time, u32(*cb)(void *), void *cb_priv); +#else +#define file_dec_set_start_play(a) +#define file_dec_set_start_dest_play(a,b,c,d) +#endif/*FILE_DEC_DEST_PLAY*/ + + +#endif /*TCFG_APP_MUSIC_EN*/ + diff --git a/cpu/br23/audio_dec/audio_dec_fm.c b/cpu/br23/audio_dec/audio_dec_fm.c new file mode 100644 index 0000000..2c405b2 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_fm.c @@ -0,0 +1,921 @@ +/* + **************************************************************** + *File : audio_dec_fm.c + *Note : + * + **************************************************************** + */ + +#include "asm/includes.h" +#include "media/includes.h" +#include "media/pcm_decoder.h" +#include "system/includes.h" +#include "effectrs_sync.h" +#include "media/audio_eq_drc_apply.h" +#include "app_config.h" +#include "audio_config.h" +#include "audio_dec.h" +#include "app_config.h" +#include "app_main.h" +#include "audio_enc.h" +#include "audio_dec.h" +#include "clock_cfg.h" +#include "dev_manager.h" +#include "media/convert_data.h" +#include "audio_effect/audio_dynamic_eq_demo.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" + +#if TCFG_PCM_ENC2TWS_ENABLE +#include "bt_tws.h" +#endif + +#if (RECORDER_MIX_EN) +#include "stream_sync.h" +#endif/*RECORDER_MIX_EN*/ + +#if TCFG_FM_ENABLE + + +////////////////////////////////////////////////////////////////////////////// + +struct fm_dec_hdl { + struct audio_stream *stream; // 音频流 + struct pcm_decoder pcm_dec; // pcm解码句柄 + struct audio_res_wait wait; // 资源等待句柄 + struct audio_mixer_ch mix_ch; // 叠加句柄 + +#if (RECORDER_MIX_EN) + struct audio_mixer_ch rec_mix_ch; // 叠加句柄 + struct __stream_sync *sync; +#endif/*RECORDER_MIX_EN*/ + + +#if AUDIO_SURROUND_CONFIG + surround_hdl *surround; //环绕音效句柄 +#endif + +#if AUDIO_VBASS_CONFIG + struct aud_gain_process *vbass_prev_gain; + vbass_hdl *vbass; //虚拟低音句柄 +#endif + + struct audio_eq *high_bass; + struct audio_drc *hb_drc;//高低音后的drc + struct convert_data *hb_convert; + + struct audio_eq *eq; //eq drc句柄 + struct audio_drc *drc; // drc句柄 + struct convert_data *convert; + struct audio_eq *eq2; //eq drc句柄 + struct dynamic_eq_hdl *dy_eq; + struct convert_data *convert2; + struct aud_gain_process *gain; + + +#if TCFG_EQ_DIVIDE_ENABLE + struct audio_eq *eq_rl_rr; //eq drc句柄 + struct audio_drc *drc_rl_rr; // drc句柄 + struct convert_data *convert_rl_rr; + struct __stream_entry *rl_rr_mix;//双声道相加除2处理 + struct aud_gain_process *gain_rl_rr; + + struct audio_vocal_tract vocal_tract;//声道合并目标句柄 + struct audio_vocal_tract_ch synthesis_ch_fl_fr;//声道合并句柄 + struct audio_vocal_tract_ch synthesis_ch_rl_rr;//声道合并句柄 + struct channel_switch *ch_switch;//声道变换 +#endif + + u32 id; // 唯一标识符,随机值 + u32 start : 1; // 正在解码 + u32 source : 8; // fm音频源 + void *fm; // 底层驱动句柄 +}; + +////////////////////////////////////////////////////////////////////////////// + +struct fm_dec_hdl *fm_dec = NULL; // fm解码句柄 + + +////////////////////////////////////////////////////////////////////////////// +int linein_sample_size(void *hdl); +int linein_sample_total(void *hdl); + +////////////////////////////////////////////////////////////////////////////// + +/*----------------------------------------------------------------------------*/ +/**@brief fm数据填充 + @param *data: 数据 + @param len: 数据长度 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void fm_sample_output_handler(s16 *data, int len) +{ + struct fm_dec_hdl *dec = fm_dec; + if ((dec) && (dec->fm) && (dec->start)) { + fm_inside_output_handler(dec->fm, data, len); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief fm解码释放 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void fm_dec_relaese(void) +{ + if (fm_dec) { + audio_decoder_task_del_wait(&decode_task, &fm_dec->wait); + clock_remove(DEC_FM_CLK); + local_irq_disable(); + free(fm_dec); + fm_dec = NULL; + local_irq_enable(); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief fm解码事件处理 + @param *decoder: 解码器句柄 + @param argc: 参数个数 + @param *argv: 参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void fm_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ + switch (argv[0]) { + case AUDIO_DEC_EVENT_END: + if (!fm_dec) { + log_i("fm_dec handle err "); + break; + } + + if (fm_dec->id != argv[1]) { + log_w("fm_dec id err : 0x%x, 0x%x \n", fm_dec->id, argv[1]); + break; + } + + fm_dec_close(); + break; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief fm解码数据输出 + @param *entry: 音频流句柄 + @param *in: 输入信息 + @param *out: 输出信息 + @return 输出长度 + @note *out未使用 +*/ +/*----------------------------------------------------------------------------*/ +static int fm_dec_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + struct audio_decoder *decoder = container_of(entry, struct audio_decoder, entry); + struct pcm_decoder *pcm_dec = container_of(decoder, struct pcm_decoder, decoder); + struct fm_dec_hdl *dec = container_of(pcm_dec, struct fm_dec_hdl, pcm_dec); + if (!dec->start) { + return 0; + } + audio_stream_run(&decoder->entry, in); + return decoder->process_len; +} + +/*----------------------------------------------------------------------------*/ +/**@brief fm解码数据流激活 + @param *p: 私有句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +AT(.fm_data_code) +static void fm_dec_out_stream_resume(void *p) +{ + struct fm_dec_hdl *dec = p; + audio_decoder_resume(&dec->pcm_dec.decoder); +} + +/*----------------------------------------------------------------------------*/ +/**@brief fm解码激活 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +AT(.fm_data_code) +static void fm_dec_resume(void) +{ + if (fm_dec) { + audio_decoder_resume(&fm_dec->pcm_dec.decoder); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 计算fm输入采样率 + @param + @return 采样率 + @note +*/ +/*----------------------------------------------------------------------------*/ +AT(.fm_data_code) +static int audio_fm_input_sample_rate(void *priv) +{ + struct fm_dec_hdl *dec = (struct fm_dec_hdl *)priv; + int sample_rate = linein_stream_sample_rate(dec->fm); + int buf_size = linein_sample_size(dec->fm); +#if TCFG_PCM_ENC2TWS_ENABLE + if (dec->pcm_dec.dec_no_out_sound) { + /*TWS的上限在fm输入buffer,下限在tws push buffer*/ + if (buf_size >= linein_sample_total(dec->fm) / 2) { + sample_rate += (sample_rate * 5 / 10000); + } else if (tws_api_local_media_trans_check_ready_total() < 1024) { + sample_rate -= (sample_rate * 5 / 10000); + } + } +#endif + if (buf_size >= (linein_sample_total(dec->fm) * 3 / 4)) { + sample_rate += (sample_rate * 5 / 10000); + } + if (buf_size <= (linein_sample_total(dec->fm) * 1 / 4)) { + sample_rate -= (sample_rate * 5 / 10000); + } + return sample_rate; +} + +/*----------------------------------------------------------------------------*/ +/**@brief fm解码开始 + @param + @return 0:成功 + @return 非0:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int fm_dec_start(void) +{ + int err; + struct fm_dec_hdl *dec = fm_dec; + struct audio_mixer *p_mixer = &mixer; + + if (!fm_dec) { + return -EINVAL; + } + + err = pcm_decoder_open(&dec->pcm_dec, &decode_task); + if (err) { + goto __err1; + } + + // 打开fm驱动 + dec->fm = fm_sample_open(dec->source, dec->pcm_dec.sample_rate); + linein_sample_set_resume_handler(dec->fm, fm_dec_resume); + + pcm_decoder_set_event_handler(&dec->pcm_dec, fm_dec_event_handler, dec->id); + pcm_decoder_set_read_data(&dec->pcm_dec, linein_sample_read, dec->fm); + pcm_decoder_set_data_handler(&dec->pcm_dec, fm_dec_data_handler); + +#if TCFG_PCM_ENC2TWS_ENABLE + { + // localtws使用sbc等编码转发 + struct audio_fmt enc_f; + memcpy(&enc_f, &dec->pcm_dec.decoder.fmt, sizeof(struct audio_fmt)); + enc_f.coding_type = AUDIO_CODING_SBC; + if (dec->pcm_dec.ch_num == 2) { // 如果是双声道数据,localtws在解码时才变成对应声道 + enc_f.channel = 2; + } + int ret = localtws_enc_api_open(&enc_f, LOCALTWS_ENC_FLAG_STREAM); + if (ret == true) { + dec->pcm_dec.dec_no_out_sound = 1; + // 重定向mixer + p_mixer = &g_localtws.mixer; + // 关闭资源等待。最终会在localtws解码处等待 + audio_decoder_task_del_wait(&decode_task, &dec->wait); + if (dec->pcm_dec.output_ch_num != enc_f.channel) { + dec->pcm_dec.output_ch_num = dec->pcm_dec.decoder.fmt.channel = enc_f.channel; + if (enc_f.channel == 2) { + dec->pcm_dec.output_ch_type = AUDIO_CH_LR; + } else { + dec->pcm_dec.output_ch_type = AUDIO_CH_DIFF; + } + } + } + } +#endif + + if (!dec->pcm_dec.dec_no_out_sound) { + audio_mode_main_dec_open(AUDIO_MODE_MAIN_STATE_DEC_FM); + } + + // 设置叠加功能 + audio_mixer_ch_open_head(&dec->mix_ch, p_mixer); + audio_mixer_ch_set_no_wait(&dec->mix_ch, 1, 10); // 超时自动丢数 +#if (RECORDER_MIX_EN) + audio_mixer_ch_open_head(&dec->rec_mix_ch, &recorder_mixer); + audio_mixer_ch_set_no_wait(&dec->rec_mix_ch, 1, 10); // 超时自动丢数 +#endif/*RECORDER_MIX_EN*/ + +#if 0 + if (dec->pcm_dec.dec_no_out_sound) { + // 自动变采样 + audio_mixer_ch_set_src(&dec->mix_ch, 1, 0); +#if (RECORDER_MIX_EN) + audio_mixer_ch_set_src(&dec->rec_mix_ch, 1, 0); +#endif/*RECORDER_MIX_EN*/ + } else { + // 根据buf数据量动态变采样 +#if (RECORDER_MIX_EN && (TCFG_MIC_EFFECT_ENABLE == 0)) + struct stream_sync_info info = {0}; + info.i_sr = dec->pcm_dec.sample_rate; + info.o_sr = recorder_mix_get_samplerate(); + /* info.o_sr = audio_output_rate(info.i_sr); */ + info.ch_num = audio_output_channel_num(); + info.priv = dec->fm; + info.get_total = linein_sample_total; + info.get_size = linein_sample_size; + printf("info.i_sr = %d, info.o_sr = %d, ch_num = %d\n", info.i_sr, info.o_sr, info.ch_num); + dec->sync = stream_sync_open(&info, 1); +#else + struct audio_mixer_ch_sync_info info = {0}; + info.priv = dec->fm; + info.get_total = linein_sample_total; + info.get_size = linein_sample_size; + audio_mixer_ch_set_sync(&dec->mix_ch, &info, 1, 1); +#if (RECORDER_MIX_EN) + audio_mixer_ch_set_sync(&dec->rec_mix_ch, &info, 1, 1); +#endif/*RECORDER_MIX_EN*/ + +#endif/*RECORDER_MIX_EN*/ + } +#else /*0*/ + + if (dec->pcm_dec.dec_no_out_sound) { + // 自动变采样 + audio_mixer_ch_follow_resample_enable(&dec->mix_ch, dec, audio_fm_input_sample_rate); +#if (RECORDER_MIX_EN) + audio_mixer_ch_follow_resample_enable(&dec->rec_mix_ch, dec, audio_fm_input_sample_rate); +#endif/*RECORDER_MIX_EN*/ + } else { + // 根据buf数据量动态变采样 +#if (RECORDER_MIX_EN && (TCFG_MIC_EFFECT_ENABLE == 0)) + struct stream_sync_info info = {0}; + info.i_sr = dec->pcm_dec.sample_rate; + info.o_sr = recorder_mix_get_samplerate(); + /* info.o_sr = audio_output_rate(info.i_sr); */ + info.ch_num = audio_output_channel_num(); + info.priv = dec->fm; + info.get_total = linein_sample_total; + info.get_size = linein_sample_size; + printf("info.i_sr = %d, info.o_sr = %d, ch_num = %d\n", info.i_sr, info.o_sr, info.ch_num); + dec->sync = stream_sync_open(&info, 1); +#else + audio_mixer_ch_follow_resample_enable(&dec->mix_ch, dec, audio_fm_input_sample_rate); +#if (RECORDER_MIX_EN) + audio_mixer_ch_follow_resample_enable(&dec->rec_mix_ch, dec, audio_fm_input_sample_rate); +#endif/*RECORDER_MIX_EN*/ + +#endif/*RECORDER_MIX_EN*/ + } +#endif /*0*/ + +#if AUDIO_SURROUND_CONFIG + //环绕音效 + dec->surround = surround_open_demo(AEID_MUSIC_SURROUND, dec->pcm_dec.output_ch_type); +#endif + + +#if AUDIO_VBASS_CONFIG + dec->vbass_prev_gain = audio_gain_open_demo(AEID_MUSIC_VBASS_PREV_GAIN, dec->pcm_dec.output_ch_num); + //虚拟低音 + dec->vbass = audio_vbass_open_demo(AEID_MUSIC_VBASS, dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num); +#endif + + dec->high_bass = high_bass_eq_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num); + dec->hb_drc = high_bass_drc_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num); + if (dec->hb_drc && dec->hb_drc->run32bit) { + dec->hb_convert = convet_data_open(0, 512); + } + +#if TCFG_EQ_ENABLE && TCFG_FM_MODE_EQ_ENABLE + dec->eq = music_eq_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);// eq +#if TCFG_DRC_ENABLE && TCFG_FM_MODE_DRC_ENABLE + dec->drc = music_drc_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);//drc +#endif/*TCFG_FM_MODE_DRC_ENABLE*/ + if (dec->eq && dec->eq->out_32bit) { + dec->convert = convet_data_open(0, 512); + } + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + dec->eq2 = music_eq2_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);// eq + dec->dy_eq = audio_dynamic_eq_ctrl_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);//动态eq + dec->convert2 = convet_data_open(0, 512); +#endif/*TCFG_DYNAMIC_EQ_ENABLE*/ + dec->gain = audio_gain_open_demo(AEID_MUSIC_GAIN, dec->pcm_dec.output_ch_num); +#endif/*TCFG_FM_MODE_EQ_ENABLE*/ + + + +#if TCFG_EQ_DIVIDE_ENABLE + dec->eq_rl_rr = music_eq_rl_rr_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);// eq +#if TCFG_DRC_ENABLE && TCFG_BT_MUSIC_DRC_ENABLE + dec->drc_rl_rr = music_drc_rl_rr_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);//drc +#endif + if (dec->eq_rl_rr && dec->eq_rl_rr->out_32bit) { + dec->convert_rl_rr = convet_data_open(0, 512); + } +#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) && SOUND_TRACK_2_P_X_CH_CONFIG +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + dec->rl_rr_mix = stream_entry_open(NULL, stream_rl_rr_mix_data_handler, 0); +#endif +#endif + dec->gain_rl_rr = audio_gain_open_demo(AEID_MUSIC_RL_GAIN, dec->pcm_dec.output_ch_num); + + if (dec->eq_rl_rr) { + audio_vocal_tract_open(&dec->vocal_tract, AUDIO_SYNTHESIS_LEN); + { + u8 entry_cnt = 0; + struct audio_stream_entry *entries[8] = {NULL}; + entries[entry_cnt++] = &dec->vocal_tract.entry; + entries[entry_cnt++] = &dec->mix_ch.entry; + dec->vocal_tract.stream = audio_stream_open(&dec->vocal_tract, audio_vocal_tract_stream_resume); + audio_stream_add_list(dec->vocal_tract.stream, entries, entry_cnt); + } + audio_vocal_tract_synthesis_open(&dec->synthesis_ch_fl_fr, &dec->vocal_tract, FL_FR); + audio_vocal_tract_synthesis_open(&dec->synthesis_ch_rl_rr, &dec->vocal_tract, RL_RR); + } else { + dec->ch_switch = channel_switch_open(AUDIO_CH_QUAD, AUDIO_SYNTHESIS_LEN / 2); + } +#ifdef CONFIG_MIXER_CYCLIC + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 0, BIT(0)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 1, BIT(1)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 2, BIT(2)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 3, BIT(3)); +#endif + +#endif + + // 数据流串联 + struct audio_stream_entry *entries[32] = {NULL}; + u8 entry_cnt = 0; + u8 rl_rr_entry_start = 0; + entries[entry_cnt++] = &dec->pcm_dec.decoder.entry; + +#if AUDIO_SURROUND_CONFIG + if (dec->surround) { + entries[entry_cnt++] = &dec->surround->entry; + } +#endif + + +#if AUDIO_VBASS_CONFIG + if (dec->vbass_prev_gain) { + entries[entry_cnt++] = &dec->vbass_prev_gain->entry; + } + if (dec->vbass) { + entries[entry_cnt++] = &dec->vbass->entry; + } +#endif + + if (dec->high_bass) { //高低音 + entries[entry_cnt++] = &dec->high_bass->entry; + } + if (dec->hb_drc) { //高低音后drc + entries[entry_cnt++] = &dec->hb_drc->entry; + if (dec->hb_convert) { + entries[entry_cnt++] = &dec->hb_convert->entry; + } + } + + rl_rr_entry_start = entry_cnt - 1;//记录eq的上一个节点 +#if TCFG_EQ_ENABLE && TCFG_FM_MODE_EQ_ENABLE + if (dec->eq) { + entries[entry_cnt++] = &dec->eq->entry; + if (dec->drc) { + entries[entry_cnt++] = &dec->drc->entry; + } + if (dec->convert) { + entries[entry_cnt++] = &dec->convert->entry; + } +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + if (dec->eq2) { + entries[entry_cnt++] = &dec->eq2->entry; + } + if (dec->dy_eq && dec->dy_eq->dy_eq) { + entries[entry_cnt++] = &dec->dy_eq->dy_eq->entry; + } + if (dec->convert2) { + entries[entry_cnt++] = &dec->convert2->entry; + } +#endif + if (dec->gain) { + entries[entry_cnt++] = &dec->gain->entry; + } + + } +#endif + +#if (RECORDER_MIX_EN) + if (dec->sync) { + entries[entry_cnt++] = &dec->sync->entry; + } +#endif + +#if SYS_DIGVOL_GROUP_EN + void *dvol_entry = sys_digvol_group_ch_open("music_fm", -1, NULL); + entries[entry_cnt++] = dvol_entry; +#endif // SYS_DIGVOL_GROUP_EN + +#if TCFG_EQ_DIVIDE_ENABLE + if (dec->eq_rl_rr) { + entries[entry_cnt++] = &dec->synthesis_ch_fl_fr.entry;//四声道eq独立时,该节点后不接节点 + } else { + if (dec->ch_switch) { + entries[entry_cnt++] = &dec->ch_switch->entry; + } + entries[entry_cnt++] = &dec->mix_ch.entry; + } +#else + entries[entry_cnt++] = &dec->mix_ch.entry; +#endif + + + // 创建数据流,把所有节点连接起来 + dec->stream = audio_stream_open(dec, fm_dec_out_stream_resume); + audio_stream_add_list(dec->stream, entries, entry_cnt); +#if TCFG_EQ_DIVIDE_ENABLE + struct audio_stream_entry *rl_rr_entries[16] = {NULL}; + entry_cnt = 0; + if (dec->eq_rl_rr) { //接在eq_drc的上一个节点 + rl_rr_entries[entry_cnt++] = entries[rl_rr_entry_start]; + rl_rr_entries[entry_cnt++] = &dec->eq_rl_rr->entry; + if (dec->drc_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->drc_rl_rr->entry; + } + + if (dec->convert_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->convert_rl_rr->entry; + } +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + if (dec->rl_rr_mix) { + rl_rr_entries[entry_cnt++] = &dec->rl_rr_mix->entry; + } +#endif + if (dec->gain_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->gain_rl_rr->entry; + } + + rl_rr_entries[entry_cnt++] = &dec->synthesis_ch_rl_rr.entry;//必须是最后一个 + for (int i = 0; i < (entry_cnt - 1); i++) { + audio_stream_add_entry(rl_rr_entries[i], rl_rr_entries[i + 1]); + } + } +#endif + +#if (RECORDER_MIX_EN) + audio_stream_add_entry(entries[entry_cnt - 2], &dec->rec_mix_ch.entry); +#endif/*RECORDER_MIX_EN*/ + + // 设置音频输出音量 + audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); + + // 开始解码 + dec->start = 1; + err = audio_decoder_start(&dec->pcm_dec.decoder); + if (err) { + goto __err3; + } + clock_set_cur(); + return 0; +__err3: + dec->start = 0; + +#if AUDIO_SURROUND_CONFIG + surround_close_demo(dec->surround); +#endif + + +#if AUDIO_VBASS_CONFIG + audio_gain_close_demo(dec->vbass_prev_gain); + audio_vbass_close_demo(dec->vbass); +#endif + + high_bass_eq_close(dec->high_bass); + high_bass_drc_close(dec->hb_drc); + convet_data_close(dec->hb_convert); + +#if TCFG_EQ_ENABLE && TCFG_FM_MODE_EQ_ENABLE + music_eq_close(dec->eq); +#if TCFG_DRC_ENABLE && TCFG_FM_MODE_DRC_ENABLE + music_drc_close(dec->drc); +#endif + convet_data_close(dec->convert); +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + music_eq2_close(dec->eq2); + audio_dynamic_eq_ctrl_close(dec->dy_eq); + convet_data_close(dec->convert2); +#endif + audio_gain_close_demo(dec->gain); +#endif + + +#if TCFG_EQ_DIVIDE_ENABLE + music_eq_rl_rr_close(dec->eq_rl_rr); + music_drc_rl_rr_close(dec->drc_rl_rr); + convet_data_close(dec->convert_rl_rr); +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + stream_entry_close(&dec->rl_rr_mix); +#endif + audio_gain_close_demo(dec->gain_rl_rr); + + audio_vocal_tract_synthesis_close(&dec->synthesis_ch_fl_fr); + audio_vocal_tract_synthesis_close(&dec->synthesis_ch_rl_rr); + audio_vocal_tract_close(&dec->vocal_tract); + channel_switch_close(&dec->ch_switch); +#endif + if (dec->fm) { + local_irq_disable(); + fm_sample_close(dec->fm, dec->source); + dec->fm = NULL; + local_irq_enable(); + } + + + audio_mixer_ch_close(&dec->mix_ch); +#if (RECORDER_MIX_EN) + audio_mixer_ch_close(&dec->rec_mix_ch); + if (dec->sync) { + stream_sync_close(&dec->sync); + } +#endif/*RECORDER_MIX_EN*/ +#if TCFG_PCM_ENC2TWS_ENABLE + if (dec->pcm_dec.dec_no_out_sound) { + dec->pcm_dec.dec_no_out_sound = 0; + localtws_enc_api_close(); + } +#endif + +#if SYS_DIGVOL_GROUP_EN + sys_digvol_group_ch_close("music_fm"); +#endif // SYS_DIGVOL_GROUP_EN + + + if (dec->stream) { + audio_stream_close(dec->stream); + dec->stream = NULL; + } + + pcm_decoder_close(&dec->pcm_dec); +__err1: + fm_dec_relaese(); + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief fm解码关闭 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void __fm_dec_close(void) +{ + if (fm_dec && fm_dec->start) { + fm_dec->start = 0; + + pcm_decoder_close(&fm_dec->pcm_dec); + + local_irq_disable(); + fm_sample_close(fm_dec->fm, fm_dec->source); + fm_dec->fm = NULL; + local_irq_enable(); +#if AUDIO_SURROUND_CONFIG + surround_close_demo(fm_dec->surround); +#endif + +#if AUDIO_VBASS_CONFIG + audio_gain_close_demo(fm_dec->vbass_prev_gain); + audio_vbass_close_demo(fm_dec->vbass); +#endif + + high_bass_eq_close(fm_dec->high_bass); + high_bass_drc_close(fm_dec->hb_drc); + convet_data_close(fm_dec->hb_convert); + +#if TCFG_EQ_ENABLE && TCFG_FM_MODE_EQ_ENABLE + music_eq_close(fm_dec->eq); +#if TCFG_DRC_ENABLE && TCFG_FM_MODE_DRC_ENABLE + music_drc_close(fm_dec->drc); +#endif + convet_data_close(fm_dec->convert); + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + music_eq2_close(fm_dec->eq2); + audio_dynamic_eq_ctrl_close(fm_dec->dy_eq); + convet_data_close(fm_dec->convert2); +#endif + audio_gain_close_demo(fm_dec->gain); +#endif + +#if TCFG_EQ_DIVIDE_ENABLE + music_eq_rl_rr_close(fm_dec->eq_rl_rr); + music_drc_rl_rr_close(fm_dec->drc_rl_rr); + convet_data_close(fm_dec->convert_rl_rr); +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + stream_entry_close(&fm_dec->rl_rr_mix); +#endif + audio_gain_close_demo(fm_dec->gain_rl_rr); + + audio_vocal_tract_synthesis_close(&fm_dec->synthesis_ch_fl_fr); + audio_vocal_tract_synthesis_close(&fm_dec->synthesis_ch_rl_rr); + audio_vocal_tract_close(&fm_dec->vocal_tract); + channel_switch_close(&fm_dec->ch_switch); +#endif + + + audio_mixer_ch_close(&fm_dec->mix_ch); +#if (RECORDER_MIX_EN) + audio_mixer_ch_close(&fm_dec->rec_mix_ch); + if (fm_dec->sync) { + stream_sync_close(&fm_dec->sync); + } +#endif/*RECORDER_MIX_EN*/ +#if TCFG_PCM_ENC2TWS_ENABLE + if (fm_dec->pcm_dec.dec_no_out_sound) { + fm_dec->pcm_dec.dec_no_out_sound = 0; + localtws_enc_api_close(); + } +#endif +#if SYS_DIGVOL_GROUP_EN + sys_digvol_group_ch_close("music_fm"); +#endif // SYS_DIGVOL_GROUP_EN + + + // 先关闭各个节点,最后才close数据流 + if (fm_dec->stream) { + audio_stream_close(fm_dec->stream); + fm_dec->stream = NULL; + } + + } + +} + +/*----------------------------------------------------------------------------*/ +/**@brief fm解码资源等待 + @param *wait: 句柄 + @param event: 事件 + @return 0:成功 + @note 用于多解码打断处理 +*/ +/*----------------------------------------------------------------------------*/ +static int fm_wait_res_handler(struct audio_res_wait *wait, int event) +{ + int err = 0; + log_i("fm_wait_res_handler, event:%d\n", event); + if (event == AUDIO_RES_GET) { + // 启动解码 + err = fm_dec_start(); + } else if (event == AUDIO_RES_PUT) { + // 被打断 + __fm_dec_close(); + } + + return err; +} +/*----------------------------------------------------------------------------*/ +/**@brief 暂停/启动 fm解码mix ch输出 + @param pause : 1:暂停 0:启动 + @return NULL + @note +*/ +/*----------------------------------------------------------------------------*/ +void fm_dec_pause_out(u8 pause) +{ + if (!fm_dec) { + return; + } +#if 0 + audio_mixer_ch_pause(&fm_dec->mix_ch, pause); +#if (RECORDER_MIX_EN) + audio_mixer_ch_pause(&fm_dec->rec_mix_ch, pause); +#endif/*RECORDER_MIX_EN*/ + audio_decoder_resume_all(&decode_task); +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 打开fm解码 + @param source: 音频源 + @param sample_rate: 采样率 + @return 0:成功 + @return 非0:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int fm_dec_open(u8 source, u32 sample_rate) +{ + int err; + struct fm_dec_hdl *dec; + dec = zalloc(sizeof(*dec)); + if (!dec) { + return -ENOMEM; + } + fm_dec = dec; + + dec->id = rand32(); + + dec->source = source; + + dec->pcm_dec.ch_num = 2; + dec->pcm_dec.output_ch_num = audio_output_channel_num(); + dec->pcm_dec.output_ch_type = audio_output_channel_type(); + dec->pcm_dec.sample_rate = sample_rate; + + dec->wait.priority = 2; + dec->wait.preemption = 0; + dec->wait.snatch_same_prio = 1; + dec->wait.handler = fm_wait_res_handler; + + clock_add(DEC_FM_CLK); + + +#if TCFG_DEC2TWS_ENABLE + // 设置localtws重播接口 + localtws_globle_set_dec_restart(fm_dec_push_restart); +#endif + + err = audio_decoder_task_add_wait(&decode_task, &dec->wait); + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭fm解码 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void fm_dec_close(void) +{ + if (!fm_dec) { + return; + } + + __fm_dec_close(); + fm_dec_relaese(); + clock_set_cur(); + log_i("fm dec close \n\n "); +} + +/*----------------------------------------------------------------------------*/ +/**@brief fm解码重新开始 + @param id: 文件解码id + @return 0:成功 + @return 非0:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int fm_dec_restart(int id) +{ + if ((!fm_dec) || (id != fm_dec->id)) { + return -1; + } + u8 source = fm_dec->source; + u32 sample_rate = fm_dec->pcm_dec.sample_rate; + fm_dec_close(); + int err = fm_dec_open(source, sample_rate); + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 推送fm解码重新开始命令 + @param + @return true:成功 + @return false:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int fm_dec_push_restart(void) +{ + if (!fm_dec) { + return false; + } + int argv[3]; + argv[0] = (int)fm_dec_restart; + argv[1] = 1; + argv[2] = (int)fm_dec->id; + os_taskq_post_type(os_current_task(), Q_CALLBACK, ARRAY_SIZE(argv), argv); + return true; +} + + + + + +#endif diff --git a/cpu/br23/audio_dec/audio_dec_fm.h b/cpu/br23/audio_dec/audio_dec_fm.h new file mode 100644 index 0000000..d2d3952 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_fm.h @@ -0,0 +1,37 @@ + +#ifndef _AUDIO_DEC_FM_H_ +#define _AUDIO_DEC_FM_H_ + +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "media/audio_decoder.h" +#include "mic_effect.h" + +// fm数据填充 +void fm_sample_output_handler(s16 *data, int len); +// fm解码释放 +void fm_dec_relaese(); + +// fm解码开始 +int fm_dec_start(); +// 打开fm解码 +int fm_dec_open(u8 source, u32 sample_rate); +// 关闭fm解码 +void fm_dec_close(void); +// fm解码重新开始 +int fm_dec_restart(int magic); +// 推送fm解码重新开始命令 +int fm_dec_push_restart(void); +// 暂停/启动 fm解码mix ch输出 +void fm_dec_pause_out(u8 pause); + +/***********************inein pcm enc******************************/ +// fm录音停止 +void fm_pcm_enc_stop(void); +// fm录音开始 +int fm_pcm_enc_start(void); +// 检测fm是否在录音 +bool fm_pcm_enc_check(); + +#endif diff --git a/cpu/br23/audio_dec/audio_dec_linein.c b/cpu/br23/audio_dec/audio_dec_linein.c new file mode 100644 index 0000000..d999480 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_linein.c @@ -0,0 +1,901 @@ +/* + **************************************************************** + *File : audio_dc_linein.c + *Note : + * + **************************************************************** + */ + + +#include "asm/includes.h" +#include "media/includes.h" +#include "media/pcm_decoder.h" +#include "system/includes.h" +#include "effectrs_sync.h" +#include "app_config.h" +#include "audio_config.h" +#include "audio_dec.h" +#include "app_config.h" +#include "app_main.h" +#include "audio_enc.h" +#include "clock_cfg.h" +#include "dev_manager.h" +#include "media/convert_data.h" +#include "audio_effect/audio_dynamic_eq_demo.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" +#include "avctp_user.h" + +#if TCFG_PCM_ENC2TWS_ENABLE +#include "bt_tws.h" +#endif + +#if (TCFG_LINEIN_ENABLE || TCFG_FM_ENABLE)//外部收音走linein + +////////////////////////////////////////////////////////////////////////////// + +struct linein_dec_hdl { + struct audio_stream *stream; // 音频流 + struct pcm_decoder pcm_dec; // pcm解码句柄 + struct audio_res_wait wait; // 资源等待句柄 + struct audio_mixer_ch mix_ch; // 叠加句柄 +#if (RECORDER_MIX_EN) + struct audio_mixer_ch rec_mix_ch; // 叠加句柄 +#endif/*RECORDER_MIX_EN*/ + +#if AUDIO_SURROUND_CONFIG + surround_hdl *surround; //环绕音效句柄 +#endif + + +#if AUDIO_VBASS_CONFIG + struct aud_gain_process *vbass_prev_gain; + vbass_hdl *vbass; //虚拟低音句柄 +#endif + + struct audio_eq *high_bass; + struct audio_drc *hb_drc;//高低音后的drc + struct convert_data *hb_convert; + + struct audio_eq *eq; //eq drc句柄 + struct audio_drc *drc; // drc句柄 + struct convert_data *convert; + struct audio_eq *eq2; //eq drc句柄 + struct dynamic_eq_hdl *dy_eq; + struct convert_data *convert2; + struct aud_gain_process *gain; + +#if TCFG_EQ_DIVIDE_ENABLE + struct audio_eq *eq_rl_rr; //eq drc句柄 + struct audio_drc *drc_rl_rr; // drc句柄 + struct convert_data *convert_rl_rr; + struct __stream_entry *rl_rr_mix;//双声道相加除2处理 + struct aud_gain_process *gain_rl_rr; + + struct audio_vocal_tract vocal_tract;//声道合并目标句柄 + struct audio_vocal_tract_ch synthesis_ch_fl_fr;//声道合并句柄 + struct audio_vocal_tract_ch synthesis_ch_rl_rr;//声道合并句柄 + struct channel_switch *ch_switch;//声道变换 +#endif + + u32 id; // 唯一标识符,随机值 + u32 start : 1; // 正在解码 + u32 source : 8; // linein音频源 + void *linein; // 底层驱动句柄 +}; + + +////////////////////////////////////////////////////////////////////////////// + +struct linein_dec_hdl *linein_dec = NULL; // linein解码句柄 + +////////////////////////////////////////////////////////////////////////////// +int linein_sample_size(void *hdl); +int linein_sample_total(void *hdl); + + +////////////////////////////////////////////////////////////////////////////// + +/*----------------------------------------------------------------------------*/ +/**@brief linein解码释放 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void linein_dec_relaese() +{ + if (linein_dec) { + audio_decoder_task_del_wait(&decode_task, &linein_dec->wait); + clock_remove(AUDIO_CODING_PCM); + local_irq_disable(); + free(linein_dec); + linein_dec = NULL; + local_irq_enable(); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief linein解码事件处理 + @param *decoder: 解码器句柄 + @param argc: 参数个数 + @param *argv: 参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void linein_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ + switch (argv[0]) { + case AUDIO_DEC_EVENT_END: + if (!linein_dec) { + log_i("linein_dec handle err "); + break; + } + + if (linein_dec->id != argv[1]) { + log_w("linein_dec id err : 0x%x, 0x%x \n", linein_dec->id, argv[1]); + break; + } + + linein_dec_close(); + //audio_decoder_resume_all(&decode_task); + break; + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief linein解码数据输出 + @param *entry: 音频流句柄 + @param *in: 输入信息 + @param *out: 输出信息 + @return 输出长度 + @note *out未使用 +*/ +/*----------------------------------------------------------------------------*/ +static int linein_dec_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + struct audio_decoder *decoder = container_of(entry, struct audio_decoder, entry); + struct pcm_decoder *pcm_dec = container_of(decoder, struct pcm_decoder, decoder); + struct linein_dec_hdl *dec = container_of(pcm_dec, struct linein_dec_hdl, pcm_dec); + if (!dec->start) { + return 0; + } + audio_stream_run(&decoder->entry, in); + return decoder->process_len; +} + +/*----------------------------------------------------------------------------*/ +/**@brief linein解码数据流激活 + @param *p: 私有句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void linein_dec_out_stream_resume(void *p) +{ + struct linein_dec_hdl *dec = p; + audio_decoder_resume(&dec->pcm_dec.decoder); +} + +/*----------------------------------------------------------------------------*/ +/**@brief linein解码激活 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void linein_dec_resume(void) +{ + if (linein_dec) { + audio_decoder_resume(&linein_dec->pcm_dec.decoder); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 计算linein输入采样率 + @param + @return 采样率 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int audio_linein_input_sample_rate(void *priv) +{ + struct linein_dec_hdl *dec = (struct linein_dec_hdl *)priv; + int sample_rate = linein_stream_sample_rate(dec->linein); + int buf_size = linein_sample_size(dec->linein); +#if TCFG_PCM_ENC2TWS_ENABLE + if (dec->pcm_dec.dec_no_out_sound) { + /*TWS的上限在linein输入buffer,下限在tws push buffer*/ + if (buf_size >= linein_sample_total(dec->linein) / 2) { + sample_rate += (sample_rate * 1 / 10000); + } else if (tws_api_local_media_trans_check_ready_total() < 1024) { + sample_rate -= (sample_rate * 1 / 10000); + } + return sample_rate; + } +#endif + /* if (dec->pcm_dec.sample_rate == 44100 && audio_mixer_get_sample_rate(&mixer) == 44100) { */ + if ((dec->pcm_dec.sample_rate == 44100) && (audio_mixer_get_original_sample_rate_by_type(&mixer, MIXER_SR_SPEC) == 44100)) { + sample_rate = 44100 + (sample_rate - 44118); + } + if (buf_size >= (linein_sample_total(dec->linein) * 3 / 5)) { + sample_rate += (sample_rate * 6 / 10000); + } + if (buf_size <= (linein_sample_total(dec->linein) * 2 / 5)) { + sample_rate -= (sample_rate * 6 / 10000); + } + return sample_rate; +} + +/*----------------------------------------------------------------------------*/ +/**@brief linein解码开始 + @param + @return 0:成功 + @return 非0:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int linein_dec_start() +{ + int err; + struct linein_dec_hdl *dec = linein_dec; + struct audio_mixer *p_mixer = &mixer; + + if (!linein_dec) { + return -EINVAL; + } + + err = pcm_decoder_open(&dec->pcm_dec, &decode_task); + if (err) { + goto __err1; + } + + // 打开linein驱动 + dec->linein = linein_sample_open(dec->source, dec->pcm_dec.sample_rate); + linein_sample_set_resume_handler(dec->linein, linein_dec_resume); + + pcm_decoder_set_event_handler(&dec->pcm_dec, linein_dec_event_handler, dec->id); + pcm_decoder_set_read_data(&dec->pcm_dec, linein_sample_read, dec->linein); + pcm_decoder_set_data_handler(&dec->pcm_dec, linein_dec_data_handler); + +#if TCFG_PCM_ENC2TWS_ENABLE + { + // localtws使用sbc等编码转发 + struct audio_fmt enc_f; + memcpy(&enc_f, &dec->pcm_dec.decoder.fmt, sizeof(struct audio_fmt)); + enc_f.coding_type = AUDIO_CODING_SBC; + if (dec->pcm_dec.ch_num == 2) { // 如果是双声道数据,localtws在解码时才变成对应声道 + enc_f.channel = 2; + } + int ret = localtws_enc_api_open(&enc_f, LOCALTWS_ENC_FLAG_STREAM); + if (ret == true) { + dec->pcm_dec.dec_no_out_sound = 1; + // 重定向mixer + p_mixer = &g_localtws.mixer; + // 关闭资源等待。最终会在localtws解码处等待 + audio_decoder_task_del_wait(&decode_task, &dec->wait); + if (dec->pcm_dec.output_ch_num != enc_f.channel) { + dec->pcm_dec.output_ch_num = dec->pcm_dec.decoder.fmt.channel = enc_f.channel; + if (enc_f.channel == 2) { + dec->pcm_dec.output_ch_type = AUDIO_CH_LR; + } else { + dec->pcm_dec.output_ch_type = AUDIO_CH_DIFF; + } + } + } + } +#endif + + if (!dec->pcm_dec.dec_no_out_sound) { + audio_mode_main_dec_open(AUDIO_MODE_MAIN_STATE_DEC_LINEIN); + } + + // 设置叠加功能 + audio_mixer_ch_open_head(&dec->mix_ch, p_mixer); + audio_mixer_ch_set_no_wait(&dec->mix_ch, 1, 10); // 超时自动丢数 +#if (RECORDER_MIX_EN) + audio_mixer_ch_open_head(&dec->rec_mix_ch, &recorder_mixer); + audio_mixer_ch_set_no_wait(&dec->rec_mix_ch, 1, 10); // 超时自动丢数 +#endif/*RECORDER_MIX_EN*/ + +#if 0 + if (dec->pcm_dec.dec_no_out_sound) { + // 自动变采样 + audio_mixer_ch_set_src(&dec->mix_ch, 1, 0); +#if (RECORDER_MIX_EN) + audio_mixer_ch_set_src(&dec->rec_mix_ch, 1, 0); +#endif/*RECORDER_MIX_EN*/ + } else { + // 根据buf数据量动态变采样 + struct audio_mixer_ch_sync_info info = {0}; + info.priv = dec->linein; + info.get_total = linein_sample_total; + info.get_size = linein_sample_size; +#if (!SOUNDCARD_ENABLE) + audio_mixer_ch_set_sync(&dec->mix_ch, &info, 1, 1); +#endif/*SOUNDCARD_ENABLE*/ +#if (RECORDER_MIX_EN) + audio_mixer_ch_set_sync(&dec->rec_mix_ch, &info, 1, 1); +#endif/*RECORDER_MIX_EN*/ + } +#else /*0*/ + + if (dec->pcm_dec.dec_no_out_sound) { + audio_mixer_ch_follow_resample_enable(&dec->mix_ch, dec, audio_linein_input_sample_rate); +#if (RECORDER_MIX_EN) + audio_mixer_ch_follow_resample_enable(&dec->rec_mix_ch, dec, audio_linein_input_sample_rate); +#endif/*RECORDER_MIX_EN*/ + } else { +#if (!SOUNDCARD_ENABLE) + if ((dec->pcm_dec.sample_rate == audio_mixer_get_sample_rate(p_mixer)) && (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC)) { + } else { + audio_mixer_ch_follow_resample_enable(&dec->mix_ch, dec, audio_linein_input_sample_rate); + } +#endif/*SOUNDCARD_ENABLE*/ +#if (RECORDER_MIX_EN) + audio_mixer_ch_follow_resample_enable(&dec->rec_mix_ch, dec, audio_linein_input_sample_rate); +#endif/*RECORDER_MIX_EN*/ + } +#endif /*0*/ + +#if AUDIO_SURROUND_CONFIG + //环绕音效 + dec->surround = surround_open_demo(AEID_MUSIC_SURROUND, dec->pcm_dec.output_ch_type); +#endif + + +#if AUDIO_VBASS_CONFIG + dec->vbass_prev_gain = audio_gain_open_demo(AEID_MUSIC_VBASS_PREV_GAIN, dec->pcm_dec.output_ch_num); + //虚拟低音 + dec->vbass = audio_vbass_open_demo(AEID_MUSIC_VBASS, dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num); +#endif + + dec->high_bass = high_bass_eq_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num); + dec->hb_drc = high_bass_drc_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num); + if (dec->hb_drc && dec->hb_drc->run32bit) { + dec->hb_convert = convet_data_open(0, 512); + } + +#if TCFG_EQ_ENABLE && TCFG_LINEIN_MODE_EQ_ENABLE +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN + dec->eq = linein_eq_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);// eq +#else + dec->eq = music_eq_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);// eq +#endif +#if TCFG_DRC_ENABLE && TCFG_LINEIN_MODE_DRC_ENABLE +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN + dec->drc = linein_drc_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);//drc +#else + dec->drc = music_drc_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);//drc +#endif +#endif/*TCFG_LINEIN_MODE_DRC_ENABLE*/ + if (dec->eq && dec->eq->out_32bit) { + dec->convert = convet_data_open(0, 512); + } + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + dec->eq2 = music_eq2_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);// eq + dec->dy_eq = audio_dynamic_eq_ctrl_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);//动态eq + dec->convert2 = convet_data_open(0, 512); +#endif/*TCFG_DYNAMIC_EQ_ENABLE*/ + u16 gain_name = AEID_MUSIC_GAIN; +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN + gain_name = AEID_LINEIN_GAIN; +#endif + dec->gain = audio_gain_open_demo(gain_name, dec->pcm_dec.output_ch_num); +#endif/*TCFG_LINEIN_MODE_EQ_ENABLE*/ + + + +#if TCFG_EQ_DIVIDE_ENABLE + dec->eq_rl_rr = music_eq_rl_rr_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);// eq +#if TCFG_DRC_ENABLE && TCFG_BT_MUSIC_DRC_ENABLE + dec->drc_rl_rr = music_drc_rl_rr_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);//drc +#endif + if (dec->eq_rl_rr && dec->eq_rl_rr->out_32bit) { + dec->convert_rl_rr = convet_data_open(0, 512); + } + +#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) && SOUND_TRACK_2_P_X_CH_CONFIG +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + dec->rl_rr_mix = stream_entry_open(NULL, stream_rl_rr_mix_data_handler, 0); +#endif +#endif + dec->gain_rl_rr = audio_gain_open_demo(AEID_MUSIC_RL_GAIN, dec->pcm_dec.output_ch_num); + if (dec->eq_rl_rr) { + audio_vocal_tract_open(&dec->vocal_tract, AUDIO_SYNTHESIS_LEN); + { + u8 entry_cnt = 0; + struct audio_stream_entry *entries[8] = {NULL}; + entries[entry_cnt++] = &dec->vocal_tract.entry; + entries[entry_cnt++] = &dec->mix_ch.entry; + dec->vocal_tract.stream = audio_stream_open(&dec->vocal_tract, audio_vocal_tract_stream_resume); + audio_stream_add_list(dec->vocal_tract.stream, entries, entry_cnt); + } + audio_vocal_tract_synthesis_open(&dec->synthesis_ch_fl_fr, &dec->vocal_tract, FL_FR); + audio_vocal_tract_synthesis_open(&dec->synthesis_ch_rl_rr, &dec->vocal_tract, RL_RR); + } else { + dec->ch_switch = channel_switch_open(AUDIO_CH_QUAD, AUDIO_SYNTHESIS_LEN / 2); + } +#ifdef CONFIG_MIXER_CYCLIC + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 0, BIT(0)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 1, BIT(1)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 2, BIT(2)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 3, BIT(3)); +#endif + +#endif + + // 数据流串联 + struct audio_stream_entry *entries[32] = {NULL}; + u8 entry_cnt = 0; + u8 rl_rr_entry_start = 0; + entries[entry_cnt++] = &dec->pcm_dec.decoder.entry; + +#if AUDIO_SURROUND_CONFIG + if (dec->surround) { + entries[entry_cnt++] = &dec->surround->entry; + } +#endif + + + +#if AUDIO_VBASS_CONFIG + if (dec->vbass_prev_gain) { + entries[entry_cnt++] = &dec->vbass_prev_gain->entry; + } + if (dec->vbass) { + entries[entry_cnt++] = &dec->vbass->entry; + } +#endif + + if (dec->high_bass) { //高低音 + entries[entry_cnt++] = &dec->high_bass->entry; + } + if (dec->hb_drc) { //高低音后drc + entries[entry_cnt++] = &dec->hb_drc->entry; + if (dec->hb_convert) { + entries[entry_cnt++] = &dec->hb_convert->entry; + } + } + + rl_rr_entry_start = entry_cnt - 1;//记录eq的上一个节点 +#if TCFG_EQ_ENABLE && TCFG_LINEIN_MODE_EQ_ENABLE + if (dec->eq) { + entries[entry_cnt++] = &dec->eq->entry; + if (dec->drc) { + entries[entry_cnt++] = &dec->drc->entry; + } + if (dec->convert) { + entries[entry_cnt++] = &dec->convert->entry; + } + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + if (dec->eq2) { + entries[entry_cnt++] = &dec->eq2->entry; + } + if (dec->dy_eq && dec->dy_eq->dy_eq) { + entries[entry_cnt++] = &dec->dy_eq->dy_eq->entry; + } + if (dec->convert2) { + entries[entry_cnt++] = &dec->convert2->entry; + } +#endif + if (dec->gain) { + entries[entry_cnt++] = &dec->gain->entry; + } + } +#endif +#if SYS_DIGVOL_GROUP_EN + void *dvol_entry = sys_digvol_group_ch_open("music_linein", -1, NULL); + entries[entry_cnt++] = dvol_entry; +#endif // SYS_DIGVOL_GROUP_EN + + + + +#if TCFG_EQ_DIVIDE_ENABLE + if (dec->eq_rl_rr) { + entries[entry_cnt++] = &dec->synthesis_ch_fl_fr.entry;//四声道eq独立时,该节点后不接节点 + } else { + if (dec->ch_switch) { + entries[entry_cnt++] = &dec->ch_switch->entry; + } + entries[entry_cnt++] = &dec->mix_ch.entry; + } +#else + entries[entry_cnt++] = &dec->mix_ch.entry; +#endif + + // 创建数据流,把所有节点连接起来 + dec->stream = audio_stream_open(dec, linein_dec_out_stream_resume); + audio_stream_add_list(dec->stream, entries, entry_cnt); +#if TCFG_EQ_DIVIDE_ENABLE + struct audio_stream_entry *rl_rr_entries[16] = {NULL}; + entry_cnt = 0; + if (dec->eq_rl_rr) { //接在eq_drc的上一个节点 + rl_rr_entries[entry_cnt++] = entries[rl_rr_entry_start]; + rl_rr_entries[entry_cnt++] = &dec->eq_rl_rr->entry; + if (dec->drc_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->drc_rl_rr->entry; + } + if (dec->convert_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->convert_rl_rr->entry; + } +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + if (dec->rl_rr_mix) { + rl_rr_entries[entry_cnt++] = &dec->rl_rr_mix->entry; + } +#endif + if (dec->gain_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->gain_rl_rr->entry; + } + + rl_rr_entries[entry_cnt++] = &dec->synthesis_ch_rl_rr.entry;//必须是最后一个 + for (int i = 0; i < (entry_cnt - 1); i++) { + audio_stream_add_entry(rl_rr_entries[i], rl_rr_entries[i + 1]); + } + } +#endif + +#if (RECORDER_MIX_EN) + audio_stream_add_entry(entries[entry_cnt - 2], &dec->rec_mix_ch.entry); +#endif/*RECORDER_MIX_EN*/ + + // 设置音频输出音量 + audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); + + // 开始解码 + dec->start = 1; + err = audio_decoder_start(&dec->pcm_dec.decoder); + if (err) { + goto __err3; + } + clock_set_cur(); + __bt_emitter_pp(1); + return 0; +__err3: + dec->start = 0; + +#if AUDIO_SURROUND_CONFIG + surround_close_demo(dec->surround); +#endif + + +#if AUDIO_VBASS_CONFIG + audio_gain_close_demo(dec->vbass_prev_gain); + audio_vbass_close_demo(dec->vbass); +#endif + + high_bass_eq_close(dec->high_bass); + high_bass_drc_close(dec->hb_drc); + convet_data_close(dec->hb_convert); + +#if TCFG_EQ_ENABLE && TCFG_LINEIN_MODE_EQ_ENABLE +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN + linein_eq_close(dec->eq); +#else + music_eq_close(dec->eq); +#endif +#if TCFG_DRC_ENABLE && TCFG_LINEIN_MODE_DRC_ENABLE +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN + linein_drc_close(dec->drc); +#else + music_drc_close(dec->drc); +#endif +#endif + convet_data_close(dec->convert); + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + music_eq2_close(dec->eq2); + audio_dynamic_eq_ctrl_close(dec->dy_eq); + convet_data_close(dec->convert2); +#endif + audio_gain_close_demo(dec->gain); +#endif + +#if TCFG_EQ_DIVIDE_ENABLE + music_eq_rl_rr_close(dec->eq_rl_rr); + music_drc_rl_rr_close(dec->drc_rl_rr); + convet_data_close(dec->convert_rl_rr); +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + stream_entry_close(&dec->rl_rr_mix); +#endif + audio_gain_close_demo(dec->gain_rl_rr); + + audio_vocal_tract_synthesis_close(&dec->synthesis_ch_fl_fr); + audio_vocal_tract_synthesis_close(&dec->synthesis_ch_rl_rr); + audio_vocal_tract_close(&dec->vocal_tract); + channel_switch_close(&dec->ch_switch); +#endif + + if (dec->linein) { + linein_sample_close(dec->linein); + dec->linein = NULL; + } + audio_mixer_ch_close(&dec->mix_ch); +#if (RECORDER_MIX_EN) + audio_mixer_ch_close(&dec->rec_mix_ch); +#endif/*RECORDER_MIX_EN*/ +#if TCFG_PCM_ENC2TWS_ENABLE + if (linein_dec->pcm_dec.dec_no_out_sound) { + linein_dec->pcm_dec.dec_no_out_sound = 0; + localtws_enc_api_close(); + } +#endif +#if SYS_DIGVOL_GROUP_EN + sys_digvol_group_ch_close("music_linein"); +#endif // SYS_DIGVOL_GROUP_EN + + + if (dec->stream) { + audio_stream_close(dec->stream); + dec->stream = NULL; + } + + pcm_decoder_close(&dec->pcm_dec); +__err1: + linein_dec_relaese(); + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief fm解码关闭 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void __linein_dec_close(void) +{ + if (linein_dec && linein_dec->start) { + linein_dec->start = 0; + + pcm_decoder_close(&linein_dec->pcm_dec); + linein_sample_close(linein_dec->linein); + linein_dec->linein = NULL; + +#if AUDIO_SURROUND_CONFIG + surround_close_demo(linein_dec->surround); +#endif + + + +#if AUDIO_VBASS_CONFIG + audio_gain_close_demo(linein_dec->vbass_prev_gain); + audio_vbass_close_demo(linein_dec->vbass); +#endif + + high_bass_eq_close(linein_dec->high_bass); + high_bass_drc_close(linein_dec->hb_drc); + convet_data_close(linein_dec->hb_convert); + +#if TCFG_EQ_ENABLE && TCFG_LINEIN_MODE_EQ_ENABLE +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN + linein_eq_close(linein_dec->eq); +#else + music_eq_close(linein_dec->eq); +#endif +#if TCFG_DRC_ENABLE && TCFG_LINEIN_MODE_DRC_ENABLE +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN + linein_drc_close(linein_dec->drc); +#else + music_drc_close(linein_dec->drc); +#endif +#endif + convet_data_close(linein_dec->convert); + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + music_eq2_close(linein_dec->eq2); + audio_dynamic_eq_ctrl_close(linein_dec->dy_eq); + convet_data_close(linein_dec->convert2); +#endif + audio_gain_close_demo(linein_dec->gain); +#endif + +#if TCFG_EQ_DIVIDE_ENABLE + music_eq_rl_rr_close(linein_dec->eq_rl_rr); + music_drc_rl_rr_close(linein_dec->drc_rl_rr); + convet_data_close(linein_dec->convert_rl_rr); +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + stream_entry_close(&linein_dec->rl_rr_mix); +#endif + audio_gain_close_demo(linein_dec->gain_rl_rr); + + audio_vocal_tract_synthesis_close(&linein_dec->synthesis_ch_fl_fr); + audio_vocal_tract_synthesis_close(&linein_dec->synthesis_ch_rl_rr); + audio_vocal_tract_close(&linein_dec->vocal_tract); + channel_switch_close(&linein_dec->ch_switch); +#endif + audio_mixer_ch_close(&linein_dec->mix_ch); +#if (RECORDER_MIX_EN) + audio_mixer_ch_close(&linein_dec->rec_mix_ch); +#endif/*RECORDER_MIX_EN*/ +#if TCFG_PCM_ENC2TWS_ENABLE + if (linein_dec->pcm_dec.dec_no_out_sound) { + linein_dec->pcm_dec.dec_no_out_sound = 0; + localtws_enc_api_close(); + } +#endif +#if SYS_DIGVOL_GROUP_EN + sys_digvol_group_ch_close("music_linein"); +#endif // SYS_DIGVOL_GROUP_EN + + + // 先关闭各个节点,最后才close数据流 + if (linein_dec->stream) { + audio_stream_close(linein_dec->stream); + linein_dec->stream = NULL; + } + __bt_emitter_pp(0); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief linein解码资源等待 + @param *wait: 句柄 + @param event: 事件 + @return 0:成功 + @note 用于多解码打断处理 +*/ +/*----------------------------------------------------------------------------*/ +static int linein_wait_res_handler(struct audio_res_wait *wait, int event) +{ + int err = 0; + log_i("linein_wait_res_handler, event:%d\n", event); + if (event == AUDIO_RES_GET) { + // 启动解码 + err = linein_dec_start(); + } else if (event == AUDIO_RES_PUT) { + // 被打断 + __linein_dec_close(); + } + + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 打开linein解码 + @param source: 音频源 + @param sample_rate: 采样率 + @return 0:成功 + @return 非0:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int linein_dec_open(u8 source, u32 sample_rate) +{ + int err; + struct linein_dec_hdl *dec; + dec = zalloc(sizeof(*dec)); + if (!dec) { + return -ENOMEM; + } + linein_dec = dec; + dec->id = rand32(); + + switch (source) { + case BIT(0): + case BIT(1): + /* dec->source = 0; */ + dec->pcm_dec.ch_num = 1; + break; + case BIT(2): + case BIT(3): + /* dec->source = 1; */ + dec->pcm_dec.ch_num = 1; + break; + case BIT(4): + case BIT(5): + /* dec->source = 2; */ + dec->pcm_dec.ch_num = 1; + break; + case (BIT(0)|BIT(1)): + /* dec->source = 0; */ + dec->pcm_dec.ch_num = 2; + break; + case (BIT(2)|BIT(3)): + /* dec->source = 1; */ + dec->pcm_dec.ch_num = 2; + break; + case (BIT(4)|BIT(5)): + /* dec->source = 2; */ + dec->pcm_dec.ch_num = 2; + break; + default: + log_e("Linein can only select a single channel\n"); + ASSERT(0, "err\n"); + break; + } + dec->source = source; + + dec->pcm_dec.output_ch_num = audio_output_channel_num(); + dec->pcm_dec.output_ch_type = audio_output_channel_type(); +#if TCFG_MIC_EFFECT_ENABLE + dec->pcm_dec.sample_rate = MIC_EFFECT_SAMPLERATE; +#else + dec->pcm_dec.sample_rate = sample_rate; +#endif + dec->wait.priority = 2; + dec->wait.preemption = 0; + dec->wait.snatch_same_prio = 1; +#if SOUNDCARD_ENABLE + dec->wait.protect = 1; +#endif + dec->wait.handler = linein_wait_res_handler; + clock_add(AUDIO_CODING_PCM); + + +#if TCFG_DEC2TWS_ENABLE + // 设置localtws重播接口 + localtws_globle_set_dec_restart(linein_dec_push_restart); +#endif + + err = audio_decoder_task_add_wait(&decode_task, &dec->wait); + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭linein解码 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void linein_dec_close(void) +{ + if (!linein_dec) { + return; + } + + __linein_dec_close(); + linein_dec_relaese(); + clock_set_cur(); + log_i("linein dec close \n\n "); +} + +/*----------------------------------------------------------------------------*/ +/**@brief linein解码重新开始 + @param id: 文件解码id + @return 0:成功 + @return 非0:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int linein_dec_restart(int id) +{ + if ((!linein_dec) || (id != linein_dec->id)) { + return -1; + } + u8 source = linein_dec->source; + u32 sample_rate = linein_dec->pcm_dec.sample_rate; + linein_dec_close(); + int err = linein_dec_open(source, sample_rate); + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 推送linein解码重新开始命令 + @param + @return true:成功 + @return false:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int linein_dec_push_restart(void) +{ + if (!linein_dec) { + return false; + } + int argv[3]; + argv[0] = (int)linein_dec_restart; + argv[1] = 1; + argv[2] = (int)linein_dec->id; + os_taskq_post_type(os_current_task(), Q_CALLBACK, ARRAY_SIZE(argv), argv); + return true; +} +#endif diff --git a/cpu/br23/audio_dec/audio_dec_linein.h b/cpu/br23/audio_dec/audio_dec_linein.h new file mode 100644 index 0000000..e67d51e --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_linein.h @@ -0,0 +1,32 @@ + +#ifndef _AUDIO_DEC_LINEIN_H_ +#define _AUDIO_DEC_LINEIN_H_ + +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "media/audio_decoder.h" + +// linein解码释放 +void linein_dec_relaese(); +// linein解码开始 +int linein_dec_start(); + +// 打开linein解码 +int linein_dec_open(u8 source, u32 sample_rate); +// 关闭linein解码 +void linein_dec_close(void); +// linein解码重新开始 +int linein_dec_restart(int magic); +// 推送linein解码重新开始命令 +int linein_dec_push_restart(void); + +/***********************linein pcm enc******************************/ +// linein录音停止 +void linein_pcm_enc_stop(void); +// linein录音开始 +int linein_pcm_enc_start(void); +// 检测linein是否在录音 +bool linein_pcm_enc_check(); + +#endif diff --git a/cpu/br23/audio_dec/audio_dec_midi_ctrl.c b/cpu/br23/audio_dec/audio_dec_midi_ctrl.c new file mode 100644 index 0000000..9ff8e25 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_midi_ctrl.c @@ -0,0 +1,643 @@ +#include "audio_dec_midi_ctrl.h" + +#if AUDIO_MIDI_CTRL_CONFIG +/* + *如遇到多按琴键同时按下或重复快速按某琴键出现卡顿的情况 + *处理方法:1、减少同时发声MIDI_KEY_NUM 个数 + * 2、提高外挂flash的 波特率(60M、90M),调整spi读线宽的为2线模式或4线 + * 3、提高系统时钟 + * */ +extern struct audio_dac_hdl dac_hdl; + +#define MIDI_KEY_NUM (10)//(支持多少个key同时发声(1~18), 越大,需要的时钟越大) + +static const u16 midi_samplerate_tab[9] = { + 48000, + 44100, + 32000, + 24000, + 22050, + 16000, + 12000, + 11025, + 8000 +}; + +struct _midi_obj { + u8 channel; + u32 sample_rate; + u32 id; // 唯一标识符,随机值 + u32 start : 1; // 正在解码 + char *path; //音色文件路径 + struct audio_res_wait wait; // 资源等待句柄 + struct midi_ctrl_decoder midi_ctrl_dec; + struct audio_mixer_ch mix_ch; // 叠加句柄 + struct audio_stream *stream; // 音频流 +}; + +struct _midi_obj *midi_ctrl_dec_hdl = NULL; + +void midi_ctrl_ioctrl(u32 cmd, void *priv); +/*----------------------------------------------------------------------------*/ +/**@brief midi ctrl解码释放 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_dec_relaese() +{ + if (midi_ctrl_dec_hdl) { + audio_decoder_task_del_wait(&decode_task, &midi_ctrl_dec_hdl->wait); + clock_remove(DEC_MIDI_CLK); + local_irq_disable(); + free(midi_ctrl_dec_hdl); + midi_ctrl_dec_hdl = NULL; + local_irq_enable(); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief midi音色文件获取 + @param + @return + @note 内部调用 +*/ +/*----------------------------------------------------------------------------*/ +static int midi_get_cfg_addr(u8 **addr) +{ + if (!midi_ctrl_dec_hdl) { + return -1; + } + +#ifndef CONFIG_MIDI_DEC_ADDR + //音色文件支持在外部存储卡或者外挂flash,sdk默认使用本方式 + /* FILE *file = fopen("storage/sd0/C/MIDI.bin\0", "r"); */ + FILE *file = fopen(midi_ctrl_dec_hdl->path, "r"); + + /* FILE *file = fopen(SDFILE_RES_ROOT_PATH"MIDI.bin\0", "r"); */ + if (!file) { + log_e("MIDI.bin open err\n"); + return -1; + } + *addr = (u8 *)file; + log_i("midi_file %x\n", file); +#else + //音色文件仅支持在内置flash + /* FILE *file = fopen(SDFILE_RES_ROOT_PATH"MIDI.bin\0", "r"); */ + FILE *file = fopen(midi_ctrl_dec_hdl->path, "r"); + if (!file) { + log_e("MIDI.bin open err\n"); + return -1; + } + + struct vfs_attr attr = {0}; + fget_attrs(file, &attr); + *addr = (u8 *)attr.sclust; + fclose(file); +#endif + + return 0; +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief midi音色文件读 + @param + @return + @note 内部调用 +*/ +/*----------------------------------------------------------------------------*/ +static int midi_fread(void *file, void *buf, u32 len) +{ +#ifndef CONFIG_MIDI_DEC_ADDR + FILE *hd = (FILE *)file; + if (hd) { + len = fread(hd, buf, len); + } +#endif + return len; +} +/*----------------------------------------------------------------------------*/ +/**@brief midi音色文件seek + @param + @return + @note 内部调用 +*/ +/*----------------------------------------------------------------------------*/ +static int midi_fseek(void *file, u32 offset, int seek_mode) +{ +#ifndef CONFIG_MIDI_DEC_ADDR + FILE *hd = (FILE *)file; + if (hd) { + fseek(hd, offset, seek_mode); + } +#endif + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief midi ctrl初始化函数,该函数由库调用 + @param 参数返回地址 + @return 0 + @note 该函数是弱定义函数,不可修改定义 +*/ +/*----------------------------------------------------------------------------*/ +int midi_ctrl_init(void *info) +{ + if (!midi_ctrl_dec_hdl) { + return -1; + } + u8 *cache_addr; + if (midi_get_cfg_addr(&cache_addr)) { + return -1; + } + midi_ctrl_open_parm *parm = (midi_ctrl_open_parm *)info; + parm->ctrl_parm.tempo = 1024;//解码会改变播放速度,1024是正常值 + parm->ctrl_parm.track_num = 1;//支持音轨的最大个数0~15 + + parm->sample_rate = midi_ctrl_dec_hdl->midi_ctrl_dec.sample_rate;//midi_samplerate_tab[5]; + parm->cfg_parm.player_t = MIDI_KEY_NUM; //(支持多少个key同时发声,用户可修改) + parm->cfg_parm.spi_pos = (unsigned int)cache_addr; + parm->cfg_parm.fread = midi_fread; + parm->cfg_parm.fseek = midi_fseek; + + for (int i = 0; i < ARRAY_SIZE(midi_samplerate_tab); i++) { + if (parm->sample_rate == midi_samplerate_tab[i]) { + parm->cfg_parm.sample_rate = i; + break; + } + } + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief midi ctrl音色文件关闭 + @param + @return + @note 该函数在midi关闭时调用,该函数是弱定义函数,不可修改定义 +*/ +/*----------------------------------------------------------------------------*/ +int midi_ctrl_uninit(void *priv) +{ +#ifndef CONFIG_MIDI_DEC_ADDR + if (priv) { + fclose((FILE *)priv); + priv = NULL; + } +#endif + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 乐器更新 + @param prog:乐器号 + @param trk_num :音轨 (0~15) + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_set_porg(u8 prog, u8 trk_num) +{ + struct set_prog_parm parm = {0}; + parm.prog = prog; + parm.trk_num = trk_num; + midi_ctrl_ioctrl(MIDI_CTRL_SET_PROG, &parm); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按键按下 + @param nkey:按键序号(0~127) + @param nvel:按键力度(0~127) + @param chn :通道(0~15) + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_note_on(u8 nkey, u8 nvel, u8 chn) +{ + struct note_on_parm parm = {0}; + parm.nkey = nkey; + parm.nvel = nvel; + parm.chn = chn; + midi_ctrl_ioctrl(MIDI_CTRL_NOTE_ON, &parm); +} +/*----------------------------------------------------------------------------*/ +/**@brief 按键松开 + @param nkey:按键序号(0~127) + @param chn :通道(0~15) + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_note_off(u8 nkey, u8 chn) +{ + struct note_off_parm parm = {0}; + parm.nkey = nkey; + parm.chn = chn; + midi_ctrl_ioctrl(MIDI_CTRL_NOTE_OFF, &parm); +} +/*----------------------------------------------------------------------------*/ +/**@brief midi 配置接口 + @param cmd:命令 + @param priv:对应cmd的结构体 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_confing(u32 cmd, void *priv) +{ + midi_ctrl_ioctrl(cmd, priv); +} + +/*----------------------------------------------------------------------------*/ +/**@brief midi keyboard 设置按键按下音符发声的衰减系数 + @param val:((衰减系数&0x7fff) | (延时系数&0x1f <<11)) + @return + @note 低11bit为调节衰减系数,值越小,衰减越快, 1024为默认值, 范围:0~1024 + 大于11bit为延时系数,节尾音长度的,值越大拉德越长,0为默认值,31延长1s,范围:0~31(延时系数无效) + @example midi_ctrl_confing_set_melody_decay((衰减系数&0x7fff) | (延时系数&0x1f <<11)); + u16 val = ((1024&0x7ff) | (31&0x1f << 11)); + midi_ctrl_confing_set_melody_decay(val); +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_confing_set_melody_decay(u16 val) +{ + u32 cmd = CMD_MIDI_CTRL_TEMPO; + MIDI_PLAY_CTRL_TEMPO tempo = {0}; + for (int i = 0; i < 16; i++) { + tempo.decay_val[i] = val; + } + tempo.tempo_val = 1024;//设置为固定1024即可 + midi_ctrl_confing(cmd, (void *)&tempo); +} +/*----------------------------------------------------------------------------*/ +/**@brief midi keyboard 设置每个通道按下音符发声的衰减系数 + @param val:16个值的数组,每个值组成组成结构((衰减系数&0x7fff) | (延时系数&0x1f <<11)) + @return + @note 低11bit为调节衰减系数,值越小,衰减越快, 1024为默认值, 范围:0~1024 + 大于11bit为延时系数,节尾音长度的,值越大拉德越长,0为默认值,31延长1s,范围:0~31(延时系数无效) + @example u16 val[16]; + for (int i = 0; i< 16; i++){ + val[i] = ((1024&0x7ff) | (31&0x1f << 11)); + } + midi_ctrl_confing_set_melody_decay(val); +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_confing_set_melody_decay_each_chn(u16 *val) +{ + u32 cmd = CMD_MIDI_CTRL_TEMPO; + MIDI_PLAY_CTRL_TEMPO tempo = {0}; + if (val) { + memcpy(tempo.decay_val, val, sizeof(tempo.decay_val)); + } + tempo.tempo_val = 1024;//设置为固定1024即可 + midi_ctrl_confing(cmd, (void *)&tempo); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 弯音轮配置 + @param pitch_val:弯音轮值,1 - 65535 ;256是正常值,对音高有作用 + @param chn :通道(0~15) + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_pitch_bend(u16 pitch_val, u8 chn) +{ + struct pitch_bend_parm parm = {0}; + parm.pitch_val = pitch_val; + parm.chn = chn; + midi_ctrl_ioctrl(MIDI_CTRL_PITCH_BEND, &parm); +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief midi ctrl解码数据流激活 + @param *p: 私有句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void midi_ctrl_dec_out_stream_resume(void *p) +{ + struct _midi_obj *dec = p; +#if FILE_DEC_USE_OUT_TASK + if (dec->midi_ctrl_dec.dec_no_out_sound == 0) { + audio_decoder_resume_out_task(&dec->midi_ctrl_dec.decoder); + return ; + } +#endif + audio_decoder_resume(&dec->midi_ctrl_dec.decoder); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief midi ctrl解码事件处理 + @param *decoder: 解码器句柄 + @param argc: 参数个数 + @param *argv: 参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void midi_ctrl_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ + switch (argv[0]) { + case AUDIO_DEC_EVENT_END: + if (!midi_ctrl_dec_hdl) { + log_i("midi_ctrl_dec_hdl handle err "); + break; + } + + if (midi_ctrl_dec_hdl->id != argv[1]) { + log_w("midi_ctrl_dec_hdl id err : 0x%x, 0x%x \n", midi_ctrl_dec_hdl->id, argv[1]); + break; + } + + midi_ctrl_dec_close(); + //audio_decoder_resume_all(&decode_task); + break; + } +} +/*----------------------------------------------------------------------------*/ +/**@brief midi ctrl解码开始 + @param + @return 0:成功 + @return 非0:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int midi_ctrl_dec_start() +{ + int err; + struct _midi_obj *dec = midi_ctrl_dec_hdl; + + struct audio_mixer *p_mixer = &mixer; + + if (!dec) { + return -EINVAL; + } + + log_i("midi_ctrl dec start: in\n"); +// 打开midi ctrl解码器 + err = midi_ctrl_decoder_open(&dec->midi_ctrl_dec, &decode_task); + if (err) { + goto __err1; + } + + midi_ctrl_decoder_set_event_handler(&dec->midi_ctrl_dec, midi_ctrl_dec_event_handler, dec->id); + +// 设置叠加功能 + audio_mixer_ch_open_head(&dec->mix_ch, p_mixer); + audio_mixer_ch_set_src(&dec->mix_ch, 1, 0); + +#if FILE_DEC_USE_OUT_TASK + if (dec->midi_ctrl_dec.dec_no_out_sound == 0) { + audio_decoder_out_task_ch_enable(&dec->midi_ctrl_dec.decoder); + } +#endif + + +// 数据流串联 + struct audio_stream_entry *entries[8] = {NULL}; + u8 entry_cnt = 0; + + entries[entry_cnt++] = &dec->midi_ctrl_dec.decoder.entry; + entries[entry_cnt++] = &dec->mix_ch.entry; + + // 创建数据流,把所有节点连接起来 + + dec->stream = audio_stream_open(dec, midi_ctrl_dec_out_stream_resume); + audio_stream_add_list(dec->stream, entries, entry_cnt); + +// 设置音频输出音量 + audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); +// 设置时钟 + clock_set_cur(); + + // 开始解码 + dec->midi_ctrl_dec.status = FILE_DEC_STATUS_PLAY; + err = audio_decoder_start(&dec->midi_ctrl_dec.decoder); + dec->start = 1; + if (err) { + goto __err3; + } + return 0; +__err3: + audio_mixer_ch_close(&dec->mix_ch); + + midi_ctrl_decoder_close(&dec->midi_ctrl_dec); + + if (dec->stream) { + audio_stream_close(dec->stream); + dec->stream = NULL; + } +__err1: + log_w(" start err close\n"); + midi_ctrl_dec_relaese(); + return -1; +} +/*----------------------------------------------------------------------------*/ +/**@brief midi ctrl解码关闭 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void __midi_ctrl_dec_close(void) +{ + if (midi_ctrl_dec_hdl && midi_ctrl_dec_hdl->start) { + midi_ctrl_dec_hdl->start = 0; + + midi_ctrl_decoder_close(&midi_ctrl_dec_hdl->midi_ctrl_dec); + + audio_mixer_ch_close(&midi_ctrl_dec_hdl->mix_ch); + + // 先关闭各个节点,最后才close数据流 + if (midi_ctrl_dec_hdl->stream) { + audio_stream_close(midi_ctrl_dec_hdl->stream); + midi_ctrl_dec_hdl->stream = NULL; + } + + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭midi ctrl解码 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_dec_close(void) +{ + if (!midi_ctrl_dec_hdl) { + return; + } + __midi_ctrl_dec_close(); + midi_ctrl_dec_relaese(); + clock_set_cur(); + log_i("midi ctrl dec close \n\n "); +} + +/*----------------------------------------------------------------------------*/ +/**@brief midi ctrl解码资源等待 + @param *wait: 句柄 + @param event: 事件 + @return 0:成功 + @note 用于多解码打断处理 +*/ +/*----------------------------------------------------------------------------*/ +static void __midi_ctrl_dec_close(void); +static int midi_ctrl_wait_res_handler(struct audio_res_wait *wait, int event) +{ + int err = 0; + log_i("midi_ctrl_wait_res_handler, event:%d\n", event); + if (event == AUDIO_RES_GET) { + // 启动解码 + err = midi_ctrl_dec_start(); + } else if (event == AUDIO_RES_PUT) { + // 被打断 + __midi_ctrl_dec_close(); + } + + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 打开midi ctrl解码 + @param sample_rate: 采样率 + @param *path:音色文件路径 + @return 0:成功 + @return 非0:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int midi_ctrl_dec_open(u32 sample_rate, char *path) +{ + int err = 0; + int i = 0; + struct _midi_obj *dec; + dec = zalloc(sizeof(*dec)); + if (!dec) { + return -ENOMEM; + } + midi_ctrl_dec_hdl = dec; + dec->id = rand32(); + dec->path = path; + + dec->midi_ctrl_dec.ch_num = 2; + + dec->midi_ctrl_dec.output_ch_num = audio_output_channel_num(); + dec->midi_ctrl_dec.output_ch_type = audio_output_channel_type(); +#if TCFG_MIC_EFFECT_ENABLE + dec->midi_ctrl_dec.sample_rate = MIC_EFFECT_SAMPLERATE; +#else + for (i = 0; i < ARRAY_SIZE(midi_samplerate_tab); i++) { + if (sample_rate == midi_samplerate_tab[i]) { + dec->midi_ctrl_dec.sample_rate = midi_samplerate_tab[i]; + break; + } + } + if (i >= ARRAY_SIZE(midi_samplerate_tab)) { + dec->midi_ctrl_dec.sample_rate = 16000; + log_e("midi sample_rate check err ,will set default 16000 Hz\n"); + } +#endif + dec->wait.priority = 2; + dec->wait.preemption = 0; + dec->wait.snatch_same_prio = 1; + /* dec->wait.protect = 1; */ + dec->wait.handler = midi_ctrl_wait_res_handler; + clock_add(DEC_MIDI_CLK); + + + err = audio_decoder_task_add_wait(&decode_task, &dec->wait); + return err; +} +/*----------------------------------------------------------------------------*/ +/**@brief midi ctrl控制函数 + @param cmd: + MIDI_CTRL_NOTE_ON, //按键按下,参数结构对应struct note_on_parm + MIDI_CTRL_NOTE_OFF, //按键松开,参数结构对应struct note_off_parm + MIDI_CTRL_SET_PROG, //更改乐器,参数结构对应struct set_prog_parm + MIDI_CTRL_PITCH_BEND, //弯音轮,参数结构对应struct pitch_bend_parm + CMD_MIDI_CTRL_TEMPO, //改变节奏,参数结构对应 MIDI_PLAY_CTRL_TEMPO + @param priv:对应cmd的参数地址 + @return 0 + @note midi解码控制例程 +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_ioctrl(u32 cmd, void *priv) +{ + struct _midi_obj *dec = midi_ctrl_dec_hdl; + if (!dec) { + log_e("midi ctrl dec NULL\n"); + return ; + } + + log_i("midi ctrl cmd %x", cmd); + audio_decoder_ioctrl(&dec->midi_ctrl_dec.decoder, cmd, priv); +} + +#if 0 +/*----------------------------------------------------------------------------*/ +/**@brief midi key 测试样例 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_paly_test(u32 key) +{ + static u8 open_close = 0; + static u8 change_prog = 0; + static u8 note_on_off = 0; + switch (key) { + case KEY_IR_NUM_0: + if (!open_close) { + /* midi_ctrl_dec_open(16000);//启动midi key */ + /* midi_ctrl_dec_open(16000, "storage/sd0/C/MIDI.bin\0");//启动midi key */ + midi_ctrl_dec_open(16000, SDFILE_RES_ROOT_PATH"MIDI.bin\0");//启动midi key + + } else { + midi_ctrl_dec_close();//关闭midi key + } + open_close = !open_close; + break; + case KEY_IR_NUM_1: + if (!change_prog) { + midi_ctrl_set_porg(0, 0);//设置0号乐器,音轨0 + } else { + midi_ctrl_set_porg(22, 0);//设置22号乐器,音轨0 + } + change_prog = !change_prog; + break; + case KEY_IR_NUM_2: + if (!note_on_off) { + //模拟按键57、58、59、60、61、62,以力度127,通道0,按下测试 + midi_ctrl_note_on(57, 127, 0); + midi_ctrl_note_on(58, 127, 0); + midi_ctrl_note_on(59, 127, 0); + midi_ctrl_note_on(60, 127, 0); + midi_ctrl_note_on(61, 127, 0); + midi_ctrl_note_on(62, 127, 0); + } else { + //模拟按键57、58、59、60、61、62松开测试 + midi_ctrl_note_off(57, 0); + midi_ctrl_note_off(58, 0); + midi_ctrl_note_off(59, 0); + midi_ctrl_note_off(60, 0); + midi_ctrl_note_off(61, 0); + midi_ctrl_note_off(62, 0); + } + note_on_off = !note_on_off; + break; + default: + break; + } +} +#endif +#endif diff --git a/cpu/br23/audio_dec/audio_dec_midi_ctrl.h b/cpu/br23/audio_dec/audio_dec_midi_ctrl.h new file mode 100644 index 0000000..ee7f019 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_midi_ctrl.h @@ -0,0 +1,100 @@ +#ifndef _AUDIO_DEC_MIDI_CTRL_H_ +#define _AUDIO_DEC_MIDI_CTRL_H_ +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "app_config.h" +#include "audio_config.h" +#include "audio_dec.h" +#include "app_main.h" +#include "asm/dac.h" +#include "clock_cfg.h" +#include "key_event_deal.h" +#include "midi_ctrl_decoder.h" + +/*----------------------------------------------------------------------------*/ +/**@brief 打开midi ctrl解码 + @param sample_rate: 采样率 + @param *path:音色文件路径 + @return 0:成功 + @return 非0:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int midi_ctrl_dec_open(u32 sample_rate, char *path); + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭midi ctrl解码 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_dec_close(void); + + +/*----------------------------------------------------------------------------*/ +/**@brief 乐器更新 + @param prog:乐器号 + @param trk_num :音轨 (0~15) + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_set_porg(u8 prog, u8 trk_num); + +/*----------------------------------------------------------------------------*/ +/**@brief 按键按下 + @param nkey:按键序号(0~127) + @param nvel:按键力度(0~127) + @param chn :通道(0~15) + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_note_on(u8 nkey, u8 nvel, u8 chn); + + +/*----------------------------------------------------------------------------*/ +/**@brief 按键松开 + @param nkey:按键序号(0~127) + @param chn :通道(0~15) + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_note_off(u8 nkey, u8 chn); + + +/*----------------------------------------------------------------------------*/ +/**@brief midi 配置接口 + @param cmd:命令 + @param priv:对应cmd的结构体 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_confing(u32 cmd, void *priv); + + +/*----------------------------------------------------------------------------*/ +/**@brief midi keyboard 设置按键按下音符发声的衰减系数 + @param obj:控制句柄 + @param samp:对应samplerate_tab坐标 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_confing_set_melody_decay(u16 val); + +/*----------------------------------------------------------------------------*/ +/**@brief 弯音轮配置 + @param pitch_val:弯音轮值,1 - 65535 ;256是正常值,对音高有作用 + @param chn :通道(0~15) + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_ctrl_pitch_bend(u16 pitch_val, u8 chn); + +#endif diff --git a/cpu/br23/audio_dec/audio_dec_midi_file.c b/cpu/br23/audio_dec/audio_dec_midi_file.c new file mode 100644 index 0000000..ee5b656 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_midi_file.c @@ -0,0 +1,431 @@ +/* + **************************************************************** + *File : audio_dec_midi_file.c + *Note : + * + **************************************************************** + */ +////////////////////////////////////////////////////////////////////////////// +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "effectrs_sync.h" +#include "app_config.h" +#include "audio_config.h" +#include "audio_dec.h" +#include "app_config.h" +#include "app_main.h" +#include "MIDI_DEC_API.h" +#include "audio_dec_file.h" +#include "lfwordana_enc_api.h" + +#if defined(TCFG_DEC_MIDI_ENABLE) && TCFG_DEC_MIDI_ENABLE +//midi文件播放时,对应的音色文件路径(用户可修改路径) +#define MIDI_FILE_PATH SDFILE_RES_ROOT_PATH"MIDI.bin\0" +//替换主旋律的音色库,由录音得到(用户可修改路径) +int *MIDI_W2S_FILE_PATH = "storage/sd0/C/W2S/W2S.raw\0"; +//替换主旋律音色库对应的参数文件,录音时生成(用户可修改路径) +#define MIDI_W2S_PARM_PATH "storage/sd0/C/W2S/parmout.raw\0" + +static const u16 midi_samplerate_tab[9] = { + 48000, + 44100, + 32000, + 24000, + 22050, + 16000, + 12000, + 11025, + 8000 +}; +static u32 get_sr_tab_num(u32 sr) +{ + int i = 0; + for (i = 0; i < ARRAY_SIZE(midi_samplerate_tab); i++) { + if (sr == midi_samplerate_tab[i]) { + return i; + } + } + return 4; +} +u32 tmark_trigger(void *priv, u8 *val, u8 len) +{ + return 0; +} + +u32 melody_trigger(void *priv, u8 key, u8 vel) +{ + return 0; +} + +u32 melody_stop_trigger(void *priv, u8 key) +{ + return 0; +} + +u32 timDiv_trigger(void *priv) +{ + return 0; +} + +u32 beat_trigger(void *priv, u8 val1/*一节多少拍*/, u8 val2/*每拍多少分音符*/) +{ + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief midi音色文件读 + @param + @return + @note 内部调用 +*/ +/*----------------------------------------------------------------------------*/ +int midi_fread(void *file, void *buf, u32 len) +{ + +#ifndef CONFIG_MIDI_DEC_ADDR + FILE *hd = (FILE *)file; + if (hd) { + len = fread(hd, buf, len); + } +#endif + return len; +} +/*----------------------------------------------------------------------------*/ +/**@brief midi音色文件seek + @param + @return + @note 内部调用 +*/ +/*----------------------------------------------------------------------------*/ +int midi_fseek(void *file, u32 offset, int seek_mode) +{ +#ifndef CONFIG_MIDI_DEC_ADDR + FILE *hd = (FILE *)file; + if (hd) { + fseek(hd, offset, seek_mode); + } +#endif + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief midi初始化函数,由midi_init调用 + @param midi_init_info_v:midi信息 + @param addr:音色文件句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void init_midi_info_val(MIDI_INIT_STRUCT *midi_init_info_v, void *addr) +{ + //midi初始化表 + midi_init_info_v->init_info.player_t = 8; + midi_init_info_v->init_info.sample_rate = get_sr_tab_num(22050); + midi_init_info_v->init_info.spi_pos = (u32)addr; + midi_init_info_v->init_info.fread = midi_fread; + midi_init_info_v->init_info.fseek = midi_fseek; + + + //midi的模式初始化 + midi_init_info_v->mode_info.mode = CMD_MIDI_CTRL_MODE_0; //CMD_MIDI_CTRL_MODE_2; + + //midi节奏初始化 + midi_init_info_v->tempo_info.tempo_val = 1042; + + for (u32 tmp_i = 0; tmp_i < 16; tmp_i++) { + midi_init_info_v->tempo_info.decay_val[tmp_i] = ((u16)31 << 11) | 1024; + } + midi_init_info_v->tempo_info.mute_threshold = (u16)1L << 29; + + //midi主轨道初始化 + midi_init_info_v->mainTrack_info.chn = 17; //把哪个轨道当成主轨道 , 17:库内自动分配 + + //midi外部音量初始化 + for (u32 tmp_i = 0; tmp_i < 16; tmp_i++) { + midi_init_info_v->vol_info.cc_vol[tmp_i] = 4096; //4096即原来的音量 + } + midi_init_info_v->vol_info.ex_vol_use_chn = 1; + + //midi的主轨道乐器设置 + midi_init_info_v->prog_info.prog = 0; + midi_init_info_v->prog_info.ex_vol = 1024; + midi_init_info_v->prog_info.replace_mode = 0; + + //OKON 模式设置 + midi_init_info_v->okon_info.Melody_Key_Mode = CMD_MIDI_MELODY_KEY_0; + midi_init_info_v->okon_info.OKON_Mode = CMD_MIDI_OKON_MODE_0; + + + //midi的mark控制初始化 + midi_init_info_v->mark_info.priv = NULL; //&file_mark; + midi_init_info_v->mark_info.mark_trigger = tmark_trigger; + + //midi的melody控制初始化 + midi_init_info_v->moledy_info.priv = NULL; //&file_melody; + midi_init_info_v->moledy_info.melody_trigger = melody_trigger; + + //midi的melody stop控制初始化 + midi_init_info_v->moledy_stop_info.priv = NULL; + midi_init_info_v->moledy_stop_info.melody_stop_trigger = melody_stop_trigger;//主旋律音符停止播放回调 + + //midi的小节回调控制初始化 + midi_init_info_v->tmDiv_info.priv = NULL; + midi_init_info_v->tmDiv_info.timeDiv_trigger = timDiv_trigger; + + //midi的小拍回调控制初始化 + midi_init_info_v->beat_info.priv = NULL; + midi_init_info_v->beat_info.beat_trigger = beat_trigger; + + //使能位控制 + midi_init_info_v->switch_info = MELODY_PLAY_ENABLE;// | MELODY_ENABLE | EX_VOL_ENABLE; //主轨道播放使能 + +#if defined(MIDI_SUPPORT_W2S) && MIDI_SUPPORT_W2S + //设置替换主轨道的声音的音源 + void *cache_addr; + extern int midi_w2s_get_cfg_addr(void **addr); + if (midi_w2s_get_cfg_addr(&cache_addr)) { + log_e("get midi w2s addr err\n"); + return; + } + midi_w2s_parm_get(&midi_init_info_v->w2s_info); + midi_init_info_v->w2s_info.key_diff = -7;////与音高成反比 + midi_init_info_v->w2s_info.rec_data = (u32)cache_addr; +#endif/*MIDI_SUPPORT_W2S*/ + return; +} + +FILE *midi_w2s_file = NULL; +int midi_w2s_get_cfg_addr(void **addr) +{ +#ifndef CONFIG_MIDI_DEC_ADDR + //音色文件支持在外部存储卡或者外挂flash,sdk默认使用本方式 + //获取音色文件 + FILE *file = fopen(MIDI_W2S_FILE_PATH, "r"); + if (!file) { + log_e("MIDI.bin open err\n"); + return -1; + } + *addr = (void *)file; + midi_w2s_file = file; + log_i("midi_w2s_file %x\n", midi_w2s_file); +#else + //音色文件仅支持在内置flash + FILE *file = fopen(MIDI_W2S_FILE_PATH, "r"); + if (!file) { + log_e("MIDI.bin open err\n"); + return -1; + } + + struct vfs_attr attr = {0}; + fget_attrs(file, &attr); + *addr = (void *)attr.sclust; + fclose(file); +#endif + + return 0; +} + + +FILE *midi_file = NULL; +int midi_get_cfg_addr(void **addr) +{ +#ifndef CONFIG_MIDI_DEC_ADDR + //音色文件支持在外部存储卡或者外挂flash,sdk默认使用本方式 + //获取音色文件 + FILE *file = fopen(MIDI_FILE_PATH, "r"); + if (!file) { + log_e("MIDI.bin open err\n"); + return -1; + } + *addr = (void *)file; + midi_file = file; + log_i("midi_file %x\n", midi_file); +#else + //音色文件仅支持在内置flash + FILE *file = fopen(MIDI_FILE_PATH, "r"); + if (!file) { + log_e("MIDI.bin open err\n"); + return -1; + } + + struct vfs_attr attr = {0}; + fget_attrs(file, &attr); + *addr = (void *)attr.sclust; + fclose(file); +#endif + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief midi音色文件关闭 + @param + @return + @note 该函数在midi关闭时调用,该函数是弱定义函数,不可修改定义 +*/ +/*----------------------------------------------------------------------------*/ +int midi_uninit() +{ +#ifndef CONFIG_MIDI_DEC_ADDR + if (midi_file) { + fclose(midi_file); + midi_file = NULL; + } + + if (midi_w2s_file) { + fclose(midi_w2s_file); + midi_w2s_file = NULL; + } +#endif + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief midi初始化函数,该函数由库调用 + @param 参数返回地址 + @return 0 + @note 该函数是弱定义函数,不可修改定义 +*/ +/*----------------------------------------------------------------------------*/ +int midi_init(void *info) +{ + void *cache_addr; + if (midi_get_cfg_addr(&cache_addr)) { + log_e("get midi addr err\n"); + return -1; + } + //初始化midi参数 + init_midi_info_val(info, cache_addr); //需要外部写 + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief midi控制函数 + @param cmd: + CMD_MIDI_SET_CHN_PROG, //更改乐器,参数结构对应 MIDI_PROG_CTRL_STRUCT + CMD_MIDI_CTRL_TEMPO, //改变节奏,参数结构对应 MIDI_PLAY_CTRL_TEMPO + CMD_MIDI_GOON, //one key one note的时候接着播放使用,参数为空 + CMD_MIDI_CTRL_MODE, //改变模式,参数结构对应 MIDI_PLAY_CTRL_MO + CMD_MIDI_SET_SWITCH, //配置开关使能,要不要替换乐器,使用外部音量,参数对应 MIDI_SET_SWITCH + CMD_MIDI_SET_EX_VOL, //设置外部声道音量,参数结构对应 EX_CH_VOL_PARM + @param priv:对应cmd的参数地址 + @return 0 + @note midi解码控制例程 +*/ +/*----------------------------------------------------------------------------*/ +void midi_ioctrl(u32 cmd, void *priv) +{ + struct file_dec_hdl *dec = get_file_dec_hdl(); // 文件解码句柄 + if (dec) { + log_e("file dec NULL\n"); + return ; + } + + int status = file_dec_get_status(); + if (status == FILE_DEC_STATUS_STOP) { + if (tone_get_dec_status()) { + audio_decoder_ioctrl(get_tone_dec_file_decoder(), cmd, priv); + } else { + log_w("file dec is stop\n"); + } + return ; + } + + log_i("midi cmd %x", cmd); + audio_decoder_ioctrl(&dec->file_dec.decoder, cmd, priv); +} +#if 0 +//测试例子 +void *ex_vol_test() +{ + static int val = 4096; + EX_CH_VOL_PARM ex_vol; + for (int test_ci = 0; test_ci < CTRL_CHANNEL_NUM; test_ci++) { + ex_vol.cc_vol[test_ci] = val; + } + val -= 64; + if (val <= 0) { + val = 4096; + } + midi_ioctrl(CMD_MIDI_SET_EX_VOL, &ex_vol); + return NULL; +} +#endif + + +#if defined(MIDI_SUPPORT_W2S) && MIDI_SUPPORT_W2S +int midi_w2s_init(void *info) +{ + struct _AUDIO_DECODE_PARA { + u32 mode; + }; + struct _AUDIO_DECODE_PARA *mode_parm = (struct _AUDIO_DECODE_PARA *)info; + mode_parm->mode = CMD_MIDI_CTRL_MODE_W2S; + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief midi主旋律是否用录音文件替换主旋律 + @param flag:1(替换主旋律) 0(不替换主旋律) + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_mode_change(u8 flag) +{ + struct _AUDIO_DECODE_PARA { + u32 mode; + }; + struct _AUDIO_DECODE_PARA mode_parm = {0}; + if (flag) { + mode_parm.mode = CMD_MIDI_CTRL_MODE_W2S; + } else { + mode_parm.mode = CMD_MIDI_CTRL_MODE_0; + } + midi_ioctrl(CMD_MIDI_CTRL_MODE, &mode_parm); +} + +void midi_mode_test(void *p) +{ + static u8 flag = 0; + midi_mode_change(flag); + flag = !flag; +} +#endif/*MIDI_SUPPORT_W2S*/ + +/*----------------------------------------------------------------------------*/ +/**@brief midi预处理的音色,对应的输出的参数 + @param data:参数地址 + @param len:参数长度 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_w2s_parm_set(void *data, u32 len) +{ + MIDI_W2S_STRUCT *w2s_parmOut; + void *fp = fopen(MIDI_W2S_PARM_PATH, "wb"); + if (fp) { + fwrite(fp, data, len); + fclose(fp); + fp = NULL; + } +} +/*----------------------------------------------------------------------------*/ +/**@brief 获取midi预处理的音色,对应的参数 + @param parm:参数返回地址 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void midi_w2s_parm_get(void *parm) +{ + void *fp = fopen(MIDI_W2S_PARM_PATH, "r"); + if (fp) { + fread(fp, parm, sizeof(MIDI_W2S_STRUCT)); + fclose(fp); + fp = NULL; + } +} + + +#endif /*TCFG_DEC_MIDI_ENABLE*/ diff --git a/cpu/br23/audio_dec/audio_dec_pc.c b/cpu/br23/audio_dec/audio_dec_pc.c new file mode 100644 index 0000000..93cbd17 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_pc.c @@ -0,0 +1,1182 @@ +/***************************************************************** +>file name : audio_dec_pc.c +>author : lichao +>create time : Wed 22 May 2019 10:36:22 AM CST +*****************************************************************/ +#include "uac_stream.h" +#include "app_config.h" +#include "audio_decoder.h" +#include "media/includes.h" +#include "audio_config.h" +#include "system/includes.h" +#include "audio_enc.h" +#include "media/audio_eq_drc_apply.h" +#include "app_config.h" +#include "audio_config.h" +#include "audio_dec.h" +#include "app_main.h" +#include "clock_cfg.h" +#include "media/pcm_decoder.h" +#include "bt_tws.h" +#include "media/audio_stream.h" +#include "media/convert_data.h" +#include "audio_effect/audio_dynamic_eq_demo.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" +#include "avctp_user.h" + +#if (SOUNDCARD_ENABLE) +#include "stream_sync.h" +#endif/*SOUNDCARD_ENABLE*/ + +#if TCFG_UI_ENABLE +#include "ui/ui_api.h" +#endif + + +#if TCFG_APP_PC_EN + +////////////////////////////////////////////////////////////////////////////// +#if ((AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_DAC) && !TCFG_USER_TWS_ENABLE) +#define PC_SYNC_BY_DAC_HRP (1) +#else +#define PC_SYNC_BY_DAC_HRP (0) +#endif + +struct uac_dec_hdl { + struct audio_stream *stream; // 音频流 + struct pcm_decoder pcm_dec; // pcm解码句柄 + struct audio_res_wait wait; // 资源等待句柄 + struct audio_mixer_ch mix_ch; // 叠加句柄 + +#if AUDIO_SURROUND_CONFIG + surround_hdl *surround; //环绕音效句柄 +#endif + +#if AUDIO_VBASS_CONFIG + struct aud_gain_process *vbass_prev_gain; + vbass_hdl *vbass; //虚拟低音句柄 +#endif + + struct audio_eq *high_bass; + struct audio_drc *hb_drc;//高低音后的drc + struct convert_data *hb_convert; + + struct audio_eq *eq; //eq drc句柄 + struct audio_drc *drc; // drc句柄 + struct convert_data *convert; + struct audio_eq *eq2; //eq drc句柄 + struct dynamic_eq_hdl *dy_eq; + struct convert_data *convert2; + struct aud_gain_process *gain; + +#if TCFG_EQ_DIVIDE_ENABLE + struct audio_eq *eq_rl_rr; //eq drc句柄 + struct audio_drc *drc_rl_rr; // drc句柄 + struct convert_data *convert_rl_rr; + struct __stream_entry *rl_rr_mix;//双声道相加除2处理 + struct aud_gain_process *gain_rl_rr; + + struct audio_vocal_tract vocal_tract;//声道合并目标句柄 + struct audio_vocal_tract_ch synthesis_ch_fl_fr;//声道合并句柄 + struct audio_vocal_tract_ch synthesis_ch_rl_rr;//声道合并句柄 + struct channel_switch *ch_switch;//声道变换 +#endif + + u32 id; // 唯一标识符,随机值 + u32 start : 1; // 正在解码 + u32 source : 8; // 音频源 + u32 cnt: 8; + u32 state: 1; + u32 in_info; + int check_data_timer; + volatile u8 rrrl_output_en; +}; + +////////////////////////////////////////////////////////////////////////////// + +static struct uac_dec_hdl *uac_dec = NULL; // pc解码句柄 + +static u16 sys_event_id = 0; +////////////////////////////////////////////////////////////////////////////// + +extern u16 uac_get_cur_vol(const u8 id, u16 *l_vol, u16 *r_vol); +extern u8 uac_get_mute(void); +extern int usb_audio_mic_open(void *_info); +extern int usb_audio_mic_close(void *arg); +extern void usb_audio_mic_set_gain(int gain); + +/* void *pc_eq_drc_open(u16 sample_rate, u8 ch_num); */ +/* void pc_eq_drc_close(struct audio_eq_drc *eq_drc); */ + +////////////////////////////////////////////////////////////////////////////// + +/*----------------------------------------------------------------------------*/ +/**@brief pc音量值转换 + @param vol: pc音量 + @return 转换后的系统音量 + @note +*/ +/*----------------------------------------------------------------------------*/ +int uac_vol_switch(int vol) +{ + u16 valsum = vol * (SYS_MAX_VOL + 1) / 100; + + if (valsum > SYS_MAX_VOL) { + valsum = SYS_MAX_VOL; + } + return valsum; +} + +/*----------------------------------------------------------------------------*/ +/**@brief uac解码释放 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void uac_dec_relaese() +{ + if (!uac_dec) { + return; + } + audio_decoder_task_del_wait(&decode_task, &uac_dec->wait); + + clock_remove(DEC_PCM_CLK); + + local_irq_disable(); + free(uac_dec); + uac_dec = NULL; + local_irq_enable(); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief uac解码数据流激活 + @param *p: 私有句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void uac_dec_out_stream_resume(void *p) +{ + struct uac_dec_hdl *dec = p; + audio_decoder_resume(&dec->pcm_dec.decoder); +} + +/*----------------------------------------------------------------------------*/ +/**@brief uac解码激活 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void uac_dec_resume(void) +{ + if (uac_dec) { + audio_decoder_resume(&uac_dec->pcm_dec.decoder); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief uac获取buf总长度 + @param *priv: 私有参数 + @return 总长度 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int uac_dec_get_total(void *priv) +{ + return uac_speaker_stream_length(); +} + +/*----------------------------------------------------------------------------*/ +/**@brief uac获取数据长度 + @param *priv: 私有参数 + @return 数据长度 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int uac_dec_get_size(void *priv) +{ + return uac_speaker_stream_size(); +} + +/*----------------------------------------------------------------------------*/ +/**@brief pc解码关闭 + @param + @return 0:成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int uac_audio_close(void) +{ + if (!uac_dec || !uac_dec->start) { + return 0; + } + + uac_dec->start = 0; + if (uac_dec->check_data_timer) { + sys_hi_timer_del(uac_dec->check_data_timer); + } + pcm_decoder_close(&uac_dec->pcm_dec); + +#if AUDIO_SURROUND_CONFIG + surround_close_demo(uac_dec->surround); +#endif + + +#if AUDIO_VBASS_CONFIG + audio_gain_close_demo(uac_dec->vbass_prev_gain); + audio_vbass_close_demo(uac_dec->vbass); +#endif + + high_bass_eq_close(uac_dec->high_bass); + high_bass_drc_close(uac_dec->hb_drc); + convet_data_close(uac_dec->hb_convert); + +#if TCFG_EQ_ENABLE && TCFG_PC_MODE_EQ_ENABLE + music_eq_close(uac_dec->eq); +#if TCFG_DRC_ENABLE && TCFG_PC_MODE_DRC_ENABLE + music_drc_close(uac_dec->drc); +#endif + convet_data_close(uac_dec->convert); + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + music_eq2_close(uac_dec->eq2); + audio_dynamic_eq_ctrl_close(uac_dec->dy_eq); + convet_data_close(uac_dec->convert2); +#endif + audio_gain_close_demo(uac_dec->gain); +#endif + +#if TCFG_EQ_DIVIDE_ENABLE + music_eq_rl_rr_close(uac_dec->eq_rl_rr); + music_drc_rl_rr_close(uac_dec->drc_rl_rr); + convet_data_close(uac_dec->convert_rl_rr); +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + stream_entry_close(&uac_dec->rl_rr_mix); +#endif + audio_gain_close_demo(uac_dec->gain_rl_rr); + + audio_vocal_tract_synthesis_close(&uac_dec->synthesis_ch_fl_fr); + audio_vocal_tract_synthesis_close(&uac_dec->synthesis_ch_rl_rr); + audio_vocal_tract_close(&uac_dec->vocal_tract); + channel_switch_close(&uac_dec->ch_switch); +#endif + audio_mixer_ch_close(&uac_dec->mix_ch); + app_audio_state_exit(APP_AUDIO_STATE_MUSIC); + +#if TCFG_PCM_ENC2TWS_ENABLE + if (uac_dec->pcm_dec.dec_no_out_sound) { + uac_dec->pcm_dec.dec_no_out_sound = 0; + localtws_enc_api_close(); + } +#endif + +#if SYS_DIGVOL_GROUP_EN + sys_digvol_group_ch_close("music_pc"); +#endif // SYS_DIGVOL_GROUP_EN + + + // 先关闭各个节点,最后才close数据流 + if (uac_dec->stream) { + audio_stream_close(uac_dec->stream); + uac_dec->stream = NULL; + } + + clock_set_cur(); + __bt_emitter_pp(0); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief uac解码事件处理 + @param *decoder: 解码器句柄 + @param argc: 参数个数 + @param *argv: 参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void uac_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ + switch (argv[0]) { + case AUDIO_DEC_EVENT_END: + puts("USB AUDIO_DEC_EVENT_END\n"); + if (!uac_dec) { + log_i("uac_dec handle err "); + break; + } + + if (uac_dec->id != argv[1]) { + log_w("uac_dec id err : 0x%x, 0x%x \n", uac_dec->id, argv[1]); + break; + } + + /*uac_audio_close();*/ + break; + } +} +/*----------------------------------------------------------------------------*/ +/**@brief 检测uac是否收到数据,没数据时暂停mix_ch + @param *priv: 私有参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void audio_pc_check_timer(void *priv) +{ +#if 1 + u8 alive = uac_speaker_get_alive(); + if (alive) { + uac_dec->cnt++; + if (uac_dec->cnt > 5) { + if (!uac_dec->state) { +#if TCFG_DEC2TWS_ENABLE + if (uac_dec->pcm_dec.dec_no_out_sound) { + localtws_decoder_pause(1); + } +#endif + audio_mixer_ch_pause(&uac_dec->mix_ch, 1); + audio_decoder_resume_all(&decode_task); + uac_dec->state = 1; + } + } + } else { + if (uac_dec->cnt) { + uac_dec->cnt--; + } + if (uac_dec->state) { + uac_dec->state = 0; + uac_dec->cnt = 0; +#if TCFG_DEC2TWS_ENABLE + if (uac_dec->pcm_dec.dec_no_out_sound) { + localtws_decoder_pause(0); + } +#endif + audio_mixer_ch_pause(&uac_dec->mix_ch, 0); + audio_decoder_resume_all(&decode_task); + } + } + uac_speaker_set_alive(1); +#else + static u8 cnt = 0; + if (uac_speaker_stream_size(NULL) == 0) { + if (cnt < 20) { + cnt++; + } + if (cnt == 15) { +#if TCFG_DEC2TWS_ENABLE + if (uac_dec->pcm_dec.dec_no_out_sound) { + localtws_decoder_pause(1); + } +#endif + audio_mixer_ch_pause(&uac_dec->mix_ch, 1); + audio_decoder_resume_all(&decode_task); + } + } else { + if (cnt > 14) { +#if TCFG_DEC2TWS_ENABLE + if (uac_dec->pcm_dec.dec_no_out_sound) { + localtws_decoder_pause(0); + } +#endif + audio_mixer_ch_pause(&uac_dec->mix_ch, 0); + audio_decoder_resume_all(&decode_task); + } + cnt = 0; + } +#endif +} + +void pc_rrrl_output_enable(u8 onoff) +{ + struct uac_dec_hdl *dec = uac_dec; + if (dec) { + dec->rrrl_output_en = onoff; +#ifdef CONFIG_MIXER_CYCLIC + if (dec->rrrl_output_en) { + printf("1111111\n"); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 0, BIT(0) | BIT(2) | BIT(3)); //R -> DFR DRR并且RRRL左右合并 + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 1, BIT(1) | BIT(2) | BIT(3)); //R -> DFL DRL并且RRRL左右合并 + } else { + printf("222222\n"); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 0, BIT(0));//R -> DFR DRR + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 1, BIT(1));//R -> DFL DRL + } +#endif + } +} + +u8 pc_rrrl_output_enable_status(void) +{ + struct uac_dec_hdl *dec = uac_dec; + if (dec) { + return dec->rrrl_output_en; + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 计算pc输入采样率 + @param + @return 采样率 + @note +*/ +/*----------------------------------------------------------------------------*/ + +#if PC_SYNC_BY_DAC_HRP + +#include "media/includes.h" +extern struct audio_dac_hdl dac_hdl; +/* extern int audio_dac_get_hrp(struct audio_dac_hdl *dac); */ +u32 in_points = 0; +u32 out_points = 0; +u32 last_hrp = 0; +u8 dac_start_flag = 0; +int sample_rate_set = 0; +u16 usb_icnt = 0; + +#endif // PC_SYNC_BY_DAC_HRP + +static int audio_pc_input_sample_rate(void *priv) +{ + struct uac_dec_hdl *dec = (struct uac_dec_hdl *)priv; + int sample_rate = uac_speaker_stream_sample_rate(); + +#if PC_SYNC_BY_DAC_HRP + + if (sample_rate_set == 0) { + sample_rate_set = sample_rate; + } + sample_rate = sample_rate_set; + return sample_rate; + +#endif // PC_SYNC_BY_DAC_HRP + + int buf_size = uac_speaker_stream_size(); +#if TCFG_PCM_ENC2TWS_ENABLE + if (dec->pcm_dec.dec_no_out_sound) { + /*TWS的上限在uac输入buffer,下限在tws push buffer*/ + if (buf_size >= uac_speaker_stream_length() / 2) { + sample_rate += (sample_rate * 5 / 10000); + } else if (tws_api_local_media_trans_check_ready_total() < 1024) { + sample_rate -= (sample_rate * 5 / 10000); + } + return sample_rate; + } +#endif + +#if(TCFG_CLOCK_SYS_SRC==SYS_CLOCK_INPUT_PLL_RCL) + if (buf_size >= (uac_speaker_stream_length() * 3 / 4)) { + sample_rate += (sample_rate * 40 / 10000); + } + if (buf_size <= (uac_speaker_stream_length() / 4)) { + sample_rate -= (sample_rate * 40 / 10000); + } +#else + if (buf_size >= (uac_speaker_stream_length() * 3 / 5)) { + sample_rate += (sample_rate * 20 / 10000); + } + if (buf_size <= (uac_speaker_stream_length() * 2 / 5)) { + sample_rate -= (sample_rate * 20 / 10000); + } +#endif + return sample_rate; +} + +/*----------------------------------------------------------------------------*/ +/**@brief uac解码开始 + @param + @return 0:成功 + @return 非0:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int uac_audio_start(void) +{ + int err; + struct uac_dec_hdl *dec = uac_dec; + struct audio_mixer *p_mixer = &mixer; + + if (!uac_dec) { + return -EINVAL; + } + + // 打开pcm解码器 + err = pcm_decoder_open(&dec->pcm_dec, &decode_task); + if (err) { + goto __err1; + } + + pcm_decoder_set_event_handler(&dec->pcm_dec, uac_dec_event_handler, dec->id); + pcm_decoder_set_read_data(&dec->pcm_dec, uac_speaker_read, NULL); + + +#if TCFG_PCM_ENC2TWS_ENABLE + { + // localtws使用sbc等编码转发 + struct audio_fmt enc_f; + memcpy(&enc_f, &dec->pcm_dec.decoder.fmt, sizeof(struct audio_fmt)); + enc_f.coding_type = AUDIO_CODING_SBC; + if (dec->pcm_dec.ch_num == 2) { // 如果是双声道数据,localtws在解码时才变成对应声道 + enc_f.channel = 2; + } + int ret = localtws_enc_api_open(&enc_f, LOCALTWS_ENC_FLAG_STREAM); + if (ret == true) { + dec->pcm_dec.dec_no_out_sound = 1; + // 重定向mixer + p_mixer = &g_localtws.mixer; + // 关闭资源等待。最终会在localtws解码处等待 + audio_decoder_task_del_wait(&decode_task, &dec->wait); + if (dec->pcm_dec.output_ch_num != enc_f.channel) { + dec->pcm_dec.output_ch_num = dec->pcm_dec.decoder.fmt.channel = enc_f.channel; + if (enc_f.channel == 2) { + dec->pcm_dec.output_ch_type = AUDIO_CH_LR; + } else { + dec->pcm_dec.output_ch_type = AUDIO_CH_DIFF; + } + } + } + } +#endif + + if (!dec->pcm_dec.dec_no_out_sound) { + audio_mode_main_dec_open(AUDIO_MODE_MAIN_STATE_DEC_PC); + } + + // 设置叠加功能 + audio_mixer_ch_open_head(&dec->mix_ch, p_mixer); + +#ifdef CONFIG_MIXER_CYCLIC +#if (SOUNDCARD_ENABLE) + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 0, BIT(0) | BIT(2) | BIT(3)); //R -> DFR DRR + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 1, BIT(1) | BIT(2) | BIT(3)); //R -> DFL DRL + dec->rrrl_output_en = 1; +#endif/*SOUNDCARD_ENABLE*/ +#endif/*CONFIG_MIXER_CYCLIC*/ + + +#if 0 + if (dec->pcm_dec.dec_no_out_sound) { + // 自动变采样 + audio_mixer_ch_set_src(&dec->mix_ch, 1, 0); + } else { + // 根据buf数据量动态变采样 + struct audio_mixer_ch_sync_info info = {0}; +#if(TCFG_CLOCK_SYS_SRC==SYS_CLOCK_INPUT_PLL_RCL) + info.max_step = 500; + info.inc_step = 10; + info.dec_step = 10; +#endif + info.priv = dec; + info.get_total = uac_dec_get_total; + info.get_size = uac_dec_get_size; + audio_mixer_ch_set_sync(&dec->mix_ch, &info, 1, 1); + } +#else + audio_mixer_ch_follow_resample_enable(&dec->mix_ch, dec, audio_pc_input_sample_rate); +#endif + + /* audio_mixer_ch_set_no_wait(&dec->mix_ch, 1, 10); // 超时自动丢数 */ + +#if AUDIO_SURROUND_CONFIG + //环绕音效 + dec->surround = surround_open_demo(AEID_MUSIC_SURROUND, dec->pcm_dec.output_ch_type); +#endif + + +#if AUDIO_VBASS_CONFIG + dec->vbass_prev_gain = audio_gain_open_demo(AEID_MUSIC_VBASS_PREV_GAIN, dec->pcm_dec.output_ch_num); + //虚拟低音 + dec->vbass = audio_vbass_open_demo(AEID_MUSIC_VBASS, dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num); +#endif + + dec->high_bass = high_bass_eq_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num); + dec->hb_drc = high_bass_drc_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num); + if (dec->hb_drc && dec->hb_drc->run32bit) { + dec->hb_convert = convet_data_open(0, 512); + } + +#if TCFG_EQ_ENABLE && TCFG_PC_MODE_EQ_ENABLE + dec->eq = music_eq_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);// eq +#if TCFG_DRC_ENABLE && TCFG_PC_MODE_DRC_ENABLE + dec->drc = music_drc_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);//drc +#endif/*TCFG_PC_MODE_DRC_ENABLE*/ + if (dec->eq && dec->eq->out_32bit) { + dec->convert = convet_data_open(0, 512); + } + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + dec->eq2 = music_eq2_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);// eq + dec->dy_eq = audio_dynamic_eq_ctrl_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);//动态eq + dec->convert2 = convet_data_open(0, 512); +#endif/*TCFG_DYNAMIC_EQ_ENABLE*/ + dec->gain = audio_gain_open_demo(AEID_MUSIC_GAIN, dec->pcm_dec.output_ch_num); +#endif/*TCFG_PC_MODE_EQ_ENABLE*/ + +#if TCFG_EQ_DIVIDE_ENABLE + dec->eq_rl_rr = music_eq_rl_rr_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);// eq +#if TCFG_DRC_ENABLE && TCFG_BT_MUSIC_DRC_ENABLE + dec->drc_rl_rr = music_drc_rl_rr_open(dec->pcm_dec.sample_rate, dec->pcm_dec.output_ch_num);//drc +#endif + if (dec->eq_rl_rr && dec->eq_rl_rr->out_32bit) { + dec->convert_rl_rr = convet_data_open(0, 512); + } + +#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) && SOUND_TRACK_2_P_X_CH_CONFIG +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + dec->rl_rr_mix = stream_entry_open(NULL, stream_rl_rr_mix_data_handler, 0); +#endif +#endif + dec->gain_rl_rr = audio_gain_open_demo(AEID_MUSIC_RL_GAIN, dec->pcm_dec.output_ch_num); + + if (dec->eq_rl_rr) { + audio_vocal_tract_open(&dec->vocal_tract, AUDIO_SYNTHESIS_LEN); + { + u8 entry_cnt = 0; + struct audio_stream_entry *entries[8] = {NULL}; + entries[entry_cnt++] = &dec->vocal_tract.entry; + entries[entry_cnt++] = &dec->mix_ch.entry; + dec->vocal_tract.stream = audio_stream_open(&dec->vocal_tract, audio_vocal_tract_stream_resume); + audio_stream_add_list(dec->vocal_tract.stream, entries, entry_cnt); + } + audio_vocal_tract_synthesis_open(&dec->synthesis_ch_fl_fr, &dec->vocal_tract, FL_FR); + audio_vocal_tract_synthesis_open(&dec->synthesis_ch_rl_rr, &dec->vocal_tract, RL_RR); + } else { + dec->ch_switch = channel_switch_open(AUDIO_CH_QUAD, AUDIO_SYNTHESIS_LEN / 2); + } +#ifdef CONFIG_MIXER_CYCLIC + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 0, BIT(0)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 1, BIT(1)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 2, BIT(2)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 3, BIT(3)); +#endif + +#endif + + // 数据流串联 + struct audio_stream_entry *entries[32] = {NULL}; + u8 entry_cnt = 0; + u8 rl_rr_entry_start = 0; + entries[entry_cnt++] = &dec->pcm_dec.decoder.entry; +#if AUDIO_SURROUND_CONFIG + if (dec->surround) { + entries[entry_cnt++] = &dec->surround->entry; + } +#endif + +#if AUDIO_VBASS_CONFIG + if (dec->vbass_prev_gain) { + entries[entry_cnt++] = &dec->vbass_prev_gain->entry; + } + if (dec->vbass) { + entries[entry_cnt++] = &dec->vbass->entry; + } +#endif + + if (dec->high_bass) { //高低音 + entries[entry_cnt++] = &dec->high_bass->entry; + } + if (dec->hb_drc) { //高低音后drc + entries[entry_cnt++] = &dec->hb_drc->entry; + if (dec->hb_convert) { + entries[entry_cnt++] = &dec->hb_convert->entry; + } + } + + rl_rr_entry_start = entry_cnt - 1;//记录eq的上一个节点 +#if TCFG_EQ_ENABLE && TCFG_PC_MODE_EQ_ENABLE + if (dec->eq) { + entries[entry_cnt++] = &dec->eq->entry; + if (dec->drc) { + entries[entry_cnt++] = &dec->drc->entry; + } + if (dec->convert) { + entries[entry_cnt++] = &dec->convert->entry; + } +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + if (dec->eq2) { + entries[entry_cnt++] = &dec->eq2->entry; + } + if (dec->dy_eq && dec->dy_eq->dy_eq) { + entries[entry_cnt++] = &dec->dy_eq->dy_eq->entry; + } + if (dec->convert2) { + entries[entry_cnt++] = &dec->convert2->entry; + } +#endif + if (dec->gain) { + entries[entry_cnt++] = &dec->gain->entry; + } + + } +#endif +#if SYS_DIGVOL_GROUP_EN + void *dvol_entry = sys_digvol_group_ch_open("music_pc", -1, NULL); + entries[entry_cnt++] = dvol_entry; +#endif // SYS_DIGVOL_GROUP_EN + + +#if TCFG_EQ_DIVIDE_ENABLE + if (dec->eq_rl_rr) { + entries[entry_cnt++] = &dec->synthesis_ch_fl_fr.entry;//四声道eq独立时,该节点后不接节点 + } else { + if (dec->ch_switch) { + entries[entry_cnt++] = &dec->ch_switch->entry; + } + entries[entry_cnt++] = &dec->mix_ch.entry; + } +#else + entries[entry_cnt++] = &dec->mix_ch.entry; +#endif + + // 创建数据流,把所有节点连接起来 + dec->stream = audio_stream_open(dec, uac_dec_out_stream_resume); + audio_stream_add_list(dec->stream, entries, entry_cnt); +#if TCFG_EQ_DIVIDE_ENABLE + struct audio_stream_entry *rl_rr_entries[16] = {NULL}; + entry_cnt = 0; + if (dec->eq_rl_rr) { //接在eq_drc的上一个节点 + rl_rr_entries[entry_cnt++] = entries[rl_rr_entry_start]; + rl_rr_entries[entry_cnt++] = &dec->eq_rl_rr->entry; + if (dec->drc_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->drc_rl_rr->entry; + } + if (dec->convert_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->convert_rl_rr->entry; + } +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + if (dec->rl_rr_mix) { + rl_rr_entries[entry_cnt++] = &dec->rl_rr_mix->entry; + } +#endif + if (dec->gain_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->gain_rl_rr->entry; + } + + rl_rr_entries[entry_cnt++] = &dec->synthesis_ch_rl_rr.entry;//必须是最后一个 + for (int i = 0; i < (entry_cnt - 1); i++) { + audio_stream_add_entry(rl_rr_entries[i], rl_rr_entries[i + 1]); + } + } +#endif + + // 设置音量 + audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); + u16 l_volume, r_volume; + uac_get_cur_vol(0, &l_volume, &r_volume); + u8 vol = uac_vol_switch(l_volume); + app_audio_set_volume(APP_AUDIO_STATE_MUSIC, vol, 0); +#if (TCFG_DEC2TWS_ENABLE) + bt_tws_sync_volume(); +#endif + + // 开始解码 + dec->start = 1; + err = audio_decoder_start(&dec->pcm_dec.decoder); + if (err) { + goto __err3; + } + + dec->state = 0; + dec->cnt = 0; + dec->check_data_timer = sys_hi_timer_add(NULL, audio_pc_check_timer, 10); + +#if PC_SYNC_BY_DAC_HRP + + in_points = 0; + out_points = 0; + last_hrp = 0; + dac_start_flag = 0; + sample_rate_set = 0; + usb_icnt = 0; + +#endif // PC_SYNC_BY_DAC_HRP + + clock_set_cur(); + return 0; + +__err3: + dec->start = 0; + + +#if AUDIO_SURROUND_CONFIG + surround_close_demo(dec->surround); +#endif + + + +#if AUDIO_VBASS_CONFIG + audio_gain_close_demo(dec->vbass_prev_gain); + audio_vbass_close_demo(dec->vbass); +#endif + high_bass_eq_close(dec->high_bass); + high_bass_drc_close(dec->hb_drc); + convet_data_close(dec->hb_convert); + +#if TCFG_EQ_ENABLE && TCFG_PC_MODE_EQ_ENABLE + music_eq_close(dec->eq); +#if TCFG_DRC_ENABLE && TCFG_PC_MODE_DRC_ENABLE + music_drc_close(dec->drc); +#endif + convet_data_close(dec->convert); +#endif + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + music_eq2_close(dec->eq2); + audio_dynamic_eq_ctrl_close(dec->dy_eq); + convet_data_close(dec->convert2); + audio_gain_close_demo(dec->gain); +#endif + +#if TCFG_EQ_DIVIDE_ENABLE + music_eq_rl_rr_close(dec->eq_rl_rr); + music_drc_rl_rr_close(dec->drc_rl_rr); + convet_data_close(dec->convert_rl_rr); +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + stream_entry_close(&dec->rl_rr_mix); +#endif + audio_gain_close_demo(dec->gain_rl_rr); + + audio_vocal_tract_synthesis_close(&dec->synthesis_ch_fl_fr); + audio_vocal_tract_synthesis_close(&dec->synthesis_ch_rl_rr); + audio_vocal_tract_close(&dec->vocal_tract); + channel_switch_close(&dec->ch_switch); +#endif + audio_mixer_ch_close(&dec->mix_ch); +#if TCFG_PCM_ENC2TWS_ENABLE + if (dec->pcm_dec.dec_no_out_sound) { + dec->pcm_dec.dec_no_out_sound = 0; + localtws_enc_api_close(); + } +#endif +#if SYS_DIGVOL_GROUP_EN + sys_digvol_group_ch_close("music_pc"); +#endif // SYS_DIGVOL_GROUP_EN + + + if (dec->stream) { + audio_stream_close(dec->stream); + dec->stream = NULL; + } + + pcm_decoder_close(&dec->pcm_dec); +__err1: + uac_dec_relaese(); + __bt_emitter_pp(1); + return err; +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief uac解码资源等待 + @param *wait: 句柄 + @param event: 事件 + @return 0:成功 + @note 用于多解码打断处理 +*/ +/*----------------------------------------------------------------------------*/ +static int uac_wait_res_handler(struct audio_res_wait *wait, int event) +{ + int err = 0; + + if (event == AUDIO_RES_GET) { + // 启动解码 + err = uac_audio_start(); + } else if (event == AUDIO_RES_PUT) { + // 被打断 + uac_audio_close(); + } + + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief uac收到数据处理 + @param event: 事件 + @param *data: 数据 + @param len: 数据长度 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void uac_speaker_stream_rx_handler(int event, void *data, int len) +{ + +#if PC_SYNC_BY_DAC_HRP + + u32 hrp = audio_dac_get_hrp(&dac_hdl); + /* printf("\nl:%d h:%d\n", last_hrp, hrp); */ + + /* int sample_rate = uac_speaker_stream_sample_rate(); */ + int sample_rate = SPK_AUDIO_RATE; + + if (sample_rate_set == 0) { + sample_rate_set = sample_rate; + } + + in_points += len / 2 / 2; + + if (hrp >= last_hrp) { + out_points += hrp - last_hrp; + } else { + out_points += hrp + JL_AUDIO->DAC_LEN - last_hrp; + } + last_hrp = hrp; + + if ((!dac_start_flag) && (out_points != 0)) { + dac_start_flag = 1; + in_points = 0; + out_points = 0; + } + + if (dac_start_flag) { + if (out_points) { + usb_icnt++; + if (usb_icnt == 1000) { + usb_icnt = 0; + sample_rate_set = (int)((float)sample_rate * ((float)in_points / (float)out_points)); + int buf_size = uac_speaker_stream_size(); + + if (buf_size >= (uac_speaker_stream_length() * 3 / 4)) { + sample_rate_set += 1; + } else if (buf_size <= (uac_speaker_stream_length() / 4)) { + sample_rate_set -= 1; + } + + /* printf(">> in:%d out:%d sr:%d b:%d\n", in_points, out_points, sample_rate_set, buf_size); */ + in_points = 0; + out_points = 0; + } + } + } + +#endif // PC_SYNC_BY_DAC_HRP + + if (uac_speaker_stream_size() >= (uac_speaker_stream_length() * 50 / 100)) { + /* putchar('A'); */ + uac_dec_resume(); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 打开pc解码 + @param *_info: pc信息 + @return 0:成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int usb_audio_play_open(void *_info) +{ + struct uac_dec_hdl *dec; + + if (uac_dec) { + return 0; + } + + dec = zalloc(sizeof(*dec)); + if (!dec) { + return -ENOMEM; + } + + uac_dec = dec; + +#if TCFG_DEC2TWS_ENABLE + // 设置localtws重播接口 + localtws_globle_set_dec_restart(uac_dec_push_restart); +#endif + + dec->in_info = (u32)_info; + dec->pcm_dec.sample_rate = (u32)_info & 0xFFFFFF; + dec->pcm_dec.ch_num = (u32)_info >> 24; + dec->pcm_dec.output_ch_num = audio_output_channel_num(); + dec->pcm_dec.output_ch_type = audio_output_channel_type(); + printf("usb_audio_play_open sr:%d ch:%d out ch:[%d]\n", dec->pcm_dec.sample_rate, dec->pcm_dec.ch_num, dec->pcm_dec.output_ch_num); + set_uac_speaker_rx_handler(dec, uac_speaker_stream_rx_handler); + dec->wait.priority = 2; + dec->wait.preemption = 0; + dec->wait.snatch_same_prio = 1; +#if SOUNDCARD_ENABLE + dec->wait.protect = 1; +#endif + dec->wait.handler = uac_wait_res_handler; + audio_decoder_task_add_wait(&decode_task, &dec->wait); + + clock_add(DEC_PCM_CLK); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭pc解码 + @param *arg: 参数 + @return 0:成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int usb_audio_play_close(void *arg) +{ + int err = 0; + + if (!uac_dec) { + return 0; + } + + if (uac_dec->start) { + uac_audio_close(); + } + + uac_dec_relaese(); + + return 0; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief pc解码重新开始 + @param id: 文件解码id + @return 0:成功 + @return 非0:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int uac_dec_restart(int id) +{ + if ((!uac_dec) || (id != uac_dec->id)) { + return -1; + } + int _info = uac_dec->in_info;//(uac_dec->pcm_dec.ch_num << 24) | uac_dec->pcm_dec.sample_rate; + usb_audio_play_close(NULL); + int err = usb_audio_play_open((void *)_info); + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 推送pc解码重新开始命令 + @param + @return true:成功 + @return false:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int uac_dec_push_restart(void) +{ + if (!uac_dec) { + return false; + } + int argv[3]; + argv[0] = (int)uac_dec_restart; + argv[1] = 1; + argv[2] = (int)uac_dec->id; + os_taskq_post_type(os_current_task(), Q_CALLBACK, ARRAY_SIZE(argv), argv); + return true; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief pc事件处理 + @param event: 事件 + @param value: 参数 + @return 0:成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int usb_device_event_handler(u8 event, int value) +{ + switch (event) { + case USB_AUDIO_PLAY_OPEN: + /*tone_play_stop();*/ + usb_audio_play_open((void *)value); + break; + case USB_AUDIO_PLAY_CLOSE: + usb_audio_play_close((void *)value); + break; + case USB_AUDIO_MIC_OPEN: + usb_audio_mic_open((void *)value); + break; + case USB_AUDIO_MIC_CLOSE: + usb_audio_mic_close((void *)value); + break; + case USB_AUDIO_SET_MIC_VOL: + usb_audio_mic_set_gain(value); + break; + case USB_AUDIO_SET_PLAY_VOL: + value = uac_vol_switch(value & 0xffff); //left ch volume + app_audio_set_volume(APP_AUDIO_STATE_MUSIC, value, 1); +#if (TCFG_DEC2TWS_ENABLE) + bt_tws_sync_volume(); +#endif +#if TCFG_UI_ENABLE + u8 vol = app_audio_get_volume(APP_AUDIO_STATE_MUSIC); + UI_SHOW_MENU(MENU_MAIN_VOL, 1000, vol, NULL); +#endif //TCFG_UI_ENABLE + break; + default: + break; + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief pc系统事件处理 + @param *event: 事件 + @param *priv: 参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void usb_audio_event_handler(struct sys_event *event, void *priv) +{ + //log_d("usb device event : %d %x\n", event->u.dev.event, event->u.dev.value); + usb_device_event_handler(event->u.dev.event, event->u.dev.value); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 音频设备初始化 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +__attribute__((weak))int audio_dev_init() +{ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief usb音频初始化 + @param + @return 0:成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int usb_audio_demo_init(void) +{ + int err = 0; + + audio_dev_init(); + register_sys_event_handler(SYS_DEVICE_EVENT, DEVICE_EVENT_FROM_UAC, 2, + usb_audio_event_handler); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief usb音频退出 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void usb_audio_demo_exit(void) +{ + unregister_sys_event_handler(usb_audio_event_handler); + usb_audio_play_close(NULL); + usb_audio_mic_close(NULL); +} + +#endif /* TCFG_APP_PC_EN */ + diff --git a/cpu/br23/audio_dec/audio_dec_pc.h b/cpu/br23/audio_dec/audio_dec_pc.h new file mode 100644 index 0000000..d38c4a0 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_pc.h @@ -0,0 +1,16 @@ + +#ifndef _AUDIO_DEC_PC_H_ +#define _AUDIO_DEC_PC_H_ + +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "media/audio_decoder.h" + +// pc解码重新开始 +int uac_dec_restart(int magic); +// 推送pc解码重新开始命令 +int uac_dec_push_restart(void); + +#endif /* TCFG_APP_PC_EN */ + diff --git a/cpu/br23/audio_dec/audio_dec_record.c b/cpu/br23/audio_dec/audio_dec_record.c new file mode 100644 index 0000000..5fc4703 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_record.c @@ -0,0 +1,137 @@ +#include "system/includes.h" +#include "media/includes.h" +#include "tone_player.h" +#include "audio_config.h" +#include "app_main.h" +#include "clock_cfg.h" +#include "audio_dec.h" + +////////////////////////////////////////////////////////////////////////////// + +static FILE *record_file = NULL; + +////////////////////////////////////////////////////////////////////////////// + +extern int last_enc_file_path_get(char path[64]); + +////////////////////////////////////////////////////////////////////////////// +/*----------------------------------------------------------------------------*/ +/**@brief 关闭录音文件播放 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void record_file_close(void) +{ + file_dec_close(); + if (record_file) { + fclose(record_file); + record_file = NULL; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 录音播放事件回调 + @param *priv: 私有句柄 + @param argc: 参数个数 + @param *argv: 参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void record_file_play_evt_handler(void *priv, int argc, int *argv) +{ + u8 event = (u8)argv[0]; + /* printf("fun = %s\n", __FUNCTION__); */ + if (event == AUDIO_DEC_EVENT_END) { + record_file_close(); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 录音文件播放 + @param + @return 0:成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int record_file_play(void) +{ + int ret; + record_file_close(); + + char path[64] = {0}; + ret = last_enc_file_path_get(path); + if (ret) { + return -1; + } + record_file = fopen(path, "r"); + if (!record_file) { + return -1; + } + ret = file_dec_create(NULL, record_file_play_evt_handler); + if (ret) { + return -1; + } + ret = file_dec_open(record_file, NULL); + return ret; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按照路径播放录音文件 + @param + @return 0:成功 + @note 针对特殊需求, 用户可以直接指定录音路径播放,盘符在路径中直接指定 +*/ +/*----------------------------------------------------------------------------*/ +int record_file_play_by_path(char *path) +{ + int ret; + record_file_close(); + + record_file = fopen(path, "r"); + if (!record_file) { + return -1; + } + ret = file_dec_create(NULL, record_file_play_evt_handler); + if (ret) { + return -1; + } + ret = file_dec_open(record_file, NULL); + return ret; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 获取录音播放总事件 + @param + @return 总时间 + @note +*/ +/*----------------------------------------------------------------------------*/ +int record_file_get_total_time(void) +{ + if (!record_file) { + return 0; + } + return file_dec_get_total_time(); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 获取录音播放当前时间 + @param + @return 当前时间 + @note +*/ +/*----------------------------------------------------------------------------*/ +int record_file_dec_get_cur_time(void) +{ + if (!record_file) { + return 0; + } + return file_dec_get_cur_time(); +} + + + diff --git a/cpu/br23/audio_dec/audio_dec_record.h b/cpu/br23/audio_dec/audio_dec_record.h new file mode 100644 index 0000000..48441fa --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_record.h @@ -0,0 +1,21 @@ +#ifndef _AUDIO_DEC_RECORD_H_ +#define _AUDIO_DEC_RECORD_H_ + +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "media/audio_decoder.h" + +// 录音文件播放 +int record_file_play(void); +// 指定路径播放录音文件 +int record_file_play_by_path(char *path); +// 关闭录音文件播放 +void record_file_close(void); +// 获取录音播放总事件 +int record_file_get_total_time(void); +// 获取录音播放当前时间 +int record_file_dec_get_cur_time(void); + +#endif /*_AUDIO_DEC_RECORD_H_*/ + diff --git a/cpu/br23/audio_dec/audio_dec_spdif.c b/cpu/br23/audio_dec/audio_dec_spdif.c new file mode 100644 index 0000000..f62ea53 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_spdif.c @@ -0,0 +1,980 @@ +/* + **************************************************************** + *File : audio_spdif.c + *Note : + * + **************************************************************** +*********************** spdif_dec ******************************/ +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "effectrs_sync.h" +#include "media/audio_eq_drc_apply.h" +#include "app_config.h" +#include "audio_config.h" +#include "audio_dec.h" +#include "app_config.h" +#include "app_main.h" +#include "audio_enc.h" +#include "clock_cfg.h" +#include "media/pcm_decoder.h" + +#if TCFG_SPDIF_ENABLE + +#define SPDIF_DEC_DATA_BUF_LEN 1024*4 +struct s_spdif_decode { + struct pcm_decoder pcm_dec; + struct file_decoder file_dec; + struct audio_stream *audio_stream; // 音频流 + struct audio_res_wait wait; + struct audio_mixer_ch mix_ch; + u32 coding_type; + struct audio_fmt fmt; + volatile u32 pcm_sr; + cbuffer_t dec_cbuf; + u8 dec_data_buf[SPDIF_DEC_DATA_BUF_LEN]; + u8 status; + +#if AUDIO_SURROUND_CONFIG + surround_hdl *surround; //环绕音效句柄 +#endif + + +#if AUDIO_VBASS_CONFIG + struct aud_gain_process *vbass_prev_gain; + vbass_hdl *vbass; //虚拟低音句柄 +#endif + + struct audio_eq *high_bass; + struct audio_drc *hb_drc;//高低音后的drc + struct convert_data *hb_convert; + + struct audio_eq *eq; //eq drc句柄 + struct audio_drc *drc; // drc句柄 + struct convert_data *convert; + struct audio_eq *eq2; //eq drc句柄 + struct dynamic_eq_hdl *dy_eq; + struct convert_data *convert2; + struct aud_gain_process *gain; + + +#if TCFG_EQ_DIVIDE_ENABLE + struct audio_eq *eq_rl_rr; //eq drc句柄 + struct audio_drc *drc_rl_rr; // drc句柄 + struct convert_data *convert_rl_rr; + struct __stream_entry *rl_rr_mix;//双声道相加除2处理 + struct aud_gain_process *gain_rl_rr; + + struct audio_vocal_tract vocal_tract;//声道合并目标句柄 + struct audio_vocal_tract_ch synthesis_ch_fl_fr;//声道合并句柄 + struct audio_vocal_tract_ch synthesis_ch_rl_rr;//声道合并句柄 + struct channel_switch *ch_switch;//声道变换 +#endif + +}; + +static void reset_pcm_sample_rate(u32 sr); +int spdif_dec_open(struct audio_fmt fmt); +void spdif_dec_close(void); + +struct audio_spdif_hdl spdif_slave_hdl; +struct s_spdif_decode *spdif_dec_hdl = NULL; + +int spdif_non_linear_packet(u16 *pkt, u16 pkt_len) +{ + enum IEC61937DataType data_type; + u16 search_index = 0; + int data_cp_begin_idx = 0; + int data_cp_len = 0; + u16 *data = pkt; + u16 *data_ptr = NULL; + int zero_cnt = 0; + u32 state = 0; + int pkt_size_bits, offset, skip_len; + if (spdif_slave_hdl.length_code > 0) { + if (spdif_slave_hdl.length_code >= SPDIF_DATA_DAM_LEN * 2) { + data_cp_begin_idx = 0; + data_cp_len = SPDIF_DATA_DAM_LEN * 2; + spdif_slave_hdl.length_code -= data_cp_len; + } else { + data_cp_begin_idx = 0; + data_cp_len = spdif_slave_hdl.length_code; + spdif_slave_hdl.length_code = 0; + } + //写入解码cbuf + /* int spdif_dec_write_data(s16 *data, int len) */ + spdif_dec_write_data(&data[data_cp_begin_idx], data_cp_len * 2); + if (spdif_slave_hdl.length_code != 0) { + return 0; + } else { + search_index = data_cp_len; + } + } + if (spdif_slave_hdl.find_sync_word != 0) { + printf("[last:%d,%x]", search_index, data[search_index]); + if (data[search_index] == SYNCWORD2) { + puts("3"); + } else { + puts("M"); + spdif_slave_hdl.find_sync_word = 0; + return -1; + } + } else { + while (search_index < pkt_len) { + if (data[search_index] == SYNCWORD1) { + spdif_slave_hdl.find_sync_word = 1; + } + if (++search_index >= pkt_len) { + return -1; + } + if (spdif_slave_hdl.find_sync_word) { + if ((data[search_index] == SYNCWORD2) && (data[search_index - 1] == SYNCWORD1)) { + break; + } else { + spdif_slave_hdl.find_sync_word = 0; + } + } + } + } + spdif_slave_hdl.find_sync_word = 0; + + data_type = data[++search_index]; + spdif_slave_hdl.decoder_type = data_type & 0xff; + pkt_size_bits = data[++search_index]; + spdif_slave_hdl.length_code = (pkt_size_bits >> 3) >> 1; //16bit + if (pkt_size_bits % 16) { + printf("packet not endinf at a 16-bit boundary %d-%d \n", pkt_size_bits, search_index); + for (int i = 0; i < pkt_len; i++) { + printf("%x ", data[i]); + } + } + ++search_index; + data_cp_len = pkt_len - search_index; + skip_len = 2048 - (spdif_slave_hdl.length_code << 1) - BURST_HEADER_SZIE; + if (data_cp_len) { + spdif_dec_write_data(&data[search_index], data_cp_len * 2); + data_cp_len = 0; + } + return 0; +} +void reset_data_buf(void) +{ + if (!spdif_dec_hdl) { + return; + } + cbuf_clear(&spdif_dec_hdl->dec_cbuf); +} + +#define SAMPLE_RATE_TABLE_SIZE 14 +static u8 old_samplerate_index = 6; /*位置记得要跟默认采样率对应*/ +u16 spdif_sample_rate_table[SAMPLE_RATE_TABLE_SIZE] = { + 80, + 110, + 160, + 221, + 240, + 320, + 441, + 480, + 504, + 640, + 882, + 960, + 1764, + 1920, +}; +#define SPDIF_DEFAULT_OUT_SAMPLE_RATE 44100 +static u32 cal_samplerate(void) +{ + static u32 pre_sr_cnt = 0; + static u32 sr_cnt = 0; + sr_cnt = JL_SS->SR_CNT; + u8 search_index = 0, i = 0; + u32 tick_result = 0 ; + tick_result = (((clk_get("lsb") / 100 * SPDIF_DATA_DAM_LEN)) / sr_cnt); + for (i = 0; i < SAMPLE_RATE_TABLE_SIZE; i++) { + if ((tick_result > (spdif_sample_rate_table[i] - 20)) && (tick_result < (spdif_sample_rate_table[i] + 20))) { + search_index = i; + } + } + if ((search_index != 0) && (old_samplerate_index != search_index)) { + printf("\n\n spdif SET src param %d %d--- \n\n", spdif_sample_rate_table[search_index], tick_result); + reset_data_buf(); + reset_pcm_sample_rate(spdif_sample_rate_table[search_index] * 100); + old_samplerate_index = search_index; + } + return 0; +} + +___interrupt +static void spdif_isr_handler() +{ + int index = 0; + s32 *ptr; + u8 *info_ptr = NULL; + s16 data_ptr[SPDIF_DATA_DAM_LEN * SPDIF_CHANNEL_NUMBER]; + u16 *u_data_ptr = (u16 *)data_ptr; + /* putchar('A'); */ + if (I_PND) { //information pending + I_PND_CLR; + index = !(USING_INF_BUF_INDEX >> 13); + info_ptr = (u8 *) &spdif_slave_hdl.p_spdif_info_buf[index]; + for (int i = 0; i < SPDIF_INFO_LEN; i++) { + if (!(info_ptr[0]&INFO_VALIDITY_BIT)) { + break; + } + spdif_slave_hdl.validity_bit_flag = 1; + } + } + + if (ERROR_VALUE) { // some error flag + if (ERROR_VALUE & (BIT(8) | BIT(9))) {//块/帧错误 + memset(&spdif_slave_hdl.p_spdif_data_buf[0], 0x0, SPDIF_DATA_DAM_LEN * SPDIF_CHANNEL_NUMBER); + memset(&spdif_slave_hdl.p_spdif_data_buf[1], 0x0, SPDIF_DATA_DAM_LEN * SPDIF_CHANNEL_NUMBER); + } + if (JL_SS->CON & BIT(11)) {//电平长度接收错误 + //模块复位 + putchar('E'); + audio_spdif_slave_close(&spdif_slave_hdl); + spdif_slave_hdl.error_flag = 1; + ERR_CLR; + return; + } + ERR_CLR; + } + if (spdif_slave_hdl.error_flag) { + return; + } + if (D_PND) { //data pending + D_PND_CLR; + if (spdif_slave_hdl.validity_bit_flag) { //DST + spdif_slave_hdl.validity_bit_flag = 0; + index = !(USING_BUF_INDEX >> 12); + ptr = (s32 *)spdif_slave_hdl.p_spdif_data_buf[index]; + for (int i = 0; i < SPDIF_DATA_DAM_LEN * 2; i += 2) { + u_data_ptr[i] = (u16)(ptr[i] >> 8); + u_data_ptr[i + 1] = (u16)(ptr[i + 1] >> 8); + } + if (!spdif_dec_hdl) { +#if 0 + struct audio_fmt fmt; + fmt.channel = 2; + fmt.coding_type = AUDIO_CODING_DTS; + fmt.sample_rate = SPDIF_DEFAULT_OUT_SAMPLE_RATE; + spdif_dec_open(fmt); +#endif + audio_spdif_slave_close(&spdif_slave_hdl); + spdif_slave_hdl.error_flag = 2; + + } else if (spdif_dec_hdl->fmt.coding_type != AUDIO_CODING_DTS) { + putchar('d'); + //模块复位 + audio_spdif_slave_close(&spdif_slave_hdl); + spdif_slave_hdl.error_flag = 2; + return; + } + if (spdif_dec_hdl && (spdif_slave_hdl.status == SPDIF_STATE_START)) { + spdif_non_linear_packet(u_data_ptr, SPDIF_DATA_DAM_LEN * 2); + } + + /* putchar('D'); */ + return; + } else { //PCM + if (!spdif_dec_hdl) { +#if 0 + putchar('p'); + struct audio_fmt fmt; + fmt.channel = 2; + fmt.coding_type = AUDIO_CODING_PCM; + fmt.sample_rate = SPDIF_DEFAULT_OUT_SAMPLE_RATE; + spdif_dec_open(fmt); +#endif + audio_spdif_slave_close(&spdif_slave_hdl); + spdif_slave_hdl.error_flag = 1; + + return; + } else if (spdif_dec_hdl->fmt.coding_type != AUDIO_CODING_PCM) { + putchar('p'); + audio_spdif_slave_close(&spdif_slave_hdl); + spdif_slave_hdl.error_flag = 1; + return; + } + + /* putchar('D'); */ + cal_samplerate(); + index = !(USING_BUF_INDEX >> 12); + ptr = (s32 *) spdif_slave_hdl.p_spdif_data_buf[index]; + for (int i = 0; i < SPDIF_DATA_DAM_LEN * 2; i += 2) { + data_ptr[i] = (s16)(ptr[i] >> 8); + data_ptr[i + 1] = (s16)(ptr[i + 1] >> 8); + } + if ((spdif_dec_hdl) && (spdif_slave_hdl.status == SPDIF_STATE_START)) { + int wlen = spdif_dec_write_data(data_ptr, SPDIF_DATA_DAM_LEN * SPDIF_CHANNEL_NUMBER * 2); + if (wlen == 0) { + /* printf(" wlen = 0"); */ + } + } + memset(spdif_slave_hdl.p_spdif_data_buf[index], 0, SPDIF_DATA_DAM_LEN * SPDIF_CHANNEL_NUMBER * 2); + } + } + if (CSB_PND) { + CSB_PND_CLR; + } + +} + +// 写入spdif数据 +/* int spdif_dec_write_data(s16 *data, int len) */ +int spdif_dec_write_data(void *data, int len) +{ + if (!spdif_dec_hdl) { + return 0; + } + u16 wlen = cbuf_write(&spdif_dec_hdl->dec_cbuf, data, len); + if (wlen) { + audio_decoder_resume(&spdif_dec_hdl->pcm_dec.decoder); + } + /* printf("wl:%d ", wlen); */ + return wlen; +} + +static void spdif_dec_release(void) +{ + audio_decoder_task_del_wait(&decode_task, &spdif_dec_hdl->wait); + if (spdif_dec_hdl) { + clock_remove(SPDIF_CLK); + free(spdif_dec_hdl); + spdif_dec_hdl = NULL; + } +} +static void file_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ + switch (argv[0]) { + case AUDIO_DEC_EVENT_END: + printf("\n--func=%s\n", __FUNCTION__); + spdif_dec_close(); + break; + } +} +/*----------------------------------------------------------------------------*/ +/**@brief 文件指针定位 + @param *decoder: 解码器句柄 + @param offset: 定位偏移 + @param seek_mode: 定位类型 + @return 0:成功 + @return 非0:错误 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int spdif_file_seek(struct audio_decoder *decoder, u32 offset, int seek_mode) +{ + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 读取文件数据 + @param *decoder: 解码器句柄 + @param *buf: 数据 + @param len: 数据长度 + @return >=0:读到的数据长度 + @return <0:错误 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int spdif_file_read(struct audio_decoder *decoder, void *buf, u32 len) +{ + int rlen; + rlen = cbuf_read(&spdif_dec_hdl->dec_cbuf, buf, len); + return rlen; +} + +static const struct audio_dec_input file_input = { + .coding_type = AUDIO_CODING_DTS, + .data_type = AUDIO_INPUT_FILE, + .ops = { + .file = { + .fread = spdif_file_read, + .fseek = spdif_file_seek, + } + } +}; + + +static int spdif_dec_read(void *hdl, void *buf, int len) +{ + int rlen = 0; + rlen = cbuf_read(&spdif_dec_hdl->dec_cbuf, buf, len); + /* printf("rlen:%d\n",rlen); */ + return rlen; +} + +int spdif_data_size(void *hdl) +{ + struct s_spdif_decode *spdif_hdl = (struct s_spdif_decode *)hdl; + return cbuf_get_data_size(&spdif_hdl->dec_cbuf); +} + +int spdif_data_total(void *hdl) +{ + struct s_spdif_decode *spdif_hdl = (struct s_spdif_decode *)hdl; + return spdif_hdl->dec_cbuf.total_len; +} +static void reset_pcm_sample_rate(u32 sr) +{ + spdif_dec_hdl->pcm_sr = sr; +} +static u32 get_pcm_sample_rate(void) +{ + /* printf("[%d]",spdif_dec_hdl->pcm_sr); */ + return spdif_dec_hdl->pcm_sr; +} +/*----------------------------------------------------------------------------*/ +/**@brief pcm解码数据输出 + @param *entry: 音频流句柄 + @param *in: 输入信息 + @param *out: 输出信息 + @return 输出长度 + @note *out未使用 +*/ +/*----------------------------------------------------------------------------*/ +static int pcm_dec_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + struct audio_decoder *decoder = container_of(entry, struct audio_decoder, entry); + struct pcm_decoder *pcm_dec = container_of(decoder, struct pcm_decoder, decoder); + if (in->offset == 0) { + in->sample_rate = get_pcm_sample_rate(); + } + audio_stream_run(&decoder->entry, in); + return decoder->process_len; +} +static void pcm_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ +} +/*----------------------------------------------------------------------------*/ +/**@brief pcm解码数据流激活 + @param *p: 私有句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void dec_out_stream_resume(void *p) +{ + struct s_spdif_decode *dec = (struct s_spdif_decode *)p; + + audio_decoder_resume(&dec->pcm_dec.decoder); +} + + +int spdif_dec_start(void) +{ + int err = 0; + u8 ch_num = 0; + struct audio_fmt f; + if (!spdif_dec_hdl) { + return -EINVAL; + } + struct s_spdif_decode *dec = spdif_dec_hdl; + if (dec->fmt.coding_type == AUDIO_CODING_DTS) { + puts("dts \n");//DTS未测试 + return -EINVAL; + err = file_decoder_open(&dec->file_dec, &file_input, &decode_task, NULL, 0); + if (err) { + return err; + } + file_decoder_set_event_handler(&dec->file_dec, file_dec_event_handler, 0); + + } else { + puts("pcm \n"); + err = pcm_decoder_open(&dec->pcm_dec, &decode_task); + if (err) { + return err; + } + pcm_decoder_set_event_handler(&dec->pcm_dec, pcm_dec_event_handler, 0); + pcm_decoder_set_read_data(&dec->pcm_dec, spdif_dec_read, dec); + pcm_decoder_set_data_handler(&dec->pcm_dec, pcm_dec_data_handler); + } + printf("\n--func=%s\n", __FUNCTION__); + + audio_mode_main_dec_open(AUDIO_MODE_MAIN_STATE_DEC_SPDIF); + + audio_mixer_ch_open_head(&dec->mix_ch, &mixer); + audio_mixer_ch_set_no_wait(&dec->mix_ch, 1, 10); // 超时自动丢数 + /* audio_mixer_ch_set_src(&dec->mix_ch, 1, 0); */ +#if 1 + struct audio_mixer_ch_sync_info info = {0}; + info.priv = dec; + info.get_total = spdif_data_total; + info.get_size = spdif_data_size; + audio_mixer_ch_set_sync(&dec->mix_ch, &info, 1, 1); +#endif + + ch_num = audio_output_channel_num(); + u16 sample_rate = dec->fmt.sample_rate; + +#if AUDIO_SURROUND_CONFIG + //环绕音效 + dec->surround = surround_open_demo(AEID_MUSIC_SURROUND, dec->pcm_dec.output_ch_type); +#endif + + +#if AUDIO_VBASS_CONFIG + dec->vbass_prev_gain = audio_gain_open_demo(AEID_MUSIC_VBASS_PREV_GAIN, ch_num); + //虚拟低音 + dec->vbass = audio_vbass_open_demo(AEID_MUSIC_VBASS, sample_rate, ch_num); +#endif + + dec->high_bass = high_bass_eq_open(sample_rate, ch_num); + dec->hb_drc = high_bass_drc_open(sample_rate, ch_num); + if (dec->hb_drc && dec->hb_drc->run32bit) { + dec->hb_convert = convet_data_open(0, 512); + } + +#if TCFG_EQ_ENABLE && TCFG_SPDIF_MODE_EQ_ENABLE + dec->eq = music_eq_open(sample_rate, ch_num);// eq +#if TCFG_DRC_ENABLE && TCFG_SPDIF_MODE_DRC_ENABLE + dec->drc = music_drc_open(sample_rate, ch_num);//drc +#endif/*TCFG_SPDIF_MODE_DRC_ENABLE*/ + if (dec->eq && dec->eq->out_32bit) { + dec->convert = convet_data_open(0, 512); + } + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + dec->eq2 = music_eq2_open(sample_rate, ch_num);// eq + dec->dy_eq = audio_dynamic_eq_ctrl_open(sample_rate, ch_num);//动态eq + dec->convert2 = convet_data_open(0, 512); +#endif/*TCFG_DYNAMIC_EQ_ENABLE*/ + dec->gain = audio_gain_open_demo(AEID_MUSIC_GAIN, dec->file_dec.output_ch_num); +#endif/*TCFG_SPDIF_MODE_EQ_ENABLE*/ + + + +#if TCFG_EQ_DIVIDE_ENABLE + dec->eq_rl_rr = music_eq_rl_rr_open(sample_rate, ch_num);// eq +#if TCFG_DRC_ENABLE && TCFG_BT_MUSIC_DRC_ENABLE + dec->drc_rl_rr = music_drc_rl_rr_open(sample_rate, ch_num);//drc +#endif + if (dec->eq_rl_rr && dec->eq_rl_rr->out_32bit) { + dec->convert_rl_rr = convet_data_open(0, 512); + } +#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) && SOUND_TRACK_2_P_X_CH_CONFIG +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + dec->rl_rr_mix = stream_entry_open(NULL, stream_rl_rr_mix_data_handler, 0); +#endif +#endif + dec->gain_rl_rr = audio_gain_open_demo(AEID_MUSIC_RL_GAIN, ch_num); + + if (dec->eq_rl_rr) { + audio_vocal_tract_open(&dec->vocal_tract, AUDIO_SYNTHESIS_LEN); + { + u8 entry_cnt = 0; + struct audio_stream_entry *entries[8] = {NULL}; + entries[entry_cnt++] = &dec->vocal_tract.entry; + entries[entry_cnt++] = &dec->mix_ch.entry; + dec->vocal_tract.stream = audio_stream_open(&dec->vocal_tract, audio_vocal_tract_stream_resume); + audio_stream_add_list(dec->vocal_tract.stream, entries, entry_cnt); + } + audio_vocal_tract_synthesis_open(&dec->synthesis_ch_fl_fr, &dec->vocal_tract, FL_FR); + audio_vocal_tract_synthesis_open(&dec->synthesis_ch_rl_rr, &dec->vocal_tract, RL_RR); + } else { + dec->ch_switch = channel_switch_open(AUDIO_CH_QUAD, AUDIO_SYNTHESIS_LEN / 2); + } +#ifdef CONFIG_MIXER_CYCLIC + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 0, BIT(0)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 1, BIT(1)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 2, BIT(2)); + audio_mixer_ch_set_aud_ch_out(&dec->mix_ch, 3, BIT(3)); +#endif + +#endif + + + + // 数据流串联 + struct audio_stream_entry *entries[32] = {NULL}; + u8 entry_cnt = 0; + u8 rl_rr_entry_start = 0; + + if (dec->fmt.coding_type == AUDIO_CODING_DTS) { + entries[entry_cnt++] = &dec->file_dec.decoder.entry; + } else { + entries[entry_cnt++] = &dec->pcm_dec.decoder.entry; + } + +#if AUDIO_SURROUND_CONFIG + if (dec->surround) { + entries[entry_cnt++] = &dec->surround->entry; + } +#endif + + +#if AUDIO_VBASS_CONFIG + if (dec->vbass_prev_gain) { + entries[entry_cnt++] = &dec->vbass_prev_gain->entry; + } + if (dec->vbass) { + entries[entry_cnt++] = &dec->vbass->entry; + } +#endif + + if (dec->high_bass) { //高低音 + entries[entry_cnt++] = &dec->high_bass->entry; + } + if (dec->hb_drc) { //高低音后drc + entries[entry_cnt++] = &dec->hb_drc->entry; + if (dec->hb_convert) { + entries[entry_cnt++] = &dec->hb_convert->entry; + } + } + + rl_rr_entry_start = entry_cnt - 1;//记录eq的上一个节点 +#if TCFG_EQ_ENABLE && TCFG_SPDIF_MODE_EQ_ENABLE + if (dec->eq) { + entries[entry_cnt++] = &dec->eq->entry; + if (dec->drc) { + entries[entry_cnt++] = &dec->drc->entry; + } + if (dec->convert) { + entries[entry_cnt++] = &dec->convert->entry; + } +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + if (dec->eq2) { + entries[entry_cnt++] = &dec->eq2->entry; + } + if (dec->dy_eq && dec->dy_eq->dy_eq) { + entries[entry_cnt++] = &dec->dy_eq->dy_eq->entry; + } + if (dec->convert2) { + entries[entry_cnt++] = &dec->convert2->entry; + } +#endif + if (dec->gain) { + entries[entry_cnt++] = &dec->gain->entry; + } + } +#endif +#if TCFG_EQ_DIVIDE_ENABLE + if (dec->eq_rl_rr) { + entries[entry_cnt++] = &dec->synthesis_ch_fl_fr.entry;//四声道eq独立时,该节点后不接节点 + } else { + if (dec->ch_switch) { + entries[entry_cnt++] = &dec->ch_switch->entry; + } + entries[entry_cnt++] = &dec->mix_ch.entry; + } +#else + entries[entry_cnt++] = &dec->mix_ch.entry; +#endif + + dec->audio_stream = audio_stream_open(dec, dec_out_stream_resume); + audio_stream_add_list(dec->audio_stream, entries, entry_cnt); +#if TCFG_EQ_DIVIDE_ENABLE + struct audio_stream_entry *rl_rr_entries[8] = {NULL}; + entry_cnt = 0; + if (dec->eq_rl_rr) { //接在eq_drc的上一个节点 + rl_rr_entries[entry_cnt++] = entries[rl_rr_entry_start]; + rl_rr_entries[entry_cnt++] = &dec->eq_rl_rr->entry; + if (dec->drc_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->drc_rl_rr->entry; + } + if (dec->convert_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->convert_rl_rr->entry; + } +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + if (dec->rl_rr_mix) { + rl_rr_entries[entry_cnt++] = &dec->rl_rr_mix->entry; + } +#endif + if (dec->gain_rl_rr) { + rl_rr_entries[entry_cnt++] = &dec->gain_rl_rr->entry; + } + + rl_rr_entries[entry_cnt++] = &dec->synthesis_ch_rl_rr.entry;//必须是最后一个 + for (int i = 0; i < (entry_cnt - 1); i++) { + audio_stream_add_entry(rl_rr_entries[i], rl_rr_entries[i + 1]); + } + } +#endif + + audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); + err = audio_decoder_start(&dec->pcm_dec.decoder); + if (err) { + +#if AUDIO_SURROUND_CONFIG + surround_close_demo(dec->surround); +#endif + + +#if AUDIO_VBASS_CONFIG + audio_gain_close_demo(dec->vbass_prev_gain); + audio_vbass_close_demo(dec->vbass); +#endif + + high_bass_eq_close(dec->high_bass); + high_bass_drc_close(dec->hb_drc); + convet_data_close(dec->hb_convert); + +#if TCFG_EQ_ENABLE && TCFG_SPDIF_MODE_EQ_ENABLE + music_eq_close(dec->eq); +#if TCFG_DRC_ENABLE && TCFG_SPDIF_MODE_DRC_ENABLE + music_drc_close(dec->drc); +#endif + convet_data_close(dec->convert); + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + music_eq2_close(dec->eq2); + audio_dynamic_eq_ctrl_close(dec->dy_eq); + convet_data_close(dec->convert2); +#endif + audio_gain_close_demo(dec->gain); +#endif + +#if TCFG_EQ_DIVIDE_ENABLE + music_eq_rl_rr_close(dec->eq_rl_rr); + music_drc_rl_rr_close(dec->drc_rl_rr); + convet_data_close(dec->convert_rl_rr); +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + stream_entry_close(&dec->rl_rr_mix); +#endif + audio_gain_close_demo(dec->gain_rl_rr); + + audio_vocal_tract_synthesis_close(&dec->synthesis_ch_fl_fr); + audio_vocal_tract_synthesis_close(&dec->synthesis_ch_rl_rr); + audio_vocal_tract_close(&dec->vocal_tract); + channel_switch_close(&dec->ch_switch); +#endif + return err; + } + clock_set_cur(); + dec->status = SPDIF_STATE_START; + return 0; +} + +int spdif_dec_stop(void) +{ + if (spdif_dec_hdl) { + spdif_dec_hdl->status = SPDIF_STATE_STOP; + pcm_decoder_close(&spdif_dec_hdl->pcm_dec); + struct s_spdif_decode *dec = spdif_dec_hdl; + +#if AUDIO_SURROUND_CONFIG + surround_close_demo(dec->surround); +#endif + + +#if AUDIO_VBASS_CONFIG + audio_gain_close_demo(dec->vbass_prev_gain); + audio_vbass_close_demo(dec->vbass); +#endif + + high_bass_eq_close(dec->high_bass); + high_bass_drc_close(dec->hb_drc); + convet_data_close(dec->hb_convert); + +#if TCFG_EQ_ENABLE && TCFG_SPDIF_MODE_EQ_ENABLE + music_eq_close(dec->eq); +#if TCFG_DRC_ENABLE && TCFG_SPDIF_MODE_DRC_ENABLE + music_drc_close(dec->drc); +#endif + convet_data_close(dec->convert); +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + music_eq2_close(dec->eq2); + audio_dynamic_eq_ctrl_close(dec->dy_eq); + convet_data_close(dec->convert2); +#endif + audio_gain_close_demo(dec->gain); +#endif + +#if TCFG_EQ_DIVIDE_ENABLE + music_eq_rl_rr_close(spdif_dec_hdl->eq_rl_rr); + music_drc_rl_rr_close(spdif_dec_hdl->drc_rl_rr); + convet_data_close(spdif_dec_hdl->convert_rl_rr); +#if defined(TWO_POINT_X_CH) && (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + stream_entry_close(&spdif_dec_hdl->rl_rr_mix); +#endif + audio_gain_close_demo(spdif_dec_hdl->gain_rl_rr); + + audio_vocal_tract_synthesis_close(&spdif_dec_hdl->synthesis_ch_fl_fr); + audio_vocal_tract_synthesis_close(&spdif_dec_hdl->synthesis_ch_rl_rr); + audio_vocal_tract_close(&spdif_dec_hdl->vocal_tract); + channel_switch_close(&spdif_dec_hdl->ch_switch); +#endif + + audio_mixer_ch_close(&spdif_dec_hdl->mix_ch); + if (spdif_dec_hdl->audio_stream) { + audio_stream_close(spdif_dec_hdl->audio_stream); + spdif_dec_hdl->audio_stream = 0; + } + } + return 0; +} +static int spdif_wait_res_handler(struct audio_res_wait *wait, int event) +{ + int err = 0; + if (event == AUDIO_RES_GET) { + err = spdif_dec_start(); + } else if (event == AUDIO_RES_PUT) { + err = spdif_dec_stop(); + } + return err; +} + + +static void spdif_status_check(void *priv) +{ + static u8 cnt = 0; + if (spdif_dec_hdl && (spdif_slave_hdl.status == SPDIF_STATE_START || spdif_slave_hdl.status == SPDIF_STATE_STOP)) { + /* printf("spdif status \n"); */ + if (spdif_slave_hdl.error_flag == 1) { + printf("spdif reset \n"); + /* audio_spdif_slave_close(&spdif_slave_hdl); */ + spdif_dec_close(); + struct audio_fmt fmt; + fmt.channel = 2; + fmt.coding_type = AUDIO_CODING_PCM; + fmt.sample_rate = SPDIF_DEFAULT_OUT_SAMPLE_RATE; + spdif_dec_open(fmt); + audio_spdif_slave_open(&spdif_slave_hdl); + audio_spdif_slave_start(&spdif_slave_hdl); + spdif_slave_hdl.error_flag = 0; + } else if (spdif_slave_hdl.error_flag == 2) { + printf("spdif reset \n"); + /* audio_spdif_slave_close(&spdif_slave_hdl); */ + spdif_dec_close(); + struct audio_fmt fmt; + fmt.channel = 2; + fmt.coding_type = AUDIO_CODING_DTS; + fmt.sample_rate = SPDIF_DEFAULT_OUT_SAMPLE_RATE; + spdif_dec_open(fmt); + audio_spdif_slave_open(&spdif_slave_hdl); + audio_spdif_slave_start(&spdif_slave_hdl); + spdif_slave_hdl.error_flag = 0; + } else { +#if 10 + if (spdif_dec_hdl->status == SPDIF_STATE_START) { + if (spdif_data_size(spdif_dec_hdl) == 0) { + if (cnt < 6) { + cnt++; + } + if (cnt == 5) { + audio_mixer_ch_pause(&spdif_dec_hdl->mix_ch, 1); + audio_decoder_resume_all(&decode_task); + } + } else { + if (cnt > 4) { + audio_mixer_ch_pause(&spdif_dec_hdl->mix_ch, 0); + audio_decoder_resume_all(&decode_task); + } + cnt = 0; + } + } +#endif + } + } +} +///*----------------------------------------------------------------------------*/ +/**@brief spdif 硬件设置 + @param 无 + @return 无 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void _spdif_open(void) +{ +#if TCFG_SPDIF_OUTPUT_ENABLE + spdif_slave_hdl.output_port = SPDIF_OUT_PORT_A;//PB11 +#endif + spdif_slave_hdl.input_port = SPDIF_IN_PORT_A;//PA9 + audio_spdif_slave_open(&spdif_slave_hdl); + + audio_spdif_slave_start(&spdif_slave_hdl); +#if TCFG_HDMI_ARC_ENABLE + extern void hdmi_cec_init(void); + hdmi_cec_init(); +#endif +} + +void spdif_init(void) +{ + audio_spdif_slave_init(&spdif_slave_hdl); + request_irq(IRQ_SPDIF_IDX, 2, spdif_isr_handler, 0); + sys_timer_add(NULL, spdif_status_check, 250); + +#if (TCFG_APP_SPDIF_EN == 0) + spdif_dec_init(); + _spdif_open(); //for test +#endif + +} + +void spdif_dec_init(void) +{ + struct audio_fmt fmt; + fmt.channel = 2; + fmt.coding_type = AUDIO_CODING_PCM; + fmt.sample_rate = SPDIF_DEFAULT_OUT_SAMPLE_RATE; + spdif_dec_open(fmt); +} + +int spdif_dec_open(struct audio_fmt fmt) +{ + int err; + if (spdif_dec_hdl) { + return -1; + } + spdif_dec_hdl = zalloc(sizeof(struct s_spdif_decode)); + if (!spdif_dec_hdl) { + return -ENOMEM; + } + + clock_add(SPDIF_CLK); + cbuf_init(&spdif_dec_hdl->dec_cbuf, spdif_dec_hdl->dec_data_buf, SPDIF_DEC_DATA_BUF_LEN); + spdif_dec_hdl->fmt.channel = fmt.channel; + spdif_dec_hdl->fmt.coding_type = fmt.coding_type; + spdif_dec_hdl->fmt.sample_rate = fmt.sample_rate; + spdif_dec_hdl->fmt.coding_type = fmt.coding_type; + spdif_dec_hdl->coding_type = fmt.coding_type; + if (fmt.coding_type == AUDIO_CODING_DTS) { + spdif_dec_hdl->file_dec.ch_type = AUDIO_CH_MAX; + spdif_dec_hdl->file_dec.output_ch_num = audio_output_channel_num(); + spdif_dec_hdl->file_dec.output_ch_type = audio_output_channel_type(); + } else { + old_samplerate_index = 6; + spdif_dec_hdl->pcm_dec.ch_num = fmt.channel; + spdif_dec_hdl->pcm_dec.output_ch_num = audio_output_channel_num(); + spdif_dec_hdl->pcm_dec.output_ch_type = audio_output_channel_type(); + spdif_dec_hdl->pcm_dec.sample_rate = fmt.sample_rate; + spdif_dec_hdl->pcm_sr = fmt.sample_rate; + } + spdif_dec_hdl->wait.priority = 4; + spdif_dec_hdl->wait.preemption = 0; + spdif_dec_hdl->wait.protect = 1;//1 叠加模式 + spdif_dec_hdl->wait.snatch_same_prio = 1; + spdif_dec_hdl->wait.handler = spdif_wait_res_handler; + spdif_dec_hdl->status = SPDIF_STATE_OPEN; + err = audio_decoder_task_add_wait(&decode_task, &spdif_dec_hdl->wait); + return err; +} + +void spdif_dec_close(void) +{ + printf("\n--func1=%s\n", __FUNCTION__); + if (!spdif_dec_hdl) { + return; + } + spdif_dec_stop(); + spdif_dec_release(); + clock_set_cur(); +} + +bool spdif_dec_check(void) +{ + if (spdif_dec_hdl) { + + return true; + } + return false; +} +#endif // TCFG_SPDIF_ENABLE +/***********************spdif dec end*****************************/ diff --git a/cpu/br23/audio_dec/audio_dec_spdif.h b/cpu/br23/audio_dec/audio_dec_spdif.h new file mode 100644 index 0000000..eac25a8 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_spdif.h @@ -0,0 +1,22 @@ + +#ifndef _AUDIO_DEC_SPDIF_H_ +#define _AUDIO_DEC_SPDIF_H_ + +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "media/audio_decoder.h" + +// 写入spdif数据 +// int spdif_dec_write_data(s16 *data, int len); +int spdif_dec_write_data(void *data, int len); +void spdif_init(void); +int spdif_dec_start(void); +int spdif_dec_stop(void); +int spdif_dec_open(struct audio_fmt fmt); +void spdif_dec_close(void); +bool spdif_dec_check(void); + +void spdif_dec_init(void); +#endif + diff --git a/cpu/br23/audio_dec/audio_dec_tone.c b/cpu/br23/audio_dec/audio_dec_tone.c new file mode 100644 index 0000000..96b9921 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_tone.c @@ -0,0 +1,885 @@ +#include "system/includes.h" +#include "media/includes.h" +#include "tone_player.h" +#include "audio_config.h" +#include "app_main.h" +#include "clock_cfg.h" +#include "audio_dec.h" +#include "avctp_user.h" + +#define AUDIO_DEC_TONE_AT_CODE_EVENT_CB AT(.audio_dec_tone_event_callback) + +#define AUDIO_DEC_TONE_WAIT_USE_PRIO 0 // 采用优先级顺序播放方式 + +extern struct audio_dac_hdl dac_hdl; +extern struct audio_dac_channel default_dac; +extern const int audio_dec_app_mix_en; + +////////////////////////////////////////////////////////////////////////////// +extern int audio_dec_file_app_init_ok(struct audio_dec_file_app_hdl *file_dec); +extern int audio_dec_sine_app_init_ok(struct audio_dec_sine_app_hdl *sine_dec); +extern int audio_dec_file_app_play_end(struct audio_dec_file_app_hdl *file_dec); +extern int audio_dec_sine_app_play_end(struct audio_dec_sine_app_hdl *sine_dec); + +static int tone_dec_list_play(struct tone_dec_handle *dec, u8 next); +////////////////////////////////////////////////////////////////////////////// + +/*----------------------------------------------------------------------------*/ +/**@brief tone解码数据流推送stop + @param *dec: 解码句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tone_dec_stream_run_stop(struct audio_dec_app_hdl *dec) +{ +#if AUDIO_DAC_MULTI_CHANNEL_ENABLE + struct audio_data_frame frame = {0}; + struct audio_data_frame output = {0}; + frame.stop = 1; + frame.channel = audio_output_channel_num(); + frame.sample_rate = app_audio_output_samplerate_get(); + /* audio_stream_run(&default_dac.entry, &frame); */ + default_dac.entry.data_handler(&default_dac.entry, &frame, &output); + audio_stream_del_entry(&default_dac.entry); +#else /*AUDIO_DAC_MULTI_CHANNEL_ENABLE*/ + audio_dac_stop(&dac_hdl); +#endif /*AUDIO_DAC_MULTI_CHANNEL_ENABLE*/ +} + +#if TONE_DEC_PROTECT_LIST_PLAY +struct tone_dec_list_protect { + struct audio_res_wait wait; +}; +/*----------------------------------------------------------------------------*/ +/**@brief tone链表播放保护用的临时解码资源等待 + @param *wait: 句柄 + @param event: 事件 + @return 0:成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int tone_dec_list_protect_res_handler(struct audio_res_wait *wait, int event) +{ + y_printf("tone protect event:%d \n", event); + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief tone链表播放保护用的临时解码释放 + @param *dec: 解码链表句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tone_dec_list_protect_release(struct tone_dec_list_handle *dec_list) +{ + if ((!dec_list) || (!dec_list->list_protect)) { + return ; + } + y_printf("tone_dec_list_protect_release \n"); + struct tone_dec_list_protect *prot = dec_list->list_protect; + audio_decoder_task_del_wait(&decode_task, &prot->wait); + free(dec_list->list_protect); + dec_list->list_protect = NULL; +} +/*----------------------------------------------------------------------------*/ +/**@brief tone链表播放保护用的临时解码处理 + @param *dec_list: 解码链表句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tone_dec_list_protect_deal(struct tone_dec_list_handle *dec_list) +{ + if ((!dec_list) || (!dec_list->preemption)) { + return ; + } + if ((!dec_list->file_list) || (!dec_list->file_list[1])) { + return ; + } + if (dec_list->list_protect) { + return ; + } + struct tone_dec_list_protect *prot = zalloc(sizeof(struct tone_dec_list_protect)); + if (!prot) { + return ; + } + y_printf("tone_dec_list_protect_deal \n"); + dec_list->list_protect = prot; +#if AUDIO_DEC_TONE_WAIT_USE_PRIO + prot->wait.priority = 3; + prot->wait.preemption = 0; + prot->wait.snatch_same_prio = 1; +#else + prot->wait.preemption = 1; +#endif + prot->wait.handler = tone_dec_list_protect_res_handler; + audio_decoder_task_add_wait(&decode_task, &prot->wait); +} +#endif + +/*----------------------------------------------------------------------------*/ +/**@brief 获取文件名后缀 + @param *name: 文件名 + @return 后缀 + @note +*/ +/*----------------------------------------------------------------------------*/ +static char *get_file_ext_name(char *name) +{ + int len = strlen(name); + char *ext = (char *)name; + + while (len--) { + if (*ext++ == '.') { + break; + } + } + if (len <= 0) { + ext = name + (strlen(name) - 3); + } + + return ext; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提示音list解码事件 + @param *dec_list: list句柄 + @param end_flag: 结束类型 + @return true: 成功 + @return false: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int tone_dec_list_event_handler(struct tone_dec_list_handle *dec_list, u8 end_flag) +{ + int argv[4]; + if (!dec_list->evt_handler) { + log_i("evt_handler null\n"); + return false; + } + argv[0] = (int)dec_list->evt_handler; + argv[1] = 2; + argv[2] = (int)dec_list->evt_priv; + argv[3] = (int)end_flag; //0正常关闭,1被打断关闭 + + int ret = os_taskq_post_type(dec_list->evt_owner, Q_CALLBACK, 4, argv); + if (ret) { + return false; + } + return true; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 创建提示音播放句柄 + @param + @return 提示音句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +struct tone_dec_handle *tone_dec_create(void) +{ + struct tone_dec_handle *dec = zalloc(sizeof(struct tone_dec_handle)); + if (!dec) { + return NULL; + } + INIT_LIST_HEAD(&dec->head); + os_mutex_create(&dec->mutex); + return dec; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 设置sine数组获取回调 + @param *dec: 提示音句柄 + @param *get_sine: sine数组获取 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void tone_dec_set_sin_get_hdl(struct tone_dec_handle *dec, struct sin_param * (*get_sine)(u8 id, u8 *num)) +{ + if (dec) { + dec->get_sine = get_sine; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提示音解码器释放 + @param *dec: 提示音句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tone_dec_hdl_release(struct tone_dec_handle *dec) +{ + if (dec->dec_file) { + audio_dec_file_app_play_end(dec->dec_file); + dec->dec_file = NULL; + } + if (dec->dec_sin) { + audio_dec_sine_app_play_end(dec->dec_sin); + dec->dec_sin = NULL; + } + + clock_remove_set(DEC_TONE_CLK); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提示音list释放 + @param *dec_list: list句柄 + @param push_event: 普通提示音是否推送消息 + @param end_flag: 结束类型 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tone_dec_list_release(struct tone_dec_list_handle *dec_list, u8 push_event, u8 end_flag) +{ + if (dec_list == NULL) { + return ; + } + if (push_event) { + tone_dec_list_event_handler(dec_list, end_flag); + } +#if TONE_DEC_PROTECT_LIST_PLAY + tone_dec_list_protect_release(dec_list); +#endif + list_del(&dec_list->list_entry); + if (dec_list->file_list) { + free(dec_list->file_list); + } + free(dec_list); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提示音解码结束处理 + @param *dec: 提示音句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tone_dec_end_ctrl(struct tone_dec_handle *dec) +{ + os_mutex_pend(&dec->mutex, 0); + // 检查循环播放 + int ret = tone_dec_list_play(dec, 1); + if (ret == true) { + os_mutex_post(&dec->mutex); + return ; + } + // 发送播放完成 + tone_dec_list_release(dec->cur_list, 1, TONE_DEC_STOP_NOR); + dec->cur_list = NULL; + + // 检查链表播放 + struct list_head *list_entry = dec->head.next; + if (list_entry && (list_entry != &dec->head)) { + struct tone_dec_list_handle *dec_list = container_of(list_entry, struct tone_dec_list_handle, list_entry); + dec->cur_list = dec_list; + tone_dec_list_play(dec, 0); + } + os_mutex_post(&dec->mutex); +} + +/*----------------------------------------------------------------------------*/ +/**@brief file提示音解码回调 + @param *priv: 私有句柄 + @param event: 事件 + @param *param: 事件参数 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +AUDIO_DEC_TONE_AT_CODE_EVENT_CB +static int tone_dec_file_app_evt_cb(void *priv, enum audio_dec_app_event event, int *param) +{ + /* log_i("audio_dec_file_app_evt_cb, priv:0x%x, event:%d \n", priv, event); */ + + struct audio_dec_stream_entries_hdl *entries_hdl = (struct audio_dec_stream_entries_hdl *)param; + void *dvol_entry = NULL; + + int ret ; + struct audio_dec_file_app_hdl *file_dec = priv; + struct tone_dec_handle *dec = file_dec->priv; + switch (event) { + case AUDIO_DEC_APP_EVENT_DEC_PROBE: + break; + case AUDIO_DEC_APP_EVENT_DEC_OUTPUT: + // param[0]:*data. param[1]:data_len + break; + case AUDIO_DEC_APP_EVENT_DEC_POST: + break; + case AUDIO_DEC_APP_EVENT_START_INIT_OK: + log_i("tone_file start init ok\n"); + if (dec->cur_list->stream_handler) { + // 删除原有的数据流,需要在回调中重新设置 + if (file_dec->dec->stream) { + audio_stream_del_entry(&file_dec->dec->mix_ch.entry); + audio_stream_del_entry(&file_dec->dec->decoder.entry); + audio_stream_close(file_dec->dec->stream); + file_dec->dec->stream = NULL; + } + dec->cur_list->stream_handler(dec->cur_list->stream_priv, event, file_dec->dec); + } + + clock_add_set(DEC_TONE_CLK); + audio_dec_file_app_init_ok(file_dec); + __bt_emitter_pp(1); + break; + case AUDIO_DEC_APP_EVENT_DEC_CLOSE: + if (!audio_dec_app_mix_en) { + tone_dec_stream_run_stop(file_dec->dec); + } + if (dec->cur_list->stream_handler) { + dec->cur_list->stream_handler(dec->cur_list->stream_priv, event, file_dec->dec); + } +#if SYS_DIGVOL_GROUP_EN + if (dec->cur_list->stream_handler == NULL) { + sys_digvol_group_ch_close("tone_tone"); + } +#endif // SYS_DIGVOL_GROUP_EN + + break; + case AUDIO_DEC_APP_EVENT_START_OK: + dec->cur_list->dec_ok_cnt++; + break; + case AUDIO_DEC_APP_EVENT_START_ERR: + log_i("tone_file start err\n"); + case AUDIO_DEC_APP_EVENT_PLAY_END: + log_i("tone_file play end\n"); + tone_dec_end_ctrl(dec); + #if 1 + extern struct audio_mixer mixer; + int mixer_channel_num = audio_mixer_get_ch_num(&mixer); + printf("mixer_channel_num:%d \n", mixer_channel_num); + if (mixer_channel_num >= 1) { + + }else { + __bt_emitter_pp(0); + } + #endif + break; + case AUDIO_DEC_APP_EVENT_STREAM_OPEN: +#if SYS_DIGVOL_GROUP_EN + audio_dig_vol_param temp_digvol_param = { + .vol_start = get_max_sys_vol(), + .vol_max = get_max_sys_vol(), + .ch_total = 2, + .fade_en = 0, //提示音不能淡入淡出 + .fade_points_step = 5, + .fade_gain_step = 10, + .vol_list = NULL, + }; + + + if (dec->cur_list->stream_handler == NULL) { + dvol_entry = sys_digvol_group_ch_open("tone_tone", -1, &temp_digvol_param); + (entries_hdl->entries_addr)[entries_hdl->entries_cnt++] = dvol_entry; + } +#endif // SYS_DIGVOL_GROUP_EN + + break; + case AUDIO_DEC_APP_EVENT_STREAM_CLOSE: + break; + + default : + break; + + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief sine提示音解码回调 + @param *priv: 私有句柄 + @param event: 事件 + @param *param: 事件参数 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +AUDIO_DEC_TONE_AT_CODE_EVENT_CB +static int tone_dec_sine_app_evt_cb(void *priv, enum audio_dec_app_event event, int *param) +{ + /* log_i("audio_dec_sine_app_evt_cb, priv:0x%x, event:%d \n", priv, event); */ + struct audio_dec_sine_app_hdl *sine_dec = priv; + struct tone_dec_handle *dec = sine_dec->priv; + struct audio_dec_stream_entries_hdl *entries_hdl = (struct audio_dec_stream_entries_hdl *)param; + void *dvol_entry = NULL; + switch (event) { + case AUDIO_DEC_APP_EVENT_DEC_PROBE: + if (sine_dec->sin_maker) { + break; + } + audio_dec_sine_app_probe(sine_dec); + if (!sine_dec->sin_maker) { + return -ENOENT; + } + break; + case AUDIO_DEC_APP_EVENT_START_INIT_OK: + log_i("tone_sine start init ok\n"); + if (dec->cur_list->stream_handler) { + // 删除原有的数据流,需要在回调中重新设置 + if (sine_dec->dec->stream) { + audio_stream_del_entry(&sine_dec->dec->mix_ch.entry); + audio_stream_del_entry(&sine_dec->dec->decoder.entry); + audio_stream_close(sine_dec->dec->stream); + sine_dec->dec->stream = NULL; + } + dec->cur_list->stream_handler(dec->cur_list->stream_priv, event, sine_dec->dec); + } + clock_add_set(DEC_TONE_CLK); + audio_dec_sine_app_init_ok(sine_dec); + __bt_emitter_pp(1); + break; + case AUDIO_DEC_APP_EVENT_DEC_CLOSE: + if (!audio_dec_app_mix_en) { + tone_dec_stream_run_stop(sine_dec->dec); + } + if (dec->cur_list->stream_handler) { + dec->cur_list->stream_handler(dec->cur_list->stream_priv, event, sine_dec->dec); + } +#if SYS_DIGVOL_GROUP_EN + if (dec->cur_list->stream_handler == NULL) { + sys_digvol_group_ch_close("tone_tone"); + } +#endif // SYS_DIGVOL_GROUP_EN + +#if (TCFG_MIC_EFFECT_ENABLE) + mic_effect_pause(0); +#endif + break; + case AUDIO_DEC_APP_EVENT_START_OK: + dec->cur_list->dec_ok_cnt++; + break; + case AUDIO_DEC_APP_EVENT_START_ERR: + log_i("tone_file start err\n"); + case AUDIO_DEC_APP_EVENT_PLAY_END: + log_i("tone_sine play end\n"); + /* audio_dec_sine_app_play_end(sine_dec); */ + tone_dec_end_ctrl(dec); + #if 1 + extern struct audio_mixer mixer; + int mixer_channel_num = audio_mixer_get_ch_num(&mixer); + printf("mixer_channel_num:%d \n", mixer_channel_num); + if (mixer_channel_num >= 1) { + + }else { + __bt_emitter_pp(0); + } + #endif + break; + case AUDIO_DEC_APP_EVENT_STREAM_OPEN: +#if SYS_DIGVOL_GROUP_EN + audio_dig_vol_param temp_digvol_param = { + .vol_start = get_max_sys_vol(), + .vol_max = get_max_sys_vol(), + .ch_total = 2, + .fade_en = 0, //提示音不能淡入淡出 + .fade_points_step = 5, + .fade_gain_step = 10, + .vol_list = NULL, + }; + + if (dec->cur_list->stream_handler == NULL) { + dvol_entry = sys_digvol_group_ch_open("tone_tone", -1, &temp_digvol_param); + (entries_hdl->entries_addr)[entries_hdl->entries_cnt++] = dvol_entry; + } +#endif // SYS_DIGVOL_GROUP_EN +#if (TCFG_MIC_EFFECT_ENABLE) + mic_effect_pause(1); +#endif + break; + + + default : + break; + + } + return 0; +} + +static void _tone_dec_app_comm_deal(struct audio_dec_app_hdl *dec, struct tone_dec_handle *tone) +{ + dec->sync_confirm_time = tone->cur_list->sync_confirm_time; + if (dec->dec_type == AUDIO_CODING_SBC) { + audio_dec_app_set_frame_info(dec, 0x4e, dec->dec_type); + } +#if AUDIO_DEC_TONE_WAIT_USE_PRIO + if (dec->dec_mix == 0) { + dec->wait.priority = 3; + dec->wait.preemption = 0; + dec->wait.snatch_same_prio = 1; + } +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提示音list播放 + @param *dec: 句柄 + @param next: 播放下一个 + @return true: 成功 + @return false: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int tone_dec_list_play(struct tone_dec_handle *dec, u8 next) +{ + struct tone_dec_list_handle *dec_list = dec->cur_list; + if (!dec_list) { + return false; + } +#if TONE_DEC_PROTECT_LIST_PLAY + tone_dec_list_protect_deal(dec_list); +#endif + + tone_dec_hdl_release(dec); + + if (next) { + dec_list->idx++; + } + if (IS_REPEAT_END(dec_list->file_list[dec_list->idx])) { + //log_i("repeat_loop:%d",dec_list->loop); + if (!dec_list->dec_ok_cnt) { + log_i("repeat dec err \n"); + return false; + } + if (dec_list->loop) { + dec_list->loop--; + dec_list->idx = dec_list->repeat_begin; + } else { + dec_list->idx++; + if (!dec_list->file_list[dec_list->idx]) { + log_i("repeat end 2:idx end"); + return false; + } + } + } + + if (IS_REPEAT_BEGIN(dec_list->file_list[dec_list->idx])) { + if (dec_list->loop == 0) { + dec_list->loop = TONE_REPEAT_COUNT(dec_list->file_list[dec_list->idx]); + log_i("repeat begin:%d", dec_list->loop); + } + dec_list->idx++; + dec_list->repeat_begin = dec_list->idx; + dec_list->dec_ok_cnt = 0; + } + + if (dec_list->file_list[dec_list->idx] == NULL) { + return false; + } + + if (IS_DEFAULT_SINE(dec_list->file_list[dec_list->idx])) { + // is sine idx + if (dec->get_sine == NULL) { + log_e("get_sine is NULL "); + return false; + } + u8 num = 0; + struct sin_param *sin = dec->get_sine(DEFAULT_SINE_ID(dec_list->file_list[dec_list->idx]), &num); + if (!sin) { + log_e("sine is NULL "); + return false; + } + dec->dec_sin = audio_dec_sine_app_create_by_parm(sin, num, !dec_list->preemption); + if (dec->dec_sin == NULL) { + return false; + } + _tone_dec_app_comm_deal(dec->dec_sin->dec, dec); + dec->dec_sin->dec->evt_cb = tone_dec_sine_app_evt_cb; + dec->dec_sin->priv = dec; + audio_dec_sine_app_open(dec->dec_sin); + return true; + } + u8 file_name[16]; + char *format = NULL; + FILE *file = fopen(dec_list->file_list[dec_list->idx], "r"); + if (!file) { + return false; + } + fget_name(file, file_name, 16); + format = get_file_ext_name((char *)file_name); + fclose(file); + if (ASCII_StrCmpNoCase(format, "sin", 3) == 0) { + // is sine file + dec->dec_sin = audio_dec_sine_app_create(dec_list->file_list[dec_list->idx], !dec_list->preemption); + if (dec->dec_sin == NULL) { + return false; + } + _tone_dec_app_comm_deal(dec->dec_sin->dec, dec); + dec->dec_sin->dec->evt_cb = tone_dec_sine_app_evt_cb; + dec->dec_sin->priv = dec; + audio_dec_sine_app_open(dec->dec_sin); + return true; + } + + // is file + dec->dec_file = audio_dec_file_app_create(dec_list->file_list[dec_list->idx], !dec_list->preemption); + if (dec->dec_file == NULL) { + return false; + } + _tone_dec_app_comm_deal(dec->dec_file->dec, dec); + dec->dec_file->dec->evt_cb = tone_dec_file_app_evt_cb; + dec->dec_file->priv = dec; + audio_dec_file_app_open(dec->dec_file); + return true; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 创建提示音播放list句柄 + @param *dec: 提示音句柄 + @param **file_list: 文件名 + @param preemption: 打断标记 + @param *evt_handler: 事件回调接口 + @param *evt_priv: 事件回调私有句柄 + @param *stream_handler: tone数据流设置回调 + @param *stream_priv: tone数据流设置回调私有句柄 + @return list句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +struct tone_dec_list_handle *tone_dec_list_create(struct tone_dec_handle *dec, + const char **file_list, + u8 preemption, + void (*evt_handler)(void *priv, int flag), + void *evt_priv, + void (*stream_handler)(void *priv, int event, struct audio_dec_app_hdl *app_dec), + void *stream_priv) +{ + if (!dec || !file_list) { + return NULL; + } + struct tone_dec_list_handle *dec_list = zalloc(sizeof(struct tone_dec_list_handle)); + if (!dec_list) { + return NULL; + } + + int i = 0; + while (file_list[i] != NULL) { + i++; + } + dec_list->file_list = malloc(4 * (i + 1)); + if (!dec_list->file_list) { + free(dec_list); + return NULL; + } + memcpy(dec_list->file_list, file_list, 4 * (i + 1)); + dec_list->preemption = preemption; + dec_list->evt_handler = evt_handler; + dec_list->evt_priv = evt_priv; + dec_list->evt_owner = os_current_task(); + dec_list->stream_handler = stream_handler; + dec_list->stream_priv = stream_priv; + return dec_list; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提示音list开始播放 + @param *dec: 提示音句柄 + @param *dec_list: list句柄 + @return true: 成功 + @return false: 成功 + @note 当前没有播放,马上开始播放。当前有播放,挂载到链表后面等待播放 +*/ +/*----------------------------------------------------------------------------*/ +int tone_dec_list_add_play(struct tone_dec_handle *dec, struct tone_dec_list_handle *dec_list) +{ + int ret = false; + if (!dec || !dec_list) { + return false; + } + + os_mutex_pend(&dec->mutex, 0); + + list_add_tail(&dec_list->list_entry, &dec->head); + + if (dec->cur_list == NULL) { + // 当前没有播放,开始播放 + dec->cur_list = dec_list; + ret = tone_dec_list_play(dec, 0); + } else { + // 当前有播放,等播放完自动播放 + ret = true; + } + + os_mutex_post(&dec->mutex); + + return ret; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 提示音播放停止 + @param **ppdec: 提示音句柄 + @param push_event: 普通提示音是否推送消息 + @param end_flag: 结束类型 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void tone_dec_stop(struct tone_dec_handle **ppdec, + u8 push_event, + u8 end_flag) +{ + if (!ppdec || !*ppdec) { + return ; + } + struct tone_dec_handle *dec = *ppdec; + struct tone_dec_list_handle *p, *n; + + os_mutex_pend(&dec->mutex, 0); + + tone_dec_hdl_release(dec); + + list_for_each_entry_safe(p, n, &dec->head, list_entry) { + tone_dec_list_release(p, push_event, end_flag); + } + + os_mutex_post(&dec->mutex); + + free(dec); + + *ppdec = NULL; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 指定提示音播放停止 + @param **ppdec: 提示音句柄 + @param push_event: 普通提示音是否推送消息 + @param end_flag: 结束类型 + @return + @note 如果该提示音正在播,停止播放并且播放下一个。如果不在播放,只从链表中删除 +*/ +/*----------------------------------------------------------------------------*/ +void tone_dec_stop_spec_file(struct tone_dec_handle **ppdec, + char *file_name, + u8 push_event, + u8 end_flag) +{ + if (!ppdec || !*ppdec || !file_name) { + return ; + } + struct tone_dec_handle *dec = *ppdec; + struct tone_dec_list_handle *p, *n; + + os_mutex_pend(&dec->mutex, 0); + if (dec->cur_list) { + do { + if (IS_DEFAULT_SINE(file_name)) { + if (dec->cur_list->file_list[0] != file_name) { + break; + } + } else if (IS_DEFAULT_SINE(dec->cur_list->file_list[0])) { + break; + } else if (strcmp(dec->cur_list->file_list[0], file_name)) { + break; + } + // 当前正在播放,停止播放 + tone_dec_hdl_release(dec); + tone_dec_list_release(dec->cur_list, push_event, end_flag); + dec->cur_list = NULL; + // 检查链表播放 + struct list_head *list_entry = dec->head.next; + if (list_entry && (list_entry != &dec->head)) { + // 如果还有,则继续播放 + struct tone_dec_list_handle *dec_list = container_of(list_entry, struct tone_dec_list_handle, list_entry); + dec->cur_list = dec_list; + tone_dec_list_play(dec, 0); + os_mutex_post(&dec->mutex); + } else { + // 如果没有,释放 + os_mutex_post(&dec->mutex); + free(dec); + *ppdec = NULL; + } + return ; + } while (0); + } + + // 从链表中删除,不停止解码 + list_for_each_entry_safe(p, n, &dec->head, list_entry) { + do { + if (IS_DEFAULT_SINE(file_name)) { + if (dec->cur_list->file_list[0] != file_name) { + break; + } + } else if (IS_DEFAULT_SINE(dec->cur_list->file_list[0])) { + break; + } else if (strcmp(dec->cur_list->file_list[0], file_name)) { + break; + } + tone_dec_list_release(p, push_event, end_flag); + os_mutex_post(&dec->mutex); + return ; + } while (0); + } + + os_mutex_post(&dec->mutex); +} + + +#if 0 +static struct tone_dec_handle *test_tone_dec = NULL; +static struct audio_eq_drc *test_tone_eq_drc = NULL; + +extern void *file_eq_drc_open(u16 sample_rate, u8 ch_num); +extern void file_eq_drc_close(struct audio_eq_drc *eq_drc); + +static void tone_test_stream_resume(void *p) +{ + struct audio_dec_app_hdl *app_dec = p; + audio_decoder_resume(&app_dec->decoder); +} + +static void tone_test_stream_handler(void *priv, int event, struct audio_dec_app_hdl *app_dec) +{ + switch (event) { + case AUDIO_DEC_APP_EVENT_START_INIT_OK: + y_printf("AUDIO_DEC_APP_EVENT_START_INIT_OK \n"); + struct audio_stream_entry *entries[8] = {NULL}; + u8 entry_cnt = 0; + entries[entry_cnt++] = &app_dec->decoder.entry; + { + // add eq + test_tone_eq_drc = file_eq_drc_open(app_dec->sample_rate, app_dec->ch_num); + entries[entry_cnt++] = &test_tone_eq_drc->entry; + } + + entries[entry_cnt++] = &app_dec->mix_ch.entry; + app_dec->stream = audio_stream_open(app_dec, tone_test_stream_resume); + audio_stream_add_list(app_dec->stream, entries, entry_cnt); + break; + case AUDIO_DEC_APP_EVENT_DEC_CLOSE: + y_printf("AUDIO_DEC_APP_EVENT_DEC_CLOSE \n"); + { + // del eq + if (test_tone_eq_drc) { + file_eq_drc_close(test_tone_eq_drc); + test_tone_eq_drc = NULL; + } + } + break; + } +} + +static void tone_test_play_close(void) +{ + tone_dec_stop(&test_tone_dec, 0, 0); +} + +void tone_test_play(void) +{ + tone_test_play_close(); + test_tone_dec = tone_dec_create(); + static char *single_file[2] = {NULL}; + single_file[0] = (char *)TONE_POWER_OFF; + single_file[1] = NULL; + struct tone_dec_list_handle *dec_list = tone_dec_list_create(test_tone_dec, single_file, 1, NULL, NULL, tone_test_stream_handler, NULL); + tone_dec_list_add_play(test_tone_dec, dec_list); +} +#endif + + diff --git a/cpu/br23/audio_dec/audio_dec_tone.h b/cpu/br23/audio_dec/audio_dec_tone.h new file mode 100644 index 0000000..747b0e7 --- /dev/null +++ b/cpu/br23/audio_dec/audio_dec_tone.h @@ -0,0 +1,149 @@ + + +#ifndef _AUDIO_DEC_TONE_H_ +#define _AUDIO_DEC_TONE_H_ + +#include "asm/includes.h" +#include "media/includes.h" +#include "media/file_decoder.h" +#include "system/includes.h" +#include "media/audio_decoder.h" +#include "application/audio_dec_app.h" +#include "tone_player.h" + +// 提示音解码结束缘由 +#define TONE_DEC_STOP_NOR 0 // 正常播放关闭 +#define TONE_DEC_STOP_BY_OTHER_PLAY 1 // 被其他播放打断关闭 + +/* + * 用于保护file_list播放 + * 原理是在当前播放结束后先启动一个空的解码占住res, + * 避免播放file_list下一个时插入了其他解码 + */ +#define TONE_DEC_PROTECT_LIST_PLAY 1 + + +/* + * 提示音file_list解码结构体 + * 依次播放"char **file_list"变量中定义的文件,直到file_list[n]为NULL + * 如 file_list[0]=123.*; file_list[1]=456.*; file_list[2]=NULL; + * 支持文件名解码、正弦波数组参数解码(需要实现get_sine()接口获取参数) + * 正弦波数组播放格式示例:file_list[n]=DEFAULT_SINE_TONE(SINE_WTONE_NORAML); + * 支持循环播放,循环播放需要指定播放起始(参数是代表循环次数)和结束, + * 如:file_list[n]=TONE_REPEAT_BEGIN(-1); file_list[n+1]=456.*; file_list[n+2]=TONE_REPEAT_END(); + * 当需要使用外部自定义数据流时,可以通过实现*stream_handler接口来处理 + */ +struct tone_dec_list_handle { + struct list_head list_entry; // 链表 + u8 preemption : 1; // 打断 + u8 idx; // 循环播放序号 + u8 repeat_begin; // 循环播放起始序号 + u8 dec_ok_cnt; // 正常播放计数 + u16 loop; // 循环播放次数 + int sync_confirm_time; + char **file_list; // 文件名 + const char *evt_owner; // 事件接受任务 + void (*evt_handler)(void *priv, int flag); // 事件回调 + void *evt_priv; // 事件回调私有句柄 + void (*stream_handler)(void *priv, int event, struct audio_dec_app_hdl *); // 数据流设置回调 + void *stream_priv; // 数据流设置回调私有句柄 +#if TONE_DEC_PROTECT_LIST_PLAY + void *list_protect; +#endif +}; + +/* + * 提示音解码结构体 + * 可以实现多个tone_dec_list_handle播放,通过结构体中的链表连接 + * 当解码中有正弦波数组播放时,必须要实现*get_sine接口 + */ +struct tone_dec_handle { + struct list_head head; // 链表头 + struct audio_dec_sine_app_hdl *dec_sin; // 文件播放句柄 + struct audio_dec_file_app_hdl *dec_file; // sine播放句柄 + struct tone_dec_list_handle *cur_list; // 当前播放list + struct sin_param *(*get_sine)(u8 id, u8 *num); // 按序列号获取sine数组 + OS_MUTEX mutex; // 互斥 +}; + +/*----------------------------------------------------------------------------*/ +/**@brief 创建提示音播放句柄 + @param + @return 提示音句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +struct tone_dec_handle *tone_dec_create(void); + +/*----------------------------------------------------------------------------*/ +/**@brief 设置sine数组获取回调 + @param *dec: 提示音句柄 + @param *get_sine: sine数组获取 + @return + @note 当解码中有正弦波数组播放时,必须设置该接口 +*/ +/*----------------------------------------------------------------------------*/ +void tone_dec_set_sin_get_hdl(struct tone_dec_handle *dec, struct sin_param * (*get_sine)(u8 id, u8 *num)); + +/*----------------------------------------------------------------------------*/ +/**@brief 创建提示音播放list句柄 + @param *dec: 提示音句柄 + @param **file_list: 文件名 + @param preemption: 打断标记 + @param *evt_handler: 事件回调接口 + @param *evt_priv: 事件回调私有句柄 + @param *stream_handler: tone数据流设置回调 + @param *stream_priv: tone数据流设置回调私有句柄 + @return list句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +struct tone_dec_list_handle *tone_dec_list_create(struct tone_dec_handle *dec, + const char **file_list, + u8 preemption, + void (*evt_handler)(void *priv, int flag), + void *evt_priv, + void (*stream_handler)(void *priv, int event, struct audio_dec_app_hdl *app_dec), + void *stream_priv); + +/*----------------------------------------------------------------------------*/ +/**@brief 提示音list开始播放 + @param *dec: 提示音句柄 + @param *dec_list: list句柄 + @return true: 成功 + @return false: 成功 + @note 当前没有播放,马上开始播放。当前有播放,挂载到链表后面等待播放 +*/ +/*----------------------------------------------------------------------------*/ +int tone_dec_list_add_play(struct tone_dec_handle *dec, struct tone_dec_list_handle *dec_list); + +/*----------------------------------------------------------------------------*/ +/**@brief 提示音播放停止 + @param **ppdec: 提示音句柄 + @param push_event: 普通提示音是否推送消息 + @param end_flag: 结束类型 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void tone_dec_stop(struct tone_dec_handle **ppdec, + u8 push_event, + u8 end_flag); + +/*----------------------------------------------------------------------------*/ +/**@brief 指定提示音播放停止 + @param **ppdec: 提示音句柄 + @param push_event: 普通提示音是否推送消息 + @param end_flag: 结束类型 + @return + @note 如果该提示音正在播,停止播放并且播放下一个。如果不在播放,只从链表中删除 +*/ +/*----------------------------------------------------------------------------*/ +void tone_dec_stop_spec_file(struct tone_dec_handle **ppdec, + char *file_name, + u8 push_event, + u8 end_flag); + + +#endif /*_AUDIO_DEC_TONE_H_*/ + diff --git a/cpu/br23/audio_dec/audio_spectrum.c b/cpu/br23/audio_dec/audio_spectrum.c new file mode 100644 index 0000000..2baabe9 --- /dev/null +++ b/cpu/br23/audio_dec/audio_spectrum.c @@ -0,0 +1,83 @@ +#include "audio_spectrum.h" + + +#if AUDIO_SPECTRUM_CONFIG +/*----------------------------------------------------------------------------*/ +/**@brief 频响输出例子 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void spectrum_get_demo(void *p) +{ + spectrum_fft_hdl *hdl = p; + if (hdl) { + u8 db_num = audio_spectrum_fft_get_num(hdl);//获取频谱个数 + short *db_data = audio_spectrum_fft_get_val(hdl);//获取存储频谱值得地址 + if (!db_data) { + return; + } + for (int i = 0; i < db_num; i++) { + //输出db_num个 db值 + printf("db_data db[%d] %d\n", i, db_data[i]); + } + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 打开频响统计 + @param sr:采样率 + @return hdl:句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +spectrum_fft_hdl *spectrum_open_demo(u32 sr, u8 channel) +{ + spectrum_fft_hdl *hdl = NULL; + spectrum_fft_open_parm parm = {0}; + parm.sr = sr; + parm.channel = channel; + parm.attackFactor = 0.9; + parm.releaseFactor = 0.9; + parm.mode = 2; + hdl = audio_spectrum_fft_open(&parm); + /* int ret = sys_timer_add(hdl, spectrum_get_demo, 500);//频谱值获取测试 */ + clock_add(SPECTRUM_CLK); + return hdl; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭频响统计 + @param hdl:句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void spectrum_close_demo(spectrum_fft_hdl *hdl) +{ + audio_spectrum_fft_close(hdl); + clock_remove(SPECTRUM_CLK); +} + + +spectrum_fft_hdl *spec_hdl; +/*----------------------------------------------------------------------------*/ +/**@brief 切换频响计算 + @param en:0 不做频响计算, 1 使能频响计算(通话模式,需关闭频响计算) + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void spectrum_switch_demo(u8 en) +{ + if (spec_hdl) { + audio_spectrum_fft_switch(spec_hdl, en); + } +} + + +#else +void spectrum_switch_demo(u8 en) +{ +} +#endif diff --git a/cpu/br23/audio_dec/audio_spectrum.h b/cpu/br23/audio_dec/audio_spectrum.h new file mode 100644 index 0000000..3c17ee7 --- /dev/null +++ b/cpu/br23/audio_dec/audio_spectrum.h @@ -0,0 +1,52 @@ +#ifndef _AUDIO_SPECTRUM_H_ +#define _AUDIO_SPECTRUM_H_ + +#include "app_config.h" +#include "clock_cfg.h" +#include "media/includes.h" +#include "asm/includes.h" +#include "spectrum/spectrum_eq.h" +#include "spectrum/spectrum_fft.h" + + +/*----------------------------------------------------------------------------*/ +/**@brief 打开频响统计 + @param sr:采样率 + @return hdl:句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +spectrum_fft_hdl *spectrum_open_demo(u32 sr, u8 channel); + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭频响统计 + @param hdl:句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void spectrum_close_demo(spectrum_fft_hdl *hdl); + +/*----------------------------------------------------------------------------*/ +/**@brief 频响输出例子 + @return + @note 如何获取频谱值,参考该函数 +*/ +/*----------------------------------------------------------------------------*/ +void spectrum_get_demo(void *p); + + +/*----------------------------------------------------------------------------*/ +/**@brief 切换频响计算 + @param en:0 不做频响计算, 1 使能频响计算(通话模式,需关闭频响计算) + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void spectrum_switch_demo(u8 en); + +#endif + + + + diff --git a/cpu/br23/audio_dec/audio_sync.c b/cpu/br23/audio_dec/audio_sync.c new file mode 100644 index 0000000..fdf82b5 --- /dev/null +++ b/cpu/br23/audio_dec/audio_sync.c @@ -0,0 +1,466 @@ +#include "board_config.h" +#include "asm/dac.h" +#include "audio_common/audio_iis.h" +#include "media/includes.h" +#include "effectrs_sync.h" +#include "asm/gpio.h" + + +extern struct audio_dac_hdl dac_hdl; +extern int bt_media_sync_master(u8 type); +extern u8 bt_media_device_online(u8 dev); +extern void *bt_media_sync_open(void); +extern void bt_media_sync_close(void *); +extern int bt_send_audio_sync_data(void *, void *buf, u32 len); +extern void bt_media_sync_set_handler(void *, void *priv, + void (*event_handler)(void *, int *, int)); +extern u32 get_bt_slot_time(u8 type, u32 time, int *ret_time, int (*local_us_time)(void)); + + +const static struct audio_tws_conn_ops tws_conn_ops = { + .open = bt_media_sync_open, + .set_handler = bt_media_sync_set_handler, + .close = bt_media_sync_close, + .master = bt_media_sync_master, + .online = bt_media_device_online, + .send = bt_send_audio_sync_data, +}; + + +extern struct audio_dac_channel default_dac; +struct audio_wireless_sync *a2dp_output_sync_open(int sample_rate, int output_sample_rate, u8 channels) +{ + struct audio_wireless_sync_info info = {0}; + struct audio_sample_sync *sample_sync; + struct audio_wireless_sync *a2dp_sync; + + a2dp_sync = (struct audio_wireless_sync *)zalloc(sizeof(struct audio_wireless_sync)); + if (!a2dp_sync) { + return NULL; + } + + sample_sync = audio_sample_sync_open(0); + + /*选择SYNC模块接入到DAC内部*/ + /*audio_dac_add_sample_sync(&dac_hdl, sample_sync, 1);*/ + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) + audio_iis_channel_sync_enable(sample_sync); + info.target = AUDIO_SYNC_TARGET_IIS; +#else + audio_dac_channel_sync_enable(&default_dac, sample_sync); + info.target = AUDIO_SYNC_TARGET_DAC; +#endif + + info.tws_ops = &tws_conn_ops; + info.sample_ch = sample_sync; + info.protocol = WL_PROTOCOL_RTP; + info.sample_rate = sample_rate; + info.output_rate = output_sample_rate; + info.channel = channels; + + a2dp_sync->context = audio_wireless_sync_open(&info, &a2dp_sync->entry); + + a2dp_sync->sample_sync = sample_sync; + a2dp_sync->resample_entry = &sample_sync->entry; + + return a2dp_sync; +} + +void a2dp_output_sync_close(struct audio_wireless_sync *a2dp_sync) +{ + if (a2dp_sync) { + audio_stream_del_entry(a2dp_sync->entry); + audio_stream_del_entry(a2dp_sync->resample_entry); + audio_wireless_sync_close(a2dp_sync->context); + /*audio_dac_remove_sample_sync(&dac_hdl, a2dp_sync->sample_sync);*/ + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) + audio_iis_channel_sync_disable(a2dp_sync->sample_sync); +#else + audio_dac_channel_sync_disable(&default_dac, a2dp_sync->sample_sync); +#endif + + audio_sample_sync_close(a2dp_sync->sample_sync); + free(a2dp_sync); + } +} + +struct audio_wireless_sync *esco_output_sync_open(int sample_rate, int output_sample_rate, u8 channels) +{ + struct audio_wireless_sync_info info = {0}; + struct audio_sample_sync *sample_sync; + struct audio_wireless_sync *esco_sync; + + esco_sync = (struct audio_wireless_sync *)zalloc(sizeof(struct audio_wireless_sync)); + if (!esco_sync) { + return NULL; + } + + sample_sync = audio_sample_sync_open(0); + + /*选择SYNC模块接入到DAC内部*/ + /*audio_dac_add_sample_sync(&dac_hdl, sample_sync, 1);*/ + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) + audio_iis_channel_sync_enable(sample_sync); + info.target = AUDIO_SYNC_TARGET_IIS; +#else + audio_dac_channel_sync_enable(&default_dac, sample_sync); + info.target = AUDIO_SYNC_TARGET_DAC; +#endif + + info.tws_ops = &tws_conn_ops; + info.sample_ch = sample_sync; + info.protocol = WL_PROTOCOL_SCO; + info.sample_rate = sample_rate; + info.output_rate = output_sample_rate; + info.channel = channels; + + esco_sync->context = audio_wireless_sync_open(&info, &esco_sync->entry); + + esco_sync->sample_sync = sample_sync; + esco_sync->resample_entry = &sample_sync->entry; + + return esco_sync; +} + +void esco_output_sync_close(struct audio_wireless_sync *esco_sync) +{ + if (esco_sync) { + audio_stream_del_entry(esco_sync->entry); + audio_stream_del_entry(esco_sync->resample_entry); + audio_wireless_sync_close(esco_sync->context); + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) + audio_iis_channel_sync_disable(esco_sync->sample_sync); +#else + audio_dac_channel_sync_disable(&default_dac, esco_sync->sample_sync); +#endif + + /*audio_dac_remove_sample_sync(&dac_hdl, esco_sync->sample_sync);*/ + audio_sample_sync_close(esco_sync->sample_sync); + free(esco_sync); + } +} + +#if TCFG_DEC2TWS_ENABLE + +#include "classic/tws_api.h" + +extern int tws_api_local_media_trans_get_total_buffer_size(void); + +extern u8 is_tws_active_device(void); + +static u8 local_tws_media_sync_no_check = 0; +void local_tws_sync_no_check_data_buf(u8 no_check) +{ + local_tws_media_sync_no_check = no_check; +} + +u8 local_tws_sync_no_check_data_buf_status(void) +{ + return local_tws_media_sync_no_check; +} + +int local_bt_media_sync_master(u8 type) +{ + int state = tws_api_get_tws_state(); + if (!(state & TWS_STA_SIBLING_CONNECTED)) { + return 1; + } + return is_tws_active_device() ? 1 : 0; +} + +u8 local_bt_media_device_online(u8 type) +{ + return bt_media_device_online(type); +} + +const static struct audio_tws_conn_ops local_tws_conn_ops = { + .open = bt_media_sync_open, + .set_handler = bt_media_sync_set_handler, + .close = bt_media_sync_close, + .master = local_bt_media_sync_master, + .online = local_bt_media_device_online, + .send = bt_send_audio_sync_data, +}; + +struct audio_wireless_sync *audio_localtws_sync_open(int sample_rate, int output_sample_rate, u8 channels) +{ + struct audio_wireless_sync_info info = {0}; + struct audio_sample_sync *sample_sync; + struct audio_wireless_sync *localtws_sync; + + localtws_sync = (struct audio_wireless_sync *)zalloc(sizeof(struct audio_wireless_sync)); + if (!localtws_sync) { + return NULL; + } + + sample_sync = audio_sample_sync_open(0); + /*选择SYNC模块接入到DAC内部*/ + /*audio_dac_add_sample_sync(&dac_hdl, sample_sync, 1);*/ + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) + audio_iis_channel_sync_enable(sample_sync); + info.target = AUDIO_SYNC_TARGET_IIS; +#else + audio_dac_channel_sync_enable(&default_dac, sample_sync); + info.target = AUDIO_SYNC_TARGET_DAC; +#endif + + info.tws_ops = &local_tws_conn_ops; + info.sample_ch = sample_sync; + info.protocol = WL_PROTOCOL_RTP; + info.sample_rate = sample_rate; + info.output_rate = output_sample_rate; + info.channel = channels; + + localtws_sync->context = audio_wireless_sync_open(&info, &localtws_sync->entry); + + localtws_sync->sample_sync = sample_sync; + localtws_sync->resample_entry = &sample_sync->entry; + + return localtws_sync; +} + +void audio_localtws_sync_close(struct audio_wireless_sync *localtws_sync) +{ + if (localtws_sync) { + audio_stream_del_entry(localtws_sync->resample_entry); + audio_stream_del_entry(localtws_sync->entry); + audio_wireless_sync_close(localtws_sync->context); + /*audio_dac_remove_sample_sync(&dac_hdl, localtws_sync->sample_sync);*/ + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_IIS) + audio_iis_channel_sync_disable(localtws_sync->sample_sync); +#else + audio_dac_channel_sync_disable(&default_dac, localtws_sync->sample_sync); +#endif + audio_sample_sync_close(localtws_sync->sample_sync); + free(localtws_sync); + } +} +#if 0 +void *local_tws_play_sync_open(struct audio_decoder *dec, u8 channel, u32 sample_rate, u32 output_rate) +{ + struct audio_wireless_sync_info sync_param; + /*int total_size = tws_api_local_media_trans_get_total_buffer_size();*/ + + sync_param.channel = channel; + sync_param.tws_ops = &local_tws_conn_ops; + sync_param.sample_rate = sample_rate; + sync_param.output_rate = output_rate; + sync_param.reset_enable = 0; + +#if 0 + if (local_tws_media_sync_no_check) { + sync_param.data_top = total_size; + sync_param.data_bottom = 0; + } else { + sync_param.data_top = 70 * total_size / 100; + sync_param.data_bottom = 60 * total_size / 100; + } + sync_param.begin_size = 50 * total_size / 100; + sync_param.tws_together_time = SYNC_START_TIME; + printf("tws sync begin:%d, top:%d, bottom:%d \n", sync_param.begin_size, sync_param.data_top, sync_param.data_bottom); +#endif + + sync_param.protocol = WL_PROTOCOL_RTP; +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) + sync_param.target = AUDIO_SYNC_TARGET_FM; + sync_param.dev = NULL; +#else + sync_param.target = AUDIO_SYNC_TARGET_DAC; + sync_param.dev = &dac_hdl; +#endif + + return audio_wireless_sync_open(&sync_param); +} +#endif +#endif + + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) +#define FM_EMIT_BOTTOM 40 +#define FM_EMIT_TOP 70 +#define MAX_STEP 5 +#define ONE_STEP_SIZE 512 + +#define FM_SYNC_SRC_OUTPUT_SIZE (256 + 16) +#define FM_SYNC_SRC_INPUT_SIZE (256) +#define MAX_COUNT_FOR_ADJUST 1 +#define MAX_ADJUST_STEP 20 +#define ABS(x) (x > 0 ? x : (-x)) + +struct local_fm_sync_handle { + int top_size; + int bottom_size; + u16 sample_rate; + u16 out_rate; + u16 base_out_rate; + u8 channel; + s8 step_dir_count; + void *src; + void *output_addr; + void *input_addr; + int output_len; +}; + +static int local_fm_sync_event_handler(void *priv, enum audio_src_event event, void *arg) +{ + struct local_fm_sync_handle *fm_sync = (struct local_fm_sync_handle *)priv; + struct audio_src_buffer *b = (struct audio_src_buffer *)arg; + + switch (event) { + case SRC_EVENT_GET_OUTPUT_BUF: + b->addr = fm_sync->output_addr; + b->len = FM_SYNC_SRC_OUTPUT_SIZE; + break; + case SRC_EVENT_OUTPUT_DONE: + case SRC_EVENT_INPUT_DONE: + case SRC_EVENT_ALL_DONE: + ASSERT(b->len < FM_SYNC_SRC_OUTPUT_SIZE, ", fm sync output err : %d\n", b->len); + fm_sync->output_len = b->len; + break; + default: + break; + } + + return 0; +} + +void *local_fm_sync_open(u16 sample_rate, u16 output_rate, u8 channel, u32 total_size) +{ + struct local_fm_sync_handle *fm_sync; + + fm_sync = (struct local_fm_sync_handle *)zalloc(sizeof(struct local_fm_sync_handle)); + if (!fm_sync) { + return NULL; + } + + fm_sync->top_size = total_size * FM_EMIT_TOP / 100; + fm_sync->bottom_size = total_size * FM_EMIT_BOTTOM / 100; + fm_sync->sample_rate = sample_rate; + fm_sync->out_rate = output_rate; + fm_sync->base_out_rate = output_rate; + fm_sync->channel = channel; + if (!fm_sync->src) { + fm_sync->src = zalloc(sizeof(struct audio_src_base_handle)); + + if (!fm_sync->src) { + goto __err; + } + } + fm_sync->input_addr = zalloc(FM_SYNC_SRC_INPUT_SIZE); + if (!fm_sync->input_addr) { + goto __err1; + } + fm_sync->output_addr = zalloc(FM_SYNC_SRC_OUTPUT_SIZE); + if (!fm_sync->output_addr) { + goto __err2; + } + + audio_src_base_open(fm_sync->src, channel, SRC_TYPE_AUDIO_SYNC); + + audio_src_base_set_rate(fm_sync->src, sample_rate, sample_rate); + + audio_src_base_set_event_handler(fm_sync->src, fm_sync, local_fm_sync_event_handler); + + audio_src_base_set_input_buff(fm_sync->src, fm_sync->input_addr, FM_SYNC_SRC_INPUT_SIZE); + + return fm_sync; + +__err2: + free(fm_sync->input_addr); +__err1: + free(fm_sync->src); +__err: + free(fm_sync); + return NULL; +} + +int local_fm_sync_by_emitter(void *sync, void *data, int len, int emitter_data_len) +{ + struct local_fm_sync_handle *fm_sync = (struct local_fm_sync_handle *)sync; + int diff = 0; + s8 step = 0; + + if (emitter_data_len < fm_sync->bottom_size) { + diff = fm_sync->bottom_size - emitter_data_len; + step = 1; + } else if (emitter_data_len > fm_sync->top_size) { + diff = fm_sync->top_size - emitter_data_len; + step = -1; + } else { + if (fm_sync->out_rate < fm_sync->base_out_rate) { + step = 1; + } else if (fm_sync->out_rate > fm_sync->base_out_rate) { + step = -1; + } + } + + step += diff / 512; + if (step < 0) { + fm_sync->step_dir_count--; + } else if (step > 0) { + fm_sync->step_dir_count++; + } else { + if (fm_sync->step_dir_count < 0) { + fm_sync->step_dir_count++; + } else if (fm_sync->step_dir_count > 0) { + fm_sync->step_dir_count--; + } + } + + if (ABS(fm_sync->step_dir_count) >= MAX_COUNT_FOR_ADJUST) { + fm_sync->out_rate += step; + if (fm_sync->out_rate < fm_sync->base_out_rate - MAX_ADJUST_STEP) { + fm_sync->out_rate = fm_sync->base_out_rate - MAX_ADJUST_STEP; + } else if (fm_sync->out_rate > fm_sync->base_out_rate + MAX_ADJUST_STEP) { + fm_sync->out_rate = fm_sync->base_out_rate + MAX_ADJUST_STEP; + } + /*printf("--%d--\n", fm_sync->out_rate);*/ + audio_src_base_set_rate(fm_sync->src, fm_sync->sample_rate, fm_sync->out_rate); + fm_sync->step_dir_count = 0; + } + + audio_src_base_write(fm_sync->src, data, len); + audio_src_base_data_flush_out(fm_sync->src); + + /*printf("%d - %d - %d\n", len, fm_sync->output_len, step);*/ + return fm_sync->output_len; +} + +void *local_fm_sync_output_addr(void *sync) +{ + struct local_fm_sync_handle *fm_sync = (struct local_fm_sync_handle *)sync; + + return fm_sync->output_addr; +} + +void local_fm_sync_close(void *sync) +{ + struct local_fm_sync_handle *fm_sync = (struct local_fm_sync_handle *)sync; + if (!fm_sync) { + return; + } + + if (fm_sync->src) { + audio_src_base_stop(fm_sync->src); + audio_src_base_close(fm_sync->src); + free(fm_sync->src); + } + + if (fm_sync->input_addr) { + free(fm_sync->input_addr); + } + + if (fm_sync->output_addr) { + free(fm_sync->output_addr); + } + + free(fm_sync); +} + +#endif diff --git a/cpu/br23/audio_dec/audio_usb_mic.c b/cpu/br23/audio_dec/audio_usb_mic.c new file mode 100644 index 0000000..24686ef --- /dev/null +++ b/cpu/br23/audio_dec/audio_usb_mic.c @@ -0,0 +1,568 @@ +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "audio_enc.h" +#include "app_main.h" +#include "app_config.h" +#include "audio_splicing.h" +#include "media/audio_echo_reverb.h" + +/*usb mic的数据是否经过AEC,包括里面的ANS模块*/ +#define USB_MIC_AEC_EN 0 +/*AEC模块只能处理16k数据,如果经过aec,就需要对输出数据做变采样*/ +#define USB_MIC_SRC_ENABLE 1 + +#if USB_MIC_AEC_EN +#include "aec_user.h" +#endif/*USB_MIC_AEC_EN*/ + +#if TCFG_APP_PC_EN +#include "device/uac_stream.h" + +#define PCM_ENC2USB_OUTBUF_LEN (4 * 1024) + +/* #define USB_MIC_BUF_NUM 3 */ +/* #define USB_MIC_CH_NUM 1 */ +/* #define USB_MIC_IRQ_POINTS 1//256 */ +/* #define USB_MIC_BUFS_SIZE (USB_MIC_CH_NUM * USB_MIC_BUF_NUM * USB_MIC_IRQ_POINTS) */ + +#define USB_MIC_STOP 0x00 +#define USB_MIC_START 0x01 + +extern struct audio_adc_hdl adc_hdl; +extern u16 uac_get_mic_vol(const u8 usb_id); + +struct _usb_mic_hdl { + struct audio_adc_output_hdl adc_output; + struct adc_mic_ch mic_ch; + struct audio_adc_ch linein_ch; +#if SOUNDCARD_ENABLE //4取1 + s16 *temp_buf; + u32 temp_buf_len; +#endif + enum enc_source source; + + cbuffer_t output_cbuf; + u8 *output_buf;//[PCM_ENC2USB_OUTBUF_LEN]; + u8 rec_tx_channels; + u8 mic_data_ok;/*mic数据等到一定长度再开始发送*/ + u8 status; + u8 mic_busy; +#if TCFG_USB_MIC_ECHO_ENABLE + ECHO_API_STRUCT *p_echo_hdl; +#endif +}; + +static struct _usb_mic_hdl *usb_mic_hdl = NULL; +#if TCFG_USB_MIC_ECHO_ENABLE +ECHO_PARM_SET usbmic_echo_parm_default = { + .delay = 200, //回声的延时时间 0-300ms + .decayval = 50, // 0-70% + .direct_sound_enable = 1, //直达声使能 0/1 + .filt_enable = 1, //发散滤波器使能 +}; +EF_REVERB_FIX_PARM usbmic_echo_fix_parm_default = { + .wetgain = 2048, ////湿声增益:[0:4096] + .drygain = 4096, ////干声增益: [0:4096] + .sr = MIC_EFFECT_SAMPLERATE, ////采样率 + .max_ms = 200, ////所需要的最大延时,影响 need_buf 大小 +}; +#endif +static int usb_audio_mic_sync(u32 data_size) +{ +#if 0 + int change_point = 0; + + if (data_size > __this->rec_top_size) { + change_point = -1; + } else if (data_size < __this->rec_bottom_size) { + change_point = 1; + } + + if (change_point) { + struct audio_pcm_src src; + src.resample = 0; + src.ratio_i = (1024) * 2; + src.ratio_o = (1024 + change_point) * 2; + src.convert = 1; + dev_ioctl(__this->rec_dev, AUDIOC_PCM_RATE_CTL, (u32)&src); + } +#endif + + return 0; +} +static int usb_audio_mic_tx_handler(int event, void *data, int len) +{ + if (usb_mic_hdl == NULL) { + return 0; + } + if (usb_mic_hdl->status == USB_MIC_STOP) { + return 0; + } + + int i = 0; + int r_len = 0; + u8 ch = 0; + u8 double_read = 0; + + int rlen = 0; + + if (usb_mic_hdl->mic_data_ok == 0) { + if (usb_mic_hdl->output_cbuf.data_len > (PCM_ENC2USB_OUTBUF_LEN / 4)) { + usb_mic_hdl->mic_data_ok = 1; + } else { + //y_printf("mic_tx NULL\n"); + memset(data, 0, len); + return 0; + } + } + + /* usb_audio_mic_sync(size); */ + if (usb_mic_hdl->rec_tx_channels == 2) { + rlen = cbuf_get_data_size(&usb_mic_hdl->output_cbuf); + if (rlen) { + rlen = rlen > (len / 2) ? (len / 2) : rlen; + rlen = cbuf_read(&usb_mic_hdl->output_cbuf, data, rlen); + } else { + /* printf("uac read err1\n"); */ + usb_mic_hdl->mic_data_ok = 0; + return 0; + } + + len = rlen * 2; + s16 *tx_pcm = (s16 *)data; + int cnt = len / 2; + for (cnt = len / 2; cnt >= 2;) { + tx_pcm[cnt - 1] = tx_pcm[cnt / 2 - 1]; + tx_pcm[cnt - 2] = tx_pcm[cnt / 2 - 1]; + cnt -= 2; + } + rlen = len; + } else { + rlen = cbuf_get_data_size(&usb_mic_hdl->output_cbuf); + if (rlen) { + rlen = rlen > len ? len : rlen; + rlen = cbuf_read(&usb_mic_hdl->output_cbuf, data, rlen); + } else { + /* printf("uac read err2\n"); */ + usb_mic_hdl->mic_data_ok = 0; + return 0; + } + } + return rlen; +} + + + + +int usb_audio_mic_write_do(void *data, u16 len) +{ + int wlen = len; + if (usb_mic_hdl && usb_mic_hdl->status == USB_MIC_START) { + usb_mic_hdl->mic_busy = 1; + +#if SOUNDCARD_ENABLE //4取1 + if (usb_mic_hdl->temp_buf) { + if (usb_mic_hdl->temp_buf_len < len / 4) { + free(usb_mic_hdl->temp_buf); + usb_mic_hdl->temp_buf = NULL; + } + } + + if (!usb_mic_hdl->temp_buf) { + usb_mic_hdl->temp_buf_len = len / 4; + usb_mic_hdl->temp_buf = (s16 *) zalloc(usb_mic_hdl->temp_buf_len); + } + s16 *temp_pcm = (s16 *)data; + for (int cnt = 0; cnt < len / 8; cnt++) { + usb_mic_hdl->temp_buf[cnt] = temp_pcm[cnt * 4 + 2];//取RL通道 + } + len = len / 4; + wlen = cbuf_write(&usb_mic_hdl->output_cbuf, usb_mic_hdl->temp_buf, len); +#else + + wlen = cbuf_write(&usb_mic_hdl->output_cbuf, data, len); +#endif //SOUNDCARD_ENABLE + +#if 0 + static u32 usb_mic_data_max = 0; + if (usb_mic_data_max < usb_mic_hdl->output_cbuf.data_len) { + usb_mic_data_max = usb_mic_hdl->output_cbuf.data_len; + y_printf("usb_mic_max:%d", usb_mic_data_max); + } +#endif + if (wlen != (len)) { + putchar('L'); + //r_printf("usb_mic write full:%d-%d\n", wlen, len); + } + usb_mic_hdl->mic_busy = 0; + } + return wlen; +} + + + +int usb_audio_mic_write(void *data, u16 len) +{ + pcm_dual_to_single(data, data, len); + int wlen = usb_audio_mic_write_do(data, len / 2); + return wlen; +} + +static void adc_output_to_cbuf(void *priv, s16 *data, int len) +{ + if (usb_mic_hdl == NULL) { + return ; + } + if (usb_mic_hdl->status == USB_MIC_STOP) { + return ; + } + + switch (usb_mic_hdl->source) { + case ENCODE_SOURCE_MIC: + case ENCODE_SOURCE_LINE0_LR: + case ENCODE_SOURCE_LINE1_LR: + case ENCODE_SOURCE_LINE2_LR: { +#if USB_MIC_AEC_EN + audio_aec_inbuf(data, len); +#else +#if TCFG_USB_MIC_ECHO_ENABLE + if (usb_mic_hdl->p_echo_hdl) { + run_echo(usb_mic_hdl->p_echo_hdl, data, data, len); + } +#endif + int wlen = cbuf_write(&usb_mic_hdl->output_cbuf, data, len); + if (wlen != len) { + printf("wlen %d len %d\n", wlen, len); + } +#endif + } + break; + default: + break; + } +} + +#if USB_MIC_SRC_ENABLE +#include "common/Resample_api.h" +typedef struct { + u8 start; + u8 busy; + u16 output_rate; + u32 *runbuf; + s16 output[320 * 3 + 16]; + RS_STUCT_API *ops; +} usb_mic_sw_src_t; +static usb_mic_sw_src_t *usb_mic_src = NULL; + +static int sw_src_init(u32 in_sr, u32 out_sr) +{ + usb_mic_src = zalloc(sizeof(usb_mic_sw_src_t)); + ASSERT(usb_mic_src); + usb_mic_src->ops = get_rs16_context(); + ASSERT(usb_mic_src->ops); + u32 need_buf = usb_mic_src->ops->need_buf(); + printf("sw_src need_buf:%d\n", need_buf); + usb_mic_src->runbuf = zalloc(need_buf); + ASSERT(usb_mic_src->runbuf); + + RS_PARA_STRUCT rs_para_obj; + rs_para_obj.nch = 1; + rs_para_obj.new_insample = in_sr; + rs_para_obj.new_outsample = out_sr; + printf("sw src,in = %d,out = %d\n", rs_para_obj.new_insample, rs_para_obj.new_outsample); + usb_mic_src->ops->open(usb_mic_src->runbuf, &rs_para_obj); + usb_mic_src->start = 1; + return 0; +} + +static int sw_src_exit(void) +{ + if (usb_mic_src) { + usb_mic_src->start = 0; + while (usb_mic_src->busy) { + putchar('w'); + os_time_dly(2); + } + local_irq_disable(); + if (usb_mic_src->runbuf) { + free(usb_mic_src->runbuf); + } + free(usb_mic_src); + local_irq_enable(); + printf("sw_src_exit\n"); + } + printf("sw_src_exit ok\n"); + return 0; +} +#endif/*USB_MIC_SRC_ENABLE*/ + +static int usb_mic_aec_output(s16 *data, u16 len) +{ + //putchar('k'); + if (usb_mic_hdl == NULL) { + return len ; + } + if (usb_mic_hdl->status == USB_MIC_STOP) { + return len; + } + + u16 olen = len; + s16 *obuf = data; + +#if USB_MIC_SRC_ENABLE + if (usb_mic_src && usb_mic_src->start) { + usb_mic_src->busy = 1; + int outlen = usb_mic_src->ops->run(usb_mic_src->runbuf, data, len >> 1, usb_mic_src->output); + usb_mic_src->busy = 0; + ASSERT(outlen <= (sizeof(usb_mic_src->output) >> 1)); + /* printf("16->48k:%d,%d,%d\n",len >> 1,outlen,sizeof(sw_src->output)); */ + obuf = usb_mic_src->output; + olen = outlen << 1; + } +#endif/*USB_MIC_SRC_ENABLE*/ + + usb_audio_mic_write_do(obuf, olen); + return len; +} + +int uac_mic_vol_switch(int vol) +{ + return vol * 14 / 100; +} + +int usb_audio_mic_open(void *_info) +{ + printf("usb_audio_mic_open -----------------------------------------------------\n"); + if (usb_mic_hdl) { + return 0; + } + struct _usb_mic_hdl *hdl = NULL; + hdl = zalloc(sizeof(struct _usb_mic_hdl)); + if (!hdl) { + return -EFAULT; + } + + local_irq_disable(); + usb_mic_hdl = hdl; + local_irq_enable(); + + hdl->status = USB_MIC_STOP; +#if 0 + hdl->adc_buf = zalloc(USB_MIC_BUFS_SIZE * 2); + if (!hdl->adc_buf) { + printf("hdl->adc_buf NULL\n"); + if (hdl) { + free(hdl); + hdl = NULL; + } + return -EFAULT; + } +#endif + hdl->output_buf = zalloc(PCM_ENC2USB_OUTBUF_LEN); + if (!hdl->output_buf) { + printf("hdl->output_buf NULL\n"); + /* if (hdl->adc_buf) { */ + /* free(hdl->adc_buf); */ + /* } */ + if (hdl) { + free(hdl); + hdl = NULL; + } + return -EFAULT; + } + + u32 sample_rate = (u32)_info & 0xFFFFFF; + u32 output_rate = sample_rate; + hdl->rec_tx_channels = (u32)_info >> 24; + hdl->source = ENCODE_SOURCE_MIC; + printf("usb mic sr:%d ch:%d\n", sample_rate, hdl->rec_tx_channels); + +#if USB_MIC_AEC_EN + printf("usb mic sr[aec]:%d\n", sample_rate); + sample_rate = 16000; +#if USB_MIC_SRC_ENABLE + sw_src_init(sample_rate, output_rate); +#endif/*USB_MIC_SRC_ENABLE*/ + //audio_aec_init(sample_rate); + audio_aec_open(sample_rate, ANS_EN, usb_mic_aec_output); +#endif/*USB_MIC_AEC_EN*/ + + cbuf_init(&hdl->output_cbuf, hdl->output_buf, PCM_ENC2USB_OUTBUF_LEN); +#if (SOUNDCARD_ENABLE) + ///从mix output哪里获取usb mic上行数据 +#if(TCFG_USB_MIC_DATA_FROM_DAC) + mic_effect_to_usbmic_onoff(1); +#endif//TCFG_USB_MIC_DATA_FROM_DAC +#else + +#if TCFG_MIC_EFFECT_ENABLE + app_var.usb_mic_gain = mic_effect_get_micgain(); +#else + app_var.usb_mic_gain = uac_mic_vol_switch(uac_get_mic_vol(0)); +#endif//TCFG_MIC_EFFECT_ENABLE + +#if (TCFG_USB_MIC_DATA_FROM_MICEFFECT) + mic_effect_to_usbmic_onoff(1); +#else +#if 0 + audio_adc_mic_open(&hdl->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl); + audio_adc_mic_set_sample_rate(&hdl->mic_ch, sample_rate); + audio_adc_mic_set_gain(&hdl->mic_ch, app_var.usb_mic_gain); + audio_adc_mic_set_buffs(&hdl->mic_ch, hdl->adc_buf, USB_MIC_IRQ_POINTS * 2, USB_MIC_BUF_NUM); + hdl->adc_output.handler = adc_output_to_cbuf; + audio_adc_add_output_handler(&adc_hdl, &hdl->adc_output); + audio_adc_mic_start(&hdl->mic_ch); +#else + audio_mic_open(&hdl->mic_ch, sample_rate, app_var.usb_mic_gain); + hdl->adc_output.handler = adc_output_to_cbuf; + audio_mic_add_output(&hdl->adc_output); + audio_mic_start(&hdl->mic_ch); +#endif +#endif//TCFG_USB_MIC_DATA_FROM_MICEFFECT +#endif//SOUNDCARD_ENABLE +#if TCFG_USB_MIC_ECHO_ENABLE + hdl->p_echo_hdl = open_echo(&usbmic_echo_parm_default, &usbmic_echo_fix_parm_default); +#endif + set_uac_mic_tx_handler(NULL, usb_audio_mic_tx_handler); + + hdl->status = USB_MIC_START; + hdl->mic_busy = 0; + + /* __this->rec_begin = 0; */ + return 0; +} + +u32 usb_mic_is_running() +{ + if (usb_mic_hdl) { + return SPK_AUDIO_RATE; + } + return 0; +} + +/* + ************************************************************* + * + * usb mic gain save + * + ************************************************************* + */ +static int usb_mic_gain_save_timer; +static u8 usb_mic_gain_save_cnt; +static void usb_audio_mic_gain_save_do(void *priv) +{ + //printf(" usb_audio_mic_gain_save_do %d\n", usb_mic_gain_save_cnt); + local_irq_disable(); + if (++usb_mic_gain_save_cnt >= 5) { + sys_hi_timer_del(usb_mic_gain_save_timer); + usb_mic_gain_save_timer = 0; + usb_mic_gain_save_cnt = 0; + local_irq_enable(); + printf("USB_GAIN_SAVE\n"); + syscfg_write(VM_USB_MIC_GAIN, &app_var.usb_mic_gain, 1); + return; + } + local_irq_enable(); +} + +static void usb_audio_mic_gain_change(u8 gain) +{ + local_irq_disable(); + app_var.usb_mic_gain = gain; + usb_mic_gain_save_cnt = 0; + if (usb_mic_gain_save_timer == 0) { + usb_mic_gain_save_timer = sys_hi_timer_add(NULL, usb_audio_mic_gain_save_do, 1000); + } + local_irq_enable(); +} + +int usb_audio_mic_get_gain(void) +{ + return app_var.usb_mic_gain; +} + +void usb_audio_mic_set_gain(int gain) +{ +#if (SOUNDCARD_ENABLE) + return ; +#endif//SOUNDCARD_ENABLE + + if (usb_mic_hdl == NULL) { + r_printf("usb_mic_hdl NULL gain"); + return; + } + gain = uac_mic_vol_switch(gain); + audio_adc_mic_set_gain(&usb_mic_hdl->mic_ch, gain); + usb_audio_mic_gain_change(gain); +} +int usb_audio_mic_close(void *arg) +{ + if (usb_mic_hdl == NULL) { + r_printf("usb_mic_hdl NULL close"); + return 0; + } + printf("usb_mic_hdl->status %x\n", usb_mic_hdl->status); + if (usb_mic_hdl && usb_mic_hdl->status == USB_MIC_START) { + printf("usb_audio_mic_close in\n"); + usb_mic_hdl->status = USB_MIC_STOP; +#if USB_MIC_AEC_EN + audio_aec_close(); +#endif/*USB_MIC_AEC_EN*/ +#if USB_MIC_SRC_ENABLE + sw_src_exit(); +#endif/*USB_MIC_SRC_ENABLE*/ +#if (SOUNDCARD_ENABLE) + //从声卡输出端获取, 没有打开mic, 所以这里不需要关 +#if (TCFG_USB_MIC_DATA_FROM_DAC) + mic_effect_to_usbmic_onoff(0); +#endif//TCFG_USB_MIC_DATA_FROM_DAC +#else +#if (TCFG_USB_MIC_DATA_FROM_MICEFFECT) + mic_effect_to_usbmic_onoff(0); +#else +#if 0 + audio_adc_mic_close(&usb_mic_hdl->mic_ch); + audio_adc_del_output_handler(&adc_hdl, &usb_mic_hdl->adc_output); +#else + audio_mic_close(&usb_mic_hdl->mic_ch, &usb_mic_hdl->adc_output); +#endif +#endif//TCFG_USB_MIC_DATA_FROM_MICEFFECT +#endif//SOUNDCARD_ENABLE + +#if TCFG_USB_MIC_ECHO_ENABLE + if (usb_mic_hdl->p_echo_hdl) { + close_echo(usb_mic_hdl->p_echo_hdl); + } +#endif + cbuf_clear(&usb_mic_hdl->output_cbuf); + if (usb_mic_hdl) { + while (usb_mic_hdl->mic_busy) { + os_time_dly(3); + } + + local_irq_disable(); + +#if SOUNDCARD_ENABLE //4取1 + if (usb_mic_hdl->temp_buf) { + free(usb_mic_hdl->temp_buf); + usb_mic_hdl->temp_buf = NULL; + } + usb_mic_hdl->temp_buf_len = 0; +#endif + + if (usb_mic_hdl->output_buf) { + free(usb_mic_hdl->output_buf); + usb_mic_hdl->output_buf = NULL; + } + free(usb_mic_hdl); + usb_mic_hdl = NULL; + local_irq_enable(); + } + } + printf("usb_audio_mic_close out\n"); + + return 0; +} +#endif + diff --git a/cpu/br23/audio_dec/lfwordana_enc_api.c b/cpu/br23/audio_dec/lfwordana_enc_api.c new file mode 100644 index 0000000..bd58a18 --- /dev/null +++ b/cpu/br23/audio_dec/lfwordana_enc_api.c @@ -0,0 +1,161 @@ +#include "lfwordana_enc_api.h" + +//使用内置flash音源时(默认使用) +#define MIDI_W2S_SOUCE_FILE_PATH SDFILE_RES_ROOT_PATH"nihao.raw\0" +//使用内置flash、外挂flash 或者sd卡音源时 +#define MIDI_W2S_SOUCE_FILE_PATH2 SDFILE_RES_ROOT_PATH"nihao.raw\0" + +#if defined(MIDI_SUPPORT_W2S) && MIDI_SUPPORT_W2S +#define REC_LEN 3000 //预处理输出长度 +struct ana_process { + struct lfwordana_encoder *ana; + OS_MUTEX mutex; + short rec_outdata[REC_LEN]; + + struct audio_adc_output_hdl adc_output; + struct adc_mic_ch mic_ch; + cbuffer_t cbuf; + short *mic_out_buf; + u8 source; + + void *data_in; + int data_in_len; + u8 *out_path; + void *w2s_fp;//句柄预留 + + u16 timer; + void *in_fp; +}; +#define SOURCE_FROM_MIC 0 +#define SOURCE_FROM_FILE 1 +#define SOURCE_FROM_BUF 2 + +struct ana_process *ana_proc = NULL; + +static void lfwordana_process_task(void *priv) +{ + struct ana_process *ana_p = priv; + struct lfwordana_encoder *ana = ana_p->ana; + int ret = 0; + u32 len = 0; + while (1) { + if ((ana_p->source == SOURCE_FROM_MIC) || (ana_p->source == SOURCE_FROM_FILE)) { + os_sem_pend(&ana_p->mutex, 0); + void *data = cbuf_read_alloc(&ana_p->cbuf, &len); + ret = lfwordana_encoder_run(ana, data, len); + cbuf_read_updata(&ana_p->cbuf, len); + } else if (ana_p->source == SOURCE_FROM_BUF) { + if (ana_p->data_in) { + ret = lfwordana_encoder_run(ana, ana_p->data_in, ana_p->data_in_len); + } + } + if (!ret) { + if (ana_p->w2s_fp) { //保存预处理后的数据 + ret = fwrite(ana_p->w2s_fp, ana_p->ana->w2s_parmIn.rec_data, ana_p->ana->w2s_parmIn.rec_len); + if (ret != ana_p->ana->w2s_parmIn.rec_len) { + log_e("lfwordana write err\n"); + } + fclose(ana_p->w2s_fp); + ana_p->w2s_fp = NULL; + } + + midi_w2s_parm_set(&ana->w2s_parmOut, sizeof(MIDI_W2S_STRUCT));//保存预处理输出的参数 + if (ana_p->source == SOURCE_FROM_MIC) { + audio_mic_close(&ana_p->mic_ch, &ana_p->adc_output); + if (ana_p->mic_out_buf) { + free(ana_p->mic_out_buf); + } + } + lfwordana_encoder_close(ana_p->ana); + free(ana_p); + ana_proc = ana_p = NULL; + os_task_del("audio_enc");//线程自杀 + break; + } + } +} + +static void adc_output_to_enc(void *priv, s16 *data, int len) +{ + struct ana_process *ana_p = priv; + int ret = cbuf_write(&ana_p->cbuf, data, len); + if (!ret) { + log_e("mic data lose \n"); + } + os_mutex_post(&ana_p->mutex); +} +void input_file_process(void *p) +{ + struct ana_process *ana_p = (struct ana_process *)p; + if (ana_p->in_fp) { + int len; + void *ptr = cbuf_write_alloc(&ana_p->cbuf, &len); + if (!len) { + log_e("mic data lose \n"); + return; + } + if (len > 512) { + len = 512; + } + len = fread(ana_p->in_fp, ptr, len); + cbuf_write_updata(&ana_p->cbuf, len); + os_mutex_post(&ana_p->mutex); + } +} +void lfwordana_process() +{ + if (!ana_proc) { + ana_proc = zalloc(sizeof(struct ana_process)); + } + struct ana_process *ana_p = &ana_proc; + REC_W2S_STUCT parm = {0}; + parm.toneadjust_enable = 1; //滤波使能 + parm.multi_enable = 0; //是否区分多字的情况,buf大的时候考虑做,buf小的时候不考虑 + parm.rec_data = ana_p->rec_outdata; //输出数据地址【保证short对齐】 + parm.rec_len = REC_LEN; //输出地址长度【按short】 + parm.energy_thresh = 3000; //能量阈值 + ana_p->out_path = MIDI_W2S_FILE_PATH;//"storage/sd0/C/W2S/W2S.raw\0"; + struct lfwordana_encoder *ana = lfwordana_encoder_open(&parm); + ana_p->ana = ana; + ana_p->w2s_fp = fopen(ana_p->out_path, "wb"); + + /* ana_p->source = SOURCE_FROM_FILE; */ + ana_p->source = SOURCE_FROM_BUF; + u32 mic_out_buf_len = 2048; + if (ana_p->source == SOURCE_FROM_MIC) { //算法库未支持多次输入 + u8 gain = 8; + u32 sample_rate = 16000; + ana_p->mic_out_buf = malloc(mic_out_buf_len); + cbuf_init(&ana_p->cbuf, ana_p->mic_out_buf, mic_out_buf_len); + os_sem_create(&ana_p->mutex, 0); + ana_p->adc_output.handler = adc_output_to_enc; + ana_p->adc_output.priv = ana_p; + if (audio_mic_open(&ana_p->mic_ch, sample_rate, gain) == 0) { + audio_mic_add_output(&ana_p->adc_output); + audio_mic_start(&ana_p->mic_ch); + } + } else if (ana_p->source == SOURCE_FROM_BUF) { + void *fp = fopen(MIDI_W2S_SOUCE_FILE_PATH, "r");//在内置flash的,pcm音源文件 + if (!fp) { + lfwordana_encoder_close(ana_p->ana); + return; + } + struct vfs_attr attr = {0}; + fget_attrs(fp, &attr); + ana_p->data_in = (void *)attr.sclust; + ana_p->data_in_len = attr.fsize; + fclose(fp); + /* ana_p->data_in = your_data_addr; //输入数据地址,内置flash可用文件簇地址 */ + /* ana_p->data_in_len = your_data_len;//输入出数据总长度 */ + } else if (ana_p->source == SOURCE_FROM_FILE) { //算法库未支持多次输入 + ana_p->mic_out_buf = malloc(mic_out_buf_len); + cbuf_init(&ana_p->cbuf, ana_p->mic_out_buf, mic_out_buf_len); + os_sem_create(&ana_p->mutex, 0); + ana_p->in_fp = fopen(MIDI_W2S_SOUCE_FILE_PATH2, "r");//在内置flash、外挂flash、sd卡等路径的,pcm音源文件 + ana_p->timer = sys_timer_add(ana_p, input_file_process, 50); + } + + task_create(lfwordana_process_task, ana_p, "audio_enc"); +} + +#endif/* MIDI_SUPPORT_W2S */ diff --git a/cpu/br23/audio_dec/lfwordana_enc_api.h b/cpu/br23/audio_dec/lfwordana_enc_api.h new file mode 100644 index 0000000..6ed4682 --- /dev/null +++ b/cpu/br23/audio_dec/lfwordana_enc_api.h @@ -0,0 +1,16 @@ +#ifndef __LFWORDANA_ENC_API__H +#define __LFWORDANA_ENC_API__H +#include "media/lfwordana_enc.h" +#include "audio_enc.h" + +void midi_w2s_parm_get(void *parm); +void midi_w2s_parm_set(void *data, u32 len); +void lfwordana_process(); + +/*midi支持外部音源替换主旋律, 0:不支持, 1:支持*/ +#define MIDI_SUPPORT_W2S 0 + + +extern int *MIDI_W2S_FILE_PATH; +#endif/* __LFWORDANA_ENC_API__H */ + diff --git a/cpu/br23/audio_dec/tone_player.c b/cpu/br23/audio_dec/tone_player.c new file mode 100644 index 0000000..738e831 --- /dev/null +++ b/cpu/br23/audio_dec/tone_player.c @@ -0,0 +1,639 @@ +#include "system/includes.h" +#include "media/includes.h" +#include "application/audio_dec_app.h" +#include "tone_player.h" +#include "audio_config.h" +#include "app_main.h" +#include "audio_dec.h" +#include "sine_make.h" +#if TCFG_USER_TWS_ENABLE +#include "bt_tws.h" +#endif/*TCFG_USER_TWS_ENABLE*/ + +////////////////////////////////////////////////////////////////////////////// + + +#define TWS_FUNC_ID_TONE2TWS TWS_FUNC_ID('2', 'T', 'W', 'S') + +#define TONE_TWS_CONFIRM_TIME 500 + +////////////////////////////////////////////////////////////////////////////// +static const char *const tone_index[] = { + [IDEX_TONE_NUM_0] = SDFILE_RES_ROOT_PATH"tone/0.*", + [IDEX_TONE_NUM_1] = SDFILE_RES_ROOT_PATH"tone/1.*", + [IDEX_TONE_NUM_2] = SDFILE_RES_ROOT_PATH"tone/2.*", + [IDEX_TONE_NUM_3] = SDFILE_RES_ROOT_PATH"tone/3.*", + [IDEX_TONE_NUM_4] = SDFILE_RES_ROOT_PATH"tone/4.*", + [IDEX_TONE_NUM_5] = SDFILE_RES_ROOT_PATH"tone/5.*", + [IDEX_TONE_NUM_6] = SDFILE_RES_ROOT_PATH"tone/6.*", + [IDEX_TONE_NUM_7] = SDFILE_RES_ROOT_PATH"tone/7.*", + [IDEX_TONE_NUM_8] = SDFILE_RES_ROOT_PATH"tone/8.*", + [IDEX_TONE_NUM_9] = SDFILE_RES_ROOT_PATH"tone/9.*", + [IDEX_TONE_BT_MODE] = SDFILE_RES_ROOT_PATH"tone/bt.*", + [IDEX_TONE_BT_CONN] = SDFILE_RES_ROOT_PATH"tone/bt_conn.*", + [IDEX_TONE_BT_DISCONN] = SDFILE_RES_ROOT_PATH"tone/bt_dconn.*", + [IDEX_TONE_TWS_CONN] = SDFILE_RES_ROOT_PATH"tone/tws_conn.*", + [IDEX_TONE_TWS_DISCONN] = SDFILE_RES_ROOT_PATH"tone/tws_dconn.*", + [IDEX_TONE_LOW_POWER] = SDFILE_RES_ROOT_PATH"tone/low_power.*", + [IDEX_TONE_POWER_OFF] = SDFILE_RES_ROOT_PATH"tone/power_off.*", + [IDEX_TONE_POWER_ON] = SDFILE_RES_ROOT_PATH"tone/power_on.*", + [IDEX_TONE_RING] = SDFILE_RES_ROOT_PATH"tone/ring.*", + [IDEX_TONE_MAX_VOL] = SDFILE_RES_ROOT_PATH"tone/vol_max.*", + [IDEX_TONE_NORMAL] = TONE_NORMAL, +#if (TCFG_APP_MUSIC_EN) + [IDEX_TONE_MUSIC] = SDFILE_RES_ROOT_PATH"tone/music.*", +#endif +#if (TCFG_APP_LINEIN_EN) + [IDEX_TONE_LINEIN] = SDFILE_RES_ROOT_PATH"tone/linein.*", +#endif +#if (TCFG_APP_FM_EN) + [IDEX_TONE_FM] = SDFILE_RES_ROOT_PATH"tone/fm.*", +#endif +#if (TCFG_APP_PC_EN) + [IDEX_TONE_PC] = SDFILE_RES_ROOT_PATH"tone/pc.*", +#endif +#if (TCFG_APP_RTC_EN) + [IDEX_TONE_RTC] = SDFILE_RES_ROOT_PATH"tone/rtc.*", +#endif +#if (TCFG_APP_RECORD_EN) + [IDEX_TONE_RECORD] = SDFILE_RES_ROOT_PATH"tone/record.*", +#endif +} ; + +#if TCFG_TONE2TWS_ENABLE +// 用于转发的提示音 +static const char *const tone2tws_index[] = { + TONE_BT_MODE, + TONE_MUSIC, + TONE_LINEIN, + TONE_FM, + TONE_PC, + TONE_RTC, + TONE_RECORD, + TONE_RES_ROOT_PATH"tone/sd.*", + TONE_RES_ROOT_PATH"tone/udisk.*", +} ; +#endif + +/* + * 参数配置: + * freq : 实际频率 * 512 + * points : 正弦波点数 + * win : 正弦窗 + * decay : 衰减系数(百分比), 正弦窗模式下为频率设置:频率*512 + * + */ +static const struct sin_param sine_16k_normal[] = { + /*{0, 1000, 0, 100},*/ + {200 << 9, 4000, 0, 100}, +}; + +#if CONFIG_USE_DEFAULT_SINE +static const struct sin_param sine_tws_disconnect_16k[] = { + /* + {390 << 9, 4026, SINE_TOTAL_VOLUME / 4026}, + {262 << 9, 8000, SINE_TOTAL_VOLUME / 8000}, + */ + {262 << 9, 4026, 0, 100}, + {390 << 9, 8000, 0, 100}, +}; + +static const struct sin_param sine_tws_connect_16k[] = { + /* + {262 << 9, 4026, SINE_TOTAL_VOLUME / 4026}, + {390 << 9, 8000, SINE_TOTAL_VOLUME / 8000}, + */ + {262.298 * 512, 8358, 0, 100}, +}; + +static const struct sin_param sine_low_power[] = { + {848 << 9, 3613, 0, 50}, + {639 << 9, 3623, 0, 50}, +}; + +static const struct sin_param sine_ring[] = { + {450 << 9, 24960, 1, 16.667 * 512}, + {0, 16000, 0, 100}, +}; + +static const struct sin_param sine_tws_max_volume[] = { + {210 << 9, 2539, 0, 100}, + {260 << 9, 7619, 0, 100}, + {400 << 9, 2539, 0, 100}, +}; +#endif + +////////////////////////////////////////////////////////////////////////////// + +struct tone_dec_handle *tone_dec = NULL; + + +////////////////////////////////////////////////////////////////////////////// +/*----------------------------------------------------------------------------*/ +/**@brief 按序列号获取sine数组 + @param id: 序号 + @param *num: 数组个数 + @return sine数组 + @note +*/ +/*----------------------------------------------------------------------------*/ +static const struct sin_param *get_sine_param_data(u8 id, u8 *num) +{ + const struct sin_param *param_data; + + switch (id) { + case SINE_WTONE_NORAML: + param_data = sine_16k_normal; + *num = ARRAY_SIZE(sine_16k_normal); + break; +#if CONFIG_USE_DEFAULT_SINE + case SINE_WTONE_TWS_CONNECT: + param_data = sine_tws_connect_16k; + *num = ARRAY_SIZE(sine_tws_connect_16k); + break; + case SINE_WTONE_TWS_DISCONNECT: + param_data = sine_tws_disconnect_16k; + *num = ARRAY_SIZE(sine_tws_disconnect_16k); + break; + case SINE_WTONE_LOW_POWER: + param_data = sine_low_power; + *num = ARRAY_SIZE(sine_low_power); + break; + case SINE_WTONE_RING: + param_data = sine_ring; + *num = ARRAY_SIZE(sine_ring); + break; + case SINE_WTONE_MAX_VOLUME: + param_data = sine_tws_max_volume; + *num = ARRAY_SIZE(sine_tws_max_volume); + break; +#endif + default: + return NULL; + } + + return param_data; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提示音播放基础函数(带有事件回调) + @param **list: 文件名 + @param follow: 现有提示音播放完毕后跟随着播放 + @param preemption: 打断标记 + @param *evt_handler: 事件回调接口 + @param *evt_priv: 事件回调私有句柄 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int tone_play_open_with_callback_base(const char **list, u8 follow, u8 preemption, void (*evt_handler)(void *priv, int flag), void *evt_priv, int sync_confirm_time) +{ + if (follow && tone_dec) { + struct tone_dec_list_handle *dec_list = tone_dec_list_create(tone_dec, list, preemption, evt_handler, evt_priv, NULL, NULL); + int ret = tone_dec_list_add_play(tone_dec, dec_list); + if (ret == false) { + tone_play_stop(); + return -1; + } + return 0; + } + + tone_dec_stop(&tone_dec, 1, TONE_DEC_STOP_BY_OTHER_PLAY); + + tone_dec = tone_dec_create(); + if (tone_dec == NULL) { + return -1; + } + tone_dec_set_sin_get_hdl(tone_dec, get_sine_param_data); + + struct tone_dec_list_handle *dec_list = tone_dec_list_create(tone_dec, list, preemption, evt_handler, evt_priv, NULL, NULL); + if (dec_list) { + dec_list->sync_confirm_time = sync_confirm_time; + } + int ret = tone_dec_list_add_play(tone_dec, dec_list); + if (ret == false) { + tone_play_stop(); + return -1; + } + return 0; +} + +#if TCFG_TONE2TWS_ENABLE +#include "app_task.h" + +static u32 tone2tws_dat = 0; + +/*----------------------------------------------------------------------------*/ +/**@brief tws提示音数据处理 + @param dat: 数据 + @return + @note 在任务中集中处理tws信息 +*/ +/*----------------------------------------------------------------------------*/ +static void tone2tws_rx_play(u32 dat) +{ + int idex = dat - 1; + if (idex >= ARRAY_SIZE(tone2tws_index)) { + return ; + } + /* y_printf("tone2tws_rx_play name:%d \n", tone2tws_index[idex]); */ + char *single_file[2] = {NULL}; + // is file name + single_file[0] = (char *)tone2tws_index[idex]; + single_file[1] = NULL; + tone_play_open_with_callback_base(single_file, 0, 1, NULL, NULL, TONE_TWS_CONFIRM_TIME); +} + +void tone2tws_bt_task_start(u8 tone_play) +{ + if (tone2tws_dat == 0) { + return ; + } + if (tone_play) { + // 播放蓝牙提示音,抛弃该提示音 + tone2tws_dat = 0; + } else { + // 播放该提示音 + tone2tws_rx_play(tone2tws_dat); + tone2tws_dat = 0; + } +} + +static void tone2tws_rx_callback_func(u32 dat) +{ + /* printf("tone2tws_rx_callback_func\n"); */ + if (!dat) { + return ; + } +#if TCFG_DEC2TWS_ENABLE + if (tone2tws_dat) { // 释放旧的 + tone2tws_dat = 0; + } + if (APP_BT_TASK != app_get_curr_task()) { + r_printf("tone2tws task:%d ", app_get_curr_task()); + // 该提示音一定是在蓝牙模式播放,否则代表有问题。 + // 等返回蓝牙模式再播放 + tone2tws_dat = dat; + return ; + } +#endif + + tone2tws_rx_play(dat); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提示音tws私有信息处理 + @param *data: 数据 + @param len: 数据长度 + @param rx: 1-接受端 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void tone2tws_tws_rx_data(void *data, u16 len, bool rx) +{ + /* printf("tone2tws_tws_rx_data, l:%d, rx:%d \n", len, rx); */ + if (!rx) { + return; + } + /* printf("data rx \n"); */ + /* printf_buf(data, len); */ + + u32 dat; + memcpy(&dat, data, 4); + /* y_printf("rx dat:%d \n", dat); */ + + // 该函数是在中断里面调用,实际处理放在task里面 + int argv[3]; + argv[0] = (int)tone2tws_rx_callback_func; + argv[1] = 1; + argv[2] = (int)dat; + int ret = os_taskq_post_type("app_core", Q_CALLBACK, 3, argv); + /* printf("put taskq, ret:%d, len:%d \n", ret, len); */ + if (ret) { + log_e("taskq post err \n"); + } +} + +REGISTER_TWS_FUNC_STUB(tws_tone2tws_rx) = { + .func_id = TWS_FUNC_ID_TONE2TWS, + .func = tone2tws_tws_rx_data, +}; + +#endif + +/*----------------------------------------------------------------------------*/ +/**@brief 提示音播放(带有事件回调) + @param **list: 文件名 + @param follow: 现有提示音播放完毕后跟随着播放 + @param preemption: 打断标记 + @param *evt_handler: 事件回调接口 + @param *evt_priv: 事件回调私有句柄 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int tone_play_open_with_callback(const char **list, u8 follow, u8 preemption, void (*evt_handler)(void *priv, int flag), void *evt_priv) +{ + int sync_confirm_time = 0; +#if TCFG_TONE2TWS_ENABLE + int state = tws_api_get_tws_state(); + if (state & TWS_STA_SIBLING_CONNECTED) { + // 有tws连接,检查是否需要把提示音推送给对方 + char *name = list[0]; + for (int i = 0; i < ARRAY_SIZE(tone2tws_index); i++) { + if (IS_REPEAT_BEGIN(name) || IS_REPEAT_END(name)) { + break; + } + if (IS_DEFAULT_SINE(name) || IS_DEFAULT_SINE(tone2tws_index[i])) { + if ((u32)name == (u32)tone2tws_index[i]) { + // is sine idx + u32 dat = i + 1; + tws_api_send_data_to_sibling(&dat, 4, TWS_FUNC_ID_TONE2TWS); + sync_confirm_time = TONE_TWS_CONFIRM_TIME; + break; + } + } else if (!strcmp(tone2tws_index[i], name)) { + // is file name + u32 dat = i + 1; + tws_api_send_data_to_sibling(&dat, 4, TWS_FUNC_ID_TONE2TWS); + sync_confirm_time = TONE_TWS_CONFIRM_TIME; + break; + } + } + } +#endif + return tone_play_open_with_callback_base(list, follow, preemption, evt_handler, evt_priv, sync_confirm_time); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按文件播放提示音 + @param *name: 文件名 + @param preemption: 打断标记 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int tone_play(const char *name, u8 preemption) +{ + char *single_file[2] = {NULL}; + single_file[0] = (char *)name; + single_file[1] = NULL; + return tone_play_open_with_callback(single_file, 0, preemption, NULL, NULL); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按文件播放提示音 + @param *name: 文件名 + @param preemption: 打断标记 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int tone_play_by_path(const char *name, u8 preemption) +{ + return tone_play(name, preemption); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按序列号播放提示音 + @param index: 序列号 + @param preemption: 打断标记 + @param *evt_handler: 事件回调接口 + @param *evt_priv: 事件回调私有句柄 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int tone_play_index_with_callback(u8 index, u8 preemption, void (*evt_handler)(void *priv), void *evt_priv) +{ + if (index >= IDEX_TONE_NONE) { + return -1; + } + char *single_file[2] = {NULL}; + single_file[0] = (char *)tone_index[index]; + single_file[1] = NULL; + return tone_play_open_with_callback(single_file, 0, preemption, evt_handler, evt_priv); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按序列号播放提示音(带有事件回调) + @param index: 序列号 + @param preemption: 打断标记 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int tone_play_index(u8 index, u8 preemption) +{ + return tone_play_index_with_callback(index, preemption, NULL, NULL); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按文件名列表播放提示音 + @param **list: 文件名列表 + @param preemption: 打断标记 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int tone_file_list_play(const char **list, u8 preemption) +{ + return tone_play_open_with_callback(list, 0, preemption, NULL, NULL); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按序列号播放提示音 + @param index: 序列号 + @param preemption: 打断标记 + @param *evt_handler: 事件回调接口 + @param *evt_priv: 事件回调私有句柄 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int tone_play_with_callback_by_index(u8 index, + u8 preemption, + void (*evt_handler)(void *priv, int flag), + void *evt_priv) +{ + if (index >= IDEX_TONE_NONE) { + return -1; + } + char *single_file[2] = {NULL}; + single_file[0] = (char *)tone_index[index]; + single_file[1] = NULL; + return tone_play_open_with_callback(single_file, 0, preemption, evt_handler, evt_priv); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按名字播放提示音 + @param *name: 文件名 + @param preemption: 打断标记 + @param *evt_handler: 事件回调接口 + @param *evt_priv: 事件回调私有句柄 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int tone_play_with_callback_by_name(char *name, + u8 preemption, + void (*evt_handler)(void *priv, int flag), + void *evt_priv) +{ + char *single_file[2] = {NULL}; + single_file[0] = name; + single_file[1] = NULL; + return tone_play_open_with_callback(single_file, 0, preemption, evt_handler, evt_priv); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 按列表播放提示音 + @param **list: 文件列表 + @param preemption: 打断标记 + @param *evt_handler: 事件回调接口 + @param *evt_priv: 事件回调私有句柄 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int tone_play_with_callback_by_list(const char **list, + u8 preemption, + void (*evt_handler)(void *priv, int flag), + void *evt_priv) +{ + return tone_play_open_with_callback(list, 0, preemption, evt_handler, evt_priv); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 停止指定序号提示音 + @param index: 序号 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int tone_play_stop_by_index(u8 index) +{ + if (index >= IDEX_TONE_NONE) { + return -1; + } + tone_dec_stop_spec_file(&tone_dec, tone_index[index], 1, TONE_DEC_STOP_BY_OTHER_PLAY); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 停止指定序号提示音 + @param path: 序号 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int tone_play_stop_by_path(char *path) +{ + if (path == NULL) { + return -1; + } + tone_dec_stop_spec_file(&tone_dec, path, 1, TONE_DEC_STOP_BY_OTHER_PLAY); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 停止提示音播放 + @param + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int tone_play_stop(void) +{ + tone_dec_stop(&tone_dec, 1, TONE_DEC_STOP_BY_OTHER_PLAY); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 获取提示音播放状态 + @param + @return TONE_START: 正在播放 + @return TONE_STOP: 不在播放 + @note +*/ +/*----------------------------------------------------------------------------*/ +int tone_get_status(void) +{ + if (tone_dec && tone_dec->cur_list) { + return TONE_START; + } + return TONE_STOP; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 获取提示音播放解码器状态 + @param + @return TONE_START: 正在解码 + @return TONE_STOP: 不在解码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int tone_get_dec_status() +{ + if (!tone_dec) { + return TONE_STOP; + } + if (tone_dec->dec_sin && (tone_dec->dec_sin->dec->decoder.state != DEC_STA_WAIT_STOP)) { + return TONE_START; + } + if (tone_dec->dec_file && (tone_dec->dec_file->dec->decoder.state != DEC_STA_WAIT_STOP)) { + return TONE_START; + } + return TONE_STOP; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 超时等待提示音播放解码完成 + @param timeout_ms: 超时等待 + @return TONE_START: 正在解码 + @return TONE_STOP: 不在解码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int tone_dec_wait_stop(u32 timeout_ms) +{ + u32 to_cnt = 0; + while (tone_get_dec_status()) { + /* putchar('t'); */ + os_time_dly(1); + if (timeout_ms) { + to_cnt += 10; + if (to_cnt >= timeout_ms) { + break; + } + } + } + return tone_get_dec_status(); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 提示音idle判断 + @param + @return 1: idle + @return 0: busy + @note +*/ +/*----------------------------------------------------------------------------*/ +static u8 tone_dec_idle_query() +{ + if (tone_get_status() == TONE_START) { + return 0; + } + return 1; +} +REGISTER_LP_TARGET(tone_dec_lp_target) = { + .name = "tone_dec", + .is_idle = tone_dec_idle_query, +}; + + + + diff --git a/cpu/br23/audio_effect/audio_dynamic_eq_demo.c b/cpu/br23/audio_effect/audio_dynamic_eq_demo.c new file mode 100644 index 0000000..5c8e891 --- /dev/null +++ b/cpu/br23/audio_effect/audio_dynamic_eq_demo.c @@ -0,0 +1,131 @@ +#include "audio_dynamic_eq_demo.h" +#include "app_config.h" + +#if TCFG_DYNAMIC_EQ_ENABLE +struct dynamic_eq_detection *detect_hdl = NULL; +struct dynamic_eq *dynamic_eq_hdl = NULL; + +/* 先打开audio_dynamic_eq_detection_open_demo */ +/* 再打开audio_dynamic_eq_open_demo */ +struct dynamic_eq *audio_dynamic_eq_open_demo(u32 sample_rate, u8 channel) +{ + DynamicEQEffectParam effectParam[2]; + DynamicEQParam param = {0}; + + param.detect_mode = dynamic_eq.detect_mode;//TWOPOINT; + param.channel = channel; + param.nSection = dynamic_eq.nSection;//EQ_NSECTION; + param.SampleRate = sample_rate; + param.DetectdataInc = (channel == 1) ? 1 : 2; + param.IndataInc = (channel == 1) ? 1 : 2; + param.OutdataInc = (channel == 1) ? 1 : 2; + memcpy(effectParam, &dynamic_eq.effect_param, sizeof(DynamicEQEffectParam)*param.nSection); + struct dynamic_eq *hdl = dynamic_eq_open((DynamicEQEffectParam *)effectParam, (DynamicEQParam *)¶m); + return hdl; +} + +void audio_dynamic_eq_close_demo(struct dynamic_eq *hdl) +{ + dynamic_eq_close(hdl); + dynamic_eq_hdl = NULL; +} + +void audio_dynamic_eq_update_parm(void *parm, void *parm2, int bypass) +{ + if (dynamic_eq_hdl) { + dynamic_eq_update(dynamic_eq_hdl, parm, parm2); + + dynamic_eq_bypass(dynamic_eq_hdl, bypass); + } +} + + +struct dynamic_eq_detection *audio_dynamic_eq_detection_open_demo(u32 sample_rate, u8 channel) +{ + DynamicEQDetectionParam detectParm[2]; + detectParm[0].fc = dynamic_eq.effect_param[0].fc;//CENTER_FREQ_0; + detectParm[1].fc = dynamic_eq.effect_param[1].fc;//CENTER_FREQ_1; + + struct dynamic_eq_detection *hdl = dynamic_eq_detection_open((DynamicEQDetectionParam *)&detectParm, dynamic_eq.nSection, channel, sample_rate); + detect_hdl = hdl; + return hdl; +} + + +void audio_dynamic_eq_detection_close_demo(struct dynamic_eq_detection *hdl) +{ + dynamic_eq_detection_close(hdl); +} + + +void audio_dynamic_eq_detection_update_parm(void *parm, int bypass) +{ + if (detect_hdl) { + dynamic_eq_detection_update(detect_hdl, parm); + + dynamic_eq_detection_bypass(detect_hdl, bypass); + } +} + + +int dy_eq_prob_handler(struct audio_stream_entry *entry, struct audio_data_frame *in) // 预处理 +{ + if (in->data_len - in->offset > 0) { + if (detect_hdl) { + detect_hdl->in_32bit = 1; + dynamic_eq_detection_run(detect_hdl, (short *)((int)in->data + in->offset), in->data_len - in->offset); + } + } + return 0; +} + + +struct dynamic_eq_hdl *audio_dynamic_eq_ctrl_open(u32 sample_rate, u8 channel) +{ + struct dynamic_eq_hdl *hdl = zalloc(sizeof(struct dynamic_eq_hdl)); + if (!hdl) { + return NULL; + } + struct dynamic_eq_detection *dy_eq_det = audio_dynamic_eq_detection_open_demo(sample_rate, channel); + if (!dy_eq_det) { + return NULL; + } + struct dynamic_eq *dy_eq = audio_dynamic_eq_open_demo(sample_rate, channel); + if (!dy_eq) { + log_e("dy_eq NULL\n"); + return NULL; + } + if (dy_eq_det) { + dynamic_eq_set_detection_callback(dy_eq, dy_eq_det, get_dynamic_eq_detection_parm); + } + hdl->dy_eq_det = dy_eq_det; + hdl->dy_eq = dy_eq; + hdl->dy_eq->entry.prob_handler = dy_eq_prob_handler; + + detect_hdl = dy_eq_det; + dynamic_eq_hdl = dy_eq; + return hdl; +} + +void audio_dynamic_eq_ctrl_close(struct dynamic_eq_hdl *hdl) +{ + if (!hdl) { + return; + } + + if (hdl->dy_eq) { + audio_dynamic_eq_close_demo(hdl->dy_eq); + hdl->dy_eq = NULL; + dynamic_eq_hdl = NULL; + } + if (hdl->dy_eq_det) { + audio_dynamic_eq_detection_close_demo(hdl->dy_eq_det); + hdl->dy_eq_det = NULL; + detect_hdl = NULL; + } + if (hdl) { + free(hdl); + hdl = NULL; + } +} +#endif diff --git a/cpu/br23/audio_effect/audio_dynamic_eq_demo.h b/cpu/br23/audio_effect/audio_dynamic_eq_demo.h new file mode 100644 index 0000000..302c1ad --- /dev/null +++ b/cpu/br23/audio_effect/audio_dynamic_eq_demo.h @@ -0,0 +1,25 @@ +#ifndef __AUDIO_DYNAMEIC_EQ_H__ +#define __AUDIO_DYNAMEIC_EQ_H__ + +#include "media/dynamic_eq.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" + + +struct dynamic_eq_hdl { + struct dynamic_eq_detection *dy_eq_det; + struct dynamic_eq *dy_eq; +}; + +/* 先打开audio_dynamic_eq_detection_open_demo */ +/* 再打开audio_dynamic_eq_open_demo */ +struct dynamic_eq *audio_dynamic_eq_open_demo(u32 sample_rate, u8 channel); +void audio_dynamic_eq_close_demo(struct dynamic_eq *hdl); + +struct dynamic_eq_detection *audio_dynamic_eq_detection_open_demo(u32 sample_rate, u8 channel); +void audio_dynamic_eq_detection_close_demo(struct dynamic_eq_detection *hdl); + +struct dynamic_eq_hdl *audio_dynamic_eq_ctrl_open(u32 sample_rate, u8 channel); +void audio_dynamic_eq_ctrl_close(struct dynamic_eq_hdl *hdl); + +#endif/*__AUDIO_DYNAMEIC_EQ_H__*/ diff --git a/cpu/br23/audio_effect/audio_eff_default_parm.c b/cpu/br23/audio_effect/audio_eff_default_parm.c new file mode 100644 index 0000000..b4284aa --- /dev/null +++ b/cpu/br23/audio_effect/audio_eff_default_parm.c @@ -0,0 +1,304 @@ +#include "media/effects_adj.h" +#include "audio_eff_default_parm.h" +#include "app_config.h" +#include "math.h" +float powf(float x, float y); +extern struct mode_list *get_group_list(u16 module_name); +extern const struct eq_seg_info phone_eq_tab_normal[3]; +extern const struct eq_seg_info ul_eq_tab_normal[3]; +extern const struct eq_seg_info eq_tab_normal[10]; +const struct eq_seg_info mic_eff_eq_tab[5] = { + {0, EQ_IIR_TYPE_BAND_PASS, 200, 0, 0.7f}, + {1, EQ_IIR_TYPE_BAND_PASS, 300, 0, 0.7f}, + {2, EQ_IIR_TYPE_BAND_PASS, 400, 0, 0.7f}, + {3, EQ_IIR_TYPE_BAND_PASS, 400, 0, 0.7f}, + {4, EQ_IIR_TYPE_BAND_PASS, 500, 0, 0.7f}, +}; + +void phone_eff_default_parm(void) +{ +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE + //通话下行eq + for (u8 tar = 0; tar < 2; tar++) { + phone_mode[tar].eq_parm.global_gain = 0; + phone_mode[tar].eq_parm.seg_num = ARRAY_SIZE(phone_eq_tab_normal); + memcpy(phone_mode[tar].eq_parm.seg, phone_eq_tab_normal, sizeof(phone_eq_tab_normal)); + } + //通话上行eq + for (u8 tar = 2; tar < 4; tar++) { + phone_mode[tar].eq_parm.global_gain = 0; + phone_mode[tar].eq_parm.seg_num = ARRAY_SIZE(ul_eq_tab_normal); + memcpy(phone_mode[tar].eq_parm.seg, ul_eq_tab_normal, sizeof(ul_eq_tab_normal)); + } +#endif + + //通话下行drc + struct threshold_group group[] = {{0, 0}, {50, 50}, {90, 90}}; + for (u8 tar = 0; tar < 2; tar++) { + phone_mode[tar].drc_parm.is_bypass = 0; + phone_mode[tar].drc_parm.parm.attacktime = 10; + phone_mode[tar].drc_parm.parm.releasetime = 300; + phone_mode[tar].drc_parm.parm.inputgain = 0; + phone_mode[tar].drc_parm.parm.outputgain = 0; + phone_mode[tar].drc_parm.parm.threshold_num = ARRAY_SIZE(group); + memcpy(phone_mode[tar].drc_parm.parm.threshold, group, sizeof(group)); + phone_mode[tar].drc_parm.parm.rms_time = 25; + phone_mode[tar].drc_parm.parm.algorithm = 0; + phone_mode[tar].drc_parm.parm.mode = 1; + } + + //通话上行行drc + struct threshold_group group2[] = {{0, 0}, {50, 50}, {90, 90}}; + for (u8 tar = 2; tar < 4; tar++) { + phone_mode[tar].drc_parm.is_bypass = 0; + phone_mode[tar].drc_parm.parm.attacktime = 10; + phone_mode[tar].drc_parm.parm.releasetime = 300; + phone_mode[tar].drc_parm.parm.inputgain = 0; + phone_mode[tar].drc_parm.parm.outputgain = 0; + phone_mode[tar].drc_parm.parm.threshold_num = ARRAY_SIZE(group2); + memcpy(phone_mode[tar].drc_parm.parm.threshold, group2, sizeof(group2)); + phone_mode[tar].drc_parm.parm.rms_time = 25; + phone_mode[tar].drc_parm.parm.algorithm = 0; + phone_mode[tar].drc_parm.parm.mode = 1; + } +} + + + +void music_eff_default_parm(void) +{ + + + float gain = 0; +#if AUDIO_VBASS_CONFIG +//gain + vbass_prev_gain_parm.is_bypass = 0; + vbass_prev_gain_parm.parm.gain = powf(10, gain / 20.0f); //db转mag,工具传下来的值 + + vbass_parm.is_bypass = 0; + vbass_parm.parm.ratio = 10; + vbass_parm.parm.boost = 1; + vbass_parm.parm.fc = 100; +#endif + +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE +//eq + music_mode.eq_parm.global_gain = 0; + music_mode.eq_parm.seg_num = ARRAY_SIZE(eq_tab_normal); + memcpy(music_mode.eq_parm.seg, eq_tab_normal, sizeof(eq_tab_normal)); +#endif + +//wdcrc + struct mode_list *list = get_group_list(AEID_MUSIC_DRC); + if (list) { + struct threshold_group group[] = {{0, 0}, {50, 50}, {90, 90}}; + for (int i = 0; i < list->group_num; i++) { + if (i == (list->group_num - 1)) { //最后一个存分频器系数 + music_mode.drc_parm.crossover.way_num = 2; + music_mode.drc_parm.crossover.N = 2; + music_mode.drc_parm.crossover.low_freq = 200; + } else { + music_mode.drc_parm.wdrc_parm[i].is_bypass = 0; + music_mode.drc_parm.wdrc_parm[i].parm.attacktime = 10; + music_mode.drc_parm.wdrc_parm[i].parm.releasetime = 300; + music_mode.drc_parm.wdrc_parm[i].parm.inputgain = 0; + music_mode.drc_parm.wdrc_parm[i].parm.outputgain = 0; + music_mode.drc_parm.wdrc_parm[i].parm.threshold_num = ARRAY_SIZE(group); + memcpy(music_mode.drc_parm.wdrc_parm[i].parm.threshold, group, sizeof(group)); + music_mode.drc_parm.wdrc_parm[i].parm.rms_time = 25; + music_mode.drc_parm.wdrc_parm[i].parm.algorithm = 0; + music_mode.drc_parm.wdrc_parm[i].parm.mode = 1; + } + } + } + + +#if TCFG_DYNAMIC_EQ_ENABLE +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE +//eq2 + music_eq2_parm.global_gain = 0; + music_eq2_parm.seg_num = ARRAY_SIZE(eq_tab_normal); + memcpy(music_eq2_parm.seg, eq_tab_normal, sizeof(eq_tab_normal)); +#endif + +//dynamic eq + dynamic_eq.is_bypass = 0; + dynamic_eq.nSection = 1; + dynamic_eq.detect_mode = 1; + for (u8 i = 0; i < dynamic_eq.nSection; i++) { + dynamic_eq.effect_param[i].fc = 1000; + dynamic_eq.effect_param[i].Q = 0.7f; + dynamic_eq.effect_param[i].gain = 0.0f; + dynamic_eq.effect_param[i].type = 0x2; + dynamic_eq.effect_param[i].attackTime = 5; + dynamic_eq.effect_param[i].releaseTime = 300; + dynamic_eq.effect_param[i].rmsTime = 25; + dynamic_eq.effect_param[i].threshold = 0.0f; + dynamic_eq.effect_param[i].ratio = 1.0f; + dynamic_eq.effect_param[i].noisegate_threshold = -90.3f; + dynamic_eq.effect_param[i].fixGain = 0.0f; + dynamic_eq.effect_param[i].algorithm = 1; + } +#endif + +#if GAIN_PROCESS_EN +//gain + gain_parm.is_bypass = 0; + gain = 0; + gain_parm.parm.gain = powf(10, gain / 20.0f); //db转mag,工具传下来的值 +#endif + +#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) &&SOUND_TRACK_2_P_X_CH_CONFIG +//low pass + low_pass_parm.is_bypass = 0; + low_pass_parm.low_pass.fc = 100; + low_pass_parm.low_pass.order = 4; + low_pass_parm.low_pass.type = 1; +#endif +//rl_wdrc + +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) + struct threshold_group group2[] = {{0, 0}, {50, 50}, {90, 90}}; + for (int i = 0; i < 4; i++) { + rl_drc_parm.wdrc_parm[i].is_bypass = 0; + rl_drc_parm.wdrc_parm[i].parm.attacktime = 10; + rl_drc_parm.wdrc_parm[i].parm.releasetime = 300; + rl_drc_parm.wdrc_parm[i].parm.inputgain = 0; + rl_drc_parm.wdrc_parm[i].parm.outputgain = 0; + rl_drc_parm.wdrc_parm[i].parm.threshold_num = ARRAY_SIZE(group2); + memcpy(rl_drc_parm.wdrc_parm[i].parm.threshold, group2, sizeof(group2)); + rl_drc_parm.wdrc_parm[i].parm.rms_time = 25; + rl_drc_parm.wdrc_parm[i].parm.algorithm = 0; + rl_drc_parm.wdrc_parm[i].parm.mode = 1; + } +#endif + +#if GAIN_PROCESS_EN +//rl_gain + rl_gain_parm.is_bypass = 0; + rl_gain_parm.parm.gain = powf(10, gain / 20.0f); //db转mag,工具传下来的值 +#endif +} + + +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN +void linein_eff_default_parm(void) +{ +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE +//eq + linein_mode.eq_parm.global_gain = 0; + linein_mode.eq_parm.seg_num = ARRAY_SIZE(eq_tab_normal); + memcpy(linein_mode.eq_parm.seg, eq_tab_normal, sizeof(eq_tab_normal)); +#endif + +//wdcrc + struct mode_list *list = get_group_list(AEID_MUSIC_DRC); + if (list) { + struct threshold_group group[] = {{0, 0}, {50, 50}, {90, 90}}; + for (int i = 0; i < list->group_num; i++) { + if ((list->group_num > 1) && (i == (list->group_num - 1))) { //最后一个存分频器系数 + linein_mode.drc_parm.crossover.way_num = 2; + linein_mode.drc_parm.crossover.N = 2; + linein_mode.drc_parm.crossover.low_freq = 200; + } else { + linein_mode.drc_parm.wdrc_parm[i].is_bypass = 0; + linein_mode.drc_parm.wdrc_parm[i].parm.attacktime = 10; + linein_mode.drc_parm.wdrc_parm[i].parm.releasetime = 300; + linein_mode.drc_parm.wdrc_parm[i].parm.inputgain = 0; + linein_mode.drc_parm.wdrc_parm[i].parm.outputgain = 0; + linein_mode.drc_parm.wdrc_parm[i].parm.threshold_num = ARRAY_SIZE(group); + memcpy(linein_mode.drc_parm.wdrc_parm[i].parm.threshold, group, sizeof(group)); + linein_mode.drc_parm.wdrc_parm[i].parm.rms_time = 25; + linein_mode.drc_parm.wdrc_parm[i].parm.algorithm = 0; + linein_mode.drc_parm.wdrc_parm[i].parm.mode = 1; + } + } + } +#if GAIN_PROCESS_EN +//rl_gain + float gain = 0; + linein_gain_parm.is_bypass = 0; + linein_gain_parm.parm.gain = powf(10, gain / 20.0f); //db转mag,工具传下来的值 +#endif + +} +#endif + + +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE +void mic_eff_default_parm(u8 index) +{ +//noisegate + eff_mode[index].noise_gate_parm.is_bypass = 0; + eff_mode[index].noise_gate_parm.parm.attackTime = 300; + eff_mode[index].noise_gate_parm.parm.releaseTime = 5; + eff_mode[index].noise_gate_parm.parm.threshold = -90300;//mdb -90.3dB + eff_mode[index].noise_gate_parm.parm.low_th_gain = 0; + +//howlingps_parm + eff_mode[index].howlingps_parm.is_bypass = 0; + eff_mode[index].howlingps_parm.parm.effect_v = EFFECT_HOWLING_FS; + eff_mode[index].howlingps_parm.parm.ps_parm = -50; + eff_mode[index].howlingps_parm.parm.fe_parm = 4; + +//notchowling_parm + eff_mode[index].notchhowling_parm.is_bypass = 0; + eff_mode[index].notchhowling_parm.parm.Q = 2.0f; + eff_mode[index].notchhowling_parm.parm.gain = -20; + eff_mode[index].notchhowling_parm.parm.fade_n = 10; + eff_mode[index].notchhowling_parm.parm.threshold = 25; + +//voice_changer +#if defined(TCFG_MIC_VOICE_CHANGER_ENABLE) && TCFG_MIC_VOICE_CHANGER_ENABLE + eff_mode[index].voicechanger_parm.is_bypass = 0; + eff_mode[index].voicechanger_parm.parm.effect_v = 0; + eff_mode[index].voicechanger_parm.parm.shiftv = 56; + eff_mode[index].voicechanger_parm.parm.formant_shift = 90; +#endif + +//echo + eff_mode[index].echo_parm.is_bypass = 0; + eff_mode[index].echo_parm.parm.decayval = 60; + eff_mode[index].echo_parm.parm.delay = 400; + eff_mode[index].echo_parm.parm.filt_enable = 1; + eff_mode[index].echo_parm.parm.lpf_cutoff = 5000; + eff_mode[index].echo_parm.parm.drygain = 60; + eff_mode[index].echo_parm.parm.wetgain = 50; + +//palte_reverb + eff_mode[index].plate_reverb_parm.is_bypass = 0; + eff_mode[index].plate_reverb_parm.parm.pre_delay = 0; + eff_mode[index].plate_reverb_parm.parm.highcutoff = 12200; + eff_mode[index].plate_reverb_parm.parm.diffusion = 43; + eff_mode[index].plate_reverb_parm.parm.decayfactor = 70; + eff_mode[index].plate_reverb_parm.parm.highfrequencydamping = 26; + eff_mode[index].plate_reverb_parm.parm.dry = 80; + eff_mode[index].plate_reverb_parm.parm.wet = 40; + eff_mode[index].plate_reverb_parm.parm.modulate = 1; + eff_mode[index].plate_reverb_parm.parm.roomsize = 100; + + for (int i = 0; i < 5; i++) { +//eq + eff_mode[index].eq_parm[i].global_gain = 0; + eff_mode[index].eq_parm[i].seg_num = ARRAY_SIZE(mic_eff_eq_tab); + memcpy(eff_mode[index].eq_parm[i].seg, mic_eff_eq_tab, sizeof(mic_eff_eq_tab)); +//drc + struct threshold_group group[] = {{0, 0}, {50, 50}, {90, 90}}; + eff_mode[index].drc_parm[i].is_bypass = 0; + eff_mode[index].drc_parm[i].parm.attacktime = 10; + eff_mode[index].drc_parm[i].parm.releasetime = 300; + eff_mode[index].drc_parm[i].parm.inputgain = 0; + eff_mode[index].drc_parm[i].parm.outputgain = 0; + eff_mode[index].drc_parm[i].parm.threshold_num = ARRAY_SIZE(group); + memcpy(eff_mode[index].drc_parm[i].parm.threshold, group, sizeof(group)); + eff_mode[index].drc_parm[i].parm.rms_time = 25; + eff_mode[index].drc_parm[i].parm.algorithm = 0; + eff_mode[index].drc_parm[i].parm.mode = 1; + } +#if GAIN_PROCESS_EN + float gain = 0; + eff_mode[index].gain_parm.parm.gain = powf(10, gain / 20.0f); //db转mag,工具传下来的值 + eff_mode[index].gain_parm.is_bypass = 0; +#endif +} +#endif diff --git a/cpu/br23/audio_effect/audio_eff_default_parm.h b/cpu/br23/audio_effect/audio_eff_default_parm.h new file mode 100644 index 0000000..15a1451 --- /dev/null +++ b/cpu/br23/audio_effect/audio_eff_default_parm.h @@ -0,0 +1,49 @@ +#ifndef _AUD_EFF_DEFAULT_PARM__H +#define _AUD_EFF_DEFAULT_PARM__H + +#include "app_config.h" +#include "media/effects_adj.h" + +#if(TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE) +enum { + EFFECT_REVERB_PARM_KTV = 0, + EFFECT_REVERB_PARM_POP, + EFFECT_REVERB_PARM_qingrou, + EFFECT_REVERB_PARM_SUPER_REVERB, + EFFECT_REVERB_PARM_SONG, + EFFECT_REVERB_PARM_MAX, +}; +#else +enum { + EFFECT_REVERB_PARM_KTV = 0, + EFFECT_REVERB_PARM_MAX, + + EFFECT_REVERB_PARM_POP, + EFFECT_REVERB_PARM_qingrou, + EFFECT_REVERB_PARM_SUPER_REVERB, + EFFECT_REVERB_PARM_SONG, +}; + +#endif + +extern struct phone_parm_tool_set phone_mode[4];//通话上下行模式 0:下行宽 1:下行窄 2:上行宽 3:上行窄 +extern struct eff_parm eff_mode[EFFECT_REVERB_PARM_MAX];//混响的8个模式 +extern struct music_parm_tool_set music_mode;//音乐模式 +extern struct music_eq2_tool music_eq2_parm; +extern DynamicEQParam_TOOL_SET dynamic_eq;//动态eq +extern Gain_Process_TOOL_SET gain_parm;//音乐模式尾部的增益调节 +extern LowPassParam_TOOL_SET low_pass_parm;//rl rr通道低通滤波器 +extern struct music_eq_tool rl_eq_parm;//rl通道eq +extern struct nband_drc rl_drc_parm;//rl通道drc +extern Gain_Process_TOOL_SET rl_gain_parm;//rl通道gain parm + +extern struct music_parm_tool_set linein_mode;//音乐模式 +extern Gain_Process_TOOL_SET linein_gain_parm;//音乐模式尾部的增益调节 +extern Gain_Process_TOOL_SET vbass_prev_gain_parm; + +extern VirtualBass_TOOL_SET vbass_parm;//虚拟低音 + +extern struct music_eq_tool high_bass_eq_parm; +extern wdrc_struct_TOOL_SET high_bass_drc_parm; + +#endif diff --git a/cpu/br23/audio_effect/audio_eq_drc_demo.c b/cpu/br23/audio_effect/audio_eq_drc_demo.c new file mode 100644 index 0000000..70f3186 --- /dev/null +++ b/cpu/br23/audio_effect/audio_eq_drc_demo.c @@ -0,0 +1,613 @@ + +#include "system/includes.h" +#include "media/includes.h" +#include "app_config.h" +#include "clock_cfg.h" +#include "media/audio_eq_drc_apply.h" +#include "audio_eq_drc_demo.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" +#include "audio_effect/audio_sound_track_2_p_x.h" + + +#if 0 +//系数切换 +void eq_sw_demo() +{ + eq_mode_sw();//7种默认系数切换 +} + +//获取当前eq系数表类型 +void eq_mode_get_demo() +{ + u8 mode ; + mode = eq_mode_get_cur(); +} +//宏TCFG_USE_EQ_FILE配0 +//自定义系数表动态更新 +//本demo 示意更新中心截止频率,增益,总增益,如需设置更多参数,请查看eq_config.h头文件的demo +void eq_update_demo() +{ + eq_mode_set_custom_info(0, 200, 2);//第0段,200Hz中心截止频率,2db + eq_mode_set_custom_info(5, 2000, 2);//第5段,2000Hz中心截止频率,2db + + set_global_gain(get_eq_cfg_hdl(), song_eq_mode, -2);//设置普通音乐eq 总增益 -2db(可避免最大增益大于0db,导致失真) + + eq_mode_set(EQ_MODE_CUSTOM);//设置系数、总增益更新 +} + +#endif + +//用户自定义eq drc系数 +#if 1 + +static const struct eq_seg_info your_audio_out_eq_tab[] = {//2段系数 + {0, EQ_IIR_TYPE_BAND_PASS, 125, 0, 0.7f}, + {1, EQ_IIR_TYPE_BAND_PASS, 12000, 0, 0.7f}, +}; +static int your_eq_coeff_tab[2][5];//2段eq系数表的长度 +/*----------------------------------------------------------------------------*/ +/**@brief 用户自定义eq的系数回调 + @param eq:句柄 + @param sr:采样率 + @param info: 系数地址 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int eq_get_filter_info_demo(void *_eq, int sr, struct audio_eq_filter_info *info) +{ + if (!sr) { + sr = 44100; + } +#if TCFG_EQ_ENABLE + local_irq_disable(); + u8 nsection = ARRAY_SIZE(your_audio_out_eq_tab); + for (int i = 0; i < nsection; i++) { + eq_seg_design(&your_audio_out_eq_tab[i], sr, your_eq_coeff_tab[i]);//根据采样率对eq系数表,重计算,得出适用的系数表 + } + local_irq_enable(); + info->L_coeff = info->R_coeff = (void *)your_eq_coeff_tab;//系数指针赋值 + info->L_gain = info->R_gain = 0;//总增益填写,用户可修改(-20~20db),注意大于0db存在失真风险 + info->nsection = nsection;//eq段数,根据提供给的系数表来填写,例子是2 +#endif//TCFG_EQ_ENABLE + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 更新自定义eq系数后,需要使用本函数将系数更新到eq模块 + @param *_drc: 句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void eq_filter_info_update_demo(void *_eq) +{ +#if TCFG_EQ_ENABLE + struct audio_eq *eq = (struct audio_eq *)_eq; + local_irq_disable(); + if (eq) { + eq->updata = 1; + } + local_irq_enable(); +#endif//TCFG_EQ_ENABLE + +} + + + +static struct drc_ch drc_fliter = {0}; +#define your_threshold (0) +/*----------------------------------------------------------------------------*/ +/**@brief 自定义限幅器系数回调 + @param *drc: 句柄 + @param *info: 系数结构地址 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int drc_get_filter_info_demo(void *drc, struct audio_drc_filter_info *info) +{ +#if TCFG_DRC_ENABLE + float th = your_threshold;//-60 ~0db + int threshold = round(pow(10.0, th / 20.0) * 32768); // 0db:32768, -60db:33 + + /* drc_fliter.nband = 1; */ + /* drc_fliter.type = 1; */ + /* drc_fliter._p.limiter[0].attacktime = 5; */ + /* drc_fliter._p.limiter[0].releasetime = 300; */ + /* drc_fliter._p.limiter[0].threshold[0] = threshold; */ + /* drc_fliter._p.limiter[0].threshold[1] = 32768; */ + + /* info->pch = info->R_pch = &drc_fliter; */ +#endif//TCFG_DRC_ENABLE + + return 0; +} +#endif + + +/*----------------------------------------------------------------------------*/ +/**@brief 更新自定义限幅器系数后,需要使用本函数将系数更新到drc模块 + @param *_drc: 句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void drc_filter_info_update_demo(void *_drc) +{ +#if TCFG_DRC_ENABLE + struct audio_drc *drc = (struct audio_drc *)_drc; + local_irq_disable(); + if (drc) { + drc->updata = 1; + } + local_irq_enable(); +#endif//TCFG_DRC_ENABLE + +} + +struct audio_eq *music_eq_open(u32 sample_rate, u8 ch_num) +{ +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE + struct audio_eq_param parm = {0}; + parm.channels = ch_num; +#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE + parm.out_32bit = 1;//32bit位宽输出 +#endif + parm.no_wait = 1; + parm.cb = eq_get_filter_info; + parm.sr = sample_rate; + parm.eq_name = AEID_MUSIC_EQ; + + parm.max_nsection = music_mode.eq_parm.seg_num; + parm.nsection = music_mode.eq_parm.seg_num; + parm.seg = music_mode.eq_parm.seg; + parm.global_gain = music_mode.eq_parm.global_gain; + struct audio_eq *eq = audio_dec_eq_open(&parm); + clock_add(EQ_CLK); + return eq; +#endif //TCFG_EQ_ENABLE + return NULL; +} + +void music_eq_close(struct audio_eq *eq) +{ +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE + if (eq) { + audio_dec_eq_close(eq); + clock_remove(EQ_CLK); + } +#endif/*TCFG_EQ_ENABLE*/ +} + +struct audio_eq *music_eq2_open(u32 sample_rate, u8 ch_num) +{ +#if TCFG_DYNAMIC_EQ_ENABLE +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE + struct audio_eq_param parm = {0}; + parm.channels = ch_num; +#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE + parm.out_32bit = 1;//32bit位宽输出 +#endif + parm.no_wait = 1; + parm.cb = eq_get_filter_info; + parm.sr = sample_rate; + parm.eq_name = AEID_MUSIC_EQ2; + + parm.max_nsection = music_eq2_parm.seg_num; + parm.nsection = music_eq2_parm.seg_num; + parm.seg = music_eq2_parm.seg; + parm.global_gain = music_eq2_parm.global_gain; + struct audio_eq *eq = audio_dec_eq_open(&parm); + clock_add(EQ_CLK); + return eq; +#endif //TCFG_EQ_ENABLE +#endif + return NULL; +} + +void music_eq2_close(struct audio_eq *eq) +{ +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE + if (eq) { + audio_dec_eq_close(eq); + clock_remove(EQ_CLK); + } +#endif/*TCFG_EQ_ENABLE*/ +} + + + +struct audio_drc *music_drc_open(u32 sample_rate, u8 ch_num) +{ +#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE + struct audio_drc_param parm = {0}; + parm.channels = ch_num; + parm.sr = sample_rate; + parm.out_32bit = 1; + parm.cb = drc_get_filter_info; + parm.drc_name = AEID_MUSIC_DRC; +#if defined(TCFG_AUDIO_MDRC_ENABLE) && (TCFG_AUDIO_MDRC_ENABLE == 1) + parm.nband = CROSSOVER_EN;// +#elif defined(TCFG_AUDIO_MDRC_ENABLE) && (TCFG_AUDIO_MDRC_ENABLE == 2) + parm.nband = CROSSOVER_EN | MORE_BAND_EN;// +#endif/*TCFG_AUDIO_MDRC_ENABLE*/ + + parm.crossover = &music_mode.drc_parm.crossover; + parm.wdrc = music_mode.drc_parm.wdrc_parm; + struct audio_drc *drc = audio_dec_drc_open(&parm); + clock_add(EQ_DRC_CLK); + return drc; +#endif/*TCFG_DRC_ENABLE*/ + return NULL; +} + +void music_drc_close(struct audio_drc *drc) +{ + if (drc) { + audio_dec_drc_close(drc); + clock_remove(EQ_DRC_CLK); + } +} + + + +struct audio_eq *esco_eq_open(u32 sample_rate, u8 ch_num, u8 bit_wide) +{ +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE + struct audio_eq_param parm = {0}; + parm.channels = ch_num; +#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE + parm.out_32bit = bit_wide;//32bit位宽输出 +#endif + parm.no_wait = 1; + parm.cb = eq_get_filter_info; + parm.sr = sample_rate; + parm.eq_name = AEID_ESCO_DL_EQ; + u8 index = 0; + if (sample_rate == 8000) { //窄频 + index = 1; + } + parm.max_nsection = phone_mode[index].eq_parm.seg_num; + parm.nsection = phone_mode[index].eq_parm.seg_num; + parm.seg = phone_mode[index].eq_parm.seg; + parm.global_gain = phone_mode[index].eq_parm.global_gain; + struct audio_eq *eq = audio_dec_eq_open(&parm); + clock_add(EQ_CLK); + return eq; +#endif //TCFG_EQ_ENABLE + return NULL; +} + +void esco_eq_close(struct audio_eq *eq) +{ +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE + if (eq) { + audio_dec_eq_close(eq); + clock_remove(EQ_CLK); + } +#endif/*TCFG_EQ_ENABLE*/ +} + +struct audio_drc *esco_drc_open(u32 sample_rate, u8 ch_num, u8 bit_wide) +{ +#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE + struct audio_drc_param parm = {0}; + parm.channels = ch_num; + parm.sr = sample_rate; + parm.out_32bit = bit_wide; + parm.cb = drc_get_filter_info; + parm.drc_name = AEID_ESCO_DL_DRC; + u8 index = 0; + if (sample_rate == 8000) { //窄频 + index = 1; + } + parm.wdrc = &phone_mode[index].drc_parm; + struct audio_drc *drc = audio_dec_drc_open(&parm); + clock_add(EQ_DRC_CLK); + return drc; +#endif/*TCFG_DRC_ENABLE*/ + return NULL; +} + +void esco_drc_close(struct audio_drc *drc) +{ + if (drc) { + audio_dec_drc_close(drc); + clock_remove(EQ_DRC_CLK); + } +} + +struct audio_eq *music_eq_rl_rr_open(u32 sample_rate, u8 ch_num) +{ +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE + struct audio_eq_param parm = {0}; + parm.channels = ch_num; +#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE + parm.out_32bit = 1;//32bit位宽输出 +#endif + parm.no_wait = 1; +#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) &&SOUND_TRACK_2_P_X_CH_CONFIG + parm.cb = low_bass_eq_get_filter_info_demo; +#else + parm.cb = eq_get_filter_info; +#endif + parm.sr = sample_rate; + parm.eq_name = AEID_MUSIC_RL_EQ; + + parm.max_nsection = music_mode.eq_parm.seg_num; + parm.nsection = music_mode.eq_parm.seg_num; + parm.seg = music_mode.eq_parm.seg; + parm.global_gain = music_mode.eq_parm.global_gain; + struct audio_eq *eq = audio_dec_eq_open(&parm); + clock_add(EQ_CLK); + return eq; +#endif //TCFG_EQ_ENABLE + return NULL; +} + +void music_eq_rl_rr_close(struct audio_eq *eq) +{ +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE + if (eq) { + audio_dec_eq_close(eq); + clock_remove(EQ_CLK); + } +#endif/*TCFG_EQ_ENABLE*/ +} + + +struct audio_drc *music_drc_rl_rr_open(u32 sample_rate, u8 ch_num) +{ +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) +#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE + struct audio_drc_param parm = {0}; + parm.channels = ch_num; + parm.sr = sample_rate; + parm.out_32bit = 1; + parm.cb = drc_get_filter_info; + parm.drc_name = AEID_MUSIC_RL_DRC; +#if defined(TCFG_AUDIO_MDRC_ENABLE) && (TCFG_AUDIO_MDRC_ENABLE == 1) + parm.nband = CROSSOVER_EN;// +#elif defined(TCFG_AUDIO_MDRC_ENABLE) && (TCFG_AUDIO_MDRC_ENABLE == 2) + parm.nband = CROSSOVER_EN | MORE_BAND_EN;// +#endif/*TCFG_AUDIO_MDRC_ENABLE*/ + + parm.crossover = &rl_drc_parm.crossover;//参数需要修改 + parm.wdrc = rl_drc_parm.wdrc_parm; + struct audio_drc *drc = audio_dec_drc_open(&parm); + clock_add(EQ_DRC_CLK); + return drc; +#endif/*TCFG_DRC_ENABLE*/ +#endif + return NULL; +} + +void music_drc_rl_rr_close(struct audio_drc *drc) +{ + if (drc) { + audio_dec_drc_close(drc); + clock_remove(EQ_DRC_CLK); + } +} + + + + +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN +struct audio_eq *linein_eq_open(u32 sample_rate, u8 ch_num) +{ +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE + struct audio_eq_param parm = {0}; + parm.channels = ch_num; +#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE + parm.out_32bit = 1;//32bit位宽输出 +#endif + parm.no_wait = 1; + parm.cb = eq_get_filter_info; + parm.sr = sample_rate; + parm.eq_name = AEID_LINEIN_EQ; + + parm.max_nsection = linein_mode.eq_parm.seg_num; + parm.nsection = linein_mode.eq_parm.seg_num; + parm.seg = linein_mode.eq_parm.seg; + parm.global_gain = linein_mode.eq_parm.global_gain; + struct audio_eq *eq = audio_dec_eq_open(&parm); + clock_add(EQ_CLK); + return eq; +#endif //TCFG_EQ_ENABLE + return NULL; +} + +void linein_eq_close(struct audio_eq *eq) +{ +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE + if (eq) { + audio_dec_eq_close(eq); + clock_remove(EQ_CLK); + } +#endif/*TCFG_EQ_ENABLE*/ +} + +struct audio_drc *linein_drc_open(u32 sample_rate, u8 ch_num) +{ +#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE + struct audio_drc_param parm = {0}; + parm.channels = ch_num; + parm.sr = sample_rate; + parm.out_32bit = 1; + parm.cb = drc_get_filter_info; + parm.drc_name = AEID_LINEIN_DRC; + +#if 0 +#if defined(TCFG_AUDIO_MDRC_ENABLE) && (TCFG_AUDIO_MDRC_ENABLE == 1) + parm.nband = CROSSOVER_EN;// +#elif defined(TCFG_AUDIO_MDRC_ENABLE) && (TCFG_AUDIO_MDRC_ENABLE == 2) + parm.nband = CROSSOVER_EN | MORE_BAND_EN;// +#endif/*TCFG_AUDIO_MDRC_ENABLE*/ + + parm.crossover = &linein_mode.drc_parm.crossover; +#endif + parm.wdrc = linein_mode.drc_parm.wdrc_parm; + struct audio_drc *drc = audio_dec_drc_open(&parm); + clock_add(EQ_DRC_CLK); + return drc; +#endif/*TCFG_DRC_ENABLE*/ + return NULL; +} + +void linein_drc_close(struct audio_drc *drc) +{ + if (drc) { + audio_dec_drc_close(drc); + clock_remove(EQ_DRC_CLK); + } +} +#endif + +struct music_eq_tool high_bass_eq_parm = {0}; +struct eq_seg_info high_bass_eq_seg[] = { + {0, EQ_IIR_TYPE_BAND_PASS, 125, 0, 0.7f}, + {1, EQ_IIR_TYPE_BAND_PASS, 12000, 0, 0.3f}, +}; +struct audio_eq *high_bass_eq_open(u32 sample_rate, u8 ch_num) +{ +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE && TCFG_AUDIO_OUT_EQ_ENABLE + + u16 seg_num = high_bass_eq_parm.seg_num; + for (int i = 0; i < ARRAY_SIZE(high_bass_eq_seg); i++) { + high_bass_eq_seg[i].index = seg_num + i; + memcpy(&high_bass_eq_parm.seg[seg_num + i], &high_bass_eq_seg[i], sizeof(struct eq_seg_info)); + } + + struct audio_eq_param parm = {0}; + parm.channels = ch_num; +#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE && TCFG_AUDIO_OUT_DRC_ENABLE + parm.out_32bit = 1;//32bit位宽输出 +#endif + parm.no_wait = 1; + parm.cb = eq_get_filter_info; + parm.sr = sample_rate; + parm.eq_name = AEID_HIGH_BASS_EQ; + seg_num += ARRAY_SIZE(high_bass_eq_seg); + parm.max_nsection = seg_num; + parm.nsection = seg_num; + parm.seg = high_bass_eq_parm.seg; + parm.global_gain = high_bass_eq_parm.global_gain; + + parm.fade = 1;//高低音增益更新差异大,会引入哒哒音,此处使能系数淡入 + parm.fade_step = 0.4f;//淡入步进(0.1f~1.0f) + + struct audio_eq *eq = audio_dec_eq_open(&parm); + clock_add(EQ_CLK); + return eq; +#endif /*TCFG_EQ_ENABLE*/ + return NULL; +} + +void high_bass_eq_close(struct audio_eq *eq) +{ +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE && TCFG_AUDIO_OUT_EQ_ENABLE + if (eq) { + audio_dec_eq_close(eq); + clock_remove(EQ_CLK); + } +#endif/*TCFG_EQ_ENABLE*/ +} +/* + *index: 0, 更新低音中心频率freq,增益gain + *index: 1, 更新高音中心频率freq,增益gain + * */ +void high_bass_eq_udpate(u8 index, int freq, float gain) +{ + if (freq) { + high_bass_eq_seg[index].freq = freq; + } + high_bass_eq_seg[index].gain = gain; + printf("index %d ,gain %d\n", index, (int)gain); + cur_eq_set_update(AEID_HIGH_BASS_EQ, &high_bass_eq_seg[index], high_bass_eq_parm.seg_num + ARRAY_SIZE(high_bass_eq_seg), 0); +} + +//兼容旧接口 +void mix_out_high_bass(u32 cmd, struct high_bass *hb) +{ + if (cmd == AUDIO_EQ_HIGH) { + high_bass_eq_udpate(1, hb->freq, hb->gain); + } else if (cmd == AUDIO_EQ_BASS) { + high_bass_eq_udpate(0, hb->freq, hb->gain); + } +} + +wdrc_struct_TOOL_SET high_bass_drc_parm = {0}; +struct audio_drc *high_bass_drc_open(u32 sample_rate, u8 ch_num) +{ +#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE && TCFG_AUDIO_OUT_DRC_ENABLE + struct threshold_group group[] = {{0, 0}, {50, 50}, {90, 90}}; + high_bass_drc_parm.is_bypass = 0; + high_bass_drc_parm.parm.attacktime = 10; + high_bass_drc_parm.parm.releasetime = 300; + high_bass_drc_parm.parm.inputgain = 0; + high_bass_drc_parm.parm.outputgain = 0; + high_bass_drc_parm.parm.threshold_num = ARRAY_SIZE(group); + memcpy(high_bass_drc_parm.parm.threshold, group, sizeof(group)); + high_bass_drc_parm.parm.rms_time = 25; + high_bass_drc_parm.parm.algorithm = 0; + high_bass_drc_parm.parm.mode = 1; + + struct audio_drc_param parm = {0}; + parm.channels = ch_num; + parm.sr = sample_rate; +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE && TCFG_AUDIO_OUT_EQ_ENABLE + parm.out_32bit = 1; +#else + parm.out_32bit = 0; +#endif + parm.cb = drc_get_filter_info; + parm.drc_name = AEID_HIGH_BASS_DRC; + parm.wdrc = &high_bass_drc_parm; + struct audio_drc *drc = audio_dec_drc_open(&parm); + clock_add(EQ_DRC_CLK); + return drc; +#endif/*TCFG_DRC_ENABLE*/ + + return NULL; +} + +void high_bass_drc_close(struct audio_drc *drc) +{ +#if defined(TCFG_DRC_ENABLE) && TCFG_DRC_ENABLE && TCFG_AUDIO_OUT_DRC_ENABLE + if (drc) { + audio_dec_drc_close(drc); + clock_remove(EQ_DRC_CLK); + } +#endif +} +/*----------------------------------------------------------------------------*/ +/**@brief 高低音限幅器系数回调 + @param *drc: 句柄 + @param *info: 系数结构地址 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int high_bass_drc_set_filter_info(int th) +{ + if (th < -60) { + th = -60; + } + if (th > 0) { + th = 0; + } + + struct threshold_group group[] = {{0, 0}, {50, 50}, {90, 90}}; + group[1].in_threshold = 90 + th; + group[1].out_threshold = 90 + th; + group[2].in_threshold = 90.3f; + group[2].out_threshold = 90 + th; + memcpy(high_bass_drc_parm.parm.threshold, group, sizeof(group)); + cur_drc_set_update(AEID_HIGH_BASS_DRC, 0, &high_bass_drc_parm); + return 0; +} + diff --git a/cpu/br23/audio_effect/audio_eq_drc_demo.h b/cpu/br23/audio_effect/audio_eq_drc_demo.h new file mode 100644 index 0000000..d9ff732 --- /dev/null +++ b/cpu/br23/audio_effect/audio_eq_drc_demo.h @@ -0,0 +1,43 @@ +#ifndef _AUD_DEC_EFF_H +#define _AUD_DEC_EFF_H +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "media/eq_config.h" +#include "app_config.h" +#include "audio_config.h" + +struct audio_eq *music_eq_open(u32 sample_rate, u8 ch_num); +void music_eq_close(struct audio_eq *eq); +struct audio_drc *music_drc_open(u32 sample_rate, u8 ch_num); +void music_drc_close(struct audio_drc *drc); +struct audio_eq *music_eq2_open(u32 sample_rate, u8 ch_num); +void music_eq2_close(struct audio_eq *eq); + +struct audio_eq *music_eq_rl_rr_open(u32 sample_rate, u8 ch_num); +void music_eq_rl_rr_close(struct audio_eq *eq); +struct audio_drc *music_drc_rl_rr_open(u32 sample_rate, u8 ch_num); +void music_drc_rl_rr_close(struct audio_drc *drc); + +struct audio_eq *esco_eq_open(u32 sample_rate, u8 ch_num, u8 bit_wide); +void esco_eq_close(struct audio_eq *eq); +struct audio_drc *esco_drc_open(u32 sample_rate, u8 ch_num, u8 bit_wide); +void esco_drc_close(struct audio_drc *drc); + + +struct audio_eq *linein_eq_open(u32 sample_rate, u8 ch_num); +void linein_eq_close(struct audio_eq *eq); +struct audio_drc *linein_drc_open(u32 sample_rate, u8 ch_num); +void linein_drc_close(struct audio_drc *drc); + + +struct audio_eq *high_bass_eq_open(u32 sample_rate, u8 ch_num); +void high_bass_eq_close(struct audio_eq *eq); +void high_bass_eq_udpate(u8 index, int freq, float gain); +void mix_out_high_bass(u32 cmd, struct high_bass *hb); + +struct audio_drc *high_bass_drc_open(u32 sample_rate, u8 ch_num); +void high_bass_drc_close(struct audio_drc *drc); +int high_bass_drc_set_filter_info(int th); + +#endif diff --git a/cpu/br23/audio_effect/audio_gain_process_demo.c b/cpu/br23/audio_effect/audio_gain_process_demo.c new file mode 100644 index 0000000..6d400a8 --- /dev/null +++ b/cpu/br23/audio_effect/audio_gain_process_demo.c @@ -0,0 +1,73 @@ +#include "audio_gain_process_demo.h" +#include "app_config.h" + +#if GAIN_PROCESS_EN +Gain_Process_TOOL_SET rl_gain_parm;//rl通道gain parm +Gain_Process_TOOL_SET gain_parm;//音乐模式尾部的增益调节 +Gain_Process_TOOL_SET linein_gain_parm;//音乐模式尾部的增益调节 +#endif +Gain_Process_TOOL_SET vbass_prev_gain_parm; +struct aud_gain_process *audio_gain_open_demo(u16 gain_name, u8 channel) +{ + if (gain_name != AEID_MUSIC_VBASS_PREV_GAIN) { + return NULL; + } + struct aud_gain_parm parm = {0}; + + float gain = 0; + u8 bypass = 0; +#if GAIN_PROCESS_EN + if (gain_name == AEID_MUSIC_GAIN) { + gain = gain_parm.parm.gain; + bypass = gain_parm.is_bypass; + } else if (gain_name == AEID_MUSIC_RL_GAIN) { + gain = rl_gain_parm.parm.gain; + bypass = rl_gain_parm.is_bypass; + } else if (gain_name == AEID_LINEIN_GAIN) { +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN + gain = linein_gain_parm.parm.gain; + bypass = linein_gain_parm.is_bypass; +#endif + } else if (gain_name == AEID_MIC_GAIN) { +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + + u8 mode = get_mic_eff_mode(); + gain = eff_mode[mode].gain_parm.parm.gain; + bypass = eff_mode[mode].gain_parm.is_bypass; +#endif + } else +#endif/*GAIN_PROCESS_EN*/ + if (gain_name == AEID_MUSIC_VBASS_PREV_GAIN) { + gain = vbass_prev_gain_parm.parm.gain; + bypass = vbass_prev_gain_parm.is_bypass; + } + + parm.gain = gain; + parm.channel = channel; + parm.indata_inc = (channel == 1) ? 1 : 2; + parm.outdata_inc = (channel == 1) ? 1 : 2; + parm.bit_wide = 0; //16bit_wide + parm.gain_name = gain_name; + struct aud_gain_process *hdl = audio_gain_process_open(&parm); + audio_gain_process_bypass(parm.gain_name, bypass); + return hdl; +} + + +void audio_gain_close_demo(struct aud_gain_process *hdl) +{ + if (!hdl) { + return; + } + audio_gain_process_close(hdl); + hdl = NULL; +} + +void audio_gain_update_parm(u16 gain_name, void *parm, int bypass) +{ + audio_gain_process_update(gain_name, parm); + audio_gain_process_bypass(gain_name, bypass); +} + + + diff --git a/cpu/br23/audio_effect/audio_gain_process_demo.h b/cpu/br23/audio_effect/audio_gain_process_demo.h new file mode 100644 index 0000000..2a16d46 --- /dev/null +++ b/cpu/br23/audio_effect/audio_gain_process_demo.h @@ -0,0 +1,12 @@ +#ifndef __AUDIO_GAIN_DEMO__H +#define __AUDIO_GAIN_DEMO__H + + +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" +#include "media/audio_gain_process.h" + +struct aud_gain_process *audio_gain_open_demo(u16 gain_name, u8 channel); +void audio_gain_close_demo(struct aud_gain_process *hdl); +void audio_gain_update_parm(u16 gain_name, void *parm, int bypass); +#endif diff --git a/cpu/br23/audio_effect/audio_sound_track_2_p_x.c b/cpu/br23/audio_effect/audio_sound_track_2_p_x.c new file mode 100644 index 0000000..656695d --- /dev/null +++ b/cpu/br23/audio_effect/audio_sound_track_2_p_x.c @@ -0,0 +1,264 @@ +#include "audio_sound_track_2_p_x.h" +#include "app_config.h" + + +#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) &&SOUND_TRACK_2_P_X_CH_CONFIG + +#define LOW_BASS_GLOBAL_GAIN_STEP 1//(0.2f)//低音总增益调节淡入淡出步进,范围(0.1f~1) +#define LOW_BASS_NSOS 4 //多阶低通滤波器使能,4阶级IIR(最大配8) +#define LOW_BASS_FREQ (100)//低通滤波器的中心截止频率 + +#define LOW_BASS_THRESHOLD (-0.5f)//低通滤波后的限幅器阈值,范围(-60~0)db +#define LOW_BASS_DRC_PRE_EN 1 //(低通滤波前是否需要对数据先做一次衰减) + +static float cur_L_global_gain = 0; +static float cur_R_global_gain = 0; +static u16 fade_tmr = 0; + +static const struct eq_seg_info low_bass_eq_tab[] = {//一段低通滤波器 + {0, EQ_IIR_TYPE_LOW_PASS, LOW_BASS_FREQ, 0, 0.7f} +}; +static int your_eq_coeff_tab[2][5];//2段eq系数表的长度 +static float low_bass_L_global_gain = 0; +static float low_bass_R_global_gain = 0; +int low_bass_eq_get_filter_info_demo(void *_eq, int sr, struct audio_eq_filter_info *info) +{ + if (!sr) { + sr = 44100; + } +#if TCFG_EQ_ENABLE +#if LOW_BASS_NSOS + struct audio_eq *eq = (struct audio_eq *)_eq; + /* local_irq_disable(); */ + u16 is_bypass = low_pass_parm.is_bypass; + u16 center_freq = low_pass_parm.low_pass.fc;//中心截止频率 + u16 nsos = low_pass_parm.low_pass.order;//阶数 + u16 nsection = 0; + if (!is_bypass) { + if (!center_freq) { + center_freq = 100; + } + if (!nsos) { + nsos = 1; + } + nsection = ((nsos & 1) + (nsos >> 1));//LOW_BASS_NSOS; + + if (eq->eq_coeff_tab) { + free(eq->eq_coeff_tab); + eq->eq_coeff_tab = NULL; + } + if (!eq->eq_coeff_tab) { + eq->eq_coeff_tab = zalloc(sizeof(int) * 5 * nsection); + } + butterworth_lp_design(center_freq, sr, nsos, eq->eq_coeff_tab);//多阶低通滤波器运算,得出系数 + } else { + nsection = 1; + eq_get_AllpassCoeff(eq->eq_coeff_tab); + } + /* + for (int i = 0; i < nsection; i++) { + printf("cal coeff:%d, %d, %d, %d, %d ", + eq->eq_coeff_tab[5 * i] + , eq->eq_coeff_tab[5 * i + 1] + , eq->eq_coeff_tab[5 * i + 2] + , eq->eq_coeff_tab[5 * i + 3] + , eq->eq_coeff_tab[5 * i + 4] + ); + + } + */ + /* local_irq_enable(); */ + info->L_coeff = info->R_coeff = (void *)eq->eq_coeff_tab; +#else + local_irq_disable(); + u8 nsection = ARRAY_SIZE(low_bass_eq_tab); + for (int i = 0; i < nsection; i++) { + eq_seg_design(&low_bass_eq_tab[i], sr, your_eq_coeff_tab[i]);//根据采样率对eq系数表,重计算,得出适用的系数表 + } + local_irq_enable(); + info->L_coeff = info->R_coeff = (void *)your_eq_coeff_tab;//系数指针赋值 +#endif + info->L_gain = cur_L_global_gain; + info->R_gain = cur_R_global_gain;//总增益填写,用户可修改(-20~20db),注意大于0db存在失真风险 + info->nsection = nsection;//eq段数,根据提供给的系数表来填写,例子是2 +#endif//TCFG_EQ_ENABLE + return 0; +} + +static void global_gain_fade_run(void *p) +{ + struct audio_eq *eq = (struct audio_eq *)p; + u8 update = 0; + if (cur_L_global_gain > low_bass_L_global_gain) { + cur_L_global_gain -= LOW_BASS_GLOBAL_GAIN_STEP; + if (cur_L_global_gain < low_bass_L_global_gain) { + cur_L_global_gain = low_bass_L_global_gain; + } + update = 1; + } + if (cur_L_global_gain < low_bass_L_global_gain) { + cur_L_global_gain += LOW_BASS_GLOBAL_GAIN_STEP; + if (cur_L_global_gain > low_bass_L_global_gain) { + cur_L_global_gain = low_bass_L_global_gain; + } + update = 1; + } + + if (cur_R_global_gain > low_bass_R_global_gain) { + cur_R_global_gain -= LOW_BASS_GLOBAL_GAIN_STEP; + if (cur_R_global_gain < low_bass_R_global_gain) { + cur_R_global_gain = low_bass_R_global_gain; + } + update = 1; + } + if (cur_R_global_gain < low_bass_R_global_gain) { + cur_R_global_gain += LOW_BASS_GLOBAL_GAIN_STEP; + if (cur_R_global_gain > low_bass_R_global_gain) { + cur_R_global_gain = low_bass_R_global_gain; + } + update = 1; + } + if (update) { + update = 0; + //printf("cur_L_global_gain %d, cur_R_global_gain %d\n", (int)cur_L_global_gain, (int)cur_R_global_gain); + //printf("low_bass_L_global_gain %d, low_bass_R_global_gain %d\n", (int)low_bass_L_global_gain, (int)low_bass_R_global_gain); + + local_irq_disable(); + if (eq) { + eq->updata = 1; + } + local_irq_enable(); + } else { + if (fade_tmr) { + sys_hi_timer_del(fade_tmr); + fade_tmr = 0; + } + } +} + +static void low_bass_eq_filter_info_update_demo(u32 eq_name) +{ +#if TCFG_EQ_ENABLE + struct audio_eq *eq = get_cur_eq_hdl_by_name(eq_name); + if (!eq) { + return; + } +#if 1 + if (!fade_tmr) { + fade_tmr = sys_hi_timer_add(eq, global_gain_fade_run, 20); + } +#else + // 参数直接更新,dB 跳跃大时,会有哒哒音 + cur_L_global_gain = low_bass_L_global_gain; + cur_R_global_gain = low_bass_R_global_gain; + local_irq_disable(); + if (eq) { + eq->updata = 1; + } + local_irq_enable(); +#endif +#endif//TCFG_EQ_ENABLE +} + + +void low_bass_set_global_gain(float left_global_gain, float right_global_gain) +{ + + if (left_global_gain > 20) { + left_global_gain = 20; + } else if (left_global_gain < -90) { + left_global_gain = -90; + } + + if (right_global_gain > 20) { + right_global_gain = 20; + } else if (right_global_gain < -90) { + right_global_gain = -90; + } + + /* log_i("global_gain "); */ + /* put_buf(&left_global_gain, 4); */ + /* put_buf(&right_global_gain, 4); */ + low_bass_L_global_gain = left_global_gain; + low_bass_R_global_gain = right_global_gain; + low_bass_eq_filter_info_update_demo(EFF_MUSIC_RL_EQ); +} + +void low_bass_set_left_global_gain(float left_global_gain) +{ + if (left_global_gain > 12) { + left_global_gain = 12; + } else if (left_global_gain < -12) { + left_global_gain = -12; + } + + log_i("left global_gain "); + put_buf(&left_global_gain, 4); + low_bass_L_global_gain = left_global_gain; + low_bass_eq_filter_info_update_demo(EFF_MUSIC_RL_EQ); +} + +void low_bass_set_right_global_gain(float right_global_gain) +{ + + if (right_global_gain > 12) { + right_global_gain = 12; + } else if (right_global_gain < -12) { + right_global_gain = -12; + } + + log_i("right global_gain "); + put_buf(&right_global_gain, 4); + low_bass_R_global_gain = right_global_gain; + low_bass_eq_filter_info_update_demo(EFF_MUSIC_RL_EQ); +} + +void global_gain_test(void *p) +{ + struct sound_track_2_p_x *hdl = p; + static char g_gain = -12; + printf("g_gain %d\n", g_gain); + low_bass_set_global_gain(g_gain, g_gain); + g_gain++; + if (g_gain > 0) { + g_gain = -12; + } +} + +//left_righ_diff 0:左声道反相 1:右声道反相 2:不反相位 +void pcm_dual_mix_to_dual_and_diff(void *out, void *in, u16 len, u8 left_righ_diff) +{ + s16 *outbuf = out; + s16 *inbuf = in; + s32 tmp32; + len >>= 2; + while (len--) { + tmp32 = data_sat_s16((inbuf[0] + inbuf[1]) / 2); + if (!left_righ_diff) { + *outbuf++ = (tmp32 == -32768) ? 32767 : -tmp32; + *outbuf++ = tmp32; + } else if (left_righ_diff == 1) { + *outbuf++ = tmp32; + *outbuf++ = (tmp32 == -32768) ? 32767 : -tmp32; + } else { + *outbuf++ = tmp32; + *outbuf++ = tmp32; + } + inbuf += 2; + } +} + +int stream_rl_rr_mix_data_handler(struct audio_stream_entry *entry, struct audio_data_frame *in) +{ + if (in->offset == 0) { +#if (TWO_POINT_X_CH == TWO_POINT_ONE_CH) + pcm_dual_mix_to_dual_and_diff(in->data, in->data, in->data_len, 2);//左右叠加除2后, +#endif + } + return in->data_len; +} + + + +#endif/*defined(SOUND_TRACK_2_P_X_CH_CONFIG) && SOUND_TRACK_2_P_X_CH_CONFIG*/ + diff --git a/cpu/br23/audio_effect/audio_sound_track_2_p_x.h b/cpu/br23/audio_effect/audio_sound_track_2_p_x.h new file mode 100644 index 0000000..d6454dd --- /dev/null +++ b/cpu/br23/audio_effect/audio_sound_track_2_p_x.h @@ -0,0 +1,25 @@ +#ifndef _SOUND_TRACK_2_P_X_H_ +#define _SOUND_TRACK_2_P_X_H_ + +#include "app_config.h" +#include "clock_cfg.h" +#include "media/includes.h" +#include "asm/includes.h" +#include "media/eq_config.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" +#include "application/audio_vocal_tract_synthesis.h" +#include "audio_config.h" + +//低通总增益调节 +void low_bass_set_global_gain(float left_global_gain, float right_global_gain); +//高阶低通滤波器系数回调 +int low_bass_eq_get_filter_info_demo(void *_eq, int sr, struct audio_eq_filter_info *info); + +//左右声道叠加后除2,再对左或者右声道做反相处理 +int stream_rl_rr_mix_data_handler(struct audio_stream_entry *entry, struct audio_data_frame *in); +#endif/*_SOUND_TRACK_2_P_X_H_*/ + + + + diff --git a/cpu/br23/audio_effect/audio_surround_demo.c b/cpu/br23/audio_effect/audio_surround_demo.c new file mode 100644 index 0000000..b1af463 --- /dev/null +++ b/cpu/br23/audio_effect/audio_surround_demo.c @@ -0,0 +1,188 @@ +#include "audio_surround_demo.h" +#include "app_config.h" + + + +/*----------------------------------------------------------------------------*/ +/**@brief 环绕音效模块打开例子 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +surround_hdl *surround_open_demo(u32 sur_name, u8 ch_type) +{ + surround_hdl *surround = NULL; +#if AUDIO_SURROUND_CONFIG + surround_open_parm parm = {0}; + u8 nch = EFFECT_CH_L; + if (ch_type == AUDIO_CH_L) { + nch = EFFECT_CH_L; + } else if (ch_type == AUDIO_CH_R) { + nch = EFFECT_CH_R; + } else if (ch_type == AUDIO_CH_LR) { + nch = 2; + } else { + log_e("surround ch_type err 0x%x, nch 0x%x\n", ch_type, nch); + return NULL; + } + + //printf("nch 0x%x, ch_type 0x%x\n", nch,ch_type); + parm.channel = nch; + parm.sur_name = sur_name; + parm.surround_effect_type = EFFECT_3D_PANORAMA;//打开时默认使用3d全景音,使用者,根据需求修改 + surround = audio_surround_open(&parm); + + u8 bypass = RUN_NORMAL; + audio_surround_bypass(sur_name, bypass); + clock_add(DEC_3D_CLK); + + //void test_sur(void *p); + //sys_timer_add(NULL,test_sur, 5000); +#endif + return surround; +} + +void test_sur(void *p) +{ + static u8 tttf = 0; + audio_surround_effect_switch_demo(AEID_MUSIC_SURROUND, tttf); + tttf++; + if (tttf >= KARAOKE_SPK_MAX) { + tttf = 0; + } + +} +/*----------------------------------------------------------------------------*/ +/**@brief 环绕音效关闭例子 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void surround_close_demo(surround_hdl *surround) +{ +#if AUDIO_SURROUND_CONFIG + if (surround) { + audio_surround_close(surround); + surround = NULL; + } + clock_remove(DEC_3D_CLK); +#endif +} + + + + +/*----------------------------------------------------------------------------*/ +/**@brief 环绕音效切换测试例子 + @param surround:句柄 + @param effect_type: + EFFECT_3D_PANORAMA, //3d全景 + EFFECT_3D_ROTATES, //3d环绕 + EFFECT_FLOATING_VOICE, //流动人声 + EFFECT_GLORY_OF_KINGS, //王者荣耀 + EFFECT_FOUR_SENSION_BATTLEFIELD, //四季战场 + EFFECT_OFF,//原声 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_surround_effect_switch(u32 sur_name, u32 effect_type) +{ +#if AUDIO_SURROUND_CONFIG + surround_update_parm parm = {0}; + parm.rotatestep = 2;//旋转速度 + parm.damping = 120;//高频衰减速度 + parm.feedback = 110;//整体衰减速度 + parm.roomsize = 128;//空间大小 + if (EFFECT_OFF == effect_type) { + //中途关测试 + /* u8 en = 0; */ + /* audio_surround_parm_update(surround, effect_type, (surround_update_parm *)en); */ + + //此处关闭音效处理使用surround_type = 0的方式 + u8 en = 1; + audio_surround_parm_update(sur_name, effect_type, (surround_update_parm *)en); + parm.surround_type = 0; + audio_surround_parm_update(sur_name, EFFECT_3D_PANORAMA, &parm); + } else { + //音效切换测试 + u8 en = 1; + audio_surround_parm_update(sur_name, EFFECT_OFF, (surround_update_parm *)en); + if (effect_type == EFFECT_3D_PANORAMA) { + parm.surround_type = EFFECT_3D_TYPE1; + audio_surround_parm_update(sur_name, EFFECT_3D_PANORAMA, &parm); + } else { + audio_surround_parm_update(sur_name, effect_type, NULL); + } + } + +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 环绕音效、虚拟低音切换例子 + @param eff_mode: + KARAOKE_SPK_OST,//原声 + KARAOKE_SPK_DBB,//重低音 + KARAOKE_SPK_SURROUND,//全景环绕 + KARAOKE_SPK_3D,//3d环绕 + KARAOKE_SPK_FLOW_VOICE,//流动人声 + KARAOKE_SPK_KING,//王者荣耀 + KARAOKE_SPK_WAR,//四季战场 + KARAOKE_SPK_MAX, + + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_surround_effect_switch_demo(u32 sur_name, u8 eff_mode) +{ + log_i("SPK eff***************:%d ", eff_mode); +#if AUDIO_SURROUND_CONFIG +#if AUDIO_VBASS_CONFIG + u32 vbass_name = AEID_MUSIC_VBASS; + if (eff_mode != KARAOKE_SPK_DBB) { + audio_vbass_bypass(vbass_name, RUN_BYPASS); + } +#endif + + switch (eff_mode) { + case KARAOKE_SPK_OST://原声 + audio_surround_effect_switch(sur_name, EFFECT_OFF); + log_i("spk_OST\n"); + break; + case KARAOKE_SPK_DBB://重低音 + audio_surround_effect_switch(sur_name, EFFECT_OFF);//这里要用回原声处理的地方不一样 +#if AUDIO_VBASS_CONFIG + audio_vbass_bypass(vbass_name, RUN_NORMAL); +#endif + log_i("spk_DDB\n"); + break; + case KARAOKE_SPK_SURROUND://全景环绕 + audio_surround_effect_switch(sur_name, EFFECT_3D_PANORAMA); + log_i("spk_SURRROUND\n"); + break; + case KARAOKE_SPK_3D://3d旋转 + audio_surround_effect_switch(sur_name, EFFECT_3D_ROTATES); + log_i("spk_3D\n"); + break; + case KARAOKE_SPK_FLOW_VOICE://流动人声 + audio_surround_effect_switch(sur_name, EFFECT_FLOATING_VOICE); + log_i("spk_FLOW\n"); + break; + case KARAOKE_SPK_KING://王者荣耀 + audio_surround_effect_switch(sur_name, EFFECT_GLORY_OF_KINGS); + log_i("spk_KING\n"); + break; + case KARAOKE_SPK_WAR://四季战场 + audio_surround_effect_switch(sur_name, EFFECT_FOUR_SENSION_BATTLEFIELD); + log_i("spk_WAR\n"); + break; + default: + log_i("spk_ERROR\n"); + break; + } +#endif +} diff --git a/cpu/br23/audio_effect/audio_surround_demo.h b/cpu/br23/audio_effect/audio_surround_demo.h new file mode 100644 index 0000000..f4456b6 --- /dev/null +++ b/cpu/br23/audio_effect/audio_surround_demo.h @@ -0,0 +1,15 @@ +#ifndef __AUDIO_SURROUND_DEMO__H +#define __AUDIO_SURROUND_DEMO__H +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" +#include "media/audio_surround.h" +#include "app_config.h" +#include "clock_cfg.h" +#include "audio_dec.h" + +surround_hdl *surround_open_demo(u32 sur_name, u8 ch_type); +void surround_close_demo(surround_hdl *surround); + +void audio_surround_effect_switch_demo(u32 sur_name, u8 eff_mode); + +#endif diff --git a/cpu/br23/audio_effect/audio_vbass_demo.c b/cpu/br23/audio_effect/audio_vbass_demo.c new file mode 100644 index 0000000..80e8349 --- /dev/null +++ b/cpu/br23/audio_effect/audio_vbass_demo.c @@ -0,0 +1,42 @@ +#include "audio_vbass_demo.h" +#include "app_config.h" + +#if AUDIO_VBASS_CONFIG +VirtualBass_TOOL_SET vbass_parm; +vbass_hdl *audio_vbass_open_demo(u32 vbass_name, u32 sample_rate, u8 ch_num) +{ + u8 bypass = vbass_parm.is_bypass; + VirtualBassParam parm = {0}; + parm.ratio = vbass_parm.parm.ratio; + parm.boost = vbass_parm.parm.boost; + parm.fc = vbass_parm.parm.fc; + parm.channel = ch_num; + parm.SampleRate = sample_rate; + //printf("vbass ratio %d, boost %d, fc %d, channel %d, SampleRate %d\n", parm.ratio, parm.boost, parm.fc,parm.channel, parm.SampleRate); + vbass_hdl *vbass = audio_vbass_open(vbass_name, &parm); + audio_vbass_bypass(vbass_name, bypass); + clock_add(DEC_VBASS_CLK); + return vbass; +} + + +void audio_vbass_close_demo(vbass_hdl *vbass) +{ + if (vbass) { + audio_vbass_close(vbass); + vbass = NULL; + } + clock_remove(DEC_VBASS_CLK); +} + + + +void audio_vbass_update_demo(u32 vbass_name, VirtualBassUdateParam *parm, u32 bypass) +{ + audio_vbass_parm_update(vbass_name, parm); + audio_vbass_bypass(vbass_name, bypass); +} + + + +#endif diff --git a/cpu/br23/audio_effect/audio_vbass_demo.h b/cpu/br23/audio_effect/audio_vbass_demo.h new file mode 100644 index 0000000..c7a5ad3 --- /dev/null +++ b/cpu/br23/audio_effect/audio_vbass_demo.h @@ -0,0 +1,18 @@ + +#ifndef _AUDIO_VBASS_DEMO_H +#define _AUDIO_VBASS_DEMO_H + +#include "audio_vbass_demo.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" +#include "app_config.h" +#include "media/audio_vbass.h" +#include "clock_cfg.h" + + +vbass_hdl *audio_vbass_open_demo(u32 vbass_name, u32 sample_rate, u8 ch_num); +void audio_vbass_close_demo(vbass_hdl *vbass); +void audio_vbass_update_demo(u32 vbass_name, VirtualBassUdateParam *parm, u32 bypass); + + +#endif diff --git a/cpu/br23/audio_effect/audio_voice_changer_demo.c b/cpu/br23/audio_effect/audio_voice_changer_demo.c new file mode 100644 index 0000000..f820cc2 --- /dev/null +++ b/cpu/br23/audio_effect/audio_voice_changer_demo.c @@ -0,0 +1,124 @@ +#include "audio_voice_changer_demo.h" +#include "app_config.h" + +#if defined(TCFG_MIC_VOICE_CHANGER_ENABLE) && TCFG_MIC_VOICE_CHANGER_ENABLE +voice_changer_hdl *audio_voice_changer_open_demo(u32 voice_changer_name, u32 sample_rate) +{ + VOICECHANGER_PARM parm = {0}; + u32 bypass = 0; + if (voice_changer_name == AEID_MIC_VOICE_CHANGER) { +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + u8 mode = get_mic_eff_mode(); + memcmp(&parm, &eff_mode[mode].voicechanger_parm.parm, sizeof(voice_changer_hdl)); + bypass = eff_mode[mode].voicechanger_parm.is_bypass; +#endif + } else if (voice_changer_name == AEID_MUSIC_VOICE_CHANGER) { + + } + voice_changer_hdl *hdl = audio_voice_changer_open(&parm, sample_rate, voice_changer_name); + audio_voice_changer_bypass(voice_changer_name, bypass); + return hdl; +} + + +void audio_voice_changer_close_demo(voice_changer_hdl *hdl) +{ + audio_voice_changer_close(hdl); +} + +void audio_voice_changer_update_demo(u32 voice_changer_name, VOICECHANGER_PARM *parm, u32 bypass) +{ + audio_voice_changer_update_parm(voice_changer_name, parm); + audio_voice_changer_bypass(voice_changer_name, bypass); +} + +//变声模式切换 +void audio_voice_changer_mode_switch(u32 voice_changer_name, VOICE_CHANGER_MODE voice_changer_mode) +{ + VOICECHANGER_PARM parm = {0}; + switch (voice_changer_mode) { + case VOICE_CHANGER_NONE://原声 + audio_voice_changer_bypass(voice_changer_name, RUN_BYPASS); + break; + case VOICE_CHANGER_UNCLE://大叔 + audio_voice_changer_bypass(voice_changer_name, RUN_NORMAL); + parm.shiftv = 130; + parm.formant_shift = 100;//无效参数 + parm.effect_v = EFFECT_VOICECHANGE_PITCHSHIFT; + audio_voice_changer_update_parm(voice_changer_name, &parm); + break; + case VOICE_CHANGER_GODDESS://女神 + audio_voice_changer_bypass(voice_changer_name, RUN_NORMAL); + parm.shiftv = 56; + parm.formant_shift = 90; + parm.effect_v = EFFECT_VOICECHANGE_SPECTRUM; + audio_voice_changer_update_parm(voice_changer_name, &parm); + break; + case VOICE_CHANGER_BABY://娃娃音 + audio_voice_changer_bypass(voice_changer_name, RUN_NORMAL); + parm.shiftv = 50; + parm.formant_shift = 100;//无效参数 + parm.effect_v = EFFECT_VOICECHANGE_PITCHSHIFT; + audio_voice_changer_update_parm(voice_changer_name, &parm); + break; + case VOICE_CHANGER_MAGIC://魔音女声 + audio_voice_changer_bypass(voice_changer_name, RUN_NORMAL); + parm.shiftv = 75; + parm.formant_shift = 80; + parm.effect_v = EFFECT_VOICECHANGE_PITCHSHIFT; + audio_voice_changer_update_parm(voice_changer_name, &parm); + break; + case VOICE_CHANGER_MONSTER://怪兽音 + audio_voice_changer_bypass(voice_changer_name, RUN_NORMAL); + parm.shiftv = 160; + parm.formant_shift = 100;//无效参数 + parm.effect_v = EFFECT_VOICECHANGE_PITCHSHIFT; + audio_voice_changer_update_parm(voice_changer_name, &parm); + break; + case VOICE_CHANGER_DONALD_DUCK://唐老鸭 + audio_voice_changer_bypass(voice_changer_name, RUN_NORMAL); + parm.shiftv = 60; + parm.formant_shift = 170; + parm.effect_v = EFFECT_VOICECHANGE_CARTOON; + audio_voice_changer_update_parm(voice_changer_name, &parm); + break; + case VOICE_CHANGER_MINIONS://小黄人 + audio_voice_changer_bypass(voice_changer_name, RUN_NORMAL); + parm.shiftv = 50; + parm.formant_shift = 60; + parm.effect_v = EFFECT_VOICECHANGE_CARTOON; + audio_voice_changer_update_parm(voice_changer_name, &parm); + break; + case VOICE_CHANGER_ROBOT://机器音 + audio_voice_changer_bypass(voice_changer_name, RUN_NORMAL); + parm.shiftv = 70; + parm.formant_shift = 80; + parm.effect_v = EFFECT_VOICECHANGE_ROBORT; + audio_voice_changer_update_parm(voice_changer_name, &parm); + break; + case VOICE_CHANGER_WHISPER://气音 + audio_voice_changer_bypass(voice_changer_name, RUN_NORMAL); + parm.shiftv = 70; + parm.formant_shift = 80; + parm.effect_v = EFFECT_VOICECHANGE_WHISPER; + audio_voice_changer_update_parm(voice_changer_name, &parm); + break; + case VOICE_CHANGER_MELODY://固定旋律音 + audio_voice_changer_bypass(voice_changer_name, RUN_NORMAL); + parm.shiftv = 70; + parm.formant_shift = 80; + parm.effect_v = EFFECT_VOICECHANGE_MELODY; + audio_voice_changer_update_parm(voice_changer_name, &parm); + break; + case VOICE_CHANGER_FEEDBACK://调制音 + audio_voice_changer_bypass(voice_changer_name, RUN_NORMAL); + parm.shiftv = 150; + parm.formant_shift = 80; + parm.effect_v = EFFECT_VOICECHANGE_FEEDBACK; + audio_voice_changer_update_parm(voice_changer_name, &parm); + break; + default: + break; + } +} +#endif diff --git a/cpu/br23/audio_effect/audio_voice_changer_demo.h b/cpu/br23/audio_effect/audio_voice_changer_demo.h new file mode 100644 index 0000000..696f1d1 --- /dev/null +++ b/cpu/br23/audio_effect/audio_voice_changer_demo.h @@ -0,0 +1,37 @@ +#ifndef __VOICE_CHANGER_DEMO_H_ +#define __VOICE_CHANGER_DEMO_H_ + +#include "system/includes.h" +#include "media/includes.h" +#include "media/audio_voice_changer.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" + +//参数调节的趋势:shiftv越小,音高越高, formant_shift越小,音色越明亮 +typedef enum { + VOICE_CHANGER_NONE,//原声 + VOICE_CHANGER_UNCLE,//大叔 + VOICE_CHANGER_GODDESS,//女神 + VOICE_CHANGER_BABY,//娃娃音 + VOICE_CHANGER_MAGIC,//魔音女声 + VOICE_CHANGER_MONSTER,//怪兽音 + VOICE_CHANGER_DONALD_DUCK,//唐老鸭 + VOICE_CHANGER_MINIONS,//小黄人 + VOICE_CHANGER_ROBOT,//机器音 + VOICE_CHANGER_WHISPER,//气音 + VOICE_CHANGER_MELODY,//固定旋律音 + VOICE_CHANGER_FEEDBACK,//调制音 + + VOICE_CHANGER_MAX, + +} VOICE_CHANGER_MODE; + + +voice_changer_hdl *audio_voice_changer_open_demo(u32 voice_changer_name, u32 sample_rate); +void audio_voice_changer_close_demo(voice_changer_hdl *hdl); +void audio_voice_changer_update_demo(u32 voice_changer_name, VOICECHANGER_PARM *parm, u32 bypass); +void audio_voice_changer_mode_switch(u32 voice_changer_name, VOICE_CHANGER_MODE voice_changer_mode); + + + +#endif diff --git a/cpu/br23/audio_effect/effects_adj.c b/cpu/br23/audio_effect/effects_adj.c new file mode 100644 index 0000000..d60d25c --- /dev/null +++ b/cpu/br23/audio_effect/effects_adj.c @@ -0,0 +1,1748 @@ +#include "audio_effect/audio_gain_process_demo.h" +#include "audio_effect/audio_voice_changer_demo.h" +#include "audio_effect/audio_vbass_demo.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" +#include "app_sound_box_tool.h" +#include "app_config.h" +#include "audio_mic/effect_parm.h" + +#define PARM_DEBUG 0 + +#define LOG_TAG "[EFFECT]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +#define LOG_DUMP_ENABLE +#include "debug.h" +#ifdef SUPPORT_MS_EXTENSIONS +//#pragma bss_seg(".audio_mic_stream_bss") +//#pragma data_seg(".audio_mic_stream_data") +#pragma const_seg(".audio_effect_adj_const") +#pragma code_seg(".audio_effect_adj_code") +#endif + +#define EFF_CFG_FILE_NAME SDFILE_RES_ROOT_PATH"eq_cfg_hw.bin" +const u8 eff_sdk_name[16] = "AC695N"; +const u8 eff_eq_ver[4] = {1, 0, 0, 0}; + + +extern const u16 eq_name[5] ; +extern const u16 drc_name[5] ; +static const u16 eff_mode_seq[8] = {mic_mode_seq0, mic_mode_seq1, mic_mode_seq2, mic_mode_seq3, mic_mode_seq4, mic_mode_seq5, mic_mode_seq6, mic_mode_seq7}; //混响模式标号 + +//每个模块id对应一个group_id(功能id) +const struct mode_list mlist[] = { + {AEID_ESCO_DL_EQ, phone_eq_nsection, 2, {EFF_PHONE_WIDEBAND_EQ, EFF_PHONE_NARROWBAND_EQ}}, + {AEID_ESCO_DL_DRC, phone_eq_nsection, 2, {EFF_PHONE_WIDEBAND_DRC, EFF_PHONE_NARROWBAND_DRC}}, + {AEID_ESCO_UL_EQ, phone_eq_nsection, 2, {EFF_AEC_WIDEBAND_EQ, EFF_AEC_NARROWBAND_EQ}}, + {AEID_ESCO_UL_DRC, phone_eq_nsection, 2, {EFF_AEC_WIDEBAND_DRC, EFF_AEC_NARROWBAND_DRC}}, + + {AEID_MUSIC_EQ, music_eq_nsection, 1, {EFF_MUSIC_EQ}}, + {AEID_MUSIC_EQ2, music_eq2_nsection, 1, {EFF_MUSIC_EQ2}}, + {AEID_MUSIC_DRC, music_eq_nsection, 5, {EFF_MUSIC_LOW_DRC, EFF_MUSIC_MID_DRC, EFF_MUSIC_HIGH_DRC, EFF_MUSIC_WHOLE_DRC, EFF_MUSIC_CROSSOVER }}, //最后一个groud_id存方分频器 + {AEID_MUSIC_FR_EQ, music_eq_nsection, 1, {0x2003}}, + {AEID_MUSIC_FR_DRC, music_eq_nsection, 1, {0x2004}}, + {AEID_MUSIC_RL_EQ, music_eq_nsection, 1, {0x2005}}, + {AEID_MUSIC_RL_DRC, music_eq_nsection, 5, {EFF_MUSIC_RL_LOW_DRC, EFF_MUSIC_RL_MID_DRC, EFF_MUSIC_RL_MID_DRC, EFF_MUSIC_RL_HIGH_DRC, EFF_MUSIC_RL_WHOLE_DRC }}, + {AEID_MUSIC_RR_EQ, music_eq_nsection, 1, {0x2007}}, + {AEID_MUSIC_RR_DRC, music_eq_nsection, 1, {0x2008}}, + + {AEID_MIC_EQ0, mic_eq_nsection, 1, {EFF_MIC_EQ0}}, + {AEID_MIC_DRC0, mic_eq_nsection, 1, {EFF_MIC_DRC0}}, + {AEID_MIC_EQ1, mic_eq_nsection, 1, {EFF_MIC_EQ1}}, + {AEID_MIC_DRC1, mic_eq_nsection, 1, {EFF_MIC_DRC1}}, + {AEID_MIC_EQ2, mic_eq_nsection, 1, {EFF_MIC_EQ2}}, + {AEID_MIC_DRC2, mic_eq_nsection, 1, {EFF_MIC_DRC2}}, + {AEID_MIC_EQ3, mic_eq_nsection, 1, {EFF_MIC_EQ3}}, + {AEID_MIC_DRC3, mic_eq_nsection, 1, {EFF_MIC_DRC3}}, + {AEID_MIC_EQ4, mic_eq_nsection, 1, {EFF_MIC_EQ4}}, + {AEID_MIC_DRC4, mic_eq_nsection, 1, {EFF_MIC_DRC4}}, + + {AEID_LINEIN_EQ, music_eq_nsection, 1, {EFF_LINEIN_EQ}}, + {AEID_LINEIN_DRC, music_eq_nsection, 1, {EFF_LINEIN_DRC}}, + {AEID_HIGH_BASS_EQ, music_eq_nsection, 1, {EFF_MUSIC_HIGH_BASS_EQ}}, + {AEID_HIGH_BASS_DRC, music_eq_nsection, 1, {EFF_MUSIC_HIGH_BASS_DRC}}, + {AEID_MUSIC_LPF_EQ, music_eq_nsection, 1, {EFF_MUSIC_LPF_EQ}}, + +}; + +int get_module_name(u16 group_id) +{ + for (int i = 0; i < ARRAY_SIZE(mlist); i++) { + struct mode_list *list = (struct mode_list *)&mlist[i]; + for (int j = 0; j < list->group_num; j++) { + if (list->group_id[j] == group_id) { + return list->module_name; + } + } + } + log_e("get_module_name error\n"); + return 0; +} +int get_module_name_and_index(u16 group_id, u16 *index) +{ + for (int i = 0; i < ARRAY_SIZE(mlist); i++) { + struct mode_list *list = (struct mode_list *)&mlist[i]; + for (int j = 0; j < list->group_num; j++) { + if (list->group_id[j] == group_id) { + *index = j; + return list->module_name; + } + } + } + log_e("get_module_name error\n"); + return 0; +} + +int get_group_id(u16 module_name, u8 tar) +{ + for (int i = 0; i < ARRAY_SIZE(mlist); i++) { + struct mode_list *list = (struct mode_list *)&mlist[i]; + if (list->module_name == module_name) { // + return list->group_id[tar]; + } + } + log_e("get_module_id error\n"); + return 0; +} +struct mode_list *get_group_list(u16 module_name) +{ + for (int i = 0; i < ARRAY_SIZE(mlist); i++) { + struct mode_list *list = (struct mode_list *)&mlist[i]; + if (list->module_name == module_name) { // + return list; + } + } + return NULL; +} +int get_eq_nsection(u16 module_name) +{ + for (int i = 0; i < ARRAY_SIZE(mlist); i++) { + struct mode_list *list = (struct mode_list *)&mlist[i]; + if (list->module_name == module_name) { + return list->nsection; + } + } + log_e("get_eq_nsection error\n"); + return 0; +} + +int get_eq_seg(u16 module_name) +{ + return 0; +} +void get_eff_mode(u16 mode_id, u16 group_id, u8 *mode_index, u8 *drc_index)//获取混响模式的index +{ + *mode_index = mode_id - mic_mode_seq0; + *drc_index = group_id - EFF_MIC_DRC0; +} +int get_phone_mode(u16 group_id) +{ + return group_id - EFF_PHONE_WIDEBAND_EQ; +} + +#define REPLY_TO_TOOL (0) +#define EFF_CFG_FILE_ID (0x3)//音效配置项源文件id + +static u8 eff_mode_save = 0; +#if TCFG_DYNAMIC_EQ_ENABLE +DynamicEQParam_TOOL_SET dynamic_eq; +#endif +struct eff_parm eff_mode[EFFECT_REVERB_PARM_MAX];//混响的8个模式 + +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN +struct music_parm_tool_set linein_mode;//linin模式 + +#endif +struct music_parm_tool_set music_mode;//音乐模式 + +#if TCFG_DYNAMIC_EQ_ENABLE +struct music_eq2_tool music_eq2_parm;//音乐模式下第二eq +#endif + +struct phone_parm_tool_set phone_mode[4];//通话上下行模式 0:下行宽 1:下行窄 2:上行宽 3:上行窄 + +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) +struct music_eq_tool rl_eq_parm;//rl通道eq +struct nband_drc rl_drc_parm;//rl通道drc +#endif +#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) &&SOUND_TRACK_2_P_X_CH_CONFIG +LowPassParam_TOOL_SET low_pass_parm;//rl rr通道低通滤波器 +#endif + +void wdrc_printf(void *_wdrc); +static u16 alive_timer = 0; + +int vbass_prev_gain_process_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if AUDIO_VBASS_CONFIG + u8 mode_id = packet->data[0]; + memcpy(&vbass_prev_gain_parm, &packet->data[1], sizeof(vbass_prev_gain_parm)); + audio_gain_update_parm(AEID_MUSIC_VBASS_PREV_GAIN, &vbass_prev_gain_parm.parm, vbass_prev_gain_parm.is_bypass); +#if PARM_DEBUG + log_debug("vbass_prev_gain_parm.is_bypass %d, gain 0x%x", vbass_prev_gain_parm.is_bypass, *(int *)&vbass_prev_gain_parm.parm.gain); +#endif +#endif + return 0; +} + + +int music_vbass_parm_ananlyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if AUDIO_VBASS_CONFIG + u8 mode_id = packet->data[0]; + memcpy(&vbass_parm, &packet->data[1], sizeof(vbass_parm)); + audio_vbass_update_demo(AEID_MUSIC_VBASS, &vbass_parm.parm, vbass_parm.is_bypass); +#if PARM_DEBUG + log_debug("is_bypass %d, ratio %d, boost %d, fc %d\n", vbass_parm.is_bypass, vbass_parm.parm.ratio, vbass_parm.parm.boost, vbass_parm.parm.fc); +#endif +#endif + return 0; +} + + +int mic_voice_changer_parm_ananlyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE +#if defined(TCFG_MIC_VOICE_CHANGER_ENABLE) && TCFG_MIC_VOICE_CHANGER_ENABLE + u8 mode_id = packet->data[0]; + VoiceChangerParam_TOOL_SET *changer_parm = &eff_mode[mode_id - mic_mode_seq0].voicechanger_parm; + memcpy(changer_parm, &packet->data[1], sizeof(eff_mode[mode_id - mic_mode_seq0].voicechanger_parm)); + audio_voice_changer_update_demo(AEID_MIC_VOICE_CHANGER, &changer_parm->parm, changer_parm->is_bypass); +#if PARM_DEBUG + log_debug("effect_v %d, shiftv %d, formant_shift %d, is_bypass %d\n", changer_parm->parm.effect_v, changer_parm->parm.shiftv, changer_parm->parm.formant_shift, changer_parm->is_bypass); +#endif +#endif +#endif + return 0; +} + +int mic_gain_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if GAIN_PROCESS_EN +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + u8 mode_id = packet->data[0]; + Gain_Process_TOOL_SET *gain_parm = &eff_mode[mode_id - mic_mode_seq0].gain_parm; //增益 + memcpy(gain_parm, &packet->data[1], sizeof(eff_mode[mode_id - mic_mode_seq0].gain_parm)); + audio_gain_update_parm(AEID_MIC_GAIN, &gain_parm->parm, eff_mode[mode_id - mic_mode_seq0].gain_parm.is_bypass); +#if PARM_DEBUG + log_debug("gain_parm.is_bypass %d, gain 0x%x", gain_parm->is_bypass, *(int *)&gain_parm->parm.gain); +#endif +#endif +#endif + return 0; +} + +int gain_process_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if GAIN_PROCESS_EN + u8 mode_id = packet->data[0]; + memcpy(&gain_parm, &packet->data[1], sizeof(gain_parm)); + audio_gain_update_parm(AEID_MUSIC_GAIN, &gain_parm.parm, gain_parm.is_bypass); +#if PARM_DEBUG + log_debug("gain_parm.is_bypass %d, gain 0x%x", gain_parm.is_bypass, *(int *)&gain_parm.parm.gain); +#endif +#endif + return 0; +} +int linein_gain_process_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if GAIN_PROCESS_EN +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN + u8 mode_id = packet->data[0]; + memcpy(&linein_gain_parm, &packet->data[1], sizeof(linein_gain_parm)); + audio_gain_update_parm(AEID_LINEIN_GAIN, &linein_gain_parm.parm, linein_gain_parm.is_bypass); +#if PARM_DEBUG + log_debug("linein_gain_parm.is_bypass %d, gain 0x%x", linein_gain_parm.is_bypass, *(int *)&linein_gain_parm.parm.gain); +#endif +#endif +#endif + return 0; +} + +int rl_gain_process_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if GAIN_PROCESS_EN + u8 mode_id = packet->data[0]; + memcpy(&rl_gain_parm, &packet->data[1], sizeof(rl_gain_parm)); + audio_gain_update_parm(AEID_MUSIC_RL_GAIN, &rl_gain_parm.parm, rl_gain_parm.is_bypass); +#if PARM_DEBUG + log_debug("rl_gain_parm.is_bypass %d, gain 0x%x", rl_gain_parm.is_bypass, *(int *)&rl_gain_parm.parm.gain); +#endif +#endif + return 0; +} + +void dynamic_eq_printf(DynamicEQParam_TOOL_SET *dy_parm) +{ +#if PARM_DEBUG + log_debug("dy_parm->is_bypass %d\n", dy_parm->is_bypass); + for (int i = 0; i < dy_parm->nSection; i++) { + log_debug("fc %d , Q 0x%x, gain:0x%x, type %d, attacktime %d, releaseTime %d, rmsTime %d, threshold 0x%x, ratio 0x%x, noisegate_threshold 0x%x, fixGain %x, algorithm %d\n", + dy_parm->effect_param[i].fc, + *(int *)&dy_parm->effect_param[i].Q, + *(int *)&dy_parm->effect_param[i].gain, + dy_parm->effect_param[i].type, + dy_parm->effect_param[i].attackTime, + dy_parm->effect_param[i].releaseTime, + dy_parm->effect_param[i].rmsTime, + *(int *)&dy_parm->effect_param[i].threshold, + *(int *)&dy_parm->effect_param[i].ratio, + *(int *)&dy_parm->effect_param[i].noisegate_threshold, + *(int *)&dy_parm->effect_param[i].fixGain, + dy_parm->effect_param[i].algorithm); + } + + log_debug("nSection %d, detect_mode %d\n", dy_parm->nSection, dy_parm->detect_mode); +#endif +} + + +int dynamic_eq_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if TCFG_DYNAMIC_EQ_ENABLE + u8 mode_id = packet->data[0]; + memcpy(&dynamic_eq, &packet->data[1], sizeof(dynamic_eq)); + + DynamicEQParam_TOOL_SET *dy_parm = &dynamic_eq;//&packet->data[1]; + DynamicEQEffectParam *parm1 = dy_parm->effect_param; + + DynamicEQParam parm2 = {0}; + parm2.nSection = dy_parm->nSection; + parm2.detect_mode = dy_parm->detect_mode; + + DynamicEQDetectionParam detectParm[2] = {0}; + detectParm[0].fc = dy_parm->effect_param[0].fc; + detectParm[1].fc = dy_parm->effect_param[1].fc; + + dynamic_eq_printf(&dynamic_eq); + audio_dynamic_eq_detection_update_parm(detectParm, dy_parm->is_bypass);//动态eq检测更新 + + audio_dynamic_eq_update_parm((void *)parm1, (void *)&parm2, dy_parm->is_bypass);//动态eq更新 +#endif + return 0; +} + +int phone_eq_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ + u32 eq_name = get_module_name(packet->cmd);//查询到相应模块 + float global_gain = 0; + u8 mode_id = packet->data[0]; + log_debug("mode_id %d\n", mode_id); + struct eq_seg_info *seg = (struct eq_seg_info *)&packet->data[1]; + + if (seg->index == (u16) - 1) { + memcpy(&global_gain, &seg->iir_type, sizeof(float)); + cur_eq_set_global_gain(eq_name, global_gain); + log_info("global_gain 0x%x\n", *(int *)&global_gain); + } + + void *tar_seg = NULL; + u8 tar = packet->cmd - EFF_PHONE_WIDEBAND_EQ; + log_debug("phone_mode tar %d\n", tar); + if (seg->index == (u16) - 1) { + phone_mode[tar].eq_parm.global_gain = global_gain; + } else { + tar_seg = &phone_mode[tar].eq_parm.seg[seg->index]; + } + if (seg->index != (u16) - 1) { +#if PARM_DEBUG + log_info("idx:%d, iir:%d, frq:%d, gain:0x%x, q:0x%x \n", seg->index, seg->iir_type, seg->freq, *(int *)&seg->gain, *(int *)&seg->q); +#endif + memcpy(tar_seg, seg, sizeof(struct eq_seg_info)); + cur_eq_set_update(eq_name, tar_seg, get_eq_nsection(eq_name), 0); + } + + return 0; +} + +int low_pass_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) &&SOUND_TRACK_2_P_X_CH_CONFIG + u8 mode_id = packet->data[0]; + memcpy(&low_pass_parm, &packet->data[1], sizeof(LowPassParam_TOOL_SET)); + cur_eq_set_update(AEID_MUSIC_RL_EQ, NULL, 1, 0); +#if PARM_DEBUG + log_info("low_pass_parm.is_bypass %d\n", low_pass_parm.is_bypass); + struct advance_iir *low_p = &low_pass_parm.low_pass; + log_info("low_p->fc %d, low_p->order %d, low_p->type %d\n", low_p->fc, low_p->order, low_p->type); +#endif +#endif + return 0; +} +int mic_eq_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + u32 eq_name = get_module_name(packet->cmd);//查询到相应模块 + float global_gain = 0; + u8 mode_id = packet->data[0]; + log_debug("mode_id %d\n", mode_id); + struct eq_seg_info *seg = (struct eq_seg_info *)&packet->data[1]; + + if (seg->index == (u16) - 1) { + memcpy(&global_gain, &seg->iir_type, sizeof(float)); + cur_eq_set_global_gain(eq_name, global_gain); + log_info("global_gain 0x%x\n", *(int *)&global_gain); + } + + void *tar_seg = NULL; + u8 tar = packet->cmd - EFF_MIC_EQ0; + log_debug("eff_mode tar %d\n", tar); + if (seg->index == (u16) - 1) { + eff_mode[mode_id - mic_mode_seq0].eq_parm[tar].global_gain = global_gain; + } else { + tar_seg = &eff_mode[mode_id - mic_mode_seq0].eq_parm[tar].seg[seg->index]; + } + if (seg->index != (u16) - 1) { +#if PARM_DEBUG + log_info("idx:%d, iir:%d, frq:%d, gain:0x%x, q:0x%x \n", seg->index, seg->iir_type, seg->freq, *(int *)&seg->gain, *(int *)&seg->q); +#endif + memcpy(tar_seg, seg, sizeof(struct eq_seg_info)); + cur_eq_set_update(eq_name, tar_seg, get_eq_nsection(eq_name), 1); + } +#endif + + return 0; +} + +int music_eq_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ + u32 eq_name = get_module_name(packet->cmd);//查询到相应模块 + float global_gain = 0; + u8 mode_id = packet->data[0]; + log_debug("mode_id %d\n", mode_id); + struct eq_seg_info *seg = (struct eq_seg_info *)&packet->data[1]; + + if (seg->index == (u16) - 1) { + memcpy(&global_gain, &seg->iir_type, sizeof(float)); + cur_eq_set_global_gain(eq_name, global_gain); + log_info("global_gain 0x%x\n", *(int *)&global_gain); + } + + void *tar_seg = NULL; + if (packet->cmd == EFF_MUSIC_EQ) { + if (seg->index == (u16) - 1) { + music_mode.eq_parm.global_gain = global_gain; + } else { + tar_seg = &music_mode.eq_parm.seg[seg->index]; + } + } else if (packet->cmd == EFF_MUSIC_EQ2) { +#if TCFG_DYNAMIC_EQ_ENABLE + if (seg->index == (u16) - 1) { + music_eq2_parm.global_gain = global_gain; + } else { + tar_seg = &music_eq2_parm.seg[seg->index]; + } +#endif + } else if (packet->cmd == EFF_MUSIC_HIGH_BASS_EQ) { + if (seg->index == (u16) - 1) { + high_bass_eq_parm.global_gain = global_gain; + } else { + tar_seg = &high_bass_eq_parm.seg[seg->index]; + } + } + if (seg->index != (u16) - 1) { +#if PARM_DEBUG + log_info("idx:%d, iir:%d, frq:%d, gain:0x%x, q:0x%x \n", seg->index, seg->iir_type, seg->freq, *(int *)&seg->gain, *(int *)&seg->q); +#endif + memcpy(tar_seg, seg, sizeof(struct eq_seg_info)); + cur_eq_set_update(eq_name, tar_seg, get_eq_nsection(eq_name), 0); + } + + return 0; +} + +int linein_eq_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN + u32 eq_name = get_module_name(packet->cmd);//查询到相应模块 + float global_gain = 0; + u8 mode_id = packet->data[0]; + log_debug("mode_id %d\n", mode_id); + struct eq_seg_info *seg = (struct eq_seg_info *)&packet->data[1]; + + if (seg->index == (u16) - 1) { + memcpy(&global_gain, &seg->iir_type, sizeof(float)); + cur_eq_set_global_gain(eq_name, global_gain); + log_info("global_gain 0x%x\n", *(int *)&global_gain); + } + + void *tar_seg = NULL; + if (packet->cmd == EFF_LINEIN_EQ) { + if (seg->index == (u16) - 1) { + linein_mode.eq_parm.global_gain = global_gain; + } else { + tar_seg = &linein_mode.eq_parm.seg[seg->index]; + } + } + if (seg->index != (u16) - 1) { +#if PARM_DEBUG + log_info("idx:%d, iir:%d, frq:%d, gain:0x%x, q:0x%x \n", seg->index, seg->iir_type, seg->freq, *(int *)&seg->gain, *(int *)&seg->q); +#endif + memcpy(tar_seg, seg, sizeof(struct eq_seg_info)); + cur_eq_set_update(eq_name, tar_seg, get_eq_nsection(eq_name), 0); + } +#endif + + return 0; +} +int linein_wdrc_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN + u16 type = 0; //0:low 1:mid 2:high ,3:other band, 4:crossover + u32 drc_name = get_module_name_and_index(packet->cmd, &type); + wdrc_struct_TOOL_SET *wdrc_parm = (wdrc_struct_TOOL_SET *)&packet->data[1]; + void *tar_wdrc = NULL; + + log_debug("wdrc_parm type %d\n", type); + struct mode_list *list = get_group_list(drc_name); + if ((list->group_num > 1) && (type == (list->group_num - 1))) { ////最后一个存分频器系数 + CrossOverParam_TOOL_SET *parm = (CrossOverParam_TOOL_SET *)&packet->data[1]; + tar_wdrc = &linein_mode.drc_parm.crossover; + memcpy(tar_wdrc, parm, sizeof(CrossOverParam_TOOL_SET)); + cur_crossover_set_update(drc_name, tar_wdrc); + log_debug("way_num %d, N %d, low_freq %d, high_freq %d\n", parm->way_num, parm->N, parm->low_freq, parm->high_freq); + return 0; + } else { + tar_wdrc = &linein_mode.drc_parm.wdrc_parm[type]; + } + + memcpy(tar_wdrc, wdrc_parm, sizeof(wdrc_struct_TOOL_SET)); + + wdrc_printf(tar_wdrc); + cur_drc_set_update(drc_name, type, tar_wdrc); + cur_drc_set_bypass(drc_name, type, wdrc_parm->is_bypass); +#endif + + return 0; +} + + +int mic_wdrc_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + u16 type = 0; //0:low 1:mid 2:high ,3:other band, 4:crossover + u32 drc_name = get_module_name_and_index(packet->cmd, &type); + type = 0;//混响没有多带drc + wdrc_struct_TOOL_SET *wdrc_parm = (wdrc_struct_TOOL_SET *)&packet->data[1]; + void *tar_wdrc = NULL; + + log_debug("wdrc_parm type %d\n", type); + u8 mode_id = packet->data[0]; + u8 tar = packet->cmd - EFF_MIC_DRC0; + tar_wdrc = &eff_mode[mode_id - mic_mode_seq0].drc_parm[tar]; + memcpy(tar_wdrc, wdrc_parm, sizeof(wdrc_struct_TOOL_SET)); + + wdrc_printf(tar_wdrc); + cur_drc_set_update(drc_name, type, tar_wdrc); + cur_drc_set_bypass(drc_name, type, wdrc_parm->is_bypass); +#endif + + return 0; +} +int high_bass_wdrc_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ + u16 type = 0; //0:low 1:mid 2:high ,3:other band, 4:crossover + u32 drc_name = get_module_name_and_index(packet->cmd, &type); + type = 0;//混响没有多带drc + wdrc_struct_TOOL_SET *wdrc_parm = (wdrc_struct_TOOL_SET *)&packet->data[1]; + void *tar_wdrc = NULL; + + log_debug("wdrc_parm type %d\n", type); + u8 mode_id = packet->data[0]; + u8 tar = packet->cmd - EFF_MIC_DRC0; + tar_wdrc = &eff_mode[mode_id - mic_mode_seq0].drc_parm[tar]; + memcpy(tar_wdrc, wdrc_parm, sizeof(wdrc_struct_TOOL_SET)); + + wdrc_printf(tar_wdrc); + cur_drc_set_update(drc_name, type, tar_wdrc); + cur_drc_set_bypass(drc_name, type, wdrc_parm->is_bypass); + + return 0; +} + +int music_wdrc_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ + u16 type = 0; //0:low 1:mid 2:high ,3:other band, 4:crossover + u32 drc_name = get_module_name_and_index(packet->cmd, &type); + wdrc_struct_TOOL_SET *wdrc_parm = (wdrc_struct_TOOL_SET *)&packet->data[1]; + void *tar_wdrc = NULL; + + log_debug("wdrc_parm type %d\n", type); + struct mode_list *list = get_group_list(drc_name); + if (type == (list->group_num - 1)) { ////最后一个存分频器系数 + CrossOverParam_TOOL_SET *parm = (CrossOverParam_TOOL_SET *)&packet->data[1]; + tar_wdrc = &music_mode.drc_parm.crossover; + memcpy(tar_wdrc, parm, sizeof(CrossOverParam_TOOL_SET)); + cur_crossover_set_update(drc_name, tar_wdrc); + log_debug("way_num %d, N %d, low_freq %d, high_freq %d\n", parm->way_num, parm->N, parm->low_freq, parm->high_freq); + return 0; + } else { + tar_wdrc = &music_mode.drc_parm.wdrc_parm[type]; + } + + memcpy(tar_wdrc, wdrc_parm, sizeof(wdrc_struct_TOOL_SET)); + + wdrc_printf(tar_wdrc); + cur_drc_set_update(drc_name, type, tar_wdrc); + cur_drc_set_bypass(drc_name, type, wdrc_parm->is_bypass); + + return 0; +} + + +int music_rl_wdrc_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) + u16 type = 0; //0:low 1:mid 2:high ,3:other band, 4:crossover + u32 drc_name = get_module_name_and_index(packet->cmd, &type); + wdrc_struct_TOOL_SET *wdrc_parm = (wdrc_struct_TOOL_SET *)&packet->data[1]; + void *tar_wdrc = NULL; + + log_debug("wdrc_parm type %d\n", type); + struct mode_list *list = get_group_list(drc_name); + if (type == (list->group_num - 1)) { ////最后一个存分频器系数 + CrossOverParam_TOOL_SET *parm = (CrossOverParam_TOOL_SET *)&packet->data[1]; + tar_wdrc = &rl_drc_parm.crossover; + memcpy(tar_wdrc, parm, sizeof(CrossOverParam_TOOL_SET)); + cur_crossover_set_update(drc_name, tar_wdrc); + log_debug("way_num %d, N %d, low_freq %d, high_freq %d\n", parm->way_num, parm->N, parm->low_freq, parm->high_freq); + return 0; + } else { + tar_wdrc = &rl_drc_parm.wdrc_parm[type]; + } + + memcpy(tar_wdrc, wdrc_parm, sizeof(wdrc_struct_TOOL_SET)); + + wdrc_printf(tar_wdrc); + cur_drc_set_update(drc_name, type, tar_wdrc); + cur_drc_set_bypass(drc_name, type, wdrc_parm->is_bypass); +#endif + return 0; +} + + +int phone_wdrc_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ + u16 type = 0; //0:low 1:mid 2:high ,3:other band, 4:crossover + u32 drc_name = get_module_name_and_index(packet->cmd, &type); + wdrc_struct_TOOL_SET *wdrc_parm = (wdrc_struct_TOOL_SET *)&packet->data[1]; + type = 0;//通话下行使用type位置做更新 + void *tar_wdrc = NULL; + log_debug("wdrc_parm type %d\n", type); + u8 tar = packet->cmd - EFF_PHONE_WIDEBAND_DRC; + tar_wdrc = &phone_mode[tar].drc_parm; + memcpy(tar_wdrc, wdrc_parm, sizeof(wdrc_struct_TOOL_SET)); + wdrc_printf(tar_wdrc); + cur_drc_set_update(drc_name, type, tar_wdrc); + cur_drc_set_bypass(drc_name, type, wdrc_parm->is_bypass); + + return 0; +} + + +int noise_gate_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + u8 mode_id = packet->data[0]; + memcpy(&eff_mode[mode_id - mic_mode_seq0].noise_gate_parm, &packet->data[1], sizeof(NoiseGateParam_TOOL_SET)); + NoiseGateParam_TOOL_SET *parmt = &eff_mode[mode_id - mic_mode_seq0].noise_gate_parm; + noisegate_update_parm(&parmt->parm, parmt->is_bypass); + +#if PARM_DEBUG + noisegate_update_param *parm = &parmt->parm; + log_debug("noise gate attact_time %d,releasetime %d, threshold %d, low_th_gain %d\n", + parm->attackTime, parm->releaseTime, parm->threshold, parm->low_th_gain); +#endif +#endif + return 0; +} + +int howling_pitch_shift_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + u8 mode_id = packet->data[0]; + memcpy(&eff_mode[mode_id - mic_mode_seq0].howlingps_parm, &packet->data[1], sizeof(HowlingPs_PARM_TOOL_SET)); + HowlingPs_PARM_TOOL_SET *parmt = &eff_mode[mode_id - mic_mode_seq0].howlingps_parm; + howling_pitch_shift_update_parm(&parmt->parm, parmt->is_bypass); +#if PARM_DEBUG + HOWLING_PITCHSHIFT_PARM *parm = &parmt->parm; + log_debug("ps_parm %d, fe_parm %d, effect_v %d\n", parm->ps_parm, parm->fe_parm, parm->effect_v); +#endif +#endif + return 0; +} + +int notchhowline_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + u8 mode_id = packet->data[0]; + memcpy(&eff_mode[mode_id - mic_mode_seq0].notchhowling_parm, &packet->data[1], sizeof(NotchHowlingParam_TOOL_SET)); + NotchHowlingParam_TOOL_SET *parmt = &eff_mode[mode_id - mic_mode_seq0].notchhowling_parm; + notchhowline_update_parm(&parmt->parm, parmt->is_bypass); + +#if PARM_DEBUG + NotchHowlingParam *parm = &parmt->parm; + log_debug("parmt->is_bypass %d\n", parmt->is_bypass); + log_debug("Q 0x%x, gain 0x%x, fade_n %d\n", *(int *)&parm->Q, *(int *)&parm->gain, parm->fade_n); +#endif +#endif + return 0; +} + + +int reverb_parm_analyze(EFF_ONLINE_PACKET *packet) +{ +#if 0 + u8 mode_id = packet->data[0]; + memcpy(&eff_mode[mode_id - mic_mode_seq0].reverb_parm, &packet->data[1], sizeof(REVERBN_PARM_TOOL_SET)); + REVERBN_PARM_TOOL_SET *parmt = &eff_mode[mode_id - mic_mode_seq0].reverb_parm; + reverb_update_parm(&parmt->parm); + REVERBN_PARM_SET *parm = &parmt->parm; + log_debug("dry %d,\n wet %d,\n delay %d,\n rot60 %d,\n Erwet %d,\nErfactor %d,\n Ewidth %d,\n Ertolate %d,\nErbasslpf %d,\nErbassB %d,\n predelay %d,\nallpassfeedback %d,\ndiffusion %d,\n dampinglpf %d,\n basslpf %d,\n bassB %d,\n lowcut %d\n", + parm->dry, + parm->wet, + parm->delay, + parm->rot60, + parm->Erwet, + parm->Erfactor, + parm->Ewidth, + parm->Ertolate, + parm->Erbasslpf, + parm->ErbassB, + parm->predelay, + parm->allpassfeedback, + parm->diffusion, + parm->dampinglpf, + parm->basslpf, + parm->bassB, + parm->lowcut + ); +#endif + return 0; +} + +int plate_reverb_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + u8 mode_id = packet->data[0]; + memcpy(&eff_mode[mode_id - mic_mode_seq0].plate_reverb_parm, &packet->data[1], sizeof(Plate_reverb_TOOL_SET)); + Plate_reverb_TOOL_SET *parmt = &eff_mode[mode_id - mic_mode_seq0].plate_reverb_parm; + plate_reverb_update_parm(&parmt->parm, parmt->is_bypass); + +#if PARM_DEBUG + Plate_reverb_parm *parm = &parmt->parm; + log_debug("wet %d\n dry %d\n pre_delay %d\n highcutoff %d\n diffusion %d\n decayfactor %d\n highfrequencydamping %d\n modulate %d\n roomsize %d\n", parm->wet, parm->dry, parm->pre_delay, parm->highcutoff, parm->diffusion, parm->decayfactor, parm->highfrequencydamping, parm->modulate, parm->roomsize); +#endif +#endif + return 0; +} + + +int echo_parm_analyze(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + u8 mode_id = packet->data[0]; + memcpy(&eff_mode[mode_id - mic_mode_seq0].echo_parm, &packet->data[1], sizeof(EF_ECHO_TOOL_SET)); + EF_ECHO_TOOL_SET *parmt = &eff_mode[mode_id - mic_mode_seq0].echo_parm; + echo_updata_parm(&parmt->parm, parmt->is_bypass); +#if PARM_DEBUG + ECHO_PARM_SET *parm = &parmt->parm; + log_debug("delay %d, decayval %d, filt_enable %d, lpf_cutoff %d, wetgain %d, drygain %d\n", + parm->delay, parm->decayval, parm->filt_enable, parm->lpf_cutoff, parm->wetgain, parm->drygain); +#endif +#endif + return 0; +} + + + +void eff_send_packet(void *priv, u32 id, u8 *packet, int size, u8 sq) +{ + all_assemble_package_send_to_pc(id, sq, packet, size); +} + +void alive_timer_send_packet(void *p) +{ + u32 T = 2; + u8 sq = 0; + eff_send_packet(NULL, T, (u8 *)"empty", 5, sq); +} + + +int eff_tool_get_cfg_file_size(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ + struct file_s { + int id; + int fileid; + }; + struct file_s fs; + memcpy(&fs, packet, sizeof(struct file_s)); + u32 file_size = 0; + if (fs.fileid == EFF_CFG_FILE_ID) { + FILE *file = NULL; + file = fopen(EFF_CFG_FILE_NAME, "r"); + if (!file) { + log_error("EFF_CFG_FILE_NAME err %s\n", EFF_CFG_FILE_NAME); + } else { + file_size = flen(file); + fclose(file); + } + eff_send_packet(NULL, REPLY_TO_TOOL, (u8 *)&file_size, sizeof(u32), sq); + } + return 1; +} +int eff_tool_get_cfg_file_data(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ + struct file_s { + int id; + int fileid; + int offset; + int size; + }; + struct file_s fs; + memcpy(&fs, packet, sizeof(struct file_s)); + if (fs.fileid == (int)EFF_CFG_FILE_ID) { + FILE *file = NULL; + file = fopen(EFF_CFG_FILE_NAME, "r"); + if (!file) { + return -EINVAL; + } + + fseek(file, fs.offset, SEEK_SET); + u8 *data = malloc(fs.size); + if (!data) { + fclose(file); + return -EINVAL; + } + int ret = fread(file, data, fs.size); + if (ret != fs.size) { + } + fclose(file); + eff_send_packet(NULL, REPLY_TO_TOOL, (u8 *)data, fs.size, sq); + free(data); + } + return 1; +} + + +static s32 eff_online_update(void *_packet) +{ + u8 *ptr = _packet; + u8 id = ptr[0]; + u8 sq = ptr[1]; + int res = -1; + EFF_ONLINE_PACKET *packet = (EFF_ONLINE_PACKET *)&ptr[2]; + struct cmd_interface *p = NULL; +#if PARM_DEBUG + if (packet->cmd != 0x4) {//离线查询 + log_debug(" id 0x%x, sq %d\n", id, sq); + log_debug("_cmd:0x%x mode_id %d\n", packet->cmd, packet->data[0]); + } +#endif + if (!alive_timer) { + alive_timer = sys_timer_add(NULL, alive_timer_send_packet, 900);//定时往上位机推送,可能对工具离线的消息有帮助 + } + list_for_each_cmd_interface(p) { + if (p->cmd == packet->cmd) { + if (p->cmd_deal) { + res = p->cmd_deal(packet, REPLY_TO_TOOL, sq); + } + } + } + return res; +} + +int eff_tool_get_version(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ + struct _ver_info { + char sdkname[16]; + u8 eqver[4]; + }; + struct _ver_info _ver_info = {0}; + memcpy(_ver_info.sdkname, eff_sdk_name, sizeof(eff_sdk_name)); + memcpy(_ver_info.eqver, eff_eq_ver, sizeof(eff_eq_ver)); + eff_send_packet(NULL, REPLY_TO_TOOL, (u8 *)&_ver_info, sizeof(struct _ver_info), sq); + return 1; +} +int eff_tool_set_channge_mode(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + struct cmd { + int id; + int modeId; + }; + struct cmd cmd; + memcpy(&cmd, packet, sizeof(struct cmd)); + log_debug("cmd.modeId %d\n", cmd.modeId); + if ((cmd.modeId >= mic_mode_seq0) && (cmd.modeId <= mic_mode_seq7)) { //混响0~7 + set_mic_reverb_mode_by_id(cmd.modeId - mic_mode_seq0); + } +#endif + eff_send_packet(NULL, REPLY_TO_TOOL, (u8 *)"OK", 2, sq); + return 1; +} +//在线检测应答 +int eff_tool_set_inquire(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ + //eff_send_packet(NULL, id, (u8 *)"OK", 2, sq);//OK表示需要重传,NO表示不需要重传,ER还是表示未知命令 + eff_send_packet(NULL, id, (u8 *)"NO", 2, sq);//OK表示需要重传,NO表示不需要重传,ER还是表示未知命令 + return 1; +} + +int eff_tool_resync_parm_begin(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + eff_mode_save = get_mic_eff_mode(); +#endif + eff_send_packet(NULL, REPLY_TO_TOOL, (u8 *)"OK", 2, sq); + return 1; +} + +int eff_tool_resync_parm_end(EFF_ONLINE_PACKET *packet, u8 id, u8 sq) +{ +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + u8 eff_mode = eff_mode_save; + set_mic_reverb_mode_by_id(eff_mode);//还原混响的模式 +#endif + eff_send_packet(NULL, REPLY_TO_TOOL, (u8 *)"OK", 2, sq); + return 1; +} + + +static void effect_tool_callback(u8 *_packet, u32 size) +{ + int res = 0; + u8 *ptr = _packet; + u8 id = ptr[0]; + u8 sq = ptr[1]; + u8 *packet = (u8 *)&ptr[2]; + ASSERT(((int)packet & 0x3) == 0, "buf %x size %d\n", (unsigned int)packet, size - 2); + + res = eff_online_update(ptr); + if (!res) { + log_debug("Ack"); + eff_send_packet(NULL, REPLY_TO_TOOL, (u8 *)"OK", 2, sq); + } else if (res != 1) { + log_debug("Nack"); + eff_send_packet(NULL, REPLY_TO_TOOL, (u8 *)"ER", 2, sq); + } +} + +REGISTER_DETECT_TARGET(eff_adj_target) = { + .id = 0x11,//EFF_CONFIG_ID, + .tool_message_deal = effect_tool_callback, +}; + +//在线调试不进power down +static u8 effect_tool_idle_query(void) +{ +#if TCFG_EFFECT_TOOL_ENABLE + return 1; +#endif + return 0; +} + +REGISTER_LP_TARGET(effect_adj_lp_target) = { + .name = "effect_adj", + .is_idle = effect_tool_idle_query, +}; + +#define INDEX_HEAD 0xFFFD +int eff_file_exist() +{ + FILE *file = fopen((const char *)EFF_CFG_FILE_NAME, "r"); + if (file) { + fclose(file); + return 1; + } + return 0; +} + +int eff_file_analyze(u32 mode_id, u16 group_id, void *data_buf, u32 buf_len) +{ +#if PARM_DEBUG + log_debug("mode_id 0x%x, group_id 0x%x\n", mode_id, group_id); +#endif + int ret = 0; + u8 *crc_buf = NULL; + FILE *file = NULL; + file = fopen((const char *)EFF_CFG_FILE_NAME, "r"); + if (!file) { + log_error("eff file open err\n"); + return -ENOENT; + } + u8 FV = 0; + if (1 != fread(file, &FV, 1)) { + ret = -1; + + goto err_exit; + } + + u8 ver[4] = {0}; + if (4 != fread(file, ver, 4)) { + ret = -2; + goto err_exit; + } + + if (memcmp(ver, eff_eq_ver, sizeof(eff_eq_ver))) { + log_error("eff ver err \n"); + log_error_hexdump((unsigned char *)ver, 4); + fseek(file, 0, SEEK_SET); + ret = -3; + goto err_exit; + } + + u16 index_head = 0;//索引头 + if (2 != fread(file, &index_head, 2)) { + ret = -4; + goto err_exit; + } + + if (index_head != INDEX_HEAD) { + ret = -5; + goto err_exit; + } + u16 index_len = 0;//索引区域长度 + if (2 != fread(file, &index_len, 2)) { + ret = -6; + goto err_exit; + } + u8 mode_num = 0;//模式个数 + if (1 != fread(file, &mode_num, 1)) { + ret = -7; + goto err_exit; + } + + u16 off0 = 0; //组索引区域的偏移 + u16 off1 = 0; //模式索引区域的偏移 + for (int mode_cnt = 0; mode_cnt < mode_num; mode_cnt++) { + u16 mode_seq = 0;//模式标识 + if (2 != fread(file, &mode_seq, 2)) { + ret = -8; + goto err_exit; + } + if (2 != fread(file, &off0, 2)) { + ret = -9; + goto err_exit; + } + if (2 != fread(file, &off1, 2)) { + ret = -10; + goto err_exit; + } + if (mode_seq != mode_id) { //查询到相应的模式 + continue; + } else { + break; + } + } + fseek(file, off0, SEEK_SET);//偏移到组索引区域 + + u8 group_num = 0; + if (1 != fread(file, &group_num, 1)) { + ret = -11; + goto err_exit; + } + u16 g_id = 0;//模块id + u16 group_id_addr = 0;//模块id的内容地址 + int group_cnt = 0; + for (group_cnt = 0; group_cnt < group_num; group_cnt++) { + if (2 != fread(file, &g_id, 2)) { + ret = -12; + goto err_exit; + } + if (2 != fread(file, &group_id_addr, 2)) { + ret = -13; + goto err_exit; + } + if (g_id != group_id) { + continue; + } else { + break; + } + } + if (group_cnt == group_num) { + ret = -14; +#if PARM_DEBUG + log_error("seek group id addr err\n"); +#endif + goto err_exit; + } + fseek(file, group_id_addr, SEEK_SET);//偏移到模式id的具体内容 + + u16 crc16 = 0; + u16 verify_group_id = 0; + u16 group_len; + if (2 != fread(file, &crc16, 2)) { + ret = -15; + goto err_exit; + } + int cur_addr = fpos(file); + if (2 != fread(file, &verify_group_id, 2)) { + ret = -16; + goto err_exit; + } + if (2 != fread(file, &group_len, 2)) { + ret = -17; + goto err_exit; + } + if (!group_len) { + ret = -18; + goto err_exit; + } + if (verify_group_id != group_id) { + ret = -19; + log_error("verify_group_id %x != group_id %x\n", verify_group_id, group_id); + log_error("verify groud id err\n"); + goto err_exit; + } + + fseek(file, cur_addr, SEEK_SET); + u16 size = sizeof(crc16) + sizeof(group_len); + crc_buf = zalloc(group_len + size); + u8 *group_buf = &crc_buf[size]; + if ((group_len + size) != fread(file, crc_buf, group_len + size)) { + ret = -20; + goto err_exit; + } + u16 calc_crc = CRC16(crc_buf, group_len + size); //id + len +playload + if (crc16 != calc_crc) { + ret = -21; + log_error("crc16 %x, calc_crc %x\n", crc16, calc_crc); + goto err_exit; + } + if (!data_buf) { + ret = -22; +#if PARM_DEBUG + log_error("input data buf NULL\n"); +#endif + goto err_exit; + } + if (group_len <= buf_len) { + memcpy(data_buf, group_buf, group_len); + } else { + ret = -23; + log_error("input data buf len : %d < group_len:%d\n", buf_len, group_len); + goto err_exit; + } + +err_exit: + if (crc_buf) { + free(crc_buf); + crc_buf = NULL; + } + fclose(file); + +#if PARM_DEBUG + if (ret) { + log_error("ret :%d, analyze eff file err, please check it\n", ret); + } +#endif + return 0; +} + +void phone_eff_analyze_data(void) +{ + u16 phone_eq_name[] = {AEID_ESCO_DL_EQ}; + u16 aec_eq_name[] = {AEID_ESCO_UL_EQ}; + u8 index = 0; + void *tar_buf = NULL; + u16 tar_len = 0; + u16 group_id = 0; + u16 mode_seq = 0; + + mode_seq = phone_mode_seq; + for (int i = 0; i < ARRAY_SIZE(phone_eq_name); i++) { + struct mode_list *list = get_group_list(phone_eq_name[i]); + for (int j = 0; j < list->group_num; j++) { + group_id = get_group_id(phone_eq_name[i], j); + index = group_id - EFF_PHONE_WIDEBAND_EQ; + tar_buf = &phone_mode[index].eq_parm; + tar_len = sizeof(phone_mode[index].eq_parm); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); + } + } + mode_seq = aec_mode_seq; + for (int i = 0; i < ARRAY_SIZE(aec_eq_name); i++) { + struct mode_list *list = get_group_list(aec_eq_name[i]); + for (int j = 0; j < list->group_num; j++) { + group_id = get_group_id(aec_eq_name[i], j); + index = group_id - EFF_PHONE_WIDEBAND_EQ; + tar_buf = &phone_mode[index].eq_parm; + tar_len = sizeof(phone_mode[index].eq_parm); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); + } + } + + u16 phone_drc_name[] = {AEID_ESCO_DL_DRC}; + u16 aec_drc_name[] = {AEID_ESCO_UL_DRC}; + mode_seq = phone_mode_seq; + for (int i = 0; i < ARRAY_SIZE(phone_drc_name); i++) { + struct mode_list *list = get_group_list(phone_drc_name[i]); + for (int j = 0; j < list->group_num; j++) { + group_id = get_group_id(phone_drc_name[i], j); + index = group_id - EFF_PHONE_WIDEBAND_DRC; + tar_buf = &phone_mode[index].drc_parm; + tar_len = sizeof(phone_mode[index].drc_parm); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); + wdrc_printf(tar_buf); + } + } + + mode_seq = aec_mode_seq; + for (int i = 0; i < ARRAY_SIZE(aec_drc_name); i++) { + struct mode_list *list = get_group_list(aec_drc_name[i]); + for (int j = 0; j < list->group_num; j++) { + group_id = get_group_id(aec_drc_name[i], j); + index = group_id - EFF_PHONE_WIDEBAND_DRC; + tar_buf = &phone_mode[index].drc_parm; + tar_len = sizeof(phone_mode[index].drc_parm); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); + wdrc_printf(tar_buf); + } + } +} + +void music_eq_printf(void *_parm) +{ +#if PARM_DEBUG + puts("----------------------- music eq ----------------------\n"); + struct music_eq_tool *parm = _parm; + log_debug("global_gain:0x%x\n", *(int *)&parm->global_gain); + log_debug("seg_num:%d\n", parm->seg_num); + struct eq_seg_info *seg; + for (int i = 0; i < parm->seg_num; i++) { + seg = &parm->seg[i]; + log_debug("idx:%d, iir:%d, frq:%d, gain:0x%x, q:0x%x \n", seg->index, seg->iir_type, seg->freq, *(int *)&seg->gain, *(int *)&seg->q); + } +#endif +} +void music_eq2_printf(void *_parm) +{ +#if PARM_DEBUG + puts("----------------------- music eq2 ----------------------\n"); + struct music_eq2_tool *parm = _parm; + log_debug("global_gain:0x%x\n", *(int *)&parm->global_gain); + log_debug("seg_num:%d\n", parm->seg_num); + struct eq_seg_info *seg; + for (int i = 0; i < parm->seg_num; i++) { + seg = &parm->seg[i]; + log_debug("idx:%d, iir:%d, frq:%d, gain:0x%x, q:0x%x \n", seg->index, seg->iir_type, seg->freq, *(int *)&seg->gain, *(int *)&seg->q); + } +#endif +} + +void music_eff_analyze_data(void) +{ + u8 index = 0; + void *tar_buf = NULL; + u16 tar_len = 0; + u16 group_id = 0; + u16 mode_seq = music_mode_seq0; + + +#if AUDIO_VBASS_CONFIG + tar_buf = &vbass_prev_gain_parm; + tar_len = sizeof(vbass_prev_gain_parm); + eff_file_analyze(mode_seq, EFF_MUSIC_VBASS_PREV_GAIN, tar_buf, tar_len); + + tar_buf = &vbass_parm; + tar_len = sizeof(vbass_parm); + eff_file_analyze(mode_seq, EFF_MUSIC_VBASS, tar_buf, tar_len); +#endif + +#if defined(TCFG_EQ_ENABLE) && TCFG_EQ_ENABLE +//eq + group_id = get_group_id(AEID_MUSIC_EQ, 0); + tar_buf = &music_mode.eq_parm; + tar_len = sizeof(music_mode.eq_parm); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); + music_eq_printf(tar_buf); +#endif +//drc + struct mode_list *list = get_group_list(AEID_MUSIC_DRC); + if (list) { + for (int i = 0; i < list->group_num; i++) { + group_id = list->group_id[i]; + if (i == (list->group_num - 1)) { //最后一个存分频器系数 + tar_buf = &music_mode.drc_parm.crossover; + tar_len = sizeof(music_mode.drc_parm.crossover); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); +#if PARM_DEBUG + CrossOverParam_TOOL_SET *parm = tar_buf; + log_debug("way_num %d, N %d, low_freq %d, high_freq %d\n", parm->way_num, parm->N, parm->low_freq, parm->high_freq); +#endif + } else { + tar_buf = &music_mode.drc_parm.wdrc_parm[i]; + tar_len = sizeof(music_mode.drc_parm.wdrc_parm[i]); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); + wdrc_printf(tar_buf); + } + } + } + +#if TCFG_DYNAMIC_EQ_ENABLE + group_id = get_group_id(AEID_MUSIC_EQ2, 0); + tar_buf = &music_eq2_parm; + tar_len = sizeof(music_eq2_parm); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); + music_eq2_printf(tar_buf); + +//dynamic eq + group_id = EFF_MUSIC_DYNAMIC_EQ;//get_group_id(AEID_MUSIC_EQ2, 0); + tar_buf = &dynamic_eq; + tar_len = sizeof(DynamicEQParam_TOOL_SET); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); + dynamic_eq_printf(tar_buf); +#endif + +#if GAIN_PROCESS_EN +//gain + group_id = EFF_MUSIC_GAIN; + tar_buf = &gain_parm; + tar_len = sizeof(gain_parm); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); +#if PARM_DEBUG + log_debug("gain_parm.is_bypass %d, gain 0x%x", gain_parm.is_bypass, *(int *)&gain_parm.parm.gain); +#endif +#endif + +#if defined(SOUND_TRACK_2_P_X_CH_CONFIG) &&SOUND_TRACK_2_P_X_CH_CONFIG +//low pass + group_id = EFF_MUSIC_RL_RR_LOW_PASS; + tar_buf = &low_pass_parm; + tar_len = sizeof(low_pass_parm); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); +#if PARM_DEBUG + log_info("low_pass_parm.is_bypass %d\n", low_pass_parm.is_bypass); + struct advance_iir *low_p = &low_pass_parm.low_pass; + log_info("low_p->fc %d, low_p->order %d, low_p->type %d\n", low_p->fc, low_p->order, low_p->type); +#endif +#endif + +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) +//rl_wdrc + u8 type = 0; + group_id = EFF_MUSIC_RL_LOW_DRC; + tar_buf = &rl_drc_parm.wdrc_parm[type]; + tar_len = sizeof(rl_drc_parm.wdrc_parm[type]); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); + wdrc_printf(tar_buf); +#endif +#if GAIN_PROCESS_EN +//rl_rr_gain + group_id = EFF_MUSIC_RL_GAIN; + tar_buf = &rl_gain_parm; + tar_len = sizeof(rl_gain_parm); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); +#if PARM_DEBUG + log_debug("rl_gain_parm.is_bypass %d, gain 0x%x", rl_gain_parm.is_bypass, *(int *)&rl_gain_parm.parm.gain); +#endif +#endif +} + +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN +void linein_eff_analyze_data(void) +{ + u8 index = 0; + void *tar_buf = NULL; + u16 tar_len = 0; + u16 group_id = 0; + u16 mode_seq = linein_mode_seq; +//eq + group_id = get_group_id(AEID_LINEIN_EQ, 0); + tar_buf = &linein_mode.eq_parm; + tar_len = sizeof(linein_mode.eq_parm); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); + music_eq_printf(tar_buf); +//drc + struct mode_list *list = get_group_list(AEID_LINEIN_DRC); + if (list) { + for (int i = 0; i < list->group_num; i++) { + group_id = list->group_id[i]; + if ((list->group_num > 1) && (i == (list->group_num - 1))) { //最后一个存分频器系数 + tar_buf = &linein_mode.drc_parm.crossover; + tar_len = sizeof(linein_mode.drc_parm.crossover); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); +#if PARM_DEBUG + CrossOverParam_TOOL_SET *parm = tar_buf; + log_debug("way_num %d, N %d, low_freq %d, high_freq %d\n", parm->way_num, parm->N, parm->low_freq, parm->high_freq); +#endif + } else { + tar_buf = &linein_mode.drc_parm.wdrc_parm[i]; + tar_len = sizeof(linein_mode.drc_parm.wdrc_parm[i]); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); + wdrc_printf(tar_buf); + } + } + } + +#if GAIN_PROCESS_EN +//gain + group_id = EFF_LINEIN_GAIN; + tar_buf = &gain_parm; + tar_len = sizeof(gain_parm); + eff_file_analyze(mode_seq, group_id, tar_buf, tar_len); +#if PARM_DEBUG + log_debug("gain_parm.is_bypass %d, gain 0x%x", gain_parm.is_bypass, *(int *)&gain_parm.parm.gain); +#endif +#endif +} +#endif + + +extern struct phone_parm_tool_set phone_mode[4]; +extern int eff_file_analyze(u32 mode_id, u16 group_id, void *data_buf, u32 buf_len); +void wdrc_printf(void *_wdrc) +{ +#if PARM_DEBUG + puts("---------------------- drc -----------------------\n"); + wdrc_struct_TOOL_SET *twdrc = _wdrc; + struct wdrc_struct *wdrc = &twdrc->parm; + printf("wdrc->is_bypass %d\n", twdrc->is_bypass); + printf("wdrc attacktime %d, releasetime %d threshold_num %d rms_time %d algorithm%d, mode%d ,0x%x,0x%x\n", wdrc->attacktime, wdrc->releasetime, wdrc->threshold_num, wdrc->rms_time, wdrc->algorithm, wdrc->mode, *(int *)&wdrc->inputgain, *(int *)&wdrc->outputgain); + struct threshold_group *tt = (struct threshold_group *)wdrc->threshold; + for (int i = 0; i < wdrc->threshold_num; i++) { + printf("in_threshold 0x%x, out_threshold 0x%x\n", *(int *)&tt[i].in_threshold, *(int *)&tt[i].out_threshold); + } +#endif +} + +void eq_printf(void *_parm) +{ +#if PARM_DEBUG + puts("----------------------- eq ----------------------\n"); + struct eq_tool *parm = _parm; + printf("global_gain:0x%x\n", *(int *)&parm->global_gain); + printf("seg_num:%d\n", parm->seg_num); + struct eq_seg_info *seg;// = parm->seg; + for (int i = 0; i < parm->seg_num; i++) { + seg = &parm->seg[i]; + printf("idx:%d, iir:%d, frq:%d, gain:0x%x, q:0x%x \n", seg->index, seg->iir_type, seg->freq, *(int *)&seg->gain, *(int *)&seg->q); + } +#endif +} + + +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE +//文件效果还原到 相应结构体 +void mic_eff_analyze_data(u8 tar_mode) +{ +#if PARM_DEBUG + log_debug("------------------------------ eff mode %d\n", tar_mode); +#endif + u8 index = tar_mode; + void *tar_buf = NULL;// + u16 tar_len = 0; + u16 group_id = 0; +//noisegate + tar_buf = (void *)&eff_mode[index].noise_gate_parm; + tar_len = sizeof(eff_mode[index].noise_gate_parm); + eff_file_analyze(eff_mode_seq[index], EFF_MIC_NOISEGATE, tar_buf, tar_len); +//howlingps_parm + tar_buf = (void *)&eff_mode[index].howlingps_parm; + tar_len = sizeof(eff_mode[index].howlingps_parm); + eff_file_analyze(eff_mode_seq[index], EFF_MIC_HOWLINE_PS, tar_buf, tar_len); +//notchowling_parm + tar_buf = (void *)&eff_mode[index].notchhowling_parm; + tar_len = sizeof(eff_mode[index].notchhowling_parm); + eff_file_analyze(eff_mode_seq[index], EFF_MIC_NOTCH_HOWLING, tar_buf, tar_len); +//voice_changer +#if defined(TCFG_MIC_VOICE_CHANGER_ENABLE) && TCFG_MIC_VOICE_CHANGER_ENABLE + tar_buf = (void *)&eff_mode[index].voicechanger_parm; + tar_len = sizeof(eff_mode[index].voicechanger_parm); + eff_file_analyze(eff_mode_seq[index], EFF_MIC_VOICE_CHANGER, tar_buf, tar_len); +#endif + +//echo + tar_buf = (void *)&eff_mode[index].echo_parm; + tar_len = sizeof(eff_mode[index].echo_parm); + eff_file_analyze(eff_mode_seq[index], EFF_MIC_ECHO, tar_buf, tar_len); +//palte_reverb + tar_buf = (void *)&eff_mode[index].plate_reverb_parm; + tar_len = sizeof(eff_mode[index].plate_reverb_parm); + eff_file_analyze(eff_mode_seq[index], EFF_MIC_PLATE_REVERB, tar_buf, tar_len); + Plate_reverb_TOOL_SET *parm = tar_buf; + + +//eq + for (int i = 0; i < ARRAY_SIZE(eq_name); i++) { + group_id = get_group_id(eq_name[i], 0); + tar_buf = (void *)&eff_mode[index].eq_parm[i]; + tar_len = sizeof(eff_mode[index].eq_parm[i]); + eff_file_analyze(eff_mode_seq[index], group_id, tar_buf, tar_len); + eq_printf(tar_buf); + } +//wdrc + for (int i = 0; i < ARRAY_SIZE(drc_name); i++) { + group_id = get_group_id(drc_name[i], 0); + tar_buf = (void *)&eff_mode[index].drc_parm[i]; + tar_len = sizeof(eff_mode[index].drc_parm[i]); + eff_file_analyze(eff_mode_seq[index], group_id, tar_buf, tar_len); + wdrc_printf(tar_buf); + } + +#if GAIN_PROCESS_EN +//gain + group_id = EFF_MIC_GAIN; + tar_buf = &eff_mode[index].gain_parm; + tar_len = sizeof(eff_mode[index].gain_parm); + eff_file_analyze(eff_mode_seq[index], group_id, tar_buf, tar_len); +#if PARM_DEBUG + log_debug("gain_parm.is_bypass %d, gain 0x%x", gain_parm.is_bypass, *(int *)&gain_parm.parm.gain); +#endif +#endif +} +#endif +/** + *注册相应模块的解析函数,返回值0成功,返回小于0失败 + * */ +REGISTER_CMD_TARGET(mic_g) = { + .cmd = EFF_MIC_GAIN, + .cmd_deal = mic_gain_parm_analyze, +}; +REGISTER_CMD_TARGET(music_g) = { + .cmd = EFF_MUSIC_GAIN, + .cmd_deal = gain_process_parm_analyze, +}; +REGISTER_CMD_TARGET(music_rl_g) = { + .cmd = EFF_MUSIC_RL_GAIN, + .cmd_deal = rl_gain_process_parm_analyze, +}; + + +REGISTER_CMD_TARGET(dyeq) = { + .cmd = EFF_MUSIC_DYNAMIC_EQ, + .cmd_deal = dynamic_eq_parm_analyze, +}; +REGISTER_CMD_TARGET(echo) = { + .cmd = EFF_MIC_ECHO, + .cmd_deal = echo_parm_analyze, +}; +REGISTER_CMD_TARGET(p_reverb) = { + .cmd = EFF_MIC_PLATE_REVERB, + .cmd_deal = plate_reverb_parm_analyze, +}; +REGISTER_CMD_TARGET(notch_howling) = { + .cmd = EFF_MIC_NOTCH_HOWLING, + .cmd_deal = notchhowline_parm_analyze, +}; +REGISTER_CMD_TARGET(howling_ps) = { + .cmd = EFF_MIC_HOWLINE_PS, + .cmd_deal = howling_pitch_shift_parm_analyze, +}; +REGISTER_CMD_TARGET(noisegate) = { + .cmd = EFF_MIC_NOISEGATE, + .cmd_deal = noise_gate_parm_analyze, +}; +REGISTER_CMD_TARGET(pw_drc) = {//下行宽频drc + .cmd = EFF_PHONE_WIDEBAND_DRC, + .cmd_deal = phone_wdrc_parm_analyze, +}; +REGISTER_CMD_TARGET(ph_drc) = {//下行窄频drc + .cmd = EFF_PHONE_NARROWBAND_DRC, + .cmd_deal = phone_wdrc_parm_analyze, +}; +REGISTER_CMD_TARGET(aw_drc) = {//上行宽频drc + .cmd = EFF_AEC_WIDEBAND_DRC, + .cmd_deal = phone_wdrc_parm_analyze, +}; +REGISTER_CMD_TARGET(an_drc) = {//上行窄频drc + .cmd = EFF_AEC_NARROWBAND_DRC, + .cmd_deal = phone_wdrc_parm_analyze, +}; +REGISTER_CMD_TARGET(ml_drc) = {//music_drc + .cmd = EFF_MUSIC_LOW_DRC, + .cmd_deal = music_wdrc_parm_analyze, +}; +REGISTER_CMD_TARGET(mm_drc) = {//music_drc + .cmd = EFF_MUSIC_MID_DRC, + .cmd_deal = music_wdrc_parm_analyze, +}; +REGISTER_CMD_TARGET(mh_drc) = {//music_drc + .cmd = EFF_MUSIC_HIGH_DRC, + .cmd_deal = music_wdrc_parm_analyze, +}; +REGISTER_CMD_TARGET(m_whole_drc) = {//music_drc + .cmd = EFF_MUSIC_WHOLE_DRC, + .cmd_deal = music_wdrc_parm_analyze, +}; +REGISTER_CMD_TARGET(m_cross) = {//music_crossover + .cmd = EFF_MUSIC_CROSSOVER, + .cmd_deal = music_wdrc_parm_analyze, +}; + +REGISTER_CMD_TARGET(rl_drc_p) = {//music_rl_drc + .cmd = EFF_MUSIC_RL_LOW_DRC, + .cmd_deal = music_rl_wdrc_parm_analyze, +}; + + +REGISTER_CMD_TARGET(micDrc0) = {//mic_drc0 + .cmd = EFF_MIC_DRC0, + .cmd_deal = mic_wdrc_parm_analyze, +}; +REGISTER_CMD_TARGET(micDrc1) = {//mic_drc1 + .cmd = EFF_MIC_DRC1, + .cmd_deal = mic_wdrc_parm_analyze, +}; +REGISTER_CMD_TARGET(micDrc2) = {//mic_drc2 + .cmd = EFF_MIC_DRC2, + .cmd_deal = mic_wdrc_parm_analyze, +}; +REGISTER_CMD_TARGET(micDrc3) = {//mic_drc3 + .cmd = EFF_MIC_DRC3, + .cmd_deal = mic_wdrc_parm_analyze, +}; +REGISTER_CMD_TARGET(micDrc4) = {//mic_drc4 + .cmd = EFF_MIC_DRC4, + .cmd_deal = mic_wdrc_parm_analyze, +}; +REGISTER_CMD_TARGET(music_eq) = {//music eq + .cmd = EFF_MUSIC_EQ2, + .cmd_deal = music_eq_parm_analyze, +}; +REGISTER_CMD_TARGET(music_eq2) = {//music eq2 + .cmd = EFF_MUSIC_EQ, + .cmd_deal = music_eq_parm_analyze, +}; +REGISTER_CMD_TARGET(music_hbass_eq) = {//high bass eq + .cmd = EFF_MUSIC_HIGH_BASS_EQ, + .cmd_deal = music_eq_parm_analyze, +}; + +REGISTER_CMD_TARGET(micEq0) = {//mic eq0 + .cmd = EFF_MIC_EQ0, + .cmd_deal = mic_eq_parm_analyze, +}; +REGISTER_CMD_TARGET(micEq1) = {//mic eq1 + .cmd = EFF_MIC_EQ1, + .cmd_deal = mic_eq_parm_analyze, +}; +REGISTER_CMD_TARGET(micEq2) = {//mic eq2 + .cmd = EFF_MIC_EQ2, + .cmd_deal = mic_eq_parm_analyze, +}; +REGISTER_CMD_TARGET(micEq3) = {//mic eq3 + .cmd = EFF_MIC_EQ3, + .cmd_deal = mic_eq_parm_analyze, +}; +REGISTER_CMD_TARGET(micEq4) = {//mic eq4 + .cmd = EFF_MIC_EQ4, + .cmd_deal = mic_eq_parm_analyze, +}; + +REGISTER_CMD_TARGET(ph_Eq) = {//通话下行宽频(16k sr) + .cmd = EFF_PHONE_WIDEBAND_EQ, + .cmd_deal = phone_eq_parm_analyze, +}; +REGISTER_CMD_TARGET(pn_Eq) = {//通话下行窄频(8k sr) + .cmd = EFF_PHONE_NARROWBAND_EQ, + .cmd_deal = phone_eq_parm_analyze, +}; +REGISTER_CMD_TARGET(aw_Eq) = {//通话上行宽频(16k sr) + .cmd = EFF_AEC_WIDEBAND_EQ, + .cmd_deal = phone_eq_parm_analyze, +}; +REGISTER_CMD_TARGET(an_Eq) = {//通话上行窄频(8k sr) + .cmd = EFF_AEC_NARROWBAND_EQ, + .cmd_deal = phone_eq_parm_analyze, +}; +REGISTER_CMD_TARGET(lowpass_p) = {//2.1/2.2声道低通滤波器 + .cmd = EFF_MUSIC_RL_RR_LOW_PASS, + .cmd_deal = low_pass_parm_analyze, +}; +REGISTER_CMD_TARGET(linein_eq) = {//linein eq + .cmd = EFF_LINEIN_EQ, + .cmd_deal = linein_eq_parm_analyze, +}; +REGISTER_CMD_TARGET(linein_drc) = {//linein drc + .cmd = EFF_LINEIN_DRC, + .cmd_deal = linein_wdrc_parm_analyze, +}; +REGISTER_CMD_TARGET(linein_g) = { + .cmd = EFF_LINEIN_GAIN, + .cmd_deal = linein_gain_process_parm_analyze, +}; +REGISTER_CMD_TARGET(mic_voice_changer) = { + .cmd = EFF_MIC_VOICE_CHANGER, + .cmd_deal = mic_voice_changer_parm_ananlyze, +}; +REGISTER_CMD_TARGET(vbass_h) = { + .cmd = EFF_MUSIC_VBASS, + .cmd_deal = music_vbass_parm_ananlyze, +}; + +REGISTER_CMD_TARGET(vbass_prev_g) = { + .cmd = EFF_MUSIC_VBASS_PREV_GAIN, + .cmd_deal = vbass_prev_gain_process_parm_analyze, +}; + + +/** + *注册个别查询命令解析函数,返回值1成功,返回小于0失败 + * */ +REGISTER_CMD_TARGET(version) = { + .cmd = EFF_CMD_GETVER, + .cmd_deal = eff_tool_get_version, +}; +REGISTER_CMD_TARGET(file_s) = { + .cmd = EFF_CMD_FILE_SIZE, + .cmd_deal = eff_tool_get_cfg_file_size, +}; +REGISTER_CMD_TARGET(file_p) = { + .cmd = EFF_CMD_FILE, + .cmd_deal = eff_tool_get_cfg_file_data, +}; +REGISTER_CMD_TARGET(change_mode) = { + .cmd = EFF_CMD_CHANGE_MODE, + .cmd_deal = eff_tool_set_channge_mode, +}; +REGISTER_CMD_TARGET(inquire) = { + .cmd = EFF_CMD_INQUIRE, + .cmd_deal = eff_tool_set_inquire, +}; +REGISTER_CMD_TARGET(resync_begin) = { + .cmd = EFF_CMD_RESYNC_PARM_BEGIN, + .cmd_deal = eff_tool_resync_parm_begin, +}; + +REGISTER_CMD_TARGET(resync_end) = { + .cmd = EFF_CMD_RESYNC_PARM_END, + .cmd_deal = eff_tool_resync_parm_end, +}; + + + +int eff_init(void) +{ + int i = 0; + phone_eff_default_parm(); + music_eff_default_parm(); +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN + linein_eff_default_parm(); +#endif +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + for (i = 0 ; i < EFFECT_REVERB_PARM_MAX; i++) { + mic_eff_default_parm(i); + } +#endif + + phone_eff_analyze_data(); + music_eff_analyze_data(); +#if (TCFG_EQ_ENABLE != 0) + cp_eq_file_seg_to_custom_tab(); +#endif +#if defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN + linein_eff_analyze_data(); +#endif + +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + for (i = 0 ; i < EFFECT_REVERB_PARM_MAX; i++) { + mic_eff_analyze_data(i); + } +#endif + return 0; +} +__initcall(eff_init); diff --git a/cpu/br23/audio_effect/eq_config.c b/cpu/br23/audio_effect/eq_config.c new file mode 100644 index 0000000..8384ab5 --- /dev/null +++ b/cpu/br23/audio_effect/eq_config.c @@ -0,0 +1,264 @@ + +#include "system/includes.h" +#include "media/includes.h" +#include "media/effects_adj.h" +#include "app_config.h" +#include "app_online_cfg.h" +#include "online_db/online_db_deal.h" +#include "media/audio_eq_drc_apply.h" +#include "config/config_interface.h" + + +//eq_cfg_hw.bin中播歌eq曲线,当作用户自定义模式,参与效果切换. +#define EQ_FILE_CP_TO_CUSTOM 0 + +#if (TCFG_EQ_ENABLE != 0) + +const struct eq_seg_info eq_tab_normal[] = { + {0, EQ_IIR_TYPE_BAND_PASS, 31, 0, 0.7f}, + {1, EQ_IIR_TYPE_BAND_PASS, 62, 0, 0.7f}, + {2, EQ_IIR_TYPE_BAND_PASS, 125, 0, 0.7f}, + {3, EQ_IIR_TYPE_BAND_PASS, 250, 0, 0.7f}, + {4, EQ_IIR_TYPE_BAND_PASS, 500, 0, 0.7f}, + {5, EQ_IIR_TYPE_BAND_PASS, 1000, 0, 0.7f}, + {6, EQ_IIR_TYPE_BAND_PASS, 2000, 0, 0.7f}, + {7, EQ_IIR_TYPE_BAND_PASS, 4000, 0, 0.7f}, + {8, EQ_IIR_TYPE_BAND_PASS, 8000, 0, 0.7f}, + {9, EQ_IIR_TYPE_BAND_PASS, 16000, 0, 0.7f}, +}; + +const struct eq_seg_info eq_tab_rock[] = { + {0, EQ_IIR_TYPE_BAND_PASS, 31, -2, 0.7f}, + {1, EQ_IIR_TYPE_BAND_PASS, 62, 0, 0.7f}, + {2, EQ_IIR_TYPE_BAND_PASS, 125, 2, 0.7f}, + {3, EQ_IIR_TYPE_BAND_PASS, 250, 4, 0.7f}, + {4, EQ_IIR_TYPE_BAND_PASS, 500, -2, 0.7f}, + {5, EQ_IIR_TYPE_BAND_PASS, 1000, -2, 0.7f}, + {6, EQ_IIR_TYPE_BAND_PASS, 2000, 0, 0.7f}, + {7, EQ_IIR_TYPE_BAND_PASS, 4000, 0, 0.7f}, + {8, EQ_IIR_TYPE_BAND_PASS, 8000, 4, 0.7f}, + {9, EQ_IIR_TYPE_BAND_PASS, 16000, 4, 0.7f}, +}; + +const struct eq_seg_info eq_tab_pop[] = { + {0, EQ_IIR_TYPE_BAND_PASS, 31, 3, 0.7f}, + {1, EQ_IIR_TYPE_BAND_PASS, 62, 1, 0.7f}, + {2, EQ_IIR_TYPE_BAND_PASS, 125, 0, 0.7f}, + {3, EQ_IIR_TYPE_BAND_PASS, 250, -2, 0.7f}, + {4, EQ_IIR_TYPE_BAND_PASS, 500, -4, 0.7f}, + {5, EQ_IIR_TYPE_BAND_PASS, 1000, -4, 0.7f}, + {6, EQ_IIR_TYPE_BAND_PASS, 2000, -2, 0.7f}, + {7, EQ_IIR_TYPE_BAND_PASS, 4000, 0, 0.7f}, + {8, EQ_IIR_TYPE_BAND_PASS, 8000, 1, 0.7f}, + {9, EQ_IIR_TYPE_BAND_PASS, 16000, 2, 0.7f}, +}; + +const struct eq_seg_info eq_tab_classic[] = { + {0, EQ_IIR_TYPE_BAND_PASS, 31, 0, 0.7f}, + {1, EQ_IIR_TYPE_BAND_PASS, 62, 8, 0.7f}, + {2, EQ_IIR_TYPE_BAND_PASS, 125, 8, 0.7f}, + {3, EQ_IIR_TYPE_BAND_PASS, 250, 4, 0.7f}, + {4, EQ_IIR_TYPE_BAND_PASS, 500, 0, 0.7f}, + {5, EQ_IIR_TYPE_BAND_PASS, 1000, 0, 0.7f}, + {6, EQ_IIR_TYPE_BAND_PASS, 2000, 0, 0.7f}, + {7, EQ_IIR_TYPE_BAND_PASS, 4000, 0, 0.7f}, + {8, EQ_IIR_TYPE_BAND_PASS, 8000, 2, 0.7f}, + {9, EQ_IIR_TYPE_BAND_PASS, 16000, 2, 0.7f}, + +}; + +const struct eq_seg_info eq_tab_country[] = { + {0, EQ_IIR_TYPE_BAND_PASS, 31, -2, 0.7f}, + {1, EQ_IIR_TYPE_BAND_PASS, 62, 0, 0.7f}, + {2, EQ_IIR_TYPE_BAND_PASS, 125, 0, 0.7f}, + {3, EQ_IIR_TYPE_BAND_PASS, 250, 2, 0.7f}, + {4, EQ_IIR_TYPE_BAND_PASS, 500, 2, 0.7f}, + {5, EQ_IIR_TYPE_BAND_PASS, 1000, 0, 0.7f}, + {6, EQ_IIR_TYPE_BAND_PASS, 2000, 0, 0.7f}, + {7, EQ_IIR_TYPE_BAND_PASS, 4000, 0, 0.7f}, + {8, EQ_IIR_TYPE_BAND_PASS, 8000, 4, 0.7f}, + {9, EQ_IIR_TYPE_BAND_PASS, 16000, 4, 0.7f}, +}; + +const struct eq_seg_info eq_tab_jazz[] = { + {0, EQ_IIR_TYPE_BAND_PASS, 31, 0, 0.7f}, + {1, EQ_IIR_TYPE_BAND_PASS, 62, 0, 0.7f}, + {2, EQ_IIR_TYPE_BAND_PASS, 125, 0, 0.7f}, + {3, EQ_IIR_TYPE_BAND_PASS, 250, 4, 0.7f}, + {4, EQ_IIR_TYPE_BAND_PASS, 500, 4, 0.7f}, + {5, EQ_IIR_TYPE_BAND_PASS, 1000, 4, 0.7f}, + {6, EQ_IIR_TYPE_BAND_PASS, 2000, 0, 0.7f}, + {7, EQ_IIR_TYPE_BAND_PASS, 4000, 2, 0.7f}, + {8, EQ_IIR_TYPE_BAND_PASS, 8000, 3, 0.7f}, + {9, EQ_IIR_TYPE_BAND_PASS, 16000, 4, 0.7f}, +}; +struct eq_seg_info eq_tab_custom[] = { + {0, EQ_IIR_TYPE_BAND_PASS, 31, 0, 0.7f}, + {1, EQ_IIR_TYPE_BAND_PASS, 62, 0, 0.7f}, + {2, EQ_IIR_TYPE_BAND_PASS, 125, 0, 0.7f}, + {3, EQ_IIR_TYPE_BAND_PASS, 250, 0, 0.7f}, + {4, EQ_IIR_TYPE_BAND_PASS, 500, 0, 0.7f}, + {5, EQ_IIR_TYPE_BAND_PASS, 1000, 0, 0.7f}, + {6, EQ_IIR_TYPE_BAND_PASS, 2000, 0, 0.7f}, + {7, EQ_IIR_TYPE_BAND_PASS, 4000, 0, 0.7f}, + {8, EQ_IIR_TYPE_BAND_PASS, 8000, 0, 0.7f}, + {9, EQ_IIR_TYPE_BAND_PASS, 16000, 0, 0.7f}, +}; + +// 默认系数表,用户可修改 +const struct eq_seg_info *eq_type_tab[EQ_MODE_MAX] = { + eq_tab_normal, eq_tab_rock, eq_tab_pop, eq_tab_classic, eq_tab_jazz, eq_tab_country, eq_tab_custom +}; +// 默认系数表,每个表对应的总增益,用户可修改 +float globa_gain_tab[EQ_MODE_MAX] = {0, 0, 0, 0, 0, 0, 0}; + + +/* + *通话下行eq系数表 + * */ + +const struct eq_seg_info phone_eq_tab_normal[] = { + {0, EQ_IIR_TYPE_HIGH_PASS, 200, 0, 0.7f}, + {1, EQ_IIR_TYPE_BAND_PASS, 300, 0, 0.7f}, + {2, EQ_IIR_TYPE_BAND_PASS, 400, 0, 0.7f}, +}; + +/* + *通话上行eq系数表 + * */ +const struct eq_seg_info ul_eq_tab_normal[] = { + {0, EQ_IIR_TYPE_HIGH_PASS, 200, 0, 0.7f}, + {1, EQ_IIR_TYPE_BAND_PASS, 300, 0, 0.7f}, + {2, EQ_IIR_TYPE_BAND_PASS, 400, 0, 0.7f}, +}; + +static u8 eq_mode = 0; +//eq效果表切换 +int eq_mode_sw(void) +{ + eq_mode++; + if (eq_mode >= ARRAY_SIZE(eq_type_tab)) { + eq_mode = 0; + } + struct eq_seg_info *seg = eq_type_tab[eq_mode]; + + u8 nsection = ARRAY_SIZE(eq_tab_normal); + if (nsection > mSECTION_MAX) { + log_e("ERROR nsection:%d > mSECTION_MAX:%d ", nsection, mSECTION_MAX); + return -1;// + } + /* music_mode.eq_parm.seg_num = nsection; */ + /* music_mode.eq_parm.global_gain = globa_gain_tab[eq_mode]; */ + cur_eq_set_global_gain(AEID_MUSIC_EQ, globa_gain_tab[eq_mode]); + for (int i = 0; i < nsection; i++) { + /* memcpy(&music_mode.eq_parm.seg[i], &seg[i], sizeof(struct eq_seg_info)); */ + cur_eq_set_update(AEID_MUSIC_EQ, &seg[i], nsection, 1); + } + + return 0; +} +//指定设置某个eq效果表 +int eq_mode_set(EQ_MODE mode) +{ + if (eq_mode >= ARRAY_SIZE(eq_type_tab)) { + eq_mode = 0; + } + struct eq_seg_info *seg = eq_type_tab[eq_mode]; + u8 nsection = ARRAY_SIZE(eq_tab_normal); + if (nsection > mSECTION_MAX) { + log_e("ERROR nsection:%d > mSECTION_MAX:%d ", nsection, mSECTION_MAX); + return -1;// + } + /* music_mode.eq_parm.seg_num = nsection; */ + /* music_mode.eq_parm.global_gain = globa_gain_tab[eq_mode]; */ + cur_eq_set_global_gain(AEID_MUSIC_EQ, globa_gain_tab[eq_mode]); + for (int i = 0; i < nsection; i++) { + /* memcpy(&music_mode.eq_parm.seg[i], &seg[i], sizeof(struct eq_seg_info)); */ + cur_eq_set_update(AEID_MUSIC_EQ, &seg[i], nsection, 1); + } + + return 0; +} +//返回某个eq效果模式标号 +EQ_MODE eq_mode_get_cur(void) +{ + return eq_mode; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 设置用户自定义模式某段eq信息 + @param + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int eq_mode_set_custom_seg(struct eq_seg_info *seg) +{ + struct eq_seg_info *tar_seg = eq_tab_custom; + u8 index = seg->index; + if (index > ARRAY_SIZE(eq_tab_custom)) { + log_e("index %d > max_nsection %d", index, ARRAY_SIZE(eq_tab_custom)); + return -1; + } + memcpy(&tar_seg[index], seg, sizeof(struct eq_seg_info)); + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief 获取某个模式eq表内,某一段eq的信息 + @param + @param + @return 返回eq信息 + @note +*/ +/*----------------------------------------------------------------------------*/ +struct eq_seg_info *eq_mode_get_seg(EQ_MODE mode, u8 index) +{ + if (mode >= ARRAY_SIZE(eq_type_tab)) { + return NULL; + } + struct eq_seg_info *seg = eq_type_tab[mode]; + return &seg[index]; +} + +/* + *更新某段自定义系数表,某段eq的中心截止频率以及增益 + * */ +int eq_mode_set_custom_info(u16 index, int freq, float gain) +{ + struct eq_seg_info *seg = eq_mode_get_seg(EQ_MODE_CUSTOM, index);//获取某段eq系数 + if (!seg) { + return -1; + } + seg->freq = freq;//修改freq gain + seg->gain = gain; + eq_mode_set_custom_seg(seg);//重设系数 + + eq_mode_set(EQ_MODE_CUSTOM);//设置更新系数 + return 0; +} +void cp_eq_file_seg_to_custom_tab() +{ +#if EQ_FILE_CP_TO_CUSTOM + u8 nsection = music_mode.eq_parm.seg_num; + struct eq_seg_info *seg = eq_tab_custom; + for (nsection > ARRAY_SIZE(eq_tab_custom)) { + log_e("music nsection:%d > custom nsection:%d\n", nsection, ARRAY_SIZE(eq_tab_custom)); + return ; + } + globa_gain_tab[EQ_MODE_CUSTOM] = music_mode.eq_parm.global_gain; + memcpy(seg, music_mode.eq_parm.seg, sizeof(struct eq_seg_info)*nsection); +#endif +} + + +int eq_init(void) +{ + audio_eq_init(); + audio_drc_init(); + return 0; +} +__initcall(eq_init); + + +#endif diff --git a/cpu/br23/audio_enc/audio_adc_demo.c b/cpu/br23/audio_enc/audio_adc_demo.c new file mode 100644 index 0000000..3818103 --- /dev/null +++ b/cpu/br23/audio_enc/audio_adc_demo.c @@ -0,0 +1,235 @@ +/* + ***************************************************************** + * + * Audio ADC 多通道使用demo + * + ***************************************************************** + */ + +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "asm/audio_src.h" +#include "audio_enc.h" +#include "app_main.h" +//#include "app_task.h" +#include "audio_config.h" + +extern struct audio_adc_hdl adc_hdl; + +/*总共使能多少个通道*/ +#define LADC_CH_NUM 1 + +#define LADC_BUF_NUM 2 +#define LADC_IRQ_POINTS 256 /*中断点数*/ +#define LADC_BUFS_SIZE (LADC_CH_NUM * LADC_BUF_NUM * LADC_IRQ_POINTS) + +/*调试使用,推mic数据/linein数据/mic&line混合数据到dac*/ +#define LADC_2_DAC_ENABLE 1 +#define LADC_MIC_2_DAC BIT(0) +#define LADC_LIN_2_DAC BIT(1) +#define LADC_2_DAC (LADC_MIC_2_DAC | LADC_LIN_2_DAC) + +typedef struct { + struct audio_adc_output_hdl output; + struct audio_adc_ch linein_ch; + struct adc_mic_ch mic_ch; + s16 adc_buf[LADC_BUFS_SIZE]; //align 4Bytes + s16 temp_buf[LADC_IRQ_POINTS * 3]; +} audio_adc_t; +static audio_adc_t *ladc_var = NULL; + +/* + * 使能1个通道,1个linein或者1个mic: + * 数据结构:DAT0 DAT1 DAT2 + */ +static void audio_adc1_output_demo(void *priv, s16 *data, int len) +{ + struct audio_adc_hdl *hdl = priv; + int wlen = 0; + + putchar('1'); + if (ladc_var == NULL) { + return; + } + /* printf("linein:%x,len:%d,ch:%d",data,len,hdl->channel); */ + +#if LADC_2_DAC_ENABLE +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)//双声道数据结构 + for (int i = 0; i < (len / 2); i++) { + ladc_var->temp_buf[i * 2] = data[i]; + ladc_var->temp_buf[i * 2 + 1] = data[i]; + } + wlen = app_audio_output_write(ladc_var->temp_buf, len * 2); +#else //单声道数据结构 + //TODO + wlen = app_audio_output_write(data, len * hdl->channel); +#endif/*TCFG_AUDIO_DAC_CONNECT_MODE*/ +#endif/*LADC_2_DAC_ENABLE*/ +} + +/* + * 使能2个通道,1个linein和1个mic: + * 数据结构:LIN0 MIC0 LIN1 MIC1 LIN2 MIC2 + */ +static void audio_adc2_output_demo(void *priv, s16 *data, int len) +{ + struct audio_adc_hdl *hdl = priv; + int wlen = 0; + + putchar('2'); + if (ladc_var == NULL) { + return; + } + /* printf("linein:%x,len:%d,ch:%d",data,len,hdl->channel); */ + +#if LADC_2_DAC_ENABLE +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)//双声道数据结构 + wlen = app_audio_output_write(data, len * 2); +#else //单声道数据结构 + //TODO +#endif/*TCFG_AUDIO_DAC_CONNECT_MODE*/ +#endif/*LADC_2_DAC_ENABLE*/ +} +/* + * 使能3个通道,2个linein 和 1个mic: + * 数据结构:LINL0 LINR0 MIC0 LINL1 LINR1 MIC1 LINL2 LINR2 MIC2... + */ +static void audio_adc3_output_demo(void *priv, s16 *data, int len) +{ + struct audio_adc_hdl *hdl = priv; + int wlen = 0; + + putchar('3'); + if (ladc_var == NULL) { + return; + } + /* printf("linein:%x,len:%d,ch:%d",data,len,hdl->channel); */ + +#if LADC_2_DAC_ENABLE +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR)//双声道数据结构 +#if (LADC_2_DAC == LADC_LIN_2_DAC) + for (u16 i = 0; i < len / 2; i++) { + data[2 * i] = data[3 * i]; + data[2 * i + 1] = data[3 * i + 1]; + } +#elif (LADC_2_DAC == LADC_MIC_2_DAC) + for (u16 i = 0; i < len / 2; i++) { + data[2 * i] = data[3 * i + 2]; + data[2 * i + 1] = data[3 * i + 2]; + } +#else //linein data and mic data mix + int tmp_data; + for (u16 i = 0; i < len / 2; i++) { + tmp_data = data[3 * i]; + tmp_data += data[3 * i + 2]; + if (tmp_data > 32767) { + tmp_data = 32767; + } else if (tmp_data < -32768) { + tmp_data = -32768; + } + data[2 * i] = tmp_data; + + tmp_data = data[3 * i + 1]; + tmp_data += data[3 * i + 2]; + if (tmp_data > 32767) { + tmp_data = 32767; + } else if (tmp_data < -32768) { + tmp_data = -32768; + } + data[2 * i + 1] = tmp_data; + } +#endif/*LADC_2_DAC*/ + wlen = app_audio_output_write(data, len * 2); +#else //单声道数据结构 + +#endif/*TCFG_AUDIO_DAC_CONNECT_MODE*/ +#endif/*LADC_2_DAC_ENABLE*/ +} + + +int audio_adc_open_demo(void) +{ + u16 ladc_sr = 16000; + u8 mic_gain = 5; + u8 linein_gain = 3; + r_printf("audio_adc_open_demo,sr:%d,mic_gain:%d,linein_gain:%d\n", ladc_sr, mic_gain, linein_gain); + if (ladc_var) { + r_printf("ladc already open \n"); + return 0; + } + ladc_var = zalloc(sizeof(audio_adc_t)); + if (ladc_var) { +#if (LADC_CH_NUM == 1) + audio_adc_mic_open(&ladc_var->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl); + audio_adc_mic_set_sample_rate(&ladc_var->mic_ch, ladc_sr); + audio_adc_mic_set_gain(&ladc_var->mic_ch, mic_gain); + audio_adc_mic_set_buffs(&ladc_var->mic_ch, ladc_var->adc_buf, LADC_CH_NUM * LADC_IRQ_POINTS * 2, LADC_BUF_NUM); + ladc_var->output.handler = audio_adc1_output_demo; + ladc_var->output.priv = &adc_hdl; + audio_adc_add_output_handler(&adc_hdl, &ladc_var->output); + audio_adc_mic_start(&ladc_var->mic_ch); +#else + audio_adc_mic_open(&ladc_var->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl); + audio_adc_mic_set_sample_rate(&ladc_var->mic_ch, ladc_sr); + audio_adc_mic_set_gain(&ladc_var->mic_ch, mic_gain); + +#if (LADC_CH_NUM ==2 ) + audio_adc_linein_open(&ladc_var->linein_ch, AUDIO_ADC_LINE0_L, &adc_hdl); + //audio_adc_linein_open(&ladc_var->linein_ch, AUDIO_ADC_LINE0_R, &adc_hdl); +#else + audio_adc_linein_open(&ladc_var->linein_ch, AUDIO_ADC_LINE0_LR, &adc_hdl); +#endif + audio_adc_linein_set_sample_rate(&ladc_var->linein_ch, ladc_sr); + audio_adc_linein_set_gain(&ladc_var->linein_ch, linein_gain); + + printf("adc_buf_size:%d", sizeof(ladc_var->adc_buf)); + audio_adc_set_buffs(&ladc_var->linein_ch, ladc_var->adc_buf, LADC_CH_NUM * LADC_IRQ_POINTS * 2, LADC_BUF_NUM); +#if (LADC_CH_NUM == 2) + ladc_var->output.handler = audio_adc2_output_demo; +#else + ladc_var->output.handler = audio_adc3_output_demo; +#endif/*LADC_CH_NUM*/ + ladc_var->output.priv = &adc_hdl; + audio_adc_add_output_handler(&adc_hdl, &ladc_var->output); + audio_adc_start(&ladc_var->linein_ch, &ladc_var->mic_ch); +#endif + +#if LADC_2_DAC_ENABLE + app_audio_output_samplerate_set(ladc_sr); + app_audio_output_start(); +#endif/*LADC_2_DAC_ENABLE*/ + return 0; + } else { + return -1; + } +} + +void audio_adc_close_demo() +{ + if (ladc_var) { + audio_adc_mic_close(&ladc_var->mic_ch); + audio_adc_del_output_handler(&adc_hdl, &ladc_var->output); + local_irq_disable(); + free(ladc_var); + ladc_var = NULL; + local_irq_enable(); + extern void audio_output_stop(void); + audio_output_stop(); + } +} + +#if 1 +static u8 audio_adc_demo_idle_query(void) +{ + if (ladc_var) { + return 0; + } + return 1; +} + +REGISTER_LP_TARGET(audio_adc_demo) = { + .name = "audio_adc_demo", + .is_idle = audio_adc_demo_idle_query, +}; +#endif diff --git a/cpu/br23/audio_enc/audio_enc.c b/cpu/br23/audio_enc/audio_enc.c new file mode 100644 index 0000000..9aea666 --- /dev/null +++ b/cpu/br23/audio_enc/audio_enc.c @@ -0,0 +1,1069 @@ +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "asm/audio_src.h" +#include "audio_enc.h" +#include "app_main.h" +#include "clock_cfg.h" +#include "classic/hci_lmp.h" +#include "app_config.h" +#include "audio_common/audio_iis.h" +#include "Resample_api.h" + +#ifndef CONFIG_LITE_AUDIO +#include "app_task.h" +#include "aec_user.h" +#include "loud_speaker.h" +#include "mic_effect.h" +#else +__attribute__((weak))void audio_aec_inbuf(s16 *buf, u16 len) +{ +} +#endif/*CONFIG_LITE_AUDIO*/ + +/* #include "encode/encode_write.h" */ +extern struct adc_platform_data adc_data; + +struct audio_adc_hdl adc_hdl; +struct esco_enc_hdl *esco_enc = NULL; +struct audio_encoder_task *encode_task = NULL; + +static u16 ladc_irq_point_unit = 0; + +#define ESCO_ADC_BUF_NUM 3 +#define ESCO_ADC_IRQ_POINTS 256 +#define ESCO_ADC_BUFS_SIZE (ESCO_ADC_BUF_NUM * ESCO_ADC_IRQ_POINTS) + +struct esco_enc_hdl { + struct audio_encoder encoder; + struct audio_adc_output_hdl adc_output; + struct adc_mic_ch mic_ch; + //OS_SEM pcm_frame_sem; + s16 output_frame[30]; //align 4Bytes + int pcm_frame[60]; //align 4Bytes + /* s16 adc_buf[ESCO_ADC_BUFS_SIZE]; //align 4Bytes */ + u8 state; + RS_STUCT_API *mic_sw_src_api ; + u8 *mic_sw_src_buf; +}; + +static void adc_mic_output_handler(void *priv, s16 *data, int len) +{ + /* printf("buf:%x,data:%x,len:%d",esco_enc->adc_buf,data,len); */ + audio_aec_inbuf(data, len); +} + + +#if TCFG_IIS_INPUT_EN +#define IIS_MIC_SRC_DIFF_MAX (50) +#define IIS_MIC_BUF_SIZE (2*1024) +cbuffer_t *iis_mic_cbuf = NULL; +static RS_STUCT_API *iis_mic_sw_src_api = NULL; +static u8 *iis_mic_sw_src_buf = NULL; +static s16 iis_mic_sw_src_output[ALNK_BUF_POINTS_NUM]; +s32 sw_src_in_sr = 0; +s32 sw_src_in_sr_top = 0; +s32 sw_src_in_sr_botton = 0; + +int iis_mic_sw_src_init() +{ + printf("%s !!\n", __func__); + if (iis_mic_sw_src_api) { + printf("iis mic sw src is already open !\n"); + return -1; + } + iis_mic_sw_src_api = get_rs16_context(); + g_printf("iis_mic_sw_src_api:0x%x\n", iis_mic_sw_src_api); + ASSERT(iis_mic_sw_src_api); + u32 iis_mic_sw_src_need_buf = iis_mic_sw_src_api->need_buf(); + g_printf("iis_mic_sw_src_buf:%d\n", iis_mic_sw_src_need_buf); + iis_mic_sw_src_buf = malloc(iis_mic_sw_src_need_buf); + ASSERT(iis_mic_sw_src_buf); + RS_PARA_STRUCT rs_para_obj; + rs_para_obj.nch = 1; + rs_para_obj.new_insample = TCFG_IIS_INPUT_SR; + rs_para_obj.new_outsample = 16000; + + sw_src_in_sr = rs_para_obj.new_insample; + sw_src_in_sr_top = rs_para_obj.new_insample + IIS_MIC_SRC_DIFF_MAX; + sw_src_in_sr_botton = rs_para_obj.new_insample - IIS_MIC_SRC_DIFF_MAX; + printf("sw src,in = %d,out = %d\n", rs_para_obj.new_insample, rs_para_obj.new_outsample); + iis_mic_sw_src_api->open(iis_mic_sw_src_buf, &rs_para_obj); + return 0; +} + +int iis_mic_sw_src_uninit() +{ + printf("%s !!\n", __func__); + if (iis_mic_sw_src_api) { + iis_mic_sw_src_api = NULL; + } + if (iis_mic_sw_src_buf) { + free(iis_mic_sw_src_buf); + iis_mic_sw_src_buf = NULL; + } + return 0; +} + +static void iis_mic_output_handler(void *priv, s16 *data, int len) +{ + s16 *outdat = NULL; + int outlen = 0; + int wlen = 0; + int i = 0; + + // dual to mono + for (i = 0; i < len / 2 / 2; i++) { + /* data[i] = ((s32)(data[i*2]) + (s32)(data[i*2-1])) / 2; */ + data[i] = data[i * 2]; + } + len >>= 1; + + + + + + if (iis_mic_cbuf) { + if (iis_mic_sw_src_api && iis_mic_sw_src_buf) { + if (iis_mic_cbuf->data_len > IIS_MIC_BUF_SIZE * 3 / 4) { + sw_src_in_sr--; + if (sw_src_in_sr < sw_src_in_sr_botton) { + sw_src_in_sr = sw_src_in_sr_botton; + } + } else if (iis_mic_cbuf->data_len < IIS_MIC_BUF_SIZE / 4) { + sw_src_in_sr++; + if (sw_src_in_sr > sw_src_in_sr_top) { + sw_src_in_sr = sw_src_in_sr_top; + } + } + + outlen = iis_mic_sw_src_api->run(iis_mic_sw_src_buf, \ + data, \ + len >> 1, \ + iis_mic_sw_src_output); + ASSERT(outlen <= (sizeof(iis_mic_sw_src_output) >> 1)); + outlen = outlen << 1; + outdat = iis_mic_sw_src_output; + } + wlen = cbuf_write(iis_mic_cbuf, outdat, outlen); + if (wlen != outlen) { + putchar('w'); + } + esco_enc_resume(); + } +} + +static int iis_mic_output_read(s16 *buf, u16 len) +{ + int rlen = 0; + if (iis_mic_cbuf) { + rlen = cbuf_read(iis_mic_cbuf, buf, len); + } + return rlen; +} + +#endif // TCFG_IIS_INPUT_EN + +#if TCFG_MIC_EFFECT_ENABLE +unsigned int jl_sr_table[] = { + 7616, + 10500, + 11424, + 15232, + 21000, + 22848, + 30464, + 42000, + 45696, +}; + +unsigned int normal_sr_table[] = { + 8000, + 11025, + 12000, + 16000, + 22050, + 24000, + 32000, + 44100, + 48000, +}; +static u8 get_sample_rate_index(u32 sr) +{ + u8 i; + for (i = 0; i < ARRAY_SIZE(normal_sr_table); i++) { + if (normal_sr_table[i] == sr) { + return i; + } + } + return i - 1; +} +int mic_sw_src_init(u16 out_sr) +{ + if (!esco_enc) { + printf(" mic is not open !\n"); + return -1; + } + esco_enc->mic_sw_src_api = get_rsfast_context(); + esco_enc->mic_sw_src_buf = malloc(esco_enc->mic_sw_src_api->need_buf()); + + ASSERT(esco_enc->mic_sw_src_buf); + RS_PARA_STRUCT rs_para_obj; + rs_para_obj.nch = 1; + /* rs_para_obj.new_insample = MIC_EFFECT_SAMPLERATE; */ + /* rs_para_obj.new_outsample = out_sr; */ + rs_para_obj.new_insample = jl_sr_table[get_sample_rate_index(MIC_EFFECT_SAMPLERATE)]; + rs_para_obj.new_outsample = jl_sr_table[get_sample_rate_index(out_sr)]; + esco_enc->mic_sw_src_api->open(esco_enc->mic_sw_src_buf, &rs_para_obj); + return 0; +} + +int mic_sw_src_uninit(void) +{ + if (!esco_enc) { + return 0; + } + if (esco_enc->mic_sw_src_buf) { + free(esco_enc->mic_sw_src_buf); + esco_enc->mic_sw_src_buf = NULL; + } + return 0; +} + +#endif //TCFG_MIC_EFFECT_ENABLE + +static void adc_mic_output_handler_downsr(void *priv, s16 *data, int len) +{ + //printf("buf:%x,data:%x,len:%d",esco_enc->adc_buf,data,len); + u16 i; + s16 temp_buf[160]; + if (esco_enc && esco_enc->mic_sw_src_buf) { + int wlen = esco_enc->mic_sw_src_api->run(esco_enc->mic_sw_src_buf, data, len / 2, temp_buf); + audio_aec_inbuf(temp_buf, wlen << 1); + } + /* audio_aec_inbuf(temp_buf, len / 2); */ +} + +__attribute__((weak)) int audio_aec_output_read(s16 *buf, u16 len) +{ + return 0; +} + +void esco_enc_resume(void) +{ + if (esco_enc) { + //os_sem_post(&esco_enc->pcm_frame_sem); + audio_encoder_resume(esco_enc); + } +} + +static int esco_enc_pcm_get(struct audio_encoder *encoder, s16 **frame, u16 frame_len) +{ + int rlen = 0; + if (encoder == NULL) { + r_printf("encoder NULL"); + } + struct esco_enc_hdl *enc = container_of(encoder, struct esco_enc_hdl, encoder); + + if (enc == NULL) { + r_printf("enc NULL"); + } + + while (1) { + +#if TCFG_IIS_INPUT_EN + rlen = iis_mic_output_read(enc->pcm_frame, frame_len); +#else // TCFG_IIS_INPUT_EN + + rlen = audio_aec_output_read(enc->pcm_frame, frame_len); +#endif // TCFG_IIS_INPUT_EN + + if (rlen == frame_len) { + /*esco编码读取数据正常*/ +#if (RECORDER_MIX_EN) + recorder_mix_sco_data_write(enc->pcm_frame, frame_len); +#endif/*RECORDER_MIX_EN*/ + break; + } else if (rlen == 0) { + /*esco编码读不到数,返回0*/ + return 0; + /*esco编码读不到数,pend住*/ + /* int ret = os_sem_pend(&enc->pcm_frame_sem, 100); + if (ret == OS_TIMEOUT) { + r_printf("esco_enc pend timeout\n"); + break; + } */ + } else { + /*通话结束,aec已经释放*/ + printf("audio_enc end:%d\n", rlen); + rlen = 0; + break; + } + } + + *frame = enc->pcm_frame; + return rlen; +} +static void esco_enc_pcm_put(struct audio_encoder *encoder, s16 *frame) +{ +} + +static const struct audio_enc_input esco_enc_input = { + .fget = esco_enc_pcm_get, + .fput = esco_enc_pcm_put, +}; + +static int esco_enc_probe_handler(struct audio_encoder *encoder) +{ + return 0; +} + +static int esco_enc_output_handler(struct audio_encoder *encoder, u8 *frame, int len) +{ + lmp_private_send_esco_packet(NULL, frame, len); + //printf("frame:%x,out:%d\n",frame, len); + + return len; +} + +const static struct audio_enc_handler esco_enc_handler = { + .enc_probe = esco_enc_probe_handler, + .enc_output = esco_enc_output_handler, +}; + +static void esco_enc_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ + printf("esco_enc_event_handler:0x%x,%d\n", argv[0], argv[0]); + switch (argv[0]) { + case AUDIO_ENC_EVENT_END: + puts("AUDIO_ENC_EVENT_END\n"); + break; + } +} + +int esco_enc_open(u32 coding_type, u8 frame_len) +{ + int err; + struct audio_fmt fmt; + + printf("esco_enc_open: %d,frame_len:%d\n", coding_type, frame_len); + + fmt.channel = 1; + fmt.frame_len = frame_len; + if (coding_type == AUDIO_CODING_MSBC) { + fmt.sample_rate = 16000; + fmt.coding_type = AUDIO_CODING_MSBC; + clock_add(ENC_MSBC_CLK); + } else if (coding_type == AUDIO_CODING_CVSD) { + fmt.sample_rate = 8000; + fmt.coding_type = AUDIO_CODING_CVSD; + clock_add(ENC_CVSD_CLK); + } else { + /*Unsupoport eSCO Air Mode*/ + } + +#if (RECORDER_MIX_EN) + recorder_mix_pcm_set_info(fmt.sample_rate, fmt.channel); +#endif/*RECORDER_MIX_EN*/ + + audio_encoder_task_open(); + + if (!esco_enc) { + esco_enc = zalloc(sizeof(*esco_enc)); + } + //os_sem_create(&esco_enc->pcm_frame_sem, 0); + + audio_encoder_open(&esco_enc->encoder, &esco_enc_input, encode_task); + audio_encoder_set_handler(&esco_enc->encoder, &esco_enc_handler); + audio_encoder_set_fmt(&esco_enc->encoder, &fmt); + audio_encoder_set_event_handler(&esco_enc->encoder, esco_enc_event_handler, 0); + audio_encoder_set_output_buffs(&esco_enc->encoder, esco_enc->output_frame, + sizeof(esco_enc->output_frame), 1); + + audio_encoder_start(&esco_enc->encoder); + + printf("esco sample_rate: %d,mic_gain:%d\n", fmt.sample_rate, app_var.aec_mic_gain); + +#if TCFG_IIS_INPUT_EN + if (iis_mic_cbuf == NULL) { + iis_mic_cbuf = zalloc(sizeof(cbuffer_t) + IIS_MIC_BUF_SIZE); + if (iis_mic_cbuf) { + cbuf_init(iis_mic_cbuf, iis_mic_cbuf + 1, IIS_MIC_BUF_SIZE); + } else { + printf("iis_mic_cbuf zalloc err !!!!!!!!!!!!!!\n"); + } + } + iis_mic_sw_src_init(); + audio_iis_input_start(TCFG_IIS_INPUT_PORT, TCFG_IIS_INPUT_DATAPORT_SEL, iis_mic_output_handler); +#else // TCFG_IIS_INPUT_EN +#if 0 + audio_adc_mic_open(&esco_enc->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl); + audio_adc_mic_set_sample_rate(&esco_enc->mic_ch, fmt.sample_rate); + audio_adc_mic_set_gain(&esco_enc->mic_ch, app_var.aec_mic_gain); + audio_adc_mic_set_buffs(&esco_enc->mic_ch, esco_enc->adc_buf, + ESCO_ADC_IRQ_POINTS * 2, ESCO_ADC_BUF_NUM); + esco_enc->adc_output.handler = adc_mic_output_handler; + audio_adc_add_output_handler(&adc_hdl, &esco_enc->adc_output); + +#if (AUDIO_OUTPUT_WAY != AUDIO_OUTPUT_WAY_FM) + audio_adc_mic_start(&esco_enc->mic_ch); +#endif +#else +#if TCFG_MIC_EFFECT_ENABLE + if (fmt.sample_rate != MIC_EFFECT_SAMPLERATE) {//8K时需把mic数据采样率降低 + mic_sw_src_init(fmt.sample_rate); + esco_enc->adc_output.handler = adc_mic_output_handler_downsr; + } else { + esco_enc->adc_output.handler = adc_mic_output_handler; + } + audio_mic_open(&esco_enc->mic_ch, MIC_EFFECT_SAMPLERATE, app_var.aec_mic_gain); +#else + esco_enc->adc_output.handler = adc_mic_output_handler; + audio_mic_open(&esco_enc->mic_ch, fmt.sample_rate, app_var.aec_mic_gain); +#endif + audio_mic_add_output(&esco_enc->adc_output); + audio_mic_start(&esco_enc->mic_ch); +#endif + +#endif // TCFG_IIS_INPUT_EN + + clock_set_cur(); + esco_enc->state = 1; + +#if TCFG_APP_FM_EMITTER_EN + /* extern void audio_aec_ref_start(u8 en); */ + audio_aec_ref_start(1); +#endif + + return 0; +} + +int esco_adc_mic_en() +{ + if (esco_enc && esco_enc->state) { + /* audio_adc_mic_start(&esco_enc->mic_ch); */ + /* audio_mic_start(&esco_enc->mic_ch); */ + return 0; + } + return -1; +} + +void esco_enc_close() +{ + printf("esco_enc_close\n"); + if (!esco_enc) { + printf("esco_enc NULL\n"); + return; + } + + if (esco_enc->encoder.fmt.coding_type == AUDIO_CODING_MSBC) { + clock_remove(ENC_MSBC_CLK); + } else if (esco_enc->encoder.fmt.coding_type == AUDIO_CODING_CVSD) { + clock_remove(ENC_CVSD_CLK); + } +#if TCFG_IIS_INPUT_EN + audio_iis_input_stop(TCFG_IIS_INPUT_PORT, TCFG_IIS_INPUT_DATAPORT_SEL); + if (iis_mic_cbuf) { + free(iis_mic_cbuf); + iis_mic_cbuf = NULL; + } + iis_mic_sw_src_uninit(); + audio_encoder_close(&esco_enc->encoder); +#else // TCFG_IIS_INPUT_EN +#if 0 + audio_adc_mic_close(&esco_enc->mic_ch); + //os_sem_post(&esco_enc->pcm_frame_sem); + audio_encoder_close(&esco_enc->encoder); + audio_adc_del_output_handler(&adc_hdl, &esco_enc->adc_output); +#else + audio_mic_close(&esco_enc->mic_ch, &esco_enc->adc_output); +#if TCFG_MIC_EFFECT_ENABLE + mic_sw_src_uninit(); +#endif //TCFG_MIC_EFFECT_ENABLE + + audio_encoder_close(&esco_enc->encoder); +#endif +#endif // TCFG_IIS_INPUT_EN + + local_irq_disable(); + free(esco_enc); + esco_enc = NULL; + local_irq_enable(); + + audio_encoder_task_close(); + clock_set_cur(); +} + +struct __encoder_task { + u8 init_ok; + atomic_t used; + OS_MUTEX mutex; +}; + +static struct __encoder_task enc_task = {0}; + +int audio_encoder_task_open(void) +{ + local_irq_disable(); + if (enc_task.init_ok == 0) { + atomic_set(&enc_task.used, 0); + os_mutex_create(&enc_task.mutex); + enc_task.init_ok = 1; + } + local_irq_enable(); + + os_mutex_pend(&enc_task.mutex, 0); + if (!encode_task) { + encode_task = zalloc(sizeof(*encode_task)); + audio_encoder_task_create(encode_task, "audio_enc"); + } + atomic_inc_return(&enc_task.used); + os_mutex_post(&enc_task.mutex); + return 0; +} + +void audio_encoder_task_close(void) +{ + os_mutex_pend(&enc_task.mutex, 0); + if (encode_task) { + if (atomic_dec_and_test(&enc_task.used)) { + audio_encoder_task_del(encode_task); + //local_irq_disable(); + free(encode_task); + encode_task = NULL; + //local_irq_enable(); + } + } + os_mutex_post(&enc_task.mutex); +} + + + +////////////////////////////////////////////////////////////////////////////// +int audio_enc_init() +{ + printf("audio_enc_init\n"); + + audio_adc_init(&adc_hdl, &adc_data); + + init_audio_adc(); + return 0; +} + + +/**************************mic linein 接口***************************************************/ +#define LADC_BUF_NUM 2 +#define LADC_CH_NUM 3 +#if TCFG_MIC_EFFECT_ENABLE +#if (RECORDER_MIX_EN) +#define LADC_IRQ_POINTS 160 +#else +#if (TCFG_MIC_EFFECT_SEL == MIC_EFFECT_REVERB) +#define LADC_IRQ_POINTS REVERB_LADC_IRQ_POINTS +#else +#define LADC_IRQ_POINTS ((MIC_EFFECT_SAMPLERATE/1000)*4) +#endif +#endif/*RECORDER_MIX_EN*/ +#else +#define LADC_IRQ_POINTS 256 +#endif +/* #define LADC_BUFS_SIZE (LADC_CH_NUM * LADC_BUF_NUM * LADC_IRQ_POINTS) */ + + +/* #define ENABLE_MIC_LINEIN */ +#define LADC_LINE_L_MASK (BIT(0)) +#define LADC_LINE_R_MASK (BIT(1)) +#define LADC_MIC_CH_MASK (BIT(2)) + +typedef struct { + struct audio_adc_hdl *p_adc_hdl; + struct adc_mic_ch mic_ch; + struct audio_adc_ch linein_ch; + atomic_t used; + /* s16 adc_buf[MIC_ADC_BUFS_SIZE]; //align 4Bytes */ + s16 *adc_buf; + OS_MUTEX mutex; + u8 init_flag: 2; + u8 states: 4; + u16 sample_rate; + struct list_head mic_head; + struct list_head linein_head; + int mic_gain; + int linein_gain; + u8 mic_en: 2; + u8 ladc_en: 2; + u8 ladc_ch_mark: 3;// adc 组合BIT(2):MIC BIT(1):LIN1 BIT(0):LIN0 + u8 ladc_ch_num: 3;// 1 2 3 + //s16 temp_buf[LADC_IRQ_POINTS]; + s16 *temp_buf; + struct audio_adc_output_hdl output; + + +} audio_adc_t; +static audio_adc_t ladc_var = {.init_flag = 1}; + + +static void audio_adc_output_demo(void *priv, s16 *data, int len) +{ + u16 i; + struct audio_adc_output_hdl *p; + /* struct audio_adc_hdl *hdl = priv; */ + if (ladc_var.ladc_ch_num == 1) { + if (ladc_var.ladc_ch_mark & LADC_MIC_CH_MASK) { //单mic + if (!list_empty(&ladc_var.mic_head)) { + list_for_each_entry(p, &ladc_var.mic_head, entry) { + p->handler(p->priv, data, len); + } + } + } else { //单linein + if (!list_empty(&ladc_var.linein_head)) { + list_for_each_entry(p, &ladc_var.linein_head, entry) { + p->handler(p->priv, data, len); + } + } + } + } else if (ladc_var.ladc_ch_num == 2) { + if (ladc_var.ladc_ch_mark & LADC_MIC_CH_MASK) { //数据结构:LIN0 MIC0 LIN1 MIC1 LIN2 MIC2 + if (!list_empty(&ladc_var.mic_head)) { + if (ladc_var.ladc_ch_mark & LADC_LINE_R_MASK) { + for (i = 0; i < len / 2; i++) { + ladc_var.temp_buf[i] = data[i * 2 + 0]; + } + } else { + for (i = 0; i < len / 2; i++) { + ladc_var.temp_buf[i] = data[i * 2 + 1]; + } + } + + list_for_each_entry(p, &ladc_var.mic_head, entry) { + p->handler(p->priv, ladc_var.temp_buf, len); + } + } + if (!list_empty(&ladc_var.linein_head)) { + if (ladc_var.ladc_ch_mark & LADC_LINE_R_MASK) { + for (i = 0; i < len / 2; i++) { + data[i] = data[i * 2 + 1]; + } + } else { + for (i = 0; i < len / 2; i++) { + data[i] = data[i * 2 + 0]; + } + } + list_for_each_entry(p, &ladc_var.linein_head, entry) { + p->handler(p->priv, data, len); + } + } + } else { //两路linein LINL0 LINR0 LINL1 LINR1 + if (!list_empty(&ladc_var.linein_head)) { + list_for_each_entry(p, &ladc_var.linein_head, entry) { + p->handler(p->priv, data, len); + } + } + } + + } else if (ladc_var.ladc_ch_num == 3) {//数据结构:LINL0 LINR0 MIC0 + if (!list_empty(&ladc_var.mic_head)) { + for (i = 0; i < len / 2; i++) { + ladc_var.temp_buf[i] = data[i * 3 + 2]; + } + list_for_each_entry(p, &ladc_var.mic_head, entry) { + p->handler(p->priv, ladc_var.temp_buf, len); + } + } + if (!list_empty(&ladc_var.linein_head)) { + for (i = 1; i < len / 2; i++) { + data[i * 2] = data[i * 3 + 0]; + data[i * 2 + 1] = data[i * 3 + 1]; + } + list_for_each_entry(p, &ladc_var.linein_head, entry) { + p->handler(p->priv, data, len); + } + } + } else { + + return; + } +} + +void init_audio_adc() +{ + if (ladc_var.init_flag) { + log_i("\n mic init_flag \n\n\n\n"); + ladc_var.init_flag = 0; + atomic_set(&ladc_var.used, 0); + os_mutex_create(&ladc_var.mutex); + INIT_LIST_HEAD(&ladc_var.mic_head); + INIT_LIST_HEAD(&ladc_var.linein_head); + /* ladc_var.adc_buf = (s16 *)zalloc(LADC_BUFS_SIZE * 2); */ + ladc_var.states = 0; + } +} + +void audio_adc_set_irq_point_unit(u16 point_unit) +{ + ladc_irq_point_unit = point_unit; +} + +//------------------ +int audio_mic_open(struct adc_mic_ch *mic, u16 sample_rate, u8 gain) +{ + u16 irq_point_unit = LADC_IRQ_POINTS; + if (ladc_irq_point_unit != 0) { + irq_point_unit = ladc_irq_point_unit; + } + +#if TCFG_AUDIO_ADC_ENABLE + os_mutex_pend(&ladc_var.mutex, 0); + if (!ladc_var.adc_buf) { + log_i("\n mic malloc \n\n\n\n"); + ladc_var.ladc_ch_mark = 0; + ladc_var.ladc_ch_mark |= LADC_MIC_CH_MASK; + ladc_var.ladc_ch_num = 1; +#if TCFG_MIC_EFFECT_ENABLE //开混响时启用多路AD +#if (TCFG_LINEIN_ENABLE&&(LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ADC)) + if (TCFG_LINEIN_LR_CH & (AUDIO_LIN0L_CH | AUDIO_LIN1L_CH | AUDIO_LIN2L_CH)) { //判断Line0L Line1L Line2L 是否有打开 + ladc_var.ladc_ch_mark |= LADC_LINE_L_MASK; + ladc_var.ladc_ch_num++; + } + if (TCFG_LINEIN_LR_CH & (AUDIO_LIN0R_CH | AUDIO_LIN1R_CH | AUDIO_LIN2R_CH)) { //判断Line0R Line1R Line2R 是否有打开 + ladc_var.ladc_ch_mark |= LADC_LINE_R_MASK; + ladc_var.ladc_ch_num++; + } +#endif +#endif//TCFG_MIC_EFFECT_ENABLE + + ladc_var.adc_buf = (s16 *)zalloc(ladc_var.ladc_ch_num * irq_point_unit * 2 * LADC_BUF_NUM); + if (ladc_var.ladc_ch_num > 1) { + ladc_var.temp_buf = (s16 *)zalloc(irq_point_unit * 2); + } + printf("ladc_ch_num[%d],[%x]", ladc_var.ladc_ch_num, ladc_var.ladc_ch_mark); + } + if (ladc_var.states == 0) { + atomic_inc_return(&ladc_var.used); + audio_adc_mic_open(&ladc_var.mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl); + audio_adc_mic_set_sample_rate(&ladc_var.mic_ch, sample_rate); + audio_adc_mic_set_gain(&ladc_var.mic_ch, gain); + ladc_var.mic_gain = gain; + if (ladc_var.ladc_ch_mark & (LADC_LINE_R_MASK | LADC_LINE_L_MASK)) { + audio_adc_linein_open(&ladc_var.linein_ch, TCFG_LINEIN_LR_CH << 2, &adc_hdl); + audio_adc_linein_set_sample_rate(&ladc_var.linein_ch, sample_rate); + audio_adc_linein_set_gain(&ladc_var.linein_ch, 0); + } + ladc_var.linein_gain = -1; + if (ladc_var.ladc_ch_num == 1) { + audio_adc_mic_set_buffs(&ladc_var.mic_ch, ladc_var.adc_buf, ladc_var.ladc_ch_num * irq_point_unit * 2, LADC_BUF_NUM); + } else { + audio_adc_set_buffs(&ladc_var.linein_ch, ladc_var.adc_buf, ladc_var.ladc_ch_num * irq_point_unit * 2, LADC_BUF_NUM); + JL_ANA->ADA_CON1 |= BIT(17); //默认先关闭linein通路 + JL_ANA->ADA_CON2 |= BIT(13); + + } + + ladc_var.output.handler = audio_adc_output_demo; + /* ladc_var->output.priv = &adc_hdl; */ + audio_adc_add_output_handler(&adc_hdl, &ladc_var.output); + ladc_var.sample_rate = sample_rate; + ladc_var.states = 1; + } else { + if (ladc_var.sample_rate != sample_rate) { + log_e("err: mic is on,sample_rate not match \n"); + os_mutex_post(&ladc_var.mutex); + return -1; + } + if (ladc_var.mic_gain < 0) { + audio_adc_mic_set_gain(&ladc_var.mic_ch, gain); + ladc_var.mic_gain = gain; + } + atomic_inc_return(&ladc_var.used); + } + mic->hdl = &adc_hdl; + log_i("mic open success \n"); + os_mutex_post(&ladc_var.mutex); + return 0; +#else + return -1; +#endif +} +void audio_mic_add_output(struct audio_adc_output_hdl *output) +{ +#if TCFG_AUDIO_ADC_ENABLE + os_mutex_pend(&ladc_var.mutex, 0); + if (ladc_var.states == 1) { + struct audio_adc_output_hdl *p; + local_irq_disable(); + list_for_each_entry(p, &ladc_var.mic_head, entry) { + if (p == &output->entry) { + goto __exit; + } + } + list_add_tail(&output->entry, &ladc_var.mic_head); +__exit: + local_irq_enable(); + } else { + printf("audio mic not open \n"); + } + os_mutex_post(&ladc_var.mutex); +#endif +} +void audio_mic_start(struct adc_mic_ch *mic) +{ +#if TCFG_AUDIO_ADC_ENABLE + if (!mic || mic->hdl != &adc_hdl) { + log_i("\n adc_mic_ch not open 1\n"); + return; + } + os_mutex_pend(&ladc_var.mutex, 0); + if (ladc_var.ladc_ch_num == 1) { + /* audio_adc_start(NULL, &ladc_var.mic_ch); */ + audio_adc_mic_start(&ladc_var.mic_ch); + } else { + audio_adc_start(&ladc_var.linein_ch, &ladc_var.mic_ch); + } + + os_mutex_post(&ladc_var.mutex); +#endif +} +void audio_mic_close(struct adc_mic_ch *mic, struct audio_adc_output_hdl *output) +{ +#if TCFG_AUDIO_ADC_ENABLE + if (!mic || mic->hdl != &adc_hdl) { + log_i("\n adc_mic_ch not open 2\n"); + return; + } + os_mutex_pend(&ladc_var.mutex, 0); + struct audio_adc_output_hdl *p; + local_irq_disable(); + list_for_each_entry(p, &ladc_var.mic_head, entry) { + if (p == &output->entry) { + list_del(&output->entry); + break; + } + } + local_irq_enable(); + + if (atomic_dec_and_test(&ladc_var.used)) { + log_i("\n audio_adc_mic_close \n"); + if (ladc_var.ladc_ch_num == 1) { + audio_adc_mic_close(&ladc_var.mic_ch); + } else { + audio_adc_close(&ladc_var.linein_ch, &ladc_var.mic_ch); + } + audio_adc_del_output_handler(&adc_hdl, &ladc_var.output); + list_del_init(&ladc_var.mic_head); + list_del_init(&ladc_var.linein_head); + free(ladc_var.adc_buf); + ladc_var.adc_buf = NULL; + if (ladc_var.temp_buf) { + free(ladc_var.temp_buf); + } + ladc_var.temp_buf = NULL; + ladc_var.states = 0; + ladc_var.ladc_ch_mark = 0; + } else { + if (list_empty(&ladc_var.mic_head)) { + audio_adc_mic_set_gain(&ladc_var.mic_ch, 0); + ladc_var.mic_gain = -1; + } + } + os_mutex_post(&ladc_var.mutex); +#endif +} +void audio_mic_set_gain(u8 gain) +{ +#if TCFG_AUDIO_ADC_ENABLE + os_mutex_pend(&ladc_var.mutex, 0); + audio_adc_mic_set_gain(&ladc_var.mic_ch, gain); + ladc_var.mic_gain = gain; + os_mutex_post(&ladc_var.mutex); +#endif +} +//------------------ +int audio_linein_open(struct audio_adc_ch *linein, u16 sample_rate, int gain) +{ + u16 irq_point_unit = LADC_IRQ_POINTS; + if (ladc_irq_point_unit != 0) { + irq_point_unit = ladc_irq_point_unit; + } + +#if (TCFG_LINEIN_ENABLE&&(LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ADC)) + os_mutex_pend(&ladc_var.mutex, 0); + if (!ladc_var.adc_buf) { + log_i("\n ladc malloc \n\n\n\n"); + ladc_var.ladc_ch_mark = 0; +#if (TCFG_AUDIO_ADC_ENABLE&&TCFG_MIC_EFFECT_ENABLE)//开混响时启用多路AD + ladc_var.ladc_ch_mark |= LADC_MIC_CH_MASK; + ladc_var.ladc_ch_num = 1; +#else + ladc_var.ladc_ch_mark = 0; + ladc_var.ladc_ch_num = 0; +#endif + /* if (TCFG_LINEIN_LR_CH & (0x15)) { */ + if (TCFG_LINEIN_LR_CH & (AUDIO_LIN0L_CH | AUDIO_LIN1L_CH | AUDIO_LIN2L_CH)) { //判断Line0L Line1L Line2L 是否有打开 + ladc_var.ladc_ch_mark |= LADC_LINE_L_MASK; + ladc_var.ladc_ch_num++; + } + if (TCFG_LINEIN_LR_CH & (AUDIO_LIN0R_CH | AUDIO_LIN1R_CH | AUDIO_LIN2R_CH)) { //判断Line0R Line1R Line2R 是否有打开 + ladc_var.ladc_ch_mark |= LADC_LINE_R_MASK; + ladc_var.ladc_ch_num++; + } + ladc_var.adc_buf = (s16 *)zalloc(ladc_var.ladc_ch_num * irq_point_unit * 2 * LADC_BUF_NUM); + if (ladc_var.ladc_ch_mark & LADC_MIC_CH_MASK) { //mic通路有打开 + ladc_var.temp_buf = (s16 *)zalloc(irq_point_unit * 2); + } + printf("ladc_ch_num[%d],[%x]", ladc_var.ladc_ch_num, ladc_var.ladc_ch_mark); + } + if (ladc_var.states == 0) { + atomic_inc_return(&ladc_var.used); +#if (TCFG_AUDIO_ADC_ENABLE&&TCFG_MIC_EFFECT_ENABLE)//开混响时启用多路AD + audio_adc_mic_open(&ladc_var.mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl); + audio_adc_mic_set_sample_rate(&ladc_var.mic_ch, sample_rate); + audio_adc_mic_set_gain(&ladc_var.mic_ch, 0); +#endif + ladc_var.mic_gain = -1 ; + + + audio_adc_linein_open(&ladc_var.linein_ch, TCFG_LINEIN_LR_CH << 2, &adc_hdl); + audio_adc_linein_set_sample_rate(&ladc_var.linein_ch, sample_rate); + audio_adc_linein_set_gain(&ladc_var.linein_ch, gain); + ladc_var.linein_gain = gain; + + audio_adc_set_buffs(&ladc_var.linein_ch, ladc_var.adc_buf, ladc_var.ladc_ch_num * irq_point_unit * 2, LADC_BUF_NUM); + ladc_var.output.handler = audio_adc_output_demo; + ladc_var.output.priv = &adc_hdl; + audio_adc_add_output_handler(&adc_hdl, &ladc_var.output); + ladc_var.sample_rate = sample_rate; + ladc_var.states = 1; + log_i("sample_rate [%d]\n", sample_rate); + } else { + if (ladc_var.sample_rate != sample_rate) { + log_e("err: linein is on,sample_rate not match \n"); + os_mutex_post(&ladc_var.mutex); + return -1; + } + if (ladc_var.linein_gain < 0) { + audio_adc_linein_set_gain(&ladc_var.linein_ch, gain); + ladc_var.linein_gain = gain; + } + if (ladc_var.ladc_ch_mark & LADC_LINE_L_MASK) { + JL_ANA->ADA_CON1 &= ~BIT(17); + } + if (ladc_var.ladc_ch_mark & LADC_LINE_R_MASK) { + JL_ANA->ADA_CON2 &= ~BIT(13); + } + + atomic_inc_return(&ladc_var.used); + } + linein->hdl = &adc_hdl; + log_i("linein open success \n"); + + os_mutex_post(&ladc_var.mutex); + return 0; +#else + return -1; +#endif +} +void audio_linein_add_output(struct audio_adc_output_hdl *output) +{ +#if (TCFG_LINEIN_ENABLE&&(LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ADC)) + os_mutex_pend(&ladc_var.mutex, 0); + if (ladc_var.states == 1) { + struct audio_adc_output_hdl *p; + + local_irq_disable(); + list_for_each_entry(p, &ladc_var.linein_head, entry) { + if (p == &output->entry) { + goto __exit; + } + } + list_add_tail(&output->entry, &ladc_var.linein_head); +__exit: + local_irq_enable(); + } else { + printf("audio linein not open \n"); + } + os_mutex_post(&ladc_var.mutex); +#endif +} +void audio_linein_start(struct audio_adc_ch *linein) +{ +#if (TCFG_LINEIN_ENABLE&&(LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ADC)) + if (!linein || linein->hdl != &adc_hdl) { + log_i("\n adc_mic_ch not open 1\n"); + return; + } + os_mutex_pend(&ladc_var.mutex, 0); + if (ladc_var.ladc_ch_mark & LADC_MIC_CH_MASK) { + audio_adc_start(&ladc_var.linein_ch, &ladc_var.mic_ch); + } else { + audio_adc_start(&ladc_var.linein_ch, NULL); + } + os_mutex_post(&ladc_var.mutex); +#endif +} +void audio_linein_close(struct audio_adc_ch *linein, struct audio_adc_output_hdl *output) +{ +#if (TCFG_LINEIN_ENABLE&&(LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ADC)) + if (!linein || linein->hdl != &adc_hdl) { + log_i("\n adc_mic_ch not open 2\n"); + return; + } + os_mutex_pend(&ladc_var.mutex, 0); + struct audio_adc_output_hdl *p; + local_irq_disable(); + list_for_each_entry(p, &ladc_var.linein_head, entry) { + if (p == &output->entry) { + list_del(&output->entry); + break; + } + } + local_irq_enable(); + if (atomic_dec_and_test(&ladc_var.used)) { + log_i("\n audio_adc_mic_close \n"); + audio_adc_close(&ladc_var.linein_ch, &ladc_var.mic_ch); + audio_adc_del_output_handler(&adc_hdl, &ladc_var.output); + list_del_init(&ladc_var.mic_head); + list_del_init(&ladc_var.linein_head); + free(ladc_var.adc_buf); + ladc_var.adc_buf = NULL; + if (ladc_var.temp_buf) { + free(ladc_var.temp_buf); + } + ladc_var.temp_buf = NULL; + ladc_var.states = 0; + ladc_var.ladc_ch_mark = 0; + } else { + if (list_empty(&ladc_var.linein_head)) { + audio_adc_linein_set_gain(&ladc_var.linein_ch, 0); + JL_ANA->ADA_CON1 |= BIT(17); + JL_ANA->ADA_CON2 |= BIT(13); + ladc_var.linein_gain = -1; + } + } + os_mutex_post(&ladc_var.mutex); +#endif +} +void audio_linein_set_gain(int gain) +{ +#if (TCFG_LINEIN_ENABLE&&(LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ADC)) + os_mutex_pend(&ladc_var.mutex, 0); + audio_adc_linein_set_gain(&ladc_var.linein_ch, gain); + ladc_var.linein_gain = gain; + os_mutex_post(&ladc_var.mutex); +#endif +} +u8 get_audio_linein_ch_num(void) +{ + u8 ret = 0; +#if (TCFG_LINEIN_ENABLE&&(LINEIN_INPUT_WAY == LINEIN_INPUT_WAY_ADC)) + os_mutex_pend(&ladc_var.mutex, 0); + if (ladc_var.states == 1) { + ret = ladc_var.ladc_ch_num; + if (ladc_var.ladc_ch_mark & LADC_MIC_CH_MASK) { + ret--; + } + } + os_mutex_post(&ladc_var.mutex); +#endif + return ret; +} +/*****************************************************************************/ diff --git a/cpu/br23/audio_enc/audio_enc.h b/cpu/br23/audio_enc/audio_enc.h new file mode 100644 index 0000000..820ec91 --- /dev/null +++ b/cpu/br23/audio_enc/audio_enc.h @@ -0,0 +1,74 @@ +#ifndef _AUDIO_ENC_H_ +#define _AUDIO_ENC_H_ + +#include "generic/typedef.h" +#include "media/includes.h" + +#ifndef CONFIG_LITE_AUDIO +#include "mic_effect.h" +#include "loud_speaker.h" +#include "audio_enc_file.h" +#include "audio_enc_recoder.h" +#include "audio_recorder_mix.h" +#endif/*CONFIG_LITE_AUDIO*/ + + +struct record_file_fmt { + u8 gain;//增益配置 + u8 channel;//声道数,1:单声道, 2:双声道 + u16 sample_rate;//采样率 + u32 bit_rate;//码率 + u32 coding_type;//编码格式 + char *dev;//录音设备盘符 + char *folder;//录音文件夹 + char *filename;//录音文件名 + u32 cut_head_time;//录音文件去头时间,单位ms + u32 cut_tail_time;//录音文件去尾时间,单位ms + u32 limit_size;//录音文件大小最小限制, 单位byte + u8 source;//录音输入源 + void (*err_callback)(void); +}; + + +int esco_enc_open(u32 coding_type, u8 frame_len); +void esco_enc_close(); + +enum enc_source { + ENCODE_SOURCE_MIX = 0x0, + ENCODE_SOURCE_MIC, + ENCODE_SOURCE_LINE0_LR, + ENCODE_SOURCE_LINE1_LR, + ENCODE_SOURCE_LINE2_LR, + ENCODE_SOURCE_USER, +}; + +void esco_enc_resume(void); +u32 recorder_get_encoding_time(); +int recorder_is_encoding(void); +void recorder_device_offline_check(char *logo); +void recorder_encode_stop(void); +int mixer_recorder_encoding(void); +int mixer_recorder_start(void); +void mixer_recorder_stop(void); +int recorder_encode_start(struct record_file_fmt *f); +int recorder_userdata_to_enc(s16 *data, int len); + +int audio_encoder_task_open(void); +void audio_encoder_task_close(void); + +void init_audio_adc(); +int audio_mic_open(struct adc_mic_ch *mic, u16 sample_rate, u8 gain); +void audio_mic_add_output(struct audio_adc_output_hdl *output); +void audio_mic_start(struct adc_mic_ch *mic); +void audio_mic_close(struct adc_mic_ch *mic, struct audio_adc_output_hdl *output); +void audio_mic_set_gain(u8 gain); + +int audio_linein_open(struct audio_adc_ch *linein, u16 sample_rate, int gain); +void audio_linein_add_output(struct audio_adc_output_hdl *output); +void audio_linein_start(struct audio_adc_ch *linein); +void audio_linein_close(struct audio_adc_ch *linein, struct audio_adc_output_hdl *output); +void audio_linein_set_gain(int gain); +u8 get_audio_linein_ch_num(void); +////////////////////////////////////////////////////////////////// +#define REVERB_LADC_IRQ_POINTS 256//(160-8)//(160)//(176)//(184)//(192)//(224)//(256) +#endif/*_AUDIO_ENC_H_*/ diff --git a/cpu/br23/audio_enc/audio_enc_file.c b/cpu/br23/audio_enc/audio_enc_file.c new file mode 100644 index 0000000..d8f0427 --- /dev/null +++ b/cpu/br23/audio_enc/audio_enc_file.c @@ -0,0 +1,568 @@ + +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "encode/encode_write.h" +#include "asm/audio_src.h" +#include "audio_enc.h" +#include "app_main.h" +#include "app_task.h" +#include "clock_cfg.h" +#include "dev_manager.h" +#include "btstack/btstack_task.h" +#include "btstack/avctp_user.h" + +#if TCFG_ENC_WRITE_FILE_ENABLE + +#define PCM_ENC2FILE_PCM_LEN (2 * 1024) +#define PCM_ENC2FILE_FILE_LEN (8 * 1024) + +#if (TCFG_MIC_EFFECT_ENABLE && RECORDER_MIX_EN) +#define PCM_ENC2FILE_PCM_LEN_OVERLAY (4 * 1024 + 512) +#define PCM_ENC2FILE_FILE_LEN_OVERLAY (4 * 1024) +#else +#define PCM_ENC2FILE_PCM_LEN_OVERLAY (1 * 1024 + 512) +#define PCM_ENC2FILE_FILE_LEN_OVERLAY (2 * 1024) +#endif + +#define WAV_FILE_HEAD_LEN 90 + +#define PCM2FILE_ENC_BUF_COUNT 1 + +//wav录音头部信息定时更新时间设置, 单位ms +#define UPDATA_WAV_HEAD_TIME (5000) + +//是否使用overlay 使能, 695暂时不支持overlay +#define PCM_ENC2FILE_USE_OVERLAY_EN 0 + + +extern struct audio_encoder_task *encode_task; + +struct pcm2file_enc_hdl { + struct audio_encoder encoder; + s16 output_frame[1152 / 2]; //align 4Bytes + + int pcm_frame[64]; //align 4Bytes + u8 file_head_frame[128]; + u8 file_head_len; + /* u8 pcm_buf[PCM_ENC2FILE_PCM_LEN]; */ + u8 *pcm_buf; + cbuffer_t pcm_cbuf; + + int out_file_frame[512 / 4]; + /* u8 out_file_buf[PCM_ENC2FILE_FILE_LEN]; */ + u8 *out_file_buf; + cbuffer_t out_file_cbuf; + + void *whdl; + OS_SEM sem_wfile; + OS_MUTEX mutex; + + volatile u32 status : 1; + volatile u32 enc_err : 1; + volatile u32 encoding : 1; + volatile u32 write_head_busy : 1; + volatile u32 input_busy : 1; + + u32 lost; + +#if PCM2FILE_ENC_BUF_COUNT + u16 pcm_buf_max; + u16 out_file_max; +#endif + + u32 head_update_tick; + + }; + + + static volatile u8 pcm2file_used_overlay = 0; + +#if (RECORDER_MIX_EN && PCM_ENC2FILE_USE_OVERLAY_EN) + struct pcm2file_enc_hdl pcm2file_enc_overlay_handle sec(.enc_file_mem); + u8 pcm_buf_overlay[PCM_ENC2FILE_PCM_LEN_OVERLAY] sec(.enc_file_mem); + u8 out_file_buf_overlay[PCM_ENC2FILE_FILE_LEN_OVERLAY] sec(.enc_file_mem); +#endif/*RECORDER_MIX_EN*/ + + + + static void pcm2file_enc_resume(struct pcm2file_enc_hdl *enc) +{ + audio_encoder_resume(&enc->encoder); +} + +static void pcm2file_wfile_resume(struct pcm2file_enc_hdl *enc) +{ + os_sem_set(&enc->sem_wfile, 0); + os_sem_post(&enc->sem_wfile); + enc_write_file_resume(enc->whdl); +} + +// 写pcm数据 +int pcm2file_enc_write_pcm(void *priv, s16 *data, int len) +{ + struct pcm2file_enc_hdl *enc = (struct pcm2file_enc_hdl *)priv; + if (!enc || enc->enc_err || enc->status == 0) { + return 0; + } + + u16 wlen = 0; + enc->input_busy = 1; + if (enc->status == 1) { + wlen = cbuf_write(&enc->pcm_cbuf, data, len); + if (!wlen) { + enc->lost++; + putchar('~'); + } else { + /* putchar('G');//__G__ */ + } +#if PCM2FILE_ENC_BUF_COUNT + if (enc->pcm_buf_max < enc->pcm_cbuf.data_len) { + enc->pcm_buf_max = enc->pcm_cbuf.data_len; + } +#endif + /* printf("wl:%d ", wlen); */ + // 激活录音编码器 + pcm2file_enc_resume(enc); + } + enc->input_busy = 0; + return wlen; +} + +// 编码器获取数据 +static int pcm2file_enc_pcm_get(struct audio_encoder *encoder, s16 **frame, u16 frame_len) +{ + int rlen = 0; + int dlen = 0; + if (encoder == NULL) { + r_printf("encoder NULL"); + } + struct pcm2file_enc_hdl *enc = container_of(encoder, struct pcm2file_enc_hdl, encoder); + + if (enc == NULL) { + r_printf("enc NULL"); + } + + /* printf("l:%d", frame_len); */ + + if (!enc->status) { + return 0; + } + if (enc->enc_err) { + return 0; + } + + dlen = cbuf_get_data_len(&enc->pcm_cbuf); + if (dlen < frame_len) { + /* putchar('T');//__T__ */ + return 0; + } + + rlen = cbuf_read(&enc->pcm_cbuf, enc->pcm_frame, frame_len); + + *frame = enc->pcm_frame; + +#if (RECORDER_MIX_EN) + recorder_mix_stream_resume(); +#endif/*RECORDER_MIX_EN*/ + + return rlen; +} + +static void pcm2file_enc_pcm_put(struct audio_encoder *encoder, s16 *frame) +{ +} + +static const struct audio_enc_input pcm2file_enc_input = { + .fget = pcm2file_enc_pcm_get, + .fput = pcm2file_enc_pcm_put, +}; + +static int pcm2file_enc_probe_handler(struct audio_encoder *encoder) +{ + return 0; +} +// 编码器输出 +static int pcm2file_enc_output_handler(struct audio_encoder *encoder, u8 *frame, int len) +{ + struct pcm2file_enc_hdl *enc = container_of(encoder, struct pcm2file_enc_hdl, encoder); + + int wlen = cbuf_write(&enc->out_file_cbuf, frame, len); +#if PCM2FILE_ENC_BUF_COUNT + if (enc->out_file_max < enc->out_file_cbuf.data_len) { + enc->out_file_max = enc->out_file_cbuf.data_len; + } +#endif + pcm2file_wfile_resume(enc); + /* if (wlen != len) { */ + /* printf("X"); */ + /* } */ + /* if (!enc->status) { */ + /* return 0; */ + /* } */ + if (enc->enc_err) { + return 0; + } + + return wlen; +} + +static void pcm2file_enc_get_head_info(struct audio_encoder *encoder) +{ + struct pcm2file_enc_hdl *pcm2file = container_of(encoder, struct pcm2file_enc_hdl, encoder); + u16 len = 0; + u8 *ptr = (u8 *)audio_encoder_ioctrl(&pcm2file->encoder, 2, AUDIO_ENCODER_IOCTRL_CMD_GET_HEAD_INFO, &len); + /* printf("%s, ptr = %x, len = %d\n", __FUNCTION__, ptr, len); */ + if (ptr) { + if (len > sizeof(pcm2file->file_head_frame)) { + printf("file_head_frame buf not enough\n"); + return; + } + memcpy(pcm2file->file_head_frame, ptr, len); + /* put_buf(pcm2file->file_head_frame, len); */ + pcm2file->file_head_len = len; + } +} + +static int pcm2file_enc_close_handler(struct audio_encoder *encoder) +{ + //做一些编码关闭前的操作, 例如:adpcm写头操作 + pcm2file_enc_get_head_info(encoder);//写编码头部信息 + return 0; +} + +const static struct audio_enc_handler pcm2file_enc_handler = { + .enc_probe = pcm2file_enc_probe_handler, + .enc_output = pcm2file_enc_output_handler, + .enc_close = pcm2file_enc_close_handler, +}; + +static int enc_wfile_set_head(void *hdl, char **head) +{ + struct pcm2file_enc_hdl *enc = hdl; + /* struct enc_write_test *tst = hdl; */ + *head = enc->file_head_frame; + return enc->file_head_len; +} + + +static void updata_wav_head_info(struct audio_encoder *encoder, void *priv) +{ + int len; + char *head; + int cur_write_pos; + struct audio_fmt *enc_fmt; + struct pcm2file_enc_hdl *enc = (struct pcm2file_enc_hdl *)priv; + + /* extern int audio_encoder_get_fmt(struct audio_encoder * enc, struct audio_fmt **fmt); */ + audio_encoder_get_fmt(encoder, &enc_fmt); + if ((enc_fmt->coding_type != AUDIO_CODING_WAV) + && (enc_fmt->coding_type != AUDIO_CODING_G726) + ) { + return; + } + + cur_write_pos = fpos(get_wfil_file(enc->whdl)); + pcm2file_enc_get_head_info(encoder); + len = enc_wfile_set_head(get_wfil_head_hdl(enc->whdl), &head); + if (len) { + fseek(get_wfil_file(enc->whdl), 0, SEEK_SET); + fwrite(get_wfil_file(enc->whdl), head, len); + } + fseek(get_wfil_file(enc->whdl), cur_write_pos, SEEK_SET); + //printf("update head!!\n"); +} + +static void pcm2file_enc_w_evt(void *hdl, int evt, int parm) +{ + struct pcm2file_enc_hdl *enc = hdl; + printf("evt: %d ", evt); + if (evt == ENC_WRITE_FILE_EVT_WRITE_ERR) { + enc->enc_err = 1; + pcm2file_wfile_resume(enc); + pcm2file_enc_resume(enc); + audio_encoder_stop(&enc->encoder); + } else if (evt == ENC_WRITE_FILE_EVT_FILE_CLOSE) { + printf("sclust: %d ", parm); + } +} + +static int pcm2file_enc_w_get(void *hdl, s16 **frame, u16 frame_len) +{ + int rlen; + struct pcm2file_enc_hdl *enc = hdl; + os_sem_set(&enc->sem_wfile, 0); + /* printf("r:%d", frame_len); */ + do { + rlen = cbuf_read(&enc->out_file_cbuf, enc->out_file_frame, frame_len); + if (rlen == frame_len) { +// if (cbuf_get_data_len(&enc->out_file_cbuf) <= (PCM_ENC2FILE_FILE_LEN / 2)) { +// ///当写文件有数据取走达到一定程度主动激活编码线程 +// pcm2file_enc_resume(enc); +// } + break; + } + + if (!enc->status) { + rlen = cbuf_get_data_len(&enc->out_file_cbuf); + rlen = cbuf_read(&enc->out_file_cbuf, enc->out_file_frame, rlen); + break; + } + + if (enc->enc_err) { + return 0; + } + pcm2file_enc_resume(enc); + os_sem_pend(&enc->sem_wfile, 2); + } while (1); + + *frame = enc->out_file_frame; + return rlen; +} +static void pcm2file_enc_w_put(void *hdl, s16 *frame) +{ +#if TCFG_NOR_FS_ENABLE || FLASH_INSIDE_REC_ENABLE + return ; +#endif + + struct pcm2file_enc_hdl *enc = (struct pcm2file_enc_hdl *)hdl; + u32 cur_sys_time = timer_get_ms(); + os_mutex_pend(&enc->mutex, 0); + if (enc->status == 0) { + os_mutex_post(&enc->mutex); + return ; + } + if (cur_sys_time - enc->head_update_tick >= UPDATA_WAV_HEAD_TIME) { + updata_wav_head_info(&(enc->encoder), enc); + enc->head_update_tick = cur_sys_time; + } + os_mutex_post(&enc->mutex); +} + +const struct audio_enc_write_input pcm2file_enc_w_input = { + .get = pcm2file_enc_w_get, + .put = pcm2file_enc_w_put, +}; + + + + + +void pcm2file_enc_write_file_set_limit(void *hdl, u32 cut_size, u32 limit_size) +{ + struct pcm2file_enc_hdl *pcm2file = hdl; + enc_write_file_set_limit(pcm2file->whdl, cut_size, limit_size); +} + +void pcm2file_enc_set_evt_handler(void *hdl, void (*handler)(struct audio_encoder *, int, int *), u32 maigc) +{ + struct pcm2file_enc_hdl *pcm2file = hdl; + audio_encoder_set_event_handler(&pcm2file->encoder, handler, maigc); +} + +void pcm2file_enc_start(void *hdl) +{ + struct pcm2file_enc_hdl *pcm2file = hdl; + + pcm2file->status = 1; + + audio_encoder_start(&pcm2file->encoder); + + enc_write_file_start(pcm2file->whdl); + + //记录录音启动时的tick, 后面定时更新头部信息用到 + pcm2file->head_update_tick = timer_get_ms(); +} + +int pcm2file_enc_get_time(void *hdl) +{ + struct pcm2file_enc_hdl *pcm2file = hdl; + if (!pcm2file) { + return 0; + } + os_mutex_pend(&pcm2file->mutex, 0); + if (pcm2file->status == 0) { + os_mutex_post(&pcm2file->mutex); + return 0; + } + int ret = audio_encoder_ioctrl(&pcm2file->encoder, 1, AUDIO_ENCODER_IOCTRL_CMD_GET_TIME); + os_mutex_post(&pcm2file->mutex); + return ret; +} +void *pcm2file_enc_open(struct audio_fmt *pfmt, char *logo, char *folder, char *filename) +{ + int err; + struct pcm2file_enc_hdl *pcm2file = NULL; + char *temp_filename = NULL; + u32 out_file_buf_size = 0; + u32 pcm_buf_size = 0; + + if (pfmt->coding_type != AUDIO_CODING_MP3 && pfmt->coding_type != AUDIO_CODING_WAV && pfmt->coding_type != AUDIO_CODING_G726) { + return NULL; + } + + ///创建录音编码线程 + audio_encoder_task_open(); + +#if (RECORDER_MIX_EN && PCM_ENC2FILE_USE_OVERLAY_EN) + if (BT_CALL_HANGUP != get_call_status()) { + printf("[%s], used overlay!!\n", __FUNCTION__); + pcm2file_used_overlay = 1; + pcm2file = &pcm2file_enc_overlay_handle; + memset(&pcm2file_enc_overlay_handle, 0, sizeof(struct pcm2file_enc_hdl)); + pcm2file->pcm_buf = pcm_buf_overlay; + pcm2file->out_file_buf = out_file_buf_overlay; + pcm_buf_size = PCM_ENC2FILE_PCM_LEN_OVERLAY; + out_file_buf_size = PCM_ENC2FILE_FILE_LEN_OVERLAY; + memset(pcm2file->pcm_buf, 0, PCM_ENC2FILE_PCM_LEN_OVERLAY); + memset(pcm2file->out_file_buf, 0, PCM_ENC2FILE_FILE_LEN_OVERLAY); + } else +#endif/*RECORDER_MIX_EN*/ + { + printf("[%s], used malloc!!\n", __FUNCTION__); + pcm2file_used_overlay = 0; + pcm2file = zalloc(sizeof(struct pcm2file_enc_hdl)); + if (!pcm2file) { + goto __out; + } + pcm_buf_size = PCM_ENC2FILE_PCM_LEN; + out_file_buf_size = PCM_ENC2FILE_FILE_LEN; + pcm2file->pcm_buf = zalloc(pcm_buf_size); + if (pcm2file->pcm_buf == NULL) { + goto __out; + } + pcm2file->out_file_buf = zalloc(out_file_buf_size); + if (pcm2file->out_file_buf == NULL) { + goto __out; + } + + } + + os_sem_create(&pcm2file->sem_wfile, 0); + os_mutex_create(&pcm2file->mutex); + cbuf_init(&pcm2file->out_file_cbuf, pcm2file->out_file_buf, out_file_buf_size); + + temp_filename = zalloc(strlen(filename) + 5); + if (temp_filename == NULL) { + goto __out; + } + if (pfmt->coding_type == AUDIO_CODING_MP3) { + strcat(temp_filename, filename); + strcat(temp_filename, ".mp3"); + } else if (pfmt->coding_type == AUDIO_CODING_WAV || pfmt->coding_type == AUDIO_CODING_G726) { + strcat(temp_filename, filename); + strcat(temp_filename, ".wav"); + } + pcm2file->whdl = enc_write_file_open(logo, folder, temp_filename); + free(temp_filename); + if (!pcm2file->whdl) { + goto __out; + } + + enc_write_file_set_evt_handler(pcm2file->whdl, pcm2file_enc_w_evt, pcm2file); + enc_write_file_set_input(pcm2file->whdl, &pcm2file_enc_w_input, pcm2file, sizeof(pcm2file->out_file_frame)); + if ((pfmt->coding_type == AUDIO_CODING_WAV) || (pfmt->coding_type == AUDIO_CODING_G726)) { + pcm2file->file_head_len = WAV_FILE_HEAD_LEN; + enc_write_file_set_head_handler(pcm2file->whdl, enc_wfile_set_head, pcm2file); + } + if (pfmt->coding_type == AUDIO_CODING_MP3) { + if ((pfmt->sample_rate < 16000) && (pfmt->bit_rate > 64)) { + pfmt->bit_rate = 64; + } + } + cbuf_init(&pcm2file->pcm_cbuf, pcm2file->pcm_buf, pcm_buf_size); + audio_encoder_open(&pcm2file->encoder, &pcm2file_enc_input, encode_task); + audio_encoder_set_handler(&pcm2file->encoder, &pcm2file_enc_handler); + audio_encoder_set_fmt(&pcm2file->encoder, pfmt); + audio_encoder_set_output_buffs(&pcm2file->encoder, pcm2file->output_frame, + sizeof(pcm2file->output_frame), 1); + + return pcm2file; +__out: + if (pcm2file_used_overlay == 0) { + if (pcm2file->pcm_buf) { + free(pcm2file->pcm_buf); + } + if (pcm2file->out_file_buf) { + free(pcm2file->out_file_buf); + } + if (pcm2file) { + free(pcm2file); + } + } + return NULL; +} + + +void pcm2file_enc_close(void **hdl) +{ + struct pcm2file_enc_hdl *pcm2file = *hdl; + if (!pcm2file) { + return; + } + os_mutex_pend(&pcm2file->mutex, 0); + pcm2file->status = 0; + os_mutex_post(&pcm2file->mutex); + while (pcm2file->input_busy) { + os_time_dly(1); + } + audio_encoder_close(&pcm2file->encoder); + enc_write_file_stop(pcm2file->whdl, 1000); + enc_write_file_close(pcm2file->whdl); + + printf("pcm2file_enc_close, lost:%d ", pcm2file->lost); + +#if PCM2FILE_ENC_BUF_COUNT + printf("pcm_buf_max:%d,%d/100; out_file_max:%d,%d/100 ", + pcm2file->pcm_buf_max, pcm2file->pcm_buf_max * 100 / PCM_ENC2FILE_PCM_LEN, + pcm2file->out_file_max, pcm2file->out_file_max * 100 / PCM_ENC2FILE_FILE_LEN + ); +#endif + if (pcm2file_used_overlay == 0) { + printf("[%s], used malloc, need free!!\n", __FUNCTION__); + if (pcm2file->pcm_buf) { + free(pcm2file->pcm_buf); + } + if (pcm2file->out_file_buf) { + free(pcm2file->out_file_buf); + } + OS_ENTER_CRITICAL(); + free(pcm2file); + *hdl = NULL; + OS_EXIT_CRITICAL(); + } else { + printf("[%s], used overlay, noneed free!!\n", __FUNCTION__); + } + + audio_encoder_task_close(); +} + +int pcm2file_enc_is_work(void *hdl) +{ + struct pcm2file_enc_hdl *enc = hdl; + if (!enc || !enc->status || enc->enc_err) { + return false; + } + return true; +} + +int get_pcm2file_enc_file_len(void *hdl) +{ + struct pcm2file_enc_hdl *pcm2file = hdl; + return get_enc_file_len(pcm2file->whdl); +} + +struct audio_encoder *get_pcm2file_encoder_hdl(void *hdl) +{ + struct pcm2file_enc_hdl *enc = hdl; + return &(enc->encoder); +} + + +#endif + + + + + + diff --git a/cpu/br23/audio_enc/audio_enc_file.h b/cpu/br23/audio_enc/audio_enc_file.h new file mode 100644 index 0000000..e97eb1b --- /dev/null +++ b/cpu/br23/audio_enc/audio_enc_file.h @@ -0,0 +1,27 @@ + +#ifndef _AUDIO_ENC_FILE_H_ +#define _AUDIO_ENC_FILE_H_ + +#include "media/audio_encoder.h" +#include "dev_manager.h" + + +// 写pcm数据 +int pcm2file_enc_write_pcm(void *priv, s16 *data, int len); +void *pcm2file_enc_open(struct audio_fmt *pfmt, char *logo, char *folder, char *filename); +void pcm2file_enc_write_file_set_limit(void *hdl, u32 cut_size, u32 limit_size); +void pcm2file_enc_set_evt_handler(void *hdl, void (*handler)(struct audio_encoder *, int, int *), u32 maigc); +void pcm2file_enc_start(void *hdl); +void pcm2file_enc_close(void **hdl); +int pcm2file_enc_is_work(void *hdl); +int get_pcm2file_enc_file_len(void *hdl); +struct audio_encoder *get_pcm2file_encoder_hdl(void *hdl); +int pcm2file_enc_get_time(void *hdl); + +#endif + + + + + + diff --git a/cpu/br23/audio_enc/audio_enc_recoder.c b/cpu/br23/audio_enc/audio_enc_recoder.c new file mode 100644 index 0000000..d659afc --- /dev/null +++ b/cpu/br23/audio_enc/audio_enc_recoder.c @@ -0,0 +1,1103 @@ +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "asm/audio_src.h" +#include "audio_enc.h" +#include "app_main.h" +#include "app_task.h" +#include "encode/encode_write.h" +#include "clock_cfg.h" +#include "audio_config.h" +#include "dev_manager.h" +#include "audio_track.h" + +#define LADC_MIC_BUF_NUM 2 +#define LADC_MIC_CH_NUM 1 +#define LADC_MIC_IRQ_POINTS 256 +#define LADC_MIC_BUFS_SIZE (LADC_MIC_CH_NUM * LADC_MIC_BUF_NUM * LADC_MIC_IRQ_POINTS) + +struct ladc_mic_demo { + struct audio_adc_output_hdl adc_output; + struct adc_mic_ch mic_ch; + s16 adc_buf[LADC_MIC_BUFS_SIZE]; //align 4Bytes +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR) + s16 tmp_buf[LADC_MIC_IRQ_POINTS * 2]; +#endif + int cut_timer; +}; +struct ladc_mic_demo *ladc_mic = NULL; + + +extern struct audio_adc_hdl adc_hdl; +extern bool app_task_msg_post(int msg, int argc, ...); + +static void adc_mic_demo_output(void *priv, s16 *data, int len) +{ + struct audio_adc_hdl *hdl = priv; + //putchar('o'); + if (ladc_mic == NULL) { + return; + } + //printf("mic:%x,len:%d,ch:%d",data,len,hdl->channel); + putchar('.'); +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR) + //mono->dual + for (u16 i = 0; i < len / 2; i++) { + ladc_mic->tmp_buf[2 * i] = data[i]; + ladc_mic->tmp_buf[2 * i + 1] = data[i]; + } + int wlen = app_audio_output_write(ladc_mic->tmp_buf, len * hdl->channel * 2); +#else + int wlen = app_audio_output_write(data, len * hdl->channel); + if (wlen != len) { + //printf("wlen:%d-%d",wlen,len); + } +#endif +} + +static u8 mic_demo_idle_query() +{ + return (ladc_mic ? 0 : 1); +} +REGISTER_LP_TARGET(mic_demo_lp_target) = { + .name = "mic_demo", + .is_idle = mic_demo_idle_query, +}; + +void audio_adc_mic_demo(u16 sr) +{ + r_printf("audio_adc_mic_open:%d\n", sr); + ladc_mic = zalloc(sizeof(struct ladc_mic_demo)); + if (ladc_mic) { + audio_adc_mic_open(&ladc_mic->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl); + audio_adc_mic_set_sample_rate(&ladc_mic->mic_ch, sr); + audio_adc_mic_set_gain(&ladc_mic->mic_ch, 20); + audio_adc_mic_set_buffs(&ladc_mic->mic_ch, ladc_mic->adc_buf, LADC_MIC_IRQ_POINTS * 2, LADC_MIC_BUF_NUM); + ladc_mic->adc_output.handler = adc_mic_demo_output; + ladc_mic->adc_output.priv = &adc_hdl; + audio_adc_add_output_handler(&adc_hdl, &ladc_mic->adc_output); + audio_adc_mic_start(&ladc_mic->mic_ch); + + app_audio_output_samplerate_set(sr); + app_audio_output_start(); + } +} + +int audio_adc_mic_init(u16 sr) +{ + //printf("ladc_mic_open:%d\n",sr); + u8 ladc_mic_gain = 5; + ASSERT(ladc_mic == NULL); + ladc_mic = zalloc(sizeof(struct ladc_mic_demo)); + if (ladc_mic) { + audio_adc_mic_open(&ladc_mic->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl); + audio_adc_mic_set_sample_rate(&ladc_mic->mic_ch, sr); + audio_adc_mic_set_gain(&ladc_mic->mic_ch, ladc_mic_gain); + audio_adc_mic_set_buffs(&ladc_mic->mic_ch, ladc_mic->adc_buf, LADC_MIC_IRQ_POINTS * 2, LADC_MIC_BUF_NUM); + audio_adc_mic_start(&ladc_mic->mic_ch); + return 0; + } else { + return -1; + } +} + +void audio_adc_mic_exit(void) +{ + //printf("ladc_mic_close\n"); + if (ladc_mic) { + audio_adc_mic_close(&ladc_mic->mic_ch); + free(ladc_mic); + ladc_mic = NULL; + } +} + +/******************************************************/ +#define LADC_LINEIN_BUF_NUM 2 +#define LADC_LINEIN_CH_NUM 2 +#define LADC_LINEIN_IRQ_POINTS 32//256 +#define LADC_LINEIN_BUFS_SIZE (LADC_LINEIN_CH_NUM * LADC_LINEIN_BUF_NUM * LADC_LINEIN_IRQ_POINTS) +struct audio_adc_var { + struct audio_adc_output_hdl adc_output; + struct audio_adc_ch ch; + s16 adc_buf[LADC_LINEIN_BUFS_SIZE]; //align 4Bytes +}; +struct audio_adc_var *ladc_linein = NULL; + +static void adc_linein_demo_output(void *priv, s16 *data, int len) +{ + struct audio_adc_hdl *hdl = priv; + putchar('.'); + //printf("linein:%x,len:%d,ch:%d",data,len,hdl->channel); + int wlen = app_audio_output_write(data, len * hdl->channel); + if (wlen != len) { + //printf("wlen:%d-%d",wlen,len); + } +} + +void audio_adc_linein_demo(void) +{ + u16 ladc_linein_sr = 44100; + u8 ladc_linein_gain = 5; + r_printf("audio_adc_linein_demo..."); + ladc_linein = zalloc(sizeof(*ladc_linein)); + if (ladc_linein) { + audio_adc_linein_open(&ladc_linein->ch, AUDIO_ADC_LINE0_LR, &adc_hdl); + audio_adc_linein_set_sample_rate(&ladc_linein->ch, ladc_linein_sr); + audio_adc_linein_set_gain(&ladc_linein->ch, ladc_linein_gain); + printf("adc_buf:%x size:%d", ladc_linein->adc_buf, sizeof(ladc_linein->adc_buf)); + audio_adc_set_buffs(&ladc_linein->ch, ladc_linein->adc_buf, LADC_LINEIN_CH_NUM * LADC_LINEIN_IRQ_POINTS * 2, LADC_LINEIN_BUF_NUM); + ladc_linein->adc_output.handler = adc_linein_demo_output; + ladc_linein->adc_output.priv = &adc_hdl; + audio_adc_add_output_handler(&adc_hdl, &ladc_linein->adc_output); + audio_adc_linein_start(&ladc_linein->ch); + + app_audio_output_samplerate_set(ladc_linein_sr); + app_audio_output_start(); + } +} +#if 0 +/* + ************************************************************** + * Audio ADC 多通道使用demo + * 数据结构:LINL LINR MIC LINL LINR MIC ... + * + ************************************************************** + */ +#define LADC_BUF_NUM 2 +#define LADC_CH_NUM 3 +#if TCFG_REVERB_SAMPLERATE_DEFUALT >= 32000 +#define LADC_IRQ_POINTS 48 +#else +#define LADC_IRQ_POINTS 32 +#endif +#define LADC_BUFS_SIZE (LADC_CH_NUM * LADC_BUF_NUM * LADC_IRQ_POINTS) +#define LADC_2_DAC_ENABLE 0 + +/*调试使用,推mic数据/linein数据/mic&line混合数据到dac*/ +#define LADC_MIC_2_DAC BIT(0) +#define LADC_LIN_2_DAC BIT(1) +#define LADC_2_DAC (LADC_MIC_2_DAC | LADC_LIN_2_DAC) + +typedef struct { + struct audio_adc_output_hdl output; + struct audio_adc_ch linein_ch; + struct adc_mic_ch mic_ch; + s16 adc_buf[LADC_BUFS_SIZE]; //align 4Bytes + s16 temp_buf[LADC_IRQ_POINTS * 2]; + u8 mic_gain; + u8 ladc_gain; + u8 mic_en: 2; + u8 ladc_en: 2; + u8 ladc_ch: 3; + cbuffer_t *mic_pcm_cbuf; + void (*mic_pcm_resume)(void *priv); + void *mic_pcm_resume_priv; + cbuffer_t *ladc_pcm_cbuf; + void (*ladc_pcm_resume)(void *priv); + void *ladc_pcm_resume_priv; +} audio_adc_t; +static audio_adc_t *ladc_var = NULL; + +static void audio_adc_output_demo(void *priv, s16 *data, int len) +{ + struct audio_adc_hdl *hdl = priv; + int wlen = 0; + u16 i; + /* putchar('.'); */ + if (ladc_var == NULL) { + return; + } + /* printf("linein:%x,len:%d,ch:%d",data,len,hdl->channel); */ + if (ladc_var->ladc_ch == 2) { + if (ladc_var->mic_en) { + if (ladc_var->mic_pcm_cbuf) { + for (i = 0; i < len / 2; i++) { + ladc_var->temp_buf[i] = data[i * 3 + 2]; + } + wlen = cbuf_write(ladc_var->mic_pcm_cbuf, ladc_var->temp_buf, len); + if (wlen != len) { + putchar('#'); + } + if (ladc_var->mic_pcm_resume) { + ladc_var->mic_pcm_resume(ladc_var->mic_pcm_resume_priv); + } + } + } + if (ladc_var->ladc_en) { + if (ladc_var->ladc_pcm_cbuf) { + for (i = 1; i < len / 2; i++) { + data[i * 2] = data[i * 3]; + data[i * 2 + 1] = data[i * 3 + 1]; + + } + wlen = cbuf_write(ladc_var->ladc_pcm_cbuf, data, len * 2); + if (wlen != len * 2) { + putchar('e'); + } + if (ladc_var->ladc_pcm_resume) { + ladc_var->ladc_pcm_resume(ladc_var->ladc_pcm_resume_priv); + } + } + } + } else { + if (ladc_var->mic_en) { + if (ladc_var->mic_pcm_cbuf) { + for (i = 0; i < len / 2; i++) { + ladc_var->temp_buf[i] = data[i * 2 + 1]; + } + wlen = cbuf_write(ladc_var->mic_pcm_cbuf, ladc_var->temp_buf, len); + if (wlen != len) { + putchar('E'); + } + if (ladc_var->mic_pcm_resume) { + ladc_var->mic_pcm_resume(ladc_var->mic_pcm_resume_priv); + } + } + } + if (ladc_var->ladc_en) { + if (ladc_var->ladc_pcm_cbuf) { + for (i = 1; i < len / 2; i++) { + data[i] = data[i * 2]; + } + wlen = cbuf_write(ladc_var->ladc_pcm_cbuf, data, len); + if (wlen != len) { + putchar('e'); + } + if (ladc_var->ladc_pcm_resume) { + ladc_var->ladc_pcm_resume(ladc_var->ladc_pcm_resume_priv); + } + } + } + } +} + + + +/* void audio_adc_open_demo(void) */ +int audio_three_adc_open(void) +{ + u16 ladc_sr; +#if (defined(TCFG_REVERB_SAMPLERATE_DEFUALT)) + ladc_sr = TCFG_REVERB_SAMPLERATE_DEFUALT; +#else + ladc_sr = 16000; +#endif + u8 mic_gain = 5; + u8 linein_gain = 3; + u8 i, temp; + r_printf("audio_adc_open_demo,sr:%d,mic_gain:%d,linein_gain:%d\n", ladc_sr, mic_gain, linein_gain); + if (ladc_var) { + r_printf("ladc already open \n"); + return 0; + } + ladc_var = zalloc(sizeof(audio_adc_t)); + if (ladc_var) { + temp = (0x3F & TCFG_LINEIN_LR_CH); + printf("linein ch [%d]\n\n\n", temp); + ladc_var->ladc_ch = 0; + for (i = 0; i < 8; i++) { + if ((temp >> i)&BIT(0)) { + ladc_var->ladc_ch++; + } + } + printf("linein ch [%d]\n\n\n", ladc_var->ladc_ch); + if ((ladc_var->ladc_ch > 2) || (ladc_var->ladc_ch == 0)) { + printf(" err ladc ch \n\n"); + free(ladc_var); + return -1; + } + audio_adc_mic_open(&ladc_var->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl); + audio_adc_mic_set_sample_rate(&ladc_var->mic_ch, ladc_sr); + audio_adc_mic_set_gain(&ladc_var->mic_ch, mic_gain); + /* audio_adc_linein_open(&ladc_var->linein_ch, AUDIO_ADC_LINE0_LR, &adc_hdl); */ + audio_adc_linein_open(&ladc_var->linein_ch, TCFG_LINEIN_LR_CH << 2, &adc_hdl); + + audio_adc_linein_set_sample_rate(&ladc_var->linein_ch, ladc_sr); + audio_adc_linein_set_gain(&ladc_var->linein_ch, linein_gain); + + printf("adc_buf_size:%d", sizeof(ladc_var->adc_buf)); + /* audio_adc_set_buffs(&ladc_var->linein_ch, ladc_var->adc_buf, LADC_CH_NUM * LADC_IRQ_POINTS * 2, LADC_BUF_NUM); */ + audio_adc_set_buffs(&ladc_var->linein_ch, ladc_var->adc_buf, (ladc_var->ladc_ch + 1) * LADC_IRQ_POINTS * 2, LADC_BUF_NUM); + ladc_var->output.handler = audio_adc_output_demo; + ladc_var->output.priv = &adc_hdl; + audio_adc_add_output_handler(&adc_hdl, &ladc_var->output); + audio_adc_start(&ladc_var->linein_ch, &ladc_var->mic_ch); + +#if LADC_2_DAC_ENABLE + app_audio_output_samplerate_set(ladc_sr); + app_audio_output_start(); +#endif/*LADC_2_DAC_ENABLE*/ + return 0; + } else { + return -1; + } +} + +void audio_three_adc_close() +{ + if (ladc_var) { + if (ladc_var->mic_en == 0) { + ladc_var->mic_pcm_cbuf = NULL; + } + if (ladc_var->ladc_en == 0) { + ladc_var->ladc_pcm_cbuf = NULL; + } + + if (ladc_var->mic_en || ladc_var->ladc_en) { + return; + } + audio_adc_close(&ladc_var->linein_ch, &ladc_var->mic_ch); + audio_adc_del_output_handler(&adc_hdl, &ladc_var->output); + free(ladc_var); + ladc_var = NULL; + } +} +void three_adc_mic_enable(u8 mark) +{ + if (ladc_var) { + ladc_var->mic_en = mark ? 1 : 0; + } +} + +void three_adc_ladc_enable(u8 mark) +{ + if (ladc_var) { + ladc_var->ladc_en = mark ? 1 : 0; + } +} + +void set_mic_cbuf_hdl(cbuffer_t *mic_cbuf) +{ + if (ladc_var && mic_cbuf) { + ladc_var->mic_pcm_cbuf = mic_cbuf; + } +} +void set_mic_resume_hdl(void (*resume)(void *priv), void *priv) +{ + if (ladc_var) { + ladc_var->mic_pcm_resume = resume; + ladc_var->mic_pcm_resume_priv = priv; + } +} +void set_ladc_cbuf_hdl(cbuffer_t *ladc_cbuf) +{ + if (ladc_var && ladc_cbuf) { + ladc_var->ladc_pcm_cbuf = ladc_cbuf; + } +} +void set_ladc_resume_hdl(void (*resume)(void *priv), void *priv) +{ + if (ladc_var) { + ladc_var->ladc_pcm_resume = resume; + ladc_var->ladc_pcm_resume_priv = priv; + } +} +void three_adc_mic_set_gain(u8 level) +{ + if (ladc_var) { + audio_adc_mic_set_gain(&ladc_var->mic_ch, level); + } +} +#endif +/***********************************************************************************************************/ +#define ADC_BUF_NUM 2 +#define ADC_CH_NUM 2 +#define ADC_IRQ_POINTS 256 +#define ADC_BUFS_SIZE (ADC_BUF_NUM *ADC_CH_NUM* ADC_IRQ_POINTS) + +#if SOUNDCARD_ENABLE +#define ADC_STORE_PCM_SIZE (ADC_BUFS_SIZE * 4) +#else +#define ADC_STORE_PCM_SIZE (ADC_BUFS_SIZE * 4) +#endif + +//#define ADC_STORE_PCM_MAX (ADC_STORE_PCM_SIZE * 80 / 100) + +struct linein_sample_hdl { + OS_SEM sem; + struct audio_adc_ch linein_ch; + struct audio_adc_output_hdl sample_output; +#if SOUNDCARD_ENABLE + s16 adc_buf[4]; +#else + s16 adc_buf[ADC_BUFS_SIZE]; +#endif + /* s16 *store_pcm_buf[ADC_STORE_PCM_SIZE]; */ + s16 *store_pcm_buf; + cbuffer_t cbuf; + void (*resume)(void); + u8 channel_num; + volatile u8 wait_resume; + u16 output_fade_in_gain; + u8 output_fade_in; + u16 sample_rate; + void *audio_track; +}; + +/* struct linein_sample_hdl g_linein_sample_hdl sec(.linein_pcm_mem); */ +/* static s16 linein_store_pcm_buf[ADC_STORE_PCM_SIZE] sec(.linein_pcm_mem); */ + +void linein_sample_set_resume_handler(void *priv, void (*resume)(void)) +{ + struct linein_sample_hdl *linein = (struct linein_sample_hdl *)priv; + + if (linein) { + linein->resume = resume; + } +} + +void fm_inside_output_handler(void *priv, s16 *data, int len) +{ + struct linein_sample_hdl *linein = (struct linein_sample_hdl *)priv; + + if (linein->audio_track) { + audio_local_sample_track_in_period(linein->audio_track, (len >> 1) / linein->channel_num); + } + + int wlen = cbuf_write(&linein->cbuf, data, len); + os_sem_post(&linein->sem); + if (wlen != len) { + putchar('W'); + } + if (linein->resume) { + if (linein->wait_resume) { + linein->wait_resume = 0; + linein->resume(); + } + } +} + +static void linein_sample_output_handler(void *priv, s16 *data, int len) +{ + struct linein_sample_hdl *linein = (struct linein_sample_hdl *)priv; + + + if (linein->audio_track) { + audio_local_sample_track_in_period(linein->audio_track, (len >> 1)); + } + + + if (linein->output_fade_in) + + { + s32 tmp_data; + //printf("fade:%d\n",aec_hdl->output_fade_in_gain); + for (int i = 0; i < len * linein->channel_num / 2; i++) { + tmp_data = data[i]; + data[i] = tmp_data * linein->output_fade_in_gain >> 7; + + } //end of for + + linein->output_fade_in_gain += 2 ; + if (linein->output_fade_in_gain >= 128) { + linein->output_fade_in = 0; + } + + } + + int wlen = cbuf_write(&linein->cbuf, data, len * linein->channel_num); + /* os_sem_post(&linein->sem); */ + if (wlen != len * linein->channel_num) { + putchar('W'); + } + if (linein->resume) { + if (linein->wait_resume) { + linein->wait_resume = 0; + linein->resume(); + } + } +} + +AT(.fm_data_code) +int linein_stream_sample_rate(void *hdl) +{ + struct linein_sample_hdl *linein = (struct linein_sample_hdl *)hdl; + + if (linein->audio_track) { + int sr = audio_local_sample_track_rate(linein->audio_track); + if ((sr < (linein->sample_rate + 200)) && (sr > linein->sample_rate - 200)) { + return sr; + } + printf("linein audio_track reset \n"); + local_irq_disable(); + audio_local_sample_track_close(linein->audio_track); + linein->audio_track = audio_local_sample_track_open(linein->channel_num, linein->sample_rate, 1000); + local_irq_enable(); + } + + return linein->sample_rate; +} + +AT(.fm_data_code) +int linein_sample_read(void *hdl, void *data, int len) +{ + struct linein_sample_hdl *linein = (struct linein_sample_hdl *)hdl; +#if 0 +// no wait + u8 count = 0; +__retry: + if (cbuf_get_data_size(&linein->cbuf) < len) { + local_irq_disable(); + os_sem_set(&linein->sem, 0); + local_irq_enable(); + os_sem_pend(&linein->sem, 2); + if (cbuf_get_data_size(&linein->cbuf) < len) { + if (++count > 4) { + return 0; + } + goto __retry; + } + + } +#endif + int rlen = cbuf_read(&linein->cbuf, data, len); + local_irq_disable(); + if (rlen < len) { + linein->wait_resume = 1; + } + local_irq_enable(); + + return rlen; +} + +AT(.fm_data_code) +int linein_sample_size(void *hdl) +{ + struct linein_sample_hdl *linein = (struct linein_sample_hdl *)hdl; + return cbuf_get_data_size(&linein->cbuf); +} + +AT(.fm_data_code) +int linein_sample_total(void *hdl) +{ + struct linein_sample_hdl *linein = (struct linein_sample_hdl *)hdl; + return linein->cbuf.total_len; +} + +static void linein_sample_resume(void *priv) +{ + struct linein_sample_hdl *linein = priv; + if (linein->resume) { + linein->resume(); + } +} + +void *linein_sample_open(u8 source, u16 sample_rate) +{ + struct linein_sample_hdl *linein = NULL; + + /* linein = &g_linein_sample_hdl;// zalloc(sizeof(struct linein_sample_hdl)); */ + linein = zalloc(sizeof(struct linein_sample_hdl)); + if (!linein) { + return NULL; + } + + memset(linein, 0x0, sizeof(struct linein_sample_hdl)); + + linein->store_pcm_buf = malloc(ADC_STORE_PCM_SIZE); + if (!linein->store_pcm_buf) { + return NULL; + } + + linein->output_fade_in_gain = 0; + + linein->output_fade_in = 1; + if (source != 0xff) { +#if 0 +#ifndef THREE_ADC_ENABLE + audio_adc_linein_open(&linein->linein_ch, (source << 2), &adc_hdl); +#endif +#endif + } + + cbuf_init(&linein->cbuf, linein->store_pcm_buf, ADC_STORE_PCM_SIZE); + os_sem_create(&linein->sem, 0); + if (source == 0xff) { + return linein; + } +#if 0 +#ifndef THREE_ADC_ENABLE + linein->channel_num = adc_hdl.channel; + audio_adc_linein_set_sample_rate(&linein->linein_ch, sample_rate); + audio_adc_linein_set_gain(&linein->linein_ch, 3); + audio_adc_set_buffs(&linein->linein_ch, linein->adc_buf, ADC_CH_NUM * ADC_IRQ_POINTS * 2, ADC_BUF_NUM); + + linein->sample_output.handler = linein_sample_output_handler; + linein->sample_output.priv = linein; + + audio_adc_add_output_handler(&adc_hdl, &linein->sample_output); + audio_adc_linein_start(&linein->linein_ch); +#else + if (audio_three_adc_open() == 0) { + printf("mic adc open success \n"); + set_ladc_cbuf_hdl(&linein->cbuf); + set_ladc_resume_hdl(linein_sample_resume, linein); + three_adc_ladc_enable(1); + } +#endif +#else + + if (audio_linein_open(&linein->linein_ch, sample_rate, 3) == 0) { + linein->sample_output.handler = linein_sample_output_handler; + linein->sample_output.priv = linein; + linein->channel_num = get_audio_linein_ch_num(); + printf("-------------linein->channel_num:%d ----------\n", linein->channel_num); + audio_linein_add_output(&linein->sample_output); + audio_linein_start(&linein->linein_ch); + } +#endif + + linein->sample_rate = sample_rate; + /* linein->audio_track = audio_local_sample_track_open(linein->channel_num, sample_rate, 1000); */ + + + + return linein; +} + +void linein_sample_close(void *hdl) +{ + struct linein_sample_hdl *linein = (struct linein_sample_hdl *)hdl; + + if (!linein) { + return; + } +#if 0 +#ifndef THREE_ADC_ENABLE + audio_adc_linein_close(&linein->linein_ch); + audio_adc_del_output_handler(&adc_hdl, &linein->sample_output); +#else + three_adc_ladc_enable(0); + audio_three_adc_close(); +#endif +#else + audio_linein_close(&linein->linein_ch, &linein->sample_output); +#endif + if (linein->audio_track) { + audio_local_sample_track_close(linein->audio_track); + } + + free(linein->store_pcm_buf); + free(linein); +} + + +void *fm_sample_open(u8 source, u16 sample_rate) +{ + + struct linein_sample_hdl *linein = NULL; + /* linein = &g_linein_sample_hdl;// zalloc(sizeof(struct linein_sample_hdl)); */ + linein = zalloc(sizeof(struct linein_sample_hdl)); + if (!linein) { + return NULL; + } + memset(linein, 0x0, sizeof(struct linein_sample_hdl)); + + linein->store_pcm_buf = zalloc(ADC_STORE_PCM_SIZE); + if (!linein->store_pcm_buf) { + return NULL; + } + + cbuf_init(&linein->cbuf, linein->store_pcm_buf, ADC_STORE_PCM_SIZE); + os_sem_create(&linein->sem, 0); + + linein->sample_rate = sample_rate; + linein->audio_track = audio_local_sample_track_open(linein->channel_num, sample_rate, 1000); + + linein->channel_num = 2; + if (source == 1) { //line1 + audio_adc_linein_open(&linein->linein_ch, AUDIO_ADC_LINE1_LR, &adc_hdl); + } else if (source == 0) { //linein0 + audio_adc_linein_open(&linein->linein_ch, AUDIO_ADC_LINE0_LR, &adc_hdl); + } else if (source == 2) { + audio_adc_linein_open(&linein->linein_ch, AUDIO_ADC_LINE2_LR, &adc_hdl); + } else { + return linein; + } + + audio_adc_linein_set_sample_rate(&linein->linein_ch, sample_rate); + audio_adc_linein_set_gain(&linein->linein_ch, 1); + + audio_adc_set_buffs(&linein->linein_ch, linein->adc_buf, ADC_CH_NUM * ADC_IRQ_POINTS * 2, ADC_BUF_NUM); + + linein->sample_output.handler = linein_sample_output_handler; + linein->sample_output.priv = linein; + + audio_adc_add_output_handler(&adc_hdl, &linein->sample_output); + audio_adc_linein_start(&linein->linein_ch); + return linein; +} + +void fm_sample_close(void *hdl, u8 source) +{ + struct linein_sample_hdl *linein = (struct linein_sample_hdl *)hdl; + + if (!linein) { + return; + } + + if (source <= 2) { + audio_adc_linein_close(&linein->linein_ch); + audio_adc_del_output_handler(&adc_hdl, &linein->sample_output); + } + if (linein->audio_track) { + audio_local_sample_track_close(linein->audio_track); + } + + free(linein->store_pcm_buf); + free(linein); +} + + +////>>>>>>>>>>>>>>record_player api录音接口<<<<<<<<<<<<<<<<<<<<file) { + ret = pcm2file_enc_get_time(rec_hdl->file); + } +// log_d("get ret %d s\n", ret); + return ret; +} + +static void recorder_encode_clock_add(u32 coding_type) +{ + if ((coding_type == AUDIO_CODING_WAV) || (coding_type == AUDIO_CODING_PCM)) { + clock_add(ENC_WAV_CLK); + } else if (coding_type == AUDIO_CODING_G726) { + clock_add(ENC_G726_CLK); + } else if (coding_type == AUDIO_CODING_MP3) { + clock_add(ENC_MP3_CLK); + } + clock_set_cur(); +} + +static void recorder_encode_clock_remove(u32 coding_type) +{ + if ((coding_type == AUDIO_CODING_WAV) || (coding_type == AUDIO_CODING_PCM)) { + clock_remove(ENC_WAV_CLK); + } else if (coding_type == AUDIO_CODING_G726) { + clock_remove(ENC_G726_CLK); + } else if (coding_type == AUDIO_CODING_MP3) { + clock_remove(ENC_MP3_CLK); + } + clock_set_cur(); +} + +void recorder_encode_stop(void) +{ + if (rec_hdl) { + switch (rec_hdl->source) { + case ENCODE_SOURCE_MIX: + break; + case ENCODE_SOURCE_MIC: +#if 0 + audio_adc_mic_close(&rec_hdl->mic_ch); + audio_adc_del_output_handler(&adc_hdl, &rec_hdl->adc_output); +#else + audio_mic_close(&rec_hdl->mic_ch, &rec_hdl->adc_output); +#endif + break; + case ENCODE_SOURCE_LINE0_LR: + case ENCODE_SOURCE_LINE1_LR: + case ENCODE_SOURCE_LINE2_LR: + audio_adc_linein_close(&rec_hdl->linein_ch); + audio_adc_del_output_handler(&adc_hdl, &rec_hdl->adc_output); + break; + default: + break; + } + rec_hdl->magic++; + + rec_hdl->status = 0; + printf("[%s], wait busy\n", __FUNCTION__); + while (rec_hdl->busy) { + os_time_dly(2); + } + printf("[%s], wait busy ok\n", __FUNCTION__); + pcm2file_enc_close(&rec_hdl->file); + recorder_encode_clock_remove(rec_hdl->coding_type); + rec_hdl->file = NULL; + sys_timeout_del(rec_hdl->cut_head_timer); + local_irq_disable(); + free(rec_hdl); + rec_hdl = NULL; + local_irq_enable(); + } +} + +static void recorder_encode_event_handler(struct audio_encoder *hdl, int argc, int *argv) +{ + if (rec_hdl == NULL) { + return ; + } + + struct audio_encoder *enc = get_pcm2file_encoder_hdl(rec_hdl->file); + printf("%s, argv[]:%d, %d , hdl = %x, enc = %x", __FUNCTION__, argv[0], argv[1], hdl, enc); + if ((hdl != NULL) && (hdl == enc)) { + if (rec_hdl->err_callback) { + rec_hdl->err_callback(); + } else { + recorder_encode_stop(); + } + } else { + printf("err enc handle !!\n"); + } +} + + + +static void adc_output_to_enc(void *priv, s16 *data, int len) +{ + /* putchar('o'); */ + if (rec_hdl == NULL) { + return ; + } + + if (rec_hdl->cut_head_flag) { + return ; + } + + switch (rec_hdl->source) { + case ENCODE_SOURCE_MIC: + pcm2file_enc_write_pcm(rec_hdl->file, data, len); + break; + case ENCODE_SOURCE_LINE0_LR: + case ENCODE_SOURCE_LINE1_LR: + case ENCODE_SOURCE_LINE2_LR: + pcm2file_enc_write_pcm(rec_hdl->file, data, len * 2); + break; + default: + break; + } +} + +void record_cut_head_timeout(void *priv) +{ + if (rec_hdl) { + rec_hdl->cut_head_flag = 0; + printf("record_cut_head_timeout \n"); + } +} + +u32 recorder_get_encoding_time() +{ + return recorder_get_enc_time(); +// u32 time_sec = 0; +// if (rec_hdl) { +// time_sec = (timer_get_ms() - rec_hdl->start_sys_tick) / 1000; +// /* printf("rec time sec = %d\n",time_sec); */ +// } +// return time_sec; +} + +///检查录音是否正在进行 +int recorder_is_encoding(void) +{ + if (rec_hdl) { + return 1; + } + return 0; +} + + + +int recorder_encode_start(struct record_file_fmt *f) +{ + struct audio_fmt afmt; + struct record_file_fmt fmt; + u32 cut_tail_size = 0; + struct record_hdl *rec = NULL; + + memcpy((u8 *)&fmt, (u8 *)f, sizeof(struct record_file_fmt)); + if ((fmt.coding_type == AUDIO_CODING_WAV) || fmt.coding_type == AUDIO_CODING_G726) { + fmt.bit_rate = RECORD_PLAYER_DEFULT_ADPCM_BLOCKSIZE; + } else { + fmt.bit_rate = RECORD_PLAYER_DEFULT_BITRATE; + } + afmt.coding_type = fmt.coding_type; + afmt.channel = fmt.channel; + afmt.sample_rate = fmt.sample_rate; + afmt.bit_rate = fmt.bit_rate; + + if (rec_hdl) { + recorder_encode_stop(); + } + + u32 offset = 0; + u32 size = REC_ALIN(sizeof(struct record_hdl), 4); + if ((fmt.source == ENCODE_SOURCE_LINE0_LR) + || (fmt.source == ENCODE_SOURCE_LINE1_LR) + || (fmt.source == ENCODE_SOURCE_LINE2_LR) + ) { + size += REC_ALIN((sizeof(s16) * ADC_BUFS_SIZE), 4); + } + + u8 *buf = zalloc(size); + if (!buf) { + return -1; + } + rec = (struct record_hdl *)(buf + offset); + offset += REC_ALIN(sizeof(struct record_hdl), 4); + + rec->source = fmt.source; + rec->dev = dev_manager_find_spec(fmt.dev, 0); + if (rec->dev == NULL) { + free(rec); + return -1; + } + + rec->sample_rate = fmt.sample_rate; + rec->nchl = fmt.channel; + rec->coding_type = fmt.coding_type; + recorder_encode_clock_add(fmt.coding_type); + rec->file = pcm2file_enc_open(&afmt, fmt.dev, fmt.folder, fmt.filename); + if (!rec->file) { + free(rec); + recorder_encode_clock_remove(fmt.coding_type); + return -1; + } + + rec->cut_head_flag = 1; + rec->cut_head_timer = sys_timeout_add(NULL, record_cut_head_timeout, fmt.cut_head_time); + + if ((fmt.coding_type == AUDIO_CODING_WAV) || (fmt.coding_type == AUDIO_CODING_G726)) { + cut_tail_size = (4 * fmt.sample_rate * fmt.channel) * fmt.cut_tail_time / 1000 / 8; + cut_tail_size = ((cut_tail_size + fmt.bit_rate - 1) / fmt.bit_rate) * fmt.bit_rate; + } else { + cut_tail_size = fmt.bit_rate * fmt.cut_tail_time / 8; + } + + + rec->err_callback = NULL; + if (fmt.err_callback) { + rec->err_callback = fmt.err_callback; + } + + last_enc_file_codeing_type_save(afmt.coding_type); + pcm2file_enc_set_evt_handler(rec->file, recorder_encode_event_handler, rec->magic); + pcm2file_enc_write_file_set_limit(rec->file, cut_tail_size, fmt.limit_size); + pcm2file_enc_start(rec->file); + + switch (rec->source) { + case ENCODE_SOURCE_MIX: + break; + case ENCODE_SOURCE_MIC: +#if 0 + audio_adc_mic_open(&rec->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl); + audio_adc_mic_set_sample_rate(&rec->mic_ch, fmt.sample_rate); + audio_adc_mic_set_gain(&rec->mic_ch, fmt.gain);///调节录音mic的增益 + audio_adc_mic_set_buffs(&rec->mic_ch, rec->adc_buf, LADC_MIC_IRQ_POINTS * 2, LADC_MIC_BUF_NUM); + + rec->adc_output.handler = adc_output_to_enc; + audio_adc_add_output_handler(&adc_hdl, &rec->adc_output); + audio_adc_mic_start(&rec->mic_ch); +#else + rec->adc_output.handler = adc_output_to_enc; + rec->adc_output.priv = rec; + if (audio_mic_open(&rec->mic_ch, fmt.sample_rate, fmt.gain) == 0) { + audio_mic_add_output(&rec->adc_output); + audio_mic_start(&rec->mic_ch); + } + +#endif + break; + case ENCODE_SOURCE_LINE0_LR: + case ENCODE_SOURCE_LINE1_LR: + case ENCODE_SOURCE_LINE2_LR: + rec->adc_buf = (s16 *)(buf + offset); + audio_adc_linein_open(&rec->linein_ch, AUDIO_ADC_LINE0_LR + (rec->source - ENCODE_SOURCE_LINE0_LR), &adc_hdl); + audio_adc_linein_set_sample_rate(&rec->linein_ch, fmt.sample_rate); + audio_adc_linein_set_gain(&rec->linein_ch, fmt.gain); + audio_adc_set_buffs(&rec->linein_ch, rec->adc_buf, ADC_CH_NUM * ADC_IRQ_POINTS * 2, ADC_BUF_NUM); + rec->adc_output.handler = adc_output_to_enc; + rec->adc_output.priv = &adc_hdl; + audio_adc_add_output_handler(&adc_hdl, &rec->adc_output); + audio_adc_linein_start(&rec->linein_ch); + break; + default: + break; + } + + rec->start_sys_tick = timer_get_ms(); + rec_hdl = rec; + + rec_hdl->status = 1; + rec_hdl->busy = 0; + + return 0; +} + +int recorder_userdata_to_enc(s16 *data, int len) +{ + if ((rec_hdl == NULL) || (rec_hdl->status == 0)) { + return 0; + } + rec_hdl->busy = 1; + if (rec_hdl->cut_head_flag) { + rec_hdl->busy = 0; + return 0; + } + int wlen = pcm2file_enc_write_pcm(rec_hdl->file, data, len); + rec_hdl->busy = 0; + return wlen; +} + +void recorder_device_offline_check(char *logo) +{ + if (rec_hdl) { + if (!strcmp(dev_manager_get_logo(rec_hdl->dev), logo)) { + ///当前录音正在使用的设备掉线, 应该停掉录音 + printf("is the recording dev = %s\n", logo); + recorder_encode_stop(); + } + } +} + +#endif// + + + + + + + diff --git a/cpu/br23/audio_enc/audio_enc_recoder.h b/cpu/br23/audio_enc/audio_enc_recoder.h new file mode 100644 index 0000000..ee7bec8 --- /dev/null +++ b/cpu/br23/audio_enc/audio_enc_recoder.h @@ -0,0 +1,35 @@ + +#ifndef _AUDIO_ENC_RECODER_H_ +#define _AUDIO_ENC_RECODER_H_ + +#include "media/audio_encoder.h" + + +int audio_adc_mic_init(u16 sr); +void audio_adc_mic_exit(void); + +void linein_sample_set_resume_handler(void *priv, void (*resume)(void)); +void fm_inside_output_handler(void *priv, s16 *data, int len); +int linein_sample_read(void *hdl, void *data, int len); +int linein_sample_size(void *hdl); +int linein_sample_total(void *hdl); +int linein_stream_sample_rate(void *hdl); +void *linein_sample_open(u8 source, u16 sample_rate); +void linein_sample_close(void *hdl); +void *fm_sample_open(u8 source, u16 sample_rate); +void fm_sample_close(void *hdl, u8 source); + +////>>>>>>>>>>>>>>record_player api录音接口<<<<<<<<<<<<<<<<<<<<mic_output = output_func; + } +} + +void mic_enc_resume(void) +{ + if (mic_enc) { + os_sem_post(&mic_enc->pcm_frame_sem); + } +} + +static int mic_enc_pcm_get(struct audio_encoder *encoder, s16 **frame, u16 frame_len) +{ + int pcm_len = 0; + if (mic_enc == NULL) { + r_printf("mic_enc NULL\n"); + return 0; + } + + + /* putchar('!'); */ + if ((&mic_enc->pcm_in_cbuf)->data_len < frame_len) { + /* putchar('#'); */ + os_sem_set(&mic_enc->pcm_frame_sem, 0); + os_sem_pend(&mic_enc->pcm_frame_sem, 5); + if (mic_enc == NULL) { + printf("mic_enc is NULL\n"); + return 0; + } + } + + pcm_len = cbuf_read(&mic_enc->pcm_in_cbuf, mic_enc->pcm_frame, frame_len); + if (pcm_len != frame_len) { + putchar('L'); + } + /* putchar('D'); */ + + *frame = mic_enc->pcm_frame; + return pcm_len; +} + +static void mic_enc_pcm_put(struct audio_encoder *encoder, s16 *frame) +{ +} + +static const struct audio_enc_input mic_enc_input = { + .fget = mic_enc_pcm_get, + .fput = mic_enc_pcm_put, +}; + +static int mic_enc_probe_handler(struct audio_encoder *encoder) +{ + return 0; +} + + + + +static int mic_enc_output_handler(struct audio_encoder *encoder, u8 *frame, int len) +{ + if (encoder == NULL) { + r_printf("encoder NULL"); + } + wdt_clear(); + /* printf("mic frame len:%d \n",len); */ + if (mic_enc && mic_enc->mic_output) { + mic_enc->mic_output(NULL, frame, len); + } + /* put_buf(frame, 16); */ + return len; +} + +const static struct audio_enc_handler mic_enc_handler = { + .enc_probe = mic_enc_probe_handler, + .enc_output = mic_enc_output_handler, +}; + +static void mic_enc_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ + printf("mic_enc_event_handler:0x%x,%d\n", argv[0], argv[0]); + switch (argv[0]) { + case AUDIO_ENC_EVENT_END: + puts("AUDIO_ENC_EVENT_END\n"); + break; + } +} + + + +static void adc_mic_output_handler(void *priv, s16 *data, int len) +{ + if (mic_enc) { + u16 wlen = cbuf_write(&mic_enc->pcm_in_cbuf, data, len); + if (wlen != len) { + putchar('@'); + } + audio_encoder_resume(&mic_enc->encoder); + mic_enc_resume(); + } +} + + + +#define HIGHT_COMPLEX 0 +#define LOW_COMPLEX (BIT(4)) + + +extern struct audio_adc_hdl adc_hdl; +int audio_mic_enc_open(int (*mic_output)(void *priv, void *buf, int len), u32 code_type, u8 ai_type) +{ + int err; + struct audio_fmt fmt; + + switch (code_type) { + case AUDIO_CODING_OPUS: + //1. quality:bitrate 0:16kbps 1:32kbps 2:64kbps + // quality: MSB_2:(bit7_bit6) format_mode //0:百度_无头. 1:酷狗_eng+range. + // quality:LMSB_2:(bit5_bit4) low_complexity //0:高复杂度,高质量.兼容之前库. 1:低复杂度,低质量. + //2. sample_rate sample_rate=16k ignore + fmt.quality = 0 | ai_type/*| LOW_COMPLEX*/; + fmt.sample_rate = 16000; + fmt.coding_type = AUDIO_CODING_OPUS; + break; + case AUDIO_CODING_SPEEX: + fmt.quality = 5; + fmt.complexity = 2; + fmt.sample_rate = 16000; + fmt.coding_type = AUDIO_CODING_SPEEX; + break; + default: + printf("do not support this type !!!\n"); + return -1; + break; + } + + audio_encoder_task_open(); + if (!mic_enc) { + mic_enc = zalloc(sizeof(*mic_enc)); + if (!mic_enc) { + printf("mic_enc NULL !!!\n"); + } + memset(mic_enc, 0x00, sizeof(*mic_enc)); + } + + mic_enc_output_func_register(mic_output); + cbuf_init(&mic_enc->pcm_in_cbuf, mic_enc->in_cbuf_buf, MIC_ENC_IN_SIZE * 4); + os_sem_create(&mic_enc->pcm_frame_sem, 0); + audio_encoder_open(&mic_enc->encoder, &mic_enc_input, encode_task); + audio_encoder_set_handler(&mic_enc->encoder, &mic_enc_handler); + audio_encoder_set_fmt(&mic_enc->encoder, &fmt); + audio_encoder_set_event_handler(&mic_enc->encoder, mic_enc_event_handler, 0); + audio_encoder_set_output_buffs(&mic_enc->encoder, mic_enc->output_frame, + sizeof(mic_enc->output_frame), 1); + int start_err = audio_encoder_start(&mic_enc->encoder); + +#if MIC_USE_MIC_CHANNEL + fmt.sample_rate = 16000; + audio_adc_mic_open(&mic_enc->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl); + audio_adc_mic_set_sample_rate(&mic_enc->mic_ch, fmt.sample_rate); + app_var.aec_mic_gain = 15; + printf(">>>>>>>>>mic gain:%d \n", app_var.aec_mic_gain); + audio_adc_mic_set_gain(&mic_enc->mic_ch, app_var.aec_mic_gain); + audio_adc_mic_set_buffs(&mic_enc->mic_ch, mic_enc->adc_buf, + ENC_ADC_IRQ_POINTS * 2, ENC_ADC_BUF_NUM); + mic_enc->adc_output.handler = adc_mic_output_handler; + audio_adc_add_output_handler(&adc_hdl, &mic_enc->adc_output); + + + //app_audio_output_samplerate_set(44100); + //app_audio_output_start(); + audio_adc_mic_start(&mic_enc->mic_ch); +#endif + + printf("mic_enc_open ok %d\n", start_err); + + + return 0; +} + + +int audio_mic_enc_close() +{ + if (!mic_enc) { + return -1; + } + printf("audio_mic_enc_close\n"); +#if MIC_USE_MIC_CHANNEL + audio_adc_mic_close(&mic_enc->mic_ch); + audio_adc_del_output_handler(&adc_hdl, &mic_enc->adc_output); +#endif + mic_enc_resume(); + audio_encoder_close(&mic_enc->encoder); + + audio_encoder_task_close(); + + free(mic_enc); + mic_enc = NULL; + + printf("audio_mic_enc_close end\n"); + return 0; +} + +#endif diff --git a/cpu/br23/audio_enc/audio_recorder_mix.c b/cpu/br23/audio_enc/audio_recorder_mix.c new file mode 100644 index 0000000..0fbe05c --- /dev/null +++ b/cpu/br23/audio_enc/audio_recorder_mix.c @@ -0,0 +1,937 @@ +#include "audio_recorder_mix.h" +#include "audio_enc.h" +#include "audio_dec.h" +#include "media/pcm_decoder.h" +#include "btstack/btstack_task.h" +#include "btstack/avctp_user.h" +#include "audio_splicing.h" +#include "app_main.h" +#include "mic_effect.h" +#include "app_task.h" + +#if (RECORDER_MIX_EN) + +#if (TCFG_AEC_ENABLE) +//AEC回声消除使能情况下此配置必须为1, 由于资源局限蓝牙录音在高级音频和通话之前切换会打断正在进行的录音, 要继续录音需要按键再次触发 +#define RECORDER_MIX_BREAK_EN 1 +#else +#define RECORDER_MIX_BREAK_EN 0 +#endif/*TCFG_AEC_ENABLE*/ + +#if (TCFG_MIC_EFFECT_ENABLE && RECORDER_MIX_BREAK_EN) +#error "TCFG_MIC_EFFECT_ENABLE && RECORDER_MIX_BREAK_EN no support!!\n" +#endif + +#define RECORDER_MIX_PCM_INBUF_SIZE (2*1024L)// +#define RECORDER_MIX_PCM_SYNC_INBUF_SIZE (8*1024L)// +#define RECORDER_MIX_MAX_DATA_ONCE (512)//不建议修改 +#define RECORDER_MIX_SAMPLERATE (32000L) +#define RECORDER_MIX_SAMPLERATE_LIMIT(sr) ((sr<16000)?16000:sr) + +#if (TCFG_MIC_EFFECT_ENABLE) +//混响打开之后, 不支持AUDIO_CODING_MP3 +#define RECORDER_MIX_CODING_TYPE AUDIO_CODING_WAV +#else +#define RECORDER_MIX_CODING_TYPE AUDIO_CODING_MP3 +#endif + +#define REC_ALIN(var,al) ((((var)+(al)-1)/(al))*(al)) + +//填0数据流控制句柄 +struct __zero_stream { + struct audio_stream *audio_stream; + struct audio_decoder decoder; + struct audio_res_wait wait; + struct pcm_decoder pcm_dec; + struct audio_mixer_ch mix_ch; + struct audio_mixer_ch rec_mix_ch; +}; + + +//通话上行数据流控制句柄 +struct __pcm_stream { + struct audio_stream *audio_stream; + struct audio_decoder decoder; + struct audio_res_wait wait; + struct pcm_decoder pcm_dec; + struct audio_mixer_ch rec_mix_ch; + cbuffer_t cbuf; + u8 *pcm_buf; + u8 start; + u8 busy; + u8 sync; +}; + +//混合录音总控制句柄 +struct __recorder_mix { + struct __zero_stream *zero; + struct __pcm_stream *pcm; + u8 phone_active; + u8 sync_en; + u16 timer; +}; + +extern u8 mic_effect_get_status(void); + +static u16 pcm_sample_rate = 8000L; +static u8 pcm_channel = 1; +static struct recorder_mix_stream *rec_mix = NULL; +struct __recorder_mix *recorder_hdl = NULL; +#define __this recorder_hdl + +void recorder_mix_pcm_set_info(u16 sample_rate, u8 channel) +{ + printf("[%s], sample_rate = %d, channel = %d\n", __FUNCTION__, sample_rate, channel); + pcm_sample_rate = sample_rate; + pcm_channel = channel; +} + +u32 recorder_mix_pcm_write(u8 *data, u16 len) +{ + u32 wlen = 0; + if (__this) { + if (__this->pcm && __this->pcm->start) { + __this->pcm->busy = 1; + /* putchar('.'); */ + u32 wlen = cbuf_write(&__this->pcm->cbuf, data, len); + if (!wlen) { + putchar('s'); + } + + audio_decoder_resume(&__this->pcm->pcm_dec.decoder); + __this->pcm->busy = 0; + } + } + return len; +} +//*----------------------------------------------------------------------------*/ +/**@brief 通话音频数据混合写接口 + @param + data:输入数据地址 + len:输入数据长度 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +u32 recorder_mix_sco_data_write(u8 *data, u16 len) +{ +#if (TCFG_MIC_EFFECT_ENABLE) + if (mic_effect_get_status()) { + return 0; + } +#endif + return recorder_mix_pcm_write(data, len); +} + + +static int recorder_mix_pcm_data_max(void *priv) +{ + cbuffer_t *cbuf = (cbuffer_t *)priv; + return cbuf->total_len; +} + +static int recorder_mix_pcm_data_size(void *priv) +{ + cbuffer_t *cbuf = (cbuffer_t *)priv; + return cbuf_get_data_size(cbuf); +} + +static int zero_pcm_fread(void *hdl, void *buf, u32 len) +{ + len = len / 2; + memset(buf, 0, len); + /* putchar('A'); */ + return len; +} + +static int zero_pcm_dec_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + struct audio_decoder *decoder = container_of(entry, struct audio_decoder, entry); + struct pcm_decoder *pcm_dec = container_of(decoder, struct pcm_decoder, decoder); + audio_stream_run(&decoder->entry, in); + return decoder->process_len; +} +static void zero_pcm_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ +} +static void zero_pcm_dec_out_stream_resume(void *p) +{ + struct __zero_stream *zero = (struct __zero_stream *)p; + if (zero) { + audio_decoder_resume(&zero->pcm_dec.decoder); + } +} +static int zero_pcm_dec_start(struct __zero_stream *zero) +{ + int err = 0; + if (zero == NULL) { + return -EINVAL; + } + err = pcm_decoder_open(&zero->pcm_dec, &decode_task); + if (err) { + return err; + } + pcm_decoder_set_event_handler(&zero->pcm_dec, zero_pcm_dec_event_handler, 0); + pcm_decoder_set_read_data(&zero->pcm_dec, (void *)zero_pcm_fread, zero); + pcm_decoder_set_data_handler(&zero->pcm_dec, zero_pcm_dec_data_handler); + + audio_mixer_ch_open(&zero->mix_ch, &mixer); + audio_mixer_ch_set_src(&zero->mix_ch, 1, 0); + audio_mixer_ch_set_no_wait(&zero->mix_ch, 1, 10); // 超时自动丢数 + + audio_mixer_ch_open(&zero->rec_mix_ch, &recorder_mixer); + //audio_mixer_ch_set_src(&zero->rec_mix_ch, 1, 0); + audio_mixer_ch_set_no_wait(&zero->rec_mix_ch, 1, 10); // 超时自动丢数 + +// 数据流串联 + struct audio_stream_entry *entries[8] = {NULL}; + u8 entry_cnt = 0; + entries[entry_cnt++] = &zero->pcm_dec.decoder.entry; + entries[entry_cnt++] = &zero->mix_ch.entry; + zero->audio_stream = audio_stream_open(zero, zero_pcm_dec_out_stream_resume); + audio_stream_add_list(zero->audio_stream, entries, entry_cnt); + + audio_stream_add_entry(entries[entry_cnt - 2], &zero->rec_mix_ch.entry); + + err = audio_decoder_start(&zero->pcm_dec.decoder); + if (err == 0) { + printf("zero_pcm_dec_start ok\n"); + } + return err; +} +static void zero_pcm_dec_stop(struct __zero_stream *zero) +{ + printf("[%s, %d] \n\n", __FUNCTION__, __LINE__); + if (zero) { + /* audio_decoder_close(&zero->decoder); */ + /* audio_mixer_ch_close(&zero->mix_ch); */ + pcm_decoder_close(&zero->pcm_dec); + audio_mixer_ch_close(&zero->mix_ch); + audio_mixer_ch_close(&zero->rec_mix_ch); + if (zero->audio_stream) { + audio_stream_close(zero->audio_stream); + zero->audio_stream = NULL; + } + /* audio_decoder_task_del_wait(&decode_task, &zero->wait); */ + } +} +static int zero_pcm_dec_wait_res_handler(struct audio_res_wait *wait, int event) +{ + int err = 0; + struct __zero_stream *zero = container_of(wait, struct __zero_stream, wait); + if (event == AUDIO_RES_GET) { + err = zero_pcm_dec_start(zero); + } else if (event == AUDIO_RES_PUT) { + /* zero_pcm_dec_stop(zero); */ + } + return err; +} +static void zero_pcm_dec_close(struct __zero_stream **hdl) +{ + if (hdl && (*hdl)) { + struct __zero_stream *zero = *hdl; + zero_pcm_dec_stop(zero); + audio_decoder_task_del_wait(&decode_task, &zero->wait); + local_irq_disable(); + free(zero); + *hdl = NULL; + local_irq_enable(); + } +} +static struct __zero_stream *zero_pcm_dec_open(void) +{ + struct __zero_stream *zero = zalloc(sizeof(struct __zero_stream)); + if (zero == NULL) { + return NULL; + } + zero->pcm_dec.ch_num = 2; + zero->pcm_dec.output_ch_num = audio_output_channel_num(); + zero->pcm_dec.output_ch_type = audio_output_channel_type(); +#if (RECORDER_MIX_BREAK_EN == 0) + zero->pcm_dec.sample_rate = RECORDER_MIX_SAMPLERATE; +#else + u16 sr = audio_mixer_get_cur_sample_rate(&recorder_mixer); + zero->pcm_dec.sample_rate = RECORDER_MIX_SAMPLERATE_LIMIT(sr); +#endif + + zero->wait.priority = 0; + zero->wait.preemption = 0; + zero->wait.protect = 1; + zero->wait.handler = zero_pcm_dec_wait_res_handler; + printf("[%s], zero->pcm_dec.sample_rate:%d\n", __FUNCTION__, zero->pcm_dec.sample_rate); + int err = audio_decoder_task_add_wait(&decode_task, &zero->wait); + if (err) { + printf("[%s, %d] fail\n\n", __FUNCTION__, __LINE__); + zero_pcm_dec_close(&zero); + } + return zero; +} + + + + +static int pcm_fread(void *hdl, void *buf, u32 len) +{ + struct __pcm_stream *pcm = (struct __pcm_stream *)hdl; + if (pcm) { + if (pcm->start == 0) { + return 0; + } + if (pcm_channel == 1) { + int rlen = len >> 1; + s16 *tmp = (s16 *)buf; + tmp += (rlen >> 1); + rlen = cbuf_read(&pcm->cbuf, tmp, rlen); + if (rlen) { + pcm_single_to_dual(buf, tmp, rlen); + return len; + } + } else { + return cbuf_read(&pcm->cbuf, buf, len); + } + } + return 0; +} +static int pcm_dec_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + struct audio_decoder *decoder = container_of(entry, struct audio_decoder, entry); + struct pcm_decoder *pcm_dec = container_of(decoder, struct pcm_decoder, decoder); + audio_stream_run(&decoder->entry, in); + return decoder->process_len; +} +static void pcm_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ +} +static void pcm_dec_out_stream_resume(void *p) +{ + struct __pcm_stream *pcm = (struct __pcm_stream *)p; + if (pcm) { + audio_decoder_resume(&pcm->pcm_dec.decoder); + } +} + + +static int pcm_dec_start(struct __pcm_stream *pcm) +{ + int err = 0; + if (pcm == NULL) { + return -EINVAL; + } + err = pcm_decoder_open(&pcm->pcm_dec, &decode_task); + if (err) { + return err; + } + pcm_decoder_set_event_handler(&pcm->pcm_dec, pcm_dec_event_handler, 0); + pcm_decoder_set_read_data(&pcm->pcm_dec, (void *)pcm_fread, pcm); + pcm_decoder_set_data_handler(&pcm->pcm_dec, pcm_dec_data_handler); + + /* audio_mixer_ch_open(&pcm->mix_ch, &mixer); */ + /* audio_mixer_ch_set_src(&pcm->mix_ch, 1, 0); */ + + audio_mixer_ch_open(&pcm->rec_mix_ch, &recorder_mixer); + /* audio_mixer_ch_set_src(&pcm->rec_mix_ch, 1, 0); */ + audio_mixer_ch_set_no_wait(&pcm->rec_mix_ch, 1, 10); + + if (pcm->sync) { + struct audio_mixer_ch_sync_info info = {0}; + info.priv = &pcm->cbuf; + info.get_total = recorder_mix_pcm_data_max; + info.get_size = recorder_mix_pcm_data_size; + audio_mixer_ch_set_sync(&pcm->rec_mix_ch, &info, 1, 1); + } else { + audio_mixer_ch_set_src(&pcm->rec_mix_ch, 1, 0); + } + +// 数据流串联 + struct audio_stream_entry *entries[8] = {NULL}; + u8 entry_cnt = 0; + entries[entry_cnt++] = &pcm->pcm_dec.decoder.entry; + entries[entry_cnt++] = &pcm->rec_mix_ch.entry; + pcm->audio_stream = audio_stream_open(pcm, pcm_dec_out_stream_resume); + audio_stream_add_list(pcm->audio_stream, entries, entry_cnt); + + /* audio_stream_add_entry(entries[entry_cnt - 2], &pcm->rec_mix_ch.entry); */ + + err = audio_decoder_start(&pcm->pcm_dec.decoder); + if (err == 0) { + pcm->start = 1; + printf("pcm_dec_start ok\n"); + } else { + printf("pcm_dec_start fail %d\n", err); + } + return err; +} +static void pcm_dec_stop(struct __pcm_stream *pcm) +{ + printf("[%s, %d] \n\n", __FUNCTION__, __LINE__); + if (pcm) { + pcm->start = 0; + while (pcm->busy) { + os_time_dly(2); + } + printf("[%s, %d] wait busy ok\n\n", __FUNCTION__, __LINE__); + /* audio_decoder_close(&pcm->decoder); */ + /* audio_mixer_ch_close(&pcm->mix_ch); */ + pcm_decoder_close(&pcm->pcm_dec); + /* audio_mixer_ch_close(&pcm->mix_ch); */ + audio_mixer_ch_close(&pcm->rec_mix_ch); + if (pcm->audio_stream) { + audio_stream_close(pcm->audio_stream); + pcm->audio_stream = NULL; + } + /* audio_decoder_task_del_wait(&decode_task, &pcm->wait); */ + } +} +static int pcm_dec_wait_res_handler(struct audio_res_wait *wait, int event) +{ + int err = 0; + struct __pcm_stream *pcm = container_of(wait, struct __pcm_stream, wait); + if (event == AUDIO_RES_GET) { + err = pcm_dec_start(pcm); + } else if (event == AUDIO_RES_PUT) { + /* pcm_dec_stop(pcm); */ + } + return err; +} + + +static void pcm_dec_close(struct __pcm_stream **hdl) +{ + if (hdl && (*hdl)) { + struct __pcm_stream *pcm = *hdl; + pcm_dec_stop(pcm); + audio_decoder_task_del_wait(&decode_task, &pcm->wait); + local_irq_disable(); + free(pcm); + *hdl = NULL; + local_irq_enable(); + } +} + +static struct __pcm_stream *pcm_dec_open(u8 sync) +{ + u32 offset = 0; + u32 size = REC_ALIN(sizeof(struct __pcm_stream), 4); + u32 cbuf_size; + if (sync) { + cbuf_size = RECORDER_MIX_PCM_SYNC_INBUF_SIZE; + } else { + cbuf_size = RECORDER_MIX_PCM_INBUF_SIZE; + } + size += REC_ALIN(cbuf_size, 4); + u8 *buf = zalloc(size); + if (buf == NULL) { + return NULL; + } + struct __pcm_stream *pcm = (struct __pcm_stream *)(buf + offset); + offset += REC_ALIN(sizeof(struct __pcm_stream), 4); + + pcm->pcm_buf = (buf + offset); + offset += REC_ALIN(cbuf_size, 4); + + cbuf_init(&pcm->cbuf, pcm->pcm_buf, cbuf_size); + pcm->sync = sync; + pcm->pcm_dec.ch_num = 2; + pcm->pcm_dec.output_ch_num = audio_output_channel_num(); + pcm->pcm_dec.output_ch_type = audio_output_channel_type(); + pcm->pcm_dec.sample_rate = pcm_sample_rate; + pcm->wait.priority = 0; + pcm->wait.preemption = 0; + pcm->wait.protect = 1; + pcm->wait.handler = pcm_dec_wait_res_handler; + printf("[%s], pcm->pcm_dec.sample_rate:%d\n", __FUNCTION__, pcm->pcm_dec.sample_rate); + int err = audio_decoder_task_add_wait(&decode_task, &pcm->wait); + if (err) { + printf("[%s, %d] fail\n\n", __FUNCTION__, __LINE__); + pcm_dec_close(&pcm); + } + return pcm; +} + +static int recorder_mix_stream_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + struct recorder_mix_stream *hdl = container_of(entry, struct recorder_mix_stream, entry); + if (in->data_len == 0) { + /* printf("data = 0\n"); */ + return 0; + } + /* putchar('$'); */ + + s16 *data = in->data;//(s16 *)(in->data + in->offset / 2); + u16 data_len = in->data_len; + + if (data_len >= RECORDER_MIX_MAX_DATA_ONCE) { + data_len = RECORDER_MIX_MAX_DATA_ONCE; + } + int wlen = recorder_userdata_to_enc(data, data_len); + if (wlen == 0) { + //数据无法输出直接丢掉, 保证数据流能够顺利激活 + return in->data_len; + } + return wlen; +} + +static void recorder_mix_stream_output_data_process_len(struct audio_stream_entry *entry, int len) +{ +} + +static struct recorder_mix_stream *recorder_mix_stream_open(u8 source) +{ + struct recorder_mix_stream *hdl; + hdl = zalloc(sizeof(struct recorder_mix_stream)); + hdl->source = source; + hdl->entry.data_process_len = recorder_mix_stream_output_data_process_len; + hdl->entry.data_handler = recorder_mix_stream_data_handler; + + return hdl; +} + +static void recorder_mix_stream_close(struct recorder_mix_stream *hdl) +{ +} + +//*----------------------------------------------------------------------------*/ +/**@brief 录音数据流节点激活接口 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void recorder_mix_stream_resume(void) +{ + if (rec_mix) { + audio_stream_resume(&rec_mix->entry); + } +} + +static void audio_last_out_stream_resume(void *p) +{ +} + +static u32 recorder_mix_audio_mixer_check_sr(struct audio_mixer *mixer, u32 sr) +{ + u16 o_sr; +#if (RECORDER_MIX_BREAK_EN == 0) + o_sr = RECORDER_MIX_SAMPLERATE; +#else + o_sr = RECORDER_MIX_SAMPLERATE_LIMIT(sr); + ///对于一些特殊采样率的音频, 如FM的37500, 默认变采样为RECORDER_MIX_SAMPLERATE + if (o_sr == 37500) { + o_sr = RECORDER_MIX_SAMPLERATE; + } +#endif + //printf("o_sr ============================= %d\n", o_sr); + return o_sr; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 混合录音mix节点初始化 + @param + mix:通道混合控制句柄 + mix_buf:通道混合后输出的缓存 + buf_size:通道混合输出缓存大小 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void recorder_mix_init(struct audio_mixer *mix, s16 *mix_buf, u16 buf_size) +{ + if (mix == NULL) { + return ; + } + audio_mixer_open(mix); + audio_mixer_set_event_handler(mix, NULL); + audio_mixer_set_check_sr_handler(mix, recorder_mix_audio_mixer_check_sr); + /*初始化mix_buf的长度*/ + audio_mixer_set_output_buf(mix, mix_buf, buf_size); +#ifdef CONFIG_MIXER_CYCLIC + audio_mixer_set_min_len(mix, buf_size / 2); +#endif/*CONFIG_MIXER_CYCLIC*/ + u8 ch_num = audio_output_channel_num(); + audio_mixer_set_channel_num(mix, ch_num); + // 固定采样率输出 + audio_mixer_set_sample_rate(mix, MIXER_SR_SPEC, RECORDER_MIX_SAMPLERATE); + + rec_mix = recorder_mix_stream_open(ENCODE_SOURCE_MIX); + + struct audio_stream_entry *entries[8] = {NULL}; + u8 entry_cnt = 0; + + entries[entry_cnt++] = &mix->entry; + entries[entry_cnt++] = &rec_mix->entry; + + /* mix->stream = audio_stream_open(NULL, audio_last_out_stream_resume); */ + mix->stream = audio_stream_open(mix, audio_mixer_stream_resume); + audio_stream_add_list(mix->stream, entries, entry_cnt); + +} + +static void recorder_mix_err_callback(void) +{ + recorder_mix_stop(); +} + +static void recorder_mix_destroy(struct __recorder_mix **hdl) +{ + if (hdl == NULL || (*hdl == NULL)) { + return ; + } + struct __recorder_mix *recorder = *hdl; + + zero_pcm_dec_close(&recorder->zero); + pcm_dec_close(&recorder->pcm); + + local_irq_disable(); + free(*hdl); + *hdl = NULL; + local_irq_enable(); +} + +static struct __recorder_mix *recorder_mix_creat(void) +{ + struct __recorder_mix *recorder = (struct __recorder_mix *)zalloc(sizeof(struct __recorder_mix)); + return recorder; +} + +static int __recorder_mix_start(struct __recorder_mix *recorder) +{ + struct record_file_fmt fmt = {0}; + /* char logo[] = {"sd0"}; */ //可以指定设备 + char folder[] = {REC_FOLDER_NAME}; //录音文件夹名称 + char filename[] = {"AC69****"}; //录音文件名,不需要加后缀,录音接口会根据编码格式添加后缀 + +#if (TCFG_NOR_REC) + char logo[] = {"rec_nor"}; //外挂flash录音 +#elif (FLASH_INSIDE_REC_ENABLE) + char logo[] = {"rec_sdfile"}; //内置flash录音 +#else + char *logo = dev_manager_get_phy_logo(dev_manager_find_active(0));//普通设备录音,获取最后活动设备 +#endif + + fmt.dev = logo; + fmt.folder = folder; + fmt.filename = filename; + fmt.channel = audio_output_channel_num();//跟mix通道数一致 + u16 sr = audio_mixer_get_cur_sample_rate(&recorder_mixer); +#if (RECORDER_MIX_BREAK_EN == 0) + fmt.coding_type = RECORDER_MIX_CODING_TYPE; + fmt.sample_rate = sr; +#else + if (recorder->phone_active) { + fmt.coding_type = AUDIO_CODING_WAV; + fmt.sample_rate = pcm_sample_rate; + audio_mixer_set_sample_rate(&recorder_mixer, MIXER_SR_SPEC, pcm_sample_rate); + } else { + fmt.coding_type = RECORDER_MIX_CODING_TYPE; + fmt.sample_rate = RECORDER_MIX_SAMPLERATE; + audio_mixer_set_sample_rate(&recorder_mixer, MIXER_SR_SPEC, RECORDER_MIX_SAMPLERATE); + } +#endif/*RECORDER_MIX_BREAK_EN*/ + + printf("[%s], fmt.sample_rate = %d\n", __FUNCTION__, fmt.sample_rate); + fmt.cut_head_time = 300; //录音文件去头时间,单位ms + fmt.cut_tail_time = 300; //录音文件去尾时间,单位ms + fmt.limit_size = 3000; //录音文件大小最小限制, 单位byte + fmt.source = ENCODE_SOURCE_MIX; //录音输入源 + fmt.err_callback = recorder_mix_err_callback; + + int ret = recorder_encode_start(&fmt); + if (ret) { + log_e("[%s] fail !!, dev = %s\n", __FUNCTION__, logo); + } else { + log_e("[%s] succ !!, dev = %s\n", __FUNCTION__, logo); + } + return ret; +} + +static void __recorder_mix_stop(struct __recorder_mix *recorder) +{ + recorder_encode_stop(); +} + +static void __recorder_mix_timer(void *priv) +{ + u32 sec = recorder_get_encoding_time(); + printf("%d\n", sec); +} + +//*----------------------------------------------------------------------------*/ +/**@brief 混合录音开始 + @param + @return 0成功, 非0失败 + @note + 混合录音支持录制内容: + BT sbc(高级音频) + BT sco(蓝牙通话) + FM(内置FM) + Linein(外部音源输入) + 录音参数配置: + 请在__recorder_mix_start函数内部修改参数 + 1、支持设备选择, 如:sd0、udisk0等 + 2、修改文件名称及文件夹名称, 默认文件夹名称为JL_REC,文件名AC69**** + 3、编码格式(资源受限,通话支持adpcm wav) + 4、支持砍头砍尾处理 + 说明: + 1、录音允许打断配置, 通过RECORDER_MIX_BREAK_EN来配置 + 1)录音过程中, 蓝牙音乐播放与通话切换过程, 自动打断, 如需继续录音需要手动启动 + A、该配置支持AEC回声消除,因为回声消除占用cpu及ram资源比较多,所以录音会被打断 + B、编码类型可选, SDK默认是除通话情况下使用wav格式,其他使用mp3 + C、采样率随当前dac的采样率 + 2) 录音过程中, 蓝牙音乐播放与通话切换过程, 不允许打断, 录音继续 + A、该配置不支持AEC回声消除,因为该过程固定了编码采样率, 需要较大的ram及cpu资源 + B、编码类型可以选, 开混响情况下,只可以选择WAV, 不开混响可选MP3 + C、编码采样率固定,SDK默认配置采样率为32000, 不建议高于此采样率 + D、录制混响时,会录制混响+背景音乐 + 2、混合录音支持蓝牙、FM、LINEIN模式, 其他模式不支持 +*/ +/*----------------------------------------------------------------------------*/ +int recorder_mix_start(void) +{ + if (__this) { + recorder_mix_stop(); + } + + u8 sync_en = 0; + u8 pcm_en = 0; + u8 zero_pcm_en = 0; + u8 phone_active = 0; + u8 cur_app = app_get_curr_task(); + + switch (cur_app) { + case APP_BT_TASK: + sync_en = 0; + zero_pcm_en = 1; + break; + case APP_FM_TASK: + sync_en = 1; + zero_pcm_en = 1; + break; + case APP_LINEIN_TASK: + sync_en = 0; + zero_pcm_en = 1; + break; + default: + log_e("cur app not support recorder mix\n"); + return -1; + } + u8 call_status = get_call_status(); + +#if (RECORDER_MIX_BREAK_EN) + if ((call_status != BT_CALL_HANGUP) && (call_status == BT_CALL_INCOMING)) { + printf("phone incomming, no active, no record!!!!\n"); + return -1; + } + + if (app_var.siri_stu) { + printf("siri active, no record!!!\n"); + return -1; + } + + if (call_status != BT_CALL_HANGUP) { + sync_en = 0; + } +#endif/*RECORDER_MIX_BREAK_EN*/ + + if (call_status != BT_CALL_HANGUP) { + phone_active = 1; + } + + if (phone_active +#if (TCFG_MIC_EFFECT_ENABLE) + || mic_effect_get_status() +#endif/*TCFG_MIC_EFFECT_ENABLE*/ + ) { + pcm_en = 1; + } + + struct __recorder_mix *recorder = recorder_mix_creat(); + if (recorder == NULL) { + return -1; + } + + recorder->phone_active = phone_active; + recorder->sync_en = sync_en; + + if (zero_pcm_en) { + //启动时间轴解码(填充0), 用于确保混合录音始终有数据写入编码器 + recorder->zero = zero_pcm_dec_open(); + if (recorder->zero == NULL) { + recorder_mix_destroy(&recorder); + return -1; + } + } + + if (pcm_en) { + recorder->pcm = pcm_dec_open(recorder->sync_en); + if (recorder->pcm == NULL) { + recorder_mix_destroy(&recorder); + return -1; + } + } + + int ret = __recorder_mix_start(recorder); + if (ret) { + recorder_mix_destroy(&recorder); + return -1; + } + + + local_irq_disable(); + __this = recorder; + local_irq_enable(); + + __this->timer = sys_timer_add((void *)__this, __recorder_mix_timer, 1000); + + printf("[%s] start ok\n", __FUNCTION__); + printf("pcm_en = %d\n", pcm_en); + printf("zero_pcm_en = %d\n", zero_pcm_en); + printf("sync_en = %d\n", sync_en); + printf("phone_active = %d\n", phone_active); + + mem_stats(); + + return 0; +} + +//*----------------------------------------------------------------------------*/ +/**@brief 混合录音停止 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void recorder_mix_stop(void) +{ + if (__this && __this->timer) { + sys_timer_del(__this->timer); + } + __recorder_mix_stop(__this); + recorder_mix_destroy(&__this); + printf("[%s] stop ok\n", __FUNCTION__); + + mem_stats(); +} +//*----------------------------------------------------------------------------*/ +/**@brief 获取混合录音状态 + @param + @return + 1:正在录音状态 + 0:录音停止状态 + @note +*/ +/*----------------------------------------------------------------------------*/ +int recorder_mix_get_status(void) +{ + return (__this ? 1 : 0); +} + +u16 recorder_mix_get_samplerate(void) +{ + return RECORDER_MIX_SAMPLERATE; +} + +u32 recorder_mix_get_coding_type(void) +{ + return RECORDER_MIX_CODING_TYPE; +} + +void recorder_mix_call_status_change(u8 active) +{ + printf("[%s] = %d\n", __FUNCTION__, active); + if (active) { + if (__this && (__this->phone_active == 0)) { +#if (RECORDER_MIX_BREAK_EN) + printf("phone rec unactive !!, stop cur rec first\n"); + recorder_mix_stop(); +#else + if (__this->pcm == NULL) { + __this->pcm = pcm_dec_open(__this->sync_en); + } +#endif/*RECORDER_MIX_BREAK_EN*/ + } + } else { + if (__this) { +#if (RECORDER_MIX_BREAK_EN == 0) + if (__this->pcm) { +#if (TCFG_MIC_EFFECT_ENABLE) + if (mic_effect_get_status() == 0) +#endif + { + pcm_dec_close(&__this->pcm); + } + } +#endif/*RECORDER_MIX_BREAK_EN*/ + } + } +} + +void recorder_mix_bt_status_event(struct bt_event *e) +{ + switch (e->event) { + case BT_STATUS_PHONE_INCOME: + break; + case BT_STATUS_PHONE_OUT: + break; + case BT_STATUS_PHONE_ACTIVE: + break; + case BT_STATUS_PHONE_HANGUP: +#if (RECORDER_MIX_BREAK_EN) + recorder_mix_stop(); +#endif + break; + case BT_STATUS_PHONE_NUMBER: + break; + case BT_STATUS_SCO_STATUS_CHANGE: + if (e->value != 0xff) { + //电话激活, 先停止当前录音 +#if (RECORDER_MIX_BREAK_EN) + recorder_mix_stop(); +#endif + } else { + + } + break; + case BT_STATUS_VOICE_RECOGNITION: + if (e->value) { //如果是siri语音状态,停止录音 +#if (RECORDER_MIX_BREAK_EN) + recorder_mix_stop(); +#endif + } + break; + default: + break; + } +} + +int recorder_mix_pcm_stream_open(u16 sample_rate, u8 channel) +{ + recorder_mix_pcm_set_info(sample_rate, channel); + if (__this && (__this->pcm == NULL)) { + __this->pcm = pcm_dec_open(__this->sync_en); + if (__this->pcm) { + return 0; + } + } + return -1; +} + +void recorder_mix_pcm_stream_close(void) +{ + if (__this && __this->pcm) { + if (get_call_status() != BT_CALL_HANGUP) { + ///如果通话还在,不要关闭pcm解码,因为通话录音还要使用 + return ; + } + pcm_dec_close(&__this->pcm); + } +} + +#endif//RECORDER_MIX_EN + + diff --git a/cpu/br23/audio_enc/audio_recorder_mix.h b/cpu/br23/audio_enc/audio_recorder_mix.h new file mode 100644 index 0000000..6e6022a --- /dev/null +++ b/cpu/br23/audio_enc/audio_recorder_mix.h @@ -0,0 +1,31 @@ +#ifndef _AUDIO_RECORDER_MIX_H_ +#define _AUDIO_RECORDER_MIX_H_ + +#include "system/includes.h" +#include "media/includes.h" + + +struct recorder_mix_stream { + u8 source; + struct audio_stream_entry entry; +}; + +void recorder_mix_pcm_set_info(u16 sample_rate, u8 channel); +u32 recorder_mix_pcm_write(u8 *data, u16 len); +u32 recorder_mix_pcm_write(u8 *data, u16 len); +u32 recorder_mix_sco_data_write(u8 *data, u16 len); +void recorder_mix_stream_resume(void); +void recorder_mix_init(struct audio_mixer *mixer, s16 *mix_buf, u16 buf_size); +int recorder_mix_start(void); +void recorder_mix_stop(void); +int recorder_mix_get_status(void); +u16 recorder_mix_get_samplerate(void); +u32 recorder_mix_get_coding_type(void); +void recorder_mix_bt_status(u8 status); +void recorder_mix_call_status_change(u8 active); +void recorder_mix_bt_status_event(struct bt_event *e); +int recorder_mix_pcm_stream_open(u16 sample_rate, u8 channel); +void recorder_mix_pcm_stream_close(void); + +#endif//_AUDIO_RECORDER_MIX_H_ + diff --git a/cpu/br23/audio_enc/audio_sbc_codec.c b/cpu/br23/audio_enc/audio_sbc_codec.c new file mode 100644 index 0000000..db6cf84 --- /dev/null +++ b/cpu/br23/audio_enc/audio_sbc_codec.c @@ -0,0 +1,1031 @@ +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "aec_user.h" +#include "asm/audio_src.h" +#include "audio_enc.h" +#include "app_main.h" +#include "btstack/avctp_user.h" +#include "audio_digital_vol.h" +#include "audio_sbc_codec.h" +#include "clock_cfg.h" +#include "media/pcm_decoder.h" +#include "audio_dec.h" + + +#define BT_USE_PCM_DEC 0 //多加一个解码,会多耗资源,时钟也会增加,用来解决完全切歌的时候出现杂音的问题 + +#define SBC_RESERVED_LAST_PCM 1 //淡入淡出功能,耗资源很小,可以解决正常速度切歌杂音,但是快速连续切歌会有杂音 + +enum { + SBC_RUN_STEP_NOR = 0, + SBC_RUN_STEP_WAIT_STOP, + SBC_RUN_STEP_STOP, + SBC_RUN_STEP_WAIT_NOR, +}; + + + + + +extern struct audio_encoder_task *encode_task; +//static struct audio_encoder_task *encode_task = NULL; +#define SBC_ENC_WRITING BIT(1) +#define SBC_ENC_START BIT(2) +#define SBC_ENC_WAKEUP_SEND BIT(3) /*减少唤醒问题*/ +#define SBC_ENC_PCM_MUTE_DATA BIT(4) /*发一包静音数据*/ + +static u8 sbc_buf_flag = 0; +#define ESCO_ADC_BUF_NUM 2 +#define ESCO_ADC_IRQ_POINTS 256 +#define ESCO_ADC_BUFS_SIZE (ESCO_ADC_BUF_NUM * ESCO_ADC_IRQ_POINTS) + +#define SBC_USE_MIC_CHANNEL 0 +#define SBC_ENC_PACK_ENABLE 0 /*sbc数据包封装*/ +#define SBC_ENC_IN_SIZE 512 +#define SBC_ENC_OUT_SIZE 256 + +#define SBC_ENC_IN_CBUF_SIZE (SBC_ENC_IN_SIZE * 8) +#define SBC_ENC_OUT_CBUF_SIZE (SBC_ENC_OUT_SIZE * 8) + +struct sbc_enc_hdl { + struct audio_encoder encoder; + OS_SEM pcm_frame_sem; + u8 output_frame[SBC_ENC_OUT_SIZE]; + u8 pcm_frame[SBC_ENC_IN_SIZE]; + u8 frame_size; + u8 backup_digital_vol; + cbuffer_t output_cbuf; + u8 out_cbuf_buf[SBC_ENC_OUT_CBUF_SIZE]; + cbuffer_t pcm_in_cbuf;/*要注意要跟DAC的buf大小一致*/ + u8 in_cbuf_buf[SBC_ENC_IN_CBUF_SIZE]; +#if SBC_ENC_PACK_ENABLE + u16 cp_type; + u16 packet_head_sn; +#endif + int mute_data_send_timer; +#if SBC_USE_MIC_CHANNEL + struct audio_adc_output_hdl adc_output; + struct adc_mic_ch mic_ch; + s16 adc_buf[ESCO_ADC_BUFS_SIZE]; //align 4Bytes +#endif + +#if SBC_RESERVED_LAST_PCM + u8 run_step; + u8 run_cnt; + u8 in_cnt; + OS_SEM run_sem; +#endif + + + +#if BT_USE_PCM_DEC + struct audio_mixer_ch mix_ch; + struct audio_res_wait wait; + struct pcm_decoder pcm_dec; // pcm解码句柄 + struct audio_stream *audio_stream; // 音频流 +#endif + + /* dvol_handle *dvol; */ +}; +static struct sbc_enc_hdl *sbc_enc = NULL; + +__attribute__((weak)) +void audio_sbc_enc_inbuf_resume(void) +{ + ; +} + +__attribute__((weak)) +void audio_sbc_enc_open_exit(void) +{ + ; +} + +__attribute__((weak)) +void audio_sbc_enc_close_enter(void) +{ + ; +} + +short const tsin_441k[441] = { + 0x0000, 0x122d, 0x23fb, 0x350f, 0x450f, 0x53aa, 0x6092, 0x6b85, 0x744b, 0x7ab5, 0x7ea2, 0x7fff, 0x7ec3, 0x7af6, 0x74ab, 0x6c03, + 0x612a, 0x545a, 0x45d4, 0x35e3, 0x24db, 0x1314, 0x00e9, 0xeeba, 0xdce5, 0xcbc6, 0xbbb6, 0xad08, 0xa008, 0x94fa, 0x8c18, 0x858f, + 0x8181, 0x8003, 0x811d, 0x84ca, 0x8af5, 0x9380, 0x9e3e, 0xaaf7, 0xb969, 0xc94a, 0xda46, 0xec06, 0xfe2d, 0x105e, 0x223a, 0x3365, + 0x4385, 0x5246, 0x5f5d, 0x6a85, 0x7384, 0x7a2d, 0x7e5b, 0x7ffa, 0x7f01, 0x7b75, 0x7568, 0x6cfb, 0x6258, 0x55b7, 0x4759, 0x3789, + 0x2699, 0x14e1, 0x02bc, 0xf089, 0xdea7, 0xcd71, 0xbd42, 0xae6d, 0xa13f, 0x95fd, 0x8ce1, 0x861a, 0x81cb, 0x800b, 0x80e3, 0x844e, + 0x8a3c, 0x928c, 0x9d13, 0xa99c, 0xb7e6, 0xc7a5, 0xd889, 0xea39, 0xfc5a, 0x0e8f, 0x2077, 0x31b8, 0x41f6, 0x50de, 0x5e23, 0x697f, + 0x72b8, 0x799e, 0x7e0d, 0x7fee, 0x7f37, 0x7bed, 0x761f, 0x6ded, 0x6380, 0x570f, 0x48db, 0x392c, 0x2855, 0x16ad, 0x048f, 0xf259, + 0xe06b, 0xcf20, 0xbed2, 0xafd7, 0xa27c, 0x9705, 0x8db0, 0x86ab, 0x821c, 0x801a, 0x80b0, 0x83da, 0x8988, 0x919c, 0x9bee, 0xa846, + 0xb666, 0xc603, 0xd6ce, 0xe86e, 0xfa88, 0x0cbf, 0x1eb3, 0x3008, 0x4064, 0x4f73, 0x5ce4, 0x6874, 0x71e6, 0x790a, 0x7db9, 0x7fdc, + 0x7f68, 0x7c5e, 0x76d0, 0x6ed9, 0x64a3, 0x5863, 0x4a59, 0x3acc, 0x2a0f, 0x1878, 0x0661, 0xf42a, 0xe230, 0xd0d0, 0xc066, 0xb145, + 0xa3bd, 0x9813, 0x8e85, 0x8743, 0x8274, 0x8030, 0x8083, 0x836b, 0x88da, 0x90b3, 0x9acd, 0xa6f5, 0xb4ea, 0xc465, 0xd515, 0xe6a3, + 0xf8b6, 0x0aee, 0x1ced, 0x2e56, 0x3ecf, 0x4e02, 0x5ba1, 0x6764, 0x710e, 0x786f, 0x7d5e, 0x7fc3, 0x7f91, 0x7cc9, 0x777a, 0x6fc0, + 0x65c1, 0x59b3, 0x4bd3, 0x3c6a, 0x2bc7, 0x1a41, 0x0833, 0xf5fb, 0xe3f6, 0xd283, 0xc1fc, 0xb2b7, 0xa503, 0x9926, 0x8f60, 0x87e1, + 0x82d2, 0x804c, 0x805d, 0x8303, 0x8833, 0x8fcf, 0x99b2, 0xa5a8, 0xb372, 0xc2c9, 0xd35e, 0xe4da, 0xf6e4, 0x091c, 0x1b26, 0x2ca2, + 0x3d37, 0x4c8e, 0x5a58, 0x664e, 0x7031, 0x77cd, 0x7cfd, 0x7fa3, 0x7fb4, 0x7d2e, 0x781f, 0x70a0, 0x66da, 0x5afd, 0x4d49, 0x3e04, + 0x2d7d, 0x1c0a, 0x0a05, 0xf7cd, 0xe5bf, 0xd439, 0xc396, 0xb42d, 0xa64d, 0x9a3f, 0x9040, 0x8886, 0x8337, 0x806f, 0x803d, 0x82a2, + 0x8791, 0x8ef2, 0x989c, 0xa45f, 0xb1fe, 0xc131, 0xd1aa, 0xe313, 0xf512, 0x074a, 0x195d, 0x2aeb, 0x3b9b, 0x4b16, 0x590b, 0x6533, + 0x6f4d, 0x7726, 0x7c95, 0x7f7d, 0x7fd0, 0x7d8c, 0x78bd, 0x717b, 0x67ed, 0x5c43, 0x4ebb, 0x3f9a, 0x2f30, 0x1dd0, 0x0bd6, 0xf99f, + 0xe788, 0xd5f1, 0xc534, 0xb5a7, 0xa79d, 0x9b5d, 0x9127, 0x8930, 0x83a2, 0x8098, 0x8024, 0x8247, 0x86f6, 0x8e1a, 0x978c, 0xa31c, + 0xb08d, 0xbf9c, 0xcff8, 0xe14d, 0xf341, 0x0578, 0x1792, 0x2932, 0x39fd, 0x499a, 0x57ba, 0x6412, 0x6e64, 0x7678, 0x7c26, 0x7f50, + 0x7fe6, 0x7de4, 0x7955, 0x7250, 0x68fb, 0x5d84, 0x5029, 0x412e, 0x30e0, 0x1f95, 0x0da7, 0xfb71, 0xe953, 0xd7ab, 0xc6d4, 0xb725, + 0xa8f1, 0x9c80, 0x9213, 0x89e1, 0x8413, 0x80c9, 0x8012, 0x81f3, 0x8662, 0x8d48, 0x9681, 0xa1dd, 0xaf22, 0xbe0a, 0xce48, 0xdf89, + 0xf171, 0x03a6, 0x15c7, 0x2777, 0x385b, 0x481a, 0x5664, 0x62ed, 0x6d74, 0x75c4, 0x7bb2, 0x7f1d, 0x7ff5, 0x7e35, 0x79e6, 0x731f, + 0x6a03, 0x5ec1, 0x5193, 0x42be, 0x328f, 0x2159, 0x0f77, 0xfd44, 0xeb1f, 0xd967, 0xc877, 0xb8a7, 0xaa49, 0x9da8, 0x9305, 0x8a98, + 0x848b, 0x80ff, 0x8006, 0x81a5, 0x85d3, 0x8c7c, 0x957b, 0xa0a3, 0xadba, 0xbc7b, 0xcc9b, 0xddc6, 0xefa2, 0x01d3, 0x13fa, 0x25ba, + 0x36b6, 0x4697, 0x5509, 0x61c2, 0x6c80, 0x750b, 0x7b36, 0x7ee3, 0x7ffd, 0x7e7f, 0x7a71, 0x73e8, 0x6b06, 0x5ff8, 0x52f8, 0x444a, + 0x343a, 0x231b, 0x1146, 0xff17, 0xecec, 0xdb25, 0xca1d, 0xba2c, 0xaba6, 0x9ed6, 0x93fd, 0x8b55, 0x850a, 0x813d, 0x8001, 0x815e, + 0x854b, 0x8bb5, 0x947b, 0x9f6e, 0xac56, 0xbaf1, 0xcaf1, 0xdc05, 0xedd3 +}; +static u16 tx_s_cnt = 0; +static int get_sine_data(u16 *s_cnt, s16 *data, u16 points, u8 ch) +{ + while (points--) { + if (*s_cnt >= 441) { + *s_cnt = 0; + } + *data++ = tsin_441k[*s_cnt]; + if (ch == 2) { + *data++ = tsin_441k[*s_cnt]; + } + (*s_cnt)++; + } + return 0; +} + +#if SBC_RESERVED_LAST_PCM +static void sbc_enc_pcm_data_fade_out(s16 *data, int len) +{ + u16 samples = len >> 1; + int down_step = (32767 + samples - 1) / samples + 1; + int value = 32767; + + for (int i = 0; i < samples; i++) { + if (value > down_step) { + value -= down_step; + } else { + value = 0; + } + s32 tmp = *data; + *data++ = tmp * value / 32767; + } +} +static void sbc_enc_pcm_data_fade_in(s16 *data, int len) +{ + + u16 samples = len >> 1; + int down_step = (32767 + samples - 1) / samples + 1; + int value = 0; + + for (int i = 0; i < samples; i++) { + if (value + down_step < 32767) { + value += down_step; + } else { + value = 32767; + } + s32 tmp = *data; + *data++ = tmp * value / 32767; + } + +} + +#endif /* SBC_RESERVED_LAST_PCM */ + + + +static void sbc_send_mute_data() +{ + sbc_buf_flag |= SBC_ENC_PCM_MUTE_DATA; + audio_encoder_resume(&sbc_enc->encoder); +} +static int sbc_enc_pcm_get(struct audio_encoder *encoder, s16 **frame, u16 frame_len) +{ + u8 read_flag = 1; + int pcm_len = 0; + if (encoder == NULL) { + r_printf("encoder NULL"); + } + struct sbc_enc_hdl *enc = container_of(encoder, struct sbc_enc_hdl, encoder); + + if (enc == NULL) { + r_printf("enc NULL"); + } + int limit_size = SBC_ENC_IN_SIZE; +#if SBC_RESERVED_LAST_PCM + if (enc->run_step == SBC_RUN_STEP_NOR) { + limit_size += SBC_ENC_IN_SIZE; + } +#endif + + + if (cbuf_get_data_size(&enc->pcm_in_cbuf) < limit_size) { + if (!(sbc_buf_flag & SBC_ENC_PCM_MUTE_DATA)) { +#if SBC_RESERVED_LAST_PCM + if (enc->run_step == SBC_RUN_STEP_STOP) { + if (enc->run_cnt) { + enc->run_cnt--; + if (enc->run_cnt == 0) { + os_sem_post(&enc->run_sem); + } + memset(enc->pcm_frame, 0, SBC_ENC_IN_SIZE); + *frame = enc->pcm_frame; + return SBC_ENC_IN_SIZE; + } + } +#endif + + + + return 0; + } else { + read_flag = 0; + } + } + if (read_flag) { + pcm_len = cbuf_read(&enc->pcm_in_cbuf, enc->pcm_frame, SBC_ENC_IN_SIZE); + + // get_sine_data(&tx_s_cnt, enc->pcm_frame, pcm_len >> 2, 2); + +#if SBC_RESERVED_LAST_PCM + if (pcm_len && enc->run_step) { + local_irq_disable(); + if (enc->run_step == SBC_RUN_STEP_WAIT_STOP) { + enc->run_step = SBC_RUN_STEP_STOP; + enc->run_cnt = 200; // 发射每次读取5包,至少保证发射一帧 + sbc_enc_pcm_data_fade_out(enc->pcm_frame, pcm_len); + } else if (enc->run_step == SBC_RUN_STEP_STOP) { + memset(enc->pcm_frame, 0, pcm_len); + if (enc->run_cnt) { + enc->run_cnt--; + if (enc->run_cnt == 0) { + os_sem_post(&enc->run_sem); + } + } + } else if (sbc_enc->run_step == SBC_RUN_STEP_WAIT_NOR) { + + if (sbc_enc->in_cnt > 0) { + sbc_enc->in_cnt--; + memset(enc->pcm_frame, 0, pcm_len); + + } else { + sbc_enc->run_step = SBC_RUN_STEP_NOR; + sbc_enc_pcm_data_fade_in(enc->pcm_frame, pcm_len); + + } + } + + local_irq_enable(); + } else { + } +#endif + + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) + audio_stream_resume(&sbc_emitter.entry); +#endif + } else { + putchar('h'); + memset(enc->pcm_frame, 0, SBC_ENC_IN_SIZE); + pcm_len = SBC_ENC_IN_SIZE; + } + if (pcm_len != SBC_ENC_IN_SIZE) { + putchar('L'); + } + + *frame = enc->pcm_frame; + return pcm_len; +} + +static void sbc_enc_pcm_put(struct audio_encoder *encoder, s16 *frame) +{ +} + +static const struct audio_enc_input sbc_enc_input = { + .fget = sbc_enc_pcm_get, + .fput = sbc_enc_pcm_put, +}; + +static int sbc_enc_probe_handler(struct audio_encoder *encoder) +{ + return 0; +} + + +#if BT_USE_PCM_DEC + +static int pcm_fread(void *hdl, void *buf, int len) +{ + len = len / 2; + memset(buf, 0, len); + return len; +} +static int pcm_dec_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + struct audio_decoder *decoder = container_of(entry, struct audio_decoder, entry); + struct pcm_decoder *pcm_dec = container_of(decoder, struct pcm_decoder, decoder); + struct sbc_enc_hdl *dec = container_of(pcm_dec, struct sbc_enc_hdl, pcm_dec); + audio_stream_run(&decoder->entry, in); + /* audio_mixer_ch_pause(&dec->mix_ch, 0); */ + return decoder->process_len; +} +static void pcm_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ +} +static void dec_out_stream_resume(void *p) +{ + struct sbc_enc_hdl *dec = (struct sbc_enc_hdl *)p; + + audio_decoder_resume(&dec->pcm_dec.decoder); +} +static int pcm_dec_start(struct sbc_enc_hdl *stream) +{ + int err = 0; + if (stream == NULL) { + return -EINVAL; + } + err = pcm_decoder_open(&stream->pcm_dec, &decode_task); + if (err) { + return err; + } + pcm_decoder_set_event_handler(&stream->pcm_dec, pcm_dec_event_handler, 0); + pcm_decoder_set_read_data(&stream->pcm_dec, pcm_fread, stream); + pcm_decoder_set_data_handler(&stream->pcm_dec, pcm_dec_data_handler); + + audio_mixer_ch_open(&stream->mix_ch, &mixer); + audio_mixer_ch_set_src(&stream->mix_ch, 0, 0); + struct audio_stream_entry *entries[8] = {NULL}; + u8 entry_cnt = 0; + entries[entry_cnt++] = &stream->pcm_dec.decoder.entry; + entries[entry_cnt++] = &stream->mix_ch.entry; + stream->audio_stream = audio_stream_open(stream, dec_out_stream_resume); + audio_stream_add_list(stream->audio_stream, entries, entry_cnt); + + audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); + err = audio_decoder_start(&stream->pcm_dec.decoder); + if (err == 0) { + printf("pcm_dec_start ok\n"); + } + return err; +} +static void pcm_dec_stop(struct sbc_enc_hdl *stream) +{ + printf("mic stream dec stop \n\n"); + if (stream) { + + pcm_decoder_close(&stream->pcm_dec); + audio_mixer_ch_close(&stream->mix_ch); + if (stream->audio_stream) { + audio_stream_close(stream->audio_stream); + stream->audio_stream = NULL; + } + } +} + +static int pcmdec_wait_res_handler(struct audio_res_wait *wait, int event) +{ + int err = 0; + struct sbc_enc_hdl *stream = container_of(wait, struct sbc_enc_hdl, wait); + if (event == AUDIO_RES_GET) { + err = pcm_dec_start(stream); + } else if (event == AUDIO_RES_PUT) { + /* pcm_dec_stop(stream); */ + } + + return err; +} +static int pcm_dec_open(struct sbc_enc_hdl *stream, struct audio_fmt *pfmt) +{ + stream->pcm_dec.output_ch_num = stream->pcm_dec.ch_num = pfmt->channel; + stream->pcm_dec.sample_rate = pfmt->sample_rate; + if (stream->pcm_dec.output_ch_num == 2) { + stream->pcm_dec.output_ch_type = AUDIO_CH_LR; + } else { + stream->pcm_dec.output_ch_type = AUDIO_CH_DIFF; + } + + stream->wait.priority = 0; + stream->wait.preemption = 0; + stream->wait.protect = 1; + stream->wait.handler = pcmdec_wait_res_handler; + return audio_decoder_task_add_wait(&decode_task, &stream->wait); +} + +static void pcm_dec_close(struct sbc_enc_hdl *stream) +{ + pcm_dec_stop(stream); + audio_decoder_task_del_wait(&decode_task, &stream->wait); +} + +#endif /*BT_USE_PCM_DEC*/ + + + + + + + + + + + + +#if SBC_ENC_PACK_ENABLE +/* + struct Media_Playload_Header { + u8 Version: 2; + u8 Padding: 1; + u8 Extension: 1; + u8 CSRC_Count: 4; + u8 Marker: 1; + u8 PayloadType: 7; + u16 SequenceNumber; + u32 TimeStamp; + u32 SSRC; + }; + SBC_FRAME_SUM defined within sbc_packet_head_buf used for Media Playload parameter:Number of Frames + */ +#define SBC_PACKET_HEADER_LEN (14) /*包头Max Length*/ +#define SBC_FRAME_SUM (4) /*一包多少帧*/ +static unsigned char sbc_packet_head_buf[SBC_PACKET_HEADER_LEN] = { + 0x80, 0x60, //Version:2 Playload Type:0x60 + 0x00, 0x64, //Sequencenumber + 0x00, 0x00, 0x03, 0x20, //Timestamp + 0x00, 0x00, 0x00, 0x00 //Synchronization Source + //SBC_FRAME_SUM //defined for Media Payload +}; + +void sbc_enc_packet_pack(struct sbc_enc_hdl *hdl) +{ + unsigned int TS; /*TimeStamp*/ + /*SequenceNumber*/ + hdl->packet_head_sn++; + /*Timestamp*/ + TS = hdl->packet_head_sn * (128 * SBC_FRAME_SUM); + + sbc_packet_head_buf[2] = hdl->packet_head_sn >> 8; + sbc_packet_head_buf[3] = hdl->packet_head_sn & 0xff; + sbc_packet_head_buf[4] = TS >> 24; + sbc_packet_head_buf[5] = (TS >> 16) & 0xff; + sbc_packet_head_buf[6] = (TS >> 8) & 0xff; + sbc_packet_head_buf[7] = (TS) & 0xff; + if (hdl->cp_type == 0x0002) { + /* + *Content Protection Header + *L-bit :bit0 + *Cp-bit:bit1 + *RFA :bit2 to bit7 + */ + sbc_packet_head_buf[12] = 0; + sbc_packet_head_buf[13] = SBC_FRAME_SUM; + } else { + sbc_packet_head_buf[12] = SBC_FRAME_SUM; + } +} +#endif/*SBC_ENC_PACK_ENABLE*/ + +static int sbc_enc_output_handler(struct audio_encoder *encoder, u8 *frame, int len) +{ + if (encoder == NULL) { + r_printf("encoder NULL"); + } + struct sbc_enc_hdl *enc = container_of(encoder, struct sbc_enc_hdl, encoder); + enc->frame_size = len; + + u16 wlen = cbuf_write(&enc->output_cbuf, frame, len); + if (wlen != len) { + putchar('F'); + return len; + } + //printf("sbc_enc out,frame:%x,out:%d[0x%x]\n", frame, len, enc->frame_size); + if (cbuf_get_data_size(&sbc_enc->output_cbuf) >= enc->frame_size * 5) { + //达到基本的数据量,唤醒蓝牙发数 + user_emitter_cmd_prepare(USER_CTRL_CMD_RESUME_STACK, 0, NULL); + } + return len; +} + +const static struct audio_enc_handler sbc_enc_handler = { + .enc_probe = sbc_enc_probe_handler, + .enc_output = sbc_enc_output_handler, +}; + + +static u32 debug_len = 0; +static u32 last_jiffies = 0; +int a2dp_sbc_encoder_get_data(u8 *packet, u16 buf_len, int *frame_size) +{ + if (sbc_enc == NULL) { + return 0; + } + + // if(sbc_enc->frame_size) { + // // printf("sbc frame size:%d\n", sbc_enc->frame_size); + // buf_len = sbc_enc->frame_size *7; + // } + + if (cbuf_get_data_size(&sbc_enc->output_cbuf) < buf_len) { + return 0; + } + + int debug_frame_size = sbc_enc->frame_size; + int number = buf_len / debug_frame_size; /*取整数包*/ + // printf("number = %d\n", number); + *frame_size = debug_frame_size; + u16 rlen = cbuf_read(&sbc_enc->output_cbuf, packet, *frame_size * number); + //put_buf(packet,8); + if (rlen == 0) { + putchar('N'); + } + + debug_len += rlen; + if(jiffies_to_msecs(jiffies - last_jiffies) >= 1000){ + printf("l: %d bytes/s, s:%d\n", debug_len,jiffies_to_msecs(jiffies - last_jiffies)); + debug_len = 0; + last_jiffies = jiffies; + } + +#if SBC_RESERVED_LAST_PCM + if (sbc_enc->run_step != SBC_RUN_STEP_NOR) { + // 非正常状态,sbc数据取走后激活一下编码 + audio_encoder_resume(&sbc_enc->encoder); + } +#endif + + return rlen; +} + +static void sbc_enc_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ + printf("sbc_enc_event_handler:0x%x,%d\n", argv[0], argv[0]); + switch (argv[0]) { + case AUDIO_ENC_EVENT_END: + puts("AUDIO_ENC_EVENT_END\n"); + break; + } +} +#include "sbc_enc.h" +sbc_t sbc_param = { + .frequency = SBC_FREQ_44100, + .blocks = SBC_BLK_16, + .subbands = SBC_SB_8, + .mode = SBC_MODE_STEREO, + .allocation = 0, + .endian = SBC_LE, + .bitpool = 53, +}; + +int audio_sbc_enc_config(void *cfg) +{ + sbc_t *p = cfg; + if (p) { + printf("sbc_enc_param update:\n"); + printf("frequency:%d\n", p->frequency); + printf("blocks:%d\n", p->blocks); + printf("subbands:%d\n", p->subbands); + printf("mode:%d\n", p->mode); + printf("allocation:%d\n", p->allocation); + printf("endian:%d\n", p->endian); + printf("bitpool:%d\n", p->bitpool); + } + return 0; +} + +int audio_sbc_enc_check_empty_len(void) +{ + if (!(sbc_buf_flag & SBC_ENC_START)) { + return 0; + } + if (!sbc_enc) { + return 0; + } + return sbc_enc->pcm_in_cbuf.total_len - sbc_enc->pcm_in_cbuf.data_len; +} + +static int audio_sbc_enc_write_base(s16 *data, int len, u8 ch_i, u8 ch_o) +{ + if (!(sbc_buf_flag & SBC_ENC_START)) { + return 0; + } + if (!sbc_enc) { + return 0; + } + sbc_buf_flag |= SBC_ENC_WRITING; + + int wlen = 0; + int ilen = 0; + int remain_len = len; + while (remain_len) { + wlen = 0; + void *obuf = cbuf_write_alloc(&sbc_enc->pcm_in_cbuf, &wlen); + if (!wlen) { + break; + } + if (ch_o == ch_i) { + ilen = wlen; + if (ilen > remain_len) { + ilen = remain_len; + wlen = ilen; + } + memcpy(obuf, data, wlen); + } else if ((ch_o == 2) && (ch_i == 1)) { + ilen = (wlen >> 2) << 1; + if (ilen > remain_len) { + ilen = remain_len; + wlen = ilen << 1; + } + s16 *outbuf = obuf; + s16 *inbuf = data; + int run_len = ilen >> 1; + while (run_len --) { + *outbuf++ = *inbuf; + *outbuf++ = *inbuf; + inbuf++; + } + } else if ((ch_o == 1) && (ch_i == 2)) { + ilen = wlen << 1; + if (ilen > remain_len) { + ilen = remain_len; + wlen = ilen >> 1; + } + s16 *outbuf = obuf; + s16 *inbuf = data; + int run_len = ilen >> 2; + while (run_len--) { + *outbuf++ = data_sat_s16(inbuf[0] + inbuf[1]); + inbuf += 2; + } + } + cbuf_write_updata(&sbc_enc->pcm_in_cbuf, wlen); + remain_len -= ilen; + data += ilen / 2; + }; + wlen = len - remain_len; + + if (cbuf_get_data_size(&sbc_enc->pcm_in_cbuf) >= SBC_ENC_IN_SIZE) { + audio_encoder_resume(&sbc_enc->encoder); + } + sbc_buf_flag &= ~SBC_ENC_WRITING; + return wlen; +} + +int audio_sbc_enc_write(s16 *data, int len) +{ + if (!(sbc_buf_flag & SBC_ENC_START)) { + return 0; + } + if (!sbc_enc) { + return 0; + } + sbc_buf_flag |= SBC_ENC_WRITING; + +#if 0 + u16 wlen = cbuf_write(&sbc_enc->pcm_in_cbuf, data, len); + if (wlen != len) { + putchar('@'); + } +#else + int wlen = 0; + int remain_len = len; + while (remain_len) { + wlen = 0; + void *obuf = cbuf_write_alloc(&sbc_enc->pcm_in_cbuf, &wlen); + if (!wlen) { + break; + } + if (wlen > remain_len) { + wlen = remain_len; + } + memcpy(obuf, data, wlen); + /* audio_digital_vol_run(sbc_enc->dvol, obuf, wlen); */ + cbuf_write_updata(&sbc_enc->pcm_in_cbuf, wlen); + remain_len -= wlen; + data += wlen / 2; + }; + wlen = len - remain_len; +#endif + + if (cbuf_get_data_size(&sbc_enc->pcm_in_cbuf) >= SBC_ENC_IN_SIZE) { + audio_encoder_resume(&sbc_enc->encoder); + } + sbc_buf_flag &= ~SBC_ENC_WRITING; + return wlen; +} + +#if SBC_USE_MIC_CHANNEL +s16 temp_data[ESCO_ADC_IRQ_POINTS * 2]; +extern struct audio_adc_hdl adc_hdl; +static void adc_mic_output_handler(void *priv, s16 *data, int len) +{ + u16 points = len >> 1; + if (!(sbc_buf_flag & SBC_ENC_START)) { + return 0; + } + if (sbc_enc) { + //单变双 + for (int i = 0; i < points ; i++) { + temp_data[i * 2] = data[i]; + temp_data[i * 2 + 1] = data[i]; + } + //app_audio_output_write(temp_data, len*2); + //memset(temp_data, 0 , sizeof(temp_data)); + audio_sbc_enc_write(temp_data, len * 2); + } +} +#endif + +int audio_sbc_enc_open() +{ + int err; + struct audio_fmt fmt; + u16 frame_len = 512; + + if (encode_task) { + return -1; + } + printf("sbc_enc_open,frame_len:%d\n", frame_len); + sbc_buf_flag &= ~SBC_ENC_START; + fmt.channel = 1; + fmt.frame_len = frame_len; + fmt.coding_type = AUDIO_CODING_SBC; + + fmt.priv = &sbc_param; + + audio_encoder_task_open(); + if (!sbc_enc) { + sbc_enc = zalloc(sizeof(*sbc_enc)); +#if SBC_RESERVED_LAST_PCM + os_sem_create(&sbc_enc->run_sem, 0); +#endif + + + } + printf("init vol:%d \n", app_var.music_volume); + /* sbc_enc->dvol = audio_digital_vol_open(app_var.music_volume, 30, 7); */ + cbuf_init(&sbc_enc->output_cbuf, sbc_enc->out_cbuf_buf, SBC_ENC_OUT_CBUF_SIZE); + cbuf_init(&sbc_enc->pcm_in_cbuf, sbc_enc->in_cbuf_buf, SBC_ENC_IN_CBUF_SIZE); + os_sem_create(&sbc_enc->pcm_frame_sem, 0); + audio_encoder_open(&sbc_enc->encoder, &sbc_enc_input, encode_task); + audio_encoder_set_handler(&sbc_enc->encoder, &sbc_enc_handler); + audio_encoder_set_fmt(&sbc_enc->encoder, &fmt); + audio_encoder_set_event_handler(&sbc_enc->encoder, sbc_enc_event_handler, 0); + audio_encoder_set_output_buffs(&sbc_enc->encoder, sbc_enc->output_frame, + sizeof(sbc_enc->output_frame), 1); + int start_err = audio_encoder_start(&sbc_enc->encoder); + r_printf("sbc_enc_open ok %d\n", start_err); +#if 1 + int sr = audio_sbc_enc_get_rate(); + fmt.sample_rate = sr; +#endif + +#if SBC_USE_MIC_CHANNEL + fmt.sample_rate = 44100; + audio_adc_mic_open(&sbc_enc->mic_ch, AUDIO_ADC_MIC_CH, &adc_hdl); + audio_adc_mic_set_sample_rate(&sbc_enc->mic_ch, fmt.sample_rate); + audio_adc_mic_set_gain(&sbc_enc->mic_ch, app_var.aec_mic_gain); + audio_adc_mic_set_buffs(&sbc_enc->mic_ch, sbc_enc->adc_buf, + ESCO_ADC_IRQ_POINTS * 2, ESCO_ADC_BUF_NUM); + sbc_enc->adc_output.handler = adc_mic_output_handler; + audio_adc_add_output_handler(&adc_hdl, &sbc_enc->adc_output); + + + //app_audio_output_samplerate_set(44100); + //app_audio_output_start(); + audio_adc_mic_start(&sbc_enc->mic_ch); +#endif + + +#if BT_USE_PCM_DEC + + clock_add(DEC_PCM_CLK); + pcm_dec_open(sbc_enc, &fmt); +#endif + + + + + clock_add(ENC_SBC_CLK); + + clock_set_cur(); + sbc_buf_flag |= SBC_ENC_START; + audio_sbc_enc_open_exit(); + return 0; + +} +int audio_sbc_enc_reset_buf(u8 flag) +{ + if (!sbc_enc) { + return -1; + } + r_printf("audio_sbc_enc_reset_buf %d\n", flag); + if (flag) { + //有些情况(提示音)没有足够的参数去fade out,使得下次fade in受影响。 + //所以默认每次都reset一下 + /* audio_digital_vol_reset_fade(sbc_enc->dvol); */ + /* audio_digital_vol_set(sbc_enc->dvol, sbc_enc->backup_digital_vol); */ + if (sbc_enc->mute_data_send_timer) { + sys_hi_timer_del(sbc_enc->mute_data_send_timer); + sbc_enc->mute_data_send_timer = 0; + sbc_buf_flag &= ~SBC_ENC_PCM_MUTE_DATA; + } + } else { + /* audio_digital_vol_set(sbc_enc->dvol, 0); */ + if (sbc_enc->mute_data_send_timer == 0) { + //sbc_enc->mute_data_send_timer= sys_hi_timer_add((void *)0, sbc_send_mute_data, 12); + } + } + return 0; +} +int audio_sbc_enc_close() +{ + if (!sbc_enc) { + return -1; + } + printf("audio_sbc_enc_close\n"); + audio_sbc_enc_close_enter(); + sbc_buf_flag &= ~SBC_ENC_START; + +#if BT_USE_PCM_DEC + pcm_dec_close(sbc_enc); + clock_remove(DEC_PCM_CLK); +#endif + + +#if SBC_RESERVED_LAST_PCM + os_sem_post(&sbc_enc->run_sem); +#endif + while (sbc_buf_flag & SBC_ENC_WRITING) { + os_time_dly(1); + + } + + + + /* audio_digital_vol_close(sbc_enc->dvol); */ +#if SBC_USE_MIC_CHANNEL + audio_adc_mic_close(&sbc_enc->mic_ch); + audio_adc_del_output_handler(&adc_hdl, &sbc_enc->adc_output); +#endif + audio_encoder_close(&sbc_enc->encoder); + free(sbc_enc); + sbc_enc = NULL; + + audio_encoder_task_close(); + + clock_remove(ENC_SBC_CLK); + + clock_set_cur(); + printf("audio_sbc_enc_close end\n"); + return 0; +} + +void audio_sbc_enc_init(void) +{ + /* audio_digital_vol_open(0, 30, 4); */ + //printf("init vol:%d \n", app_var.music_volume); + //audio_digital_vol_open(app_var.music_volume, 30, 7); +} + +int audio_sbc_enc_is_work(void) +{ + if ((sbc_buf_flag & SBC_ENC_START) && sbc_enc) { + return true; + } + return false; +} + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) +#include "application/audio_dig_vol.h" +extern void *bt_digvol_last; +#endif +void bt_emitter_set_vol(u8 vol) +{ + if (!(sbc_buf_flag & SBC_ENC_START)) { + return ; + } + if (!sbc_enc) { + return ; + } + sbc_enc->backup_digital_vol = vol; + r_printf("=======set vol %d\n", vol); +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) + if (bt_digvol_last) { + audio_dig_vol_set(bt_digvol_last, AUDIO_DIG_VOL_ALL_CH, vol); + } +#endif +} + +int audio_sbc_enc_get_rate(void) +{ + int sr = 44100; + switch (sbc_param.frequency) { + case SBC_FREQ_16000: + sr = 16000; + break; + case SBC_FREQ_32000: + sr = 32000; + break; + case SBC_FREQ_44100: + sr = 44100; + break; + case SBC_FREQ_48000: + sr = 48000; + break; + } + return sr; +} +int audio_sbc_enc_get_channel_num(void) +{ + return sbc_param.mode == SBC_MODE_MONO ? 1 : 2; +} + +int a2dp_sbc_encoder_init(void *sbc_struct) +{ + extern void audio_mixer_reset_sample_rate(u8 flag, u32 sr); + if (sbc_struct) { + //更新连接过程中的a2dp source参数 + audio_sbc_enc_config(&sbc_param); + g_printf("sbc enc open"); + memcpy(&sbc_param, sbc_struct, sizeof(sbc_t)); + audio_mixer_reset_sample_rate(1, audio_sbc_enc_get_rate()); + audio_sbc_enc_config(&sbc_param); + audio_sbc_enc_open(); + } else { + g_printf("sbc enc close"); + +#if USER_SUPPORT_DUAL_A2DP_SOURCE + if (get_total_connect_dev() == 0) { + audio_mixer_reset_sample_rate(0, audio_sbc_enc_get_rate()); + audio_sbc_enc_close(); + } +#else + audio_mixer_reset_sample_rate(0, audio_sbc_enc_get_rate()); + audio_sbc_enc_close(); +#endif + + } + return 0; +} + + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_BT) + +struct sbc_emitter_hdl sbc_emitter = {0}; + +static int audio_stream_sbc_emitter_data_handler(struct audio_stream_entry *entry, struct audio_data_frame *in, + struct audio_data_frame *out) +{ + + local_irq_disable(); + if (false == audio_sbc_enc_is_work()) { + local_irq_enable(); + return in->data_len; + } +#if SBC_RESERVED_LAST_PCM + if (in->stop) { + if (sbc_enc->run_step == SBC_RUN_STEP_NOR) { + sbc_enc->run_step = SBC_RUN_STEP_WAIT_STOP; + } + audio_encoder_resume(&sbc_enc->encoder); + os_sem_set(&sbc_enc->run_sem, 0); + local_irq_enable(); + if ((sbc_enc->run_step == SBC_RUN_STEP_WAIT_STOP) || (sbc_enc->run_cnt)) { + os_sem_pend(&sbc_enc->run_sem, 3); + if ((sbc_enc->run_step == SBC_RUN_STEP_WAIT_STOP) || (sbc_enc->run_cnt)) { + log_w("sbc wait stop err, step:%d, cnt:%d \n\n", sbc_enc->run_step, sbc_enc->run_cnt); + } + } + return in->data_len; + } else { + if (sbc_enc->run_step != SBC_RUN_STEP_NOR && (sbc_enc->run_step != SBC_RUN_STEP_WAIT_NOR)) { + cbuf_clear(&sbc_enc->pcm_in_cbuf); + + sbc_enc->run_step = SBC_RUN_STEP_WAIT_NOR; + + sbc_enc->in_cnt = 100; //丢掉前面几包 + + + + } + + } +#endif + /* return audio_sbc_enc_write(in->data, in->data_len); */ + local_irq_enable(); + if (in->data_len == 0) { + return 0; + } + + return audio_sbc_enc_write_base(in->data, in->data_len, in->channel, audio_sbc_enc_get_channel_num()); +} + +void audio_sbc_emitter_init(void) +{ + sbc_emitter.entry.data_handler = audio_stream_sbc_emitter_data_handler; +} + +#endif + + diff --git a/cpu/br23/audio_enc/audio_sbc_codec.h b/cpu/br23/audio_enc/audio_sbc_codec.h new file mode 100644 index 0000000..dc7b4f6 --- /dev/null +++ b/cpu/br23/audio_enc/audio_sbc_codec.h @@ -0,0 +1,25 @@ +#ifndef _AUDIO_SBC_CODEC_H_ +#define _AUDIO_SBC_CODEC_H_ + +#include "generic/typedef.h" +#include "generic/list.h" +#include "media/audio_base.h" +#include "media/audio_stream.h" + +struct sbc_emitter_hdl { + struct audio_stream_entry entry; // 音频流入口 +}; +extern struct sbc_emitter_hdl sbc_emitter; + +extern void audio_sbc_enc_init(void); +extern int audio_sbc_enc_is_work(void); +extern int audio_sbc_enc_write(s16 *data, int len); +extern int audio_sbc_enc_get_rate(void); +extern int audio_sbc_enc_get_channel_num(void); +extern void bt_emitter_set_vol(u8 vol); +extern int audio_sbc_enc_reset_buf(u8 flag); + +extern void audio_sbc_emitter_init(void); + +#endif + diff --git a/cpu/br23/audio_mic/effect_linein.c b/cpu/br23/audio_mic/effect_linein.c new file mode 100644 index 0000000..b41d70e --- /dev/null +++ b/cpu/br23/audio_mic/effect_linein.c @@ -0,0 +1,129 @@ +#include "effect_linein.h" +#include "stream_entry.h" +#include "application/audio_dig_vol.h" +#include "system/includes.h" +#include "audio_config.h" +#include "audio_enc.h" +#include "audio_dec.h" +#include "audio_adc.h" +#include "audio_config.h" +#include "media/includes.h" + + +struct __effect_linein { + struct audio_adc_ch ch; + struct audio_adc_output_hdl output; + s16 *adc_buf; + u16 adc_buf_len; + void *dvol; + struct __stream_entry *stream; +}; + +//adc出数顺序 lineinL lineinR mic +//mic通路数据源是单声道,用reverb会变双声道,用echo声道数不变 +int effect_linein_mix_callback(void *priv, struct audio_data_frame *in) +{ + struct __effect_linein *linein = (struct __effect_linein *)priv; + s16 *data = in->data; + u32 len = in->data_len; + if (linein && linein->adc_buf) { +#if SYS_DIGVOL_GROUP_EN + if (linein->dvol) { + audio_dig_vol_run(linein->dvol, linein->adc_buf, len); + } +#endif/*SYS_DIGVOL_GROUP_EN*/ + int i, j; + int points = len >> 1; + if (in->channel == 2) { + for (i = 0; i < points; i++) { + data[i] = data_sat_s16(data[i] + linein->adc_buf[i]);//声道数一致时,lineinLR与过了reverb后混响通路数据点数一致 + } + } else { + //混响通路是单声道时,lineinLR声道点数是mic通路数据的两倍 + s16 *tmp = linein->adc_buf; + for (i = 0, j = 0; i < points * 2; i += 2, j++) { + tmp[j] = data_sat_s16(tmp[i] + tmp[i + 1]); //将linein LR合成 单声道 + } + + for (i = 0; i < points; i++) { + data[i] = data_sat_s16(data[i] + linein->adc_buf[i]);//将合成单声道后的linein数据,叠加到混响通路 + } + } + } + return len; +} + + +static void linein_adc_irq_output(void *priv, s16 *data, int len) +{ + struct __effect_linein *linein = (struct __effect_linein *)priv; + if (linein) { + linein->adc_buf = data; + linein->adc_buf_len = len; + } +} + +struct __effect_linein *effect_linein_open(void) +{ + struct __effect_linein *linein = zalloc(sizeof(struct __effect_linein)); + if (linein) { + linein->stream = stream_entry_open(linein, effect_linein_mix_callback, 0); + if (linein->stream) { + if (audio_linein_open(&linein->ch, MIC_EFFECT_SAMPLERATE, 3) == 0) { +#if SYS_DIGVOL_GROUP_EN + audio_dig_vol_param linein_digvol_param = { + .vol_start = 0, + .vol_max = 100, + .ch_total = 2, + .fade_en = 1, + .fade_points_step = 5, + .fade_gain_step = 10, + .vol_list = NULL, + }; + linein->dvol = audio_dig_vol_open(&linein_digvol_param); + + if (linein->dvol) { + audio_dig_vol_group_add(sys_digvol_group, linein->dvol, "music_linein"); + } +#endif/*SYS_DIGVOL_GROUP_EN*/ + linein->output.handler = linein_adc_irq_output; + linein->output.priv = linein; + audio_linein_add_output(&linein->output); + audio_linein_start(&linein->ch); + printf("audio_linein_open ok!!!\n "); + return linein; + } + } else { + effect_linein_close(&linein); + return NULL; + } + } + return NULL; +} + +void effect_linein_close(struct __effect_linein **hdl) +{ + if (hdl && (*hdl)) { + struct __effect_linein *linein = *hdl; +#if SYS_DIGVOL_GROUP_EN + sys_digvol_group_ch_close("music_linein"); +#endif/*SYS_DIGVOL_GROUP_EN*/ + audio_linein_close(&linein->ch, &linein->output); + stream_entry_close(&linein->stream); + local_irq_disable(); + free(linein); + *hdl = NULL; + local_irq_enable(); + } +} + +struct audio_stream_entry *effect_linein_get_stream_entry(struct __effect_linein *hdl) +{ + if (hdl && hdl->stream) { + return &(hdl->stream->entry); + } + return NULL; +} + + + diff --git a/cpu/br23/audio_mic/effect_linein.h b/cpu/br23/audio_mic/effect_linein.h new file mode 100644 index 0000000..b8264f7 --- /dev/null +++ b/cpu/br23/audio_mic/effect_linein.h @@ -0,0 +1,17 @@ + +#ifndef __EFFECT_LINEIN_H__ +#define __EFFECT_LINEIN_H__ + +#include "system/includes.h" +#include "app_config.h" +#include "media/includes.h" +#include "application/audio_vocal_tract_synthesis.h" + +struct __effect_linein; + +struct __effect_linein *effect_linein_open(void); +void effect_linein_close(struct __effect_linein **hdl); +struct audio_stream_entry *effect_linein_get_stream_entry(struct __effect_linein *hdl); + +#endif//__EFFECT_LINEIN_H__ + diff --git a/cpu/br23/audio_mic/effect_parm.c b/cpu/br23/audio_mic/effect_parm.c new file mode 100644 index 0000000..6b73dfd --- /dev/null +++ b/cpu/br23/audio_mic/effect_parm.c @@ -0,0 +1,126 @@ +#include "effect_parm.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" + +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE +static u8 mic_eff_mode = 0;//EFFECT_REVERB_PARM_OST; +const u16 eq_name[] = {AEID_MIC_EQ0, AEID_MIC_EQ1, AEID_MIC_EQ2, AEID_MIC_EQ3, AEID_MIC_EQ4}; +const u16 drc_name[] = {AEID_MIC_DRC0, AEID_MIC_DRC1, AEID_MIC_DRC2, AEID_MIC_DRC3, AEID_MIC_DRC4}; + +u8 get_mic_eff_mode() +{ + return mic_eff_mode; +} +int get_eq_module_index(u16 module_name) +{ + for (int i = 0; i < ARRAY_SIZE(eq_name); i++) { //5个类型的eq + if (module_name == eq_name[i]) { + return i; + } + } + log_e("get eq index err\n"); + return 0; +} +int get_drc_module_index(u16 module_name) +{ + for (int i = 0; i < ARRAY_SIZE(drc_name); i++) { //5个类型的eq + if (module_name == drc_name[i]) { + return i; + } + } + log_e("get drc index err\n"); + return 0; +} + +void mic_eq_update_parm(u8 mode) +{ + for (int i = 0; i < ARRAY_SIZE(eq_name); i++) { //5个类型的eq + u8 max_nsection = get_eq_nsection(eq_name[i]); + u8 seg_num = eff_mode[mode].eq_parm[i].seg_num; + if (seg_num > max_nsection) { + log_e("eff mode %d, eq%d, seg num %d\n", mode, i, seg_num); + return; + } + float global_gain = eff_mode[mode].eq_parm[i].global_gain; + cur_eq_set_global_gain(eq_name[i], global_gain); + printf("seg num %d\n", seg_num); + for (int j = 0; j < seg_num; j++) { //每个类型的eq有5段系数 + void *tar_seg = &eff_mode[mode].eq_parm[i].seg[j]; + cur_eq_set_update(eq_name[i], tar_seg, seg_num, 1); + } + } +} + +void mic_drc_update_parm(u8 mode) +{ + u8 type = 0; //全带 + u8 bypass = 0; + void *tar_wdrc = NULL; + for (int i = 0; i < ARRAY_SIZE(drc_name); i++) { //有5个wdrc + tar_wdrc = &eff_mode[mode].drc_parm[i]; + cur_drc_set_update((u32)drc_name[mode], type, tar_wdrc); + bypass = eff_mode[mode].drc_parm[i].is_bypass; + cur_drc_set_bypass((u32)drc_name[mode], type, bypass); + } +} + + +//模式切换时 参数更新接口 +void set_mic_reverb_mode_by_id(u8 mode) +{ + REVERBN_PARM_SET *reverb_parm_obj; + mic_eff_mode = mode; + if (mic_eff_mode >= EFFECT_REVERB_PARM_MAX) { + mic_eff_mode = 0; + } + mode = mic_eff_mode; + printf("tar mode %d\n", mic_eff_mode); + switch (mic_eff_mode) { + + case EFFECT_REVERB_PARM_KTV: + // ktv + printf(" ktv ........................ \n"); + /* tone_play_by_path(tone_table[IDEX_TONE_NUM_1], 1); */ + break; + case EFFECT_REVERB_PARM_POP: + // 流行音效 + /* tone_play_by_path(tone_table[IDEX_TONE_NUM_2], 1); */ + printf(" liu xing.. \n"); + break; + case EFFECT_REVERB_PARM_qingrou: + // 柔 + printf(" qing rou.. \n"); + /* tone_play_by_path(tone_table[IDEX_TONE_NUM_3], 1); */ + break; + case EFFECT_REVERB_PARM_SUPER_REVERB: + // 超级混响 + printf(" chaoji.. \n"); + /* tone_play_by_path(tone_table[IDEX_TONE_NUM_4], 1); */ + break; + case EFFECT_REVERB_PARM_SONG: + // 民歌模式 + printf(" min ge........................ \n"); + /* tone_play_by_path(tone_table[IDEX_TONE_NUM_5], 1); */ + break; + + } + noisegate_update_parm(&eff_mode[mode].noise_gate_parm.parm, eff_mode[mode].noise_gate_parm.is_bypass); + howling_pitch_shift_update_parm(&eff_mode[mode].howlingps_parm.parm, eff_mode[mode].howlingps_parm.is_bypass);//内部未实现 + notchhowline_update_parm(&eff_mode[mode].notchhowling_parm.parm, eff_mode[mode].notchhowling_parm.is_bypass);//内部未实现 +#if defined(TCFG_MIC_VOICE_CHANGER_ENABLE) && TCFG_MIC_VOICE_CHANGER_ENABLE + audio_voice_changer_update_demo(AEID_MIC_VOICE_CHANGER, &eff_mode[mode].voicechanger_parm.parm, eff_mode[mode].voicechanger_parm.is_bypass); +#endif + echo_updata_parm(&eff_mode[mode].echo_parm.parm, eff_mode[mode].echo_parm.is_bypass); + plate_reverb_update_parm(&eff_mode[mode].plate_reverb_parm.parm, eff_mode[mode].plate_reverb_parm.is_bypass); +#if GAIN_PROCESS_EN + audio_gain_update_parm(AEID_MIC_GAIN, &eff_mode[mode].gain_parm.parm, eff_mode[mode].gain_parm.is_bypass); +#endif + mic_eq_update_parm(mode); + mic_drc_update_parm(mode); + printf("mdoe[%d]\n\n", mic_eff_mode); +} + + +#endif + + diff --git a/cpu/br23/audio_mic/effect_parm.h b/cpu/br23/audio_mic/effect_parm.h new file mode 100644 index 0000000..47157b7 --- /dev/null +++ b/cpu/br23/audio_mic/effect_parm.h @@ -0,0 +1,14 @@ +#ifndef __EFFECT_PARM_H_ +#define __EFFECT_PARM_H_ + +#include "mic_effect.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_voice_changer_demo.h" + +void mic_eff_analyze_data(u8 tar_mode); +int get_eq_module_index(u16 module_name); +int get_drc_module_index(u16 module_name); +void set_mic_reverb_mode_by_id(u8 mode); + +u8 get_mic_eff_mode(); +#endif diff --git a/cpu/br23/audio_mic/effect_reg.c b/cpu/br23/audio_mic/effect_reg.c new file mode 100644 index 0000000..3f59984 --- /dev/null +++ b/cpu/br23/audio_mic/effect_reg.c @@ -0,0 +1,116 @@ +#include "effect_reg.h" +#include "app_config.h" +#include "audio_enc.h" +/**********************混响功能选配*********************************/ +#if (TCFG_MIC_EFFECT_ENABLE) +#define MIC_EFFECT_CONFIG 0 \ + | BIT(MIC_EFFECT_CONFIG_REVERB) \ + | BIT(MIC_EFFECT_CONFIG_NOISEGATE) \ + | BIT(MIC_EFFECT_CONFIG_EQ) \ + | BIT(MIC_EFFECT_CONFIG_HOWLING) \ + | BIT(MIC_EFFECT_CONFIG_HOWLING_TRAP) \ + /* | BIT(MIC_EFFECT_CONFIG_PITCH) \ */ +/* | BIT(MIC_EFFECT_CONFIG_ENERGY_DETECT) \ */ +/* | BIT(MIC_EFFECT_CONFIG_LINEIN) \ */ +/* | BIT(MIC_EFFECT_CONFIG_DVOL) \ */ + +/*********************************************************************/ + +const struct __mic_effect_parm effect_parm_default = { + .effect_config = MIC_EFFECT_CONFIG,///混响通路支持哪些功能 + .effect_run = MIC_EFFECT_CONFIG,///混响打开之时, 默认打开的功能 + .sample_rate = MIC_EFFECT_SAMPLERATE, +}; + +const struct __mic_stream_parm effect_mic_stream_parm_default = { +#if (TCFG_MIC_EFFECT_SEL == MIC_EFFECT_REVERB) + .mic_gain = 0, +#else + .mic_gain = 0, +#endif + .sample_rate = MIC_EFFECT_SAMPLERATE,//采样率 +#if (RECORDER_MIX_EN) + .point_unit = 160,//一次处理数据的数据单元, 单位点 4对齐(要配合mic起中断点数修改) + .dac_delay = 20,//dac硬件混响延时, 单位ms 要大于 point_unit*2 +#else +#if (TCFG_MIC_EFFECT_SEL == MIC_EFFECT_REVERB) + .point_unit = REVERB_LADC_IRQ_POINTS,//一次处理数据的数据单元, 单位点 4对齐(要配合mic起中断点数修改) + .dac_delay = (int)((REVERB_LADC_IRQ_POINTS * 2) / (TCFG_REVERB_SAMPLERATE_DEFUAL / 1000.0)), //6,//8,//8,//10,//dac硬件混响延时, 单位ms 要大于 point_unit*2 // (REVERB_LADC_IRQ_POINTS*1.5)/(TCFG_REVERB_SAMPLERATE_DEFUAL/1000.0) +#else + .point_unit = ((MIC_EFFECT_SAMPLERATE / 1000) * 4), //一次处理数据的数据单元, 单位点 4对齐(要配合mic起中断点数修改) + .dac_delay = 10,//dac硬件混响延时, 单位ms 要大于 point_unit*2 +#endif +#endif +}; + + +const EF_REVERB_FIX_PARM effect_echo_fix_parm_default = { + .sr = MIC_EFFECT_SAMPLERATE, ////采样率 + .max_ms = 200, ////所需要的最大延时,影响 need_buf 大小 + +}; + + +static const u16 r_dvol_table[] = { + 0 , //0 + 93 , //1 + 111 , //2 + 132 , //3 + 158 , //4 + 189 , //5 + 226 , //6 + 270 , //7 + 323 , //8 + 386 , //9 + 462 , //10 + 552 , //11 + 660 , //12 + 789 , //13 + 943 , //14 + 1127, //15 + 1347, //16 + 1610, //17 + 1925, //18 + 2301, //19 + 2751, //20 + 3288, //21 + 3930, //22 + 4698, //23 + 5616, //24 + 6713, //25 + 8025, //26 + 9592, //27 + 11466,//28 + 15200,//29 + 16000,//30 + 16384 //31 +}; + +audio_dig_vol_param effect_dvol_default_parm = { +#if (SOUNDCARD_ENABLE) + .vol_start = 0,//30, +#else + .vol_start = 30, +#endif + .vol_max = ARRAY_SIZE(r_dvol_table) - 1, + .ch_total = 1, + .fade_en = 1, + .fade_points_step = 2, + .fade_gain_step = 2, + .vol_list = (void *)r_dvol_table, +}; + + + +const struct __effect_dodge_parm dodge_parm = { + .dodge_in_thread = 1000,//触发闪避的能量阈值 + .dodge_in_time_ms = 1,//能量值持续大于dodge_in_thread 就触发闪避 + .dodge_out_thread = 1000,//退出闪避的能量阈值 + .dodge_out_time_ms = 500,//能量值持续小于dodge_out_thread 就退出闪避 +}; + + + +#endif//TCFG_MIC_EFFECT_ENABLE + + diff --git a/cpu/br23/audio_mic/effect_reg.h b/cpu/br23/audio_mic/effect_reg.h new file mode 100644 index 0000000..7d4c53a --- /dev/null +++ b/cpu/br23/audio_mic/effect_reg.h @@ -0,0 +1,45 @@ +#ifndef __EFFECT_REG_H__ +#define __EFFECT_REG_H__ + +#include "system/includes.h" +#include "audio_mic/mic_stream.h" +#include "media/audio_eq.h" +#include "media/audio_howling.h" +#include "media/audio_voice_changer.h" +#include "media/audio_noisegate.h" +#include "media/audio_echo_reverb.h" +#include "application/audio_dig_vol.h" +#include "application/audio_energy_detect.h" + +struct __mic_effect_parm { + u32 effect_config; + u32 effect_run; + u16 sample_rate; + +}; + +struct __effect_dodge_parm { + u32 dodge_in_thread;//触发闪避的能量阈值 + u32 dodge_in_time_ms;//能量值持续大于dodge_in_thread 就触发闪避 + u32 dodge_out_thread;//退出闪避的能量阈值 + u32 dodge_out_time_ms;//能量值持续小于dodge_out_thread 就退出闪避 +}; + + +extern const struct __mic_effect_parm effect_parm_default; +extern const struct __mic_stream_parm effect_mic_stream_parm_default; +extern const REVERBN_PARM_SET effect_reverb_parm_default; +extern const Plate_reverb_parm effect_plate_reverb_parm_default; +extern const EF_REVERB_FIX_PARM effect_echo_fix_parm_default; +extern const ECHO_PARM_SET effect_echo_parm_default; +// extern const PITCH_SHIFT_PARM effect_pitch_parm_default; +extern const NoiseGateParam effect_noisegate_parm_default; +extern const HOWLING_PARM_SET howling_param_default; +extern audio_dig_vol_param effect_dvol_default_parm; +extern const struct __effect_dodge_parm dodge_parm; + + + + +#endif// __EFFECT_REG_H__ + diff --git a/cpu/br23/audio_mic/loud_speaker.c b/cpu/br23/audio_mic/loud_speaker.c new file mode 100644 index 0000000..55ba939 --- /dev/null +++ b/cpu/br23/audio_mic/loud_speaker.c @@ -0,0 +1,536 @@ +#include "system/includes.h" +#include "media/includes.h" +#include "app_config.h" +#include "app_online_cfg.h" +/* #include "audio_drc.h" */ +/* #include "audio_reverb.h" */ +#include "clock_cfg.h" +#include "audio_config.h" +#include "storage_dev/storage_dev.h" +#include "loud_speaker.h" +#include "audio_dec.h" +#include "audio_enc.h" +#include "media/pcm_decoder.h" +#include "media/audio_howling.h" +#include "media/audio_voice_changer.h" +#include "media/audio_echo_reverb.h" +#define LOG_TAG "[APP-SPEAKER]" +#define LOG_ERROR_ENABLE +#define LOG_INFO_ENABLE +#define LOG_DUMP_ENABLE +#include "debug.h" + +#define ECHO_ENABLE 0 //K歌混响 +#define HOWLING_ENABLE 0 //啸叫抑制 +#define PITCH_ENABLE 0 //变声 + +// mic 采样率 若存在与mic录音/usb mic 等同开情况 需保证采样率一致 +#define LOUND_SPEAKER_MIC_SAMPLE_RATE 44100 + + +//简易版扩音器功能 使用解码数据流程把mic数据接入mix,能把数据输出到DAC/FM/IIS等 (mic_effect.c里面的混响只能输出到DAC) +// 可用于mic to dac的测试 /mic混响数据到fm/iis输出功能 +// +#if 0 + +extern struct audio_adc_hdl adc_hdl; +extern struct audio_decoder_task decode_task; +extern struct audio_mixer mixer; + +#define PCM_BUF_LEN (2*1024) +enum { + REVERB_STATUS_STOP = 0, + REVERB_STATUS_START, + REVERB_STATUS_PAUSE, +}; + +struct s_speaker_hdl { + struct audio_adc_output_hdl adc_output; + struct adc_mic_ch mic_ch; + + u32 process_len; + struct audio_stream *stream; // 音频流 + int mic_gain; + u16 mic_sr; + u16 src_out_sr; + u16 src_out_sr_n; + int begin_size; + int top_size; + int bottom_size; + u16 audio_new_rate; + u16 audio_max_speed; + u16 audio_min_speed; + u8 sync_start; + u8 pcm_buf[PCM_BUF_LEN ]; + cbuffer_t pcm_cbuf; + u32 status : 2; + u32 source_ch_num : 2; + u32 reverb_en : 2; + u32 howling_en : 2; + u8 first_start; + u8 speaker_pause; + /* struct audio_decoder decoder; */ + struct audio_res_wait wait; + struct audio_mixer_ch mix_ch; + struct pcm_decoder pcm_dec; // pcm解码句柄 + +#if ECHO_ENABLE + ECHO_API_STRUCT *p_echo_hdl; +#endif +#if HOWLING_ENABLE + HOWLING_API_STRUCT *p_howling_hdl; +#endif +#if PITCH_ENABLE + s_pitch_hdl *p_pitch_hdl; +#endif + struct channel_switch *channel_zoom; +}; +static struct s_speaker_hdl *speaker_hdl = NULL; +static u8 pcm_dec_maigc = 0; + +//echo 参数 +EF_REVERB_FIX_PARM effect_echo_fix_parm = { + .wetgain = 2048, ////湿声增益:[0:4096] + .drygain = 4096, ////干声增益: [0:4096] + .sr = LOUND_SPEAKER_MIC_SAMPLE_RATE, ////采样率 + .max_ms = 200, ////所需要的最大延时,影响 need_buf 大小 + +}; + +ECHO_PARM_SET effect_echo_parm = { + .delay = 200, //回声的延时时间 0-300ms + .decayval = 50, // 0-70% + .direct_sound_enable = 1, //直达声使能 0/1 + .filt_enable = 0, //发散滤波器使能 +}; + +static void adc_output_to_buf(void *priv, s16 *data, int len) +{ + if ((!speaker_hdl) || (speaker_hdl->status != REVERB_STATUS_START)) { + return; + } + if (speaker_hdl->speaker_pause) { + return; + } + int wlen = cbuf_write(&speaker_hdl->pcm_cbuf, data, len); + if (!wlen) { + putchar('W'); + } + audio_decoder_resume(&speaker_hdl->pcm_dec.decoder); +} + + +static void pcm_dec_relaese() +{ + audio_decoder_task_del_wait(&decode_task, &speaker_hdl->wait); +} + +static void pcm_dec_close(void) +{ + audio_decoder_close(&speaker_hdl->pcm_dec.decoder); + audio_mixer_ch_close(&speaker_hdl->mix_ch); + if (speaker_hdl->stream) { + audio_stream_close(speaker_hdl->stream); + speaker_hdl->stream = NULL; + } +} + +static int pcm_fread(void *hdl, void *buf, int len) +{ + struct s_speaker_hdl *dec = (struct s_speaker_hdl *)hdl; + int rlen = cbuf_read(&dec->pcm_cbuf, buf, len); + /* printf("rlen %d",rlen); */ + return rlen; +} + +static void pcm_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ + switch (argv[0]) { + case AUDIO_DEC_EVENT_END: + if ((u8)argv[1] != (u8)(pcm_dec_maigc - 1)) { + log_i("maigc err, %s\n", __FUNCTION__); + break; + } + /* pcm_dec_close(); */ + break; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief pcm解码数据输出 + @param *entry: 音频流句柄 + @param *in: 输入信息 + @param *out: 输出信息 + @return 输出长度 + @note *out未使用 +*/ +/*----------------------------------------------------------------------------*/ +static int pcm_dec_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + struct audio_decoder *decoder = container_of(entry, struct audio_decoder, entry); + struct pcm_decoder *pcm_dec = container_of(decoder, struct pcm_decoder, decoder); + struct s_speaker_hdl *dec = container_of(pcm_dec, struct s_speaker_hdl, pcm_dec); + audio_stream_run(&decoder->entry, in); + return decoder->process_len; +} +/*----------------------------------------------------------------------------*/ +/**@brief pcm解码数据流激活 + @param *p: 私有句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void dec_out_stream_resume(void *p) +{ + struct s_speaker_hdl *dec = (struct s_speaker_hdl *)p; + + audio_decoder_resume(&dec->pcm_dec.decoder); +} + +static int pcm_dec_start(void) +{ + int err; + struct audio_fmt f; + struct s_speaker_hdl *dec = speaker_hdl; + + log_i("\n--func=%s\n", __FUNCTION__); + err = pcm_decoder_open(&dec->pcm_dec, &decode_task); + if (err) { + goto __err1; + } + + pcm_decoder_set_event_handler(&dec->pcm_dec, pcm_dec_event_handler, 0); + pcm_decoder_set_read_data(&dec->pcm_dec, pcm_fread, dec); + pcm_decoder_set_data_handler(&dec->pcm_dec, pcm_dec_data_handler); + + audio_mixer_ch_open(&dec->mix_ch, &mixer); + audio_mixer_ch_set_src(&dec->mix_ch, 1, 1); + /* audio_mixer_ch_set_no_wait(&dec->mix_ch, 1, 10); // 超时自动丢数 */ + + +// 数据流串联 + struct audio_stream_entry *entries[8] = {NULL}; + u8 entry_cnt = 0; + entries[entry_cnt++] = &dec->pcm_dec.decoder.entry; +#if HOWLING_ENABLE + entries[entry_cnt++] = &dec->p_howling_hdl->entry; +#endif + +#if ECHO_ENABLE + entries[entry_cnt++] = &dec->p_echo_hdl->entry; +#endif +#if PITCH_ENABLE + entries[entry_cnt++] = &dec->p_pitch_hdl->entry; + //for test pitch + loundspeaker_set_pitch_para(66, LOUND_SPEAKER_MIC_SAMPLE_RATE, EFFECT_VOICECHANGE_KIN0, 150); +#endif + if (dec->channel_zoom) { + entries[entry_cnt++] = &dec->channel_zoom->entry; + } + + entries[entry_cnt++] = &dec->mix_ch.entry; + dec->stream = audio_stream_open(dec, dec_out_stream_resume); + audio_stream_add_list(dec->stream, entries, entry_cnt); + + + audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); + + /* audio_adc_mic_start(&dec->mic_ch); */ + log_i("\n\n audio decoder start \n"); + dec->status = REVERB_STATUS_START; + err = audio_decoder_start(&dec->pcm_dec.decoder); + if (err) { + goto __err3; + } + log_i("\n\n audio mic start 1 \n"); + return 0; +__err3: + + dec->status = 0; + audio_mic_close(&dec->mic_ch, &dec->adc_output); +__err2: + if (dec->stream) { + audio_stream_close(dec->stream); + dec->stream = NULL; + } + + pcm_decoder_close(&dec->pcm_dec); +__err1: + audio_decoder_task_del_wait(&decode_task, &dec->wait); + return err; +} + + + +static int pcmdec_wait_res_handler(struct audio_res_wait *wait, int event) +{ + int err = 0; + if (!speaker_hdl) { + log_e("speaker_hdl err \n"); + return -1; + } + log_i("pcmdec_wait_res_handler, event:%d;status:%d; \n", event, speaker_hdl->status); + if (event == AUDIO_RES_GET) { + if (speaker_hdl->status == REVERB_STATUS_STOP) { + err = pcm_dec_start(); + } else if (speaker_hdl->status == REVERB_STATUS_PAUSE) { + speaker_hdl->status = REVERB_STATUS_START; + } + } else if (event == AUDIO_RES_PUT) { + if (speaker_hdl->status == REVERB_STATUS_START) { + /* reverb_hdl->status = REVERB_STATUS_PAUSE; */ + } + } + return err; +} +//************************* MIC to DAC API *****************************// +void stop_loud_speaker(void) +{ + if (!speaker_hdl) { + return; + } + log_i("\n--func=%s\n", __FUNCTION__); + + speaker_hdl->status = REVERB_STATUS_STOP; + + audio_mic_close(&speaker_hdl->mic_ch, &speaker_hdl->adc_output); + pcm_dec_close(); + +#if ECHO_ENABLE + close_echo(speaker_hdl->p_echo_hdl); +#endif +#if HOWLING_ENABLE + close_howling(speaker_hdl->p_howling_hdl); +#endif +#if PITCH_ENABLE + close_pitch(speaker_hdl->p_pitch_hdl); +#endif + if (speaker_hdl->channel_zoom) { + channel_switch_close(&speaker_hdl->channel_zoom); + } + pcm_dec_relaese(); + + free(speaker_hdl); + speaker_hdl = NULL; + clock_remove_set(REVERB_CLK); +} + +void start_loud_speaker(struct audio_fmt *fmt) +{ + struct s_speaker_hdl *reverb = NULL; + int err; + if (speaker_hdl) { + stop_loud_speaker(); + } + clock_add_set(REVERB_CLK); + reverb = zalloc(sizeof(struct s_speaker_hdl)); + log_i("speaker hdl:%lu", sizeof(struct s_speaker_hdl)); + ASSERT(reverb); + + struct audio_fmt f = {0}; + if (fmt) { + f.sample_rate = fmt->sample_rate; + } + if (f.sample_rate == 0) { + f.sample_rate = LOUND_SPEAKER_MIC_SAMPLE_RATE; + } + f.channel = 1; + + reverb->source_ch_num = f.channel; + reverb->mic_sr = f.sample_rate; + reverb->mic_gain = 2; + + +#if ECHO_ENABLE + reverb->p_echo_hdl = open_echo(&effect_echo_parm, &effect_echo_fix_parm); + ASSERT(reverb->p_echo_hdl); +#endif +#if HOWLING_ENABLE + reverb->p_howling_hdl = open_howling(NULL, f.sample_rate, audio_output_channel_num(), 1); +#endif + +#if PITCH_ENABLE + reverb->p_pitch_hdl = open_pitch(NULL); + /* pause_pitch(reverb->p_pitch_hdl, 1); */ +#endif + + if (audio_output_channel_num() != 1) { + reverb->channel_zoom = channel_switch_open(audio_output_channel_type(), 1024); + } +#if 1 + cbuf_init(&reverb->pcm_cbuf, reverb->pcm_buf, sizeof(reverb->pcm_buf)); + if (audio_mic_open(&reverb->mic_ch, f.sample_rate, reverb->mic_gain) == 0) { + reverb->adc_output.handler = adc_output_to_buf; + audio_mic_add_output(&reverb->adc_output); + audio_mic_start(&reverb->mic_ch); + } +#endif + reverb->pcm_dec.ch_num = 1; + reverb->pcm_dec.output_ch_num = 1;//audio_output_channel_num(); echo/pitch 只能处理单声道数据 + reverb->pcm_dec.output_ch_type = audio_output_channel_type(); + reverb->pcm_dec.sample_rate = reverb->mic_sr; + + reverb->wait.priority = 0; + reverb->wait.preemption = 0; + reverb->wait.protect = 1; + reverb->wait.handler = pcmdec_wait_res_handler; + speaker_hdl = reverb; + err = audio_decoder_task_add_wait(&decode_task, &reverb->wait); + if (err == 0) { + return ; + } + + log_e("audio decoder task add wait err \n"); + audio_mic_close(&reverb->mic_ch, &reverb->adc_output); + +#if ECHO_ENABLE + close_echo(reverb->p_echo_hdl); +#endif +#if HOWLING_ENABLE + close_howling(reverb->p_howling_hdl); +#endif +#if PITCH_ENABLE + close_pitch(reverb->p_pitch_hdl); +#endif + if (speaker_hdl->channel_zoom) { + channel_switch_close(&speaker_hdl->channel_zoom); + } + clock_remove_set(REVERB_CLK); +} +/***************************************************************/ +int speaker_if_working(void) +{ + if (speaker_hdl && (speaker_hdl->status == REVERB_STATUS_START)) { + return 1; + } + return 0; +} + + +void loud_speaker_pause(void) +{ + if (speaker_hdl) { + speaker_hdl->speaker_pause = 1; + audio_mixer_ch_pause(&speaker_hdl->mix_ch, 1); + printf("speaker_pause [%d]", speaker_hdl->speaker_pause); + } +} +void loud_speaker_resume(void) +{ + if (speaker_hdl) { + audio_mixer_ch_pause(&speaker_hdl->mix_ch, 0); + speaker_hdl->speaker_pause = 0; + printf("speaker_pause [%d]", speaker_hdl->speaker_pause); + } +} + +/****************************效果设置接口***********************************/ + +void switch_holwing_en(void) +{ + if (speaker_hdl) { + speaker_hdl->howling_en ^= 1; +#if HOWLING_ENABLE + if (speaker_hdl->p_howling_hdl) { + pause_howling(speaker_hdl->p_howling_hdl, speaker_hdl->howling_en); + printf("howling_en [%d]", speaker_hdl->howling_en); + } +#endif + } +} + +void switch_echo_en(void) +{ + if (speaker_hdl) { + speaker_hdl->reverb_en ^= 1; + printf("reverb_en [%d]", speaker_hdl->reverb_en); +#if ECHO_ENABLE + if (speaker_hdl->reverb_en) { + pause_echo(speaker_hdl->p_echo_hdl, speaker_hdl->reverb_en); + } +#endif + } + +} + +/*----------------------------------------------------------------------------*/ +/**@brief loundspeaker echo 回声延时调节接口 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void loundspeaker_set_echo_delay(u32 delay) +{ +#if ECHO_ENABLE + if (speaker_hdl == NULL || speaker_hdl->p_echo_hdl == NULL) { + return ; + } + effect_echo_parm.delay = delay; + update_echo_parm(speaker_hdl->p_echo_hdl, &effect_echo_parm); +#endif +} +u32 loundspeaker_get_echo_delay(void) +{ +#if ECHO_ENABLE + if (speaker_hdl && speaker_hdl->p_echo_hdl) { + return effect_echo_parm.delay; + } +#endif + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief loundspeaker echo 回声衰减系数调节接口 + @param + @return + @note + */ +/*----------------------------------------------------------------------------*/ +void loundspeaker_set_echo_decay(u32 decay) +{ +#if ECHO_ENABLE + if (speaker_hdl == NULL || speaker_hdl->p_echo_hdl == NULL) { + return ; + } + effect_echo_parm.decayval = decay; + update_echo_parm(speaker_hdl->p_echo_hdl, &effect_echo_parm); +#endif +} + +u32 loundspeaker_get_echo_decay(void) +{ +#if ECHO_ENABLE + if (speaker_hdl && speaker_hdl->p_echo_hdl) { + return effect_echo_parm.decayval; + } +#endif + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief loundspeaker 变声参数设置 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void loundspeaker_set_pitch_para(u32 shiftv, u32 sr, u8 effect, u32 formant_shift) +{ +#if PITCH_ENABLE + if (speaker_hdl == NULL || speaker_hdl->p_pitch_hdl == NULL) { + return ; + } + PITCH_SHIFT_PARM p_pitch_parm = {0};//get_pitch_parm(); + + p_pitch_parm.sr = sr; + p_pitch_parm.shiftv = shiftv; + p_pitch_parm.effect_v = effect; + p_pitch_parm.formant_shift = formant_shift; + + printf("\n\n\nshiftv[%d],sr[%d],effect[%d],formant_shift[%d] \n\n", p_pitch_parm.shiftv, p_pitch_parm.sr, p_pitch_parm.effect_v, p_pitch_parm.formant_shift); + update_picth_parm(speaker_hdl->p_pitch_hdl, &p_pitch_parm); +#endif +} +#endif /*TCFG_LOUDSPEAKER_ENABLE*/ + diff --git a/cpu/br23/audio_mic/loud_speaker.h b/cpu/br23/audio_mic/loud_speaker.h new file mode 100644 index 0000000..b394973 --- /dev/null +++ b/cpu/br23/audio_mic/loud_speaker.h @@ -0,0 +1,17 @@ + +#ifndef _AUDIO_SPEAKER_API_H_ +#define _AUDIO_SPEAKER_API_H_ + +void stop_loud_speaker(void); +void start_loud_speaker(struct audio_fmt *fmt); +int speaker_if_working(void); +void loud_speaker_pause(void); +void loud_speaker_resume(void); + +void switch_holwing_en(void); +void switch_echo_en(void); +void loundspeaker_set_echo_delay(u32 delay); +void loundspeaker_set_echo_decay(u32 decay); +void loundspeaker_set_pitch_para(u32 shiftv, u32 sr, u8 effect, u32 formant_shift); +#endif + diff --git a/cpu/br23/audio_mic/mic_effect.c b/cpu/br23/audio_mic/mic_effect.c new file mode 100644 index 0000000..e512ce0 --- /dev/null +++ b/cpu/br23/audio_mic/mic_effect.c @@ -0,0 +1,1356 @@ +#include "audio_splicing.h" +#include "application/audio_bfilt.h" +#include "media/audio_eq_drc_apply.h" +#include "application/audio_echo_src.h" +#include "application/audio_energy_detect.h" +#include "clock_cfg.h" +#include "media/audio_stream.h" +#include "media/includes.h" +#include "mic_effect.h" +#include "asm/dac.h" +#include "audio_enc.h" +#include "audio_dec.h" +#include "stream_entry.h" +#include "effect_linein.h" +#include "audio_recorder_mix.h" +#include "app_task.h" +#include "vollevel_detect.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" +#include "media/convert_data.h" +#include "simpleAGC.h" + +#define LOG_TAG "[APP-REVERB]" +#define LOG_ERROR_ENABLE +#define LOG_INFO_ENABLE +#define LOG_DUMP_ENABLE +#define LOG_DEBUG_ENABLE +#include "debug.h" + +#ifdef SUPPORT_MS_EXTENSIONS +//#pragma bss_seg(".audio_mic_stream_bss") +//#pragma data_seg(".audio_mic_stream_data") +#pragma const_seg(".audio_mic_effect_const") +#pragma code_seg(".audio_mic_effect_code") +#endif + +#if defined(TCFG_MIC_EFFECT_ENABLE) && TCFG_MIC_EFFECT_ENABLE + +#define LOUDNESS_DEBUG_ENABLE 0//分贝指示器 + + + +extern struct audio_dac_hdl dac_hdl; +struct aud_reverb_process { + struct audio_stream_entry entry; // 音频流入口 + s16 *tmpbuf[3]; + void *eff;//struct __mic_effect + s16 *out_buf; + u8 bit_wide;//eq是否输出32bit位宽 + u8 in_ch; +}; + +struct __mic_effect { + OS_MUTEX mutex; + struct __mic_effect_parm parm; + mic_stream *mic; + struct audio_eq *mic_eq0; //eq 句柄 + struct audio_drc *mic_drc0; //eq 句柄 + struct convert_data *convert0;//32-》16 + + struct audio_eq *mic_eq4; //eq drc句柄 + struct audio_drc *mic_drc4; //eq drc句柄 + struct convert_data *convert4;//32-》16 + struct aud_gain_process *gain;//最后一级 的增益调节 + + struct audio_stream *stream; // 音频流 + struct audio_stream_entry entry; // effect 音频入口 + int out_len; + int process_len; + u8 input_ch_num; //mic输入给混响数据流的源声道数 + + NOISEGATE_API_STRUCT *noisegate; + void *d_vol; + HOWLING_API_STRUCT *howling_ps; + HOWLING_API_STRUCT *notch_howling; + voice_changer_hdl *voice_changer; + + struct channel_switch *channel_zoom; + struct audio_dac_channel *dac; +#if (RECORDER_MIX_EN) + struct __stream_entry *rec_hdl; +#endif +#if (TCFG_USB_MIC_DATA_FROM_MICEFFECT||TCFG_USB_MIC_DATA_FROM_DAC) + struct __stream_entry *usbmic_hdl; + u8 usbmic_start; +#endif + void *energy_hdl; //能量检测的hdl + u8 dodge_en; //能量检测运行过程闪避是否使能 + + struct __effect_linein *linein; + struct audio_drc *drc; + + + u8 pause_mark; + LOUDNESS_M_STRUCT loudness_adc; + LOUDNESS_M_STRUCT loudness_drc_out; + struct __stream_entry *loudness_debug_hdl; + + struct audio_src_handle *src_hdl; + + struct audio_eq *mic_eq3; //eq drc句柄 + struct audio_drc *mic_drc3; //eq drc句柄 + + u8 main_pause; + //分支0节点 + PLATE_REVERB_API_STRUCT *sub_0_plate_reverb_hdl; + struct audio_eq *mic_eq1; //eq drc句柄 + struct audio_drc *mic_drc1; //eq drc句柄 + + //分支1节点 + ECHO_API_STRUCT *sub_1_echo_hdl; + struct audio_eq *mic_eq2; //eq drc句柄 + struct audio_drc *mic_drc2; //eq drc句柄 + + + //分支1 2 3的总处理 + struct aud_reverb_process *aud_reverb; +}; + +struct __mic_stream_parm *g_mic_parm = NULL; +static struct __mic_effect *p_effect = NULL; +#define __this p_effect +#define R_ALIN(var,al) ((((var)+(al)-1)/(al))*(al)) + +void *mic_eq_open(u32 sample_rate, u8 ch_num, u8 eq_name); +void *mic_drc_open(u32 sample_rate, u8 ch_num, u8 eq_name); +void mic_eq_close(void *eq); +void mic_drc_close(void *drc); +void mic_effect_echo_parm_parintf(ECHO_PARM_SET *parm); +void *mic_energy_detect_open(u32 sr, u8 ch_num); +void mic_energy_detect_close(void *hdl); + + + +s16 *aud_reverb_process_run(struct aud_reverb_process *hdl, s16 *data, int len); +static void audio_reverb_process_output_data_process_len(struct audio_stream_entry *entry, int len) +{ + struct aud_reverb_process *hdl = container_of(entry, struct aud_reverb_process, entry); +} +static int audio_reverb_process_data_handler(struct audio_stream_entry *entry, + struct audio_data_frame *in, + struct audio_data_frame *out) +{ + struct aud_reverb_process *hdl = container_of(entry, struct aud_reverb_process, entry); + /* if (in->data_len != 304) { */ + /* printf("in->data_len %d\n", in->data_len); */ + /* } */ + + out->data_sync = in->data_sync; + + struct __mic_effect *eff = hdl->eff; + if (eff->sub_0_plate_reverb_hdl) { + out->channel = 2;//in->channel; + } else { + out->channel = in->channel; + } + out->data_len = out->channel * in->data_len; + hdl->in_ch = in->channel; + out->data = aud_reverb_process_run(hdl, (short *)((int)in->data + in->offset), (in->data_len - in->offset)); //默认输出2ch + if (out->channel == 1) { + pcm_dual_to_single(out->data, out->data, in->data_len * 2); + } + return in->data_len; +} + + +struct aud_reverb_process *aud_reverb_open(struct __mic_effect *eff, u8 bit_wide) +{ + struct aud_reverb_process *hdl = zalloc(sizeof(struct aud_reverb_process)); + hdl->eff = eff; + hdl->bit_wide = bit_wide; + hdl->entry.data_process_len = audio_reverb_process_output_data_process_len; + hdl->entry.data_handler = audio_reverb_process_data_handler; + + return hdl; +} + +void aud_reverb_close(struct aud_reverb_process *hdl) +{ + if (!hdl) { + return; + } + local_irq_disable(); + audio_stream_del_entry(&hdl->entry); + local_irq_enable(); + for (int i = 0; i < 3; i++) { + if (hdl->tmpbuf[i]) { + free(hdl->tmpbuf[i]); + hdl->tmpbuf[i] = NULL; + } + } + free(hdl); + hdl = NULL; +} + +void pcm_single_to_dual_32bit(void *out, void *in, u16 len) +{ + s32 *outbuf = out; + s32 *inbuf = in; + len >>= 2; + while (len--) { + *outbuf++ = *inbuf; + *outbuf++ = *inbuf; + inbuf++; + } +} + +s16 *aud_reverb_process_run(struct aud_reverb_process *hdl, s16 *data, int len) +{ + struct __mic_effect *eff = hdl->eff; + u8 ch_num = eff->input_ch_num; + if (eff->sub_0_plate_reverb_hdl) { + //ch0 + if (hdl->in_ch == 2) { + u8 *tmp = hdl->tmpbuf[0]; + pcm_dual_to_single(&tmp[len], data, len); + run_plate_reverb(eff->sub_0_plate_reverb_hdl, &tmp[len], hdl->tmpbuf[0], len / 2); //内部单变双 + } else { + if (!hdl->bit_wide) { //16 bit + if (!hdl->tmpbuf[0]) { + hdl->tmpbuf[0] = malloc(len * 2);//2ch 16 bit buf + } + run_plate_reverb(eff->sub_0_plate_reverb_hdl, data, hdl->tmpbuf[0], len); //16bit 内部单变双 + audio_dec_eq_run(eff->mic_eq1, hdl->tmpbuf[0], hdl->tmpbuf[0], len * 2);// 16bit 2ch + audio_dec_drc_run(eff->mic_drc1, hdl->tmpbuf[0], len * 2); //16bit 2ch + } else { + if (!hdl->tmpbuf[0]) { + hdl->tmpbuf[0] = malloc(len * 2 * 2);//2ch 32 bit buf + } + u8 *tmp = hdl->tmpbuf[0]; + u8 *tar = &tmp[len * 2 * 2 - 2 * len]; //放在最后 16bit 2ch + run_plate_reverb(eff->sub_0_plate_reverb_hdl, data, tar, len); //16 bit 内部单变双 + audio_dec_eq_run(eff->mic_eq1, tar, hdl->tmpbuf[0], len * 2);// 32bit 2ch out + audio_dec_drc_run(eff->mic_drc1, hdl->tmpbuf[0], len * 2 * 2); //32bit 2ch + } + } + } + + //ch1 + u32 points = 0; + if (hdl->in_ch == 1) { + if (!hdl->bit_wide) { //16 bit + + u8 *tmp = NULL; + u8 *tar = NULL; + if (eff->sub_1_echo_hdl) { + if (!hdl->tmpbuf[1]) { + hdl->tmpbuf[1] = malloc(len * 2);//2ch 16 bit buf + } + //ch1 + tmp = hdl->tmpbuf[1]; + tar = &tmp[len]; + run_echo(eff->sub_1_echo_hdl, data, tar, len); + audio_dec_eq_run(eff->mic_eq2, tar, NULL, len); //1ch + audio_dec_drc_run(eff->mic_drc2, tar, len); //16bit 1ch + pcm_single_to_dual(hdl->tmpbuf[1], tar, len);//16bit 2ch + } + + if (!hdl->tmpbuf[2]) { + hdl->tmpbuf[2] = malloc(len * 2);//2ch 16 bit buf + } + //ch2 + audio_dec_eq_run(eff->mic_eq3, data, NULL, len);//1ch + audio_dec_drc_run(eff->mic_drc3, data, len); //16bit 1ch + pcm_single_to_dual(hdl->tmpbuf[2], data, len);//16bit 2ch + points = (len * 2) / 2; + } else { + u8 *tmp = NULL; + u8 *tar = NULL; + if (eff->sub_1_echo_hdl) { + if (!hdl->tmpbuf[1]) { + hdl->tmpbuf[1] = malloc(len * 2 * 2); //2ch 32 bit buf + } + //ch1 + tmp = hdl->tmpbuf[1]; + tar = &tmp[len * 2 * 2 - len]; //放在最后 16bit 1ch + u8 *tar2 = &tmp[len * 2]; //buf中间位置 + run_echo(eff->sub_1_echo_hdl, data, tar, len); + audio_dec_eq_run(eff->mic_eq2, tar, tar2, len); //16 ->32 1ch + audio_dec_drc_run(eff->mic_drc2, tar2, len * 2); //32bit 1ch + pcm_single_to_dual_32bit(hdl->tmpbuf[1], tar2, len * 2); //32bit 2ch out + } + + //ch2 + if (!hdl->tmpbuf[2]) { + hdl->tmpbuf[2] = malloc(len * 2 * 2); //2ch 32 bit buf + } + tmp = hdl->tmpbuf[2]; + tar = &tmp[len * 2]; //buf中间位置 + audio_dec_eq_run(eff->mic_eq3, data, tar, len);//16->32bit 1ch + audio_dec_drc_run(eff->mic_drc3, tar, len * 2); //32bit 1ch + pcm_single_to_dual_32bit(hdl->tmpbuf[2], tar, len * 2); //32bit 2ch + + points = (len * 2 * 2) / 4; + } + } else { + if (!hdl->bit_wide) { //16 bit + + u8 *tmp = NULL; + u8 *tar = NULL; + if (eff->sub_1_echo_hdl) { + if (!hdl->tmpbuf[1]) { + hdl->tmpbuf[1] = malloc(len);//2ch 16 bit buf + } + tmp = hdl->tmpbuf[1]; + tar = &tmp[len / 2]; + pcm_dual_to_single(tar, data, len); + run_echo(eff->sub_1_echo_hdl, tar, tar, len / 2); + pcm_single_to_dual(tmp, tar, len / 2); + audio_dec_eq_run(eff->mic_eq2, tmp, hdl->tmpbuf[1], len); //立体声处理2ch + audio_dec_drc_run(eff->mic_drc2, hdl->tmpbuf[1], len); //16bit 2ch + } + + //ch2 + if (!hdl->tmpbuf[2]) { + hdl->tmpbuf[2] = malloc(len);//2ch 16bit buf + } + audio_dec_eq_run(eff->mic_eq3, data, hdl->tmpbuf[2], len); + audio_dec_drc_run(eff->mic_drc3, hdl->tmpbuf[2], len); //16bit 2ch + points = len / 2; + } else { + + u8 *tmp = NULL; + u8 *tar = NULL; + if (eff->sub_1_echo_hdl) { + if (!hdl->tmpbuf[1]) { + hdl->tmpbuf[1] = malloc(len * 2); //2ch 32 bit buf + } + //ch1 + tmp = hdl->tmpbuf[1]; + tar = &tmp[len * 2 - len / 2]; + pcm_dual_to_single(tar, data, len); + run_echo(eff->sub_1_echo_hdl, tar, tar, len / 2); + pcm_single_to_dual(tmp, tar, len / 2); + audio_dec_eq_run(eff->mic_eq2, tmp, hdl->tmpbuf[1], len); //立体声处理2ch + audio_dec_drc_run(eff->mic_drc2, hdl->tmpbuf[1], len * 2); //32bit 2ch + } + + //ch2 + if (!hdl->tmpbuf[2]) { + hdl->tmpbuf[2] = malloc(len * 2 * 2); //2ch 32 bit buf + } + audio_dec_eq_run(eff->mic_eq3, data, hdl->tmpbuf[2], len); + audio_dec_drc_run(eff->mic_drc3, hdl->tmpbuf[2], len * 2); //32bit 2ch + points = (len * 2) / 4; + } + } + if (!hdl->bit_wide) { //16 bit + if (eff->sub_1_echo_hdl && eff->sub_0_plate_reverb_hdl) { + band_merging_16bit(hdl->tmpbuf[0], hdl->tmpbuf[1], hdl->tmpbuf[2], hdl->tmpbuf[0], points, 3); + } else if (eff->sub_0_plate_reverb_hdl) { + band_merging_16bit(hdl->tmpbuf[0], hdl->tmpbuf[2], NULL, hdl->tmpbuf[0], points, 2); + } else { + band_merging_16bit(hdl->tmpbuf[1], hdl->tmpbuf[2], NULL, hdl->tmpbuf[1], points, 2); + return hdl->tmpbuf[1]; + } + + return hdl->tmpbuf[0]; + } else { + if (eff->sub_1_echo_hdl && eff->sub_0_plate_reverb_hdl) { + band_merging_32bit(hdl->tmpbuf[0], hdl->tmpbuf[1], hdl->tmpbuf[2], hdl->tmpbuf[0], points, 3); + } else if (eff->sub_0_plate_reverb_hdl) { + band_merging_32bit(hdl->tmpbuf[0], hdl->tmpbuf[2], NULL, hdl->tmpbuf[0], points, 2); + } else { + band_merging_32bit(hdl->tmpbuf[1], hdl->tmpbuf[2], NULL, hdl->tmpbuf[1], points, 2); + user_sat16(hdl->tmpbuf[1], hdl->tmpbuf[1], len); + return hdl->tmpbuf[1]; + } + //饱和输出 + user_sat16(hdl->tmpbuf[0], hdl->tmpbuf[0], len); + } + return hdl->tmpbuf[0]; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief mic数据流串接入口 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static u32 mic_effect_effect_run(void *priv, void *in, void *out, u32 inlen, u32 outlen) +{ + struct __mic_effect *effect = (struct __mic_effect *)priv; + if (effect == NULL) { + return 0; + } + struct audio_data_frame frame = {0}; + frame.channel = effect->input_ch_num; + frame.sample_rate = effect->parm.sample_rate; + frame.data_len = inlen; + frame.data = in; + effect->out_len = 0; + effect->process_len = inlen; + + if (effect->pause_mark) { + memset(in, 0, inlen); + return inlen; + } else { + + } +#if LOUDNESS_DEBUG_ENABLE + loudness_meter_short(&effect->loudness_adc, in, inlen / 2); +#endif + while (1) { + audio_stream_run(&effect->entry, &frame); + if (effect->out_len >= effect->process_len) { + break; + } + frame.data = (s16 *)((u8 *)in + effect->out_len); + frame.data_len = inlen - effect->out_len; + } + return outlen; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 释放mic数据流资源 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void mic_effect_destroy(struct __mic_effect **hdl) +{ + if (hdl == NULL || *hdl == NULL) { + return ; + } + struct __mic_effect *effect = *hdl; + if (effect->mic) { + log_i("mic_stream_destroy\n\n\n"); + mic_stream_destroy(&effect->mic); + } + +#if TCFG_MIC_DODGE_EN + if (effect->energy_hdl) { + mic_energy_detect_close(effect->energy_hdl); + } +#endif + + if (effect->noisegate) { + log_i("close_noisegate\n\n\n"); + close_noisegate(effect->noisegate); + } + + + if (effect->howling_ps) { + log_i("close_howling\n\n\n"); + close_howling(effect->howling_ps); + } + if (effect->notch_howling) { + log_i("close_howling\n\n\n"); + close_howling(effect->notch_howling); + } +#if defined(TCFG_MIC_VOICE_CHANGER_ENABLE) && TCFG_MIC_VOICE_CHANGER_ENABLE + if (effect->voice_changer) { + audio_voice_changer_close_demo(effect->voice_changer); + } +#endif + if (effect->mic_eq0) { + log_i("mic_eq0_close\n\n\n"); + mic_eq_close(effect->mic_eq0); + } + if (effect->mic_drc0) { + log_i("mic_drc0_close\n\n\n"); + mic_drc_close(effect->mic_drc0); + } + if (effect->convert0) { + log_i("convet0_data_close\n\n\n"); + convet_data_close(effect->convert0); + } + + if (effect->mic_eq1) { + log_i("mic_eq1_close\n\n\n"); + mic_eq_close(effect->mic_eq1); + } + if (effect->mic_drc1) { + log_i("mic_drc1_close\n\n\n"); + mic_drc_close(effect->mic_drc1); + } + + if (effect->mic_eq2) { + log_i("mic_eq2_close\n\n\n"); + mic_eq_close(effect->mic_eq2); + } + if (effect->mic_drc2) { + log_i("mic_drc2_close\n\n\n"); + mic_drc_close(effect->mic_drc2); + } + + if (effect->mic_eq3) { + log_i("mic_eq3_close\n\n\n"); + mic_eq_close(effect->mic_eq3); + } + if (effect->mic_drc3) { + log_i("mic_drc3_close\n\n\n"); + mic_drc_close(effect->mic_drc3); + } + + if (effect->mic_eq4) { + log_i("mic_eq4_close\n\n\n"); + mic_eq_close(effect->mic_eq4); + } + if (effect->mic_drc4) { + log_i("mic_drc4_close\n\n\n"); + mic_drc_close(effect->mic_drc4); + } + + if (effect->convert4) { + log_i("convet4_data_close\n\n\n"); + convet_data_close(effect->convert4); + } + if (effect->gain) { + log_i("audio_gain_close_demo\n\n\n"); + audio_gain_close_demo(effect->gain); + effect->gain = NULL; + } + if (effect->sub_1_echo_hdl) { + close_echo(effect->sub_1_echo_hdl); + } + if (effect->sub_0_plate_reverb_hdl) { + close_plate_reverb(effect->sub_0_plate_reverb_hdl); + } + if (effect->d_vol) { + audio_stream_del_entry(audio_dig_vol_entry_get(effect->d_vol)); +#if SYS_DIGVOL_GROUP_EN + sys_digvol_group_ch_close("mic_mic"); +#else + audio_dig_vol_close(effect->d_vol); +#endif/*SYS_DIGVOL_GROUP_EN*/ + } + if (effect->linein) { + effect_linein_close(&effect->linein); + } + + if (effect->src_hdl) { + audio_stream_del_entry(&effect->src_hdl->entry); + audio_hw_src_stop(effect->src_hdl); + audio_hw_src_close(effect->src_hdl); + free(effect->src_hdl); + effect->src_hdl = NULL; + } + if (effect->channel_zoom) { + channel_switch_close(&effect->channel_zoom); + /*effect->channel_zoom = NULL;*/ + } + if (effect->loudness_debug_hdl) { + stream_entry_close(&effect->loudness_debug_hdl); + } + if (effect->dac) { + audio_stream_del_entry(&effect->dac->entry); + audio_dac_free_channel(effect->dac); + free(effect->dac); + effect->dac = NULL; + } + +#if (RECORDER_MIX_EN) + if (effect->rec_hdl) { + stream_entry_close(&effect->rec_hdl); + } +#endif +#if (TCFG_USB_MIC_DATA_FROM_MICEFFECT||TCFG_USB_MIC_DATA_FROM_DAC) + if (effect->usbmic_hdl) { + stream_entry_close(&effect->usbmic_hdl); + } +#endif + if (effect->aud_reverb) { + aud_reverb_close(effect->aud_reverb); + } + + if (effect->stream) { + audio_stream_close(effect->stream); + } + local_irq_disable(); + free(effect); + *hdl = NULL; + local_irq_enable(); + + mem_stats(); + clock_remove_set(REVERB_CLK); +} +/*----------------------------------------------------------------------------*/ +/**@brief 串流唤醒 + @param + @return + @note 暂未使用 +*/ +/*----------------------------------------------------------------------------*/ +static void mic_stream_resume(void *p) +{ + struct __mic_effect *effect = (struct __mic_effect *)p; + /* audio_decoder_resume_all(&decode_task); */ +} + +/*----------------------------------------------------------------------------*/ +/**@brief 串流数据处理长度回调 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void mic_effect_data_process_len(struct audio_stream_entry *entry, int len) +{ + + struct __mic_effect *effect = container_of(entry, struct __mic_effect, entry); + effect->out_len += len; + /* printf("out len[%d]",effect->out_len); */ +} + +static int mic_effect_record_stream_callback(void *priv, struct audio_data_frame *in) +{ + struct __mic_effect *effect = (struct __mic_effect *)priv; + + s16 *data = in->data; + u32 len = in->data_len; + + return recorder_mix_pcm_write((u8 *)data, len); +} +extern int usb_audio_mic_write_do(void *data, u16 len); +static int mic_effect_otherout_stream_callback(void *priv, struct audio_data_frame *in) +{ + struct __mic_effect *effect = (struct __mic_effect *)priv; + s16 *data = in->data; + u32 len = in->data_len; + +#if ((TCFG_USB_MIC_DATA_FROM_MICEFFECT||TCFG_USB_MIC_DATA_FROM_DAC)) + if (effect->usbmic_start) { + if (len) { + usb_audio_mic_write_do(data, len); + } + } else { + } +#endif + return len; +} + +void mic_effect_to_usbmic_onoff(u8 mark) +{ +#if (TCFG_USB_MIC_DATA_FROM_MICEFFECT||TCFG_USB_MIC_DATA_FROM_DAC) + if (__this) { + __this->usbmic_start = mark ? 1 : 0; + } +#endif +} + +static void inline rl_rr_mix_to_rl_rr(short *data, int len) +{ + s32 tmp32_1; + s32 tmp32_2; + s16 *inbuf = data; + inbuf = inbuf + 2; //定位到第三通道 + len >>= 3; + __asm__ volatile( + "1: \n\t" + "rep %0 { \n\t" + " %2 = h[%1 ++= 2](s) \n\t" //取第三通道值,并地址偏移两个字节指向第四通道数据 + " %3 = h[%1 ++= -2](s) \n\t" //取第四通道值,并地址偏移两个字节指向第三通道数据 + " %2 = %2 + %3 \n\t" + " %2 = sat16(%2)(s) \n\t" //饱和处理 + " h[%1 ++= 2] = %2 \n\t" //存取第三通道数据,并地址偏移两个字节指向第四通道数据 + " h[%1 ++= 6] = %2 \n\t" //存取第四通道数据,并地址偏移六个字节指向第三通道相邻的数据 + "} \n\t" + "if(%0 != 0) goto 1b \n\t" + : + "=&r"(len), + "=&r"(inbuf), + "=&r"(tmp32_1), + "=&r"(tmp32_2) + : + "0"(len), + "1"(inbuf), + "2"(tmp32_1), + "3"(tmp32_2) + : + ); +} +static int effect_to_dac_data_pro_handle(struct audio_stream_entry *entry, struct audio_data_frame *in) +{ +#if (SOUNDCARD_ENABLE) + if (in->data_len == 0) { + return 0; + } +#if 1 + rl_rr_mix_to_rl_rr(in->data, in->data_len);//汇编加速 +#else + s16 *outbuf = in->data; + s16 *inbuf = in->data; + s32 tmp32; + u16 len = in->data_len; + len >>= 3; + while (len--) { + *outbuf++ = inbuf[0]; + *outbuf++ = inbuf[1]; + tmp32 = (inbuf[2] + inbuf[3]); + if (tmp32 < -32768) { + tmp32 = -32768; + } else if (tmp32 > 32767) { + tmp32 = 32767; + } + *outbuf++ = tmp32; + *outbuf++ = tmp32; + inbuf += 4; + } +#endif +#endif + return 0; +} + +#if TCFG_APP_RECORD_EN +static int prob_handler_to_record(struct audio_stream_entry *entry, struct audio_data_frame *in) +{ + if (app_get_curr_task() != APP_RECORD_TASK) { + return 0; + } + if (in->data_len == 0) { + return 0; + } + if (recorder_is_encoding() == 0) { + return 0; + } + int wlen = recorder_userdata_to_enc(in->data, in->data_len); + if (wlen != in->data_len) { + putchar('N'); + } + return 0; +} +#endif + +int audio_data_check_cb(struct audio_stream_entry *entry, struct audio_data_frame *data_buf) +{ + + if (__this) { + loudness_meter_short(&__this->loudness_drc_out, data_buf->data, data_buf->data_len / 2); + } + return data_buf->data_len; +} + +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR || TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_DUAL_LR_DIFF) +#define DAC_OUTPUT_CHANNELS 2 +#elif (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_L || TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_R || TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_LR_DIFF) +#define DAC_OUTPUT_CHANNELS 1 +#elif (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) +#define DAC_OUTPUT_CHANNELS 4 +#else +#define DAC_OUTPUT_CHANNELS 3 +#endif + +static u8 reverb_mode = 0; +void switch_mic_effect_mode(void) +{ + reverb_mode++; + if (reverb_mode > 2) { + reverb_mode = 0; + } + printf("\n--func=%s [%d] \n", __FUNCTION__, reverb_mode); + + set_mic_reverb_mode_by_id(reverb_mode); +} +/*----------------------------------------------------------------------------*/ +/**@brief (mic数据流)混响打开接口 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +bool mic_effect_start(void) +{ + bool ret = false; + mem_stats(); + printf("\n--func=%s\n", __FUNCTION__); + if (__this) { + log_e("reverb is already start \n"); + return ret; + } + struct __mic_effect *effect = (struct __mic_effect *)zalloc(sizeof(struct __mic_effect)); + if (effect == NULL) { + return false; + } + u8 mode = get_mic_eff_mode(); + clock_add_set(REVERB_CLK); + os_mutex_create(&effect->mutex); + memcpy(&effect->parm, &effect_parm_default, sizeof(struct __mic_effect_parm)); + struct __mic_stream_parm *mic_parm = (struct __mic_stream_parm *)&effect_mic_stream_parm_default; + if (g_mic_parm) { + mic_parm = g_mic_parm; + } + +#if LOUDNESS_DEBUG_ENABLE + loudness_meter_init(&effect->loudness_adc, effect_mic_stream_parm_default.sample_rate, 50, 1); + loudness_meter_init(&effect->loudness_drc_out, effect_mic_stream_parm_default.sample_rate, 50, 2); + effect->loudness_debug_hdl = stream_entry_open(effect, audio_data_check_cb, 0);// 能量计算及打印节点 +#endif + if ((effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_REVERB)) + && (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_ECHO))) { + log_e("effect config err ?? !!!, cann't support echo && reverb at the same time\n"); + mic_effect_destroy(&effect); + return false; + } + u16 irq_points = mic_parm->point_unit; + u8 ch_num = 1; //?? + effect->input_ch_num = ch_num; +#if TCFG_MIC_DODGE_EN + if (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_ENERGY_DETECT)) { + effect->energy_hdl = mic_energy_detect_open(effect->parm.sample_rate, ch_num); + effect->dodge_en = 0;//默认关闭, 需要通过按键触发打开 + } +#endif + ///声音门限初始化 + if (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_NOISEGATE)) { + NoiseGateParam noisegate_parm = { + .attackTime = eff_mode[mode].noise_gate_parm.parm.attackTime, + .releaseTime = eff_mode[mode].noise_gate_parm.parm.releaseTime, + .threshold = eff_mode[mode].noise_gate_parm.parm.threshold, + .low_th_gain = eff_mode[mode].noise_gate_parm.parm.low_th_gain, + .sampleRate = MIC_EFFECT_SAMPLERATE, + .channel = ch_num, + }; + effect->noisegate = open_noisegate((NoiseGateParam *)&noisegate_parm); + } + +///啸叫抑制初始化 + if (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_HOWLING)) { + log_i("open_howling\n\n\n"); + effect->howling_ps = open_howling(NULL, effect->parm.sample_rate, 0, 1);//以频 + } + + if (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_HOWLING_TRAP)) { + log_i("open_howling\n\n\n"); + + HOWLING_PARM_SET howling_param = { + .threshold = eff_mode[mode].notchhowling_parm.parm.threshold, + .fade_time = eff_mode[mode].notchhowling_parm.parm.fade_n, + .notch_Q = eff_mode[mode].notchhowling_parm.parm.Q, + .notch_gain = eff_mode[mode].notchhowling_parm.parm.gain, + .sample_rate = MIC_EFFECT_SAMPLERATE, + .channel = 1, + + }; +#if (TCFG_USER_TWS_ENABLE == 0) + effect->notch_howling = open_howling(&howling_param, effect->parm.sample_rate, 0, 0);//陷波 +#endif + } + +#if defined(TCFG_MIC_VOICE_CHANGER_ENABLE) && TCFG_MIC_VOICE_CHANGER_ENABLE + effect->voice_changer = audio_voice_changer_open_demo(AEID_MIC_VOICE_CHANGER, effect->parm.sample_rate); +#endif + + log_i("effect->parm.sample_rate %d\n", effect->parm.sample_rate); + effect->mic_eq0 = mic_eq_open(effect->parm.sample_rate, ch_num, AEID_MIC_EQ0); + if (effect->mic_eq0 && effect->mic_eq0->out_32bit) { + effect->mic_drc0 = mic_drc_open(effect->parm.sample_rate, ch_num, AEID_MIC_DRC0); + effect->convert0 = convet_data_open(0, (irq_points << 1) * ch_num); + } + + effect->mic_eq3 = mic_eq_open(effect->parm.sample_rate, ch_num, AEID_MIC_EQ3); + if (effect->mic_eq3 && effect->mic_eq3->out_32bit) { + effect->mic_drc3 = mic_drc_open(effect->parm.sample_rate, ch_num, AEID_MIC_DRC3); + } + +// sub 0 分流节点 + if (TCFG_MIC_EFFECT_SEL & MIC_EFFECT_ECHO) { + effect->sub_1_echo_hdl = open_echo((ECHO_PARM_SET *)&eff_mode[mode].echo_parm.parm, (EF_REVERB_FIX_PARM *)&effect_echo_fix_parm_default); + + if (effect->sub_1_echo_hdl) { + effect->mic_eq2 = mic_eq_open(effect->parm.sample_rate, ch_num, AEID_MIC_EQ2); + if (effect->mic_eq2 && effect->mic_eq2->out_32bit) { + effect->mic_drc2 = mic_drc_open(effect->parm.sample_rate, ch_num, AEID_MIC_DRC2); + } + } + } + + if (TCFG_MIC_EFFECT_SEL & MIC_EFFECT_REVERB) { + effect->sub_0_plate_reverb_hdl = open_plate_reverb((Plate_reverb_parm *)&eff_mode[mode].plate_reverb_parm.parm, effect->parm.sample_rate); + if (effect->sub_0_plate_reverb_hdl) { + ch_num = 2; + } + + effect->mic_eq1 = mic_eq_open(effect->parm.sample_rate, ch_num, AEID_MIC_EQ1); + if (effect->mic_eq1 && effect->mic_eq1->out_32bit) { + effect->mic_drc1 = mic_drc_open(effect->parm.sample_rate, ch_num, AEID_MIC_DRC1); + } + } + + //多路混合后 EQ drc +#if TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE + effect->mic_eq4 = mic_eq_open(effect->parm.sample_rate, ch_num, AEID_MIC_EQ4); + if (effect->mic_eq4 && effect->mic_eq4->out_32bit) { + effect->mic_drc4 = mic_drc_open(effect->parm.sample_rate, ch_num, AEID_MIC_DRC4); + effect->convert4 = convet_data_open(0, (irq_points << 1) * ch_num); + } +#endif/*TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE*/ + + effect->gain = audio_gain_open_demo(AEID_MIC_GAIN, ch_num); + + ///初始化数字音量 + if (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_DVOL)) { + effect_dvol_default_parm.ch_total = ch_num; + struct audio_stream_entry *dvol_entry; +#if SYS_DIGVOL_GROUP_EN + dvol_entry = sys_digvol_group_ch_open("mic_mic", -1, &effect_dvol_default_parm); + effect->d_vol = audio_dig_vol_group_hdl_get(sys_digvol_group, "mic_mic"); +#else + effect->d_vol = audio_dig_vol_open((audio_dig_vol_param *)&effect_dvol_default_parm); + dvol_entry = audio_dig_vol_entry_get(effect->d_vol); +#endif /*SYS_DIGVOL_GROUP_EN*/ + } + + //打开混响变采样 + if (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_SOFT_SRC)) { + u32 out_sr = audio_output_nor_rate(); + + effect->src_hdl = zalloc(sizeof(struct audio_src_handle)); + audio_hw_src_open(effect->src_hdl, ch_num, SRC_TYPE_RESAMPLE); + audio_hw_src_set_rate(effect->src_hdl, effect->parm.sample_rate, out_sr); + } + + //混响通路混合linein + if (effect->parm.effect_config & BIT(MIC_EFFECT_CONFIG_LINEIN)) { + effect->linein = effect_linein_open(); + } + + u8 output_channels = DAC_OUTPUT_CHANNELS; + if (output_channels != ch_num) { + u32 points_num = REVERB_LADC_IRQ_POINTS * 4; + effect->channel_zoom = channel_switch_open(output_channels == 2 ? AUDIO_CH_LR : (output_channels == 4 ? AUDIO_CH_QUAD : AUDIO_CH_DIFF), output_channels == 4 ? (points_num * 2 + 128) : 1024); + //effect->channel_zoom = channel_switch_open(AUDIO_CH_LR, 1024); + } + + effect->dac = (struct audio_dac_channel *)zalloc(sizeof(struct audio_dac_channel)); + if (effect->dac) { + audio_dac_new_channel(&dac_hdl, effect->dac); + struct audio_dac_channel_attr attr; + audio_dac_channel_get_attr(effect->dac, &attr); + attr.delay_time = mic_parm->dac_delay; + attr.write_mode = WRITE_MODE_FORCE; + audio_dac_channel_set_attr(effect->dac, &attr); + effect->dac->entry.prob_handler = effect_to_dac_data_pro_handle; + /* audio_dac_channel_set_pause(effect->dac,1); */ + } + + effect->entry.data_process_len = mic_effect_data_process_len; + +#if (RECORDER_MIX_EN) + ///送录音数据流 + effect->rec_hdl = stream_entry_open(effect, mic_effect_record_stream_callback, 1); +#endif +#if (TCFG_USB_MIC_DATA_FROM_MICEFFECT||TCFG_USB_MIC_DATA_FROM_DAC) + effect->usbmic_hdl = stream_entry_open(effect, mic_effect_otherout_stream_callback, 1); +#endif + + u8 bit_wide = 0; + if (effect->mic_eq1 && effect->mic_eq1->out_32bit) { + bit_wide = 1; + } + +#if(TCFG_MIC_EFFECT_SEL != MIC_EFFECT_MEGAPHONE) + effect->aud_reverb = aud_reverb_open(effect, bit_wide); +#endif + +// 数据流串联 + struct audio_stream_entry *entries[25] = {NULL}; + u8 entry_cnt = 0; + entries[entry_cnt++] = &effect->entry; + +#if TCFG_MIC_DODGE_EN + if (effect->energy_hdl) { + entries[entry_cnt++] = audio_energy_detect_entry_get(effect->energy_hdl); + } +#endif + if (effect->noisegate) { + entries[entry_cnt++] = &effect->noisegate->entry; + } + + if (effect->mic_eq0) { + entries[entry_cnt++] = &effect->mic_eq0->entry; + if (effect->mic_eq0->out_32bit) { + if (effect->mic_drc0) { + entries[entry_cnt++] = &effect->mic_drc0->entry; + } + if (effect->convert0) { + entries[entry_cnt++] = &effect->convert0->entry; + } + } + } + + if (effect->howling_ps) { + entries[entry_cnt++] = &effect->howling_ps->entry; + } + if (effect->notch_howling) { + entries[entry_cnt++] = &effect->notch_howling->entry; + } + if (effect->voice_changer) { + entries[entry_cnt++] = &effect->voice_changer->entry; + } + if (effect->aud_reverb) { + entries[entry_cnt++] = &effect->aud_reverb->entry; + } + + + if (effect->mic_eq4) { + entries[entry_cnt++] = &effect->mic_eq4->entry; + if (effect->mic_eq4->out_32bit) { + if (effect->mic_drc4) { + entries[entry_cnt++] = &effect->mic_drc4->entry; + } + if (effect->convert4) { + entries[entry_cnt++] = &effect->convert4->entry; + } + } + } + if (effect->gain) { + entries[entry_cnt++] = &effect->gain->entry; + } + if (effect->loudness_debug_hdl) { + entries[entry_cnt++] = &effect->loudness_debug_hdl->entry; + } + + if (effect->channel_zoom) { + entries[entry_cnt++] = &effect->channel_zoom->entry; + } + if (effect->dac) { + entries[entry_cnt++] = &effect->dac->entry; +#if (TCFG_USB_MIC_DATA_FROM_DAC) + if (effect->usbmic_hdl) { + entries[entry_cnt++] = &effect->usbmic_hdl->entry; + } +#endif + } + + effect->stream = audio_stream_open(effect, mic_stream_resume); + audio_stream_add_list(effect->stream, entries, entry_cnt); + + /* effect->main_pause = 2; */ + ///mic 数据流初始化 + effect->mic = mic_stream_creat(mic_parm); + if (effect->mic == NULL) { + mic_effect_destroy(&effect); + return false; + } + mic_stream_set_output(effect->mic, (void *)effect, mic_effect_effect_run); + mic_stream_start(effect->mic); +#if (RECORDER_MIX_EN) + recorder_mix_pcm_stream_open(effect->parm.sample_rate, ch_num); +#endif + + clock_set_cur(); + __this = effect; + + + log_info("--------------------------effect start ok\n"); + mem_stats(); + + mic_effect_change_mode(mode); + + return true; +} + +/*----------------------------------------------------------------------------*/ +/**@brief mic增益调节 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +/* void mic_effect_mic_gain_parm_fill(EFFECTS_MIC_GAIN_PARM *parm, u8 fade, u8 online) */ +/* { */ +/* if (__this == NULL || parm == NULL) { */ +/* return ; */ +/* } */ +/* audio_mic_set_gain(parm->gain); */ +/* } */ +/*----------------------------------------------------------------------------*/ +/**@brief mic效果模式切换(数据流音效组合切换) + @param + @return + @note 使用效果配置文件时生效 +*/ +/*----------------------------------------------------------------------------*/ +void mic_effect_change_mode(u16 mode) +{ + set_mic_reverb_mode_by_id(mode); +} +/*----------------------------------------------------------------------------*/ +/**@brief 获取mic效果模式(数据流音效组合) + @param + @return + @note 使用效果配置文件时生效 +*/ +/*----------------------------------------------------------------------------*/ +u16 mic_effect_get_cur_mode(void) +{ + /* return effect_cfg_get_cur_mode(); */ + return 0; +} + +void *mic_eq_open(u32 sample_rate, u8 ch_num, u8 eq_name) +{ +#if TCFG_EQ_ENABLE + +#if(TCFG_MIC_EFFECT_SEL == MIC_EFFECT_MEGAPHONE) + if ((eq_name == AEID_MIC_EQ1) || (eq_name == AEID_MIC_EQ2) || (eq_name == AEID_MIC_EQ3)) { + return NULL; + } +#endif + + + u8 mode = get_mic_eff_mode(); + + struct audio_eq_param parm = {0}; + parm.channels = ch_num; + if ((eq_name == AEID_MIC_EQ0) || (eq_name == AEID_MIC_EQ4)) { + parm.out_32bit = 1;//32bit位宽输出 + } + parm.no_wait = 0;//同步方式 + parm.cb = eq_get_filter_info; + parm.sr = sample_rate; + parm.eq_name = eq_name; + + u8 index = get_eq_module_index(eq_name); + log_d("index %d\n", index); + parm.max_nsection = eff_mode[mode].eq_parm[index].seg_num; + parm.nsection = eff_mode[mode].eq_parm[index].seg_num; + parm.seg = eff_mode[mode].eq_parm[index].seg; + parm.global_gain = eff_mode[mode].eq_parm[index].global_gain; + log_d("=====mic eq_name %d\n", eq_name); + struct audio_eq *eq = audio_dec_eq_open(&parm); + return eq; + +#else + return NULL; +#endif//TCFG_EQ_ENABLE +} + +void *mic_drc_open(u32 sample_rate, u8 ch_num, u8 drc_name) +{ +#if TCFG_DRC_ENABLE + u8 mode = get_mic_eff_mode(); + log_i("sample_rate %d %d\n", sample_rate, ch_num); + struct audio_drc_param parm = {0}; + parm.channels = ch_num; + parm.sr = sample_rate; + parm.out_32bit = 1; + parm.cb = drc_get_filter_info; + parm.drc_name = drc_name; + u8 index = get_drc_module_index(drc_name); + parm.wdrc = &eff_mode[mode].drc_parm[index]; + log_d("=====drc_name %d\n", drc_name); + struct audio_drc *drc = audio_dec_drc_open(&parm); + clock_add(EQ_CLK); + return drc; +#else + return NULL; +#endif//TCFG_DRC_ENABLE + +} + +void mic_eq_close(void *eq) +{ +#if TCFG_EQ_ENABLE + if (eq) { + audio_dec_eq_close(eq); + clock_remove(EQ_CLK); + } +#endif + return; +} + +void mic_drc_close(void *drc) +{ +#if TCFG_DRC_ENABLE + if (drc) { + audio_dec_drc_close(drc); + drc = NULL; + clock_remove(EQ_CLK); + } +#endif + return; +} + + + + + +#if TCFG_MIC_DODGE_EN +void mic_e_det_handler(u8 event, u8 ch) +{ + //printf(">>>> ch:%d %s\n", ch, event ? ("MUTE") : ("UNMUTE")); + struct __mic_effect *effect = (struct __mic_effect *)__this; +#if SYS_DIGVOL_GROUP_EN + //printf("effect_dvol_default_parm.ch_total %d effect->dodge_en %d\n", effect_dvol_default_parm.ch_total, effect->dodge_en); + if (ch == effect_dvol_default_parm.ch_total) { + if (effect->dodge_en) { + if (effect && effect->d_vol) { + if (event) { //推出闪避 + audio_dig_vol_group_dodge(sys_digvol_group, "mic_mic", 100, 100); + } else { //启动闪避 + audio_dig_vol_group_dodge(sys_digvol_group, "mic_mic", 100, 0); + } + } + } + } +#endif +} +/*----------------------------------------------------------------------------*/ +/**@brief 打开mic 能量检测 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void *mic_energy_detect_open(u32 sr, u8 ch_num) +{ + audio_energy_detect_param e_det_param = {0}; + e_det_param.mute_energy = dodge_parm.dodge_out_thread;//人声能量小于mute_energy 退出闪避 + e_det_param.unmute_energy = dodge_parm.dodge_in_thread;//人声能量大于 100触发闪避 + e_det_param.mute_time_ms = dodge_parm.dodge_out_time_ms; + e_det_param.unmute_time_ms = dodge_parm.dodge_in_time_ms; + e_det_param.count_cycle_ms = 2; + e_det_param.sample_rate = sr; + e_det_param.event_handler = mic_e_det_handler; + e_det_param.ch_total = ch_num; + e_det_param.dcc = 1; + void *audio_e_det_hdl = audio_energy_detect_open(&e_det_param); + return audio_e_det_hdl; +} +/*----------------------------------------------------------------------------*/ +/**@brief 关闭mic 能量检测 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void mic_energy_detect_close(void *hdl) +{ + if (hdl) { + audio_stream_del_entry(audio_energy_detect_entry_get(hdl)); +#if SYS_DIGVOL_GROUP_EN + struct __mic_effect *effect = (struct __mic_effect *)__this; + if (effect->d_vol) { + audio_dig_vol_group_dodge(sys_digvol_group, "mic_mic", 100, 100); // undodge + } +#endif + + audio_energy_detect_close(hdl); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 能量检测运行过程,是否触发闪避 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void mic_dodge_ctr(void) +{ + struct __mic_effect *effect = (struct __mic_effect *)__this; + if (effect) { + effect->dodge_en = !effect->dodge_en; + } +} +u8 mic_dodge_get_status(void) +{ + struct __mic_effect *effect = (struct __mic_effect *)__this; + if (effect) { + return effect->dodge_en; + } + return 0; +} +#endif + +/*----------------------------------------------------------------------------*/ +/**@brief (mic数据流)混响关闭接口 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void mic_effect_stop(void) +{ + mic_effect_destroy(&__this); +} +/*----------------------------------------------------------------------------*/ +/**@brief (mic数据流)混响暂停接口(整个数据流不运行) + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void mic_effect_pause(u8 mark) +{ + if (__this) { + __this->pause_mark = mark ? 1 : 0; + } +} +/*----------------------------------------------------------------------------*/ +/**@brief (mic数据流)混响状态获取接口 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 mic_effect_get_status(void) +{ + return ((__this) ? 1 : 0); +} + + + + +void plate_reverb_update_parm(void *parm, int bypass) +{ + if (__this && __this->sub_0_plate_reverb_hdl) { + update_plate_reverb_parm(__this->sub_0_plate_reverb_hdl, parm); + plate_reverb_update_bypass(__this->sub_0_plate_reverb_hdl, bypass); + } +} + +void echo_updata_parm(void *parm, int bypass) +{ + if (__this && __this->sub_1_echo_hdl) { + update_echo_parm(__this->sub_1_echo_hdl, parm); + echo_update_bypass(__this->sub_1_echo_hdl, bypass); + } +} + +void noisegate_update_parm(void *parm, int bypass) +{ + if (__this && __this->noisegate) { + update_noisegate(__this->noisegate, parm); + noisegate_bypass(__this->noisegate, bypass); + } +} + +void howling_pitch_shift_update_parm(void *parm, int bypass) +{ + if (__this && __this->howling_ps) { + update_howling_parm(__this->howling_ps, parm); + howling_update_bypass(__this->howling_ps, bypass); + } +} + +void notchhowline_update_parm(void *parm, int bypass) +{ + if (__this && __this->notch_howling) { + update_howling_parm(__this->notch_howling, parm); + howling_update_bypass(__this->notch_howling, bypass); + } + +} +u8 mic_effect_get_micgain(void) +{ + //动态调的需实时记录 + return effect_mic_stream_parm_default.mic_gain; +} +#endif diff --git a/cpu/br23/audio_mic/mic_effect.h b/cpu/br23/audio_mic/mic_effect.h new file mode 100644 index 0000000..d856e74 --- /dev/null +++ b/cpu/br23/audio_mic/mic_effect.h @@ -0,0 +1,288 @@ +#ifndef __MIC_EFFECT_H__ +#define __MIC_EFFECT_H__ + + + +#include "system/includes.h" +#include "audio_mic/effect_reg.h" +#include "audio_mic/effect_parm.h" +#include "app_config.h" +#include "application/audio_pemafrow.h" +/* enum { */ +// MIC_EQ_MODE_SHOUT_WHEAT = 0x0, +// MIC_EQ_MODE_LOW_SOUND, +// MIC_EQ_MODE_HIGH_SOUND, +/* }; */ + +void switch_mic_effect_mode(void); +void set_mic_reverb_mode(void); +void switch_mic_agc(void); +/*----------------------------------------------------------------------------*/ +/**@brief (mic数据流)混响打开接口 + @param + @return true - 成功, false - 失败. + @note +*/ +/*----------------------------------------------------------------------------*/ +bool mic_effect_start(void); + +/*----------------------------------------------------------------------------*/ +/**@brief (mic数据流)混响关闭接口 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void mic_effect_stop(void); + + +/*----------------------------------------------------------------------------*/ +/**@brief (mic数据流)混响暂停接口(数据置0) + @param mark :1 暂停 0:恢复 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void mic_effect_pause(u8 mark); + + +/*----------------------------------------------------------------------------*/ +/**@brief (mic数据流)混响暂停输出到DAC(数据流后级不写入DAC) + @param mark :1 暂停 0:恢复 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void mic_effect_dac_pause(u8 mark); + +/*----------------------------------------------------------------------------*/ +/**@brief (mic数据流)混响状态获取接口 + @param + @return true - 运行, false - 未启动 + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 mic_effect_get_status(void); + +/*----------------------------------------------------------------------------*/ +/**@brief 数字音量调节接口 + @param vol 待设置的音量值[0,31] + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void mic_effect_set_dvol(u8 vol); + +/*----------------------------------------------------------------------------*/ +/**@brief 获取数字音量接口 + @param + @return 当前数字数字音量等级 + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 mic_effect_get_dvol(void); + + +/*----------------------------------------------------------------------------*/ +/**@brief 获取默认mic增益 + @param + @return 默认mic增益值 + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 mic_effect_get_micgain(void); + + +/*----------------------------------------------------------------------------*/ +/**@brief 设置reverb 湿声增益 + @param 待设增益值[0,300] + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void mic_effect_set_reverb_wet(int wet); + +/*----------------------------------------------------------------------------*/ +/**@brief 获取当前reverb混响湿声增益值 + @param + @return 当前增益值[0,300] + @note +*/ +/*----------------------------------------------------------------------------*/ +int mic_effect_get_reverb_wet(void); + + +/*----------------------------------------------------------------------------*/ +/**@brief 设置echo 回声延时 + @param delay 回声延时[0,max_ms] + @return + @note 默认max_ms = 200 +*/ +/*----------------------------------------------------------------------------*/ +void mic_effect_set_echo_delay(u32 delay); + +/*----------------------------------------------------------------------------*/ +/**@brief 获取当前 echo 回声延时值 + @param + @return 当前回声延时delay值 + @note +*/ +/*----------------------------------------------------------------------------*/ +u32 mic_effect_get_echo_delay(void); + + +/*----------------------------------------------------------------------------*/ +/**@brief 设置echo 回声衰减系数 + @param decay 衰减系数值[0,70] + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void mic_effect_set_echo_decay(u32 decay); + + +/*----------------------------------------------------------------------------*/ +/**@brief 获取echo 回声衰减系数 + @param + @return 当前衰减系数值 + @note +*/ +/*----------------------------------------------------------------------------*/ +u32 mic_effect_get_echo_decay(void); + + +/* [>----------------------------------------------------------------------------<] */ +// [>*@brief mic_effect_cal_coef 混响喊麦、高低音 调节接口 +// @param type :MIC_EQ_MODE_SHOUT_WHEAT 喊麦模式,gainN:喊麦开关,0:关喊麦, 1:开喊麦 +// @param type:MIC_EQ_MODE_LOW_SOUND 低音调节 gainN:调节的增益,范围0~10 +// @param type:MIC_EQ_MODE_HIGH_SOUND 高音调节 gainN:调节的增益,范围0~10 +// @return +// @note 混响喊麦、高低音调节 +// */ +// [>----------------------------------------------------------------------------<] +// void mic_effect_cal_coef(u8 type, u32 gainN); + + +// [>----------------------------------------------------------------------------<] +// [>*@brief 获取EQ段数 +// @param +// @return 当前EQ使用的段数 +// @note +// */ +// [>----------------------------------------------------------------------------<] +/* u8 mic_effect_eq_section_num(void); */ + + + +/*----------------------------------------------------------------------------*/ +/**@brief mic数据流参数更新 + @param parm 新参数, + @return + @note 暂未使用 +*/ +/*----------------------------------------------------------------------------*/ +void mic_effect_set_mic_parm(struct __mic_stream_parm *parm); + + + +/*----------------------------------------------------------------------------*/ +/**@brief 设置变声模式 + @param shiftv: 变声模式 + sr :数据采样率 + effect:变调比例[40,230] + formant_shift:共振峰偏移比例 [40,230] + @return + @note + 模式配置说明: + 1.EFFECT_PITCH_SHIFT 移频,变调不变速,shiftv调节有效,formant_shift调节无效 + 2.EFFECT_VOICECHANGE_KIN0 变声,可以调节不同的 shiftv 跟 formant_shift ,调出更多的声音效果 + 3.EFFECT_VOICECHANGE_KIN1 变声,同EFFECT_VOICECHANGE_KIN0类似的,但是2者由于运算的不同,会有区别。 + 4.EFFECT_ROBORT 机器音效果,类似 喜马拉雅那样的 + 5.EFFECT_AUTOTUNE 电音效果 +*/ +/*----------------------------------------------------------------------------*/ +// void set_pitch_para(u32 shiftv, u32 sr, u8 effect, u32 formant_shift); + + +/*----------------------------------------------------------------------------*/ +/**@brief 设置音效模式 + @param mode 模式索引 + @return + @note 模式与工具调试出的效果文件对应 + 模式在effect_reg_echo.c和effect_reg_reverb.c中定义 +*/ +/*----------------------------------------------------------------------------*/ +void mic_effect_change_mode(u16 mode); + +/*----------------------------------------------------------------------------*/ +/**@brief 获取音效模式 + @param + @return 模式索引 + @note 未使用效果文件时无效 +*/ +/*----------------------------------------------------------------------------*/ +u16 mic_effect_get_cur_mode(void); + + + +/*----------------------------------------------------------------------------*/ +/**@brief 能量检测运行过程,是否触发闪避 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void mic_dodge_ctr(void); + + +/*----------------------------------------------------------------------------*/ +/**@brief 能量检测运行过程,是否触发闪避 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 mic_dodge_get_status(void); + +/*----------------------------------------------------------------------------*/ +/**@brief mic eq信息获取接口 + @param index:获取第几段eq + @return 返回struct eq_seg_info结构体 + @note +*/ +/*----------------------------------------------------------------------------*/ +struct eq_seg_info *mic_eq_get_info(u16 index); + +/*----------------------------------------------------------------------------*/ +/**@brief mic eq设置接口 + @param 详见struct eq_seg_info结构体 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ + +int mic_eq_set_info(struct eq_seg_info *info); + +/*----------------------------------------------------------------------------*/ +/**@brief K歌模式音效切换例程 + @param eff_mode 模式索引 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void mic_mode_switch(u8 eff_mode); + + +/*----------------------------------------------------------------------------*/ +/**@brief 混响mic数据到USB mic 开关 + @param mark : true 开 false 关 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void mic_effect_to_usbmic_onoff(u8 mark); + + + + +#endif// __MIC_EFFECT_H__ diff --git a/cpu/br23/audio_mic/mic_stream.c b/cpu/br23/audio_mic/mic_stream.c new file mode 100644 index 0000000..d78c19b --- /dev/null +++ b/cpu/br23/audio_mic/mic_stream.c @@ -0,0 +1,235 @@ +#include "mic_stream.h" +#include "app_config.h" +#include "system/includes.h" +#include "audio_splicing.h" +#include "audio_config.h" +#include "asm/dac.h" +#include "audio_enc.h" +#include "audio_dec.h" +#include "media/includes.h" +#include "application/audio_dig_vol.h" +#include "media/pcm_decoder.h" + + +#if (TCFG_MIC_EFFECT_ENABLE) + +#define MIC_STREAM_TASK_NAME "mic_stream" + +#ifdef SUPPORT_MS_EXTENSIONS +//#pragma bss_seg(".audio_mic_stream_bss") +//#pragma data_seg(".audio_mic_stream_data") +#pragma const_seg(".audio_mic_stream_const") +#pragma code_seg(".audio_mic_stream_code") +#endif + + +static struct __mic_stream *mic = NULL; +#define __this mic + +#define MIC_SIZEOF_ALIN(var,al) ((((var)+(al)-1)/(al))*(al)) + +/* extern struct audio_dac_hdl dac_hdl; */ +/* extern struct audio_mixer mixer; */ + +/*----------------------------------------------------------------------------*/ +/**@brief 唤醒mic数据处理任务 + @param + @return + @note + */ +/*----------------------------------------------------------------------------*/ +void mic_stream_adc_resume(void *priv) +{ + struct __mic_stream *stream = (struct __mic_stream *)priv; + if (stream != NULL && (stream->release == 0)) { + os_sem_set(&stream->sem, 0); + os_sem_post(&stream->sem); + } +} +/*----------------------------------------------------------------------------*/ +/**@brief mic数据处理函数 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ + +static int mic_stream_effects_run(struct __mic_stream *stream) +{ + int res = os_sem_pend(&stream->sem, 0); + if (res) { + return -1; + } + if (stream->release) { + return -1; + } + s16 *read_buf = (s16 *)(stream->adc_buf); + if (stream->out.func) { + stream->out.func(stream->out.priv, read_buf, NULL, stream->parm->point_unit * 2, stream->parm->point_unit * 2 * 2); + } + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief mic数据处理任务 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void mic_stream_task_deal(void *p) +{ + int res = 0; + struct __mic_stream *stream = (struct __mic_stream *)p; + stream->busy = 1; + while (1) { + res = mic_stream_effects_run(stream); + if (res) { + ///等待删除线程 + stream->busy = 0; + while (1) { + os_time_dly(10000); + } + } + } +} +/*----------------------------------------------------------------------------*/ +/**@brief 创建mic数据流 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +struct __mic_stream *mic_stream_creat(struct __mic_stream_parm *parm) +{ + int err = 0; + struct __mic_stream_parm *p = parm; + if (parm == NULL) { + printf("%s parm err\n", __FUNCTION__); + return NULL; + } + printf("p->dac_delay = %d\n", p->dac_delay); + printf("p->point_unit = %d\n", p->point_unit); + printf("p->sample_rate = %d\n", p->sample_rate); + + u32 offset = 0; + u32 buf_size = MIC_SIZEOF_ALIN(sizeof(struct __mic_stream), 4); + + u8 *buf = zalloc(buf_size); + if (buf == NULL) { + return NULL; + } + + struct __mic_stream *stream = (struct __mic_stream *)buf; + offset += MIC_SIZEOF_ALIN(sizeof(struct __mic_stream), 4); + + stream->parm = p; + os_sem_create(&stream->sem, 0); + err = task_create(mic_stream_task_deal, (void *)stream, MIC_STREAM_TASK_NAME); + if (err != OS_NO_ERR) { + printf("%s creat fail %x\n", __FUNCTION__, err); + free(stream); + return NULL; + } + + local_irq_disable(); + __this = stream; + local_irq_enable(); + + printf("mic stream creat ok\n"); + return stream; +} +/*----------------------------------------------------------------------------*/ +/**@brief 设置mic处理函数的回调处理 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void mic_stream_set_output(struct __mic_stream *stream, void *priv, u32(*func)(void *priv, void *in, void *out, u32 inlen, u32 outlen)) +{ + if (stream) { + stream->out.priv = priv; + stream->out.func = func; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief mic中断数据输出回调函数 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void adc_output_to_buf(void *priv, s16 *data, int len) +{ + struct __mic_stream *stream = (struct __mic_stream *)priv; + int wlen = 0; + if (stream != NULL && (stream->release == 0)) { + stream->adc_buf = data; + stream->adc_buf_len = len; + os_sem_set(&stream->sem, 0); + os_sem_post(&stream->sem); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 打开mic + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +bool mic_stream_start(struct __mic_stream *stream) +{ + if (stream) { + if (audio_mic_open(&stream->mic_ch, stream->parm->sample_rate, stream->parm->mic_gain) == 0) { + stream->adc_output.handler = adc_output_to_buf; + stream->adc_output.priv = stream; + audio_mic_add_output(&stream->adc_output); + audio_mic_start(&stream->mic_ch); + audio_mic_0dB_en(1);//关闭mic前置6dB增益,默认打开 + log_i("mic_stream_start ok 11\n"); + return true; + } + } + return false; +} +/*----------------------------------------------------------------------------*/ +/**@brief 关闭mic数据流 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void mic_stream_destroy(struct __mic_stream **hdl) +{ + int err = 0; + if ((hdl == NULL) || (*hdl == NULL)) { + return ; + } + + struct __mic_stream *stream = *hdl; + stream->release = 1; + + os_sem_set(&stream->sem, 0); + os_sem_post(&stream->sem); + + while (stream->busy) { + os_time_dly(5); + } + audio_mic_close(&stream->mic_ch, &stream->adc_output); + printf("%s wait busy ok!!!\n", __FUNCTION__); + + err = task_kill(MIC_STREAM_TASK_NAME); + os_sem_del(&stream->sem, 0); + + local_irq_disable(); + free(*hdl); + *hdl = NULL; + __this = NULL; + local_irq_enable(); +} + +#endif//TCFG_MIC_EFFECT_ENABLE + + diff --git a/cpu/br23/audio_mic/mic_stream.h b/cpu/br23/audio_mic/mic_stream.h new file mode 100644 index 0000000..2aa871b --- /dev/null +++ b/cpu/br23/audio_mic/mic_stream.h @@ -0,0 +1,92 @@ +#ifndef __MIC_STREAM_H__ +#define __MIC_STREAM_H__ + +#include "system/includes.h" +#include "media/includes.h" +enum { + MIC_EFFECT_CONFIG_REVERB = 0x0, //声卡混响 + MIC_EFFECT_CONFIG_ECHO, //K歌混响 + MIC_EFFECT_CONFIG_PITCH, //变声 + MIC_EFFECT_CONFIG_NOISEGATE, //噪声压制,主要压制无人声时底噪 + MIC_EFFECT_CONFIG_DODGE, //闪避 + MIC_EFFECT_CONFIG_DVOL, //数字音量 + MIC_EFFECT_CONFIG_HOWLING, //移频啸叫抑制 + MIC_EFFECT_CONFIG_HOWLING_TRAP, //陷波啸叫抑制 + MIC_EFFECT_CONFIG_FILT, //高低音处理,新版本 与EQ合并 + MIC_EFFECT_CONFIG_EQ, //MIC EQ + MIC_EFFECT_CONFIG_ENERGY_DETECT,//能量检测 + MIC_EFFECT_CONFIG_SOFT_SRC, //变采样 + MIC_EFFECT_CONFIG_LINEIN, //linein 叠加,仅限声卡使用 + MIC_EFFECT_CONFIG_DIGIT_ENHANCE,//数字放大,提升mic灵敏度 + MIC_EFFECT_CONFIG_DEBUG_SOUND_PRESSURE,//实时声压检测计算 +}; + + +struct __mic_stream_io { + void *priv; + u32(*func)(void *priv, void *in, void *out, u32 inlen, u32 outlen); +}; + +struct __mic_stream_parm { + u16 sample_rate; + u16 point_unit; + u16 dac_delay; + u16 mic_gain; +}; + +struct __mic_stream { + struct adc_mic_ch mic_ch; + struct audio_adc_output_hdl adc_output; + struct __mic_stream_parm *parm; + struct __mic_stream_io out; + OS_SEM sem; + volatile u8 busy: 1; + volatile u8 release: 1; + volatile u8 revert: 6; + s16 *adc_buf; + int adc_buf_len; + }; + + typedef struct __mic_stream mic_stream; + + + /*----------------------------------------------------------------------------*/ + /**@brief 创建mic数据流 + @param 采样率、增益、ADC中断输出点数、dac延时 + @return 数据流句柄 + @note + */ + /*----------------------------------------------------------------------------*/ + mic_stream *mic_stream_creat(struct __mic_stream_parm *parm); + + + /*----------------------------------------------------------------------------*/ + /**@brief 释放mic数据流 + @param 数据流句柄 + @return + @note + */ + /*----------------------------------------------------------------------------*/ + void mic_stream_destroy(mic_stream **hdl); + + + /*----------------------------------------------------------------------------*/ + /**@brief 启动mic + @param struct __mic_stream * + @return true - 成功, false - 失败. + @note + */ + /*----------------------------------------------------------------------------*/ + bool mic_stream_start(mic_stream *stream); + + + /*----------------------------------------------------------------------------*/ + /**@brief 设置mic数据流回调函数 + @param + @return + @note + */ + /*----------------------------------------------------------------------------*/ + void mic_stream_set_output(struct __mic_stream *stream, void *priv, u32(*func)(void *priv, void *in, void *out, u32 inlen, u32 outlen)); + +#endif// __MIC_STREAM_H__ diff --git a/cpu/br23/audio_mic/simpleAGC.c b/cpu/br23/audio_mic/simpleAGC.c new file mode 100644 index 0000000..e894d50 --- /dev/null +++ b/cpu/br23/audio_mic/simpleAGC.c @@ -0,0 +1,262 @@ +//typedef struct TMPAGC_G_STRUCT_ +//{ +// int gainval; +// int energy; +//}TMPAGC_G_STRUCT; +// +//#define TST_MAXVAL 10000 +//#define TST_MAXVALh 7000 +#include "simpleAGC.h" + +void audio_mic_set_gain(u8 gain); + +void adjust_gain_init(TMPAGC_G_STRUCT *agc_obj) +{ + agc_obj->gainval = 512; + agc_obj->energy = TST_MAXVAL; +} + +void adjust_gain(TMPAGC_G_STRUCT *agc_obj, short *data, int len) +{ + int i; + for (i = 0; i < len; i++) { + int absv = (data[i] > 0) ? data[i] : -data[i]; + agc_obj->energy = ((agc_obj->energy * 4095) + absv) >> 12; + if (agc_obj->energy < absv) { + agc_obj->energy = absv; + } + + if (agc_obj->energy >= TST_MAXVAL) { + agc_obj->gainval = (agc_obj->gainval * 8170) >> 13; + if (agc_obj->gainval < 512) { + agc_obj->gainval = 512; + } + } else if (agc_obj->energy > 100) { + int destgain = 512; // 512 * TST_MAXVAL / agc_obj->energy; + if (destgain > 8192) { + destgain = 8192; + } + if (agc_obj->gainval > destgain) { + agc_obj->gainval = (agc_obj->gainval * 8180) >> 13; + if (agc_obj->gainval < destgain) { + agc_obj->gainval = destgain; + } + + } else { + agc_obj->gainval = (agc_obj->gainval * 8210) >> 13; + if (agc_obj->gainval > destgain) { + agc_obj->gainval = destgain; + } + } + } + +// int tmp = (data[i] * agc_obj->gainval) >> 9; + int tmp = (data[i] * agc_obj->gainval) >> 11; + if (tmp > 32767) { + tmp = 32767; + } else if (tmp < -32768) { + tmp = -32768; + } + data[i] = tmp; + } +} + +extern eq_sqrt(int a, int aQ, int *r, int *rQ); +int rms_calc(const short *mono_pcm, int npoint) +{ + long long acc = 0; + for (int i = 0; i < npoint; i++) { + acc += (long long)(*mono_pcm) * (long long)(*mono_pcm); + mono_pcm++; + } + int rms = (int)(acc / npoint); + int rmsQ; + eq_sqrt(rms, 0, &rms, &rmsQ); + rms >>= rmsQ; + /* printf("rms[%d]\n",rms); */ + return rms; +} +int peak_calc(const short *mono_pcm, int npoint) +{ + int peak = mono_pcm[0]; + mono_pcm++; + for (int i = 1; i < npoint; i++) { + if (peak < (int)(*mono_pcm)) { + peak = *mono_pcm; + } + mono_pcm++; + } + return peak; +} + +//初始化的fs应该是level_follower_process调用的频率.如果是ADC中断里面调用,fs应该是 采样率/adc中断点数 +/* void level_follower_init(level_follower *lvl_flw,float attack_time,float release_time,float fs) */ +level_follower *level_follower_init(float attack_time, float release_time, float fs, s8 gain) +{ + level_follower *lvl_flw; + lvl_flw = zalloc(sizeof(level_follower)); + lvl_flw->attack_factor = expf(-1.f / (attack_time * fs)); + lvl_flw->release_factor = expf(-1.f / (release_time * fs)); + lvl_flw->targe_level = round(pow(10.0, TARGE_VAL_DB / 20.0) * 32767); + lvl_flw->targe_up_level = round(pow(10.0, (TARGE_VAL_DB + 2) / 20.0) * 32767); + lvl_flw->targe_down_level = round(pow(10.0, (TARGE_VAL_DB - 2) / 20.0) * 32767); + lvl_flw->slience_level = round(pow(10.0, SILENCE_THRESHOLD_DB / 20.0) * 32767); + lvl_flw->gain = gain; + printf("\n\n targe_up[%d]targe_down[%d],slience[%d]\n\n", lvl_flw->targe_up_level, lvl_flw->targe_down_level, lvl_flw->slience_level); + return lvl_flw; +} +void level_follower_process(level_follower *lvl_flw, float cur_lvl) +{ + /* printf("energy[%d][%d]\n",lvl_flw->level,cur_lvl); */ + if (cur_lvl > lvl_flw->level) { + lvl_flw->level = (lvl_flw->level - cur_lvl) * lvl_flw->attack_factor + cur_lvl; + } else { + lvl_flw->level = (lvl_flw->level - cur_lvl) * lvl_flw->release_factor + cur_lvl; + } +} + + +void dajust_mic_gain_pause(level_follower *agc_obj, u8 mark) +{ + if (!agc_obj) { + return; + } + agc_obj->pause = mark ? 1 : 0; + printf("pause:[%d]\n\n", agc_obj->pause); +} + + + +void level_follower_close(level_follower *agc_obj) +{ + if (!agc_obj) { + return; + } + free(agc_obj); + printf("pause:[%d]\n\n", agc_obj->pause); +} + + +void adjust_mic_gain(level_follower *agc_obj, short *data, int len) +{ + if (!agc_obj) { + return; + } + if (agc_obj->pause) { + /* if(agc_obj->gain != MIC_MIN_GAIN){ */ + if (agc_obj->gain != 2) { + /* agc_obj->gain = MIC_MIN_GAIN; */ + agc_obj->gain = 2; + audio_mic_set_gain(agc_obj->gain); + } + return; + } + + static u8 cnt = 0; + /* printf("cnt[%d] len[%d]\n",cnt,len); */ + memcpy(&agc_obj->pbuf[cnt * len / 2], data, len); + if (cnt != (AGC_CAC_CNT - 1)) { + cnt++; + return; + } else { + cnt = 0; + } + agc_obj->energy = rms_calc(agc_obj->pbuf, len * AGC_CAC_CNT / 2); + + /* agc_obj->energy = rms_calc(data,len/2); */ + /* printf("energy[%d]\n",agc_obj->energy); */ + level_follower_process(agc_obj, agc_obj->energy); + if (agc_obj->level > agc_obj->slience_level) { + /* putchar('A'); */ + if (agc_obj->level > agc_obj->targe_up_level) { + /* putchar('-'); */ + if (agc_obj->gain > MIC_MIN_GAIN) { + agc_obj->gain--; + audio_mic_set_gain(agc_obj->gain); + } + } else if (agc_obj->level < agc_obj->targe_down_level) { + + /* putchar('+'); */ + if (agc_obj->gain < MIC_MAX_GAIN) { + agc_obj->gain++; + audio_mic_set_gain(agc_obj->gain); + } + } + } else { + /* if(agc_obj->gain > MIC_MIN_GAIN){ */ + /* agc_obj->gain--; */ + /* audio_mic_set_gain(agc_obj->gain); */ + /* } */ + } +} + +#if 0 +void adjust_mic_gain(AGC_G_STRUCT *agc_obj, short *data, int len) +{ + if (!agc_obj) { + return; + } +#if 10 + static s8 gain = 0; + static u8 up_mark = 1; + /* s8 gain = 0; */ + /* return; */ + agc_obj->energy = peak_calc(data, len / 2); + /* agc_obj->energy = rms_calc(data,len/2); */ + static u16 mark = 0; + mark++; + if (mark == 125) { + if (up_mark) { + + gain++; + audio_mic_set_gain(gain); + if (gain > 6) { + up_mark = 0; + } + } else { + gain--; + audio_mic_set_gain(gain); + if (gain == 0) { + up_mark = 1; + } + } + mark = 0; + } + +#endif + +#if 0 + /* printf("energy[%d]\n",agc_obj->energy); */ + if (agc_obj->energy >= TST_MAXVAL) { + if (agc_obj->new_gain_index) { + agc_obj->new_gain_index--; + } + + if (agc_obj->new_gain_index != agc_obj->cur_gain_index) { + agc_obj->cur_gain_index = agc_obj->new_gain_index; + gain = agc_obj->new_gain_index - agc_obj->default_gain_index; + gain += agc_obj->default_gain; + if (gain < 0) { + gain = 0; + } + audio_mic_set_gain(gain); + } + } else if (agc_obj->energy < TST_MINVAL) { + agc_obj->new_gain_index++; + if (agc_obj->new_gain_index > agc_obj->gain_step) { + agc_obj->new_gain_index = agc_obj->gain_step; + } + if (agc_obj->new_gain_index != agc_obj->cur_gain_index) { + agc_obj->cur_gain_index = agc_obj->new_gain_index; + gain = agc_obj->new_gain_index - agc_obj->default_gain_index; + gain += agc_obj->default_gain; + if (gain < 0) { + gain = 0; + } + audio_mic_set_gain(gain); + } + } +#endif +} +#endif + diff --git a/cpu/br23/audio_mic/simpleAGC.h b/cpu/br23/audio_mic/simpleAGC.h new file mode 100644 index 0000000..242c8c9 --- /dev/null +++ b/cpu/br23/audio_mic/simpleAGC.h @@ -0,0 +1,52 @@ +typedef struct TMPAGC_G_STRUCT_ { + int gainval; + int energy; +} TMPAGC_G_STRUCT; + +// #define TST_MAXVAL 1000 +// #define TST_MINVAL 500 +#define TST_MAXVAL 20000 +#define TST_MINVAL 10000 + +#define TARGE_VAL_DB (-18) +#define SILENCE_THRESHOLD_DB (-35) +#define MIC_MIN_GAIN 1 +#define MIC_MAX_GAIN (MIC_MIN_GAIN+3) +#define AGC_CAC_CNT 1 +#include "system/includes.h" +void adjust_gain_init(TMPAGC_G_STRUCT *agc_obj); +void adjust_gain(TMPAGC_G_STRUCT *agc_obj, short *data, int len); + +/*-----------------------------------------*/ +//u8 gain_tab[] = {} +typedef struct AGC_G_STRUCT_ { + int energy; + u8 default_gain; + u8 default_gain_index;//0λ + u8 cur_gain_index; + u8 new_gain_index; + u8 gain_step; + u8 adjust_rang; +} AGC_G_STRUCT; +//void adjust_gain_init(AGC_G_STRUCT *agc_obj,u8 gain,u8 gain_step); +// void adjust_mic_gain(AGC_G_STRUCT* agc_obj,short *data,int len); +/*-----------------------------------------*/ +#include +typedef struct { + float attack_factor; + float release_factor; + float level; + int targe_level; + int targe_up_level; + int targe_down_level; + int slience_level; + float energy; + s8 gain; + s16 pbuf[176 * AGC_CAC_CNT]; + u8 pause; +} level_follower; +// void level_follower_init(level_follower *lvl_flw,float attack_time,float release_time,float fs); +level_follower *level_follower_init(float attack_time, float release_time, float fs, s8 gain); +void adjust_mic_gain(level_follower *agc_obj, short *data, int len); +void dajust_mic_gain_pause(level_follower *agc_obj, u8 mark); +void level_follower_close(level_follower *agc_obj); diff --git a/cpu/br23/audio_mic/vollevel_detect.c b/cpu/br23/audio_mic/vollevel_detect.c new file mode 100644 index 0000000..9e152a4 --- /dev/null +++ b/cpu/br23/audio_mic/vollevel_detect.c @@ -0,0 +1,177 @@ +#include "vollevel_detect.h" + +static const unsigned short am_va_tab[] = { + 32768, 29205, 26029, 23198, 20675, 18427, 16423, 14637, 13045, 11627, 10362, 9235, 8231, 7336, 6538, 5827, 5193, 4629, 4125, 3677, 3277, 2920, 2603, 2320, 2068, 1843, 1642, 1464, 1305, 1163, 1036, 0 +}; + + +static const int rms_va_tab[] = { + 134217728, 106612931, 84685661, 67268212, 53433040, 42443372, 33713969, 26779957, 21272076, 16897011, + 13421773, 10661293, 8468566, 6726821, 5343304, 4244337, 3371397, 2677996, 2127208, 1689701, + 1342177, 1066129, 846857, 672682, 534330, 424434, 337140, 267800, 212721, 168970, + 134218, 0 +}; + + +//typedef struct _LOUDNESS_M_STRUCT_ +//{ +// int mutecnt; +// int rms; +// int counti; +// int maxval; +// int countperiod; +// int inv_counterpreiod; +// int errprintfcount0; +// short print_cnt; +// short print_dest; +// int dclevel; +// int rms_print; +// int maxval_print; +//}LOUDNESS_M_STRUCT; +// + + +void loudness_meter_init(LOUDNESS_M_STRUCT *loud_obj, int sr, int print_dest, u8 index) +{ + memset(loud_obj, 0, sizeof(LOUDNESS_M_STRUCT)); + loud_obj->countperiod = sr / 50; + loud_obj->inv_counterpreiod = 16777216 / loud_obj->countperiod; + loud_obj->print_dest = print_dest; + loud_obj->index = index; +} + +void loudness_meter_short(LOUDNESS_M_STRUCT *loud_obj, short *data, int len) +{ + int i; + int loudness_val = 0; + + for (i = 0; i < len; i++) { + int tmp = data[i] * 256; + loud_obj->dclevel = (loud_obj->dclevel * 511 + tmp) >> 9; + + + int xabs = (data[i] > 0) ? data[i] : (-data[i]); + + + int xabs2 = (xabs * xabs) >> 10; + loud_obj->rms += xabs2; + + loud_obj->maxval = (loud_obj->maxval > xabs) ? loud_obj->maxval : xabs; + + if (xabs >= 32767) { + loud_obj->errprintfcount0++; + } + + loud_obj->counti++; + if (loud_obj->counti > loud_obj->countperiod) { + + if (loud_obj->maxval_print < loud_obj->maxval) { + loud_obj->maxval_print = loud_obj->maxval; + } + + if (loud_obj->rms_print < loud_obj->rms) { + loud_obj->rms_print = loud_obj->rms; + } + + loud_obj->counti = 0; + loud_obj->maxval = 0; + loud_obj->rms = 0; + + if (loud_obj->errprintfcount0 > 2) { + loud_obj->errprintfcount0 = 0; + printf("[%d]overflow occur... \n", loud_obj->index); + } + + loud_obj->print_cnt++; + + if (loud_obj->print_cnt >= loud_obj->print_dest) { + + int rmsval = ((__int64)loud_obj->rms_print * (__int64)loud_obj->inv_counterpreiod) >> (24 - (10 - 3)); + + if (rmsval > 25837266) { + printf("[%d]energy high... \n", loud_obj->index); + } + + { + int compi = 0, found = 0;; + while (compi < 31) { + if (rmsval >= rms_va_tab[compi]) { +// float upval = (0 - compi) * 0.5; +// float dwonval = (0 - compi - 1) * 0.5; +// printf("rms level: %f to %f dB\n", upval, dwonval); + + int upval = (0 - compi); + int dwonval = (0 - compi - 1); + printf("[%d]rms level: %d to %d dB\n", loud_obj->index, upval, dwonval); + + found = 1; + break; + } + compi++; + } + + if (found == 0) { + printf("[%d]rms level < -30dB \n", loud_obj->index); + } + } + + + + + { + int compi = 0, found = 0;; + while (compi < 31) { + if (loud_obj->maxval_print >= am_va_tab[compi]) { +// float upval = (0 - compi) * 0.5; +// float dwonval = (0 - compi - 1) * 0.5; +// printf("peak level: %f to %f dB\n", upval, dwonval); + int upval = (0 - compi); + int dwonval = (0 - compi - 1); + printf("[%d]peak level: %d to %d dB\n", loud_obj->index, upval, dwonval); + + found = 1; + break; + } + + compi++; + } + + if (found == 0) { + printf("[%d]peak level < -30dB \n", loud_obj->index); + } + } + + loud_obj->print_cnt = 0; + loud_obj->maxval_print = 0; + loud_obj->rms_print = 0; + + + if (loud_obj->dclevel > (255 * 256)) { + printf("[%d] why ??? dc level : %d \n", loud_obj->index, loud_obj->dclevel >> 8); + } + printf("\n\n"); + + + + } + + } + } + +// return 0; +} + + + + +#if 0 + +loudness_meter_init(&loudness_adc, sr, 50); + +while (1) +{ + loudness_meter_short(&loudness_adc, datain, points); +} + +#endif + diff --git a/cpu/br23/audio_mic/vollevel_detect.h b/cpu/br23/audio_mic/vollevel_detect.h new file mode 100644 index 0000000..badb866 --- /dev/null +++ b/cpu/br23/audio_mic/vollevel_detect.h @@ -0,0 +1,37 @@ +#include "system/includes.h" +#include "app_config.h" + +typedef struct _LOUDNESS_M_STRUCT_ { + int mutecnt; + int rms; + int counti; + int maxval; + int countperiod; + int inv_counterpreiod; + int errprintfcount0; + short print_cnt; + short print_dest; + int dclevel; + int rms_print; + int maxval_print; + u8 index; +} LOUDNESS_M_STRUCT; + + + +void loudness_meter_init(LOUDNESS_M_STRUCT *loud_obj, int sr, int print_dest, u8 index); +void loudness_meter_short(LOUDNESS_M_STRUCT *loud_obj, short *data, int len); + + +#if 0 +//sample +LOUDNESS_M_STRUCT loudness_adc; +loudness_meter_init(&loudness_adc, sr, 50); + +while (1) +{ + loudness_meter_short(&loudness_adc, datain, points); +} + +#endif + diff --git a/cpu/br23/charge.c b/cpu/br23/charge.c new file mode 100644 index 0000000..e110dd5 --- /dev/null +++ b/cpu/br23/charge.c @@ -0,0 +1,614 @@ +#include "asm/clock.h" +#include "timer.h" +#include "asm/power/p33.h" +#include "asm/charge.h" +#include "uart.h" +#include "device/device.h" +#include "asm/power_interface.h" +/*#include "power/power_hw.h"*/ +#include "system/event.h" +#include "asm/efuse.h" +#include "gpio.h" +#include "app_config.h" + +#define LOG_TAG_CONST CHARGE +#define LOG_TAG "[CHARGE]" +#define LOG_INFO_ENABLE +#define LOG_DUMP_ENABLE +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#include "debug.h" + +#define IO_PORT_LDOIN 58//IO编号 + +#define BIT_LDO5V_IN BIT(0) +#define BIT_LDO5V_OFF BIT(1) +#define BIT_LDO5V_ERR BIT(2) + +enum { + CHARGE_TIMER_10_MS = 0, + CHARGE_TIMER_10_S, +} CHARGE_CHECK_TIME; + +typedef struct _CHARGE_VAR { + struct charge_platform_data *data; + volatile u8 charge_online_flag; + volatile u8 init_ok; + volatile u8 timer_period; + volatile int ldo5v_timer; + volatile int charge_timer; + volatile int charge_timer_pre; +} CHARGE_VAR; + +#define __this (&charge_var) +static CHARGE_VAR charge_var; +static u8 charge_flag; +extern void charge_set_callback(void (*wakup_callback)(void), void (*sub_callback)(void)); + +//芯片寄存器默认值,这几个寄存器只能写,不能读 +volatile u8 chg_con0 = 0x03; +volatile u8 chg_con1 = 0x00; +volatile u8 chg_con2 = 0x00; +volatile u8 chg_wkup = 0x00; + +void chg_reg_set(u8 addr, u8 start, u8 len, u8 data) +{ + switch (addr) { + case P3_CHG_CON0: + SFR(chg_con0, start, len, data); + p33_tx_1byte(P3_CHG_CON0, chg_con0); + break; + case P3_CHG_CON1: + SFR(chg_con1, start, len, data); + p33_tx_1byte(P3_CHG_CON1, chg_con1); + break; + case P3_CHG_CON2: + SFR(chg_con2, start, len, data); + p33_tx_1byte(P3_CHG_CON2, chg_con2); + break; + case P3_CHG_WKUP: + SFR(chg_wkup, start, len, data); + p33_tx_1byte(P3_CHG_WKUP, chg_wkup); + break; + } +} + +u8 chg_reg_get(u8 addr) +{ + switch (addr) { + case P3_CHG_CON0: + return chg_con0; + case P3_CHG_CON1: + return chg_con1; + case P3_CHG_CON2: + return chg_con2; + case P3_CHG_WKUP: + return chg_wkup; + } + return 0; +} + +u8 get_charge_poweron_en(void) +{ + return __this->data->charge_poweron_en; +} + +void charge_check_and_set_pinr(u8 level) +{ + u8 pinr_io; + if (P33_CON_GET(P3_PINR_CON) & BIT(0)) { + pinr_io = P33_CON_GET(P3_PORT_SEL10); + if (pinr_io == IO_PORT_LDOIN) { + if (level == 0) { + P33_CON_SET(P3_PINR_CON, 2, 1, 0); + } else { + P33_CON_SET(P3_PINR_CON, 2, 1, 1); + } + } + } +} + +static void udelay(u32 usec) +{ + JL_TIMER0->CON = BIT(14); + JL_TIMER0->CNT = 0; + JL_TIMER0->PRD = clk_get("lsb") / 1000000L * usec; //1us + JL_TIMER0->CON = BIT(0); //sys clk + while ((JL_TIMER0->CON & BIT(15)) == 0); + JL_TIMER0->CON = BIT(14); +} + +static u8 check_charge_state(void) +{ + u8 online_cnt = 0; + u8 i = 0; + + //only for br23 fix charge load too small + if (__this->data->ldo5v_pulldown_en) { + gpio_set_pull_down(IO_PORTB_05, 1); + } + + __this->charge_online_flag = 0; + + for (i = 0; i < 20; i++) { + if (LVCMP_DET_GET() || LDO5V_DET_GET()) { + online_cnt++; + } + udelay(1000); + } + log_info("online_cnt = %d\n", online_cnt); + if (online_cnt > 5) { + __this->charge_online_flag = 1; + } + + return __this->charge_online_flag; +} + +//only for br23 fix charge load too small +void charge_reset_pb5_pd_status(void) +{ + if (__this->data == NULL) { + return; + } + switch (charge_flag) { + case 0: + case BIT_LDO5V_OFF: + if (__this->data->ldo5v_pulldown_en) { + gpio_set_pull_down(IO_PORTB_05, 1); + } + break; + + case BIT_LDO5V_IN: + case BIT_LDO5V_ERR: + if (__this->data->ldo5v_pulldown_en) { + gpio_set_pull_down(IO_PORTB_05, 0); + } + break; + } +} + +//only for br23,还是负载弱问题 +bool charge_check_wakeup_is_set_ok(void) +{ +#if TCFG_CHARGE_ENABLE + //判断插拔检测设置是否正确 + if (LDO5V_IS_EN() && LDO5V_EDGE_WKUP_IS_EN()) { + //设置为下降沿时(bit1 = 1),当前状态应该为插入(bit5 = 1) + //设置为上升沿时(bit1 = 0),当前状态应该为拔出(bit5 = 0) + if (LDO5V_EDGE_GET() ^ LDO5V_DET_GET()) { + return FALSE; + } + } +#endif + return TRUE; +} + +void set_charge_online_flag(u8 flag) +{ + __this->charge_online_flag = flag; +} + +u8 get_charge_online_flag(void) +{ + return __this->charge_online_flag; +} + + +u8 get_ldo5v_online_hw(void) +{ + return LDO5V_DET_GET(); +} + +u8 get_lvcmp_det(void) +{ + return LVCMP_DET_GET(); +} + +u8 get_ldo5v_pulldown_en(void) +{ + return __this->data->ldo5v_pulldown_en; +} + +void charge_event_to_user(u8 event) +{ + struct sys_event e; + e.type = SYS_DEVICE_EVENT; + e.arg = (void *)DEVICE_EVENT_FROM_CHARGE; + e.u.dev.event = event; + e.u.dev.value = 0; + sys_event_notify(&e); +} + +static void set_charge_wkup_source(u8 source) +{ + CHARGE_WKUP_EDGE_SEL(0); //0:上升沿,高电平 1:下降沿,低电平 + CHARGE_WKUP_SOURCE_SEL(source); + CHARGE_EDGE_DETECT_EN(1); + CHARGE_LEVEL_DETECT_EN(1); + CHARGE_WKUP_EN(1); + CHARGE_WKUP_PND_CLR(); +} + +void charge_start(void) +{ + log_info("%s\n", __func__); + + if (__this->charge_timer_pre) { + sys_hi_timer_del(__this->charge_timer_pre); + __this->charge_timer_pre = 0; + } + + if (__this->charge_timer) { + sys_timer_del(__this->charge_timer); + __this->charge_timer = 0; + } + + set_charge_wkup_source(CHARGE_FULL_33V); + + CHGBG_EN(1); + CHARGE_EN(1); + /* PDIO_KEEP(1);//防止进入pdown后充电通路被切断 */ + + charge_event_to_user(CHARGE_EVENT_CHARGE_START); +} + +void charge_close(void) +{ + log_info("%s\n", __func__); + + CHARGE_WKUP_EN(0); + CHARGE_EDGE_DETECT_EN(0); + CHARGE_LEVEL_DETECT_EN(0); + CHGBG_EN(0); + CHARGE_EN(0); + CHARGE_WKUP_PND_CLR(); + /* PDIO_KEEP(0); */ + + charge_event_to_user(CHARGE_EVENT_CHARGE_CLOSE); + + if (__this->charge_timer_pre) { + sys_hi_timer_del(__this->charge_timer_pre); + __this->charge_timer_pre = 0; + } + + if (__this->charge_timer) { + sys_timer_del(__this->charge_timer); + __this->charge_timer = 0; + } +} + +static u8 CHARGE_FULL_FLAG_GET(void) +{ + u8 sfr; + //若保证timer中断优先级和RTC中断优先级一致则不用开关总中断 + local_irq_disable(); + CHARGE_LEVEL_DETECT_EN(1); + sfr = p33_rx_1byte(P3_WKUP_SRC); + CHARGE_LEVEL_DETECT_EN(0); + if (sfr & BIT(6)) { + CHARGE_WKUP_PND_CLR(); + } + local_irq_enable(); + return (sfr & BIT(6)); +} + +static void charge_full_detect(void *priv) +{ + static u16 charge_full_cnt = 0; + + if (__this->timer_period == CHARGE_TIMER_10_S) { + sys_timer_modify(__this->charge_timer, 10); + __this->timer_period = CHARGE_TIMER_10_MS; + } + + if (CHARGE_FULL_FLAG_GET() && LVCMP_DET_GET()) { + /* putchar('F'); */ + if (charge_full_cnt < 5) { + charge_full_cnt++; + } else { + charge_full_cnt = 0; + sys_timer_del(__this->charge_timer); + __this->charge_timer = 0; + charge_event_to_user(CHARGE_EVENT_CHARGE_FULL); + } + } else { + /* putchar('K'); */ + charge_full_cnt = 0; + sys_timer_modify(__this->charge_timer, 10000); + __this->timer_period = CHARGE_TIMER_10_S; + } +} + +static void charge_full_detect_pre(void *priv) +{ + u8 full_flag, lvcmp_lvl; + static u16 charge_no_full_cnt = 0; + sys_hi_timer_del(__this->charge_timer_pre); + __this->charge_timer_pre = 0; + full_flag = CHARGE_FULL_FLAG_GET(); + lvcmp_lvl = LVCMP_DET_GET(); + if (full_flag && lvcmp_lvl) { + goto __exit_det_pre; + } else { + if ((!full_flag) && lvcmp_lvl) { + //电压正常且连续起了n个充满中断后,进入查询方式 + charge_no_full_cnt++; + if (charge_no_full_cnt > 50) { + goto __exit_det_pre; + } + } else { + charge_no_full_cnt = 0; + } + CHARGE_EDGE_DETECT_EN(1); + CHARGE_LEVEL_DETECT_EN(1); + } + return; +__exit_det_pre: + //充满信号检测到之后,切换检测方式,采用查询方法(为了提高充电效率) + //若不进入查询方式,此时充满中断会频繁唤醒系统,系统功耗会增大,造成充电效率低 + charge_no_full_cnt = 0; + __this->charge_timer = sys_timer_add(NULL, charge_full_detect, 10); + __this->timer_period = CHARGE_TIMER_10_MS; + return; +} + +static void ldo5v_detect(void *priv) +{ + /* log_info("%s\n",__func__); */ + + static u16 ldo5v_in_normal_cnt = 0; + static u16 ldo5v_in_err_cnt = 0; + static u16 ldo5v_off_cnt = 0; + + if (LVCMP_DET_GET()) { //ldoin > vbat + /* putchar('X'); */ + ldo5v_off_cnt = 0; + ldo5v_in_err_cnt = 0; + if (ldo5v_in_normal_cnt < 50) { + ldo5v_in_normal_cnt++; + } else { + /* printf("ldo5V_IN\n"); */ + set_charge_online_flag(1); + ldo5v_in_normal_cnt = 0; + sys_hi_timer_del(__this->ldo5v_timer); + __this->ldo5v_timer = 0; + if ((charge_flag & BIT_LDO5V_IN) == 0) { + charge_flag = BIT_LDO5V_IN; + + //only for br23 fix charge load too small + if (__this->data->ldo5v_pulldown_en) { + gpio_set_pull_down(IO_PORTB_05, 0); + } + + charge_event_to_user(CHARGE_EVENT_LDO5V_IN); + LVCMP_EDGE_SEL(1); //检测ldoin比vbat电压低的情况(充电仓给电池充满后会关断,此时电压会掉下来) + LDO5V_EDGE_SEL(1); + //only for br23 fix charge wkup bug (ldoin 3.3v to 5v) + power_wakeup_index_disable(7); + } + } + } else if (LDO5V_DET_GET() == 0) { //ldoin<拔出电压(0.6) + /* putchar('Q'); */ + ldo5v_in_normal_cnt = 0; + ldo5v_in_err_cnt = 0; + if (ldo5v_off_cnt < (__this->data->ldo5v_off_filter + 10)) { + ldo5v_off_cnt++; + } else { + /* printf("ldo5V_OFF\n"); */ + set_charge_online_flag(0); + ldo5v_off_cnt = 0; + sys_hi_timer_del(__this->ldo5v_timer); + __this->ldo5v_timer = 0; + if ((charge_flag & BIT_LDO5V_OFF) == 0) { + charge_flag = BIT_LDO5V_OFF; + LVCMP_EDGE_SEL(0);//拔出后重新检测插入 + LDO5V_EDGE_SEL(0); + + //only for br23 fix charge load too small + if (__this->data->ldo5v_pulldown_en) { + gpio_set_pull_down(IO_PORTB_05, 1); + } + + charge_event_to_user(CHARGE_EVENT_LDO5V_OFF); + //only for br23 fix charge wkup bug (ldoin 3.3v to 5v) + power_wakeup_index_disable(7); + } + } + } else { //拔出电压(0.6左右)< ldoin < vbat + ldo5v_in_normal_cnt = 0; + /* putchar('E'); */ + ldo5v_off_cnt = 0; + if (ldo5v_in_err_cnt < 50) { + ldo5v_in_err_cnt++; + } else { + /* printf("ldo5V_ERR\n"); */ + set_charge_online_flag(1); + ldo5v_in_err_cnt = 0; + sys_hi_timer_del(__this->ldo5v_timer); + __this->ldo5v_timer = 0; + if ((charge_flag & BIT_LDO5V_ERR) == 0) { + charge_flag = BIT_LDO5V_ERR; + LVCMP_EDGE_SEL(0); + LDO5V_EDGE_SEL(1); + + //only for br23 fix charge load too small + if (__this->data->ldo5v_pulldown_en) { + gpio_set_pull_down(IO_PORTB_05, 0); + } + + //only for br23 fix charge wkup bug (ldoin 3.3v to 5v) + power_wakeup_index_enable(7); + if (__this->data->ldo5v_off_filter) { + charge_event_to_user(CHARGE_EVENT_LDO5V_KEEP); + } + } + } + } +} + + +void sub_wakeup_isr(void) +{ + if (__this->ldo5v_timer == 0) { + __this->ldo5v_timer = sys_hi_timer_add(0, ldo5v_detect, 2); + } +} + +void charge_wakeup_isr(void) +{ + /* printf("\ncharge_wkup_deal\n"); */ + if (__this->charge_timer_pre == 0) { + __this->charge_timer_pre = sys_hi_timer_add(0, charge_full_detect_pre, 10); + } +} + +#if 0 +static void test_func(void *priv) +{ + if (P33_CON_GET(P3_CHG_READ) & BIT(0)) { + JL_PORTA->DIR &= ~BIT(3); + JL_PORTA->OUT |= BIT(3); + } else { + JL_PORTA->OUT &= ~BIT(3); + } +} +#endif + +u8 get_charge_mA_config(void) +{ + return __this->data->charge_mA; +} + +void set_charge_mA(u8 charge_mA) +{ + static u8 charge_mA_old = 0xff; + if (charge_mA_old != charge_mA) { + charge_mA_old = charge_mA; + CHARGE_mA_SEL(charge_mA); + } +} + +const u16 full_table[CHARGE_FULL_V_MAX] = { + 3869, 3907, 3946, 3985, 4026, 4068, 4122, 4157, + 4202, 4249, 4295, 4350, 4398, 4452, 4509, 4567, +}; +u16 get_charge_full_value(void) +{ + ASSERT(__this->init_ok, "charge not init ok!\n"); + ASSERT(__this->data->charge_full_V < CHARGE_FULL_V_MAX); + return full_table[__this->data->charge_full_V]; +} + +static void charge_config(void) +{ + u8 charge_4202_trim_val = CHARGE_FULL_V_4202; + u8 offset = 0; + u8 charge_full_v_val = 0; + + if (get_vbat_trim() == 0xf) { + log_info("vbat not trim, use default config!!!!!!"); + } else { + charge_4202_trim_val = get_vbat_trim(); //4.2V对应的trim出来的实际档位 + } + + log_info("charge_4202_trim_val = %d\n", charge_4202_trim_val); + + if (__this->data->charge_full_V >= CHARGE_FULL_V_4202) { + offset = __this->data->charge_full_V - CHARGE_FULL_V_4202; + charge_full_v_val = charge_4202_trim_val + offset; + if (charge_full_v_val > 0xf) { + charge_full_v_val = 0xf; + } + } else { + offset = CHARGE_FULL_V_4202 - __this->data->charge_full_V; + if (charge_4202_trim_val >= offset) { + charge_full_v_val = charge_4202_trim_val - offset; + } else { + charge_full_v_val = 0; + } + } + + log_info("charge_full_v_val = %d\n", charge_full_v_val); + + CHARGE_FULL_V_SEL(charge_full_v_val); + CHARGE_FULL_mA_SEL(__this->data->charge_full_mA); + /* CHARGE_mA_SEL(__this->data->charge_mA); */ + CHARGE_mA_SEL(CHARGE_mA_20); +} + +int charge_init(const struct dev_node *node, void *arg) +{ + log_info("%s\n", __func__); + + __this->data = (struct charge_platform_data *)arg; + + ASSERT(__this->data); + + //充电相关寄存器设置默认值 + p33_tx_1byte(P3_CHG_CON0, chg_con0); + p33_tx_1byte(P3_CHG_CON1, chg_con1); + p33_tx_1byte(P3_CHG_CON2, chg_con2); + p33_tx_1byte(P3_CHG_WKUP, chg_wkup); + + __this->init_ok = 0; + __this->charge_online_flag = 0; + + /*先关闭充电使能,后面检测到充电插入再开启*/ + /* CHGBG_EN(0); */ + /* CHARGE_EN(0); */ + + /*LDO5V的100K下拉电阻使能*/ + L5V_LOAD_EN(__this->data->ldo5v_pulldown_en); + + /*LDO5V,检测上升沿,用于检测ldoin插入*/ + LDO5V_EN(1); + LDO5V_EDGE_SEL(0); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); + + /*LVCMP,检测上升沿,用于检测ldoin插入*/ + LVCMP_EN(1); + LVCMP_EDGE_SEL(0); + LVCMP_PND_CLR(); + LVCMP_EDGE_WKUP_EN(1); + /*使用COMPH,在LDOIN和VBAT比较接近时检测信号会抖动,所以切成使用COMPL,注意softoff需要切成COMPH*/ + /*COMPH:LDO5V<->VBAT COMPL:LDO5V<->VDD50*/ + LVCMP_CMP_SEL(1); + + charge_config(); + + //only for br23 fix charge wkup bug (ldoin 3.3v to 5v) + //原因:softoff后没有rc时钟唤醒的滤波逻辑不工作给不出唤醒信号 + struct port_wakeup port; + port.pullup_down_enable = 0; + port.edge = RISING_EDGE; + port.attribute = 0; + port.iomap = IO_LDOIN_DET; + power_wakeup_set_wakeup_io(7, &port); + power_wakeup_index_disable(7); + + if (check_charge_state()) { + if (__this->ldo5v_timer == 0) { + __this->ldo5v_timer = sys_hi_timer_add(0, ldo5v_detect, 2); + } + } else { + charge_flag = BIT_LDO5V_OFF; + CHARGE_WKUP_PND_CLR(); + CHGBG_EN(0); + CHARGE_EN(0); + } + charge_set_callback(charge_wakeup_isr, sub_wakeup_isr); + /* sys_hi_timer_add(0,test_func,1); */ + + __this->init_ok = 1; + + return 0; +} + +int charge_api_init(void *arg) +{ + return charge_init(NULL, arg); +} +/* const struct device_operations charge_dev_ops = { */ +/* .init = charge_init, */ +/* }; */ diff --git a/cpu/br23/chargebox_hw.c b/cpu/br23/chargebox_hw.c new file mode 100644 index 0000000..551b84b --- /dev/null +++ b/cpu/br23/chargebox_hw.c @@ -0,0 +1,264 @@ +#include "board_config.h" +#include "generic/typedef.h" +#include "generic/gpio.h" +#include "asm/gpio.h" +#include "asm/clock.h" +#include "device/chargebox.h" + +#if(TCFG_CHARGE_BOX_ENABLE) + +#define BUF_LEN (64) + +struct chargebox_handle { + const struct chargebox_platform_data *data; + u32 uart2_baud; + u32 uart1_baud; + u8 init_flag; +}; + +static u8 uart2_buf[BUF_LEN] __attribute__((aligned(4))); +static u8 uart1_buf[BUF_LEN] __attribute__((aligned(4))); +#define __this (&hdl) +static struct chargebox_handle hdl; + +extern void chargebox_data_deal(u8 cmd, u8 l_r, u8 *data, u8 length); +void __attribute__((weak)) chargebox_data_deal(u8 cmd, u8 l_r, u8 *data, u8 len) +{ + +} + +___interrupt +static void uart2_isr(void) +{ + u32 rx_len, timeout; + + if ((JL_UART2->CON0 & BIT(2)) && (JL_UART2->CON0 & BIT(15))) {//发送完成 + JL_UART2->CON0 |= BIT(13); + chargebox_data_deal(CMD_COMPLETE, EAR_L, NULL, 0); + } + if ((JL_UART2->CON0 & BIT(3)) && (JL_UART2->CON0 & BIT(14))) {//接收中断 + JL_UART2->CON0 |= BIT(12); + JL_UART2->RXSADR = (u32)uart2_buf; + JL_UART2->RXEADR = (u32)(uart2_buf + BUF_LEN); + JL_UART2->RXCNT = BUF_LEN; + chargebox_data_deal(CMD_RECVDATA, EAR_L, uart2_buf, BUF_LEN); + } + if ((JL_UART2->CON0 & BIT(5)) && (JL_UART2->CON0 & BIT(11))) { + //OTCNT PND + JL_UART2->CON0 |= BIT(7);//DMA模式 + JL_UART2->CON0 |= BIT(10);//清OTCNT PND + asm volatile("nop"); + rx_len = JL_UART2->HRXCNT;//读当前串口接收数据的个数 + JL_UART2->CON0 |= BIT(12);//清RX PND(这里的顺序不能改变,这里要清一次) + JL_UART2->RXSADR = (u32)uart2_buf; + JL_UART2->RXEADR = (u32)(uart2_buf + BUF_LEN); + JL_UART2->RXCNT = BUF_LEN; + timeout = 20 * 1000000 / __this->uart2_baud; + JL_UART2->OTCNT = timeout * (clk_get("uart") / 1000000); + chargebox_data_deal(CMD_RECVDATA, EAR_L, uart2_buf, rx_len); + } +} +___interrupt +static void uart1_isr(void) +{ + u32 rx_len, timeout; + + + if ((JL_UART1->CON0 & BIT(2)) && (JL_UART1->CON0 & BIT(15))) {//发送完成 + JL_UART1->CON0 |= BIT(13); + /* printf("uart1 sned isr\n"); */ + chargebox_data_deal(CMD_COMPLETE, EAR_R, NULL, 0); + } + if ((JL_UART1->CON0 & BIT(3)) && (JL_UART1->CON0 & BIT(14))) {//接收中断 + /* putchar('Z'); */ + JL_UART1->CON0 |= BIT(12); + JL_UART1->RXSADR = (u32)uart1_buf; + JL_UART1->RXEADR = (u32)(uart1_buf + BUF_LEN); + JL_UART1->RXCNT = BUF_LEN; + chargebox_data_deal(CMD_RECVDATA, EAR_R, uart1_buf, BUF_LEN); + } + if ((JL_UART1->CON0 & BIT(5)) && (JL_UART1->CON0 & BIT(11))) { + //OTCNT PND + /* putchar('W'); */ + JL_UART1->CON0 |= BIT(7);//DMA模式 + JL_UART1->CON0 |= BIT(10);//清OTCNT PND + asm volatile("nop"); + JL_UART1->CON0 |= BIT(12);//清RX PND(这里的顺序不能改变,这里要清一次) + rx_len = JL_UART1->HRXCNT;//读当前串口接收数据的个数 + JL_UART1->RXSADR = (u32)uart1_buf; + JL_UART1->RXEADR = (u32)(uart1_buf + BUF_LEN); + JL_UART1->RXCNT = BUF_LEN; + timeout = 20 * 1000000 / __this->uart1_baud; + JL_UART1->OTCNT = timeout * (clk_get("lsb") / 1000000); + /* printf("uart1 dma recvdata isr:%x\n",uart1_buf[0]); */ + /* put_buf(uart1_buf,rx_len); */ + chargebox_data_deal(CMD_RECVDATA, EAR_R, uart1_buf, rx_len); + } +} + + +u8 chargebox_write(u8 l_r, u8 *data, u8 len) +{ + if ((len == 0) || (len > BUF_LEN)) { + return 0; + } + if (l_r == EAR_L) { + memcpy(uart2_buf, data, len); + JL_UART2->TXADR = (u32)uart2_buf; + JL_UART2->TXCNT = (u16)len; + } else { + memcpy(uart1_buf, data, len); + JL_UART1->TXADR = (u32)uart1_buf; + JL_UART1->TXCNT = (u16)len; + } + return len; +} + +void chargebox_open(u8 l_r, u8 mode) +{ + if (mode == MODE_RECVDATA) { + if (l_r == EAR_L) { + JL_UART2->CON0 = BIT(13) | BIT(12) | BIT(10); + gpio_uart_rx_input(__this->data->L_port, 2, INPUT_CH0); + gpio_set_pull_up(__this->data->L_port, 1); + JL_UART2->RXSADR = (u32)uart2_buf; + JL_UART2->RXEADR = (u32)(uart2_buf + BUF_LEN); + JL_UART2->RXCNT = BUF_LEN; + JL_UART2->CON0 |= BIT(6) | BIT(5) | BIT(3); + JL_UART2->CON0 |= BIT(13) | BIT(12) | BIT(10) | BIT(0); + } else { + JL_UART1->CON0 = BIT(13) | BIT(12) | BIT(10); + gpio_uart_rx_input(__this->data->R_port, 1, INPUT_CH3); + gpio_set_pull_up(__this->data->R_port, 1); + JL_UART1->RXSADR = (u32)uart1_buf; + JL_UART1->RXEADR = (u32)(uart1_buf + BUF_LEN); + JL_UART1->RXCNT = BUF_LEN; + JL_UART1->CON0 |= BIT(6) | BIT(5) | BIT(3); + JL_UART1->CON0 |= BIT(13) | BIT(12) | BIT(10) | BIT(0); + } + } else { + if (l_r == EAR_L) { + JL_UART2->CON0 = BIT(13) | BIT(12) | BIT(10); + gpio_output_channle(__this->data->L_port, CH1_UT2_TX); + gpio_set_hd(__this->data->L_port, 0); + gpio_set_hd0(__this->data->L_port, 0); + JL_UART2->CON0 = BIT(13) | BIT(12) | BIT(10) | BIT(2) | BIT(0); + } else { + JL_UART1->CON0 = BIT(13) | BIT(12) | BIT(10); + gpio_output_channle(__this->data->R_port, CH2_UT1_TX); + gpio_set_hd(__this->data->R_port, 0); + gpio_set_hd0(__this->data->R_port, 0); + JL_UART1->CON0 = BIT(13) | BIT(12) | BIT(10) | BIT(2) | BIT(0); + } + } +} + + +void chargebox_close(u8 l_r) +{ + if (l_r == EAR_L) { + JL_UART2->CON0 = BIT(13) | BIT(12) | BIT(10); + gpio_set_pull_down(__this->data->L_port, 0); + gpio_set_pull_up(__this->data->L_port, 0); + gpio_set_die(__this->data->L_port, 1); + gpio_set_hd(__this->data->L_port, 0); + gpio_direction_output(__this->data->L_port, 1); + } else { + JL_UART1->CON0 = BIT(13) | BIT(12) | BIT(10); + gpio_set_pull_down(__this->data->R_port, 0); + gpio_set_pull_up(__this->data->R_port, 0); + gpio_set_die(__this->data->R_port, 1); + gpio_set_hd(__this->data->R_port, 0); + gpio_direction_output(__this->data->R_port, 1); + } +} + +void chargebox_set_baud(u8 l_r, u32 baudrate) +{ + u32 uart_timeout; + if (l_r == EAR_L) { + __this->uart2_baud = baudrate; + uart_timeout = 20 * 1000000 / __this->uart2_baud; + JL_UART2->OTCNT = uart_timeout * (clk_get("lsb") / 1000000); + JL_UART2->BAUD = (clk_get("uart") / __this->uart2_baud) / 4 - 1; + JL_UART2->CON1 = (((clk_get("uart") / __this->uart2_baud) % 4) << 4); + } else { + __this->uart1_baud = baudrate; + uart_timeout = 20 * 1000000 / __this->uart1_baud; + JL_UART1->OTCNT = uart_timeout * (clk_get("lsb") / 1000000); + JL_UART1->BAUD = (clk_get("uart") / __this->uart1_baud) / 4 - 1; + JL_UART1->CON1 = (((clk_get("uart") / __this->uart1_baud) % 4) << 4); + } +} + +void chargebox_init(const struct chargebox_platform_data *data) +{ + u32 uart_timeout; + __this->data = (struct chargebox_platform_data *)data; + ASSERT(data); + ASSERT(!(JL_UART2->CON0 & BIT(0)), "uart2 already used!\n"); + ASSERT(!(JL_UART1->CON0 & BIT(0)), "uart1 already used!\n"); + + ///////////////////////////////////////////////////////////////////////////////////////////// + /* JL_CLOCK->CLK_CON1 |= BIT(11); */ + /* JL_CLOCK->CLK_CON1 &= ~BIT(10); */ + ///////////////////////////////////////////////////////////////////////////////////////////// + + uart_timeout = 20 * 1000000 / __this->data->baudrate; + __this->uart2_baud = __this->data->baudrate; + __this->uart1_baud = __this->data->baudrate; + //init uart2 + JL_UART2->CON0 = BIT(13) | BIT(12) | BIT(10); + JL_UART2->OTCNT = uart_timeout * (clk_get("lsb") / 1000000); + JL_UART2->BAUD = (clk_get("uart") / __this->data->baudrate) / 4 - 1; + JL_UART2->CON1 = (((clk_get("uart") / __this->data->baudrate) % 4) << 4); + gpio_set_pull_down(__this->data->L_port, 0); + gpio_set_pull_up(__this->data->L_port, 1); + gpio_set_die(__this->data->L_port, 1); + gpio_direction_input(__this->data->L_port); + request_irq(IRQ_UART2_IDX, 3, uart2_isr, 0); + //used output_channel0 input_ch0 + JL_IOMAP->CON3 &= ~BIT(11);//不占用IO + + //init uart1 + JL_UART1->CON0 = BIT(13) | BIT(12) | BIT(10); + JL_UART1->OTCNT = uart_timeout * (clk_get("lsb") / 1000000); + JL_UART1->BAUD = (clk_get("uart") / __this->data->baudrate) / 4 - 1; + JL_UART1->CON1 = (((clk_get("uart") / __this->data->baudrate) % 4) << 4); + gpio_set_pull_down(__this->data->R_port, 0); + gpio_set_pull_up(__this->data->R_port, 1); + gpio_set_die(__this->data->R_port, 1); + gpio_direction_input(__this->data->R_port); + request_irq(IRQ_UART1_IDX, 3, uart1_isr, 0); + //used output_channel1, input_ch3 + JL_IOMAP->CON3 &= ~BIT(7);//不占用IO + + __this->init_flag = 1; +} + +static void clock_critical_enter(void) +{ + +} +static void clock_critical_exit(void) +{ + u32 uart_timeout; + if (!__this->init_flag) { + return; + } + JL_UART1->CON0 = BIT(13) | BIT(12) | BIT(10); + JL_UART2->CON0 = BIT(13) | BIT(12) | BIT(10); + //set uart2 + uart_timeout = 20 * 1000000 / __this->uart2_baud; + JL_UART2->OTCNT = uart_timeout * (clk_get("lsb") / 1000000); + JL_UART2->BAUD = (clk_get("uart") / __this->uart2_baud) / 4 - 1; + JL_UART2->CON1 = (((clk_get("uart") / __this->uart2_baud) % 4) << 4); + //set uart1 + uart_timeout = 20 * 1000000 / __this->uart1_baud; + JL_UART1->OTCNT = uart_timeout * (clk_get("lsb") / 1000000); + JL_UART1->BAUD = (clk_get("uart") / __this->uart1_baud) / 4 - 1; + JL_UART1->CON1 = (((clk_get("uart") / __this->uart1_baud) % 4) << 4); +} +CLOCK_CRITICAL_HANDLE_REG(chargebox, clock_critical_enter, clock_critical_exit) + +#endif//end if TCFG_CHARGE_BOX_ENABLE diff --git a/cpu/br23/chargestore.c b/cpu/br23/chargestore.c new file mode 100644 index 0000000..2157e2e --- /dev/null +++ b/cpu/br23/chargestore.c @@ -0,0 +1,248 @@ +#include "generic/typedef.h" +#include "generic/gpio.h" +#include "asm/power/p33.h" +#include "asm/hwi.h" +#include "asm/gpio.h" +#include "asm/clock.h" +#include "asm/chargestore.h" +#include "update.h" +#include "app_config.h" + +struct chargestore_handle { + const struct chargestore_platform_data *data; + JL_UART_TypeDef *UART; + u32 baudrate; +}; +#define DMA_ISR_LEN 64 +#define DMA_BUF_LEN 64 +#define __this (&hdl) +static struct chargestore_handle hdl; +u8 uart_dma_buf[DMA_BUF_LEN] __attribute__((aligned(4))); +volatile u8 send_busy; + +//串口时钟和串口超时时钟是分开的 +#define UART_SRC_CLK clk_get("uart") +#define UART_OT_CLK clk_get("lsb") + +enum { + UPGRADE_NULL = 0, + UPGRADE_USB_HARD_KEY, + UPGRADE_USB_SOFTKEY, + UPGRADE_UART_SOFT_KEY, + UPGRADE_UART_ONE_WIRE_HARD_KEY, +}; +extern void charge_reset_pb5_pd_status(void); +extern void nvram_set_boot_state(u32 state); +extern void local_irq_disable(); +void chargestore_set_update_ram(void) +{ + //需要补充设置ram + int tmp; + __asm__ volatile("%0 =icfg" : "=r"(tmp)); + tmp &= ~(3 << 8); + __asm__ volatile("icfg = %0" :: "r"(tmp));//GIE1 + local_irq_disable(); + nvram_set_boot_state(UPGRADE_UART_SOFT_KEY); +} + +static u8 chargestore_get_f95_det_res(u32 equ_res) +{ + u8 det_res = (equ_res + 50) / 100; + if (det_res > 0) { + det_res -= 1; + } + if (det_res > 0x0f) { + det_res = 0x0f; + } + return det_res; +} + +//br23, LDOIN电压为2V时等效电阻约1M, 功耗约1.8uA +u8 chargestore_get_det_level(u8 chip_type) +{ + switch (chip_type) { + case TYPE_F95: + return chargestore_get_f95_det_res(1600); + case TYPE_NORMAL: + default: + return 0x0f; + } +} + +void __attribute__((weak)) chargestore_data_deal(u8 cmd, u8 *data, u8 len) +{ + +} + +___interrupt +static void uart_isr(void) +{ + u16 i; + u32 rx_len = 0; + if ((__this->UART->CON0 & BIT(2)) && (__this->UART->CON0 & BIT(15))) { + __this->UART->CON0 |= BIT(13); + send_busy = 0; + chargestore_data_deal(CMD_COMPLETE, NULL, 0); + } + if ((__this->UART->CON0 & BIT(3)) && (__this->UART->CON0 & BIT(14))) { + __this->UART->CON0 |= BIT(12);//清RX PND + chargestore_data_deal(CMD_RECVDATA, uart_dma_buf, DMA_ISR_LEN); + memset((void *)uart_dma_buf, 0, sizeof(uart_dma_buf)); + __this->UART->RXSADR = (u32)uart_dma_buf; + __this->UART->RXEADR = (u32)(uart_dma_buf + DMA_BUF_LEN); + __this->UART->RXCNT = DMA_ISR_LEN; + } + if ((__this->UART->CON0 & BIT(5)) && (__this->UART->CON0 & BIT(11))) { + //OTCNT PND + __this->UART->CON0 |= BIT(7);//DMA模式 + __this->UART->CON0 |= BIT(10);//清OTCNT PND + asm volatile("nop"); + rx_len = __this->UART->HRXCNT;//读当前串口接收数据的个数 + __this->UART->CON0 |= BIT(12);//清RX PND(这里的顺序不能改变,这里要清一次) + chargestore_data_deal(CMD_RECVDATA, uart_dma_buf, rx_len); + memset((void *)uart_dma_buf, 0, sizeof(uart_dma_buf)); + __this->UART->RXSADR = (u32)uart_dma_buf; + __this->UART->RXEADR = (u32)(uart_dma_buf + DMA_BUF_LEN); + __this->UART->RXCNT = DMA_ISR_LEN; + } +} + +void chargestore_write(u8 *data, u8 len) +{ + u32 data_addr = (u32)data; + if (data_addr % 4) {//4byte对齐 + ASSERT(0, "%s: unaligned accesses!", __func__); + } + send_busy = 1; + __this->UART->TXADR = data_addr; + __this->UART->TXCNT = len; +} + +void chargestore_open(u8 mode) +{ + send_busy = 0; + __this->UART->CON0 = BIT(13) | BIT(12) | BIT(10); + if (mode == MODE_RECVDATA) { + //约定:ut0->input_ch0 ut1->input_ch3(因为input_ch1要给IR用) + if (__this->UART == JL_UART0) { + gpio_uart_rx_input(__this->data->io_port, 0, INPUT_CH0); + } else { + gpio_uart_rx_input(__this->data->io_port, 1, INPUT_CH3); + } + //避免插入普通充电舱,舱体不升压 only for br23 + if (__this->data->io_port == IO_PORTB_05) { + charge_reset_pb5_pd_status(); + } + memset((void *)uart_dma_buf, 0, sizeof(uart_dma_buf)); + __this->UART->RXSADR = (u32)uart_dma_buf; + __this->UART->RXEADR = (u32)(uart_dma_buf + DMA_BUF_LEN); + __this->UART->RXCNT = DMA_ISR_LEN; + __this->UART->CON0 |= BIT(6) | BIT(5) | BIT(3); + } else { + //约定:ut0->output_ch0 ut1->output_ch1 + if (__this->UART == JL_UART0) { + gpio_output_channle(__this->data->io_port, CH0_UT0_TX); + } else { + gpio_output_channle(__this->data->io_port, CH1_UT1_TX); + } + gpio_set_hd(__this->data->io_port, 1); + __this->UART->CON0 |= BIT(2); + } + __this->UART->CON0 |= BIT(13) | BIT(12) | BIT(10) | BIT(0); +} + +void chargestore_close(void) +{ + __this->UART->CON0 = BIT(13) | BIT(12) | BIT(10) | BIT(0); + gpio_set_pull_down(__this->data->io_port, 0); + gpio_set_pull_up(__this->data->io_port, 0); + gpio_set_die(__this->data->io_port, 1); + gpio_set_hd(__this->data->io_port, 0); + gpio_direction_input(__this->data->io_port); + send_busy = 0; + memset((void *)uart_dma_buf, 0, sizeof(uart_dma_buf)); + if (__this->data->io_port == IO_PORTB_05) { + charge_reset_pb5_pd_status(); + } +} + +void chargestore_set_baudrate(u32 baudrate) +{ + u32 uart_timeout; + __this->baudrate = baudrate; + uart_timeout = 20 * 1000000 / __this->baudrate; + __this->UART->OTCNT = uart_timeout * (UART_OT_CLK / 1000000); + __this->UART->BAUD = (UART_SRC_CLK / __this->baudrate) / 4 - 1; +} + +void chargestore_init(const struct chargestore_platform_data *data) +{ + u32 uart_timeout; + __this->data = (struct chargestore_platform_data *)data; + ASSERT(data); + switch (__this->data->uart_irq) { + case IRQ_UART0_IDX: + __this->UART = JL_UART0; + break; + case IRQ_UART1_IDX: + __this->UART = JL_UART1; + break; + default: + ASSERT(0, "uart irq(%d) err!\n", __this->data->uart_irq); + break; + } + if (__this->UART->CON0 & BIT(0)) { + ASSERT(0, "uart used!\n"); + } + send_busy = 0; + uart_timeout = 20 * 1000000 / __this->data->baudrate; + __this->UART->CON0 = BIT(13) | BIT(12) | BIT(10) | BIT(0); + __this->UART->OTCNT = uart_timeout * (UART_OT_CLK / 1000000); + __this->UART->BAUD = (UART_SRC_CLK / __this->data->baudrate) / 4 - 1; + __this->baudrate = __this->data->baudrate; + if (__this->data->io_port == IO_PORTB_05) { + charge_reset_pb5_pd_status(); + } else { + gpio_set_pull_down(__this->data->io_port, 0); + } + gpio_set_pull_up(__this->data->io_port, 0); + gpio_set_die(__this->data->io_port, 1); + gpio_direction_input(__this->data->io_port); + request_irq(__this->data->uart_irq, 2, uart_isr, 0); + if (__this->UART == JL_UART0) { + //不占用IO + gpio_set_uart0(-1); + } else { + //不占用IO + gpio_set_uart1(-1); + } +#if (!TCFG_CHARGE_ENABLE) + LDO5V_EN(1); + LDO5V_EDGE_SEL(1); + LDO5V_PND_CLR(); + LDO5V_EDGE_WKUP_EN(1); +#endif +} + +static void clock_critical_enter(void) +{ + u8 cmp_buf[2] = {0x55, 0xAA}; + //等待数据收完 + extern void *memmem(void *srcmem, int src_len, void *desmem, int des_len); + while (memmem(uart_dma_buf, sizeof(uart_dma_buf), cmp_buf, sizeof(cmp_buf))); + //等待数据发完 + while (send_busy); +} + +static void clock_critical_exit(void) +{ + u32 uart_timeout; + if (__this->UART == NULL) { + return; + } + uart_timeout = 20 * 1000000 / __this->baudrate; + __this->UART->OTCNT = uart_timeout * (UART_OT_CLK / 1000000); + __this->UART->BAUD = (UART_SRC_CLK / __this->baudrate) / 4 - 1; +} +CLOCK_CRITICAL_HANDLE_REG(chargestore, clock_critical_enter, clock_critical_exit) + diff --git a/cpu/br23/clock_cfg.h b/cpu/br23/clock_cfg.h new file mode 100644 index 0000000..b0f220c --- /dev/null +++ b/cpu/br23/clock_cfg.h @@ -0,0 +1,112 @@ +#ifndef CLOCK_CFG_H +#define CLOCK_CFG_H + +#include "typedef.h" +/* + + */ + + +enum { + BT_IDLE_CLOCK = 1, + MUSIC_IDLE_CLOCK, + FM_IDLE_CLOCK, + LINEIN_IDLE_CLOCK, + PC_IDLE_CLOCK, + REC_IDLE_CLOCK, + RTC_IDLE_CLOCK, + SPDIF_IDLE_CLOCK, + BOX_IDLE_CLOCK, + + + DEC_SBC_CLK , + DEC_AAC_CLK , + DEC_MSBC_CLK, + DEC_CVSD_CLK, + + AEC8K_CLK , + AEC8K_ADV_CLK, + AEC16K_CLK , + AEC16K_ADV_CLK, + + DEC_TONE_CLK, + DEC_MP3_CLK , + DEC_WAV_CLK , /// 10 + DEC_G729_CLK, + DEC_G726_CLK, + DEC_PCM_CLK , + DEC_MTY_CLK , + DEC_WMA_CLK , + + DEC_APE_CLK , + DEC_FLAC_CLK, + DEC_AMR_CLK , + DEC_DTS_CLK , + + DEC_M4A_CLK , ///20 + DEC_ALAC_CLK, + DEC_FM_CLK , + DEC_LINE_CLK, + DEC_TWS_SBC_CLK, + SPDIF_CLK , + + ENC_RECODE_CLK, + ENC_SBC_CLK , + ENC_WAV_CLK , + ENC_G726_CLK, + ENC_MP3_CLK , + ENC_TWS_SBC_CLK, + + ENC_MSBC_CLK, //////30 + ENC_CVSD_CLK, + SYNC_CLK , + AUTOMUTE_CLK , + FINDF_CLK , + FM_INSIDE_CLK, + BT_CONN_CLK , + + EQ_CLK , + EQ_DRC_CLK , + EQ_ONLINE_CLK, + REVERB_CLK , + REVERB_HOWLING_CLK, + REVERB_PITCH_CLK, + + DEC_MP3PICK_CLK , + DEC_WMAPICK_CLK , + DEC_M4APICK_CLK , + DEC_MIX_CLK, + + DEC_IIS_CLK, + DEC_UI_CLK, + DEC_MIDI_CLK, + CHARGE_BOX_CLK, + + DEC_3D_CLK, + DEC_VBASS_CLK, + DEC_LOUDNES_CLK, + + LCD_UI_CLK, + SCAN_DISK_CLK, + SPECTRUM_CLK, + + LOCALTWS_CLK, + + AI_SPEECH_CLK, + SMARTBOX_ACTION_CLK, + + ENUM_MAX_CLK = 63 , +}; + +void clock_pause_play(u8 mode); + + +void clock_idle(u32 type); +void clock_add(u32 type); +void clock_remove(u32 type); +void clock_set_cur(void); +void clock_add_set(u32 type); +void clock_remove_set(u32 type); + + +#endif diff --git a/cpu/br23/clock_manager.c b/cpu/br23/clock_manager.c new file mode 100644 index 0000000..d4bb0cc --- /dev/null +++ b/cpu/br23/clock_manager.c @@ -0,0 +1,395 @@ +#include "system/includes.h" +#include "app_config.h" +#include "clock_cfg.h" +#include "asm/dac.h" +struct clock_type { + u8 type; + u32 clock; + const char *name; +}; + +/***** + +idle clk : 模式里面的空闲时钟 + +时钟通过idle clk 加上每一种解码或者运算的时钟 +累加总和来设置需要的时钟 + +模式空闲时钟设置 +void clock_idle(u32 type) + + +把时钟设置加入到ext中,但是不是立刻设置时钟 +需要最后调用clock_set_cur来最后设置时钟 +用于连续地方设置时钟 +用完后必须把时钟remove +void clock_add(u32 type) +void clock_remove(u32 type) +void clock_set_cur(void) + + +把时钟设置加入到ext中,立刻设置时钟 +需要立刻添加时钟 +用完后必须把时钟remove +void clock_add_set(u32 type) +void clock_remove_set(u32 type) + +*****/ + +//// 如果clock_fix 为0 就按照配置设置时钟,如果有值就固定频率 +#if (SOUNDCARD_ENABLE) || (TCFG_MIC_EFFECT_ENABLE) +#define CLOCK_FIX 240 +#else +#define CLOCK_FIX 240 +#endif + +#if (TCFG_AUDIO_DAC_CONNECT_MODE == DAC_OUTPUT_FRONT_LR_REAR_LR) && TCFG_EQ_DIVIDE_ENABLE +#define EQ4_CLK (24) //20段eq double eq +#else +#define EQ4_CLK (0) +#endif +#if defined(TCFG_EQ_ONLINE_ENABLE) && TCFG_EQ_ONLINE_ENABLE +#define EQ_ONLINE_CLK (64) +#else +#define EQ_ONLINE_CLK (0) +#endif + +#define MIX_SRC_CLK (24)//src + +const struct clock_type clock_enum[] = { + + { BT_IDLE_CLOCK , (24), " BT_IDLE_CLOCK " }, + { MUSIC_IDLE_CLOCK , (24), " MUSIC_IDLE_CLOCK " }, + { FM_IDLE_CLOCK , (48), " FM_IDLE_CLOCK " }, + { LINEIN_IDLE_CLOCK , (96), " LINEIN_IDLE_CLOCK " }, + { PC_IDLE_CLOCK , (120), " PC_IDLE_CLOCK " }, + { REC_IDLE_CLOCK , (12), " REC_IDLE_CLOCK " }, + { RTC_IDLE_CLOCK , (12), " RTC_IDLE_CLOCK " }, + { SPDIF_IDLE_CLOCK , (12), " SPDIF_IDLE_CLOCK " }, + { BOX_IDLE_CLOCK , (24), " BOX_IDLE_CLOCK " }, + /**************************************************************************/ + + { DEC_SBC_CLK , (32), "DEC_SBC_CLK " }, + { DEC_AAC_CLK , (32), "DEC_AAC_CLK " }, + { DEC_MSBC_CLK , (12), "DEC_MSBC_CLK " }, + { DEC_CVSD_CLK , (8), "DEC_CVSD_CLK " }, + + { AEC8K_CLK , (48), "AEC8K_CLK " }, + { AEC8K_ADV_CLK , (60), "AEC8K_ADV_CLK " }, + { AEC16K_CLK , (80), "AEC16K_CLK " }, + { AEC16K_ADV_CLK, (120), "AEC16K_ADV_CLK " }, + + { DEC_TONE_CLK , (24 + 32), "DEC_TONE_CLK " }, + { DEC_MP3_CLK , (46), "DEC_MP3_CLK " }, + { DEC_WAV_CLK , (24), "DEC_WAV_CLK " }, + { DEC_G729_CLK , (24), "DEC_G729_CLK " }, + { DEC_G726_CLK , (24), "DEC_G726_CLK " }, + { DEC_PCM_CLK , (24), "DEC_PCM_CLK " }, + { DEC_MTY_CLK , (24), "DEC_MTY_CLK " }, + { DEC_WMA_CLK , (48), "DEC_WMA_CLK " }, + + { DEC_APE_CLK , (160), "DEC_APE_CLK "}, + { DEC_FLAC_CLK , (96), "DEC_FLAC_CLK "}, + { DEC_AMR_CLK , (96), "DEC_AMR_CLK "}, + { DEC_DTS_CLK , (120), "DEC_DTS_CLK " }, + + { DEC_M4A_CLK , (48), "DEC_M4A_CLK "}, + { DEC_ALAC_CLK , (48), "DEC_ALAC_CLK "}, + { DEC_FM_CLK , (12), "DEC_FM_CLK " }, + { DEC_LINE_CLK , (24), "DEC_LINE_CLK " }, + { DEC_TWS_SBC_CLK, (32), "DEC_TWS_SBC_CLK" }, + { SPDIF_CLK , (120), "SPDIF_CLK " }, + + { ENC_RECODE_CLK, (64), "ENC_RECODE_CLK " }, + { ENC_SBC_CLK , (64), "ENC_SBC_CLK " }, + { ENC_WAV_CLK , (96), "ENC_WAV_CLK " }, + { ENC_G726_CLK, (64), "ENC_G726_CLK " }, + { ENC_MP3_CLK , (120), "ENC_MP3_CLK " }, + { ENC_TWS_SBC_CLK, (48), "ENC_TWS_SBC_CLK" }, + { ENC_MSBC_CLK , (12), "ENC_MSBC_CLK " }, + { ENC_CVSD_CLK , (8), "ENC_CVSD_CLK " }, + + { SYNC_CLK , (4), "SYNC_CLK " }, + { AUTOMUTE_CLK , (16), "AUTOMUTE_CLK" }, + + { FINDF_CLK , (120), "FINDF_CLK " }, + { FM_INSIDE_CLK , (96), "FM_INSIDE_CLK " }, +#if TCFG_DEC2TWS_ENABLE + { BT_CONN_CLK , (48), "BT_CONN_CLK " }, +#else + { BT_CONN_CLK , (16), "BT_CONN_CLK " }, +#endif + + + { EQ_CLK , (24 + EQ4_CLK + EQ_ONLINE_CLK), " EQ_CLK " }, + { EQ_DRC_CLK , (60), " EQ_DRC_CLK " }, + //{ EQ_ONLINE_CLK, (120), " EQ_ONLINE_CLK " }, + { REVERB_CLK , (192), " REVERB_CLK " }, + { REVERB_HOWLING_CLK , (64), " REVERB_HOWLING_CLK " }, + { REVERB_PITCH_CLK , (32), " REVERB_PITCH_CLK " }, + + { DEC_MP3PICK_CLK, (8), "DEC_MP3PICK_CLK" }, + { DEC_WMAPICK_CLK, (8), "DEC_WMAICK_CLK" }, + { DEC_M4APICK_CLK, (8), "DEC_M4AICK_CLK" }, + { DEC_MIX_CLK, (6 + MIX_SRC_CLK), "DEC_MIX_CLK" }, + + { DEC_IIS_CLK, (64), "DEC_IIS_CLK" }, + { DEC_UI_CLK, (8), "DEC_UI_CLK" }, + + /* { DEC_MIDI_CLK, (32), "DEC_MIDI_CLK" }, */ + //midi音色文件跳转读取频繁,外挂flash baud 调到6000000L, midi_clk 80M就够 + { DEC_MIDI_CLK, (110), "DEC_MIDI_CLK" }, + /* { DEC_MIDI_CLK, (80), "DEC_MIDI_CLK" }, */ + + { CHARGE_BOX_CLK, (18), "CHARGE_BOX_CLK" }, + + { DEC_3D_CLK, (24), "DEC_3D_CLK" }, + { DEC_VBASS_CLK, (24), "DEC_VBASS_CLK" }, + { DEC_LOUDNES_CLK, (108), "DEC_LOUDNES_CLK"}, + + { LCD_UI_CLK, (192), "LCD_UI_CLK" }, + + { SCAN_DISK_CLK, (120), "SCAN_DISK_CLK" },//提高扫盘速度 + +#if TCFG_DEC2TWS_ENABLE + { LOCALTWS_CLK, (24), "LOCALTWS_CLK" }, +#endif + {SPECTRUM_CLK, (5), "SPECTRUM_CLK" }, + + {AI_SPEECH_CLK, (120), "AI_SPEECH_CLK" }, + {SMARTBOX_ACTION_CLK, (160), "SMARTBOX_ACTION_CLK" }, +}; + + + +const u8 clock_tb[] = { + 24, + 32, + 48, + 60, + 80, + 96, + 120, + 160, + 192, + 240, +}; + +static u8 ext_clk_tb[10]; +static u32 idle_type = 0; + +static void clock_ext_dump() +{ + u8 i, j; + for (i = 0; i < ARRAY_SIZE(clock_enum); i++) { + if (idle_type == clock_enum[i].type) { + y_printf("--- %d %s \n", clock_enum[i].clock, clock_enum[i].name); + break; + } + } + + for (i = 0; i < ARRAY_SIZE(ext_clk_tb); i++) { + if (ext_clk_tb[i]) { + for (j = 0; j < ARRAY_SIZE(clock_enum); j++) { + if (ext_clk_tb[i] == clock_enum[j].type) { + y_printf("--- %d %s \n", clock_enum[j].clock, clock_enum[j].name); + continue; + } + } + } + } +} + + +u8 clock_idle_selet(u32 type) +{ + u8 i; + +#if (CLOCK_FIX ) + return CLOCK_FIX; +#endif + + for (i = 0; i < ARRAY_SIZE(clock_enum); i++) { + if (type == clock_enum[i].type) { + /* y_printf("--- %d %s \n", clock_enum[i].clock, clock_enum[i].name); */ + return clock_enum[i].clock; + } + } + + return 24; +} + +u8 clock_ext_push(u8 ext_type) +{ + u8 i; + for (i = 0; i < ARRAY_SIZE(ext_clk_tb); i++) { + if (ext_type == ext_clk_tb[i]) { + return 0; + } + } + + for (i = 0; i < ARRAY_SIZE(ext_clk_tb); i++) { + if (!ext_clk_tb[i]) { + ext_clk_tb[i] = ext_type; + return 1; + } + } + + y_printf("clock ext over!!! \n"); + return 0; +} + +u8 clock_ext_pop(u8 ext_type) +{ + u8 i; + for (i = 0; i < ARRAY_SIZE(ext_clk_tb); i++) { + if (ext_type == ext_clk_tb[i]) { + ext_clk_tb[i] = 0; + return 1; + } + } + return 0; +} + +u16 clock_match(u16 clk) +{ + u8 i; + for (i = 0; i < ARRAY_SIZE(clock_tb); i++) { + if (clk <= clock_tb[i]) { + return clock_tb[i]; + } + } + y_printf("clock overlimit!!! %d\n", clock_tb[ARRAY_SIZE(clock_tb) - 1]); + return clock_tb[ARRAY_SIZE(clock_tb) - 1]; +} + + +u16 clock_ext_cal() +{ + u32 ext_clk = 0 ; + u8 i, j; + for (i = 0; i < ARRAY_SIZE(ext_clk_tb); i++) { + if (ext_clk_tb[i]) { + for (j = 0; j < ARRAY_SIZE(clock_enum); j++) { + if (ext_clk_tb[i] == clock_enum[j].type) { + /* y_printf("--- %d %s \n", clock_enum[j].clock, clock_enum[j].name); */ + ext_clk += clock_enum[j].clock; + continue; + } + } + } + } + + return ext_clk; +} + +u32 clock_cur_cal() +{ + u32 idle_clk, cur_clk, ext_clk; + +#if (CLOCK_FIX ) + return CLOCK_FIX; +#endif + + local_irq_disable(); + idle_clk = clock_idle_selet(idle_type); + ext_clk = clock_ext_cal(); + cur_clk = idle_clk + ext_clk; + cur_clk = clock_match(cur_clk); + local_irq_enable(); + return cur_clk ; +} + +void clock_pause_play(u8 mode) +{ + u32 idle_clk, cur_clk ; + u8 i, j; + if (mode) { + idle_clk = clock_idle_selet(idle_type); +#if TCFG_SPI_LCD_ENABLE + for (i = 0; i < ARRAY_SIZE(ext_clk_tb); i++) { + + if (LCD_UI_CLK == ext_clk_tb[i]) { + for (j = 0; j < ARRAY_SIZE(clock_enum); j++) { + if (ext_clk_tb[i] == clock_enum[j].type) { + idle_clk += clock_enum[j].clock; + /* y_printf("--- %d %s \n", clock_enum[j].clock, clock_enum[j].name); */ + } + } + } + } +#endif + idle_clk = clock_match(idle_clk); + clk_set("sys", idle_clk * 1000000L); + } else { + clock_ext_dump(); + cur_clk = clock_cur_cal(); + clk_set("sys", cur_clk * 1000000L); + } +} + +void clock_idle(u32 type) +{ + u32 cur_clk; + local_irq_disable(); + idle_type = type; + cur_clk = clock_cur_cal(); + local_irq_enable(); + clock_ext_dump(); + clk_set("sys", cur_clk * 1000000L); +} + +//////把时钟设置加入到ext中,但是不是立刻设置时钟 +void clock_add(u32 type) +{ + u32 cur_clk ; + u8 resoult = clock_ext_push(type); + if (!resoult) { + return; + } +} + +void clock_remove(u32 type) +{ + u32 cur_clk ; + + u8 resoult = clock_ext_pop(type); + if (!resoult) { + return; + } +} + +void clock_set_cur(void) +{ + u32 cur_clk ; + clock_ext_dump(); + cur_clk = clock_cur_cal(); + clk_set("sys", cur_clk * 1000000L); +} + +//////把时钟设置加入到ext中,立刻设置时钟 +void clock_add_set(u32 type) +{ + u32 cur_clk ; + u8 resoult = clock_ext_push(type); + if (!resoult) { + return; + } + clock_ext_dump(); + cur_clk = clock_cur_cal(); + clk_set("sys", cur_clk * 1000000L); +} + +void clock_remove_set(u32 type) +{ + u32 cur_clk ; + + u8 resoult = clock_ext_pop(type); + if (!resoult) { + return; + } + + clock_ext_dump(); + cur_clk = clock_cur_cal(); + clk_set("sys", cur_clk * 1000000L); +} diff --git a/cpu/br23/ctmu.c b/cpu/br23/ctmu.c new file mode 100644 index 0000000..8398c33 --- /dev/null +++ b/cpu/br23/ctmu.c @@ -0,0 +1,352 @@ +#include "app_config.h" +#include "asm/ctmu.h" +#include "asm/gpio.h" + + +#if TCFG_CTMU_TOUCH_KEY_ENABLE + +#define TOUCH_CTMU_DEBUG 0 +#if TOUCH_CTMU_DEBUG +#define touch_ctmu_debug(fmt, ...) printf("[CTMU] "fmt, ##__VA_ARGS__) +#else +#define touch_ctmu_debug(fmt, ...) +#endif /* #if TOUCH_CTMU_DEBUG */ + +#define touch_ctmu_err(fmt, ...) printf("[CTMU ERR] "fmt, ##__VA_ARGS__) + +#define CTMU_CON0 JL_CTM->CON0 +#define CTMU_CON1 JL_CTM->CON1 +#define CTMU_ADR JL_CTM->ADR + +static u32 ctm_buf[16 * 2] = {0}; + +static sCTMU_KEY_VAR ctm_key_value; +static sCTMU_KEY_VAR *ctm_key_var; + +static u8 port_index_mapping_talbe[CTMU_KEY_CH_MAX] = {0}; + +static const struct ctmu_touch_key_platform_data *user_data = NULL; + + +//=================================================================================// +/* +ctmu原理: + + 1.三个时钟源: + 1)闸门时钟源(可选), 分频值可以选 + 2)放电时钟源(固定是lsb), 分频值可以选 + 3)充电时钟源(可选), 分频值不可选 + + 2.闸门时间内 + _________________________________ + __| |__ + __ __ __ __ __ + 放电时计数 __| |__| |__| |__| |__| |__ + + 3. 过程: 放电 --> 充电(计数) --> 放电[该过程可选] + + 4.分析计数值 + */ +//=================================================================================// + +//时钟闸门时钟源选择, 可分频 +enum { + GATE_SOURCE_OSC = 0, + GATE_SOURCE_LRC, + GATE_SOURCE_PLL240M, + GATE_SOURCE_PLL480M, +}; + +enum { + GATE_SOURCE_PRE_DIV8 = 0, + GATE_SOURCE_PRE_DIV16, + GATE_SOURCE_PRE_DIV32, + GATE_SOURCE_PRE_DIV64, + GATE_SOURCE_PRE_DIV8192, + GATE_SOURCE_PRE_DIV16384, + GATE_SOURCE_PRE_DIV32768, + GATE_SOURCE_PRE_DIV65536, +}; + + +//放电时钟源硬件上默认是lsb, 可分频 +enum { + DISCHARGE_SOURCE_PRE_DIV1 = 0, + DISCHARGE_SOURCE_PRE_DIV2, + DISCHARGE_SOURCE_PRE_DIV4, + DISCHARGE_SOURCE_PRE_DIV8, + DISCHARGE_SOURCE_PRE_DIV16, + DISCHARGE_SOURCE_PRE_DIV32, + DISCHARGE_SOURCE_PRE_DIV64, + DISCHARGE_SOURCE_PRE_DIV128, +}; + + +//充电时钟源选择, 不可分频 +enum { + CHARGE_SOURCE_OSC = 0, + CHARGE_SOURCE_LRC, + CHARGE_SOURCE_PLL240M, + CHARGE_SOURCE_PLL480M, +}; + + +static const u8 ctmu_ch_table[] = { + IO_PORTA_00, IO_PORTA_01, IO_PORTA_02, IO_PORTA_03, + IO_PORTA_04, IO_PORTA_05, IO_PORTA_06, IO_PORTA_07, + IO_PORTA_09, IO_PORTA_10, IO_PORTC_00, IO_PORTC_01, + IO_PORTC_02, IO_PORTC_03, IO_PORTC_04, IO_PORTC_05 +}; + + +static u32 get_ctmu_ch_val(u8 ch_index, u32 *ctm_buf) +{ + if (ch_index >= user_data->num) { + return 0; + } + + return ctm_buf[port_index_mapping_talbe[ch_index]]; +} + +static void ctm_irq(u16 ctm_res, u8 ch) +{ + u16 temp_u16_0, temp_u16_1; + s16 temp_s16_0, temp_s16_1; + s32 temp_s32_0; +//.............................................................................................. +//取计数值/通道判断 +//.............................................................................................. + + + if (ctm_key_var->touch_init_cnt[ch]) { + ctm_key_var->touch_init_cnt[ch]--; + ctm_key_var->touch_cnt_buf[ch] = (u32)ctm_res << (ctm_key_var->FLT0CFG + 1); + ctm_key_var->touch_release_buf[ch] = (u32)ctm_res << (ctm_key_var->FLT1CFG0 + 1); + } + +//.............................................................................................. +//当前计数值去抖动滤波器 +//.............................................................................................. + temp_u16_0 = ctm_key_var->touch_cnt_buf[ch]; + temp_u16_1 = temp_u16_0; + temp_u16_1 -= (temp_u16_1 >> ctm_key_var->FLT0CFG); + temp_u16_1 += ctm_res; + ctm_key_var->touch_cnt_buf[ch] = temp_u16_1; + temp_u16_0 += temp_u16_1; + temp_u16_0 >>= (ctm_key_var->FLT0CFG + 1); + + +//.............................................................................................. +//各通道按键释放计数值滤波器 +//.............................................................................................. + temp_s32_0 = ctm_key_var->touch_release_buf[ch]; + temp_u16_1 = temp_s32_0 >> ctm_key_var->FLT1CFG0; //获得滤波器之后的按键释放值 + temp_s16_0 = temp_u16_0 - temp_u16_1; //获得和本次检测值的差值,按下按键为负值,释放按键为正值 + temp_s16_1 = temp_s16_0; + +// if(ch == 1) +// { +// printf("ch%d: %d %d", (short)ch, temp_u16_0, temp_s16_1); +// } + + if (ctm_key_var->touch_key_state & BIT(ch)) { //如果本通道按键目前是处于释放状态 + if (temp_s16_1 <= 0) { //当前计数值小于低通值,放大后参与运算 + if (temp_s16_1 > -(ctm_key_var->FLT1CFG2 >> 3)) { + temp_s16_1 = temp_s16_1 * 8; //temp_s16_1 <<= 3; //放大后参与运算 + } else { + temp_s16_1 = -(ctm_key_var->FLT1CFG2); //饱和,防止某些较大的正偏差导致错判 + } + } else if (temp_s16_1 <= ctm_key_var->FLT1CFG1) { //当前计数值小于低通值不多,正常参与运算 + } else { //当前计数值小于低通值很多,缩小后参与运算 + temp_s16_1 = temp_s16_1 / 8; //temp_s16_1 >>= 3;(有符号数右移自动扩展符号位???) + } + } else { //如果本通道按键目前是处于按下状态, 缓慢降低释放计数值 + if (temp_s16_1 >= ctm_key_var->RELEASECFG1) { + temp_s16_1 >>= 3; //缩小后参与运算 + } else { + temp_s16_1 = 0; + } + } + + temp_s32_0 += (s32)temp_s16_1; + ctm_key_var->touch_release_buf[ch] = temp_s32_0; + +//.............................................................................................. +//按键按下与释放检测 +//.............................................................................................. + if (temp_s16_0 >= ctm_key_var->PRESSCFG) { //按键按下 + ctm_key_var->touch_key_state &= ~BIT(ch); + } else if (temp_s16_0 >= ctm_key_var->RELEASECFG0) { //按键释放 + ctm_key_var->touch_key_state |= BIT(ch); + } +} + + +static void scan_capkey(u8 ch_index, u32 *ctmu_buf) +{ + u16 Touchkey_value_delta; + + if (user_data == NULL || user_data->num == 0) { + return; + } + + Touchkey_value_delta = get_ctmu_ch_val(ch_index, ctmu_buf); ///获取计数值; + /* g_printf("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = %d",Touchkey_value_delta); */ + /*调用滤波算法*/ + ctm_irq(Touchkey_value_delta, ch_index); +} + + +___interrupt +static void ctmu_isr_handle(void) +{ + u32 *rbuf = NULL; + u8 i, j; + if (CTMU_CON0 & BIT(7)) { + CTMU_CON0 |= BIT(6); + } + + if (CTMU_CON0 & BIT(9)) { + rbuf = (u32 *)(&ctm_buf[0]); + } else { + rbuf = (u32 *)(&ctm_buf[16]); + } + + for (i = 0; i < user_data->num; i++) { + scan_capkey(i, rbuf); + } +} + +static void ctmu_port_init(const struct ctmu_key_port *port_list, u8 port_num) +{ + u8 i, j; + for (i = 0; i < port_num; i++) { + for (j = 0; j < ARRAY_SIZE(ctmu_ch_table); j++) { + if (ctmu_ch_table[j] == port_list[i].port) { + CTMU_CON1 |= (BIT(j) << 0); + port_index_mapping_talbe[i] = j; + } + } + if (j > sizeof(ctmu_ch_table)) { + touch_ctmu_err("port err!!!"); + return; + } + + gpio_set_pull_down(port_list[i].port, 0); + gpio_set_pull_up(port_list[i].port, 0); + gpio_set_die(port_list[i].port, 0); + gpio_set_direction(port_list[i].port, 1); + } +} + +static void ctmu_buf_init(void) +{ + memset((u8 *)&ctm_buf, 0x00, sizeof(ctm_buf)); + CTMU_ADR = (u32)&ctm_buf; +} + +static void log_ctmu_info(void) +{ + touch_ctmu_debug("CTMU_CON0 = 0x%x", CTMU_CON0); + touch_ctmu_debug("CTMU_CON1 = 0x%x", CTMU_CON1); +} + +static void touch_ctmu_init(const struct ctmu_key_port *port, u8 num) +{ + touch_ctmu_debug("%s", __func__); + CTMU_CON0 = 0; + CTMU_CON1 = 0; + //充电时钟选择 + CTMU_CON0 |= (CHARGE_SOURCE_PLL480M << 10); + //放电时钟分频选择, 时钟源固定是lsb + CTMU_CON0 |= (DISCHARGE_SOURCE_PRE_DIV128 << 12); //要求 > 2uS + + //闸门时钟选择 + CTMU_CON0 |= (GATE_SOURCE_OSC << 4); //24 MHz + CTMU_CON0 |= (GATE_SOURCE_PRE_DIV32768 << 1); //1.36ms + + //充电电流 + CTMU_CON0 |= 3 << 18; //0 ~ 7 + //comparator reference voltage + CTMU_CON0 |= 2 << 16; //0 ~ 3 + //放电模式(在充电完成后是否放电, 这样会放电更彻底) + CTMU_CON0 |= 1 << 23; + + CTMU_CON0 |= 1 << 6; // Clear Pending + + ctmu_port_init(port, num); + ctmu_buf_init(); + + log_ctmu_info(); +} + +static void touch_ctmu_enable(u8 en) +{ + if (en) { + CTMU_CON0 |= BIT(8); //Int Enable + CTMU_CON0 |= BIT(0); //Moudle Enable + } else { + CTMU_CON0 &= ~BIT(8); //Int Disable + CTMU_CON0 &= ~BIT(0); //Moudle Disable + } +} + +//API: +int ctmu_init(void *_data) +{ + if (_data == NULL) { + return -1; + } + user_data = (const struct ctmu_touch_key_platform_data *)_data; + + memset((u8 *)&ctm_key_value, 0x0, sizeof(sCTMU_KEY_VAR)); + + /*触摸按键参数配置*/ + ctm_key_value.FLT0CFG = 2; + ctm_key_value.FLT1CFG0 = 2; + ctm_key_value.FLT1CFG1 = 80; + ctm_key_value.FLT1CFG2 = 10 * 128; //128 = 2^7 + + ///调节灵敏度的主要参数 + ctm_key_value.PRESSCFG = user_data->press_cfg;; + ctm_key_value.RELEASECFG0 = user_data->release_cfg0; + ctm_key_value.RELEASECFG1 = user_data->release_cfg1; + + memset((u8 *) & (ctm_key_value.touch_init_cnt[0]), 0x10, CTMU_KEY_CH_MAX); + + ctm_key_value.touch_key_state = 0xffff; //<按键默认释放 + + ctm_key_var = &ctm_key_value; + + if (user_data->num > CTMU_KEY_CH_MAX) { + touch_ctmu_err("ctm key num config err!!!"); + return -1; + } + + touch_ctmu_init(user_data->port_list, user_data->num); + + request_irq(IRQ_CTM_IDX, 1, ctmu_isr_handle, 0); + + touch_ctmu_enable(1); + + return 0; +} + + +u8 get_ctmu_value(void) +{ + u8 key = 0xFF; + u8 i; + + for (i = 0; i < user_data->num; i++) { + if (!(ctm_key_value.touch_key_state & (u16)(BIT(i)))) { + break; + } + } + key = (i < user_data->num) ? i : 0xFF; + + return key; +} + +#endif /* #if TCFG_CTMU_TOUCH_KEY_ENABLE */ + diff --git a/cpu/br23/iic_eeprom_test.c b/cpu/br23/iic_eeprom_test.c new file mode 100644 index 0000000..dae6463 --- /dev/null +++ b/cpu/br23/iic_eeprom_test.c @@ -0,0 +1,310 @@ +#include "system/includes.h" +#include "media/includes.h" +//#include "device/iic.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" + +#if 0 +#define EEPROM_RADDR 0xa1 +#define EEPROM_WADDR 0xa0 + +#define DELAY_CNT 0 + +#if 0 +#define iic_dev 0 +#define iic_init(iic) hw_iic_init(iic) +#define iic_uninit(iic) hw_iic_uninit(iic) +#define iic_start(iic) hw_iic_start(iic) +#define iic_stop(iic) hw_iic_stop(iic) +#define iic_tx_byte(iic, byte) hw_iic_tx_byte(iic, byte) +#define iic_rx_byte(iic, ack) hw_iic_rx_byte(iic, ack) +#define iic_read_buf(iic, buf, len) hw_iic_read_buf(iic, buf, len) +#define iic_write_buf(iic, buf, len) hw_iic_write_buf(iic, buf, len) +#define iic_suspend(iic) hw_iic_suspend(iic) +#define iic_resume(iic) hw_iic_resume(iic) +#else +#define iic_dev 0 +#define iic_init(iic) soft_iic_init(iic) +#define iic_uninit(iic) soft_iic_uninit(iic) +#define iic_start(iic) soft_iic_start(iic) +#define iic_stop(iic) soft_iic_stop(iic) +#define iic_tx_byte(iic, byte) soft_iic_tx_byte(iic, byte) +#define iic_rx_byte(iic, ack) soft_iic_rx_byte(iic, ack) +#define iic_read_buf(iic, buf, len) soft_iic_read_buf(iic, buf, len) +#define iic_write_buf(iic, buf, len) soft_iic_write_buf(iic, buf, len) +#define iic_suspend(iic) soft_iic_suspend(iic) +#define iic_resume(iic) soft_iic_resume(iic) +#endif + +static u8 eeprom_rbuf[512], eeprom_wbuf[512]; +extern void delay(unsigned int cnt); + +void eeprom_write(int iic, u8 *buf, u32 addr, u32 len) +{ + int i; + u32 retry; + int ret; + u32 tx_len; + u32 offset; +#if 0 + offset = 0; + while (offset < len) { + tx_len = len - offset > 8 ? 8 : len - offset; + retry = 1; + do { + iic_start(iic); + ret = iic_tx_byte(iic, EEPROM_WADDR); + if (!ret) { + if (--retry) { + continue; + } else { + goto __exit; + } + } + delay(DELAY_CNT); + ret = iic_tx_byte(iic, addr + offset); + if (!ret) { + if (--retry) { + continue; + } else { + goto __exit; + } + } + delay(DELAY_CNT); + putchar('h'); + for (i = 0; i < tx_len - 1; i++) { + ret = iic_tx_byte(iic, buf[offset + i]); + if (!ret) { + if (--retry) { + continue; + } else { + goto __exit; + } + } + delay(DELAY_CNT); + } + putchar('i'); + ret = iic_tx_byte(iic, buf[offset + tx_len - 1]); + if (!ret) { + if (--retry) { + continue; + } else { + goto __exit; + } + } + putchar('j'); + iic_stop(iic); + delay(DELAY_CNT); + } while (0); + offset += tx_len; + do { + iic_start(iic); + ret = iic_tx_byte(iic, EEPROM_WADDR); + if (ret) { + break; + } + delay(DELAY_CNT); + } while (1); + } +__exit: + iic_stop(iic); +#else + offset = 0; + while (offset < len) { + retry = 1; + tx_len = len - offset > 8 ? 8 : len - offset; + do { + iic_start(iic); + ret = iic_tx_byte(iic, EEPROM_WADDR); + if (!ret) { + if (--retry) { + continue; + } else { + goto __exit; + } + } + iic_tx_byte(iic, addr + offset); + if (!ret) { + if (--retry) { + continue; + } else { + goto __exit; + } + } + /* putchar('h'); */ + ret = iic_write_buf(iic, buf + offset, tx_len); + if (ret < tx_len) { + if (--retry) { + continue; + } else { + goto __exit; + } + } + /* putchar('i'); */ + iic_stop(iic); + delay(DELAY_CNT); + } while (0); + offset += tx_len; + do { + iic_start(iic); + ret = iic_tx_byte(iic, EEPROM_WADDR); + if (ret) { + break; + } + delay(DELAY_CNT); + } while (1); + /* putchar('j'); */ + } +__exit: + iic_stop(iic); +#endif +} + +void eeprom_read(int iic, u8 *buf, u32 addr, u32 len) +{ + int i; + u32 retry = 1; + int ret; +#if 0 + do { + iic_start(iic); + ret = iic_tx_byte(iic, EEPROM_WADDR); + if (!ret) { + if (--retry) { + continue; + } else { + break; + } + } + delay(DELAY_CNT); + ret = iic_tx_byte(iic, addr); + if (!ret) { + if (--retry) { + continue; + } else { + break; + } + } + delay(DELAY_CNT); + iic_start(iic); + ret = iic_tx_byte(iic, EEPROM_RADDR); + if (!ret) { + if (--retry) { + continue; + } else { + break; + } + } + delay(DELAY_CNT); + putchar('k'); + for (i = 0; i < len - 1; i++) { + buf[i] = iic_rx_byte(iic, 1); + delay(DELAY_CNT); + } + putchar('l'); + buf[len - 1] = iic_rx_byte(iic, 0); + iic_stop(iic); + delay(DELAY_CNT); + putchar('m'); + } while (0); +#else + do { + iic_start(iic); + ret = iic_tx_byte(iic, EEPROM_WADDR); + if (!ret) { + if (--retry) { + continue; + } else { + break; + } + } + iic_tx_byte(iic, addr); + if (!ret) { + if (--retry) { + continue; + } else { + break; + } + } + iic_start(iic); + ret = iic_tx_byte(iic, EEPROM_RADDR); + if (!ret) { + if (--retry) { + continue; + } else { + break; + } + } + iic_read_buf(iic, buf, len); + iic_stop(iic); + } while (0); +#endif +} + +void eeprom_test_main() +{ + int i = 0; + u8 flag = 0; + + iic_init(iic_dev); + for (i = 0; i < 512; i++) { + eeprom_wbuf[i] = i % 26 + 'A'; + eeprom_rbuf[i] = 0; + } + puts(">>>> write in\n"); + eeprom_write(iic_dev, eeprom_wbuf, 0, 128); + puts("<<<< write out\n"); + puts(">>>> read in\n"); + eeprom_read(iic_dev, eeprom_rbuf, 0, 128); + puts("<<<< read out\n"); + + for (i = 0; i < 128; i++) { + if (eeprom_wbuf[i] != eeprom_rbuf[i]) { + flag = 1; + break; + } + } + for (i = 0; i < 128; i++) { + putchar(eeprom_rbuf[i]); + putchar(' '); + if (i % 16 == 15) { + putchar('\n'); + } + } + putchar('\n'); + if (flag == 0) { + puts("eeprom read/write test pass\n"); + } else { + puts("eeprom read/write test fail\n"); + } + iic_uninit(iic_dev); +} + + +extern u8 sd_io_suspend(u8 sdx, u8 sd_io); +extern u8 sd_io_resume(u8 sdx, u8 sd_io); +void eeprom_det(void *p) +{ + u32 dly_cnt = 0; + while (sd_io_suspend(0, 0)) { + os_time_dly(1); + dly_cnt ++; + if (dly_cnt > 5) { + return; + } + } + u8 t_buf[8] = {9, 1, 2, 3, 4, 5, 6, 7}; + u8 r_buf[8] = {0}; + iic_init(iic_dev); + eeprom_write(iic_dev, t_buf, 0, 8); + eeprom_read(iic_dev, r_buf, 0, 8); + put_buf(r_buf, 8); + iic_uninit(iic_dev); + sd_io_resume(0, 0); +} +void eeprom_use_sd_io_test(void) +{ + sys_timer_add(0, eeprom_det, 50); +} + +#endif diff --git a/cpu/br23/iic_hw.c b/cpu/br23/iic_hw.c new file mode 100644 index 0000000..242fd69 --- /dev/null +++ b/cpu/br23/iic_hw.c @@ -0,0 +1,471 @@ +#include "asm/iic_hw.h" +#include "system/generic/gpio.h" +#include "system/generic/log.h" +#include "asm/clock.h" +#include "asm/cpu.h" +#include "update.h" + +/* + [[ 注意!!! ]] + * 适用于带cfg_done的硬件IIC,另一种硬件IIC另作说明 + * 硬件IIC的START / ACK(NACK)必须在发送或接收字节cfg_done前设置,且不能 + 接cfg_done单独发送;而STOP则应在发送或接收字节cfg_done后设置,必须接 + cfg_done单独发送 +*/ +struct iic_iomapping { + u8 scl; + u8 sda; +}; + +static const struct iic_iomapping hwiic_iomap[IIC_HW_NUM][IIC_PORT_GROUP_NUM] = { + { + {IO_PORT_DP, IO_PORT_DM}, //group a + {IO_PORTC_04, IO_PORTC_05}, //group b + {IO_PORTB_04, IO_PORTB_06}, //group c + {IO_PORTA_05, IO_PORTA_06}, //group d + }, +}; + +static JL_IIC_TypeDef *const iic_regs[IIC_HW_NUM] = { + JL_IIC, +}; + +#define iic_get_id(iic) (iic) + +#define iic_info_port(iic) (hw_iic_cfg[iic_get_id(iic)].port - 'A') +#define iic_info_baud(iic) (hw_iic_cfg[iic_get_id(iic)].baudrate) +#define iic_info_hdrive(iic) (hw_iic_cfg[iic_get_id(iic)].hdrive) +#define iic_info_io_filt(iic) (hw_iic_cfg[iic_get_id(iic)].io_filter) +#define iic_info_io_pu(iic) (hw_iic_cfg[iic_get_id(iic)].io_pu) +#define iic_info_role(iic) (hw_iic_cfg[iic_get_id(iic)].role) + +static inline u32 iic_get_scl(hw_iic_dev iic) +{ + u8 port = iic_info_port(iic); + return hwiic_iomap[iic_get_id(iic)][port].scl; +} + +static inline u32 iic_get_sda(hw_iic_dev iic) +{ + u8 port = iic_info_port(iic); + return hwiic_iomap[iic_get_id(iic)][port].sda; +} + +static int iic_port_init(hw_iic_dev iic) +{ + u32 reg; + int ret = 0; + u8 port; + u8 id = iic_get_id(iic); + u32 scl, sda; + + port = iic_info_port(iic); + if (port >= IIC_PORT_GROUP_NUM) { + return -EINVAL; + } + scl = iic_get_scl(iic); + sda = iic_get_sda(iic); + if (id == 0) { + reg = JL_IOMAP->CON1; + reg &= ~(0x3 << 18); + reg |= (port << 18); + JL_IOMAP->CON1 = reg; +#if 0 + if (port == 0) { + //USB_DP, USB_DM init + log_w("warning!!! iic overwrite usb configuration\n"); + JL_USB_IO->CON0 |= (BIT(11) | BIT(8)); //IO MODE + /* JL_USB_IO->CON0 &= ~BIT(2); //DP DIR OUT */ + /* JL_USB_IO->CON0 &= ~BIT(3); //DM DIR OUT */ + /* JL_USB_IO->CON0 |= BIT(0); //DP output 1 */ + /* JL_USB_IO->CON0 |= BIT(1); //DM output 1 */ + if (iic_info_io_pu(iic)) { + JL_USB_IO->CON0 |= BIT(6); //DP PU + JL_USB_IO->CON0 |= BIT(7); //DM PU + } else { + JL_USB_IO->CON0 &= ~BIT(6); //DP PU + JL_USB_IO->CON0 &= ~BIT(7); //DM PU + } + } else { + //gpio_direction_output(sca, 1); + //gpio_direction_output(sda, 1); + if (iic_info_hdrive(iic)) { + gpio_set_hd(scl, 1); + gpio_set_hd(sda, 1); + } else { + gpio_set_hd(scl, 0); + gpio_set_hd(sda, 0); + } + if (iic_info_io_pu(iic)) { + gpio_set_pull_up(scl, 1); + gpio_set_pull_up(sda, 1); + } else { + gpio_set_pull_up(scl, 0); + gpio_set_pull_up(sda, 0); + } + } +#else + if (port == 0) { + usb_iomode(1); + } + if (iic_info_hdrive(iic)) { + gpio_set_hd(scl, 1); + gpio_set_hd(sda, 1); + } else { + gpio_set_hd(scl, 0); + gpio_set_hd(sda, 0); + } + if (iic_info_io_pu(iic)) { + gpio_set_pull_up(scl, 1); + gpio_set_pull_up(sda, 1); + } else { + gpio_set_pull_up(scl, 0); + gpio_set_pull_up(sda, 0); + } +#endif + //} else if (fh->id == 1) { + } else { + ret = -EINVAL; + } + return ret; +} + +int hw_iic_set_baud(hw_iic_dev iic, u32 baud) +{ + //f_iic = f_sys / ((IIC_BAUD + 1) * 2) + //=> IIC_BAUD = f_sys / (2 * f_iic) - 1 + u32 sysclk; + u8 id = iic_get_id(iic); + + sysclk = clk_get("lsb"); + if (sysclk < 2 * baud) { + return -EINVAL; + } + iic_baud_reg(iic_regs[id]) = sysclk / (2 * baud) - 1; + return 0; +} + +static void hw_iic_set_die(hw_iic_dev iic, u8 en) +{ + u8 id = iic_get_id(iic); + u8 port = iic_info_port(iic); + u32 scl, sda; + + if (port >= IIC_PORT_GROUP_NUM) { + return ; + } + scl = iic_get_scl(iic); + sda = iic_get_sda(iic); + if (id == 0) { +#if 0 + if (port == 0) { + if (en) { + JL_USB_IO->CON0 |= BIT(9); //DP 1.2V digital input en + JL_USB_IO->CON0 |= BIT(10); //DM 1.2V digital input en + } else { + JL_USB_IO->CON0 &= ~BIT(9); + JL_USB_IO->CON0 &= ~BIT(10); + } + } else { + gpio_set_die(scl, en); //!!!must set + gpio_set_die(sda, en); //!!!must set + } +#else + gpio_set_die(scl, en); + gpio_set_die(sda, en); +#endif + } else { + //undefined + } +} + +void hw_iic_suspend(hw_iic_dev iic) +{ + hw_iic_set_die(iic, 0); +} + +void hw_iic_resume(hw_iic_dev iic) +{ + hw_iic_set_die(iic, 1); +} + +int hw_iic_init(hw_iic_dev iic) +{ + int ret; + u8 id = iic_get_id(iic); + + if ((ret = iic_port_init(iic))) { + log_e("invalid hardware iic port\n"); + return ret; + } + hw_iic_set_die(iic, 1); + if (iic_info_role(iic) == IIC_MASTER) { + iic_role_host(iic_regs[id]); + } else { + iic_role_slave(iic_regs[id]); + iic_si_mode_en(iic_regs[id]); + } + if (iic_info_io_filt(iic)) { + iic_isel_filter(iic_regs[id]); + } else { + iic_isel_direct(iic_regs[id]); + } + if ((ret = hw_iic_set_baud(iic, iic_info_baud(iic)))) { + log_e("iic baudrate is invalid\n"); + return ret ; + } + iic_pnd_clr(iic_regs[id]); + iic_end_pnd_clr(iic_regs[id]); + iic_start_pnd_clr(iic_regs[id]); + iic_enable(iic_regs[id]); +#if 0 + printf("info->scl = %d\n", iic_get_scl(iic)); + printf("info->sda = %d\n", iic_get_sda(iic)); + printf("info->baudrate = %d\n", iic_info_baud(iic)); + printf("info->hdrive = %d\n", iic_info_hdrive(iic)); + printf("info->io_filter = %d\n", iic_info_io_filt(iic)); + printf("info->io_pu = %d\n", iic_info_io_pu(iic)); + printf("info->role = %d\n", iic_info_role(iic)); + printf("IIC_CON0 0x%04x\n", iic_regs[id]->CON0); + printf("IIC_CON1 0x%04x\n", iic_regs[id]->CON1); + printf("IIC_BAUD 0x%02x\n", iic_regs[id]->BAUD); + //printf("IIC_BUF %02x\n", iic_regs[id]->BUF); + printf("IOMC1 0x%08x\n", JL_IOMAP->CON1); +#endif + return 0; +} + +void hw_iic_uninit(hw_iic_dev iic) +{ + u8 id = iic_get_id(iic); + u8 port = iic_info_port(iic); + u32 scl, sda; + + scl = iic_get_scl(iic); + sda = iic_get_sda(iic); + hw_iic_set_die(iic, 0); + if (id == 0) { +#if 0 + if (port == 0) { + //JL_USB_IO->CON0 |= BIT(2); //DP DIR IN + //JL_USB_IO->CON0 |= BIT(3); //DM DIR IN + JL_USB_IO->CON0 &= ~(BIT(11) | BIT(8)); //disable IO_MODE + JL_USB_IO->CON0 &= ~BIT(6); //DP PU + JL_USB_IO->CON0 &= ~BIT(7); //DM PU + } else { + /* gpio_set_direction(scl, 1); */ + /* gpio_set_direction(sda, 1); */ + gpio_set_hd(scl, 0); + gpio_set_hd(sda, 0); + gpio_set_pull_up(scl, 0); + gpio_set_pull_up(sda, 0); + } +#else + gpio_set_hd(scl, 0); + gpio_set_hd(sda, 0); + gpio_set_pull_up(scl, 0); + gpio_set_pull_up(sda, 0); + if (port == 0) { + usb_iomode(0); + } +#endif + } + iic_disable(iic_regs[id]); +} + +void hw_iic_start(hw_iic_dev iic) +{ + u8 id = iic_get_id(iic); + iic_preset_restart(iic_regs[id]); + //don't add iic_cfg_done() here, it must be used with send byte +} + +void hw_iic_stop(hw_iic_dev iic) +{ + u8 id = iic_get_id(iic); + iic_preset_end(iic_regs[id]); + iic_cfg_done(iic_regs[id]); +} + +u8 hw_iic_tx_byte(hw_iic_dev iic, u8 byte) +{ + u8 id = iic_get_id(iic); + iic_dir_out(iic_regs[id]); + iic_buf_reg(iic_regs[id]) = byte; + iic_cfg_done(iic_regs[id]); + /* putchar('a'); */ + while (!iic_pnd(iic_regs[id])); + iic_pnd_clr(iic_regs[id]); + /* putchar('b'); */ + return iic_send_is_ack(iic_regs[id]); +} + +u8 hw_iic_rx_byte(hw_iic_dev iic, u8 ack) +{ + u8 id = iic_get_id(iic); + iic_dir_in(iic_regs[id]); + if (ack) { + iic_recv_ack(iic_regs[id]); + } else { + iic_recv_nack(iic_regs[id]); + } + iic_buf_reg(iic_regs[id]) = 0xff; + iic_cfg_done(iic_regs[id]); + /* putchar('c'); */ + while (!iic_pnd(iic_regs[id])); + iic_pnd_clr(iic_regs[id]); + /* putchar('d'); */ + return iic_buf_reg(iic_regs[id]); +} + +int hw_iic_read_buf(hw_iic_dev iic, void *buf, int len) +{ + u8 id = iic_get_id(iic); + int i; + + if (!buf || !len) { + return -1; + } + iic_dir_in(iic_regs[id]); + iic_recv_ack(iic_regs[id]); + for (i = 0; i < len; i++) { + if (i == len - 1) { + iic_recv_nack(iic_regs[id]); + } + iic_buf_reg(iic_regs[id]) = 0xff; + iic_cfg_done(iic_regs[id]); + while (!iic_pnd(iic_regs[id])); + iic_pnd_clr(iic_regs[id]); + ((u8 *)buf)[i] = iic_buf_reg(iic_regs[id]); + } + return len; +} + +int hw_iic_write_buf(hw_iic_dev iic, const void *buf, int len) +{ + u8 id = iic_get_id(iic); + int i = 0; + + if (!buf || !len) { + return -1; + } + iic_dir_out(iic_regs[id]); + for (i = 0; i < len; i++) { + iic_buf_reg(iic_regs[id]) = ((u8 *)buf)[i]; + iic_cfg_done(iic_regs[id]); + while (!iic_pnd(iic_regs[id])); + iic_pnd_clr(iic_regs[id]); + if (!iic_send_is_ack(iic_regs[id])) { + break; + } + } + return i; +} + +void hw_iic_set_ie(hw_iic_dev iic, u8 en) +{ + u8 id = iic_get_id(iic); + + if (en) { + iic_set_ie(iic_regs[id]); + } else { + iic_clr_ie(iic_regs[id]); + } +} + +u8 hw_iic_get_pnd(hw_iic_dev iic) +{ + u8 id = iic_get_id(iic); + + return !!iic_pnd(iic_regs[id]); +} + +void hw_iic_clr_pnd(hw_iic_dev iic) +{ + u8 id = iic_get_id(iic); + + iic_pnd_clr(iic_regs[id]); +} + +void hw_iic_set_end_ie(hw_iic_dev iic, u8 en) +{ + u8 id = iic_get_id(iic); + + if (en) { + iic_set_end_ie(iic_regs[id]); + } else { + iic_clr_end_ie(iic_regs[id]); + } +} + +u8 hw_iic_get_end_pnd(hw_iic_dev iic) +{ + u8 id = iic_get_id(iic); + + return !!iic_end_pnd(iic_regs[id]); +} + +void hw_iic_clr_end_pnd(hw_iic_dev iic) +{ + u8 id = iic_get_id(iic); + + iic_end_pnd_clr(iic_regs[id]); +} + +void hw_iic_slave_set_addr(hw_iic_dev iic, u8 addr, u8 addr_ack) +{ + u8 id = iic_get_id(iic); + + iic_baud_reg(iic_regs[id]) = (addr & 0xfe) | !!addr_ack; +} + +void hw_iic_slave_rx_prepare(hw_iic_dev iic, u8 ack) +{ + u8 id = iic_get_id(iic); + + iic_dir_in(iic_regs[id]); + if (ack) { + iic_recv_ack(iic_regs[id]); + } else { + iic_recv_nack(iic_regs[id]); + } + iic_buf_reg(iic_regs[id]) = 0xff; + iic_cfg_done(iic_regs[id]); +} + +u8 hw_iic_slave_rx_byte(hw_iic_dev iic, bool *is_start_addr) +{ + u8 id = iic_get_id(iic); + if (iic_start_pnd(iic_regs[id])) { + iic_start_pnd_clr(iic_regs[id]); + is_start_addr ? (*is_start_addr = 1) : 0; + } else { + is_start_addr ? (*is_start_addr = 0) : 0; + } + return iic_buf_reg(iic_regs[id]); +} + +void hw_iic_slave_tx_byte(hw_iic_dev iic, u8 byte) +{ + u8 id = iic_get_id(iic); + + iic_dir_out(iic_regs[id]); + iic_buf_reg(iic_regs[id]) = byte; + iic_cfg_done(iic_regs[id]); +} + +u8 hw_iic_slave_tx_check_ack(hw_iic_dev iic) +{ + u8 id = iic_get_id(iic); + + return iic_send_is_ack(iic_regs[id]); +} +void iic_disable_for_ota() +{ + JL_IIC->CON0 = 0; +} + +REGISTER_UPDATE_TARGET(iic_update_target) = { + .name = "iic", + .driver_close = iic_disable_for_ota, +}; diff --git a/cpu/br23/iic_slave_test.c b/cpu/br23/iic_slave_test.c new file mode 100644 index 0000000..61ab539 --- /dev/null +++ b/cpu/br23/iic_slave_test.c @@ -0,0 +1,315 @@ +#include "system/includes.h" +#include "media/includes.h" +//#include "device/iic.h" +#include "asm/iic_hw.h" +#include "asm/iic_soft.h" + +#if 0 +/* + [[[ README ]]] + 1. iic从机需要赋值hw_iic_cfg.role = IIC_SLAVE,若role没有赋值或赋值成 + IIC_MASTER,则默认是主机模式。 + 2. iic从机的demo使用中断-任务的交互方式,避免while(!iic_pnd)的阻塞方式造成的 + CPU浪费及响应不及时。由于IIC没有DMA,每传输1 byte就会触发1次中断,所以IIC主机 + 必须每传输完成1字节delay一段时间,以至少等待IIC从机响应中断。iic stop产生的 + end中断被用于计算接收字节数及复位状态机,不要去掉end中断的使能及处理。IIC可能 + 会收到意外的end中断,所以end中断的处理必须用start-end包住。 + 3. demo的接收/发送使用double buffer,避免处理数据过程中被下次接收/发送的数据 + 覆盖。 + 4. IIC从机收到IIC_S_RADDR后需要尽快准备需要发送的数据,因为主机会很短时间内发 + 送下一个IIC字节时钟以请求数据。 + 5. IIC主机的TX的STOP到下个RX的START需要delay一段时间,否则会收多收一个不正确 + 的字节。 + 6. 未尽事项代码中的注释。 +*/ + +#define IIC_S_RADDR 0x61 +#define IIC_S_WADDR 0x60 + +#define IIC_S_DEV 0 +#define IIC_S_TXBUF_SIZE 128 +#define IIC_S_RXBUF_SIZE 128 + +enum { + IIC_S_MSG_TX, + IIC_S_MSG_RX, +}; + +struct iic_s_tx_statemachine { + u8 *buf[2]; + u32 b_size; + bool toggle; + u32 cur_cnt; + u32 tx_cnt; +}; + +struct iic_s_rx_statemachine { + u8 *buf[2]; + u32 b_size; + bool toggle; + u32 cur_cnt; + u32 rx_cnt; +}; + +struct iic_slave { + enum {IIC_S_TX, IIC_S_RX} dir; + struct iic_s_tx_statemachine tx; + struct iic_s_rx_statemachine rx; + u8 bus_occupy; +}; + +static struct iic_slave iic_s; +static u8 iic_s_txbuf[2][IIC_S_TXBUF_SIZE]; +static u8 iic_s_rxbuf[2][IIC_S_RXBUF_SIZE]; + +SET_INTERRUPT +static void iic_slave_isr() +{ + u8 is_addr = 0; + u8 byte; + + if (hw_iic_get_pnd(IIC_S_DEV)) { + hw_iic_clr_pnd(IIC_S_DEV); + putchar('a'); + if (iic_s.dir == IIC_S_RX) { + byte = hw_iic_slave_rx_byte(IIC_S_DEV, &is_addr); //判断是否为地址 + if (is_addr) { + iic_s.rx.cur_cnt = 0; + iic_s.rx.rx_cnt = 0; + iic_s.tx.cur_cnt = 0; + iic_s.tx.tx_cnt = 0; + if (byte == IIC_S_WADDR) { + putchar('b'); + hw_iic_slave_rx_prepare(IIC_S_DEV, 1); //触发下1 byte接收,并使能recv ack + iic_s.bus_occupy = 1; + } else if (byte == IIC_S_RADDR) { + putchar('c'); + iic_s.dir = IIC_S_TX; + os_taskq_post_msg("iic_slave", 1, IIC_S_MSG_TX); + iic_s.bus_occupy = 1; //包住start-stop,避免处理意外的stop处理 + } + } else { + putchar('d'); + if (iic_s.rx.cur_cnt < iic_s.rx.b_size) { + iic_s.rx.buf[iic_s.rx.toggle][iic_s.rx.cur_cnt++] = byte; + } + hw_iic_slave_rx_prepare(IIC_S_DEV, 1); //触发下1 byte接收,并使能recv ack + } + } else { + putchar('e'); + //如果主机接收ACK或者是最后1 byte主机NACK,发送下1 byte,否则重发当前byte + if (hw_iic_slave_tx_check_ack(IIC_S_DEV) || + (iic_s.tx.tx_cnt - iic_s.tx.cur_cnt == 1)) { + iic_s.tx.cur_cnt++; + } + if (iic_s.tx.cur_cnt < iic_s.tx.tx_cnt) { + hw_iic_slave_tx_byte(IIC_S_DEV, iic_s.tx.buf[iic_s.tx.toggle][iic_s.tx.cur_cnt]); + } else { + //如果主机请求字节数比实际IIC发送字节数多,则发送0xff,防止主机while(!iic_pnd)阻塞卡死 + hw_iic_slave_tx_byte(IIC_S_DEV, 0xff); + } + } + } + if (hw_iic_get_end_pnd(IIC_S_DEV)) { + hw_iic_clr_end_pnd(IIC_S_DEV); + putchar('f'); + //start-stop包住,收到stop时的处理 + if (iic_s.bus_occupy) { + iic_s.bus_occupy = 0; + if (iic_s.dir == IIC_S_RX) { + putchar('g'); + iic_s.rx.toggle = !iic_s.rx.toggle; + iic_s.rx.rx_cnt = iic_s.rx.cur_cnt; + os_taskq_post_msg("iic_slave", 2, IIC_S_MSG_RX, iic_s.rx.rx_cnt); + } else { + putchar('h'); + iic_s.tx.toggle = !iic_s.tx.toggle; + } + iic_s.dir = IIC_S_RX; + iic_s.rx.cur_cnt = 0; + iic_s.tx.cur_cnt = 0; + iic_s.tx.tx_cnt = 0; + hw_iic_slave_rx_prepare(IIC_S_DEV, 0); //触发下1 byte接收,并NACK + } + } +} + +static void iic_slave_task(void *arg) +{ + int res; + int msg[8]; + u32 rxlen = 0; + u32 txlen = 0; + u8 *addr; + + printf("iic_slave_task run\n"); + memset(&iic_s, 0, sizeof(struct iic_slave)); + iic_s.dir = IIC_S_RX; + iic_s.rx.buf[0] = iic_s_rxbuf[0]; + iic_s.rx.buf[1] = iic_s_rxbuf[1]; + iic_s.rx.b_size = IIC_S_RXBUF_SIZE; + iic_s.tx.buf[0] = iic_s_txbuf[0]; + iic_s.tx.buf[1] = iic_s_txbuf[1]; + iic_s.tx.b_size = IIC_S_TXBUF_SIZE; + + hw_iic_init(IIC_S_DEV); + //设置IIC从机地址,并且使能地址包自动ACK + hw_iic_slave_set_addr(IIC_S_DEV, IIC_S_WADDR, 1); + //注册中断isr + request_irq(IRQ_IIC_IDX, 3, iic_slave_isr, 0); + //使能byte传输中断 + hw_iic_set_ie(IIC_S_DEV, 1); + //使能stop中断 + hw_iic_set_end_ie(IIC_S_DEV, 1); + //请求接收,禁止ACK,避免与地址包自动ACK冲突。bit ACK需要在接收数据前设置,关 + //闭ACK并打开地址包自动ACK是为了挂多个IIC从机时,本IIC从机不会ACK其他IIC设备 + //地址,造成多从机失效。地址包自动ACK只有当从机收到设置的地址才会ACK,否则 + //NACK + hw_iic_slave_rx_prepare(IIC_S_DEV, 0); + __asm__ volatile("%0 = icfg" : "=r"(res)); + printf("icfg = %08x\n", res); + + while (1) { + res = os_taskq_pend("taskq", msg, 8); + switch (res) { + case OS_TASKQ: + switch (msg[0]) { + case Q_MSG: + switch (msg[1]) { + case IIC_S_MSG_RX: + puts(">>>>>> iic_s rx msg\n"); + rxlen = msg[2]; + addr = iic_s.rx.buf[!iic_s.rx.toggle]; + printf("rx len: %d\n", rxlen); + //put_buf(addr, rxlen); + for (int i = 0; i < rxlen; i++) { + putchar(*(addr + i)); + putchar(0x20); + if (i % 16 == 15) { + putchar('\n'); + } + } + break; + case IIC_S_MSG_TX: + puts(">>>>>> iic_s tx msg\n"); + txlen = rxlen; + memcpy(iic_s.tx.buf[!iic_s.tx.toggle], iic_s.rx.buf[!iic_s.rx.toggle], txlen); + iic_s.tx.tx_cnt = txlen; + hw_iic_slave_tx_byte(IIC_S_WADDR, iic_s.tx.buf[!iic_s.tx.toggle][0]); + iic_s.tx.toggle = !iic_s.tx.toggle; + printf("tx req len: %d\n", txlen); + break; + } + break; + } + break; + } + } +} + +void iic_demo_slave_main() +{ + printf("%s() %d\n", __func__, __LINE__); + os_task_create(iic_slave_task, NULL, 30, 1024, 64, "iic_slave"); +} + + + + +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~ iic host below ~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ + +#define IIC_H_DEV 0 +#define IIC_H_TXBUF_SIZE 128 +#define IIC_H_RXBUF_SIZE 128 +#define IIC_H_DELAY 500 + +#define iic_h_check_ack(ack, pCnt) \ + if (!(ack)) { \ + printf("nack %d\n", __LINE__); \ + if (*(pCnt) > 0 && --(*(pCnt))) { \ + continue; \ + } else { \ + break; \ + } \ + } + +static u8 iic_h_txbuf[IIC_H_TXBUF_SIZE]; +static u8 iic_h_rxbuf[IIC_H_RXBUF_SIZE]; + +void iic_demo_host_main() +{ + int i; + int ret; + u32 retry; + u8 byte; + + printf("%s() %d\n", __func__, __LINE__); + hw_iic_init(IIC_H_DEV); + for (i = 0; i < IIC_H_TXBUF_SIZE; i++) { + iic_h_txbuf[i] = 'A' + i % 26; + } + for (u8 times = 0; times < 3; times++) { //测试次数 + retry = 10; + do { + hw_iic_start(IIC_H_DEV); + putchar('a'); + ret = hw_iic_tx_byte(IIC_H_DEV, IIC_S_WADDR); + putchar('b'); + iic_h_check_ack(ret, &retry); + delay(IIC_H_DELAY); + i = 0; + while (i < IIC_H_TXBUF_SIZE) { + ret = hw_iic_tx_byte(IIC_H_DEV, iic_h_txbuf[i]); + putchar('c'); + iic_h_check_ack(ret, &retry); + delay(IIC_H_DELAY); + i++; + } + break; + } while (1); + hw_iic_stop(IIC_H_DEV); + delay(IIC_H_DELAY); //stop后需要delay一段时间后再start + + retry = 10; + do { + hw_iic_start(IIC_H_DEV); + putchar('d'); + ret = hw_iic_tx_byte(IIC_H_DEV, IIC_S_RADDR); + putchar('e'); + iic_h_check_ack(ret, &retry); + delay(IIC_H_DELAY); + i = 0; + while (i < IIC_H_RXBUF_SIZE - 1) { + iic_h_rxbuf[i] = hw_iic_rx_byte(IIC_H_DEV, 1); + putchar('f'); + delay(IIC_H_DELAY); + i++; + } + iic_h_rxbuf[i] = hw_iic_rx_byte(IIC_H_DEV, 0); //IIC主机接收最后1 byte NACK + putchar('g'); + delay(IIC_H_DELAY); + break; + } while (1); + hw_iic_stop(IIC_H_DEV); //stop后需要delay一段时间后再start + delay(IIC_H_DELAY); + putchar('\n'); + + ret = 0; + for (i = 0; i < IIC_H_RXBUF_SIZE; i++) { + putchar(iic_h_rxbuf[i]); + putchar(0x20); + if (i % 16 == 15) { + putchar('\n'); + } + if (iic_h_txbuf[i] != iic_h_rxbuf[i]) { + ret = 1; + } + } + if (!ret) { + puts("iic slave test pass\n"); + } else { + puts("iic slave test fail\n"); + } + } +} +#endif diff --git a/cpu/br23/iic_soft.c b/cpu/br23/iic_soft.c new file mode 100644 index 0000000..c659dbd --- /dev/null +++ b/cpu/br23/iic_soft.c @@ -0,0 +1,336 @@ +//#include "system/init.h" +#include "asm/iic_soft.h" +#include "generic/gpio.h" + +#define IIC_SCL_DIR(scl, val) \ + gpio_set_direction(scl, val) + +#define IIC_SCL_SET_PU(scl, on) \ + gpio_set_pull_up(scl, on) + +#define IIC_SCL_SET_PD(scl, on) \ + gpio_set_pull_down(scl, on) + +#define IIC_SCL_SET_DIE(scl, on) \ + gpio_set_die(scl, on) + +#define IIC_SCL_H(scl) \ + gpio_direction_output(scl, 1) + +#define IIC_SCL_L(scl) \ + gpio_direction_output(scl, 0) + +#define IIC_SDA_DIR(sda, val) \ + gpio_set_direction(sda, val) + +#define IIC_SDA_SET_PU(sda, on) \ + gpio_set_pull_up(sda, on) + +#define IIC_SDA_SET_PD(sda, on) \ + gpio_set_pull_down(sda, on) + +#define IIC_SDA_SET_DIE(sda, on) \ + gpio_set_die(sda, on) + +#define IIC_SDA_H(sda) \ + gpio_direction_output(sda, 1) + +#define IIC_SDA_L(sda) \ + gpio_direction_output(sda, 0) + +#define IIC_SDA_READ(sda) \ + gpio_read(sda) + +#define iic_get_id(iic) (iic) + +static inline u32 iic_get_scl(soft_iic_dev iic) +{ + u8 id = iic_get_id(iic); + return soft_iic_cfg[id].scl; +} + +static inline u32 iic_get_sda(soft_iic_dev iic) +{ + u8 id = iic_get_id(iic); + return soft_iic_cfg[id].sda; +} + +static inline u32 iic_get_delay(soft_iic_dev iic) +{ + u8 id = iic_get_id(iic); + return soft_iic_cfg[id].delay; +} + +static inline u32 iic_get_io_pu(soft_iic_dev iic) +{ + u8 id = iic_get_id(iic); + return soft_iic_cfg[id].io_pu; +} + + +int soft_iic_init(soft_iic_dev iic) +{ + u32 scl, sda; + + scl = iic_get_scl(iic); + sda = iic_get_sda(iic); + + IIC_SCL_DIR(scl, 0); + IIC_SCL_SET_PD(scl, 0); + IIC_SCL_SET_DIE(scl, 1); + IIC_SCL_H(scl); + IIC_SDA_DIR(sda, 0); + IIC_SDA_SET_PD(sda, 0); + IIC_SDA_SET_DIE(sda, 1); + IIC_SDA_H(sda); + if (iic_get_io_pu(iic)) { + IIC_SCL_SET_PU(scl, 1); + IIC_SDA_SET_PU(sda, 1); + } else { + IIC_SCL_SET_PU(scl, 0); + IIC_SDA_SET_PU(sda, 0); + } + return 0; +} + +void soft_iic_uninit(soft_iic_dev iic) +{ + u32 scl, sda; + + scl = iic_get_scl(iic); + sda = iic_get_sda(iic); + + IIC_SCL_DIR(scl, 1); + IIC_SCL_SET_PU(scl, 0); + IIC_SCL_SET_PD(scl, 0); + IIC_SCL_SET_DIE(scl, 0); + IIC_SDA_DIR(sda, 1); + IIC_SDA_SET_PU(sda, 0); + IIC_SDA_SET_PD(sda, 0); + IIC_SDA_SET_DIE(sda, 0); +} + +void soft_iic_suspend(soft_iic_dev iic) +{ + u32 scl, sda; + + scl = iic_get_scl(iic); + sda = iic_get_sda(iic); + + IIC_SCL_SET_DIE(scl, 0); + IIC_SDA_SET_DIE(sda, 0); +} + +void soft_iic_resume(soft_iic_dev iic) +{ + u32 scl, sda; + + scl = iic_get_scl(iic); + sda = iic_get_sda(iic); + + IIC_SCL_SET_DIE(scl, 1); + IIC_SDA_SET_DIE(sda, 1); +} + +void soft_iic_start(soft_iic_dev iic) +{ + u32 scl, sda, dly_t; + + scl = iic_get_scl(iic); + sda = iic_get_sda(iic); + dly_t = iic_get_delay(iic); + + IIC_SDA_H(sda); + delay(dly_t); + + IIC_SCL_H(scl); + delay(dly_t * 2); + + IIC_SDA_L(sda); + delay(dly_t); + + IIC_SCL_L(scl); + delay(dly_t); +} + +void soft_iic_stop(soft_iic_dev iic) +{ + u32 scl, sda, dly_t; + + scl = iic_get_scl(iic); + sda = iic_get_sda(iic); + dly_t = iic_get_delay(iic); + + IIC_SDA_L(sda); + delay(dly_t); + + IIC_SCL_H(scl); + delay(dly_t * 2); + + IIC_SDA_H(sda); + delay(dly_t); +} + +static u8 soft_iic_check_ack(soft_iic_dev iic) +{ + u8 ack; + u32 scl, sda, dly_t; + + scl = iic_get_scl(iic); + sda = iic_get_sda(iic); + dly_t = iic_get_delay(iic); + + IIC_SDA_DIR(sda, 1); + IIC_SCL_L(scl); + delay(dly_t); + + IIC_SCL_H(scl); + delay(dly_t); + + if (IIC_SDA_READ(sda) == 0) { + ack = 1; + } else { + ack = 0; + } + delay(dly_t); + + IIC_SCL_L(scl); + delay(dly_t); + IIC_SDA_DIR(sda, 0); + IIC_SDA_L(sda); + + return ack; +} + +static void soft_iic_rx_ack(soft_iic_dev iic) +{ + u32 scl, sda, dly_t; + + scl = iic_get_scl(iic); + sda = iic_get_sda(iic); + dly_t = iic_get_delay(iic); + + IIC_SDA_L(sda); + delay(dly_t); + + IIC_SCL_H(scl); + delay(dly_t * 2); + + IIC_SCL_L(scl); + delay(dly_t); +} + +static void soft_iic_rx_nack(soft_iic_dev iic) +{ + u32 scl, sda, dly_t; + + scl = iic_get_scl(iic); + sda = iic_get_sda(iic); + dly_t = iic_get_delay(iic); + + IIC_SDA_H(sda); + delay(dly_t); + + IIC_SCL_H(scl); + delay(dly_t * 2); + + IIC_SCL_L(scl); + delay(dly_t); +} + +u8 soft_iic_tx_byte(soft_iic_dev iic, u8 byte) +{ + u8 i, ret; + u32 scl, sda, dly_t; + + scl = iic_get_scl(iic); + sda = iic_get_sda(iic); + dly_t = iic_get_delay(iic); + + IIC_SCL_L(scl); + for (i = 0; i < 8; i++) { //MSB FIRST + if ((byte << i) & 0x80) { + IIC_SDA_H(sda); + } else { + IIC_SDA_L(sda); + } + delay(dly_t); + + IIC_SCL_H(scl); + delay(dly_t * 2); + + IIC_SCL_L(scl); + delay(dly_t); + } + return soft_iic_check_ack(iic); +} + +u8 soft_iic_rx_byte(soft_iic_dev iic, u8 ack) +{ + u8 byte = 0, i; + u32 scl, sda, dly_t; + + scl = iic_get_scl(iic); + sda = iic_get_sda(iic); + dly_t = iic_get_delay(iic); + + IIC_SDA_DIR(sda, 1); + + for (i = 0; i < 8; i++) { + delay(dly_t); + + IIC_SCL_H(scl); + delay(dly_t); + + byte = byte << 1; + if (IIC_SDA_READ(sda)) { + byte |= 1; + } + delay(dly_t); + + IIC_SCL_L(scl); + delay(dly_t); + } + + IIC_SDA_DIR(sda, 0); + if (ack) { + soft_iic_rx_ack(iic); + } else { + soft_iic_rx_nack(iic); + } + + return byte; +} + + +int soft_iic_read_buf(soft_iic_dev iic, void *buf, int len) +{ + int i = 0; + + if (!buf || !len) { + return -1; + } + for (i = 0; i < len - 1; i++) { + ((u8 *)buf)[i] = soft_iic_rx_byte(iic, 1); + } + ((u8 *)buf)[len - 1] = soft_iic_rx_byte(iic, 0); + return len; +} + +int soft_iic_write_buf(soft_iic_dev iic, const void *buf, int len) +{ + int i; + u8 ack; + + if (!buf || !len) { + return -1; + } + for (i = 0; i < len; i++) { + ack = soft_iic_tx_byte(iic, ((u8 *)buf)[i]); + if (ack == 0) { + break; + } + } + return i; +} + diff --git a/cpu/br23/irflt.c b/cpu/br23/irflt.c new file mode 100644 index 0000000..1cb8a06 --- /dev/null +++ b/cpu/br23/irflt.c @@ -0,0 +1,220 @@ + +#include "asm/includes.h" +#include "asm/irflt.h" +#include "timer.h" +#include "generic/gpio.h" + +#define ir_log log_d + +//红外定时器定义 +#define IR_TIMER TIMER3 +#define IR_IRQ_TIME_IDX IRQ_TIME3_IDX +#define IR_TIME_REG JL_TIMER3 + +IR_CODE ir_code; ///<红外遥控信息 +u16 timer1_pad; + +static const u16 timer_div[] = { + /*0000*/ 1, + /*0001*/ 4, + /*0010*/ 16, + /*0011*/ 64, + /*0100*/ 2, + /*0101*/ 8, + /*0110*/ 32, + /*0111*/ 128, + /*1000*/ 256, + /*1001*/ 4 * 256, + /*1010*/ 16 * 256, + /*1011*/ 64 * 256, + /*1100*/ 2 * 256, + /*1101*/ 8 * 256, + /*1110*/ 32 * 256, + /*1111*/ 128 * 256, +}; + + +#define IRFLT_OUTPUT_TIMER_SEL(x) SFR(JL_IOMAP->CON0, 8, 3, x) + + +/*----------------------------------------------------------------------------*/ +/**@brief time1红外中断服务函数 + @param void + @param void + @return void + @note void timer1_ir_isr(void) +*/ +/*----------------------------------------------------------------------------*/ +___interrupt +void timer_ir_isr(void) +{ + u16 bCap1; + u8 cap = 0; + + static u8 cnt = 0; + + IR_TIME_REG->CON |= BIT(14); + + bCap1 = IR_TIME_REG->PRD; + IR_TIME_REG->CNT = 0; + cap = bCap1 / ir_code.timer_pad; + + /* ir_log("cnt = %d, cap = 0x%x", cnt++, cap); */ + if (cap <= 1) { + ir_code.wData >>= 1; + ir_code.bState++; + ir_code.boverflow = 0; + } else if (cap == 2) { + ir_code.wData >>= 1; + ir_code.bState++; + ir_code.wData |= 0x8000; + ir_code.boverflow = 0; + } + /*13ms-Sync*/ + /* + else if ((cap == 13) || (cap < 8) || (cap > 110)) + { + ir_code.bState = 0; + } + else + { + ir_code.boverflow = 0; + } + */ + else if ((cap == 13) && (ir_code.boverflow < 8)) { + ir_code.bState = 0; + } else if ((cap < 8) && (ir_code.boverflow < 5)) { + ir_code.bState = 0; + } else if ((cap > 110) && (ir_code.boverflow > 53)) { + ir_code.bState = 0; + } else if ((cap > 20) && (ir_code.boverflow > 53)) { //溢出情况下 (12M 48M) + ir_code.bState = 0; + } else { + ir_code.boverflow = 0; + } + if (ir_code.bState == 16) { + ir_code.wUserCode = ir_code.wData; + } + if (ir_code.bState == 32) { + /* printf("[0x%X]",ir_code.wData); */ + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief ir按键初始化 + @param void + @param void + @return void + @note void set_ir_clk(void) + + ((cnt - 1)* 分频数)/lsb_clk = 1ms +*/ +/*----------------------------------------------------------------------------*/ +/* #define APP_TIMER_CLK clk_get("timer")//选osc时钟源 */ +#define APP_TIMER_CLK 12000000L //pll12m +#define TIMER_UNIT_MS 1 +#define MAX_TIME_CNT 0x07ff //分频准确范围,更具实际情况调整 +#define MIN_TIME_CNT 0x0030 +void set_ir_clk(void) +{ + u32 clk; + u32 prd_cnt; + u8 index; + + + for (index = 0; index < (sizeof(timer_div) / sizeof(timer_div[0])); index++) { + prd_cnt = TIMER_UNIT_MS * (APP_TIMER_CLK / 1000) / timer_div[index]; + if (prd_cnt > MIN_TIME_CNT && prd_cnt < MAX_TIME_CNT) { + break; + } + } + + ir_code.timer_pad = prd_cnt; + /* IR_TIME_REG->CON = ((index << 4) | BIT(3) | BIT(1) | BIT(0));//选择osc时钟 */ + JL_IOMAP->CON1 |= BIT(27);//这里已选了timer3,时钟源选io信号里的pll_12m,不是所有的timer都可选pll,修改请看文档 + IR_TIME_REG->CON = ((index << 4) | BIT(2) | BIT(1) | BIT(0)); + +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 获取ir按键值 + @param void + @param void + @return void + @note void get_irkey_value(void) +*/ +/*----------------------------------------------------------------------------*/ +u8 get_irflt_value(void) +{ + u8 tkey = 0xff; + if (ir_code.bState != 32) { + return tkey; + } + + /* printf("(0x%X_%x)",ir_code.wUserCode,ir_code.wData); */ + if ((((u8 *)&ir_code.wData)[0] ^ ((u8 *)&ir_code.wData)[1]) == 0xff) { + /* if (ir_code.wUserCode == 0xFF00) */ + { + /* printf("<%d>",(u8)ir_code.wData); */ + tkey = (u8)ir_code.wData; + } + } else { + ir_code.bState = 0; + } + + return tkey; +} + +void ir_input_io_sel(u8 port) +{ + //选择input channel1输入 + // IOMC2[13 : 8] + // 0 ~ 15: PA0 ~ PA15 + //16 ~ 31: PB0 ~ PB15 + //32 ~ 47: PC0 ~ PC15 + //48 ~ 55: PD0 ~ PD7 + gpio_irflt_in(port); + gpio_set_direction(port, 1); + gpio_set_die(port, 1); +} + +void ir_output_timer_sel() +{ + IRFLT_OUTPUT_TIMER_SEL(IR_TIMER); + request_irq(IR_IRQ_TIME_IDX, 5, timer_ir_isr, 0); +} + +static void ir_timeout(void *priv) +{ + ir_code.boverflow++; + if (ir_code.boverflow > 56) { //56*2ms ~= 112ms + ir_code.bState = 0; + } +} + +void ir_timeout_set(void) +{ + sys_s_hi_timer_add(NULL, ir_timeout, 2); //2ms +} + +void irflt_config() +{ + JL_IR->RFLT_CON = 0; + /* JL_IR->RFLT_CON |= BIT(7); //256 div */ + /* JL_IR->RFLT_CON |= BIT(3); //osc 24m */ + JL_IR->RFLT_CON |= BIT(7) | BIT(4); //512 div + JL_IR->RFLT_CON |= BIT(3) | BIT(2); //PLL_48m(兼容省晶振) + JL_IR->RFLT_CON |= BIT(0); //irflt enable + + set_ir_clk(); +} + +void log_irflt_info() +{ + ir_log("IOMC0 = 0x%x", JL_IOMAP->CON0); + ir_log("IOMC2 = 0x%x", JL_IOMAP->CON2); + ir_log("RFLT_CON = 0x%x", JL_IR->RFLT_CON); + ir_log("IR_TIME_REG = 0x%x", IR_TIME_REG->CON); +} + diff --git a/cpu/br23/led_spi.c b/cpu/br23/led_spi.c new file mode 100644 index 0000000..9e66d81 --- /dev/null +++ b/cpu/br23/led_spi.c @@ -0,0 +1,166 @@ +#include "system/includes.h" + + + +static const u8 SPI1_DO[2] = { + IO_PORTB_01,//'A' + IO_PORTC_05 //'B' +}; +static const u8 SPI2_DO[2] = { + IO_PORTB_10,//'A' + IO_PORT_DM //'B' +}; +#define LED_SPI JL_SPI1 +#define LED_SPI_PORT 'B' +#define LED_SPI_DAT_BAUD 8000000 +#define LED_SPI_REST_BAUD 1000000 +#define LED_SPI_CLOCK_BASE clk_get("lsb") + +static OS_SEM led_spi_sem; +static u32 spi_do = 0; +static u8 led_spi_busy = 0; +static u8 led_spi_sus = 0; + +___interrupt +void led_spi_isr() +{ + LED_SPI->CON &= ~BIT(13); //关闭中断 + LED_SPI->CON |= BIT(14); //清pnding + os_sem_post(&led_spi_sem); + led_spi_busy = 0; +} + +void led_spi_init(void) +{ + if ((u32)LED_SPI == (u32)JL_SPI1) { + spi_do = SPI1_DO[LED_SPI_PORT - 'A']; + SFR(JL_IOMAP->CON1, 4, 1, LED_SPI_PORT - 'A'); + request_irq(IRQ_SPI1_IDX, 0, led_spi_isr, 0); + } else { + spi_do = SPI2_DO[LED_SPI_PORT - 'A']; + SFR(JL_IOMAP->CON1, 16, 1, LED_SPI_PORT - 'A'); + request_irq(IRQ_SPI2_IDX, 0, led_spi_isr, 0); + } + gpio_set_die(spi_do, 1); + gpio_set_direction(spi_do, 0); + gpio_set_pull_up(spi_do, 0); + gpio_set_pull_down(spi_do, 0); + gpio_write(spi_do, 0); + + os_sem_create(&led_spi_sem, 1); + + LED_SPI->CON = 0x4021; +} + +void led_spi_rgb_to_24byte(u8 r, u8 g, u8 b, u8 *buf, int idx) +{ + buf = buf + idx * 24; + u32 dat = ((g << 16) | (r << 8) | b); + for (u8 i = 0; i < 24; i ++) { + if (dat & BIT(23 - i)) { + *(buf + i) = 0x7c; + } else { + *(buf + i) = 0x60; + } + } +} + +void led_spi_rest() +{ + u8 tmp_buf[16] = {0}; + LED_SPI->BAUD = LED_SPI_CLOCK_BASE / LED_SPI_REST_BAUD - 1; + LED_SPI->CON |= BIT(14); + LED_SPI->ADR = (u32)tmp_buf; + LED_SPI->CNT = 16; + while (!(LED_SPI->CON & BIT(15))); + LED_SPI->CON |= BIT(14); +} + +void led_spi_send_rgbbuf(u8 *rgb_buf, u16 led_num) //rgb_buf的大小 至少要等于 led_num * 24 +{ + if (!led_num) { + return; + } + while (led_spi_sus) { + os_time_dly(1); + } + led_spi_busy = 1; + led_spi_rest(); + LED_SPI->BAUD = LED_SPI_CLOCK_BASE / LED_SPI_DAT_BAUD - 1; + LED_SPI->CON |= BIT(14); + LED_SPI->ADR = (u32)rgb_buf; + LED_SPI->CNT = led_num * 24; + while (!(LED_SPI->CON & BIT(15))); + LED_SPI->CON |= BIT(14); + led_spi_busy = 0; +} + +void led_spi_send_rgbbuf_isr(u8 *rgb_buf, u16 led_num) //rgb_buf的大小 至少要等于 led_num * 24 +{ + if (!led_num) { + return; + } + while (led_spi_sus) { + os_time_dly(1); + } + led_spi_busy = 1; + os_sem_pend(&led_spi_sem, 0); + led_spi_rest(); + LED_SPI->BAUD = LED_SPI_CLOCK_BASE / LED_SPI_DAT_BAUD - 1; + LED_SPI->CON |= BIT(14); + LED_SPI->ADR = (u32)rgb_buf; + LED_SPI->CNT = led_num * 24; + LED_SPI->CON |= BIT(13);//打开中断 +} + +u8 led_spi_suspend(void) +{ + if (led_spi_sus) { + return 1; + } + if (led_spi_busy) { + return 1; + } + LED_SPI->CON |= BIT(14); + LED_SPI->CON &= ~BIT(0); + led_spi_sus = 1; + return 0; +} + +u8 led_spi_resume(void) +{ + if (!led_spi_sus) { + return 0; + } + gpio_set_die(spi_do, 1); + gpio_set_direction(spi_do, 0); + gpio_set_pull_up(spi_do, 0); + gpio_set_pull_down(spi_do, 0); + gpio_write(spi_do, 0); + LED_SPI->CON = 0x4021; + led_spi_sus = 0; + return 0; +} + +static u8 spi_dat_buf[24 * 2] __attribute__((aligned(4))); +extern void wdt_clear(); +void led_spi_test(void) +{ + printf("****************** led spi test *******************\n"); + led_spi_init(); + u8 cnt = 0; + u8 pulse = 0; + while (1) { + cnt ++; + led_spi_rgb_to_24byte(cnt, 255 - cnt, 0, spi_dat_buf, 0); + led_spi_rgb_to_24byte(0, 0, cnt, spi_dat_buf, 1); +#if 1 + led_spi_send_rgbbuf(spi_dat_buf, 2); //等待的方式,建议用在发的数据量小的场合 +#else + led_spi_send_rgbbuf_isr(spi_dat_buf, 2); //中断的方式,建议用在发的数据量大的场合 +#endif + os_time_dly(2); + wdt_clear(); + } +} + diff --git a/cpu/br23/ledc_test.c b/cpu/br23/ledc_test.c new file mode 100644 index 0000000..6693cf8 --- /dev/null +++ b/cpu/br23/ledc_test.c @@ -0,0 +1,443 @@ + +#if 0 + +#include "system/includes.h" +#include "audio_spectrum.h" + + +#define LED_NUM_MAX (18 * 6) +static u8 led_rgb_val_buf[24 * LED_NUM_MAX] __attribute__((aligned(4))); + +void led_spi_init(void); +void led_spi_send_rgbbuf_isr(u8 *rgb_buf, u16 led_num); +void led_spi_rgb_to_24byte(u8 r, u8 g, u8 b, u8 *buf, int idx); + +/*********************************************************************************************** + * 接口替换区 +***********************************************************************************************/ +#define led_init() led_spi_init() +#define led_rgb_to_buf(r,g,b,buf,idx) led_spi_rgb_to_24byte(r,g,b,buf,idx) +#define led_send_rgbbuf(buf,num) led_spi_send_rgbbuf_isr(buf,num) + + +/*********************************************************************************************** + ******** ** +r: * * * + * * * + ******* ******** + ** ******** +g: * * * + * * * + ******* ******** + ****** ******** +b: * * * + * * * + ******* **** + * 流水灯控制驱动原理: + *1. 每个模式都会一个周期 *********** + *2. 以一个灯为例,一个模式周期内,又分三个颜色,即每个颜色各有各的周期。 * * + *3. 最核心的思维是:一个灯的三个颜色的地位是相等的,灯与灯之间,每个灯的地位是相等。 * * + *4. 每个颜色在一个周期里分为几个阶段:最暗到最亮,最亮维持,最亮到最暗,最暗维持 ******** ******* + *5. 颜色之间可以存在相位差, + *6. 灯与灯之间的计数值可以存在相位差 +***********************************************************************************************/ + +struct led_rgb_t { + u8 mode_idx; //灯亮的模式号 + u8 div_sec_num; //一条灯带分几段 + u8 sec_led_num; //每段灯带几个灯 + u8 cnt_freq; //CNT多久加一次,单位10ms,这个值越大,灯变化越慢 + u8 rgb_val_max[3]; //可配置某颜色值的最大值,一般是255 + u8 rgb_val_min[3]; //可配置某颜色值的最大值,一般是0 + int cnt[3]; //单个灯,颜色的变化计数值,cnt的初值,就是三个颜色的相位差。 + int next_cnt_dir[3]; //同个颜色灯与灯之间的传递方向和传递间隔, 下一个灯的cnt是上一个灯的cnt+next_cnt_dir + int next_sec_cnt_phase[3]; //同个颜色段与段之间的相位差,即下一段灯带的颜色cnt初始值是上一段灯带的cnt+next_sec_cnt_phase + int cnt_unit[3]; //CNT加一次加多少,这个值越大,灯变化越快,CNT加到最大周期值后,又从0开始加 + int cnt_max_prd[3]; //一个颜色的整个模式的周期, 不管CNT怎么加,都映射在这个周期里,即cnt %= cnt_max_prd + int pu_cnt_start[3]; //一个周期内,颜色值上升开始的时间,即这个颜色开始亮了 + int pu_cnt_end[3]; //一个周期内,颜色值上升结束的时间,即颜色值达到最大值 + int keep_cnt_start[3]; //一个周期内,颜色值维持最大的开始时间,一般为颜色值上升结束的时间 + int keep_cnt_end[3]; //一个周期内,颜色值维持最大的结束时间 + int pd_cnt_start[3]; //一个周期内,颜色值下降开始的时间,一般为颜色值维持最大的结束时间 + int pd_cnt_end[3]; //一个周期内,颜色值下降结束的时间,即颜色值没有为0了 +}; + +static struct led_rgb_t mode0_led_rgb = { + .mode_idx = 0, + .div_sec_num = 6, + .sec_led_num = 18, + .cnt_freq = 1, +//r: + .rgb_val_max[ 0] = 255, .rgb_val_min[ 0] = 0, + .cnt[ 0] = 0, .next_cnt_dir[ 0] = -10, + .cnt_unit[ 0] = 1, .cnt_max_prd[ 0] = 90, + .pu_cnt_start[ 0] = 0, .pu_cnt_end[ 0] = 30, + .keep_cnt_start[0] = 30, .keep_cnt_end[ 0] = 30, + .pd_cnt_start[ 0] = 30, .pd_cnt_end[ 0] = 60, +//g: + .rgb_val_max[ 1] = 255, .rgb_val_min[ 1] = 0, + .cnt[ 1] = 30, .next_cnt_dir[ 1] = -10, + .cnt_unit[ 1] = 1, .cnt_max_prd[ 1] = 90, + .pu_cnt_start[ 1] = 0, .pu_cnt_end[ 1] = 30, + .keep_cnt_start[1] = 30, .keep_cnt_end[ 1] = 30, + .pd_cnt_start[ 1] = 30, .pd_cnt_end[ 1] = 60, +//b: + .rgb_val_max[ 2] = 255, .rgb_val_min[ 2] = 0, + .cnt[ 2] = 60, .next_cnt_dir[ 2] = -10, + .cnt_unit[ 2] = 1, .cnt_max_prd[ 2] = 90, + .pu_cnt_start[ 2] = 0, .pu_cnt_end[ 2] = 30, + .keep_cnt_start[2] = 30, .keep_cnt_end[ 2] = 30, + .pd_cnt_start[ 2] = 30, .pd_cnt_end[ 2] = 60, +}; +static struct led_rgb_t mode1_led_rgb = { + .mode_idx = 1, + .div_sec_num = 6, + .sec_led_num = 18, + .cnt_freq = 1, +//r: + .rgb_val_max[ 0] = 255, .rgb_val_min[ 0] = 0, + .cnt[ 0] = 0, .next_cnt_dir[ 0] = 6, + .cnt_unit[ 0] = 1, .cnt_max_prd[ 0] = 108, + .pu_cnt_start[ 0] = 0, .pu_cnt_end[ 0] = 0, + .keep_cnt_start[0] = 0, .keep_cnt_end[ 0] = 54, + .pd_cnt_start[ 0] = 54, .pd_cnt_end[ 0] = 54, +//g: + .rgb_val_max[ 1] = 255, .rgb_val_min[ 1] = 0, + .cnt[ 1] = 36, .next_cnt_dir[ 1] = 6, + .cnt_unit[ 1] = 1, .cnt_max_prd[ 1] = 108, + .pu_cnt_start[ 1] = 0, .pu_cnt_end[ 1] = 0, + .keep_cnt_start[1] = 0, .keep_cnt_end[ 1] = 54, + .pd_cnt_start[ 1] = 54, .pd_cnt_end[ 1] = 54, +//b: + .rgb_val_max[ 2] = 255, .rgb_val_min[ 2] = 0, + .cnt[ 2] = 72, .next_cnt_dir[ 2] = 6, + .cnt_unit[ 2] = 1, .cnt_max_prd[ 2] = 108, + .pu_cnt_start[ 2] = 0, .pu_cnt_end[ 2] = 0, + .keep_cnt_start[2] = 0, .keep_cnt_end[ 2] = 54, + .pd_cnt_start[ 2] = 54, .pd_cnt_end[ 2] = 54, +}; +static struct led_rgb_t mode2_led_rgb = { + .mode_idx = 2, + .div_sec_num = 6, + .sec_led_num = 18, + .cnt_freq = 1, +//r: + .rgb_val_max[ 0] = 255, .rgb_val_min[ 0] = 0, + .cnt[ 0] = 0, .next_cnt_dir[ 0] = -5, + .cnt_unit[ 0] = 1, .cnt_max_prd[ 0] = 90, + .pu_cnt_start[ 0] = 0, .pu_cnt_end[ 0] = 0, + .keep_cnt_start[0] = 0, .keep_cnt_end[ 0] = 30, + .pd_cnt_start[ 0] = 30, .pd_cnt_end[ 0] = 30, +//g: + .rgb_val_max[ 1] = 255, .rgb_val_min[ 1] = 0, + .cnt[ 1] = 30, .next_cnt_dir[ 1] = -5, + .cnt_unit[ 1] = 1, .cnt_max_prd[ 1] = 90, + .pu_cnt_start[ 1] = 0, .pu_cnt_end[ 1] = 0, + .keep_cnt_start[1] = 0, .keep_cnt_end[ 1] = 30, + .pd_cnt_start[ 1] = 30, .pd_cnt_end[ 1] = 30, +//b: + .rgb_val_max[ 2] = 255, .rgb_val_min[ 2] = 0, + .cnt[ 2] = 60, .next_cnt_dir[ 2] = -5, + .cnt_unit[ 2] = 1, .cnt_max_prd[ 2] = 90, + .pu_cnt_start[ 2] = 0, .pu_cnt_end[ 2] = 0, + .keep_cnt_start[2] = 0, .keep_cnt_end[ 2] = 30, + .pd_cnt_start[ 2] = 30, .pd_cnt_end[ 2] = 30, +}; +static struct led_rgb_t mode3_led_rgb = { + .mode_idx = 3, + .div_sec_num = 6, + .sec_led_num = 18, + .cnt_freq = 1, +//r: + .rgb_val_max[ 0] = 255, .rgb_val_min[ 0] = 0, + .cnt[ 0] = 0, .next_cnt_dir[ 0] = 2, + .cnt_unit[ 0] = 1, .cnt_max_prd[ 0] = 108, + .pu_cnt_start[ 0] = 0, .pu_cnt_end[ 0] = 0, + .keep_cnt_start[0] = 0, .keep_cnt_end[ 0] = 36, + .pd_cnt_start[ 0] = 36, .pd_cnt_end[ 0] = 36, +//g: + .rgb_val_max[ 1] = 255, .rgb_val_min[ 1] = 0, + .cnt[ 1] = 36, .next_cnt_dir[ 1] = 2, + .cnt_unit[ 1] = 1, .cnt_max_prd[ 1] = 108, + .pu_cnt_start[ 1] = 0, .pu_cnt_end[ 1] = 0, + .keep_cnt_start[1] = 0, .keep_cnt_end[ 1] = 36, + .pd_cnt_start[ 1] = 36, .pd_cnt_end[ 1] = 36, +//b: + .rgb_val_max[ 2] = 255, .rgb_val_min[ 2] = 0, + .cnt[ 2] = 72, .next_cnt_dir[ 2] = 2, + .cnt_unit[ 2] = 1, .cnt_max_prd[ 2] = 108, + .pu_cnt_start[ 2] = 0, .pu_cnt_end[ 2] = 0, + .keep_cnt_start[2] = 0, .keep_cnt_end[ 2] = 36, + .pd_cnt_start[ 2] = 36, .pd_cnt_end[ 2] = 36, +}; +static struct led_rgb_t mode4_led_rgb = { + .mode_idx = 4, + .div_sec_num = 6, + .sec_led_num = 18, + .cnt_freq = 1, +//r: + .rgb_val_max[ 0] = 255, .rgb_val_min[ 0] = 0, + .cnt[ 0] = 0, .next_cnt_dir[ 0] = -12, + .cnt_unit[ 0] = 1, .cnt_max_prd[ 0] = 108, + .pu_cnt_start[ 0] = 0, .pu_cnt_end[ 0] = 12, + .keep_cnt_start[0] = 12, .keep_cnt_end[ 0] = 24, + .pd_cnt_start[ 0] = 24, .pd_cnt_end[ 0] = 36, +//g: + .rgb_val_max[ 1] = 255, .rgb_val_min[ 1] = 0, + .cnt[ 1] = 36, .next_cnt_dir[ 1] = -12, + .cnt_unit[ 1] = 1, .cnt_max_prd[ 1] = 108, + .pu_cnt_start[ 1] = 0, .pu_cnt_end[ 1] = 12, + .keep_cnt_start[1] = 12, .keep_cnt_end[ 1] = 24, + .pd_cnt_start[ 1] = 24, .pd_cnt_end[ 1] = 36, +//b: + .rgb_val_max[ 2] = 255, .rgb_val_min[ 2] = 0, + .cnt[ 2] = 72, .next_cnt_dir[ 2] = -12, + .cnt_unit[ 2] = 1, .cnt_max_prd[ 2] = 108, + .pu_cnt_start[ 2] = 0, .pu_cnt_end[ 2] = 12, + .keep_cnt_start[2] = 12, .keep_cnt_end[ 2] = 24, + .pd_cnt_start[ 2] = 24, .pd_cnt_end[ 2] = 36, +}; +static struct led_rgb_t mode5_led_rgb = { + .mode_idx = 5, + .div_sec_num = 6, + .sec_led_num = 18, + .cnt_freq = 1, +//r: + .rgb_val_max[ 0] = 255, .rgb_val_min[ 0] = 0, + .cnt[ 0] = 0, .next_cnt_dir[ 0] = 2, + .cnt_unit[ 0] = 1, .cnt_max_prd[ 0] = 108, + .pu_cnt_start[ 0] = 0, .pu_cnt_end[ 0] = 0, + .keep_cnt_start[0] = 0, .keep_cnt_end[ 0] = 2, + .pd_cnt_start[ 0] = 2, .pd_cnt_end[ 0] = 2, +//g: + .rgb_val_max[ 1] = 255, .rgb_val_min[ 1] = 0, + .cnt[ 1] = 36, .next_cnt_dir[ 1] = 2, + .cnt_unit[ 1] = 1, .cnt_max_prd[ 1] = 108, + .pu_cnt_start[ 1] = 0, .pu_cnt_end[ 1] = 0, + .keep_cnt_start[1] = 0, .keep_cnt_end[ 1] = 2, + .pd_cnt_start[ 1] = 2, .pd_cnt_end[ 1] = 2, +//b: + .rgb_val_max[ 2] = 255, .rgb_val_min[ 2] = 0, + .cnt[ 2] = 72, .next_cnt_dir[ 2] = 2, + .cnt_unit[ 2] = 1, .cnt_max_prd[ 2] = 108, + .pu_cnt_start[ 2] = 0, .pu_cnt_end[ 2] = 0, + .keep_cnt_start[2] = 0, .keep_cnt_end[ 2] = 2, + .pd_cnt_start[ 2] = 2, .pd_cnt_end[ 2] = 2, +}; +static struct led_rgb_t mode6_led_rgb = { + .mode_idx = 6, + .div_sec_num = 4, + .sec_led_num = 6, + .cnt_freq = 1, +//r: + .rgb_val_max[ 0] = 255, .rgb_val_min[ 0] = 200, + .cnt[ 0] = 0, .next_cnt_dir[ 0] = -18, + .cnt_unit[ 0] = 1, .cnt_max_prd[ 0] = 48, + .pu_cnt_start[ 0] = 0, .pu_cnt_end[ 0] = 0, + .keep_cnt_start[0] = 0, .keep_cnt_end[ 0] = 24, + .pd_cnt_start[ 0] = 24, .pd_cnt_end[ 0] = 24, + .next_sec_cnt_phase[0] = 18, +//g: + .rgb_val_max[ 1] = 128, .rgb_val_min[ 1] = 32, + .cnt[ 1] = 0, .next_cnt_dir[ 1] = 18, + .cnt_unit[ 1] = 0, .cnt_max_prd[ 1] = 108, + .pu_cnt_start[ 1] = 0, .pu_cnt_end[ 1] = 0, + .keep_cnt_start[1] = 0, .keep_cnt_end[ 1] = 1, + .pd_cnt_start[ 1] = 1, .pd_cnt_end[ 1] = 108, +}; +static struct led_rgb_t mode7_led_rgb = { + .mode_idx = 7, + .div_sec_num = 6, + .sec_led_num = 18, + .cnt_freq = 1, +//r: + .rgb_val_max[ 0] = 255, .rgb_val_min[ 0] = 255, +}; +struct led_rgb_t *led_rgb_table[] = { + &mode0_led_rgb,//流水灯 + &mode1_led_rgb,//流水灯 + &mode2_led_rgb,//流水灯 + &mode3_led_rgb,//流水灯 + &mode4_led_rgb,//流水灯 + &mode5_led_rgb,//流水灯 + &mode6_led_rgb,//用于4X6火焰效果 + &mode7_led_rgb,//用于显示播歌的频点能量 +}; + +extern spectrum_fft_hdl *spec_hdl; +static short db_data_old[32]; +static short led_on_table[32]; +/* + * @brief 获取频谱能量,板级头文件要定义音频的宏#define AUDIO_SPECTRUM_CONFIG 1 //频响能量值获取接口 + * @param p 音频接口的结构体参数 + */ +void led_get_spectrum(void *p) +{ + spectrum_fft_hdl *hdl = p; + if (hdl) { + u8 db_num = audio_spectrum_fft_get_num(hdl);//获取频谱个数 + short *db_data = audio_spectrum_fft_get_val(hdl);//获取存储频谱值得地址 + if (!db_data) { + return; + } + for (int i = 0; i < db_num; i++) { + if (i < 32) { + led_on_table[i] = db_data[i] - db_data_old[i]; + db_data_old[i] = db_data[i]; + } + } + } +} + +/* + * @brief 一段灯带亮灯的数量 + * @param led_rgb 该模式结构体参数 + * @param sec_num 第几段灯带 + * @return 可以亮灯的数量 + */ +int get_led_sec_on_num(struct led_rgb_t *led_rgb, int sec_num) +{ + int on_num = led_rgb->sec_led_num; + switch (led_rgb->mode_idx) { + case 0: + break; + case 1: + break; + case 2: + break; + case 3: + break; + case 4: + break; + case 5: + break; + case 6: + break; + case 7: + if (spec_hdl) { + short sum0 = 0; + short sum1 = 0; + int tmp = 32 / led_rgb->div_sec_num; + for (short i = 0; i < tmp; i ++) { + sum0 += led_on_table[i + sec_num * tmp]; + sum1 += db_data_old[i + sec_num * tmp]; + } + sum0 /= 5; + sum1 /= 5; + short num = ((sum1 * led_rgb->sec_led_num / 90) + sum0); + if (num < 0) { + num = 0; + } + on_num = num % led_rgb->sec_led_num; + } + break; + } + return on_num; +} + +/* + * @brief 约束CNT值在周期值内 + * @param led_rgb 该模式结构体参数 + * @param colour 颜色号:0,红色 1,绿色 2,蓝色 + * @param cnt 颜色对应的计数值 + * @return 映射后的值 + */ +int get_map_cnt(struct led_rgb_t *led_rgb, int colour, int cnt) +{ + if (led_rgb->cnt_max_prd[colour] == 0) { + return 0; + } + while (cnt < 0) { + cnt += led_rgb->cnt_max_prd[colour]; + } + cnt %= led_rgb->cnt_max_prd[colour]; + return cnt; +} + +/* + * @brief 将CNT值转换为RGB值 + * @param led_rgb 该模式结构体参数 + * @param colour 颜色号:0,红色 1,绿色 2,蓝色 + * @param cnt 颜色对应的计数值 + * @return 对应的颜色亮度值 + */ +u8 led_cnt_to_rgb_val(struct led_rgb_t *led_rgb, int colour, int cnt) +{ + u8 rgb_val = led_rgb->rgb_val_min[colour]; + int tmp_cnt = 0; + int i = colour; + int rgb_val_delta = led_rgb->rgb_val_max[i] - led_rgb->rgb_val_min[i]; + if ((led_rgb->pu_cnt_start[i] <= cnt) && (cnt < led_rgb->pu_cnt_end[i])) { //递增区间 + tmp_cnt = cnt - led_rgb->pu_cnt_start[i] + 1; + rgb_val = led_rgb->rgb_val_min[i] + (tmp_cnt * rgb_val_delta / (led_rgb->pu_cnt_end[i] - led_rgb->pu_cnt_start[i])); + } else if ((led_rgb->keep_cnt_start[i] <= cnt) && (cnt < led_rgb->keep_cnt_end[i])) { //高维持区间 + rgb_val = led_rgb->rgb_val_max[i]; + } else if ((led_rgb->pd_cnt_start[i] <= cnt) && (cnt < led_rgb->pd_cnt_end[i])) { //递减区间 + tmp_cnt = led_rgb->pd_cnt_end[i] - cnt - 1; + rgb_val = led_rgb->rgb_val_min[i] + (tmp_cnt * rgb_val_delta / (led_rgb->pd_cnt_end[i] - led_rgb->pd_cnt_start[i])); + } + return rgb_val; +} + +/* + * @brief 更新RGB的DMA buf数据,并发送出去,更新灯带 + * @param led_rgb 该模式结构体参数 + * @param cnt 基础节拍计数值 + */ +void led_rgb_upgrade(struct led_rgb_t *led_rgb, int cnt) +{ + u8 r_val = 0; + u8 g_val = 0; + u8 b_val = 0; + if ((cnt % led_rgb->cnt_freq) == 0) { + led_rgb->cnt[0] = get_map_cnt(led_rgb, 0, led_rgb->cnt[0] + led_rgb->cnt_unit[0]); + led_rgb->cnt[1] = get_map_cnt(led_rgb, 1, led_rgb->cnt[1] + led_rgb->cnt_unit[1]); + led_rgb->cnt[2] = get_map_cnt(led_rgb, 2, led_rgb->cnt[2] + led_rgb->cnt_unit[2]); + for (int i = 0; i < led_rgb->div_sec_num; i ++) { + int led_on_num = get_led_sec_on_num(led_rgb, i); + for (int j = 0; j < led_rgb->sec_led_num; j ++) { + r_val = led_cnt_to_rgb_val(led_rgb, 0, get_map_cnt(led_rgb, 0, led_rgb->cnt[0] + (i * led_rgb->next_sec_cnt_phase[0] + j) * led_rgb->next_cnt_dir[0])); + g_val = led_cnt_to_rgb_val(led_rgb, 1, get_map_cnt(led_rgb, 1, led_rgb->cnt[1] + (i * led_rgb->next_sec_cnt_phase[1] + j) * led_rgb->next_cnt_dir[1])); + b_val = led_cnt_to_rgb_val(led_rgb, 2, get_map_cnt(led_rgb, 2, led_rgb->cnt[2] + (i * led_rgb->next_sec_cnt_phase[2] + j) * led_rgb->next_cnt_dir[2])); + if (j >= led_on_num) { + r_val = 0; + g_val = 0; + b_val = 0; + } + led_rgb_to_buf(r_val, g_val, b_val, led_rgb_val_buf, i * led_rgb->sec_led_num + j); + } + } + led_send_rgbbuf(led_rgb_val_buf, led_rgb->div_sec_num * led_rgb->sec_led_num); + } +} + +/* + * @brief 定时轮询各模式 + */ +void led_rgb_scan(void *priv) +{ + static u32 step_cnt = 0; + static u32 mode_idx = 0; + static struct led_rgb_t *led_rgb = NULL; + if ((step_cnt % 800) == 0) { //8s + step_cnt = 0; + led_rgb = led_rgb_table[mode_idx]; + mode_idx ++; + if (mode_idx >= (sizeof(led_rgb_table) / 4)) { + mode_idx = 0; + } + } + led_rgb_upgrade(led_rgb, step_cnt); + step_cnt ++; +} + +void my_led_test(void) +{ + printf("****************** led test *******************\n"); + led_init(); + sys_timer_add(NULL, led_rgb_scan, 10); + sys_timer_add(spec_hdl, led_get_spectrum, 100);//定期获取能量值 +} + +#endif + diff --git a/cpu/br23/localtws/localtws.c b/cpu/br23/localtws/localtws.c new file mode 100644 index 0000000..889eeb2 --- /dev/null +++ b/cpu/br23/localtws/localtws.c @@ -0,0 +1,680 @@ +/***********************************Jieli tech************************************************ + File : localtws.c + By : Huxi + brief: + Email: huxi@zh-jieli.com + date : 2020-07 +********************************************************************************************/ + +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "classic/tws_api.h" +#include "classic/tws_local_media_sync.h" +#include "localtws/localtws.h" +#include "clock_cfg.h" +#include "app_config.h" +#include "audio_config.h" +#include "audio_dec.h" +#include "audio_enc.h" +#include "app_task.h" +#include "bt/bt_tws.h" +#include "bt/bt.h" + +#if TCFG_DEC2TWS_ENABLE + +#define LOCALTWS_LOG_ENABLE +#ifdef LOCALTWS_LOG_ENABLE +#define LOCALTWS_LOG log_i //y_printf +#define LOCALTWS_LOG_CHAR putchar +#else +#define LOCALTWS_LOG(...) +#define LOCALTWS_LOG_CHAR(...) +#endif + + +////////////////////////////////////////////////////////////////////////////// + +#define LOCALTWS_MEDIA_ALLOC_EN 1 // 使用空间申请方式 +#define LOCALTWS_CHANGE_USE_BT_CMD 1 // 使用蓝牙命令发送localtws变化信息 + +const u16 LOCALTWS_MEDIA_BUF_LEN = (12 * 1024); // localtws传输空间 +const u16 LOCALTWS_MEDIA_BUF_LIMIT_LEN = (LOCALTWS_MEDIA_BUF_LEN * 7 / 10); // 起始数据累计达到该值才发送 +const u16 LOCALTWS_MEDIA_TO_MS = 6000; // tws多长时间没收到数据认为是超时 + +#ifdef CONFIG_MIXER_CYCLIC +#if MIXER_AUDIO_DIRECT_OUT +const u16 LOCALTWS_MIXER_BUF_LEN = (8); // mixer空间大小,有直通 +#else /*MIXER_AUDIO_DIRECT_OUT*/ +const u16 LOCALTWS_MIXER_BUF_LEN = (256 * 2 * 2); // mixer空间大小,没有直通 +#endif /*MIXER_AUDIO_DIRECT_OUT*/ +#else /*CONFIG_MIXER_CYCLIC*/ +const u16 LOCALTWS_MIXER_BUF_LEN = 8; // mixer空间大小,只有一个通道时直接输出,不经过该buf +#endif /*CONFIG_MIXER_CYCLIC*/ + +////////////////////////////////////////////////////////////////////////////// +// +#if (LOCALTWS_MEDIA_ALLOC_EN == 0) +static u8 localtws_media_buf[LOCALTWS_MEDIA_BUF_LEN] sec(.dec2tws_mem); +#endif + +struct localtws_globle_hdl g_localtws = {0}; +static u8 tws_background_connected_flag = 0; + +////////////////////////////////////////////////////////////////////////////// +// +extern struct audio_encoder_task *encode_task; +extern struct audio_decoder_task decode_task; + +extern void local_tws_sync_no_check_data_buf(u8 no_check); +extern void tws_api_local_media_trans_clear_no_ready(void); +extern u8 is_tws_active_device(void); + +extern int tone_get_status(); + +extern void localtws_decoder_resume_pre(void); + +/////////////////////////////////////////////////////////////////////////////////// + +void set_tws_background_connected_flag(u8 flag) +{ + tws_background_connected_flag = flag; +} + +u8 get_tws_background_connected_flag() +{ + return tws_background_connected_flag; +} + +/*----------------------------------------------------------------------------*/ +/**@brief tws数据处理 + @param *data: 数据 + @param len: 数据长度 + @param rx: 收数 + @return 0: 成功 + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +int tws_api_local_media_sync_rx_handler_notify(u8 *data, int len, u8 rx) +{ + /* LOCALTWS_LOG_CHAR('r'); */ + if (g_localtws.drop_frame_start) { + /* LOCALTWS_LOG("localtws_wait_drop_over\n"); */ + LOCALTWS_LOG_CHAR('O'); + LOCALTWS_LOG_CHAR('V'); + LOCALTWS_LOG_CHAR(' '); + } + return localtws_tws_rx_handler_notify(data, len, rx); +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws事件发送 + @param event_type: 事件 + @param value: 事件参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void localtws_dec_event(u8 event_type, u32 value) +{ + struct sys_event event; + event.type = SYS_BT_EVENT; + event.arg = (void *)SYS_BT_EVENT_FROM_TWS; + event.u.bt.event = event_type; + event.u.bt.value = value; + sys_event_notify(&event); +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws事件回调 + @param event: 事件 + @param *pram: 事件参数 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int localtws_globle_event_cb(int event, int *pram) +{ + switch (event) { +#if (!LOCALTWS_CHANGE_USE_BT_CMD) + case LOCALTWS_GLOBLE_EVENT_MEDIA_START: + localtws_dec_event(TWS_EVENT_LOCAL_MEDIA_START, pram[0]); + break; + case LOCALTWS_GLOBLE_EVENT_MEDIA_STOP: + localtws_dec_event(TWS_EVENT_LOCAL_MEDIA_STOP, 0); + break; +#endif + case LOCALTWS_GLOBLE_EVENT_MEDIA_TIMEOUT: + localtws_dec_event(TWS_EVENT_LOCAL_MEDIA_STOP, 0); + break; + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws检查活动设备 + @param + @return true: 活动设备 + @return false: 非活动设备 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int localtws_globle_check_active(void) +{ + if (app_check_curr_task(APP_BT_TASK)) { + // 蓝牙模式一定是unactive设备 + return false; + } + if (is_tws_active_device()) { + return true; + } + return false; +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws中断传输判断 + @param + @return true: 中断传输 + @return false: 继续传输 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int localtws_globle_check_frame_drop(void) +{ + if (tone_get_status() || bt_media_is_running()) { + return true; + } + return false; +} + +////////////////////////////////////////////////////////////////////////////// +// +/*----------------------------------------------------------------------------*/ +/**@brief localtws全局初始化 + @param + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int localtws_globle_init(void) +{ + os_mutex_create(&g_localtws.mutex); +#if LOCALTWS_MEDIA_ALLOC_EN + g_localtws.media_buf_malloc = 1; +#else + g_localtws.media_buf = localtws_media_buf; +#endif + localtws_globle_set_event_cb(localtws_globle_event_cb); + localtws_globle_set_check_active(localtws_globle_check_active); + localtws_globle_set_resume(localtws_dec_resume); + localtws_globle_set_data_abandon(localtws_media_dat_abandon); + localtws_globle_set_frame_drop(localtws_globle_check_frame_drop); + localtws_media_enable(); + return 0; +} +__initcall(localtws_globle_init); + + +/*----------------------------------------------------------------------------*/ +/**@brief localtws检测是否使能 + @param + @return true: 使能 + @return false: 不使能 + @note +*/ +/*----------------------------------------------------------------------------*/ +int localtws_check_enable(void) +{ + int state = tws_api_get_tws_state(); + if ((state & TWS_STA_SIBLING_CONNECTED)) { + return true; + } + return false; +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws蓝牙事件处理 + @param *evt: 蓝牙事件 + @return 0: 成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +#define __this (&app_bt_hdl) +int localtws_bt_event_deal(struct bt_event *evt) +{ + /* int state = tws_api_get_tws_state(); */ + /* LOCALTWS_LOG(">>>>>>>>>>>>>>>>> %s, state:0x%x ", __func__, state); */ + + switch (evt->event) { + case TWS_EVENT_CONNECTED: + __this->cmd_flag = 2; + tws_background_connected_flag = 1; + app_task_switch_to(APP_BT_TASK); + break; + case TWS_EVENT_CONNECTION_DETACH: + if (g_localtws.dec_restart) { + g_localtws.dec_restart(); + } + break; + } + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws mixer事件回调 + @param *mixer: 句柄 + @param event: 事件 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void localtws_mixer_event_handler(struct audio_mixer *mixer, int event) +{ + switch (event) { + case MIXER_EVENT_OPEN: + break; + case MIXER_EVENT_CLOSE: + break; + case MIXER_EVENT_SR_CHANGE: + break; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws mixer 检查采样率 + @param *mixer: 句柄 + @param sr: 采样率 + @return 支持的采样率 + @note +*/ +/*----------------------------------------------------------------------------*/ +static u32 localtws_mixer_check_sbc_sr(struct audio_mixer *mixer, u32 sr) +{ + return localtws_enc_sbc_sample_rate_select(sr, 1); +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws mixer 关闭 + @param *pfmt: 音频信息 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void localtws_mixer_close(struct audio_fmt *pfmt) +{ + if (g_localtws.mixer_buf) { + audio_mixer_close(&g_localtws.mixer); + free(g_localtws.mixer_buf); + g_localtws.mixer_buf = NULL; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief 打开localtws mixer + @param *enc: 编码句柄 + @param *pfmt: 音频信息 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void localtws_mixer_open(struct localtws_enc_hdl *enc, struct audio_fmt *pfmt) +{ + g_localtws.mixer_buf = malloc(LOCALTWS_MIXER_BUF_LEN); + ASSERT(g_localtws.mixer_buf); + + // 打开mixer + audio_mixer_open(&g_localtws.mixer); + audio_mixer_set_event_handler(&g_localtws.mixer, localtws_mixer_event_handler); + /* if (pfmt->coding_type & AUDIO_CODING_SBC) { */ + /* audio_mixer_set_check_sr_handler(&g_localtws.mixer, localtws_mixer_check_sbc_sr); */ + /* } */ + // 固定mixer采样率 + audio_mixer_set_sample_rate(&g_localtws.mixer, MIXER_SR_SPEC, pfmt->sample_rate); + + /*初始化mix_buf的长度*/ + audio_mixer_set_output_buf(&g_localtws.mixer, g_localtws.mixer_buf, LOCALTWS_MIXER_BUF_LEN); + /* audio_mixer_set_channel_num(&g_localtws.mixer, audio_output_channel_num()); */ + audio_mixer_set_channel_num(&g_localtws.mixer, pfmt->channel); +#ifdef CONFIG_MIXER_CYCLIC + audio_mixer_set_min_len(&g_localtws.mixer, LOCALTWS_MIXER_BUF_LEN / 2); +#endif + + struct audio_stream_entry *entries[8] = {NULL}; + // 数据流串联 + u8 entry_cnt = 0; + entries[entry_cnt++] = &g_localtws.mixer.entry; + entries[entry_cnt++] = &enc->entry; + g_localtws.mixer.stream = audio_stream_open(&g_localtws.mixer, audio_mixer_stream_resume); + audio_stream_add_list(g_localtws.mixer.stream, entries, entry_cnt); +} + +////////////////////////////////////////////////////////////////////////////// +// lib weak func + +/*----------------------------------------------------------------------------*/ +/**@brief localtws编码打开完成 + @param *enc: 编码句柄 + @param *pfmt: 音频信息 + @return 0-成功 + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +int localtws_enc_open_use(struct localtws_enc_hdl *enc, struct audio_fmt *pfmt) +{ + /* if (!encode_task) { */ + /* encode_task = zalloc(sizeof(*encode_task)); */ + /* ASSERT(encode_task); */ + /* audio_encoder_task_create(encode_task, "audio_enc"); */ + /* } */ + audio_encoder_task_open(); + enc->encode_task = encode_task; + if (pfmt->coding_type & AUDIO_CODING_SBC) { + clock_add(ENC_TWS_SBC_CLK); + } else { + clock_add(ENC_MP3_CLK); + } + + clock_set_cur(); + + localtws_mixer_open(enc, pfmt); + + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws编码关闭完成 + @param *enc: 编码句柄 + @return + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +void localtws_enc_close_use(struct localtws_enc_hdl *enc) +{ + struct audio_fmt *pfmt = &enc->encoder.fmt; + + audio_encoder_task_close(); + /* if (encode_task) { */ + /* audio_encoder_task_del(encode_task); */ + /* free(encode_task); */ + /* encode_task = NULL; */ + /* } */ + if (enc->encoder.enc_ops->coding_type & AUDIO_CODING_SBC) { + clock_remove(ENC_TWS_SBC_CLK); + } else { + clock_remove(ENC_MP3_CLK); + } + clock_set_cur(); + + localtws_mixer_close(pfmt); +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws转换打开完成 + @param *dec: 转换句柄 + @param *pfmt: 音频信息 + @return 0-成功 + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +int localtws_code_convert_open_use(struct localtws_code_convert_hdl *dec, struct audio_fmt *pfmt) +{ + dec->decode_task = &decode_task; + audio_stream_add_tail(g_localtws.mixer.stream, &dec->entry); + return 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws转换关闭完成 + @param *dec: 转换句柄 + @return + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +void localtws_code_convert_close_use(struct localtws_code_convert_hdl *dec) +{ +} + +////////////////////////////////////////////////////////////////////////////// +// enc api + +/*----------------------------------------------------------------------------*/ +/**@brief 打开localtws编码 + @param *pfmt: 音频信息 + @param flag: 源信息 + @return true: 成功 + @return false: 失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int localtws_enc_api_open(struct audio_fmt *pfmt, u32 flag) +{ + if (localtws_check_enable() == true) { + struct audio_fmt enc_fmt = {0}; + if (pfmt->coding_type != AUDIO_CODING_MP3) { + pfmt->coding_type = AUDIO_CODING_SBC; + } + if (pfmt->coding_type == AUDIO_CODING_SBC) { + pfmt->sample_rate = localtws_enc_sbc_sample_rate_select(pfmt->sample_rate, 1); + } + + enc_fmt.coding_type = pfmt->coding_type; + enc_fmt.bit_rate = 128; + enc_fmt.channel = pfmt->channel; + enc_fmt.sample_rate = pfmt->sample_rate; + + LOCALTWS_LOG("localtws sr:%d, chnum:%d, cod:0x%x \n", enc_fmt.sample_rate, enc_fmt.channel, enc_fmt.coding_type); + + int ret = localtws_enc_open(&enc_fmt); + if (ret == 0) { + if (enc_fmt.coding_type != AUDIO_CODING_SBC) { + ret = localtws_code_convert_open(&enc_fmt); + } + if (ret == 0) { + + localtws_push_open(); + audio_stream_add_tail(g_localtws.mixer.stream, &g_localtws.push.entry); + + if (flag & LOCALTWS_ENC_FLAG_STREAM) { + localtws_enc_set_stream_data_ctrl(localtws_dec_out_is_start, 500); + } else { + local_tws_sync_no_check_data_buf(1); + } + + localtws_start(&enc_fmt); + return true; + } else { + localtws_enc_close(); + } + } + } + return false; +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws编码写入 + @param *data: 数据 + @param len: 数据长度 + @return 实际写入长度 + @note +*/ +/*----------------------------------------------------------------------------*/ +int localtws_enc_api_write(s16 *data, int len) +{ + return localtws_enc_write(NULL, data, len); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭localtws编码 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void localtws_enc_api_close(void) +{ + localtws_enc_close(); + localtws_code_convert_close(); + localtws_push_close(); + localtws_stop(); +} + +////////////////////////////////////////////////////////////////////////////// +// api + +/*----------------------------------------------------------------------------*/ +/**@brief localtws设置等待a2dp状态 + @param flag: 状态 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void localtws_set_wait_a2dp_start(u8 flag) +{ + if (localtws_dec_is_open()) { + g_localtws.drop_frame_start = flag; + } +} + +#if LOCALTWS_CHANGE_USE_BT_CMD + +enum { + LOCALTWS_BT_CMD_MEDIA = 0, + LOCALTWS_BT_CMD_PAUSE, +}; + +struct localtws_bt_info { + int cmd; + int value; +}; + +#define TWS_FUNC_ID_LOCALTWS TWS_FUNC_ID('L', 'C', 'L', 'T') + +static void localtws_rx_data(void *data, u16 len, bool rx) +{ + struct localtws_bt_info info; + memcpy(&info, data, sizeof(struct localtws_bt_info)); + switch (info.cmd) { + case LOCALTWS_BT_CMD_MEDIA: + if (!rx) { + return; + } + y_printf("localtws_rx_data:0x%x \n", info.value); + g_localtws.media_value = info.value; + if (info.value) { + localtws_dec_event(TWS_EVENT_LOCAL_MEDIA_START, info.value); + } else { + localtws_dec_event(TWS_EVENT_LOCAL_MEDIA_STOP, 0); + } + break; + case LOCALTWS_BT_CMD_PAUSE: + y_printf("localtws_rx pause:%d \n", info.value); + if (info.value) { + g_localtws.tws_send_pause = LOCALTWS_MEDIA_DEC_PAUSE; + g_localtws.fade_ms = 30; + g_localtws.fade_out_mute_ms = 10; + } else { + g_localtws.tws_send_pause = LOCALTWS_MEDIA_DEC_PAUSE_RECOVER; + g_localtws.fade_ms = 30; + } + break; + } +} + +REGISTER_TWS_FUNC_STUB(localtws_rx) = { + .func_id = TWS_FUNC_ID_LOCALTWS, + .func = localtws_rx_data, +}; +#endif /*LOCALTWS_CHANGE_USE_BT_CMD*/ + + +/*----------------------------------------------------------------------------*/ +/**@brief localtws启动 + @param *pfmt: 音频信息 + @return + @note 活动设备主动调用 +*/ +/*----------------------------------------------------------------------------*/ +void localtws_start(struct audio_fmt *pfmt) +{ + clock_add_set(LOCALTWS_CLK); + + localtws_media_set_info((u8 *)&g_localtws.media_value, pfmt); + +#if LOCALTWS_CHANGE_USE_BT_CMD + struct localtws_bt_info info = {0}; + info.cmd = LOCALTWS_BT_CMD_MEDIA; + info.value = g_localtws.media_value; + tws_api_send_data_to_sibling((u8 *)&info, sizeof(struct localtws_bt_info), TWS_FUNC_ID_LOCALTWS); +#endif /*LOCALTWS_CHANGE_USE_BT_CMD*/ + + localtws_dec_open(g_localtws.media_value); +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws停止 + @param + @return + @note 活动设备主动调用 +*/ +/*----------------------------------------------------------------------------*/ +void localtws_stop(void) +{ + LOCALTWS_LOG("localtws_stop\n"); + g_localtws.tws_stop = 1; + // 清除还没有准备发射的 + tws_api_local_media_trans_clear_no_ready(); + +#if LOCALTWS_CHANGE_USE_BT_CMD + struct localtws_bt_info info = {0}; + info.cmd = LOCALTWS_BT_CMD_MEDIA; + info.value = 0; + tws_api_send_data_to_sibling((u8 *)&info, sizeof(struct localtws_bt_info), TWS_FUNC_ID_LOCALTWS); +#else /*LOCALTWS_CHANGE_USE_BT_CMD*/ + + // 发送一个结束包 + localtws_media_send_end(200); + int to_cnt = 0; + // 超时等待结束包被取走 + while (tws_api_local_media_trans_check_total(0)) { + localtws_decoder_resume_pre(); + os_time_dly(1); + to_cnt += 10; + if (to_cnt > 500) { + LOCALTWS_LOG("local tws send end timer out \n"); + break; + } + } +#endif /*LOCALTWS_CHANGE_USE_BT_CMD*/ + + localtws_dec_close(0); + g_localtws.tws_stop = 0; + + clock_remove_set(LOCALTWS_CLK); +} + +void localtws_decoder_pause(u8 pause) +{ +#if LOCALTWS_CHANGE_USE_BT_CMD + struct localtws_bt_info info = {0}; + info.cmd = LOCALTWS_BT_CMD_PAUSE; + info.value = pause; + tws_api_send_data_to_sibling((u8 *)&info, sizeof(struct localtws_bt_info), TWS_FUNC_ID_LOCALTWS); +#else /*LOCALTWS_CHANGE_USE_BT_CMD*/ + if (pause) { + // 发送一个暂停命令,避免从机收数超时进入stop + localtws_dec_pause(); + } +#endif /*LOCALTWS_CHANGE_USE_BT_CMD*/ +} +#else +void set_tws_background_connected_flag(u8 flag) +{ + +} + +u8 get_tws_background_connected_flag() +{ + return 0; +} +#endif /*(defined(TCFG_DEC2TWS_ENABLE) && (TCFG_DEC2TWS_ENABLE))*/ + diff --git a/cpu/br23/localtws/localtws.h b/cpu/br23/localtws/localtws.h new file mode 100644 index 0000000..8083a7a --- /dev/null +++ b/cpu/br23/localtws/localtws.h @@ -0,0 +1,51 @@ +#ifndef __LOCALTWS_H_ +#define __LOCALTWS_H_ + +#include "application/audio_localtws.h" +#include "media/localtws_decoder.h" + +#define LOCALTWS_ENC_FLAG_STREAM BIT(0) // 数据源是流数据 + + +// localtws检测是否使能 +int localtws_check_enable(void); + +// localtws蓝牙事件处理 +int localtws_bt_event_deal(struct bt_event *evt); + +// 打开localtws编码 +int localtws_enc_api_open(struct audio_fmt *pfmt, u32 flag); +// 关闭localtws编码 +void localtws_enc_api_close(void); +// localtws编码写入 +int localtws_enc_api_write(s16 *data, int len); + +// localtws设置等待a2dp状态 +void localtws_set_wait_a2dp_start(u8 flag); + +// localtws启动(活动设备主动调用) +void localtws_start(struct audio_fmt *pfmt); +// localtws停止(活动设备主动调用) +void localtws_stop(void); + +// 打开localtws解码 +int localtws_dec_open(u32 value); +// 关闭localtws解码 +int localtws_dec_close(u8 drop_frame_start); +// localtws已经打开 +u8 localtws_dec_is_open(void); +// localtws解码激活 +void localtws_dec_resume(void); +// localtws抛弃数据 +int localtws_media_dat_abandon(void); +// localtws暂停 +void localtws_dec_pause(void); +// localtws已经开始解码 +int localtws_dec_out_is_start(void); + +// localtws暂停控制 +void localtws_decoder_pause(u8 pause); + + +#endif /*__LOCALTWS_H_*/ + diff --git a/cpu/br23/localtws/localtws_dec.c b/cpu/br23/localtws/localtws_dec.c new file mode 100644 index 0000000..d375478 --- /dev/null +++ b/cpu/br23/localtws/localtws_dec.c @@ -0,0 +1,718 @@ +/***********************************Jieli tech************************************************ + File : localtws_dec.c + By : Huxi + brief: + Email: huxi@zh-jieli.com + date : 2020-07 +********************************************************************************************/ + +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" +#include "classic/tws_api.h" +#include "classic/tws_local_media_sync.h" +#include "localtws/localtws.h" +#include "clock_cfg.h" +#include "app_config.h" +#include "audio_config.h" +#include "audio_dec.h" +#include "media/audio_eq_drc_apply.h" +#include "media/audio_surround.h" +#include "media/audio_vbass.h" +#include "media/effects_adj.h" +#include "audio_effect/audio_eff_default_parm.h" +#include "audio_effect/audio_dynamic_eq_demo.h" + + +#if TCFG_DEC2TWS_ENABLE + +#define LOCALTWS_LOG_ENABLE +#ifdef LOCALTWS_LOG_ENABLE +#define LOCALTWS_LOG log_i //y_printf +#define LOCALTWS_LOG_CHAR putchar +#else +#define LOCALTWS_LOG(...) +#define LOCALTWS_LOG_CHAR(...) +#endif + + +////////////////////////////////////////////////////////////////////////////// +// + +struct localtws_dec_hdl { + struct audio_stream *stream; // 音频流 + struct localtws_decoder local_dec; // local解码句柄 + struct audio_res_wait wait; // 资源等待句柄 + struct audio_eq *eq; //eq drc句柄 + struct audio_drc *drc; // drc句柄 + struct convert_data *convert; + struct audio_eq *eq2; //eq drc句柄 + struct dynamic_eq_hdl *dy_eq; + struct convert_data *convert2; + struct aud_gain_process *gain; + + struct audio_mixer_ch mix_ch; // 叠加句柄 + u32 id; // 唯一标识符,随机值 + u32 media_value; // localtws媒体信息 + struct audio_wireless_sync *sync; +}; +static struct localtws_dec_hdl *localtws_dec = NULL; + +/* void *file_eq_drc_open(u16 sample_rate, u8 ch_num); */ +/* void file_eq_drc_close(struct audio_eq_drc *eq_drc); */ + +////////////////////////////////////////////////////////////////////////////// +// +extern struct audio_decoder_task decode_task; + +#if TCFG_DEC2TWS_TASK_ENABLE +extern struct audio_decoder_task localtws_decode_task; +#define LOCALTWS_TASK localtws_decode_task +#else /*TCFG_DEC2TWS_TASK_ENABLE*/ +#define LOCALTWS_TASK decode_task +#endif /*TCFG_DEC2TWS_TASK_ENABLE*/ + +extern void tws_api_local_media_trans_clear_no_ready(void); +extern int tws_api_local_media_trans_get_total_buffer_size(void); +extern void bt_drop_a2dp_frame_start(void); +extern int a2dp_media_clear_packet(); +extern struct audio_wireless_sync *audio_localtws_sync_open(int sample_rate, int output_sample_rate, u8 channels); +extern void audio_localtws_sync_close(struct audio_wireless_sync *localtws_sync); +extern u8 is_tws_active_device(void); + +extern void sys_auto_shut_down_disable(void); + +/////////////////////////////////////////////////////////////////////////////////// +struct local_dec_type { + u32 type; + u32 clk; +}; + +const struct local_dec_type local_dec_clk_tb[] = { + {AUDIO_CODING_SBC, DEC_TWS_SBC_CLK}, + {AUDIO_CODING_MP3, DEC_MP3_CLK}, + {AUDIO_CODING_WMA, DEC_WMA_CLK}, + {AUDIO_CODING_M4A, DEC_M4A_CLK}, +}; + +/*----------------------------------------------------------------------------*/ +/*----------------------------------------------------------------------------*/ +/**@brief localtws解码时钟添加 + @param type: 解码类型 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void local_dec_clock_add(u32 type) +{ + LOCALTWS_LOG("local_dec_clock_add : 0x%x \n", type); + int i = 0; + for (i = 0; i < ARRAY_SIZE(local_dec_clk_tb); i++) { + if (type == local_dec_clk_tb[i].type) { + clock_add(local_dec_clk_tb[i].clk); + return; + } + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws解码时钟移除 + @param type: 解码类型 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void local_dec_clock_remove(u32 type) +{ + LOCALTWS_LOG("local_dec_clock_remove : 0x%x \n", type); + int i = 0; + for (i = 0; i < ARRAY_SIZE(local_dec_clk_tb); i++) { + if (type == local_dec_clk_tb[i].type) { + clock_remove(local_dec_clk_tb[i].clk); + return; + } + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws激活前级解码/编码 + @param + @return + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +#if 0 +void localtws_decoder_resume_pre(void) +{ + audio_stream_resume(&g_localtws.push.entry); +#ifdef TCFG_PCM_ENC2TWS_ENABLE + localtws_enc_resume(); +#endif +} +#endif + +/*----------------------------------------------------------------------------*/ +/**@brief localtws解码输出重启 + @param ms: 重启静音时长 + @return + @note 弱函数重定义 +*/ +/*----------------------------------------------------------------------------*/ +void localtws_decoder_output_reset(u32 ms) +{ + app_audio_output_reset(ms); +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws解码激活 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void localtws_dec_resume(void) +{ + if (localtws_dec && localtws_dec->local_dec.status) { + audio_decoder_resume(&localtws_dec->local_dec.decoder); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws已经打开 + @param + @return true: 打开 + @return false: 没有打开 + @note +*/ +/*----------------------------------------------------------------------------*/ +u8 localtws_dec_is_open(void) +{ + if (localtws_dec) { + return true; + } + return false; +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws抛弃数据 + @param + @return true: 抛弃数据 + @return false: 不抛弃 + @note +*/ +/*----------------------------------------------------------------------------*/ +int localtws_media_dat_abandon(void) +{ + if ((localtws_dec) && (localtws_dec->local_dec.status) && (localtws_dec->local_dec.tmp_pause)) { + // 从机,暂停,抛弃中间数据包 + return true; + } + return false; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief localtws解码释放 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void localtws_dec_release() +{ + audio_decoder_task_del_wait(&LOCALTWS_TASK, &localtws_dec->wait); + + clock_remove(DEC_TWS_SBC_CLK); + + local_irq_disable(); + free(localtws_dec); + localtws_dec = NULL; + g_localtws.tws_send_pause = 0; + local_irq_enable(); +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws解码事件回调 + @param *decoder: 解码器句柄 + @param argc: 参数个数 + @param *argv: 参数 + @note +*/ +/*----------------------------------------------------------------------------*/ +static void localtws_dec_event_handler(struct audio_decoder *decoder, int argc, int *argv) +{ + switch (argv[0]) { + case AUDIO_DEC_EVENT_END: + LOCALTWS_LOG("AUDIO_DEC_EVENT_END\n"); + localtws_dec_close(1); + //audio_decoder_resume_all(&LOCALTWS_TASK); + break; + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws解码数据流激活 + @param *p: 私有句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +static void localtws_dec_out_stream_resume(void *p) +{ + struct localtws_dec_hdl *dec = p; + audio_decoder_resume(&dec->local_dec.decoder); +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws解码开始 + @param + @return 0:成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +static int localtws_dec_start() +{ + int err; + struct localtws_dec_hdl *dec = localtws_dec; + + if (!dec) { + return -EINVAL; + } + + struct audio_fmt fmt = {0}; + localtws_media_get_info((u8 *)&dec->media_value, &fmt); + dec->local_dec.dec_type = fmt.coding_type; + dec->local_dec.sample_rate = fmt.sample_rate; + dec->local_dec.ch_num = fmt.channel; + + LOCALTWS_LOG("localtws_dec_start: in, type:0x%x \n", dec->local_dec.dec_type); + LOCALTWS_LOG("sr:%d, ch:%d, outch:%d \n", dec->local_dec.sample_rate, dec->local_dec.ch_num, dec->local_dec.output_ch_num); + + // 打开file解码器 + err = localtws_decoder_open(&dec->local_dec, &LOCALTWS_TASK); + if (err) { + goto __err1; + } + + audio_decoder_set_event_handler(&dec->local_dec.decoder, localtws_dec_event_handler, dec->id); + + audio_mode_main_dec_open(AUDIO_MODE_MAIN_STATE_DEC_LOCALTWS); + + // 设置叠加功能 + audio_mixer_ch_open_head(&dec->mix_ch, &mixer); // 挂载到mixer最前面 + audio_mixer_ch_set_src(&dec->mix_ch, 1, 0); + audio_mixer_ch_set_no_wait(&dec->mix_ch, 1, 10); // 超时自动丢数 + audio_mixer_ch_sample_sync_enable(&dec->mix_ch, 1); + audio_mixer_ch_set_sample_rate(&dec->mix_ch, dec->local_dec.sample_rate); + + dec->sync = audio_localtws_sync_open(dec->local_dec.sample_rate, audio_mixer_get_sample_rate(&mixer), dec->local_dec.output_ch_num); + localtws_decoder_stream_sync_enable(&dec->local_dec, dec->sync->context, 200, is_tws_active_device); + + if (dec->local_dec.dec_type != AUDIO_CODING_SBC) { +#if TCFG_EQ_ENABLE && TCFG_MUSIC_MODE_EQ_ENABLE + dec->eq = music_eq_open(dec->local_dec.sample_rate, dec->local_dec.output_ch_num);// eq +#if TCFG_DRC_ENABLE && TCFG_MUSIC_MODE_DRC_ENABLE + dec->drc = music_drc_open(dec->local_dec.sample_rate, dec->local_dec.output_ch_num);//drc +#endif/*TCFG_MUSIC_MODE_DRC_ENABLE*/ + if (dec->eq && dec->eq->out_32bit) { + dec->convert = convet_data_open(0, 512); + } + +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + dec->eq2 = music_eq2_open(dec->local_dec.sample_rate, dec->local_dec.output_ch_num);// eq + dec->dy_eq = audio_dynamic_eq_ctrl_open(dec->local_dec.sample_rate, dec->local_dec.output_ch_num);//动态eq + dec->convert2 = convet_data_open(0, 512); +#endif/*TCFG_DYNAMIC_EQ_ENABLE*/ + dec->gain = audio_gain_open_demo(AEID_MUSIC_GAIN, dec->local_dec.output_ch_num); +#endif/*TCFG_MUSIC_MODE_EQ_ENABLE*/ + + } + + // 数据流串联 + struct audio_stream_entry *entries[8] = {NULL}; + u8 entry_cnt = 0; + entries[entry_cnt++] = &dec->local_dec.decoder.entry; + if (dec->sync) { + entries[entry_cnt++] = dec->sync->entry; + } +#if TCFG_EQ_ENABLE && TCFG_MUSIC_MODE_EQ_ENABLE + + if (dec->eq) { + entries[entry_cnt++] = &dec->eq->entry; + if (dec->drc) { + entries[entry_cnt++] = &dec->drc->entry; + } + if (dec->convert) { + entries[entry_cnt++] = &dec->convert->entry; + } +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + if (dec->eq2) { + entries[entry_cnt++] = &dec->eq2->entry; + } + if (dec->dy_eq && dec->dy_eq->dy_eq) { + entries[entry_cnt++] = &dec->dy_eq->dy_eq->entry; + } + if (dec->convert2) { + entries[entry_cnt++] = &dec->convert2->entry; + } +#endif + if (dec->gain) { + entries[entry_cnt++] = &dec->gain->entry; + } + } +#endif + if (dec->sync) { + entries[entry_cnt++] = dec->sync->resample_entry; + } + entries[entry_cnt++] = &dec->mix_ch.entry; + dec->stream = audio_stream_open(dec, localtws_dec_out_stream_resume); + audio_stream_add_list(dec->stream, entries, entry_cnt); + + audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); + + dec->local_dec.status = 1; + if (is_tws_active_device()) { + /*audio_decoder_set_run_max(&dec->local_dec.decoder, 10);*/ + } + err = audio_decoder_start(&dec->local_dec.decoder); + if (err) { + goto __err3; + } + + localtws_drop_frame_stop(); + bt_drop_a2dp_frame_start(); + local_dec_clock_add(dec->local_dec.decoder.dec_ops->coding_type); + clock_set_cur(); + + return 0; + +__err3: + dec->local_dec.status = 0; + /* file_eq_drc_close(dec->eq_drc); */ +#if TCFG_EQ_ENABLE && TCFG_MUSIC_MODE_EQ_ENABLE + music_eq_close(dec->eq); +#if TCFG_DRC_ENABLE && TCFG_MUSIC_MODE_DRC_ENABLE + music_drc_close(dec->drc); +#endif + convet_data_close(dec->convert); +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + music_eq2_close(dec->eq2); + audio_dynamic_eq_ctrl_close(dec->dy_eq); + convet_data_close(dec->convert2); +#endif + audio_gain_close_demo(dec->gain); +#endif + + audio_mixer_ch_close(&dec->mix_ch); + if (dec->stream) { + audio_stream_close(dec->stream); + dec->stream = NULL; + } + localtws_decoder_close(&dec->local_dec); +__err1: + localtws_dec_release(); + + return err; +} + +static void localtws_dec_res_put(struct localtws_dec_hdl *dec) +{ + if (!dec->local_dec.status) { + return; + } + os_mutex_pend(&g_localtws.mutex, 0); + g_localtws.drop_frame_start = 1; + dec->local_dec.status = 0; + localtws_decoder_close(&dec->local_dec); + /* file_eq_drc_close(dec->eq_drc); */ +#if TCFG_EQ_ENABLE && TCFG_MUSIC_MODE_EQ_ENABLE + music_eq_close(dec->eq); +#if TCFG_DRC_ENABLE && TCFG_MUSIC_MODE_DRC_ENABLE + music_drc_close(dec->drc); +#endif + convet_data_close(dec->convert); +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + music_eq2_close(dec->eq2); + audio_dynamic_eq_ctrl_close(dec->dy_eq); + convet_data_close(dec->convert2); +#endif + audio_gain_close_demo(dec->gain); +#endif + + if (dec->sync) { + audio_localtws_sync_close(dec->sync); + dec->sync = NULL; + } + audio_mixer_ch_close(&dec->mix_ch); + if (dec->stream) { + audio_stream_close(dec->stream); + dec->stream = NULL; + } + local_dec_clock_remove(dec->local_dec.decoder.dec_ops->coding_type); + /* g_localtws.media_value = 0; */ + if (g_localtws.tmrout) { + sys_hi_timeout_del(g_localtws.tmrout); + g_localtws.tmrout = 0; + } + tws_api_local_media_trans_clear(); + localtws_drop_frame_start(); + os_mutex_post(&g_localtws.mutex); +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws解码资源等待 + @param *wait: 句柄 + @param event: 事件 + @return 0:成功 + @note 用于多解码打断处理 +*/ +/*----------------------------------------------------------------------------*/ +static int localtws_dec_wait_res_handler(struct audio_res_wait *wait, int event) +{ + int err = 0; + + struct localtws_dec_hdl *dec = localtws_dec; + +#if 0 + if (event == AUDIO_RES_GET) { + if (dec->local_dec.status == 0) { + tws_api_local_media_set_limit_size(LOCALTWS_MEDIA_BUF_LIMIT_LEN); + err = localtws_dec_start(); + } else if (dec->local_dec.tmp_pause) { + tws_api_local_media_set_limit_size(LOCALTWS_MEDIA_BUF_LIMIT_LEN); + localtws_drop_frame_stop(); + dec->local_dec.tmp_pause = 0; + + /* audio_mixer_ch_open(&dec->mix_ch, &mixer); */ + + audio_output_set_start_volume(APP_AUDIO_STATE_MUSIC); + /*audio_output_start(dec->src_out_sr, 1);*/ + if (dec->local_dec.status) { + err = audio_decoder_start(&dec->local_dec.decoder); + } + } + } else if (event == AUDIO_RES_PUT) { + /* LOCALTWS_LOG("localtws AUDIO_RES_PUT\n"); */ + if (dec->local_dec.status) { + dec->local_dec.tmp_pause = 1; + err = audio_decoder_pause(&dec->local_dec.decoder); + os_time_dly(2); + // 先暂停再清数据,避免清了数据后dec还在output + tws_api_local_media_trans_clear(); + localtws_drop_frame_start(); + /* audio_mixer_ch_close(&dec->mix_ch); */ + } + } +#else + y_printf("%s,%d, evt:%d \n", __func__, __LINE__, event); + if (event == AUDIO_RES_GET) { + tws_api_local_media_set_limit_size(LOCALTWS_MEDIA_BUF_LIMIT_LEN); + err = localtws_dec_start(); + localtws_decoder_resume_pre(); + } else if (event == AUDIO_RES_PUT) { + if (dec->local_dec.status) { + localtws_dec_res_put(dec); + } + } +#endif + + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 打开localtws解码 + @param : + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int localtws_dec_open(u32 value) +{ + + if (localtws_dec && (localtws_dec->media_value != value)) { + localtws_dec_close(0); + } + + os_mutex_pend(&g_localtws.mutex, 0); + if (!localtws_dec) { + localtws_dec_close(0); + localtws_dec = zalloc(sizeof(struct localtws_dec_hdl)); + ASSERT(localtws_dec); + } else { + os_mutex_post(&g_localtws.mutex); + return 0; + } + + int err; + struct localtws_dec_hdl *dec = localtws_dec; + + LOCALTWS_LOG(" ****** localtws_dec_open: in, \n"); + sys_auto_shut_down_disable(); + + if (!dec) { + os_mutex_post(&g_localtws.mutex); + return -EPERM; + } + +#if 1 + a2dp_dec_close(); + esco_dec_close(); + g_localtws.drop_frame_start = 0; +#endif + + dec->id = rand32(); + + dec->media_value = value; + dec->local_dec.ch_type = AUDIO_CH_MAX; + dec->local_dec.output_ch_num = audio_output_channel_num(); + dec->local_dec.output_ch_type = audio_output_channel_type(); + + dec->wait.priority = 1; +#if DEC_MIX_ENABLE + dec->wait.preemption = 0; + dec->wait.protect = 1; +#else + dec->wait.preemption = 1; +#endif//DEC_MIX_ENABLE + + dec->wait.handler = localtws_dec_wait_res_handler; + err = audio_decoder_task_add_wait(&LOCALTWS_TASK, &dec->wait); + + os_mutex_post(&g_localtws.mutex); + + return err; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭localtws解码 + @param drop_frame_start: 是否中止传输 + @return 0:成功 + @note +*/ +/*----------------------------------------------------------------------------*/ +int localtws_dec_close(u8 drop_frame_start) +{ + os_mutex_pend(&g_localtws.mutex, 0); + /* LOCALTWS_LOG("localtws_dec_close start\n"); */ + if (!localtws_dec) { + os_mutex_post(&g_localtws.mutex); + return 0; + } + + if (drop_frame_start) { + g_localtws.drop_frame_start = 1; // 关闭过程中可能刚好会有数据过来 + } + + if (localtws_dec->local_dec.status) { + localtws_dec->local_dec.status = 0; + localtws_decoder_close(&localtws_dec->local_dec); + /* file_eq_drc_close(localtws_dec->eq_drc); */ +#if TCFG_EQ_ENABLE && TCFG_MUSIC_MODE_EQ_ENABLE + music_eq_close(localtws_dec->eq); +#if TCFG_DRC_ENABLE && TCFG_MUSIC_MODE_DRC_ENABLE + music_drc_close(localtws_dec->drc); +#endif + convet_data_close(localtws_dec->convert); +#if defined(TCFG_DYNAMIC_EQ_ENABLE) && TCFG_DYNAMIC_EQ_ENABLE + music_eq2_close(localtws_dec->eq2); + audio_dynamic_eq_ctrl_close(localtws_dec->dy_eq); + convet_data_close(localtws_dec->convert2); +#endif + audio_gain_close_demo(localtws_dec->gain); +#endif + + audio_mixer_ch_close(&localtws_dec->mix_ch); + if (localtws_dec->sync) { + audio_localtws_sync_close(localtws_dec->sync); + localtws_dec->sync = NULL; + } + if (localtws_dec->stream) { + audio_stream_close(localtws_dec->stream); + localtws_dec->stream = NULL; + } + local_dec_clock_remove(localtws_dec->local_dec.decoder.dec_ops->coding_type); + } + + /* g_localtws.media_value = 0; */ + if (g_localtws.tmrout) { + sys_hi_timeout_del(g_localtws.tmrout); + g_localtws.tmrout = 0; + } + + localtws_dec_release(); + + tws_api_local_media_trans_clear(); + if (drop_frame_start) { + g_localtws.drop_frame_start = 1; + localtws_drop_frame_start(); + } else { + localtws_drop_frame_stop(); + g_localtws.drop_frame_start = 0; + } + clock_set_cur(); + LOCALTWS_LOG("***** localtws_dec_close: exit\n"); + os_mutex_post(&g_localtws.mutex); + return 1; +} + +/*----------------------------------------------------------------------------*/ +/**@brief localtws暂停 + @param : + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void localtws_dec_pause(void) +{ + g_localtws.tws_send_pause = 1; +#ifdef TCFG_PCM_ENC2TWS_ENABLE + localtws_enc_clear(); +#endif + localtws_media_send_pause(100); + g_localtws.tws_send_pause = 2; +} +/*----------------------------------------------------------------------------*/ +/**@brief localtws已经开始解码 + @param + @return true: 已经开始解码 + @return false: 没有开始解码 + @note +*/ +/*----------------------------------------------------------------------------*/ +int localtws_dec_out_is_start(void) +{ + if ((!localtws_dec) || (!localtws_dec->local_dec.status)) { + return false; + } + if (localtws_dec->local_dec.read_en) { + return true; + } + return false; +} + + +/*----------------------------------------------------------------------------*/ +/**@brief localtws解码idle判断 + @param + @return 1: idle + @return 0: busy + @note +*/ +/*----------------------------------------------------------------------------*/ +static u8 localtws_dec_idle_query() +{ + if (localtws_dec) { + return 0; + } + + return 1; +} +REGISTER_LP_TARGET(localtws_dec_lp_target) = { + .name = "local_dec", + .is_idle = localtws_dec_idle_query, +}; + + + +#endif /*(defined(TCFG_DEC2TWS_ENABLE) && (TCFG_DEC2TWS_ENABLE))*/ + diff --git a/cpu/br23/maskrom_stubs.ld b/cpu/br23/maskrom_stubs.ld new file mode 100644 index 0000000..0f302ab --- /dev/null +++ b/cpu/br23/maskrom_stubs.ld @@ -0,0 +1,19 @@ + memmem = ABSOLUTE(0x1127a4); + memcpy = ABSOLUTE(0x1127a8); + memmove = ABSOLUTE(0x1127ac); + memcmp = ABSOLUTE(0x1127b0); + memset = ABSOLUTE(0x1127b4); + strcmp = ABSOLUTE(0x1127b8); + strcpy = ABSOLUTE(0x1127bc); + strlen = ABSOLUTE(0x1127c0); + strncmp = ABSOLUTE(0x1127c4); + strstr = ABSOLUTE(0x1127c8); + flush_dcache = ABSOLUTE(0x1127cc); + flushinv_dcache = ABSOLUTE(0x1127d0); + sfc_suspend = ABSOLUTE(0x1127d4); + sfc_resume = ABSOLUTE(0x1127d8); + chip_crc16 = ABSOLUTE(0x1127e0); + nvram_set_boot_state = ABSOLUTE(0x1127f0); + _IRQ_MEM_ADDR = ABSOLUTE(0x2bf00); + _MASK_MEM_BEGIN = ABSOLUTE(0x2bdc0); + _MASK_MEM_SIZE = ABSOLUTE(0x12c); diff --git a/cpu/br23/mcpwm.c b/cpu/br23/mcpwm.c new file mode 100644 index 0000000..861a226 --- /dev/null +++ b/cpu/br23/mcpwm.c @@ -0,0 +1,588 @@ +#include "asm/mcpwm.h" +#include "asm/clock.h" +#include "asm/gpio.h" + +#define MCPWM_DEBUG_ENABLE 1 +#if MCPWM_DEBUG_ENABLE +#define mcpwm_debug(fmt, ...) printf("[MCPWM] "fmt, ##__VA_ARGS__) +#else +#define mcpwm_debug(...) +#endif + +#define MCPWM_CLK clk_get("mcpwm") + +/*mcpwm硬件引脚,上下为一对:---CH0--- ---CH1--- ---CH2--- ---CH3--- ---CH4--- ---CH5--- */ +static u8 pwm_hw_h_pin[6] = {IO_PORTA_00, IO_PORTB_00, IO_PORTB_04, IO_PORTB_09, IO_PORTA_09, IO_PORTC_04}; +static u8 pwm_hw_l_pin[6] = {IO_PORTA_01, IO_PORTB_02, IO_PORTB_06, IO_PORTB_10, IO_PORTA_10, IO_PORTC_05}; +//fpin +static u8 pwm_fpin[6] = {IO_PORTA_14, IO_PORTA_15, IO_PORTA_08, IO_PORTC_00, IO_PORTC_01, IO_PORTC_02}; + +//mctmr extern clk in pin +static u8 mctmr_clkin_pin[6] = {IO_PORTA_02, IO_PORTA_03, IO_PORTA_12, IO_PORTA_13, IO_PORTB_03, IO_PORTC_03}; + +//output_channle +static u8 CHx_CHx_PWM_H[3][3] = {CH0_CH0_PWM_H, CH0_CH1_PWM_H, CH0_CH2_PWM_H, CH1_CH0_PWM_H, CH1_CH1_PWM_H, CH1_CH2_PWM_H, CH2_CH0_PWM_H, CH2_CH1_PWM_H, CH2_CH2_PWM_H}; +static u8 CHx_CHx_PWM_L[3][3] = {CH0_CH0_PWM_L, CH0_CH1_PWM_L, CH0_CH2_PWM_L, CH1_CH0_PWM_L, CH1_CH1_PWM_L, CH1_CH2_PWM_L, CH2_CH0_PWM_L, CH2_CH1_PWM_L, CH2_CH2_PWM_L}; + + +PWM_TIMER_REG *get_pwm_timer_reg(pwm_timer_num_type index) +{ + PWM_TIMER_REG *reg = NULL; + switch (index) { + case pwm_timer0: + reg = (PWM_TIMER_REG *)(&(JL_MCPWM->TMR0_CON)); + break; + case pwm_timer1: + reg = (PWM_TIMER_REG *)(&(JL_MCPWM->TMR1_CON)); + break; + case pwm_timer2: + reg = (PWM_TIMER_REG *)(&(JL_MCPWM->TMR2_CON)); + break; + case pwm_timer3: + reg = (PWM_TIMER_REG *)(&(JL_MCPWM->TMR3_CON)); + break; + case pwm_timer4: + reg = (PWM_TIMER_REG *)(&(JL_MCPWM->TMR4_CON)); + break; + case pwm_timer5: + reg = (PWM_TIMER_REG *)(&(JL_MCPWM->TMR5_CON)); + break; + default: + break; + } + + return reg; +} + + +PWM_CH_REG *get_pwm_ch_reg(pwm_ch_num_type index) +{ + PWM_CH_REG *reg = NULL; + switch (index) { + case pwm_timer0: + reg = (PWM_CH_REG *)(&(JL_MCPWM->CH0_CON0)); + break; + case pwm_timer1: + reg = (PWM_CH_REG *)(&(JL_MCPWM->CH1_CON0)); + break; + case pwm_timer2: + reg = (PWM_CH_REG *)(&(JL_MCPWM->CH2_CON0)); + break; + case pwm_timer3: + reg = (PWM_CH_REG *)(&(JL_MCPWM->CH3_CON0)); + break; + case pwm_timer4: + reg = (PWM_CH_REG *)(&(JL_MCPWM->CH4_CON0)); + break; + case pwm_timer5: + reg = (PWM_CH_REG *)(&(JL_MCPWM->CH5_CON0)); + break; + default: + break; + } + + return reg; +} + +static u32 _pow(u32 num, int n) +{ + u32 powint = 1; + int i; + for (i = 1; i <= n; i++) { + powint *= num; + } + return powint; +} + +/* + * @brief 更改MCPWM的频率 + * @parm frequency 频率 + */ +void mcpwm_set_frequency(pwm_timer_num_type ch, pwm_aligned_mode_type align, u32 frequency) +{ + PWM_TIMER_REG *reg = get_pwm_timer_reg(ch); + if (reg == NULL) { + return; + } + + u32 i = 0; + u32 mcpwm_div_clk = 0; + u32 mcpwm_tmr_pr = 0; + u32 mcpwm_fre_min = 0; + + reg->tmr_con = 0; + reg->tmr_cnt = 0; + reg->tmr_pr = 0; + + u32 clk = MCPWM_CLK; + + for (i = 0; i < 16; i++) { + mcpwm_fre_min = clk / (65536 * _pow(2, i)); + if ((frequency >= mcpwm_fre_min) || (i == 15)) { + break; + } + } + + reg->tmr_con |= (i << 4); //div 2^i + + mcpwm_div_clk = clk / _pow(2, i); + + if (frequency == 0) { + mcpwm_tmr_pr = 0; + } else { + if (align == pwm_center_aligned) { //中心对齐 + mcpwm_tmr_pr = mcpwm_div_clk / (frequency * 2) - 1; + } else { + mcpwm_tmr_pr = mcpwm_div_clk / frequency - 1; + } + } + reg->tmr_pr = mcpwm_tmr_pr; + + //timer mode + if (align == pwm_center_aligned) { //中心对齐 + reg->tmr_con |= 0b10; + } else { + reg->tmr_con |= 0b01; + } +} + + +/* + * @brief 设置一个通道的占空比 + * @parm pwm_ch_num 通道号:pwm_ch0,pwm_ch1,pwm_ch2 + * @parm duty 占空比:0 ~ 10000 对应 0% ~ 100% + */ +void mcpwm_set_duty(pwm_ch_num_type pwm_ch, pwm_timer_num_type timer_ch, u16 duty) +{ + PWM_TIMER_REG *timer_reg = get_pwm_timer_reg(timer_ch); + PWM_CH_REG *pwm_reg = get_pwm_ch_reg(pwm_ch); + + if (pwm_reg && timer_reg) { + pwm_reg->ch_cmpl = timer_reg->tmr_pr * duty / 10000; + pwm_reg->ch_cmph = pwm_reg->ch_cmpl; + timer_reg->tmr_cnt = 0; + timer_reg->tmr_con |= 0b01; + if (duty == 10000) { + timer_reg->tmr_cnt = 0; + timer_reg->tmr_con &= ~(0b11); + } else if (duty == 0) { + timer_reg->tmr_cnt = pwm_reg->ch_cmpl; + timer_reg->tmr_con &= ~(0b11); + } + } +} + +/* + * @brief 打开或者关闭一个时基 + * @parm pwm_ch_num 通道号:pwm_ch0,pwm_ch1,pwm_ch2 + * @parm enable 1:打开 0:关闭 + */ +void mctimer_ch_open_or_close(pwm_timer_num_type timer_ch, u8 enable) +{ + if (timer_ch > pwm_timer_max) { + return; + } + if (enable) { + JL_MCPWM->MCPWM_CON0 |= BIT(timer_ch + 8); //TnEN + } else { + JL_MCPWM->MCPWM_CON0 &= (~BIT(timer_ch + 8)); //TnDIS + } +} + + +/* + * @brief 打开或者关闭一个通道 + * @parm pwm_ch_num 通道号:pwm_ch0,pwm_ch1,pwm_ch2 + * @parm enable 1:打开 0:关闭 + */ +void mcpwm_ch_open_or_close(pwm_ch_num_type pwm_ch, u8 enable) +{ + if (pwm_ch >= pwm_ch_max) { + return; + } + + if (enable) { + JL_MCPWM->MCPWM_CON0 |= BIT(pwm_ch); //PWMnEN + } else { + JL_MCPWM->MCPWM_CON0 &= (~BIT(pwm_ch)); //PWMnDIS + } +} + +/* + * @brief 关闭MCPWM模块 + */ +void mcpwm_open(pwm_ch_num_type pwm_ch, pwm_timer_num_type timer_ch) +{ + if ((pwm_ch >= pwm_ch_max) || (timer_ch >= pwm_timer_max)) { + return; + } + PWM_CH_REG *pwm_reg = get_pwm_ch_reg(pwm_ch); + pwm_reg->ch_con1 &= ~(0b111 << 8); + pwm_reg->ch_con1 |= (timer_ch << 8); //sel mctmr + + mcpwm_ch_open_or_close(pwm_ch, 1); + mctimer_ch_open_or_close(timer_ch, 1); +} + + +/* + * @brief 关闭MCPWM模块 + */ +void mcpwm_close(pwm_ch_num_type pwm_ch, pwm_timer_num_type timer_ch) +{ + mctimer_ch_open_or_close(timer_ch, 0); + mcpwm_ch_open_or_close(pwm_ch, 0); +} + + +void log_pwm_info(pwm_ch_num_type pwm_ch, pwm_timer_num_type timer_ch) +{ + PWM_CH_REG *pwm_reg = get_pwm_ch_reg(pwm_ch); + PWM_TIMER_REG *timer_reg = get_pwm_timer_reg(timer_ch); + mcpwm_debug("pwm_ch %d @ 0x%x, timer_ch %d @ 0x%x", pwm_ch, pwm_reg, timer_ch, timer_reg); + mcpwm_debug("tmr%d con0 = 0x%x", timer_ch, timer_reg->tmr_con); + mcpwm_debug("tmr%d pr = 0x%x", timer_ch, timer_reg->tmr_pr); + mcpwm_debug("pwm ch%d_con0 = 0x%x", pwm_ch, pwm_reg->ch_con0); + mcpwm_debug("pwm ch%d_con1 = 0x%x", pwm_ch, pwm_reg->ch_con1); + mcpwm_debug("pwm ch%d_cmph = 0x%x, pwm ch%d_cmpl = 0x%x", pwm_ch, pwm_reg->ch_cmph, pwm_ch, pwm_reg->ch_cmpl); + mcpwm_debug("MCPWM_CON0 = 0x%x", JL_MCPWM->MCPWM_CON0); + mcpwm_debug("mcpwm clk = %d", MCPWM_CLK); +} + +void mcpwm_init(struct pwm_platform_data *arg) +{ + u8 h_output_channel = 0; + u8 l_output_channel = 0; + u8 use_output_ch_flag = 0; + + //set mctimer frequency + mcpwm_set_frequency(arg->pwm_timer_num, arg->pwm_aligned_mode, arg->frequency); + //set output IO + PWM_CH_REG *pwm_reg = get_pwm_ch_reg(arg->pwm_ch_num); + if (pwm_reg == NULL) { + return; + } + + pwm_reg->ch_con0 = 0; + + //H: + if (arg->h_pin == pwm_hw_h_pin[arg->pwm_ch_num]) { //硬件引脚 + pwm_reg->ch_con0 |= BIT(2); //H_EN + gpio_set_direction(arg->h_pin, 0); //DIR output + } else { + pwm_reg->ch_con0 &= ~BIT(2); //H_DISABLE + if (arg->h_pin < IO_MAX_NUM) { //任意引脚 + //TODO: output_channle + if (arg->pwm_ch_num >= pwm_ch3) { + printf("error: mcpwm ch %d not support output_channel", arg->pwm_ch_num); + goto _CH_L_SET; + } + h_output_channel = 1; + /* gpio_output_channle(arg->h_pin, CHx_CHx_PWM_H[arg->h_pin_output_ch_num][arg->pwm_ch_num]); */ + use_output_ch_flag = 1; + } + } + +_CH_L_SET: + //L: + if (arg->l_pin == pwm_hw_l_pin[arg->pwm_ch_num]) { //硬件引脚 + pwm_reg->ch_con0 |= BIT(3); //L_EN + gpio_set_direction(arg->l_pin, 0); //DIR output + } else { + pwm_reg->ch_con0 &= ~BIT(3); //L_DISABLE + if (arg->l_pin < IO_MAX_NUM) { //任意引脚 + //TODO: + if (arg->pwm_ch_num >= pwm_ch3) { + printf("error: mcpwm ch %d not support output_channel", arg->pwm_ch_num); + goto _PWM_OPEN; + } + if ((use_output_ch_flag == 1) && (arg->h_pin_output_ch_num == arg->l_pin_output_ch_num)) { + arg->l_pin_output_ch_num ++; + if (arg->l_pin_output_ch_num > 2) { + arg->l_pin_output_ch_num = 0; + } + } + l_output_channel = 1; + /* gpio_output_channle(arg->l_pin, CHx_CHx_PWM_L[arg->l_pin_output_ch_num][arg->pwm_ch_num]); */ + } + } + + if (arg->complementary_en) { //是否互补 + pwm_reg->ch_con0 &= ~(BIT(5) | BIT(4)); + pwm_reg->ch_con0 |= BIT(5); //L_INV + } else { + pwm_reg->ch_con0 &= ~(BIT(5) | BIT(4)); + } + +_PWM_OPEN: + mcpwm_open(arg->pwm_ch_num, arg->pwm_timer_num); //mcpwm enable + if (h_output_channel) { + gpio_output_channle(arg->h_pin, CHx_CHx_PWM_H[arg->h_pin_output_ch_num][arg->pwm_ch_num]); + } + if (l_output_channel) { + gpio_output_channle(arg->l_pin, CHx_CHx_PWM_L[arg->l_pin_output_ch_num][arg->pwm_ch_num]); + } + //set duty + mcpwm_set_duty(arg->pwm_ch_num, arg->pwm_timer_num, arg->duty); + + /* log_pwm_info(arg->pwm_ch_num, arg->pwm_timer_num); */ +} + + +///////////// for test code ////////////////// +void mcpwm_test(void) +{ +#define PWM_CH0_ENABLE 1 +#define PWM_CH1_ENABLE 1 +#define PWM_CH2_ENABLE 1 +#define PWM_CH3_ENABLE 1 +#define PWM_CH4_ENABLE 1 +#define PWM_CH5_ENABLE 1 + + struct pwm_platform_data pwm_p_data; +#if PWM_CH0_ENABLE + //CH0 + pwm_p_data.pwm_aligned_mode = pwm_edge_aligned; //边沿对齐 + pwm_p_data.frequency = 1000; //1KHz + + pwm_p_data.pwm_ch_num = pwm_ch0; //通道0 + pwm_p_data.pwm_timer_num = pwm_timer0; //时基选择通道0 + pwm_p_data.duty = 5000; //占空比50% + //hw + pwm_p_data.h_pin = IO_PORTA_00; //没有则填 -1。h_pin_output_ch_num无效,可不配置 + pwm_p_data.l_pin = IO_PORTA_01; //硬件引脚,l_pin_output_ch_num无效,可不配置 + //output_channel + /* pwm_p_data.h_pin = IO_PORTB_00; //没有则填 -1。h_pin_output_ch_num无效,可不配置 */ + /* pwm_p_data.l_pin = IO_PORTB_01; //硬件引脚,l_pin_output_ch_num无效,可不配置 */ + /* pwm_p_data.h_pin_output_ch_num = 0; //output channel0 */ + /* pwm_p_data.l_pin_output_ch_num = 1; //output channel1 */ + pwm_p_data.complementary_en = 1; //两个引脚的波形, 1: 互补, 0: 同步; + + mcpwm_init(&pwm_p_data); +#endif + +#if PWM_CH1_ENABLE + //CH1 + pwm_p_data.pwm_aligned_mode = pwm_edge_aligned; //边沿对齐 + pwm_p_data.frequency = 100; //1KHz + + pwm_p_data.pwm_ch_num = pwm_ch1; //通道0 + pwm_p_data.pwm_timer_num = pwm_timer1; //时基选择通道0 + pwm_p_data.duty = 5000; //占空比50% + //hw + pwm_p_data.h_pin = IO_PORTB_00; //没有则填 -1。h_pin_output_ch_num无效,可不配置 + pwm_p_data.l_pin = IO_PORTB_02; //硬件引脚,l_pin_output_ch_num无效,可不配置 + //output_channel + /* pwm_p_data.h_pin = IO_PORTA_00; //没有则填 -1。h_pin_output_ch_num无效,可不配置 */ + /* pwm_p_data.l_pin = IO_PORTA_04; //硬件引脚,l_pin_output_ch_num无效,可不配置 */ + /* pwm_p_data.h_pin_output_ch_num = 0; //output channel0 */ + /* pwm_p_data.l_pin_output_ch_num = 2; //output channel1 */ + pwm_p_data.complementary_en = 1; //两个引脚的波形同步 + + mcpwm_init(&pwm_p_data); +#endif + +#if PWM_CH2_ENABLE + //CH2 + pwm_p_data.pwm_aligned_mode = pwm_edge_aligned; //边沿对齐 + pwm_p_data.frequency = 2000; //1KHz + + pwm_p_data.pwm_ch_num = pwm_ch2; //通道0 + pwm_p_data.pwm_timer_num = pwm_timer2; //时基选择通道0 + pwm_p_data.duty = 5000; //占空比50% + //hw + pwm_p_data.h_pin = IO_PORTB_04; //没有则填 -1。h_pin_output_ch_num无效,可不配置 + //output_channel + /* pwm_p_data.h_pin = IO_PORTB_05; //没有则填 -1。h_pin_output_ch_num无效,可不配置 */ + /* pwm_p_data.h_pin_output_ch_num = 1; //output channel0 */ + //hw + pwm_p_data.l_pin = IO_PORTB_06; //硬件引脚,l_pin_output_ch_num无效,可不配置 + pwm_p_data.complementary_en = 1; //两个引脚的波形同步 + + mcpwm_init(&pwm_p_data); +#endif + + //注意: CH3, CH4, CH5不支持通过output channel输出 +#if PWM_CH3_ENABLE + //CH3 + pwm_p_data.pwm_aligned_mode = pwm_edge_aligned; //边沿对齐 + pwm_p_data.frequency = 4000; //1KHz + + pwm_p_data.pwm_ch_num = pwm_ch3; //通道0 + pwm_p_data.pwm_timer_num = pwm_timer3; //时基选择通道0 + pwm_p_data.duty = 5000; //占空比50% + pwm_p_data.h_pin = IO_PORTB_09; //没有则填 -1。h_pin_output_ch_num无效,可不配置 + pwm_p_data.l_pin = IO_PORTB_10; //硬件引脚,l_pin_output_ch_num无效,可不配置 + pwm_p_data.complementary_en = 1; //两个引脚的波形同步 + + mcpwm_init(&pwm_p_data); +#endif + +#if PWM_CH4_ENABLE + //CH4 + pwm_p_data.pwm_aligned_mode = pwm_edge_aligned; //边沿对齐 + pwm_p_data.frequency = 8000; //1KHz + + pwm_p_data.pwm_ch_num = pwm_ch4; //通道0 + pwm_p_data.pwm_timer_num = pwm_timer4; //时基选择通道0 + pwm_p_data.duty = 5000; //占空比50% + pwm_p_data.h_pin = IO_PORTA_09; //没有则填 -1。h_pin_output_ch_num无效,可不配置 + pwm_p_data.l_pin = IO_PORTA_10; //硬件引脚,l_pin_output_ch_num无效,可不配置 + pwm_p_data.complementary_en = 1; //两个引脚的波形同步 + + mcpwm_init(&pwm_p_data); +#endif + +#if PWM_CH5_ENABLE + //CH5 + pwm_p_data.pwm_aligned_mode = pwm_edge_aligned; //边沿对齐 + pwm_p_data.frequency = 16000; //1KHz + //pwm_p_data.frequency = 50000; //1KHz + + pwm_p_data.pwm_ch_num = pwm_ch5; //通道0 + pwm_p_data.pwm_timer_num = pwm_timer5; //时基选择通道0 + pwm_p_data.duty = 5000; //占空比50% + pwm_p_data.h_pin = IO_PORTC_04; //没有则填 -1。h_pin_output_ch_num无效,可不配置 + pwm_p_data.l_pin = IO_PORTC_05; //硬件引脚,l_pin_output_ch_num无效,可不配置 + pwm_p_data.complementary_en = 1; //两个引脚的波形同步 + + mcpwm_init(&pwm_p_data); +#endif + + while (1); +} + + +/************************************** 外部引脚中断参考代码 **************************/ +static IO_ISR_FUNC io_isr_cbfun; +___interrupt +void io_interrupt(void) +{ + JL_MCPWM->CH0_CON1 |= BIT(14); + io_isr_cbfun(); +} +void io_ext_interrupt_init(u8 port, trigger_mode_type trigger_mode, IO_ISR_FUNC cbfun) +{ + if (port > IO_PORT_MAX) { + return; + } + gpio_set_die(port, 1); + gpio_set_direction(port, 1); + if (trigger_mode) { + gpio_set_pull_up(port, 1); + gpio_set_pull_down(port, 0); + JL_MCPWM->FPIN_CON = 0; + } else { + gpio_set_pull_up(port, 0); + gpio_set_pull_down(port, 1); + JL_MCPWM->FPIN_CON = BIT(16); + } + if (port == IO_PORTA_14) { + JL_IOMAP->CON3 &= ~BIT(12); //使用硬件引脚 + } else { + JL_IOMAP->CON3 |= BIT(12); //使用input_channel 2 + JL_IOMAP->CON2 &= ~(0b111111 << 16); + JL_IOMAP->CON2 |= (port << 16); + } + io_isr_cbfun = cbfun; + request_irq(IRQ_CHX_PWM_IDX, 3, io_interrupt, 0); //注册中断函数 + JL_MCPWM->CH0_CON1 = BIT(14) | BIT(11) | BIT(4); + JL_MCPWM->MCPWM_CON0 |= BIT(0); +} +void io_ext_interrupt_close(u8 port) +{ + if (port > IO_PORT_MAX) { + return; + } + gpio_set_die(port, 0); + gpio_set_direction(port, 1); + gpio_set_pull_up(port, 0); + gpio_set_pull_down(port, 0); + JL_MCPWM->CH0_CON1 = BIT(14); +} + +///////////// 使用举例如下 ////////////////// +void my_io_isr_cbfun(void) +{ + printf("Hello world !\n"); +} +void io_ext_interrupt_test(void) +{ + io_ext_interrupt_init(IO_PORTA_09, rising_edge_trigger, my_io_isr_cbfun); + while (1); +} + + +#define OSC_Hz 24000000 +/** + * @param JL_TIMERx : JL_TIMER0/1/2/3/4/5 + * @param fre : 频率,单位Hz,不小于95 + * @param duty : 初始占空比,0~10000对应0~100% + * @param port : pwm脚,可选硬件脚,也可选非硬件脚。(建议选择硬件引脚) + * @param output_ch : 映射通道,当pwm脚选择非硬件脚时有效,这时我们给他分配output_channel 0/1/2 + */ +int timer_pwm_init(JL_TIMER_TypeDef *JL_TIMERx, u32 fre, u32 duty, u32 port, int output_ch) +{ + u32 hw_port; + switch ((u32)JL_TIMERx) { + case (u32)JL_TIMER0 : + hw_port = IO_PORTA_05; + break; + case (u32)JL_TIMER1 : + hw_port = IO_PORTA_12; + break; + case (u32)JL_TIMER2 : + hw_port = IO_PORTB_03; + break; + case (u32)JL_TIMER3 : + bit_clr_ie(IRQ_TIME3_IDX); + hw_port = IO_PORTB_05; + break; + default: + return (-1); + } + if ((output_ch == (-1)) && (hw_port != port)) { + //not support output_ch + return (-1); + } + + //初始化timer + JL_TIMERx->CON = 0; + JL_TIMERx->CON |= (0b10 << 2); //选择晶振时钟源:24MHz + JL_TIMERx->CON |= (0b0001 << 4); //时钟源4分频 + JL_TIMERx->PRD = OSC_Hz / (4 * fre); //设置周期 + JL_TIMERx->PWM = (JL_TIMERx->PRD * duty) / fre; //0~10000对应0~100g + JL_TIMERx->CNT = 0; //清计数值 + JL_TIMERx->CON |= (0b01 << 0); //计数模式 + + if (hw_port == port) { + gpio_set_die(hw_port, 1); + gpio_set_pull_up(hw_port, 0); + gpio_set_pull_down(hw_port, 0); + gpio_set_direction(hw_port, 0); + JL_TIMERx->CON |= BIT(8); //PWM使能 + } else { + + gpio_output_channle(port, output_ch); + return 1; + } + return 0; +} + +/** + * @param JL_TIMERx : JL_TIMER0/1/2/3/4/5 + * @param duty : 占空比,0~10000对应0~100% + */ +void set_timer_pwm_duty(JL_TIMER_TypeDef *JL_TIMERx, u32 duty) +{ + JL_TIMERx->PWM = (JL_TIMERx->PRD * duty) / 10000; //0~10000对应0~100% +} + +/* */ +/* void timer_pwm_test(void) */ +/* { */ +/* timer_pwm_init(JL_TIMER2, 10000, 2000, IO_PORTB_00, CH2_T2_PWM_OUT); */ +/* timer_pwm_init(JL_TIMER3, 10000, 5000, IO_PORTB_05, 0); */ +/* timer_pwm_init(JL_TIMER5, 10000, 8000, IO_PORTB_07, 0); */ +/* } */ + diff --git a/cpu/br23/overlay_code.c b/cpu/br23/overlay_code.c new file mode 100644 index 0000000..524a1d7 --- /dev/null +++ b/cpu/br23/overlay_code.c @@ -0,0 +1,105 @@ +#include "asm/includes.h" +#include "media/includes.h" +#include "overlay_code.h" + + +struct code_type { + u32 type; + u32 dst; + u32 src; + u32 size; +}; + +////用于区分 overlay code 和 bss +/*此处不使用这种用法,直接在overlay段中使用LONG(0xFFFFFFFF),避免印代码被优化掉,导致的坑*/ +/* u32 aec_bss_id sec(.aec_bss_id) = 0xffffffff; */ +/* u32 fm_bss_id sec(.fm_bss_id) = 0xffffffff; */ +/* u32 mp3_bss_id sec(.mp3_bss_id) = 0xffffffff; */ +/* u32 wma_bss_id sec(.wma_bss_id) = 0xffffffff; */ +/* u32 wav_bss_id sec(.wav_bss_id) = 0xffffffff; */ + +/* u32 wav_bss_id sec(.wav_bss_id) = 0xffffffff; +u32 ape_bss_id sec(.ape_bss_id) = 0xffffffff; +u32 flac_bss_id sec(.flac_bss_id) = 0xffffffff; +u32 m4a_bss_id sec(.m4a_bss_id) = 0xffffffff; +u32 amr_bss_id sec(.amr_bss_id) = 0xffffffff; +u32 dts_bss_id sec(.dts_bss_id) = 0xffffffff; + */ +extern int aec_addr, aec_begin, aec_size; +extern int wav_addr, wav_begin, wav_size; +extern int ape_addr, ape_begin, ape_size; +extern int flac_addr, flac_begin, flac_size; +extern int m4a_addr, m4a_begin, m4a_size; +extern int amr_addr, amr_begin, amr_size; +extern int dts_addr, dts_begin, dts_size; +extern int fm_addr, fm_begin, fm_size; + +#ifdef CONFIG_MP3_WMA_LIB_SPECIAL +extern int mp3_addr, mp3_begin, mp3_size; +extern int wma_addr, wma_begin, wma_size; +#endif + +const struct code_type ctype[] = { + {OVERLAY_AEC, (u32) &aec_addr, (u32) &aec_begin, (u32) &aec_size}, + {OVERLAY_WAV, (u32) &wav_addr, (u32) &wav_begin, (u32) &wav_size }, + {OVERLAY_APE, (u32) &ape_addr, (u32) &ape_begin, (u32) &ape_size }, + {OVERLAY_FLAC, (u32) &flac_addr, (u32) &flac_begin, (u32) &flac_size}, + {OVERLAY_M4A, (u32) &m4a_addr, (u32) &m4a_begin, (u32) &m4a_size }, + {OVERLAY_AMR, (u32) &amr_addr, (u32) &amr_begin, (u32) &amr_size }, + {OVERLAY_DTS, (u32) &dts_addr, (u32) &dts_begin, (u32) &dts_size }, + {OVERLAY_FM, (u32) &fm_addr, (u32) &fm_begin, (u32) &fm_size }, + +#ifdef CONFIG_MP3_WMA_LIB_SPECIAL + {OVERLAY_MP3, (u32) &mp3_addr, (u32) &mp3_begin, (u32) &mp3_size }, + {OVERLAY_WMA, (u32) &wma_addr, (u32) &wma_begin, (u32) &wma_size }, +#endif + +}; + +struct audio_overlay_type { + u32 atype; + u32 otype; +}; + +const struct audio_overlay_type aotype[] = { + + {AUDIO_CODING_MSBC, OVERLAY_AEC }, + {AUDIO_CODING_CVSD, OVERLAY_AEC }, + {AUDIO_CODING_WAV, OVERLAY_WAV}, + {AUDIO_CODING_APE, OVERLAY_APE }, + {AUDIO_CODING_FLAC, OVERLAY_FLAC}, + {AUDIO_CODING_M4A, OVERLAY_M4A }, + {AUDIO_CODING_ALAC, OVERLAY_M4A }, + {AUDIO_CODING_AMR, OVERLAY_AMR }, + {AUDIO_CODING_DTS, OVERLAY_DTS }, + {AUDIO_CODING_AAC, OVERLAY_M4A }, +#ifdef CONFIG_MP3_WMA_LIB_SPECIAL + {AUDIO_CODING_MP3, OVERLAY_MP3 }, + {AUDIO_CODING_WMA, OVERLAY_WMA }, +#endif + +}; + + +void overlay_load_code(u32 type) +{ + int i = 0; + for (i = 0; i < ARRAY_SIZE(ctype); i++) { + if (type == ctype[i].type) { + if (ctype[i].dst != 0) { + memcpy((void *)ctype[i].dst, (void *)ctype[i].src, (int)ctype[i].size); + } + break; + } + } +} + +void audio_overlay_load_code(u32 type) +{ + int i = 0; + for (i = 0; i < ARRAY_SIZE(aotype); i++) { + if (type == aotype[i].atype) { + overlay_load_code(aotype[i].otype); + } + } +} diff --git a/cpu/br23/overlay_code.h b/cpu/br23/overlay_code.h new file mode 100644 index 0000000..cb76522 --- /dev/null +++ b/cpu/br23/overlay_code.h @@ -0,0 +1,29 @@ + +#ifndef _OVERLAY_CODE_H_ +#define _OVERLAY_CODE_H_ + +#include "typedef.h" + +enum { + OVERLAY_AEC = 0, + OVERLAY_WAV, + OVERLAY_APE, + OVERLAY_FLAC, + OVERLAY_M4A, + OVERLAY_ALAC, + OVERLAY_AMR, + OVERLAY_DTS, + OVERLAY_FM, + +#ifdef CONFIG_MP3_WMA_LIB_SPECIAL + OVERLAY_MP3, + OVERLAY_WMA, +#endif + +}; + +void overlay_load_code(u32 type); +void audio_overlay_load_code(u32 type); + +#endif + diff --git a/cpu/br23/plcnt.c b/cpu/br23/plcnt.c new file mode 100644 index 0000000..e6208b1 --- /dev/null +++ b/cpu/br23/plcnt.c @@ -0,0 +1,284 @@ +#include "includes.h" +#include "asm/plcnt.h" + +#define PLCNT_CTM_DEBUG 0 + +#if PLCNT_CTM_DEBUG +#define plcnt_ctm_debug(fmt, ...) printf("[PLCNT] "fmt, ##__VA_ARGS__) +#else +#define plcnt_ctm_debug(fmt, ...) +#endif + +u8 g_touch_len; //触摸按键数 +u8 bCapState; //电容充放电状态 +u8 bCap_ch = 0; //触摸通道 +u16 Touchkey_value_new = 0; +u16 Touchkey_value_old = 0; +sCTM_KEY_VAR ctm_key_value; + + +#define PLCNT_CLOCK_SEL(x) SFR(JL_PCNT->CON, 2, 2, x) +#define INPUT_CHANNLE2_SRC_SEL(x) SFR(JL_IOMAP->CON2, 16, 6, x) + +static const struct touch_key_platform_data *user_data = NULL; + + +sCTM_KEY_VAR *ctm_key_var; + + +static u8 plcnt_channel2port(u8 chan) +{ + return user_data->port_list[chan].port; +} + + +static void set_port_out_H(u8 chan) +{ + gpio_direction_output(plcnt_channel2port(chan), 1); +} + +static void set_port_pd(u8 chan) +{ + gpio_set_pull_down(plcnt_channel2port(chan), 1); +} + +static void set_port_die(u8 chan) +{ + gpio_set_die(plcnt_channel2port(chan), 1); +} + + +static void set_port_in(u8 chan) +{ + gpio_direction_input(plcnt_channel2port(chan)); //输入 +} + +static void set_touch_io(u8 chan) +{ + INPUT_CHANNLE2_SRC_SEL(plcnt_channel2port(chan)); + set_port_in(chan); //设置为输入 +} + + +static void ctm_key_var_init(sCTM_KEY_VAR *ptr) +{ + ctm_key_var = ptr; +} + +static void ctm_irq(u16 ctm_res, u8 ch) +{ + u16 temp_u16_0, temp_u16_1; + s16 temp_s16_0, temp_s16_1; + s32 temp_s32_0; +//.............................................................................................. +//取计数值/通道判断 +//.............................................................................................. + + + if (ctm_key_var->touch_init_cnt[ch]) { + ctm_key_var->touch_init_cnt[ch]--; +// touch_cnt_buf[ch] = rvalue << FLT0CFG; +// touch_release_buf[ch] = (long)(rvalue) << FLT1CFG0; + ctm_key_var->touch_cnt_buf[ch] = (u32)ctm_res << ctm_key_var->FLT0CFG; + ctm_key_var->touch_release_buf[ch] = (u32)ctm_res << ctm_key_var->FLT1CFG0; + } + +//.............................................................................................. +//当前计数值去抖动滤波器 +//.............................................................................................. + temp_u16_0 = ctm_key_var->touch_cnt_buf[ch]; + temp_u16_1 = temp_u16_0; + temp_u16_1 -= (temp_u16_1 >> ctm_key_var->FLT0CFG); + temp_u16_1 += ctm_res;//temp_u16_1 += rvalue; + ctm_key_var->touch_cnt_buf[ch] = temp_u16_1; + temp_u16_0 += temp_u16_1; + temp_u16_0 >>= (ctm_key_var->FLT0CFG + 1); + + +//.............................................................................................. +//各通道按键释放计数值滤波器 +//.............................................................................................. + temp_s32_0 = ctm_key_var->touch_release_buf[ch]; + temp_u16_1 = temp_s32_0 >> ctm_key_var->FLT1CFG0; //获得滤波器之后的按键释放值 + temp_s16_0 = temp_u16_0 - temp_u16_1; //获得和本次检测值的差值,按下按键为负值,释放按键为正值 + temp_s16_1 = temp_s16_0; + +// if(ch == 1) +// { +// printf("ch%d: %d %d", (short)ch, temp_u16_0, temp_s16_1); +// } + + if (ctm_key_var->touch_key_state & BIT(ch)) { //如果本通道按键目前是处于释放状态 + if (temp_s16_1 >= 0) { //当前计数值大于低通值,放大后参与运算 + if (temp_s16_1 < (ctm_key_var->FLT1CFG2 >> 3)) { + temp_s16_1 <<= 3; //放大后参与运算 + } else { + temp_s16_1 = ctm_key_var->FLT1CFG2; //饱和,防止某些较大的正偏差导致错判 + } + } else if (temp_s16_1 >= ctm_key_var->FLT1CFG1) { //当前计数值小于低通值不多,正常参与运算 + } else { //当前计数值小于低通值很多,缩小后参与运算 (有符号数右移自动扩展符号位???) + temp_s16_1 >>= 3; + } + } else { //如果本通道按键目前是处于按下状态, 缓慢降低释放计数值 + if (temp_s16_1 <= ctm_key_var->RELEASECFG1) { + temp_s16_1 >>= 3; //缩小后参与运算 + } else { + temp_s16_1 = 0; + } + } + + temp_s32_0 += (s32)temp_s16_1; + ctm_key_var->touch_release_buf[ch] = temp_s32_0; + +//.............................................................................................. +//按键按下与释放检测 +//.............................................................................................. + if (temp_s16_0 <= ctm_key_var->PRESSCFG) { //按键按下 + ctm_key_var->touch_key_state &= ~BIT(ch); + } else if (temp_s16_0 >= ctm_key_var->RELEASECFG0) { //按键释放 + ctm_key_var->touch_key_state |= BIT(ch); + } +} + + +static void scan_capkey(void *priv) +{ + u16 temp; + u16 Touchkey_value_delta; + + if (0 == g_touch_len) { + return; + } + + if (bCapState == 0) { + bCapState = 1; + Touchkey_value_new = JL_PCNT->VAL; ///获取计数值 + + set_port_out_H(bCap_ch);//set output H + ///////***wait IO steady for pulse counter + + if (Touchkey_value_old > Touchkey_value_new) { + Touchkey_value_new += 0x10000; + } + + Touchkey_value_delta = Touchkey_value_new - Touchkey_value_old; + //plcnt_ctm_debug("old: %x new: %x", Touchkey_value_old, Touchkey_value_new); + Touchkey_value_old = Touchkey_value_new; ///记录旧值 + temp = 6800L - Touchkey_value_delta * user_data->change_gain; ///1变化增大倍数 + + /* if(bCap_ch == 0){ */ + /* plcnt_ctm_debug("value: %x\n", Touchkey_value_delta); */ + /* } */ + + //plcnt_ctm_debug("delta: %d, ch: %d", Touchkey_value_delta, bCap_ch); + /* if(bCap_ch == 0) */ + /* { */ + /* plcnt_ctm_debug("temp: %d\n", Touchkey_value_delta); */ + /* } */ + + /*调用滤波算法*/ + ctm_irq(temp, bCap_ch); + + /*清除前一个通道状态,锁定PLL CNT*/ + //set_port_out(bCap_ch); //设为输出 + /*切换通道,开始充电,PLL CNT 输入Mux 切换*/ + bCap_ch++; + bCap_ch %= g_touch_len; + //bCap_ch = (bCap_ch >= g_touch_len) ? 0 : bCap_ch; + + + ////////***make sure IO is steady (IO output high voltage) for pulse counter + + set_port_out_H(bCap_ch); + //set_port_out(bCap_ch); + + } else { + bCapState = 0; + set_touch_io(bCap_ch); //设为输入开始计数 + } +} + +//API: +u8 get_plcnt_value(void) +{ + u8 key; + u8 i; + + for (i = 0; i < g_touch_len; i++) { + if (!(ctm_key_value.touch_key_state & (u8)(BIT(i)))) { + break; + } + } + key = (i < g_touch_len) ? i : NO_KEY; + + if (key != NO_KEY) { + //plcnt_ctm_debug("tch %x", key); + } + + return key; +} + + +//API: +int plcnt_init(void *_data) +{ + if (_data == NULL) { + return -1; + } + user_data = (const struct touch_key_platform_data *)_data; + + + ctm_key_var_init(&ctm_key_value); + + memset((u8 *)&ctm_key_value, 0x0, sizeof(sCTM_KEY_VAR)); + + /*触摸按键参数配置*/ + ctm_key_value.FLT0CFG = 0; + ctm_key_value.FLT1CFG0 = 7; + ctm_key_value.FLT1CFG1 = -80; + ctm_key_value.FLT1CFG2 = (-(-10)) << 7; //1280 + + ///调节灵敏度的主要参数 + /* ctm_key_value.PRESSCFG = -10; */ + /* ctm_key_value.RELEASECFG0 = -50; */ + /* ctm_key_value.RELEASECFG1 = -80;//-81; */ + + ctm_key_value.PRESSCFG = user_data->press_cfg; + ctm_key_value.RELEASECFG0 = user_data->release_cfg0; + ctm_key_value.RELEASECFG1 = user_data->release_cfg1; + + memset((u8 *) & (ctm_key_value.touch_init_cnt[0]), 0x10, TOUCH_KEY_CH_MAX); + + ctm_key_value.touch_key_state = 0xffff; //<按键默认释放 + + //初始化计数器配置: + PLCNT_CLOCK_SEL(user_data->clock); + + JL_PCNT->CON |= BIT(1); //使能计数器 + + if (user_data->num > TOUCH_KEY_CH_MAX) { + printf("plcnt_ctm key num config err!!!"); + return -1; + } + + g_touch_len = user_data->num; + Touchkey_value_old = JL_PCNT->VAL; ///获取计数值 + + set_port_out_H(bCap_ch); + +#if 1 //如果外部有下拉电阻,可不是用芯片内部下拉 + for (u8 i = 0; i < g_touch_len; i++) { + set_port_pd(i); + set_port_die(i); + } +#endif + + plcnt_ctm_debug("touch_key_init , plcnt_con = 0x%x, val = 0x%x", JL_PCNT->CON, JL_PCNT->VAL); + + sys_s_hi_timer_add(NULL, scan_capkey, 2); //2ms + + return 0; +} + + + diff --git a/cpu/br23/port_wkup.c b/cpu/br23/port_wkup.c new file mode 100644 index 0000000..6672e65 --- /dev/null +++ b/cpu/br23/port_wkup.c @@ -0,0 +1,83 @@ +#include "typedef.h" +#include "irq.h" +#include "asm/gpio.h" + +/** + * 注意:JL_WAKEUP 区别于PMU管理的唤醒。可理解为一个独立的模块使用。但在低功耗的情况下,中断无效。 + */ + +static void (*port_wkup_irq_cbfun)(void) = NULL; +static u32 user_port = -1;; +/** + * @brief 引脚中断函数 + */ +___interrupt +void port_wkup_irq_fun(void) +{ + if (JL_WAKEUP->CON3 & BIT(0)) { + JL_WAKEUP->CON2 |= BIT(0); + if (port_wkup_irq_cbfun) { + port_wkup_irq_cbfun(); + } + } +} +/** + * @brief 引脚中断初始化 + * @param port 任意引脚的引脚号:IO_PORTA_00...... + * @param trigger_edge 触发边沿。 0:上升沿触发。 1;下降沿触发 + * @param cbfun 相应的中断回调函数 + */ +void port_wkup_interrupt_init(u32 port, u8 trigger_edge, void (*cbfun)(void)) +{ + JL_WAKEUP->CON0 &= ~BIT(0); + gpio_set_die(port, 1); + gpio_set_direction(port, 1); + if (trigger_edge == 0) { + JL_WAKEUP->CON1 &= ~BIT(0); + gpio_set_pull_up(port, 0); + gpio_set_pull_down(port, 1); + } else { + JL_WAKEUP->CON1 |= BIT(0); + gpio_set_pull_up(port, 1); + gpio_set_pull_down(port, 0); + } + user_port = port; + if (cbfun) { + port_wkup_irq_cbfun = cbfun; + } + request_irq(IRQ_PORT_IDX, 3, port_wkup_irq_fun, 0); //注册中断函数 + JL_IOMAP->CON2 &= ~(0b111111 << 0); //使用inputchannel 0 + JL_IOMAP->CON2 |= (port << 0); + JL_WAKEUP->CON2 |= BIT(0); //清一次pnd + JL_WAKEUP->CON0 |= BIT(0); //引脚中断使能 +} + +/** + * @brief 关掉该引脚的中断功能 + * @param port 引脚号:IO_PORTA_00...... + */ +void port_wkup_interrupt_close(u32 port) +{ + JL_WAKEUP->CON0 &= ~BIT(0); + if (port == user_port) { + gpio_set_die(port, 0); + gpio_set_direction(port, 1); + gpio_set_pull_up(port, 0); + gpio_set_pull_down(port, 0); + } +} + +/********************************************************************************************************* + * ****************************** 使用举例如下 *************************************** + * ******************************************************************************************************/ +void port_irq_cbfun(void) +{ + printf("Hello world !\n"); +} +void my_port_wkup_test() +{ + port_wkup_interrupt_init(IO_PORTA_03, 0, port_irq_cbfun);//上升沿触发 + /* port_wkup_interrupt_init(IO_PORT_DP, 1, port_irq_cbfun);//下降沿触发 */ + while (1); +} + diff --git a/cpu/br23/pwm_led.c b/cpu/br23/pwm_led.c new file mode 100644 index 0000000..e795b37 --- /dev/null +++ b/cpu/br23/pwm_led.c @@ -0,0 +1,1581 @@ +#include "generic/gpio.h" +#include "asm/includes.h" +#include "asm/power/p33.h" +#include "asm/pwm_led.h" +#include "system/timer.h" + +/******************************************************************* +* 推灯注意事项: +* 1)PWM_CON1的BIT(4), OUT_LOGIC位一定要设置为1; +* 2)PWM_CON1的BIT(0), PWM0_INV位一定要设置为0; +* 3)在非呼吸灯效果下, 单IO双LED模式, PWM_PRD_DIV寄存器和PWM_BRI_PRD设置成相同值; +* 4)在闪灯模式下, PWM_BRI_PRD(亮度值)固定下来后, PWM0的BRI_DUTY0和BRI_DUTY1一定不能超过PWM_BRI_PRD; +*********************************************************************/ +/* #ifdef SUPPORT_MS_EXTENSIONS */ +/* #pragma bss_seg( ".pwm_led_bss") */ +/* #pragma data_seg( ".pwm_led_data") */ +/* #pragma const_seg( ".pwm_led_const") */ +/* #pragma code_seg( ".pwm_led_code") */ +/* #endif */ + +//#define PWM_LED_TEST_MODE //LED模块测试函数 + +//#define PWM_LED_DEBUG_ENABLE + +#ifdef PWM_LED_DEBUG_ENABLE +#define led_debug(fmt, ...) printf("[PWM_LED] "fmt, ##__VA_ARGS__) +#define led_err(fmt, ...) printf("[PWM_LED_ERR] "fmt, ##__VA_ARGS__) +#else +#define led_debug(...) +#define led_err(...) +#endif + +////////////////////////////////////////////////////////////// +#define PWM_LED_SFR SFR + +//========================= 0.模块开关相关寄存器 +#define LED_PWM_ENABLE (JL_PLED->CON0 |= BIT(0)) +#define LED_PWM_DISABLE (JL_PLED->CON0 &= ~BIT(0)) +#define IS_PWM_LED_ON (JL_PLED->CON0 & BIT(0)) + +#define RESET_PWM_CON0 (JL_PLED->CON0 = 0) +#define RESET_PWM_CON1 (JL_PLED->CON1 = 0) +#define RESET_PWM_CON2 (JL_PLED->CON2 = 0) +#define RESET_PWM_CON3 (JL_PLED->CON3 = 0) + +//========================= 1.时钟设置相关寄存器 +//PWM0 CLK DIV +#define CLK_DIV_1 0 +#define CLK_DIV_4 1 +#define CLK_DIV_16 2 +#define CLK_DIV_64 3 + +#define CLK_DIV_x2(x) (0x04 | x) +#define CLK_DIV_x256(x) (0x08 | x) +#define CLK_DIV_x2_x256(x) (0x0c | x) +//SOURCE +//0:rclk(250kHz) 1:btosc(24MHz) 2:osc32k(32kHz) 3:rc32k(32kHz) +#define LED_PWM0_CLK_SEL(x) PWM_LED_SFR(JL_PLED->CON0, 2, 2, x) +//SOURCE -- DIV --> PWM0 +//[1:0] 00:div1 01:div4 10:div16 11:div64 +//[2]: 0:x1 1:x2 +//[3]: 0:x1 1:x256 +//DIV = [1:0] * [2] * [3] +#define LED_PWM0_CLK_DIV(x) PWM_LED_SFR(JL_PLED->CON0, 4, 4, x) +//PWM0 -- DIV --> PWM1 +//PWM_CON3[3:0] -- PWM_PRD_DIVL[7:0] //12bit +#define LED_PWM1_CLK_DIV(x) {do {JL_PLED->PRD_DIVL = ((x-1) & 0xFF); JL_PLED->CON3 &= ~(0xF); JL_PLED->CON3 |= (((x-1) >> 8) & 0xF);} while(0);} + +//========================= 2.亮度设置相关寄存器 +//最高亮度级数设置 +//PWM_BRI_PRDH[1:0] -- PWM_BRI_PRDL[7:0] //10bit +#define LED_BRI_DUTY_CYCLE(x) {do {JL_PLED->BRI_PRDL = (x & 0xFF); JL_PLED->BRI_PRDH = ((x >> 8) & 0x3);} while(0);} +//高电平亮灯亮度设置 +#define LED_BRI_DUTY1_SET(x) {do {JL_PLED->BRI_DUTY0L = (x & 0xFF); JL_PLED->BRI_DUTY0H = ((x >> 8) & 0x3);} while(0);} +//低电平亮灯亮度设置 +#define LED_BRI_DUTY0_SET(x) {do {JL_PLED->BRI_DUTY1L = (x & 0xFF); JL_PLED->BRI_DUTY1H = ((x >> 8) & 0x3);} while(0);} +//同步LED0 <-- LED1亮度 +#define LED_BRI_DUTY0_SYNC1() {do {JL_PLED->BRI_DUTY0L = JL_PLED->BRI_DUTY1L; JL_PLED->BRI_DUTY0H = JL_PLED->BRI_DUTY1H;} while(0);} +//同步LED1 <-- LED0亮度 +#define LED_BRI_DUTY1_SYNC0() {do {JL_PLED->BRI_DUTY1L = JL_PLED->BRI_DUTY0L; JL_PLED->BRI_DUTY1H = JL_PLED->BRI_DUTY0H;} while(0);} + + +//========================= 3.亮灭设置相关寄存器 +//duty_cycle 固定为255或者设置PWM_DUTY3, 8bit +// _duty1_ _duty3_ +// | | | | +// | | | | +//0__ __ duty0| | __ duty2| |__ __255/PWM_DUTY3 + +//PWM1 duty_cycle 选择 +#define LED_PWM1_DUTY_FIX_SET (JL_PLED->CON1 &= ~BIT(3)) //固定PWM1周期为0xFF +#define LED_PWM1_DUTY_VARY_SET(x) {do {JL_PLED->CON1 |= BIT(3); JL_PLED->DUTY3 = x;} while(0);} + +#define LED_PWM1_DUTY0_SET(x) (JL_PLED->DUTY0 = x) +#define LED_PWM1_DUTY1_SET(x) (JL_PLED->DUTY1 = x) +#define LED_PWM1_DUTY2_SET(x) (JL_PLED->DUTY2 = x) +#define LED_PWM1_DUTY3_SET(x) (JL_PLED->DUTY3 = x) //可以设置为PWM1_DUTY_CYCLE +#define LED_PWM1_PRD_SEL_DIS (JL_PLED->CON1 &= ~BIT(3)) + +#define LED_PWM1_PRD_SEL_EN (JL_PLED->CON1 |= BIT(3)) +#define LED_PWM1_DUTY0_EN (JL_PLED->CON1 |= BIT(4)) +#define LED_PWM1_DUTY1_EN (JL_PLED->CON1 |= BIT(5)) +#define LED_PWM1_DUTY2_EN (JL_PLED->CON1 |= BIT(6)) +#define LED_PWM1_DUTY3_EN (JL_PLED->CON1 |= BIT(7)) + +#define LED_PWM1_ALL_DUTY_DIS (JL_PLED->CON1 &= ~(0xF << 4)) +#define LED_PWM1_DUTY0_DIS (JL_PLED->CON1 &= ~BIT(4)) +#define LED_PWM1_DUTY1_DIS (JL_PLED->CON1 &= ~BIT(5)) +#define LED_PWM1_DUTY2_DIS (JL_PLED->CON1 &= ~BIT(6)) +#define LED_PWM1_DUTY3_DIS (JL_PLED->CON1 &= ~BIT(7)) + +//========================= 5.输出取反相关寄存器 +//以下几个需要设置为固定值 +#define LED_PWM0_INV_DISABLE (JL_PLED->CON1 &= ~BIT(0)) +#define LED_PWM1_INV_DISABLE (JL_PLED->CON1 &= ~BIT(1)) //周期从灭灯开始 +#define LED_PWM1_INV_ENABLE (JL_PLED->CON1 |= BIT(1)) //周期从亮灯开始 +#define LED_PWM_OUT_LOGIC_SET (JL_PLED->CON3 |= BIT(4)) +//以下几个可以灵活设置 +#define LED_PWM_OUTPUT_INV_ENABLE (JL_PLED->CON1 |= BIT(2)) +#define LED_PWM_OUTPUT_INV_DISABLE (JL_PLED->CON1 &= ~BIT(2)) + +//========================= 6.与周期变色相关寄存器 +#define LED_PWM_SHIFT_DUTY_SET(x) PWM_LED_SFR(JL_PLED->CON2, 4, 4, x) + +//========================= 7.与驱动强度相关寄存器 +#define LED_PWM_IO_MAX_DRIVE(x) PWM_LED_SFR(JL_PLED->CON2, 0, 2, x) + +//========================= 8.与中断相关寄存器 +#define LED_PWM_INT_EN (JL_PLED->CON3 |= BIT(5)) +#define LED_PWM_INT_DIS (JL_PLED->CON3 &= ~BIT(5)) +#define LED_PWM_CLR_PENDING (JL_PLED->CON3 |= BIT(6)) + +//========================= 9.与呼吸模式相关寄存器 +#define LED_PWM_BREATHE_ENABLE (JL_PLED->CON0 |= BIT(1)) +#define LED_PWM_BREATHE_DISABLE (JL_PLED->CON0 &= ~BIT(1)) +//LED呼吸灭灯延时设置, 16bit +#define LED_PWM_BREATHE_BLANK_TIME_SET(x) {do {LED_PWM1_DUTY2_EN; LED_PWM1_DUTY3_EN; LED_PWM1_DUTY2_SET((x & 0xFF)); LED_PWM1_DUTY3_SET((x >> 8) & 0xFF)} while(0)} +//LED呼吸灯(低电平灯)最高亮度延时设置, 8bit +#define LED0_PWM_BREATHE_LIGHT_TIME_SET(x) {do {LED_PWM1_DUTY0_EN; LED_PWM1_DUTY0_SET(x)} while(0)} +//LED呼吸灯(高电平灯)最高亮度延时设置, 8bit +#define LED1_PWM_BREATHE_LIGHT_TIME_SET(x) {do {LED_PWM1_DUTY1_EN; LED_PWM1_DUTY1_SET(x)} while(0)} + +struct pwm_led { + u8 init; + u8 led_pin; + u8 clock; + u8 last_mode; + const struct led_platform_data *user_data; + //中断相关 + void (*pwm_led_extern_isr)(void); + void (*pwm_led_local_isr)(void); +#ifdef PWM_LED_TWO_IO_SUPPORT + u8 display_index; +#endif /* #ifdef PWM_LED_TWO_IO_SUPPORT */ +}; + +typedef struct { + pwm_led_on_para on; + pwm_led_one_flash_para one_flash; + pwm_led_double_flash_para double_flash; + pwm_led_breathe_para breathe; +} pwm_led_para_t; +static pwm_led_para_t led_para; + +enum _PWM0_CLK { + PWM0_CLK_32K, //for rc normal + //BT24M + PWM0_CLK_46K, //24M / 512 = 46875, for normal period < 22s + PWM0_CLK_23K, //24M / 1024 = 23437, for normal period > 22s +}; + +#define PWM0_RC_CLK32K_VALUE 32000 +#define PWM0_BT_CLK23K_VALUE 23437 +#define PWM0_BT_CLK46K_VALUE 46875 + +#define PWM_LED_USER_DEFINE_MODE 0xFE + +static struct pwm_led _led; + +#define __this (&_led) + +#define P3_CLK_CON0 0xa6 +extern void p33_tx_1byte(u16 addr, u8 data0); +extern u8 p33_rx_1byte(u16 addr); +static void _pwm_led_display_mode(u8 display); +static void _led_pwm1_duty_set(u8 duty_prd, u8 duty0, u8 duty1, u8 duty2, u8 breathe); + +static void pwm_clock_set(u8 _clock) +{ + u8 clock = _clock; + u8 clk_val = 0; + + switch (clock) { + case PWM_LED_CLK_RC32K: + clk_val = 1; + break; + case PWM_LED_CLK_BTOSC_24M: + clk_val = 2; + break; + default: + break; + } + + P33_CON_SET(P3_CLK_CON0, 0, 2, clk_val); + /* p33_tx_1byte(P3_CLK_CON0, clk_val); */ + __this->clock = clock; + led_debug("clock = 0x%x, clk_val= %d, P3_CLK_CON0 = 0x%x", __this->clock, clk_val, p33_rx_1byte(P3_CLK_CON0)); +} + + +/* + * IO使能注意, 否则有可能会出现在显示效果前会出现闪烁 + * 1)设置PU, PD为1; + * 2)设置DIR, OUT为1; + * 3)最后设置为方向为输出; + */ +static void led_pin_set_enable(u8 gpio) +{ + gpio_set_pull_up(gpio, 1); + gpio_set_pull_down(gpio, 1); + gpio_set_die(gpio, 1); + + gpio_set_output_value(gpio, 1); + gpio_set_direction(gpio, 0); +} + +//把IO设置为高阻 +static void led_pin_set_disable(u8 disable_pin) +{ + gpio_set_pull_down(disable_pin, 0); + gpio_set_pull_up(disable_pin, 0); + gpio_direction_input(disable_pin); +} + + +___interrupt +static void pwm_led_isr_func(void) +{ + LED_PWM_CLR_PENDING; + led_debug("led isr"); + if (__this->pwm_led_extern_isr) { + __this->pwm_led_extern_isr(); + } + if (__this->pwm_led_local_isr) { + __this->pwm_led_local_isr(); + } +} + +//index = 0: 内部切IO中断; +//index = 1: 外部注册中断; +static void _pwm_led_register_irq(void (*func)(void), u8 index) +{ + LED_PWM_INT_DIS; + LED_PWM_CLR_PENDING; + + if (func) { + if (index) { + __this->pwm_led_local_isr = func; + } else { + __this->pwm_led_extern_isr = func; + } + request_irq(IRQ_PWM_LED_IDX, 1, pwm_led_isr_func, 0); + LED_PWM_INT_EN; + } +} + + +static void _pwm_led_close_irq(void) +{ + __this->pwm_led_extern_isr = NULL; + __this->pwm_led_local_isr = NULL; + LED_PWM_INT_DIS; +} +extern const struct low_power_param power_param; +void pwm_led_init(const struct led_platform_data *user_data) +{ + led_debug("pwm led init ..."); + + memset(__this, 0, sizeof(struct pwm_led)); + + LED_PWM_DISABLE; + LED_PWM_BREATHE_DISABLE; //呼吸灯使能位 + + RESET_PWM_CON0; + RESET_PWM_CON1; + RESET_PWM_CON2; + RESET_PWM_CON3; + + LED_PWM_OUT_LOGIC_SET; + LED_PWM_CLR_PENDING; + + if (power_param.config == SLEEP_EN && power_param.osc_type == OSC_TYPE_LRC) { + pwm_clock_set(PWM_LED_CLK_RC32K); + } else { + pwm_clock_set(PWM_LED_CLK_BTOSC_24M); + } + + if (user_data->io_mode == LED_ONE_IO_MODE) { + __this->led_pin = user_data->io_cfg.one_io.pin; + led_pin_set_enable(user_data->io_cfg.one_io.pin); //一个IO推两个灯 + } + + __this->user_data = user_data; + __this->last_mode = PWM_LED_ALL_OFF; + + __this->init = 1; +} + +//prd: 亮度总级数 +//duty: 设置亮度级数 +//实际输出频率 = Flrc / prd +//输出占空比: duty /prd +//gpio: 设置输出的IO +//注意:duty不能大于prd,并且prd和duty是非标准非线性的,建议用示波器看着来调 +int pwm_led_output_clk(u8 gpio, u8 prd, u8 duty) +{ + RESET_PWM_CON0; + RESET_PWM_CON1; + RESET_PWM_CON2; + RESET_PWM_CON3; + + if (power_param.config == SLEEP_EN && power_param.osc_type == OSC_TYPE_LRC) { + g_printf(">>>PWM_LED_CLK_RC32K"); + pwm_clock_set(PWM_LED_CLK_RC32K); + LED_PWM0_CLK_DIV(0); + } else { + pwm_clock_set(PWM_LED_CLK_BTOSC_24M); + g_printf(">>>PWM_LED_CLK_BTOSC_24M"); + LED_PWM0_CLK_DIV(CLK_DIV_x2_x256(CLK_DIV_1)); + } + + duty = duty > prd ? prd : duty; + + LED_BRI_DUTY_CYCLE(prd); + LED_BRI_DUTY1_SET(duty); + LED_BRI_DUTY0_SET(duty); + + LED_PWM1_INV_ENABLE; + + /* LED_PWM1_DUTY0_SET(1); */ + /* LED_PWM1_DUTY0_EN; */ + + LED_PWM_OUT_LOGIC_SET; + + LED_PWM1_CLK_DIV(200); + led_pin_set_enable(gpio); + LED_PWM_ENABLE; + + return 0; +} + +void log_pwm_led_info() +{ + led_debug("======== PWM LED CONFIG ======"); + led_debug("P3_CLK_CON0 = 0x%x", p33_rx_1byte(P3_CLK_CON0)); + led_debug("PWM_CON0 = 0x%x", JL_PLED->CON0); + led_debug("PWM_CON1 = 0x%x", JL_PLED->CON1); + led_debug("PWM_CON2 = 0x%x", JL_PLED->CON2); + led_debug("PWM_CON3 = 0x%x", JL_PLED->CON3); + led_debug("PRD_DIVL = 0x%x", JL_PLED->PRD_DIVL); + + led_debug("BRI_PRDL = 0x%x", JL_PLED->BRI_PRDL); + led_debug("BRI_PRDH = 0x%x", JL_PLED->BRI_PRDH); + + led_debug("BRI_DUTY0L = 0x%x", JL_PLED->BRI_DUTY0L); + led_debug("BRI_DUTY0H = 0x%x", JL_PLED->BRI_DUTY0H); + + led_debug("BRI_DUTY1L = 0x%x", JL_PLED->BRI_DUTY1L); + led_debug("BRI_DUTY1H = 0x%x", JL_PLED->BRI_DUTY1H); + + led_debug("PWM1_DUTY0 = 0x%x", JL_PLED->DUTY0); + led_debug("PWM1_DUTY1 = 0x%x", JL_PLED->DUTY1); + led_debug("PWM1_DUTY2 = 0x%x", JL_PLED->DUTY2); + led_debug("PWM1_DUTY3 = 0x%x", JL_PLED->DUTY3); +} + + +/** + * @brief: pwm0 时钟设置 + * 默认RC = 32K, + * 呼吸BT24M = 93750Hz + * 普通BT24M = 46875Hz/23437Hz + * + * @param: clk0 + * @return int + */ +static int _led_pwm0_clk_set(enum _PWM0_CLK clk0) +{ + u8 pwm0_clk_div_val = 0; + + if (__this->clock == PWM_LED_CLK_RC32K) { + if (clk0 != PWM0_CLK_32K) { + return -1; + } + pwm0_clk_div_val = CLK_DIV_1; //RC32k div 1 = 32k + } else { +#if CONFIG_FPGA_ENABLE + //12M + if (clk0 == PWM0_CLK_46K) { + pwm0_clk_div_val = CLK_DIV_x256(CLK_DIV_1); //12M div 256 = 46875Hz + } else if (clk0 == PWM0_CLK_23K) { + pwm0_clk_div_val = CLK_DIV_x256(CLK_DIV_x2(CLK_DIV_1)); //12M div 512 = 23437Hz + } else { + return -1; + } +#else + if (clk0 == PWM0_CLK_46K) { + pwm0_clk_div_val = CLK_DIV_x256(CLK_DIV_x2(CLK_DIV_1)); //24M div 512 = 46875Hz + } else if (clk0 == PWM0_CLK_23K) { + pwm0_clk_div_val = CLK_DIV_x256(CLK_DIV_4); //24M div 1024 = 23437Hz + } else { + return -1; + } +#endif /* #if CONFIG_FPGA_ENABLE */ + } + + LED_PWM0_CLK_DIV(pwm0_clk_div_val); + + return 0; +} + + + +static void led_pwm_pre_set() +{ + LED_PWM_DISABLE; + LED_PWM_BREATHE_DISABLE; +} + + +#ifdef PWM_LED_TWO_IO_SUPPORT + +static void _change_io_display(void) +{ + u8 disable_pin = 0; + u8 enable_pin = 0; + if (__this->display_index == 0) { + enable_pin = __this->user_data->io_cfg.two_io.pin1; + disable_pin = __this->user_data->io_cfg.two_io.pin0; + __this->display_index = 1; + } else { + enable_pin = __this->user_data->io_cfg.two_io.pin0; + disable_pin = __this->user_data->io_cfg.two_io.pin1; + __this->display_index = 0; + } + + led_pin_set_disable(disable_pin); + led_pin_set_enable(enable_pin); +} + +static void pwm_led_two_io_mode_display(u8 display) +{ + u8 change_mode = 0; + u8 isr_mode = 0; + + led_pin_set_disable(__this->user_data->io_cfg.two_io.pin0); + led_pin_set_disable(__this->user_data->io_cfg.two_io.pin1); + + switch (display) { + case PWM_LED_ALL_OFF: + case PWM_LED0_OFF: + case PWM_LED1_OFF: + _pwm_led_display_mode(PWM_LED_ALL_OFF); + break; + + case PWM_LED1_ON: + case PWM_LED1_SLOW_FLASH: + case PWM_LED1_FAST_FLASH: + case PWM_LED1_ONE_FLASH_5S: + case PWM_LED1_DOUBLE_FLASH_5S: + case PWM_LED1_BREATHE: + led_pin_set_enable(__this->user_data->io_cfg.two_io.pin1); + _pwm_led_display_mode(display); + break; + + case PWM_LED0_ON: + change_mode = PWM_LED1_ON; + break; + case PWM_LED0_SLOW_FLASH: + change_mode = PWM_LED1_SLOW_FLASH; + break; + case PWM_LED0_FAST_FLASH: + change_mode = PWM_LED1_FAST_FLASH; + break; + case PWM_LED0_ONE_FLASH_5S: + change_mode = PWM_LED1_ONE_FLASH_5S; + break; + case PWM_LED0_DOUBLE_FLASH_5S: + change_mode = PWM_LED1_DOUBLE_FLASH_5S; + break; + case PWM_LED0_BREATHE: + change_mode = PWM_LED1_BREATHE; + break; + case PWM_LED_ALL_ON: + _pwm_led_display_mode(PWM_LED1_ON); + led_pin_set_enable(__this->user_data->io_cfg.two_io.pin0); + led_pin_set_enable(__this->user_data->io_cfg.two_io.pin1); + break; +///////////// + +//双灯互闪 + case PWM_LED0_LED1_FAST_FLASH: //使用中断切灯 + isr_mode = PWM_LED1_FAST_FLASH; + break; + case PWM_LED0_LED1_SLOW_FLASH: + isr_mode = PWM_LED1_SLOW_FLASH; + break; +//呼吸模式 + case PWM_LED0_LED1_BREATHE: //使用中断切灯 + isr_mode = PWM_LED1_BREATHE; + break; + + default: + break; + } + if (change_mode) { + _pwm_led_display_mode(change_mode); + LED_PWM_DISABLE; + LED_BRI_DUTY1_SYNC0(); + led_pin_set_enable(__this->user_data->io_cfg.two_io.pin0); + LED_PWM_ENABLE; + } + if (isr_mode) { + _pwm_led_display_mode(isr_mode); + _led_pwm1_duty_set(0xFF, 2, 0, 0, 0); //占满整个周期 + _pwm_led_register_irq(_change_io_display, 0); + led_pin_set_enable(__this->user_data->io_cfg.two_io.pin0); + __this->display_index = 0; + } +} + +static void _pwm_led_two_io_user_define_mode(u8 led_index) +{ + led_pwm_pre_set(); //led disable + led_pin_set_disable(__this->user_data->io_cfg.two_io.pin0); + led_pin_set_disable(__this->user_data->io_cfg.two_io.pin1); + + if (led_index == 0) { + led_pin_set_enable(__this->user_data->io_cfg.two_io.pin0); + } else if (led_index == 1) { + led_pin_set_enable(__this->user_data->io_cfg.two_io.pin1); + } else if (led_index == 2) { + //双灯互闪切换 + __this->display_index = 0; + led_pin_set_enable(__this->user_data->io_cfg.two_io.pin0); + _pwm_led_register_irq(_change_io_display, 0); + } +} + + +#else +static void pwm_led_two_io_mode_display(u8 display) +{ + return; +} +#endif /* #ifdef PWM_LED_TWO_IO_SUPPORT */ + +static void pwm_led_one_io_mode_display(u8 display) +{ + _pwm_led_display_mode(display); +} + +///////////////////////////// +/** + * @brief: 设置led灯亮度 + * @param: bri_max, 最大亮度, 10bit, 0 ~ 1023 + * @param: bri_duty0, LED0亮度, 10bit, 0 ~ 1023 + * @param: bri_duty1, LED1亮度, 10bit, 0 ~ 1023 + * + * @return void + */ +static void _led_pwm_bright_set(u16 bri_max, u16 bri_duty0, u16 bri_duty1) +{ + bri_max = bri_max >= 1024 ? 1023 : bri_max; + bri_duty0 = bri_duty0 >= 1024 ? 1023 : bri_duty0; + bri_duty1 = bri_duty1 >= 1024 ? 1023 : bri_duty1; + + bri_duty0 = bri_duty0 >= bri_max ? bri_max : bri_duty0; + bri_duty1 = bri_duty1 >= bri_max ? bri_max : bri_duty1; + + LED_BRI_DUTY_CYCLE(bri_max); + LED_BRI_DUTY0_SET(bri_duty0); + LED_BRI_DUTY1_SET(bri_duty1); +} + + +/** + * @brief: 设置PWM输出逻辑, + * @param: pwm_inv_en, 最后pwm波形输出逻辑(默认是高电平灯亮), + 0: 不取反, 高电平灯亮; 1: 取反, 低电平灯亮; + * @param: shift_num + 是否需要互闪, + 0: 单闪; 1 ~ : 互闪; + * + * @return void + */ +static void _led_pwm_output_logic_set(u8 pwm_inv_en, u8 shift_num) +{ + if (pwm_inv_en) { + LED_PWM_OUTPUT_INV_ENABLE; + } else { + LED_PWM_OUTPUT_INV_DISABLE; + } + LED_PWM_OUT_LOGIC_SET; + LED_PWM_SHIFT_DUTY_SET(shift_num); +} + +/** + * @brief: 设置PWM1亮灭设置, 可以实现一个周期亮灭1次和2次, + * @param: pwm_inv_en, 最后pwm波形输出逻辑(默认是高电平灯亮), + 0: 不取反, 高电平灯亮; 1: 取反, 低电平灯亮; + * @param: shift_num + 是否需要互闪, + 0: 单闪; 1 ~ : 互闪; + *duty_cycle 固定为255或者设置PWM_DUTY3, 8bit + * _duty1_ _duty3_ + * | | | | + * | | | | + *0__ __ duty0| | __ duty2| |__ __255/PWM_DUTY3 + * @return void + */ +static void _led_pwm1_duty_set(u8 duty_prd, u8 duty0, u8 duty1, u8 duty2, u8 breathe) +{ + if (duty_prd != 0xFF) { + if (breathe == 0) { + duty0 = duty0 > duty_prd ? duty_prd : duty0; + duty1 = duty1 > duty_prd ? duty_prd : duty1; + duty2 = duty2 > duty_prd ? duty_prd : duty2; + LED_PWM1_PRD_SEL_EN; + LED_PWM1_DUTY3_DIS; + } else { + LED_PWM1_PRD_SEL_DIS; //呼吸模式, duty0/1是亮灯延时, {duty3,duty2}是灭灯延时 + LED_PWM1_DUTY3_EN; + } + + LED_PWM1_DUTY3_SET(duty_prd); + } else { + LED_PWM1_PRD_SEL_DIS; + LED_PWM1_DUTY3_DIS; + } + if (duty0) { + LED_PWM1_DUTY0_SET(duty0); + LED_PWM1_DUTY0_EN; + } else { + LED_PWM1_DUTY0_DIS; + } + if (duty1) { + LED_PWM1_DUTY1_SET(duty1); + LED_PWM1_DUTY1_EN; + } else { + LED_PWM1_DUTY1_DIS; + } + if (duty2) { + LED_PWM1_DUTY2_SET(duty2); + LED_PWM1_DUTY2_EN; + } else { + LED_PWM1_DUTY2_DIS; + } +} + + +/** + * @brief: + * @param: module_en = 0, breathe_en = 0, 关LED模块 + * @param: module_en = 0, breathe_en = 1, 关LED模块 + * @param: module_en = 1, breathe_en = 0, 开LED普通闪烁模式 + * @param: module_en = 1, breathe_en = 1, 开LED呼吸模式 + * @return void + */ +static void _led_pwm_module_enable(u8 module_en, u8 breathe_en) +{ + if (breathe_en) { + LED_PWM_BREATHE_ENABLE; + } else { + LED_PWM_BREATHE_DISABLE; + } + + if (module_en) { + LED_PWM_ENABLE; + } else { + LED_PWM_DISABLE; + } +} + +/** + * @brief: 设置pwm0时钟分频 + * clk0_div + * pwm0_clk --------> pwm1_clk + * @param: clk0_div, 12bit, 0 ~ 4095 + * + * @return void + */ +static void _led_pwm1_clk_set(u16 clk0_div) +{ + clk0_div = clk0_div > 4096 ? 4096 : clk0_div; + LED_PWM1_CLK_DIV(clk0_div); +} + +/** + * @brief: 关 led 配置, 亮度也设置为0 + * + * @param led_index: 0: led0, 1:led1, 3:led0 & led1 + * @param led0_bright: 0 ~ 100 + * @param led1_bright: 0 ~ 100 + * + * @return void + */ +static void _pwm_led_off_display(void) +{ + //TODO: set bright duty 0: avoid set on case + led_pwm_pre_set(); //led disable + _led_pwm_bright_set(0xFF, 0, 0); +} + + + +/** + * @brief: led 常亮显示设置 + * @param led_index: 0: led0, 1:led1, 3:led0 & led1 + * @param led0_bright, LED0亮度: 0 ~ 500 + * @param led1_bright, LED1亮度: 0 ~ 500 + * + * @return void + */ +static void _pwm_led_on_display(u8 led_index, u16 led0_bright, u16 led1_bright) +{ + //step1: pwm0 clock + if (__this->clock == PWM_LED_CLK_RC32K) { + _led_pwm0_clk_set(PWM0_CLK_32K); + } else { + _led_pwm0_clk_set(PWM0_CLK_46K); + } + //step2: pwm1 clock + _led_pwm1_clk_set(4); + + //bright set + u8 shift_num = 0; + u8 out_inv = 0; + u16 led0_bri_duty = 0; + u16 led1_bri_duty = 0; + u16 led_bri_prd = 200; + + led0_bri_duty = led0_bright; + led1_bri_duty = led1_bright; + + switch (led_index) { + case 0: + out_inv = 1; + break; + case 1: + break; + case 2: + shift_num = 1; + led_bri_prd = 160; + break; + default: + led_debug("%s led index err", __func__); + return; + break; + } + + led0_bri_duty = (led0_bri_duty * led_bri_prd) / 500; + led1_bri_duty = (led1_bri_duty * led_bri_prd) / 500; //调试数据 + + //step3: bright亮度 + _led_pwm_bright_set(led_bri_prd, led0_bri_duty, led1_bri_duty); + + //step4: 1.输出取反, 2.变色(互闪); + _led_pwm_output_logic_set(out_inv, shift_num); + + //step5: 周期亮灭配置 + //pwm1 duty0, duty1, duty2 + _led_pwm1_duty_set(40, 2, 0, 0, 0); + + //step6: enable led module + _led_pwm_module_enable(1, 0); +} + +static void __pwm_led_flash_common_handle(u8 led_index, u16 led0_bright, u16 led1_bright, u32 period) +{ +//step1: pwm0 clock + u16 pwm0_prd = 500; + u16 pwm0_div = 0; + if (__this->clock == PWM_LED_CLK_RC32K) { + _led_pwm0_clk_set(PWM0_CLK_32K); + pwm0_div = (PWM0_RC_CLK32K_VALUE * period) / (1000 * 256); + } else { + if (period < 22000) { + _led_pwm0_clk_set(PWM0_CLK_46K); + pwm0_div = (PWM0_BT_CLK46K_VALUE * period) / (1000 * 256); + } else { + _led_pwm0_clk_set(PWM0_CLK_23K); + pwm0_div = (PWM0_BT_CLK23K_VALUE * period) / (1000 * 256); + pwm0_prd = 300; + led0_bright = (led0_bright * 300) / 500; + led1_bright = (led1_bright * 300) / 500; + } + } + //step2: pwm1 clock + _led_pwm1_clk_set(pwm0_div); + + //bright set + u8 shift_num = 0; + u8 out_inv = 0; + u16 led0_bri_duty = 0; + u16 led1_bri_duty = 0; + + switch (led_index) { + case 0: + led0_bri_duty = led0_bright; + led1_bri_duty = 0; + out_inv = 1; + break; + + case 1: + led0_bri_duty = 0; + led1_bri_duty = led1_bright; + break; + case 2: + shift_num = 1; + led0_bri_duty = led0_bright; + led1_bri_duty = led1_bright; + break; + default: + led_debug("%s led index err", __func__); + return; + break; + } + + //step3: bright亮度 + _led_pwm_bright_set(pwm0_prd, led0_bri_duty, led1_bri_duty); + + //step4: 1.输出取反, 2.变色(互闪); + _led_pwm_output_logic_set(out_inv, shift_num); +} + +/** + * @brief: led 周期闪一次显示设置 + * @param led_index: 0: led0, 1:led1, 3:led0 & led1(互闪) + led0_bright: led0亮度(0 ~ 500), + led1_bright: led1亮度(0 ~ 500), + period: 闪灯周期(ms), 多少ms闪一下(100 ~ 20000), 100ms - 20S, + start_light_time: 在周期中开始亮灯的时间, -1: 周期最后亮灯, 默认填-1即可, + light_time: 灯亮持续时间, + * + * @return void + */ +static void _pwm_led_one_flash_display(u8 led_index, u16 led0_bright, u16 led1_bright, + u32 period, u32 start_light_time, u32 light_time) +{ + __pwm_led_flash_common_handle(led_index, led0_bright, led1_bright, period); + //step5: 周期亮灭配置 + //pwm1 duty0, duty1, duty2 + u8 pwm1_duty0 = 0; + u8 pwm1_duty1 = 0; + if (start_light_time != -1) { + if (start_light_time >= period) { + led_err("start_light_time config err"); + _pwm_led_off_display(); //led off + return; + } + //指定从哪个时间亮, + pwm1_duty0 = (256 * start_light_time) / period; + pwm1_duty0 = (pwm1_duty0) ? pwm1_duty0 : 2; + if ((start_light_time + light_time) > period) { + pwm1_duty1 = 0; //只开duty0 + } else { + pwm1_duty1 = (256 * light_time) / period; + pwm1_duty1 = (pwm1_duty1) ? pwm1_duty1 : 2; + if ((pwm1_duty0 + pwm1_duty1) > 0xFF) { + pwm1_duty1 = 0 ; + } else { + pwm1_duty1 += pwm1_duty0; + } + } + } else { + pwm1_duty0 = (256 * light_time) / period; + pwm1_duty0 = (pwm1_duty0) ? pwm1_duty0 : 2; + pwm1_duty0 = 256 - pwm1_duty0; + } + + if ((led_index == 2) && (light_time == -1)) { //互闪, 占满整个周期 + pwm1_duty0 = 2; + pwm1_duty1 = 0; + } + _led_pwm1_duty_set(0xFF, pwm1_duty0, pwm1_duty1, 0, 0); + + //step6: enable led module + _led_pwm_module_enable(1, 0); +} + + +/** + * @brief: led 周期闪一次显示设置 + * @param led_index: 0: led0, 1:led1, 3:led0 & led1(互闪) + led0_bright: led0亮度, + led1_bright: led1亮度, + period: 闪灯周期(ms), 多少ms闪一下 + first_light_time: 第一次亮灯持续时间, + second_light_time: 第二次亮灯持续时间, + gap_time: 两次亮灯时间间隔, + * @param led0_bright, LED0亮度: 0 ~ 500 + * @param led1_bright, LED1亮度: 0 ~ 500 + * + * @return void + */ +static void _pwm_led_double_flash_display(u8 led_index, u16 led0_bright, u16 led1_bright, + u32 period, u32 first_light_time, u32 gap_time, u32 second_light_time) +{ + __pwm_led_flash_common_handle(led_index, led0_bright, led1_bright, period); + + //step5: 周期亮灭配置 + //pwm1 duty0, duty1, duty2 + u8 pwm1_duty0 = 0; + u8 pwm1_duty1 = 0; + u8 pwm1_duty2 = 0; + + pwm1_duty2 = (256 * second_light_time) / period; + pwm1_duty2 = (pwm1_duty2) ? (0xFF - pwm1_duty2) : (0xFF - 2); + + pwm1_duty1 = (256 * gap_time) / period; + pwm1_duty1 = (pwm1_duty1) ? (pwm1_duty2 - pwm1_duty1) : (pwm1_duty2 - 2); + + pwm1_duty0 = (256 * first_light_time) / period; + pwm1_duty0 = (pwm1_duty0) ? (pwm1_duty1 - pwm1_duty0) : (pwm1_duty1 - 2); + + _led_pwm1_duty_set(0xFF, pwm1_duty0, pwm1_duty1, pwm1_duty2, 0); + + //step6: enable led module + _led_pwm_module_enable(1, 0); +} + +/** + * @brief: led 周期呼吸显示, + * @param led_index: 0: led0, 1:led1, 2:led0 & led1(交互呼吸) + breathe_time: 呼吸周期(灭->最亮->灭), 设置范围: 500ms以上; + led0_bright: led0呼吸到最亮的亮度(0 ~ 500); + led1_bright: led1呼吸到最亮的亮度(0 ~ 500); + led0_light_delay_time: led0最高亮度延时(0 ~ 100ms); + led1_light_delay_time: led1最高亮度延时(0 ~ 100ms); + led_blink_delay_time: led0和led1灭灯延时(0 ~ 20000ms), 0 ~ 20S; + * + * @return void + */ +static void _pwm_led_breathe_display(u8 led_index, u16 breathe_time, u16 led0_bright, u16 led1_bright, + u32 led0_light_delay_time, u32 led1_light_delay_time, u32 led_blink_delay_time) +{ + u16 led0_bri_duty = led0_bright; + u16 led1_bri_duty = led1_bright; + u16 pwm1_div = 0; + u16 Tpwm1 = 0; + pwm1_div = led0_bri_duty > led1_bri_duty ? led0_bri_duty : led1_bri_duty; + + breathe_time = breathe_time / 2; //呼吸总时间, 单个灭到最亮的时间 + //step1: pwm0 clock + if (__this->clock == PWM_LED_CLK_RC32K) { + _led_pwm0_clk_set(PWM0_CLK_32K); + pwm1_div = breathe_time * 32 / pwm1_div; + Tpwm1 = (pwm1_div * 1000 / 32000); //ms + } else { + _led_pwm0_clk_set(PWM0_CLK_46K); + pwm1_div = breathe_time * 46 / pwm1_div; + Tpwm1 = (pwm1_div * 1000 / 46000); //ms + } + //step2: pwm1 clock + _led_pwm1_clk_set(pwm1_div); + + //bright set + u8 shift_num = 0; + u8 out_inv = 0; + + switch (led_index) { + case 0: + led1_bri_duty = 0; + out_inv = 1; + break; + + case 1: + led0_bri_duty = 0; + break; + case 2: + shift_num = 2; + break; + default: + led_debug("%s led index err", __func__); + return; + } + + //step3: bright亮度 + _led_pwm_bright_set(500, led0_bri_duty, led1_bri_duty); + + //step4: 1.输出取反, 2.变色(互闪); + _led_pwm_output_logic_set(out_inv, shift_num); + + //step5: 周期亮灭配置 + //pwm1 duty0, duty1, duty2 + u8 pwm1_duty0 = 0; + u8 pwm1_duty1 = 0; + u8 pwm1_duty2 = 0; + u8 pwm1_duty3 = 0xFF; + + if (Tpwm1 == 0) { + led0_light_delay_time *= 2; + led1_light_delay_time *= 2; + led_blink_delay_time *= 2; + Tpwm1 = 1; + } + + //最高亮度延时 + pwm1_duty0 = led0_light_delay_time / Tpwm1; + pwm1_duty1 = led1_light_delay_time / Tpwm1; + //灭灯延时,{duty3, duty2}, 16bit + pwm1_duty2 = (led_blink_delay_time / Tpwm1) & 0xFF; + pwm1_duty3 = ((led_blink_delay_time / Tpwm1) >> 8) & 0xFF; + + _led_pwm1_duty_set(pwm1_duty3, pwm1_duty0, pwm1_duty1, pwm1_duty2, 1); + + //step6: enable led module + _led_pwm_module_enable(1, 1); +} + +static void _pwm_led_display_mode(u8 display) +{ + led_pwm_pre_set(); + + switch (display) { + +#if PWM_LED_NEW_FORMAT_EN + case PWM_LED_ALL_OFF: + case PWM_LED0_OFF: + case PWM_LED1_OFF: + _pwm_led_off_display(); + break; +//灯常亮 + case PWM_LED0_ON: + printf("led0 on:%d %d \n", led_para.on.led0_bright, led_para.on.led1_bright); + _pwm_led_on_display(0, led_para.on.led0_bright, led_para.on.led1_bright); + break; + case PWM_LED1_ON: + printf("led1 on:%d %d \n", led_para.on.led0_bright, led_para.on.led1_bright); + _pwm_led_on_display(1, led_para.on.led0_bright, led_para.on.led1_bright); + break; + case PWM_LED_ALL_ON: + printf("led0_led1 on:%d %d \n", led_para.on.led0_bright, led_para.on.led1_bright); + _pwm_led_on_display(2, led_para.on.led0_bright, led_para.on.led1_bright); + break; + +//单灯单闪 + case PWM_LED0_SLOW_FLASH: + printf("led0 slow:%d %d %d %d %d \n", led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + _pwm_led_one_flash_display(0, \ + led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + break; + case PWM_LED1_SLOW_FLASH: + printf("led1 slow:%d %d %d %d %d \n", led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + _pwm_led_one_flash_display(1, \ + led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + + break; + case PWM_LED0_FAST_FLASH: + printf("led0 fast:%d %d %d %d %d \n", led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + _pwm_led_one_flash_display(0, \ + led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + + break; + case PWM_LED1_FAST_FLASH: + printf("led1 fast:%d %d %d %d %d \n", led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + _pwm_led_one_flash_display(1, \ + led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + + break; + case PWM_LED0_ONE_FLASH_5S: + printf("led0 one 5s:%d %d %d %d %d \n", led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + _pwm_led_one_flash_display(0, \ + led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + break; + case PWM_LED1_ONE_FLASH_5S: + printf("led1 one 5s:%d %d %d %d %d \n", led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + _pwm_led_one_flash_display(1, \ + led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + break; +//双灯互闪 + case PWM_LED0_LED1_FAST_FLASH: + printf("led0_led1 fast flash:%d %d %d %d %d \n", led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + _pwm_led_one_flash_display(2, \ + led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + break; + case PWM_LED0_LED1_SLOW_FLASH: + printf("led0_led1 slow flash:%d %d %d %d %d \n", led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + _pwm_led_one_flash_display(2, \ + led_para.one_flash.led0_bright, led_para.one_flash.led1_bright, \ + led_para.one_flash.period, led_para.one_flash.start_light_time, \ + led_para.one_flash.light_time); + break; + +//单灯双闪 + case PWM_LED0_DOUBLE_FLASH_5S: + printf("led0 double 5s:%d %d %d %d %d %d \n", led_para.double_flash.led0_bright, led_para.double_flash.led1_bright, \ + led_para.double_flash.period, led_para.double_flash.first_light_time, \ + led_para.double_flash.gap_time, led_para.double_flash.second_light_time); + _pwm_led_double_flash_display(2, \ + led_para.double_flash.led0_bright, led_para.double_flash.led1_bright, \ + led_para.double_flash.period, led_para.double_flash.first_light_time, \ + led_para.double_flash.gap_time, led_para.double_flash.second_light_time); + break; + case PWM_LED1_DOUBLE_FLASH_5S: + printf("led1 double 5s:%d %d %d %d %d %d \n", led_para.double_flash.led0_bright, led_para.double_flash.led1_bright, \ + led_para.double_flash.period, led_para.double_flash.first_light_time, \ + led_para.double_flash.gap_time, led_para.double_flash.second_light_time); + _pwm_led_double_flash_display(2, \ + led_para.double_flash.led0_bright, led_para.double_flash.led1_bright, \ + led_para.double_flash.period, led_para.double_flash.first_light_time, \ + led_para.double_flash.gap_time, led_para.double_flash.second_light_time); + break; + +//呼吸模式 + case PWM_LED0_BREATHE: + printf("led0 breathe:%d %d %d %d %d %d \n", led_para.breathe.breathe_time, led_para.breathe.led0_bright, \ + led_para.breathe.led1_bright, led_para.breathe.led0_light_delay_time, \ + led_para.breathe.led1_light_delay_time, led_para.breathe.led_blink_delay_time); + _pwm_led_breathe_display(0, \ + led_para.breathe.breathe_time, led_para.breathe.led0_bright, \ + led_para.breathe.led1_bright, led_para.breathe.led0_light_delay_time, \ + led_para.breathe.led1_light_delay_time, led_para.breathe.led_blink_delay_time); + break; + case PWM_LED1_BREATHE: + printf("led1 breathe:%d %d %d %d %d %d \n", led_para.breathe.breathe_time, led_para.breathe.led0_bright, \ + led_para.breathe.led1_bright, led_para.breathe.led0_light_delay_time, \ + led_para.breathe.led1_light_delay_time, led_para.breathe.led_blink_delay_time); + _pwm_led_breathe_display(1, \ + led_para.breathe.breathe_time, led_para.breathe.led0_bright, \ + led_para.breathe.led1_bright, led_para.breathe.led0_light_delay_time, \ + led_para.breathe.led1_light_delay_time, led_para.breathe.led_blink_delay_time); + break; + case PWM_LED0_LED1_BREATHE: + printf("led0_led1 breathe:%d %d %d %d %d %d \n", led_para.breathe.breathe_time, led_para.breathe.led0_bright, \ + led_para.breathe.led1_bright, led_para.breathe.led0_light_delay_time, \ + led_para.breathe.led1_light_delay_time, led_para.breathe.led_blink_delay_time); + _pwm_led_breathe_display(2, \ + led_para.breathe.breathe_time, led_para.breathe.led0_bright, \ + led_para.breathe.led1_bright, led_para.breathe.led0_light_delay_time, \ + led_para.breathe.led1_light_delay_time, led_para.breathe.led_blink_delay_time); + break; + +#else + case PWM_LED_ALL_OFF: + case PWM_LED0_OFF: + case PWM_LED1_OFF: + _pwm_led_off_display(); + break; +//灯常亮 + case PWM_LED0_ON: + _pwm_led_on_display(0, CFG_LED0_LIGHT, CFG_LED1_LIGHT); + break; + case PWM_LED1_ON: + _pwm_led_on_display(1, CFG_LED0_LIGHT, CFG_LED1_LIGHT); + break; + + case PWM_LED_ALL_ON: + _pwm_led_on_display(2, CFG_LED0_LIGHT, CFG_LED1_LIGHT); + break; +//单灯单闪 + case PWM_LED0_SLOW_FLASH: + _pwm_led_one_flash_display(0, CFG_LED0_LIGHT, CFG_LED1_LIGHT, CFG_SINGLE_SLOW_FLASH_FREQ, -1, CFG_SINGLE_SLOW_LIGHT_TIME); + break; + case PWM_LED1_SLOW_FLASH: + _pwm_led_one_flash_display(1, CFG_LED0_LIGHT, CFG_LED1_LIGHT, CFG_SINGLE_SLOW_FLASH_FREQ, -1, CFG_SINGLE_SLOW_LIGHT_TIME); + break; + case PWM_LED0_FAST_FLASH: + _pwm_led_one_flash_display(0, CFG_LED0_LIGHT, CFG_LED1_LIGHT, CFG_SINGLE_FAST_FLASH_FREQ, -1, CFG_SINGLE_FAST_LIGHT_TIME); + break; + case PWM_LED1_FAST_FLASH: + _pwm_led_one_flash_display(1, CFG_LED0_LIGHT, CFG_LED1_LIGHT, CFG_SINGLE_FAST_FLASH_FREQ, -1, CFG_SINGLE_FAST_LIGHT_TIME); + break; + case PWM_LED0_ONE_FLASH_5S: + _pwm_led_one_flash_display(0, CFG_LED0_LIGHT, CFG_LED1_LIGHT, 5000, 10, CFG_LED_5S_FLASH_LIGHT_TIME); + break; + case PWM_LED1_ONE_FLASH_5S: + _pwm_led_one_flash_display(1, CFG_LED0_LIGHT, CFG_LED1_LIGHT, 5000, 10, CFG_LED_5S_FLASH_LIGHT_TIME); + break; +//单灯双闪 + case PWM_LED0_DOUBLE_FLASH_5S: + _pwm_led_double_flash_display(0, CFG_LED0_LIGHT, CFG_LED1_LIGHT, 5000, 100, 200, 100); + break; + case PWM_LED1_DOUBLE_FLASH_5S: + _pwm_led_double_flash_display(1, CFG_LED0_LIGHT, CFG_LED1_LIGHT, 5000, 100, 200, 100); + break; + +//双灯互闪 + case PWM_LED0_LED1_FAST_FLASH: + _pwm_led_one_flash_display(2, CFG_LED0_LIGHT, CFG_LED1_LIGHT, CFG_DOUBLE_FAST_FLASH_FREQ, -1, -1); + break; + case PWM_LED0_LED1_SLOW_FLASH: + _pwm_led_one_flash_display(2, CFG_LED0_LIGHT, CFG_LED1_LIGHT, CFG_DOUBLE_SLOW_FLASH_FREQ, -1, -1); + break; + +//呼吸模式 + case PWM_LED0_BREATHE: + _pwm_led_breathe_display(0, CFG_LED_BREATH_TIME, CFG_LED0_BREATH_BRIGHT, CFG_LED1_BREATH_BRIGHT, 0, 0, CFG_LED_BREATH_BLINK_TIME); + break; + case PWM_LED1_BREATHE: + _pwm_led_breathe_display(1, CFG_LED_BREATH_TIME, CFG_LED0_BREATH_BRIGHT, CFG_LED1_BREATH_BRIGHT, 0, 0, CFG_LED_BREATH_BLINK_TIME); + break; + case PWM_LED0_LED1_BREATHE: + _pwm_led_breathe_display(2, CFG_LED_BREATH_TIME, CFG_LED0_BREATH_BRIGHT, CFG_LED1_BREATH_BRIGHT, 0, 0, CFG_LED_BREATH_BLINK_TIME); + break; +#endif + } +} + +static void _pwm_led_user_define_mode_handle(u8 dis_mode) +{ + return; +} + +//=================================================================================// +// 以下为 LED API // +//=================================================================================// + + +//=================================================================================// +//@brief: LED模式显示模式设置 +//@input: display, 显示模式 +//@return: void +//@note: +//=================================================================================// +void pwm_led_mode_set(u8 display) +{ + if (__this->init == 0) { + led_debug("led no init"); + return; + } + + led_debug("Mode %d Display", display); + + if (display == PWM_LED_NULL) { + return; + } + + if (((display >= PWM_LED_USER_DEFINE_BEGIN) && (display <= PWM_LED_USER_DEFINE_END))) { + //用户自定义模式 + if (display != __this->last_mode) { + _pwm_led_user_define_mode_handle(display); + } + return; + } + + if ((display >= PWM_LED_MODE_END)/* || (display == __this->last_mode)*/) { + return; + } + + if ((display == PWM_LED_ALL_OFF) || (display == PWM_LED0_OFF) || (display == PWM_LED1_OFF)) { + led_pwm_pre_set(); //关LED + __this->last_mode = display; + return; + } + + _pwm_led_close_irq(); + + if (__this->user_data->io_mode == LED_TWO_IO_MODE) { + pwm_led_two_io_mode_display(display); + } else { + pwm_led_one_io_mode_display(display); + } + __this->last_mode = display; + log_pwm_led_info(); +} + +//=================================================================================// +//@brief: LED模块时钟源选择 +//@input: src, 时钟源BT24M/RC32K +//@return: void +//@note: +//=================================================================================// +void pwm_led_clk_set(enum pwm_led_clk_source src) +{ + u8 mode_bak; + + if (src == __this->clock) { + return; + } + + if (src != PWM_LED_CLK_RC32K && src != PWM_LED_CLK_BTOSC_24M) { + return; + } + + mode_bak = __this->last_mode; + pwm_led_mode_set(PWM_LED_ALL_OFF); + pwm_clock_set(src); + pwm_led_mode_set(mode_bak); +} + +//=================================================================================// +//@brief: LED显示周期复位, 重新开始一个周期, 可用于同步等操作 +//@input: void +//@return: void +//@note: +//=================================================================================// +void pwm_led_display_mode_reset(void) +{ + /* u8 last_mode; */ + /* last_mode = __this->last_mode; */ + /* pwm_led_mode_set(PWM_LED_ALL_OFF); */ + /* pwm_led_mode_set(last_mode); */ + LED_PWM_DISABLE; + LED_PWM_ENABLE; +} + +//=================================================================================// +//@brief: 获取LED当前显示模式 +//@input: void +//@return: 当前LED显示模式 +//@note: +//=================================================================================// +enum pwm_led_mode pwm_led_display_mode_get(void) +{ + return __this->last_mode; +} + +//=================================================================================// +//@brief: 修改LED灯IO口驱动能力, +//@input: void +//@return: 当前LED显示模式 +//@note: +//挡位: 0 ~ 3 +// 0: 2.4mA(8mA mos + 120Ωres) +// 1: 8mA(8mA mos) +// 2: 18.4mA(24mA mos + 120Ωres) +// 3: 24mA(24mA mos) +//=================================================================================// +void pwm_led_io_max_drive_set(u8 strength) +{ + LED_PWM_IO_MAX_DRIVE(strength); +} + +//=================================================================================// +//@brief: 获取LED模块是否开启, 可用于sniff灯同步 +//@input: void +//@return: 0: 模块开启; 1: 模块关闭 +//@note: +//=================================================================================// +u8 is_pwm_led_on(void) +{ + return IS_PWM_LED_ON; +} + +//=================================================================================// +//@brief: 获取LED模块开启, 可用于sniff灯同步 +//@input: void +//@return: void +//@note: +//=================================================================================// +void pwm_led_set_on(void) +{ + LED_PWM_ENABLE; +} + +//=================================================================================// +//@brief: 获取LED模块关闭, 可用于sniff灯同步 +//@input: void +//@return: void +//@note: +//=================================================================================// +void pwm_led_set_off(void) +{ + LED_PWM_DISABLE; +} + +//=================================================================================// +//@brief: 自定义设置单灯闪状态 +//@input: void +// led_index: 0: led0, 1:led1, 2:led0 & led1(互闪) +// led0_bright: led0亮度(0 ~ 500), +// led1_bright: led1亮度(0 ~ 500), +// period: 闪灯周期(ms), 多少ms闪一下, +// start_light_time: 在周期中开始亮灯的时间, -1: 周期最后亮灯, 默认填-1即可, +// light_time: 灯亮持续时间(ms), +//@return: void +//@note: +//=================================================================================// +void pwm_led_one_flash_display(u8 led_index, u16 led0_bright, u16 led1_bright, + u32 period, u32 start_light_time, u32 light_time) +{ + _pwm_led_close_irq(); + //两个IO特殊处理 + if (__this->user_data->io_mode == LED_TWO_IO_MODE) { +#ifdef PWM_LED_TWO_IO_SUPPORT + _pwm_led_two_io_user_define_mode(led_index); + if (led_index == 0) { + led_index = 1; + led1_bright = led0_bright; + } +#endif /* #ifdef PWM_LED_TWO_IO_SUPPORT */ + } + _pwm_led_one_flash_display(led_index, led0_bright, led1_bright, + period, start_light_time, light_time); + __this->last_mode = PWM_LED_USER_DEFINE_MODE; +} + + +//=================================================================================// +//@brief: 自定义设置单灯双闪状态 +//@input: +// led_index: 0: led0, 1:led1, 3:led0 & led1(互闪) +// led0_bright: led0亮度, +// led1_bright: led1亮度, +// period: 闪灯周期(ms), 多少ms闪一下 +// first_light_time: 第一次亮灯持续时间, +// second_light_time: 第二次亮灯持续时间, +// gap_time: 两次亮灯时间间隔, +// led0_bright, LED0亮度: 0 ~ 500 +// led1_bright, LED1亮度: 0 ~ 500 +//@return: void +//@note: +//=================================================================================// +void pwm_led_double_flash_display(u8 led_index, u16 led0_bright, u16 led1_bright, + u32 period, u32 first_light_time, u32 gap_time, u32 second_light_time) +{ + _pwm_led_close_irq(); + //两个IO特殊处理 + if (__this->user_data->io_mode == LED_TWO_IO_MODE) { +#ifdef PWM_LED_TWO_IO_SUPPORT + _pwm_led_two_io_user_define_mode(led_index); + + if (led_index == 0) { + led_index = 1; + led1_bright = led0_bright; + } + + led_index = 0; +#endif /* #ifdef PWM_LED_TWO_IO_SUPPORT */ + } + _pwm_led_double_flash_display(led_index, led0_bright, led1_bright, + period, first_light_time, gap_time, second_light_time); + + __this->last_mode = PWM_LED_USER_DEFINE_MODE; +} + + +//=================================================================================// +//@brief: 自定义设置呼吸模式 +//@input: +// led_index: 0: led0, 1:led1, 2:led0 & led1(互闪) +// led0_bright: led0亮度, +// led1_bright: led1亮度, +// period: 闪灯周期(ms), 多少ms闪一下, +// start_light_time: 在周期中开始亮灯的时间, -1: 周期最后亮灯 +// light_time: 灯亮持续时间, +// led0_bright, LED0亮度: 0 ~ 500 +// led1_bright, LED1亮度: 0 ~ 500 +//@return: void +//@note: +//=================================================================================// +void pwm_led_breathe_display(u8 led_index, u16 breathe_time, u16 led0_bright, u16 led1_bright, + u32 led0_light_delay_time, u32 led1_light_delay_time, u32 led_blink_delay_time) +{ + _pwm_led_close_irq(); + if (__this->user_data->io_mode == LED_TWO_IO_MODE) { +#ifdef PWM_LED_TWO_IO_SUPPORT + _pwm_led_two_io_user_define_mode(led_index); + if (led_index == 0) { + led_index = 1; + led1_bright = led0_bright; + } + +#endif /* #ifdef PWM_LED_TWO_IO_SUPPORT */ + } + _pwm_led_breathe_display(led_index, breathe_time, led0_bright, led1_bright, + led0_light_delay_time, led1_light_delay_time, led_blink_delay_time); + + __this->last_mode = PWM_LED_USER_DEFINE_MODE; +} + + +//=================================================================================// +//@brief: 注册LED周期中断函数, 每个LED周期结束后会调用一次, 可以统计指定状态闪烁多少次 +//@input: +//@return: void +//@note: +//=================================================================================// +void pwm_led_register_irq(void (*func)(void)) +{ + _pwm_led_register_irq(func, 1); +} + +//=================================================================================// +//@brief: LED模式显示参数设置 +//@input: display, 显示模式 +// para 显示的参数 +//@return: void +//@note: +//=================================================================================// + +static void pwm_led_para_set(u8 display, pwm_led_para para) +{ + switch (display) { + case PWM_LED_ALL_OFF: + case PWM_LED0_OFF: + case PWM_LED1_OFF: + break; + +//灯常亮 + case PWM_LED0_ON: + case PWM_LED1_ON: + case PWM_LED_ALL_ON: + led_para.on = para.on; + break; + +//单灯单闪 + case PWM_LED0_SLOW_FLASH: + case PWM_LED1_SLOW_FLASH: + case PWM_LED0_FAST_FLASH: + case PWM_LED1_FAST_FLASH: + case PWM_LED0_ONE_FLASH_5S: + case PWM_LED1_ONE_FLASH_5S: +//双灯互闪 + case PWM_LED0_LED1_FAST_FLASH: + case PWM_LED0_LED1_SLOW_FLASH: + led_para.one_flash = para.one_flash; + break; + +//单灯双闪 + case PWM_LED0_DOUBLE_FLASH_5S: + case PWM_LED1_DOUBLE_FLASH_5S: + led_para.double_flash = para.double_flash; + break; + +//呼吸模式 + case PWM_LED0_BREATHE: + case PWM_LED1_BREATHE: + case PWM_LED0_LED1_BREATHE: + led_para.breathe = para.breathe; + break; + + default: + return; + break; + } +} +//=================================================================================// +//@brief: LED模式显示模式设置 +//@input: display, 显示模式 +//@return: void +//@note: +//=================================================================================// +void pwm_led_mode_set_with_para(u8 display, pwm_led_para para) +{ + pwm_led_para_set(display, para); + pwm_led_mode_set(display); +} + diff --git a/cpu/br23/sdk_ld.c b/cpu/br23/sdk_ld.c new file mode 100644 index 0000000..d8fdc68 --- /dev/null +++ b/cpu/br23/sdk_ld.c @@ -0,0 +1,806 @@ +// *INDENT-OFF* +#include "app_config.h" + +/* +| updata | +|_______________| +| ram1 | +|_______________| +| TLB | +|_______________| +| isr base | (HW fixed) +|_______________| +| ram0 | +|_______________| +| DCACHE | +|_______________| +*/ + + + + +RAM1_LIMIT_L = 0x2C000; +RAM1_LIMIT_H = 0x30000; + + +/********************************************/ +/* 0x2FF80 ~ 0x30000 */ +/********************************************/ +UPDATA_SIZE = 0x80; +UPDATA_BEG = RAM1_LIMIT_H - UPDATA_SIZE; + +RAM1_BEGIN = RAM1_LIMIT_L; +RAM1_END = RAM1_LIMIT_H - UPDATA_SIZE; +RAM1_SIZE = RAM1_END - RAM1_BEGIN; + + +#ifdef CONFIG_PSRAM_ENABLE +RAM_LIMIT_L = 0x04000; +#else +RAM_LIMIT_L = 0x00000; +#endif + +RAM_LIMIT_H = 0x2C000; +/********************************************/ +/* 0x2BF00 ~ 0x2C000 */ +/********************************************/ +/* ISR_BASE = _IRQ_MEM_ADDR; */ +ISR_SIZE = 0x100; +ISR_BASE = RAM_LIMIT_H - ISR_SIZE; + +/********************************************/ +/* 0x00000 ~ 0x2BF00 */ +/********************************************/ +RAM_BEGIN = RAM_LIMIT_L; +RAM_END = RAM_LIMIT_H - ISR_SIZE; +RAM_SIZE = RAM_END - RAM_BEGIN; + + +BANK_SIZE = 5*1024; + + +PSRAM_BEG = 0x800000; +PSRAM_SIZE = 2M; + + +CODE_BEG = 0X1E000C0; + +UPDATA_BREDR_BASE_BEG = 0xF9000; + +#if MIC_EFFECT_EQ_EN +MIC_EFFECT_EQ_SECTION = 8; +#else +MIC_EFFECT_EQ_SECTION = 3; +#endif + +#if (EQ_SECTION_MAX > 10) +EQ_SECTION_NUM = EQ_SECTION_MAX+MIC_EFFECT_EQ_SECTION; +#else +EQ_SECTION_NUM = 10+MIC_EFFECT_EQ_SECTION; +#endif + +MEMORY +{ + psram(rwx) : ORIGIN = PSRAM_BEG , LENGTH = PSRAM_SIZE +#if (USE_SDFILE_NEW) + code0(rx) : ORIGIN = 0x1E00100, LENGTH = CONFIG_FLASH_SIZE +#else + code0(rx) : ORIGIN = 0x1E00000, LENGTH = CONFIG_FLASH_SIZE +#endif + ram0(rwx) : ORIGIN = RAM_BEGIN , LENGTH = RAM_SIZE + ram1(rwx) : ORIGIN = RAM1_BEGIN , LENGTH = RAM1_SIZE +} + +#include "maskrom_stubs.ld" + +EXTERN( +_start +#include "sdk_used_list.c" +); + +ENTRY(_start) + +EXTERN( + lib_update_version +) + +SECTIONS +{ +/********************************************/ + . =ORIGIN(psram); + .psram_text ALIGN(4): + { +#ifdef CONFIG_PSRAM_ENABLE + *(.text*) + *(.LOG_TAG_CONST*) + *(.rodata*) +#endif + } > psram + + .psram ALIGN(32): + { +#ifdef CONFIG_PSRAM_ENABLE + *(.bss) + *(COMMON) +#endif + } > psram + + . = ORIGIN(code0); + .text ALIGN(4): + { + text_code_begin = .; + + PROVIDE(text_rodata_begin = .); + + *(.startup.text) + + bank_stub_start = .; + *(.bank.stub.*) + bank_stub_size = . - bank_stub_start; + + *(.aac_const) + *(.aac_code) + + *(.alac_const) + *(.alac_code) + *(.alac_dec_code) + + *(.bt_aac_dec_eng_const) + *(.bt_aac_dec_eng_code) + *(.bt_aac_dec_core_code) + *(.bt_aac_dec_core_sparse_code) + + *(.dts_dec_const) + +#if (!TCFG_LED7_RUN_RAM) + *(.gpio_ram) + *(.LED_code) + *(.LED_const) + . = ALIGN(4); +#endif + + +#if (!TCFG_CODE_RUN_RAM_FM_MODE) + *(.usr_timer_const) + *(.usr_timer_code) + *(.timer_const) + *(.timer_code) + *(.cbuf_const) + *(.cbuf_code) + *(.fm_data_code) + *(.fm_data_const) + . = ALIGN(4); +#endif + *(.cvsd_const) + *(.cvsd_code) + + . = ALIGN(4); + gsensor_dev_begin = .; + KEEP(*(.gsensor_dev)) + gsensor_dev_end = .; + + . = ALIGN(4); + hrsensor_dev_begin = .; + KEEP(*(.hrsensor_dev)) + hrsensor_dev_end = .; + + . = ALIGN(4); + fm_dev_begin = .; + KEEP(*(.fm_dev)) + fm_dev_end = .; + + . = ALIGN(4); + fm_emitter_dev_begin = .; + KEEP(*(.fm_emitter_dev)) + fm_emitter_dev_end = .; + + . = ALIGN(4); + tool_interface_begin = .; + KEEP(*(.tool_interface)) + tool_interface_end = .; + + . = ALIGN(4); + cmd_interface_begin = .; + KEEP(*(.eff_cmd)) + cmd_interface_end = .; + . = ALIGN(4); + + /* . = ALIGN(4); */ + /* storage_device_begin = .; */ + /* KEEP(*(.storage_device)) */ + /* storage_device_end = .; */ + + /* . = ALIGN(4); */ + /* ui_main_begin = .; */ + /* KEEP(*(.ui_main)) */ + /* ui_main_end = .; */ + /* . = ALIGN(4); */ + + chargeIc_dev_begin = .; + KEEP(*(.chargeIc_dev)) + chargeIc_dev_end = .; + . = ALIGN(4); + + /********maskrom arithmetic ****/ + *(.opcore_table_maskrom) + *(.bfilt_table_maskroom) + *(.opcore_maskrom) + *(.bfilt_code) + *(.bfilt_const) + + . = ALIGN(4); + #include "btctrler/btctler_lib_text.ld" + . = ALIGN(4); + #include "btstack/btstack_lib_text.ld" + . = ALIGN(4); + #include "system/system_lib_text.ld" + . = ALIGN(4); + #include "ui/ui/ui.ld" + . = ALIGN(4); + #include "media/cpu/br23/media_lib_text.ld" + + . = ALIGN(4); + update_target_begin = .; + PROVIDE(update_target_begin = .); + KEEP(*(.update_target)) + update_target_end = .; + PROVIDE(update_target_end = .); + . = ALIGN(4); + + *(.text*) + *(.LOG_TAG_CONST*) + *(.rodata*) + . = ALIGN(4); + + __VERSION_BEGIN = .; + KEEP(*(.version)) + __VERSION_END = .; + . = ALIGN(4); + + text_code_end = .; + + } >code0 + + + . = ORIGIN(ram0); + + _data_code_begin = . ; + + +#ifdef CONFIG_CODE_BANK_ENABLE + + bank_code_run_addr = .; + + OVERLAY : AT(0x300000) SUBALIGN(4) + { + .overlay_bank0 + { + *(.bank.code.0*) + *(.bank.const.0*) + . = ALIGN(4); + } + .overlay_bank1 + { + *(.bank.code.1*) + *(.bank.const.1*) + . = ALIGN(4); + } + .overlay_bank2 + { + *(.bank.code.2*) + *(.bank.const.2*) + . = ALIGN(4); + } + .overlay_bank3 + { + *(.bank.code.3*) + *(.bank.const.3*) + . = ALIGN(4); + } + } > ram0 + bank_code_run_end_addr = .; + + common_code_run_addr = bank_code_run_addr + BANK_SIZE; + ASSERT(bank_code_run_end_addr <= common_code_run_addr, "bank overflow!") + + . = common_code_run_addr; + + .common ALIGN(4): + { + *(.common*) + . = ALIGN(4); + } > ram0 +#else + + bank_code_run_addr = .; + common_code_run_addr = .; +#endif + + //cpu start + .data ALIGN(4): + { + /// 放在data 里面的code 必须放在这个位置保护起来 + + *(.data_magic) + . = ALIGN(4); + + *(.flushinv_icache) + *(.volatile_ram_code) + *(.os_critical_code) + *(.chargebox_code) + + *(.os_code) + *(.os_const) + + + *(.ui_ram) + + *(.fat_data_code) +#if (TCFG_LED7_RUN_RAM) + *(.gpio_ram) + *(.LED_code) + *(.LED_const) + . = ALIGN(4); +#endif + +#if (TCFG_CODE_RUN_RAM_FM_MODE) + *(.usr_timer_const) + *(.usr_timer_code) + *(.timer_const) + *(.timer_code) + *(.cbuf_const) + *(.cbuf_code) + *(.fm_data_code) + *(.fm_data_const) + . = ALIGN(4); +#endif + +#if TCFG_FM_INSIDE_ENABLE + *(.fm_code) +#endif + + . = ALIGN(4); + #include "media/cpu/br23/media_lib_data_text.ld" + . = ALIGN(4); + + _data_code_end = . ; + + _cpu_store_begin = . ; + . = ALIGN(4); + *(.data*) + + *(.cvsd_data) + + . = ALIGN(4); + dec_board_param_mem_begin = .; + KEEP(*(.dec_board_param_mem)) + dec_board_param_mem_end = .; + + . = ALIGN(4); + *(.sbc_eng_code) + . = ALIGN(4); + + . = ALIGN(32); + #include "btstack/btstack_lib_data.ld" + . = ALIGN(4); + #include "btctrler/btctler_lib_data.ld" + . = ALIGN(4); + #include "system/system_lib_data.ld" + . = ALIGN(4); + #include "media/cpu/br23/media_lib_data.ld" + . = ALIGN(4); + + } > ram0 + + .irq_stack ALIGN(32) : + { + *(.stack_magic) + _cpu0_sstack_begin = .; + PROVIDE(cpu0_sstack_begin = .); + *(.stack) + _cpu0_sstack_end = .; + PROVIDE(cpu0_sstack_end = .); + _stack_end = . ; + *(.stack_magic0) + + . = ALIGN(4); + *(.boot_info) + + } > ram0 + + .bss ALIGN(32) : + { + *(.usb_h_dma) //由于usb有个bug,会导致dma写的数据超出预设的buf,最长可能写超1k,为了避免死机,所以usb dma buffer后面放一些其他模块的buff来避免死机 + *(.usb_ep0) + *(.dec_mix_buff) + *(.sd0_var) + *(.sd1_var) + *(.dac_buff) + + *(.bss) + *(COMMON) + *(.cvsd_bss) + + *(.volatile_ram) + #include "btctrler/btctler_lib_bss.ld" + #include "btstack/btstack_lib_bss.ld" + #include "system/system_lib_bss.ld" + #include "media/cpu/br23/media_lib_bss.ld" + + . = (( . + 31) / 32 * 32); + + . = ALIGN(4); + +#if TCFG_USB_CDC_BACKGROUND_RUN + *(.usb_cdc_dma) + *(.usb_config_var) + *(.cdc_var) + . = ALIGN(32); +#endif + + } > ram0 + //cpu end + _cpu_store_end = . ; + + _prp_store_begin = . ; + .prp_bss ALIGN(32) : + { + //bt + // + //sbc + // + //audio + . = (( . + 31) / 32 * 32); + } > ram0 + _prp_store_end = . ; + + .bss ALIGN(32) : + { + NVRAM_DATA_START = .; + *(.non_volatile_ram) + NVRAM_DATA_SIZE = ABSOLUTE(. - NVRAM_DATA_START); + . = ALIGN(4); + NVRAM_END = .; + _nv_pre_begin = . ; + + *(.src_filt) + *(.src_dma) + . = ALIGN(4); + + } > ram0 + + overlay_begin = .; + OVERLAY : NOCROSSREFS AT(0x200000) SUBALIGN(4) + { + + .overlay_aec + { + LONG(0xFFFFFFFF); + /* *(.aec_bss_id) */ + o_aec_end = .; + + *(.aec_mem) + *(.msbc_enc) + } + .overlay_mp3 + { +#ifdef CONFIG_MP3_WMA_LIB_SPECIAL + *(.mp3_decstream_const) + *(.mp3_decstream_code) + *(.mp3_decstream_sparse_code) + *(.mp3_decstream_sparse_const) + + *(.mp3_dec_sparse_code) + *(.mp3_dec_sparse_const) + + *(.mp3_dec_code) + *(.mp3_dec_const) + /* *(.mp3_dec_data) */ + /* *(.mp3_dec_bss) */ + + /* *(.mp3_bss) */ + /* *(.mp3_data) */ + *(.mp3_const) + *(.mp3_code) +#endif + LONG(0xFFFFFFFF); + /* *(.mp3_bss_id) */ + o_mp3_end = .; + + *(.mp3_mem) + *(.mp3_ctrl_mem) + *(.mp3pick_mem) + *(.mp3pick_ctrl_mem) + } + .overlay_wma + { +#ifdef CONFIG_MP3_WMA_LIB_SPECIAL + *(.wma_code) + *(.wma_const) + *(.wma_dec_code) + *(.wma_dec_const) + /* *(.wma_dec_data) */ + /* *(.wma_dec_bss) */ + + /* *(.wma_bss) */ + /* *(.wma_data) */ +#endif + LONG(0xFFFFFFFF); + /* *(.wma_bss_id) */ + o_wma_end = .; + + *(.wma_mem) + *(.wma_ctrl_mem) + *(.wmapick_mem) + *(.wmapick_ctrl_mem) + } + .overlay_wav + { + + LONG(0xFFFFFFFF); + /* *(.wav_bss_id) */ + + *(.wav_bss) + *(.wav_dec_bss) + *(.wav_mem) + *(.wav_ctrl_mem) + } + + .overlay_ape + { + *(.ape_mem) + *(.ape_ctrl_mem) + + *(.ape_dec_sparse_code) + *(.ape_dec_sparse_const) + + *(.ape_dec_code) + *(.ape_dec_const) + *(.ape_dec_data) + *(.ape_dec_bss) + + LONG(0xFFFFFFFF); + /* *(.ape_bss_id) */ + + *(.ape_bss) + *(.ape_data) + *(.ape_const) + *(.ape_code) + + } + .overlay_flac + { + + LONG(0xFFFFFFFF); + /* *(.flac_bss_id) */ + + *(.flac_mem) + *(.flac_ctrl_mem) + *(.flac_dec_bss) + *(.flac_bss) + } + + .overlay_m4a + { + *(.m4a_dec_code) + *(.m4a_dec_ff_const) + *(.m4a_dec_const) + *(.m4a_dec_data) + + *(.m4a_data) + *(.m4a_const) + *(.m4a_code) + *(.m4apick_mem) + *(.m4apick_ctrl_mem) + + LONG(0xFFFFFFFF); + /* *(.m4a_bss_id) */ + + *(.m4a_mem) + *(.m4a_ctrl_mem) + *(.m4a_dec_bss) + *(.m4a_bss) + *(.aac_ctrl_mem) + *(.aac_bss) + + *(.alac_ctrl_mem) + *(.alac_bss) + } + + + .overlay_amr + { + *(.amr_dec_sparse_code) + *(.amr_dec_sparse_const) + *(.amr_dec_code) + + *(.amr_dec_data) + + LONG(0xFFFFFFFF); + /* *(.amr_bss_id) */ + + *(.amr_mem) + *(.amr_ctrl_mem) + *(.amr_dec_bss) + } + .overlay_dts + { + *(.dts_dec_code) + *(.dts_dec_data) + + *(.dts_data) + *(.dts_const) + *(.dts_code) + + LONG(0xFFFFFFFF); + /* *(.dts_bss_id) */ + + *(.dts_mem) + *(.dts_ctrl_mem) + *(.dts_dec_bss) + *(.dts_bss) + + } + + + + .overlay_fm + { + LONG(0xFFFFFFFF); + /* *(.fm_bss_id) */ + o_fm_end = .; + + *(.fm_mem) + *(.linein_pcm_mem) + } + .overlay_pc + { +#if TCFG_VIR_UDISK_ENABLE == 0 + *(.usb_audio_play_dma) + *(.usb_audio_rec_dma) + *(.uac_rx) + *(.mass_storage) + + *(.usb_msd_dma) + *(.usb_hid_dma) + *(.usb_iso_dma) + *(.usb_cdc_dma) + *(.uac_var) + *(.usb_config_var) + *(.cdc_var) +#endif + } + } > ram0 + + overlay_end = .; + + ASSERT(overlay_end <= overlay_begin + 64k, "overlay overflow 64k!") + + RAM_USED = .; + + + . =ORIGIN(ram1); + //TLB 起始需要16K 对齐; + .mmu_tlb ALIGN(0x4000): + { + *(.mmu_tlb_segment); + } > ram1 + + + .bss1 ALIGN(32) : + { + } > ram1 + RAM1_USED = .; + + +/********************************************/ + /* + . =ORIGIN(ram0); + .ram0_data ALIGN(4): + { + _VM_CODE_START = . ; + *(.vm) + _VM_CODE_END = . ; + *(.flushinv_icache) + + . = ALIGN(4); // must at tail, make ram0_data size align 4 + } > ram0 + */ + +/********************************************/ +} + + +#include "update/update.ld" +#include "driver/cpu/br23/driver_lib.ld" + +text_begin = ADDR(.text) ; +text_size = SIZEOF(.text) ; +text_end = ADDR(.text) + SIZEOF(.text) ; + +bss_begin = ADDR(.bss) ; +bss_size = SIZEOF(.bss); + +bss1_begin = ADDR(.bss1) ; +bss1_size = SIZEOF(.bss1); + +data_addr = ADDR(.data) ; +data_begin = text_begin + text_size; +data_size = SIZEOF(.data) ; + +psram_vaddr = ADDR(.psram_text) ; +psram_laddr = text_begin + text_size + data_size; +psram_text_size = SIZEOF(.psram_text) ; + +bank_code_load_addr = data_begin + data_size; + + +//================ OVERLAY Code Info Export ==================// + +aec_addr = ADDR(.overlay_aec); +aec_begin = text_begin + text_size + data_size; +aec_size = o_aec_end - aec_addr; +/* aec_size = SIZEOF(.overlay_aec); */ + +wav_addr = ADDR(.overlay_wav); +wav_begin = aec_begin + aec_size; +wav_size = SIZEOF(.overlay_wav); + +ape_addr = ADDR(.overlay_ape); +ape_begin = wav_begin + wav_size; +ape_size = SIZEOF(.overlay_ape); + +flac_addr = ADDR(.overlay_flac); +flac_begin = ape_begin + ape_size; +flac_size = SIZEOF(.overlay_flac); + +m4a_addr = ADDR(.overlay_m4a); +m4a_begin = flac_begin + flac_size; +m4a_size = SIZEOF(.overlay_m4a); + +amr_addr = ADDR(.overlay_amr); +amr_begin = m4a_begin + m4a_size; +amr_size = SIZEOF(.overlay_amr); + +dts_addr = ADDR(.overlay_dts); +dts_begin = amr_begin + amr_size; +dts_size = SIZEOF(.overlay_dts); + +fm_addr = ADDR(.overlay_fm); +fm_begin = dts_begin + dts_size; +fm_size = o_fm_end - fm_addr; +/* fm_size = SIZEOF(.overlay_fm); */ + +#ifdef CONFIG_MP3_WMA_LIB_SPECIAL +mp3_addr = ADDR(.overlay_mp3); +mp3_begin = fm_begin + fm_size; +mp3_size = o_mp3_end - mp3_addr; + +wma_addr = ADDR(.overlay_wma); +wma_begin = mp3_begin + mp3_size; +wma_size = o_wma_end - wma_addr; + +#endif + + +_HEAP_BEGIN = RAM_USED; +PROVIDE(HEAP_BEGIN = RAM_USED); + +_HEAP_END = RAM_END; +PROVIDE(HEAP_END = RAM_END); + +_HEAP_SIZE = HEAP_END - HEAP_BEGIN; +PROVIDE(HEAP_SIZE = HEAP_END - HEAP_BEGIN); + +_HEAP1_BEGIN = RAM1_USED; +PROVIDE(HEAP1_BEGIN = RAM1_USED); + +_HEAP1_END = RAM1_END; +PROVIDE(HEAP1_END = RAM1_END); + +_HEAP1_SIZE = HEAP1_END - HEAP1_BEGIN; +PROVIDE(HEAP1_SIZE = HEAP1_END - HEAP1_BEGIN); + +_MALLOC_SIZE = HEAP_SIZE + HEAP1_SIZE; +PROVIDE(MALLOC_SIZE = HEAP_SIZE + HEAP1_SIZE); + diff --git a/cpu/br23/sdk_used_list.c b/cpu/br23/sdk_used_list.c new file mode 100644 index 0000000..c520b26 --- /dev/null +++ b/cpu/br23/sdk_used_list.c @@ -0,0 +1,166 @@ +#include "app_config.h" + +#if TCFG_USER_TWS_ENABLE +tws_local_media_sync +tws_afh_sync +tws_ci_data +tws_acl_data_sync +tws_event_sync +tws_conn_sync +tws_lmp_slot_sync +tws_low_latency +tws_media_sync +tws_power_balance +tws_sync_call +tws_tx_sync +tws_link_sync +#endif + + +#if CONFIG_FATFS_ENABLE +fat_vfs_ops +#endif + +#if VFS_ENABLE +sdfile_vfs_ops +#endif + +#if TCFG_NORFLASH_DEV_ENABLE && VFS_ENABLE +nor_fs_vfs_ops +nor_sdfile_vfs_ops +nor_rec_fs_vfs_ops +fat_sdfile_fat_ops +#endif + +#if FLASH_INSIDE_REC_ENABLE +inside_nor_fs_vfs_ops +#endif + +#if TCFG_DEC_SBC_ENABLE +sbc_decoder +msbc_decoder +sbc_hwaccel +#endif + +#if TCFG_DEC_CVSD_ENABLE +cvsd_decoder +#endif + +#if TCFG_DEC_PCM_ENABLE +pcm_decoder +#endif + +#if TCFG_DEC_MTY_ENABLE +mty_decoder +#endif + +#if TCFG_DEC_MP3_ENABLE +mp3_decoder +#if TCFG_DEC2TWS_ENABLE +mp3pick_decoder +#endif +#endif + +#if TCFG_DEC_WMA_ENABLE +wma_decoder +#if TCFG_DEC2TWS_ENABLE +wmapick_decoder +#endif +#endif + +#if TCFG_DEC_FLAC_ENABLE +flac_decoder +#endif + +#if TCFG_DEC_APE_ENABLE +ape_decoder +#endif + +#if TCFG_DEC_M4A_ENABLE +m4a_decoder +#if TCFG_DEC2TWS_ENABLE +m4apick_decoder +#endif +#endif + +#if TCFG_DEC_ALAC_ENABLE +alac_decoder +#endif + +#if TCFG_DEC_AMR_ENABLE +amr_decoder +#endif + +#if TCFG_DEC_DTS_ENABLE +dts_decoder +#endif + +#if TCFG_DEC_G729_ENABLE +g729_decoder +#endif + +#if TCFG_DEC_WTGV2_ENABLE +wtgv2_decoder +#endif + +#if (TCFG_DEC_AAC_ENABLE || TCFG_BT_SUPPORT_AAC) +aac_decoder +#endif + +#if TCFG_DEC_G726_ENABLE +g726_decoder +#endif + +#if TCFG_DEC_MIDI_ENABLE +midi_decoder +#endif + +#if TCFG_DEC_WAV_ENABLE +wav_decoder +#endif + +#if AUDIO_MIDI_CTRL_CONFIG +midi_ctrl_decoder +#endif + + + +#if TCFG_ENC_CVSD_ENABLE +cvsd_encoder +#endif + +#if TCFG_ENC_MSBC_ENABLE +msbc_encoder +#endif + +#if TCFG_ENC_MP3_ENABLE +mp3_encoder +#endif + +#if TCFG_ENC_G726_ENABLE +g726_encoder +#endif + +#if TCFG_ENC_ADPCM_ENABLE +adpcm_encoder +#endif + +#if TCFG_ENC_PCM_ENABLE +pcm_encoder +#endif + +#if TCFG_ENC_OPUS_ENABLE +opus_encoder +#endif + +#if TCFG_ENC_SPEEX_ENABLE +speex_encoder +#endif + +#if TCFG_ENC_SBC_ENABLE +sbc_encoder +#endif + +eff_adj_target + + diff --git a/cpu/br23/sdk_used_list.used b/cpu/br23/sdk_used_list.used new file mode 100644 index 0000000..f4bd03b --- /dev/null +++ b/cpu/br23/sdk_used_list.used @@ -0,0 +1,36 @@ + + +fat_vfs_ops + + + +sdfile_vfs_ops +sbc_decoder +msbc_decoder +sbc_hwaccel + + + +cvsd_decoder + + + +pcm_decoder + + + + + + + +mp3_decoder +g729_decoder +cvsd_encoder + + + +msbc_encoder +sbc_encoder + + +eff_adj_target diff --git a/cpu/br23/setup.c b/cpu/br23/setup.c new file mode 100644 index 0000000..d613e58 --- /dev/null +++ b/cpu/br23/setup.c @@ -0,0 +1,263 @@ +#include "asm/includes.h" +//#include "asm/ldo.h" +//#include "asm/cache.h" +#include "asm/wdt.h" +#include "asm/debug.h" +#include "asm/efuse.h" +#include "asm/power/p33.h" +#include "system/task.h" +#include "timer.h" +#include "system/init.h" +#include "system/includes.h" + +#include "app_config.h" +#include "gpio.h" +//#include "power_manage.h" +// +#define LOG_TAG_CONST SETUP +#define LOG_TAG "[SETUP]" +#define LOG_ERROR_ENABLE +#define LOG_DEBUG_ENABLE +#define LOG_INFO_ENABLE +/* #define LOG_DUMP_ENABLE */ +#define LOG_CLI_ENABLE +#include "debug.h" + +//extern void dv15_dac_early_init(u8 ldo_sel, u8 pwr_sel, u32 dly_msecs); +// +extern void sys_timer_init(void); + +extern void tick_timer_init(void); + +extern void vPortSysSleepInit(void); + +extern void reset_source_dump(void); + +extern u8 power_reset_source_dump(void); + +extern void exception_irq_handler(void); +int __crc16_mutex_init(); + +extern int __crc16_mutex_init(); + +#define DEBUG_SINGAL_IDLE(x) //if (x) IO_DEBUG_1(A, 7) else IO_DEBUG_0(A, 7) +#define DEBUG_SINGAL_1S(x) //if (x) IO_DEBUG_1(A, 6) else IO_DEBUG_0(A, 6) + +#if (defined CONFIG_DEBUG_ENABLE) || (defined CONFIG_DEBUG_LITE_ENABLE) +void debug_uart_init(const struct uart_platform_data *data); +#endif + +#if 0 +___interrupt +void exception_irq_handler(void) +{ + ___trig; + + exception_analyze(); + + log_flush(); + while (1); +} +#endif + + +#if 0 + +#define CACHE_LINE_COUNT (32) +#define ONE_TIME_CODE (1*1024) + +extern u32 text_code_begin; +extern u32 text_code_end; +static u32 load_ptr = 0xffffffff; + +void load_code2cache() +{ + u32 i = 0; + volatile u8 tmp; + + u32 ali_start = ((u32)&text_code_begin & ~(CACHE_LINE_COUNT - 1)); + u32 ali_end = (u32)&text_code_end + (4 * CACHE_LINE_COUNT); + if (load_ptr == 0xffffffff) { + load_ptr = ali_start; + } + + while (1) { + i += CACHE_LINE_COUNT; + load_ptr += CACHE_LINE_COUNT; + tmp = *(u8 *)load_ptr; + + if (load_ptr >= ali_end) { + load_ptr = ali_start; + } + if (i >= ONE_TIME_CODE) { + /* y_printf("-- %x \n",load_ptr); */ + return; + } + } +} + +#endif + +/* + * 此函数在cpu0上电后首先被调用,负责初始化cpu内部模块 + * + * 此函数返回后,操作系统才开始初始化并运行 + * + */ + +#if 0 +static void early_putchar(char a) +{ + if (a == '\n') { + UT2_BUF = '\r'; + __asm_csync(); + while ((UT2_CON & BIT(15)) == 0); + } + UT2_BUF = a; + __asm_csync(); + while ((UT2_CON & BIT(15)) == 0); +} + +void early_puts(char *s) +{ + do { + early_putchar(*s); + } while (*(++s)); +} +#endif + +void cpu_assert_debug() +{ +#ifdef CONFIG_DEBUG_ENABLE + log_flush(); + local_irq_disable(); + while (1); +#else + cpu_reset(); +#endif +} + +void timer(void *p) +{ + /* DEBUG_SINGAL_1S(1); */ + sys_timer_dump_time(); + /* DEBUG_SINGAL_1S(0);*/ + + /* void os_system_info_output(void); */ + /* os_system_info_output(); */ +} + +u8 power_reset_src = 0; +extern void sputchar(char c); +extern void sput_buf(const u8 *buf, int len); +void sput_u32hex(u32 dat); +void *vmem_get_phy_adr(void *vaddr); + +void test_fun() +{ + wdt_close(); + while (1); + +} + +AT_VOLATILE_RAM_CODE +void __lvd_irq_handler(void) +{ + VLVD_PND_CLR(1); +} + + + +void load_common_code(); +void app_load_common_code() +{ +#ifdef CONFIG_CODE_BANK_ENABLE + /* load_common_code(); */ +#endif +} + +u32 stack_magic[4] sec(.stack_magic); +u32 stack_magic0[4] sec(.stack_magic0); + +extern void port_init(void); +extern void lvd_enable(void); + +void memory_init(void); +void setup_arch() +{ + memory_init(); + + memset(stack_magic, 0x5a, sizeof(stack_magic)); + memset(stack_magic0, 0x5a, sizeof(stack_magic0)); + + + wdt_init(WDT_4S); + /* wdt_close(); */ + +#if (AUDIO_OUTPUT_WAY == AUDIO_OUTPUT_WAY_FM) + clk_init_osc_ldos(2); +#else + clk_init_osc_ldos(3); +#endif + + clk_init_osc_cap(0x0a, 0x0a); + clk_voltage_init(TCFG_CLOCK_MODE, SYSVDD_VOL_SEL_126V, TCFG_LOWPOWER_POWER_SEL, VDC13_VOL_SEL_140V); + + + clk_early_init(TCFG_CLOCK_SYS_SRC, TCFG_CLOCK_OSC_HZ, TCFG_CLOCK_SYS_HZ); + + //上电初始所有io + port_init(); + + tick_timer_init(); + /* lvd_enable(); */ + /*interrupt_init();*/ + +#if (defined CONFIG_DEBUG_ENABLE) || (defined CONFIG_DEBUG_LITE_ENABLE) + debug_uart_init(NULL); + +#ifdef CONFIG_DEBUG_ENABLE + log_early_init(1024); +#endif + +#endif + +#ifdef CONFIG_CODE_BANK_ENABLE + extern void bank_syscall_entry(); + request_irq(IRQ_SYSCALL_IDX, 0, bank_syscall_entry, 0); +#endif + + + printf("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); + printf(" setup_arch %s %s \n", __DATE__, __TIME__); + printf("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"); + + + clock_dump(); + /* log_info("resour est: %d", get_boot_flag()); */ + //set_boot_flag(99); + /* log_info("resour est: %d", get_boot_flag()); */ + + reset_source_dump(); + + power_reset_src = power_reset_source_dump(); + + //Register debugger interrupt + request_irq(0, 2, exception_irq_handler, 0); + + request_irq(1, 2, exception_irq_handler, 0); + + debug_init(); + + /* CHGBG_EN(0); */ + /* CHARGE_EN(0); */ + + sys_timer_init(); + + /* sys_timer_add(NULL, timer, 10 * 1000); */ + + + __crc16_mutex_init(); +} + +/*-----------------------------------------------------------*/ diff --git a/cpu/br23/spi.c b/cpu/br23/spi.c new file mode 100644 index 0000000..29d202e --- /dev/null +++ b/cpu/br23/spi.c @@ -0,0 +1,709 @@ + +#undef LOG_TAG_CONST +#define LOG_TAG "[SPI]" +#define LOG_ERROR_ENABLE +//#define LOG_DEBUG_ENABLE +#include "system/debug.h" +#include "generic/gpio.h" +#include "asm/clock.h" +#include "asm/spi.h" +#include "update.h" + + +#define spi_enable(reg) ((reg)->CON |= BIT(0)) +#define spi_disable(reg) ((reg)->CON &= ~BIT(0)) +#define spi_role_slave(reg) ((reg)->CON |= BIT(1)) +#define spi_role_master(reg) ((reg)->CON &= ~BIT(1)) +#define spi_cs_en(reg) ((reg)->CON |= BIT(2)) +#define spi_cs_dis(reg) ((reg)->CON &= ~BIT(2)) +#define spi_bidir(reg) ((reg)->CON |= BIT(3)) +#define spi_unidir(reg) ((reg)->CON &= ~BIT(3)) +#define spi_smp_edge_rise(reg) ((reg)->CON &= ~BIT(4)) +#define spi_smp_edge_fall(reg) ((reg)->CON |= BIT(4)) +#define spi_ud_edge_rise(reg) ((reg)->CON &= ~BIT(5)) +#define spi_ud_edge_fall(reg) ((reg)->CON |= BIT(5)) +#define spi_clk_idle_h(reg) ((reg)->CON |= BIT(6)) +#define spi_clk_idle_l(reg) ((reg)->CON &= ~BIT(6)) +#define spi_cs_idle_h(reg) ((reg)->CON |= BIT(7)) +#define spi_cs_idle_l(reg) ((reg)->CON &= ~BIT(7)) +#define spi_data_width(reg, x) ((reg)->CON = (reg->CON&~(3<<10))|((x)<<10)) +#define spi_dir_in(reg) ((reg)->CON |= BIT(12)) +#define spi_dir_out(reg) ((reg)->CON &= ~BIT(12)) +#define spi_ie_en(reg) ((reg)->CON |= BIT(13)) +#define spi_ie_dis(reg) ((reg)->CON &= ~BIT(13)) +#define spi_clr_pnd(reg) ((reg)->CON |= BIT(14)) +#define spi_pnd(reg) ((reg)->CON & BIT(15)) + +#define spi_w_reg_con(reg, val) ((reg)->CON = (val)) +#define spi_r_reg_con(reg) ((reg)->CON) +#define spi_w_reg_buf(reg, val) ((reg)->BUF = (val)) +#define spi_r_reg_buf(reg) ((reg)->BUF) +#define spi_w_reg_baud(reg, baud) ((reg)->BAUD = (baud)) +#define spi_r_reg_baud(reg) ((reg)->BAUD) +#define spi_w_reg_dma_addr(reg, addr) ((reg)->ADR = (addr)) +#define spi_w_reg_dma_cnt(reg, cnt) ((reg)->CNT = (cnt)) + + +#define SPI0_ENABLE 1 //是否使能SPI0,使能后需定义spi0_p_data +#define SPI1_ENABLE 1 //是否使能SPI1,使能后需定义spi1_p_data +#define SPI2_ENABLE 1 //是否使能SPI2,使能后需定义spi2_p_data + + +static const struct spi_io_mapping spi_io_map[SPI_MAX_HW_NUM] = { + //SPI0 + { + .num = 4, + //port A + .io[0] = { + .cs_pin = IO_PORTD_03, + .di_pin = IO_PORTD_02, + .do_pin = IO_PORTD_01, + .clk_pin = IO_PORTD_00, + .d2_pin = IO_PORTB_07, + .d3_pin = IO_PORTD_05, + }, + //port B + .io[1] = { + .cs_pin = IO_PORTA_13, + .di_pin = IO_PORTA_14, + .do_pin = IO_PORTD_01, + .clk_pin = IO_PORTD_00, + .d2_pin = IO_PORTA_15, + .d3_pin = IO_PORTD_05, + }, + //port C + .io[2] = { + .cs_pin = -1,//IO_PORTA_04, + .di_pin = IO_PORTA_06, + .do_pin = IO_PORTA_08, + .clk_pin = IO_PORTA_03, + .d2_pin = IO_PORTA_07, + .d3_pin = IO_PORTA_02, + }, + //port D + .io[3] = { + .cs_pin = -1,//IO_PORTB_06, + .di_pin = IO_PORTB_08, + .do_pin = IO_PORTB_10, + .clk_pin = IO_PORTB_05, + .d2_pin = IO_PORTB_09, + .d3_pin = IO_PORTB_04, + } + }, + //SPI1 + { + .num = 2, + //port A + .io[0] = { + .cs_pin = -1, + .di_pin = IO_PORTB_02, + .do_pin = IO_PORTB_01, + .clk_pin = IO_PORTB_00, + .d2_pin = -1, + .d3_pin = -1, + }, + //port B + .io[1] = { + .cs_pin = -1, + .di_pin = IO_PORTC_03, + .do_pin = IO_PORTC_05, + .clk_pin = IO_PORTC_04, + .d2_pin = -1, + .d3_pin = -1, + } + }, + //SPI2 + { + .num = 2, + //port A + .io[0] = { + .cs_pin = -1, + .di_pin = IO_PORTB_08, + .do_pin = IO_PORTB_10, + .clk_pin = IO_PORTB_09, + .d2_pin = -1, + .d3_pin = -1, + }, + //port B + .io[1] = { + .cs_pin = -1, + .di_pin = IO_PORTA_13, + .do_pin = IO_PORT_DM, + .clk_pin = IO_PORT_DP, + .d2_pin = -1, + .d3_pin = -1, + } + }, +}; + +static JL_SPI_TypeDef *const spi_regs[SPI_MAX_HW_NUM] = { + JL_SPI0, + JL_SPI1, + JL_SPI2, +}; + +static u8 spi_get_info_id(spi_dev spi) +{ + ASSERT(spi < SPI_MAX_HW_NUM); + return spi; +} + +static u8 spi_get_info_port(spi_dev spi) +{ + u8 port = (u8) - 1; + u8 id = spi_get_info_id(spi); + switch (id) { +#if SPI0_ENABLE + case SPI0: + port = spi0_p_data.port; + break; +#endif +#if SPI1_ENABLE + case SPI1: + port = spi1_p_data.port; + break; +#endif +#if SPI2_ENABLE + case SPI2: + port = spi2_p_data.port; + break; +#endif + default: + break; + } + ASSERT(port - 'A' < spi_io_map[id].num); + return port; +} + +static u8 spi_get_info_mode(spi_dev spi) +{ + u8 mode = (u8) - 1; + u8 id = spi_get_info_id(spi); + switch (id) { +#if SPI0_ENABLE + case SPI0: + mode = spi0_p_data.mode; + break; +#endif +#if SPI1_ENABLE + case SPI1: + mode = spi1_p_data.mode; + break; +#endif +#if SPI2_ENABLE + case SPI2: + mode = spi2_p_data.mode; + break; +#endif + default: + break; + } + return mode; +} + +static u8 spi_get_info_role(spi_dev spi) +{ + u8 role = (u8) - 1; + u8 id = spi_get_info_id(spi); + switch (id) { +#if SPI0_ENABLE + case SPI0: + role = spi0_p_data.role; + break; +#endif +#if SPI1_ENABLE + case SPI1: + role = spi1_p_data.role; + break; +#endif +#if SPI2_ENABLE + case SPI2: + role = spi2_p_data.role; + break; +#endif + default: + break; + } + return role; +} + +static u32 spi_get_info_clock(spi_dev spi) +{ + u32 clock = (u8) - 1; + u8 id = spi_get_info_id(spi); + switch (id) { +#if SPI0_ENABLE + case SPI0: + clock = spi0_p_data.clk; + break; +#endif +#if SPI1_ENABLE + case SPI1: + clock = spi1_p_data.clk; + break; +#endif +#if SPI2_ENABLE + case SPI2: + clock = spi2_p_data.clk; + break; +#endif + default: + break; + } + return clock; +} + +static void spi0_iomc_config(spi_dev spi) +{ + u8 port = spi_get_info_port(spi); + if (port == 'A') { + JL_IOMAP->CON0 &= ~(BIT(16) | BIT(17)); + } else if (port == 'B') { + JL_IOMAP->CON0 &= ~(BIT(16) | BIT(17)); + JL_IOMAP->CON0 |= (BIT(16)); + } else if (port == 'C') { + JL_IOMAP->CON0 &= ~(BIT(16) | BIT(17)); + JL_IOMAP->CON0 |= (BIT(17)); + } else { + JL_IOMAP->CON0 |= (BIT(16) | BIT(17)); + } +} + +static void spi1_iomc_config(spi_dev spi) +{ + u8 port = spi_get_info_port(spi); + if (port == 'A') { + JL_IOMAP->CON1 &= ~BIT(4); + } else if (port == 'B') { + JL_IOMAP->CON1 |= BIT(4); + } +} + +static void spi2_iomc_config(spi_dev spi) +{ + u8 port = spi_get_info_port(spi); + if (port == 'A') { + JL_IOMAP->CON1 &= ~BIT(16); + } else if (port == 'B') { + JL_IOMAP->CON1 |= BIT(16); + } +} + +static void (*pSPI_IOMC_CONFIG[])(spi_dev spi) = { + spi0_iomc_config, + spi1_iomc_config, + spi2_iomc_config, +}; + + +static void spi_io_port_init(u8 port, u8 dir) +{ + if (port != (u8) - 1) { + if (dir == 1) { + gpio_set_direction(port, 1); + } else { + gpio_set_direction(port, 0); + } + gpio_set_die(port, 1); + gpio_set_pull_up(port, 0); + gpio_set_pull_down(port, 0); + } +} + +static void spi_io_port_uninit(u8 port) +{ + if (port != (u8) - 1) { + gpio_set_direction(port, 1); + gpio_set_die(port, 0); + gpio_set_pull_up(port, 0); + gpio_set_pull_down(port, 0); + } +} + +/* + * @brief 设置波特率 + * @parm spi spi句柄 + * @parm baud 波特率 + * @return 0 成功,< 0 失败 + */ +int spi_set_baud(spi_dev spi, u32 baud) +{ + //SPICK = sysclk / (SPIx_BAUD + 1) + //=> SPIx_BAUD = sysclk / SPICK - 1 + u8 id = spi_get_info_id(spi); + u32 sysclk; + + sysclk = clk_get("spi"); + log_debug("spi clock source freq %lu", sysclk); + if (sysclk < baud) { + spi_w_reg_baud(spi_regs[id], 0); + return -EINVAL; + } + spi_w_reg_baud(spi_regs[id], sysclk / baud - 1); + return 0; +} + +/* + * @brief 获取波特率 + * @parm spi spi句柄 + * @return 波特率 + */ +u32 spi_get_baud(spi_dev spi) +{ + u8 id = spi_get_info_id(spi); + return spi_get_info_clock(spi); +} + +static int __spi_wait_ok(spi_dev spi, u32 n) +{ + u8 id = spi_get_info_id(spi); + u32 baud = spi_get_info_clock(spi); + baud = clk_get("spi") / baud - 1; + u32 retry = baud * (clk_get("sys") / clk_get("spi")) * 8 * n * 5; //500% spi baudate + + while (!spi_pnd(spi_regs[id])) { + __asm__ volatile("nop"); + if (--retry == 0) { + log_error("spi wait pnd timeout"); + return -EFAULT; + } + } + spi_clr_pnd(spi_regs[id]); + return 0; +} + +/* + * @brief 发送1个字节 + * @parm spi spi句柄 + * @parm byte 发送的字节 + * @return 0 成功,< 0 失败 + */ +int spi_send_byte(spi_dev spi, u8 byte) +{ + u8 id = spi_get_info_id(spi); + + spi_dir_out(spi_regs[id]); + spi_w_reg_buf(spi_regs[id], byte); + return __spi_wait_ok(spi, 1); +} + +/* + * @brief 发送1个字节,不等待pnd,用于中断 + * @parm spi spi句柄 + * @parm byte 发送的字节 + * @return null + */ +void spi_send_byte_for_isr(spi_dev spi, u8 byte) +{ + u8 id = spi_get_info_id(spi); + + spi_dir_out(spi_regs[id]); + spi_w_reg_buf(spi_regs[id], byte); +} + +/* + * @brief 接收1个字节 + * @parm spi spi句柄 + * @parm err 返回错误信息,若err为非空指针,0 成功,< 0 失败,若为空指针,忽略 + * @return 接收的字节 + */ +u8 spi_recv_byte(spi_dev spi, int *err) +{ + u8 id = spi_get_info_id(spi); + int ret; + + spi_dir_in(spi_regs[id]); + spi_w_reg_buf(spi_regs[id], 0xff); + ret = __spi_wait_ok(spi, 1); + if (ret) { + err != NULL ? *err = ret : 0; + return 0; + } + err != NULL ? *err = 0 : 0; + return spi_r_reg_buf(spi_regs[id]); +} + + +/* + * @brief 接收1个字节,不等待pnd,用于中断 + * @parm spi spi句柄 + * @return 接收的字节 + */ +u8 spi_recv_byte_for_isr(spi_dev spi) +{ + u8 id = spi_get_info_id(spi); + + spi_dir_in(spi_regs[id]); + return spi_r_reg_buf(spi_regs[id]); +} + +/* + * @brief 发送并接收1个字节,在8个时钟内完成,仅使用于SPI_MODE_BIDIR_1BIT + * @parm spi spi句柄 + * @parm byte 发送的字节 + * @parm err 返回错误信息,若err为非空指针,0 成功,< 0 失败,若为空指针,忽略 + * @return 接收的字节 + */ +u8 spi_send_recv_byte(spi_dev spi, u8 byte, int *err) +{ + u8 id = spi_get_info_id(spi); + int ret; + + spi_w_reg_buf(spi_regs[id], byte); + ret = __spi_wait_ok(spi, 1); + if (ret) { + err != NULL ? *err = ret : 0; + return 0; + } + err != NULL ? *err = 0 : 0; + return spi_r_reg_buf(spi_regs[id]); +} + +/* + * @brief 设置spi[单向/双向,位数]模式 + * @parm spi spi句柄 + * @parm mode 模式 + * @return null + */ +void spi_set_bit_mode(spi_dev spi, int mode) +{ + u8 id = spi_get_info_id(spi); + u8 port = spi_get_info_port(spi); + u8 role = spi_get_info_role(spi); + + switch (mode) { + case SPI_MODE_BIDIR_1BIT: + spi_bidir(spi_regs[id]); + spi_data_width(spi_regs[id], 0); + break; + case SPI_MODE_UNIDIR_1BIT: + spi_unidir(spi_regs[id]); + spi_data_width(spi_regs[id], 0); + break; + case SPI_MODE_UNIDIR_2BIT: + /* ASSERT(id == 0, "spi%d not support SPI_MODE_UNIDIR_2BIT\n", id); */ + spi_unidir(spi_regs[id]); + spi_data_width(spi_regs[id], 1); + break; + case SPI_MODE_UNIDIR_4BIT: + ASSERT(id == 0, "spi%d not support SPI_MODE_UNIDIR_4BIT\n", id); + spi_unidir(spi_regs[id]); + spi_data_width(spi_regs[id], 2); + break; + } + + port -= 'A'; + if (id == SPI2 && port + 'A' == 'B') { + JL_USB_IO->CON0 |= BIT(11); //IO MODE + spi_io_port_init(spi_io_map[id].io[port].di_pin, 1); + JL_USB_IO->CON0 &= ~BIT(2); //DP DIR OUT + JL_USB_IO->CON0 &= ~BIT(3); //DM DIR OUT + JL_USB_IO->CON0 |= BIT(9); //DP 1.2V digital input en + JL_USB_IO->CON0 |= BIT(10); //DM 1.2V digital input en + } else { + spi_io_port_init(spi_io_map[id].io[port].clk_pin, + role == SPI_ROLE_MASTER ? 0 : 1); + spi_io_port_init(spi_io_map[id].io[port].do_pin, 0); + if (mode == SPI_MODE_BIDIR_1BIT) { + spi_io_port_init(spi_io_map[id].io[port].di_pin, 1); + } else if (mode == SPI_MODE_UNIDIR_2BIT) { + spi_io_port_init(spi_io_map[id].io[port].di_pin, 0); + } else if (mode == SPI_MODE_UNIDIR_4BIT) { + spi_io_port_init(spi_io_map[id].io[port].di_pin, 0); + spi_io_port_init(spi_io_map[id].io[port].d2_pin, 0); + spi_io_port_init(spi_io_map[id].io[port].d3_pin, 0); + } + } +} + +/* + * @brief 打开spi + * @parm spi spi句柄 + * @return 0 成功,< 0 失败 + */ +int spi_open(spi_dev spi) +{ + int err; + u8 id = spi_get_info_id(spi); + u8 port = spi_get_info_port(spi); + u8 mode = spi_get_info_mode(spi); + u8 role = spi_get_info_role(spi); + u32 clock = spi_get_info_clock(spi); + + pSPI_IOMC_CONFIG[id](spi); + + spi_set_bit_mode(spi, mode); + spi_cs_dis(spi_regs[id]); + if (role == SPI_ROLE_MASTER) { + spi_role_master(spi_regs[id]); + } else if (role == SPI_ROLE_SLAVE) { + spi_role_slave(spi_regs[id]); + } + spi_smp_edge_fall(spi_regs[id]); + spi_ud_edge_fall(spi_regs[id]); + spi_cs_idle_h(spi_regs[id]); + spi_clk_idle_l(spi_regs[id]); + spi_clr_pnd(spi_regs[id]); + if ((err = spi_set_baud(spi, clock))) { + log_error("invalid spi baudrate"); + /* return 0; */ + } + spi_w_reg_buf(spi_regs[id], 0);//设定spi初始化后DO口默认电平为低 + spi_enable(spi_regs[id]); + +#if 0 + printf("spi%d port = '%c'\n", id, port); + printf("spi%d clk = %d\n", id, clock); + printf("spi%d mode = %d\n", id, mode); + printf("spi%d role = %d\n", id, role); + printf("spi%d di_pin = %d\n", id, spi_io_map[id].io[port - 'A'].di_pin); + printf("spi%d clk_pin = %d\n", id, spi_io_map[id].io[port - 'A'].clk_pin); + printf("spi%d do_pin = %d\n", id, spi_io_map[id].io[port - 'A'].do_pin); + printf("spi%d d2_pin = %d\n", id, spi_io_map[id].io[port - 'A'].d2_pin); + printf("spi%d d3_pin = %d\n", id, spi_io_map[id].io[port - 'A'].d3_pin); + printf("spi%d CON = %04x\n", id, spi_r_reg_con(spi_regs[id])); + printf("spi%d IOMC1 = %08x\n", id, JL_IOMAP->CON1); +#endif + return 0; +} + +/* + * @brief spi dma接收 + * @parm spi spi句柄 + * @parm buf 接收缓冲区基地址 + * @parm len 期望接收长度 + * @return 实际接收长度,< 0表示失败 + */ +int spi_dma_recv(spi_dev spi, void *buf, u32 len) +{ + u8 id = spi_get_info_id(spi); + + /* ASSERT((u32)buf % 4 == 0, "spi dma addr need 4-aligned"); */ + spi_dir_in(spi_regs[id]); + spi_w_reg_dma_addr(spi_regs[id], (u32)buf); + spi_w_reg_dma_cnt(spi_regs[id], len); + asm("csync"); + if (__spi_wait_ok(spi, len)) { + return -EFAULT; + } + return len; +} + +/* + * @brief spi dma发送 + * @parm spi spi句柄 + * @parm buf 发送缓冲区基地址 + * @parm len 期望发送长度 + * @return 实际发送长度,< 0表示失败 + */ +int spi_dma_send(spi_dev spi, const void *buf, u32 len) +{ + u8 id = spi_get_info_id(spi); + + /* ASSERT((u32)buf % 4 == 0, "spi dma addr need 4-aligned"); */ + spi_dir_out(spi_regs[id]); + spi_w_reg_dma_addr(spi_regs[id], (u32)buf); + spi_w_reg_dma_cnt(spi_regs[id], len); + asm("csync"); + if (__spi_wait_ok(spi, len)) { + return -EFAULT; + } + return len; +} + +/* + * @brief spi 配置dma,不等待pnd,用于中断 + * @parm spi spi句柄 + * @parm buf 缓冲区基地址 + * @parm len 期望长度 + * @parm rw 1 接收 / 0 发送 + * @return null + */ +void spi_dma_set_addr_for_isr(spi_dev spi, void *buf, u32 len, u8 rw) +{ + u8 id = spi_get_info_id(spi); + + /* ASSERT((u32)buf % 4 == 0, "spi dma addr need 4-aligned"); */ + rw ? spi_dir_in(spi_regs[id]) : spi_dir_out(spi_regs[id]); + spi_w_reg_dma_addr(spi_regs[id], (u32)buf); + spi_w_reg_dma_cnt(spi_regs[id], len); +} + +/* + * @brief 中断使能 + * @parm spi spi句柄 + * @parm en 1 使能,0 失能 + * @return null + */ +void spi_set_ie(spi_dev spi, u8 en) +{ + u8 id = spi_get_info_id(spi); + en ? spi_ie_en(spi_regs[id]) : spi_ie_dis(spi_regs[id]); +} + +/* + * @brief 判断中断标志 + * @parm spi spi句柄 + * @return 0 / 1 + */ +u8 spi_get_pending(spi_dev spi) +{ + u8 id = spi_get_info_id(spi); + return spi_pnd(spi_regs[id]) ? 1 : 0; +} + +/* + * @brief 清除中断标志 + * @parm spi spi句柄 + * @return null + */ +void spi_clear_pending(spi_dev spi) +{ + u8 id = spi_get_info_id(spi); + spi_clr_pnd(spi_regs[id]); +} + +/* + * @brief 关闭spi + * @parm spi spi句柄 + * @return null + */ +void spi_close(spi_dev spi) +{ + u8 id = spi_get_info_id(spi); + u8 port = spi_get_info_port(spi); + u8 mode = spi_get_info_mode(spi); + + port -= 'A'; + if (id == SPI2 && port + 'A' == 'B') { + spi_io_port_uninit(spi_io_map[id].io[port].di_pin); + JL_USB_IO->CON0 |= BIT(2); //DP DIR IN + JL_USB_IO->CON0 |= BIT(3); //DM DIR IN + JL_USB_IO->CON0 &= ~BIT(9); //DP 1.2V digital input dis + JL_USB_IO->CON0 &= ~BIT(10); //DM 1.2V digital input dis + } else { + spi_io_port_uninit(spi_io_map[id].io[port].clk_pin); + spi_io_port_uninit(spi_io_map[id].io[port].do_pin); + if (mode == SPI_MODE_BIDIR_1BIT) { + spi_io_port_uninit(spi_io_map[id].io[port].di_pin); + } else if (mode == SPI_MODE_UNIDIR_2BIT) { + spi_io_port_uninit(spi_io_map[id].io[port].di_pin); + } else if (mode == SPI_MODE_UNIDIR_4BIT) { + spi_io_port_uninit(spi_io_map[id].io[port].di_pin); + spi_io_port_uninit(spi_io_map[id].io[port].d2_pin); + spi_io_port_uninit(spi_io_map[id].io[port].d3_pin); + } + } + spi_disable(spi_regs[id]); +} +void spi_disable_for_ota() +{ + for (int i = 0; i < 2; i++) { + spi_disable(spi_regs[i]); + } +} + +REGISTER_UPDATE_TARGET(spi_update_target) = { + .name = "spi", + .driver_close = spi_disable_for_ota, +}; diff --git a/cpu/br23/spi_test.c b/cpu/br23/spi_test.c new file mode 100644 index 0000000..986da1d --- /dev/null +++ b/cpu/br23/spi_test.c @@ -0,0 +1,206 @@ +#include "system/includes.h" +#include "media/includes.h" +#include "asm/spi.h" +#include "generic/log.h" + +#if 0 +/* + [[[ README ]]] + 1. 本spi测试demo提供了spi.c的API使用例程,测试方式为两个spi的环回测试。 + spi1设置为主机模式,spi2设置为从机模式,spi1发送数据到spi2,然后接收spi2 + 原样返回的数据,然后比较发送出去的数据与接收的数据是否一致,一致则说明 + 验证通过。 + 2. 本demo涉及BYTE收发测试及DMA收发测试,通过宏SPI_TEST_MODE选择。另外 + demo还涉及到spi中断中调用可用于中断的spi API的使用。 + 3. spi.c的API不包含CS引脚,CS由API以外控制。 + 4. 请在board_xxx.c中定义配置结构体,例如用到spi1,需要定义spi1_p_data, + 否则编译出错。 + 5. spi的DMA地址需要4字节对齐。 + 6. 虽然spi.c的API带有spi0,但在有挂spi flash的芯片上使用可能会出问题, + 避免使用spi0。 + +*/ + +#define SPI1_CS_OUT() \ + do { \ + JL_PORTB->DIR &= ~BIT(4); \ + JL_PORTB->DIE |= BIT(4); \ + JL_PORTB->PU &= ~BIT(4); \ + JL_PORTB->PD &= ~BIT(4); \ + } while(0) +#define SPI1_CS_L() (JL_PORTB->OUT &= ~BIT(4)) +#define SPI1_CS_H() (JL_PORTB->OUT |= BIT(4)) + +#define SPI2_CS_IN() \ + do { \ + JL_PORTA->DIR |= BIT(3); \ + JL_PORTA->DIE |= BIT(3); \ + JL_PORTA->PU &= ~BIT(3); \ + JL_PORTA->PD &= ~BIT(3); \ + } while (0) +#define SPI2_READ_CS() (JL_PORTA->IN & BIT(3)) + +static u8 slave_dir = 1; +static u8 spi1_send_buf[100] __attribute__((aligned(4))); +static u8 spi1_recv_buf[100] __attribute__((aligned(4))); +static u8 spi2_send_buf[100] __attribute__((aligned(4))); +static u8 spi2_recv_buf[100] __attribute__((aligned(4))); + +static spi_dev spi1_hdl = 1; +static spi_dev spi2_hdl = 2; + +#define SPI_TEST_BYTE_MODE 0x01 +#define SPI_TEST_DMA_MODE 0x02 +//测试模式选择 +#define SPI_TEST_MODE SPI_TEST_BYTE_MODE + +static void my_put_u8hex(u8 b) +{ + u8 dat; + dat = b / 16; + if (dat >= 0 && dat <= 9) { + putchar('0' + dat); + } else { + putchar('A' + dat - 10); + } + dat = b % 16; + if (dat >= 0 && dat <= 9) { + putchar('0' + dat); + } else { + putchar('A' + dat - 10); + } + putchar(' '); +} + +//中断函数,需以下特殊声明 +__attribute__((interrupt(""))) +static void spi2_isr() +{ + static int i = 0; + if (spi_get_pending(spi2_hdl)) { + spi_clear_pending(spi2_hdl); + if (SPI2_READ_CS()) { + return; + } +#if SPI_TEST_MODE == SPI_TEST_BYTE_MODE + if (slave_dir == 1) { + spi2_recv_buf[i] = spi_recv_byte_for_isr(spi2_hdl); + spi_send_byte_for_isr(spi2_hdl, spi2_recv_buf[i]); + i >= 100 ? i = 0 : i++; + slave_dir = 0; + } else { + slave_dir = 1; + } +#elif SPI_TEST_MODE == SPI_TEST_DMA_MODE + if (slave_dir == 1) { + spi_dma_set_addr_for_isr(spi2_hdl, spi2_recv_buf, 100, 0); + slave_dir = 0; + } else { + slave_dir = 1; + } +#endif + } +} + +#if 1 //仅用于spi demo,正式工程请放到board_xxx.c文件中 +/* const struct spi_platform_data spi0_p_data = { */ +/* .port = 'A', */ +/* .mode = SPI_MODE_BIDIR_1BIT, */ +/* .clk = 1000000, */ +/* .role = SPI_ROLE_MASTER, */ +/* }; */ + +const struct spi_platform_data spi1_p_data = { + .port = 'A', + .mode = SPI_MODE_BIDIR_1BIT, + .clk = 1000000, + .role = SPI_ROLE_MASTER, +}; + +const struct spi_platform_data spi2_p_data = { + .port = 'A', + .mode = SPI_MODE_BIDIR_1BIT, + .clk = 1000000, + .role = SPI_ROLE_SLAVE, +}; +#endif + + +void spi_test_main() +{ + int i; + int err; + + spi_open(spi1_hdl); + spi_open(spi2_hdl); + spi_set_ie(spi2_hdl, 1); + //配置中断优先级,中断函数 + request_irq(IRQ_SPI2_IDX, 3, spi2_isr, 0); + + SPI1_CS_OUT(); + SPI2_CS_IN(); + SPI1_CS_H(); + for (i = 0; i < 100; i++) { + spi1_send_buf[i] = i % 26 + 'A'; + spi1_recv_buf[i] = 0; + } + puts(">>> spi test start\n"); +#if SPI_TEST_MODE == SPI_TEST_BYTE_MODE + SPI1_CS_L(); + for (i = 0; i < 100; i++) { + err = spi_send_byte(spi1_hdl, spi1_send_buf[i]); + if (err) { + puts("spi1 byte send timeout\n"); + break; + } + delay(100); + spi1_recv_buf[i] = spi_recv_byte(spi1_hdl, &err); + if (err) { + puts("spi1 byte recv timeout\n"); + break; + } + delay(100); + } + SPI1_CS_H(); +#elif SPI_TEST_MODE == SPI_TEST_DMA_MODE + spi_dma_set_addr_for_isr(spi2_hdl, spi2_recv_buf, 100, 1); + SPI1_CS_L(); + err = spi_dma_send(spi1_hdl, spi1_send_buf, 100); + if (err < 0) { + puts("spi1 dma send timeout\n"); + goto __out_dma; + } + //delay(100); + err = spi_dma_recv(spi1_hdl, spi1_recv_buf, 100); + if (err < 0) { + puts("spi1 dma recv timeout\n"); + goto __out_dma; + } + //delay(100); +__out_dma: + SPI1_CS_H(); +#endif + puts("<<< spi test end\n"); + + puts("\nspi master receivce buffer:\n"); + for (i = 0; i < 100; i++) { + //my_put_u8hex(spi1_recv_buf[i]); + putchar(spi1_recv_buf[i]), putchar(0x20); + if (i % 16 == 15) { + putchar('\n'); + } + } + if (i % 16) { + putchar('\n'); + } + + if (!memcmp(spi1_send_buf, spi1_recv_buf, 100)) { + puts("\nspi test pass\n"); + } else { + puts("\nspi test fail\n"); + } + + spi_close(spi1_hdl); + spi_close(spi2_hdl); +} +#endif diff --git a/cpu/br23/tools/ac695x配置入口.jlxproj b/cpu/br23/tools/ac695x配置入口.jlxproj new file mode 100644 index 0000000..989d747 --- /dev/null +++ b/cpu/br23/tools/ac695x配置入口.jlxproj @@ -0,0 +1,101 @@ +package.path = package.path .. ';' .. cfg.dir .. '/?.lua' + +local lang_en = { + ["AC696X"]="", + ["调音工具"]="Audio Config Tool", + ["检查依赖的软件包是否更新"]="Check Update", + ["配置工具"]="Config Tool", + ["生成配置\n(生成 cfg_tool.bin)"]="Generate Config\n(generate cfg_tool.bin)", + ["配置音效\n(生成 eq_cfg_hw.bin)"]="Generate Audio Effect\n(generate eq_cfg_hw.bin)", + ["打开"]="Open", + ["路径"]="Path", +}; + +cfg:setTranslate("en", lang_en); + +local rootDir = cfg.rootDir; + +local pkgman = rootDir .. "/pkgman.exe"; +-- 依赖的软件包 +local req_pkgs = {"efftool", "sdktool", "luaconfig", "3rd", "sdkaudiocvt"}; +local check_prog = {pkgman}; + +local missing_pkgs = {}; +for k, v in pairs(req_pkgs) do + if cfg:utilsGetPkg(v) == nil then + -- 检查是否缺失依赖的软件 + table.insert(missing_pkgs, v) + end +end + +for k, v in pairs(missing_pkgs) do table.insert(check_prog, v) end + +if #missing_pkgs ~= 0 then + if (cfg:runProg(check_prog) ~= 0) then + cfg:msgBox("warn", "软件包不是最新,可能会出现问题"); + end +end + +local sdktool = rootDir .. '/' .. cfg:utilsGetPkg("sdktool").run; +local luaconfig = rootDir .. '/' .. cfg:utilsGetPkg("luaconfig").run; +local projdir = cfg.dir .. '/download/'; +local efftool = rootDir .. '/' .. cfg:utilsGetPkg("efftool").run; +local title = "AC695X-SDK"; + +local default_bin_path = cfg.dir .. '/cfg_tool.bin'; +local default_tone_path = cfg.dir .. '/tone.cfg'; +local sdk_jcf_path = cfg.dir .. '/sdk.jcf'; + +local cfgtool_entry_view = cfg:stEntry(":/uires/icon_settle.png", + "配置工具", "生成配置\n(生成 cfg_tool.bin)", + cfg:stButton2("路径", "", "secondary", function () + cfg:utilsShellShow(luaconfig); + end), + cfg:stButton2("打开", "", "main", function () + cfg:runProgNoWait({luaconfig, sdk_jcf_path, + '-p', cfg.dir, + '-r', rootDir, + '-b', default_bin_path, + '-t', default_tone_path}); + end)); + +local efftool_entry_view = cfg:stEntry(":/uires/icon_eq.png", + "调音工具", "配置音效\n(生成 eq_cfg_hw.bin)", + cfg:stButton2("路径", "", "secondary", function () + cfg:utilsShellShow(efftool); + end), + cfg:stButton2("打开", "", "main", function () + cfg:runProgNoWait({efftool, '--type', 'atk'}); + end)) + +local check_allupdate_btn = cfg:stButton2("检查依赖的软件包是否更新", "", "secondary", function () + local check_prog = {pkgman}; + for k, v in pairs(req_pkgs) do table.insert(check_prog, v) end + if (cfg:runProg(check_prog) ~= 0) then + if(cfg.lang == "zh") then + cfg:msgBox("warn", "软件包不是最新,可能会出现问题"); + else + cfg:msgBox("warn", "software Packages are not up-to-date and may have problems"); + end + else + if(cfg.lang == "zh") then + cfg:msgBox("info", "已经是最新"); + else + cfg:msgBox("info", "software Packages are up-to-date"); + end + end +end); + +local layout = cfg:vBox{ cfg:stGroup(title, cfg:stHScroll ( cfg:vBox { + cfgtool_entry_view, + efftool_entry_view, + check_allupdate_btn, +}))}; + + +cfg:addKeyInfo("jlxproj.width", "600"); +cfg:addKeyInfo("jlxproj.height", "400"); +cfg:addKeyInfo("jlxproj.title", title); + + +cfg:setLayout(layout) diff --git a/cpu/br23/tools/br23loader.bin b/cpu/br23/tools/br23loader.bin new file mode 100644 index 0000000..79d44b5 Binary files /dev/null and b/cpu/br23/tools/br23loader.bin differ diff --git a/cpu/br23/tools/br23loader.uart b/cpu/br23/tools/br23loader.uart new file mode 100644 index 0000000..f8286fb Binary files /dev/null and b/cpu/br23/tools/br23loader.uart differ diff --git a/cpu/br23/tools/cfg_tool.bin b/cpu/br23/tools/cfg_tool.bin new file mode 100644 index 0000000..8b0e75e Binary files /dev/null and b/cpu/br23/tools/cfg_tool.bin differ diff --git a/cpu/br23/tools/cfg_tool_state_complete.lua b/cpu/br23/tools/cfg_tool_state_complete.lua new file mode 100644 index 0000000..b9a4dff --- /dev/null +++ b/cpu/br23/tools/cfg_tool_state_complete.lua @@ -0,0 +1 @@ +{["1"]="695310\095GBT",["蓝牙名字开关1"]=1,["对耳配对码(2字节)"]=65535,["蓝牙名字开关12"]=0,["lrc_ws_inc"]=480,["lrc_ws_init"]=400,["bt_osc_ws_inc"]=480,["低功耗蓝牙MAC地址:"]={255,255,255,255,255,255},["bt_osc_ws_init"]=140,["蓝牙名字开关13"]=0,["20"]="jl\095soundbox\09520",["经典蓝牙发射功率:"]=7,["osc_change_mode"]=1,["经典蓝牙MAC地址:"]={255,255,255,255,255,255},["17"]="jl\095soundbox\09517",["18"]="jl\095soundbox\09518",["16"]="jl\095soundbox\09516",["蓝牙名字开关11"]=0,["14"]="jl\095soundbox\09514",["13"]="jl\095soundbox\09513",["蓝牙名字开关16"]=0,["蓝牙名字开关17"]=0,["蓝牙名字开关18"]=0,["12"]="jl\095soundbox\09512",["15"]="jl\095soundbox\09515",["19"]="jl\095soundbox\09519",["蓝牙名字开关19"]=0,["蓝牙名字开关14"]=0,["低功耗蓝牙名字"]="jl\095soundbox\095ble\095lihui",["10"]="jl\095soundbox\09510",["蓝牙名字开关15"]=0,["蓝牙名字开关20"]=0,["低功耗蓝牙发射功率:"]=10,["没有连接自动关机时间配置: "]=3,["蓝牙名字开关3"]=0,["蓝牙名字开关9"]=0,["蓝牙名字开关4"]=0,["4"]="jl\095soundbox\0954",["蓝牙名字开关5"]=0,["蓝牙名字开关2"]=0,["6"]="jl\095soundbox\0956",["蓝牙名字开关10"]=0,["蓝牙名字开关7"]=0,["2"]="jl\095soundbox\0952",["5"]="jl\095soundbox\0955",["蓝牙名字开关6"]=0,["11"]="jl\095soundbox\09511",["3"]="jl\095soundbox\0953",["8"]="jl\095soundbox\0958",["7"]="jl\095soundbox\0957",["蓝牙名字开关8"]=0,["9"]="jl\095soundbox\0959",["comvol期望音量-1 2"]=0.000000,["comvol期望音量-1 4"]=0.000000,["comvol期望音量-1 6"]=0.000000,["DT_SPEECH_THR"]=-40.000000,["comvol期望音量-1 8"]=0.000000,["提示音"]={{"0","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\0470\046wtg",0},{"1","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\0471\046wtg",1},{"2","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\0472\046wtg",2},{"3","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\0473\046wtg",3},{"4","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\0474\046wtg",4},{"5","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\0475\046wtg",5},{"6","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\0476\046wtg",6},{"7","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\0477\046wtg",7},{"8","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\0478\046wtg",8},{"9","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\0479\046wtg",9},{"bt","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047bt\046wtg",10},{"bt\095conn","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047bt\095conn\046wtg",11},{"bt\095dconn","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047bt\095dconn\046wtg",12},{"tws\095conn","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047tws\095conn\046wtg",13},{"tws\095dconn","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047tws\095dconn\046wtg",14},{"low\095power","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047low\095power\046wtg",15},{"power\095off","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047power\095off\046wtg",16},{"power\095on","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047power\095on\046wtg",17},{"ring","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047ring\046wtg",18},{"\233\133\141\229\175\185\230\168\161\229\188\143","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047paired\046wtg",27},{"linein\230\168\161\229\188\143","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047linein\046wtg",27},{"music\230\168\161\229\188\143","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047music\046wtg",27},{"fm\230\168\161\229\188\143","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047fm\046wtg",27},{"record\230\168\161\229\188\143","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047record\046wtg",27},{"rtc\230\168\161\229\188\143","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047rtc\046wtg",27},{"pc\230\168\161\229\188\143","D\058\047JLSDK\0470\046test\04720231023\229\141\142\233\146\156\232\138\175695310\232\139\185\230\158\156\231\148\181\232\132\145\230\151\160\230\179\149\230\142\167\229\136\182\233\159\179\233\135\143\228\184\141\229\144\140\230\173\165\047ac695n\095soundbox\095sdk\047cpu\047br23\047tools\047extra\095tones\047pc\046wtg",27}},["comvol使能-1-3"]=0,["AEC_Mode"]=23,["comvol使能-1-4"]=0,["comvol使能-1-5"]=0,["DT_MIN_GAIN"]=0.000000,["comvol期望音量-1 1"]=0.000000,["ECHO_PRESENT_THR"]=-70.000000,["comvol使能-1-1"]=0,["comvol期望音量-1 5"]=0.000000,["comvol期望音量-1 7"]=0.000000,["comvol使能-1-7"]=0,["comvol使能-1-6"]=0,["NLP_MIN_SUPPRESS"]=4.000000,["ANS_AGGRESS"]=1.250000,["ANS_SUPPRESS"]=0.090000,["comvol使能-1-2"]=0,["comvol期望音量-1 3"]=0.000000,["固定模拟音量"]=0,["NLP_AGGRESS_FACTOR"]=-3.000000,["MIC模式选择"]=0,["偏置电阻选择:"]=8,["MICLDO电压选择:"]=2,["DAC_Gain"]=22,["NS"]=1,["AGC"]=1,["AEC_DT_AGGRESS"]=1.000000,["AEC_REFENGTHR"]=-70.000000,["DT_FADE_IN"]=1.300000,["DT_FADE_OUT"]=1.300000,["MIC_Gain"]=3,["NDT_FADE_OUT"]=1.300000,["NLP"]=1,["NDT_MAX_GAIN"]=6.000000,["EQ"]=1,["NDT_MIN_GAIN"]=3.000000,["NDT_FADE_IN"]=1.300000,["DT_MAX_GAIN"]=12.000000,["AEC"]=1,["NDT_SPEECH_THR"]=-50.000000,["comvol期望音量-1 21"]=0.000000,["comvol期望音量-1 14"]=0.000000,["comvol期望音量-1 9"]=0.000000,["comvol使能-1-14"]=0,["comvol使能-1-16"]=0,["comvol使能-1-15"]=0,["comvol期望音量-1 18"]=0.000000,["comvol使能-1-18"]=0,["comvol期望音量-1 15"]=0.000000,["comvol期望音量-1 19"]=0.000000,["comvol使能-1-10"]=0,["comvol期望音量-1 11"]=0.000000,["comvol使能-1-11"]=0,["comvol使能-1-13"]=0,["comvol使能-1-20"]=0,["comvol使能-1-12"]=0,["comvol使能-1-21"]=0,["comvol期望音量-1 12"]=0.000000,["comvol使能-1-9"]=0,["comvol期望音量-1 23"]=0.000000,["comvol使能-1-23"]=0,["comvol期望音量-1 24"]=0.000000,["comvol使能-1-8"]=0,["comvol期望音量-1 10"]=0.000000,["comvol期望音量-1 13"]=0.000000,["comvol期望音量-1 17"]=0.000000,["comvol使能-1-19"]=0,["comvol期望音量-1 22"]=0.000000,["comvol使能-1-22"]=0,["comvol期望音量-1 20"]=0.000000,["comvol使能-1-17"]=0,["comvol期望音量-1 16"]=0.000000,["comvol期望音量-1 28"]=0.000000,["comvol使能-1-31"]=0,["comvol使能-1-26"]=0,["comvol期望音量-1 27"]=0.000000,["comvol期望音量-1 32"]=0.000000,["comvol使能-1-25"]=0,["comvol使能-1-28"]=0,["comvol期望音量-1 30"]=0.000000,["comvol使能-1-24"]=0,["comvol期望音量-1 26"]=0.000000,["comvol期望音量-1 29"]=0.000000,["comvol期望音量-1 25"]=0.000000,["comvol期望音量-1 31"]=0.000000,["comvol使能-1-32"]=0,["comvol使能-1-29"]=0,["comvol使能-1-30"]=0,["comvol期望音量-1 33"]=0.000000,["comvol使能-1-27"]=0,["comvol期望音量-1 39"]=0.000000,["comvol使能-1-45"]=0,["comvol期望音量-1 46"]=0.000000,["comvol使能-1-34"]=0,["comvol期望音量-1 41"]=0.000000,["comvol使能-1-40"]=0,["comvol期望音量-1 42"]=0.000000,["comvol使能-1-41"]=0,["comvol使能-1-42"]=0,["comvol期望音量-1 47"]=0.000000,["comvol使能-1-35"]=0,["comvol使能-1-38"]=0,["comvol使能-1-39"]=0,["comvol期望音量-1 44"]=0.000000,["comvol使能-1-46"]=0,["comvol期望音量-1 48"]=0.000000,["comvol使能-1-48"]=0,["comvol使能-1-47"]=0,["comvol期望音量-1 49"]=0.000000,["comvol期望音量-1 43"]=0.000000,["comvol使能-1-36"]=0,["comvol期望音量-1 36"]=0.000000,["comvol期望音量-1 45"]=0.000000,["comvol期望音量-1 35"]=0.000000,["comvol使能-1-37"]=0,["comvol期望音量-1 40"]=0.000000,["comvol使能-1-43"]=0,["comvol使能-1-33"]=0,["comvol使能-1-44"]=0,["comvol期望音量-1 37"]=0.000000,["comvol期望音量-1 34"]=0.000000,["comvol期望音量-1 38"]=0.000000,["comvol使能-1-52"]=0,["comvol期望音量-1 55"]=0.000000,["comvol期望音量-1 52"]=0.000000,["comvol期望音量-1 58"]=0.000000,["comvol使能-1-50"]=0,["comvol使能-1-56"]=0,["comvol期望音量-1 50"]=0.000000,["comvol使能-1-51"]=0,["comvol期望音量-1 54"]=0.000000,["comvol期望音量-1 57"]=0.000000,["comvol期望音量-1 56"]=0.000000,["comvol使能-1-49"]=0,["comvol使能-1-57"]=0,["comvol使能-1-54"]=0,["comvol使能-1-55"]=0,["comvol期望音量-1 51"]=0.000000,["comvol期望音量-1 53"]=0.000000,["comvol使能-1-53"]=0,["comvol期望音量-1 67"]=0.000000,["comvol使能-1-68"]=0,["comvol使能-1-70"]=0,["comvol期望音量-1 63"]=0.000000,["comvol使能-1-64"]=0,["comvol使能-1-72"]=0,["comvol期望音量-1 74"]=0.000000,["comvol期望音量-1 61"]=0.000000,["comvol使能-1-63"]=0,["comvol使能-1-66"]=0,["comvol期望音量-1 64"]=0.000000,["comvol期望音量-1 60"]=0.000000,["comvol期望音量-1 68"]=0.000000,["comvol期望音量-1 69"]=0.000000,["comvol期望音量-1 70"]=0.000000,["comvol使能-1-62"]=0,["comvol期望音量-1 62"]=0.000000,["comvol使能-1-58"]=0,["comvol使能-1-69"]=0,["comvol期望音量-1 71"]=0.000000,["comvol使能-1-71"]=0,["comvol使能-1-60"]=0,["comvol期望音量-1 73"]=0.000000,["comvol使能-1-59"]=0,["comvol期望音量-1 72"]=0.000000,["comvol使能-1-67"]=0,["comvol使能-1-73"]=0,["comvol使能-1-61"]=0,["comvol期望音量-1 65"]=0.000000,["comvol使能-1-65"]=0,["comvol期望音量-1 66"]=0.000000,["comvol期望音量-1 59"]=0.000000,["comvol期望音量-1 75"]=0.000000,["comvol使能-1-79"]=0,["comvol使能-1-77"]=0,["comvol期望音量-1 81"]=0.000000,["comvol期望音量-1 82"]=0.000000,["comvol期望音量-1 80"]=0.000000,["comvol期望音量-1 77"]=0.000000,["comvol使能-1-82"]=0,["comvol期望音量-1 79"]=0.000000,["comvol期望音量-1 83"]=0.000000,["comvol使能-1-74"]=0,["comvol期望音量-1 76"]=0.000000,["comvol使能-1-80"]=0,["comvol使能-1-75"]=0,["comvol使能-1-76"]=0,["comvol期望音量-1 78"]=0.000000,["comvol使能-1-78"]=0,["comvol使能-1-81"]=0,["comvol期望音量-1 88"]=0.000000,["comvol使能-1-97"]=0,["comvol期望音量-1 92"]=0.000000,["comvol期望音量-1 84"]=0.000000,["comvol使能-1-92"]=0,["comvol使能-1-93"]=0,["comvol期望音量-1 98"]=0.000000,["comvol使能-1-87"]=0,["comvol使能-1-98"]=0,["comvol期望音量-1 91"]=0.000000,["comvol期望音量-1 85"]=0.000000,["comvol期望音量-1 99"]=0.000000,["comvol使能-1-91"]=0,["comvol使能-1-89"]=0,["comvol使能-1-96"]=0,["comvol期望音量-1 96"]=0.000000,["comvol期望音量-1 95"]=0.000000,["comvol期望音量-1 86"]=0.000000,["comvol使能-1-88"]=0,["comvol期望音量-1 93"]=0.000000,["comvol期望音量-1 90"]=0.000000,["comvol使能-1-83"]=0,["comvol使能-1-84"]=0,["comvol期望音量-1 87"]=0.000000,["comvol期望音量-1 89"]=0.000000,["comvol期望音量-1 94"]=0.000000,["comvol使能-1-94"]=0,["comvol使能-1-86"]=0,["comvol使能-1-85"]=0,["comvol使能-1-90"]=0,["comvol使能-1-95"]=0,["comvol期望音量-1 97"]=0.000000,["comvol期望音量-out-x-1-3"]=0,["comvol期望音量-out-avol1-2"]=0,["comvol期望音量-out-avol1-3"]=0,["comvol期望音量-out-avol-zero1"]=0,["comvol期望音量-1 100"]=0.000000,["comvol使能-1-100"]=0,["comvol期望音量-out-avol1-4"]=0,["comvol期望音量-out-avol1-5"]=0,["comvol期望音量-out-x-1-5"]=0,["comvol使能-1-99"]=0,["comvol期望音量-out-x-zero1"]=0,["comvol期望音量-out-x-1-1"]=0,["comvol期望音量-out-x-1-2"]=0,["comvol期望音量-out-x-1-6"]=0,["comvol期望音量-out-avol1-6"]=0,["comvol期望音量-out-x-1-4"]=0,["comvol总是使能-1-"]=1,["comvol期望音量-out-avol1-1"]=0,["comvol期望音量-out-avol1-17"]=0,["comvol期望音量-out-x-1-10"]=0,["comvol期望音量-out-avol1-11"]=0,["comvol期望音量-out-x-1-18"]=0,["comvol期望音量-out-avol1-12"]=0,["comvol期望音量-out-x-1-7"]=0,["comvol期望音量-out-avol1-10"]=0,["comvol期望音量-out-x-1-14"]=0,["comvol期望音量-out-x-1-15"]=0,["comvol期望音量-out-x-1-20"]=0,["comvol期望音量-out-avol1-20"]=0,["comvol期望音量-out-x-1-16"]=0,["comvol期望音量-out-x-1-21"]=0,["comvol期望音量-out-x-1-9"]=0,["comvol期望音量-out-avol1-21"]=0,["comvol期望音量-out-avol1-14"]=0,["comvol期望音量-out-x-1-22"]=0,["comvol期望音量-out-avol1-22"]=0,["comvol期望音量-out-x-1-12"]=0,["comvol期望音量-out-avol1-13"]=0,["comvol期望音量-out-avol1-16"]=0,["comvol期望音量-out-x-1-8"]=0,["comvol期望音量-out-x-1-17"]=0,["comvol期望音量-out-avol1-18"]=0,["comvol期望音量-out-avol1-15"]=0,["comvol期望音量-out-x-1-19"]=0,["comvol期望音量-out-avol1-19"]=0,["comvol期望音量-out-avol1-8"]=0,["comvol期望音量-out-avol1-7"]=0,["comvol期望音量-out-avol1-9"]=0,["comvol期望音量-out-x-1-11"]=0,["comvol期望音量-out-x-1-13"]=0,["comvol期望音量-out-x-1-23"]=0,["comvol期望音量-out-avol1-25"]=0,["comvol期望音量-out-avol1-27"]=0,["comvol期望音量-out-avol1-24"]=0,["comvol期望音量-out-x-1-24"]=0,["comvol期望音量-out-x-1-25"]=0,["comvol期望音量-out-avol1-26"]=0,["comvol期望音量-out-x-1-28"]=0,["comvol期望音量-out-avol1-29"]=0,["comvol期望音量-out-x-1-30"]=0,["comvol期望音量-out-x-1-27"]=0,["comvol期望音量-out-avol1-23"]=0,["comvol期望音量-out-avol1-30"]=0,["comvol期望音量-out-x-1-31"]=0,["comvol期望音量-out-avol1-31"]=0,["comvol期望音量-out-avol1-28"]=0,["comvol期望音量-out-x-1-26"]=0,["comvol期望音量-out-x-1-29"]=0,["comvol期望音量-out-x-1-69"]=0,["comvol期望音量-out-x-1-72"]=0,["comvol期望音量-out-avol1-68"]=0,["comvol期望音量-out-avol1-70"]=0,["comvol期望音量-out-avol1-72"]=0,["comvol期望音量-out-avol1-71"]=0,["comvol期望音量-out-avol1-74"]=0,["comvol期望音量-out-x-1-78"]=0,["comvol期望音量-out-x-1-70"]=0,["comvol期望音量-out-x-1-74"]=0,["comvol期望音量-out-avol1-78"]=0,["comvol期望音量-out-x-1-80"]=0,["comvol期望音量-out-avol1-80"]=0,["comvol期望音量-out-x-1-81"]=0,["comvol期望音量-out-avol1-81"]=0,["comvol期望音量-out-x-1-71"]=0,["comvol期望音量-out-x-1-75"]=0,["comvol期望音量-out-x-1-79"]=0,["comvol期望音量-out-avol1-73"]=0,["comvol期望音量-out-x-1-68"]=0,["comvol期望音量-out-x-1-76"]=0,["comvol期望音量-out-avol1-79"]=0,["comvol期望音量-out-x-1-82"]=0,["comvol期望音量-out-avol1-82"]=0,["comvol期望音量-out-x-1-73"]=0,["comvol期望音量-out-avol1-69"]=0,["comvol期望音量-out-avol1-76"]=0,["comvol期望音量-out-x-1-77"]=0,["comvol期望音量-out-avol1-77"]=0,["comvol期望音量-out-avol1-75"]=0,["comvol期望音量-out-x-1-67"]=0,["comvol期望音量-out-avol1-67"]=0,["comvol期望音量-out-avol1-45"]=0,["comvol期望音量-out-x-1-43"]=0,["comvol期望音量-out-avol1-35"]=0,["comvol期望音量-out-x-1-38"]=0,["comvol期望音量-out-avol1-38"]=0,["comvol期望音量-out-x-1-39"]=0,["comvol期望音量-out-avol1-34"]=0,["comvol期望音量-out-x-1-37"]=0,["comvol期望音量-out-x-1-40"]=0,["comvol期望音量-out-avol1-33"]=0,["comvol期望音量-out-x-1-36"]=0,["comvol期望音量-out-x-1-34"]=0,["comvol期望音量-out-avol1-36"]=0,["comvol期望音量-out-avol1-41"]=0,["comvol期望音量-out-x-1-32"]=0,["comvol期望音量-out-avol1-42"]=0,["comvol期望音量-out-x-1-33"]=0,["comvol期望音量-out-avol1-43"]=0,["comvol期望音量-out-x-1-35"]=0,["comvol期望音量-out-x-1-44"]=0,["comvol期望音量-out-avol1-44"]=0,["comvol期望音量-out-x-1-45"]=0,["comvol期望音量-out-avol1-39"]=0,["comvol期望音量-out-x-1-42"]=0,["comvol期望音量-out-x-1-41"]=0,["comvol期望音量-out-x-1-46"]=0,["comvol期望音量-out-avol1-46"]=0,["comvol期望音量-out-x-1-47"]=0,["comvol期望音量-out-avol1-47"]=0,["comvol期望音量-out-avol1-32"]=0,["comvol期望音量-out-avol1-37"]=0,["comvol期望音量-out-avol1-40"]=0,["comvol期望音量-out-avol1-57"]=0,["comvol期望音量-out-avol1-58"]=0,["comvol期望音量-out-avol1-54"]=0,["comvol期望音量-out-avol1-55"]=0,["comvol期望音量-out-avol1-52"]=0,["comvol期望音量-out-avol1-48"]=0,["comvol期望音量-out-avol1-56"]=0,["comvol期望音量-out-x-1-58"]=0,["comvol期望音量-out-avol1-50"]=0,["comvol期望音量-out-avol1-59"]=0,["comvol期望音量-out-x-1-60"]=0,["comvol期望音量-out-avol1-60"]=0,["comvol期望音量-out-x-1-61"]=0,["comvol期望音量-out-avol1-61"]=0,["comvol期望音量-out-x-1-48"]=0,["comvol期望音量-out-x-1-62"]=0,["comvol期望音量-out-avol1-51"]=0,["comvol期望音量-out-x-1-63"]=0,["comvol期望音量-out-x-1-50"]=0,["comvol期望音量-out-x-1-51"]=0,["comvol期望音量-out-avol1-62"]=0,["comvol期望音量-out-avol1-63"]=0,["comvol期望音量-out-avol1-53"]=0,["comvol期望音量-out-avol1-49"]=0,["comvol期望音量-out-x-1-52"]=0,["comvol期望音量-out-x-1-53"]=0,["comvol期望音量-out-x-1-55"]=0,["comvol期望音量-out-x-1-56"]=0,["comvol期望音量-out-x-1-59"]=0,["comvol期望音量-out-x-1-57"]=0,["comvol期望音量-out-x-1-49"]=0,["comvol期望音量-out-x-1-54"]=0,["comvol期望音量-out-avol1-65"]=0,["comvol期望音量-out-x-1-65"]=0,["comvol期望音量-out-x-1-64"]=0,["comvol期望音量-out-avol1-64"]=0,["comvol期望音量-out-x-1-66"]=0,["comvol期望音量-out-avol1-66"]=0,["comvol使能-2-27"]=0,["comvol期望音量-2 30"]=0.000000,["comvol使能-2-16"]=0,["comvol使能-2-15"]=0,["comvol期望音量-2 22"]=0.000000,["comvol期望音量-2 15"]=0.000000,["comvol使能-2-22"]=0,["comvol使能-2-17"]=0,["comvol期望音量-2 25"]=0.000000,["comvol使能-2-21"]=0,["comvol使能-2-19"]=0,["comvol使能-2-18"]=0,["comvol使能-2-23"]=0,["comvol期望音量-2 19"]=0.000000,["comvol期望音量-2 23"]=0.000000,["comvol使能-2-25"]=0,["comvol期望音量-2 16"]=0.000000,["comvol使能-2-24"]=0,["comvol使能-2-26"]=0,["comvol期望音量-2 27"]=0.000000,["comvol期望音量-2 28"]=0.000000,["comvol期望音量-2 21"]=0.000000,["comvol使能-2-28"]=0,["comvol期望音量-2 29"]=0.000000,["comvol使能-2-29"]=0,["comvol使能-2-30"]=0,["comvol期望音量-2 26"]=0.000000,["comvol期望音量-2 20"]=0.000000,["comvol期望音量-2 17"]=0.000000,["comvol使能-2-20"]=0,["comvol期望音量-2 18"]=0.000000,["comvol期望音量-2 24"]=0.000000,["comvol期望音量-out-x-1-89"]=0,["comvol期望音量-out-avol1-86"]=0,["comvol期望音量-out-x-1-88"]=0,["comvol期望音量-out-x-1-86"]=0,["comvol期望音量-out-x-1-84"]=0,["comvol期望音量-out-x-1-85"]=0,["comvol期望音量-out-avol1-87"]=0,["comvol期望音量-out-avol1-90"]=0,["comvol期望音量-out-avol1-91"]=0,["comvol期望音量-out-x-1-83"]=0,["comvol期望音量-out-avol1-83"]=0,["comvol期望音量-out-avol1-92"]=0,["comvol期望音量-out-avol1-93"]=0,["comvol期望音量-out-avol1-94"]=0,["comvol期望音量-out-x-1-87"]=0,["comvol期望音量-out-x-1-91"]=0,["comvol期望音量-out-avol1-85"]=0,["comvol期望音量-out-x-1-95"]=0,["comvol期望音量-out-avol1-95"]=0,["comvol期望音量-out-avol1-96"]=0,["comvol期望音量-out-x-1-97"]=0,["comvol期望音量-out-avol1-84"]=0,["comvol期望音量-out-x-1-90"]=0,["comvol期望音量-out-avol1-97"]=0,["comvol期望音量-out-avol1-89"]=0,["comvol期望音量-out-x-1-98"]=0,["comvol期望音量-out-avol1-88"]=0,["comvol期望音量-out-x-1-93"]=0,["comvol期望音量-out-avol1-98"]=0,["comvol期望音量-out-x-1-94"]=0,["comvol期望音量-out-x-1-92"]=0,["comvol期望音量-out-x-1-96"]=0,["comvol使能-2-3"]=0,["comvol期望音量-2 5"]=0.000000,["comvol期望音量-2 7"]=0.000000,["comvol期望音量-2 1"]=0.000000,["comvol使能-2-1"]=0,["comvol使能-2-6"]=0,["comvol期望音量-out-avol1-100"]=0,["comvol使能-2-8"]=0,["comvol期望音量-2 10"]=0.000000,["comvol使能-2-10"]=0,["comvol第二种,最大音量1"]=0.000000,["comvol期望音量-2 4"]=0.000000,["comvol期望音量-2 6"]=0.000000,["comvol期望音量-out-avol1-99"]=0,["comvol期望音量-2 8"]=0.000000,["comvol第二种,最小音量1"]=-50.000000,["comvol第一种,最大音量1"]=0.000000,["comvol期望音量-2 2"]=0.000000,["comvol期望音量-2 3"]=0.000000,["comvol使能-2-4"]=0,["comvol使能-2-2"]=0,["comvol使能-2-9"]=0,["comvol期望音量-2 9"]=0.000000,["comvol使能-2-5"]=0,["comvol期望音量-2 11"]=0.000000,["comvol使能-2-7"]=0,["comvol使能-2-11"]=0,["comvol第一种,最小音量1"]=-50.000000,["comvol第二种,递音量1"]=2.000000,["comvol第一种,档位个数1"]=31,["comvol期望音量-out-x-1-99"]=0,["comvol期望音量-out-x-1-100"]=0,["comvol使能-2-14"]=0,["comvol使能-2-12"]=0,["comvol期望音量-2 13"]=0.000000,["comvol期望音量-2 12"]=0.000000,["comvol使能-2-13"]=0,["comvol期望音量-2 14"]=0.000000,["comvol使能-2-44"]=0,["comvol使能-2-34"]=0,["comvol期望音量-2 41"]=0.000000,["comvol使能-2-38"]=0,["comvol使能-2-45"]=0,["comvol期望音量-2 46"]=0.000000,["comvol使能-2-32"]=0,["comvol使能-2-46"]=0,["comvol期望音量-2 35"]=0.000000,["comvol使能-2-43"]=0,["comvol使能-2-33"]=0,["comvol期望音量-2 34"]=0.000000,["comvol期望音量-2 32"]=0.000000,["comvol使能-2-31"]=0,["comvol使能-2-35"]=0,["comvol期望音量-2 31"]=0.000000,["comvol期望音量-2 37"]=0.000000,["comvol期望音量-2 38"]=0.000000,["comvol期望音量-2 36"]=0.000000,["comvol使能-2-39"]=0,["comvol期望音量-2 39"]=0.000000,["comvol使能-2-36"]=0,["comvol期望音量-2 40"]=0.000000,["comvol使能-2-40"]=0,["comvol期望音量-2 33"]=0.000000,["comvol期望音量-2 42"]=0.000000,["comvol使能-2-42"]=0,["comvol期望音量-2 43"]=0.000000,["comvol期望音量-2 44"]=0.000000,["comvol使能-2-41"]=0,["comvol使能-2-37"]=0,["comvol期望音量-2 45"]=0.000000,["comvol使能-2-56"]=0,["comvol使能-2-62"]=0,["comvol使能-2-48"]=0,["comvol期望音量-2 57"]=0.000000,["comvol使能-2-58"]=0,["comvol期望音量-2 52"]=0.000000,["comvol使能-2-47"]=0,["comvol期望音量-2 61"]=0.000000,["comvol期望音量-2 62"]=0.000000,["comvol期望音量-2 51"]=0.000000,["comvol使能-2-49"]=0,["comvol期望音量-2 54"]=0.000000,["comvol使能-2-52"]=0,["comvol期望音量-2 55"]=0.000000,["comvol使能-2-60"]=0,["comvol期望音量-2 53"]=0.000000,["comvol使能-2-55"]=0,["comvol期望音量-2 58"]=0.000000,["comvol期望音量-2 48"]=0.000000,["comvol期望音量-2 59"]=0.000000,["comvol期望音量-2 47"]=0.000000,["comvol期望音量-2 50"]=0.000000,["comvol使能-2-51"]=0,["comvol使能-2-53"]=0,["comvol使能-2-59"]=0,["comvol期望音量-2 49"]=0.000000,["comvol使能-2-50"]=0,["comvol使能-2-54"]=0,["comvol期望音量-2 56"]=0.000000,["comvol使能-2-57"]=0,["comvol期望音量-2 60"]=0.000000,["comvol使能-2-61"]=0,["comvol使能-2-75"]=0,["comvol期望音量-2 75"]=0.000000,["comvol期望音量-2 66"]=0.000000,["comvol期望音量-2 63"]=0.000000,["comvol使能-2-67"]=0,["comvol使能-2-69"]=0,["comvol期望音量-2 73"]=0.000000,["comvol期望音量-2 76"]=0.000000,["comvol使能-2-76"]=0,["comvol期望音量-2 77"]=0.000000,["comvol期望音量-2 72"]=0.000000,["comvol期望音量-2 71"]=0.000000,["comvol期望音量-2 69"]=0.000000,["comvol使能-2-70"]=0,["comvol使能-2-77"]=0,["comvol期望音量-2 78"]=0.000000,["comvol使能-2-64"]=0,["comvol期望音量-2 64"]=0.000000,["comvol使能-2-65"]=0,["comvol使能-2-78"]=0,["comvol期望音量-2 65"]=0.000000,["comvol期望音量-2 68"]=0.000000,["comvol期望音量-2 67"]=0.000000,["comvol使能-2-71"]=0,["comvol使能-2-68"]=0,["comvol使能-2-63"]=0,["comvol期望音量-2 70"]=0.000000,["comvol期望音量-2 74"]=0.000000,["comvol使能-2-72"]=0,["comvol使能-2-66"]=0,["comvol使能-2-73"]=0,["comvol使能-2-74"]=0,["comvol期望音量-2 79"]=0.000000,["comvol使能-2-79"]=0,["comvol期望音量-2 80"]=0.000000,["comvol使能-2-80"]=0,["comvol使能-2-81"]=0,["comvol期望音量-2 81"]=0.000000,["comvol使能-2-93"]=0,["comvol使能-2-95"]=0,["comvol期望音量-2 92"]=0.000000,["comvol使能-2-85"]=0,["comvol使能-2-98"]=0,["comvol期望音量-2 95"]=0.000000,["comvol使能-2-97"]=0,["comvol使能-2-99"]=0,["comvol期望音量-2 100"]=0.000000,["comvol使能-2-100"]=0,["comvol使能-2-89"]=0,["comvol使能-2-87"]=0,["comvol使能-2-92"]=0,["comvol期望音量-2 97"]=0.000000,["comvol使能-2-91"]=0,["comvol期望音量-2 86"]=0.000000,["comvol期望音量-2 96"]=0.000000,["comvol期望音量-2 85"]=0.000000,["comvol期望音量-2 94"]=0.000000,["comvol使能-2-88"]=0,["comvol期望音量-2 90"]=0.000000,["comvol期望音量-2 91"]=0.000000,["comvol使能-2-94"]=0,["comvol期望音量-2 98"]=0.000000,["comvol期望音量-2 93"]=0.000000,["comvol使能-2-96"]=0,["comvol期望音量-2 99"]=0.000000,["comvol期望音量-2 87"]=0.000000,["comvol使能-2-86"]=0,["comvol期望音量-2 89"]=0.000000,["comvol期望音量-2 88"]=0.000000,["comvol使能-2-90"]=0,["comvol期望音量-out-avol2-12"]=0,["comvol期望音量-out-avol2-1"]=0,["comvol期望音量-out-x-2-4"]=0,["comvol期望音量-out-x-2-8"]=0,["comvol期望音量-out-avol2-5"]=0,["comvol期望音量-out-avol2-8"]=0,["comvol期望音量-out-avol2-13"]=0,["comvol期望音量-out-x-2-14"]=0,["comvol期望音量-out-avol-zero2"]=0,["comvol期望音量-out-avol2-9"]=0,["comvol期望音量-out-avol2-11"]=0,["comvol期望音量-out-x-2-5"]=0,["comvol期望音量-out-x-2-3"]=0,["comvol期望音量-out-x-zero2"]=0,["comvol期望音量-out-avol2-4"]=0,["comvol期望音量-out-x-2-6"]=0,["comvol期望音量-out-avol2-14"]=0,["comvol期望音量-out-x-2-15"]=0,["comvol期望音量-out-x-2-12"]=0,["comvol期望音量-out-x-2-2"]=0,["comvol总是使能-2-"]=1,["comvol期望音量-out-avol2-3"]=0,["comvol期望音量-out-avol2-6"]=0,["comvol期望音量-out-x-2-10"]=0,["comvol期望音量-out-avol2-7"]=0,["comvol期望音量-out-x-2-11"]=0,["comvol期望音量-out-avol2-2"]=0,["comvol期望音量-out-avol2-10"]=0,["comvol期望音量-out-x-2-13"]=0,["comvol期望音量-out-x-2-1"]=0,["comvol期望音量-out-x-2-9"]=0,["comvol期望音量-out-x-2-7"]=0,["comvol期望音量-out-avol2-17"]=0,["comvol期望音量-out-x-2-19"]=0,["comvol期望音量-out-x-2-22"]=0,["comvol期望音量-out-avol2-20"]=0,["comvol期望音量-out-x-2-23"]=0,["comvol期望音量-out-avol2-15"]=0,["comvol期望音量-out-x-2-20"]=0,["comvol期望音量-out-avol2-22"]=0,["comvol期望音量-out-avol2-24"]=0,["comvol期望音量-out-x-2-25"]=0,["comvol期望音量-out-x-2-27"]=0,["comvol期望音量-out-avol2-27"]=0,["comvol期望音量-out-x-2-28"]=0,["comvol期望音量-out-avol2-25"]=0,["comvol期望音量-out-avol2-28"]=0,["comvol期望音量-out-avol2-19"]=0,["comvol期望音量-out-x-2-21"]=0,["comvol期望音量-out-avol2-23"]=0,["comvol期望音量-out-x-2-16"]=0,["comvol期望音量-out-x-2-24"]=0,["comvol期望音量-out-x-2-29"]=0,["comvol期望音量-out-avol2-21"]=0,["comvol期望音量-out-avol2-29"]=0,["comvol期望音量-out-x-2-26"]=0,["comvol期望音量-out-avol2-18"]=0,["comvol期望音量-out-x-2-30"]=0,["comvol期望音量-out-avol2-30"]=0,["comvol期望音量-out-avol2-16"]=0,["comvol期望音量-out-x-2-31"]=0,["comvol期望音量-out-x-2-18"]=0,["comvol期望音量-out-x-2-17"]=0,["comvol期望音量-out-avol2-26"]=0,["comvol期望音量-2 82"]=0.000000,["comvol使能-2-82"]=0,["comvol使能-2-84"]=0,["comvol使能-2-83"]=0,["comvol期望音量-2 83"]=0.000000,["comvol期望音量-2 84"]=0.000000,["comvol期望音量-out-x-2-44"]=0,["comvol期望音量-out-avol2-45"]=0,["comvol期望音量-out-x-2-46"]=0,["comvol期望音量-out-avol2-46"]=0,["comvol期望音量-out-x-2-36"]=0,["comvol期望音量-out-x-2-47"]=0,["comvol期望音量-out-x-2-42"]=0,["comvol期望音量-out-x-2-38"]=0,["comvol期望音量-out-avol2-36"]=0,["comvol期望音量-out-x-2-32"]=0,["comvol期望音量-out-avol2-37"]=0,["comvol期望音量-out-avol2-34"]=0,["comvol期望音量-out-avol2-39"]=0,["comvol期望音量-out-x-2-40"]=0,["comvol期望音量-out-x-2-39"]=0,["comvol期望音量-out-avol2-40"]=0,["comvol期望音量-out-x-2-43"]=0,["comvol期望音量-out-avol2-31"]=0,["comvol期望音量-out-x-2-33"]=0,["comvol期望音量-out-x-2-41"]=0,["comvol期望音量-out-avol2-33"]=0,["comvol期望音量-out-avol2-41"]=0,["comvol期望音量-out-avol2-44"]=0,["comvol期望音量-out-x-2-45"]=0,["comvol期望音量-out-avol2-32"]=0,["comvol期望音量-out-x-2-34"]=0,["comvol期望音量-out-x-2-35"]=0,["comvol期望音量-out-avol2-35"]=0,["comvol期望音量-out-x-2-37"]=0,["comvol期望音量-out-avol2-38"]=0,["comvol期望音量-out-avol2-42"]=0,["comvol期望音量-out-avol2-43"]=0,["comvol期望音量-out-x-2-57"]=0,["comvol期望音量-out-avol2-59"]=0,["comvol期望音量-out-avol2-60"]=0,["comvol期望音量-out-x-2-61"]=0,["comvol期望音量-out-x-2-58"]=0,["comvol期望音量-out-avol2-61"]=0,["comvol期望音量-out-x-2-62"]=0,["comvol期望音量-out-x-2-53"]=0,["comvol期望音量-out-avol2-50"]=0,["comvol期望音量-out-avol2-62"]=0,["comvol期望音量-out-avol2-51"]=0,["comvol期望音量-out-x-2-63"]=0,["comvol期望音量-out-x-2-52"]=0,["comvol期望音量-out-avol2-56"]=0,["comvol期望音量-out-avol2-58"]=0,["comvol期望音量-out-x-2-55"]=0,["comvol期望音量-out-avol2-57"]=0,["comvol期望音量-out-avol2-47"]=0,["comvol期望音量-out-x-2-54"]=0,["comvol期望音量-out-avol2-55"]=0,["comvol期望音量-out-avol2-49"]=0,["comvol期望音量-out-x-2-50"]=0,["comvol期望音量-out-x-2-56"]=0,["comvol期望音量-out-x-2-59"]=0,["comvol期望音量-out-avol2-54"]=0,["comvol期望音量-out-x-2-60"]=0,["comvol期望音量-out-avol2-48"]=0,["comvol期望音量-out-avol2-52"]=0,["comvol期望音量-out-x-2-48"]=0,["comvol期望音量-out-x-2-49"]=0,["comvol期望音量-out-x-2-51"]=0,["comvol期望音量-out-avol2-53"]=0,["comvol期望音量-out-x-2-70"]=0,["comvol期望音量-out-avol2-72"]=0,["comvol期望音量-out-x-2-64"]=0,["comvol期望音量-out-avol2-63"]=0,["comvol期望音量-out-x-2-66"]=0,["comvol期望音量-out-avol2-67"]=0,["comvol期望音量-out-avol2-68"]=0,["comvol期望音量-out-avol2-69"]=0,["comvol期望音量-out-x-2-71"]=0,["comvol期望音量-out-x-2-67"]=0,["comvol期望音量-out-avol2-65"]=0,["comvol期望音量-out-x-2-73"]=0,["comvol期望音量-out-avol2-75"]=0,["comvol期望音量-out-x-2-68"]=0,["comvol期望音量-out-x-2-72"]=0,["comvol期望音量-out-x-2-74"]=0,["comvol期望音量-out-x-2-76"]=0,["comvol期望音量-out-x-2-77"]=0,["comvol期望音量-out-avol2-77"]=0,["comvol期望音量-out-x-2-78"]=0,["comvol期望音量-out-avol2-66"]=0,["comvol期望音量-out-avol2-70"]=0,["comvol期望音量-out-avol2-73"]=0,["comvol期望音量-out-avol2-64"]=0,["comvol期望音量-out-avol2-74"]=0,["comvol期望音量-out-avol2-76"]=0,["comvol期望音量-out-avol2-78"]=0,["comvol期望音量-out-x-2-79"]=0,["comvol期望音量-out-x-2-75"]=0,["comvol期望音量-out-avol2-71"]=0,["comvol期望音量-out-x-2-65"]=0,["comvol期望音量-out-x-2-69"]=0,["comvol期望音量-out-x-2-91"]=0,["comvol期望音量-out-avol2-91"]=0,["comvol期望音量-out-avol2-80"]=0,["comvol期望音量-out-x-2-89"]=0,["comvol期望音量-out-x-2-94"]=0,["comvol期望音量-out-avol2-84"]=0,["comvol期望音量-out-avol2-93"]=0,["comvol期望音量-out-avol2-94"]=0,["comvol期望音量-out-avol2-83"]=0,["comvol期望音量-out-x-2-80"]=0,["comvol期望音量-out-x-2-87"]=0,["comvol期望音量-out-avol2-88"]=0,["comvol期望音量-out-x-2-88"]=0,["comvol期望音量-out-avol2-92"]=0,["comvol期望音量-out-x-2-95"]=0,["comvol期望音量-out-avol2-79"]=0,["comvol期望音量-out-x-2-81"]=0,["comvol期望音量-out-avol2-86"]=0,["comvol期望音量-out-avol2-85"]=0,["comvol期望音量-out-x-2-83"]=0,["comvol期望音量-out-x-2-86"]=0,["comvol期望音量-out-avol2-87"]=0,["comvol期望音量-out-x-2-90"]=0,["comvol期望音量-out-x-2-92"]=0,["comvol期望音量-out-x-2-93"]=0,["comvol期望音量-out-x-2-82"]=0,["comvol期望音量-out-avol2-81"]=0,["comvol期望音量-out-x-2-84"]=0,["comvol期望音量-out-avol2-82"]=0,["comvol期望音量-out-x-2-85"]=0,["comvol期望音量-out-avol2-89"]=0,["comvol期望音量-out-avol2-90"]=0,["dvol期望音量-1 7"]=0.000000,["dvol使能-1-7"]=0,["dvol期望音量-1 8"]=0.000000,["comvol期望音量-out-avol2-96"]=0,["dvol使能-1-2"]=0,["comvol期望音量-out-x-2-97"]=0,["dvol使能-1-4"]=0,["comvol期望音量-out-avol2-99"]=0,["comvol期望音量-out-x-2-100"]=0,["dvol使能-1-1"]=0,["comvol期望音量-out-avol2-95"]=0,["comvol第一种,档位个数2"]=15,["comvol期望音量-out-avol2-97"]=0,["comvol期望音量-out-x-2-99"]=0,["comvol第一种,最大音量2"]=-14.000000,["comvol第二种,递音量2"]=2.000000,["comvol第二种,最大音量2"]=-14.000000,["comvol期望音量-out-x-2-98"]=0,["comvol第二种,最小音量2"]=-45.000000,["comvol期望音量-out-avol2-100"]=0,["comvol期望音量-out-avol2-98"]=0,["dvol期望音量-1 1"]=0.000000,["dvol期望音量-1 2"]=0.000000,["comvol第一种,最小音量2"]=-45.000000,["dvol期望音量-1 3"]=0.000000,["dvol使能-1-3"]=0,["dvol期望音量-1 4"]=0.000000,["dvol期望音量-1 5"]=0.000000,["comvol期望音量-out-x-2-96"]=0,["dvol使能-1-5"]=0,["dvol期望音量-1 6"]=0.000000,["dvol使能-1-6"]=0,["dvol期望音量-1 13"]=0.000000,["dvol使能-1-18"]=0,["dvol使能-1-21"]=0,["dvol期望音量-1 22"]=0.000000,["dvol期望音量-1 10"]=0.000000,["dvol使能-1-10"]=0,["dvol期望音量-1 11"]=0.000000,["dvol期望音量-1 16"]=0.000000,["dvol使能-1-14"]=0,["dvol期望音量-1 17"]=0.000000,["dvol使能-1-8"]=0,["dvol使能-1-11"]=0,["dvol期望音量-1 12"]=0.000000,["dvol期望音量-1 18"]=0.000000,["dvol使能-1-19"]=0,["dvol期望音量-1 20"]=0.000000,["dvol使能-1-20"]=0,["dvol使能-1-15"]=0,["dvol期望音量-1 23"]=0.000000,["dvol期望音量-1 14"]=0.000000,["dvol使能-1-23"]=0,["dvol使能-1-12"]=0,["dvol期望音量-1 24"]=0.000000,["dvol期望音量-1 19"]=0.000000,["dvol使能-1-16"]=0,["dvol使能-1-17"]=0,["dvol期望音量-1 9"]=0.000000,["dvol期望音量-1 21"]=0.000000,["dvol期望音量-1 15"]=0.000000,["dvol使能-1-22"]=0,["dvol使能-1-13"]=0,["dvol使能-1-9"]=0,["dvol使能-1-28"]=0,["dvol使能-1-26"]=0,["dvol期望音量-1 25"]=0.000000,["dvol期望音量-1 29"]=0.000000,["dvol期望音量-1 30"]=0.000000,["dvol使能-1-24"]=0,["dvol使能-1-29"]=0,["dvol期望音量-1 27"]=0.000000,["dvol期望音量-1 28"]=0.000000,["dvol期望音量-1 26"]=0.000000,["dvol使能-1-25"]=0,["dvol使能-1-27"]=0,["dvol使能-1-91"]=0,["dvol期望音量-1 93"]=0.000000,["dvol期望音量-1 89"]=0.000000,["dvol使能-1-85"]=0,["dvol使能-1-87"]=0,["dvol期望音量-1 92"]=0.000000,["dvol使能-1-98"]=0,["dvol使能-1-93"]=0,["dvol使能-1-95"]=0,["dvol期望音量-1 95"]=0.000000,["dvol期望音量-1 99"]=0.000000,["dvol使能-1-94"]=0,["dvol期望音量-1 88"]=0.000000,["dvol使能-1-90"]=0,["dvol使能-1-96"]=0,["dvol使能-1-99"]=0,["dvol期望音量-1 100"]=0.000000,["dvol期望音量-1 85"]=0.000000,["dvol期望音量-1 87"]=0.000000,["dvol使能-1-92"]=0,["dvol使能-1-97"]=0,["dvol期望音量-1 91"]=0.000000,["dvol使能-1-89"]=0,["dvol使能-1-84"]=0,["dvol使能-1-88"]=0,["dvol期望音量-1 94"]=0.000000,["dvol期望音量-1 86"]=0.000000,["dvol使能-1-86"]=0,["dvol期望音量-1 97"]=0.000000,["dvol期望音量-1 90"]=0.000000,["dvol期望音量-1 96"]=0.000000,["dvol期望音量-1 98"]=0.000000,["dvol期望音量-out-avol1-8"]=0,["dvol期望音量-out-x-1-2"]=0,["dvol期望音量-out-x-1-9"]=0,["dvol期望音量-out-avol1-9"]=0,["dvol期望音量-out-x-1-13"]=0,["dvol期望音量-out-avol1-13"]=0,["dvol期望音量-out-x-1-3"]=0,["dvol期望音量-out-avol1-14"]=0,["dvol期望音量-out-avol1-5"]=0,["dvol期望音量-out-avol1-11"]=0,["dvol期望音量-out-x-1-14"]=0,["dvol期望音量-out-avol1-4"]=0,["dvol使能-1-100"]=0,["dvol期望音量-out-avol1-3"]=0,["dvol期望音量-out-avol1-7"]=0,["dvol期望音量-out-x-1-1"]=0,["dvol期望音量-out-x-1-5"]=0,["dvol期望音量-out-x-1-7"]=0,["dvol期望音量-out-avol1-1"]=0,["dvol期望音量-out-x-1-10"]=0,["dvol期望音量-out-avol1-10"]=0,["dvol期望音量-out-x-1-11"]=0,["dvol期望音量-out-x-1-4"]=0,["dvol期望音量-out-x-1-12"]=0,["dvol期望音量-out-avol1-2"]=0,["dvol期望音量-out-x-1-6"]=0,["dvol期望音量-out-avol1-6"]=0,["dvol期望音量-out-x-1-8"]=0,["dvol期望音量-out-avol1-12"]=0,["dvol期望音量-out-x-1-27"]=0,["dvol期望音量-out-x-1-20"]=0,["dvol期望音量-out-avol1-27"]=0,["dvol期望音量-out-x-1-28"]=0,["dvol期望音量-out-avol1-28"]=0,["dvol期望音量-out-x-1-29"]=0,["dvol期望音量-out-avol1-29"]=0,["dvol期望音量-out-x-1-24"]=0,["dvol期望音量-out-x-1-25"]=0,["dvol期望音量-out-x-1-30"]=0,["dvol期望音量-out-avol1-30"]=0,["dvol期望音量-out-avol1-15"]=0,["dvol期望音量-out-x-1-19"]=0,["dvol期望音量-out-x-1-21"]=0,["dvol期望音量-out-avol1-19"]=0,["dvol期望音量-out-x-1-15"]=0,["dvol期望音量-out-x-1-16"]=0,["dvol期望音量-out-avol1-24"]=0,["dvol期望音量-out-avol1-16"]=0,["dvol期望音量-out-avol1-18"]=0,["dvol期望音量-out-x-1-17"]=0,["dvol期望音量-out-x-1-22"]=0,["dvol期望音量-out-avol1-25"]=0,["dvol期望音量-out-avol1-26"]=0,["dvol期望音量-out-avol1-17"]=0,["dvol期望音量-out-avol1-20"]=0,["dvol期望音量-out-avol1-21"]=0,["dvol期望音量-out-x-1-18"]=0,["dvol期望音量-out-x-1-23"]=0,["dvol期望音量-out-avol1-23"]=0,["dvol期望音量-out-avol1-22"]=0,["dvol期望音量-out-x-1-26"]=0,["dvol期望音量-1 37"]=0.000000,["dvol期望音量-1 38"]=0.000000,["dvol使能-1-39"]=0,["dvol期望音量-1 40"]=0.000000,["dvol使能-1-40"]=0,["dvol期望音量-1 41"]=0.000000,["dvol使能-1-32"]=0,["dvol使能-1-31"]=0,["dvol使能-1-33"]=0,["dvol使能-1-30"]=0,["dvol期望音量-1 31"]=0.000000,["dvol期望音量-1 36"]=0.000000,["dvol使能-1-38"]=0,["dvol使能-1-41"]=0,["dvol使能-1-42"]=0,["dvol期望音量-1 43"]=0.000000,["dvol期望音量-1 34"]=0.000000,["dvol使能-1-35"]=0,["dvol期望音量-1 42"]=0.000000,["dvol期望音量-1 33"]=0.000000,["dvol使能-1-43"]=0,["dvol期望音量-1 44"]=0.000000,["dvol使能-1-44"]=0,["dvol使能-1-45"]=0,["dvol期望音量-1 46"]=0.000000,["dvol使能-1-36"]=0,["dvol使能-1-37"]=0,["dvol期望音量-1 39"]=0.000000,["dvol期望音量-1 35"]=0.000000,["dvol使能-1-34"]=0,["dvol期望音量-1 45"]=0.000000,["dvol期望音量-1 32"]=0.000000,["dvol期望音量-1 53"]=0.000000,["dvol使能-1-60"]=0,["dvol使能-1-55"]=0,["dvol使能-1-51"]=0,["dvol期望音量-1 61"]=0.000000,["dvol使能-1-61"]=0,["dvol期望音量-1 48"]=0.000000,["dvol期望音量-1 50"]=0.000000,["dvol使能-1-49"]=0,["dvol使能-1-58"]=0,["dvol期望音量-1 62"]=0.000000,["dvol期望音量-1 52"]=0.000000,["dvol使能-1-47"]=0,["dvol期望音量-1 51"]=0.000000,["dvol使能-1-48"]=0,["dvol期望音量-1 49"]=0.000000,["dvol期望音量-1 54"]=0.000000,["dvol使能-1-54"]=0,["dvol使能-1-57"]=0,["dvol期望音量-1 55"]=0.000000,["dvol使能-1-53"]=0,["dvol期望音量-1 56"]=0.000000,["dvol使能-1-50"]=0,["dvol期望音量-1 57"]=0.000000,["dvol使能-1-46"]=0,["dvol使能-1-52"]=0,["dvol期望音量-1 59"]=0.000000,["dvol使能-1-59"]=0,["dvol期望音量-1 60"]=0.000000,["dvol期望音量-1 47"]=0.000000,["dvol使能-1-56"]=0,["dvol期望音量-1 58"]=0.000000,["dvol期望音量-1 69"]=0.000000,["dvol期望音量-1 70"]=0.000000,["dvol期望音量-1 72"]=0.000000,["dvol使能-1-72"]=0,["dvol期望音量-1 67"]=0.000000,["dvol期望音量-1 73"]=0.000000,["dvol期望音量-1 74"]=0.000000,["dvol使能-1-69"]=0,["dvol使能-1-63"]=0,["dvol期望音量-1 65"]=0.000000,["dvol期望音量-1 75"]=0.000000,["dvol使能-1-74"]=0,["dvol期望音量-1 76"]=0.000000,["dvol期望音量-1 66"]=0.000000,["dvol期望音量-1 77"]=0.000000,["dvol期望音量-1 63"]=0.000000,["dvol期望音量-1 71"]=0.000000,["dvol使能-1-75"]=0,["dvol使能-1-68"]=0,["dvol使能-1-66"]=0,["dvol使能-1-71"]=0,["dvol使能-1-76"]=0,["dvol使能-1-65"]=0,["dvol使能-1-62"]=0,["dvol使能-1-67"]=0,["dvol使能-1-70"]=0,["dvol使能-1-73"]=0,["dvol期望音量-1 68"]=0.000000,["dvol使能-1-77"]=0,["dvol期望音量-1 78"]=0.000000,["dvol使能-1-64"]=0,["dvol期望音量-1 64"]=0.000000,["dvol使能-1-78"]=0,["dvol期望音量-1 80"]=0.000000,["dvol期望音量-1 82"]=0.000000,["dvol期望音量-1 83"]=0.000000,["dvol使能-1-82"]=0,["dvol使能-1-83"]=0,["dvol期望音量-1 84"]=0.000000,["dvol期望音量-1 79"]=0.000000,["dvol使能-1-79"]=0,["dvol使能-1-80"]=0,["dvol期望音量-1 81"]=0.000000,["dvol使能-1-81"]=0,["dvol期望音量-out-x-1-38"]=0,["dvol期望音量-out-avol1-40"]=0,["dvol期望音量-out-avol1-35"]=0,["dvol期望音量-out-x-1-42"]=0,["dvol期望音量-out-x-1-39"]=0,["dvol期望音量-out-avol1-45"]=0,["dvol期望音量-out-avol1-43"]=0,["dvol期望音量-out-x-1-46"]=0,["dvol期望音量-out-avol1-46"]=0,["dvol期望音量-out-avol1-36"]=0,["dvol期望音量-out-avol1-33"]=0,["dvol期望音量-out-avol1-41"]=0,["dvol期望音量-out-avol1-44"]=0,["dvol期望音量-out-x-1-44"]=0,["dvol期望音量-out-x-1-31"]=0,["dvol期望音量-out-x-1-37"]=0,["dvol期望音量-out-avol1-42"]=0,["dvol期望音量-out-avol1-32"]=0,["dvol期望音量-out-avol1-38"]=0,["dvol期望音量-out-x-1-32"]=0,["dvol期望音量-out-avol1-31"]=0,["dvol期望音量-out-avol1-37"]=0,["dvol期望音量-out-x-1-40"]=0,["dvol期望音量-out-x-1-34"]=0,["dvol期望音量-out-x-1-45"]=0,["dvol期望音量-out-x-1-33"]=0,["dvol期望音量-out-x-1-35"]=0,["dvol期望音量-out-avol1-39"]=0,["dvol期望音量-out-x-1-43"]=0,["dvol期望音量-out-x-1-41"]=0,["dvol期望音量-out-avol1-34"]=0,["dvol期望音量-out-x-1-36"]=0,["dvol期望音量-out-avol1-54"]=0,["dvol期望音量-out-avol1-56"]=0,["dvol期望音量-out-avol1-52"]=0,["dvol期望音量-out-avol1-57"]=0,["dvol期望音量-out-x-1-50"]=0,["dvol期望音量-out-x-1-52"]=0,["dvol期望音量-out-x-1-61"]=0,["dvol期望音量-out-avol1-60"]=0,["dvol期望音量-out-avol1-59"]=0,["dvol期望音量-out-avol1-61"]=0,["dvol期望音量-out-x-1-62"]=0,["dvol期望音量-out-avol1-62"]=0,["dvol期望音量-out-x-1-55"]=0,["dvol期望音量-out-x-1-60"]=0,["dvol期望音量-out-avol1-53"]=0,["dvol期望音量-out-x-1-47"]=0,["dvol期望音量-out-avol1-50"]=0,["dvol期望音量-out-x-1-56"]=0,["dvol期望音量-out-avol1-49"]=0,["dvol期望音量-out-x-1-51"]=0,["dvol期望音量-out-x-1-53"]=0,["dvol期望音量-out-avol1-58"]=0,["dvol期望音量-out-avol1-48"]=0,["dvol期望音量-out-avol1-47"]=0,["dvol期望音量-out-x-1-57"]=0,["dvol期望音量-out-x-1-49"]=0,["dvol期望音量-out-x-1-58"]=0,["dvol期望音量-out-x-1-59"]=0,["dvol期望音量-out-avol1-55"]=0,["dvol期望音量-out-x-1-54"]=0,["dvol期望音量-out-avol1-51"]=0,["dvol期望音量-out-x-1-48"]=0,["dvol期望音量-out-avol1-78"]=0,["dvol期望音量-out-x-1-71"]=0,["dvol期望音量-out-x-1-73"]=0,["dvol期望音量-out-avol1-67"]=0,["dvol期望音量-out-x-1-65"]=0,["dvol期望音量-out-x-1-66"]=0,["dvol期望音量-out-avol1-63"]=0,["dvol期望音量-out-avol1-70"]=0,["dvol期望音量-out-x-1-63"]=0,["dvol期望音量-out-x-1-64"]=0,["dvol期望音量-out-x-1-69"]=0,["dvol期望音量-out-avol1-65"]=0,["dvol期望音量-out-avol1-69"]=0,["dvol期望音量-out-x-1-68"]=0,["dvol期望音量-out-avol1-66"]=0,["dvol期望音量-out-x-1-72"]=0,["dvol期望音量-out-avol1-73"]=0,["dvol期望音量-out-x-1-70"]=0,["dvol期望音量-out-avol1-75"]=0,["dvol期望音量-out-avol1-76"]=0,["dvol期望音量-out-x-1-77"]=0,["dvol期望音量-out-avol1-68"]=0,["dvol期望音量-out-avol1-64"]=0,["dvol期望音量-out-avol1-74"]=0,["dvol期望音量-out-x-1-74"]=0,["dvol期望音量-out-x-1-75"]=0,["dvol期望音量-out-avol1-77"]=0,["dvol期望音量-out-x-1-78"]=0,["dvol期望音量-out-x-1-67"]=0,["dvol期望音量-out-avol1-71"]=0,["dvol期望音量-out-avol1-72"]=0,["dvol期望音量-out-x-1-76"]=0,["dvol期望音量-out-avol1-87"]=0,["dvol期望音量-out-x-1-90"]=0,["dvol期望音量-out-x-1-91"]=0,["dvol期望音量-out-x-1-93"]=0,["dvol期望音量-out-x-1-94"]=0,["dvol期望音量-out-x-1-86"]=0,["dvol期望音量-out-avol1-94"]=0,["dvol期望音量-out-avol1-82"]=0,["dvol期望音量-out-x-1-85"]=0,["dvol期望音量-out-avol1-79"]=0,["dvol期望音量-out-avol1-85"]=0,["dvol期望音量-out-avol1-84"]=0,["dvol期望音量-out-avol1-88"]=0,["dvol期望音量-out-avol1-80"]=0,["dvol期望音量-out-avol1-83"]=0,["dvol期望音量-out-x-1-89"]=0,["dvol期望音量-out-avol1-86"]=0,["dvol期望音量-out-avol1-90"]=0,["dvol期望音量-out-avol1-89"]=0,["dvol期望音量-out-x-1-84"]=0,["dvol期望音量-out-avol1-91"]=0,["dvol期望音量-out-x-1-81"]=0,["dvol期望音量-out-x-1-79"]=0,["dvol期望音量-out-x-1-80"]=0,["dvol期望音量-out-x-1-92"]=0,["dvol期望音量-out-avol1-92"]=0,["dvol期望音量-out-avol1-93"]=0,["dvol期望音量-out-avol1-81"]=0,["dvol期望音量-out-x-1-82"]=0,["dvol期望音量-out-x-1-83"]=0,["dvol期望音量-out-x-1-87"]=0,["dvol期望音量-out-x-1-88"]=0,["dvol期望音量-2 4"]=0.000000,["dvol期望音量-2 6"]=0.000000,["dvol期望音量-out-avol1-100"]=0,["dvol使能-2-6"]=0,["dvol期望音量-out-avol1-95"]=0,["dvol期望音量-out-avol1-97"]=0,["dvol第一种,最大音量1"]=0.000000,["dvol第二种,最大音量1"]=0.000000,["dvol期望音量-out-avol1-96"]=0,["dvol使能-2-5"]=0,["dvol期望音量-2 2"]=0.000000,["dvol期望音量-out-x-1-98"]=0,["dvol第二种,最小音量1"]=-50.000000,["dvol期望音量-2 1"]=0.000000,["dvol使能-2-1"]=0,["dvol期望音量-out-avol1-99"]=0,["dvol使能-2-2"]=0,["dvol期望音量-out-x-1-95"]=0,["dvol期望音量-out-x-1-96"]=0,["dvol期望音量-out-avol1-98"]=0,["dvol使能-2-3"]=0,["dvol期望音量-2 5"]=0.000000,["dvol期望音量-2 7"]=0.000000,["dvol使能-2-7"]=0,["dvol期望音量-out-x-1-99"]=0,["dvol使能-2-4"]=0,["dvol期望音量-out-x-1-100"]=0,["dvol第一种,档位个数1"]=31,["dvol期望音量-out-x-1-97"]=0,["dvol第二种,递音量1"]=2.000000,["dvol第一种,最小音量1"]=-50.000000,["dvol期望音量-2 3"]=0.000000,["dvol使能-2-14"]=0,["dvol使能-2-15"]=0,["dvol期望音量-2 13"]=0.000000,["dvol期望音量-2 20"]=0.000000,["dvol使能-2-20"]=0,["dvol期望音量-2 21"]=0.000000,["dvol期望音量-2 19"]=0.000000,["dvol使能-2-21"]=0,["dvol期望音量-2 12"]=0.000000,["dvol期望音量-2 22"]=0.000000,["dvol使能-2-22"]=0,["dvol期望音量-2 23"]=0.000000,["dvol期望音量-2 16"]=0.000000,["dvol使能-2-23"]=0,["dvol期望音量-2 17"]=0.000000,["dvol使能-2-9"]=0,["dvol期望音量-2 10"]=0.000000,["dvol使能-2-11"]=0,["dvol使能-2-12"]=0,["dvol期望音量-2 8"]=0.000000,["dvol使能-2-13"]=0,["dvol期望音量-2 18"]=0.000000,["dvol使能-2-18"]=0,["dvol使能-2-16"]=0,["dvol使能-2-8"]=0,["dvol期望音量-2 15"]=0.000000,["dvol使能-2-17"]=0,["dvol期望音量-2 14"]=0.000000,["dvol期望音量-2 11"]=0.000000,["dvol使能-2-19"]=0,["dvol期望音量-2 9"]=0.000000,["dvol使能-2-10"]=0,["dvol使能-2-26"]=0,["dvol使能-2-25"]=0,["dvol使能-2-28"]=0,["dvol使能-2-24"]=0,["dvol期望音量-2 24"]=0.000000,["dvol期望音量-2 25"]=0.000000,["dvol期望音量-2 27"]=0.000000,["dvol使能-2-27"]=0,["dvol期望音量-2 29"]=0.000000,["dvol使能-2-29"]=0,["dvol期望音量-2 28"]=0.000000,["dvol期望音量-2 26"]=0.000000,["dvol使能-2-43"]=0,["dvol使能-2-31"]=0,["dvol期望音量-2 33"]=0.000000,["dvol期望音量-2 32"]=0.000000,["dvol期望音量-2 34"]=0.000000,["dvol期望音量-2 31"]=0.000000,["dvol使能-2-33"]=0,["dvol期望音量-2 36"]=0.000000,["dvol使能-2-39"]=0,["dvol期望音量-2 30"]=0.000000,["dvol使能-2-40"]=0,["dvol期望音量-2 42"]=0.000000,["dvol使能-2-32"]=0,["dvol使能-2-35"]=0,["dvol使能-2-30"]=0,["dvol期望音量-2 37"]=0.000000,["dvol使能-2-37"]=0,["dvol期望音量-2 39"]=0.000000,["dvol期望音量-2 40"]=0.000000,["dvol期望音量-2 41"]=0.000000,["dvol使能-2-41"]=0,["dvol期望音量-2 43"]=0.000000,["dvol期望音量-2 44"]=0.000000,["dvol使能-2-44"]=0,["dvol期望音量-2 45"]=0.000000,["dvol期望音量-2 35"]=0.000000,["dvol使能-2-36"]=0,["dvol期望音量-2 38"]=0.000000,["dvol使能-2-34"]=0,["dvol使能-2-45"]=0,["dvol使能-2-38"]=0,["dvol使能-2-42"]=0,["dvol期望音量-2 59"]=0.000000,["dvol使能-2-59"]=0,["dvol期望音量-2 60"]=0.000000,["dvol使能-2-60"]=0,["dvol期望音量-2 61"]=0.000000,["dvol期望音量-2 51"]=0.000000,["dvol使能-2-61"]=0,["dvol使能-2-47"]=0,["dvol期望音量-2 47"]=0.000000,["dvol使能-2-48"]=0,["dvol使能-2-51"]=0,["dvol使能-2-46"]=0,["dvol期望音量-2 52"]=0.000000,["dvol期望音量-2 53"]=0.000000,["dvol期望音量-2 50"]=0.000000,["dvol期望音量-2 54"]=0.000000,["dvol使能-2-55"]=0,["dvol使能-2-56"]=0,["dvol期望音量-2 55"]=0.000000,["dvol使能-2-53"]=0,["dvol使能-2-49"]=0,["dvol使能-2-54"]=0,["dvol使能-2-52"]=0,["dvol期望音量-2 56"]=0.000000,["dvol期望音量-2 57"]=0.000000,["dvol使能-2-57"]=0,["dvol期望音量-2 58"]=0.000000,["dvol期望音量-2 49"]=0.000000,["dvol期望音量-2 48"]=0.000000,["dvol使能-2-50"]=0,["dvol期望音量-2 46"]=0.000000,["dvol使能-2-58"]=0,["dvol使能-2-73"]=0,["dvol使能-2-68"]=0,["dvol期望音量-2 74"]=0.000000,["dvol期望音量-2 72"]=0.000000,["dvol期望音量-2 76"]=0.000000,["dvol期望音量-2 66"]=0.000000,["dvol使能-2-66"]=0,["dvol使能-2-76"]=0,["dvol期望音量-2 65"]=0.000000,["dvol期望音量-2 77"]=0.000000,["dvol使能-2-77"]=0,["dvol使能-2-72"]=0,["dvol期望音量-2 67"]=0.000000,["dvol期望音量-2 68"]=0.000000,["dvol期望音量-2 64"]=0.000000,["dvol期望音量-2 70"]=0.000000,["dvol使能-2-67"]=0,["dvol使能-2-62"]=0,["dvol使能-2-65"]=0,["dvol使能-2-69"]=0,["dvol使能-2-70"]=0,["dvol期望音量-2 71"]=0.000000,["dvol使能-2-71"]=0,["dvol使能-2-74"]=0,["dvol期望音量-2 75"]=0.000000,["dvol使能-2-63"]=0,["dvol期望音量-2 69"]=0.000000,["dvol期望音量-2 73"]=0.000000,["dvol期望音量-2 62"]=0.000000,["dvol使能-2-64"]=0,["dvol使能-2-75"]=0,["dvol期望音量-2 63"]=0.000000,["dvol期望音量-2 91"]=0.000000,["dvol期望音量-2 83"]=0.000000,["dvol期望音量-2 92"]=0.000000,["dvol使能-2-80"]=0,["dvol使能-2-92"]=0,["dvol期望音量-2 79"]=0.000000,["dvol使能-2-79"]=0,["dvol期望音量-2 84"]=0.000000,["dvol使能-2-85"]=0,["dvol期望音量-2 88"]=0.000000,["dvol使能-2-88"]=0,["dvol使能-2-89"]=0,["dvol期望音量-2 93"]=0.000000,["dvol使能-2-91"]=0,["dvol使能-2-84"]=0,["dvol使能-2-93"]=0,["dvol使能-2-78"]=0,["dvol使能-2-81"]=0,["dvol期望音量-2 82"]=0.000000,["dvol期望音量-2 80"]=0.000000,["dvol期望音量-2 81"]=0.000000,["dvol使能-2-82"]=0,["dvol使能-2-83"]=0,["dvol使能-2-87"]=0,["dvol期望音量-2 89"]=0.000000,["dvol期望音量-2 90"]=0.000000,["dvol期望音量-2 85"]=0.000000,["dvol使能-2-90"]=0,["dvol期望音量-2 78"]=0.000000,["dvol期望音量-2 86"]=0.000000,["dvol使能-2-86"]=0,["dvol期望音量-2 87"]=0.000000,["dvol期望音量-out-avol2-6"]=0,["dvol期望音量-out-x-2-1"]=0,["dvol期望音量-out-avol2-7"]=0,["dvol期望音量-2 99"]=0.000000,["dvol期望音量-out-x-2-8"]=0,["dvol期望音量-2 95"]=0.000000,["dvol期望音量-out-x-2-2"]=0,["dvol期望音量-out-avol2-2"]=0,["dvol期望音量-out-x-2-3"]=0,["dvol期望音量-2 97"]=0.000000,["dvol使能-2-95"]=0,["dvol期望音量-2 96"]=0.000000,["dvol使能-2-96"]=0,["dvol使能-2-98"]=0,["dvol使能-2-94"]=0,["dvol使能-2-100"]=0,["dvol期望音量-out-x-2-4"]=0,["dvol期望音量-out-avol2-4"]=0,["dvol期望音量-out-x-2-5"]=0,["dvol期望音量-out-avol2-5"]=0,["dvol使能-2-99"]=0,["dvol期望音量-out-x-2-6"]=0,["dvol期望音量-2 100"]=0.000000,["dvol期望音量-out-x-2-7"]=0,["dvol使能-2-97"]=0,["dvol期望音量-2 94"]=0.000000,["dvol期望音量-out-avol2-1"]=0,["dvol期望音量-out-avol2-3"]=0,["dvol期望音量-2 98"]=0.000000,["dvol期望音量-out-avol2-20"]=0,["dvol期望音量-out-avol2-17"]=0,["dvol期望音量-out-avol2-21"]=0,["dvol期望音量-out-x-2-9"]=0,["dvol期望音量-out-avol2-11"]=0,["dvol期望音量-out-avol2-22"]=0,["dvol期望音量-out-avol2-23"]=0,["dvol期望音量-out-x-2-12"]=0,["dvol期望音量-out-x-2-24"]=0,["dvol期望音量-out-x-2-14"]=0,["dvol期望音量-out-x-2-11"]=0,["dvol期望音量-out-x-2-15"]=0,["dvol期望音量-out-x-2-21"]=0,["dvol期望音量-out-x-2-16"]=0,["dvol期望音量-out-avol2-19"]=0,["dvol期望音量-out-x-2-19"]=0,["dvol期望音量-out-x-2-23"]=0,["dvol期望音量-out-avol2-9"]=0,["dvol期望音量-out-avol2-10"]=0,["dvol期望音量-out-avol2-8"]=0,["dvol期望音量-out-x-2-13"]=0,["dvol期望音量-out-avol2-13"]=0,["dvol期望音量-out-x-2-10"]=0,["dvol期望音量-out-avol2-14"]=0,["dvol期望音量-out-avol2-16"]=0,["dvol期望音量-out-x-2-17"]=0,["dvol期望音量-out-avol2-12"]=0,["dvol期望音量-out-x-2-18"]=0,["dvol期望音量-out-x-2-20"]=0,["dvol期望音量-out-x-2-22"]=0,["dvol期望音量-out-avol2-15"]=0,["dvol期望音量-out-avol2-18"]=0,["dvol期望音量-out-x-2-27"]=0,["dvol期望音量-out-avol2-28"]=0,["dvol期望音量-out-avol2-27"]=0,["dvol期望音量-out-x-2-26"]=0,["dvol期望音量-out-x-2-29"]=0,["dvol期望音量-out-avol2-29"]=0,["dvol期望音量-out-x-2-30"]=0,["dvol期望音量-out-x-2-25"]=0,["dvol期望音量-out-avol2-25"]=0,["dvol期望音量-out-avol2-26"]=0,["dvol期望音量-out-avol2-24"]=0,["dvol期望音量-out-x-2-28"]=0,["dvol期望音量-out-avol2-44"]=0,["dvol期望音量-out-avol2-37"]=0,["dvol期望音量-out-x-2-38"]=0,["dvol期望音量-out-avol2-43"]=0,["dvol期望音量-out-x-2-45"]=0,["dvol期望音量-out-x-2-44"]=0,["dvol期望音量-out-avol2-45"]=0,["dvol期望音量-out-x-2-34"]=0,["dvol期望音量-out-x-2-33"]=0,["dvol期望音量-out-x-2-42"]=0,["dvol期望音量-out-avol2-31"]=0,["dvol期望音量-out-x-2-46"]=0,["dvol期望音量-out-avol2-36"]=0,["dvol期望音量-out-avol2-30"]=0,["dvol期望音量-out-x-2-31"]=0,["dvol期望音量-out-avol2-32"]=0,["dvol期望音量-out-avol2-35"]=0,["dvol期望音量-out-avol2-33"]=0,["dvol期望音量-out-x-2-35"]=0,["dvol期望音量-out-avol2-38"]=0,["dvol期望音量-out-x-2-39"]=0,["dvol期望音量-out-x-2-41"]=0,["dvol期望音量-out-avol2-34"]=0,["dvol期望音量-out-x-2-36"]=0,["dvol期望音量-out-avol2-39"]=0,["dvol期望音量-out-x-2-40"]=0,["dvol期望音量-out-avol2-41"]=0,["dvol期望音量-out-x-2-37"]=0,["dvol期望音量-out-avol2-42"]=0,["dvol期望音量-out-x-2-32"]=0,["dvol期望音量-out-x-2-43"]=0,["dvol期望音量-out-avol2-40"]=0,["dvol期望音量-out-avol2-61"]=0,["dvol期望音量-out-avol2-46"]=0,["dvol期望音量-out-avol2-54"]=0,["dvol期望音量-out-x-2-62"]=0,["dvol期望音量-out-avol2-48"]=0,["dvol期望音量-out-avol2-49"]=0,["dvol期望音量-out-avol2-50"]=0,["dvol期望音量-out-avol2-53"]=0,["dvol期望音量-out-x-2-48"]=0,["dvol期望音量-out-x-2-51"]=0,["dvol期望音量-out-x-2-54"]=0,["dvol期望音量-out-avol2-51"]=0,["dvol期望音量-out-avol2-47"]=0,["dvol期望音量-out-x-2-55"]=0,["dvol期望音量-out-x-2-50"]=0,["dvol期望音量-out-x-2-56"]=0,["dvol期望音量-out-x-2-59"]=0,["dvol期望音量-out-avol2-59"]=0,["dvol期望音量-out-x-2-60"]=0,["dvol期望音量-out-avol2-52"]=0,["dvol期望音量-out-x-2-58"]=0,["dvol期望音量-out-x-2-61"]=0,["dvol期望音量-out-x-2-47"]=0,["dvol期望音量-out-x-2-49"]=0,["dvol期望音量-out-avol2-55"]=0,["dvol期望音量-out-avol2-57"]=0,["dvol期望音量-out-avol2-60"]=0,["dvol期望音量-out-x-2-53"]=0,["dvol期望音量-out-avol2-56"]=0,["dvol期望音量-out-x-2-57"]=0,["dvol期望音量-out-x-2-52"]=0,["dvol期望音量-out-avol2-58"]=0,["dvol期望音量-out-x-2-77"]=0,["dvol期望音量-out-avol2-63"]=0,["dvol期望音量-out-x-2-66"]=0,["dvol期望音量-out-avol2-72"]=0,["dvol期望音量-out-avol2-66"]=0,["dvol期望音量-out-x-2-74"]=0,["dvol期望音量-out-x-2-73"]=0,["dvol期望音量-out-avol2-73"]=0,["dvol期望音量-out-avol2-75"]=0,["dvol期望音量-out-x-2-78"]=0,["dvol期望音量-out-x-2-70"]=0,["dvol期望音量-out-avol2-70"]=0,["dvol期望音量-out-avol2-67"]=0,["dvol期望音量-out-x-2-69"]=0,["dvol期望音量-out-x-2-65"]=0,["dvol期望音量-out-avol2-71"]=0,["dvol期望音量-out-avol2-76"]=0,["dvol期望音量-out-avol2-68"]=0,["dvol期望音量-out-avol2-64"]=0,["dvol期望音量-out-x-2-63"]=0,["dvol期望音量-out-x-2-75"]=0,["dvol期望音量-out-x-2-68"]=0,["dvol期望音量-out-avol2-77"]=0,["dvol期望音量-out-x-2-67"]=0,["dvol期望音量-out-x-2-71"]=0,["dvol期望音量-out-avol2-74"]=0,["dvol期望音量-out-x-2-64"]=0,["dvol期望音量-out-x-2-72"]=0,["dvol期望音量-out-avol2-69"]=0,["dvol期望音量-out-x-2-76"]=0,["dvol期望音量-out-avol2-62"]=0,["dvol期望音量-out-avol2-65"]=0,["dvol期望音量-out-avol2-89"]=0,["dvol期望音量-out-x-2-79"]=0,["dvol期望音量-out-x-2-84"]=0,["dvol期望音量-out-avol2-79"]=0,["dvol期望音量-out-x-2-83"]=0,["dvol期望音量-out-avol2-78"]=0,["dvol期望音量-out-x-2-81"]=0,["dvol期望音量-out-avol2-80"]=0,["dvol期望音量-out-avol2-84"]=0,["dvol期望音量-out-x-2-85"]=0,["dvol期望音量-out-x-2-86"]=0,["dvol期望音量-out-avol2-88"]=0,["dvol期望音量-out-x-2-89"]=0,["dvol期望音量-out-avol2-85"]=0,["dvol期望音量-out-avol2-82"]=0,["dvol期望音量-out-x-2-87"]=0,["dvol期望音量-out-x-2-90"]=0,["dvol期望音量-out-avol2-87"]=0,["dvol期望音量-out-avol2-90"]=0,["dvol期望音量-out-x-2-88"]=0,["dvol期望音量-out-x-2-91"]=0,["dvol期望音量-out-avol2-91"]=0,["dvol期望音量-out-x-2-82"]=0,["dvol期望音量-out-avol2-92"]=0,["dvol期望音量-out-x-2-80"]=0,["dvol期望音量-out-avol2-93"]=0,["dvol期望音量-out-avol2-81"]=0,["dvol期望音量-out-x-2-92"]=0,["dvol期望音量-out-avol2-83"]=0,["dvol期望音量-out-x-2-93"]=0,["dvol期望音量-out-avol2-86"]=0,["dvol期望音量-out-x-2-94"]=0,["*device-info-vid*"]="",["dvol期望音量-out-x-2-95"]=0,["音量配置使能开关:"]=1,["dvol期望音量-out-avol2-99"]=0,["提示音音量:"]=25,["dvol期望音量-out-avol2-97"]=0,["dvol期望音量-out-x-2-98"]=0,["*device-info-sdk-version*"]="",["系统最大音量:"]=31,["*device-info-pid*"]="",["dvol期望音量-out-avol2-94"]=0,["dvol期望音量-out-x-2-96"]=0,["dvol期望音量-out-x-2-100"]=0,["dvol期望音量-out-x-2-97"]=0,["dvol期望音量-out-avol2-96"]=0,["dvol第二种,最小音量2"]=-45.000000,["dvol期望音量-out-avol2-98"]=0,["dvol第一种,最大音量2"]=-14.000000,["dvol第一种,档位个数2"]=15,["dvol第二种,递音量2"]=2.000000,["系统默认音量:"]=25,["dvol第一种,最小音量2"]=-45.000000,["dvol期望音量-out-avol2-100"]=0,["volume_cfg"]=0,["dvol期望音量-out-x-2-99"]=0,["*device-info-checksum*"]="",["dvol第二种,最大音量2"]=-14.000000,["dvol期望音量-out-avol2-95"]=0} \ No newline at end of file diff --git a/cpu/br23/tools/common b/cpu/br23/tools/common new file mode 100644 index 0000000..e69de29 diff --git a/cpu/br23/tools/download.bat b/cpu/br23/tools/download.bat new file mode 100644 index 0000000..e713c21 --- /dev/null +++ b/cpu/br23/tools/download.bat @@ -0,0 +1,67 @@ + + + +rem @echo off + +@echo ***************************************************************** +@echo SDK BR23 +@echo ***************************************************************** +@echo %date% + +cd %~dp0 + + +set OBJDUMP=C:\JL\pi32\bin\llvm-objdump.exe +set OBJCOPY=C:\JL\pi32\bin\llvm-objcopy.exe +set ELFFILE=sdk.elf + +%OBJDUMP% -D -address-mask=0x1ffffff -print-dbg %ELFFILE% > sdk.lst +%OBJCOPY% -O binary -j .text %ELFFILE% text.bin +%OBJCOPY% -O binary -j .data %ELFFILE% data.bin +%OBJCOPY% -O binary -j .data_code %ELFFILE% data_code.bin + + +%OBJCOPY% -O binary -j .overlay_aec %ELFFILE% aeco.bin +%OBJCOPY% -O binary -j .overlay_wav %ELFFILE% wav.bin +%OBJCOPY% -O binary -j .overlay_ape %ELFFILE% ape.bin +%OBJCOPY% -O binary -j .overlay_flac %ELFFILE% flac.bin +%OBJCOPY% -O binary -j .overlay_m4a %ELFFILE% m4a.bin +%OBJCOPY% -O binary -j .overlay_amr %ELFFILE% amr.bin +%OBJCOPY% -O binary -j .overlay_dts %ELFFILE% dts.bin +%OBJCOPY% -O binary -j .overlay_fm %ELFFILE% fmo.bin +%OBJCOPY% -O binary -j .overlay_mp3 %ELFFILE% mp3o.bin +%OBJCOPY% -O binary -j .overlay_wma %ELFFILE% wmao.bin + + +remove_tailing_zeros -i aeco.bin -o aec.bin -mark ff +remove_tailing_zeros -i fmo.bin -o fm.bin -mark ff +remove_tailing_zeros -i mp3o.bin -o mp3.bin -mark ff +remove_tailing_zeros -i wmao.bin -o wma.bin -mark ff + + + +%OBJDUMP% -section-headers -address-mask=0x1ffffff %ELFFILE% +%OBJDUMP% -t %ELFFILE% > symbol_tbl.txt +copy /b text.bin+data.bin+data_code.bin+aec.bin+wav.bin+ape.bin+flac.bin+m4a.bin+amr.bin+dts.bin+fm.bin+mp3.bin+wma.bin+bank.bin app.bin + + +del aeco.bin +del wav.bin +del ape.bin +del flac.bin +del m4a.bin +del amr.bin +del dts.bin +del fmo.bin +del mp3o.bin +del wmao.bin +del aec.bin +del fm.bin +del mp3.bin +del wma.bin +del data.bin +del data_code.bin +del text.bin +del *.bc +copy .\effect_file\music_base.bin eq_cfg_hw.bin +download\standard\download.bat diff --git a/cpu/br23/tools/download.c b/cpu/br23/tools/download.c new file mode 100644 index 0000000..4b3b0a7 --- /dev/null +++ b/cpu/br23/tools/download.c @@ -0,0 +1,242 @@ +// *INDENT-OFF* +#include "app_config.h" + +#ifdef __SHELL__ + +##!/bin/sh +${OBJDUMP} -D -address-mask=0x1ffffff -print-dbg $1.elf > $1.lst +${OBJCOPY} -O binary -j .text $1.elf text.bin +${OBJCOPY} -O binary -j .data $1.elf data.bin +${OBJCOPY} -O binary -j .data_code $1.elf data_code.bin + +${OBJCOPY} -O binary -j .overlay_aec $1.elf aeco.bin +${OBJCOPY} -O binary -j .overlay_wav $1.elf wav.bin +${OBJCOPY} -O binary -j .overlay_ape $1.elf ape.bin +${OBJCOPY} -O binary -j .overlay_flac $1.elf flac.bin +${OBJCOPY} -O binary -j .overlay_m4a $1.elf m4a.bin +${OBJCOPY} -O binary -j .overlay_amr $1.elf amr.bin +${OBJCOPY} -O binary -j .overlay_dts $1.elf dts.bin +${OBJCOPY} -O binary -j .overlay_fm $1.elf fmo.bin +${OBJCOPY} -O binary -j .overlay_mp3 $1.elf mp3o.bin +${OBJCOPY} -O binary -j .overlay_wma $1.elf wmao.bin + + + +/opt/utils/remove_tailing_zeros -i aeco.bin -o aec.bin -mark ff +/opt/utils/remove_tailing_zeros -i fmo.bin -o fm.bin -mark ff +/opt/utils/remove_tailing_zeros -i mp3o.bin -o mp3.bin -mark ff +/opt/utils/remove_tailing_zeros -i wmao.bin -o wma.bin -mark ff + + +${OBJDUMP} -section-headers -address-mask=0x1ffffff $1.elf +${OBJSIZEDUMP} -lite -skip-zero -enable-dbg-info $1.elf | sort -k 1 > symbol_tbl.txt + + +files="app.bin br23loader.bin br23loader.uart uboot.boot uboot.boot_debug uboot_no_ota.boot uboot_no_ota.boot_debug ota_all.bin ota_all_debug.bin ota_nor.bin ota_nor_debug.bin isd_config.ini isd_download.exe fw_add.exe ufw_maker.exe packres.exe json_to_res.exe md5sum.exe" + + + + +#if defined(TCFG_MIC_EFFECT_ENABLE)&& TCFG_MIC_EFFECT_ENABLE && (TCFG_MIC_EFFECT_SEL == MIC_EFFECT_REVERB)&& TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE +cp ./effect_file/mic_effect_reverb_full.bin eq_cfg_hw.bin +#elif defined(TCFG_MIC_EFFECT_ENABLE)&& TCFG_MIC_EFFECT_ENABLE && (TCFG_MIC_EFFECT_SEL == MIC_EFFECT_REVERB) +cp ./effect_file/mic_effect_reverb.bin eq_cfg_hw.bin +#elif defined(TCFG_MIC_EFFECT_ENABLE)&& TCFG_MIC_EFFECT_ENABLE && (TCFG_MIC_EFFECT_SEL == MIC_EFFECT_ECHO)&& TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE +cp ./effect_file/mic_effect_echo_full.bin eq_cfg_hw.bin +#elif defined(TCFG_MIC_EFFECT_ENABLE)&& TCFG_MIC_EFFECT_ENABLE && (TCFG_MIC_EFFECT_SEL == MIC_EFFECT_ECHO) +cp ./effect_file/mic_effect_echo.bin eq_cfg_hw.bin +#elif defined(TCFG_MIC_EFFECT_ENABLE)&& TCFG_MIC_EFFECT_ENABLE && (TCFG_MIC_EFFECT_SEL == MIC_EFFECT_REVERB_ECHO) +cp ./effect_file/mic_effect_full.bin eq_cfg_hw.bin +#elif defined(TCFG_MIC_EFFECT_ENABLE)&& TCFG_MIC_EFFECT_ENABLE && (TCFG_MIC_EFFECT_SEL == MIC_EFFECT_MEGAPHONE) +cp ./effect_file/mic_effect_megaphone.bin eq_cfg_hw.bin +#elif defined(SOUND_TRACK_2_P_X_CH_CONFIG) &&SOUND_TRACK_2_P_X_CH_CONFIG +cp ./effect_file/music_2to1_2to2.bin eq_cfg_hw.bin +#elif defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN +cp ./effect_file/music_base_linein.bin eq_cfg_hw.bin +#else +cp ./effect_file/music_base.bin eq_cfg_hw.bin +#endif + +#if(CONFIG_SPP_AND_LE_CASE_ENABLE || CONFIG_HID_CASE_ENABLE || CONFIG_MESH_CASE_ENABLE || CONFIG_GAMEBOX_CASE) +#if RCSP_UPDATE_EN + +NICKNAME="br23_app_ota" + +cp bluetooth/app_ota/isd_config.ini ./ +cp bluetooth/app_ota/download.bat ./ + +#else + +NICKNAME="br23_sdk" + +cp bluetooth/standard/isd_config.ini ./ +cp bluetooth/standard/download.bat ./ + +#endif + +cat text.bin data.bin data_code.bin \ + > app.bin + +#else + +NICKNAME="br23_sdk" + +#if CONFIG_WATCH_CASE_ENABLE +#if CONFIG_DOUBLE_BANK_ENABLE +cp download/watch/isd_config_double_bank.ini ./isd_config.ini +#else +cp download/watch/isd_config.ini ./ +#endif +cp download/watch/download.bat ./ +#else +cp download/standard/isd_config.ini ./ +cp download/standard/download.bat ./ +#endif + +cat text.bin data.bin data_code.bin \ + aec.bin \ + wav.bin \ + ape.bin \ + flac.bin \ + m4a.bin \ + amr.bin \ + dts.bin \ + fm.bin \ + mp3.bin \ + wma.bin \ + bank.bin \ + > app.bin + +#endif + +host-client -project ${NICKNAME}$2_${APP_CASE} -f ${files} $1.elf + +#else + + +rem @echo off + +@echo ***************************************************************** +@echo SDK BR23 +@echo ***************************************************************** +@echo %date% + +cd %~dp0 + + +set OBJDUMP=C:\JL\pi32\bin\llvm-objdump.exe +set OBJCOPY=C:\JL\pi32\bin\llvm-objcopy.exe +set ELFFILE=sdk.elf + +%OBJDUMP% -D -address-mask=0x1ffffff -print-dbg %ELFFILE% > sdk.lst +%OBJCOPY% -O binary -j .text %ELFFILE% text.bin +%OBJCOPY% -O binary -j .data %ELFFILE% data.bin +%OBJCOPY% -O binary -j .data_code %ELFFILE% data_code.bin + + +%OBJCOPY% -O binary -j .overlay_aec %ELFFILE% aeco.bin +%OBJCOPY% -O binary -j .overlay_wav %ELFFILE% wav.bin +%OBJCOPY% -O binary -j .overlay_ape %ELFFILE% ape.bin +%OBJCOPY% -O binary -j .overlay_flac %ELFFILE% flac.bin +%OBJCOPY% -O binary -j .overlay_m4a %ELFFILE% m4a.bin +%OBJCOPY% -O binary -j .overlay_amr %ELFFILE% amr.bin +%OBJCOPY% -O binary -j .overlay_dts %ELFFILE% dts.bin +%OBJCOPY% -O binary -j .overlay_fm %ELFFILE% fmo.bin +%OBJCOPY% -O binary -j .overlay_mp3 %ELFFILE% mp3o.bin +%OBJCOPY% -O binary -j .overlay_wma %ELFFILE% wmao.bin + + +remove_tailing_zeros -i aeco.bin -o aec.bin -mark ff +remove_tailing_zeros -i fmo.bin -o fm.bin -mark ff +remove_tailing_zeros -i mp3o.bin -o mp3.bin -mark ff +remove_tailing_zeros -i wmao.bin -o wma.bin -mark ff + + + +%OBJDUMP% -section-headers -address-mask=0x1ffffff %ELFFILE% +%OBJDUMP% -t %ELFFILE% > symbol_tbl.txt + +#if CONFIG_SPP_AND_LE_CASE_ENABLE || CONFIG_HID_CASE_ENABLE || CONFIG_MESH_CASE_ENABLE || CONFIG_GAMEBOX_CASE +copy /b text.bin+data.bin+data_code.bin+bank.bin app.bin + +#if TCFG_KWS_VOICE_RECOGNITION_ENABLE +set kws_cfg=..\..\jl_kws.cfg +#endif + +#if APP_UPDATE_EN +bluetooth\app_ota\download.bat %kws_cfg% +#else +bluetooth\standard\download.bat %kws_cfg% +#endif + +#else +copy /b text.bin+data.bin+data_code.bin+aec.bin+wav.bin+ape.bin+flac.bin+m4a.bin+amr.bin+dts.bin+fm.bin+mp3.bin+wma.bin+bank.bin app.bin +#endif //endif CONFIG_SPP_AND_LE_CASE_ENABLE || CONFIG_HID_CASE_ENABLE || CONFIG_MESH_CASE_ENABLE || CONFIG_GAMEBOX_CASE + +del aeco.bin +del wav.bin +del ape.bin +del flac.bin +del m4a.bin +del amr.bin +del dts.bin +del fmo.bin +del mp3o.bin +del wmao.bin +del aec.bin +del fm.bin +del mp3.bin +del wma.bin +del data.bin +del data_code.bin +del text.bin +del *.bc + + + +#if defined(TCFG_MIC_EFFECT_ENABLE)&& TCFG_MIC_EFFECT_ENABLE && (TCFG_MIC_EFFECT_SEL == MIC_EFFECT_REVERB) && TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE +copy .\effect_file\mic_effect_reverb_full.bin eq_cfg_hw.bin +#elif defined(TCFG_MIC_EFFECT_ENABLE)&& TCFG_MIC_EFFECT_ENABLE && (TCFG_MIC_EFFECT_SEL == MIC_EFFECT_REVERB) +copy .\effect_file\mic_effect_reverb.bin eq_cfg_hw.bin +#elif defined(TCFG_MIC_EFFECT_ENABLE)&& TCFG_MIC_EFFECT_ENABLE && (TCFG_MIC_EFFECT_SEL == MIC_EFFECT_ECHO) && TCFG_AUDIO_MIC_EFFECT_POST_EQ_ENABLE +copy .\effect_file\mic_effect_echo_full.bin eq_cfg_hw.bin +#elif defined(TCFG_MIC_EFFECT_ENABLE)&& TCFG_MIC_EFFECT_ENABLE && (TCFG_MIC_EFFECT_SEL == MIC_EFFECT_ECHO) +copy .\effect_file\mic_effect_echo.bin eq_cfg_hw.bin +#elif defined(TCFG_MIC_EFFECT_ENABLE)&& TCFG_MIC_EFFECT_ENABLE && (TCFG_MIC_EFFECT_SEL == MIC_EFFECT_REVERB_ECHO) +copy .\effect_file\mic_effect_full.bin eq_cfg_hw.bin +#elif defined(TCFG_MIC_EFFECT_ENABLE)&& TCFG_MIC_EFFECT_ENABLE && (TCFG_MIC_EFFECT_SEL == MIC_EFFECT_MEGAPHONE) +copy .\effect_file\mic_effect_megaphone.bin eq_cfg_hw.bin +#elif defined(SOUND_TRACK_2_P_X_CH_CONFIG) &&SOUND_TRACK_2_P_X_CH_CONFIG +copy .\effect_file\music_2to1_2to2.bin eq_cfg_hw.bin +#elif defined(LINEIN_MODE_SOLE_EQ_EN) && LINEIN_MODE_SOLE_EQ_EN +copy .\effect_file\music_base_linein.bin eq_cfg_hw.bin +#else +copy .\effect_file\music_base.bin eq_cfg_hw.bin +#endif + + +#ifdef CONFIG_BOARD_AC695X_SOUNDCARD + +download\soundcard\download.bat + +#elif CONFIG_WATCH_CASE_ENABLE + +download\watch\download.bat + +#elif APP_UPDATE_EN + +download\app_ota\download.bat + +#elif CONFIG_SPP_AND_LE_CASE_ENABLE || CONFIG_HID_CASE_ENABLE || CONFIG_MESH_CASE_ENABLE || CONFIG_GAMEBOX_CASE + +bluetooth\standard\download.bat + +#else + +download\standard\download.bat + +#endif //endif CONFIG_SOUNDBOX_CASE_ENABLE + +#endif + + diff --git a/cpu/br23/tools/download.sh b/cpu/br23/tools/download.sh new file mode 100644 index 0000000..8c20957 --- /dev/null +++ b/cpu/br23/tools/download.sh @@ -0,0 +1,44 @@ + + + + + + +##!/bin/sh +${OBJDUMP} -D -address-mask=0x1ffffff -print-dbg $1.elf > $1.lst +${OBJCOPY} -O binary -j .text $1.elf text.bin +${OBJCOPY} -O binary -j .data $1.elf data.bin +${OBJCOPY} -O binary -j .data_code $1.elf data_code.bin + +${OBJCOPY} -O binary -j .overlay_aec $1.elf aeco.bin +${OBJCOPY} -O binary -j .overlay_wav $1.elf wav.bin +${OBJCOPY} -O binary -j .overlay_ape $1.elf ape.bin +${OBJCOPY} -O binary -j .overlay_flac $1.elf flac.bin +${OBJCOPY} -O binary -j .overlay_m4a $1.elf m4a.bin +${OBJCOPY} -O binary -j .overlay_amr $1.elf amr.bin +${OBJCOPY} -O binary -j .overlay_dts $1.elf dts.bin +${OBJCOPY} -O binary -j .overlay_fm $1.elf fmo.bin +${OBJCOPY} -O binary -j .overlay_mp3 $1.elf mp3o.bin +${OBJCOPY} -O binary -j .overlay_wma $1.elf wmao.bin + + + +/opt/utils/remove_tailing_zeros -i aeco.bin -o aec.bin -mark ff +/opt/utils/remove_tailing_zeros -i fmo.bin -o fm.bin -mark ff +/opt/utils/remove_tailing_zeros -i mp3o.bin -o mp3.bin -mark ff +/opt/utils/remove_tailing_zeros -i wmao.bin -o wma.bin -mark ff + + +${OBJDUMP} -section-headers -address-mask=0x1ffffff $1.elf +${OBJSIZEDUMP} -lite -skip-zero -enable-dbg-info $1.elf | sort -k 1 > symbol_tbl.txt + + +files="app.bin br23loader.bin br23loader.uart uboot.boot uboot.boot_debug uboot_no_ota.boot uboot_no_ota.boot_debug ota_all.bin ota_all_debug.bin ota_nor.bin ota_nor_debug.bin isd_config.ini isd_download.exe fw_add.exe ufw_maker.exe packres.exe json_to_res.exe md5sum.exe" +cp music_base.bin eq_cfg_hw.bin +NICKNAME="br23_sdk" +cp download/standard/isd_config.ini ./ +cp download/standard/download.bat ./ + + +cat text.bin data.bin data_code.bin aec.bin wav.bin ape.bin flac.bin m4a.bin amr.bin dts.bin fm.bin mp3.bin wma.bin bank.bin > app.bin +host-client -project ${NICKNAME}$2_${APP_CASE} -f ${files} $1.elf diff --git a/cpu/br23/tools/download/app_ota/download.bat b/cpu/br23/tools/download/app_ota/download.bat new file mode 100644 index 0000000..6fb640e --- /dev/null +++ b/cpu/br23/tools/download/app_ota/download.bat @@ -0,0 +1,68 @@ +@echo off + +cd %~dp0 + +copy ..\..\script.ver . +copy ..\..\uboot.boot . +copy ..\..\tone.cfg . +copy ..\..\cfg_tool.bin . +copy ..\..\app.bin . +copy ..\..\br23loader.bin . +copy ..\..\eq_cfg_hw.bin . +copy ..\..\ota_all.bin . +copy ..\..\ota_nor.bin . + + +..\..\json_to_res.exe json.txt +..\..\md5sum.exe app.bin md5.bin +set /p "themd5=" < "md5.bin" + +..\..\isd_download.exe -tonorflash -dev br23 -boot 0x12000 -div8 -wait 300 -uboot uboot.boot -app app.bin -res tone.cfg cfg_tool.bin eq_cfg_hw.bin %1 config.dat md5.bin +:: -format all +::-reboot 2500 + + + +@rem ɾʱļ-format all +if exist *.mp3 del *.mp3 +if exist *.PIX del *.PIX +if exist *.TAB del *.TAB +if exist *.res del *.res +if exist *.sty del *.sty + + + +@rem ɹ̼ļ +copy ota_all.bin ota.bin +..\..\fw_add.exe -noenc -fw jl_isd.fw -add ota.bin -type 100 -out jl_isd_all.fw +copy ota_nor.bin ota.bin +..\..\fw_add.exe -noenc -fw jl_isd.fw -add ota.bin -type 100 -out jl_isd_nor.fw +@rem ýűİ汾Ϣ FW ļ +..\..\fw_add.exe -noenc -fw jl_isd_all.fw -add script.ver -out jl_isd_all.fw +..\..\fw_add.exe -noenc -fw jl_isd_nor.fw -add script.ver -out jl_isd_nor.fw + + + +if exist update_*.ufw del update_*.ufw + +..\..\ufw_maker.exe -fw_to_ufw jl_isd_all.fw +..\..\ufw_maker.exe -fw_to_ufw jl_isd_nor.fw +copy jl_isd_all.ufw update_%themd5%.ufw +copy jl_isd_nor.ufw nor_update.ufw +copy jl_isd_all.fw jl_isd.fw +del jl_isd_all.ufw jl_isd_nor.ufw jl_isd_all.fw jl_isd_nor.fw + + +@REM ļļ +::ufw_maker.exe -chip AC800X %ADD_KEY% -output config.ufw -res bt_cfg.cfg + +::IF EXIST jl_696x.bin del jl_696x.bin + + +@rem ˵ +@rem -format vm //VM +@rem -format cfg //BT CFG +@rem -format 0x3f0-2 //ʾӵ 0x3f0 sector ʼ 2 sector(һΪ16ƻ10ƶɣڶ10) + +ping /n 2 127.1>null +IF EXIST null del null diff --git a/cpu/br23/tools/download/app_ota/isd_config.ini b/cpu/br23/tools/download/app_ota/isd_config.ini new file mode 100644 index 0000000..d4e3c02 --- /dev/null +++ b/cpu/br23/tools/download/app_ota/isd_config.ini @@ -0,0 +1,122 @@ +# +# +# 配置数据按照 长度+配置名字+数据的方式存储 +# +# + +[EXTRA_CFG_PARAM] +NEW_FLASH_FS=YES; +FORCE_VM_ALIGN=YES; +CHIP_NAME=AC695X;//芯片型号 +ENTRY=0x1E00100;//程序入口地址 +PID=AC695N_soundbox;//长度16byte,示例:芯片封装_应用方向_方案名称 +VID=0.01; + +RESERVED_OPT=0; +SPECIAL_OPT=0; +FORCE_4K_ALIGN=YES; + +#DOWNLOAD_MODEL=SERIAL;//usb +DOWNLOAD_MODEL=usb;// +SERIAL_DEVICE_NAME=JlVirtualJtagSerial; +SERIAL_BARD_RATE=1000000; +SERIAL_CMD_OPT=6; +SERIAL_CMD_RATE=100; [n*10000] +SERIAL_CMD_RES=0; +SERIAL_INIT_BAUD_RATE=9600; +LOADER_BAUD_RATE=1000000; +LOADER_ASK_BAUD_RATE=1000000; +#SERIAL_SEND_KEY=YES; +BEFORE_LOADER_WAIT_TIME=100; + +NEED_RESERVED_4K=YES;//关闭4K保留 +##################### 烧写器配置选项, 请根据实际情况修改 ##################### +##################### 烧写器配置选项, 请根据实际情况修改 ##################### +##################### 烧写器配置选项, 请根据实际情况修改 ##################### +[BURNER_OPTIONS] +SDK_TYPE=SOUNDBOX; // SOUNDBOX:音箱方案 OTHER:其他方案(比如:耳机,BLE) SDK类型:当前仅支持音箱和非音箱两种类型 + +##################### 匹配的芯片版本, 请勿随意修改 ##################### +##################### 匹配的芯片版本, 请勿随意修改 ##################### +##################### 匹配的芯片版本, 请勿随意修改 ##################### +##################### 匹配的芯片版本, 请勿随意修改 ##################### +[CHIP_VERSION] +SUPPORTED_LIST=A,B,D;//匹配的芯片版本 + + +#UBOOT配置项,请勿随意调整顺序 # +[SYS_CFG_PARAM] +#data_width[0 1 2 3 4] 3的时候uboot自动识别2或者4线 +#clk [0-255] +#mode: +# 0 RD_OUTPUT, 1 cmd 1 addr +# 1 RD_I/O, 1 cmd x addr +# 2 RD_I/O_CONTINUE] no_send_cmd x add +#port: +# 0 优先选A端口 CS:PD3 CLK:PD0 D0:PD1 D1:PD2 D2:PB7 D3:PD5 +# 1 优先选B端口 CS:PA13 CLK:PD0 D0:PD1 D1:PA14 D2:PA15 D3:PD5 +SPI=2_3_0_0; #width_clk_mode_port; +#OSC=btosc; +#OSC_FREQ=12MHz; #[24MHz 12MHz] +#SYS_CLK=24MHz; #[48MHz 24MHz] +#UTTX=PA05;//uboot串口tx +#UTBD=1000000;//uboot串口波特率 +#UTRX=PB01;串口升级[PB00 PB05 PA05] +RESET=PB01_00_0; //port口_长按时间_有效电平(长按时间有00、01、02、04、08五个值可选,单位为秒,当长按时间为00时,则关闭长按复位功能。) +UPDATE_JUMP=0; //是否支持升级过程中维持IO电平,用于一些使用IO口维持芯片供电的方案 + +#0:disable +#1:PA9 PA10 +#2:USB +#3:PB1 PB2 +#4:PB6 PB7 + +#sdtap=2; +psram=0; + +VLVD=4;//VDDIO_LVD挡位,0: 1.9V 1: 2.0V 2: 2.1V 3: 2.2V 4: 2.3V 5: 2.4V 6: 2.5V 7: 2.6V + +#EADDR=0; //ENTRY_ADDR; +EOFFSET=0; // 4k * n,默认强制不偏移 + +############################################################################################################################################# + + + +########flash空间使用配置区域############################################### +#PDCTNAME: 产品名,对应此代码,用于标识产品,升级时可以选择匹配产品名 +#BOOT_FIRST: 1=代码更新后,提示APP是第一次启动;0=代码更新后,不提示 +#UPVR_CTL: 0:不允许高版本升级低版本 1:允许高版本升级低版本 +#XXXX_ADR: 区域起始地址 AUTO:由工具自动分配起始地址 +#XXXX_LEN: 区域长度 CODE_LEN:代码长度 +#XXXX_OPT: 区域操作属性 +# +# +# +#操作符说明 OPT: +# 0: 下载代码时擦除指定区域 +# 1: 下载代码时不操作指定区域 +# 2: 下载代码时给指定区域加上保护 +############################################################################ +[RESERVED_CONFIG] +BTIF_ADR=AUTO; +BTIF_LEN=0x1000; +BTIF_OPT=1; + +EXIF_ADR=AUTO; +EXIF_LEN=0x1000; +EXIF_OPT=1; + +PRCT_ADR=0; +PRCT_LEN=CODE_LEN; +PRCT_OPT=2; + +VM_ADR=0; +VM_LEN=32K; +VM_OPT=1; + +[BURNER_CONFIG] +SIZE=32; + + + diff --git a/cpu/br23/tools/download/app_ota/json.txt b/cpu/br23/tools/download/app_ota/json.txt new file mode 100644 index 0000000..a3bb6f0 --- /dev/null +++ b/cpu/br23/tools/download/app_ota/json.txt @@ -0,0 +1,55 @@ +{ + "output": "config.dat", + "defines": + { + "DEFINE1": "0xA", + "DEFINE2": "0xB", + "DEFINE3": "0xC", + "DEFINE4": "default4", + "DEFINE5": "default5", + "DEFINE6": 1234, + "DEFINE7": 1, + "DEFINE8": 2, + "DEFINE9": 3234, + "DEFINE10": 4 + }, + "items": + [ + { + "name": "ver_info", + "说明": "版本信息:VID(2byte),PID(2byte),VER(2byte)", + "type": "ARRAY", + "data": "0x00, 0x02, 0x00, 0x5F, 0x00, 0x00" + }, + { + "name": "ver_info_ext", + "说明": "额外信息(AuthKey,ProCode)", + "type": "STRING", + "data": "hE9yfseX6UdK7rFh,jl_v8" + }, + { + "name": "reset_io", + "说明": "uboot中PR口长按复位io选择,目前可配0、1、2、3", + "type": "STRING", + "data": "1" + }, + { + "name": "pilot_lamp_io", + "说明": "uboot中led指示灯IO配置,目前可配PA、PB、PC、PD", + "type": "STRING", + "data": "PB03" + }, + { + "name": "link_key", + "说明": "用于link_key_data的配置", + "type": "ARRAY", + "data": "0x06, 0x77, 0x5f, 0x87, 0x91, 0x8d, 0xd4, 0x23, 0x00, 0x5d, 0xf1, 0xd8, 0xcf, 0x0c, 0x14, 0x2b" + }, + { + "name": "power_io", + "说明": "用与电源io的配置,0代表低电平,1代表高电平", + "type": "STRING", + "data": "PC03_1" + } + ] +} diff --git a/cpu/br23/tools/download/soundcard/download.bat b/cpu/br23/tools/download/soundcard/download.bat new file mode 100644 index 0000000..e07d55f --- /dev/null +++ b/cpu/br23/tools/download/soundcard/download.bat @@ -0,0 +1,66 @@ +@echo off + +cd %~dp0 + +copy ..\..\script.ver . +copy ..\..\uboot.boot . +copy ..\..\cfg_tool.bin . +copy ..\..\app.bin . +copy ..\..\br23loader.bin . +copy ..\..\eq_cfg_hw.bin . +copy ..\..\ota_all.bin . +copy ..\..\ota_nor.bin . + + +..\..\json_to_res.exe json.txt +..\..\md5sum.exe app.bin md5.bin +set /p "themd5=" < "md5.bin" + +..\..\isd_download.exe -tonorflash -dev br23 -boot 0x12000 -div8 -wait 300 -uboot uboot.boot -app app.bin -res tone.cfg cfg_tool.bin eq_cfg_hw.bin config.dat md5.bin +:: -format all +::-reboot 2500 + + + +@rem ɾʱļ-format all +if exist *.mp3 del *.mp3 +if exist *.PIX del *.PIX +if exist *.TAB del *.TAB +if exist *.res del *.res +if exist *.sty del *.sty + + + +@rem ɹ̼ļ +copy ota_all.bin ota.bin +..\..\fw_add.exe -noenc -fw jl_isd.fw -add ota.bin -type 100 -out jl_isd_all.fw +copy ota_nor.bin ota.bin +..\..\fw_add.exe -noenc -fw jl_isd.fw -add ota.bin -type 100 -out jl_isd_nor.fw +@rem ýűİ汾Ϣ FW ļ +..\..\fw_add.exe -noenc -fw jl_isd_all.fw -add script.ver -out jl_isd_all.fw +..\..\fw_add.exe -noenc -fw jl_isd_nor.fw -add script.ver -out jl_isd_nor.fw + + +if exist update_*.ufw del update_*.ufw + +..\..\ufw_maker.exe -fw_to_ufw jl_isd_all.fw +..\..\ufw_maker.exe -fw_to_ufw jl_isd_nor.fw +copy jl_isd_all.ufw update_%themd5%.ufw +copy jl_isd_nor.ufw nor_update.ufw +copy jl_isd_all.fw jl_isd.fw +del jl_isd_all.ufw jl_isd_nor.ufw jl_isd_all.fw jl_isd_nor.fw + + +@REM ļļ +::ufw_maker.exe -chip AC800X %ADD_KEY% -output config.ufw -res bt_cfg.cfg + +::IF EXIST jl_696x.bin del jl_696x.bin + + +@rem ˵ +@rem -format vm //VM +@rem -format cfg //BT CFG +@rem -format 0x3f0-2 //ʾӵ 0x3f0 sector ʼ 2 sector(һΪ16ƻ10ƶɣڶ10) + +ping /n 2 127.1>null +IF EXIST null del null diff --git a/cpu/br23/tools/download/soundcard/isd_config.ini b/cpu/br23/tools/download/soundcard/isd_config.ini new file mode 100644 index 0000000..98f9659 --- /dev/null +++ b/cpu/br23/tools/download/soundcard/isd_config.ini @@ -0,0 +1,122 @@ +# +# +# 配置数据按照 长度+配置名字+数据的方式存储 +# +# + +[EXTRA_CFG_PARAM] +NEW_FLASH_FS=YES; +FORCE_VM_ALIGN=YES; +CHIP_NAME=AC695X;//芯片型号 +ENTRY=0x1E00100;//程序入口地址 +PID=AC695N_soundbox;//长度16byte,示例:芯片封装_应用方向_方案名称 +VID=0.01; + +RESERVED_OPT=0; +SPECIAL_OPT=0; +FORCE_4K_ALIGN=YES; + +#DOWNLOAD_MODEL=SERIAL;//usb +DOWNLOAD_MODEL=usb;// +SERIAL_DEVICE_NAME=JlVirtualJtagSerial; +SERIAL_BARD_RATE=1000000; +SERIAL_CMD_OPT=6; +SERIAL_CMD_RATE=100; [n*10000] +SERIAL_CMD_RES=0; +SERIAL_INIT_BAUD_RATE=9600; +LOADER_BAUD_RATE=1000000; +LOADER_ASK_BAUD_RATE=1000000; +#SERIAL_SEND_KEY=YES; +BEFORE_LOADER_WAIT_TIME=100; + +NEED_RESERVED_4K=YES;//关闭4K保留 + +##################### 烧写器配置选项, 请根据实际情况修改 ##################### +##################### 烧写器配置选项, 请根据实际情况修改 ##################### +##################### 烧写器配置选项, 请根据实际情况修改 ##################### +[BURNER_OPTIONS] +SDK_TYPE=SOUNDBOX; // SOUNDBOX:音箱方案 OTHER:其他方案(比如:耳机,BLE) SDK类型:当前仅支持音箱和非音箱两种类型 + +##################### 匹配的芯片版本, 请勿随意修改 ##################### +##################### 匹配的芯片版本, 请勿随意修改 ##################### +##################### 匹配的芯片版本, 请勿随意修改 ##################### +##################### 匹配的芯片版本, 请勿随意修改 ##################### +[CHIP_VERSION] +SUPPORTED_LIST=A,B,D;//匹配的芯片版本 + +#UBOOT配置项,请勿随意调整顺序 # +[SYS_CFG_PARAM] +#data_width[0 1 2 3 4] 3的时候uboot自动识别2或者4线 +#clk [0-255] +#mode: +# 0 RD_OUTPUT, 1 cmd 1 addr +# 1 RD_I/O, 1 cmd x addr +# 2 RD_I/O_CONTINUE] no_send_cmd x add +#port: +# 0 优先选A端口 CS:PD3 CLK:PD0 D0:PD1 D1:PD2 D2:PB7 D3:PD5 +# 1 优先选B端口 CS:PA13 CLK:PD0 D0:PD1 D1:PA14 D2:PA15 D3:PD5 +SPI=2_3_0_0; #width_clk_mode_port; +#OSC=btosc; +#OSC_FREQ=12MHz; #[24MHz 12MHz] +#SYS_CLK=24MHz; #[48MHz 24MHz] +#UTTX=PA05;//uboot串口tx +#UTBD=1000000;//uboot串口波特率 +#UTRX=PB01;串口升级[PB00 PB05 PA05] +RESET=PB01_00_0; //port口_长按时间_有效电平(长按时间有00、01、02、04、08五个值可选,单位为秒,当长按时间为00时,则关闭长按复位功能。) +UPDATE_JUMP=0; //是否支持升级过程中维持IO电平,用于一些使用IO口维持芯片供电的方案 + +#0:disable +#1:PA9 PA10 +#2:USB +#3:PB1 PB2 +#4:PB6 PB7 + +#sdtap=2; +psram=0; + +VLVD=4;//VDDIO_LVD挡位,0: 1.9V 1: 2.0V 2: 2.1V 3: 2.2V 4: 2.3V 5: 2.4V 6: 2.5V 7: 2.6V + +#EADDR=0; //ENTRY_ADDR; +EOFFSET=0; // 4k * n,默认强制不偏移 + +############################################################################################################################################# + + + +########flash空间使用配置区域############################################### +#PDCTNAME: 产品名,对应此代码,用于标识产品,升级时可以选择匹配产品名 +#BOOT_FIRST: 1=代码更新后,提示APP是第一次启动;0=代码更新后,不提示 +#UPVR_CTL: 0:不允许高版本升级低版本 1:允许高版本升级低版本 +#XXXX_ADR: 区域起始地址 AUTO:由工具自动分配起始地址 +#XXXX_LEN: 区域长度 CODE_LEN:代码长度 +#XXXX_OPT: 区域操作属性 +# +# +# +#操作符说明 OPT: +# 0: 下载代码时擦除指定区域 +# 1: 下载代码时不操作指定区域 +# 2: 下载代码时给指定区域加上保护 +############################################################################ +[RESERVED_CONFIG] +BTIF_ADR=AUTO; +BTIF_LEN=0x1000; +BTIF_OPT=1; + +EXIF_ADR=AUTO; +EXIF_LEN=0x1000; +EXIF_OPT=1; + +PRCT_ADR=0; +PRCT_LEN=CODE_LEN; +PRCT_OPT=2; + +VM_ADR=0; +VM_LEN=32K; +VM_OPT=1; + +[BURNER_CONFIG] +SIZE=32; + + + diff --git a/cpu/br23/tools/download/soundcard/json.txt b/cpu/br23/tools/download/soundcard/json.txt new file mode 100644 index 0000000..a3bb6f0 --- /dev/null +++ b/cpu/br23/tools/download/soundcard/json.txt @@ -0,0 +1,55 @@ +{ + "output": "config.dat", + "defines": + { + "DEFINE1": "0xA", + "DEFINE2": "0xB", + "DEFINE3": "0xC", + "DEFINE4": "default4", + "DEFINE5": "default5", + "DEFINE6": 1234, + "DEFINE7": 1, + "DEFINE8": 2, + "DEFINE9": 3234, + "DEFINE10": 4 + }, + "items": + [ + { + "name": "ver_info", + "说明": "版本信息:VID(2byte),PID(2byte),VER(2byte)", + "type": "ARRAY", + "data": "0x00, 0x02, 0x00, 0x5F, 0x00, 0x00" + }, + { + "name": "ver_info_ext", + "说明": "额外信息(AuthKey,ProCode)", + "type": "STRING", + "data": "hE9yfseX6UdK7rFh,jl_v8" + }, + { + "name": "reset_io", + "说明": "uboot中PR口长按复位io选择,目前可配0、1、2、3", + "type": "STRING", + "data": "1" + }, + { + "name": "pilot_lamp_io", + "说明": "uboot中led指示灯IO配置,目前可配PA、PB、PC、PD", + "type": "STRING", + "data": "PB03" + }, + { + "name": "link_key", + "说明": "用于link_key_data的配置", + "type": "ARRAY", + "data": "0x06, 0x77, 0x5f, 0x87, 0x91, 0x8d, 0xd4, 0x23, 0x00, 0x5d, 0xf1, 0xd8, 0xcf, 0x0c, 0x14, 0x2b" + }, + { + "name": "power_io", + "说明": "用与电源io的配置,0代表低电平,1代表高电平", + "type": "STRING", + "data": "PC03_1" + } + ] +} diff --git a/cpu/br23/tools/download/soundcard/tone.cfg b/cpu/br23/tools/download/soundcard/tone.cfg new file mode 100644 index 0000000..eed8563 Binary files /dev/null and b/cpu/br23/tools/download/soundcard/tone.cfg differ diff --git a/cpu/br23/tools/download/standard/br23loader.bin b/cpu/br23/tools/download/standard/br23loader.bin new file mode 100644 index 0000000..79d44b5 Binary files /dev/null and b/cpu/br23/tools/download/standard/br23loader.bin differ diff --git a/cpu/br23/tools/download/standard/cfg_tool.bin b/cpu/br23/tools/download/standard/cfg_tool.bin new file mode 100644 index 0000000..8b0e75e Binary files /dev/null and b/cpu/br23/tools/download/standard/cfg_tool.bin differ diff --git a/cpu/br23/tools/download/standard/download.bat b/cpu/br23/tools/download/standard/download.bat new file mode 100644 index 0000000..8b95d7e --- /dev/null +++ b/cpu/br23/tools/download/standard/download.bat @@ -0,0 +1,64 @@ +@echo off + +cd %~dp0 + +copy ..\..\script.ver . +copy ..\..\uboot.boot . +copy ..\..\tone.cfg . +copy ..\..\cfg_tool.bin . +copy ..\..\app.bin . +copy ..\..\br23loader.bin . +copy ..\..\eq_cfg_hw.bin . +copy ..\..\ota_all.bin . +copy ..\..\ota_nor.bin . + + +..\..\isd_download.exe -tonorflash -dev br23 -boot 0x12000 -div8 -wait 300 -uboot uboot.boot -app app.bin -res tone.cfg cfg_tool.bin eq_cfg_hw.bin %1 -format all +:: -format all +::-reboot 2500 + + + +@rem 删除临时文件-format all +if exist *.mp3 del *.mp3 +if exist *.PIX del *.PIX +if exist *.TAB del *.TAB +if exist *.res del *.res +if exist *.sty del *.sty + + + +@rem 生成固件升级文件 +copy ota_all.bin ota.bin +..\..\fw_add.exe -noenc -fw jl_isd.fw -add ota.bin -type 100 -out jl_isd_all.fw +copy ota_nor.bin ota.bin +..\..\fw_add.exe -noenc -fw jl_isd.fw -add ota.bin -type 100 -out jl_isd_nor.fw + +@rem 添加配置脚本的版本信息到 FW 文件中 +..\..\fw_add.exe -noenc -fw jl_isd_all.fw -add script.ver -out jl_isd_all.fw +..\..\fw_add.exe -noenc -fw jl_isd_nor.fw -add script.ver -out jl_isd_nor.fw + + + +..\..\ufw_maker.exe -fw_to_ufw jl_isd_all.fw +..\..\ufw_maker.exe -fw_to_ufw jl_isd_nor.fw +copy jl_isd_all.ufw update.ufw +copy jl_isd_nor.ufw nor_update.ufw +copy jl_isd_all.fw jl_isd.fw +del jl_isd_all.ufw jl_isd_nor.ufw jl_isd_all.fw jl_isd_nor.fw + + +@REM 生成配置文件升级文件 +::ufw_maker.exe -chip AC800X %ADD_KEY% -output config.ufw -res bt_cfg.cfg + +::IF EXIST jl_696x.bin del jl_696x.bin + + +@rem 常用命令说明 +@rem -format vm //擦除VM 区域 +@rem -format cfg //擦除BT CFG 区域 +@rem -format 0x3f0-2 //表示从第 0x3f0 个 sector 开始连续擦除 2 个 sector(第一个参数为16进制或10进制都可,第二个参数必须是10进制) + +ping /n 2 127.1>null +IF EXIST null del null + diff --git a/cpu/br23/tools/download/standard/eq_cfg_hw.bin b/cpu/br23/tools/download/standard/eq_cfg_hw.bin new file mode 100644 index 0000000..a006969 Binary files /dev/null and b/cpu/br23/tools/download/standard/eq_cfg_hw.bin differ diff --git a/cpu/br23/tools/download/standard/isd_config.ini b/cpu/br23/tools/download/standard/isd_config.ini new file mode 100644 index 0000000..ddd78dc --- /dev/null +++ b/cpu/br23/tools/download/standard/isd_config.ini @@ -0,0 +1,129 @@ +# +# +# 配置数据按照 长度+配置名字+数据的方式存储 +# +# + +[EXTRA_CFG_PARAM] +NEW_FLASH_FS=YES; +FORCE_VM_ALIGN=YES; +CHIP_NAME=AC695X;//芯片型号 +ENTRY=0x1E00100;//程序入口地址 +PID=AC695N_soundbox;//长度16byte,示例:芯片封装_应用方向_方案名称 +VID=0.01; + +RESERVED_OPT=0; +SPECIAL_OPT=0; +FORCE_4K_ALIGN=YES; + +#DOWNLOAD_MODEL=SERIAL;//usb +DOWNLOAD_MODEL=usb;// +SERIAL_DEVICE_NAME=JlVirtualJtagSerial; +SERIAL_BARD_RATE=1000000; +SERIAL_CMD_OPT=6; +SERIAL_CMD_RATE=100; [n*10000] +SERIAL_CMD_RES=0; +SERIAL_INIT_BAUD_RATE=9600; +LOADER_BAUD_RATE=1000000; +LOADER_ASK_BAUD_RATE=1000000; +#SERIAL_SEND_KEY=YES; +BEFORE_LOADER_WAIT_TIME=100; +FLASH_BIN_CNT=6; +NEED_RESERVED_4K=YES;//关闭4K保留 + +##################### 烧写器配置选项, 请根据实际情况修改 ##################### +##################### 烧写器配置选项, 请根据实际情况修改 ##################### +##################### 烧写器配置选项, 请根据实际情况修改 ##################### +[BURNER_OPTIONS] +SDK_TYPE=SOUNDBOX; // SOUNDBOX:音箱方案 OTHER:其他方案(比如:耳机,BLE) SDK类型:当前仅支持音箱和非音箱两种类型 + +##################### 匹配的芯片版本, 请勿随意修改 ##################### +##################### 匹配的芯片版本, 请勿随意修改 ##################### +##################### 匹配的芯片版本, 请勿随意修改 ##################### +##################### 匹配的芯片版本, 请勿随意修改 ##################### +[CHIP_VERSION] +SUPPORTED_LIST=A,B,D;//匹配的芯片版本 + +#UBOOT配置项,请勿随意调整顺序 # +[SYS_CFG_PARAM] +#data_width[0 1 2 3 4] 3的时候uboot自动识别2或者4线 +#clk [0-255] +#mode: +# 0 RD_OUTPUT, 1 cmd 1 addr +# 1 RD_I/O, 1 cmd x addr +# 2 RD_I/O_CONTINUE] no_send_cmd x add +#port: +# 0 优先选A端口 CS:PD3 CLK:PD0 D0:PD1 D1:PD2 D2:PB7 D3:PD5 +# 1 优先选B端口 CS:PA13 CLK:PD0 D0:PD1 D1:PA14 D2:PA15 D3:PD5 +SPI=2_3_0_0; #width_clk_mode_port; +#OSC=btosc; +#OSC_FREQ=12MHz; #[24MHz 12MHz] +#SYS_CLK=24MHz; #[48MHz 24MHz] +UTTX=PB04;//uboot串口tx +UTBD=1000000;//uboot串口波特率 +#UTRX=PB01;串口升级[PB00 PB05 PA05] +RESET=PB01_00_0; //port口_长按时间_有效电平(长按时间有00、01、02、04、08五个值可选,单位为秒,当长按时间为00时,则关闭长按复位功能。) +UPDATE_JUMP=0; //是否支持升级过程中维持IO电平,用于一些使用IO口维持芯片供电的方案 +#EX_FLASH=PB03_1A_NULL; //CS_HW_PORT_POWER, 示例配置为CS为PA03, 使用SPI1, A口,电源使用vddio, 如果norflash电源为vddio,填NULL即可 + +#0:disable +#1:PA9 PA10 +#2:USB +#3:PB1 PB2 +#4:PB6 PB7 + +#sdtap=2; +psram=0; + +VLVD=4;//VDDIO_LVD挡位,0: 1.9V 1: 2.0V 2: 2.1V 3: 2.2V 4: 2.3V 5: 2.4V 6: 2.5V 7: 2.6V + +#EADDR=0; //ENTRY_ADDR; +EOFFSET=1; // 4k * n,如果升级已出货的没有偏移的方案需设置成0 + +############################################################################################################################################# + + + +########flash空间使用配置区域############################################### +#PDCTNAME: 产品名,对应此代码,用于标识产品,升级时可以选择匹配产品名 +#BOOT_FIRST: 1=代码更新后,提示APP是第一次启动;0=代码更新后,不提示 +#UPVR_CTL: 0:不允许高版本升级低版本 1:允许高版本升级低版本 +#XXXX_ADR: 区域起始地址 AUTO:由工具自动分配起始地址 +#XXXX_LEN: 区域长度 CODE_LEN:代码长度 +#XXXX_OPT: 区域操作属性 +# +# +# +#操作符说明 OPT: +# 0: 下载代码时擦除指定区域 +# 1: 下载代码时不操作指定区域 +# 2: 下载代码时给指定区域加上保护 +############################################################################ +[RESERVED_CONFIG] +BTIF_ADR=AUTO; +BTIF_LEN=0x1000; +BTIF_OPT=1; + +#歌词显示使用的区域 +#LRIF_ADR=AUTO; +#LRIF_LEN=0x1000; +#LRIF_OPT=1; + +PRCT_ADR=0; +PRCT_LEN=CODE_LEN; +PRCT_OPT=2; + +#USERIF_ADR=AUTO; +#USERIF_LEN=1K; +#USERIF_OPT=1; + +VM_ADR=0; +VM_LEN=32K; +VM_OPT=1; + +[BURNER_CONFIG] +SIZE=32; + +[TOOL_CONFIG] +1TO2_MIN_VER=2.24.5; +1TO8_MIN_VER=3.0.38; diff --git a/cpu/br23/tools/download/standard/ota.bin b/cpu/br23/tools/download/standard/ota.bin new file mode 100644 index 0000000..8d56072 Binary files /dev/null and b/cpu/br23/tools/download/standard/ota.bin differ diff --git a/cpu/br23/tools/download/standard/ota_all.bin b/cpu/br23/tools/download/standard/ota_all.bin new file mode 100644 index 0000000..19177d9 Binary files /dev/null and b/cpu/br23/tools/download/standard/ota_all.bin differ diff --git a/cpu/br23/tools/download/standard/ota_nor.bin b/cpu/br23/tools/download/standard/ota_nor.bin new file mode 100644 index 0000000..8d56072 Binary files /dev/null and b/cpu/br23/tools/download/standard/ota_nor.bin differ diff --git a/cpu/br23/tools/download/standard/script.ver b/cpu/br23/tools/download/standard/script.ver new file mode 100644 index 0000000..4484321 --- /dev/null +++ b/cpu/br23/tools/download/standard/script.ver @@ -0,0 +1 @@ +AC695X-v0.01-cfg_tool-v0.08 \ No newline at end of file diff --git a/cpu/br23/tools/download/standard/tone.cfg b/cpu/br23/tools/download/standard/tone.cfg new file mode 100644 index 0000000..5a2ae32 Binary files /dev/null and b/cpu/br23/tools/download/standard/tone.cfg differ diff --git a/cpu/br23/tools/download/standard/uboot.boot b/cpu/br23/tools/download/standard/uboot.boot new file mode 100644 index 0000000..95bef82 Binary files /dev/null and b/cpu/br23/tools/download/standard/uboot.boot differ diff --git a/cpu/br23/tools/download_app_ota.bat b/cpu/br23/tools/download_app_ota.bat new file mode 100644 index 0000000..d5d8943 --- /dev/null +++ b/cpu/br23/tools/download_app_ota.bat @@ -0,0 +1,55 @@ +@echo off + +@echo ******************************************************************************** +@echo SDK BR23 +@echo ******************************************************************************** +@echo %date% + +cd /d %~dp0 + +cd tool_resource\app_ota +copy * ..\..\ +cd ..\..\ + +json_to_res.exe json.txt + +del isd_config.ini +copy isd_config_app_ota.ini isd_config.ini + +isd_download.exe -tonorflash -dev br23 -boot 0x12000 -div8 -wait 300 -uboot uboot.boot -app app.bin cfg_tool.bin -res tone.cfg config.dat +::-ex_api_bin user_api.bin +@REM ˵ +@rem -format vm // VM +@rem -format all // +@rem -reboot 500 // reset chip, valid in JTAG debug + +del isd_config.ini + +@REM ɾʱļ +if exist *.mp3 del *.mp3 +if exist *.PIX del *.PIX +if exist *.TAB del *.TAB +if exist *.res del *.res +if exist *.sty del *.sty + +if exist json_to_res.exe del json_to_res.exe +if exist json.txt del json.txt +if exist config.dat del config.dat +if exist isd_config_app_ota.ini del isd_config_app_ota.ini + +@REM ɹ̼ļ +fw_add.exe -noenc -fw jl_isd.fw -add ota.bin -type 100 -out jl_isd.fw +@REM ýűİ汾Ϣ FW ļ +fw_add.exe -noenc -fw jl_isd.fw -add script.ver -out jl_isd.fw + +ufw_maker.exe -fw_to_ufw jl_isd.fw +copy jl_isd.ufw update.ufw +del jl_isd.ufw + +@REM ļļ +rem ufw_maker.exe -chip AC693X %ADD_KEY% -output config.ufw -res bt_cfg.cfg + +ping /n 2 127.1>null +IF EXIST null del null + +pause diff --git a/cpu/br23/tools/effect_file/mic_effect_echo.bin b/cpu/br23/tools/effect_file/mic_effect_echo.bin new file mode 100644 index 0000000..03241f5 Binary files /dev/null and b/cpu/br23/tools/effect_file/mic_effect_echo.bin differ diff --git a/cpu/br23/tools/effect_file/mic_effect_echo_full.bin b/cpu/br23/tools/effect_file/mic_effect_echo_full.bin new file mode 100644 index 0000000..f47d5c4 Binary files /dev/null and b/cpu/br23/tools/effect_file/mic_effect_echo_full.bin differ diff --git a/cpu/br23/tools/effect_file/mic_effect_echo_voicechanger.bin b/cpu/br23/tools/effect_file/mic_effect_echo_voicechanger.bin new file mode 100644 index 0000000..933e2a8 Binary files /dev/null and b/cpu/br23/tools/effect_file/mic_effect_echo_voicechanger.bin differ diff --git a/cpu/br23/tools/effect_file/mic_effect_full.bin b/cpu/br23/tools/effect_file/mic_effect_full.bin new file mode 100644 index 0000000..1112d3e Binary files /dev/null and b/cpu/br23/tools/effect_file/mic_effect_full.bin differ diff --git a/cpu/br23/tools/effect_file/mic_effect_megaphone.bin b/cpu/br23/tools/effect_file/mic_effect_megaphone.bin new file mode 100644 index 0000000..082866c Binary files /dev/null and b/cpu/br23/tools/effect_file/mic_effect_megaphone.bin differ diff --git a/cpu/br23/tools/effect_file/mic_effect_reverb.bin b/cpu/br23/tools/effect_file/mic_effect_reverb.bin new file mode 100644 index 0000000..1fcc212 Binary files /dev/null and b/cpu/br23/tools/effect_file/mic_effect_reverb.bin differ diff --git a/cpu/br23/tools/effect_file/mic_effect_reverb_full.bin b/cpu/br23/tools/effect_file/mic_effect_reverb_full.bin new file mode 100644 index 0000000..f61aefb Binary files /dev/null and b/cpu/br23/tools/effect_file/mic_effect_reverb_full.bin differ diff --git a/cpu/br23/tools/effect_file/music_2to1_2to2.bin b/cpu/br23/tools/effect_file/music_2to1_2to2.bin new file mode 100644 index 0000000..4213b6b Binary files /dev/null and b/cpu/br23/tools/effect_file/music_2to1_2to2.bin differ diff --git a/cpu/br23/tools/effect_file/music_advance.bin b/cpu/br23/tools/effect_file/music_advance.bin new file mode 100644 index 0000000..58988d9 Binary files /dev/null and b/cpu/br23/tools/effect_file/music_advance.bin differ diff --git a/cpu/br23/tools/effect_file/music_base.bin b/cpu/br23/tools/effect_file/music_base.bin new file mode 100644 index 0000000..a006969 Binary files /dev/null and b/cpu/br23/tools/effect_file/music_base.bin differ diff --git a/cpu/br23/tools/effect_file/music_base_linein.bin b/cpu/br23/tools/effect_file/music_base_linein.bin new file mode 100644 index 0000000..917c46b Binary files /dev/null and b/cpu/br23/tools/effect_file/music_base_linein.bin differ diff --git a/cpu/br23/tools/eq_cfg_hw.bin b/cpu/br23/tools/eq_cfg_hw.bin new file mode 100644 index 0000000..a006969 Binary files /dev/null and b/cpu/br23/tools/eq_cfg_hw.bin differ diff --git a/cpu/br23/tools/extra_tones/0.wtg b/cpu/br23/tools/extra_tones/0.wtg new file mode 100644 index 0000000..cfc1365 Binary files /dev/null and b/cpu/br23/tools/extra_tones/0.wtg differ diff --git a/cpu/br23/tools/extra_tones/1.wtg b/cpu/br23/tools/extra_tones/1.wtg new file mode 100644 index 0000000..5713df3 Binary files /dev/null and b/cpu/br23/tools/extra_tones/1.wtg differ diff --git a/cpu/br23/tools/extra_tones/2.wtg b/cpu/br23/tools/extra_tones/2.wtg new file mode 100644 index 0000000..e0ca6a6 Binary files /dev/null and b/cpu/br23/tools/extra_tones/2.wtg differ diff --git a/cpu/br23/tools/extra_tones/3.wtg b/cpu/br23/tools/extra_tones/3.wtg new file mode 100644 index 0000000..2b7a201 Binary files /dev/null and b/cpu/br23/tools/extra_tones/3.wtg differ diff --git a/cpu/br23/tools/extra_tones/4.wtg b/cpu/br23/tools/extra_tones/4.wtg new file mode 100644 index 0000000..10f15ea Binary files /dev/null and b/cpu/br23/tools/extra_tones/4.wtg differ diff --git a/cpu/br23/tools/extra_tones/5.wtg b/cpu/br23/tools/extra_tones/5.wtg new file mode 100644 index 0000000..0b1cd2e Binary files /dev/null and b/cpu/br23/tools/extra_tones/5.wtg differ diff --git a/cpu/br23/tools/extra_tones/6.wtg b/cpu/br23/tools/extra_tones/6.wtg new file mode 100644 index 0000000..225f62d Binary files /dev/null and b/cpu/br23/tools/extra_tones/6.wtg differ diff --git a/cpu/br23/tools/extra_tones/7.wtg b/cpu/br23/tools/extra_tones/7.wtg new file mode 100644 index 0000000..fa6a266 Binary files /dev/null and b/cpu/br23/tools/extra_tones/7.wtg differ diff --git a/cpu/br23/tools/extra_tones/8.wtg b/cpu/br23/tools/extra_tones/8.wtg new file mode 100644 index 0000000..60d28c4 Binary files /dev/null and b/cpu/br23/tools/extra_tones/8.wtg differ diff --git a/cpu/br23/tools/extra_tones/9.wtg b/cpu/br23/tools/extra_tones/9.wtg new file mode 100644 index 0000000..9b6ab47 Binary files /dev/null and b/cpu/br23/tools/extra_tones/9.wtg differ diff --git a/cpu/br23/tools/extra_tones/bt.wtg b/cpu/br23/tools/extra_tones/bt.wtg new file mode 100644 index 0000000..2cb8737 Binary files /dev/null and b/cpu/br23/tools/extra_tones/bt.wtg differ diff --git a/cpu/br23/tools/extra_tones/bt_conn.wtg b/cpu/br23/tools/extra_tones/bt_conn.wtg new file mode 100644 index 0000000..58c8f76 Binary files /dev/null and b/cpu/br23/tools/extra_tones/bt_conn.wtg differ diff --git a/cpu/br23/tools/extra_tones/bt_dconn.wtg b/cpu/br23/tools/extra_tones/bt_dconn.wtg new file mode 100644 index 0000000..3c5f16d Binary files /dev/null and b/cpu/br23/tools/extra_tones/bt_dconn.wtg differ diff --git a/cpu/br23/tools/extra_tones/fm.wtg b/cpu/br23/tools/extra_tones/fm.wtg new file mode 100644 index 0000000..77a7a54 Binary files /dev/null and b/cpu/br23/tools/extra_tones/fm.wtg differ diff --git a/cpu/br23/tools/extra_tones/linein.wtg b/cpu/br23/tools/extra_tones/linein.wtg new file mode 100644 index 0000000..b5f8563 Binary files /dev/null and b/cpu/br23/tools/extra_tones/linein.wtg differ diff --git a/cpu/br23/tools/extra_tones/low_power.wtg b/cpu/br23/tools/extra_tones/low_power.wtg new file mode 100644 index 0000000..eb7e14c Binary files /dev/null and b/cpu/br23/tools/extra_tones/low_power.wtg differ diff --git a/cpu/br23/tools/extra_tones/music.wtg b/cpu/br23/tools/extra_tones/music.wtg new file mode 100644 index 0000000..89d63d2 Binary files /dev/null and b/cpu/br23/tools/extra_tones/music.wtg differ diff --git a/cpu/br23/tools/extra_tones/paired.wtg b/cpu/br23/tools/extra_tones/paired.wtg new file mode 100644 index 0000000..9e5ebd4 Binary files /dev/null and b/cpu/br23/tools/extra_tones/paired.wtg differ diff --git a/cpu/br23/tools/extra_tones/pc.wtg b/cpu/br23/tools/extra_tones/pc.wtg new file mode 100644 index 0000000..6286670 Binary files /dev/null and b/cpu/br23/tools/extra_tones/pc.wtg differ diff --git a/cpu/br23/tools/extra_tones/power_off.wtg b/cpu/br23/tools/extra_tones/power_off.wtg new file mode 100644 index 0000000..111ea09 Binary files /dev/null and b/cpu/br23/tools/extra_tones/power_off.wtg differ diff --git a/cpu/br23/tools/extra_tones/power_on.wtg b/cpu/br23/tools/extra_tones/power_on.wtg new file mode 100644 index 0000000..6ccd529 Binary files /dev/null and b/cpu/br23/tools/extra_tones/power_on.wtg differ diff --git a/cpu/br23/tools/extra_tones/record.wtg b/cpu/br23/tools/extra_tones/record.wtg new file mode 100644 index 0000000..a9df46b Binary files /dev/null and b/cpu/br23/tools/extra_tones/record.wtg differ diff --git a/cpu/br23/tools/extra_tones/ring.wtg b/cpu/br23/tools/extra_tones/ring.wtg new file mode 100644 index 0000000..a0bdd84 Binary files /dev/null and b/cpu/br23/tools/extra_tones/ring.wtg differ diff --git a/cpu/br23/tools/extra_tones/rtc.wtg b/cpu/br23/tools/extra_tones/rtc.wtg new file mode 100644 index 0000000..3241c17 Binary files /dev/null and b/cpu/br23/tools/extra_tones/rtc.wtg differ diff --git a/cpu/br23/tools/extra_tones/tws_conn.wtg b/cpu/br23/tools/extra_tones/tws_conn.wtg new file mode 100644 index 0000000..6dadfff Binary files /dev/null and b/cpu/br23/tools/extra_tones/tws_conn.wtg differ diff --git a/cpu/br23/tools/extra_tones/tws_dconn.wtg b/cpu/br23/tools/extra_tones/tws_dconn.wtg new file mode 100644 index 0000000..e4b6d6e Binary files /dev/null and b/cpu/br23/tools/extra_tones/tws_dconn.wtg differ diff --git a/cpu/br23/tools/fw_add.exe b/cpu/br23/tools/fw_add.exe new file mode 100644 index 0000000..4f8cf81 Binary files /dev/null and b/cpu/br23/tools/fw_add.exe differ diff --git a/cpu/br23/tools/isd_config.ini b/cpu/br23/tools/isd_config.ini new file mode 100644 index 0000000..ddd78dc --- /dev/null +++ b/cpu/br23/tools/isd_config.ini @@ -0,0 +1,129 @@ +# +# +# 配置数据按照 长度+配置名字+数据的方式存储 +# +# + +[EXTRA_CFG_PARAM] +NEW_FLASH_FS=YES; +FORCE_VM_ALIGN=YES; +CHIP_NAME=AC695X;//芯片型号 +ENTRY=0x1E00100;//程序入口地址 +PID=AC695N_soundbox;//长度16byte,示例:芯片封装_应用方向_方案名称 +VID=0.01; + +RESERVED_OPT=0; +SPECIAL_OPT=0; +FORCE_4K_ALIGN=YES; + +#DOWNLOAD_MODEL=SERIAL;//usb +DOWNLOAD_MODEL=usb;// +SERIAL_DEVICE_NAME=JlVirtualJtagSerial; +SERIAL_BARD_RATE=1000000; +SERIAL_CMD_OPT=6; +SERIAL_CMD_RATE=100; [n*10000] +SERIAL_CMD_RES=0; +SERIAL_INIT_BAUD_RATE=9600; +LOADER_BAUD_RATE=1000000; +LOADER_ASK_BAUD_RATE=1000000; +#SERIAL_SEND_KEY=YES; +BEFORE_LOADER_WAIT_TIME=100; +FLASH_BIN_CNT=6; +NEED_RESERVED_4K=YES;//关闭4K保留 + +##################### 烧写器配置选项, 请根据实际情况修改 ##################### +##################### 烧写器配置选项, 请根据实际情况修改 ##################### +##################### 烧写器配置选项, 请根据实际情况修改 ##################### +[BURNER_OPTIONS] +SDK_TYPE=SOUNDBOX; // SOUNDBOX:音箱方案 OTHER:其他方案(比如:耳机,BLE) SDK类型:当前仅支持音箱和非音箱两种类型 + +##################### 匹配的芯片版本, 请勿随意修改 ##################### +##################### 匹配的芯片版本, 请勿随意修改 ##################### +##################### 匹配的芯片版本, 请勿随意修改 ##################### +##################### 匹配的芯片版本, 请勿随意修改 ##################### +[CHIP_VERSION] +SUPPORTED_LIST=A,B,D;//匹配的芯片版本 + +#UBOOT配置项,请勿随意调整顺序 # +[SYS_CFG_PARAM] +#data_width[0 1 2 3 4] 3的时候uboot自动识别2或者4线 +#clk [0-255] +#mode: +# 0 RD_OUTPUT, 1 cmd 1 addr +# 1 RD_I/O, 1 cmd x addr +# 2 RD_I/O_CONTINUE] no_send_cmd x add +#port: +# 0 优先选A端口 CS:PD3 CLK:PD0 D0:PD1 D1:PD2 D2:PB7 D3:PD5 +# 1 优先选B端口 CS:PA13 CLK:PD0 D0:PD1 D1:PA14 D2:PA15 D3:PD5 +SPI=2_3_0_0; #width_clk_mode_port; +#OSC=btosc; +#OSC_FREQ=12MHz; #[24MHz 12MHz] +#SYS_CLK=24MHz; #[48MHz 24MHz] +UTTX=PB04;//uboot串口tx +UTBD=1000000;//uboot串口波特率 +#UTRX=PB01;串口升级[PB00 PB05 PA05] +RESET=PB01_00_0; //port口_长按时间_有效电平(长按时间有00、01、02、04、08五个值可选,单位为秒,当长按时间为00时,则关闭长按复位功能。) +UPDATE_JUMP=0; //是否支持升级过程中维持IO电平,用于一些使用IO口维持芯片供电的方案 +#EX_FLASH=PB03_1A_NULL; //CS_HW_PORT_POWER, 示例配置为CS为PA03, 使用SPI1, A口,电源使用vddio, 如果norflash电源为vddio,填NULL即可 + +#0:disable +#1:PA9 PA10 +#2:USB +#3:PB1 PB2 +#4:PB6 PB7 + +#sdtap=2; +psram=0; + +VLVD=4;//VDDIO_LVD挡位,0: 1.9V 1: 2.0V 2: 2.1V 3: 2.2V 4: 2.3V 5: 2.4V 6: 2.5V 7: 2.6V + +#EADDR=0; //ENTRY_ADDR; +EOFFSET=1; // 4k * n,如果升级已出货的没有偏移的方案需设置成0 + +############################################################################################################################################# + + + +########flash空间使用配置区域############################################### +#PDCTNAME: 产品名,对应此代码,用于标识产品,升级时可以选择匹配产品名 +#BOOT_FIRST: 1=代码更新后,提示APP是第一次启动;0=代码更新后,不提示 +#UPVR_CTL: 0:不允许高版本升级低版本 1:允许高版本升级低版本 +#XXXX_ADR: 区域起始地址 AUTO:由工具自动分配起始地址 +#XXXX_LEN: 区域长度 CODE_LEN:代码长度 +#XXXX_OPT: 区域操作属性 +# +# +# +#操作符说明 OPT: +# 0: 下载代码时擦除指定区域 +# 1: 下载代码时不操作指定区域 +# 2: 下载代码时给指定区域加上保护 +############################################################################ +[RESERVED_CONFIG] +BTIF_ADR=AUTO; +BTIF_LEN=0x1000; +BTIF_OPT=1; + +#歌词显示使用的区域 +#LRIF_ADR=AUTO; +#LRIF_LEN=0x1000; +#LRIF_OPT=1; + +PRCT_ADR=0; +PRCT_LEN=CODE_LEN; +PRCT_OPT=2; + +#USERIF_ADR=AUTO; +#USERIF_LEN=1K; +#USERIF_OPT=1; + +VM_ADR=0; +VM_LEN=32K; +VM_OPT=1; + +[BURNER_CONFIG] +SIZE=32; + +[TOOL_CONFIG] +1TO2_MIN_VER=2.24.5; +1TO8_MIN_VER=3.0.38; diff --git a/cpu/br23/tools/isd_download b/cpu/br23/tools/isd_download new file mode 100644 index 0000000..574a2a0 Binary files /dev/null and b/cpu/br23/tools/isd_download differ diff --git a/cpu/br23/tools/isd_download.exe b/cpu/br23/tools/isd_download.exe new file mode 100644 index 0000000..7986007 Binary files /dev/null and b/cpu/br23/tools/isd_download.exe differ diff --git a/cpu/br23/tools/jl_kws.cfg b/cpu/br23/tools/jl_kws.cfg new file mode 100644 index 0000000..c537e76 Binary files /dev/null and b/cpu/br23/tools/jl_kws.cfg differ diff --git a/cpu/br23/tools/json_to_res.exe b/cpu/br23/tools/json_to_res.exe new file mode 100644 index 0000000..cb2bf1f Binary files /dev/null and b/cpu/br23/tools/json_to_res.exe differ diff --git a/cpu/br23/tools/lz4_packet b/cpu/br23/tools/lz4_packet new file mode 100644 index 0000000..2be1809 Binary files /dev/null and b/cpu/br23/tools/lz4_packet differ diff --git a/cpu/br23/tools/lz4_packet.exe b/cpu/br23/tools/lz4_packet.exe new file mode 100644 index 0000000..88b0d9e Binary files /dev/null and b/cpu/br23/tools/lz4_packet.exe differ diff --git a/cpu/br23/tools/md5sum.exe b/cpu/br23/tools/md5sum.exe new file mode 100644 index 0000000..0719735 Binary files /dev/null and b/cpu/br23/tools/md5sum.exe differ diff --git a/cpu/br23/tools/ota_all.bin b/cpu/br23/tools/ota_all.bin new file mode 100644 index 0000000..19177d9 Binary files /dev/null and b/cpu/br23/tools/ota_all.bin differ diff --git a/cpu/br23/tools/ota_all_debug.bin b/cpu/br23/tools/ota_all_debug.bin new file mode 100644 index 0000000..bff2217 Binary files /dev/null and b/cpu/br23/tools/ota_all_debug.bin differ diff --git a/cpu/br23/tools/ota_nor.bin b/cpu/br23/tools/ota_nor.bin new file mode 100644 index 0000000..8d56072 Binary files /dev/null and b/cpu/br23/tools/ota_nor.bin differ diff --git a/cpu/br23/tools/ota_nor_debug.bin b/cpu/br23/tools/ota_nor_debug.bin new file mode 100644 index 0000000..53dca1f Binary files /dev/null and b/cpu/br23/tools/ota_nor_debug.bin differ diff --git a/cpu/br23/tools/packres.exe b/cpu/br23/tools/packres.exe new file mode 100644 index 0000000..ebd4156 Binary files /dev/null and b/cpu/br23/tools/packres.exe differ diff --git a/cpu/br23/tools/remove_tailing_zeros.exe b/cpu/br23/tools/remove_tailing_zeros.exe new file mode 100644 index 0000000..a8ac975 Binary files /dev/null and b/cpu/br23/tools/remove_tailing_zeros.exe differ diff --git a/cpu/br23/tools/report_size_usage.bat b/cpu/br23/tools/report_size_usage.bat new file mode 100644 index 0000000..de4c52d --- /dev/null +++ b/cpu/br23/tools/report_size_usage.bat @@ -0,0 +1,10 @@ + +@rem ŵĿ¼ +@rem sdk.elf ʹõĿռС +@rem ַ symbol_tbl.txt + +set OBJSIZEDUMP=C:\JL\pi32\bin\llvm-objsizedump.exe +set ELF=sdk.elf +set OUTPUT=symbol_tbl.txt + +%OBJSIZEDUMP% -lite -skip-zero -enable-dbg-info %ELF% | sort > %OUTPUT% diff --git a/cpu/br23/tools/rom.lst b/cpu/br23/tools/rom.lst new file mode 100644 index 0000000..ad4a5bc --- /dev/null +++ b/cpu/br23/tools/rom.lst @@ -0,0 +1,3995 @@ + +rom.exe: file format ELF32-pi32v2 + +Disassembly of section .rom_code: +_start: + 110000: c0 ea d9 07 goto 0xfb2 ## startup.S:25:0 + + +exception_irq_handler: + 110004: 58 e9 2f 38 [--sp] = {ssp, usp, icfg, psr, rets, retx, rete, reti} ## startup.S:91:0 + 110008: d8 e8 ff ff [--sp] = {r15-r0} ## startup.S:92:0 + 11000c: 64 e0 00 0e r0 = sp ## startup.S:93:0 + 110010: 80 ea 7b 08 call 0x10f6 ## startup.S:94:0 + 110014: f7 9f goto -0x2 ## startup.S:96:0 + + +the_debug_isr: + 110016: d8 e8 01 00 [--sp] = {r0} ## debug_stub.S:16:0 + 11001a: 64 e0 00 0e r0 = sp ## debug_stub.S:17:0 + 11001e: ee ff bc be 02 00 sp = 0x2bebc ## debug_stub.S:18:0 + 110024: 58 e9 ff 7f [--sp] = {sp, ssp, usp, icfg, sr10, sr9, sr8, sr7, cnum, psr, sr4, rets, retx, rete, reti} ## debug_stub.S:20:0 + 110028: d8 e8 ff ff [--sp] = {r15-r0} ## debug_stub.S:21:0 + 11002c: 01 60 r1 = [r0+0x0] ## debug_stub.S:41:0 + 11002e: 81 20 [sp] = r1 ## debug_stub.S:42:0 + 110030: 08 84 r0 = r0 + 0x4 ## debug_stub.S:44:0 + 110032: 80 3e [sp+120] = r0 ## debug_stub.S:45:0 + 110034: 64 e0 00 0e r0 = sp ## debug_stub.S:46:0 + 110038: c1 ff 80 f0 10 00 r1 = 0x10f080 <_IRQ_MEM_ADDR+0xE3180 : 10f080 > ## debug_stub.S:47:0 + 11003e: 90 61 [r1+0x4] = r0 ## debug_stub.S:48:0 + 110040: 12 60 r2 = [r1+0x0] ## debug_stub.S:50:0 + 110042: ba 3f r2 &= 0x7fffffff ## debug_stub.S:51:0 + 110044: 92 60 [r1+0x0] = r2 ## debug_stub.S:52:0 + 110046: 4a 20 r2 = 0x20 ## debug_stub.S:55:0 + 110048: 00 00 nop ## debug_stub.S:57:0 + 11004a: 02 ea fd ff if (--r2 != 0) goto -0x6 ## debug_stub.S:58:0 + 11004e: 10 60 r0 = [r1+0x0] ## debug_stub.S:59:0 + 110050: 50 e8 f9 f9 if ((r0 & 0x80000000) == 0) goto -0xe ## debug_stub.S:61:0 + 110054: d4 e8 ff ff {r15-r0} = [sp++] ## debug_stub.S:64:0 + 110058: 50 e9 ff 7f {sp, ssp, usp, icfg, sr10, sr9, sr8, sr7, cnum, psr, sr4, rets, retx, rete, reti} = [sp++] ## debug_stub.S:65:0 + 11005c: 83 00 rte ## debug_stub.S:67:0 + + +memmove: + 11005e: 76 04 [--sp] = {rets, r6-r4} + 110060: 00 ec 03 10 if (r1 > r0) goto 0x6 + 110064: 93 1c r3 = r1 + r2 + 110066: 00 ec 29 30 if (r3 > r0) goto 0x52 + 11006a: 03 16 r3 = r0 + 11006c: 82 f9 14 10 if (r2 < 0x8) goto 0x28 + 110070: 65 e1 03 10 r5 = r1 & 0x3 + 110074: 64 e1 03 30 r4 = r3 & 0x3 + 110078: 04 46 if (r4 == 0) goto 0xc + 11007a: a6 e0 04 40 r6 = 0x4 - r4 + 11007e: a2 1f r2 = r2 - r6 + 110080: 16 03 rep 0x4 r6 { + 110082: 16 07 r6 = b[r1++=0x1] (u) + 110084: b6 07 b[r3++=0x1] = r6 + } + 110086: 5c 19 r4 ^= r5 + 110088: a5 a2 r5 = r2 >> 0x2 + 11008a: 84 4a if (r4 != 0) goto 0x14 + 11008c: 15 03 rep 0x4 r5 { + 11008e: 16 05 r6 = [r1++=0x4] + 110090: b6 05 [r3++=0x4] = r6 + } + 110092: f5 5c if (r5 != 0) goto -0x8 + 110094: 62 e1 03 20 r2 = r2 & 0x3 + 110098: 12 03 rep 0x4 r2 { + 11009a: 12 07 r2 = b[r1++=0x1] (u) + 11009c: b2 07 b[r3++=0x1] = r2 + } + 11009e: 56 04 {pc, r6-r4} = [sp++] + 1100a0: a5 03 rep 0x16 r5 { + 1100a2: 16 07 r6 = b[r1++=0x1] (u) + 1100a4: 14 07 r4 = b[r1++=0x1] (u) + 1100a6: a6 f1 20 44 r6 <= insert(r4, p:0x8, l:0x8) # + 1100aa: 14 07 r4 = b[r1++=0x1] (u) + 1100ac: a6 f1 20 48 r6 <= insert(r4, p:0x10, l:0x8) # + 1100b0: 14 07 r4 = b[r1++=0x1] (u) + 1100b2: a6 e1 20 4c r6 <= insert(r4, p:0x18, l:0x8) + 1100b6: b6 05 [r3++=0x4] = r6 + } + 1100b8: f5 53 if (r5 != 0) goto -0x1a + 1100ba: f7 8c goto -0x28 + 1100bc: 83 1c r3 = r0 + r2 + 1100be: 91 1c r1 = r1 + r2 + 1100c0: 82 f9 17 10 if (r2 < 0x8) goto 0x2e + 1100c4: 65 e1 03 10 r5 = r1 & 0x3 + 1100c8: 64 e1 03 30 r4 = r3 & 0x3 + 1100cc: 04 47 if (r4 == 0) goto 0xe + 1100ce: 22 1f r2 = r2 - r4 + 1100d0: 46 16 r6 = r4 + 1100d2: 36 03 rep 0x8 r6 { + 1100d4: 59 ee 1f 6f r6 = b[++r1=-0x1] (u) + 1100d8: 5b ee 3f 6f b[++r3=-0x1] = r6 + } + 1100dc: 5c 19 r4 ^= r5 + 1100de: a5 a2 r5 = r2 >> 0x2 + 1100e0: 84 4e if (r4 != 0) goto 0x1c + 1100e2: 35 03 rep 0x8 r5 { + 1100e4: d7 ec 1e 6f r6 = [++r1=-0x4] + 1100e8: d7 ec 3f 6f [++r3=-0x4] = r6 + } + 1100ec: f5 5a if (r5 != 0) goto -0xc + 1100ee: 62 e1 03 20 r2 = r2 & 0x3 + 1100f2: 32 03 rep 0x8 r2 { + 1100f4: 59 ee 1f 6f r6 = b[++r1=-0x1] (u) + 1100f8: 5b ee 3f 6f b[++r3=-0x1] = r6 + } + 1100fc: 56 04 {pc, r6-r4} = [sp++] + 1100fe: f9 3f r1 += -0x1 + 110100: b5 03 rep 0x18 r5 { + 110102: 1e 07 r6 = b[r1++=-0x1] (u) + 110104: 66 b8 r6 = r6 << 0x18 + 110106: 1c 07 r4 = b[r1++=-0x1] (u) + 110108: a6 f1 20 48 r6 <= insert(r4, p:0x10, l:0x8) # + 11010c: 1c 07 r4 = b[r1++=-0x1] (u) + 11010e: a6 f1 20 44 r6 <= insert(r4, p:0x8, l:0x8) # + 110112: 1c 07 r4 = b[r1++=-0x1] (u) + 110114: 46 19 r6 |= r4 + 110116: d7 ec 3f 6f [++r3=-0x4] = r6 + } + 11011a: f5 52 if (r5 != 0) goto -0x1c + 11011c: 19 81 r1 = r1 + 0x1 + 11011e: f7 87 goto -0x32 + + +memset: + 110120: 74 04 [--sp] = {rets, r4} + 110122: 03 16 r3 = r0 + 110124: 02 52 if (r2 == 0) goto 0x24 + 110126: 33 ea 03 40 if ((r3 & 0x3) != 0) { + 11012a: f2 f0 01 20 r2 = r2 - 0x1 # + 11012e: b1 07 b[r3++=0x1] = r1 + 110130: f7 99 goto -0xe + } + 110132: a4 a2 r4 = r2 >> 0x2 + 110134: a1 e1 20 14 r1 <= insert(r1, p:0x8, l:0x8) + 110138: a1 e1 40 18 r1 <= insert(r1, p:0x10, l:0x10) + 11013c: 04 03 rep 0x2 r4 { + 11013e: b1 05 [r3++=0x4] = r1 + } + 110140: f4 5d if (r4 != 0) goto -0x6 + 110142: 62 e1 03 20 r2 = r2 & 0x3 + 110146: 02 03 rep 0x2 r2 { + 110148: b1 07 b[r3++=0x1] = r1 + } + 11014a: 54 04 {pc, r4} = [sp++] + + +memcmp: + 11014c: 74 04 [--sp] = {rets, r4} + 11014e: 82 f9 19 08 if (r2 < 0x4) goto 0x32 + 110152: 90 e1 10 30 r3 = r1 | r0 + 110156: 61 ff 03 30 14 00 if ((r3 & 0x3) != 0) goto 0x28 + 11015c: 04 83 goto 0x6 + 11015e: fa 3c r2 += -0x4 + 110160: c1 24 r1 += 0x4 + 110162: c0 24 r0 += 0x4 + 110164: 82 f9 0e 08 if (r2 < 0x4) goto 0x1c + 110168: 13 60 r3 = [r1+0x0] + 11016a: 04 60 r4 = [r0+0x0] + 11016c: 03 e8 f7 41 if (r4 == r3) goto -0x12 + 110170: 04 89 goto 0x12 + 110172: d0 ee 11 30 r3 = b[r1++=0x1] (u) + 110176: d0 ee 01 40 r4 = b[r0++=0x1] (u) + 11017a: fa 3f r2 += -0x1 + 11017c: 94 e8 00 43 if (r4 != r3) { + 110180: c8 1e r0 = r4 - r3 + 110182: 54 04 {pc, r4} = [sp++] + } + 110184: f2 56 if (r2 != 0) goto -0x14 + 110186: 40 20 r0 = 0x0 + 110188: 54 04 {pc, r4} = [sp++] + + +memmem: + 11018a: 77 04 [--sp] = {rets, r7-r4} + 11018c: 35 16 r5 = r3 + 11018e: 26 16 r6 = r2 + 110190: 17 16 r7 = r1 + 110192: 04 16 r4 = r0 + 110194: 85 49 if (r5 != 0) goto 0x12 + 110196: 04 8b goto 0x16 + 110198: 40 16 r0 = r4 + 11019a: 61 16 r1 = r6 + 11019c: 52 16 r2 = r5 + 11019e: bf ea d5 ff call -0x56 + 1101a2: 00 45 if (r0 == 0) goto 0xa + 1101a4: ff 3f r7 += -0x1 + 1101a6: c4 21 r4 += 0x1 + 1101a8: 05 e9 f6 71 if (r7 >= r5) goto -0x14 + 1101ac: 44 20 r4 = 0x0 + 1101ae: 40 16 r0 = r4 + 1101b0: 57 04 {pc, r7-r4} = [sp++] + + +strcmp: + 1101b2: 77 04 [--sp] = {rets, r7-r4} + 1101b4: 64 e1 03 00 r4 = r0 & 0x3 + 1101b8: 04 4b if (r4 == 0) goto 0x16 + 1101ba: a4 e0 04 40 r4 = 0x4 - r4 + 1101be: 0a 40 r2 = b[r0+0x0] (u) + 1101c0: 22 41 if (r2 == 0) goto 0x82 + 1101c2: 1b 40 r3 = b[r1+0x0] (u) + 1101c4: 83 e8 3f 20 if (r2 != r3) goto 0x7e + 1101c8: 08 81 r0 = r0 + 0x1 + 1101ca: 19 81 r1 = r1 + 0x1 + 1101cc: 04 ea f7 ff if (--r4 != 0) goto -0x12 + 1101d0: 90 e1 10 20 r2 = r1 | r0 + 1101d4: c6 ff ff fe fe fe r6 = 0xfefefeff <__stub_doe+0xFEEDD702 : fefefefe > + 1101da: 61 ff 03 20 13 00 if ((r2 & 0x3) != 0) goto 0x26 + 1101e0: 02 60 r2 = [r0+0x0] + 1101e2: 13 60 r3 = [r1+0x0] + 1101e4: 83 e8 26 20 if (r2 != r3) goto 0x4c + 1101e8: 14 16 r4 = r1 + 1101ea: a1 1d r1 = r2 + r6 + 1101ec: 90 e1 13 12 r1 = r1 & ~r2 + 1101f0: 61 ff 80 13 2c 00 if ((r1 & 0x80808080) != 0) goto 0x58 + 1101f6: 02 61 r2 = [r0+0x4] + 1101f8: 45 61 r5 = [r4+0x4] + 1101fa: 49 84 r1 = r4 + 0x4 + 1101fc: 08 84 r0 = r0 + 0x4 + 1101fe: 14 16 r4 = r1 + 110200: 05 e8 f3 21 if (r2 == r5) goto -0x1a + 110204: 04 97 goto 0x2e + 110206: 14 16 r4 = r1 + 110208: 02 60 r2 = [r0+0x0] + 11020a: 43 07 r3 = b[r4++=0x1] (u) + 11020c: 45 07 r5 = b[r4++=0x1] (u) + 11020e: a3 e1 20 54 r3 <= insert(r5, p:0x8, l:0x8) + 110212: 45 07 r5 = b[r4++=0x1] (u) + 110214: a3 e1 20 58 r3 <= insert(r5, p:0x10, l:0x8) + 110218: 45 07 r5 = b[r4++=0x1] (u) + 11021a: a3 e1 20 5c r3 <= insert(r5, p:0x18, l:0x8) + 11021e: 83 e8 09 20 if (r2 != r3) goto 0x12 + 110222: a5 1d r5 = r2 + r6 + 110224: 90 e1 53 52 r5 = r5 & ~r2 + 110228: 61 ff 80 53 10 00 if ((r5 & 0x80808080) != 0) goto 0x20 + 11022e: 08 84 r0 = r0 + 0x4 + 110230: 19 84 r1 = r1 + 0x4 + 110232: f7 89 goto -0x2e + 110234: 0a 40 r2 = b[r0+0x0] (u) + 110236: 02 46 if (r2 == 0) goto 0xc + 110238: 1c 40 r4 = b[r1+0x0] (u) + 11023a: 84 e8 04 20 if (r2 != r4) goto 0x8 + 11023e: 08 81 r0 = r0 + 0x1 + 110240: 19 81 r1 = r1 + 0x1 + 110242: f7 98 goto -0x10 + 110244: 42 20 r2 = 0x0 + 110246: 13 16 r3 = r1 + 110248: 38 40 r0 = b[r3+0x0] (u) + 11024a: 20 1e r0 = r2 - r0 + 11024c: 57 04 {pc, r7-r4} = [sp++] + 11024e: 40 20 r0 = 0x0 + 110250: 57 04 {pc, r7-r4} = [sp++] + + +strcpy: + 110252: 77 04 [--sp] = {rets, r7-r4} + 110254: 07 16 r7 = r0 + 110256: 64 e1 03 00 r4 = r0 & 0x3 + 11025a: 04 47 if (r4 == 0) goto 0xe + 11025c: a4 e0 04 40 r4 = 0x4 - r4 + 110260: 12 07 r2 = b[r1++=0x1] (u) + 110262: 82 07 b[r0++=0x1] = r2 + 110264: 12 4b if (r2 == 0) goto 0x56 + 110266: 04 ea fb ff if (--r4 != 0) goto -0xa + 11026a: 90 e1 10 20 r2 = r1 | r0 + 11026e: c6 ff ff fe fe fe r6 = 0xfefefeff <__stub_doe+0xFEEDD702 : fefefefe > + 110274: 61 ff 03 20 0a 00 if ((r2 & 0x3) != 0) goto 0x14 + 11027a: 12 60 r2 = [r1+0x0] + 11027c: a3 1d r3 = r2 + r6 + 11027e: 90 e1 33 32 r3 = r3 & ~r2 + 110282: 61 ff 80 33 17 00 if ((r3 & 0x80808080) != 0) goto 0x2e + 110288: 19 84 r1 = r1 + 0x4 + 11028a: 82 05 [r0++=0x4] = r2 + 11028c: f7 96 goto -0x14 + 11028e: 14 16 r4 = r1 + 110290: 42 07 r2 = b[r4++=0x1] (u) + 110292: 45 07 r5 = b[r4++=0x1] (u) + 110294: a2 e1 20 54 r2 <= insert(r5, p:0x8, l:0x8) + 110298: 45 07 r5 = b[r4++=0x1] (u) + 11029a: a2 e1 20 58 r2 <= insert(r5, p:0x10, l:0x8) + 11029e: 45 07 r5 = b[r4++=0x1] (u) + 1102a0: a2 e1 20 5c r2 <= insert(r5, p:0x18, l:0x8) + 1102a4: a5 1d r5 = r2 + r6 + 1102a6: 90 e1 53 52 r5 = r5 & ~r2 + 1102aa: 61 ff 80 53 03 00 if ((r5 & 0x80808080) != 0) goto 0x6 + 1102b0: 82 05 [r0++=0x4] = r2 + 1102b2: 41 16 r1 = r4 + 1102b4: f7 8c goto -0x28 + 1102b6: 12 07 r2 = b[r1++=0x1] (u) + 1102b8: 82 07 b[r0++=0x1] = r2 + 1102ba: f2 5d if (r2 != 0) goto -0x6 + 1102bc: 70 16 r0 = r7 + 1102be: 57 04 {pc, r7-r4} = [sp++] + + +strlen: + 1102c0: 01 16 r1 = r0 + 1102c2: d0 ee 11 20 r2 = b[r1++=0x1] (u) + 1102c6: f2 5d if (r2 != 0) goto -0x6 + 1102c8: f9 3f r1 += -0x1 + 1102ca: 10 1e r0 = r1 - r0 + 1102cc: 80 00 rts + + +nvram_uart_tag: + 1102ce: 75 61 72 74 d9 c4 05 a8 + + +nvram_usb_tag: + 1102d6: 75 73 62 ed 63 81 67 ef + + +chip_reset: + 1102de: 68 20 r0 = 0xa0 ## main.c:74:0 + 1102e0: 41 30 r1 = 0x10 ## main.c:75:5 + 1102e2: 80 ea f1 06 call 0xde2 ## main.c:75:5 + 1102e6: f7 9f goto -0x2 ## main.c:78:5 + + +nvram_boot_state: + 1102e8: 75 04 [--sp] = {rets, r5, r4} ## boot_nvram.c:121:0 + 1102ea: c5 ff 00 08 01 00 r5 = 0x10800 ## boot_nvram.c:121:0 + 1102f0: 5c 84 r4 = r5 + 0x4 ## boot_nvram.c:122:9 + 1102f2: c1 ff d6 02 11 00 r1 = 0x1102d6 ## boot_nvram.c:122:9 + 1102f8: 42 28 r2 = 0x8 ## boot_nvram.c:122:9 + 1102fa: 40 16 r0 = r4 ## boot_nvram.c:122:9 + 1102fc: bf ea 26 ff call -0x1b4 ## boot_nvram.c:122:9 + 110300: 00 4c if (r0 == 0) goto 0x18 ## boot_nvram.c:122:9 + 110302: c1 ff ce 02 11 00 r1 = 0x1102ce ## boot_nvram.c:125:16 + 110308: 42 28 r2 = 0x8 ## boot_nvram.c:125:16 + 11030a: 40 16 r0 = r4 ## boot_nvram.c:125:16 + 11030c: bf ea 1e ff call -0x1c4 ## boot_nvram.c:125:16 + 110310: 01 16 r1 = r0 ## boot_nvram.c:125:16 + 110312: 40 20 r0 = 0x0 ## boot_nvram.c:125:16 + 110314: 81 47 if (r1 != 0) goto 0xe ## boot_nvram.c:125:16 + 110316: 40 23 r0 = 0x3 + 110318: 04 81 goto 0x2 + 11031a: 40 22 r0 = 0x2 + 11031c: 42 20 r2 = 0x0 ## boot_nvram.c:118:5 + 11031e: 43 20 r3 = 0x0 ## boot_nvram.c:118:5 + 110320: 50 ec 55 20 d[r5+0x4] = r3_r2 ## boot_nvram.c:118:5 + 110324: 55 04 {pc, r5, r4} = [sp++] ## boot_nvram.c:130:1 + + +nvram_get_addr: + 110326: c0 ff 00 08 01 00 r0 = 0x10800 ## boot_nvram.c:146:0 + 11032c: 80 00 rts ## boot_nvram.c:147:5 + + +nvram_set_boot_state: + 11032e: 00 f8 09 04 if (r0 == 0x2) goto 0x12 ## boot_nvram.c:132:0 + 110332: 80 f8 12 06 if (r0 != 0x3) goto 0x24 ## boot_nvram.c:132:0 + 110336: c0 ff 75 61 72 74 r0 = 0x74726175 <__stub_doe+0x74613978 : 74726174 > ## boot_nvram.c:132:0 + 11033c: c1 ff d9 c4 05 a8 r1 = 0xa805c4d9 <__stub_doe+0xA7F49CDC : a805c4d8 > ## boot_nvram.c:132:0 + 110342: 04 86 goto 0xc ## boot_nvram.c:132:0 + 110344: c0 ff 75 73 62 ed r0 = 0xed627375 <__stub_doe+0xED514B78 : ed627374 > ## boot_nvram.c:132:0 + 11034a: c1 ff 63 81 67 ef r1 = 0xef678163 <__stub_doe+0xEF565966 : ef678162 > ## boot_nvram.c:132:0 + 110350: c2 ff 00 08 01 00 r2 = 0x10800 ## boot_nvram.c:132:0 + 110356: 50 ec 25 00 d[r2+0x4] = r1_r0 ## boot_nvram.c:132:0 + 11035a: 80 00 rts ## boot_nvram.c:144:1 + + +os_code_begin: + 11035c: 60 00 cli ## mask_export.c:60:0 + 11035e: c0 ff bc be 02 00 r0 = 0x2bebc ## mask_export.c:62:35 + 110364: c0 eb 01 00 [r0+0x0] += 0x1 ## mask_export.c:62:35 + 110368: 80 00 rts ## mask_export.c:63:1 + + +local_irq_enable: + 11036a: c0 ff bc be 02 00 r0 = 0x2bebc ## mask_export.c:71:0 + 110370: 01 60 r1 = [r0+0x0] ## mask_export.c:72:9 + 110372: f9 3f r1 += -0x1 ## mask_export.c:72:9 + 110374: 81 60 [r0+0x0] = r1 ## mask_export.c:72:9 + 110376: 81 41 if (r1 != 0) goto 0x2 ## mask_export.c:72:9 + 110378: 61 00 sti ## mask_export.c:73:9 + 11037a: 80 00 rts ## mask_export.c:75:1 + + +irq_init: + 11037c: c0 ff bc be 02 00 r0 = 0x2bebc ## mask_export.c:67:0 + 110382: 40 ea 00 00 [r0+0x0] = 0x0 ## mask_export.c:68:5 + 110386: 80 00 rts ## mask_export.c:69:1 + + +mask_init: + 110388: c1 ff bc be 02 00 r1 = 0x2bebc ## mask_export.c:53:0 + 11038e: 40 ea 00 10 [r1+0x0] = 0x0 ## mask_export.c:68:5 + 110392: c1 ff c0 be 02 00 r1 = 0x2bec0 ## mask_export.c:56:24 + 110398: 90 60 [r1+0x0] = r0 ## mask_export.c:56:24 + 11039a: 80 00 rts ## mask_export.c:57:1 + + +usb_code_begin: + 11039c: c2 ff 00 18 1e 00 r2 = 0x1e1800 <__stub_doe+0xCF004 : 1e1800 > ## usb_phy.c:52:0 + 1103a2: 23 60 r3 = [r2+0x0] ## usb_phy.c:54:19 + 1103a4: 53 e8 07 10 if ((r3 & 0x4) == 0) goto 0xe + 1103a8: a1 e1 20 04 r1 <= insert(r0, p:0x8, l:0x8) ## usb_phy.c:57:32 + 1103ac: a1 61 [r2+0x4] = r1 ## usb_phy.c:57:18 + 1103ae: 20 00 csync ## usb_phy.c:58:5 + 1103b0: 20 61 r0 = [r2+0x4] ## usb_phy.c:59:21 + 1103b2: 50 e8 fd 79 if ((r0 & 0x8000) == 0) goto -0x6 ## usb_phy.c:59:21 + 1103b6: 80 00 rts ## usb_phy.c:66:1 + + +musb_read_usb: + 1103b8: c1 ff 00 18 1e 00 r1 = 0x1e1800 <__stub_doe+0xCF004 : 1e1800 > ## usb_phy.c:31:0 + 1103be: 13 60 r3 = [r1+0x0] ## usb_phy.c:35:19 + 1103c0: 42 20 r2 = 0x0 + 1103c2: 53 e8 08 10 if ((r3 & 0x4) == 0) goto 0x10 + 1103c6: 30 26 r0 |= 0x40 ## usb_phy.c:38:26 + 1103c8: 00 a8 r0 = r0 << 0x8 ## usb_phy.c:38:36 + 1103ca: 90 61 [r1+0x4] = r0 ## usb_phy.c:38:18 + 1103cc: 20 00 csync ## usb_phy.c:39:5 + 1103ce: 10 61 r0 = [r1+0x4] ## usb_phy.c:40:21 + 1103d0: 50 e8 fd 79 if ((r0 & 0x8000) == 0) goto -0x6 ## usb_phy.c:40:5 + 1103d4: 12 61 r2 = [r1+0x4] ## usb_phy.c:47:20 + 1103d6: 20 17 r0 = r2.b0 (u) ## usb_phy.c:49:1 + 1103d8: 80 00 rts ## usb_phy.c:49:1 + + +usb_clr_intr_rxe: + 1103da: 75 04 [--sp] = {rets, r5, r4} ## usb_phy.c:210:0 + 1103dc: 04 16 r4 = r0 ## usb_phy.c:210:0 + 1103de: bf ea bd ff call -0x86 ## usb_phy.c:211:5 + 1103e2: 40 29 r0 = 0x9 ## usb_phy.c:212:20 + 1103e4: 71 89 call -0x2e ## usb_phy.c:212:20 + 1103e6: 05 16 r5 = r0 ## usb_phy.c:212:20 + 1103e8: 40 2a r0 = 0xa ## usb_phy.c:212:51 + 1103ea: 71 86 call -0x34 ## usb_phy.c:212:51 + 1103ec: b4 e8 ff df if (r4 != -0x1) { ## usb_phy.c:212:51 + 1103f0: c1 ff ff ff 00 00 r1 = 0xffff ## usb_phy.c:216:21 + 1103f6: 94 e1 11 14 r1 = r1 ^ (1 << r4) ## usb_phy.c:216:21 + 1103fa: a5 e1 20 04 r5 <= insert(r0, p:0x8, l:0x8) ## usb_phy.c:212:49 + 1103fe: 90 e1 52 41 r4 = r5 & r1 + } else { ## usb_phy.c:216:18 + 110402: 44 20 r4 = 0x0 + } + 110404: 71 e1 7f 4c r1 = r4 & 0xFFFF00FF ## usb_phy.c:218:5 + 110408: 40 29 r0 = 0x9 ## usb_phy.c:218:5 + 11040a: 61 88 call -0x70 ## usb_phy.c:218:5 + 11040c: c1 a8 r1 = r4 >> 0x8 ## usb_phy.c:219:44 + 11040e: 40 2a r0 = 0xa ## usb_phy.c:219:5 + 110410: 61 85 call -0x76 ## usb_phy.c:219:5 + 110412: 35 04 {rets, r5, r4} = [sp++] ## usb_phy.c:220:5 + 110414: ff ea a9 ff goto -0xae ## usb_phy.c:220:5 + + +usb_clr_intr_txe: + 110418: 75 04 [--sp] = {rets, r5, r4} ## usb_phy.c:188:0 + 11041a: 04 16 r4 = r0 ## usb_phy.c:188:0 + 11041c: bf ea 9e ff call -0xc4 ## usb_phy.c:189:5 + 110420: 40 27 r0 = 0x7 ## usb_phy.c:190:20 + 110422: 61 8a call -0x6c ## usb_phy.c:190:20 + 110424: 05 16 r5 = r0 ## usb_phy.c:190:20 + 110426: 40 28 r0 = 0x8 ## usb_phy.c:190:51 + 110428: 61 87 call -0x72 ## usb_phy.c:190:51 + 11042a: b4 e8 ff df if (r4 != -0x1) { ## usb_phy.c:190:51 + 11042e: c1 ff ff ff 00 00 r1 = 0xffff ## usb_phy.c:194:21 + 110434: 94 e1 11 14 r1 = r1 ^ (1 << r4) ## usb_phy.c:194:21 + 110438: a5 e1 20 04 r5 <= insert(r0, p:0x8, l:0x8) ## usb_phy.c:190:49 + 11043c: 90 e1 52 41 r4 = r5 & r1 + } else { ## usb_phy.c:194:18 + 110440: 44 20 r4 = 0x0 + } + 110442: 71 e1 7f 4c r1 = r4 & 0xFFFF00FF ## usb_phy.c:196:5 + 110446: 40 27 r0 = 0x7 ## usb_phy.c:196:5 + 110448: 51 89 call -0xae ## usb_phy.c:196:5 + 11044a: c1 a8 r1 = r4 >> 0x8 ## usb_phy.c:197:44 + 11044c: 40 28 r0 = 0x8 ## usb_phy.c:197:5 + 11044e: 51 86 call -0xb4 ## usb_phy.c:197:5 + 110450: 35 04 {rets, r5, r4} = [sp++] ## usb_phy.c:198:5 + 110452: ff ea 8a ff goto -0xec ## usb_phy.c:198:5 + + +musb_write_index: + 110456: 01 16 r1 = r0 ## usb_phy.c:68:0 + 110458: 40 2e r0 = 0xe ## usb_phy.c:69:5 + 11045a: d7 80 goto -0xc0 ## usb_phy.c:69:5 + + +usb_read_rxcsr: + 11045c: 74 04 [--sp] = {rets, r4} ## usb_phy.c:253:0 + 11045e: bf ea 7d ff call -0x106 ## usb_phy.c:254:5 + 110462: 40 21 r0 = 0x1 ## usb_phy.c:255:5 + 110464: 71 98 call -0x10 ## usb_phy.c:255:5 + 110466: 40 34 r0 = 0x14 ## usb_phy.c:256:17 + 110468: 51 87 call -0xb2 ## usb_phy.c:256:17 + 11046a: 04 16 r4 = r0 ## usb_phy.c:256:17 + 11046c: 40 35 r0 = 0x15 ## usb_phy.c:256:47 + 11046e: 51 84 call -0xb8 ## usb_phy.c:256:47 + 110470: a4 e1 20 04 r4 <= insert(r0, p:0x8, l:0x8) ## usb_phy.c:256:44 + 110474: bf ea 79 ff call -0x10e ## usb_phy.c:257:5 + 110478: 40 16 r0 = r4 ## usb_phy.c:258:5 + 11047a: 54 04 {pc, r4} = [sp++] ## usb_phy.c:258:5 + + +usb_write_rxcsr: + 11047c: 74 04 [--sp] = {rets, r4} ## usb_phy.c:245:0 + 11047e: 14 16 r4 = r1 ## usb_phy.c:245:0 + 110480: 01 16 r1 = r0 ## usb_phy.c:245:0 + 110482: bf ea 6b ff call -0x12a ## usb_phy.c:246:5 + 110486: 10 17 r0 = r1.b0 (u) ## usb_phy.c:247:5 + 110488: 71 86 call -0x34 ## usb_phy.c:247:5 + 11048a: 41 17 r1 = r4.b0 (u) ## usb_phy.c:248:5 + 11048c: 40 34 r0 = 0x14 ## usb_phy.c:248:5 + 11048e: 41 86 call -0xf4 ## usb_phy.c:248:5 + 110490: b1 e1 20 44 r1 = uextra(r4, p:0x8, l:0x8) ## usb_phy.c:249:5 + 110494: 40 35 r0 = 0x15 ## usb_phy.c:249:5 + 110496: 41 82 call -0xfc ## usb_phy.c:249:5 + 110498: 34 04 {rets, r4} = [sp++] ## usb_phy.c:250:5 + 11049a: ff ea 66 ff goto -0x134 ## usb_phy.c:250:5 + + +usb_g_bulk_read: + 11049e: 7a 04 [--sp] = {rets, r10-r4} ## usb_phy.c:432:0 + 1104a0: 14 16 r4 = r1 ## usb_phy.c:432:0 + 1104a2: 05 16 r5 = r0 ## usb_phy.c:432:0 + 1104a4: 14 5a if (r4 == 0) goto 0x74 ## usb_phy.c:432:0 + 1104a6: c0 ff ac 13 01 00 r0 = 0x113ac ## usb_phy.c:432:0 + 1104ac: d0 ec 00 80 r8 = [r0+0x0] ## usb_phy.c:432:0 + 1104b0: 4a e0 01 00 r10 = 0x1 ## usb_phy.c:432:0 + 1104b4: 32 e8 00 00 if (r2 == 0x0) { ## usb_phy.c:432:0 + 1104b8: 2a 16 r10 = r2 + } ## usb_phy.c:432:0 + 1104ba: c1 14 r9 = 0 ## usb_phy.c:432:0 + 1104bc: bf ea 4e ff call -0x164 ## usb_phy.c:337:5 + 1104c0: 40 21 r0 = 0x1 ## usb_phy.c:339:5 + 1104c2: 61 89 call -0x6e ## usb_phy.c:339:5 + 1104c4: 40 34 r0 = 0x14 ## usb_phy.c:340:9 + 1104c6: bf ea 77 ff call -0x112 ## usb_phy.c:340:9 + 1104ca: 50 e8 03 02 if ((r0 & 0x1) != 0) goto 0x6 ## usb_phy.c:340:9 + 1104ce: bf ea 4c ff call -0x168 ## usb_phy.c:343:5 + 1104d2: 04 9f goto 0x3e ## usb_phy.c:343:5 + 1104d4: 40 36 r0 = 0x16 ## usb_phy.c:341:19 + 1104d6: bf ea 6f ff call -0x122 ## usb_phy.c:341:19 + 1104da: 06 16 r6 = r0 ## usb_phy.c:341:19 + 1104dc: 40 37 r0 = 0x17 ## usb_phy.c:341:51 + 1104de: bf ea 6b ff call -0x12a ## usb_phy.c:341:51 + 1104e2: a6 e1 20 04 r6 <= insert(r0, p:0x8, l:0x8) ## usb_phy.c:341:48 + 1104e6: bf ea 40 ff call -0x180 ## usb_phy.c:343:5 + 1104ea: 06 53 if (r6 == 0) goto 0x26 ## usb_phy.c:343:5 + 1104ec: 51 97 call -0x92 ## usb_phy.c:361:21 + 1104ee: 77 e1 ba 0f r7 = r0 & 0xFFFFFE8B ## usb_phy.c:372:19 + 1104f2: b5 e8 00 c0 if (r5 != 0x0) { + 1104f6: 50 16 r0 = r5 ## usb_phy.c:375:13 + 1104f8: 81 16 r1 = r8 ## usb_phy.c:375:13 + 1104fa: 62 16 r2 = r6 ## usb_phy.c:375:13 + 1104fc: bf ea af fd call -0x4a2 + } ## usb_phy.c:375:13 + 110500: 41 e1 10 70 r1 = r7 | 0x10 ## usb_phy.c:377:46 + 110504: 40 21 r0 = 0x1 ## usb_phy.c:377:9 + 110506: 47 21 r7 = 0x1 ## usb_phy.c:377:9 + 110508: 51 99 call -0x8e ## usb_phy.c:377:9 + 11050a: 65 18 r5 += r6 ## usb_phy.c:380:13 + 11050c: 69 18 r9 += r6 ## usb_phy.c:379:14 + 11050e: c4 1f r4 = r4 - r6 ## usb_phy.c:378:13 + 110510: 04 81 goto 0x2 + 110512: a7 16 r7 = r10 + 110514: 04 43 if (r4 == 0) goto 0x6 + 110516: e7 52 if (r7 != 0) goto -0x5c + 110518: 04 81 goto 0x2 + 11051a: c1 14 r9 = 0 + 11051c: 90 16 r0 = r9 ## usb_phy.c:433:5 + 11051e: 5a 04 {pc, r10-r4} = [sp++] ## usb_phy.c:433:5 + + +rbc_get_length: + 110520: c0 ff 50 13 01 00 r0 = 0x11350 ## msd_upgrade.c:51:0 + 110526: 50 ee 05 11 r1 = b[r0+0x15] (u) ## msd_upgrade.c:63:12 + 11052a: 50 ee 06 01 r0 = b[r0+0x16] (u) ## msd_upgrade.c:63:12 + 11052e: a0 e1 20 14 r0 <= insert(r1, p:0x8, l:0x8) ## msd_upgrade.c:63:12 + 110532: 80 00 rts ## msd_upgrade.c:63:5 + + +msd_usb2mcu: + 110534: 42 21 r2 = 0x1 ## msd.c:132:0 + 110536: d7 93 goto -0x9a ## msd.c:133:12 + + +usb_read_txcsr: + 110538: 74 04 [--sp] = {rets, r4} ## usb_phy.c:237:0 + 11053a: bf ea 0f ff call -0x1e2 ## usb_phy.c:238:5 + 11053e: 40 21 r0 = 0x1 ## usb_phy.c:239:5 + 110540: 41 8a call -0xec ## usb_phy.c:239:5 + 110542: 40 31 r0 = 0x11 ## usb_phy.c:240:17 + 110544: bf ea 38 ff call -0x190 ## usb_phy.c:240:17 + 110548: 04 16 r4 = r0 ## usb_phy.c:240:17 + 11054a: 40 32 r0 = 0x12 ## usb_phy.c:240:47 + 11054c: bf ea 34 ff call -0x198 ## usb_phy.c:240:47 + 110550: a4 e1 20 04 r4 <= insert(r0, p:0x8, l:0x8) ## usb_phy.c:240:44 + 110554: bf ea 09 ff call -0x1ee ## usb_phy.c:241:5 + 110558: 40 16 r0 = r4 ## usb_phy.c:242:5 + 11055a: 54 04 {pc, r4} = [sp++] ## usb_phy.c:242:5 + + +usb_write_txcsr: + 11055c: 74 04 [--sp] = {rets, r4} ## usb_phy.c:229:0 + 11055e: 14 16 r4 = r1 ## usb_phy.c:229:0 + 110560: 01 16 r1 = r0 ## usb_phy.c:229:0 + 110562: bf ea fb fe call -0x20a ## usb_phy.c:230:5 + 110566: 10 17 r0 = r1.b0 (u) ## usb_phy.c:231:5 + 110568: bf ea 75 ff call -0x116 ## usb_phy.c:231:5 + 11056c: 41 17 r1 = r4.b0 (u) ## usb_phy.c:232:5 + 11056e: 40 31 r0 = 0x11 ## usb_phy.c:232:5 + 110570: bf ea 14 ff call -0x1d8 ## usb_phy.c:232:5 + 110574: b1 e1 20 44 r1 = uextra(r4, p:0x8, l:0x8) ## usb_phy.c:233:5 + 110578: 40 32 r0 = 0x12 ## usb_phy.c:233:5 + 11057a: bf ea 0f ff call -0x1e2 ## usb_phy.c:233:5 + 11057e: 34 04 {rets, r4} = [sp++] ## usb_phy.c:234:5 + 110580: ff ea f3 fe goto -0x21a ## usb_phy.c:234:5 + + +msd_mcu2usb: + 110584: 79 04 [--sp] = {rets, r9-r4} ## msd.c:136:0 + 110586: c2 ff 9c 13 01 00 r2 = 0x1139c ## msd.c:136:0 + 11058c: 18 d6 r8 = r1 # ## msd.c:136:0 + 11058e: 25 60 r5 = [r2+0x0] ## msd.c:136:0 + 110590: 06 16 r6 = r0 ## msd.c:136:0 + 110592: c9 ff 0c 18 1e 00 r9 = 0x1e180c <__stub_doe+0xCF010 : 1e180c > ## msd.c:136:0 + 110598: 84 16 r4 = r8 ## msd.c:136:0 + 11059a: 04 87 goto 0xe ## msd.c:136:0 + 11059c: 71 e1 05 00 r1 = r0 & 0xFFFFFFFA ## usb_phy.c:407:23 + 1105a0: 04 82 goto 0x4 ## usb_phy.c:407:23 + 1105a2: 71 e1 03 00 r1 = r0 & 0xFFFFFFFC ## usb_phy.c:412:23 + 1105a6: 40 21 r0 = 0x1 + 1105a8: 61 99 call -0x4e + 1105aa: 61 86 call -0x74 ## usb_phy.c:402:21 + 1105ac: 50 e8 06 72 if ((r0 & 0x4000) != 0) goto 0xc + 1105b0: 50 e8 f4 13 if ((r0 & 0x4) != 0) goto -0x18 + 1105b4: 50 e8 f5 0b if ((r0 & 0x2) != 0) goto -0x16 + 1105b8: 50 e8 f7 03 if ((r0 & 0x1) != 0) goto -0x12 + 1105bc: 47 16 r7 = r4 ## usb_phy.c:421:24 + 1105be: 34 e9 40 00 if (r4 >= 0x40) { ## usb_phy.c:421:24 + 1105c2: 57 20 r7 = 0x40 + } ## usb_phy.c:421:24 + 1105c4: b6 e8 00 c0 if (r6 != 0x0) { + 1105c8: 50 16 r0 = r5 ## usb_phy.c:423:13 + 1105ca: 61 16 r1 = r6 ## usb_phy.c:423:13 + 1105cc: 72 16 r2 = r7 ## usb_phy.c:423:13 + 1105ce: bf ea 46 fd call -0x574 + } ## usb_phy.c:423:13 + 1105d2: d0 ec 91 70 [r9+0x0] = r7 ## usb_phy.c:389:11 + 1105d6: 51 90 call -0xa0 ## usb_phy.c:390:17 + 1105d8: 41 e1 01 00 r1 = r0 | 0x1 ## usb_phy.c:392:11 + 1105dc: 40 21 r0 = 0x1 ## usb_phy.c:393:5 + 1105de: 51 9e call -0x84 ## usb_phy.c:393:5 + 1105e0: cc 1f r4 = r4 - r7 ## usb_phy.c:426:13 + 1105e2: 76 18 r6 += r7 ## usb_phy.c:427:13 + 1105e4: f4 42 if (r4 != 0) goto -0x3c + 1105e6: 80 16 r0 = r8 ## msd.c:137:5 + 1105e8: 59 04 {pc, r9-r4} = [sp++] ## msd.c:137:5 + + +stall_inep: + 1105ea: 10 04 [--sp] = rets ## msd.c:171:0 + 1105ec: 40 21 r0 = 0x1 ## msd.c:173:5 + 1105ee: 41 30 r1 = 0x10 ## msd.c:173:5 + 1105f0: 51 95 call -0x96 ## msd.c:173:5 + 1105f2: 51 82 call -0xbc ## msd.c:180:14 + 1105f4: 50 e8 fd 23 if ((r0 & 0x10) != 0) goto -0x6 ## msd.c:180:13 + 1105f8: 00 04 pc = [sp++] ## msd.c:184:1 + + +unknow: + 1105fa: 10 04 [--sp] = rets ## msd.c:199:0 + 1105fc: 00 49 if (r0 == 0) goto 0x12 ## msd.c:200:9 + 1105fe: 40 21 r0 = 0x1 ## msd.c:188:5 + 110600: 49 20 r1 = 0x20 ## msd.c:188:5 + 110602: bf ea 3b ff call -0x18a ## msd.c:188:5 + 110606: bf ea 29 ff call -0x1ae ## msd.c:193:14 + 11060a: 50 e8 fc 2b if ((r0 & 0x20) != 0) goto -0x8 ## msd.c:193:14 + 11060e: 04 81 goto 0x2 ## msd.c:193:14 + 110610: 71 8c call -0x28 ## msd.c:203:9 + 110612: c0 ff 6f 13 01 00 r0 = 0x1136f ## msd.c:207:20 + 110618: 41 20 r1 = 0x0 ## msd.c:207:20 + 11061a: 89 4b b[r0+0xb] = r1 ## msd.c:206:25 + 11061c: 89 4a b[r0+0xa] = r1 ## msd.c:206:25 + 11061e: 89 49 b[r0+0x9] = r1 ## msd.c:206:25 + 110620: 89 48 b[r0+0x8] = r1 ## msd.c:206:25 + 110622: 41 21 r1 = 0x1 ## msd.c:206:25 + 110624: 89 4c b[r0+0xc] = r1 ## msd.c:207:20 + 110626: c0 ff 7c 13 01 00 r0 = 0x1137c ## msd.c:208:23 + 11062c: 41 22 r1 = 0x2 ## msd.c:208:23 + 11062e: 89 40 b[r0+0x0] = r1 ## msd.c:208:23 + 110630: 00 04 pc = [sp++] ## msd.c:209:1 + + +usb_slave_mode: + 110632: e2 94 sp += -0x30 ## usb_device.c:12:0 + 110634: c0 ff 08 14 01 00 r0 = 0x11408 ## usb_onchip.c:83:5 + 11063a: c5 14 r13 = 0 ## usb_onchip.c:83:5 + 11063c: d0 ec 09 d1 [r0+0x18] = r13 ## usb_onchip.c:83:5 + 110640: 42 20 r2 = 0x0 ## usb_onchip.c:83:5 + 110642: 43 20 r3 = 0x0 ## usb_onchip.c:83:5 + 110644: 50 ec 01 21 d[r0+0x10] = r3_r2 ## usb_onchip.c:83:5 + 110648: 50 ec 09 20 d[r0+0x8] = r3_r2 ## usb_onchip.c:83:5 + 11064c: 50 ec 01 20 d[r0+0x0] = r3_r2 ## usb_onchip.c:83:5 + 110650: c0 ff ec 13 01 00 r0 = 0x113ec ## usb_onchip.c:83:5 + 110656: d0 ec 09 d1 [r0+0x18] = r13 ## usb_onchip.c:84:5 + 11065a: 50 ec 01 21 d[r0+0x10] = r3_r2 ## usb_onchip.c:84:5 + 11065e: 50 ec 09 20 d[r0+0x8] = r3_r2 ## usb_onchip.c:84:5 + 110662: 50 ec 01 20 d[r0+0x0] = r3_r2 ## usb_onchip.c:84:5 + 110666: c1 ff 0e 0c 11 00 r1 = 0x110c0e ## usb_onchip.c:86:5 + 11066c: 40 29 r0 = 0x9 ## usb_onchip.c:86:5 + 11066e: 42 21 r2 = 0x1 ## usb_onchip.c:86:5 + 110670: 80 ea 78 05 call 0xaf0 ## usb_onchip.c:86:5 + 110674: c0 ff 00 51 1e 00 r0 = 0x1e5100 <__stub_doe+0xD2904 : 1e5100 > ## usb_onchip.c:86:5 + 11067a: c0 ef 00 0e [r0+0x0] &= 0xFFFFF7FF ## usb_onchip.c:88:21 + 11067e: 00 ef 80 0d [r0+0x0] |= 0x1000 ## usb_onchip.c:89:21 + 110682: 41 e0 ca bf r1 = -0x4036 ## usb_onchip.c:90:18 + 110686: c4 ff 00 18 1e 00 r4 = 0x1e1800 <__stub_doe+0xCF004 : 1e1800 > ## usb_onchip.c:90:18 + 11068c: 64 e8 02 41 [r4+0x0] &= r1 ## usb_onchip.c:90:18 + 110690: d0 ec 45 d0 [r4+0x4] = r13 ## usb_onchip.c:91:18 + 110694: 00 ef 01 40 [r4+0x0] |= 0x1 ## usb_onchip.c:93:18 + 110698: c0 ef 30 00 [r0+0x0] &= 0xFFFFFFCF ## usb_onchip.c:95:21 + 11069c: c0 ef c0 00 [r0+0x0] &= 0xFFFFFF3F ## usb_onchip.c:96:21 + 1106a0: 00 ef 40 00 [r0+0x0] |= 0x40 ## usb_onchip.c:98:21 + 1106a4: 00 ef 20 00 [r0+0x0] |= 0x20 ## usb_onchip.c:99:21 + 1106a8: 00 ef 34 40 [r4+0x0] |= 0x34 ## usb_onchip.c:101:18 + 1106ac: bf ea 56 fe call -0x354 ## usb_phy.c:173:5 + 1106b0: 40 2b r0 = 0xb ## usb_phy.c:174:5 + 1106b2: 41 24 r1 = 0x4 ## usb_phy.c:174:5 + 1106b4: bf ea 72 fe call -0x31c ## usb_phy.c:174:5 + 1106b8: bf ea 57 fe call -0x352 ## usb_phy.c:175:5 + 1106bc: 10 3f r0 = -0x1 ## usb_onchip.c:104:5 + 1106be: bf ea 8c fe call -0x2e8 ## usb_onchip.c:104:5 + 1106c2: 10 3f r0 = -0x1 ## usb_onchip.c:105:5 + 1106c4: bf ea a8 fe call -0x2b0 ## usb_onchip.c:105:5 + 1106c8: bf ea 48 fe call -0x370 ## usb_phy.c:73:5 + 1106cc: 40 21 r0 = 0x1 ## usb_phy.c:74:5 + 1106ce: 51 20 r1 = 0x40 ## usb_phy.c:74:5 + 1106d0: bf ea 64 fe call -0x338 ## usb_phy.c:74:5 + 1106d4: bf ea 49 fe call -0x36e ## usb_phy.c:75:5 + 1106d8: 00 ef 00 4e [r4+0x0] |= 0x800 ## usb_onchip.c:114:18 + 1106dc: c0 ff 40 10 01 00 r0 = 0x11040 ## usb_phy.c:321:25 + 1106e2: c0 67 [r4+0x1c] = r0 ## usb_phy.c:321:25 + 1106e4: c1 ff 98 13 01 00 r1 = 0x11398 ## usb_phy.c:322:18 + 1106ea: 90 60 [r1+0x0] = r0 ## usb_phy.c:322:18 + 1106ec: c0 ff 80 10 01 00 r0 = 0x11080 + 1106f2: c0 68 [r4+0x20] = r0 ## usb_phy.c:308:12 + 1106f4: c1 ff 9c 13 01 00 r1 = 0x1139c ## usb_phy.c:309:22 + 1106fa: 90 60 [r1+0x0] = r0 ## usb_phy.c:309:22 + 1106fc: d0 20 r0 += 0x40 ## usb_phy.c:309:22 + 1106fe: 4b f0 53 00 r11 = 0x53 # + 110702: c0 69 [r4+0x24] = r0 ## usb_phy.c:327:12 + 110704: c1 ff ac 13 01 00 r1 = 0x113ac ## usb_phy.c:328:22 + 11070a: 4f f0 42 00 r15 = 0x42 # ## usb_phy.c:328:22 + 11070e: 90 60 [r1+0x0] = r0 ## usb_phy.c:328:22 + 110710: a8 80 r0 = sp + 32 ## usb_phy.c:328:22 + 110712: 80 22 [sp+8] = r0 + 110714: 88 8e r0 = sp + 14 + 110716: 80 21 [sp+4] = r0 + 110718: c0 21 r0 += 0x1 + 11071a: 80 20 [sp] = r0 + 11071c: c5 ff 50 13 01 00 r5 = 0x11350 + 110722: c9 ff 55 53 42 43 r9 = 0x43425355 <__stub_doe+0x43312B58 : 43425354 > + 110728: c6 ff 6f 13 01 00 r6 = 0x1136f + 11072e: ca ff 80 13 01 00 r10 = 0x11380 + 110734: ce ff 7c 13 01 00 r14 = 0x1137c + 11073a: cc ff 7d 13 01 00 r12 = 0x1137d + 110740: c8 ff 7e 13 01 00 r8 = 0x1137e + 110746: 57 35 r7 = 0x55 + 110748: 80 ea 96 06 call 0xd2c ## usb_device.c:18:9 + 11074c: 52 ee 53 d0 b[r5+0x3] = r13 ## msd.c:141:23 + 110750: 52 ee 52 d0 b[r5+0x2] = r13 ## msd.c:141:23 + 110754: 52 ee 51 d0 b[r5+0x1] = r13 ## msd.c:141:23 + 110758: 52 ee 50 d0 b[r5+0x0] = r13 ## msd.c:141:23 + 11075c: 41 3f r1 = 0x1f ## msd.c:142:18 + 11075e: 42 20 r2 = 0x0 ## msd.c:142:18 + 110760: 50 16 r0 = r5 ## msd.c:142:18 + 110762: bf ea 9c fe call -0x2c8 ## msd.c:142:18 + 110766: 5a 43 r2 = b[r5+0x3] (u) ## msd.c:146:13 + 110768: 5b 42 r3 = b[r5+0x2] (u) ## msd.c:146:13 + 11076a: a3 f1 20 24 r3 <= insert(r2, p:0x8, l:0x8) # ## msd.c:146:13 + 11076e: 5c 41 r4 = b[r5+0x1] (u) ## msd.c:146:13 + 110770: 59 40 r1 = b[r5+0x0] (u) ## msd.c:146:13 + 110772: a1 e1 20 44 r1 <= insert(r4, p:0x8, l:0x8) ## msd.c:146:13 + 110776: a1 e1 40 38 r1 <= insert(r3, p:0x10, l:0x10) ## msd.c:146:13 + 11077a: 70 46 if (r0 == 0) goto -0x34 ## msd.c:143:9 + 11077c: 89 e8 e4 11 if (r1 != r9) goto -0x38 + 110780: 58 47 r0 = b[r5+0x7] (u) ## msd.c:152:23 + 110782: 59 45 r1 = b[r5+0x5] (u) ## msd.c:152:23 + 110784: 5a 44 r2 = b[r5+0x4] (u) ## msd.c:152:23 + 110786: 5b 46 r3 = b[r5+0x6] (u) ## msd.c:152:23 + 110788: a3 f1 20 04 r3 <= insert(r0, p:0x8, l:0x8) # ## msd.c:152:23 + 11078c: e8 47 b[r6+0x7] = r0 ## msd.c:152:17 + 11078e: e9 45 b[r6+0x5] = r1 ## msd.c:152:17 + 110790: a2 f1 40 38 r2 <= insert(r3, p:0x10, l:0x10) # ## msd.c:152:23 + 110794: ea 44 b[r6+0x4] = r2 ## msd.c:152:17 + 110796: a0 b0 r0 = r2 >> 0x10 ## msd.c:152:17 + 110798: e8 46 b[r6+0x6] = r0 ## msd.c:152:17 + 11079a: 58 4b r0 = b[r5+0xb] (u) ## msd.c:153:31 + 11079c: 59 49 r1 = b[r5+0x9] (u) ## msd.c:153:31 + 11079e: 5b 48 r3 = b[r5+0x8] (u) ## msd.c:153:31 + 1107a0: 5c 4a r4 = b[r5+0xa] (u) ## msd.c:153:31 + 1107a2: a4 f1 20 04 r4 <= insert(r0, p:0x8, l:0x8) # ## msd.c:153:31 + 1107a6: e8 4b b[r6+0xb] = r0 ## msd.c:153:25 + 1107a8: e9 49 b[r6+0x9] = r1 ## msd.c:153:25 + 1107aa: a3 f1 40 48 r3 <= insert(r4, p:0x10, l:0x10) # ## msd.c:153:31 + 1107ae: eb 48 b[r6+0x8] = r3 ## msd.c:153:25 + 1107b0: d0 ec a0 20 r2 = [r10+0x0] ## msd_upgrade.c:134:9 + 1107b4: b0 b0 r0 = r3 >> 0x10 ## msd.c:153:25 + 1107b6: e8 4a b[r6+0xa] = r0 ## msd.c:153:25 + 1107b8: 02 45 if (r2 == 0) goto 0xa ## msd.c:153:25 + 1107ba: a9 80 r1 = sp + 32 + 1107bc: 50 16 r0 = r5 ## msd_upgrade.c:134:26 + 1107be: c2 00 call r2 ## msd_upgrade.c:134:26 + 1107c0: 80 f8 bf 00 if (r0 != 0x0) goto 0x17e ## msd_upgrade.c:134:26 + 1107c4: 58 4f r0 = b[r5+0xf] (u) ## msd_upgrade.c:138:18 + 1107c6: 10 f8 24 fa if (r0 == 0xfd) goto 0x48 ## msd_upgrade.c:138:5 + 1107ca: 90 f8 4c f6 if (r0 != 0xfb) goto 0x98 + 1107ce: 50 ee 50 01 r0 = b[r5+0x10] (u) ## msd_upgrade.c:142:22 + 1107d2: 00 f8 87 10 if (r0 == 0x8) goto 0x10e ## msd_upgrade.c:142:9 + 1107d6: 80 f8 7f 0c if (r0 != 0x6) goto 0xfe + 1107da: 58 91 r0 = r5 + 0x11 + 1107dc: 09 43 r1 = b[r0+0x3] (u) ## msd_upgrade.c:43:5 + 1107de: 0a 42 r2 = b[r0+0x2] (u) ## msd_upgrade.c:43:5 + 1107e0: a2 f1 20 14 r2 <= insert(r1, p:0x8, l:0x8) # ## msd_upgrade.c:43:5 + 1107e4: 0b 41 r3 = b[r0+0x1] (u) ## msd_upgrade.c:43:5 + 1107e6: 08 40 r0 = b[r0+0x0] (u) ## msd_upgrade.c:43:5 + 1107e8: a0 e1 20 34 r0 <= insert(r3, p:0x8, l:0x8) ## msd_upgrade.c:43:5 + 1107ec: a0 e1 40 28 r0 <= insert(r2, p:0x10, l:0x10) ## msd_upgrade.c:43:5 + 1107f0: 70 e0 00 40 r4 = rev8(r0) ## msd_upgrade.c:46:12 + 1107f4: bf ea 94 fe call -0x2d8 ## msd_upgrade.c:82:11 + 1107f8: 07 16 r7 = r0 ## msd_upgrade.c:82:11 + 1107fa: 40 16 r0 = r4 ## msd_upgrade.c:85:5 + 1107fc: 71 16 r1 = r7 ## msd_upgrade.c:85:5 + 1107fe: bf ea 99 fe call -0x2ce ## msd_upgrade.c:85:5 + 110802: f1 17 r1 = r7.l (u) ## msd_upgrade.c:86:5 + 110804: 57 35 r7 = 0x55 ## msd_upgrade.c:86:5 + 110806: 40 16 r0 = r4 ## msd_upgrade.c:86:5 + 110808: 80 ea 96 06 call 0xd2c ## msd_upgrade.c:86:5 + 11080c: d0 ec a1 d0 [r10+0x0] = r13 ## msd_upgrade.c:145:27 + 110810: 44 98 goto 0x130 ## msd_upgrade.c:145:27 + 110812: 50 ee 50 01 r0 = b[r5+0x10] (u) ## msd_upgrade.c:157:22 + 110816: 80 f8 5f 0e if (r0 != 0x7) goto 0xbe ## msd_upgrade.c:157:22 + 11081a: 58 91 r0 = r5 + 0x11 + 11081c: 09 43 r1 = b[r0+0x3] (u) ## msd_upgrade.c:43:5 + 11081e: 0a 42 r2 = b[r0+0x2] (u) ## msd_upgrade.c:43:5 + 110820: a2 f1 20 14 r2 <= insert(r1, p:0x8, l:0x8) # ## msd_upgrade.c:43:5 + 110824: 0b 41 r3 = b[r0+0x1] (u) ## msd_upgrade.c:43:5 + 110826: 08 40 r0 = b[r0+0x0] (u) ## msd_upgrade.c:43:5 + 110828: a0 e1 20 34 r0 <= insert(r3, p:0x8, l:0x8) ## msd_upgrade.c:43:5 + 11082c: a0 e1 40 28 r0 <= insert(r2, p:0x10, l:0x10) ## msd_upgrade.c:43:5 + 110830: 70 e0 00 40 r4 = rev8(r0) ## msd_upgrade.c:46:12 + 110834: bf ea 74 fe call -0x318 ## msd_upgrade.c:94:11 + 110838: 07 16 r7 = r0 ## msd_upgrade.c:94:11 + 11083a: 8f 16 r15 = r8 + 11083c: c8 16 r8 = r12 + 11083e: bc e1 40 70 r12 = uextra(r7, p:0x0, l:0x10) ## msd_upgrade.c:96:5 + 110842: 40 16 r0 = r4 ## msd_upgrade.c:96:5 + 110844: c1 16 r1 = r12 ## msd_upgrade.c:96:5 + 110846: 80 ea 77 06 call 0xcee ## msd_upgrade.c:96:5 + 11084a: 40 16 r0 = r4 ## msd_upgrade.c:97:5 + 11084c: 71 16 r1 = r7 ## msd_upgrade.c:97:5 + 11084e: 57 35 r7 = 0x55 ## msd_upgrade.c:97:5 + 110850: bf ea 98 fe call -0x2d0 ## msd_upgrade.c:97:5 + 110854: 40 16 r0 = r4 ## msd_upgrade.c:98:5 + 110856: c1 16 r1 = r12 ## msd_upgrade.c:98:5 + 110858: 8c 16 r12 = r8 ## msd_upgrade.c:98:5 + 11085a: f8 16 r8 = r15 ## msd_upgrade.c:98:5 + 11085c: 4f e0 42 00 r15 = 0x42 ## msd_upgrade.c:98:5 + 110860: 80 ea 6a 06 call 0xcd4 ## msd_upgrade.c:98:5 + 110864: 34 8e goto 0xdc ## msd_upgrade.c:98:5 + 110866: 30 59 if (r0 == 0) goto 0xf2 ## msd.c:283:9 + 110868: 00 f8 7d 06 if (r0 == 0x3) goto 0xfa + 11086c: 00 f8 b3 5e if (r0 == 0x2f) goto 0x166 + 110870: 00 f8 ab 34 if (r0 == 0x1a) goto 0x156 + 110874: 00 f8 ba 3c if (r0 == 0x1e) goto 0x174 + 110878: 00 f8 66 46 if (r0 == 0x23) goto 0xcc + 11087c: 00 f8 64 4a if (r0 == 0x25) goto 0xc8 + 110880: 00 f8 62 50 if (r0 == 0x28) goto 0xc4 + 110884: 80 f8 28 24 if (r0 != 0x12) goto 0x50 + 110888: 68 4b r0 = b[r6+0xb] (u) ## msd.c:159:15 + 11088a: 69 4a r1 = b[r6+0xa] (u) ## msd.c:159:15 + 11088c: a1 f1 20 04 r1 <= insert(r0, p:0x8, l:0x8) # ## msd.c:159:15 + 110890: 6a 49 r2 = b[r6+0x9] (u) ## msd.c:159:15 + 110892: 6c 48 r4 = b[r6+0x8] (u) ## msd.c:159:15 + 110894: a4 e1 20 24 r4 <= insert(r2, p:0x8, l:0x8) ## msd.c:159:15 + 110898: a4 e1 40 18 r4 <= insert(r1, p:0x10, l:0x10) ## msd.c:159:15 + 11089c: 34 e9 24 00 if (r4 >= 0x24) { ## msd.c:159:15 + 1108a0: 4c 24 r4 = 0x24 + } ## msd.c:159:15 + 1108a2: c0 ff 57 0f 11 00 r0 = 0x110f57 ## msd.c:161:5 + 1108a8: 41 16 r1 = r4 ## msd.c:161:5 + 1108aa: bf ea 6b fe call -0x32a ## msd.c:161:5 + 1108ae: 68 4b r0 = b[r6+0xb] (u) ## msd.c:162:25 + 1108b0: 69 4a r1 = b[r6+0xa] (u) ## msd.c:162:25 + 1108b2: a1 f1 20 04 r1 <= insert(r0, p:0x8, l:0x8) # ## msd.c:162:25 + 1108b6: 6a 49 r2 = b[r6+0x9] (u) ## msd.c:162:25 + 1108b8: 6b 48 r3 = b[r6+0x8] (u) ## msd.c:162:25 + 1108ba: a3 e1 20 24 r3 <= insert(r2, p:0x8, l:0x8) ## msd.c:162:25 + 1108be: a3 e1 40 18 r3 <= insert(r1, p:0x10, l:0x10) ## msd.c:162:25 + 1108c2: 30 1f r0 = r3 - r4 ## msd.c:162:25 + 1108c4: e8 48 b[r6+0x8] = r0 ## msd.c:162:25 + 1108c6: 81 b8 r1 = r0 >> 0x18 ## msd.c:162:25 + 1108c8: e9 4b b[r6+0xb] = r1 ## msd.c:162:25 + 1108ca: 81 b0 r1 = r0 >> 0x10 ## msd.c:162:25 + 1108cc: e9 4a b[r6+0xa] = r1 ## msd.c:162:25 + 1108ce: 80 a8 r0 = r0 >> 0x8 ## msd.c:162:25 + 1108d0: e8 49 b[r6+0x9] = r0 ## msd.c:162:25 + 1108d2: 52 ee 6c d0 b[r6+0xc] = r13 ## msd.c:163:20 + 1108d6: 54 8e goto 0x15c ## msd.c:163:20 + 1108d8: 58 4c r0 = b[r5+0xc] (u) ## msd.c:308:26 + 1108da: 80 a7 r0 = r0 >> 0x7 ## msd.c:308:20 + 1108dc: 38 20 r0 ^= 0x1 ## msd.c:308:20 + 1108de: bf ea 8c fe call -0x2e8 ## msd.c:308:13 + 1108e2: 54 88 goto 0x150 ## msd.c:308:13 + 1108e4: 58 91 r0 = r5 + 0x11 + 1108e6: 50 ee 01 f0 r15 = b[r0+0x1] (u) ## msd_upgrade.c:43:5 + 1108ea: 0b 40 r3 = b[r0+0x0] (u) ## msd_upgrade.c:43:5 + 1108ec: 0c 43 r4 = b[r0+0x3] (u) ## msd_upgrade.c:43:5 + 1108ee: 0f 42 r7 = b[r0+0x2] (u) ## msd_upgrade.c:43:5 + 1108f0: bf ea 16 fe call -0x3d4 ## msd_upgrade.c:108:15 + 1108f4: c2 ff 84 13 01 00 r2 = 0x11384 + 1108fa: c1 ff 84 05 11 00 r1 = 0x110584 ## msd_upgrade.c:109:26 + 110900: a7 f1 20 44 r7 <= insert(r4, p:0x8, l:0x8) # ## msd_upgrade.c:43:5 + 110904: a1 60 [r2+0x0] = r1 ## msd_upgrade.c:109:26 + 110906: c1 ff 34 05 11 00 r1 = 0x110534 ## msd_upgrade.c:110:26 + 11090c: a3 f1 20 f4 r3 <= insert(r15, p:0x8, l:0x8) # ## msd_upgrade.c:43:5 + 110910: a1 61 [r2+0x4] = r1 ## msd_upgrade.c:110:26 + 110912: d0 ec 29 a0 [r2+0x8] = r10 ## msd_upgrade.c:111:20 + 110916: 4f f0 42 00 r15 = 0x42 # ## msd_upgrade.c:111:20 + 11091a: a0 63 [r2+0xc] = r0 ## msd_upgrade.c:112:21 + 11091c: d0 ec 21 d1 [r2+0x10] = r13 ## msd_upgrade.c:113:23 + 110920: a3 e1 40 78 r3 <= insert(r7, p:0x10, l:0x10) ## msd_upgrade.c:43:5 + 110924: 57 35 r7 = 0x55 + 110926: 70 e0 00 13 r1 = rev8(r3) ## msd_upgrade.c:46:12 + 11092a: 20 16 r0 = r2 ## msd_upgrade.c:118:5 + 11092c: c1 00 call r1 ## msd_upgrade.c:118:5 + 11092e: 78 3b r0 = 0xfb ## msd_upgrade.c:120:12 + 110930: de e9 20 00 b[sp+32] = r0 ## msd_upgrade.c:120:12 + 110934: 00 22 r0 = [sp+8] ## msd_upgrade.c:121:12 + 110936: 41 28 r1 = 0x8 ## msd_upgrade.c:121:12 + 110938: 89 41 b[r0+0x1] = r1 ## msd_upgrade.c:121:12 + 11093a: a8 80 r0 = sp + 32 ## msd_upgrade.c:121:12 + 11093c: 41 30 r1 = 0x10 ## msd_upgrade.c:123:5 + 11093e: bf ea 21 fe call -0x3be ## msd_upgrade.c:123:5 + 110942: 52 ee e0 d0 b[r14+0x0] = r13 ## msd.c:280:27 + 110946: 44 93 goto 0x126 <.GJTIE61_0_0_+0x24 : 110a6e > ## msd.c:280:27 + 110948: 40 20 r0 = 0x0 ## msd.c:212:5 + 11094a: bf ea 56 fe call -0x354 ## msd.c:212:5 + 11094e: 40 25 r0 = 0x5 ## msd.c:213:23 + 110950: 52 ee e0 00 b[r14+0x0] = r0 ## msd.c:213:23 + 110954: 40 21 r0 = 0x1 ## msd.c:214:20 + 110956: e8 4c b[r6+0xc] = r0 ## msd.c:214:20 + 110958: 34 8d goto 0xda ## msd.c:214:20 + 11095a: 40 21 r0 = 0x1 ## msd.c:218:20 + 11095c: e8 4c b[r6+0xc] = r0 ## msd.c:218:20 + 11095e: 40 25 r0 = 0x5 ## msd.c:219:23 + 110960: 52 ee e0 00 b[r14+0x0] = r0 ## msd.c:219:23 + 110964: 44 8b goto 0x116 <.GJTIE61_0_0_+0x32 : 110a7c > ## msd.c:219:23 + 110966: 59 4b r1 = b[r5+0xb] (u) ## msd.c:234:11 + 110968: 5a 4a r2 = b[r5+0xa] (u) ## msd.c:234:11 + 11096a: a2 f1 20 14 r2 <= insert(r1, p:0x8, l:0x8) # ## msd.c:234:11 + 11096e: 5b 49 r3 = b[r5+0x9] (u) ## msd.c:234:11 + 110970: 58 48 r0 = b[r5+0x8] (u) ## msd.c:234:11 + 110972: a0 e1 20 34 r0 <= insert(r3, p:0x8, l:0x8) ## msd.c:234:11 + 110976: a0 e1 40 28 r0 <= insert(r2, p:0x10, l:0x10) ## msd.c:234:11 + 11097a: 04 16 r4 = r0 ## msd.c:234:11 + 11097c: 30 e9 12 00 if (r0 >= 0x12) { ## msd.c:234:11 + 110980: 44 32 r4 = 0x12 + } ## msd.c:234:11 + 110982: 20 48 if (r0 == 0) goto 0x90 + 110984: 41 20 r1 = 0x0 ## msd.c:242:9 + 110986: 42 31 r2 = 0x11 ## msd.c:242:9 + 110988: 47 20 r7 = 0x0 ## msd.c:242:9 + 11098a: 00 20 r0 = [sp] ## msd.c:242:9 + 11098c: bf ea c8 fb call -0x870 ## msd.c:242:9 + 110990: 50 ee c0 00 r0 = b[r12+0x0] (u) ## msd.c:243:36 + 110994: 50 ee 80 10 r1 = b[r8+0x0] (u) ## msd.c:244:37 + 110998: 02 21 r2 = [sp+4] ## msd.c:244:37 + 11099a: a8 42 b[r2+0x2] = r0 ## msd.c:243:23 + 11099c: 41 d6 r1 = r4 # ## msd.c:250:9 + 11099e: a9 4c b[r2+0xc] = r1 ## msd.c:244:24 + 1109a0: af 4d b[r2+0xd] = r7 ## msd.c:245:24 + 1109a2: 58 30 r0 = 0x70 ## msd.c:246:23 + 1109a4: de e9 0e 00 b[sp+14] = r0 ## msd.c:246:23 + 1109a8: 40 2a r0 = 0xa ## msd.c:247:23 + 1109aa: a8 47 b[r2+0x7] = r0 ## msd.c:247:23 + 1109ac: 88 8e r0 = sp + 14 ## msd.c:247:23 + 1109ae: bf ea e9 fd call -0x42e ## msd.c:250:9 + 1109b2: 68 4b r0 = b[r6+0xb] (u) ## msd.c:253:25 + 1109b4: 69 4a r1 = b[r6+0xa] (u) ## msd.c:253:25 + 1109b6: a1 f1 20 04 r1 <= insert(r0, p:0x8, l:0x8) # ## msd.c:253:25 + 1109ba: 6a 49 r2 = b[r6+0x9] (u) ## msd.c:253:25 + 1109bc: 6b 48 r3 = b[r6+0x8] (u) ## msd.c:253:25 + 1109be: a3 e1 20 24 r3 <= insert(r2, p:0x8, l:0x8) ## msd.c:253:25 + 1109c2: a3 e1 40 18 r3 <= insert(r1, p:0x10, l:0x10) ## msd.c:253:25 + 1109c6: 30 1f r0 = r3 - r4 ## msd.c:253:25 + 1109c8: 14 8c goto 0x58 ## msd.c:253:25 + 1109ca: 41 24 r1 = 0x4 ## msd.c:261:5 + 1109cc: c0 ff 7b 0f 11 00 r0 = 0x110f7b ## msd.c:261:5 + 1109d2: bf ea d7 fd call -0x452 ## msd.c:261:5 + 1109d6: 52 ee 6b d0 b[r6+0xb] = r13 + 1109da: 52 ee 6a d0 b[r6+0xa] = r13 + 1109de: 52 ee 69 d0 b[r6+0x9] = r13 + 1109e2: 52 ee 68 d0 b[r6+0x8] = r13 + 1109e6: 52 ee 6c d0 b[r6+0xc] = r13 + 1109ea: 14 84 goto 0x48 + 1109ec: 52 ee 6c d0 b[r6+0xc] = r13 ## msd.c:223:20 + 1109f0: 50 ee 53 01 r0 = b[r5+0x13] (u) ## msd.c:224:9 + 1109f4: b0 e8 00 c0 if (r0 != 0x0) { ## msd.c:224:9 + 1109f8: 40 22 r0 = 0x2 ## msd.c:225:27 + 1109fa: 52 ee e0 00 b[r14+0x0] = r0 ## msd.c:225:27 + 1109fe: 40 21 r0 = 0x1 ## msd.c:226:24 + 110a00: e8 4c b[r6+0xc] = r0 + } ## msd.c:226:24 + 110a02: 52 ee 6b d0 b[r6+0xb] = r13 ## msd.c:228:25 + 110a06: 52 ee 6a d0 b[r6+0xa] = r13 ## msd.c:228:25 + 110a0a: 52 ee 69 d0 b[r6+0x9] = r13 ## msd.c:228:25 + 110a0e: 52 ee 68 d0 b[r6+0x8] = r13 ## msd.c:228:25 + 110a12: 04 90 goto 0x20 ## msd.c:228:25 + 110a14: bf ea e9 fd call -0x42e ## msd.c:236:9 + 110a18: 40 22 r0 = 0x2 ## msd.c:237:27 + 110a1a: 52 ee e0 00 b[r14+0x0] = r0 ## msd.c:237:27 + 110a1e: 47 21 r7 = 0x1 ## msd.c:237:27 + 110a20: 40 20 r0 = 0x0 ## msd.c:237:27 + 110a22: e8 48 b[r6+0x8] = r0 + 110a24: 81 b8 r1 = r0 >> 0x18 + 110a26: e9 4b b[r6+0xb] = r1 + 110a28: 81 b0 r1 = r0 >> 0x10 + 110a2a: e9 4a b[r6+0xa] = r1 + 110a2c: 80 a8 r0 = r0 >> 0x8 + 110a2e: e8 49 b[r6+0x9] = r0 + 110a30: ef 4c b[r6+0xc] = r7 + 110a32: 57 35 r7 = 0x55 + 110a34: 50 ee e0 20 r2 = b[r14+0x0] (u) ## msd.c:312:24 + 110a38: 02 fc 1e 0c if (r2 > 0x6) goto 0x3c <.GJTIE61_0_0_+0x2E : 110a78 > ## msd.c:312:24 + 110a3c: 48 24 r0 = 0x24 + 110a3e: 41 25 r1 = 0x5 + 110a40: 02 01 tbb [r2] + + +.GJTIS61_0_0_: + 110a42: 16 < 22 : 0x16 > + 110a43: 04 < 4 : 0x4 > + 110a44: 11 < 17 : 0x11 > + 110a45: 04 < 4 : 0x4 > + 110a46: 04 < 4 : 0x4 > + 110a47: 1d < 29 : 0x1D > + 110a48: 18 < 24 : 0x18 > + 110a49: 00 < 0 : 0x0 > + 110a4a: 04 80 goto 0x0 <.GJTIE61_0_0_+0x2 : 110a4c > + 110a4c: 52 ee 63 b0 b[r6+0x3] = r11 ## msd.c:167:23 + 110a50: 52 ee 62 f0 b[r6+0x2] = r15 ## msd.c:167:23 + 110a54: 52 ee 61 b0 b[r6+0x1] = r11 ## msd.c:167:23 + 110a58: 60 d6 r0 = r6 # ## msd.c:168:5 + 110a5a: ef 40 b[r6+0x0] = r7 ## msd.c:167:23 + 110a5c: 41 2d r1 = 0xd ## msd.c:168:5 + 110a5e: bf ea 91 fd call -0x4de ## msd.c:168:5 + 110a62: 37 92 goto -0x31c ## msd.c:168:5 + 110a64: 52 ee c0 10 b[r12+0x0] = r1 + 110a68: 52 ee 80 00 b[r8+0x0] = r0 + 110a6c: f7 8f goto -0x22 <.GJTIE61_0_0_+0x2 : 110a4c > + 110a6e: 80 14 r1_r0 = 0 + 110a70: f7 99 goto -0xe <.GJTIE61_0_0_+0x1A : 110a64 > + 110a72: 48 20 r0 = 0x20 + 110a74: 41 2b r1 = 0xb + 110a76: f7 96 goto -0x14 <.GJTIE61_0_0_+0x1A : 110a64 > + 110a78: 82 f8 e8 1f if (r2 != 0xf) goto -0x30 <.GJTIE61_0_0_+0x2 : 110a4c > + 110a7c: 48 3a r0 = 0x3a + 110a7e: 41 22 r1 = 0x2 + 110a80: f7 91 goto -0x1e <.GJTIE61_0_0_+0x1A : 110a64 > + + +usb_g_ep_config: + 110a82: 75 04 [--sp] = {rets, r5, r4} ## usb_phy.c:456:0 + 110a84: 04 16 r4 = r0 ## usb_phy.c:456:0 + 110a86: c0 ff 98 13 01 00 r0 = 0x11398 ## usb_phy.c:456:0 + 110a8c: c2 ff 1c 18 1e 00 r2 = 0x1e181c <__stub_doe+0xCF020 : 1e181c > ## usb_phy.c:456:0 + 110a92: 54 e8 0f 3a if ((r4 & 0x80) != 0) goto 0x1e ## usb_phy.c:456:0 + 110a96: 14 41 if (r4 == 0) goto 0x42 ## usb_phy.c:456:0 + 110a98: 30 e1 ff 4f r0 = r4 + -0x1 ## usb_phy.c:326:22 + 110a9c: 02 a3 r2 = r0 << 0x3 ## usb_phy.c:326:11 + 110a9e: c3 ff 09 86 07 00 r3 = 0x78609 <_IRQ_MEM_ADDR+0x4C708 : 78608 > ## usb_phy.c:326:11 + 110aa4: d8 ec 2b 13 [r2+r3<<2] = r1 ## usb_phy.c:327:12 + 110aa8: c2 ff ac 13 01 00 r2 = 0x113ac ## usb_phy.c:328:5 + 110aae: d8 ec 2b 10 [r2+r0<<2] = r1 ## usb_phy.c:328:22 + 110ab2: 04 95 goto 0x2a + 110ab4: 65 e1 0f 40 r5 = r4 & 0xF ## usb_phy.c:459:12 + 110ab8: 60 ff 0f 40 22 00 if ((r4 & 0xF) == 0) goto 0x44 + 110abe: 30 e1 ff 5f r0 = r5 + -0x1 ## usb_phy.c:307:22 + 110ac2: 02 a3 r2 = r0 << 0x3 ## usb_phy.c:307:11 + 110ac4: c3 ff 08 86 07 00 r3 = 0x78608 <_IRQ_MEM_ADDR+0x4C708 : 78608 > ## usb_phy.c:307:11 + 110aca: d8 ec 2b 13 [r2+r3<<2] = r1 ## usb_phy.c:308:12 + 110ace: c2 ff 9c 13 01 00 r2 = 0x1139c ## usb_phy.c:309:5 + 110ad4: d8 ec 2b 10 [r2+r0<<2] = r1 ## usb_phy.c:309:22 + 110ad8: 04 96 goto 0x2c ## usb_phy.c:309:22 + 110ada: a1 60 [r2+0x0] = r1 ## usb_phy.c:321:25 + 110adc: 81 60 [r0+0x0] = r1 ## usb_phy.c:322:18 + 110ade: bf ea 3d fc call -0x786 ## usb_phy.c:262:5 + 110ae2: 40 17 r0 = r4.b0 (u) ## usb_phy.c:263:5 + 110ae4: bf ea b7 fc call -0x692 ## usb_phy.c:263:5 + 110ae8: 40 33 r0 = 0x13 ## usb_phy.c:264:5 + 110aea: 79 3f r1 = 0xff ## usb_phy.c:264:5 + 110aec: bf ea 56 fc call -0x754 ## usb_phy.c:264:5 + 110af0: bf ea 3b fc call -0x78a ## usb_phy.c:265:5 + 110af4: 61 30 r1 = 0x90 ## usb_phy.c:476:9 + 110af6: 40 16 r0 = r4 ## usb_phy.c:476:9 + 110af8: bf ea c0 fc call -0x680 ## usb_phy.c:476:9 + 110afc: 40 16 r0 = r4 ## usb_phy.c:483:13 + 110afe: 35 04 {rets, r5, r4} = [sp++] ## usb_phy.c:483:13 + 110b00: 36 8c goto -0x728 ## usb_phy.c:483:13 + 110b02: a1 60 [r2+0x0] = r1 ## usb_phy.c:302:25 + 110b04: 81 60 [r0+0x0] = r1 ## usb_phy.c:303:18 + 110b06: bf ea 29 fc call -0x7ae ## usb_phy.c:269:5 + 110b0a: 50 16 r0 = r5 ## usb_phy.c:270:5 + 110b0c: bf ea a3 fc call -0x6ba ## usb_phy.c:270:5 + 110b10: 40 30 r0 = 0x10 ## usb_phy.c:271:5 + 110b12: 79 3f r1 = 0xff ## usb_phy.c:271:5 + 110b14: bf ea 42 fc call -0x77c ## usb_phy.c:271:5 + 110b18: bf ea 27 fc call -0x7b2 ## usb_phy.c:272:5 + 110b1c: 51 28 r1 = 0x48 ## usb_phy.c:463:9 + 110b1e: 50 16 r0 = r5 ## usb_phy.c:463:9 + 110b20: bf ea 1c fd call -0x5c8 ## usb_phy.c:463:9 + 110b24: 50 16 r0 = r5 ## usb_phy.c:470:13 + 110b26: 35 04 {rets, r5, r4} = [sp++] ## usb_phy.c:470:13 + 110b28: 36 97 goto -0x712 ## usb_phy.c:470:13 + + +msd_itf_hander: + 110b2a: 76 04 [--sp] = {rets, r6-r4} ## msd.c:93:0 + 110b2c: c2 ff 80 13 01 00 r2 = 0x11380 ## msd_upgrade.c:127:19 + 110b32: 40 ea 00 20 [r2+0x0] = 0x0 ## msd_upgrade.c:127:19 + 110b36: 04 15 r5_r4 = r1_r0 ## msd_upgrade.c:127:19 + 110b38: c6 ff 80 10 01 00 r6 = 0x11080 ## msd.c:87:5 + 110b3e: 60 21 r0 = 0x81 ## msd.c:86:5 + 110b40: 61 16 r1 = r6 ## msd.c:86:5 + 110b42: 41 9f call -0xc2 ## msd.c:86:5 + 110b44: 01 e1 40 60 r1 = r6 + 0x40 ## msd.c:87:5 + 110b48: 40 21 r0 = 0x1 ## msd.c:87:5 + 110b4a: 41 9b call -0xca ## msd.c:87:5 + 110b4c: 58 40 r0 = b[r5+0x0] (u) ## msd.c:95:15 + 110b4e: 41 23 r1 = 0x3 ## msd.c:95:15 + 110b50: 10 f8 08 42 if (r0 == 0xa1) goto 0x10 ## msd.c:95:37 + 110b54: 80 f8 10 42 if (r0 != 0x21) goto 0x20 + 110b58: 58 41 r0 = b[r5+0x1] (u) ## msd.c:96:15 + 110b5a: 41 20 r1 = 0x0 ## msd.c:95:9 + 110b5c: b0 e8 ff 00 if (r0 != 0xff) { ## msd.c:95:9 + 110b60: 41 23 r1 = 0x3 + } ## msd.c:95:9 + 110b62: 04 8a goto 0x14 ## msd.c:95:9 + 110b64: 58 41 r0 = b[r5+0x1] (u) ## msd.c:101:22 + 110b66: 90 f8 07 fc if (r0 != 0xfe) goto 0xe ## msd.c:101:22 + 110b6a: 40 62 r0 = [r4+0x8] ## msd.c:104:21 + 110b6c: 41 20 r1 = 0x0 ## msd.c:104:37 + 110b6e: 89 40 b[r0+0x0] = r1 ## msd.c:104:37 + 110b70: 40 62 r0 = [r4+0x8] ## msd.c:105:45 + 110b72: c0 63 [r4+0xc] = r0 ## msd.c:105:31 + 110b74: 41 21 r1 = 0x1 ## msd.c:105:31 + 110b76: c9 61 h[r4+0x2] = r1 ## msd.c:106:33 + 110b78: 40 20 r0 = 0x0 ## msd.c:111:5 + 110b7a: c9 41 b[r4+0x1] = r1 ## msd.c:111:5 + 110b7c: 56 04 {pc, r6-r4} = [sp++] ## msd.c:111:5 + + +usb_read_csr0: + 110b7e: 10 04 [--sp] = rets ## usb_phy.c:98:0 + 110b80: bf ea ec fb call -0x828 ## usb_phy.c:99:5 + 110b84: 40 20 r0 = 0x0 ## usb_phy.c:100:5 + 110b86: bf ea 66 fc call -0x734 ## usb_phy.c:100:5 + 110b8a: 40 31 r0 = 0x11 ## usb_phy.c:101:16 + 110b8c: bf ea 14 fc call -0x7d8 ## usb_phy.c:101:16 + 110b90: 02 16 r2 = r0 ## usb_phy.c:101:16 + 110b92: bf ea ea fb call -0x82c ## usb_phy.c:102:5 + 110b96: 20 16 r0 = r2 ## usb_phy.c:103:5 + 110b98: 00 04 pc = [sp++] ## usb_phy.c:103:5 + + +usb_write_csr0: + 110b9a: 74 04 [--sp] = {rets, r4} ## usb_phy.c:107:0 + 110b9c: 04 16 r4 = r0 ## usb_phy.c:107:0 + 110b9e: bf ea dd fb call -0x846 ## usb_phy.c:108:5 + 110ba2: 40 20 r0 = 0x0 ## usb_phy.c:109:5 + 110ba4: bf ea 57 fc call -0x752 ## usb_phy.c:109:5 + 110ba8: 41 17 r1 = r4.b0 (u) ## usb_phy.c:110:5 + 110baa: 40 31 r0 = 0x11 ## usb_phy.c:110:5 + 110bac: bf ea f6 fb call -0x814 ## usb_phy.c:110:5 + 110bb0: 34 04 {rets, r4} = [sp++] ## usb_phy.c:111:5 + 110bb2: ff ea da fb goto -0x84c ## usb_phy.c:111:5 + + +usb_ep0_RxPktEnd: + 110bb6: 50 28 r0 = 0x48 ## usb_phy.c:125:0 + 110bb8: f7 90 goto -0x20 ## usb_phy.c:126:5 + + +usb_ep0_TxPktEnd: + 110bba: 40 2a r0 = 0xa ## usb_phy.c:120:0 + 110bbc: f7 8e goto -0x24 ## usb_phy.c:121:5 + + +ep0_stage_tx: + 110bbe: 75 04 [--sp] = {rets, r5, r4} ## usb_setup.c:15:0 + 110bc0: 61 9e call -0x44 ## usb_setup.c:17:11 + 110bc2: 50 e8 20 0a if ((r0 & 0x2) != 0) goto 0x40 + 110bc6: c5 ff d8 13 01 00 r5 = 0x113d8 + 110bcc: 5c 61 r4 = h[r5+0x2] (u) ## usb_setup.c:20:16 + 110bce: 04 58 if (r4 == 0) goto 0x30 ## usb_setup.c:20:16 + 110bd0: 34 e9 40 00 if (r4 >= 0x40) { + 110bd4: 54 20 r4 = 0x40 + } ## usb_setup.c:24:19 + 110bd6: c0 ff 98 13 01 00 r0 = 0x11398 ## usb_phy.c:136:20 + 110bdc: 42 d6 r2 = r4 # ## usb_phy.c:136:5 + 110bde: 00 60 r0 = [r0+0x0] ## usb_phy.c:136:20 + 110be0: 51 63 r1 = [r5+0xc] ## usb_setup.c:25:34 + 110be2: bf ea 3c fa call -0xb88 ## usb_phy.c:136:5 + 110be6: c0 ff 08 18 1e 00 r0 = 0x1e1808 <__stub_doe+0xCF00C : 1e1808 > ## usb_phy.c:137:21 + 110bec: 84 60 [r0+0x0] = r4 ## usb_phy.c:137:21 + 110bee: 68 e8 0c 54 [r5+0xc] += r4 ## usb_setup.c:26:30 + 110bf2: 58 61 r0 = h[r5+0x2] (u) ## usb_setup.c:27:32 + 110bf4: 00 1f r0 = r0 - r4 ## usb_setup.c:27:32 + 110bf6: d8 61 h[r5+0x2] = r0 ## usb_setup.c:27:32 + 110bf8: 59 46 r1 = b[r5+0x6] (u) ## usb_setup.c:28:50 + 110bfa: 81 46 if (r1 != 0) goto 0xc ## usb_setup.c:28:50 + 110bfc: 80 17 r0 = r0.l (u) ## usb_setup.c:28:13 + 110bfe: 80 44 if (r0 != 0) goto 0x8 ## usb_setup.c:28:13 + 110c00: 61 9c call -0x48 + 110c02: 40 20 r0 = 0x0 + 110c04: d8 41 b[r5+0x1] = r0 + 110c06: 55 04 {pc, r5, r4} = [sp++] ## usb_setup.c:35:1 + 110c08: 40 22 r0 = 0x2 ## usb_setup.c:29:13 + 110c0a: 35 04 {rets, r5, r4} = [sp++] ## usb_setup.c:29:13 + 110c0c: e7 86 goto -0x74 ## usb_setup.c:29:13 + + +usb_device_isr: + 110c0e: e9 04 [--sp] = {psr, rets, reti} ## usb_onchip.c:30:0 + 110c10: d8 e8 ff 3f [--sp] = {r13-r0} ## usb_phy.c:155:5 + 110c14: e2 9e sp += -0x8 ## usb_phy.c:155:5 + 110c16: bf ea a1 fb call -0x8be ## usb_phy.c:155:5 + 110c1a: 40 26 r0 = 0x6 ## usb_phy.c:156:17 + 110c1c: bf ea cc fb call -0x868 ## usb_phy.c:156:17 + 110c20: 40 22 r0 = 0x2 ## usb_phy.c:157:16 + 110c22: bf ea c9 fb call -0x86e ## usb_phy.c:157:16 + 110c26: 05 16 r5 = r0 ## usb_phy.c:157:16 + 110c28: 40 23 r0 = 0x3 ## usb_phy.c:157:46 + 110c2a: bf ea c5 fb call -0x876 ## usb_phy.c:157:46 + 110c2e: 06 16 r6 = r0 ## usb_phy.c:157:46 + 110c30: 40 24 r0 = 0x4 ## usb_phy.c:158:16 + 110c32: bf ea c1 fb call -0x87e ## usb_phy.c:158:16 + 110c36: 04 16 r4 = r0 ## usb_phy.c:158:16 + 110c38: 40 25 r0 = 0x5 ## usb_phy.c:158:46 + 110c3a: bf ea bd fb call -0x886 ## usb_phy.c:158:46 + 110c3e: 07 16 r7 = r0 ## usb_phy.c:158:46 + 110c40: bf ea 93 fb call -0x8da ## usb_phy.c:159:5 + 110c44: bf ea 8a fb call -0x8ec ## usb_phy.c:165:5 + 110c48: 40 2b r0 = 0xb ## usb_phy.c:166:18 + 110c4a: bf ea b5 fb call -0x896 ## usb_phy.c:166:18 + 110c4e: a5 e1 20 64 r5 <= insert(r6, p:0x8, l:0x8) ## usb_phy.c:157:44 + 110c52: 40 27 r0 = 0x7 ## usb_phy.c:167:17 + 110c54: bf ea b0 fb call -0x8a0 ## usb_phy.c:167:17 + 110c58: 06 16 r6 = r0 ## usb_phy.c:167:17 + 110c5a: 40 28 r0 = 0x8 ## usb_phy.c:167:48 + 110c5c: bf ea ac fb call -0x8a8 ## usb_phy.c:167:48 + 110c60: a6 e1 20 04 r6 <= insert(r0, p:0x8, l:0x8) ## usb_phy.c:167:46 + 110c64: d6 19 r6 &= r5 ## usb_onchip.c:39:13 + 110c66: a4 e1 20 74 r4 <= insert(r7, p:0x8, l:0x8) ## usb_phy.c:158:44 + 110c6a: 40 29 r0 = 0x9 ## usb_phy.c:168:17 + 110c6c: bf ea a4 fb call -0x8b8 ## usb_phy.c:168:17 + 110c70: 05 16 r5 = r0 ## usb_phy.c:168:17 + 110c72: 40 2a r0 = 0xa ## usb_phy.c:168:48 + 110c74: bf ea a0 fb call -0x8c0 ## usb_phy.c:168:48 + 110c78: a5 e1 20 04 r5 <= insert(r0, p:0x8, l:0x8) ## usb_phy.c:168:46 + 110c7c: bf ea 75 fb call -0x916 ## usb_phy.c:169:5 + 110c80: 60 ff 01 60 35 01 if ((r6 & 0x1) == 0) goto 0x26a <.GJTIE87_0_0_+0x18A : 110ef0 > ## usb_phy.c:169:5 + 110c86: c8 ff d8 13 01 00 r8 = 0x113d8 + 110c8c: 50 ee 80 10 r1 = b[r8+0x0] (u) ## usb_setup.c:220:20 + 110c90: 01 4a if (r1 == 0) goto 0x14 ## usb_setup.c:220:20 + 110c92: bf ea 63 fb call -0x93a ## usb_phy.c:224:5 + 110c96: 40 20 r0 = 0x0 ## usb_phy.c:225:5 + 110c98: 47 20 r7 = 0x0 ## usb_phy.c:225:5 + 110c9a: bf ea 7f fb call -0x902 ## usb_phy.c:225:5 + 110c9e: bf ea 64 fb call -0x938 ## usb_phy.c:226:5 + 110ca2: 52 ee 80 70 b[r8+0x0] = r7 ## usb_setup.c:222:26 + 110ca6: bf ea 6a ff call -0x12c ## usb_setup.c:224:11 + 110caa: 07 16 r7 = r0 ## usb_setup.c:224:11 + 110cac: 57 e8 0b 2a if ((r7 & 0x20) != 0) goto 0x16 + 110cb0: 57 e8 10 22 if ((r7 & 0x10) != 0) goto 0x20 + 110cb4: 50 ee 81 00 r0 = b[r8+0x1] (u) ## usb_setup.c:236:24 + 110cb8: 00 f8 5d 04 if (r0 == 0x2) goto 0xba <.GJTIE87_0_0_+0x10 : 110d76 > ## usb_setup.c:236:5 + 110cbc: 00 ff 01 00 15 01 if (r0 == 0x1) goto 0x22a <.GJTIE87_0_0_+0x186 : 110eec > + 110cc2: 00 4e if (r0 == 0) goto 0x1c + 110cc4: 84 95 goto 0x22a <.GJTIE87_0_0_+0x18A : 110ef0 > + 110cc6: 40 20 r0 = 0x0 ## usb_setup.c:226:9 + 110cc8: 47 20 r7 = 0x0 ## usb_setup.c:226:9 + 110cca: bf ea 66 ff call -0x134 ## usb_setup.c:226:9 + 110cce: 52 ee 81 70 b[r8+0x1] = r7 ## usb_setup.c:227:27 + 110cd2: 84 8e goto 0x21c <.GJTIE87_0_0_+0x18A : 110ef0 > ## usb_setup.c:227:27 + 110cd4: 60 20 r0 = 0x80 ## usb_setup.c:232:9 + 110cd6: bf ea 60 ff call -0x140 ## usb_setup.c:232:9 + 110cda: 40 20 r0 = 0x0 ## usb_setup.c:233:27 + 110cdc: 52 ee 81 00 b[r8+0x1] = r0 ## usb_setup.c:233:27 + 110ce0: 60 ff 01 70 05 01 if ((r7 & 0x1) == 0) goto 0x20a <.GJTIE87_0_0_+0x18A : 110ef0 > + 110ce6: c0 ff 98 13 01 00 r0 = 0x11398 ## usb_phy.c:149:25 + 110cec: 00 60 r0 = [r0+0x0] ## usb_phy.c:149:25 + 110cee: 09 47 r1 = b[r0+0x7] (u) ## usb_phy.c:149:5 + 110cf0: 0a 46 r2 = b[r0+0x6] (u) ## usb_phy.c:149:5 + 110cf2: a2 f1 20 14 r2 <= insert(r1, p:0x8, l:0x8) # ## usb_phy.c:149:5 + 110cf6: 0b 45 r3 = b[r0+0x5] (u) ## usb_phy.c:149:5 + 110cf8: 50 ee 04 b0 r11 = b[r0+0x4] (u) ## usb_phy.c:149:5 + 110cfc: ab f1 20 34 r11 <= insert(r3, p:0x8, l:0x8) # ## usb_phy.c:149:5 + 110d00: 09 43 r1 = b[r0+0x3] (u) ## usb_phy.c:149:5 + 110d02: ab f1 40 28 r11 <= insert(r2, p:0x10, l:0x10) # ## usb_phy.c:149:5 + 110d06: 0a 42 r2 = b[r0+0x2] (u) ## usb_phy.c:149:5 + 110d08: a2 f1 20 14 r2 <= insert(r1, p:0x8, l:0x8) # ## usb_phy.c:149:5 + 110d0c: 0b 41 r3 = b[r0+0x1] (u) ## usb_phy.c:149:5 + 110d0e: 50 ee 00 a0 r10 = b[r0+0x0] (u) ## usb_phy.c:149:5 + 110d12: aa e1 20 34 r10 <= insert(r3, p:0x8, l:0x8) ## usb_phy.c:149:5 + 110d16: aa e1 40 28 r10 <= insert(r2, p:0x10, l:0x10) ## usb_phy.c:149:5 + 110d1a: d0 e9 01 a0 d[sp] = r11_r10 ## usb_phy.c:149:5 + 110d1e: 40 21 r0 = 0x1 ## usb_phy.c:149:5 + 110d20: 52 ee 81 00 b[r8+0x1] = r0 ## usb_setup.c:187:23 + 110d24: c7 ff 40 11 01 00 r7 = 0x11140 ## usb_setup.c:187:23 + 110d2a: d0 ec 89 70 [r8+0x8] = r7 ## usb_setup.c:188:29 + 110d2e: a2 15 r3_r2 = r11_r10 ## usb_setup.c:190:5 + 110d30: d0 e1 00 29 r3_r2 >>= 0x10 ## usb_setup.c:190:5 + 110d34: ac 15 r13_r12 = r11_r10 ## usb_setup.c:190:5 + 110d36: 61 e1 1f a0 r1 = r10 & 0x1F ## usb_setup.c:190:5 + 110d3a: d0 e1 08 c8 r13_r12 >>= 0x8 ## usb_setup.c:190:5 + 110d3e: 01 f8 1d 04 if (r1 == 0x2) goto 0x3a <.GJTIE87_0_0_+0x16 : 110d7c > ## usb_setup.c:190:5 + 110d42: c9 ff bc 13 01 00 r9 = 0x113bc + 110d48: 01 f8 31 02 if (r1 == 0x1) goto 0x62 <.GJTIE87_0_0_+0x48 : 110dae > + 110d4c: 81 f8 c7 00 if (r1 != 0x0) goto 0x18e <.GJTIE87_0_0_+0x178 : 110ede > + 110d50: b0 e1 20 c0 r0 = uextra(r12, p:0x0, l:0x8) + 110d54: 00 fc 36 16 if (r0 > 0xb) goto 0x6c <.GJTIE87_0_0_+0x5E : 110dc4 > + 110d58: 00 01 tbb [r0] + + +.GJTIS87_0_0_: + 110d5a: 06 < 6 : 0x6 > + 110d5b: 74 < 116 : 0x74 > + 110d5c: 35 < 53 : 0x35 > + 110d5d: 35 < 53 : 0x35 > + 110d5e: 35 < 53 : 0x35 > + 110d5f: 53 < 83 : 0x53 > + 110d60: 56 < 86 : 0x56 > + 110d61: 35 < 53 : 0x35 > + 110d62: 67 < 103 : 0x67 > + 110d63: 72 < 114 : 0x72 > + 110d64: 35 < 53 : 0x35 > + 110d65: 74 < 116 : 0x74 > + 110d66: 40 21 r0 = 0x1 + 110d68: f8 40 b[r7+0x0] = r0 ## usb_setup.c:105:36 + 110d6a: 40 20 r0 = 0x0 ## usb_setup.c:106:36 + 110d6c: f8 41 b[r7+0x1] = r0 ## usb_setup.c:106:36 + 110d6e: 40 22 r0 = 0x2 ## usb_setup.c:107:32 + 110d70: 50 ed 83 00 h[r8+0x2] = r0 ## usb_setup.c:107:32 + 110d74: 54 94 goto 0x168 <.GJTIE87_0_0_+0x178 : 110ede > ## usb_setup.c:107:32 + 110d76: bf ea 1e ff call -0x1c4 ## usb_setup.c:38:5 + 110d7a: 14 8a goto 0x54 <.GJTIE87_0_0_+0x6A : 110dd0 > ## usb_setup.c:38:5 + 110d7c: 60 ff ff c0 2b 00 if ((r12 & 0xFF) == 0) goto 0x56 <.GJTIE87_0_0_+0x72 : 110dd8 > ## usb_setup.c:150:5 + 110d82: b1 e1 20 c0 r1 = uextra(r12, p:0x0, l:0x8) + 110d86: 01 f8 31 06 if (r1 == 0x3) goto 0x62 <.GJTIE87_0_0_+0x86 : 110dec > + 110d8a: 81 f8 2e 02 if (r1 != 0x1) goto 0x5c <.GJTIE87_0_0_+0x84 : 110dea > + 110d8e: 40 23 r0 = 0x3 + 110d90: 61 ff ff 20 2b 00 if ((r2 & 0xFF) != 0) goto 0x56 <.GJTIE87_0_0_+0x86 : 110dec > + 110d96: a2 15 r3_r2 = r11_r10 ## usb_phy.c:149:5 + 110d98: d0 e1 00 2a r3_r2 >>= 0x20 ## usb_phy.c:149:5 + 110d9c: 60 e1 03 b0 r0 = r11 & 0x3 ## usb_setup.c:149:34 + 110da0: 52 e8 58 3a if ((r2 & 0x80) != 0) goto 0xb0 <.GJTIE87_0_0_+0xEE : 110e54 > + 110da4: 61 20 r1 = 0x80 ## usb_setup.c:156:17 + 110da6: bf ea 69 fb call -0x92e ## usb_setup.c:156:17 + 110daa: 40 20 r0 = 0x0 + 110dac: 04 9f goto 0x3e <.GJTIE87_0_0_+0x86 : 110dec > + 110dae: b0 e1 20 b0 r0 = uextra(r11, p:0x0, l:0x8) ## usb_setup.c:127:19 + 110db2: 00 fc 07 0c if (r0 > 0x6) goto 0xe <.GJTIE87_0_0_+0x5E : 110dc4 > ## usb_setup.c:127:19 + 110db6: d8 ec 9a 20 r2 = [r9+r0<<2] ## usb_setup.c:130:9 + 110dba: 02 44 if (r2 == 0) goto 0x8 <.GJTIE87_0_0_+0x5E : 110dc4 > ## usb_setup.c:130:9 + 110dbc: 89 80 r1 = sp + 0 + 110dbe: 80 16 r0 = r8 ## usb_setup.c:131:10 + 110dc0: c2 00 call r2 ## usb_setup.c:131:10 + 110dc2: 20 45 if (r0 == 0) goto 0x8a <.GJTIE87_0_0_+0xE8 : 110e4e > ## usb_setup.c:131:10 + 110dc4: 40 23 r0 = 0x3 + 110dc6: 52 ee 81 00 b[r8+0x1] = r0 + 110dca: 58 20 r0 = 0x60 ## usb_phy.c:131:5 + 110dcc: bf ea e5 fe call -0x236 ## usb_phy.c:131:5 + 110dd0: 40 20 r0 = 0x0 + 110dd2: 52 ee 81 00 b[r8+0x1] = r0 + 110dd6: 44 8c goto 0x118 <.GJTIE87_0_0_+0x18A : 110ef0 > + 110dd8: 41 20 r1 = 0x0 ## usb_setup.c:164:36 + 110dda: f9 40 b[r7+0x0] = r1 ## usb_setup.c:164:36 + 110ddc: f9 41 b[r7+0x1] = r1 ## usb_setup.c:165:36 + 110dde: d0 ec 8d 70 [r8+0xc] = r7 ## usb_setup.c:166:30 + 110de2: 41 22 r1 = 0x2 ## usb_setup.c:167:32 + 110de4: 50 ed 83 10 h[r8+0x2] = r1 ## usb_setup.c:167:32 + 110de8: 04 81 goto 0x2 <.GJTIE87_0_0_+0x86 : 110dec > ## usb_setup.c:167:32 + 110dea: 40 23 r0 = 0x3 + 110dec: 52 ee 81 00 b[r8+0x1] = r0 + 110df0: 31 e1 ff 0f r1 = r0 + -0x1 ## usb_setup.c:203:9 + 110df4: 81 f9 73 04 if (r1 < 0x2) goto 0xe6 <.GJTIE87_0_0_+0x178 : 110ede > ## usb_setup.c:203:9 + 110df8: 10 47 if (r0 == 0) goto 0x4e <.GJTIE87_0_0_+0xE2 : 110e48 > + 110dfa: 00 f8 e6 07 if (r0 == 0x3) goto -0x34 <.GJTIE87_0_0_+0x64 : 110dca > + 110dfe: 34 92 goto 0xe4 <.GJTIE87_0_0_+0x17E : 110ee4 > + 110e00: 52 ee 80 20 b[r8+0x0] = r2 ## usb_setup.c:47:26 + 110e04: 04 9e goto 0x3c <.GJTIE87_0_0_+0xDC : 110e42 > ## usb_setup.c:47:26 + 110e06: a0 15 r1_r0 = r11_r10 ## usb_setup.c:64:17 + 110e08: d0 e1 08 09 r1_r0 >>= 0x18 ## usb_setup.c:64:17 + 110e0c: 00 17 r0 = r0.b0 (u) ## usb_setup.c:64:9 + 110e0e: 00 f8 26 06 if (r0 == 0x3) goto 0x4c <.GJTIE87_0_0_+0xF8 : 110e5e > ## usb_setup.c:64:9 + 110e12: 00 f8 31 04 if (r0 == 0x2) goto 0x62 <.GJTIE87_0_0_+0x112 : 110e78 > + 110e16: 80 f8 d5 03 if (r0 != 0x1) goto -0x56 <.GJTIE87_0_0_+0x5E : 110dc4 > + 110e1a: c1 ff 7f 0f 11 00 r1 = 0x110f7f ## descriptor.c:71:5 + 110e20: 42 32 r2 = 0x12 ## descriptor.c:71:5 + 110e22: 49 e0 12 00 r9 = 0x12 ## descriptor.c:71:5 + 110e26: 14 84 goto 0x48 <.GJTIE87_0_0_+0x10A : 110e70 > ## descriptor.c:71:5 + 110e28: 50 ee 85 00 r0 = b[r8+0x5] (u) ## usb_setup.c:57:49 + 110e2c: f8 40 b[r7+0x0] = r0 ## usb_setup.c:57:36 + 110e2e: d0 ec 8d 70 [r8+0xc] = r7 ## usb_setup.c:58:30 + 110e32: 40 21 r0 = 0x1 ## usb_setup.c:58:30 + 110e34: 50 ed 83 00 h[r8+0x2] = r0 ## usb_setup.c:59:32 + 110e38: 52 ee 81 00 b[r8+0x1] = r0 ## usb_setup.c:60:27 + 110e3c: 24 90 goto 0xa0 <.GJTIE87_0_0_+0x178 : 110ede > ## usb_setup.c:60:27 + 110e3e: 52 ee 85 20 b[r8+0x5] = r2 ## usb_setup.c:100:31 + 110e42: 40 20 r0 = 0x0 + 110e44: 52 ee 81 00 b[r8+0x1] = r0 + 110e48: bf ea b5 fe call -0x296 ## usb_setup.c:204:9 + 110e4c: 24 8b goto 0x96 <.GJTIE87_0_0_+0x17E : 110ee4 > ## usb_setup.c:204:9 + 110e4e: 50 ee 81 00 r0 = b[r8+0x1] (u) + 110e52: e7 8e goto -0x64 <.GJTIE87_0_0_+0x8A : 110df0 > + 110e54: 51 20 r1 = 0x40 ## usb_setup.c:154:17 + 110e56: bf ea 81 fb call -0x8fe ## usb_setup.c:154:17 + 110e5a: 40 20 r0 = 0x0 + 110e5c: e7 87 goto -0x72 <.GJTIE87_0_0_+0x86 : 110dec > + 110e5e: 60 ff ff 20 27 00 if ((r2 & 0xFF) == 0) goto 0x4e <.GJTIE87_0_0_+0x14C : 110eb2 > + 110e64: c1 ff 91 0f 11 00 r1 = 0x110f91 ## descriptor.c:79:5 + 110e6a: 42 3c r2 = 0x1c ## descriptor.c:79:5 + 110e6c: 49 e0 1c 00 r9 = 0x1c ## descriptor.c:79:5 + 110e70: 70 16 r0 = r7 + 110e72: bf ea f4 f8 call -0xe18 + 110e76: 14 83 goto 0x46 <.GJTIE87_0_0_+0x158 : 110ebe > + 110e78: c1 ff ad 0f 11 00 r1 = 0x110fad ## descriptor.c:85:5 + 110e7e: 42 29 r2 = 0x9 ## descriptor.c:85:5 + 110e80: 70 16 r0 = r7 ## descriptor.c:85:5 + 110e82: bf ea ec f8 call -0xe28 ## descriptor.c:85:5 + 110e86: 78 89 r0 = r7 + 0x9 ## descriptor.c:85:5 + 110e88: c1 ff 40 0f 11 00 r1 = 0x110f40 ## msd.c:119:5 + 110e8e: 42 37 r2 = 0x17 ## msd.c:119:5 + 110e90: bf ea e5 f8 call -0xe36 ## msd.c:119:5 + 110e94: 40 20 r0 = 0x0 ## msd.c:120:12 + 110e96: f8 4b b[r7+0xb] = r0 ## msd.c:120:12 + 110e98: c1 ff 2a 0b 11 00 r1 = 0x110b2a ## usb_setup.c:143:31 + 110e9e: d0 ec 91 10 [r9+0x0] = r1 ## usb_setup.c:143:31 + 110ea2: 49 e0 20 00 r9 = 0x20 ## usb_setup.c:143:31 + 110ea6: 52 ee 72 90 b[r7+0x2] = r9 ## descriptor.c:99:10 + 110eaa: f8 43 b[r7+0x3] = r0 ## descriptor.c:100:10 + 110eac: 40 21 r0 = 0x1 ## descriptor.c:101:10 + 110eae: f8 44 b[r7+0x4] = r0 ## descriptor.c:101:10 + 110eb0: 04 86 goto 0xc <.GJTIE87_0_0_+0x158 : 110ebe > ## descriptor.c:101:10 + 110eb2: c0 ff 04 03 09 04 r0 = 0x4090304 <__stub_doe+0x3F7DB08 : 4090304 > ## descriptor.c:75:5 + 110eb8: 49 f0 04 00 r9 = 0x4 # ## descriptor.c:75:5 + 110ebc: f0 60 [r7+0x0] = r0 ## descriptor.c:75:5 + 110ebe: d0 ec 8d 70 [r8+0xc] = r7 + 110ec2: d0 e1 00 ab r11_r10 >>= 0x30 ## usb_setup.c:190:5 + 110ec6: 90 16 r0 = r9 ## usb_setup.c:90:13 + 110ec8: 9a ec 00 00 if (r10 <= r0) { ## usb_setup.c:90:13 + 110ecc: a0 16 r0 = r10 + } ## usb_setup.c:90:13 + 110ece: 50 ed 83 00 h[r8+0x2] = r0 ## usb_setup.c:89:32 + 110ed2: 40 21 r0 = 0x1 ## usb_setup.c:90:36 + 110ed4: 9a ec 00 09 if (r10 <= r9) { ## usb_setup.c:90:36 + 110ed8: 40 20 r0 = 0x0 + } ## usb_setup.c:90:36 + 110eda: 52 ee 86 00 b[r8+0x6] = r0 ## usb_setup.c:90:36 + 110ede: 50 20 r0 = 0x40 ## usb_phy.c:116:5 + 110ee0: bf ea 5b fe call -0x34a ## usb_phy.c:116:5 + 110ee4: 50 ee 81 00 r0 = b[r8+0x1] (u) ## usb_setup.c:213:40 + 110ee8: 80 f8 02 02 if (r0 != 0x1) goto 0x4 <.GJTIE87_0_0_+0x18A : 110ef0 > ## usb_setup.c:213:40 + 110eec: bf ea 67 fe call -0x332 + 110ef0: c5 19 r5 &= r4 ## usb_onchip.c:40:13 + 110ef2: 44 21 r4 = 0x1 ## usb_onchip.c:40:13 + 110ef4: c7 ff ec 13 01 00 r7 = 0x113ec ## usb_onchip.c:40:13 + 110efa: 04 8a goto 0x14 <.GJTIE87_0_0_+0x1AA : 110f10 > ## usb_onchip.c:40:13 + 110efc: 94 e1 62 04 r0 = r6 & (1 << r4) ## usb_onchip.c:57:13 + 110f00: 00 46 if (r0 == 0) goto 0xc <.GJTIE87_0_0_+0x1A8 : 110f0e > ## usb_onchip.c:57:13 + 110f02: d8 ec 7a 14 r1 = [r7+r4<<2] ## usb_onchip.c:58:17 + 110f06: b1 e8 00 40 if (r1 != 0x0) { ## usb_onchip.c:58:17 + 110f0a: 40 16 r0 = r4 ## usb_onchip.c:59:17 + 110f0c: c1 00 call r1 + } ## usb_onchip.c:59:17 + 110f0e: c4 21 r4 += 0x1 ## usb_onchip.c:56:37 + 110f10: 84 f8 f4 0f if (r4 != 0x7) goto -0x18 <.GJTIE87_0_0_+0x196 : 110efc > ## usb_onchip.c:56:5 + 110f14: 44 21 r4 = 0x1 + 110f16: c6 ff 08 14 01 00 r6 = 0x11408 + 110f1c: 04 8a goto 0x14 <.GJTIE87_0_0_+0x1CC : 110f32 > + 110f1e: 94 e1 52 04 r0 = r5 & (1 << r4) ## usb_onchip.c:64:13 + 110f22: 00 46 if (r0 == 0) goto 0xc <.GJTIE87_0_0_+0x1CA : 110f30 > ## usb_onchip.c:64:13 + 110f24: d8 ec 6a 14 r1 = [r6+r4<<2] ## usb_onchip.c:65:17 + 110f28: b1 e8 00 40 if (r1 != 0x0) { ## usb_onchip.c:65:17 + 110f2c: 40 16 r0 = r4 ## usb_onchip.c:66:17 + 110f2e: c1 00 call r1 + } ## usb_onchip.c:66:17 + 110f30: c4 21 r4 += 0x1 ## usb_onchip.c:63:37 + 110f32: 84 f8 f4 0f if (r4 != 0x7) goto -0x18 <.GJTIE87_0_0_+0x1B8 : 110f1e > + 110f36: 02 82 sp += 0x8 + 110f38: d4 e8 ff 3f {r13-r0} = [sp++] ## usb_onchip.c:71:1 + 110f3c: a9 04 {psr, rets, reti} = [sp++] ## usb_onchip.c:71:1 + 110f3e: 81 00 rti ## usb_onchip.c:71:1 + + +sMassDescriptor: + 110f40: 09 04 00 00 02 08 06 50 .......P + 110f48: 00 07 05 81 02 40 00 01 .....@.. + 110f50: 07 05 01 02 40 00 01 . + + +SCSIInquiryData: + 110f57: 00 80 02 02 20 00 00 00 .... ... + 110f5f: 42 52 32 33 20 20 20 20 BR23 + 110f67: 55 42 4f 4f 54 31 2e 30 UBOOT1.0 + 110f6f: 30 20 20 20 20 20 20 20 0 + 110f77: 31 2e 30 30 1.00 + + +scsi_mode_sense: + 110f7b: 03 00 00 00 .... + + +sDeviceDescriptor: + 110f7f: 12 01 10 01 00 00 00 40 .......@ + 110f87: 4a 4c 42 23 00 03 01 02 JLB#.... + 110f8f: 00 01 ..B#.. + + +MANUFACTURE_STR: + 110f91: 1c 03 42 00 52 00 32 00 ..B.R.2. + 110f99: 33 00 55 00 42 00 4f 00 3.U.B.O. + 110fa1: 4f 00 54 00 31 00 2e 00 O.T.1... + 110fa9: 30 00 30 00 0.0. + + +sConfigDescriptor: + 110fad: 09 02 20 00 01 01 00 80 .. ..... + 110fb5: c8 .. .... + + +usb_code_end: + 110fb6: ed ff 20 0c 01 00 ssp = 0x10c20 ## startup.S:38:0 + 110fbc: 41 14 sp = ssp ## startup.S:39:0 + 110fbe: ec ff 20 10 01 00 usp = 0x11020 ## startup.S:40:0 + 110fc4: 80 14 r1_r0 = 0 ## startup.S:42:0 + 110fc6: 82 14 r3_r2 = 0 ## startup.S:43:0 + 110fc8: 84 14 r5_r4 = 0 ## startup.S:44:0 + 110fca: 86 14 r7_r6 = 0 ## startup.S:45:0 + 110fcc: 88 14 r9_r8 = 0 ## startup.S:46:0 + 110fce: 8a 14 r11_r10 = 0 ## startup.S:47:0 + 110fd0: 8c 14 r13_r12 = 0 ## startup.S:48:0 + 110fd2: 8e 14 r15_r14 = 0 ## startup.S:49:0 + 110fd4: 64 e0 80 05 psr = r0 ## startup.S:51:0 + 110fd8: 64 e0 80 01 rete = r0 ## startup.S:52:0 + 110fdc: 64 e0 80 02 retx = r0 ## startup.S:53:0 + 110fe0: 64 e0 80 03 rets = r0 ## startup.S:54:0 + 110fe4: 64 e0 80 00 reti = r0 ## startup.S:55:0 + 110fe8: 80 ea b1 09 call 0x1362 ## startup.S:56:0 + 110fec: e0 ff f4 0f 11 00 reti = 0x110ff4 ## startup.S:58:0 + 110ff2: 81 00 rti ## startup.S:59:0 + + +_user_mode: + 110ff4: 80 ea 6d 01 call 0x2da ## startup.S:63:0 + 110ff8: 40 20 r0 = 0x0 ## startup.S:65:0 + 110ffa: c1 ff 20 08 01 00 r1 = 0x10820 ## startup.S:66:0 + 111000: c2 ff 00 08 00 00 r2 = 0x800 ## startup.S:67:0 + 111006: a2 a2 r2 = r2 >> 0x2 ## startup.S:68:0 + 111008: 02 03 rep 0x2 r2 { ## startup.S:70:0 + 11100a: 90 05 [r1++=0x4] = r0 + } ## startup.S:71:0 + 11100c: 02 fc fc 01 if (r2 > 0x0) goto -0x8 <_user_mode+0x14 : 111008 > ## startup.S:72:0 + 111010: 40 20 r0 = 0x0 ## startup.S:75:0 + 111012: c1 ff 40 13 01 00 r1 = 0x11340 ## startup.S:76:0 + 111018: c2 ff e4 00 00 00 r2 = 0xe4 ## startup.S:77:0 + 11101e: a2 a2 r2 = r2 >> 0x2 ## startup.S:78:0 + 111020: 02 03 rep 0x2 r2 { ## startup.S:80:0 + 111022: 90 05 [r1++=0x4] = r0 + } ## startup.S:81:0 + 111024: 02 fc fc 01 if (r2 > 0x0) goto -0x8 <_user_mode+0x2C : 111020 > ## startup.S:82:0 + 111028: c0 ea 96 07 goto 0xf2c
## startup.S:85:0 + 11102c: 00 00 nop + 11102e: 00 00 nop + + +norflash_check_in.spi0_porta_config: + 111030: 00 00 00 00 .... + + +norflash_check_in.spi0_portb_config: + 111034: 08 00 00 00 00 00 00 00 ........ + 11103c: 00 00 00 00 73 79 73 00 ....sys. + 111044: 6f 73 63 00 osc. + + +ack_cmd: + 111048: 55 aa 01 20 22 75 61 72 U.. "uar + 111050: 74 00 73 70 69 20 70 6f t.spi po + 111058: 72 74 20 25 78 20 0a 00 + + +spi_flash_io_nor: + 111060: c4 be 02 00 00 00 00 00 ........ + 111068: 00 00 00 00 78 24 11 00 + + +nor_flash_boot_table: + 111070: 00 10 00 00 00 00 01 00 ........ + 111078: 00 00 08 00 00 00 10 00 ........ + 111080: 72 65 6c 65 61 73 65 20 release + 111088: 73 70 69 20 70 6f 72 74 spi port + 111090: 20 25 78 20 0a 00 00 00 %x .... + 111098: 28 6e 75 6c 6c 29 00 ( + + +CrcDecode.keylcode: + 11109f: c3 cf c0 e8 ce d2 b0 ae ........ + 1110a7: c4 e3 a3 ac d3 f1 c1 d6 ........ + 1110af: 00 ....... + + +p33_buf: + 1110b0: c1 ff 08 3e 1e 00 r1 = 0x1e3e08 <__stub_doe+0xD160C : 1e3e08 > ## p33.c:8:0 + 1110b6: 90 61 [r1+0x4] = r0 ## p33.c:9:21 + 1110b8: 00 ef 10 10 [r1+0x0] |= 0x10 ## p33.c:10:21 + 1110bc: 10 60 r0 = [r1+0x0] ## p33.c:12:20 + 1110be: 50 e8 fd 0b if ((r0 & 0x2) != 0) goto -0x6 ## p33.c:12:5 + 1110c2: 10 61 r0 = [r1+0x4] ## p33.c:13:20 + 1110c4: 00 17 r0 = r0.b0 (u) ## p33.c:13:5 + 1110c6: 80 00 rts ## p33.c:13:5 + + +p33_tx_1byte: + 1110c8: 74 04 [--sp] = {rets, r4} ## p33.c:44:0 + 1110ca: 12 16 r2 = r1 ## p33.c:44:0 + 1110cc: 03 16 r3 = r0 ## p33.c:44:0 + 1110ce: b9 17 r1 = r3.l (s) ## p33.c:44:0 + 1110d0: bf ea 44 f9 call -0xd78 ## p33.c:45:5 + 1110d4: c4 ff 08 3e 1e 00 r4 = 0x1e3e08 <__stub_doe+0xD160C : 1e3e08 > ## p33.c:45:5 + 1110da: 31 ed 00 50 ifs (r1 >= 0x0) { ## p33.c:45:5 + 1110de: c0 ef 80 4f [r4+0x0] &= 0xFFFFFEFF ## p33.c:45:5 + 1110e2: 40 21 r0 = 0x1 + } else { ## p33.c:45:5 + 1110e4: 40 e0 01 01 r0 = 0x101 + } ## p33.c:45:5 + 1110e8: 64 e8 00 40 [r4+0x0] |= r0 ## p33.c:45:5 + 1110ec: b0 e1 08 34 r0 = uextra(r3, p:0x8, l:0x2) ## p33.c:46:5 + 1110f0: 61 9f call -0x42 ## p33.c:46:5 + 1110f2: 70 e1 7f 3c r0 = r3 & 0xFFFF00FF ## p33.c:47:5 + 1110f6: 61 9c call -0x48 ## p33.c:47:5 + 1110f8: 20 16 r0 = r2 ## p33.c:48:5 + 1110fa: 61 9a call -0x4c ## p33.c:48:5 + 1110fc: 40 e0 fe fe r0 = -0x102 ## p33.c:49:5 + 111100: 64 e8 02 40 [r4+0x0] &= r0 ## p33.c:49:5 + 111104: 34 04 {rets, r4} = [sp++] ## p33.c:49:5 + 111106: ff ea 30 f9 goto -0xda0 ## p33.c:49:5 + + +exception_analyze: + 11110a: c1 ff c0 be 02 00 r1 = 0x2bec0 ## boot_init.c:38:0 + 111110: 11 60 r1 = [r1+0x0] ## boot_init.c:39:9 + 111112: b1 e8 00 00 if (r1 != 0x0) { ## boot_init.c:39:9 + 111116: c1 00 call r1 + } ## boot_init.c:40:9 + 111118: bf ea e1 f8 call -0xe3e ## boot_init.c:43:5 + + +p33_rx_1byte: + 11111c: 10 04 [--sp] = rets ## p33.c:53:0 + 11111e: 02 16 r2 = r0 ## p33.c:53:0 + 111120: a9 17 r1 = r2.l (s) ## p33.c:53:0 + 111122: bf ea 1b f9 call -0xdca ## p33.c:56:5 + 111126: c3 ff 08 3e 1e 00 r3 = 0x1e3e08 <__stub_doe+0xD160C : 1e3e08 > ## p33.c:56:5 + 11112c: 31 ed 00 50 ifs (r1 >= 0x0) { ## p33.c:56:5 + 111130: c0 ef 80 3f [r3+0x0] &= 0xFFFFFEFF ## p33.c:56:5 + 111134: 40 21 r0 = 0x1 + } else { ## p33.c:56:5 + 111136: 40 e0 01 01 r0 = 0x101 + } ## p33.c:56:5 + 11113a: 64 e8 00 30 [r3+0x0] |= r0 ## p33.c:56:5 + 11113e: a0 a8 r0 = r2 >> 0x8 ## p33.c:57:22 + 111140: 30 27 r0 |= 0x80 ## p33.c:57:13 + 111142: 60 e1 83 00 r0 = r0 & 0x83 ## p33.c:57:5 + 111146: 51 94 call -0x98 ## p33.c:57:5 + 111148: 70 e1 7f 2c r0 = r2 & 0xFFFF00FF ## p33.c:58:5 + 11114c: 51 91 call -0x9e ## p33.c:58:5 + 11114e: 50 3e r0 = 0x5e ## p33.c:59:12 + 111150: 51 8f call -0xa2 ## p33.c:59:12 + 111152: 41 e0 fe fe r1 = -0x102 ## p33.c:60:5 + 111156: 64 e8 02 31 [r3+0x0] &= r1 ## p33.c:60:5 + 11115a: 02 16 r2 = r0 ## p33.c:59:12 + 11115c: bf ea 05 f9 call -0xdf6 ## p33.c:60:5 + 111160: 20 16 r0 = r2 ## p33.c:61:5 + 111162: 00 04 pc = [sp++] ## p33.c:61:5 + + +HWI_Install: + 111164: 74 04 [--sp] = {rets, r4} ## irq.c:15:0 + 111166: c3 ff 00 bf 02 00 r3 = 0x2bf00 <_IRQ_MEM_ADDR : 2bf00 > ## irq.c:19:5 + 11116c: d8 ec 3b 10 [r3+r0<<2] = r1 ## irq.c:19:20 + 111170: 01 a2 r1 = r0 << 0x2 ## irq.c:17:41 + 111172: 61 e1 1c 10 r1 = r1 & 0x1C ## irq.c:17:41 + 111176: 43 2f r3 = 0xf ## irq.c:17:41 + 111178: 13 1a r3 <<= r1 ## irq.c:24:35 + 11117a: 80 a3 r0 = r0 >> 0x3 ## irq.c:16:36 + 11117c: c4 ff 00 f1 10 00 r4 = 0x10f100 <_IRQ_MEM_ADDR+0xE3200 : 10f100 > ## irq.c:28:27 + 111182: a4 e1 14 01 r4 <= insert(r0, p:0x2, l:0x5) ## irq.c:28:27 + 111186: bf ea e9 f8 call -0xe2e ## irq.c:22:5 + 11118a: 40 60 r0 = [r4+0x0] ## irq.c:28:27 + 11118c: 90 e1 03 03 r0 = r0 & ~r3 ## irq.c:28:46 + 111190: 22 a1 r2 = r2 << 0x1 ## irq.c:23:49 + 111192: 62 e1 0e 20 r2 = r2 & 0xE ## irq.c:23:49 + 111196: 32 20 r2 |= 0x1 ## irq.c:23:55 + 111198: c8 e1 20 11 r1 = r2 << r1 ## irq.c:25:39 + 11119c: 10 19 r0 |= r1 ## irq.c:28:58 + 11119e: c0 60 [r4+0x0] = r0 ## irq.c:28:24 + 1111a0: bf ea e3 f8 call -0xe3a ## irq.c:30:5 + 1111a4: 54 04 {pc, r4} = [sp++] ## irq.c:31:1 + + +p33_or_1byte: + 1111a6: 74 04 [--sp] = {rets, r4} ## p33.c:35:0 + 1111a8: 12 16 r2 = r1 ## p33.c:35:0 + 1111aa: 03 16 r3 = r0 ## p33.c:35:0 + 1111ac: b9 17 r1 = r3.l (s) ## p33.c:35:0 + 1111ae: bf ea d5 f8 call -0xe56 ## p33.c:36:5 + 1111b2: c4 ff 08 3e 1e 00 r4 = 0x1e3e08 <__stub_doe+0xD160C : 1e3e08 > ## p33.c:36:5 + 1111b8: 31 ed 00 50 ifs (r1 >= 0x0) { ## p33.c:36:5 + 1111bc: c0 ef 80 4f [r4+0x0] &= 0xFFFFFEFF ## p33.c:36:5 + 1111c0: 40 21 r0 = 0x1 + } else { ## p33.c:36:5 + 1111c2: 40 e0 01 01 r0 = 0x101 + } ## p33.c:36:5 + 1111c6: 64 e8 00 40 [r4+0x0] |= r0 ## p33.c:36:5 + 1111ca: b0 e1 08 34 r0 = uextra(r3, p:0x8, l:0x2) ## p33.c:37:13 + 1111ce: 30 25 r0 |= 0x20 ## p33.c:37:13 + 1111d0: bf ea 6e ff call -0x124 ## p33.c:37:5 + 1111d4: 70 e1 7f 3c r0 = r3 & 0xFFFF00FF ## p33.c:38:5 + 1111d8: bf ea 6a ff call -0x12c ## p33.c:38:5 + 1111dc: 20 16 r0 = r2 ## p33.c:39:5 + 1111de: bf ea 67 ff call -0x132 ## p33.c:39:5 + 1111e2: 40 e0 fe fe r0 = -0x102 ## p33.c:40:5 + 1111e6: 64 e8 02 40 [r4+0x0] &= r0 ## p33.c:40:5 + 1111ea: 34 04 {rets, r4} = [sp++] ## p33.c:40:5 + 1111ec: ff ea bd f8 goto -0xe86 ## p33.c:40:5 + + +p33_and_1byte: + 1111f0: 74 04 [--sp] = {rets, r4} ## p33.c:26:0 + 1111f2: 12 16 r2 = r1 ## p33.c:26:0 + 1111f4: 03 16 r3 = r0 ## p33.c:26:0 + 1111f6: b9 17 r1 = r3.l (s) ## p33.c:26:0 + 1111f8: bf ea b0 f8 call -0xea0 ## p33.c:27:5 + 1111fc: c4 ff 08 3e 1e 00 r4 = 0x1e3e08 <__stub_doe+0xD160C : 1e3e08 > ## p33.c:27:5 + 111202: 31 ed 00 50 ifs (r1 >= 0x0) { ## p33.c:27:5 + 111206: c0 ef 80 4f [r4+0x0] &= 0xFFFFFEFF ## p33.c:27:5 + 11120a: 40 21 r0 = 0x1 + } else { ## p33.c:27:5 + 11120c: 40 e0 01 01 r0 = 0x101 + } ## p33.c:27:5 + 111210: 64 e8 00 40 [r4+0x0] |= r0 ## p33.c:27:5 + 111214: b0 e1 08 34 r0 = uextra(r3, p:0x8, l:0x2) ## p33.c:28:13 + 111218: 30 26 r0 |= 0x40 ## p33.c:28:13 + 11121a: bf ea 49 ff call -0x16e ## p33.c:28:5 + 11121e: 70 e1 7f 3c r0 = r3 & 0xFFFF00FF ## p33.c:29:5 + 111222: bf ea 45 ff call -0x176 ## p33.c:29:5 + 111226: 20 16 r0 = r2 ## p33.c:30:5 + 111228: bf ea 42 ff call -0x17c ## p33.c:30:5 + 11122c: 40 e0 fe fe r0 = -0x102 ## p33.c:31:5 + 111230: 64 e8 02 40 [r4+0x0] &= r0 ## p33.c:31:5 + 111234: 34 04 {rets, r4} = [sp++] ## p33.c:31:5 + 111236: ff ea 98 f8 goto -0xed0 ## p33.c:31:5 + + +spi_cs_pu: + 11123a: 74 04 [--sp] = {rets, r4} ## spi0.c:192:0 + 11123c: c1 ff de be 02 00 r1 = 0x2bede ## boot_init.c:92:12 + 111242: 1a 40 r2 = b[r1+0x0] (u) ## boot_init.c:92:12 + 111244: c1 ff 10 50 1e 00 r1 = 0x1e5010 <__stub_doe+0xD2814 : 1e5010 > + 11124a: 52 e8 0a 10 if ((r2 & 0x4) == 0) goto 0x14 + 11124e: d0 ec 10 3c r3 = [r1+0xc0] + 111252: 74 e1 08 30 r4 = r3 & 0xFFFFFFF7 ## spi0.c:198:26 + 111256: 33 23 r3 |= 0x8 ## spi0.c:196:26 + 111258: 30 e8 00 00 if (r0 == 0x0) { ## spi0.c:196:26 + 11125c: 43 16 r3 = r4 + } ## spi0.c:195:13 + 11125e: d0 ec 11 3c [r1+0xc0] = r3 ## spi0.c:195:13 + 111262: 52 e8 08 18 if ((r2 & 0x8) == 0) goto 0x10 + 111266: 12 60 r2 = [r1+0x0] + 111268: 73 e1 00 2d r3 = r2 & 0xFFFFDFFF ## spi0.c:206:26 + 11126c: 32 2d r2 |= 0x2000 ## spi0.c:204:26 + 11126e: 30 e8 00 00 if (r0 == 0x0) { ## spi0.c:204:26 + 111272: 32 16 r2 = r3 + } ## spi0.c:203:13 + 111274: 92 60 [r1+0x0] = r2 ## spi0.c:203:13 + 111276: 54 04 {pc, r4} = [sp++] ## spi0.c:210:1 + + +udelay: + 111278: c1 ff 00 04 1e 00 r1 = 0x1e0400 <__stub_doe+0xCDC04 : 1e0400 > ## timer.c:58:0 + 11127e: 40 ea 80 1c [r1+0x0] = 0x4000 ## timer.c:64:20 + 111282: 41 ea 00 10 [r1+0x4] = 0x0 ## timer.c:65:20 + 111286: e0 e1 14 00 r0 = r0 * 0x14 ## timer.c:66:40 + 11128a: 90 62 [r1+0x8] = r0 ## timer.c:66:20 + 11128c: 40 ea 0d 10 [r1+0x0] = 0xD ## timer.c:67:20 + 111290: 10 60 r0 = [r1+0x0] ## timer.c:68:24 + 111292: 50 e8 fd 79 if ((r0 & 0x8000) == 0) goto -0x6 ## timer.c:68:5 + 111296: 40 ea 80 1c [r1+0x0] = 0x4000 ## timer.c:69:20 + 11129a: 80 00 rts ## timer.c:71:1 + + +flash_poweron: + 11129c: 10 04 [--sp] = rets ## norflash.c:386:0 + 11129e: 40 21 r0 = 0x1 ## norflash.c:389:5 + 1112a0: 61 8c call -0x68 ## norflash.c:389:5 + 1112a2: c2 ff c0 50 1e 00 r2 = 0x1e50c0 <__stub_doe+0xD28C4 : 1e50c0 > ## norflash.c:389:5 + 1112a8: c5 ef 10 20 [r2+0x14] &= 0xFFFFFFEF ## norflash.c:392:19 + 1112ac: 04 ef 10 20 [r2+0x10] |= 0x10 ## norflash.c:393:19 + 1112b0: 02 ef 10 20 [r2+0x8] |= 0x10 ## norflash.c:394:19 + 1112b4: c7 ef 10 20 [r2+0x1c] &= 0xFFFFFFEF ## norflash.c:396:19 + 1112b8: c6 ef 10 20 [r2+0x18] &= 0xFFFFFFEF ## norflash.c:397:19 + 1112bc: 00 ef 10 20 [r2+0x0] |= 0x10 ## norflash.c:398:19 + 1112c0: c2 ef 10 20 [r2+0x8] &= 0xFFFFFFEF ## norflash.c:399:19 + 1112c4: 40 34 r0 = 0x14 ## norflash.c:401:5 + 1112c6: 61 98 call -0x50 ## norflash.c:401:5 + 1112c8: 07 ef 10 20 [r2+0x1c] |= 0x10 ## norflash.c:403:19 + 1112cc: 06 ef 10 20 [r2+0x18] |= 0x10 ## norflash.c:404:19 + 1112d0: 00 04 pc = [sp++] ## norflash.c:405:1 + + +startup_init1: + 1112d2: 76 04 [--sp] = {rets, r6-r4} ## boot_init.c:95:0 + 1112d4: c5 ff dc be 02 00 r5 = 0x2bedc ## boot_init.c:95:0 + 1112da: 40 20 r0 = 0x0 ## boot_init.c:96:17 + 1112dc: d8 40 b[r5+0x0] = r0 ## boot_init.c:96:17 + 1112de: c6 ff dd be 02 00 r6 = 0x2bedd ## boot_init.c:96:17 + 1112e4: e8 40 b[r6+0x0] = r0 ## boot_init.c:97:18 + 1112e6: c0 ff e0 be 02 00 r0 = 0x2bee0 ## clock.c:219:28 + 1112ec: 41 23 r1 = 0x3 ## clock.c:215:28 + 1112ee: c2 ff 00 2d 31 01 r2 = 0x1312d00 <__stub_doe+0x1200504 : 1312d00 > ## clock.c:219:28 + 1112f4: 23 d6 r3 = r2 # ## clock.c:219:28 + 1112f6: 89 41 b[r0+0x1] = r1 ## clock.c:215:28 + 1112f8: 50 ec 05 20 d[r0+0x4] = r3_r2 ## clock.c:219:28 + 1112fc: 48 30 r0 = 0x30 ## p33.c:105:15 + 1112fe: bf ea 0d ff call -0x1e6 ## p33.c:105:15 + 111302: 50 e8 fb 39 if ((r0 & 0x80) == 0) goto -0xa ## p33.c:106:13 + 111306: c0 ff c0 be 02 00 r0 = 0x2bec0 ## boot_init.c:49:24 + 11130c: 40 ea 00 00 [r0+0x0] = 0x0 ## boot_init.c:49:24 + 111310: c1 ff 04 00 11 00 r1 = 0x110004 ## boot_init.c:51:5 + 111316: 40 21 r0 = 0x1 ## boot_init.c:51:5 + 111318: 42 27 r2 = 0x7 ## boot_init.c:51:5 + 11131a: bf ea 23 ff call -0x1ba ## boot_init.c:51:5 + 11131e: 64 e0 00 0b r0 = icfg ## boot_init.c:108:5 + 111322: 30 29 r0 |= 0x200 ## boot_init.c:109:9 + 111324: 64 e0 80 0b icfg = r0 ## boot_init.c:110:5 + 111328: bf ea 28 f8 call -0xfb0 ## boot_init.c:112:5 + 11132c: bf ea 16 f8 call -0xfd4 ## boot_init.c:113:5 + 111330: bf ea 1b f8 call -0xfca ## boot_init.c:114:5 + 111334: 48 32 r0 = 0x32 ## p33_api.h:114:11 + 111336: bf ea f1 fe call -0x21e ## p33_api.h:114:11 + 11133a: d8 40 b[r5+0x0] = r0 ## boot_init.c:116:17 + 11133c: 48 33 r0 = 0x33 ## p33_api.h:114:11 + 11133e: bf ea ed fe call -0x226 ## p33_api.h:114:11 + 111342: 04 16 r4 = r0 ## p33_api.h:114:11 + 111344: ec 40 b[r6+0x0] = r4 ## boot_init.c:117:18 + 111346: 48 31 r0 = 0x31 ## p33_api.h:114:11 + 111348: bf ea e8 fe call -0x230 ## p33_api.h:114:11 + 11134c: 0a 17 r2 = r0.b0 (s) ## p33_api.h:114:11 + 11134e: 40 2c r0 = 0xc ## boot_init.c:80:9 + 111350: 41 2c r1 = 0xc ## boot_init.c:80:9 + 111352: 32 ed 00 00 ifs (r2 >= 0x0) { ## boot_init.c:80:9 + 111356: 59 40 r1 = b[r5+0x0] (u) + } ## boot_init.c:66:16 + 111358: 31 ea 0c 00 if ((r1 & 0xC) != 0) { ## boot_init.c:66:16 + 11135c: 10 16 r0 = r1 + } ## boot_init.c:86:9 + 11135e: c1 ff de be 02 00 r1 = 0x2bede ## boot_init.c:87:25 + 111364: 98 40 b[r1+0x0] = r0 ## boot_init.c:87:25 + 111366: 54 e8 10 02 if ((r4 & 0x1) != 0) goto 0x20 ## boot_init.c:87:25 + 11136a: 60 20 r0 = 0x80 ## wdt.c:4:5 + 11136c: 79 2f r1 = 0xef ## wdt.c:4:5 + 11136e: bf ea 1a ff call -0x1cc ## wdt.c:4:5 + 111372: 60 20 r0 = 0x80 ## wdt.c:5:5 + 111374: 41 2c r1 = 0xc ## wdt.c:5:5 + 111376: bf ea a7 fe call -0x2b2 ## wdt.c:5:5 + 11137a: 60 20 r0 = 0x80 ## wdt.c:6:5 + 11137c: 71 3f r1 = 0xdf ## wdt.c:6:5 + 11137e: bf ea 37 ff call -0x192 ## wdt.c:6:5 + 111382: 60 20 r0 = 0x80 ## wdt.c:7:5 + 111384: 41 30 r1 = 0x10 ## wdt.c:7:5 + 111386: bf ea 0e ff call -0x1e4 ## wdt.c:7:5 + 11138a: c0 ff 00 51 1e 00 r0 = 0x1e5100 <__stub_doe+0xD2904 : 1e5100 > + 111390: 34 ea 02 00 if ((r4 & 0x2) != 0) { + 111394: c0 ef 10 00 [r0+0x0] &= 0xFFFFFFEF + } ## boot_init.c:130:25 + 111398: 34 ea 08 00 if ((r4 & 0x8) != 0) { ## boot_init.c:130:25 + 11139c: c0 ef 20 00 [r0+0x0] &= 0xFFFFFFDF + } ## boot_init.c:134:25 + 1113a0: 34 ea 04 00 if ((r4 & 0x4) != 0) { ## boot_init.c:134:25 + 1113a4: 00 ef 40 00 [r0+0x0] |= 0x40 + } ## boot_init.c:138:25 + 1113a8: 34 ea 10 00 if ((r4 & 0x10) != 0) { ## boot_init.c:138:25 + 1113ac: 00 ef 80 00 [r0+0x0] |= 0x80 + } ## boot_init.c:142:25 + 1113b0: 68 2f r0 = 0xaf ## boot_init.c:164:5 + 1113b2: 79 3d r1 = 0xfd ## boot_init.c:164:5 + 1113b4: bf ea 1c ff call -0x1c8 ## boot_init.c:164:5 + 1113b8: bf ea 70 ff call -0x120 ## boot_init.c:165:5 + 1113bc: c0 ff 00 41 1e 00 r0 = 0x1e4100 <__stub_doe+0xD1904 : 1e4100 > + 1113c2: 42 ea 00 00 [r0+0x8] = 0x0 ## boot_flash.c:60:24 + 1113c6: c1 ff ff ff 00 00 r1 = 0xffff ## boot_flash.c:61:24 + 1113cc: 81 61 [r0+0x4] = r1 ## boot_flash.c:61:24 + 1113ce: 40 ea 80 00 [r0+0x0] = 0x80 ## boot_flash.c:62:24 + 1113d2: 56 04 {pc, r6-r4} = [sp++] ## boot_init.c:169:1 + + +set_timer3_captrue_dp: + 1113d4: c1 ff 00 51 1e 00 r1 = 0x1e5100 <__stub_doe+0xD2904 : 1e5100 > ## clock.c:286:0 + 1113da: 00 ef 00 1e [r1+0x0] |= 0x800 ## clock.c:287:21 + 1113de: c2 ff 00 18 1e 00 r2 = 0x1e1800 <__stub_doe+0xCF004 : 1e1800 > ## clock.c:288:18 + 1113e4: 00 ef 01 20 [r2+0x0] |= 0x1 ## clock.c:288:18 + 1113e8: 00 4c if (r0 == 0) goto 0x18 ## clock.c:288:18 + 1113ea: 00 ef c0 1e [r1+0x0] |= 0x600 ## clock.c:291:25 + 1113ee: c0 ef 03 10 [r1+0x0] &= 0xFFFFFFFC ## clock.c:292:25 + 1113f2: 00 ef 0c 10 [r1+0x0] |= 0xC ## clock.c:293:25 + 1113f6: c0 ef 30 10 [r1+0x0] &= 0xFFFFFFCF ## clock.c:294:25 + 1113fa: c0 ef c0 10 [r1+0x0] &= 0xFFFFFF3F ## clock.c:295:25 + 1113fe: 00 ef 40 10 [r1+0x0] |= 0x40 ## clock.c:296:25 + 111402: c8 ef 7c 19 [r1+0x20] &= 0xFFC0FFFF ## clock.c:299:20 + 111406: 08 ef 74 19 [r1+0x20] |= 0x3D0000 ## clock.c:300:20 + 11140a: 07 ef 00 14 [r1+0x1c] |= 0x80000000 ## clock.c:302:20 + 11140e: 20 e1 00 2f r0 = r2 + -0x1100 ## clock.c:304:20 + 111412: 40 ea 80 0c [r0+0x0] = 0x4000 ## clock.c:304:20 + 111416: 80 00 rts ## clock.c:305:1 + + +clk_get: + 111418: 76 04 [--sp] = {rets, r6-r4} ## clock.c:226:0 + 11141a: 04 16 r4 = r0 ## clock.c:226:0 + 11141c: c5 ff 40 10 11 00 r5 = 0x111040 ## clock.c:226:0 + 111422: 51 16 r1 = r5 ## clock.c:227:9 + 111424: bf ea c5 f6 call -0x1276 ## clock.c:227:9 + 111428: c6 ff e0 be 02 00 r6 = 0x2bee0 ## clock.c:227:9 + 11142e: 00 50 if (r0 == 0) goto 0x20 ## clock.c:227:9 + 111430: 59 84 r1 = r5 + 0x4 ## clock.c:229:16 + 111432: 40 16 r0 = r4 ## clock.c:229:16 + 111434: bf ea bd f6 call -0x1286 ## clock.c:229:16 + 111438: 00 4d if (r0 == 0) goto 0x1a ## clock.c:229:16 + 11143a: 59 8d r1 = r5 + 0xd ## clock.c:231:16 + 11143c: 40 16 r0 = r4 ## clock.c:231:16 + 11143e: bf ea b8 f6 call -0x1290 ## clock.c:231:16 + 111442: b0 e8 00 10 if (r0 != 0x0) { ## clock.c:231:16 + 111446: 60 62 r0 = [r6+0x8] + } else { ## clock.c:237:26 + 111448: c0 ff 00 36 6e 01 r0 = 0x16e3600 + } <__stub_doe+0x15D0E04 : 16e3600 > ## clock.c:231:16 + 11144e: 56 04 {pc, r6-r4} = [sp++] ## clock.c:231:16 + 111450: 68 88 r0 = r6 + 0x8 + 111452: 04 81 goto 0x2 + 111454: 68 84 r0 = r6 + 0x4 + 111456: 00 60 r0 = [r0+0x0] + 111458: 56 04 {pc, r6-r4} = [sp++] ## clock.c:238:1 + + +set_timer3_captrue_dp_disable: + 11145a: c1 ff 00 51 1e 00 r1 = 0x1e5100 <__stub_doe+0xD2904 : 1e5100 > ## clock.c:307:0 + 111460: b0 e8 00 00 if (r0 != 0x0) { ## clock.c:307:0 + 111464: c0 ef 40 10 [r1+0x0] &= 0xFFFFFFBF + } ## clock.c:309:25 + 111468: c0 ff 00 07 1e 00 r0 = 0x1e0700 <__stub_doe+0xCDF04 : 1e0700 > ## clock.c:312:20 + 11146e: 40 ea 80 0c [r0+0x0] = 0x4000 ## clock.c:312:20 + 111472: c7 ef 00 14 [r1+0x1c] &= 0x7FFFFFFF ## clock.c:313:20 + 111476: 80 00 rts ## clock.c:314:1 + + +wdt_clr: + 111478: 60 20 r0 = 0x80 ## wdt.c:11:0 + 11147a: 51 20 r1 = 0x40 ## wdt.c:12:5 + 11147c: 47 94 goto -0x2d8 ## wdt.c:12:5 + + +uart_set_dma_dir: + 11147e: 00 49 if (r0 == 0) goto 0x12 ## uart_upgrade.c:23:0 + 111480: 10 2f r0 = -0x11 ## uart_upgrade.c:23:0 + 111482: c1 ff 04 20 1e 00 r1 = 0x1e2004 <__stub_doe+0xCF808 : 1e2004 > ## uart_upgrade.c:23:0 + 111488: 4a 20 r2 = 0x20 ## uart_upgrade.c:23:0 + 11148a: c3 ff 48 50 1e 00 r3 = 0x1e5048 <__stub_doe+0xD284C : 1e5048 > ## uart_upgrade.c:23:0 + 111490: 04 89 goto 0x12 ## uart_upgrade.c:23:0 + 111492: 40 e0 df ff r0 = -0x21 ## uart_upgrade.c:23:0 + 111496: c1 ff 48 50 1e 00 r1 = 0x1e5048 <__stub_doe+0xD284C : 1e5048 > ## uart_upgrade.c:23:0 + 11149c: 42 30 r2 = 0x10 ## uart_upgrade.c:23:0 + 11149e: c3 ff 04 20 1e 00 r3 = 0x1e2004 <__stub_doe+0xCF808 : 1e2004 > ## uart_upgrade.c:23:0 + 1114a4: 64 e8 00 32 [r3+0x0] |= r2 ## uart_upgrade.c:23:0 + 1114a8: 64 e8 02 10 [r1+0x0] &= r0 ## uart_upgrade.c:23:0 + 1114ac: 80 00 rts ## uart_upgrade.c:36:1 + + +uart_rx_data: + 1114ae: 75 04 [--sp] = {rets, r5, r4} ## uart_upgrade.c:56:0 + 1114b0: 14 16 r4 = r1 ## uart_upgrade.c:56:0 + 1114b2: 05 16 r5 = r0 ## uart_upgrade.c:56:0 + 1114b4: 71 81 call -0x3e ## uart_upgrade.c:57:5 + 1114b6: 40 21 r0 = 0x1 ## uart_upgrade.c:58:5 + 1114b8: 71 82 call -0x3c ## uart_upgrade.c:58:5 + 1114ba: 60 e0 f1 09 r0 = 0x1E2000 ## uart_upgrade.c:58:5 + 1114be: 51 dd r1 = r5 + r4 # ## uart_upgrade.c:61:33 + 1114c0: 85 67 [r0+0x1c] = r5 ## uart_upgrade.c:60:18 + 1114c2: c1 23 r1 += 0x3 ## uart_upgrade.c:61:40 + 1114c4: 71 e1 03 10 r1 = r1 & 0xFFFFFFFC ## uart_upgrade.c:61:49 + 1114c8: 81 68 [r0+0x20] = r1 ## uart_upgrade.c:61:18 + 1114ca: 84 69 [r0+0x24] = r4 ## uart_upgrade.c:63:17 + 1114cc: 20 00 csync ## uart_upgrade.c:64:5 + 1114ce: 01 60 r1 = [r0+0x0] ## uart_upgrade.c:68:19 + 1114d0: 51 e8 fd 71 if ((r1 & 0x4000) == 0) goto -0x6 ## uart_upgrade.c:68:13 + 1114d4: 00 ef a0 0d [r0+0x0] |= 0x1400 ## uart_upgrade.c:72:16 + 1114d8: 55 04 {pc, r5, r4} = [sp++] ## uart_upgrade.c:74:1 + + +chip_crc16: + 1114da: c2 ff 00 35 1e 00 r2 = 0x1e3500 <__stub_doe+0xD0D04 : 1e3500 > ## crc.c:3:0 + 1114e0: 41 ea 00 20 [r2+0x4] = 0x0 ## crc.c:5:17 + 1114e4: 04 84 goto 0x8 ## crc.c:5:17 + 1114e6: 0b 40 r3 = b[r0+0x0] (u) ## crc.c:8:24 + 1114e8: a3 60 [r2+0x0] = r3 ## crc.c:8:22 + 1114ea: c0 21 r0 += 0x1 ## crc.c:8:26 + 1114ec: f9 3f r1 += -0x1 ## crc.c:7:15 + 1114ee: f1 5b if (r1 != 0) goto -0xa + 1114f0: 20 00 csync ## crc.c:10:5 + 1114f2: 20 61 r0 = [r2+0x4] ## crc.c:12:20 + 1114f4: 80 17 r0 = r0.l (u) ## crc.c:12:5 + 1114f6: 80 00 rts ## crc.c:12:5 + + +uart_cmd_verify: + 1114f8: 74 04 [--sp] = {rets, r4} ## uart_upgrade.c:109:0 + 1114fa: c0 ff c0 bd 02 00 r0 = 0x2bdc0 ## uart_upgrade.c:109:0 + 111500: 50 ee 00 11 r1 = b[r0+0x10] (u) ## uart_upgrade.c:110:18 + 111504: 0c 4f r4 = b[r0+0xf] (u) ## uart_upgrade.c:110:18 + 111506: a4 e1 20 14 r4 <= insert(r1, p:0x8, l:0x8) ## uart_upgrade.c:110:18 + 11150a: 34 e8 00 40 if (r4 == 0x0) { ## uart_upgrade.c:110:18 + 11150e: 40 20 r0 = 0x0 ## uart_upgrade.c:115:1 + 111510: 54 04 {pc, r4} = [sp++] + } ## uart_upgrade.c:115:1 + 111512: c0 25 r0 += 0x5 ## uart_upgrade.c:111:30 + 111514: 41 2a r1 = 0xa ## uart_upgrade.c:111:30 + 111516: 71 81 call -0x3e ## uart_upgrade.c:111:30 + 111518: 01 16 r1 = r0 ## uart_upgrade.c:111:30 + 11151a: 40 21 r0 = 0x1 ## uart_upgrade.c:111:27 + 11151c: 94 e8 00 01 if (r4 != r1) { ## uart_upgrade.c:111:27 + 111520: 40 20 r0 = 0x0 + } ## uart_upgrade.c:111:27 + 111522: 54 04 {pc, r4} = [sp++] ## uart_upgrade.c:110:9 + + +mdelay: + 111524: 10 04 [--sp] = rets ## timer.c:74:0 + 111526: 02 16 r2 = r0 ## timer.c:74:0 + 111528: 04 85 goto 0xa ## timer.c:74:0 + 11152a: 40 e0 e8 03 r0 = 0x3e8 ## timer.c:76:9 + 11152e: bf ea a3 fe call -0x2ba ## timer.c:76:9 + 111532: fa 3f r2 += -0x1 ## timer.c:75:5 + 111534: f2 5a if (r2 != 0) goto -0xc ## timer.c:75:5 + 111536: 00 04 pc = [sp++] ## timer.c:78:1 + + +CrcDecode: + 111538: 77 04 [--sp] = {rets, r7-r4} ## crc.c:28:0 + 11153a: c3 ff ff ff 00 00 r3 = 0xffff ## crc.c:36:17 + 111540: c2 ff 00 35 1e 00 r2 = 0x1e3500 <__stub_doe+0xD0D04 : 1e3500 > + 111546: a3 61 [r2+0x4] = r3 ## crc.c:36:17 + 111548: 7b 3f r3 = 0xff ## crc.c:38:18 + 11154a: a3 60 [r2+0x0] = r3 ## crc.c:38:18 + 11154c: a3 60 [r2+0x0] = r3 ## crc.c:39:18 + 11154e: 44 20 r4 = 0x0 ## crc.c:39:18 + 111550: c3 ff 9f 10 11 00 r3 = 0x11109f ## crc.c:39:18 + 111556: 04 90 goto 0x20 ## crc.c:39:18 + 111558: 46 17 r6 = r4.b0 (u) ## crc.c:43:24 + 11155a: d8 ee 60 53 r5 = b[r6+r3] (u) ## crc.c:43:24 + 11155e: a5 60 [r2+0x0] = r5 ## crc.c:43:22 + 111560: 20 00 csync ## crc.c:49:9 + 111562: 0d 40 r5 = b[r0+0x0] (u) ## crc.c:50:24 + 111564: 27 61 r7 = [r2+0x4] ## crc.c:50:51 + 111566: 7d 19 r5 ^= r7 ## crc.c:50:37 + 111568: 8d 40 b[r0+0x0] = r5 ## crc.c:50:22 + 11156a: 4d 81 r5 = r4 + 0x1 ## crc.c:45:14 + 11156c: 44 20 r4 = 0x0 ## crc.c:45:13 + 11156e: b6 ec 0e 00 if (r6 <= 0xe) { ## crc.c:45:13 + 111572: 54 16 r4 = r5 + } ## crc.c:45:13 + 111574: c0 21 r0 += 0x1 ## crc.c:52:27 + 111576: f9 3f r1 += -0x1 ## crc.c:42:15 + 111578: 95 17 r5 = r1.l (u) ## crc.c:42:5 + 11157a: f5 4e if (r5 != 0) goto -0x24 ## crc.c:42:5 + 11157c: 57 04 {pc, r7-r4} = [sp++] ## crc.c:56:1 + + +uart_recv_loader: + 11157e: e2 9e sp += -0x8 ## uart_upgrade.c:138:0 + 111580: 40 25 r0 = 0x5 ## uart_upgrade.c:141:5 + 111582: 44 25 r4 = 0x5 ## uart_upgrade.c:141:5 + 111584: 61 8f call -0x62 ## uart_upgrade.c:141:5 + 111586: c6 ff 40 10 11 00 r6 = 0x111040 ## uart_upgrade.c:141:5 + 11158c: 68 4c r0 = b[r6+0xc] (u) ## uart_upgrade.c:52:5 + 11158e: 61 62 r1 = [r6+0x8] ## uart_upgrade.c:52:5 + 111590: de e9 04 00 b[sp+4] = r0 ## uart_upgrade.c:52:5 + 111594: 81 20 [sp] = r1 ## uart_upgrade.c:52:5 + 111596: 40 20 r0 = 0x0 ## uart_upgrade.c:40:5 + 111598: bf ea 71 ff call -0x11e ## uart_upgrade.c:40:5 + 11159c: 88 80 r0 = sp + 0 ## uart_upgrade.c:40:5 + 11159e: 60 e0 f1 59 r5 = 0x1E2000 ## uart_upgrade.c:40:5 + 1115a2: d0 65 [r5+0x14] = r0 ## uart_upgrade.c:42:17 + 1115a4: d4 66 [r5+0x18] = r4 ## uart_upgrade.c:43:17 + 1115a6: 20 00 csync ## uart_upgrade.c:44:5 + 1115a8: 50 60 r0 = [r5+0x0] ## uart_upgrade.c:45:19 + 1115aa: 50 e8 fd 79 if ((r0 & 0x8000) == 0) goto -0x6 ## uart_upgrade.c:45:5 + 1115ae: 00 ef 00 5d [r5+0x0] |= 0x2000 ## uart_upgrade.c:47:16 + 1115b2: 40 22 r0 = 0x2 ## uart_upgrade.c:144:5 + 1115b4: 51 97 call -0x92 ## uart_upgrade.c:144:5 + 1115b6: c4 ff c0 bd 02 00 r4 = 0x2bdc0 ## uart_upgrade.c:144:5 + 1115bc: 50 ee 42 01 r0 = b[r4+0x12] (u) ## uart_upgrade.c:146:16 + 1115c0: 30 e8 00 40 if (r0 == 0x0) { ## uart_upgrade.c:146:16 + 1115c4: 40 2a r0 = 0xa ## uart_upgrade.c:146:16 + 1115c6: 52 ee 42 01 b[r4+0x12] = r0 + } ## uart_upgrade.c:147:21 + 1115ca: 41 e0 10 27 r1 = 0x2710 ## uart_upgrade.c:150:43 + 1115ce: f0 e1 00 71 r7 = r0 * r1 ## uart_upgrade.c:150:43 + 1115d2: 68 8d r0 = r6 + 0xd ## uart_upgrade.c:150:19 + 1115d4: bf ea 20 ff call -0x1c0 ## uart_upgrade.c:150:19 + 1115d8: f4 e1 00 07 r0 = r0 / r7 (u) ## uart_upgrade.c:150:28 + 1115dc: 80 a2 r0 = r0 >> 0x2 ## uart_upgrade.c:150:53 + 1115de: f8 3f r0 += -0x1 ## uart_upgrade.c:150:57 + 1115e0: d0 62 [r5+0x8] = r0 ## uart_upgrade.c:150:16 + 1115e2: bf ea 49 ff call -0x16e ## uart_upgrade.c:151:5 + 1115e6: 48 48 r0 = b[r4+0x8] (u) ## uart_upgrade.c:152:25 + 1115e8: 4a 47 r2 = b[r4+0x7] (u) ## uart_upgrade.c:152:25 + 1115ea: a2 f1 20 04 r2 <= insert(r0, p:0x8, l:0x8) # ## uart_upgrade.c:152:25 + 1115ee: 48 45 r0 = b[r4+0x5] (u) ## uart_upgrade.c:152:25 + 1115f0: 50 ee 46 80 r8 = b[r4+0x6] (u) ## uart_upgrade.c:152:25 + 1115f4: a0 f1 20 84 r0 <= insert(r8, p:0x8, l:0x8) # ## uart_upgrade.c:152:25 + 1115f8: 4e 4c r6 = b[r4+0xc] (u) ## uart_upgrade.c:152:38 + 1115fa: a0 f1 40 28 r0 <= insert(r2, p:0x10, l:0x10) # ## uart_upgrade.c:152:25 + 1115fe: 4f 4b r7 = b[r4+0xb] (u) ## uart_upgrade.c:152:38 + 111600: a7 f1 20 64 r7 <= insert(r6, p:0x8, l:0x8) # ## uart_upgrade.c:152:38 + 111604: 4b 4a r3 = b[r4+0xa] (u) ## uart_upgrade.c:152:38 + 111606: 49 49 r1 = b[r4+0x9] (u) ## uart_upgrade.c:152:38 + 111608: a1 e1 20 34 r1 <= insert(r3, p:0x8, l:0x8) ## uart_upgrade.c:152:38 + 11160c: a1 e1 40 78 r1 <= insert(r7, p:0x10, l:0x10) ## uart_upgrade.c:152:38 + 111610: bf ea 4d ff call -0x166 ## uart_upgrade.c:152:5 + 111614: 40 ea 00 50 [r5+0x0] = 0x0 ## uart_upgrade.c:154:16 + 111618: 49 48 r1 = b[r4+0x8] (u) ## uart_upgrade.c:156:57 + 11161a: 4a 47 r2 = b[r4+0x7] (u) ## uart_upgrade.c:156:57 + 11161c: a2 f1 20 14 r2 <= insert(r1, p:0x8, l:0x8) # ## uart_upgrade.c:156:57 + 111620: 4b 46 r3 = b[r4+0x6] (u) ## uart_upgrade.c:156:57 + 111622: 48 45 r0 = b[r4+0x5] (u) ## uart_upgrade.c:156:57 + 111624: a0 f1 20 34 r0 <= insert(r3, p:0x8, l:0x8) # ## uart_upgrade.c:156:57 + 111628: 4b 4b r3 = b[r4+0xb] (u) ## uart_upgrade.c:156:70 + 11162a: a0 f1 40 28 r0 <= insert(r2, p:0x10, l:0x10) # ## uart_upgrade.c:156:57 + 11162e: 4a 4c r2 = b[r4+0xc] (u) ## uart_upgrade.c:156:70 + 111630: a3 f1 20 24 r3 <= insert(r2, p:0x8, l:0x8) # ## uart_upgrade.c:156:70 + 111634: 4d 4a r5 = b[r4+0xa] (u) ## uart_upgrade.c:156:70 + 111636: 49 49 r1 = b[r4+0x9] (u) ## uart_upgrade.c:156:70 + 111638: a1 f1 20 54 r1 <= insert(r5, p:0x8, l:0x8) # ## uart_upgrade.c:156:70 + 11163c: 4e 4e r6 = b[r4+0xe] (u) ## uart_upgrade.c:156:16 + 11163e: a1 f1 40 38 r1 <= insert(r3, p:0x10, l:0x10) # ## uart_upgrade.c:156:70 + 111642: 4f 4d r7 = b[r4+0xd] (u) ## uart_upgrade.c:156:16 + 111644: bf ea 49 ff call -0x16e ## uart_upgrade.c:156:31 + 111648: a7 e1 20 64 r7 <= insert(r6, p:0x8, l:0x8) ## uart_upgrade.c:156:16 + 11164c: 80 e8 20 70 if (r7 != r0) goto 0x40 ## uart_upgrade.c:156:16 + 111650: 50 ee 41 01 r0 = b[r4+0x11] (u) ## uart_upgrade.c:168:16 + 111654: 50 e8 10 08 if ((r0 & 0x2) == 0) goto 0x20 ## uart_upgrade.c:168:16 + 111658: 4a 48 r2 = b[r4+0x8] (u) ## uart_upgrade.c:169:34 + 11165a: 4b 47 r3 = b[r4+0x7] (u) ## uart_upgrade.c:169:34 + 11165c: a3 f1 20 24 r3 <= insert(r2, p:0x8, l:0x8) # ## uart_upgrade.c:169:34 + 111660: 4d 46 r5 = b[r4+0x6] (u) ## uart_upgrade.c:169:34 + 111662: 48 45 r0 = b[r4+0x5] (u) ## uart_upgrade.c:169:34 + 111664: a0 f1 20 54 r0 <= insert(r5, p:0x8, l:0x8) # ## uart_upgrade.c:169:34 + 111668: 4e 4a r6 = b[r4+0xa] (u) ## uart_upgrade.c:169:9 + 11166a: a0 f1 40 38 r0 <= insert(r3, p:0x10, l:0x10) # ## uart_upgrade.c:169:34 + 11166e: 49 49 r1 = b[r4+0x9] (u) ## uart_upgrade.c:169:9 + 111670: a1 e1 20 64 r1 <= insert(r6, p:0x8, l:0x8) ## uart_upgrade.c:169:9 + 111674: bf ea 60 ff call -0x140 ## uart_upgrade.c:169:9 + 111678: 48 48 r0 = b[r4+0x8] (u) ## uart_upgrade.c:172:30 + 11167a: 49 47 r1 = b[r4+0x7] (u) ## uart_upgrade.c:172:30 + 11167c: a1 f1 20 04 r1 <= insert(r0, p:0x8, l:0x8) # ## uart_upgrade.c:172:30 + 111680: 4a 46 r2 = b[r4+0x6] (u) ## uart_upgrade.c:172:30 + 111682: 40 d6 r0 = r4 # ## uart_upgrade.c:172:5 + 111684: 4b 45 r3 = b[r4+0x5] (u) ## uart_upgrade.c:172:30 + 111686: a3 e1 20 24 r3 <= insert(r2, p:0x8, l:0x8) ## uart_upgrade.c:172:30 + 11168a: a3 e1 40 18 r3 <= insert(r1, p:0x10, l:0x10) ## uart_upgrade.c:172:30 + 11168e: c3 00 call r3 ## uart_upgrade.c:172:5 + 111690: bf ea 25 f6 call -0x13b6 ## uart_upgrade.c:175:5 + + +uart_upgrade_init: + 111694: 76 04 [--sp] = {rets, r6-r4} ## uart_upgrade.c:202:0 + 111696: c1 ff 18 51 1e 00 r1 = 0x1e5118 <__stub_doe+0xD291C : 1e5118 > ## uart_upgrade.c:202:0 + 11169c: c0 ef c0 10 [r1+0x0] &= 0xFFFFFF3F ## uart_upgrade.c:205:20 + 1116a0: 00 ef 80 10 [r1+0x0] |= 0x80 ## uart_upgrade.c:206:20 + 1116a4: 31 e1 30 1f r1 = r1 + -0xd0 ## uart_upgrade.c:206:20 + 1116a8: 05 ef 20 10 [r1+0x14] |= 0x20 ## uart_upgrade.c:208:18 + 1116ac: 02 ef 20 10 [r1+0x8] |= 0x20 ## uart_upgrade.c:209:18 + 1116b0: c3 ef 20 10 [r1+0xc] &= 0xFFFFFFDF ## uart_upgrade.c:210:18 + 1116b4: 00 ef 20 10 [r1+0x0] |= 0x20 ## uart_upgrade.c:211:19 + 1116b8: c1 ff 10 00 1e 00 r1 = 0x1e0010 <__stub_doe+0xCD814 : 1e0010 > ## uart_upgrade.c:211:19 + 1116be: c0 ef 40 1e [r1+0x0] &= 0xFFFFF3FF ## uart_upgrade.c:213:24 + 1116c2: 00 ef 80 1e [r1+0x0] |= 0x400 ## uart_upgrade.c:214:24 + 1116c6: 60 e0 f1 69 r6 = 0x1E2000 ## uart_upgrade.c:214:24 + 1116ca: 40 ea 50 6d [r6+0x0] = 0x3400 ## uart_upgrade.c:216:16 + 1116ce: 05 16 r5 = r0 ## uart_upgrade.c:216:16 + 1116d0: c4 ff 4d 10 11 00 r4 = 0x11104d + 1116d6: 40 16 r0 = r4 ## uart_upgrade.c:218:19 + 1116d8: bf ea 9e fe call -0x2c4 ## uart_upgrade.c:218:19 + 1116dc: 60 e0 16 1c r1 = 0x9600 ## uart_upgrade.c:218:36 + 1116e0: f4 e1 00 01 r0 = r0 / r1 (u) ## uart_upgrade.c:218:36 + 1116e4: f8 3f r0 += -0x1 ## uart_upgrade.c:218:40 + 1116e6: e0 62 [r6+0x8] = r0 ## uart_upgrade.c:218:16 + 1116e8: 40 ea 41 60 [r6+0x0] = 0x41 ## uart_upgrade.c:220:16 + 1116ec: 00 ef 50 6d [r6+0x0] |= 0x3400 ## uart_upgrade.c:221:16 + 1116f0: 15 41 if (r5 == 0) goto 0x42 ## uart_upgrade.c:221:16 + 1116f2: c1 ff e8 24 11 00 r1 = 0x1124e8 ## uart_upgrade.c:225:9 + 1116f8: 40 32 r0 = 0x12 ## uart_upgrade.c:225:9 + 1116fa: 42 23 r2 = 0x3 ## uart_upgrade.c:225:9 + 1116fc: bf ea 32 fd call -0x59c ## uart_upgrade.c:225:9 + 111700: 40 16 r0 = r4 ## uart_upgrade.c:227:28 + 111702: bf ea 89 fe call -0x2ee ## uart_upgrade.c:227:28 + 111706: 41 e0 e8 03 r1 = 0x3e8 ## uart_upgrade.c:227:37 + 11170a: f4 e1 00 01 r0 = r0 / r1 (u) ## uart_upgrade.c:227:37 + 11170e: e0 e1 05 00 r0 = r0 * 0x5 ## uart_upgrade.c:227:25 + 111712: e0 64 [r6+0x10] = r0 ## uart_upgrade.c:227:21 + 111714: 40 21 r0 = 0x1 ## uart_upgrade.c:229:9 + 111716: bf ea b2 fe call -0x29c ## uart_upgrade.c:229:9 + 11171a: 00 ef 20 60 [r6+0x0] |= 0x20 ## uart_upgrade.c:231:20 + 11171e: c0 ff 00 be 02 00 r0 = 0x2be00 ## uart_upgrade.c:105:18 + 111724: e0 67 [r6+0x1c] = r0 ## uart_upgrade.c:104:18 + 111726: d0 23 r0 += 0x43 ## uart_upgrade.c:105:18 + 111728: 70 e1 03 00 r0 = r0 & 0xFFFFFFFC ## uart_upgrade.c:105:18 + 11172c: e0 68 [r6+0x20] = r0 ## uart_upgrade.c:105:18 + 11172e: 49 ea 40 60 [r6+0x24] = 0x40 ## uart_upgrade.c:106:17 + 111732: 56 04 {pc, r6-r4} = [sp++] ## uart_upgrade.c:255:1 + 111734: c0 ff c0 bd 02 00 r0 = 0x2bdc0 ## uart_upgrade.c:241:5 + 11173a: 41 35 r1 = 0x15 ## uart_upgrade.c:241:5 + 11173c: bf ea b7 fe call -0x292 ## uart_upgrade.c:241:5 + 111740: bf ea da fe call -0x24c ## uart_upgrade.c:243:9 + 111744: 80 42 if (r0 != 0) goto 0x4 ## uart_upgrade.c:243:9 + 111746: bf ea ca f5 call -0x146c ## uart_upgrade.c:254:5 + 11174a: bf ea 18 ff call -0x1d0 ## uart_upgrade.c:252:5 + + +check_usb_sof: + 11174e: 7c 04 [--sp] = {rets, r12-r4} ## clock.c:317:0 + 111750: c6 ff 40 13 01 00 r6 = 0x11340 ## clock.c:317:0 + 111756: 47 20 r7 = 0x0 ## clock.c:317:0 + 111758: c8 ff 68 23 11 00 r8 = 0x112368 ## clock.c:317:0 + 11175e: c4 ff 00 07 1e 00 r4 = 0x1e0700 <__stub_doe+0xCDF04 : 1e0700 > ## clock.c:317:0 + 111764: c9 ff 40 10 11 00 r9 = 0x111040 ## clock.c:317:0 + 11176a: 35 e1 00 4f r5 = r4 + -0x100 ## clock.c:317:0 + 11176e: 4a e0 01 40 r10 = 0x4001 ## clock.c:317:0 + 111772: eb e0 94 4c r11 = r4 + 0x4A00 ## clock.c:317:0 + 111776: 0c 16 r12 = r0 ## clock.c:317:0 + 111778: bf ea 7e fe call -0x304 ## clock.c:320:9 + 11177c: e7 61 [r6+0x4] = r7 ## clock.c:324:25 + 11177e: 81 d6 r1 = r8 # ## clock.c:336:9 + 111780: e7 63 [r6+0xc] = r7 ## clock.c:325:22 + 111782: ef 60 h[r6+0x0] = r7 ## clock.c:326:18 + 111784: ef 61 h[r6+0x2] = r7 ## clock.c:327:18 + 111786: e7 62 [r6+0x8] = r7 ## clock.c:328:19 + 111788: 40 27 r0 = 0x7 ## clock.c:336:9 + 11178a: 42 20 r2 = 0x0 ## clock.c:336:9 + 11178c: bf ea ea fc call -0x62c ## clock.c:336:9 + 111790: 40 21 r0 = 0x1 ## clock.c:337:9 + 111792: bf ea 1f fe call -0x3c2 ## clock.c:337:9 + 111796: c7 61 [r4+0x4] = r7 ## clock.c:339:24 + 111798: c7 62 [r4+0x8] = r7 ## clock.c:340:24 + 11179a: 40 ea 1a 40 [r4+0x0] = 0x1A ## clock.c:341:24 + 11179e: 90 16 r0 = r9 ## clock.c:342:26 + 1117a0: bf ea 3a fe call -0x38c ## clock.c:342:26 + 1117a4: 41 e0 e8 03 r1 = 0x3e8 ## clock.c:342:26 + 1117a8: f4 e1 00 01 r0 = r0 / r1 (u) ## clock.c:342:41 + 1117ac: d0 62 [r5+0x8] = r0 ## clock.c:342:24 + 1117ae: d7 61 [r5+0x4] = r7 ## clock.c:343:24 + 1117b0: d0 ec 51 a0 [r5+0x0] = r10 ## clock.c:344:24 + 1117b4: 90 17 r0 = r1.l (u) ## clock.c:347:9 + 1117b6: 00 4a if (r0 == 0) goto 0x14 ## clock.c:347:9 + 1117b8: 00 ef 80 5c [r5+0x0] |= 0x4000 ## clock.c:348:28 + 1117bc: f9 3f r1 += -0x1 ## clock.c:347:23 + 1117be: 50 60 r0 = [r5+0x0] ## clock.c:351:32 + 1117c0: 88 17 r0 = r0.l (s) ## clock.c:351:47 + 1117c2: 80 fd f7 01 ifs (r0 < 0x0) goto -0x12 ## clock.c:351:47 + 1117c6: 60 63 r0 = [r6+0xc] ## clock.c:352:21 + 1117c8: 70 5a if (r0 == 0) goto -0xc ## clock.c:352:21 + 1117ca: 04 8e goto 0x1c ## clock.c:352:21 + 1117cc: c0 ef 40 b0 [r11+0x0] &= 0xFFFFFFBF ## clock.c:360:25 + 1117d0: 40 ea 80 4c [r4+0x0] = 0x4000 ## clock.c:361:24 + 1117d4: 70 28 r0 = 0xc8 ## clock.c:364:9 + 1117d6: bf ea a5 fe call -0x2b6 ## clock.c:364:9 + 1117da: 30 e1 ff cf r0 = r12 + -0x1 ## clock.c:374:19 + 1117de: 61 ff ff c0 c9 ff if ((r12 & 0xFF) != 0) goto -0x6e ## clock.c:374:19 + 1117e4: 42 20 r2 = 0x0 + 1117e6: 04 83 goto 0x6 + 1117e8: 40 ea 80 5c [r5+0x0] = 0x4000 ## clock.c:353:36 + 1117ec: 42 21 r2 = 0x1 ## clock.c:353:36 + 1117ee: 40 21 r0 = 0x1 ## clock.c:385:5 + 1117f0: bf ea 33 fe call -0x39a ## clock.c:385:5 + 1117f4: 20 16 r0 = r2 ## clock.c:387:1 + 1117f6: 5c 04 {pc, r12-r4} = [sp++] ## clock.c:387:1 + + +spi_get_port: + 1117f8: c0 ff 18 51 1e 00 r0 = 0x1e5118 <__stub_doe+0xD291C : 1e5118 > ## spi0.c:34:0 + 1117fe: 00 60 r0 = [r0+0x0] ## spi0.c:35:27 + 111800: b0 e1 08 08 r0 = uextra(r0, p:0x10, l:0x2) ## spi0.c:35:39 + 111804: 80 00 rts ## spi0.c:36:5 + + +skip_atoi: + 111806: 02 60 r2 = [r0+0x0] ## printf-stdarg.c:18:0 + 111808: 41 20 r1 = 0x0 ## printf-stdarg.c:18:0 + 11180a: 04 89 goto 0x12 ## printf-stdarg.c:18:0 + 11180c: 2b 81 r3 = r2 + 0x1 ## printf-stdarg.c:21:29 + 11180e: e1 f1 0a 10 r1 = r1 * 0xA # ## printf-stdarg.c:21:15 + 111812: 83 60 [r0+0x0] = r3 ## printf-stdarg.c:21:29 + 111814: 54 ee 20 20 r2 = b[r2+0x0] (s) ## printf-stdarg.c:21:22 + 111818: 21 18 r1 += r2 ## printf-stdarg.c:21:20 + 11181a: f1 30 r1 += -0x30 ## printf-stdarg.c:21:33 + 11181c: 32 16 r2 = r3 ## printf-stdarg.c:20:12 + 11181e: 2b 40 r3 = b[r2+0x0] (u) ## printf-stdarg.c:20:12 + 111820: f3 30 r3 += -0x30 ## printf-stdarg.c:20:12 + 111822: 33 17 r3 = r3.b0 (u) ## printf-stdarg.c:20:12 + 111824: 83 fc f2 13 if (r3 <= 0x9) goto -0x1c ## printf-stdarg.c:20:12 + 111828: 10 16 r0 = r1 ## printf-stdarg.c:23:5 + 11182a: 80 00 rts ## printf-stdarg.c:23:5 + + +printchar: + 11182c: b0 e8 00 80 if (r0 != 0x0) { ## printf-stdarg.c:29:0 + 111830: 02 60 r2 = [r0+0x0] ## printf-stdarg.c:29:0 + 111832: a9 40 b[r2+0x0] = r1 ## printf-stdarg.c:34:15 + 111834: c0 eb 01 00 [r0+0x0] += 0x1 + } ## printf-stdarg.c:35:9 + 111838: 80 00 rts ## printf-stdarg.c:35:9 + + +prints: + 11183a: 78 04 [--sp] = {rets, r8-r4} ## printf-stdarg.c:57:0 + 11183c: 28 16 r8 = r2 ## printf-stdarg.c:57:0 + 11183e: 16 16 r6 = r1 ## printf-stdarg.c:57:0 + 111840: 82 fd 20 02 ifs (r2 < 0x1) goto 0x40 ## printf-stdarg.c:57:0 + 111844: c2 21 r2 += 0x1 ## printf-stdarg.c:62:30 + 111846: 41 20 r1 = 0x0 ## printf-stdarg.c:62:30 + 111848: 04 81 goto 0x2 ## printf-stdarg.c:62:30 + 11184a: c1 21 r1 += 0x1 ## printf-stdarg.c:64:13 + 11184c: d8 ee 60 41 r4 = b[r6+r1] (u) ## printf-stdarg.c:63:28 + 111850: f4 5c if (r4 != 0) goto -0x8 ## printf-stdarg.c:63:28 + 111852: 2c 1e r4 = r2 - r1 ## printf-stdarg.c:75:9 + 111854: 98 ee 00 01 ifs (r8 <= r1) { ## printf-stdarg.c:75:9 + 111858: 18 16 r8 = r1 + } ## printf-stdarg.c:71:13 + 11185a: b4 e0 82 81 r8 = r8 - r1 ## printf-stdarg.c:71:13 + 11185e: 31 a3 r1 = r3 << 0x3 ## printf-stdarg.c:71:13 + 111860: 61 e1 10 10 r1 = r1 & 0x10 ## printf-stdarg.c:71:13 + 111864: 45 e1 20 10 r5 = r1 | 0x20 ## printf-stdarg.c:71:13 + 111868: 47 20 r7 = 0x0 + 11186a: 53 e8 10 02 if ((r3 & 0x1) != 0) goto 0x20 + 11186e: 88 fd 0e 02 ifs (r8 < 0x1) goto 0x1c + 111872: 51 16 r1 = r5 ## printf-stdarg.c:77:17 + 111874: 61 9b call -0x4a ## printf-stdarg.c:77:17 + 111876: fc 3f r4 += -0x1 ## printf-stdarg.c:76:22 + 111878: c7 21 r7 += 0x1 ## printf-stdarg.c:80:13 + 11187a: 04 fe fa 03 ifs (r4 > 0x1) goto -0xc ## printf-stdarg.c:76:9 + 11187e: 38 e1 ff 4f r8 = r4 + -0x1 ## printf-stdarg.c:58:18 + 111882: 04 85 goto 0xa ## printf-stdarg.c:58:18 + 111884: 47 20 r7 = 0x0 + 111886: 4d 20 r5 = 0x20 + 111888: 04 82 goto 0x4 + 11188a: 61 90 call -0x60 ## printf-stdarg.c:84:13 + 11188c: c7 21 r7 += 0x1 ## printf-stdarg.c:87:9 + 11188e: d4 ee 61 10 r1 = b[r6++=0x1] (s) ## printf-stdarg.c:83:12 + 111892: f1 5b if (r1 != 0) goto -0xa ## printf-stdarg.c:83:5 + 111894: 43 20 r3 = 0x0 + 111896: 04 83 goto 0x6 + 111898: 51 16 r1 = r5 ## printf-stdarg.c:90:13 + 11189a: 61 88 call -0x70 ## printf-stdarg.c:90:13 + 11189c: fb 3f r3 += -0x1 ## printf-stdarg.c:89:5 + 11189e: b4 e0 80 13 r1 = r8 + r3 ## printf-stdarg.c:89:18 + 1118a2: 01 fd f9 03 ifs (r1 >= 0x1) goto -0xe ## printf-stdarg.c:89:18 + 1118a6: f8 1e r0 = r7 - r3 ## printf-stdarg.c:96:5 + 1118a8: 58 04 {pc, r8-r4} = [sp++] ## printf-stdarg.c:96:5 + + +printi: + 1118aa: 79 04 [--sp] = {rets, r9-r4} ## printf-stdarg.c:103:0 + 1118ac: e2 9d sp += -0xc ## printf-stdarg.c:103:0 + 1118ae: d4 e9 2c 80 r8 = [sp+44] ## printf-stdarg.c:103:0 + 1118b2: d4 e9 28 90 r9 = [sp+40] ## printf-stdarg.c:103:0 + 1118b6: 11 54 if (r1 == 0) goto 0x68 ## printf-stdarg.c:103:0 + 1118b8: 44 20 r4 = 0x0 ## printf-stdarg.c:103:0 + 1118ba: de e9 0b 40 b[sp+11] = r4 ## printf-stdarg.c:121:8 + 1118be: 44 21 r4 = 0x1 ## printf-stdarg.c:121:8 + 1118c0: 46 21 r6 = 0x1 ## printf-stdarg.c:115:17 + 1118c2: b2 e8 0a 00 if (r2 != 0xa) { ## printf-stdarg.c:115:17 + 1118c6: 46 20 r6 = 0x0 + } ## printf-stdarg.c:115:17 + 1118c8: 33 e8 00 00 if (r3 == 0x0) { ## printf-stdarg.c:115:17 + 1118cc: 34 16 r4 = r3 + } ## printf-stdarg.c:115:9 + 1118ce: e4 d9 r4 &= r6 # ## printf-stdarg.c:115:12 + 1118d0: 03 2c r3 = [sp+48] ## printf-stdarg.c:115:12 + 1118d2: a6 e0 00 10 r6 = 0x0 - r1 ## printf-stdarg.c:117:13 + 1118d6: 97 bf r7 = r1 >> 0x1f ## printf-stdarg.c:115:28 + 1118d8: 17 ea 00 04 if ((r7 & r4) == 0) { ## printf-stdarg.c:115:28 + 1118dc: 16 16 r6 = r1 + } ## printf-stdarg.c:115:28 + 1118de: c7 19 r7 &= r4 ## printf-stdarg.c:115:12 + 1118e0: 89 80 r1 = sp + 0 ## printf-stdarg.c:115:12 + 1118e2: c1 2a r1 += 0xa ## printf-stdarg.c:115:12 + 1118e4: 05 e1 c6 30 r5 = r3 + 0xc6 ## printf-stdarg.c:115:12 + 1118e8: 04 8d goto 0x1a ## printf-stdarg.c:115:12 + 1118ea: f4 e1 60 42 r4 = r6 / r2 (u) ## printf-stdarg.c:124:15 + 1118ee: f0 e1 40 32 r3 = r4 * r2 ## printf-stdarg.c:124:15 + 1118f2: ee 1e r6 = r6 - r3 ## printf-stdarg.c:124:15 + 1118f4: 53 16 r3 = r5 ## printf-stdarg.c:125:13 + 1118f6: b6 ee 09 00 ifs (r6 <= 0x9) { ## printf-stdarg.c:125:13 + 1118fa: 43 20 r3 = 0x0 + } ## printf-stdarg.c:125:13 + 1118fc: 63 18 r3 += r6 ## printf-stdarg.c:125:13 + 1118fe: cb 30 r3 += 0x30 ## printf-stdarg.c:128:18 + 111900: 46 d6 r6 = r4 # ## printf-stdarg.c:128:18 + 111902: 9b 07 b[r1++=-0x1] = r3 ## printf-stdarg.c:128:14 + 111904: f6 52 if (r6 != 0) goto -0x1c + 111906: 1b 81 r3 = r1 + 0x1 ## printf-stdarg.c:132:9 + 111908: 46 20 r6 = 0x0 ## printf-stdarg.c:132:9 + 11190a: 07 58 if (r7 == 0) goto 0x30 + 11190c: 09 f8 13 00 if (r9 == 0x0) goto 0x26 + 111910: 58 e8 11 08 if ((r8 & 0x2) == 0) goto 0x22 + 111914: 49 2d r1 = 0x2d ## printf-stdarg.c:134:17 + 111916: 41 8a call -0xec ## printf-stdarg.c:134:17 + 111918: 39 e1 ff 9f r9 = r9 + -0x1 ## printf-stdarg.c:134:17 + 11191c: 46 21 r6 = 0x1 ## printf-stdarg.c:134:17 + 11191e: 04 8e goto 0x1c ## printf-stdarg.c:134:17 + 111920: 49 30 r1 = 0x30 ## printf-stdarg.c:110:22 + 111922: de e9 00 10 b[sp] = r1 ## printf-stdarg.c:110:22 + 111926: 41 20 r1 = 0x0 ## printf-stdarg.c:111:22 + 111928: de e9 01 10 b[sp+1] = r1 ## printf-stdarg.c:111:22 + 11192c: 89 80 r1 = sp + 0 ## printf-stdarg.c:111:22 + 11192e: 92 16 r2 = r9 ## printf-stdarg.c:112:16 + 111930: 83 16 r3 = r8 ## printf-stdarg.c:112:16 + 111932: 41 83 call -0xfa ## printf-stdarg.c:112:16 + 111934: 04 89 goto 0x12 ## printf-stdarg.c:112:16 + 111936: 4a 2d r2 = 0x2d ## printf-stdarg.c:139:18 + 111938: 13 d6 r3 = r1 # ## printf-stdarg.c:139:18 + 11193a: 9a 40 b[r1+0x0] = r2 ## printf-stdarg.c:139:18 + 11193c: 31 16 r1 = r3 ## printf-stdarg.c:143:17 + 11193e: 92 16 r2 = r9 ## printf-stdarg.c:143:17 + 111940: 83 16 r3 = r8 ## printf-stdarg.c:143:17 + 111942: bf ea 7a ff call -0x10c ## printf-stdarg.c:143:17 + 111946: 60 18 r0 += r6 ## printf-stdarg.c:143:15 + 111948: 02 83 sp += 0xc + 11194a: 59 04 {pc, r9-r4} = [sp++] ## printf-stdarg.c:144:1 + + +print: + 11194c: 7c 04 [--sp] = {rets, r12-r4} ## printf-stdarg.c:147:0 + 11194e: e2 9a sp += -0x18 ## printf-stdarg.c:147:0 + 111950: 04 d6 r4 = r0 # ## printf-stdarg.c:147:0 + 111952: 81 25 [sp+20] = r1 ## printf-stdarg.c:147:0 + 111954: c1 d4 r9 = 0 # ## printf-stdarg.c:147:0 + 111956: 82 24 [sp+16] = r2 ## printf-stdarg.c:147:0 + 111958: f8 e8 0e 80 r8 = sp + 14 ## printf-stdarg.c:147:0 + 11195c: 4a e0 41 00 r10 = 0x41 ## printf-stdarg.c:147:0 + 111960: 4b e0 61 00 r11 = 0x61 ## printf-stdarg.c:147:0 + 111964: cc ff 98 10 11 00 r12 = 0x111098 ## printf-stdarg.c:147:0 + 11196a: 45 20 r5 = 0x0 ## printf-stdarg.c:147:0 + 11196c: 74 92 goto 0x1e4 <.GJTIE36_0_0_+0x116 : 111b52 > ## printf-stdarg.c:147:0 + 11196e: 1a 81 r2 = r1 + 0x1 ## printf-stdarg.c:154:13 + 111970: 82 25 [sp+20] = r2 ## printf-stdarg.c:154:13 + 111972: 18 41 r0 = b[r1+0x1] (u) ## printf-stdarg.c:156:17 + 111974: 00 f8 05 4a if (r0 == 0x25) goto 0xa ## printf-stdarg.c:156:17 + 111978: 00 f8 0a 5a if (r0 == 0x2d) goto 0x14 + 11197c: 47 20 r7 = 0x0 + 11197e: 80 4f if (r0 != 0) goto 0x1e + 111980: 74 8d goto 0x1da <.GJTIE36_0_0_+0x120 : 111b5c > + 111982: 48 25 r0 = 0x25 + 111984: 09 17 r1 = r0.b0 (s) ## printf-stdarg.c:276:39 + 111986: 40 16 r0 = r4 ## printf-stdarg.c:276:19 + 111988: bf ea 50 ff call -0x160 ## printf-stdarg.c:276:19 + 11198c: c5 21 r5 += 0x1 ## printf-stdarg.c:276:16 + 11198e: 24 96 goto 0xac <.GJTIE36_0_0_ : 111a3c > + 111990: 1a 82 r2 = r1 + 0x2 ## printf-stdarg.c:163:17 + 111992: 82 25 [sp+20] = r2 ## printf-stdarg.c:163:17 + 111994: 47 21 r7 = 0x1 + 111996: 04 83 goto 0x6 + 111998: c2 21 r2 += 0x1 ## printf-stdarg.c:167:17 + 11199a: 82 25 [sp+20] = r2 ## printf-stdarg.c:167:17 + 11199c: 37 21 r7 |= 0x2 ## printf-stdarg.c:168:21 + 11199e: 29 40 r1 = b[r2+0x0] (u) ## printf-stdarg.c:166:20 + 1119a0: 01 f8 fa 61 if (r1 == 0x30) goto -0xc ## printf-stdarg.c:166:20 + 1119a4: 30 e1 d0 1f r0 = r1 + -0x30 ## printf-stdarg.c:172:17 + 1119a8: 00 17 r0 = r0.b0 (u) ## printf-stdarg.c:172:17 + 1119aa: 16 3f r6 = -0x1 ## printf-stdarg.c:172:17 + 1119ac: 00 fc 06 12 if (r0 > 0x9) goto 0xc ## printf-stdarg.c:172:17 + 1119b0: 88 94 r0 = sp + 20 + 1119b2: bf ea 28 ff call -0x1b0 ## printf-stdarg.c:173:25 + 1119b6: 06 d6 r6 = r0 # ## printf-stdarg.c:173:25 + 1119b8: 02 25 r2 = [sp+20] ## printf-stdarg.c:173:25 + 1119ba: 29 40 r1 = b[r2+0x0] (u) ## printf-stdarg.c:173:25 + 1119bc: 81 f8 0d 5c if (r1 != 0x2e) goto 0x1a + 1119c0: 28 81 r0 = r2 + 0x1 ## printf-stdarg.c:178:17 + 1119c2: 80 25 [sp+20] = r0 ## printf-stdarg.c:178:17 + 1119c4: 29 41 r1 = b[r2+0x1] (u) ## printf-stdarg.c:179:21 + 1119c6: 33 e1 d0 1f r3 = r1 + -0x30 ## printf-stdarg.c:179:21 + 1119ca: 33 17 r3 = r3.b0 (u) ## printf-stdarg.c:179:21 + 1119cc: 03 fc 07 12 if (r3 > 0x9) goto 0xe ## printf-stdarg.c:179:21 + 1119d0: 88 94 r0 = sp + 20 + 1119d2: bf ea 18 ff call -0x1d0 ## printf-stdarg.c:180:33 + 1119d6: 00 25 r0 = [sp+20] + 1119d8: 04 89 goto 0x12 + 1119da: 20 16 r0 = r2 ## printf-stdarg.c:250:18 + 1119dc: 04 87 goto 0xe ## printf-stdarg.c:250:18 + 1119de: 31 e8 2a c0 if (r1 == 0x2a) { + 1119e2: 88 90 r0 = sp + 16 + 1119e4: c0 eb 04 00 [r0+0x0] += 0x4 ## printf-stdarg.c:183:33 + 1119e8: 28 82 r0 = r2 + 0x2 ## printf-stdarg.c:182:21 + 1119ea: 80 25 [sp+20] = r0 + } ## printf-stdarg.c:182:21 + 1119ec: 09 40 r1 = b[r0+0x0] (u) + 1119ee: 32 e1 90 1f r2 = r1 + -0x70 ## printf-stdarg.c:193:17 + 1119f2: 82 fc 1d 10 if (r2 <= 0x8) goto 0x3a ## printf-stdarg.c:193:17 + 1119f6: 01 f8 3d 98 if (r1 == 0x4c) goto 0x7a <.GJTIE36_0_0_+0x38 : 111a74 > + 1119fa: 01 f8 45 b0 if (r1 == 0x58) goto 0x8a <.GJTIE36_0_0_+0x4C : 111a88 > + 1119fe: 01 f8 52 c6 if (r1 == 0x63) goto 0xa4 <.GJTIE36_0_0_+0x6A : 111aa6 > + 111a02: 01 f8 5f c8 if (r1 == 0x64) goto 0xbe <.GJTIE36_0_0_+0x88 : 111ac4 > + 111a06: 81 f8 19 d8 if (r1 != 0x6c) goto 0x32 <.GJTIE36_0_0_ : 111a3c > + 111a0a: 09 41 r1 = b[r0+0x1] (u) ## printf-stdarg.c:202:39 + 111a0c: 01 f8 64 f0 if (r1 == 0x78) goto 0xc8 <.GJTIE36_0_0_+0x9C : 111ad8 > ## printf-stdarg.c:202:39 + 111a10: 01 f8 6b d8 if (r1 == 0x6c) goto 0xd6 <.GJTIE36_0_0_+0xAE : 111aea > + 111a14: 01 f8 76 ea if (r1 == 0x75) goto 0xec <.GJTIE36_0_0_+0xC8 : 111b04 > + 111a18: 81 f8 10 c8 if (r1 != 0x64) goto 0x20 <.GJTIE36_0_0_ : 111a3c > + 111a1c: 00 24 r0 = [sp+16] ## printf-stdarg.c:203:40 + 111a1e: 09 84 r1 = r0 + 0x4 ## printf-stdarg.c:203:40 + 111a20: 81 24 [sp+16] = r1 ## printf-stdarg.c:203:40 + 111a22: 01 60 r1 = [r0+0x0] ## printf-stdarg.c:203:40 + 111a24: d4 e9 09 b0 [sp+8] = r11 ## printf-stdarg.c:203:23 + 111a28: 87 21 [sp+4] = r7 ## printf-stdarg.c:203:23 + 111a2a: 42 2a r2 = 0xa ## printf-stdarg.c:203:23 + 111a2c: 43 21 r3 = 0x1 ## printf-stdarg.c:203:23 + 111a2e: 34 93 goto 0xe6 <.GJTIE36_0_0_+0xDA : 111b16 > ## printf-stdarg.c:203:23 + 111a30: 02 01 tbb [r2] + + +.GJTIS36_0_0_: + 111a32: 09 < 9 : 0x9 > + 111a33: 05 < 5 : 0x5 > + 111a34: 05 < 5 : 0x5 > + 111a35: 10 < 16 : 0x10 > + 111a36: 05 < 5 : 0x5 > + 111a37: 18 < 24 : 0x18 > + 111a38: 05 < 5 : 0x5 > + 111a39: 05 < 5 : 0x5 > + 111a3a: 09 < 9 : 0x9 > + 111a3b: 00 < 0 : 0x0 > + 111a3c: 00 25 r0 = [sp+20] ## printf-stdarg.c:152:26 + 111a3e: 09 81 r1 = r0 + 0x1 ## printf-stdarg.c:152:26 + 111a40: 81 25 [sp+20] = r1 ## printf-stdarg.c:152:26 + 111a42: 44 87 goto 0x10e <.GJTIE36_0_0_+0x116 : 111b52 > ## printf-stdarg.c:152:26 + 111a44: 00 24 r0 = [sp+16] + 111a46: 09 84 r1 = r0 + 0x4 + 111a48: 81 24 [sp+16] = r1 + 111a4a: 01 60 r1 = [r0+0x0] + 111a4c: d4 e9 09 b0 [sp+8] = r11 + 111a50: 14 81 goto 0x42 <.GJTIE36_0_0_+0x58 : 111a94 > + 111a52: 00 24 r0 = [sp+16] ## printf-stdarg.c:194:44 + 111a54: 09 84 r1 = r0 + 0x4 ## printf-stdarg.c:194:44 + 111a56: 81 24 [sp+16] = r1 ## printf-stdarg.c:194:44 + 111a58: 01 60 r1 = [r0+0x0] ## printf-stdarg.c:194:44 + 111a5a: 31 e8 00 00 if (r1 == 0x0) { + 111a5e: c1 16 r1 = r12 + } ## printf-stdarg.c:195:40 + 111a60: 14 8b goto 0x56 <.GJTIE36_0_0_+0x7C : 111ab8 > + 111a62: 00 24 r0 = [sp+16] ## printf-stdarg.c:236:40 + 111a64: 09 84 r1 = r0 + 0x4 ## printf-stdarg.c:236:40 + 111a66: 81 24 [sp+16] = r1 ## printf-stdarg.c:236:40 + 111a68: 01 60 r1 = [r0+0x0] ## printf-stdarg.c:236:40 + 111a6a: d4 e9 09 b0 [sp+8] = r11 ## printf-stdarg.c:236:23 + 111a6e: 87 21 [sp+4] = r7 ## printf-stdarg.c:236:23 + 111a70: 42 2a r2 = 0xa ## printf-stdarg.c:236:23 + 111a72: 04 92 goto 0x24 <.GJTIE36_0_0_+0x5C : 111a98 > ## printf-stdarg.c:236:23 + 111a74: 08 41 r0 = b[r0+0x1] (u) ## printf-stdarg.c:230:39 + 111a76: 80 f8 e1 b1 if (r0 != 0x58) goto -0x3e <.GJTIE36_0_0_ : 111a3c > + 111a7a: 00 24 r0 = [sp+16] ## printf-stdarg.c:231:40 + 111a7c: 09 84 r1 = r0 + 0x4 ## printf-stdarg.c:231:40 + 111a7e: 81 24 [sp+16] = r1 ## printf-stdarg.c:231:40 + 111a80: 01 60 r1 = [r0+0x0] ## printf-stdarg.c:231:40 + 111a82: d4 e9 09 a0 [sp+8] = r10 ## printf-stdarg.c:231:23 + 111a86: 14 8e goto 0x5c <.GJTIE36_0_0_+0xA8 : 111ae4 > ## printf-stdarg.c:231:23 + 111a88: 00 24 r0 = [sp+16] ## printf-stdarg.c:227:40 + 111a8a: 09 84 r1 = r0 + 0x4 ## printf-stdarg.c:227:40 + 111a8c: 81 24 [sp+16] = r1 ## printf-stdarg.c:227:40 + 111a8e: 01 60 r1 = [r0+0x0] ## printf-stdarg.c:227:40 + 111a90: d4 e9 09 a0 [sp+8] = r10 ## printf-stdarg.c:227:23 + 111a94: 87 21 [sp+4] = r7 + 111a96: 42 30 r2 = 0x10 + 111a98: 43 20 r3 = 0x0 + 111a9a: 40 d6 r0 = r4 # + 111a9c: 86 20 [sp] = r6 + 111a9e: bf ea 04 ff call -0x1f8 + 111aa2: 05 18 r5 += r0 + 111aa4: e7 8b goto -0x6a <.GJTIE36_0_0_ : 111a3c > + 111aa6: 00 24 r0 = [sp+16] ## printf-stdarg.c:252:32 + 111aa8: 09 84 r1 = r0 + 0x4 ## printf-stdarg.c:252:32 + 111aaa: 81 24 [sp+16] = r1 ## printf-stdarg.c:252:32 + 111aac: 00 60 r0 = [r0+0x0] ## printf-stdarg.c:252:32 + 111aae: de e9 0e 00 b[sp+14] = r0 ## printf-stdarg.c:252:24 + 111ab2: 52 ee 81 90 b[r8+0x1] = r9 ## printf-stdarg.c:253:24 + 111ab6: 89 8e r1 = sp + 14 ## printf-stdarg.c:253:24 + 111ab8: 40 16 r0 = r4 + 111aba: 62 15 r3_r2 = r7_r6 + 111abc: bf ea bd fe call -0x286 + 111ac0: 05 18 r5 += r0 + 111ac2: d7 9c goto -0x88 <.GJTIE36_0_0_ : 111a3c > + 111ac4: 00 24 r0 = [sp+16] ## printf-stdarg.c:199:40 + 111ac6: 09 84 r1 = r0 + 0x4 ## printf-stdarg.c:199:40 + 111ac8: 81 24 [sp+16] = r1 ## printf-stdarg.c:199:40 + 111aca: 01 60 r1 = [r0+0x0] ## printf-stdarg.c:199:40 + 111acc: d4 e9 09 b0 [sp+8] = r11 ## printf-stdarg.c:199:23 + 111ad0: 87 21 [sp+4] = r7 ## printf-stdarg.c:199:23 + 111ad2: 42 2a r2 = 0xa ## printf-stdarg.c:199:23 + 111ad4: 43 21 r3 = 0x1 ## printf-stdarg.c:199:23 + 111ad6: f7 81 goto -0x3e <.GJTIE36_0_0_+0x5E : 111a9a > ## printf-stdarg.c:199:23 + 111ad8: 00 24 r0 = [sp+16] ## printf-stdarg.c:222:40 + 111ada: 09 84 r1 = r0 + 0x4 ## printf-stdarg.c:222:40 + 111adc: 81 24 [sp+16] = r1 ## printf-stdarg.c:222:40 + 111ade: 01 60 r1 = [r0+0x0] ## printf-stdarg.c:222:40 + 111ae0: d4 e9 09 b0 [sp+8] = r11 ## printf-stdarg.c:222:23 + 111ae4: 87 21 [sp+4] = r7 + 111ae6: 42 30 r2 = 0x10 + 111ae8: 04 95 goto 0x2a <.GJTIE36_0_0_+0xD8 : 111b14 > + 111aea: 09 42 r1 = b[r0+0x2] (u) ## printf-stdarg.c:207:67 + 111aec: 81 f8 1c c8 if (r1 != 0x64) goto 0x38 <.GJTIE36_0_0_+0xEC : 111b28 > ## printf-stdarg.c:207:17 + 111af0: 00 24 r0 = [sp+16] ## printf-stdarg.c:208:40 + 111af2: 09 88 r1 = r0 + 0x8 ## printf-stdarg.c:208:40 + 111af4: 81 24 [sp+16] = r1 ## printf-stdarg.c:208:40 + 111af6: 01 60 r1 = [r0+0x0] ## printf-stdarg.c:208:40 + 111af8: d4 e9 09 b0 [sp+8] = r11 ## printf-stdarg.c:208:23 + 111afc: 87 21 [sp+4] = r7 ## printf-stdarg.c:208:23 + 111afe: 42 2a r2 = 0xa ## printf-stdarg.c:208:23 + 111b00: 43 21 r3 = 0x1 ## printf-stdarg.c:208:23 + 111b02: 04 9e goto 0x3c <.GJTIE36_0_0_+0x104 : 111b40 > ## printf-stdarg.c:208:23 + 111b04: 00 24 r0 = [sp+16] ## printf-stdarg.c:240:40 + 111b06: 09 84 r1 = r0 + 0x4 ## printf-stdarg.c:240:40 + 111b08: 81 24 [sp+16] = r1 ## printf-stdarg.c:240:40 + 111b0a: 01 60 r1 = [r0+0x0] ## printf-stdarg.c:240:40 + 111b0c: d4 e9 09 b0 [sp+8] = r11 ## printf-stdarg.c:240:23 + 111b10: 87 21 [sp+4] = r7 ## printf-stdarg.c:240:23 + 111b12: 42 2a r2 = 0xa ## printf-stdarg.c:240:23 + 111b14: 43 20 r3 = 0x0 + 111b16: 40 d6 r0 = r4 # + 111b18: 86 20 [sp] = r6 + 111b1a: bf ea c6 fe call -0x274 + 111b1e: 89 94 r1 = sp + 20 + 111b20: c0 eb 01 10 [r1+0x0] += 0x1 + 111b24: 05 18 r5 += r0 + 111b26: c7 8a goto -0xec <.GJTIE36_0_0_ : 111a3c > + 111b28: 08 42 r0 = b[r0+0x2] (u) ## printf-stdarg.c:244:67 + 111b2a: 80 f8 87 eb if (r0 != 0x75) goto -0xf2 <.GJTIE36_0_0_ : 111a3c > + 111b2e: 00 24 r0 = [sp+16] ## printf-stdarg.c:245:40 + 111b30: 09 88 r1 = r0 + 0x8 ## printf-stdarg.c:245:40 + 111b32: 81 24 [sp+16] = r1 ## printf-stdarg.c:245:40 + 111b34: 01 60 r1 = [r0+0x0] ## printf-stdarg.c:245:40 + 111b36: d4 e9 09 b0 [sp+8] = r11 ## printf-stdarg.c:245:23 + 111b3a: 87 21 [sp+4] = r7 ## printf-stdarg.c:245:23 + 111b3c: 42 2a r2 = 0xa ## printf-stdarg.c:245:23 + 111b3e: 43 20 r3 = 0x0 ## printf-stdarg.c:245:23 + 111b40: 40 d6 r0 = r4 # + 111b42: 86 20 [sp] = r6 + 111b44: bf ea b1 fe call -0x29e + 111b48: 89 94 r1 = sp + 20 + 111b4a: c0 eb 02 10 [r1+0x0] += 0x2 + 111b4e: 05 18 r5 += r0 + 111b50: b7 95 goto -0x116 <.GJTIE36_0_0_ : 111a3c > + 111b52: 18 40 r0 = b[r1+0x0] (u) ## printf-stdarg.c:152:12 + 111b54: 00 f8 0b 4b if (r0 == 0x25) goto -0x1ea ## printf-stdarg.c:152:5 + 111b58: 80 f8 14 01 if (r0 != 0x0) goto -0x1d8 + 111b5c: b4 e8 00 80 if (r4 != 0x0) { + 111b60: 40 60 r0 = [r4+0x0] ## printf-stdarg.c:280:10 + 111b62: 41 20 r1 = 0x0 ## printf-stdarg.c:280:15 + 111b64: 89 40 b[r0+0x0] = r1 + } ## printf-stdarg.c:280:15 + 111b66: 50 16 r0 = r5 ## printf-stdarg.c:283:5 + 111b68: 02 86 sp += 0x18 ## printf-stdarg.c:283:5 + 111b6a: 5c 04 {pc, r12-r4} = [sp++] ## printf-stdarg.c:283:5 + + +printf: + 111b6c: 61 04 [--sp] = {r3-r1} ## printf-stdarg.c:331:0 + 111b6e: 74 04 [--sp] = {rets, r4} ## printf-stdarg.c:331:0 + 111b70: e2 9f sp += -0x4 ## printf-stdarg.c:331:0 + 111b72: 8a 8c r2 = sp + 12 ## printf-stdarg.c:331:0 + 111b74: 04 d6 r4 = r0 # ## printf-stdarg.c:331:0 + 111b76: 82 20 [sp] = r2 ## printf-stdarg.c:335:5 + 111b78: 40 20 r0 = 0x0 ## printf-stdarg.c:365:11 + 111b7a: 41 16 r1 = r4 ## printf-stdarg.c:365:11 + 111b7c: bf ea e6 fe call -0x234 ## printf-stdarg.c:365:11 + 111b80: 02 81 sp += 0x4 + 111b82: 34 04 {rets, r4} = [sp++] ## printf-stdarg.c:368:5 + 111b84: 02 83 sp += 0xc ## printf-stdarg.c:368:5 + 111b86: 80 00 rts ## printf-stdarg.c:368:5 + + +SPI0_cs: + 111b88: 10 04 [--sp] = rets ## spi0.c:178:0 + 111b8a: 01 16 r1 = r0 ## spi0.c:178:0 + 111b8c: bf ea 34 fe call -0x398 ## spi0.c:179:16 + 111b90: 00 4b if (r0 == 0) goto 0x16 + 111b92: c0 ff 00 50 1e 00 r0 = 0x1e5000 <__stub_doe+0xD2804 : 1e5000 > + 111b98: c2 ef 00 0d [r0+0x8] &= 0xFFFFDFFF ## spi0.c:184:23 + 111b9c: 02 60 r2 = [r0+0x0] ## spi0.c:184:23 + 111b9e: 73 e1 00 2d r3 = r2 & 0xFFFFDFFF ## spi0.c:185:64 + 111ba2: 32 2d r2 |= 0x2000 ## spi0.c:185:29 + 111ba4: 01 4b if (r1 == 0) goto 0x16 ## spi0.c:185:29 + 111ba6: 04 8b goto 0x16 ## spi0.c:185:29 + 111ba8: c0 ff c0 50 1e 00 r0 = 0x1e50c0 <__stub_doe+0xD28C4 : 1e50c0 > + 111bae: c2 ef 08 00 [r0+0x8] &= 0xFFFFFFF7 ## spi0.c:181:23 + 111bb2: 02 60 r2 = [r0+0x0] ## spi0.c:181:23 + 111bb4: 73 e1 08 20 r3 = r2 & 0xFFFFFFF7 ## spi0.c:182:64 + 111bb8: 32 23 r2 |= 0x8 ## spi0.c:182:29 + 111bba: 81 41 if (r1 != 0) goto 0x2 ## spi0.c:182:29 + 111bbc: 32 16 r2 = r3 + 111bbe: 82 60 [r0+0x0] = r2 + 111bc0: 00 04 pc = [sp++] ## spi0.c:187:1 + + +spi0_wait_ok: + 111bc2: c0 ff 00 1c 1e 00 r0 = 0x1e1c00 <__stub_doe+0xCF404 : 1e1c00 > ## spi0.c:236:0 + 111bc8: 01 60 r1 = [r0+0x0] ## spi0.c:237:23 + 111bca: 51 e8 fd 79 if ((r1 & 0x8000) == 0) goto -0x6 ## spi0.c:237:5 + 111bce: 00 ef 80 0c [r0+0x0] |= 0x4000 ## spi0.c:239:18 + 111bd2: 80 00 rts ## spi0.c:239:18 + + +SPI0_WriteByte: + 111bd4: c1 ff 00 1c 1e 00 r1 = 0x1e1c00 <__stub_doe+0xCF404 : 1e1c00 > ## spi0.c:259:0 + 111bda: c0 ef 80 1d [r1+0x0] &= 0xFFFFEFFF ## spi0.c:260:18 + 111bde: 90 62 [r1+0x8] = r0 ## spi0.c:261:18 + 111be0: f7 90 goto -0x20 ## spi0.c:262:5 + + +SPI0_ReadByte: + 111be2: 10 04 [--sp] = rets ## spi0.c:279:0 + 111be4: c2 ff 00 1c 1e 00 r2 = 0x1e1c00 <__stub_doe+0xCF404 : 1e1c00 > ## spi0.c:279:0 + 111bea: 00 ef 80 2d [r2+0x0] |= 0x1000 ## spi0.c:281:18 + 111bee: 40 2a r0 = 0xa ## spi0.c:282:5 + 111bf0: bf ea 42 fb call -0x97c ## spi0.c:282:5 + 111bf4: 42 ea ff 20 [r2+0x8] = 0xFF ## spi0.c:283:18 + 111bf8: 71 84 call -0x38 ## spi0.c:284:5 + 111bfa: 20 62 r0 = [r2+0x8] ## spi0.c:285:25 + 111bfc: 00 17 r0 = r0.b0 (u) ## spi0.c:287:5 + 111bfe: 00 04 pc = [sp++] ## spi0.c:287:5 + + +SPI0_4WriteByte: + 111c00: 10 04 [--sp] = rets ## spi0.c:318:0 + 111c02: c2 ff 00 1c 1e 00 r2 = 0x1e1c00 <__stub_doe+0xCF404 : 1e1c00 > ## spi0.c:318:0 + 111c08: c0 ef 80 2e [r2+0x0] &= 0xFFFFFBFF ## spi0.c:320:18 + 111c0c: 00 ef 00 2e [r2+0x0] |= 0x800 ## spi0.c:321:18 + 111c10: c0 ef 80 2d [r2+0x0] &= 0xFFFFEFFF ## spi0.c:323:18 + 111c14: a0 62 [r2+0x8] = r0 ## spi0.c:324:18 + 111c16: 61 95 call -0x56 ## spi0.c:326:5 + 111c18: c0 ef 40 2e [r2+0x0] &= 0xFFFFF3FF ## spi0.c:329:18 + 111c1c: 00 04 pc = [sp++] ## spi0.c:330:1 + + +Run_App: + 111c1e: 7b 04 [--sp] = {rets, r11-r4} ## bankSwitch.c:11:0 + 111c20: e2 8c sp += -0x50 ## bankSwitch.c:11:0 + 111c22: 04 16 r4 = r0 ## bankSwitch.c:11:0 + 111c24: 04 eb 05 00 {r2, r0} = [r4+] ## sdfile.c:29:60 + 111c28: ad 90 r5 = sp + 48 ## sdfile.c:29:60 + 111c2a: 4b 20 r3 = 0x20 ## sdfile.c:29:5 + 111c2c: 51 d6 r1 = r5 # ## sdfile.c:29:5 + 111c2e: 46 63 r6 = [r4+0xc] ## sdfile.c:29:11 + 111c30: c6 00 call r6 ## sdfile.c:29:5 + 111c32: 40 e1 02 50 r0 = r5 | 0x2 ## sdfile.c:32:24 + 111c36: 41 3e r1 = 0x1e ## sdfile.c:32:12 + 111c38: bf ea 4f fc call -0x762 ## sdfile.c:32:12 + 111c3c: 20 46 if (r0 == 0) goto 0x8c ## sdfile.c:32:12 + 111c3e: d8 e9 30 10 r1 = h[sp+48] (u) ## sdfile.c:35:29 + 111c42: 80 e8 42 10 if (r1 != r0) goto 0x84 ## sdfile.c:35:29 + 111c46: 50 ec 40 00 r1_r0 = d[r4+0x0] ## sdfile.c:37:31 + 111c4a: 02 f1 20 10 r2 = r1 + 0x20 # ## sdfile.c:37:96 + 111c4e: 45 63 r5 = [r4+0xc] ## sdfile.c:37:15 + 111c50: 89 90 r1 = sp + 16 ## sdfile.c:37:15 + 111c52: 4b 20 r3 = 0x20 ## sdfile.c:37:9 + 111c54: c5 00 call r5 ## sdfile.c:37:9 + 111c56: 05 25 r5 = [sp+20] ## sdfile.c:41:33 + 111c58: f8 e8 00 80 r8 = sp + 0 ## sdfile.c:41:33 + 111c5c: 17 3c r7 = -0x4 ## sdfile.c:41:33 + 111c5e: 04 92 goto 0x24 ## sdfile.c:41:33 + 111c60: 50 ec 40 00 r1_r0 = d[r4+0x0] ## bankSwitch.c:24:57 + 111c64: 5a dc r2 = r5 + r1 # ## bankSwitch.c:24:68 + 111c66: 46 63 r6 = [r4+0xc] ## bankSwitch.c:24:19 + 111c68: 89 80 r1 = sp + 0 ## bankSwitch.c:24:19 + 111c6a: 43 30 r3 = 0x10 ## bankSwitch.c:24:13 + 111c6c: c6 00 call r6 ## bankSwitch.c:24:13 + 111c6e: 00 49 if (r0 == 0) goto 0x12 ## bankSwitch.c:24:13 + 111c70: 88 80 r0 = sp + 0 + 111c72: 41 2e r1 = 0xe ## bankSwitch.c:25:19 + 111c74: bf ea 31 fc call -0x79e ## bankSwitch.c:25:19 + 111c78: 00 44 if (r0 == 0) goto 0x8 ## bankSwitch.c:25:19 + 111c7a: 50 ed 8e 10 r1 = h[r8+0xe] (u) ## bankSwitch.c:29:32 + 111c7e: 00 e8 03 10 if (r1 == r0) goto 0x6 ## bankSwitch.c:29:32 + 111c82: c7 21 r7 += 0x1 ## bankSwitch.c:16:13 + 111c84: f7 4d if (r7 != 0) goto -0x26 + 111c86: 14 81 goto 0x42 + 111c88: f8 e8 00 b0 r11 = sp + 0 + 111c8c: d4 e9 04 80 r8 = [sp+4] ## bankSwitch.c:30:35 + 111c90: 49 e1 02 b0 r9 = r11 | 0x2 + 111c94: 16 3c r6 = -0x4 + 111c96: ca ff 04 35 1e 00 r10 = 0x1e3504 <__stub_doe+0xD0D08 : 1e3504 > + 111c9c: 04 95 goto 0x2a + 111c9e: 50 ec 40 00 r1_r0 = d[r4+0x0] ## bankSwitch.c:44:66 + 111ca2: d0 ec b8 20 r2 = [r11+0x8] ## bankSwitch.c:44:98 + 111ca6: 50 ed 90 30 r3 = h[r9+0x0] (u) ## bankSwitch.c:44:104 + 111caa: 51 d8 r1 += r5 # ## bankSwitch.c:44:77 + 111cac: 47 63 r7 = [r4+0xc] ## bankSwitch.c:44:19 + 111cae: 12 18 r2 += r1 ## bankSwitch.c:44:89 + 111cb0: 81 16 r1 = r8 ## bankSwitch.c:44:13 + 111cb2: c7 00 call r7 ## bankSwitch.c:44:13 + 111cb4: 00 48 if (r0 == 0) goto 0x10 ## bankSwitch.c:44:13 + 111cb6: d0 ec a0 00 r0 = [r10+0x0] ## bankSwitch.c:52:27 + 111cba: 50 ed bc 10 r1 = h[r11+0xc] (u) ## bankSwitch.c:58:24 + 111cbe: 80 17 r0 = r0.l (u) ## bankSwitch.c:58:28 + 111cc0: 80 e8 01 10 if (r1 != r0) goto 0x2 ## bankSwitch.c:58:28 + 111cc4: 80 44 if (r0 != 0) goto 0x8 + 111cc6: c6 21 r6 += 0x1 ## bankSwitch.c:16:13 + 111cc8: f6 4a if (r6 != 0) goto -0x2c + 111cca: 02 94 sp += 0x50 + 111ccc: 5b 04 {pc, r11-r4} = [sp++] ## bankSwitch.c:88:1 + 111cce: 64 e0 00 0b r0 = icfg ## bankSwitch.c:76:5 + 111cd2: b8 28 r0 &= 0xfffffeff ## bankSwitch.c:77:9 + 111cd4: 64 e0 80 0b icfg = r0 ## bankSwitch.c:78:5 + 111cd8: 60 00 cli ## bankSwitch.c:79:5 + 111cda: c2 ff e0 be 02 00 r2 = 0x2bee0 ## bankSwitch.c:85:5 + 111ce0: 40 15 r1_r0 = r5_r4 ## bankSwitch.c:85:5 + 111ce2: c8 00 call r8 ## bankSwitch.c:85:5 + 111ce4: f7 9f goto -0x2 ## bankSwitch.c:87:5 + + +spi_portd_a: + 111ce6: 7c 04 [--sp] = {rets, r12-r4} ## boot_flash.c:73:0 + 111ce8: c4 ff 52 10 11 00 r4 = 0x111052 ## boot_flash.c:73:0 + 111cee: 49 8e r1 = r4 + 0xe ## boot_flash.c:77:5 + 111cf0: c5 ff cc be 02 00 r5 = 0x2becc ## boot_flash.c:77:5 + 111cf6: 42 30 r2 = 0x10 ## boot_flash.c:77:5 + 111cf8: 50 16 r0 = r5 ## boot_flash.c:77:5 + 111cfa: bf ea b0 f1 call -0x1ca0 ## boot_flash.c:77:5 + 111cfe: c0 ff c4 be 02 00 r0 = 0x2bec4 ## boot_flash.c:79:27 + 111d04: d0 ec 00 b0 r11 = [r0+0x0] ## boot_flash.c:79:27 + 111d08: c0 ff 00 02 1f 00 r0 = 0x1f0200 <__stub_doe+0xDDA04 : 1f0200 > ## spi0.c:213:17 + 111d0e: 40 ea 00 00 [r0+0x0] = 0x0 ## spi0.c:213:17 + 111d12: c8 ff 00 1c 1e 00 r8 = 0x1e1c00 <__stub_doe+0xCF404 : 1e1c00 > ## spi0.c:213:17 + 111d18: 40 ea 20 80 [r8+0x0] = 0x20 ## spi0.c:214:18 + 111d1c: 50 ee b1 00 r0 = b[r11+0x1] (u) ## spi0.c:215:28 + 111d20: d0 ec 85 00 [r8+0x4] = r0 ## spi0.c:215:19 + 111d24: 50 ed b0 00 r0 = h[r11+0x0] (u) ## spi0.c:217:26 + 111d28: ca ff c8 50 1e 00 r10 = 0x1e50c8 <__stub_doe+0xD28CC : 1e50c8 > + 111d2e: d4 ef 40 ab [r10+0x50] &= 0xFFFCFFFF ## spi0.c:40:20 + 111d32: 80 a3 r0 = r0 >> 0x3 ## spi0.c:217:26 + 111d34: 61 e1 1f 00 r1 = r0 & 0x1F ## spi0.c:217:26 + 111d38: 11 b0 r1 = r1 << 0x10 ## spi0.c:41:29 + 111d3a: 64 e8 50 a1 [r10+0x50] |= r1 ## spi0.c:41:20 + 111d3e: 60 ff 1f 00 0f 00 if ((r0 & 0x1F) == 0) goto 0x1e ## spi0.c:41:20 + 111d44: 49 e0 ff bf r9 = -0x4001 + 111d48: 41 e0 00 40 r1 = 0x4000 + 111d4c: 32 e1 4c af r2 = r10 + -0xb4 + 111d50: 33 e1 fc 2f r3 = r2 + -0x4 + 111d54: 47 e0 ff df r7 = -0x2001 + 111d58: 30 e1 f4 2f r0 = r2 + -0xc + 111d5c: 4c e0 00 20 r12 = 0x2000 + 111d60: 04 8b goto 0x16 + 111d62: 49 e0 fb ff r9 = -0x5 + 111d66: 41 24 r1 = 0x4 + 111d68: 02 e1 0c a0 r2 = r10 + 0xc + 111d6c: 33 e1 fc 2f r3 = r2 + -0x4 + 111d70: 17 37 r7 = -0x9 + 111d72: a0 16 r0 = r10 + 111d74: 4c e0 08 00 r12 = 0x8 + 111d78: 36 e1 f8 0f r6 = r0 + -0x8 + 111d7c: 64 e8 00 6c [r6+0x0] |= r12 + 111d80: 64 e8 02 07 [r0+0x0] &= r7 + 111d84: 64 e8 02 37 [r3+0x0] &= r7 + 111d88: 64 e8 02 27 [r2+0x0] &= r7 + 111d8c: c2 ef 01 a0 [r10+0x8] &= 0xFFFFFFFE + 111d90: c3 ef 01 a0 [r10+0xc] &= 0xFFFFFFFE + 111d94: c0 ef 01 a0 [r10+0x0] &= 0xFFFFFFFE + 111d98: 02 ef 02 a0 [r10+0x8] |= 0x2 + 111d9c: c3 ef 02 a0 [r10+0xc] &= 0xFFFFFFFD + 111da0: 00 ef 02 a0 [r10+0x0] |= 0x2 + 111da4: 64 e8 00 31 [r3+0x0] |= r1 + 111da8: 64 e8 02 29 [r2+0x0] &= r9 + 111dac: 64 e8 00 01 [r0+0x0] |= r1 + 111db0: 00 ef 20 a0 [r10+0x0] |= 0x20 + 111db4: 02 ef 20 a0 [r10+0x8] |= 0x20 + 111db8: c3 ef 20 a0 [r10+0xc] &= 0xFFFFFFDF + 111dbc: bf ea 1c fd call -0x5c8 ## spi0.c:219:26 + 111dc0: 01 16 r1 = r0 ## spi0.c:219:26 + 111dc2: 40 16 r0 = r4 ## spi0.c:219:2 + 111dc4: bf ea d2 fe call -0x25c ## spi0.c:219:2 + 111dc8: 50 ed b0 20 r2 = h[r11+0x0] (u) ## spi0.c:221:16 + 111dcc: d0 ec 80 10 r1 = [r8+0x0] ## spi0.c:221:16 + 111dd0: 00 e1 54 a0 r0 = r10 + 0x54 ## spi0.c:221:16 + 111dd4: 60 ff 07 20 06 00 if ((r2 & 0x7) == 0) goto 0xc ## spi0.c:221:9 + 111dda: 31 23 r1 |= 0x8 ## spi0.c:222:22 + 111ddc: d0 ec 81 10 [r8+0x0] = r1 ## spi0.c:222:22 + 111de0: 01 60 r1 = [r0+0x0] ## spi0.c:223:24 + 111de2: b9 21 r1 &= 0xfffffffd ## spi0.c:223:24 + 111de4: 04 85 goto 0xa ## spi0.c:223:24 + 111de6: b9 23 r1 &= 0xfffffff7 ## spi0.c:226:22 + 111de8: d0 ec 81 10 [r8+0x0] = r1 ## spi0.c:226:22 + 111dec: 01 60 r1 = [r0+0x0] ## spi0.c:227:24 + 111dee: 31 21 r1 |= 0x2 ## spi0.c:227:24 + 111df0: 81 60 [r0+0x0] = r1 + 111df2: 00 ef 01 80 [r8+0x0] |= 0x1 ## spi0.c:230:18 + 111df6: 40 21 r0 = 0x1 ## spi0.c:231:5 + 111df8: bf ea c6 fe call -0x274 ## spi0.c:231:5 + 111dfc: 40 20 r0 = 0x0 ## norflash.c:220:5 + 111dfe: bf ea c3 fe call -0x27a ## norflash.c:220:5 + 111e02: 68 2b r0 = 0xab ## norflash.c:222:5 + 111e04: bf ea e6 fe call -0x234 ## norflash.c:222:5 + 111e08: 78 3f r0 = 0xff ## norflash.c:225:5 + 111e0a: bf ea e3 fe call -0x23a ## norflash.c:225:5 + 111e0e: 78 3f r0 = 0xff ## norflash.c:226:5 + 111e10: bf ea e0 fe call -0x240 ## norflash.c:226:5 + 111e14: 78 3f r0 = 0xff ## norflash.c:227:5 + 111e16: bf ea dd fe call -0x246 ## norflash.c:227:5 + 111e1a: bf ea e2 fe call -0x23c ## norflash.c:229:5 + 111e1e: 40 21 r0 = 0x1 ## norflash.c:230:5 + 111e20: bf ea b2 fe call -0x29c ## norflash.c:230:5 + 111e24: 47 e0 6a ff r7 = -0x96 + 111e28: 04 92 goto 0x24 + 111e2a: 40 20 r0 = 0x0 ## norflash.c:57:9 + 111e2c: bf ea ac fe call -0x2a8 ## norflash.c:57:9 + 111e30: 40 25 r0 = 0x5 ## norflash.c:58:9 + 111e32: bf ea cf fe call -0x262 ## norflash.c:58:9 + 111e36: bf ea d4 fe call -0x258 ## norflash.c:59:19 + 111e3a: 06 16 r6 = r0 ## norflash.c:59:19 + 111e3c: 40 21 r0 = 0x1 ## norflash.c:60:9 + 111e3e: bf ea a3 fe call -0x2ba ## norflash.c:60:9 + 111e42: 56 e8 05 00 if ((r6 & 0x1) == 0) goto 0xa ## norflash.c:60:9 + 111e46: 40 21 r0 = 0x1 ## norflash.c:65:9 + 111e48: bf ea 6c fb call -0x928 ## norflash.c:65:9 + 111e4c: c7 21 r7 += 0x1 ## norflash.c:65:9 + 111e4e: f7 4d if (r7 != 0) goto -0x26 + 111e50: 40 20 r0 = 0x0 ## norflash.c:236:5 + 111e52: 46 20 r6 = 0x0 ## norflash.c:236:5 + 111e54: bf ea 98 fe call -0x2d0 ## norflash.c:236:5 + 111e58: 58 26 r0 = 0x66 ## norflash.c:238:5 + 111e5a: bf ea d1 fe call -0x25e ## norflash.c:238:5 + 111e5e: 40 21 r0 = 0x1 ## norflash.c:240:5 + 111e60: bf ea 92 fe call -0x2dc ## norflash.c:240:5 + 111e64: 40 20 r0 = 0x0 ## norflash.c:242:5 + 111e66: bf ea 8f fe call -0x2e2 ## norflash.c:242:5 + 111e6a: 60 39 r0 = 0x99 ## norflash.c:244:5 + 111e6c: bf ea c8 fe call -0x270 ## norflash.c:244:5 + 111e70: 40 21 r0 = 0x1 ## norflash.c:246:5 + 111e72: bf ea 89 fe call -0x2ee ## norflash.c:246:5 + 111e76: 40 20 r0 = 0x0 ## norflash.c:253:5 + 111e78: bf ea 86 fe call -0x2f4 ## norflash.c:253:5 + 111e7c: 58 26 r0 = 0x66 ## norflash.c:254:5 + 111e7e: bf ea a9 fe call -0x2ae ## norflash.c:254:5 + 111e82: 40 21 r0 = 0x1 ## norflash.c:256:5 + 111e84: bf ea 80 fe call -0x300 ## norflash.c:256:5 + 111e88: 40 20 r0 = 0x0 ## norflash.c:258:5 + 111e8a: bf ea 7d fe call -0x306 ## norflash.c:258:5 + 111e8e: 60 39 r0 = 0x99 ## norflash.c:260:5 + 111e90: bf ea a0 fe call -0x2c0 ## norflash.c:260:5 + 111e94: 40 21 r0 = 0x1 ## norflash.c:262:5 + 111e96: bf ea 77 fe call -0x312 ## norflash.c:262:5 + 111e9a: 40 22 r0 = 0x2 ## norflash.c:263:5 + 111e9c: bf ea 42 fb call -0x97c ## norflash.c:263:5 + 111ea0: d6 61 [r5+0x4] = r6 ## boot_flash.c:81:29 + 111ea2: c0 ff e0 be 02 00 r0 = 0x2bee0 ## boot_flash.c:81:29 + 111ea8: 8e 42 b[r0+0x2] = r6 ## boot_flash.c:82:28 + 111eaa: 04 88 goto 0x10 ## boot_flash.c:82:28 + 111eac: 50 16 r0 = r5 ## boot_flash.c:85:9 + 111eae: bf ea b6 fe call -0x294 ## boot_flash.c:85:9 + 111eb2: 48 9e r0 = r4 + 0x1e ## boot_flash.c:86:35 + 111eb4: d8 ec 0a 06 r0 = [r0+r6<<2] ## boot_flash.c:86:35 + 111eb8: d0 61 [r5+0x4] = r0 ## boot_flash.c:86:33 + 111eba: c6 21 r6 += 0x1 ## boot_flash.c:84:37 + 111ebc: 86 f8 f6 0b if (r6 != 0x5) goto -0x14 + 111ec0: 40 ea 00 80 [r8+0x0] = 0x0 ## spi0.c:118:18 + 111ec4: bf ea 98 fc call -0x6d0 ## spi0.c:120:34 + 111ec8: 01 16 r1 = r0 ## spi0.c:120:34 + 111eca: 00 e1 2e 40 r0 = r4 + 0x2e ## spi0.c:120:2 + 111ece: bf ea 4d fe call -0x366 ## spi0.c:120:2 + 111ed2: bf ea 91 fc call -0x6de ## spi0.c:122:16 + 111ed6: c2 ef 03 a0 [r10+0x8] &= 0xFFFFFFFC ## spi0.c:122:16 + 111eda: c3 ef 03 a0 [r10+0xc] &= 0xFFFFFFFC ## spi0.c:122:16 + 111ede: d0 ec a0 10 r1 = [r10+0x0] ## spi0.c:122:16 + 111ee2: 00 4f if (r0 == 0) goto 0x1e + 111ee4: 72 e1 03 10 r2 = r1 & 0xFFFFFFFC ## spi0.c:153:23 + 111ee8: 40 e0 00 20 r0 = 0x2000 ## spi0.c:153:23 + 111eec: 41 e0 ff df r1 = -0x2001 + 111ef0: 44 e0 00 40 r4 = 0x4000 + 111ef4: 36 e1 40 af r6 = r10 + -0xc0 + 111ef8: 6b 8c r3 = r6 + 0xc + 111efa: 47 e0 ff bf r7 = -0x4001 + 111efe: 6d 88 r5 = r6 + 0x8 + 111f00: 04 8b goto 0x16 + 111f02: 42 e1 03 10 r2 = r1 | 0x3 ## spi0.c:127:23 + 111f06: 40 28 r0 = 0x8 ## spi0.c:127:23 + 111f08: 11 37 r1 = -0x9 + 111f0a: 44 24 r4 = 0x4 + 111f0c: 03 e1 0c a0 r3 = r10 + 0xc + 111f10: 17 3b r7 = -0x5 + 111f12: 35 e1 fc 3f r5 = r3 + -0x4 + 111f16: a6 16 r6 = r10 + 111f18: d0 ec a1 20 [r10+0x0] = r2 + 111f1c: 64 e8 02 57 [r5+0x0] &= r7 + 111f20: 64 e8 02 37 [r3+0x0] &= r7 + 111f24: 64 e8 00 64 [r6+0x0] |= r4 + 111f28: c2 ef 20 a0 [r10+0x8] &= 0xFFFFFFDF + 111f2c: c3 ef 20 a0 [r10+0xc] &= 0xFFFFFFDF + 111f30: 00 ef 20 a0 [r10+0x0] |= 0x20 + 111f34: 64 e8 02 31 [r3+0x0] &= r1 + 111f38: 64 e8 00 50 [r5+0x0] |= r0 + 111f3c: 64 e8 00 60 [r6+0x0] |= r0 + 111f40: 5c 04 {pc, r12-r4} = [sp++] ## boot_flash.c:90:1 + + +delay: + 111f42: e2 9f sp += -0x4 ## timer.c:81:0 + 111f44: 80 20 [sp] = r0 ## timer.c:81:0 + 111f46: 04 81 goto 0x2 ## timer.c:81:0 + 111f48: 00 00 nop ## timer.c:86:9 + 111f4a: 00 20 r0 = [sp] ## timer.c:85:16 + 111f4c: 31 e1 ff 0f r1 = r0 + -0x1 ## timer.c:85:16 + 111f50: 81 20 [sp] = r1 ## timer.c:85:16 + 111f52: f0 5a if (r0 != 0) goto -0xc ## timer.c:85:16 + 111f54: 02 81 sp += 0x4 + 111f56: 80 00 rts ## timer.c:89:1 + + +main: + 111f58: 40 22 r0 = 0x2 ## main.c:82:0 + 111f5a: 41 30 r1 = 0x10 ## p33.c:77:5 + 111f5c: 44 22 r4 = 0x2 ## p33.c:77:5 + 111f5e: bf ea 22 f9 call -0xdbc ## p33.c:77:5 + 111f62: c0 ff 20 19 1e 00 r0 = 0x1e1920 <__stub_doe+0xCF124 : 1e1920 > + 111f68: 42 f0 00 e0 r2 = -0x2000 # ## clock.c:90:5 + 111f6c: 01 61 r1 = [r0+0x4] ## clock.c:90:5 + 111f6e: a1 19 r1 &= r2 ## clock.c:90:5 + 111f70: 42 e0 06 07 r2 = 0x706 ## clock.c:90:5 + 111f74: 21 19 r1 |= r2 ## clock.c:90:5 + 111f76: 81 61 [r0+0x4] = r1 ## clock.c:90:5 + 111f78: c1 ff ca 9c 19 33 r1 = 0x33199cca <__stub_doe+0x330874CE : 33199cca > ## clock.c:91:22 + 111f7e: 81 60 [r0+0x0] = r1 ## clock.c:91:22 + 111f80: 00 ef 01 00 [r0+0x0] |= 0x1 ## clock.c:92:22 + 111f84: 58 32 r0 = 0x72 ## p33.c:94:5 + 111f86: 41 30 r1 = 0x10 ## p33.c:94:5 + 111f88: bf ea 9e f8 call -0xec4 ## p33.c:94:5 + 111f8c: 58 32 r0 = 0x72 ## p33.c:95:5 + 111f8e: 41 21 r1 = 0x1 ## p33.c:95:5 + 111f90: bf ea 9a f8 call -0xecc ## p33.c:95:5 + 111f94: c6 ff c8 50 1e 00 r6 = 0x1e50c8 <__stub_doe+0xD28CC : 1e50c8 > + 111f9a: 0e ef 04 60 [r6+0x38] |= 0x4 ## boot_skip.c:54:5 + 111f9e: 0e ef 08 60 [r6+0x38] |= 0x8 ## boot_skip.c:55:5 + 111fa2: 0e ef 00 6f [r6+0x38] |= 0x200 ## boot_skip.c:58:5 + 111fa6: 0e ef 80 6e [r6+0x38] |= 0x400 ## boot_skip.c:59:5 + 111faa: 40 20 r0 = 0x0 ## boot_skip.c:71:5 + 111fac: 45 20 r5 = 0x0 ## boot_skip.c:71:5 + 111fae: bf ea 11 fa call -0xbde ## boot_skip.c:71:5 + 111fb2: 40 34 r0 = 0x14 ## boot_skip.c:72:5 + 111fb4: bf ea 60 f9 call -0xd40 ## boot_skip.c:72:5 + 111fb8: c7 ff 00 07 1e 00 r7 = 0x1e0700 <__stub_doe+0xCDF04 : 1e0700 > ## boot_skip.c:72:5 + 111fbe: f5 62 [r7+0x8] = r5 ## boot_skip.c:75:20 + 111fc0: f5 61 [r7+0x4] = r5 ## boot_skip.c:76:20 + 111fc2: c8 ff 40 10 11 00 r8 = 0x111040 ## boot_skip.c:76:20 + 111fc8: 80 d6 r0 = r8 # ## boot_skip.c:80:22 + 111fca: f4 60 [r7+0x0] = r4 ## boot_skip.c:77:20 + 111fcc: bf ea 24 fa call -0xbb8 ## boot_skip.c:80:22 + 111fd0: 60 e0 7a 1c r1 = 0xFA00 ## boot_skip.c:80:42 + 111fd4: f4 e1 00 01 r0 = r0 / r1 (u) ## boot_skip.c:80:42 + 111fd8: e0 e1 0a 00 r0 = r0 * 0xA ## boot_skip.c:80:49 + 111fdc: 34 e1 00 7f r4 = r7 + -0x100 ## boot_skip.c:80:49 + 111fe0: c0 62 [r4+0x8] = r0 ## boot_skip.c:80:20 + 111fe2: c5 61 [r4+0x4] = r5 ## boot_skip.c:81:20 + 111fe4: 40 ea 80 4c [r4+0x0] = 0x4000 ## boot_skip.c:82:20 + 111fe8: 00 ef 80 7c [r7+0x0] |= 0x4000 ## boot_skip.c:86:20 + 111fec: 40 ea 31 40 [r4+0x0] = 0x31 ## boot_skip.c:87:20 + 111ff0: 01 e1 ff 15 r1 = r1 + 0x5ff ## boot_skip.c:87:20 + 111ff4: c9 ff fe ff 01 00 r9 = 0x1fffe <_system_bss_end+0xEBDA : 1fffe > ## boot_skip.c:87:20 + 111ffa: 4a e0 7c 6b r10 = 0x6b7c ## boot_skip.c:87:20 + 111ffe: 43 e0 ef 16 r3 = 0x16ef ## boot_skip.c:87:20 + 112002: 40 60 r0 = [r4+0x0] ## boot_skip.c:89:13 + 112004: 88 17 r0 = r0.l (s) ## boot_skip.c:89:12 + 112006: 80 fd 31 00 ifs (r0 < 0x0) goto 0x62 ## boot_skip.c:89:12 + 11200a: 70 60 r0 = [r7+0x0] ## boot_skip.c:90:13 + 11200c: 50 e8 f9 79 if ((r0 & 0x8000) == 0) goto -0xe ## boot_skip.c:90:13 + 112010: 00 ef 80 7c [r7+0x0] |= 0x4000 ## boot_skip.c:91:28 + 112014: 11 a1 r1 = r1 << 0x1 ## boot_skip.c:91:28 + 112016: 90 f1 12 19 r1 = r1 & r9 # ## boot_skip.c:91:28 + 11201a: 60 6f r0 = [r6+0x3c] ## boot_skip.c:93:17 + 11201c: b0 e1 84 00 r0 = uextra(r0, p:0x1, l:0x1) ## boot_skip.c:93:17 + 112020: 01 19 r1 |= r0 ## boot_skip.c:93:17 + 112022: 90 17 r0 = r1.l (u) ## boot_skip.c:104:39 + 112024: 42 25 r2 = 0x5 ## boot_skip.c:44:9 + 112026: 90 e8 00 0a if (r0 != r10) { ## boot_skip.c:44:9 + 11202a: 42 20 r2 = 0x0 + } ## boot_skip.c:44:9 + 11202c: 45 21 r5 = 0x1 ## boot_skip.c:44:9 + 11202e: 90 e8 00 03 if (r0 != r3) { ## boot_skip.c:44:9 + 112032: 25 16 r5 = r2 + } ## boot_skip.c:44:9 + 112034: 75 46 if (r5 == 0) goto -0x34 + 112036: ce ef 01 60 [r6+0x38] &= 0xFFFFFFFE ## boot_skip.c:107:17 + 11203a: ce ef 02 60 [r6+0x38] &= 0xFFFFFFFD ## boot_skip.c:108:17 + 11203e: ce ef 04 60 [r6+0x38] &= 0xFFFFFFFB ## boot_skip.c:109:17 + 112042: ce ef 08 60 [r6+0x38] &= 0xFFFFFFF7 ## boot_skip.c:110:17 + 112046: 40 ea 80 4c [r4+0x0] = 0x4000 ## boot_skip.c:111:32 + 11204a: 41 ea 00 40 [r4+0x4] = 0x0 ## boot_skip.c:112:32 + 11204e: 80 16 r0 = r8 ## boot_skip.c:113:34 + 112050: bf ea e2 f9 call -0xc3c ## boot_skip.c:113:34 + 112054: 60 e0 7a 1c r1 = 0xFA00 ## boot_skip.c:113:54 + 112058: f4 e1 00 01 r0 = r0 / r1 (u) ## boot_skip.c:113:54 + 11205c: 00 a1 r0 = r0 << 0x1 ## boot_skip.c:113:61 + 11205e: c0 62 [r4+0x8] = r0 ## boot_skip.c:113:32 + 112060: 40 ea 31 40 [r4+0x0] = 0x31 ## boot_skip.c:114:32 + 112064: 40 60 r0 = [r4+0x0] ## boot_skip.c:115:25 + 112066: 50 e8 fd 79 if ((r0 & 0x8000) == 0) goto -0x6 ## boot_skip.c:115:25 + 11206a: 04 81 goto 0x2 ## boot_skip.c:115:25 + 11206c: 45 20 r5 = 0x0 + 11206e: 40 20 r0 = 0x0 ## boot_skip.c:121:5 + 112070: bf ea f3 f9 call -0xc1a ## boot_skip.c:121:5 + 112074: 40 e0 00 40 r0 = 0x4000 ## boot_skip.c:122:20 + 112078: f0 60 [r7+0x0] = r0 ## boot_skip.c:122:20 + 11207a: c0 60 [r4+0x0] = r0 ## boot_skip.c:123:20 + 11207c: 0e ef 04 60 [r6+0x38] |= 0x4 ## boot_skip.c:125:5 + 112080: 0e ef 08 60 [r6+0x38] |= 0x8 ## boot_skip.c:126:5 + 112084: ce ef 10 60 [r6+0x38] &= 0xFFFFFFEF ## boot_skip.c:129:5 + 112088: ce ef 20 60 [r6+0x38] &= 0xFFFFFFDF ## boot_skip.c:130:5 + 11208c: ce ef 40 60 [r6+0x38] &= 0xFFFFFFBF ## boot_skip.c:132:5 + 112090: ce ef 80 60 [r6+0x38] &= 0xFFFFFF7F ## boot_skip.c:133:5 + 112094: 85 43 if (r5 != 0) goto 0x6 ## boot_skip.c:133:5 + 112096: bf ea 27 f1 call -0x1db2 ## boot_skip.c:148:11 + 11209a: 05 16 r5 = r0 ## boot_skip.c:148:11 + 11209c: 30 e1 ff 5f r0 = r5 + -0x1 ## main.c:107:5 + 1120a0: c1 ff e0 be 02 00 r1 = 0x2bee0 + 1120a6: 39 e1 0c 4a r9 = r4 + -0x5f4 + 1120aa: 00 f9 05 04 if (r0 >= 0x2) goto 0xa + 1120ae: 1f 16 r15 = r1 + 1120b0: 40 23 r0 = 0x3 ## main.c:119:9 + 1120b2: bf ea 4c fb call -0x968 ## main.c:119:9 + 1120b6: 34 96 goto 0xec ## main.c:119:9 + 1120b8: 85 f8 05 06 if (r5 != 0x3) goto 0xa + 1120bc: 1f 16 r15 = r1 + 1120be: 40 20 r0 = 0x0 ## main.c:112:9 + 1120c0: bf ea e8 fa call -0xa30 ## main.c:112:9 + 1120c4: 34 8f goto 0xde ## main.c:112:9 + 1120c6: c2 14 r10 = 0 + 1120c8: 1f 16 r15 = r1 + 1120ca: 52 ee 10 a0 b[r1+0x0] = r10 ## main.c:34:31 + 1120ce: cb ff de be 02 00 r11 = 0x2bede ## main.c:34:31 + 1120d4: c5 ff c4 be 02 00 r5 = 0x2bec4 ## main.c:34:31 + 1120da: 4c e0 01 00 r12 = 0x1 + 1120de: 4d e0 00 40 r13 = 0x4000 + 1120e2: c0 14 r8 = 0 + 1120e4: 04 8a goto 0x14 + 1120e6: bf ea c7 f9 call -0xc72 ## main.c:62:9 + 1120ea: bf ea d7 f8 call -0xe52 ## main.c:64:9 + 1120ee: 40 2a r0 = 0xa ## main.c:66:9 + 1120f0: bf ea 18 fa call -0xbd0 ## main.c:66:9 + 1120f4: 04 82 goto 0x4 ## main.c:66:9 + 1120f6: c0 14 r8 = 0 + 1120f8: f7 96 goto -0x14 + 1120fa: 50 ee b0 e0 r14 = b[r11+0x0] (u) ## boot_init.c:92:12 + 1120fe: 3e ea 04 c0 if ((r14 & 0x4) != 0) { + 112102: 52 ee 54 c0 b[r5+0x4] = r12 ## boot_flash.c:104:25 + 112106: c0 ff 30 10 11 00 r0 = 0x111030 ## boot_flash.c:105:33 + 11210c: d0 60 [r5+0x0] = r0 ## boot_flash.c:105:33 + 11210e: bf ea ea fd call -0x42c + } ## boot_flash.c:106:9 + 112112: 3e ea 08 c0 if ((r14 & 0x8) != 0) { ## boot_flash.c:106:9 + 112116: 52 ee 54 c0 b[r5+0x4] = r12 ## boot_flash.c:116:25 + 11211a: c0 ff 34 10 11 00 r0 = 0x111034 ## boot_flash.c:117:33 + 112120: d0 60 [r5+0x0] = r0 ## boot_flash.c:117:33 + 112122: bf ea e0 fd call -0x440 + } ## boot_flash.c:118:9 + 112126: c5 ef 10 60 [r6+0x14] &= 0xFFFFFFEF ## norflash.c:409:19 + 11212a: c4 ef 10 60 [r6+0x10] &= 0xFFFFFFEF ## norflash.c:410:19 + 11212e: 00 ef 10 60 [r6+0x0] |= 0x10 ## norflash.c:411:19 + 112132: c2 ef 10 60 [r6+0x8] &= 0xFFFFFFEF ## norflash.c:412:19 + 112136: 03 ef 10 60 [r6+0xc] |= 0x10 ## norflash.c:413:19 + 11213a: 40 21 r0 = 0x1 ## norflash.c:415:5 + 11213c: bf ea f2 f9 call -0xc1c ## norflash.c:415:5 + 112140: 40 20 r0 = 0x0 ## norflash.c:416:5 + 112142: bf ea 7a f8 call -0xf0c ## norflash.c:416:5 + 112146: 88 f8 29 00 if (r8 != 0x0) goto 0x52 ## norflash.c:416:5 + 11214a: d0 ec 41 d0 [r4+0x0] = r13 ## clock.c:173:20 + 11214e: d0 ec 71 d0 [r7+0x0] = r13 ## clock.c:174:20 + 112152: c0 ef 30 90 [r9+0x0] &= 0xFFFFFFCF ## clock.c:177:24 + 112156: 42 ea ff 73 [r7+0x8] = 0xFFFFFFFF ## clock.c:178:20 + 11215a: d0 ec 75 a0 [r7+0x4] = r10 ## clock.c:179:20 + 11215e: 40 e0 89 40 r0 = 0x4089 ## clock.c:180:20 + 112162: f0 60 [r7+0x0] = r0 ## clock.c:180:20 + 112164: 42 ea fa 4c [r4+0x8] = 0x7D00 ## clock.c:182:20 + 112168: d0 ec 45 a0 [r4+0x4] = r10 ## clock.c:183:20 + 11216c: 40 e0 01 40 r0 = 0x4001 ## clock.c:184:20 + 112170: c0 60 [r4+0x0] = r0 ## clock.c:184:20 + 112172: 40 60 r0 = [r4+0x0] ## clock.c:188:24 + 112174: 50 e8 06 7a if ((r0 & 0x8000) != 0) goto 0xc ## clock.c:188:24 + 112178: 70 61 r0 = [r7+0x4] ## clock.c:193:24 + 11217a: 80 f9 fa 17 if (r0 < 0xb) goto -0xc ## clock.c:193:24 + 11217e: 50 ee f1 80 r8 = b[r15+0x1] (u) ## clock.c:198:20 + 112182: 04 83 goto 0x6 + 112184: c0 14 r8 = 0 + 112186: 52 ee f1 80 b[r15+0x1] = r8 ## clock.c:189:36 + 11218a: d0 ec 71 d0 [r7+0x0] = r13 ## clock.c:198:20 + 11218e: d0 ec 41 d0 [r4+0x0] = r13 ## clock.c:199:20 + 112192: 40 21 r0 = 0x1 ## main.c:50:13 + 112194: bf ea 7e fa call -0xb04 ## main.c:50:13 + 112198: 08 f8 ad 01 if (r8 == 0x0) goto -0xa6 + 11219c: 40 20 r0 = 0x0 ## main.c:56:23 + 11219e: bf ea d6 fa call -0xa54 ## main.c:56:23 + 1121a2: 50 41 if (r0 == 0) goto -0xbe + 1121a4: c0 ff 40 13 01 00 r0 = 0x11340 + 1121aa: 44 f0 a0 0f r4 = 0xfa0 # + 1121ae: 02 61 r2 = [r0+0x4] + 1121b0: 40 20 r0 = 0x0 + 1121b2: d0 ec f5 00 [r15+0x4] = r0 ## clock.c:110:28 + 1121b6: 31 e1 60 20 r1 = r2 + -0xfa0 ## clock.c:112:10 + 1121ba: a3 e0 00 20 r3 = 0x0 - r2 ## clock.c:112:10 + 1121be: c2 ff 00 09 3d 00 r2 = 0x3d0900 <__stub_doe+0x2BE104 : 3d0900 > ## clock.c:112:10 + 1121c4: e5 e0 fb 7c r5 = r7 + 0x7D80 ## clock.c:112:10 + 1121c8: 04 86 goto 0xc ## clock.c:112:10 + 1121ca: 52 18 r2 += r5 ## clock.c:112:5 + 1121cc: 31 e1 30 18 r1 = r1 + -0x7d0 ## clock.c:112:5 + 1121d0: c0 24 r0 += 0x4 ## clock.c:112:5 + 1121d2: 04 e1 d0 47 r4 = r4 + 0x7d0 ## clock.c:112:43 + 1121d6: c6 a7 r6 = r4 >> 0x7 ## clock.c:112:5 + 1121d8: 26 fc 0c ec if (r6 > 0x176) goto 0x18 ## clock.c:112:5 + 1121dc: 36 1d r6 = r3 + r4 ## clock.c:114:13 + 1121de: b6 ee ff 0f ifs (r6 <= -0x1) { ## clock.c:114:13 + 1121e2: 16 16 r6 = r1 + } ## clock.c:114:13 + 1121e4: 0c ff e8 63 f0 ff ifs (r6 > 0x3e8) goto -0x20 ## clock.c:114:13 + 1121ea: d0 ec f5 20 [r15+0x4] = r2 ## clock.c:115:36 + 1121ee: 40 e1 51 05 r0 = r0 | 0x34400000 ## clock.c:117:13 + 1121f2: 04 81 goto 0x2 ## clock.c:117:13 + 1121f4: 10 38 r0 = -0x8 + 1121f6: d0 ec 95 03 [r9+0x34] = r0 ## clock.c:125:23 + 1121fa: c0 ff ee 30 a0 1f r0 = 0x1fa030ee <__stub_doe+0x1F8F08F2 : 1fa030ee > ## clock.c:126:24 + 112200: d0 ec 99 03 [r9+0x38] = r0 ## clock.c:126:24 + 112204: 0d ef 01 90 [r9+0x34] |= 0x1 ## clock.c:128:23 + 112208: 40 2a r0 = 0xa ## clock.c:130:5 + 11220a: bf ea 35 f8 call -0xf96 ## clock.c:130:5 + 11220e: 0d ef 02 90 [r9+0x34] |= 0x2 ## clock.c:131:23 + 112212: 68 20 r0 = 0xa0 ## clock.c:132:5 + 112214: bf ea 30 f8 call -0xfa0 ## clock.c:132:5 + 112218: c1 ef 03 90 [r9+0x4] &= 0xFFFFFFFC ## clock.c:140:24 + 11221c: c2 ef 03 90 [r9+0x8] &= 0xFFFFFFFC ## clock.c:144:24 + 112220: c2 ef 3c 90 [r9+0x8] &= 0xFFFFFFC3 ## clock.c:145:24 + 112224: 02 ef 20 90 [r9+0x8] |= 0x20 ## clock.c:146:24 + 112228: 00 ef c0 90 [r9+0x0] |= 0xC0 ## clock.c:148:24 + 11222c: 40 2a r0 = 0xa ## clock.c:150:5 + 11222e: bf ea 88 fe call -0x2f0 ## clock.c:150:5 + 112232: 00 ef 80 9f [r9+0x0] |= 0x100 ## clock.c:151:24 + 112236: 40 2a r0 = 0xa ## clock.c:152:5 + 112238: bf ea 83 fe call -0x2fa ## clock.c:152:5 + 11223c: c0 ff 00 6c dc 02 r0 = 0x2dc6c00 <__stub_doe+0x2CB4404 : 2dc6c00 > ## clock.c:154:27 + 112242: d0 ec f9 00 [r15+0x8] = r0 ## clock.c:154:27 + 112246: 48 32 r0 = 0x32 ## clock.c:155:5 + 112248: bf ea 6c f9 call -0xd28 ## clock.c:155:5 + 11224c: bf ea f1 f1 call -0x1c1e ## main.c:132:5 + + +sfc_suspend: + 112250: c1 ff 00 10 10 00 r1 = 0x101000 <_IRQ_MEM_ADDR+0xD5100 : 101000 > ## icache.c:12:0 + 112256: 12 60 r2 = [r1+0x0] ## icache.c:14:22 + 112258: 52 e8 fd 29 if ((r2 & 0x20) == 0) goto -0x6 ## icache.c:14:5 + 11225c: c1 ff 00 02 1f 00 r1 = 0x1f0200 <__stub_doe+0xDDA04 : 1f0200 > + 112262: 12 60 r2 = [r1+0x0] ## icache.c:16:20 + 112264: 82 fd fd 01 ifs (r2 < 0x0) goto -0x6 ## icache.c:16:5 + 112268: c0 ef 01 10 [r1+0x0] &= 0xFFFFFFFE ## icache.c:18:17 + 11226c: b0 e8 00 40 if (r0 != 0x0) { ## icache.c:18:17 + 112270: c0 ff 00 1c 1e 00 r0 = 0x1e1c00 <__stub_doe+0xCF404 : 1e1c00 > ## icache.c:20:22 + 112276: 00 ef 01 00 [r0+0x0] |= 0x1 + } ## icache.c:20:22 + 11227a: 80 00 rts ## icache.c:22:1 + + +sfc_resume: + 11227c: b0 e8 00 40 if (r0 != 0x0) { ## icache.c:25:0 + 112280: c0 ff 00 1c 1e 00 r0 = 0x1e1c00 <__stub_doe+0xCF404 : 1e1c00 > ## icache.c:27:22 + 112286: c0 ef 01 00 [r0+0x0] &= 0xFFFFFFFE + } ## icache.c:27:22 + 11228a: c0 ff 00 02 1f 00 r0 = 0x1f0200 <__stub_doe+0xDDA04 : 1f0200 > ## icache.c:29:17 + 112290: 00 ef 01 00 [r0+0x0] |= 0x1 ## icache.c:29:17 + 112294: 80 00 rts ## icache.c:30:1 + + +sfc_drop_cache: + 112296: 7a 04 [--sp] = {rets, r10-r4} ## icache.c:32:0 + 112298: c8 ff 00 10 10 00 r8 = 0x101000 <_IRQ_MEM_ADDR+0xD5100 : 101000 > ## icache.c:32:0 + 11229e: d0 ec 80 90 r9 = [r8+0x0] ## icache.c:33:33 + 1122a2: c0 ef e0 8e [r8+0x0] &= 0xFFFFF8FF ## icache.c:34:17 + 1122a6: 74 e1 1f 00 r4 = r0 & 0xFFFFFFE0 ## icache.c:40:31 + 1122aa: 02 1f r2 = r0 - r4 ## icache.c:41:27 + 1122ac: a0 e0 20 20 r0 = 0x20 - r2 ## icache.c:43:32 + 1122b0: c2 14 r10 = 0 + 1122b2: 23 16 r3 = r2 ## icache.c:43:9 + 1122b4: 10 e9 00 01 if (r0 >= r1) { ## icache.c:43:9 + 1122b8: 43 20 r3 = 0x0 + } ## icache.c:43:9 + 1122ba: 32 e8 00 00 if (r2 == 0x0) { ## icache.c:43:9 + 1122be: 23 16 r3 = r2 + } ## icache.c:43:9 + 1122c0: 98 1c r0 = r1 + r3 ## icache.c:43:9 + 1122c2: c0 3f r0 += 0x1f ## icache.c:48:35 + 1122c4: 70 e1 1f 00 r0 = r0 & 0xFFFFFFE0 ## icache.c:48:40 + 1122c8: 01 1d r1 = r0 + r4 + 1122ca: 60 e0 7c 5a r5 = 0xFC000 + 1122ce: 46 20 r6 = 0x0 + 1122d0: 04 98 goto 0x30 + 1122d2: c0 e1 a5 70 r7 = r10 << 0x5 + 1122d6: 42 24 r2 = 0x4 + 1122d8: 43 20 r3 = 0x0 + 1122da: 04 8d goto 0x1a + 1122dc: d8 ec 5a 03 r0 = [r5+r3<<2] ## icache.c:52:41 + 1122e0: 00 ac r0 = r0 << 0xc ## icache.c:52:45 + 1122e2: 70 18 r0 += r7 ## icache.c:52:52 + 1122e4: 01 ec 05 00 if (r0 > r1) goto 0xa + 1122e8: c8 20 r0 += 0x20 ## icache.c:54:92 + 1122ea: 10 e9 00 04 if (r0 >= r4) { + 1122ee: d8 ec 5b 63 [r5+r3<<2] = r6 + } ## icache.c:55:20 + 1122f2: c3 21 r3 += 0x1 ## icache.c:51:9 + 1122f4: fa 3f r2 += -0x1 ## icache.c:51:9 + 1122f6: 61 ff ff 20 f0 ff if ((r2 & 0xFF) != 0) goto -0x20 + 1122fc: 0a e1 01 a0 r10 = r10 + 0x1 ## icache.c:50:27 + 112300: c5 30 r5 += 0x10 ## icache.c:36:10 + 112302: 9a f8 e6 01 if (r10 != 0x80) goto -0x34 + 112306: d0 ec 81 90 [r8+0x0] = r9 ## icache.c:61:18 + 11230a: 5a 04 {pc, r10-r4} = [sp++] ## icache.c:62:1 + + +flush_dcache: + 11230c: c1 3f r1 += 0x1f ## icache.c:66:0 + 11230e: 4a 20 r2 = 0x20 ## icache.c:68:40 + 112310: f4 e1 11 12 r1 = r1 / r2 (s) ## icache.c:68:40 + 112314: 11 a5 r1 = r1 << 0x5 ## icache.c:68:59 + 112316: 70 e1 1f 00 r0 = r0 & 0xFFFFFFE0 ## icache.c:67:29 + 11231a: 04 85 goto 0xa + 11231c: f9 20 r1 += -0x20 ## icache.c:73:13 + 11231e: 22 00 ssync ## icache.c:72:9 + 112320: 20 02 flush [r0] ## icache.c:72:9 + 112322: 22 00 ssync ## icache.c:72:9 + 112324: c8 20 r0 += 0x20 ## icache.c:74:11 + 112326: 01 fd f9 03 ifs (r1 >= 0x1) goto -0xe + 11232a: 80 00 rts ## icache.c:77:1 + + +flushinv_dcache: + 11232c: c1 3f r1 += 0x1f ## icache.c:80:0 + 11232e: 4a 20 r2 = 0x20 ## icache.c:82:40 + 112330: f4 e1 11 12 r1 = r1 / r2 (s) ## icache.c:82:40 + 112334: 11 a5 r1 = r1 << 0x5 ## icache.c:82:59 + 112336: 70 e1 1f 00 r0 = r0 & 0xFFFFFFE0 ## icache.c:81:29 + 11233a: 04 85 goto 0xa + 11233c: f9 20 r1 += -0x20 ## icache.c:87:13 + 11233e: 22 00 ssync ## icache.c:86:9 + 112340: 30 02 flushinv [r0] ## icache.c:86:9 + 112342: 22 00 ssync ## icache.c:86:9 + 112344: c8 20 r0 += 0x20 ## icache.c:88:11 + 112346: 01 fd f9 03 ifs (r1 >= 0x1) goto -0xe + 11234a: 80 00 rts ## icache.c:90:1 + + +putchar: + 11234c: 80 00 rts ## uart.c:45:0 + + +switch_to_hrc_asm: + 11234e: c0 ff 0c 00 1e 00 r0 = 0x1e000c <__stub_doe+0xCD810 : 1e000c > ## clock.c:205:0 + 112354: 00 ef 01 00 [r0+0x0] |= 0x1 ## clock.c:206:24 + 112358: 00 ef 02 00 [r0+0x0] |= 0x2 ## clock.c:207:24 + 11235c: 00 00 nop ## clock.c:208:5 + 11235e: 00 00 nop ## clock.c:209:5 + 112360: 00 00 nop ## clock.c:210:5 + 112362: c0 ef 80 0f [r0+0x0] &= 0xFFFFFEFF ## clock.c:211:24 + 112366: 80 00 rts ## clock.c:212:1 + + +tmr3_isr: + 112368: e9 04 [--sp] = {psr, rets, reti} ## clock.c:250:0 + 11236a: d8 e8 3f 00 [--sp] = {r5-r0} ## clock.c:256:5 + 11236e: 58 24 r0 = 0x64 ## clock.c:256:5 + 112370: bf ea e7 fd call -0x432 ## clock.c:256:5 + 112374: c1 ff 00 07 1e 00 r1 = 0x1e0700 <__stub_doe+0xCDF04 : 1e0700 > ## clock.c:256:5 + 11237a: 00 ef 80 1c [r1+0x0] |= 0x4000 ## clock.c:258:20 + 11237e: 12 62 r2 = [r1+0x8] ## clock.c:260:30 + 112380: c0 ff 40 13 01 00 r0 = 0x11340 ## clock.c:260:30 + 112386: 0b 60 r3 = h[r0+0x0] (u) ## clock.c:260:36 + 112388: aa de r2 = r2 - r3 # ## clock.c:260:34 + 11238a: 14 62 r4 = [r1+0x8] ## clock.c:261:27 + 11238c: a3 d7 r3 = r2.l (u) # ## clock.c:267:10 + 11238e: 8c 60 h[r0+0x0] = r4 ## clock.c:261:14 + 112390: 0c 61 r4 = h[r0+0x2] (u) ## clock.c:267:21 + 112392: 35 e1 fc 4e r5 = r4 + -0x104 ## clock.c:267:30 + 112396: 85 ee 10 30 ifs (r3 <= r5) goto 0x20 ## clock.c:267:30 + 11239a: 04 e1 04 41 r4 = r4 + 0x104 ## clock.c:267:62 + 11239e: 04 e9 0c 30 if (r3 >= r4) goto 0x18 ## clock.c:267:62 + 1123a2: 68 e8 04 03 [r0+0x4] += r3 ## clock.c:268:23 + 1123a6: 03 62 r3 = [r0+0x8] ## clock.c:270:16 + 1123a8: c3 21 r3 += 0x1 ## clock.c:270:16 + 1123aa: 83 62 [r0+0x8] = r3 ## clock.c:270:16 + 1123ac: 33 e8 04 40 if (r3 == 0x4) { ## clock.c:270:16 + 1123b0: 40 ea 80 1c [r1+0x0] = 0x4000 ## clock.c:273:28 + 1123b4: 43 ea 01 00 [r0+0xc] = 0x1 + } ## clock.c:275:26 + 1123b8: 04 84 goto 0x8 ## clock.c:275:26 + 1123ba: 44 20 r4 = 0x0 ## clock.c:279:23 + 1123bc: 45 20 r5 = 0x0 ## clock.c:279:23 + 1123be: 50 ec 05 40 d[r0+0x4] = r5_r4 ## clock.c:279:23 + 1123c2: 8a 61 h[r0+0x2] = r2 ## clock.c:282:14 + 1123c4: d4 e8 3f 00 {r5-r0} = [sp++] ## clock.c:283:1 + 1123c8: a9 04 {psr, rets, reti} = [sp++] ## clock.c:283:1 + 1123ca: 81 00 rti ## clock.c:283:1 + + +p33_xor_1byte: + 1123cc: 74 04 [--sp] = {rets, r4} ## p33.c:17:0 + 1123ce: 12 16 r2 = r1 ## p33.c:17:0 + 1123d0: 03 16 r3 = r0 ## p33.c:17:0 + 1123d2: b9 17 r1 = r3.l (s) ## p33.c:17:0 + 1123d4: bf ea c2 ef call -0x207c ## p33.c:18:5 + 1123d8: c4 ff 08 3e 1e 00 r4 = 0x1e3e08 <__stub_doe+0xD160C : 1e3e08 > ## p33.c:18:5 + 1123de: 31 ed 00 50 ifs (r1 >= 0x0) { ## p33.c:18:5 + 1123e2: c0 ef 80 4f [r4+0x0] &= 0xFFFFFEFF ## p33.c:18:5 + 1123e6: 40 21 r0 = 0x1 + } else { ## p33.c:18:5 + 1123e8: 40 e0 01 01 r0 = 0x101 + } ## p33.c:18:5 + 1123ec: 64 e8 00 40 [r4+0x0] |= r0 ## p33.c:18:5 + 1123f0: b0 e1 08 34 r0 = uextra(r3, p:0x8, l:0x2) ## p33.c:19:13 + 1123f4: 40 e1 60 00 r0 = r0 | 0x60 ## p33.c:19:13 + 1123f8: bf ea 5a f6 call -0x134c ## p33.c:19:5 + 1123fc: 70 e1 7f 3c r0 = r3 & 0xFFFF00FF ## p33.c:20:5 + 112400: bf ea 56 f6 call -0x1354 ## p33.c:20:5 + 112404: 20 16 r0 = r2 ## p33.c:21:5 + 112406: bf ea 53 f6 call -0x135a ## p33.c:21:5 + 11240a: 40 e0 fe fe r0 = -0x102 ## p33.c:22:5 + 11240e: 64 e8 02 40 [r4+0x0] &= r0 ## p33.c:22:5 + 112412: 34 04 {rets, r4} = [sp++] ## p33.c:22:5 + 112414: ff ea a9 ef goto -0x20ae ## p33.c:22:5 + + +P33_CON_SET: + 112418: 76 04 [--sp] = {rets, r6-r4} ## p33.c:66:0 + 11241a: 04 16 r4 = r0 ## p33.c:66:0 + 11241c: 10 3f r0 = -0x1 ## p33.c:69:5 + 11241e: 20 1a r0 <<= r2 ## p33.c:69:5 + 112420: 90 e1 33 20 r2 = r3 & ~r0 ## p33.c:69:5 + 112424: c8 e1 20 51 r5 = r2 << r1 ## p33.c:69:5 + 112428: 88 19 r0 = ~r0 ## p33.c:69:5 + 11242a: c8 e1 00 61 r6 = r0 << r1 ## p33.c:69:5 + 11242e: 40 16 r0 = r4 ## p33.c:68:11 + 112430: bf ea 74 f6 call -0x1318 ## p33.c:68:11 + 112434: 90 e1 03 06 r0 = r0 & ~r6 ## p33.c:69:5 + 112438: 50 19 r0 |= r5 ## p33.c:69:5 + 11243a: 01 17 r1 = r0.b0 (u) ## p33.c:70:5 + 11243c: 40 16 r0 = r4 ## p33.c:70:5 + 11243e: 36 04 {rets, r6-r4} = [sp++] ## p33.c:70:5 + 112440: ff ea 42 f6 goto -0x137c ## p33.c:70:5 + + +puts: + 112444: 01 07 r1 = b[r0++=0x1] (u) ## printf-stdarg.c:288:0 + 112446: f1 5e if (r1 != 0) goto -0x4 + 112448: 40 20 r0 = 0x0 ## printf-stdarg.c:326:5 + 11244a: 80 00 rts ## printf-stdarg.c:326:5 + + +sprintf: + 11244c: 62 04 [--sp] = {r3, r2} ## printf-stdarg.c:373:0 + 11244e: 10 04 [--sp] = rets ## printf-stdarg.c:373:0 + 112450: e2 9e sp += -0x8 ## printf-stdarg.c:373:0 + 112452: 80 21 [sp+4] = r0 ## printf-stdarg.c:373:0 + 112454: 8a 8c r2 = sp + 12 ## printf-stdarg.c:373:0 + 112456: 82 20 [sp] = r2 ## printf-stdarg.c:376:5 + 112458: 88 84 r0 = sp + 4 ## printf-stdarg.c:376:5 + 11245a: bf ea 77 fa call -0xb12 ## printf-stdarg.c:378:12 + 11245e: 02 82 sp += 0x8 + 112460: 88 04 {rets} = [sp++] ## printf-stdarg.c:378:5 + 112462: 02 82 sp += 0x8 ## printf-stdarg.c:378:5 + 112464: 80 00 rts ## printf-stdarg.c:378:5 + + +vprintf: + 112466: 10 04 [--sp] = rets ## printf-stdarg.c:382:0 + 112468: 12 16 r2 = r1 ## printf-stdarg.c:382:0 + 11246a: 01 16 r1 = r0 ## printf-stdarg.c:382:0 + 11246c: 40 20 r0 = 0x0 ## printf-stdarg.c:385:12 + 11246e: bf ea 6d fa call -0xb26 ## printf-stdarg.c:385:12 + 112472: 00 04 pc = [sp++] ## printf-stdarg.c:387:5 + + +perror: + 112474: 40 20 r0 = 0x0 ## printf-stdarg.c:391:0 + 112476: 80 00 rts ## printf-stdarg.c:392:5 + + +norflash_read: + 112478: 78 04 [--sp] = {rets, r8-r4} ## norflash.c:313:0 + 11247a: 34 d6 r4 = r3 # ## norflash.c:313:0 + 11247c: 08 44 r0 = b[r0+0x4] (u) ## norflash.c:317:19 + 11247e: 26 16 r6 = r2 + 112480: 15 16 r5 = r1 + 112482: c8 ff 00 41 1e 00 r8 = 0x1e4100 <__stub_doe+0xD1904 : 1e4100 > + 112488: b0 e8 00 40 if (r0 != 0x0) { + 11248c: 42 ea 00 80 [r8+0x8] = 0x0 ## norflash.c:318:28 + 112490: 40 ea 83 80 [r8+0x0] = 0x83 + } ## norflash.c:319:28 + 112494: 40 20 r0 = 0x0 ## norflash.c:323:5 + 112496: 47 20 r7 = 0x0 ## norflash.c:323:5 + 112498: bf ea 76 fb call -0x914 ## norflash.c:323:5 + 11249c: 40 23 r0 = 0x3 ## norflash.c:325:5 + 11249e: bf ea 99 fb call -0x8ce ## norflash.c:325:5 + 1124a2: b0 e1 20 68 r0 = uextra(r6, p:0x10, l:0x8) ## norflash.c:110:5 + 1124a6: bf ea 95 fb call -0x8d6 ## norflash.c:110:5 + 1124aa: b0 e1 20 64 r0 = uextra(r6, p:0x8, l:0x8) ## norflash.c:111:5 + 1124ae: bf ea 91 fb call -0x8de ## norflash.c:111:5 + 1124b2: 60 17 r0 = r6.b0 (u) ## norflash.c:112:5 + 1124b4: bf ea 8e fb call -0x8e4 ## norflash.c:112:5 + 1124b8: 30 e1 04 84 r0 = r8 + -0xbfc ## norflash.c:329:17 + 1124bc: 22 f1 fc 06 r2 = r0 + -0x1904 # ## norflash.c:329:17 + 1124c0: 87 60 [r0+0x0] = r7 ## norflash.c:329:17 + 1124c2: 00 ef 80 2d [r2+0x0] |= 0x1000 ## spi0.c:306:18 + 1124c6: 40 2a r0 = 0xa ## spi0.c:307:5 + 1124c8: bf ea d6 f6 call -0x1254 ## spi0.c:307:5 + 1124cc: c0 ef 40 2e [r2+0x0] &= 0xFFFFF3FF ## spi0.c:308:18 + 1124d0: c0 d7 r0 = r4.l (u) # ## spi0.c:311:20 + 1124d2: a5 63 [r2+0xc] = r5 ## spi0.c:310:18 + 1124d4: a0 64 [r2+0x10] = r0 ## spi0.c:311:18 + 1124d6: bf ea 74 fb call -0x918 ## spi0.c:313:5 + 1124da: 40 21 r0 = 0x1 ## norflash.c:334:5 + 1124dc: bf ea 54 fb call -0x958 ## norflash.c:334:5 + 1124e0: 40 21 r0 = 0x1 ## norflash.c:339:5 + 1124e2: d0 ec 81 70 [r8+0x0] = r7 ## norflash.c:337:24 + 1124e6: 58 04 {pc, r8-r4} = [sp++] ## norflash.c:339:5 + + +uart_isr: + 1124e8: e9 04 [--sp] = {psr, rets, reti} ## uart_upgrade.c:180:0 + 1124ea: d8 e8 3f 00 [--sp] = {r5-r0} ## uart_upgrade.c:180:0 + 1124ee: 60 e0 f1 49 r4 = 0x1E2000 ## uart_upgrade.c:180:0 + 1124f2: 40 60 r0 = [r4+0x0] ## uart_upgrade.c:181:16 + 1124f4: 50 e8 29 58 if ((r0 & 0x800) == 0) goto 0x52 ## uart_upgrade.c:181:16 + 1124f8: 00 ef 80 40 [r4+0x0] |= 0x80 ## uart_upgrade.c:182:20 + 1124fc: 00 ef a0 4d [r4+0x0] |= 0x1400 ## uart_upgrade.c:183:20 + 112500: 20 00 csync ## uart_upgrade.c:184:9 + 112502: 40 6a r0 = [r4+0x28] ## uart_upgrade.c:185:28 + 112504: 42 20 r2 = 0x0 + 112506: c0 ff 00 be 02 00 r0 = 0x2be00 + 11250c: 21 16 r1 = r2 + 11250e: 01 fc 1c 7a if (r1 > 0x3d) goto 0x38 + 112512: d8 ee 10 30 r3 = b[r1+r0] (u) ## uart_upgrade.c:120:14 + 112516: 1a 81 r2 = r1 + 0x1 ## uart_upgrade.c:120:14 + 112518: 83 f8 f8 ab if (r3 != 0x55) goto -0x10 ## uart_upgrade.c:120:14 + 11251c: 13 1c r3 = r1 + r0 ## uart_upgrade.c:120:37 + 11251e: 3b 41 r3 = b[r3+0x1] (u) ## uart_upgrade.c:120:37 + 112520: 93 f8 f4 55 if (r3 != 0xaa) goto -0x18 ## uart_upgrade.c:120:37 + 112524: 42 20 r2 = 0x0 + 112526: c3 ff c0 bd 02 00 r3 = 0x2bdc0 + 11252c: 04 89 goto 0x12 + 11252e: 95 1c r5 = r1 + r2 ## uart_upgrade.c:124:45 + 112530: cd 3f r5 += 0x3f ## uart_upgrade.c:124:45 + 112532: 65 e1 3f 50 r5 = r5 & 0x3F ## uart_upgrade.c:124:45 + 112536: d8 ee 50 50 r5 = b[r5+r0] (u) ## uart_upgrade.c:124:30 + 11253a: d8 ee 21 53 b[r2+r3] = r5 ## uart_upgrade.c:124:28 + 11253e: c2 21 r2 += 0x1 ## uart_upgrade.c:123:50 + 112540: 82 f8 f5 2b if (r2 != 0x15) goto -0x16 + 112544: bf ea d8 f7 call -0x1050 ## uart_upgrade.c:132:20 + 112548: 80 44 if (r0 != 0) goto 0x8 + 11254a: d4 e8 3f 00 {r5-r0} = [sp++] + 11254e: a9 04 {psr, rets, reti} = [sp++] + 112550: 81 00 rti + 112552: c0 ef 20 40 [r4+0x0] &= 0xFFFFFFDF ## uart_upgrade.c:189:24 + 112556: bf ea 12 f8 call -0xfdc ## uart_upgrade.c:190:13 + + +doe: + 11255a: 76 04 [--sp] = {rets, r6-r4} ## crc.c:116:0 + 11255c: b3 e8 00 40 if (r3 != 0x0) { ## crc.c:116:0 + 112560: b3 a2 r3 = r3 >> 0x2 ## crc.c:106:19 + 112562: 38 19 r0 ^= r3 + } ## crc.c:106:25 + 112564: a2 e0 01 20 r2 = 0x1 - r2 + 112568: 43 e0 de ef r3 = -0x1022 + 11256c: 04 16 r4 = r0 + 11256e: 04 93 goto 0x26 + 112570: 04 a1 r4 = r0 << 0x1 ## crc.c:91:24 + 112572: b4 19 r4 &= r3 ## crc.c:92:19 + 112574: 80 17 r0 = r0.l (u) ## crc.c:89:33 + 112576: 85 af r5 = r0 >> 0xf ## crc.c:89:33 + 112578: 54 19 r4 |= r5 ## crc.c:92:19 + 11257a: 86 ab r6 = r0 >> 0xb ## crc.c:92:30 + 11257c: 5e 19 r6 ^= r5 ## crc.c:92:34 + 11257e: 66 ac r6 = r6 << 0xc ## crc.c:92:19 + 112580: 66 e1 80 6d r6 = r6 & 0x1000 ## crc.c:92:19 + 112584: 64 19 r4 |= r6 ## crc.c:93:18 + 112586: 80 a4 r0 = r0 >> 0x4 ## crc.c:93:29 + 112588: 58 19 r0 ^= r5 ## crc.c:93:32 + 11258a: 00 a5 r0 = r0 << 0x5 ## crc.c:93:18 + 11258c: 60 e1 20 00 r0 = r0 & 0x20 ## crc.c:93:18 + 112590: 40 19 r0 |= r4 ## crc.c:94:18 + 112592: 04 17 r4 = r0.b0 (u) ## crc.c:98:21 + 112594: c2 21 r2 += 0x1 ## crc.c:110:5 + 112596: 1d 40 r5 = b[r1+0x0] (u) + 112598: 5c 19 r4 ^= r5 + 11259a: 94 07 b[r1++=0x1] = r4 + 11259c: f2 49 if (r2 != 0) goto -0x2e + 11259e: 56 04 {pc, r6-r4} = [sp++] ## crc.c:119:1 + + +strncmp: + 1125a0: 74 04 [--sp] = {rets, r4} + 1125a2: 02 4e if (r2 == 0) goto 0x1c + 1125a4: a2 e0 01 20 r2 = 0x1 - r2 + 1125a8: 04 84 goto 0x8 + 1125aa: 02 48 if (r2 == 0) goto 0x10 + 1125ac: 83 e8 06 40 if (r4 != r3) goto 0xc + 1125b0: c2 21 r2 += 0x1 + 1125b2: d0 ee 11 30 r3 = b[r1++=0x1] (u) + 1125b6: d0 ee 01 40 r4 = b[r0++=0x1] (u) + 1125ba: f4 57 if (r4 != 0) goto -0x12 + 1125bc: c8 1e r0 = r4 - r3 + 1125be: 54 04 {pc, r4} = [sp++] + 1125c0: 40 20 r0 = 0x0 + 1125c2: 54 04 {pc, r4} = [sp++] + + +strstr: + 1125c4: 74 04 [--sp] = {rets, r4} + 1125c6: 0a 40 r2 = b[r0+0x0] (u) + 1125c8: 82 4f if (r2 != 0) goto 0x1e + 1125ca: 19 40 r1 = b[r1+0x0] (u) + 1125cc: 01 4f if (r1 == 0) goto 0x1e + 1125ce: 40 20 r0 = 0x0 + 1125d0: 54 04 {pc, r4} = [sp++] + 1125d2: 42 20 r2 = 0x0 + 1125d4: d8 ee 10 32 r3 = b[r1+r2] (u) + 1125d8: 03 49 if (r3 == 0) goto 0x12 + 1125da: d8 ee 00 42 r4 = b[r0+r2] (u) + 1125de: c2 21 r2 += 0x1 + 1125e0: 04 e8 f8 31 if (r3 == r4) goto -0x10 + 1125e4: 58 ee 01 20 r2 = b[++r0=0x1] (u) + 1125e8: f2 54 if (r2 != 0) goto -0x18 + 1125ea: f7 91 goto -0x1e + 1125ec: 54 04 {pc, r4} = [sp++] + + +rom_size: + 1125ee: 00 00 nop + 1125f0: 00 00 nop + 1125f2: 00 00 nop + 1125f4: 00 00 nop + 1125f6: 00 00 nop + 1125f8: 00 00 nop + 1125fa: 00 00 nop + 1125fc: 00 00 nop + 1125fe: 00 00 nop + 112600: 00 00 nop + 112602: 00 00 nop + 112604: 00 00 nop + 112606: 00 00 nop + 112608: 00 00 nop + 11260a: 00 00 nop + 11260c: 00 00 nop + 11260e: 00 00 nop + 112610: 00 00 nop + 112612: 00 00 nop + 112614: 00 00 nop + 112616: 00 00 nop + 112618: 00 00 nop + 11261a: 00 00 nop + 11261c: 00 00 nop + 11261e: 00 00 nop + 112620: 00 00 nop + 112622: 00 00 nop + 112624: 00 00 nop + 112626: 00 00 nop + 112628: 00 00 nop + 11262a: 00 00 nop + 11262c: 00 00 nop + 11262e: 00 00 nop + 112630: 00 00 nop + 112632: 00 00 nop + 112634: 00 00 nop + 112636: 00 00 nop + 112638: 00 00 nop + 11263a: 00 00 nop + 11263c: 00 00 nop + 11263e: 00 00 nop + 112640: 00 00 nop + 112642: 00 00 nop + 112644: 00 00 nop + 112646: 00 00 nop + 112648: 00 00 nop + 11264a: 00 00 nop + 11264c: 00 00 nop + 11264e: 00 00 nop + 112650: 00 00 nop + 112652: 00 00 nop + 112654: 00 00 nop + 112656: 00 00 nop + 112658: 00 00 nop + 11265a: 00 00 nop + 11265c: 00 00 nop + 11265e: 00 00 nop + 112660: 00 00 nop + 112662: 00 00 nop + 112664: 00 00 nop + 112666: 00 00 nop + 112668: 00 00 nop + 11266a: 00 00 nop + 11266c: 00 00 nop + 11266e: 00 00 nop + 112670: 00 00 nop + 112672: 00 00 nop + 112674: 00 00 nop + 112676: 00 00 nop + 112678: 00 00 nop + 11267a: 00 00 nop + 11267c: 00 00 nop + 11267e: 00 00 nop + 112680: 00 00 nop + 112682: 00 00 nop + 112684: 00 00 nop + 112686: 00 00 nop + 112688: 00 00 nop + 11268a: 00 00 nop + 11268c: 00 00 nop + 11268e: 00 00 nop + 112690: 00 00 nop + 112692: 00 00 nop + 112694: 00 00 nop + 112696: 00 00 nop + 112698: 00 00 nop + 11269a: 00 00 nop + 11269c: 00 00 nop + 11269e: 00 00 nop + 1126a0: 00 00 nop + 1126a2: 00 00 nop + 1126a4: 00 00 nop + 1126a6: 00 00 nop + 1126a8: 00 00 nop + 1126aa: 00 00 nop + 1126ac: 00 00 nop + 1126ae: 00 00 nop + 1126b0: 00 00 nop + 1126b2: 00 00 nop + 1126b4: 00 00 nop + 1126b6: 00 00 nop + 1126b8: 00 00 nop + 1126ba: 00 00 nop + 1126bc: 00 00 nop + 1126be: 00 00 nop + 1126c0: 00 00 nop + 1126c2: 00 00 nop + 1126c4: 00 00 nop + 1126c6: 00 00 nop + 1126c8: 00 00 nop + 1126ca: 00 00 nop + 1126cc: 00 00 nop + 1126ce: 00 00 nop + 1126d0: 00 00 nop + 1126d2: 00 00 nop + 1126d4: 00 00 nop + 1126d6: 00 00 nop + 1126d8: 00 00 nop + 1126da: 00 00 nop + 1126dc: 00 00 nop + 1126de: 00 00 nop + 1126e0: 00 00 nop + 1126e2: 00 00 nop + 1126e4: 00 00 nop + 1126e6: 00 00 nop + 1126e8: 00 00 nop + 1126ea: 00 00 nop + 1126ec: 00 00 nop + 1126ee: 00 00 nop + 1126f0: 00 00 nop + 1126f2: 00 00 nop + 1126f4: 00 00 nop + 1126f6: 00 00 nop + 1126f8: 00 00 nop + 1126fa: 00 00 nop + 1126fc: 00 00 nop + 1126fe: 00 00 nop + 112700: 00 00 nop + 112702: 00 00 nop + 112704: 00 00 nop + 112706: 00 00 nop + 112708: 00 00 nop + 11270a: 00 00 nop + 11270c: 00 00 nop + 11270e: 00 00 nop + 112710: 00 00 nop + 112712: 00 00 nop + 112714: 00 00 nop + 112716: 00 00 nop + 112718: 00 00 nop + 11271a: 00 00 nop + 11271c: 00 00 nop + 11271e: 00 00 nop + 112720: 00 00 nop + 112722: 00 00 nop + 112724: 00 00 nop + 112726: 00 00 nop + 112728: 00 00 nop + 11272a: 00 00 nop + 11272c: 00 00 nop + 11272e: 00 00 nop + 112730: 00 00 nop + 112732: 00 00 nop + 112734: 00 00 nop + 112736: 00 00 nop + 112738: 00 00 nop + 11273a: 00 00 nop + 11273c: 00 00 nop + 11273e: 00 00 nop + 112740: 00 00 nop + 112742: 00 00 nop + 112744: 00 00 nop + 112746: 00 00 nop + 112748: 00 00 nop + 11274a: 00 00 nop + 11274c: 00 00 nop + 11274e: 00 00 nop + 112750: 00 00 nop + 112752: 00 00 nop + 112754: 00 00 nop + 112756: 00 00 nop + 112758: 00 00 nop + 11275a: 00 00 nop + 11275c: 00 00 nop + 11275e: 00 00 nop + 112760: 00 00 nop + 112762: 00 00 nop + 112764: 00 00 nop + 112766: 00 00 nop + 112768: 00 00 nop + 11276a: 00 00 nop + 11276c: 00 00 nop + 11276e: 00 00 nop + 112770: 00 00 nop + 112772: 00 00 nop + 112774: 00 00 nop + 112776: 00 00 nop + 112778: 00 00 nop + 11277a: 00 00 nop + 11277c: 00 00 nop + 11277e: 00 00 nop + + +__stub_local_irq_enable: + 112780: ff ea f3 ed goto -0x241a ## entry_list.S:7:0 + + +__stub_local_irq_disable: + 112784: ff ea ea ed goto -0x242c ## entry_list.S:14:0 + + +__stub_p33_buf: + 112788: ff ea 92 f4 goto -0x16dc ## entry_list.S:21:0 + + +__stub_p33_xor_1byte: + 11278c: ff ea 1e fe goto -0x3c4 ## entry_list.S:28:0 + + +__stub_p33_and_1byte: + 112790: ff ea 2e f5 goto -0x15a4 ## entry_list.S:35:0 + + +__stub_p33_or_1byte: + 112794: ff ea 07 f5 goto -0x15f2 ## entry_list.S:42:0 + + +__stub_p33_tx_1byte: + 112798: ff ea 96 f4 goto -0x16d4 ## entry_list.S:49:0 + + +__stub_p33_rx_1byte: + 11279c: ff ea be f4 goto -0x1684 ## entry_list.S:56:0 + + +__stub_P33_CON_SET: + 1127a0: ff ea 3a fe goto -0x38c ## entry_list.S:63:0 + + +__stub_memmem: + 1127a4: ff ea f1 ec goto -0x261e ## entry_list.S:70:0 + + +__stub_memcpy: + 1127a8: ff ea 59 ec goto -0x274e ## entry_list.S:77:0 + + +__stub_memmove: + 1127ac: ff ea 57 ec goto -0x2752 ## entry_list.S:84:0 + + +__stub_memcmp: + 1127b0: ff ea cc ec goto -0x2668 ## entry_list.S:91:0 + + +__stub_memset: + 1127b4: ff ea b4 ec goto -0x2698 ## entry_list.S:98:0 + + +__stub_strcmp: + 1127b8: ff ea fb ec goto -0x260a ## entry_list.S:105:0 + + +__stub_strcpy: + 1127bc: ff ea 49 ed goto -0x256e ## entry_list.S:112:0 + + +__stub_strlen: + 1127c0: ff ea 7e ed goto -0x2504 ## entry_list.S:119:0 + + +__stub_strncmp: + 1127c4: ff ea ec fe goto -0x228 ## entry_list.S:126:0 + + +__stub_strstr: + 1127c8: ff ea fc fe goto -0x208 ## entry_list.S:133:0 + + +__stub_flush_dcache: + 1127cc: ff ea 9e fd goto -0x4c4 ## entry_list.S:140:0 + + +__stub_flushinv_dcache: + 1127d0: ff ea ac fd goto -0x4a8 ## entry_list.S:147:0 + + +__stub_sfc_suspend: + 1127d4: ff ea 3c fd goto -0x588 ## entry_list.S:154:0 + + +__stub_sfc_resume: + 1127d8: ff ea 50 fd goto -0x560 ## entry_list.S:161:0 + + +__stub_sfc_drop_cache: + 1127dc: ff ea 5b fd goto -0x54a ## entry_list.S:168:0 + + +__stub_chip_crc16: + 1127e0: ff ea 7b f6 goto -0x130a ## entry_list.S:175:0 + + +__stub_CrcDecode: + 1127e4: ff ea a8 f6 goto -0x12b0 ## entry_list.S:182:0 + + +__stub_mask_init: + 1127e8: ff ea ce ed goto -0x2464 ## entry_list.S:189:0 + + +__stub_wdt_clr: + 1127ec: ff ea 44 f6 goto -0x1378 ## entry_list.S:196:0 + + +__stub_nvram_set_boot_state: + 1127f0: ff ea 9d ed goto -0x24c6 ## entry_list.S:203:0 + + +__stub_chip_reset: + 1127f4: ff ea 73 ed goto -0x251a ## entry_list.S:210:0 + + +__stub_the_debug_isr: + 1127f8: ff ea 0d ec goto -0x27e6 ## entry_list.S:217:0 + + +__stub_doe: + 1127fc: ff ea ad fe goto -0x2a6 ## entry_list.S:224:0 + diff --git a/cpu/br23/tools/run_jtag.sh b/cpu/br23/tools/run_jtag.sh new file mode 100644 index 0000000..018e370 --- /dev/null +++ b/cpu/br23/tools/run_jtag.sh @@ -0,0 +1,5 @@ +#!/bin/sh +#sleep 4 + +#-ex "detach" -ex "q" +/opt/gdb $1 -ex "target remote proxy:"${NICKNAME}"_jtag:9872" -ex "b exception_irq_handler" -ex "c" diff --git a/cpu/br23/tools/script.ver b/cpu/br23/tools/script.ver new file mode 100644 index 0000000..4484321 --- /dev/null +++ b/cpu/br23/tools/script.ver @@ -0,0 +1 @@ +AC695X-v0.01-cfg_tool-v0.08 \ No newline at end of file diff --git a/cpu/br23/tools/sdk.elf.objs.txt b/cpu/br23/tools/sdk.elf.objs.txt new file mode 100644 index 0000000..86d210e --- /dev/null +++ b/cpu/br23/tools/sdk.elf.objs.txt @@ -0,0 +1 @@ + objs/apps/common/audio/audio_digital_vol.c.o objs/apps/common/audio/audio_utils.c.o objs/apps/common/audio/decode/audio_key_tone.c.o objs/apps/common/audio/decode/decode.c.o objs/apps/common/audio/encode/encode_write_file.c.o objs/apps/common/audio/sine_make.c.o objs/apps/common/audio/stream/stream_entry.c.o objs/apps/common/audio/stream/stream_src.c.o objs/apps/common/audio/stream/stream_sync.c.o objs/apps/common/audio/uartPcmSender.c.o objs/apps/common/bt_common/bt_test_api.c.o objs/apps/common/charge_box/chargeIc_manage.c.o objs/apps/common/charge_box/chgbox_box.c.o objs/apps/common/charge_box/chgbox_ctrl.c.o objs/apps/common/charge_box/chgbox_det.c.o objs/apps/common/charge_box/chgbox_handshake.c.o objs/apps/common/charge_box/chgbox_ui.c.o objs/apps/common/charge_box/chgbox_ui_drv_pwmled.c.o objs/apps/common/charge_box/chgbox_ui_drv_timer.c.o objs/apps/common/charge_box/chgbox_wireless.c.o objs/apps/common/config/app_config.c.o objs/apps/common/config/bt_profile_config.c.o objs/apps/common/config/ci_transport_uart.c.o objs/apps/common/debug/debug.c.o objs/apps/common/debug/debug_lite.c.o objs/apps/common/dev_manager/dev_manager.c.o objs/apps/common/dev_manager/dev_reg.c.o objs/apps/common/dev_manager/dev_update.c.o objs/apps/common/device/detection.c.o objs/apps/common/device/fm/bk1080/Bk1080.c.o objs/apps/common/device/fm/fm_inside/fm_inside.c.o objs/apps/common/device/fm/fm_manage.c.o objs/apps/common/device/fm/qn8035/QN8035.c.o objs/apps/common/device/fm/rda5807/RDA5807.c.o objs/apps/common/device/fm_emitter/ac3433/ac3433.c.o objs/apps/common/device/fm_emitter/fm_emitter_manage.c.o objs/apps/common/device/fm_emitter/fm_inside/fm_emitter_inside.c.o objs/apps/common/device/fm_emitter/qn8007/qn8007.c.o objs/apps/common/device/fm_emitter/qn8027/qn8027.c.o objs/apps/common/device/gSensor/SC7A20.c.o objs/apps/common/device/gSensor/da230.c.o objs/apps/common/device/gSensor/gSensor_manage.c.o objs/apps/common/device/nandflash/nandflash.c.o objs/apps/common/device/norflash/norflash.c.o objs/apps/common/fat_nor/nor_fs.c.o objs/apps/common/fat_nor/phone_rec_fs.c.o objs/apps/common/fat_nor/virfat_flash.c.o objs/apps/common/file_operate/file_api.c.o objs/apps/common/file_operate/file_bs_deal.c.o objs/apps/common/file_operate/file_manager.c.o objs/apps/common/iap/iAP_des.c.o objs/apps/common/iap/iAP_device.c.o objs/apps/common/iap/iAP_iic.c.o objs/apps/common/key/adkey.c.o objs/apps/common/key/adkey_rtcvdd.c.o objs/apps/common/key/ctmu_touch_key.c.o objs/apps/common/key/iokey.c.o objs/apps/common/key/irkey.c.o objs/apps/common/key/key_driver.c.o objs/apps/common/key/rdec_key.c.o objs/apps/common/key/slidekey.c.o objs/apps/common/key/touch_key.c.o objs/apps/common/music/breakpoint.c.o objs/apps/common/music/general_player.c.o objs/apps/common/music/music_decrypt.c.o objs/apps/common/music/music_id3.c.o objs/apps/common/music/music_player.c.o objs/apps/common/rec_nor/nor_interface.c.o objs/apps/common/rec_nor/nor_rec_fs.c.o objs/apps/common/third_party_profile/common/3th_profile_api.c.o objs/apps/common/third_party_profile/common/custom_cfg.c.o objs/apps/common/third_party_profile/common/mic_rec.c.o objs/apps/common/third_party_profile/interface/app_protocol_api.c.o objs/apps/common/third_party_profile/interface/app_protocol_common.c.o objs/apps/common/third_party_profile/interface/app_protocol_dma.c.o objs/apps/common/third_party_profile/interface/app_protocol_gma.c.o objs/apps/common/third_party_profile/interface/app_protocol_mma.c.o objs/apps/common/third_party_profile/interface/app_protocol_ota.c.o objs/apps/common/third_party_profile/interface/app_protocol_tme.c.o objs/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_bt_name_setting.c.o objs/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_key_setting.c.o objs/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_led_setting.c.o objs/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_mic_setting.c.o objs/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_time_stamp_setting.c.o objs/apps/common/third_party_profile/jieli/JL_rcsp/adv_app_setting/adv_work_setting.c.o objs/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_opt.c.o objs/apps/common/third_party_profile/jieli/JL_rcsp/adv_rcsp_protocol/rcsp_adv_tws_sync.c.o objs/apps/common/third_party_profile/jieli/JL_rcsp/rcsp_updata/rcsp_adv_user_update.c.o objs/apps/common/third_party_profile/jieli/hid_user.c.o objs/apps/common/third_party_profile/jieli/le_client_demo.c.o objs/apps/common/third_party_profile/jieli/multi_demo/le_multi_client.c.o objs/apps/common/third_party_profile/jieli/multi_demo/le_multi_common.c.o objs/apps/common/third_party_profile/jieli/multi_demo/le_multi_trans.c.o objs/apps/common/third_party_profile/jieli/online_db/online_db_deal.c.o objs/apps/common/third_party_profile/jieli/online_db/spp_online_db.c.o objs/apps/common/third_party_profile/jieli/trans_data_demo/le_trans_data.c.o objs/apps/common/third_party_profile/jieli/trans_data_demo/spp_trans_data.c.o objs/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_client.c.o objs/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_common.c.o objs/apps/common/third_party_profile/jieli/tuya_multi/tuya_le_multi_trans.c.o objs/apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ble_app_demo.c.o objs/apps/common/third_party_profile/tuya_protocol/app/demo/tuya_ota.c.o objs/apps/common/third_party_profile/tuya_protocol/app/product_test/tuya_ble_app_production_test.c.o objs/apps/common/third_party_profile/tuya_protocol/app/uart_common/tuya_ble_app_uart_common_handler.c.o objs/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/aes.c.o objs/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/ccm.c.o objs/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/hmac.c.o objs/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/md5.c.o objs/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha1.c.o objs/apps/common/third_party_profile/tuya_protocol/extern_components/mbedtls/sha256.c.o objs/apps/common/third_party_profile/tuya_protocol/port/JL_to_tuya_ble_port_peripheral.c.o objs/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port.c.o objs/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port_AD697x.c.o objs/apps/common/third_party_profile/tuya_protocol/port/tuya_ble_port_peripheral.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_api.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_bulk_data.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_data_handler.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event_handler.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_event_handler_weak.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_feature_weather.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_gatt_send_queue.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_heap.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_main.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_mem.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_mutli_tsf_protocol.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_queue.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_storage.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_unix_time.c.o objs/apps/common/third_party_profile/tuya_protocol/sdk/src/tuya_ble_utils.c.o objs/apps/common/ui/lcd/lcd_ui_api.c.o objs/apps/common/ui/lcd_simple/lcd_simple_api.c.o objs/apps/common/ui/lcd_simple/ui.c.o objs/apps/common/ui/lcd_simple/ui_mainmenu.c.o objs/apps/common/ui/led7/led7_ui_api.c.o objs/apps/common/update/norflash_ufw_update.c.o objs/apps/common/update/norflash_update.c.o objs/apps/common/update/testbox_update.c.o objs/apps/common/update/uart_update.c.o objs/apps/common/update/uart_update_master.c.o objs/apps/common/update/update.c.o objs/apps/common/usb/device/cdc.c.o objs/apps/common/usb/device/descriptor.c.o objs/apps/common/usb/device/hid.c.o objs/apps/common/usb/device/msd.c.o objs/apps/common/usb/device/msd_upgrade.c.o objs/apps/common/usb/device/task_pc.c.o objs/apps/common/usb/device/uac1.c.o objs/apps/common/usb/device/uac_stream.c.o objs/apps/common/usb/device/usb_device.c.o objs/apps/common/usb/device/user_setup.c.o objs/apps/common/usb/host/adb.c.o objs/apps/common/usb/host/aoa.c.o objs/apps/common/usb/host/apple_mfi.c.o objs/apps/common/usb/host/audio.c.o objs/apps/common/usb/host/audio_demo.c.o objs/apps/common/usb/host/hid.c.o objs/apps/common/usb/host/usb_bulk_transfer.c.o objs/apps/common/usb/host/usb_ctrl_transfer.c.o objs/apps/common/usb/host/usb_host.c.o objs/apps/common/usb/host/usb_storage.c.o objs/apps/common/usb/usb_config.c.o objs/apps/common/usb/usb_host_config.c.o objs/apps/soundbox/aec/br23/audio_aec.c.o objs/apps/soundbox/aec/br23/audio_aec_demo.c.o objs/apps/soundbox/app_main.c.o objs/apps/soundbox/board/br23/board_ac6083a/board_ac6083a.c.o objs/apps/soundbox/board/br23/board_ac6083a/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac6083a/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac6083a/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac6083a/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac6083a/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac6083a_iap/board_ac6083a_iap.c.o objs/apps/soundbox/board/br23/board_ac6083a_iap/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac6083a_iap/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac6083a_iap/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac6083a_iap/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac6083a_iap/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac6951_kgb_v1/board_ac6951_kgb_v1.c.o objs/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac6951_kgb_v1/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac6951g/board_ac6951g.c.o objs/apps/soundbox/board/br23/board_ac6951g/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac6951g/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac6951g/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac6951g/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac6951g/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac6952e_lighter/board_ac6952e_lighter.c.o objs/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac6952e_lighter/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac6954a_demo/board_ac6954a_demo.c.o objs/apps/soundbox/board/br23/board_ac6954a_demo/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac6954a_demo/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac6954a_demo/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac6954a_demo/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac6954a_demo/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac6955f_headset_mono/board_ac6955f_headset_mono.c.o objs/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac6955f_headset_mono/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_audio_effects/board_ac695x_audio_effects.c.o objs/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_audio_effects/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_btemitter/board_ac695x_btemitter.c.o objs/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_btemitter/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_charging_bin/board_ac695x_charging_bin.c.o objs/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_charging_bin/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_cvp_develop/board_ac695x_cvp_develop.c.o objs/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_cvp_develop/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_demo/board_ac695x_demo.c.o objs/apps/soundbox/board/br23/board_ac695x_demo/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_demo/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_demo/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_demo/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_demo/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_lcd/board_ac695x_lcd.c.o objs/apps/soundbox/board/br23/board_ac695x_lcd/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_lcd/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_lcd/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_lcd/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_lcd/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_megaphone/board_ac695x_megaphone.c.o objs/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_megaphone/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/board_ac695x_multimedia_charging_bin.c.o objs/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_multimedia_charging_bin/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_smartbox/board_ac695x_smartbox.c.o objs/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_smartbox/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_soundcard/board_ac695x_soundcard.c.o objs/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_soundcard/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_tws/board_ac695x_tws.c.o objs/apps/soundbox/board/br23/board_ac695x_tws/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_tws/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_tws/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_tws/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_tws/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_tws_box/board_ac695x_tws_box.c.o objs/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/adkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/iokey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/irkey_table.c.o objs/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/rdec_key_table.c.o objs/apps/soundbox/board/br23/board_ac695x_tws_box/key_table/touch_key_table.c.o objs/apps/soundbox/board/br23/irq_config.c.o objs/apps/soundbox/common/app_sound_box_tool.c.o objs/apps/soundbox/common/dev_status.c.o objs/apps/soundbox/common/init.c.o objs/apps/soundbox/common/task_table.c.o objs/apps/soundbox/common/tone_table.c.o objs/apps/soundbox/common/user_cfg_new.c.o objs/apps/soundbox/font/fontinit.c.o objs/apps/soundbox/log_config/app_config.c.o objs/apps/soundbox/log_config/lib_btctrler_config.c.o objs/apps/soundbox/log_config/lib_btstack_config.c.o objs/apps/soundbox/log_config/lib_driver_config.c.o objs/apps/soundbox/log_config/lib_media_config.c.o objs/apps/soundbox/log_config/lib_system_config.c.o objs/apps/soundbox/log_config/lib_update_config.c.o objs/apps/soundbox/power_manage/app_charge.c.o objs/apps/soundbox/power_manage/app_chargestore.c.o objs/apps/soundbox/power_manage/app_power_manage.c.o objs/apps/soundbox/smartbox/browser/browser.c.o objs/apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_adv.c.o objs/apps/soundbox/smartbox/bt_manage/bt_trans_data/le_smartbox_module.c.o objs/apps/soundbox/smartbox/bt_manage/smartbox_bt_manage.c.o objs/apps/soundbox/smartbox/cmd_data_deal/cmd_recieve.c.o objs/apps/soundbox/smartbox/cmd_data_deal/cmd_recieve_no_respone.c.o objs/apps/soundbox/smartbox/cmd_data_deal/cmd_respone.c.o objs/apps/soundbox/smartbox/cmd_data_deal/cmd_user.c.o objs/apps/soundbox/smartbox/cmd_data_deal/command.c.o objs/apps/soundbox/smartbox/cmd_data_deal/data_recieve.c.o objs/apps/soundbox/smartbox/cmd_data_deal/data_recieve_no_respone.c.o objs/apps/soundbox/smartbox/cmd_data_deal/data_respone.c.o objs/apps/soundbox/smartbox/config.c.o objs/apps/soundbox/smartbox/event.c.o objs/apps/soundbox/smartbox/feature.c.o objs/apps/soundbox/smartbox/file_transfer/dev_format.c.o objs/apps/soundbox/smartbox/file_transfer/file_delete.c.o objs/apps/soundbox/smartbox/file_transfer/file_transfer.c.o objs/apps/soundbox/smartbox/func_cmd/bt_func.c.o objs/apps/soundbox/smartbox/func_cmd/fm_func.c.o objs/apps/soundbox/smartbox/func_cmd/linein_func.c.o objs/apps/soundbox/smartbox/func_cmd/music_func.c.o objs/apps/soundbox/smartbox/func_cmd/rtc_func.c.o objs/apps/soundbox/smartbox/function.c.o objs/apps/soundbox/smartbox/smartbox.c.o objs/apps/soundbox/smartbox/smartbox_rcsp_manage.c.o objs/apps/soundbox/smartbox/smartbox_setting/adv_bt_name_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting/adv_key_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting/adv_led_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting/adv_mic_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting/adv_time_stamp_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting/adv_work_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting/smartbox_color_led_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting/smartbox_eq_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting/smartbox_high_low_vol_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting/smartbox_karaoke_eq_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting/smartbox_karaoke_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_drc_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_reverbration_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting/smartbox_misc_setting/smartbox_misc_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting/smartbox_music_info_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting/smartbox_vol_setting.c.o objs/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_adv_bluetooth.c.o objs/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_opt.c.o objs/apps/soundbox/smartbox/smartbox_setting_opt/smartbox_setting_sync.c.o objs/apps/soundbox/smartbox/smartbox_task.c.o objs/apps/soundbox/smartbox/smartbox_update/rcsp_ch_loader_download.c.o objs/apps/soundbox/smartbox/smartbox_update/smartbox_update.c.o objs/apps/soundbox/smartbox/smartbox_update/smartbox_update_tws.c.o objs/apps/soundbox/smartbox/switch_device.c.o objs/apps/soundbox/smartbox/tuya/tuya_demo.c.o objs/apps/soundbox/soundcard/lamp.c.o objs/apps/soundbox/soundcard/notice.c.o objs/apps/soundbox/soundcard/peripheral.c.o objs/apps/soundbox/soundcard/soundcard.c.o objs/apps/soundbox/task_manager/app_common.c.o objs/apps/soundbox/task_manager/app_task_switch.c.o objs/apps/soundbox/task_manager/bt/bt.c.o objs/apps/soundbox/task_manager/bt/bt_ble.c.o objs/apps/soundbox/task_manager/bt/bt_emitter.c.o objs/apps/soundbox/task_manager/bt/bt_event_fun.c.o objs/apps/soundbox/task_manager/bt/bt_key_fun.c.o objs/apps/soundbox/task_manager/bt/bt_product_test.c.o objs/apps/soundbox/task_manager/bt/bt_switch_fun.c.o objs/apps/soundbox/task_manager/bt/bt_tws.c.o objs/apps/soundbox/task_manager/bt/vol_sync.c.o objs/apps/soundbox/task_manager/fm/fm.c.o objs/apps/soundbox/task_manager/fm/fm_api.c.o objs/apps/soundbox/task_manager/fm/fm_rw.c.o objs/apps/soundbox/task_manager/idle/idle.c.o objs/apps/soundbox/task_manager/linein/linein.c.o objs/apps/soundbox/task_manager/linein/linein_api.c.o objs/apps/soundbox/task_manager/linein/linein_dev.c.o objs/apps/soundbox/task_manager/music/music.c.o objs/apps/soundbox/task_manager/pc/pc.c.o objs/apps/soundbox/task_manager/power_off/power_off.c.o objs/apps/soundbox/task_manager/power_on/power_on.c.o objs/apps/soundbox/task_manager/record/record.c.o objs/apps/soundbox/task_manager/rtc/alarm_api.c.o objs/apps/soundbox/task_manager/rtc/alarm_user.c.o objs/apps/soundbox/task_manager/rtc/rtc.c.o objs/apps/soundbox/task_manager/rtc/virtual_rtc.c.o objs/apps/soundbox/task_manager/sleep/sleep.c.o objs/apps/soundbox/task_manager/spdif/hdmi_cec_drv.c.o objs/apps/soundbox/task_manager/spdif/spdif.c.o objs/apps/soundbox/task_manager/task_key.c.o objs/apps/soundbox/third_party_profile/ancs_client_demo/ancs_client_demo.c.o objs/apps/soundbox/third_party_profile/app_protocol_deal.c.o objs/apps/soundbox/third_party_profile/trans_data_demo/trans_data_demo.c.o objs/apps/soundbox/ui/color_led/color_led_app.c.o objs/apps/soundbox/ui/color_led/color_led_table.c.o objs/apps/soundbox/ui/color_led/driver/color_led.c.o objs/apps/soundbox/ui/color_led/driver/color_led_driver.c.o objs/apps/soundbox/ui/lcd/STYLE_02/bt_action.c.o objs/apps/soundbox/ui/lcd/STYLE_02/clock_action.c.o objs/apps/soundbox/ui/lcd/STYLE_02/file_brower.c.o objs/apps/soundbox/ui/lcd/STYLE_02/fm_action.c.o objs/apps/soundbox/ui/lcd/STYLE_02/linein_action.c.o objs/apps/soundbox/ui/lcd/STYLE_02/music_action.c.o objs/apps/soundbox/ui/lcd/STYLE_02/record_action.c.o objs/apps/soundbox/ui/lcd/STYLE_02/system_action.c.o objs/apps/soundbox/ui/lcd/lyrics_api.c.o objs/apps/soundbox/ui/lcd/ui_sys_param_api.c.o objs/apps/soundbox/ui/lcd_simple/my_demo.c.o objs/apps/soundbox/ui/led/pwm_led_api.c.o objs/apps/soundbox/ui/led/pwm_led_para_table.c.o objs/apps/soundbox/ui/led7/ui_bt.c.o objs/apps/soundbox/ui/led7/ui_common.c.o objs/apps/soundbox/ui/led7/ui_fm.c.o objs/apps/soundbox/ui/led7/ui_fm_emitter.c.o objs/apps/soundbox/ui/led7/ui_idle.c.o objs/apps/soundbox/ui/led7/ui_linein.c.o objs/apps/soundbox/ui/led7/ui_music.c.o objs/apps/soundbox/ui/led7/ui_pc.c.o objs/apps/soundbox/ui/led7/ui_record.c.o objs/apps/soundbox/ui/led7/ui_rtc.c.o objs/apps/soundbox/user_api/app_pwmled_api.c.o objs/apps/soundbox/user_api/app_record_api.c.o objs/apps/soundbox/user_api/app_special_play_api.c.o objs/apps/soundbox/user_api/app_status_api.c.o objs/apps/soundbox/user_api/dev_multiplex_api.c.o objs/apps/soundbox/user_api/product_info_api.c.o objs/apps/soundbox/version.c.o objs/cpu/br23/adc_api.c.o objs/cpu/br23/app_timer.c.o objs/cpu/br23/audio_common/app_audio.c.o objs/cpu/br23/audio_common/audio_fmtx.c.o objs/cpu/br23/audio_common/audio_iis.c.o objs/cpu/br23/audio_common/audio_link.c.o objs/cpu/br23/audio_dec/audio_dec.c.o objs/cpu/br23/audio_dec/audio_dec_bt.c.o objs/cpu/br23/audio_dec/audio_dec_file.c.o objs/cpu/br23/audio_dec/audio_dec_fm.c.o objs/cpu/br23/audio_dec/audio_dec_linein.c.o objs/cpu/br23/audio_dec/audio_dec_midi_ctrl.c.o objs/cpu/br23/audio_dec/audio_dec_midi_file.c.o objs/cpu/br23/audio_dec/audio_dec_pc.c.o objs/cpu/br23/audio_dec/audio_dec_record.c.o objs/cpu/br23/audio_dec/audio_dec_spdif.c.o objs/cpu/br23/audio_dec/audio_dec_tone.c.o objs/cpu/br23/audio_dec/audio_spectrum.c.o objs/cpu/br23/audio_dec/audio_sync.c.o objs/cpu/br23/audio_dec/audio_usb_mic.c.o objs/cpu/br23/audio_dec/lfwordana_enc_api.c.o objs/cpu/br23/audio_dec/tone_player.c.o objs/cpu/br23/audio_effect/audio_dynamic_eq_demo.c.o objs/cpu/br23/audio_effect/audio_eff_default_parm.c.o objs/cpu/br23/audio_effect/audio_eq_drc_demo.c.o objs/cpu/br23/audio_effect/audio_gain_process_demo.c.o objs/cpu/br23/audio_effect/audio_sound_track_2_p_x.c.o objs/cpu/br23/audio_effect/audio_surround_demo.c.o objs/cpu/br23/audio_effect/audio_vbass_demo.c.o objs/cpu/br23/audio_effect/audio_voice_changer_demo.c.o objs/cpu/br23/audio_effect/effects_adj.c.o objs/cpu/br23/audio_effect/eq_config.c.o objs/cpu/br23/audio_enc/audio_adc_demo.c.o objs/cpu/br23/audio_enc/audio_enc.c.o objs/cpu/br23/audio_enc/audio_enc_file.c.o objs/cpu/br23/audio_enc/audio_enc_recoder.c.o objs/cpu/br23/audio_enc/audio_mic_codec.c.o objs/cpu/br23/audio_enc/audio_recorder_mix.c.o objs/cpu/br23/audio_enc/audio_sbc_codec.c.o objs/cpu/br23/audio_mic/effect_linein.c.o objs/cpu/br23/audio_mic/effect_parm.c.o objs/cpu/br23/audio_mic/effect_reg.c.o objs/cpu/br23/audio_mic/loud_speaker.c.o objs/cpu/br23/audio_mic/mic_effect.c.o objs/cpu/br23/audio_mic/mic_stream.c.o objs/cpu/br23/audio_mic/simpleAGC.c.o objs/cpu/br23/audio_mic/vollevel_detect.c.o objs/cpu/br23/charge.c.o objs/cpu/br23/chargebox_hw.c.o objs/cpu/br23/chargestore.c.o objs/cpu/br23/clock_manager.c.o objs/cpu/br23/ctmu.c.o objs/cpu/br23/iic_eeprom_test.c.o objs/cpu/br23/iic_hw.c.o objs/cpu/br23/iic_slave_test.c.o objs/cpu/br23/iic_soft.c.o objs/cpu/br23/irflt.c.o objs/cpu/br23/led_spi.c.o objs/cpu/br23/ledc_test.c.o objs/cpu/br23/localtws/localtws.c.o objs/cpu/br23/localtws/localtws_dec.c.o objs/cpu/br23/mcpwm.c.o objs/cpu/br23/overlay_code.c.o objs/cpu/br23/plcnt.c.o objs/cpu/br23/port_wkup.c.o objs/cpu/br23/pwm_led.c.o objs/cpu/br23/setup.c.o objs/cpu/br23/spi.c.o objs/cpu/br23/spi_test.c.o objs/cpu/br23/uart_bt_product.c.o objs/cpu/br23/uart_dev.c.o objs/cpu/br23/uart_test.c.o objs/cpu/br23/ui_driver/LED_1888/LED1888.c.o objs/cpu/br23/ui_driver/interface/ui_platform.c.o objs/cpu/br23/ui_driver/lcd_seg/lcd_seg3x9_driver.c.o objs/cpu/br23/ui_driver/lcd_spi/lcd_drive.c.o objs/cpu/br23/ui_driver/lcd_spi/spi_lcd_st7735s.c.o objs/cpu/br23/ui_driver/lcd_spi/spi_lcd_st7789v.c.o objs/cpu/br23/ui_driver/lcd_spi/spi_lcd_st7789vw.c.o objs/cpu/br23/ui_driver/lcd_spi/spi_oled.c.o objs/cpu/br23/ui_driver/led7/led7_driver.c.o objs/cpu/br23/ui_driver/ui_common.c.o objs/apps/soundbox/sdk_version.z.S.o diff --git a/cpu/br23/tools/sdk.jcf b/cpu/br23/tools/sdk.jcf new file mode 100644 index 0000000..887ae61 Binary files /dev/null and b/cpu/br23/tools/sdk.jcf differ diff --git a/cpu/br23/tools/tone.cfg b/cpu/br23/tools/tone.cfg new file mode 100644 index 0000000..5a2ae32 Binary files /dev/null and b/cpu/br23/tools/tone.cfg differ diff --git a/cpu/br23/tools/tool_resource/app_ota/isd_config_app_ota.ini b/cpu/br23/tools/tool_resource/app_ota/isd_config_app_ota.ini new file mode 100644 index 0000000..7c92477 --- /dev/null +++ b/cpu/br23/tools/tool_resource/app_ota/isd_config_app_ota.ini @@ -0,0 +1,105 @@ +##################################################### +# +# 配置数据按照 长度+配置名字+数据的方式存储 +# +##################################################### + +[EXTRA_CFG_PARAM] +NEW_FLASH_FS=YES; +FORCE_VM_ALIGN=YES; +CHIP_NAME=AC695X;//8 +ENTRY=0x1E000E0;//程序入口地址 +PID=AC695x_TWS;//长度16byte,示例:芯片封装_应用方向_方案名称 +VID=0.01; + +#DOWNLOAD_MODEL=SERIAL;//usb +DOWNLOAD_MODEL=usb;// +SERIAL_DEVICE_NAME=JlVirtualJtagSerial; +SERIAL_BARD_RATE=1000000; +SERIAL_CMD_OPT=6; +SERIAL_CMD_RATE=100; [n*10000] +SERIAL_CMD_RES=0; +SERIAL_INIT_BAUD_RATE=9600; +LOADER_BAUD_RATE=1000000; +LOADER_ASK_BAUD_RATE=1000000; +#SERIAL_SEND_KEY=YES; +BEFORE_LOADER_WAIT_TIME=100; + +NEED_RESERVED_4K=YES;//关闭4K保留 + +##################################################### UBOOT配置项,请勿随意调整顺序 ################################################## +[SYS_CFG_PARAM] +#data_width[0 1 2 3 4] 3的时候uboot自动识别2或者4线 +#clk [0-255] +#mode: +# 0 RD_OUTPUT, 1 cmd 1 addr +# 1 RD_I/O, 1 cmd x addr +# 2 RD_I/O_CONTINUE] no_send_cmd x add +#port: +# 0 优先选A端口 CS:PD3 CLK:PD0 D0:PD1 D1:PD2 D2:PB7 D3:PD5 +# 1 优先选B端口 CS:PA13 CLK:PD0 D0:PD1 D1:PA14 D2:PA15 D3:PD5 +SPI=2_3_0_0; #width_clk_mode_port; +#OSC=btosc; +#OSC_FREQ=12MHz; #[24MHz 12MHz] +#SYS_CLK=24MHz; #[48MHz 24MHz] +#UTTX=PA05;//uboot串口tx +#UTBD=1000000;//uboot串口波特率 +#UTRX=PB01;串口升级[PB00 PB05 PA05] +RESET=PB01_08_0; //port口_长按时间_有效电平(长按时间有00、01、02、04、08五个值可选,单位为秒,当长按时间为00时,则关闭长按复位功能。) + +#0:disable +#1:PA9 PA10 +#2:USB +#3:PB1 PB2 +#4:PB6 PB7 + +#sdtap=2; +psram=0; +UPDATE_JUMP=0; + +VLVD=4;//VDDIO_LVD挡位,0: 1.9V 1: 2.0V 2: 2.1V 3: 2.2V 4: 2.3V 5: 2.4V 6: 2.5V 7: 2.6V + +EOFFSET=0; // 4k * n,默认强制不偏移 + +############################################################################################################################################# + + + +########flash空间使用配置区域############################################### +#PDCTNAME: 产品名,对应此代码,用于标识产品,升级时可以选择匹配产品名 +#BOOT_FIRST: 1=代码更新后,提示APP是第一次启动;0=代码更新后,不提示 +#UPVR_CTL: 0:不允许高版本升级低版本 1:允许高版本升级低版本 +#XXXX_ADR: 区域起始地址 AUTO:由工具自动分配起始地址 +#XXXX_LEN: 区域长度 CODE_LEN:代码长度 +#XXXX_OPT: 区域操作属性 +# +# +# +#操作符说明 OPT: +# 0: 下载代码时擦除指定区域 +# 1: 下载代码时不操作指定区域 +# 2: 下载代码时给指定区域加上保护 +############################################################################ +[RESERVED_CONFIG] +BTIF_ADR=AUTO; +BTIF_LEN=0x1000; +BTIF_OPT=1; + +EXIF_ADR=AUTO; +EXIF_LEN=0x1000; +EXIF_OPT=1; + +#WTIF_ADR=BEGIN_END; +#WTIF_LEN=0x1000; +#WTIF_OPT=1; + +PRCT_ADR=0; +PRCT_LEN=CODE_LEN; +PRCT_OPT=2; + +VM_ADR=0; +VM_LEN=64K; +VM_OPT=1; + +[BURNER_CONFIG] +SIZE=32; diff --git a/cpu/br23/tools/tool_resource/app_ota/json.txt b/cpu/br23/tools/tool_resource/app_ota/json.txt new file mode 100644 index 0000000..3819126 --- /dev/null +++ b/cpu/br23/tools/tool_resource/app_ota/json.txt @@ -0,0 +1,55 @@ +{ + "output": "config.dat", + "defines": + { + "DEFINE1": "0xA", + "DEFINE2": "0xB", + "DEFINE3": "0xC", + "DEFINE4": "default4", + "DEFINE5": "default5", + "DEFINE6": 1234, + "DEFINE7": 1, + "DEFINE8": 2, + "DEFINE9": 3234, + "DEFINE10": 4 + }, + "items": + [ + { + "name": "ver_info", + "说明": "版本信息:VID(2byte),PID(2byte),VER(2byte)", + "type": "ARRAY", + "data": "0x00, 0x00, 0x00, 0x00, 0x00, 0x00" + }, + { + "name": "ver_info_ext", + "说明": "额外信息(AuthKey,ProCode)", + "type": "STRING", + "data": "hE9yfseX6UdK7rFh,AI_SDK_test1" + }, + { + "name": "reset_io", + "说明": "uboot中PR口长按复位io选择,目前可配0、1、2、3", + "type": "STRING", + "data": "1" + }, + { + "name": "pilot_lamp_io", + "说明": "uboot中led指示灯IO配置,目前可配PA、PB、PC、PD", + "type": "STRING", + "data": "PB03" + }, + { + "name": "link_key", + "说明": "用于link_key_data的配置", + "type": "ARRAY", + "data": "0x06, 0x77, 0x5f, 0x87, 0x91, 0x8d, 0xd4, 0x23, 0x00, 0x5d, 0xf1, 0xd8, 0xcf, 0x0c, 0x14, 0x2b" + }, + { + "name": "power_io", + "说明": "用与电源io的配置,0代表低电平,1代表高电平", + "type": "STRING", + "data": "PC03_1" + } + ] +} diff --git a/cpu/br23/tools/tool_resource/app_ota/json_to_res.exe b/cpu/br23/tools/tool_resource/app_ota/json_to_res.exe new file mode 100644 index 0000000..cb2bf1f Binary files /dev/null and b/cpu/br23/tools/tool_resource/app_ota/json_to_res.exe differ diff --git a/cpu/br23/tools/uboot.boot b/cpu/br23/tools/uboot.boot new file mode 100644 index 0000000..95bef82 Binary files /dev/null and b/cpu/br23/tools/uboot.boot differ diff --git a/cpu/br23/tools/uboot.boot_debug b/cpu/br23/tools/uboot.boot_debug new file mode 100644 index 0000000..760829e Binary files /dev/null and b/cpu/br23/tools/uboot.boot_debug differ diff --git a/cpu/br23/tools/uboot_no_ota.boot b/cpu/br23/tools/uboot_no_ota.boot new file mode 100644 index 0000000..cd66618 Binary files /dev/null and b/cpu/br23/tools/uboot_no_ota.boot differ diff --git a/cpu/br23/tools/uboot_no_ota.boot_debug b/cpu/br23/tools/uboot_no_ota.boot_debug new file mode 100644 index 0000000..8a41bc4 Binary files /dev/null and b/cpu/br23/tools/uboot_no_ota.boot_debug differ diff --git a/cpu/br23/tools/ufw_maker.exe b/cpu/br23/tools/ufw_maker.exe new file mode 100644 index 0000000..dc8716e Binary files /dev/null and b/cpu/br23/tools/ufw_maker.exe differ diff --git a/cpu/br23/tools/update.ufw b/cpu/br23/tools/update.ufw new file mode 100644 index 0000000..5175971 Binary files /dev/null and b/cpu/br23/tools/update.ufw differ diff --git a/cpu/br23/tools/提示音/0.mp3 b/cpu/br23/tools/提示音/0.mp3 new file mode 100644 index 0000000..7510f66 Binary files /dev/null and b/cpu/br23/tools/提示音/0.mp3 differ diff --git a/cpu/br23/tools/提示音/0.wtg b/cpu/br23/tools/提示音/0.wtg new file mode 100644 index 0000000..cfc1365 Binary files /dev/null and b/cpu/br23/tools/提示音/0.wtg differ diff --git a/cpu/br23/tools/提示音/1.mp3 b/cpu/br23/tools/提示音/1.mp3 new file mode 100644 index 0000000..43fb785 Binary files /dev/null and b/cpu/br23/tools/提示音/1.mp3 differ diff --git a/cpu/br23/tools/提示音/1.wtg b/cpu/br23/tools/提示音/1.wtg new file mode 100644 index 0000000..5713df3 Binary files /dev/null and b/cpu/br23/tools/提示音/1.wtg differ diff --git a/cpu/br23/tools/提示音/2.mp3 b/cpu/br23/tools/提示音/2.mp3 new file mode 100644 index 0000000..25580cc Binary files /dev/null and b/cpu/br23/tools/提示音/2.mp3 differ diff --git a/cpu/br23/tools/提示音/2.wtg b/cpu/br23/tools/提示音/2.wtg new file mode 100644 index 0000000..e0ca6a6 Binary files /dev/null and b/cpu/br23/tools/提示音/2.wtg differ diff --git a/cpu/br23/tools/提示音/3.mp3 b/cpu/br23/tools/提示音/3.mp3 new file mode 100644 index 0000000..7290a6e Binary files /dev/null and b/cpu/br23/tools/提示音/3.mp3 differ diff --git a/cpu/br23/tools/提示音/3.wtg b/cpu/br23/tools/提示音/3.wtg new file mode 100644 index 0000000..2b7a201 Binary files /dev/null and b/cpu/br23/tools/提示音/3.wtg differ diff --git a/cpu/br23/tools/提示音/4.mp3 b/cpu/br23/tools/提示音/4.mp3 new file mode 100644 index 0000000..1e88666 Binary files /dev/null and b/cpu/br23/tools/提示音/4.mp3 differ diff --git a/cpu/br23/tools/提示音/4.wtg b/cpu/br23/tools/提示音/4.wtg new file mode 100644 index 0000000..10f15ea Binary files /dev/null and b/cpu/br23/tools/提示音/4.wtg differ diff --git a/cpu/br23/tools/提示音/5.mp3 b/cpu/br23/tools/提示音/5.mp3 new file mode 100644 index 0000000..b3c241c Binary files /dev/null and b/cpu/br23/tools/提示音/5.mp3 differ diff --git a/cpu/br23/tools/提示音/5.wtg b/cpu/br23/tools/提示音/5.wtg new file mode 100644 index 0000000..0b1cd2e Binary files /dev/null and b/cpu/br23/tools/提示音/5.wtg differ diff --git a/cpu/br23/tools/提示音/6.mp3 b/cpu/br23/tools/提示音/6.mp3 new file mode 100644 index 0000000..d3a769a Binary files /dev/null and b/cpu/br23/tools/提示音/6.mp3 differ diff --git a/cpu/br23/tools/提示音/6.wtg b/cpu/br23/tools/提示音/6.wtg new file mode 100644 index 0000000..225f62d Binary files /dev/null and b/cpu/br23/tools/提示音/6.wtg differ diff --git a/cpu/br23/tools/提示音/7.mp3 b/cpu/br23/tools/提示音/7.mp3 new file mode 100644 index 0000000..f6b67c0 Binary files /dev/null and b/cpu/br23/tools/提示音/7.mp3 differ diff --git a/cpu/br23/tools/提示音/7.wtg b/cpu/br23/tools/提示音/7.wtg new file mode 100644 index 0000000..fa6a266 Binary files /dev/null and b/cpu/br23/tools/提示音/7.wtg differ diff --git a/cpu/br23/tools/提示音/8.mp3 b/cpu/br23/tools/提示音/8.mp3 new file mode 100644 index 0000000..b0d3389 Binary files /dev/null and b/cpu/br23/tools/提示音/8.mp3 differ diff --git a/cpu/br23/tools/提示音/8.wtg b/cpu/br23/tools/提示音/8.wtg new file mode 100644 index 0000000..60d28c4 Binary files /dev/null and b/cpu/br23/tools/提示音/8.wtg differ diff --git a/cpu/br23/tools/提示音/9.mp3 b/cpu/br23/tools/提示音/9.mp3 new file mode 100644 index 0000000..3fa4e86 Binary files /dev/null and b/cpu/br23/tools/提示音/9.mp3 differ diff --git a/cpu/br23/tools/提示音/9.wtg b/cpu/br23/tools/提示音/9.wtg new file mode 100644 index 0000000..9b6ab47 Binary files /dev/null and b/cpu/br23/tools/提示音/9.wtg differ diff --git a/cpu/br23/tools/提示音/bt.mp3 b/cpu/br23/tools/提示音/bt.mp3 new file mode 100644 index 0000000..3342c04 Binary files /dev/null and b/cpu/br23/tools/提示音/bt.mp3 differ diff --git a/cpu/br23/tools/提示音/bt.wtg b/cpu/br23/tools/提示音/bt.wtg new file mode 100644 index 0000000..c14ce49 Binary files /dev/null and b/cpu/br23/tools/提示音/bt.wtg differ diff --git a/cpu/br23/tools/提示音/bt_conn.mp3 b/cpu/br23/tools/提示音/bt_conn.mp3 new file mode 100644 index 0000000..8da4a92 Binary files /dev/null and b/cpu/br23/tools/提示音/bt_conn.mp3 differ diff --git a/cpu/br23/tools/提示音/bt_conn.wtg b/cpu/br23/tools/提示音/bt_conn.wtg new file mode 100644 index 0000000..58c8f76 Binary files /dev/null and b/cpu/br23/tools/提示音/bt_conn.wtg differ diff --git a/cpu/br23/tools/提示音/bt_dconn.mp3 b/cpu/br23/tools/提示音/bt_dconn.mp3 new file mode 100644 index 0000000..577af80 Binary files /dev/null and b/cpu/br23/tools/提示音/bt_dconn.mp3 differ diff --git a/cpu/br23/tools/提示音/bt_dconn.wtg b/cpu/br23/tools/提示音/bt_dconn.wtg new file mode 100644 index 0000000..3c5f16d Binary files /dev/null and b/cpu/br23/tools/提示音/bt_dconn.wtg differ diff --git a/cpu/br23/tools/提示音/con_fail.mp3 b/cpu/br23/tools/提示音/con_fail.mp3 new file mode 100644 index 0000000..5416525 Binary files /dev/null and b/cpu/br23/tools/提示音/con_fail.mp3 differ diff --git a/cpu/br23/tools/提示音/con_ok.mp3 b/cpu/br23/tools/提示音/con_ok.mp3 new file mode 100644 index 0000000..96883a4 Binary files /dev/null and b/cpu/br23/tools/提示音/con_ok.mp3 differ diff --git a/cpu/br23/tools/提示音/fm.mp3 b/cpu/br23/tools/提示音/fm.mp3 new file mode 100644 index 0000000..b8ebbe7 Binary files /dev/null and b/cpu/br23/tools/提示音/fm.mp3 differ diff --git a/cpu/br23/tools/提示音/fm.wtg b/cpu/br23/tools/提示音/fm.wtg new file mode 100644 index 0000000..77a7a54 Binary files /dev/null and b/cpu/br23/tools/提示音/fm.wtg differ diff --git a/cpu/br23/tools/提示音/linein.mp3 b/cpu/br23/tools/提示音/linein.mp3 new file mode 100644 index 0000000..bcebb65 Binary files /dev/null and b/cpu/br23/tools/提示音/linein.mp3 differ diff --git a/cpu/br23/tools/提示音/linein.wtg b/cpu/br23/tools/提示音/linein.wtg new file mode 100644 index 0000000..b5f8563 Binary files /dev/null and b/cpu/br23/tools/提示音/linein.wtg differ diff --git a/cpu/br23/tools/提示音/low_power.mp3 b/cpu/br23/tools/提示音/low_power.mp3 new file mode 100644 index 0000000..b21fa76 Binary files /dev/null and b/cpu/br23/tools/提示音/low_power.mp3 differ diff --git a/cpu/br23/tools/提示音/low_power.wtg b/cpu/br23/tools/提示音/low_power.wtg new file mode 100644 index 0000000..eb7e14c Binary files /dev/null and b/cpu/br23/tools/提示音/low_power.wtg differ diff --git a/cpu/br23/tools/提示音/music.mp3 b/cpu/br23/tools/提示音/music.mp3 new file mode 100644 index 0000000..a7a41c7 Binary files /dev/null and b/cpu/br23/tools/提示音/music.mp3 differ diff --git a/cpu/br23/tools/提示音/music.wtg b/cpu/br23/tools/提示音/music.wtg new file mode 100644 index 0000000..89d63d2 Binary files /dev/null and b/cpu/br23/tools/提示音/music.wtg differ diff --git a/cpu/br23/tools/提示音/paired.mp3 b/cpu/br23/tools/提示音/paired.mp3 new file mode 100644 index 0000000..0df4e27 Binary files /dev/null and b/cpu/br23/tools/提示音/paired.mp3 differ diff --git a/cpu/br23/tools/提示音/paired.wtg b/cpu/br23/tools/提示音/paired.wtg new file mode 100644 index 0000000..9e5ebd4 Binary files /dev/null and b/cpu/br23/tools/提示音/paired.wtg differ diff --git a/cpu/br23/tools/提示音/pc.mp3 b/cpu/br23/tools/提示音/pc.mp3 new file mode 100644 index 0000000..93b5a84 Binary files /dev/null and b/cpu/br23/tools/提示音/pc.mp3 differ diff --git a/cpu/br23/tools/提示音/pc.wtg b/cpu/br23/tools/提示音/pc.wtg new file mode 100644 index 0000000..6286670 Binary files /dev/null and b/cpu/br23/tools/提示音/pc.wtg differ diff --git a/cpu/br23/tools/提示音/play_rec.mp3 b/cpu/br23/tools/提示音/play_rec.mp3 new file mode 100644 index 0000000..802b809 Binary files /dev/null and b/cpu/br23/tools/提示音/play_rec.mp3 differ diff --git a/cpu/br23/tools/提示音/play_rec.wtg b/cpu/br23/tools/提示音/play_rec.wtg new file mode 100644 index 0000000..50c2830 Binary files /dev/null and b/cpu/br23/tools/提示音/play_rec.wtg differ diff --git a/cpu/br23/tools/提示音/power_off.mp3 b/cpu/br23/tools/提示音/power_off.mp3 new file mode 100644 index 0000000..a854190 Binary files /dev/null and b/cpu/br23/tools/提示音/power_off.mp3 differ diff --git a/cpu/br23/tools/提示音/power_off.wtg b/cpu/br23/tools/提示音/power_off.wtg new file mode 100644 index 0000000..111ea09 Binary files /dev/null and b/cpu/br23/tools/提示音/power_off.wtg differ diff --git a/cpu/br23/tools/提示音/power_on.mp3 b/cpu/br23/tools/提示音/power_on.mp3 new file mode 100644 index 0000000..ffe2e63 Binary files /dev/null and b/cpu/br23/tools/提示音/power_on.mp3 differ diff --git a/cpu/br23/tools/提示音/power_on.wtg b/cpu/br23/tools/提示音/power_on.wtg new file mode 100644 index 0000000..6ccd529 Binary files /dev/null and b/cpu/br23/tools/提示音/power_on.wtg differ diff --git a/cpu/br23/tools/提示音/record.mp3 b/cpu/br23/tools/提示音/record.mp3 new file mode 100644 index 0000000..bc067f0 Binary files /dev/null and b/cpu/br23/tools/提示音/record.mp3 differ diff --git a/cpu/br23/tools/提示音/record.wtg b/cpu/br23/tools/提示音/record.wtg new file mode 100644 index 0000000..a9df46b Binary files /dev/null and b/cpu/br23/tools/提示音/record.wtg differ diff --git a/cpu/br23/tools/提示音/ring.wtg b/cpu/br23/tools/提示音/ring.wtg new file mode 100644 index 0000000..a0bdd84 Binary files /dev/null and b/cpu/br23/tools/提示音/ring.wtg differ diff --git a/cpu/br23/tools/提示音/rtc.mp3 b/cpu/br23/tools/提示音/rtc.mp3 new file mode 100644 index 0000000..c41be7c Binary files /dev/null and b/cpu/br23/tools/提示音/rtc.mp3 differ diff --git a/cpu/br23/tools/提示音/rtc.wtg b/cpu/br23/tools/提示音/rtc.wtg new file mode 100644 index 0000000..3241c17 Binary files /dev/null and b/cpu/br23/tools/提示音/rtc.wtg differ diff --git a/cpu/br23/tools/提示音/start_rec.mp3 b/cpu/br23/tools/提示音/start_rec.mp3 new file mode 100644 index 0000000..60eea79 Binary files /dev/null and b/cpu/br23/tools/提示音/start_rec.mp3 differ diff --git a/cpu/br23/tools/提示音/start_rec.wtg b/cpu/br23/tools/提示音/start_rec.wtg new file mode 100644 index 0000000..c1787e4 Binary files /dev/null and b/cpu/br23/tools/提示音/start_rec.wtg differ diff --git a/cpu/br23/tools/提示音/stop_rec.mp3 b/cpu/br23/tools/提示音/stop_rec.mp3 new file mode 100644 index 0000000..78f96bb Binary files /dev/null and b/cpu/br23/tools/提示音/stop_rec.mp3 differ diff --git a/cpu/br23/tools/提示音/stop_rec.wtg b/cpu/br23/tools/提示音/stop_rec.wtg new file mode 100644 index 0000000..cfd0fbb Binary files /dev/null and b/cpu/br23/tools/提示音/stop_rec.wtg differ diff --git a/cpu/br23/tools/提示音/tws_conn.mp3 b/cpu/br23/tools/提示音/tws_conn.mp3 new file mode 100644 index 0000000..7fe13bf Binary files /dev/null and b/cpu/br23/tools/提示音/tws_conn.mp3 differ diff --git a/cpu/br23/tools/提示音/tws_conn.wtg b/cpu/br23/tools/提示音/tws_conn.wtg new file mode 100644 index 0000000..6dadfff Binary files /dev/null and b/cpu/br23/tools/提示音/tws_conn.wtg differ diff --git a/cpu/br23/tools/提示音/tws_dconn.mp3 b/cpu/br23/tools/提示音/tws_dconn.mp3 new file mode 100644 index 0000000..85c996b Binary files /dev/null and b/cpu/br23/tools/提示音/tws_dconn.mp3 differ diff --git a/cpu/br23/tools/提示音/tws_dconn.wtg b/cpu/br23/tools/提示音/tws_dconn.wtg new file mode 100644 index 0000000..e4b6d6e Binary files /dev/null and b/cpu/br23/tools/提示音/tws_dconn.wtg differ diff --git a/cpu/br23/tools/提示音/vol_max.mp3 b/cpu/br23/tools/提示音/vol_max.mp3 new file mode 100644 index 0000000..d3e96de Binary files /dev/null and b/cpu/br23/tools/提示音/vol_max.mp3 differ diff --git a/cpu/br23/tools/提示音/vol_max.wtg b/cpu/br23/tools/提示音/vol_max.wtg new file mode 100644 index 0000000..bba65e6 Binary files /dev/null and b/cpu/br23/tools/提示音/vol_max.wtg differ diff --git a/cpu/br23/tools/提示音/wait_con.mp3 b/cpu/br23/tools/提示音/wait_con.mp3 new file mode 100644 index 0000000..33982a6 Binary files /dev/null and b/cpu/br23/tools/提示音/wait_con.mp3 differ diff --git a/cpu/br23/tools/提示音/wait_con.wtg b/cpu/br23/tools/提示音/wait_con.wtg new file mode 100644 index 0000000..5e8433f Binary files /dev/null and b/cpu/br23/tools/提示音/wait_con.wtg differ diff --git a/cpu/br23/uart_bt_product.c b/cpu/br23/uart_bt_product.c new file mode 100644 index 0000000..a0b411c --- /dev/null +++ b/cpu/br23/uart_bt_product.c @@ -0,0 +1,181 @@ +#include "system/includes.h" +#include "asm/uart_dev.h" + +#if 0 +/* + [[ 注意!!! ]] + * 如果当系统任务较少时使用本demo,需要将低功耗关闭(#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN ),否则任务被串口接收函数调用信号量pend时会导致cpu休眠,串口中断和DMA接收将遗漏数据或数据不正确 +*/ + +#define UART_DEV_USAGE_TEST_SEL 2 //uart_dev.c api接口使用方法选择 +// 选择1 串口中断回调函数推送事件,由事件响应函数接收串口数据 +// 选择2 由task接收串口数据 + +#define UART_DEV_TEST_MULTI_BYTE 1 //uart_dev.c 读写多个字节api / 读写1个字节api 选择 + +static u8 uart_cbuf[512] __attribute__((aligned(4))); +static u8 uart_rxbuf[512] __attribute__((aligned(4))); + +void set_bt_uart_bus(uart_bus_t *uart_bus); +void bt_product_test_uart(u8 *data, u16 len); + +static void my_put_u8hex(u8 dat) +{ + u8 tmp; + tmp = dat / 16; + if (tmp < 10) { + putchar(tmp + '0'); + } else { + putchar(tmp - 10 + 'A'); + } + tmp = dat % 16; + if (tmp < 10) { + putchar(tmp + '0'); + } else { + putchar(tmp - 10 + 'A'); + } + putchar(0x20); +} + +//设备事件响应demo +static void uart_event_handler(struct sys_event *e) +{ + const uart_bus_t *uart_bus; + u32 uart_rxcnt = 0; + + if (!strcmp(e->arg, "uart_rx_overflow")) { + if (e->u.dev.event == DEVICE_EVENT_CHANGE) { + printf("uart event: %s\n", e->arg); + uart_bus = (const uart_bus_t *)e->u.dev.value; + uart_rxcnt = uart_bus->read(uart_rxbuf, sizeof(uart_rxbuf), 0); + if (uart_rxcnt) { + printf("get_buffer:\n"); + for (int i = 0; i < uart_rxcnt; i++) { + my_put_u8hex(uart_rxbuf[i]); + if (i % 16 == 15) { + putchar('\n'); + } + } + if (uart_rxcnt % 16) { + putchar('\n'); + } + uart_bus->write(uart_rxbuf, uart_rxcnt); + } + printf("uart out\n"); + } + } + if (!strcmp(e->arg, "uart_rx_outtime")) { + if (e->u.dev.event == DEVICE_EVENT_CHANGE) { + printf("uart event: %s\n", e->arg); + uart_bus = (const uart_bus_t *)e->u.dev.value; + uart_rxcnt = uart_bus->read(uart_rxbuf, sizeof(uart_rxbuf), 0); + if (uart_rxcnt) { + printf("get_buffer:\n"); + for (int i = 0; i < uart_rxcnt; i++) { + my_put_u8hex(uart_rxbuf[i]); + if (i % 16 == 15) { + putchar('\n'); + } + } + if (uart_rxcnt % 16) { + putchar('\n'); + } + uart_bus->write(uart_rxbuf, uart_rxcnt); + } + printf("uart out\n"); + } + } +} +SYS_EVENT_HANDLER(SYS_DEVICE_EVENT, uart_event_handler, 0); + +static void uart_u_task(void *arg) +{ + const uart_bus_t *uart_bus = arg; + int ret; + u32 uart_rxcnt = 0; + + printf("uart_u_task start\n"); + while (1) { +#if !UART_DEV_TEST_MULTI_BYTE + //uart_bus->getbyte()在尚未收到串口数据时会pend信号量,挂起task,直到UART_RX_PND或UART_RX_OT_PND中断发生,post信号量,唤醒task + ret = uart_bus->getbyte(&uart_rxbuf[0], 0); + if (ret) { + uart_rxcnt = 1; + printf("get_byte: %02x\n", uart_rxbuf[0]); + uart_bus->putbyte(uart_rxbuf[0]); + } +#else + //uart_bus->read()在尚未收到串口数据时会pend信号量,挂起task,直到UART_RX_PND或UART_RX_OT_PND中断发生,post信号量,唤醒task + uart_rxcnt = uart_bus->read(uart_rxbuf, sizeof(uart_rxbuf), 0); + if (uart_rxcnt) { + printf(" ** get_buffer:\n"); + for (int i = 0; i < uart_rxcnt; i++) { + my_put_u8hex(uart_rxbuf[i]); + if (i % 16 == 15) { + putchar('\n'); + } + } + if (uart_rxcnt % 16) { + putchar('\n'); + } + bt_product_test_uart(uart_rxbuf, uart_rxcnt); + /* uart_bus->write(uart_rxbuf, uart_rxcnt); */ + } +#endif + } +} + +static void uart_isr_hook(void *arg, u32 status) +{ + const uart_bus_t *ubus = arg; + struct sys_event e; + + //当CONFIG_UARTx_ENABLE_TX_DMA(x = 0, 1)为1时,不要在中断里面调用ubus->write(),因为中断不能pend信号量 + if (status == UT_RX) { + printf("uart_rx_isr\n"); +#if (UART_DEV_USAGE_TEST_SEL == 1) + e.type = SYS_DEVICE_EVENT; + e.arg = "uart_rx_overflow"; + e.u.dev.event = DEVICE_EVENT_CHANGE; + e.u.dev.value = (int)ubus; + sys_event_notify(&e); +#endif + } + if (status == UT_RX_OT) { + printf("uart_rx_ot_isr\n"); +#if (UART_DEV_USAGE_TEST_SEL == 1) + e.type = SYS_DEVICE_EVENT; + e.arg = "uart_rx_outtime"; + e.u.dev.event = DEVICE_EVENT_CHANGE; + e.u.dev.value = (int)ubus; + sys_event_notify(&e); +#endif + } +} + +void uart_dev_test_main() +{ + const uart_bus_t *uart_bus; + struct uart_platform_data_t u_arg = {0}; + u_arg.tx_pin = IO_PORTA_01; + u_arg.rx_pin = IO_PORTA_02; + u_arg.rx_cbuf = uart_cbuf; + u_arg.rx_cbuf_size = 512; + u_arg.frame_length = 32; + u_arg.rx_timeout = 100; + u_arg.isr_cbfun = uart_isr_hook; + u_arg.baud = 9600; + u_arg.is_9bit = 0; + + uart_bus = uart_dev_open(&u_arg); + if (uart_bus != NULL) { + printf("uart_dev_open() success\n"); + + set_bt_uart_bus(uart_bus); + +#if (UART_DEV_USAGE_TEST_SEL == 2) + os_task_create(uart_u_task, (void *)uart_bus, 31, 512, 0, "uart_u_task"); +#endif + } +} +#endif diff --git a/cpu/br23/uart_dev.c b/cpu/br23/uart_dev.c new file mode 100644 index 0000000..5bb3c07 --- /dev/null +++ b/cpu/br23/uart_dev.c @@ -0,0 +1,931 @@ +/** + * @file uart.c + * @author JL + * @brief 串口UART模块C文件 + * @version 1.2 + * @date 2018-11-22 + */ + +#include "asm/clock.h" +#include "asm/uart_dev.h" +#include "asm/cpu.h" +#include "generic/gpio.h" +#include "spinlock.h" + +#ifdef SUPPORT_MS_EXTENSIONS +#pragma bss_seg(".uart_bss") +#pragma data_seg(".uart_data") +#pragma const_seg(".uart_const") +#pragma code_seg(".uart_code") +#endif + +#define UART_CLK clk_get("uart") +#define UART_OT_CLK clk_get("lsb") + + + +static uart_bus_t uart0; +static uart_bus_t uart1; +static uart_bus_t uart2; + +/* _WEAK_ */ +/* extern */ +const u32 CONFIG_UART0_ENABLE = 1; + +/* _WEAK_ */ +/* extern */ +const u32 CONFIG_UART1_ENABLE = 1; + +/* _WEAK_ */ +/* extern */ +const u32 CONFIG_UART2_ENABLE = 1; + +/* _WEAK_ */ +/* extern */ +const u32 CONFIG_UART0_ENABLE_TX_DMA = 1; + +/* _WEAK_ */ +/* extern */ +const u32 CONFIG_UART1_ENABLE_TX_DMA = 1; + +/* _WEAK_ */ +/* extern */ +const u32 CONFIG_UART2_ENABLE_TX_DMA = 1; + + +static u32 kfifo_get(KFIFO *kfifo, u8 *buffer, u32 len) +{ + unsigned int i; + len = MIN(len, kfifo->buf_in - kfifo->buf_out); + + i = MIN(len, kfifo->buf_size - (kfifo->buf_out & (kfifo->buf_size - 1))); + + memcpy(buffer, kfifo->buffer + (kfifo->buf_out & (kfifo->buf_size - 1)), i); + + memcpy(buffer + i, kfifo->buffer, len - i); + + kfifo->buf_out += len; + return len; + +} +static u32 kfifo_length(KFIFO *kfifo) +{ + return kfifo->buf_in - kfifo->buf_out; +} +/** + * @brief ut0发送一个byte + * + * @param a 要发送的字节 + */ +static void UT0_putbyte(char a) +{ + if (JL_UART0->CON0 & BIT(0)) { + JL_UART0->BUF = a; + __asm__ volatile("csync"); + while ((JL_UART0->CON0 & BIT(15)) == 0); + JL_UART0->CON0 |= BIT(13); + } +} +/** + * @brief ut0接收一个byte + * + * @param buf 字节存放地址 + * @param timeout 接收超时时间,单位1ms + * @return 返回0:接收失败;返回1:接收成功 + */ +static u8 UT0_getbyte(u8 *buf, u32 timeout) +{ + u32 _timeout, _t_sleep; + timeout = ut_msecs_to_jiffies(timeout); + if (JL_UART0->CON0 & BIT(6)) { + //DMA_MODE + if (!kfifo_length(&uart0.kfifo)) { + UT_OSSemPend(&uart0.sem_rx, timeout); + } + UT_OSSemSet(&uart0.sem_rx, 0); + + return kfifo_get(&uart0.kfifo, buf, 1); + } else { + _timeout = timeout + ut_get_jiffies(); + _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies(); + while (!(JL_UART0->CON0 & BIT(14))) { + if (timeout && time_before(_timeout, ut_get_jiffies())) { + return 0; + } + if (time_before(_t_sleep, ut_get_jiffies())) { + ut_sleep(); + _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies(); + } + } + *buf = JL_UART0->BUF; + JL_UART0->CON0 |= BIT(12); + __asm__ volatile("csync"); //make RX_PND_CLR taking effect + } + return 1; +} +/** + * @brief ut0中断函数 + */ +SET_INTERRUPT +static void UT0_isr_fun(void) +{ + u32 rx_len = 0; + if ((JL_UART0->CON0 & BIT(2)) && (JL_UART0->CON0 & BIT(15))) { + JL_UART0->CON0 |= BIT(13); + UT_OSSemPost(&uart0.sem_tx); + if (uart0.isr_cbfun) { + uart0.isr_cbfun(&uart0, UT_TX); + } + } + if ((JL_UART0->CON0 & BIT(3)) && (JL_UART0->CON0 & BIT(14))) { + JL_UART0->CON0 |= BIT(7); //DMA模式 + JL_UART0->CON0 |= BIT(10); //清OTCNT PND + JL_UART0->CON0 |= BIT(12); //清RX PND(这里的顺序不能改变,这里要清一次) + rx_len = JL_UART0->HRXCNT; //读当前串口接收数据的个数 + uart0.kfifo.buf_in += uart0.frame_length; //每满frame_length字节则产生一次中断 + UT_OSSemPost(&uart0.sem_rx); + if (uart0.isr_cbfun) { + uart0.isr_cbfun(&uart0, UT_RX); + } + } + if ((JL_UART0->CON0 & BIT(5)) && (JL_UART0->CON0 & BIT(11))) { + //OTCNT PND + JL_UART0->CON0 |= BIT(7); //DMA模式 + JL_UART0->CON0 |= BIT(10); //清OTCNT PND + JL_UART0->CON0 |= BIT(12); //清RX PND(这里的顺序不能改变,这里要清一次) + rx_len = JL_UART0->HRXCNT; //读当前串口接收数据的个数 + + if (rx_len) { + uart0.kfifo.buf_in += rx_len; + /* printf("%s() %d\n", __func__, __LINE__); */ + UT_OSSemPost(&uart0.sem_rx); + if (uart0.isr_cbfun) { + uart0.isr_cbfun(&uart0, UT_RX_OT); + } + } + } +} +/** + * @brief ut0接收字符串 + * + * @param buf 字符串存放首地址 + * @param len 预接收长度 + * @param timeout 接收超时时间,单位1ms + * @return 返回实际接收长度 + */ +static u32 UT0_read_buf(u8 *buf, u32 len, u32 timeout) +{ + u32 i; + u32 _timeout, _t_sleep; + if (len == 0) { + return 0; + } + timeout = ut_msecs_to_jiffies(timeout); + if (JL_UART0->CON0 & BIT(6)) { + + if (!kfifo_length(&uart0.kfifo)) { + UT_OSSemPend(&uart0.sem_rx, timeout); + } + UT_OSSemSet(&uart0.sem_rx, 0); + + return kfifo_get(&uart0.kfifo, buf, len); + } else { + _timeout = timeout + ut_get_jiffies(); + _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies(); + for (i = 0; i < len; i++) { + while (!(JL_UART0->CON0 & BIT(14))) { + if (timeout && time_before(_timeout, ut_get_jiffies())) { + return i; + } + if (time_before(_t_sleep, ut_get_jiffies())) { + ut_sleep(); + _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies(); + } + } + *(buf + i) = JL_UART0->BUF; + JL_UART0->CON0 |= BIT(12); + __asm__ volatile("csync"); //make RX_PND_CLR taking effect + } + } + return len; +} +/** + * @brief ut0发送字符串 + * + * @param buf 字符串首地址 + * @param len 发送的字符串长度 + */ +static void UT0_write_buf(const u8 *buf, u32 len) +{ + u32 i; + if (len == 0) { + return; + } + if (CONFIG_UART0_ENABLE_TX_DMA) { + UT_OSSemSet(&uart0.sem_tx, 0); + JL_UART0->CON0 |= BIT(13); + JL_UART0->CON0 |= BIT(2); + JL_UART0->TXADR = (u32)buf; + JL_UART0->TXCNT = len; + UT_OSSemPend(&uart0.sem_tx, 0); + JL_UART0->CON0 &= ~BIT(2); + } else { + for (i = 0; i < len; i ++) { + UT0_putbyte(*(buf + i)); + } + } +} +/** + * @brief ut0配置波特率 + * + * @param baud 波特率值 + */ +static void UT0_set_baud(u32 baud) +{ + JL_UART0->CON0 &= ~BIT(0); + JL_UART0->CON0 |= BIT(13) | BIT(12) | BIT(10); + JL_UART0->BAUD = ((UART_CLK + baud / 2) / baud) / 4 - 1; + if (JL_UART0->CON0 & BIT(5)) { + if (uart0.rx_timeout > 10) { + JL_UART0->OTCNT = (uart0.rx_timeout / 10) * (UART_OT_CLK / 10) / 10; + } else { + JL_UART0->OTCNT = uart0.rx_timeout * UART_OT_CLK / 1000; + } + } + JL_UART0->CON0 |= BIT(13) | BIT(12) | BIT(10) | BIT(0); +} +/** + * @brief ut0使能 + */ +static void UT0_open(u32 baud, u32 is_9bit, void *cbuf, u32 cbuf_size, u32 rx_cnt, u32 ot) +{ + JL_UART0->CON0 = BIT(13) | BIT(12) | BIT(10); + UT_OSSemCreate(&uart0.sem_rx, 0); + UT_OSSemCreate(&uart0.sem_tx, 0); + request_irq(IRQ_UART0_IDX, 3, UT0_isr_fun, 0); + if (cbuf) { + uart0.kfifo.buffer = cbuf; + uart0.kfifo.buf_size = cbuf_size; + uart0.kfifo.buf_in = 0; + uart0.kfifo.buf_out = 0; + uart0.frame_length = rx_cnt; + uart0.rx_timeout = ot; + JL_UART0->RXSADR = (u32)uart0.kfifo.buffer; + JL_UART0->RXEADR = (u32)(uart0.kfifo.buffer + uart0.kfifo.buf_size); + JL_UART0->RXCNT = uart0.frame_length; + JL_UART0->CON0 |= BIT(6) | BIT(5) | BIT(3); + } + if (is_9bit) { + JL_UART0->CON0 |= BIT(1); + } else { + JL_UART0->CON0 &= ~BIT(1); + } + UT0_set_baud(baud); +} +/** + * @brief ut0关闭,注销 + */ +static void UT0_close(void) +{ + UT_OSSemClose(&uart0.sem_rx); + UT_OSSemClose(&uart0.sem_tx); + irq_disable(IRQ_UART0_IDX); + JL_UART0->CON0 = BIT(13) | BIT(12) | BIT(10); +} +/** + * @brief ut1发送一个byte + * + * @param a 要发送的字节 + */ +static void UT1_putbyte(char a) +{ + if (JL_UART1->CON0 & BIT(0)) { + JL_UART1->BUF = a; + __asm__ volatile("csync"); + while ((JL_UART1->CON0 & BIT(15)) == 0) { + JL_UART1->CON0 |= BIT(13); + while (JL_UART1->CON1 & BIT(2) && JL_UART1->CON1 & BIT(15)) { + JL_UART1->CON1 |= BIT(14); + os_time_dly(1); + } + } + } +} +/** + * @brief ut1接收一个byte + * + * @param buf 字节存放地址 + * @param timeout 接收超时时间,单位1ms +10ms¥;返回1:接收成功 + */ +static u8 UT1_getbyte(u8 *buf, u32 timeout) +{ + u32 _timeout, _t_sleep; + timeout = ut_msecs_to_jiffies(timeout); + if (JL_UART1->CON0 & BIT(6)) { + if (!kfifo_length(&uart1.kfifo)) { + UT_OSSemPend(&uart1.sem_rx, timeout); + } + UT_OSSemSet(&uart1.sem_rx, 0); + + return kfifo_get(&uart1.kfifo, buf, 1); + } else { + _timeout = timeout + ut_get_jiffies(); + _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies(); + while (!(JL_UART1->CON0 & BIT(14))) { + if (timeout && time_before(_timeout, ut_get_jiffies())) { + return 0; + } + if (time_before(_t_sleep, ut_get_jiffies())) { + ut_sleep(); + _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies(); + } + } + *buf = JL_UART1->BUF; + JL_UART1->CON0 |= BIT(12); + __asm__ volatile("csync"); //make RX_PND_CLR taking effect + } + return 1; +} +/** + * @brief ut1中断函数 + */ +SET_INTERRUPT +static void UT1_isr_fun(void) +{ + u32 rx_len = 0; + if ((JL_UART1->CON0 & BIT(2)) && (JL_UART1->CON0 & BIT(15))) { + JL_UART1->CON0 |= BIT(13); + UT_OSSemPost(&uart1.sem_tx); + if (uart1.isr_cbfun) { + uart1.isr_cbfun(&uart1, UT_TX); + } + } + if ((JL_UART1->CON0 & BIT(3)) && (JL_UART1->CON0 & BIT(14))) { + JL_UART1->CON0 |= BIT(7); //DMA模式 + JL_UART1->CON0 |= BIT(10); //清OTCNT PND + JL_UART1->CON0 |= BIT(12); //清RX PND(这里的顺序不能改变,这里要清一次) + rx_len = JL_UART1->HRXCNT; //读当前串口接收数据的个数 + uart1.kfifo.buf_in += uart1.frame_length; //每满32字节则产生一次中断 + if (JL_UART1->CON1 & BIT(0)) { + JL_UART1->CON1 |= BIT(13); + } + UT_OSSemPost(&uart1.sem_rx); + if (uart1.isr_cbfun) { + uart1.isr_cbfun(&uart1, UT_RX); + } + } + if ((JL_UART1->CON0 & BIT(5)) && (JL_UART1->CON0 & BIT(11))) { + //OTCNT PND + JL_UART1->CON0 |= BIT(7); //DMA模式 + JL_UART1->CON0 |= BIT(10); //清OTCNT PND + JL_UART1->CON0 |= BIT(12); //清RX PND(这里的顺序不能改变,这里要清一次) + rx_len = JL_UART1->HRXCNT; //读当前串口接收数据的个数 + if (JL_UART1->CON1 & BIT(0)) { + JL_UART1->CON1 |= BIT(13); + } + + if (rx_len) { + uart1.kfifo.buf_in += rx_len; + /* printf("%s() %d\n", __func__, __LINE__); */ + UT_OSSemPost(&uart1.sem_rx); + if (uart1.isr_cbfun) { + uart1.isr_cbfun(&uart1, UT_RX_OT); + } + } + } +} +/** + * @brief ut1接收字符串 + * + * @param buf 字符串存放首地址 + * @param len 预接收长度 + * @param timeout 接收超时时间,单位1ms + * @return 返回实际接收的长度 + */ +static u32 UT1_read_buf(u8 *buf, u32 len, u32 timeout) +{ + u32 i; + u32 _timeout, _t_sleep; + if (len == 0) { + return 0; + } + timeout = ut_msecs_to_jiffies(timeout); + if (JL_UART1->CON0 & BIT(6)) { + if (!kfifo_length(&uart1.kfifo)) { + UT_OSSemPend(&uart1.sem_rx, timeout); + } + UT_OSSemSet(&uart1.sem_rx, 0); + + return kfifo_get(&uart1.kfifo, buf, len); + } else { + _timeout = timeout + ut_get_jiffies(); + _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies(); + for (i = 0; i < len; i++) { + while (!(JL_UART1->CON0 & BIT(14))) { + if (timeout && time_before(_timeout, ut_get_jiffies())) { + return i; + } + if (time_before(_t_sleep, ut_get_jiffies())) { + ut_sleep(); + _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies(); + } + } + *(buf + i) = JL_UART1->BUF; + JL_UART1->CON0 |= BIT(12); + __asm__ volatile("csync"); //make RX_PND_CLR taking effect + } + } + return len; +} +/** + * @brief ut1发送字符串 + * + * @param buf 字符串首地址 + * @param len 发送的字符串长度 + * @param timeout 发送超时时间,单位10ms + */ +static void UT1_write_buf(const u8 *buf, u32 len) +{ + u32 i; + if (len == 0) { + return; + } + if (CONFIG_UART1_ENABLE_TX_DMA) { + UT_OSSemSet(&uart1.sem_tx, 0); + JL_UART1->CON0 |= BIT(13); + JL_UART1->CON0 |= BIT(2); + JL_UART1->TXADR = (u32)buf; + JL_UART1->TXCNT = len; + UT_OSSemPend(&uart1.sem_tx, 0); + JL_UART1->CON0 &= ~BIT(2); + } else { + for (i = 0; i < len; i ++) { + UT1_putbyte(*(buf + i)); + } + } +} +/** + * @brief ut1配置波特率 + * + * @param baud 波特率值 + */ +static void UT1_set_baud(u32 baud) +{ + JL_UART1->CON0 &= ~BIT(0); + JL_UART1->CON0 |= BIT(13) | BIT(12) | BIT(10); + JL_UART1->BAUD = ((UART_CLK + baud / 2) / baud) / 4 - 1; + if (JL_UART1->CON0 & BIT(5)) { + if (uart1.rx_timeout > 10) { + JL_UART1->OTCNT = (uart1.rx_timeout / 10) * (UART_OT_CLK / 10) / 10; + } else { + JL_UART1->OTCNT = uart1.rx_timeout * UART_OT_CLK / 1000; + } + } + JL_UART1->CON0 |= BIT(13) | BIT(12) | BIT(10) | BIT(0); +} +/** + * @brief ut1使能 + */ +static void UT1_open(u32 baud, u32 is_9bit, void *cbuf, u32 cbuf_size, u32 rx_cnt, u32 ot) +{ + JL_UART1->CON0 = BIT(13) | BIT(12) | BIT(10); + UT_OSSemCreate(&uart1.sem_rx, 0); + UT_OSSemCreate(&uart1.sem_tx, 0); + request_irq(IRQ_UART1_IDX, 3, UT1_isr_fun, 0); + if (cbuf) { + uart1.kfifo.buffer = cbuf; + uart1.kfifo.buf_size = cbuf_size; + uart1.kfifo.buf_in = 0; + uart1.kfifo.buf_out = 0; + uart1.frame_length = rx_cnt; + uart1.rx_timeout = ot; + JL_UART1->RXSADR = (u32)uart1.kfifo.buffer; + JL_UART1->RXEADR = (u32)(uart1.kfifo.buffer + uart1.kfifo.buf_size); + JL_UART1->RXCNT = uart1.frame_length; + JL_UART1->CON0 |= BIT(6) | BIT(5) | BIT(3); + } + if (is_9bit) { + JL_UART1->CON0 |= BIT(1); + } else { + JL_UART1->CON0 &= ~BIT(1); + } + UT1_set_baud(baud); +} +/** + * @brief ut1关闭,注销 + */ +static void UT1_close(void) +{ + UT_OSSemClose(&uart1.sem_rx); + UT_OSSemClose(&uart1.sem_tx); + irq_disable(IRQ_UART1_IDX); + JL_UART1->CON0 = BIT(13) | BIT(12) | BIT(10); +} + +/** + * @brief ut2发送一个byte + * + * @param a 要发送的字节 + */ +static void UT2_putbyte(char a) +{ + if (JL_UART2->CON0 & BIT(0)) { + JL_UART2->BUF = a; + __asm__ volatile("csync"); + while ((JL_UART2->CON0 & BIT(15)) == 0); + JL_UART2->CON0 |= BIT(13); + } +} +/** + * @brief ut2接收一个byte + * + * @param buf 字节存放地址 + * @param timeout 接收超时时间,单位1ms +10ms¥;返回1:接收成功 + */ +static u8 UT2_getbyte(u8 *buf, u32 timeout) +{ + u32 _timeout, _t_sleep; + timeout = ut_msecs_to_jiffies(timeout); + if (JL_UART2->CON0 & BIT(6)) { + if (!kfifo_length(&uart2.kfifo)) { + UT_OSSemPend(&uart2.sem_rx, timeout); + } + UT_OSSemSet(&uart2.sem_rx, 0); + + return kfifo_get(&uart2.kfifo, buf, 1); + } else { + _timeout = timeout + ut_get_jiffies(); + _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies(); + while (!(JL_UART2->CON0 & BIT(14))) { + if (timeout && time_before(_timeout, ut_get_jiffies())) { + return 0; + } + if (time_before(_t_sleep, ut_get_jiffies())) { + ut_sleep(); + _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies(); + } + } + *buf = JL_UART2->BUF; + JL_UART2->CON0 |= BIT(12); + __asm__ volatile("csync"); //make RX_PND_CLR taking effect + } + return 1; +} +/** + * @brief ut2中断函数 + */ +SET_INTERRUPT +static void UT2_isr_fun(void) +{ + u32 rx_len = 0; + if ((JL_UART2->CON0 & BIT(2)) && (JL_UART2->CON0 & BIT(15))) { + JL_UART2->CON0 |= BIT(13); + UT_OSSemPost(&uart2.sem_tx); + if (uart2.isr_cbfun) { + uart2.isr_cbfun(&uart2, UT_TX); + } + } + if ((JL_UART2->CON0 & BIT(3)) && (JL_UART2->CON0 & BIT(14))) { + JL_UART2->CON0 |= BIT(7); //DMA模式 + JL_UART2->CON0 |= BIT(10); //清OTCNT PND + JL_UART2->CON0 |= BIT(12); //清RX PND(这里的顺序不能改变,这里要清一次) + rx_len = JL_UART2->HRXCNT; //读当前串口接收数据的个数 + uart2.kfifo.buf_in += uart2.frame_length; //每满32字节则产生一次中断 + UT_OSSemPost(&uart2.sem_rx); + if (uart2.isr_cbfun) { + uart2.isr_cbfun(&uart2, UT_RX); + } + } + if ((JL_UART2->CON0 & BIT(5)) && (JL_UART2->CON0 & BIT(11))) { + //OTCNT PND + JL_UART2->CON0 |= BIT(7); //DMA模式 + JL_UART2->CON0 |= BIT(10); //清OTCNT PND + JL_UART2->CON0 |= BIT(12); //清RX PND(这里的顺序不能改变,这里要清一次) + rx_len = JL_UART2->HRXCNT; //读当前串口接收数据的个数 + + if (rx_len) { + uart2.kfifo.buf_in += rx_len; + /* printf("%s() %d\n", __func__, __LINE__); */ + UT_OSSemPost(&uart2.sem_rx); + if (uart2.isr_cbfun) { + uart2.isr_cbfun(&uart2, UT_RX_OT); + } + } + } +} +/** + * @brief ut2接收字符串 + * + * @param buf 字符串存放首地址 + * @param len 预接收长度 + * @param timeout 接收超时时间,单位1ms + * @return 返回实际接收的长度 + */ +static u32 UT2_read_buf(u8 *buf, u32 len, u32 timeout) +{ + u32 i; + u32 _timeout, _t_sleep; + if (len == 0) { + return 0; + } + timeout = ut_msecs_to_jiffies(timeout); + if (JL_UART2->CON0 & BIT(6)) { + if (!kfifo_length(&uart2.kfifo)) { + UT_OSSemPend(&uart2.sem_rx, timeout); + } + UT_OSSemSet(&uart2.sem_rx, 0); + + return kfifo_get(&uart2.kfifo, buf, len); + } else { + _timeout = timeout + ut_get_jiffies(); + _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies(); + for (i = 0; i < len; i++) { + while (!(JL_UART2->CON0 & BIT(14))) { + if (timeout && time_before(_timeout, ut_get_jiffies())) { + return i; + } + if (time_before(_t_sleep, ut_get_jiffies())) { + ut_sleep(); + _t_sleep = ut_msecs_to_jiffies(10) + ut_get_jiffies(); + } + } + *(buf + i) = JL_UART2->BUF; + JL_UART2->CON0 |= BIT(12); + __asm__ volatile("csync"); //make RX_PND_CLR taking effect + } + } + return len; +} +/** + * @brief ut2发送字符串 + * + * @param buf 字符串首地址 + * @param len 发送的字符串长度 + * @param timeout 发送超时时间,单位10ms + */ +static void UT2_write_buf(const u8 *buf, u32 len) +{ + u32 i; + if (len == 0) { + return; + } + if (CONFIG_UART2_ENABLE_TX_DMA) { + UT_OSSemSet(&uart2.sem_tx, 0); + JL_UART2->CON0 |= BIT(13); + JL_UART2->CON0 |= BIT(2); + JL_UART2->TXADR = (u32)buf; + JL_UART2->TXCNT = len; + UT_OSSemPend(&uart2.sem_tx, 0); + JL_UART2->CON0 &= ~BIT(2); + } else { + for (i = 0; i < len; i ++) { + UT2_putbyte(*(buf + i)); + } + } +} +/** + * @brief ut2配置波特率 + * + * @param baud 波特率值 + */ +static void UT2_set_baud(u32 baud) +{ + JL_UART2->CON0 &= ~BIT(0); + JL_UART2->CON0 |= BIT(13) | BIT(12) | BIT(10); + JL_UART2->BAUD = ((UART_CLK + baud / 2) / baud) / 4 - 1; + if (JL_UART2->CON0 & BIT(5)) { + if (uart2.rx_timeout > 10) { + JL_UART2->OTCNT = (uart2.rx_timeout / 10) * (UART_OT_CLK / 10) / 10; + } else { + JL_UART2->OTCNT = uart2.rx_timeout * UART_OT_CLK / 1000; + } + } + JL_UART2->CON0 |= BIT(13) | BIT(12) | BIT(10) | BIT(0); +} +/** + * @brief ut2使能 + */ +static void UT2_open(u32 baud, u32 is_9bit, void *cbuf, u32 cbuf_size, u32 rx_cnt, u32 ot) +{ + JL_UART2->CON0 = BIT(13) | BIT(12) | BIT(10); + UT_OSSemCreate(&uart2.sem_rx, 0); + UT_OSSemCreate(&uart2.sem_tx, 0); + request_irq(IRQ_UART2_IDX, 3, UT2_isr_fun, 0); + if (cbuf) { + uart2.kfifo.buffer = cbuf; + uart2.kfifo.buf_size = cbuf_size; + uart2.kfifo.buf_in = 0; + uart2.kfifo.buf_out = 0; + uart2.frame_length = rx_cnt; + uart2.rx_timeout = ot; + JL_UART2->RXSADR = (u32)uart2.kfifo.buffer; + JL_UART2->RXEADR = (u32)(uart2.kfifo.buffer + uart2.kfifo.buf_size); + JL_UART2->RXCNT = uart2.frame_length; + JL_UART2->CON0 |= BIT(6) | BIT(5) | BIT(3); + } + if (is_9bit) { + JL_UART2->CON0 |= BIT(1); + } else { + JL_UART2->CON0 &= ~BIT(1); + } + UT2_set_baud(baud); +} +/** + * @brief ut2关闭,注销 + */ +static void UT2_close(void) +{ + UT_OSSemClose(&uart2.sem_rx); + UT_OSSemClose(&uart2.sem_tx); + irq_disable(IRQ_UART2_IDX); + JL_UART2->CON0 = BIT(13) | BIT(12) | BIT(10); +} + + +static u32 uart_is_idle(u32 ut_num) +{ + switch (ut_num) { + case 0 : + return !(JL_UART0->CON0 & BIT(0)); + case 1 : + return !(JL_UART1->CON0 & BIT(0)); + case 2: + return !(JL_UART2->CON0 & BIT(0)); + default : + break; + } + return -1; +} + +/**ut硬件集成引脚名称字符串,上下对应为一对*/ +/* static char *ut_tx_pin[] = {"PA05", "PB07", "PA07", "reserved", "PB05", "reserved", "PA01", "USBDP", "PA03", "reserved", "reserved", "PA09"}; */ +/* static char *ut_rx_pin[] = {"PA06", "PB08", "PA08", "reserved", "PB06", "reserved", "PA02", "USBDM", "PA04", "reserved", "reserved", "PA10"}; */ + +static u8 ut_tx_pin[] = { + IO_PORTA_05, IO_PORTB_04, IO_PORTB_05, IO_PORTA_11, //UT0_TX + IO_PORTB_00, IO_PORTC_00, IO_PORTA_00, IO_PORT_DP, //UT1_TX + IO_PORTA_02, IO_PORTA_09, IO_PORTB_09, IO_PORTC_04, //UT2_TX +}; +static u8 ut_rx_pin[] = { + IO_PORTA_06, IO_PORTB_06, IO_PORTB_05, IO_PORTA_12, //UT0_RX + IO_PORTB_01, IO_PORTC_01, IO_PORTA_01, IO_PORT_DM, //UT1_RX + IO_PORTA_03, IO_PORTA_10, IO_PORTB_10, IO_PORTC_05, //UT2_RX +}; + +/** + * @brief ut模块初始化函数,供外部调用 + * + * @param arg 传入uart_argment型结构体指针 + * @return 返回uart_bus_t型结构体指针 + */ +__attribute__((noinline)) +const uart_bus_t *uart_dev_open(const struct uart_platform_data_t *arg) +{ + u8 i; + u8 ut_num; + u8 CHx_UTx_TX; + uart_bus_t *ut = NULL; + u32 ut_ch = -1; + u8 gpio_input_channle_flag = 0; + + for (i = 0; i < 12; i++) { + if ((arg->tx_pin == ut_tx_pin[i]) || ((arg->tx_pin == (u8) - 1) && (arg->rx_pin == ut_rx_pin[i]))) { + ut_num = i / 4; + if (uart_is_idle(ut_num)) { + ut_ch = i % 4; + if ((arg->rx_pin != ut_rx_pin[i]) && (arg->rx_pin != (u8) - 1)) { + gpio_input_channle_flag = 1; + } + break; + } + } + } + + if (ut_ch == -1) { + if (uart_is_idle(0)) { + ut_num = 0; + CHx_UTx_TX = CH0_UT0_TX; + } else if (uart_is_idle(1)) { + ut_num = 1; + CHx_UTx_TX = CH1_UT1_TX; + } else if (uart_is_idle(2)) { + ut_num = 2; + CHx_UTx_TX = CH2_UT2_TX; + } else { + return NULL; + } + } + + if (arg->rx_cbuf) { + if ((arg->rx_cbuf_size == 0) || (arg->rx_cbuf_size & (arg->rx_cbuf_size - 1))) { + return NULL; + } + } + + if (CONFIG_UART0_ENABLE && ut_num == 0) { + gpio_set_uart0(ut_ch); + uart0.argv = arg->argv; + uart0.isr_cbfun = arg->isr_cbfun; + uart0.putbyte = UT0_putbyte; + uart0.getbyte = UT0_getbyte; + uart0.read = UT0_read_buf; + uart0.write = UT0_write_buf; + uart0.set_baud = UT0_set_baud; + UT0_open(arg->baud, arg->is_9bit, + arg->rx_cbuf, arg->rx_cbuf_size, + arg->frame_length, arg->rx_timeout); + ut = &uart0; + } else if (CONFIG_UART1_ENABLE && ut_num == 1) { + gpio_set_uart1(ut_ch); + uart1.argv = arg->argv; + uart1.isr_cbfun = arg->isr_cbfun; + uart1.putbyte = UT1_putbyte; + uart1.getbyte = UT1_getbyte; + uart1.read = UT1_read_buf; + uart1.write = UT1_write_buf; + uart1.set_baud = UT1_set_baud; + UT1_open(arg->baud, arg->is_9bit, + arg->rx_cbuf, arg->rx_cbuf_size, + arg->frame_length, arg->rx_timeout); + ut = &uart1; + } else if (CONFIG_UART2_ENABLE && ut_num == 2) { + gpio_set_uart2(ut_ch); + uart2.argv = arg->argv; + uart2.isr_cbfun = arg->isr_cbfun; + uart2.putbyte = UT2_putbyte; + uart2.getbyte = UT2_getbyte; + uart2.read = UT2_read_buf; + uart2.write = UT2_write_buf; + uart2.set_baud = UT2_set_baud; + UT2_open(arg->baud, arg->is_9bit, + arg->rx_cbuf, arg->rx_cbuf_size, + arg->frame_length, arg->rx_timeout); + ut = &uart2; + } else { + return NULL; + } + if (ut_ch == -1) { + if (arg->rx_pin != (u8) - 1) { + gpio_uart_rx_input(arg->rx_pin, ut_num, ut_num); + } + if (arg->tx_pin != (u8) - 1) { + gpio_output_channle(arg->tx_pin, CHx_UTx_TX); + } + } + if (gpio_input_channle_flag) { + gpio_uart_rx_input(arg->rx_pin, ut_num, ut_num); + } + return ut; +} +u32 uart_dev_close(uart_bus_t *ut) +{ + UT_OSSemClose(&ut->sem_rx); + UT_OSSemClose(&ut->sem_tx); + if (&uart0 == ut) { + UT0_close(); + return gpio_close_uart0(); + } else if (&uart1 == ut) { + UT1_close(); + return gpio_close_uart1(); + } else { + UT2_close(); + return gpio_close_uart2(); + } + return 0; +} + +void flow_ctl_hw_init(void) +{ + JL_UART1->CON1 |= BIT(0); + gpio_set_direction(IO_PORTA_10, 0); + gpio_set_pull_up(IO_PORTA_10, 0); + gpio_set_pull_down(IO_PORTA_10, 0); + gpio_set_die(IO_PORTA_10, 1); + + JL_UART1->CON1 |= BIT(2); + gpio_set_direction(IO_PORTA_09, 1); + gpio_set_pull_up(IO_PORTA_09, 0); + gpio_set_pull_down(IO_PORTA_09, 0); + gpio_set_die(IO_PORTA_09, 1); +} + +void change_rts_state(u8 state) +{ + if (JL_UART1->CON1 & BIT(2)) { + if (state) { + JL_UART1->CON1 |= BIT(4); + } else { + JL_UART1->CON1 &= ~BIT(4); + } + } +} + +void uart_disable_for_ota() +{ + JL_UART0->CON0 = BIT(13) | BIT(12) | BIT(10); + JL_UART1->CON0 = BIT(13) | BIT(12) | BIT(10); + JL_UART2->CON0 = BIT(13) | BIT(12) | BIT(10); +} + diff --git a/cpu/br23/uart_test.c b/cpu/br23/uart_test.c new file mode 100644 index 0000000..c75ae5b --- /dev/null +++ b/cpu/br23/uart_test.c @@ -0,0 +1,212 @@ +#include "system/includes.h" +#include "asm/uart_dev.h" +#include "system/event.h" + +#if 0 +/* + [[ 注意!!! ]] + * 如果当系统任务较少时使用本demo,需要将低功耗关闭(#define TCFG_LOWPOWER_LOWPOWER_SEL 0//SLEEP_EN ),否则任务被串口接收函数调用信号量pend时会导致cpu休眠,串口中断和DMA接收将遗漏数据或数据不正确 +*/ + +#define UART_DEV_USAGE_TEST_SEL 2 //uart_dev.c api接口使用方法选择 +// 选择1 串口中断回调函数推送事件,由事件响应函数接收串口数据 +// 选择2 由task接收串口数据 + +#define UART_DEV_TEST_MULTI_BYTE 1 //uart_dev.c 读写多个字节api / 读写1个字节api 选择 + +#define UART_DEV_FLOW_CTRL 0 + +static u8 uart_cbuf[512] __attribute__((aligned(4))); +static u8 uart_rxbuf[512] __attribute__((aligned(4))); + +static void my_put_u8hex(u8 dat) +{ + u8 tmp; + tmp = dat / 16; + if (tmp < 10) { + putchar(tmp + '0'); + } else { + putchar(tmp - 10 + 'A'); + } + tmp = dat % 16; + if (tmp < 10) { + putchar(tmp + '0'); + } else { + putchar(tmp - 10 + 'A'); + } + putchar(0x20); +} + +//设备事件响应demo +static void uart_event_handler(struct sys_event *e) +{ + const uart_bus_t *uart_bus; + u32 uart_rxcnt = 0; + + if ((u32)e->arg == DEVICE_EVENT_FROM_UART_RX_OVERFLOW) { + if (e->u.dev.event == DEVICE_EVENT_CHANGE) { + /* printf("uart event: DEVICE_EVENT_FROM_UART_RX_OVERFLOW\n"); */ + uart_bus = (const uart_bus_t *)e->u.dev.value; + uart_rxcnt = uart_bus->read(uart_rxbuf, sizeof(uart_rxbuf), 0); + if (uart_rxcnt) { + printf("get_buffer:\n"); + for (int i = 0; i < uart_rxcnt; i++) { + my_put_u8hex(uart_rxbuf[i]); + if (i % 16 == 15) { + putchar('\n'); + } + } + if (uart_rxcnt % 16) { + putchar('\n'); + } +#if (!UART_DEV_FLOW_CTRL) + uart_bus->write(uart_rxbuf, uart_rxcnt); +#endif + } + printf("uart out\n"); + } + } + if ((u32)e->arg == DEVICE_EVENT_FROM_UART_RX_OUTTIME) { + if (e->u.dev.event == DEVICE_EVENT_CHANGE) { + /* printf("uart event:DEVICE_EVENT_FROM_UART_RX_OUTTIME\n"); */ + uart_bus = (const uart_bus_t *)e->u.dev.value; + uart_rxcnt = uart_bus->read(uart_rxbuf, sizeof(uart_rxbuf), 0); + if (uart_rxcnt) { + printf("get_buffer:\n"); + for (int i = 0; i < uart_rxcnt; i++) { + my_put_u8hex(uart_rxbuf[i]); + if (i % 16 == 15) { + putchar('\n'); + } + } + if (uart_rxcnt % 16) { + putchar('\n'); + } +#if (!UART_DEV_FLOW_CTRL) + uart_bus->write(uart_rxbuf, uart_rxcnt); +#endif + } + printf("uart out\n"); + } + } +} +SYS_EVENT_HANDLER(SYS_DEVICE_EVENT, uart_event_handler, 0); + +static void uart_u_task(void *arg) +{ + const uart_bus_t *uart_bus = arg; + int ret; + u32 uart_rxcnt = 0; + + printf("uart_u_task start\n"); + while (1) { +#if !UART_DEV_TEST_MULTI_BYTE + //uart_bus->getbyte()在尚未收到串口数据时会pend信号量,挂起task,直到UART_RX_PND或UART_RX_OT_PND中断发生,post信号量,唤醒task + ret = uart_bus->getbyte(&uart_rxbuf[0], 0); + if (ret) { + uart_rxcnt = 1; + printf("get_byte: %02x\n", uart_rxbuf[0]); + uart_bus->putbyte(uart_rxbuf[0]); + } +#else + //uart_bus->read()在尚未收到串口数据时会pend信号量,挂起task,直到UART_RX_PND或UART_RX_OT_PND中断发生,post信号量,唤醒task + uart_rxcnt = uart_bus->read(uart_rxbuf, sizeof(uart_rxbuf), 0); + if (uart_rxcnt) { + printf("get_buffer:\n"); + for (int i = 0; i < uart_rxcnt; i++) { + my_put_u8hex(uart_rxbuf[i]); + if (i % 16 == 15) { + putchar('\n'); + } + } + if (uart_rxcnt % 16) { + putchar('\n'); + } +#if (!UART_DEV_FLOW_CTRL) + uart_bus->write(uart_rxbuf, uart_rxcnt); +#endif + } +#endif + } +} + +static void uart_isr_hook(void *arg, u32 status) +{ + const uart_bus_t *ubus = arg; + struct sys_event e; + + //当CONFIG_UARTx_ENABLE_TX_DMA(x = 0, 1)为1时,不要在中断里面调用ubus->write(),因为中断不能pend信号量 + if (status == UT_RX) { + printf("uart_rx_isr\n"); +#if (UART_DEV_USAGE_TEST_SEL == 1) + e.type = SYS_DEVICE_EVENT; + e.arg = (void *)DEVICE_EVENT_FROM_UART_RX_OVERFLOW; + e.u.dev.event = DEVICE_EVENT_CHANGE; + e.u.dev.value = (int)ubus; + sys_event_notify(&e); +#endif + } + if (status == UT_RX_OT) { + printf("uart_rx_ot_isr\n"); +#if (UART_DEV_USAGE_TEST_SEL == 1) + e.type = SYS_DEVICE_EVENT; + e.arg = (void *)DEVICE_EVENT_FROM_UART_RX_OUTTIME; + e.u.dev.event = DEVICE_EVENT_CHANGE; + e.u.dev.value = (int)ubus; + sys_event_notify(&e); +#endif + } +} + +static void uart_flow_ctrl_task(void *arg) +{ + const uart_bus_t *uart_bus = arg; + while (1) { + uart_bus->write("flow control test ", sizeof("flow control test ")); + os_time_dly(100); + } +} + +void uart_dev_test_main() +{ + const uart_bus_t *uart_bus; + struct uart_platform_data_t u_arg = {0}; + u_arg.tx_pin = IO_PORTA_01; + u_arg.rx_pin = IO_PORTA_02; + u_arg.rx_cbuf = uart_cbuf; + u_arg.rx_cbuf_size = 512; + u_arg.frame_length = 32; + u_arg.rx_timeout = 100; + u_arg.isr_cbfun = uart_isr_hook; + u_arg.baud = 9600; + u_arg.is_9bit = 0; +#if UART_DEV_FLOW_CTRL + u_arg.tx_pin = IO_PORTA_00; + u_arg.rx_pin = IO_PORTA_01; + u_arg.baud = 1000000; + extern void flow_ctl_hw_init(void); + flow_ctl_hw_init(); +#endif + uart_bus = uart_dev_open(&u_arg); + if (uart_bus != NULL) { + printf("uart_dev_open() success\n"); +#if (UART_DEV_USAGE_TEST_SEL == 2) + os_task_create(uart_u_task, (void *)uart_bus, 31, 512, 0, "uart_u_task"); +#endif +#if UART_DEV_FLOW_CTRL + os_task_create(uart_flow_ctrl_task, (void *)uart_bus, 31, 128, 0, "flow_ctrl"); +#endif + } +} + +#if UART_DEV_FLOW_CTRL +void uart_change_rts_state(void) +{ + static u8 rts_state = 1; + extern void change_rts_state(u8 state); + change_rts_state(rts_state); + rts_state = !rts_state; +} +#endif + +#endif diff --git a/cpu/br23/ui_driver/LED_1888/LED1888.c b/cpu/br23/ui_driver/LED_1888/LED1888.c new file mode 100644 index 0000000..fbccb0a --- /dev/null +++ b/cpu/br23/ui_driver/LED_1888/LED1888.c @@ -0,0 +1,945 @@ +#include "includes.h" +#include "app_config.h" + +#pragma const_seg(".LED_const") +#pragma code_seg(".LED_code") + +#include "ui/ui_api.h" +#include "LED1888.h" + +#if TCFG_UI_LED1888_ENABLE + + +LED1888_VAR LED1888_var; + +typedef struct _LED_DISP_ { + u8 on; + u8 phase; + u16 H_time; + u16 L_time; + u16 count; +} LED_DISP; + +struct ui_led7_env { + u8 init; + u8 sys_halfsec; + u16 count; + LED_DISP led[2]; + const struct led7_platform_data *user_data; + u8 lock: 1; +}; + +static struct ui_led7_env _led7_env = {0}; +#define __this (&_led7_env) + +#define PIN1_H gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[0], 1) +#define PIN1_L gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[0], 0) + +#define PIN2_H gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[1], 1) +#define PIN2_L gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[1], 0) + +#define PIN3_H gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[2], 1) +#define PIN3_L gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[2], 0) + +#define PIN4_H gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[3], 1) +#define PIN4_L gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[3], 0) + +#define PIN5_H gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[4], 1) +#define PIN5_L gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[4], 0) + +#define PIN6_H gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[5], 1) +#define PIN6_L gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[5], 0) + +#define PIN7_H gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[6], 1) +#define PIN7_L gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[6], 0) + + +//数字'0' ~ '9'显示段码表 +static const u8 LED_NUMBER[10] = { + (u8)(LED_A | LED_B | LED_C | LED_D | LED_E | LED_F), //'0' + (u8)(LED_B | LED_C), //'1' + (u8)(LED_A | LED_B | LED_D | LED_E | LED_G), //'2' + (u8)(LED_A | LED_B | LED_C | LED_D | LED_G), //'3' + (u8)(LED_B | LED_C | LED_F | LED_G), //'4' + (u8)(LED_A | LED_C | LED_D | LED_F | LED_G), //'5' + (u8)(LED_A | LED_C | LED_D | LED_E | LED_F | LED_G), //'6' + (u8)(LED_A | LED_B | LED_C), //'7' + (u8)(LED_A | LED_B | LED_C | LED_D | LED_E | LED_F | LED_G), //'8' + (u8)(LED_A | LED_B | LED_C | LED_D | LED_F | LED_G), //'9' +}; + +//字母'A' ~ 'Z'显示段码表 +static const u8 LED_LARGE_LETTER[26] = { + 0x77, 0x40, 0x39, 0x3f, 0x79, ///sys_halfsec = 0; + __this->count = 0;//; + LED1888_var.bCoordinateX = 0; +} + +/*----------------------------------------------------------------------------*/ +/**@brief LED1888 初始化函数 + @param void + @return void + @author Change.tsai + @note void LED1888_init(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_init(void) +{ + u8 port = (u8) - 1; + u8 i = 0; + if (__this->user_data->pin_type == LED7_PIN7) { + for (i = 0; i < 7; i++) { + port = __this->user_data->pin_cfg.pin7.pin[i]; + if (port != 255) { + gpio_set_pull_down(port, 0); + gpio_set_pull_up(port, 0); + gpio_set_direction(port, 1); + } + } + } + +} + +/*----------------------------------------------------------------------------*/ +/**@brief LED1888 单个字符显示函数 + @param chardata:显示字符 + @return void + @author Change.tsai + @note void LED1888_show_char(u8 chardata) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_char(u8 chardata) +{ + //必须保证传入的参数符合范围,程序不作判断 +// printf("bCoordinateX = %d\n",LED1888_var.bCoordinateX); + if ((chardata < ' ') || (chardata > '~') || (LED1888_var.bCoordinateX > 4)) { + return; + } +// printf("bCoordinateX = %d\n",LED1888_var.bCoordinateX); + if ((chardata >= '0') && (chardata <= '9')) { + LED1888_var.bShowBuff[LED1888_var.bCoordinateX++] = LED_NUMBER[chardata - '0']; + } else if ((chardata >= 'a') && (chardata <= 'z')) { + LED1888_var.bShowBuff[LED1888_var.bCoordinateX++] = LED_SMALL_LETTER[chardata - 'a']; + } else if ((chardata >= 'A') && (chardata <= 'Z')) { + LED1888_var.bShowBuff[LED1888_var.bCoordinateX++] = LED_LARGE_LETTER[chardata - 'A']; + } else if (chardata == '.') { + LED1888_var.bShowBuff[2] |= BIT(7); + } else if (chardata == ' ') { + LED1888_var.bShowBuff[LED1888_var.bCoordinateX++] = 0; + } else { //if (chardata == '-') //不可显示 + LED1888_var.bShowBuff[LED1888_var.bCoordinateX++] = BIT(6); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief LCD_SEG 字符闪烁函数 + @param void + @return void + @author Change.tsai + @note void LCD_SEG_FlashChar(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_FlashChar(void) +{ +// LED1888_var.seg_icon |= ICON_S1; + LED1888_var.bFlashChar |= BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4); +// printf("LED1888_var.bFlashChar = %d\n",LED1888_var.bFlashChar); +} + +void LED1888_Clear_FlashChar(void) +{ +// LED1888_var.seg_icon &= ~ICON_S1; + LED1888_var.bFlashChar &= ~(BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4)); +// printf("LED1888_var.bFlashChar = %d\n",LED1888_var.bFlashChar); +} + +/*----------------------------------------------------------------------------*/ +/**@brief LCD_SEG 单个字符显示函数 + @param chardata:显示字符 + @return void + @author Change.tsai + @note void LCD_SEG4X8_show_number(u8 number) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_number(u8 number) +{ + LED1888_show_char(number + '0'); +} + +/*----------------------------------------------------------------------------*/ +/**@brief LED5X7 字符串显示函数 + @param *str:字符串的指针 offset:显示偏移量 + @return void + @author Change.tsai + @note void LED5X7_show_string(u8 *str) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_string(u8 *str) +{ + while (0 != *str) { + LED1888_show_char(*str++); + } +} + + +void LED1888_show_filenumber(u16 file_num) +{ + LED1888_setX(0); + + u8 bcd_number[5] = {0}; ///<换算结果显示缓存 + itoa4(file_num, (u8 *)bcd_number); + if (file_num > 999 && file_num <= 1999) { + bcd_number[0] = '1'; + } else { + bcd_number[0] = ' '; + } + LED1888_show_string((u8 *)bcd_number); +} + +/*----------------------------------------------------------------------------*/ +/**@brief POWER_ON 显示主界面 + @param void + @return void + @author Change.tsai + @note void LED1888_show_aux_main(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_power_on(void) +{ + LED1888_show_string((u8 *)"E"); +} + +/*----------------------------------------------------------------------------*/ +/**@brief LED1888 开机显示界面(Hi) + @param *str:字符串的指针 + @return void + @author Change.tsai + @note void LED1888_show_Hi(u8 *str) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_Hi(void) +{ + LED1888_show_string((u8 *)" HI"); +} + +/*----------------------------------------------------------------------------*/ +/** @brief: + @param: + @return: + @author: + @note: +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_waiting(void) +{ + LED1888_show_string((u8 *)" Lod"); +} + +/*----------------------------------------------------------------------------*/ +/** @brief: + @param: + @return: + @author: + @note: +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_pause(void) +{ + LED1888_show_string((u8 *)" PAU"); +} +/*----------------------------------------------------------------------------*/ +/**@brief Music模式 设备显示 + @param void + @return void + @author Change.tsai + @note void LED1888_show_dev(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_dev(void) +{ + +} + +/*----------------------------------------------------------------------------*/ +/**@brief 音量显示函数 + @param void + @return void + @author Change.tsai + @note void LCD_SEG3X9_show_volume(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_volume(u8 vol) +{ + LED1888_clear_icon(); + LED1888_show_char(' '); + LED1888_show_char('V'); + LED1888_show_number(vol / 10); + LED1888_show_number(vol % 10); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 频率显示 + @param void + @return void + @author Change.tsai + @note void LCD_SEG_show_freq(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_freq(u16 freq) +{ + /*FM - Frequency*/ + + u8 bcd_number[5] = {0}; ///<换算结果显示缓存 + itoa4(freq, bcd_number); + if (freq > 999) { + bcd_number[0] = '1'; + } else { + bcd_number[0] = ' '; + } + LED1888_show_string((u8 *)bcd_number); + LED1888_var.bShowBuff[2] |= BIT(7);//小数点 +// if(!strcmp(curr_task->name,"MusicTask") ) +// { +// puts("\n-----show SD icon--------\n"); +// LED1888_show_dev(); +// } +// +// if (freq <= 999) +// { +// LCD_STATUS_3X9 &= ~ICON_S1; +// } +// else +// { +// LCD_STATUS_3X9 |= ICON_S1; +// } +// +// LCD_STATUS_3X9 |= ICON_MHZ; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 频率显示 + @param void + @return void + @author Change.tsai + @note void LCD_SEG_show_freq_setting(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_freq_setting(u16 freq) +{ + LED1888_var.bFlashChar = 0x1f; + + LED1888_show_freq(freq); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 红外输入文件号显示函数 + @param void + @return void + @author Change.tsai + @note void LCD_SEG3X9_show_IR_number(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_IR_number(u16 ir_num) +{ + /*IR File Number info*/ +// LCD_STATUS_3X9 = 0; + u8 bcd_number[5] = {0}; ///<换算结果显示缓存 + itoa4(ir_num, bcd_number); + if (ir_num > 999) { + bcd_number[0] = '1'; + } else { + bcd_number[0] = ' '; + } + LED1888_show_string((u8 *)bcd_number); +} + +/*----------------------------------------------------------------------------*/ +/**@brief EQ显示函数 + @param void + @return void + @author Change.tsai + @note void LCD_SEG3X9_show_eq(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_eq(u8 eq) +{ +#if 1 + LED1888_setX(0); + LED1888_show_string((u8 *)" Eq"); + LED1888_show_number(eq % 10); +// LCD_SEG3X9_show_dev(); +#endif +} + +/*----------------------------------------------------------------------------*/ +/**@brief 循环模式显示函数 + @param void + @return void + @author Change.tsai + @note void LCD_SEG3X9_show_playmode(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_playmode(u8 play_mode) +{ + //printf("\n------play_mode == %d\n",play_mode); +// LCD_STATUS_3X9 = 0; + LED1888_setX(0); + /* LED1888_show_string((u8 *)&playmodestr[play_mode-FOP_MAX-1][0]); */ +} + +/*----------------------------------------------------------------------------*/ +/**@brief bt 显示空闲 + @param void + @return void + @author Change.tsai + @note void LED1888_show_bt_idle(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_bt_idle(void) +{ + LED1888_show_string((u8 *)" H "); +} + +/*----------------------------------------------------------------------------*/ +/**@brief bt 显示通话 + @param void + @return void + @author Change.tsai + @note void LCD_SEG_show_bt_call(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_bt_call(void) +{ + LED1888_show_string((u8 *)" CAL"); +} + +/*----------------------------------------------------------------------------*/ +/**@brief bt 显示主界面 + @param void + @return void + @author Change.tsai + @note void LCD_SEG_show_bt_main(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_bt_main(void) +{ + LED1888_show_string((u8 *)" bt"); +} + +/*----------------------------------------------------------------------------*/ +/**@brief Music模式 显示界面 + @param void + @return void + @author Change.tsai + @note void LED1888_show_music_main(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_music_main(void) +{ + +} + +/*----------------------------------------------------------------------------*/ +/**@brief FM 模式主界面 + @param void + @return void + @author Change.tsai + @note void LED1888_show_fm_main(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_fm_main(void) +{ + +} + +/*----------------------------------------------------------------------------*/ +/**@brief AUX 显示主界面 + @param void + @return void + @author Change.tsai + @note void LED1888_show_aux_main(void) +*/ +/*----------------------------------------------------------------------------*/ +void LED1888_show_aux_main(void) +{ + LED1888_show_string((u8 *)" AUX"); +} + +void LED1888_show_pc_main(void) +{ +#if 0 + LED1888_show_string((u8 *)menu_string[2]); +#endif +} + +void LED1888_show_pc_vol_up(void) +{ +#if 0 + LED1888_show_string((u8 *)menu_string[3]); +#endif +} + +void LED1888_show_pc_vol_down(void) +{ +#if 0 + LED1888_show_string((u8 *)menu_string[4]); +#endif +} + +void LED1888_show_led0(u32 arg) +{ + + if (arg & BIT(31)) { + __this->led[0].on = 1; + __this->led[0].phase = !!(arg & BIT(30)); + __this->led[0].H_time = (arg >> 15) & 0x7fff; + __this->led[0].L_time = (arg) & 0x7fff; + __this->led[0].count = 0;//__this->led[0].H_time; + } else { + __this->led[0].on = 0; + __this->led[0].phase = 0;//!!arg&BIT(15); + __this->led[0].H_time = 0;//(arg >> 16)&0x7fff; + __this->led[0].L_time = 0;//(arg)&0xffff; + __this->led[0].count = 0;//__this->led[0].H_time; + } + +} + +void LED1888_show_led1(u32 arg) +{ + + if (arg & BIT(31)) { + __this->led[1].on = 1; + __this->led[1].phase = !!(arg & BIT(30)); + __this->led[1].H_time = (arg >> 15) & 0x7fff; + __this->led[1].L_time = (arg) & 0x7fff; + __this->led[1].count = 0;//__this->led[1].H_time; + } else { + + __this->led[1].on = 0; + __this->led[1].phase = 0;//!!arg&BIT(15); + __this->led[1].H_time = 0;//(arg >> 16)&0x7fff; + __this->led[1].L_time = 0;//(arg)&0xffff; + __this->led[1].count = 0;//__this->led[1].H_time; + + } + +} + +/*----------------------------------------------------------------------------*/ +/**@brief LED1888 扫描函数 + @param void + @return void + @author + @note void LED1888_6p_scan(void) +*/ +/*----------------------------------------------------------------------------*/ + +void LED1888_6p_scan(void *param) +{ + static u8 cnt = 0; + u8 j; + static u8 bufdat[5]; + u8 flash = LED1888_var.bFlashChar; + + if (!cnt && !__this->lock) { + bufdat[0] = LED1888_var.bShowBuff[0]; + bufdat[1] = LED1888_var.bShowBuff[1]; + bufdat[2] = LED1888_var.bShowBuff[2]; + bufdat[3] = LED1888_var.bShowBuff[3]; + } + + __this->count++; + if (__this->count >= 256) { + __this->sys_halfsec = !__this->sys_halfsec; + __this->count = 0; + } + + + if (__this->led[0].on) { + if (__this->led[0].phase) { + __this->led[0].count++; + if (__this->led[0].count >= __this->led[0].H_time + __this->led[0].L_time) { + __this->led[0].count = 0; + } + } else { + __this->led[0].count = (__this->led[0].count == 0) ? (__this->led[0].H_time + __this->led[0].L_time) : (--__this->led[0].count); + } + } + + if (__this->led[1].on) { + + if (__this->led[1].phase) { + __this->led[1].count++; + if (__this->led[1].count >= __this->led[1].H_time + __this->led[1].L_time) { + __this->led[1].count = 0; + } + } else { + __this->led[1].count = (__this->led[1].count == 0) ? (__this->led[1].H_time + __this->led[1].L_time) : (--__this->led[1].count); + } + } + + LED1888_init(); + + if (__this->sys_halfsec) { + for (j = 0; j < 4; j++) { + if (flash & BIT(j)) { //数字位闪烁 + // putchar('F'); + bufdat[j] = 0x0; + } + } + } + + switch (cnt) { + case 0: + PIN1_L; + if (bufdat[1]&LED_A) { + PIN2_H; +#ifdef UI_FADE_EN + PIN2_FADE_PU; + PIN2_FADE_PD; +#endif + } + if (bufdat[1]&LED_B) { + PIN3_H; +#ifdef UI_FADE_EN + PIN3_FADE_PU; + PIN3_FADE_PD; +#endif + } + if (bufdat[1]&LED_C) { + PIN4_H; +#ifdef UI_FADE_EN + PIN4_FADE_PU; + PIN4_FADE_PD; +#endif + } + if (bufdat[1]&LED_D) { + PIN5_H; +#ifdef UI_FADE_EN + PIN5_FADE_PU; + PIN5_FADE_PD; +#endif + } + if (bufdat[1]&LED_E) { + PIN6_H; +#ifdef UI_FADE_EN + PIN6_FADE_PU; + PIN6_FADE_PD; +#endif + } + break; + + case 1: + PIN2_L; + if (bufdat[2]&LED_A) { + PIN1_H; + } + if (bufdat[1]&LED_F) { + PIN3_H; + } + if (bufdat[1]&LED_G) { + PIN4_H; + } + if (bufdat[2]&LED_F) { + PIN5_H; + } + if (bufdat[2]&LED_G) { + PIN6_H; + } + break; + + case 2: + PIN3_L; + if (bufdat[2]&LED_B) { + PIN1_H; + } + if (bufdat[3]&LED_A) { + PIN2_H; + } + if (bufdat[0]&LED_B) { + PIN4_H; + } + if (bufdat[0]&LED_C) { + PIN5_H; + } + if (bufdat[2]&BIT(7)) { + PIN6_H; + }; + break; + case 3: + PIN4_L; + if (bufdat[2]&LED_C) { + PIN1_H; + } + if (bufdat[3]&LED_B) { + PIN2_H; + } + if (bufdat[3]&LED_E) { + PIN3_H; + } + break; + + case 4: + PIN5_L; + if (bufdat[2]&LED_D) { + PIN1_H; + } + if (bufdat[3]&LED_C) { + PIN2_H; + } + if (bufdat[3]&LED_F) { + PIN3_H; + } + + if (__this->led[0].on && (__this->led[0].count <= __this->led[0].H_time)) { + PIN4_H; + } + + break; + + case 5: + PIN6_L; + if (bufdat[2]&LED_E) { + PIN1_H; + } + if (bufdat[3]&LED_D) { + PIN2_H; + } + if (bufdat[3]&LED_G) { + PIN3_H; + } + + + if (__this->led[1].on && (__this->led[1].count <= __this->led[1].H_time)) { + + PIN4_H; + } + + + break; + + default: + break; + } + + cnt++; + if (cnt == 6) { + cnt = 0; + } +} + +#if 0 +UI_API LED1888_ui_api = { + .setX = LED1888_setX, + .clear_icon = LED1888_clear_icon, + .clear = LED1888_clear, + .show_char = LED1888_show_char, + .FlashChar = LED1888_FlashChar, + .Clear_FlashChar = LED1888_Clear_FlashChar, + .show_number = LED1888_show_number, + .show_string = LED1888_show_string, + .show_power_on = LED1888_show_power_on, + .show_Hi = LED1888_show_Hi, + .show_waiting = LED1888_show_waiting, + .show_pause = LED1888_show_pause, + .show_dev = LED1888_show_dev, + .show_filenumber = LED1888_show_filenumber, + .show_volume = LED1888_show_volume, + .show_freq = LED1888_show_freq, + .show_freq_setting = LED1888_show_freq_setting, + .show_IR_number = LED1888_show_IR_number, + .show_eq = LED1888_show_eq, + .show_playmode = LED1888_show_playmode, + .show_bt_idle = LED1888_show_bt_idle, + .show_bt_call = LED1888_show_bt_call, + .show_bt_main = LED1888_show_bt_main, + .show_music_main = LED1888_show_music_main, + .show_fm_main = LED1888_show_fm_main, + .show_aux_main = LED1888_show_aux_main, + .show_pc_main = LED1888_show_pc_main, + .show_pc_vol_up = LED1888_show_pc_vol_up, + .show_pc_vol_down = LED1888_show_pc_vol_down, + .show_led0 = LED1888_show_led0, + .show_led1 = LED1888_show_led1, +}; +#endif + +static void LED1888_setXY(u32 x, u32 y) +{ + LED1888_setX(x); +} + +static void LED1888_Flashchar(u32 arg) +{ + LED1888_var.bFlashChar |= arg;//BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4); +} + +static void LED1888_Clear_Flashchar(u32 arg) +{ + LED1888_var.bFlashChar &= ~(arg); //BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4); +} + + + + +static void LED1888_show_icon(u32 arg) +{ + switch (arg) { + case LED7_DOT: + LED1888_var.bShowBuff[2] |= BIT(7);//小数点 + break; + default: + break; + } +} + + +static void LED1888_flash_icon(u32 arg) +{ + +} + +static void LED1888_Clear_icon(u32 arg) +{ + switch (arg) { + case LED7_DOT: + LED1888_var.bShowBuff[2] &= ~(BIT(7)); //小数点 + break; + default: + break; + } +} + + +static void LED1888_show_pic(u32 arg) +{ + +} + +static void LED1888_hide_pic(u32 arg) +{ + +} + +static void LED1888_show_lock(u32 en) +{ + __this->lock = !!en; +} + + +LCD_API LED1888_HW = { + .clear = LED1888_clear, + .setXY = LED1888_setXY, + .FlashChar = LED1888_Flashchar, + .Clear_FlashChar = LED1888_Clear_Flashchar, + .show_icon = LED1888_show_icon, + .flash_icon = LED1888_flash_icon, + .clear_icon = LED1888_Clear_icon, + .show_string = LED1888_show_string, + .show_char = LED1888_show_char, + .show_number = LED1888_show_number, + .show_pic = LED1888_show_pic, + .hide_pic = LED1888_hide_pic, + .lock = LED1888_show_lock, +}; + + + + +/*----------------------------------------------------------------------------*/ +/**@brief led7段数码管初始化 + @param void + @return void + @author Change.tsai + @note void led7_init(void) +*/ +/*----------------------------------------------------------------------------*/ +void *led_1888_init(const struct led7_platform_data *_data) +{ + memset(__this, 0x00, sizeof(struct ui_led7_env)); + + if (_data == NULL) { + return NULL; + } + memset((u8 *)&LED1888_var, 0x0, sizeof(LED1888_VAR)); + + struct led7_platform_data *data = malloc(sizeof(struct led7_platform_data)); + if (!data) { + return NULL; + } + + memcpy(data, _data, sizeof(struct led7_platform_data)); + __this->user_data = data; + LED1888_init(); + + /* sys_s_hi_timer_add(NULL, LED1888_6p_scan, 2); //2ms */ + + void app_timer_led_scan(void (*led_scan)(void *)); + app_timer_led_scan(LED1888_6p_scan); + + + __this->init = true; + return &LED1888_HW; +} + + +#endif diff --git a/cpu/br23/ui_driver/LED_1888/LED1888.h b/cpu/br23/ui_driver/LED_1888/LED1888.h new file mode 100644 index 0000000..a22264a --- /dev/null +++ b/cpu/br23/ui_driver/LED_1888/LED1888.h @@ -0,0 +1,62 @@ +#ifndef _LED1888_H_ +#define _LED1888_H_ + + +#if TCFG_UI_LED1888_ENABLE + + + +#define LED_A BIT(0) +#define LED_B BIT(1) +#define LED_C BIT(2) +#define LED_D BIT(3) +#define LED_E BIT(4) +#define LED_F BIT(5) +#define LED_G BIT(6) +#define LED_H BIT(7) + + +typedef struct _LED188_VAR { + u8 bCoordinateX; + u8 bFlashChar; + u8 bFlashIcon; + u8 bShowBuff[4]; + u8 bBrightness; + u8 bShowBuff1[9]; +} LED1888_VAR; + + +void LED1888_setX(u8 X); +void LED1888_clear_icon(void); +void LED1888_clear(void); +void LED1888_init(void); +void LED1888_show_char(u8 chardata); +void LED1888_FlashChar(void); +void LED1888_Clear_FlashChar(void); +void LED1888_show_number(u8 number); +void LED1888_show_string(u8 *str); +void LED1888_show_power_on(void); +void LED1888_show_Hi(void); +void LED1888_show_waiting(void); +void LED1888_show_pause(void); +void LED1888_show_dev(void); +void LED1888_show_filenumber(u16 file_num); +void LED1888_show_volume(u8 vol); +void LED1888_show_freq(u16 freq); +void LED1888_show_freq_setting(u16 freq); +void LED1888_show_IR_number(u16 ir_num); +void LED1888_show_eq(u8 eq); +void LED1888_show_playmode(u8 play_mode); +void LED1888_show_bt_idle(void); +void LED1888_show_bt_call(void); +void LED1888_show_bt_main(void); +void LED1888_show_music_main(void); +void LED1888_show_fm_main(void); +void LED1888_show_aux_main(void); +void LED1888_show_pc_main(void); +void LED1888_show_pc_vol_up(void); +void LED1888_show_pc_vol_down(void); +void LED1888_6p_scan(void *param); + +#endif +#endif/*LED1888_H_*/ diff --git a/cpu/br23/ui_driver/interface/ui_platform.c b/cpu/br23/ui_driver/interface/ui_platform.c new file mode 100644 index 0000000..3737d92 --- /dev/null +++ b/cpu/br23/ui_driver/interface/ui_platform.c @@ -0,0 +1,4120 @@ +#include "ui/includes.h" +#include "timer.h" +#include "asm/crc16.h" +#include "ui/lcd_spi/lcd_drive.h" +#include "ascii.h" +#include "font/font_textout.h" +#include "res/rle.h" +#include "res/resfile.h" +#include "ui/res_config.h" +#include "app_config.h" +#include "dev_manager.h" +#include "app_task.h" +#include "smartbox/smartbox_task.h" +#include "fs/fs.h" + +#if TCFG_SPI_LCD_ENABLE + + +#define UI_DEBUG 0 +/* #define UI_BUF_CALC */ + +#if (UI_DEBUG == 1) + +#define UI_PUTS puts +#define UI_PRINTF printf + +#else + +#define UI_PUTS(...) +#define UI_PRINTF(...) + +#endif + +#define _RGB565(r,g,b) (u16)((((r)>>3)<<11)|(((g)>>2)<<5)|((b)>>3)) +#define UI_RGB565(c) \ + _RGB565((c>>16)&0xff,(c>>8)&0xff,c&0xff) + +#define TEXT_MONO_CLR 0x555aaa +#define TEXT_MONO_INV 0xaaa555 +#define RECT_MONO_CLR 0x555aaa +#define BGC_MONO_SET 0x555aaa + + +struct fb_map_user { + u16 xoffset; + u16 yoffset; + u16 width; + u16 height; + u8 *baddr; + u8 *yaddr; + u8 *uaddr; + u8 *vaddr; + u8 transp; + u8 format; +}; + +struct fb_var_screeninfo { + u16 s_xoffset; //显示区域x坐标 + u16 s_yoffset; //显示区域y坐标 + u16 s_xres; //显示区域宽度 + u16 s_yres; //显示区域高度 + u16 v_xoffset; //屏幕的虚拟x坐标 + u16 v_yoffset; //屏幕的虚拟y坐标 + u16 v_xres; //屏幕的虚拟宽度 + u16 v_yres; //屏幕的虚拟高度 + u16 rotate; +}; + +struct window_head { + u32 offset; + u32 len; + u32 ptr_table_offset; + u16 ptr_table_len; + u16 crc_data; + u16 crc_table; + u16 crc_head; +}; + +struct ui_file_head { + u8 res[16]; + u8 type; + u8 window_num; + u16 prop_len; + u8 rotate; + u8 rev[3]; +}; + + +struct ui_load_info ui_load_info_table[] = { +#if UI_WATCH_RES_ENABLE + {1, NULL, NULL}, + {2, RES_PATH"sidebar/sidebar.sty", NULL}, +#endif + {-1, NULL, NULL}, +}; + + + +static u32 ui_rotate = false; +static u32 ui_hori_mirror = false; +static u32 ui_vert_mirror = false; +static int malloc_cnt = 0; +static FILE *ui_file = NULL; +static FILE *ui_file1 = NULL; +static FILE *ui_file2 = NULL; +static int ui_file_len = 0; + +static int open_resource_file(); +void select_strfile(u8 index); +void select_resfile(u8 index); + +static const struct ui_platform_api br23_platform_api; + +struct ui_priv { + struct ui_platform_api *api; + struct lcd_interface *lcd; + int window_offset; + struct lcd_info info; +}; +static struct ui_priv priv ALIGNED(4); +#define __this (&priv) + +#ifdef UI_BUF_CALC +struct buffer { + struct list_head list; + u8 *buf; + int size; +}; +struct buffer buffer_used = {0}; +#endif + +void *br23_malloc(int size) +{ + void *buf; + malloc_cnt++; + buf = (void *)malloc(size); + + /* printf("platform_malloc : 0x%x, %d\n", buf, size); */ +#ifdef UI_BUF_CALC + struct buffer *new = (struct buffer *)malloc(sizeof(struct buffer)); + new->buf = buf; + new->size = size; + list_add_tail(new, &buffer_used); + printf("platform_malloc : 0x%x, %d\n", buf, size); + + struct buffer *p; + int buffer_used_total = 0; + list_for_each_entry(p, &buffer_used.list, list) { + buffer_used_total += p->size; + } + printf("used buffer size:%d\n\n", buffer_used_total); +#endif + + return buf; +} + +void br23_free(void *buf) +{ + + /* printf("platform_free : 0x%x\n",buf); */ + free(buf); + malloc_cnt--; + +#ifdef UI_BUF_CALC + struct buffer *p, *n; + list_for_each_entry_safe(p, n, &buffer_used.list, list) { + if (p->buf == buf) { + printf("platform_free : 0x%x, %d\n", p->buf, p->size); + __list_del_entry(p); + free(p); + } + } + + int buffer_used_total = 0; + list_for_each_entry(p, &buffer_used.list, list) { + buffer_used_total += p->size; + } + printf("used buffer size:%d\n\n", buffer_used_total); +#endif +} + +int ui_platform_ok() +{ + return (malloc_cnt == 0); +} + +static void draw_rect_range_check(struct rect *r, struct fb_map_user *map) +{ + if (r->left < map->xoffset) { + r->left = map->xoffset; + } + if (r->left > (map->xoffset + map->width)) { + r->left = map->xoffset + map->width; + } + if ((r->left + r->width) > (map->xoffset + map->width)) { + r->width = map->xoffset + map->width - r->left; + } + if (r->top < map->yoffset) { + r->top = map->yoffset; + } + if (r->top > (map->yoffset + map->height)) { + r->top = map->yoffset + map->height; + } + if ((r->top + r->height) > (map->yoffset + map->height)) { + r->height = map->yoffset + map->height - r->top; + } + + ASSERT(r->left >= map->xoffset); + ASSERT(r->top >= map->yoffset); + ASSERT((r->left + r->width) <= (map->xoffset + map->width)); + ASSERT((r->top + r->height) <= (map->yoffset + map->height)); +} + + +/* 透明色: 16bits 0x55aa 0101 0xxx 1011 01xx 0101 0xxx + * 24bits 0x50b450 0101 0000 1011 0100 0101 0000 , 80 180 80 + * */ +void __font_pix_copy(struct draw_context *dc, int format, struct fb_map_user *map, u8 *pix, struct rect *draw, int x, int y, + int height, int width, int color) +{ + + int i, j, h; + u16 osd_color; + u32 size; + + osd_color = (format == DC_DATA_FORMAT_OSD8) || (format == DC_DATA_FORMAT_OSD8A) ? color & 0xff : color & 0xffff ; + + for (j = 0; j < (height + 7) / 8; j++) { /* 纵向8像素为1字节 */ + for (i = 0; i < width; i++) { + if (((i + x) >= draw->left) + && ((i + x) <= (draw->left + draw->width - 1))) { /* x在绘制区域,要绘制 */ + u8 pixel = pix[j * width + i]; + int hh = height - (j * 8); + if (hh > 8) { + hh = 8; + } + for (h = 0; h < hh; h++) { + if (((y + j * 8 + h) >= draw->top) + && ((y + j * 8 + h) <= (draw->top + draw->height - 1))) { /* y在绘制区域,要绘制 */ + u16 clr = pixel & BIT(h) ? osd_color : 0; + if (clr) { + if (platform_api->draw_point) { + platform_api->draw_point(dc, x + i, y + j * 8 + h, clr); + } + } + } + } /* endof for h */ + } + }/* endof for i */ + }/* endof for j */ +} + + +static int image_str_size_check(struct draw_context *dc, int page_num, const char *txt, int *width, int *height) +{ + + u16 id = ((u8)txt[1] << 8) | (u8)txt[0]; + u16 cnt = 0; + struct image_file file; + int w = 0, h = 0; + + while (id != 0x00ff) { + select_resfile(dc->prj); + if (open_image_by_id(NULL, &file, id, page_num) != 0) { + return -EFAULT; + } + w += file.width; + cnt += 2; + id = ((u8)txt[cnt + 1] << 8) | (u8)txt[cnt]; + } + h = file.height; + *width = w; + *height = h; + return 0; +} + +void platform_putchar(struct font_info *info, u8 *pixel, u16 width, u16 height, u16 x, u16 y) +{ + __font_pix_copy(info->dc, info->disp.format, + (struct fb_map_user *)info->disp.map, + pixel, + (struct rect *)info->disp.rect, + (s16)x, + (s16)y, + height, + width, + info->disp.color); +} + + +struct file_dev { + const char *logo; + const char *root_path; +}; + + +struct file_browser { + int show_mode; + struct rect r; + struct vfscan *fscan; + /* struct server *server; */ + struct ui_file_browser bro; + struct file_dev dev;//支持三个设备 +}; + + +static int check_file_ext(const char *ext_table, const char *ext) +{ + const char *str; + + for (str = ext_table; *str != '\0'; str += 3) { + if (0 == ASCII_StrCmpNoCase(ext, str, 3)) { + return true; + } + } + return false; +} + +static const u8 MUSIC_SCAN_PARAM[] = "-t" + "MP1MP2MP3" + " -sn -d" + ; + + + + +static int platform_file_get_dev_total() +{ + return dev_manager_get_total(1); +} + + + +static void platform_file_browser_get_dev_info(struct ui_file_browser *_bro, u8 index) +{ + struct file_browser *bro = container_of(_bro, struct file_browser, bro); + struct file_dev *file_dev;//支持三个设备 + + + if (!bro) { + return; + } + struct __dev *dev = dev_manager_find_by_index(index, 0);//storage_dev_find_by_index(index); + if (dev) { + file_dev = &bro->dev; + file_dev->logo = dev_manager_get_logo(dev);//获取设备logo + file_dev->root_path = dev_manager_get_root_path_by_logo(dev);//获取设备路径 + } +} + + + +static struct ui_file_browser *platform_file_browser_open(struct rect *r, + const char *path, const char *ftype, int show_mode) +{ + int err; + struct file_browser *bro; + struct __dev *dev = 0; + bro = (struct file_browser *)malloc(sizeof(*bro)); + if (!bro) { + return NULL; + } + bro->bro.file_number = 0; + bro->show_mode = show_mode; + + if (!path) { + dev = dev_manager_find_active(0);///storage_dev_last();//获取最后一个设备的路径 + if (!dev) { + free(bro); + return NULL; + } + path = dev_manager_get_root_path_by_logo(dev);//dev->root_path; + } + + if (!ftype) { + ftype = MUSIC_SCAN_PARAM; + } + + bro->fscan = fscan(path, ftype, 9); + bro->bro.dev_num = dev_manager_get_total(1);//获取在线设备总数 + + if (bro->fscan) { + bro->bro.file_number = bro->fscan->file_number; + if (bro->bro.file_number == 0) { + return &bro->bro; + } + } + + if (r) { + memcpy(&bro->r, r, sizeof(struct rect)); + } + + return &bro->bro; + +__err: + fscan_release(bro->fscan); + free(bro); + return NULL; +} + + + +static void platform_file_browser_close(struct ui_file_browser *_bro) +{ + struct file_browser *bro = container_of(_bro, struct file_browser, bro); + + if (!bro) { + return; + } + if (bro->fscan) { + fscan_release(bro->fscan); + } + free(bro); +} + +static int platform_get_file_attrs(struct ui_file_browser *_bro, + struct ui_file_attrs *attrs) +{ + int i, j; + struct vfs_attr attr; + struct file_browser *bro = container_of(_bro, struct file_browser, bro); + + if (!bro->fscan) { + return -ENOENT; + } + + FILE *file = fselect(bro->fscan, FSEL_BY_NUMBER, attrs->file_num + 1); + if (!file) { + return -ENOENT; + } + + attrs->format = "ascii"; + + fget_attrs(file, &attrs->attr); + /* printf(" attr = %x, fsize = %x,sclust = %x\n",attrs->attr.attr,attrs->attr.fsize,attrs->attr.sclust); */ + + struct sys_time *time; + time = &(attrs->attr.crt_time); + /* printf("y =%d m =%d d = %d,h = %d ,m = %d ,s =%d\n",time->year,time->month,time->day,time->hour,time->min,time->sec); */ + + time = &(attrs->attr.wrt_time); + /* printf("y =%d m =%d d = %d,h = %d ,m = %d ,s =%d\n",time->year,time->month,time->day,time->hour,time->min,time->sec); */ + + + int len = fget_name(file, (u8 *)attrs->fname, 16);//长文件获取有问题 + if (len < 0) { + fclose(file); + return -EINVAL; + } + + for (i = 0; i < len; i++) { + if ((u8)attrs->fname[i] >= 0x80) { + attrs->format = "uft16"; + goto _next; + } + } + + + /* ASCII_ToUpper(attrs->fname, strlen(attrs->fname)); */ + +_next: + +#if 0//文件系统接口不完善,临时解决 + for (i = 0; i < len; i++) { + if (attrs->fname[i] == '.') { + break; + } + } + + if (i == len) { + attrs->ftype = UI_FTYPE_DIR; + } else { + char *ext = attrs->fname + i + 1; + + if (check_file_ext("JPG", ext)) { + attrs->ftype = UI_FTYPE_IMAGE; + } else if (check_file_ext("MOVAVI", ext)) { + attrs->ftype = UI_FTYPE_VIDEO; + } else if (check_file_ext("MP3WMAWAV", ext)) { + attrs->ftype = UI_FTYPE_AUDIO; + } else { + attrs->ftype = UI_FTYPE_UNKNOW; + } + } +#else + /* printf("name = %d %d \n",strlen(attrs->fname),len); */ + /* put_buf(attrs->fname,len); */ + + if (attrs->attr.attr & F_ATTR_DIR) { + attrs->ftype = UI_FTYPE_DIR; + } else { + char *ext = attrs->fname + strlen(attrs->fname) - 3; + if (check_file_ext("JPG", ext)) { + attrs->ftype = UI_FTYPE_IMAGE; + } else if (check_file_ext("MOVAVI", ext)) { + attrs->ftype = UI_FTYPE_VIDEO; + } else if (check_file_ext("MP3WMAWAV", ext)) { + attrs->ftype = UI_FTYPE_AUDIO; + } else { + attrs->ftype = UI_FTYPE_UNKNOW; + } + + } + +#endif + + fclose(file); + + return 0; +} + +static int platform_set_file_attrs(struct ui_file_browser *_bro, + struct ui_file_attrs *attrs) +{ + int attr = 0; + struct file_browser *bro = container_of(_bro, struct file_browser, bro); + + if (!bro->fscan) { + return -ENOENT; + } + + FILE *file = fselect(bro->fscan, FSEL_BY_NUMBER, attrs->file_num + 1); + if (!file) { + return -EINVAL; + } + + fget_attr(file, &attr); + if (attrs->attr.attr & F_ATTR_RO) { + attr |= F_ATTR_RO; + } else { + attr &= ~F_ATTR_RO; + } + fset_attr(file, attr); + + fclose(file); + + return 0; +} + +static void *platform_open_file(struct ui_file_browser *_bro, + struct ui_file_attrs *attrs) +{ + struct file_browser *bro = container_of(_bro, struct file_browser, bro); + + if (!bro->fscan) { + return NULL; + } + + return fselect(bro->fscan, FSEL_BY_NUMBER, attrs->file_num + 1); +} + +static int platform_delete_file(struct ui_file_browser *_bro, + struct ui_file_attrs *attrs) +{ + struct file_browser *bro = container_of(_bro, struct file_browser, bro); + + if (!bro->fscan) { + return -EINVAL; + } + + FILE *file = fselect(bro->fscan, FSEL_BY_NUMBER, attrs->file_num + 1); + if (!file) { + return -EFAULT; + } + fdelete(file); + + return 0; +} + +void test_browser() +{ + struct ui_file_browser *browser = NULL; + static struct ui_file_attrs attrs = {0}; + if (!browser) { + browser = platform_file_browser_open(NULL, NULL, MUSIC_SCAN_PARAM, 0); + } + + if (browser) { + printf("file num = %d \n", browser->file_number); + platform_get_file_attrs(browser, &attrs); + printf("format =%s name =%s type = %x \n", attrs.format, attrs.fname, attrs.ftype); + platform_delete_file(browser, &attrs); + attrs.file_num ++; + if (attrs.file_num >= browser->file_number) { + attrs.file_num = 0; + } + } +} + +static void *br23_set_timer(void *priv, void (*callback)(void *), u32 msec) +{ + return (void *)sys_timer_add(priv, callback, msec); +} + +static int br23_del_timer(void *fd) +{ + if (fd) { + sys_timer_del((int)fd); + } + + return 0; +} + +u32 __attribute__((weak)) set_retry_cnt() +{ + return 10; +} + +const char *WATCH_VERSION_LIST = { + "W001" + +}; + +/* static const char *WATCH_STY_CHECK_LIST[] = { */ +/* RES_PATH"JL/JL.sty", */ +/* RES_PATH"watch/watch.sty", */ +/* RES_PATH"watch1/watch1.sty", */ +/* RES_PATH"watch2/watch2.sty", */ +/* RES_PATH"watch3/watch3.sty", */ +/* RES_PATH"watch4/watch4.sty", */ +/* RES_PATH"watch5/watch5.sty", */ +/* }; */ + +#define WATCH_ITEMS_LIMIT 40 +#define BGP_ITEMS_LIMIT (WATCH_ITEMS_LIMIT + 10)//(确保 >= WATCH_ITEMS_LIMIT就可以) +static u8 watch_style; +static u8 watch_items; +static volatile u8 watch_update_over = 0; + +static char *watch_res[WATCH_ITEMS_LIMIT] = {0}; +static char *watch_bgp_related[WATCH_ITEMS_LIMIT] = {0}; +static char *watch_bgp[BGP_ITEMS_LIMIT] = {0}; +static u8 watch_bgp_items; + +static char *watch_bgpic_path = NULL; + +extern u8 smartbox_eflash_flag_get(void); +extern u8 smartbox_eflash_update_flag_get(void); +extern void smartbox_eflash_flag_set(u8 eflash_state_type); +static int watch_mem_bgp_related(); + +u32 watch_bgp_get_nums() +{ + return watch_bgp_items; +} + +char *watch_bgp_get_item(u8 sel_item) +{ + if (sel_item >= watch_bgp_items) { + printf("\n\n\nwatch_bgp items overflow %d\n\n\n\n", sel_item); + return NULL; + } + + return watch_bgp[sel_item]; +} + +char *watch_bgp_add(char *bgp) +{ + char *root_path = RES_PATH; + char *new_bgp_item = NULL; + u32 len; + u32 i; + + if ((watch_bgp_items + 1) >= BGP_ITEMS_LIMIT) { + printf("\n\n\nwatch_bgp items overflow %d\n\n\n\n", watch_bgp_items); + return NULL; + } + + len = strlen(bgp) + strlen(root_path) + 1; + new_bgp_item = malloc(len); + if (new_bgp_item == NULL) { + printf("\n\n\nwatch_bgp items malloc err %d\n\n\n\n", len); + return NULL; + } + + ASCII_ToLower(bgp, strlen(bgp)); + strcpy(new_bgp_item, root_path); + /* strcpy(&new_bgp_item[strlen(root_path)], &bgp[1]); */ + strcpy(&new_bgp_item[strlen(root_path)], bgp); + new_bgp_item[len - 1] = '\0'; + + //如果已经存在这个背景图片路径,则直接返回对应的地址 + for (i = 0; i < watch_bgp_items; i++) { + /* printf("num %s\n", watch_bgp[i]); */ + if (strncmp(new_bgp_item, watch_bgp[i], strlen(new_bgp_item)) == 0) { + free(new_bgp_item); + new_bgp_item = watch_bgp[i]; + printf("already has %s\n", new_bgp_item); + return new_bgp_item; + } + } + + watch_bgp[watch_bgp_items] = new_bgp_item; + watch_bgp_items++; + + printf("add new_bgp_item succ %d, %s\n", watch_bgp_items, new_bgp_item); + + return new_bgp_item; +} + +int watch_bgp_del(char *bgp) +{ + u32 i; + char watch_bgp_item[64]; + u32 cur_items = watch_bgp_items; + char *root_path = RES_PATH; + char *bgp_item = NULL; + + ASSERT(((strlen(bgp) + strlen(root_path) + 1) < sizeof(watch_bgp_item)), "bgp err name0 %s\n", bgp); + + ASCII_ToLower(bgp, strlen(bgp)); + strcpy(watch_bgp_item, root_path); + /* strcpy(&watch_bgp_item[strlen(root_path)], &bgp[1]); */ + strcpy(&watch_bgp_item[strlen(root_path)], bgp); + watch_bgp_item[strlen(bgp) + strlen(root_path)] = '\0'; + printf("watch_bgp_item %s\n", watch_bgp_item); + + for (i = 0; i < cur_items; i++) { + if (strncmp(watch_bgp_item, watch_bgp[i], strlen(watch_bgp_item)) == 0) { + bgp_item = watch_bgp[i]; + watch_bgp[i] = NULL; + free(bgp_item); + watch_bgp_items--; + break; + } + } + + if (bgp_item == NULL) { + printf("can not find bgp_item %s\n", watch_bgp_item); + return -1; + } + + for (; i < cur_items; i++) { + if (watch_bgp[i + 1] != NULL) { + watch_bgp[i] = watch_bgp[i + 1]; + } else { + watch_bgp[i] = NULL; + break; + } + } + + //del related item + cur_items = sizeof(watch_bgp_related) / sizeof(watch_bgp_related[0]); + for (i = 0; i < cur_items; i++) { + if (bgp_item == watch_bgp_related[i]) { + watch_bgp_related[i] = NULL; + } + } + + for (i = 0; i < cur_items; i++) { + printf("cur related items %d, %s\n", i, watch_bgp_related[i]); + } + for (i = 0; i < watch_bgp_items; i++) { + printf("cur bgp items %d, %s\n", i, watch_bgp[i]); + } + + return 0; +} + + +//替换背景图片,(1)如果某个表盘没有背景图片,则增加,(2)如果有就替换 +//如果被替换的这个背景图片已经不关联任何表盘,则将它从表watch_bgp删除 +int watch_bgp_set_related(char *bgp, u8 cur_watch, u8 del) +{ + u32 i; + u32 cur_items; + char *root_path = RES_PATH; + char *bgp_item = NULL; + char *new_bgp_item = NULL; + u32 total_relate_items; + char old_bgp[16]; + u32 len; + + total_relate_items = sizeof(watch_bgp_related) / sizeof(watch_bgp_related[0]); + if (cur_watch >= total_relate_items) { + printf("\n\n\nwatch_bgp_related items overflow %d\n\n\n\n", cur_watch); + return -1; + } + + //提取旧的背景图片名字 + if (watch_bgp_related[cur_watch]) { + bgp_item = watch_bgp_related[cur_watch]; + len = strlen(bgp_item) - strlen(root_path) + 1; + if (len >= sizeof(old_bgp)) { + return -1; + } + memcpy(old_bgp, &bgp_item[strlen(root_path)], len); + printf("old bpg %s\n", old_bgp); + } + + if (bgp != NULL) { + new_bgp_item = watch_bgp_add(bgp); + if (new_bgp_item == NULL) { + printf("add bgp item err %s\n", bgp); + return -1; + } + } + + //如果没有背景图片 + if (watch_bgp_related[cur_watch] == NULL) { + watch_bgp_related[cur_watch] = new_bgp_item; + /* printf("a1\n"); */ + } else { + bgp_item = watch_bgp_related[cur_watch]; + watch_bgp_related[cur_watch] = new_bgp_item; + cur_items = sizeof(watch_bgp_related) / sizeof(watch_bgp_related[0]); + /* printf("a2 %s\n", bgp_item); */ + for (i = 0; i < cur_items; i++) { + if (bgp_item == watch_bgp_related[i]) { + /* printf("a3 %d\n", i); */ + break; + } + } + if ((i == cur_items) && del) { //被替换的这个背景图片已经不关联任何表盘 + /* printf("a4\n"); */ + watch_bgp_del(old_bgp); + } + } + + watch_mem_bgp_related(); + + return 0; +} + +//根据某个表盘获取对应的背景图片 +char *watch_bgp_get_related(u8 cur_watch) +{ + u32 total_relate_items; + + total_relate_items = sizeof(watch_bgp_related) / sizeof(watch_bgp_related[0]); + if (cur_watch >= total_relate_items) { + printf("\n\n\nwatch_bgp_related items overflow %d\n\n\n\n", cur_watch); + return NULL; + } + + return watch_bgp_related[cur_watch]; +} + +int watch_bgp_related_del_all(char *bgp) +{ + watch_bgp_del(bgp); + watch_mem_bgp_related(); + return 0; +} + +int watch_get_style_by_name(char *name) +{ + u32 i; + u32 ret; + printf("watch find %s\n", name); + + for (i = 0; i < watch_items; i++) { + /* printf("watch finding %s\n", watch_res[i]); */ + if (strncmp(name, watch_res[i], strlen(name)) == 0) { + printf("find watch style %d, %s\n\n\n", i, watch_res[i]); + return i; + } + } + + printf("watch find faile\n"); + return -1; +} + +#define WATCH_MEM_BGP 0x55aa66bb +static u32 wmem_last = 0; +static u32 wmem_area_num = 0; +static void *wmem_file = NULL; + +int watch_mem_new(u32 area) +{ + wmem_last = area; + wmem_area_num++; + return 0; +} + +void *watch_mem_open() +{ + if (wmem_file == NULL) { + /* wmem_file = fopen(RES_PATH"wmem.bin", "w+"); */ + wmem_file = fopen("storage/sd1/C/wmem.bin", "w+"); + } + return wmem_file; +} + +void watch_mem_close() +{ + if (wmem_file) { + fclose(wmem_file); + wmem_file = NULL; + } +} + +int watch_mem_write(u32 offset, u32 len, u8 *buf, u32 area) +{ + u32 ret; + u8 tmp_buf[8]; + u32 area_offset = 0; + u32 area_len = 0; + u32 find_tag = 0; + + if (wmem_file == NULL) { + return -1; + } + + if ((flen(wmem_file) == 0) || (wmem_area_num <= 1)) { + area_offset = 0; + } else { + do { + fseek_fast(wmem_file, area_offset, SEEK_SET); + ret = fread_fast(wmem_file, tmp_buf, 8); + if (ret != 8) { + printf("wmem find tag err end\n"); + return -1; + } + memcpy(&ret, tmp_buf + 4, 4); //flag + if (ret == area) { + memcpy(&area_len, tmp_buf, 4);//len + find_tag = 1; + break; + } + memcpy(&ret, tmp_buf, 4);//len + area_offset += ret; + } while (find_tag == 0); + } + + fseek_fast(wmem_file, area_offset + offset, SEEK_SET); + if (area == wmem_last) { + ret = fwrite(wmem_file, buf, len); + if (ret != len) { + return -1; + } + } else { + if ((offset + len) <= area_len) { + ret = fwrite(wmem_file, buf, len); + if (ret != len) { + return -1; + } + } else { + //要将这个区域的内容先搬迁到文件最后,使这个区域成为最后的区域 + //再写数据 + + } + } + + return 0; +} + +/* static u32 wmem_test_flag = 0; */ +int watch_mem_read(u32 offset, u32 len, u8 *buf, u32 area) +{ + u32 area_offset = 0; + u32 area_len = 0; + u32 find_tag = 0; + u32 ret; + u8 tmp_buf[8]; + + if (wmem_file == NULL) { + return -1; + } + + if (flen(wmem_file) == 0) { + /* wmem_test_flag = 1; */ + return 0; + } + + + if (wmem_area_num <= 1) { + area_offset = 0; + } else { + do { + fseek_fast(wmem_file, area_offset, SEEK_SET); + ret = fread_fast(wmem_file, tmp_buf, 8); + if (ret != 8) { + printf("wmem find tag err end\n"); + return -1; + } + memcpy(&ret, tmp_buf + 4, 4); //flag + if (ret == area) { + memcpy(&area_len, tmp_buf, 4);//len + find_tag = 1; + break; + } + memcpy(&ret, tmp_buf, 4);//len + area_offset += ret; + } while (find_tag == 0); + + if ((offset + len) > area_len) { + return -1; + } + } + + fseek_fast(wmem_file, area_offset + offset, SEEK_SET); + ret = fread_fast(wmem_file, buf, len); + if (ret != len) { + printf("wmem read err %d\n", ret); + return -1; + } + + return 0; +} + + +static int watch_mem_bgp_related() +{ + int ret = 0; + u8 *related_buf; + u32 total_relate_items = sizeof(watch_bgp_related) / sizeof(watch_bgp_related[0]); + u32 len; + char *related_item; + u32 area = WATCH_MEM_BGP; + u32 i; + + if (watch_bgp_items == 0) { + return -1; + } + + len = 64 * (total_relate_items + 1); + related_buf = zalloc(len); + if (related_buf == NULL) { + return -1; + } + + if (watch_mem_open() == NULL) { + return -1; + } + + memcpy(related_buf, &len, 4); + memcpy(related_buf + 4, &area, 4); + for (i = 0; i < total_relate_items; i++) { + related_item = watch_bgp_related[i]; + if (related_item) { + printf("related item : %s, %d, %d\n", related_item, strlen(related_item) + 1, i); + memcpy(&related_buf[64 + 64 * i], related_item, strlen(related_item) + 1); + } + } + ret = watch_mem_write(0, len, related_buf, area); + if (ret != 0) { + printf("watch mem werr %x\n", ret); + } else { + printf("watch mem succ\n"); + } + + watch_mem_close(); + + free(related_buf); + + return ret; +} + +static int watch_bgp_related_init() +{ + static u8 flag = 0; + int ret = 0; + u8 *related_buf; + u32 total_relate_items = sizeof(watch_bgp_related) / sizeof(watch_bgp_related[0]); + u32 len; + char *related_item; + u32 area = WATCH_MEM_BGP; + u32 i, j; + + if (flag == 0) { + watch_mem_new(area); + flag = 1; + } + + if (watch_bgp_items == 0) { + return -1; + } + + len = 64 * (total_relate_items + 1); + related_buf = zalloc(len); + if (related_buf == NULL) { + return -1; + } + + if (watch_mem_open() == NULL) { + return -1; + } + + ret = watch_mem_read(0, len, related_buf, area); + if (ret != 0) { + return -1; + } + + for (i = 0; i < total_relate_items; i++) { + watch_bgp_related[i] = NULL; + related_item = &related_buf[64 + 64 * i]; + if (related_item[0]) { + printf("related item : %s, %d, %d\n", related_item, strlen(related_item), i); + for (j = 0; j < watch_bgp_items; j++) { + if (strncmp(related_item, watch_bgp[j], strlen(watch_bgp[j])) == 0) { + watch_bgp_related[i] = watch_bgp[j]; + printf("find bgp related %d\n", j); + break; + } + } + } + } + + watch_mem_close(); + + free(related_buf); + + return 0; +} + + + +char *watch_get_background() +{ + if (watch_bgpic_path == NULL) { + return NULL; + } + return watch_bgpic_path; +} + +int watch_set_background(char *bg_pic) +{ + u32 bg_strlen = strlen(bg_pic); + u32 root_path_strlen = strlen(RES_PATH); + + /* if ((bg_strlen + root_path_strlen) >= sizeof(watch_bgpic_path)) { */ + /* printf("set background err %d, %d\n", bg_strlen, root_path_strlen); */ + /* return -1; */ + /* } */ + + if (bg_pic == NULL) { + /* memset(watch_bgpic_path, 0, sizeof(watch_bgpic_path)); */ + if (watch_bgpic_path != NULL) { + free(watch_bgpic_path); + } + watch_bgpic_path = NULL; + } else { + + if (watch_bgpic_path != NULL) { + free(watch_bgpic_path); + watch_bgpic_path = NULL; + } + + watch_bgpic_path = malloc(bg_strlen + root_path_strlen + 1); + if (watch_bgpic_path == NULL) { + printf("set background err %d, %d\n", bg_strlen, root_path_strlen); + return -1; + } + + strcpy(watch_bgpic_path, RES_PATH); + strcpy(watch_bgpic_path + root_path_strlen, bg_pic); + watch_bgpic_path[root_path_strlen + bg_strlen] = '\0'; + } + + return 0; +} + +void watch_update_finish() +{ + printf("\n\nwatch update finish\n\n"); + watch_update_over = 1; +} + +int watch_get_update_status() +{ + return watch_update_over; +} + +char *watch_get_item(int style) +{ + if (style >= watch_items) { + return NULL; + } + + return watch_res[style]; +} +char *watch_get_root_path() +{ + return RES_PATH; +} + +int watch_set_style(int style) +{ +#if UI_WATCH_RES_ENABLE + /* if (style == 0) { */ + /* style = 1; */ + /* } */ + /* if (style > sizeof(watch_res) / sizeof(watch_res[0])) { */ + if (style >= watch_items) { + return false; + } + watch_style = style; +#endif + return true; +} + + +int watch_get_version(char *watch_item, char *version) +{ + char *sty_suffix = ".sty"; + char *json_suffix = ".json"; + u32 tmp_strlen; + char tmp_name[64]; + u32 sty_strlen; + FILE *file; + /* char *version; */ + char *tver; + u32 i; + + if (watch_item == NULL) { + return -1; + } + + sty_strlen = strlen(sty_suffix); + tmp_strlen = strlen(watch_item); + strcpy(tmp_name, watch_item); + strcpy(&tmp_name[tmp_strlen - sty_strlen], json_suffix); + tmp_name[tmp_strlen - sty_strlen + strlen(json_suffix)] = '\0'; + printf("version name %s\n", tmp_name); + file = res_fopen(tmp_name, "r"); + if (!file) { + printf("open_jsonfile fail %s\n", tmp_name); + return -1; + } + memset(tmp_name, 0, sizeof(tmp_name)); + res_fread(file, tmp_name, sizeof(tmp_name)); + res_fclose(file); + /* printf("json buf : %s\n", tmp_name); */ + tmp_name[26] = '\0'; + /* version = &tmp_name[22]; */ + strcpy(version, &tmp_name[22]); + + return 0; +} + + +int watch_version_juge(char *watch_item) +{ + char *sty_suffix = ".sty"; + char *json_suffix = ".json"; + u32 tmp_strlen; + char tmp_name[64]; + u32 sty_strlen; + FILE *file; + char *version; + char *tver; + u32 i; + + if (watch_item == NULL) { + return -1; + } + + sty_strlen = strlen(sty_suffix); + tmp_strlen = strlen(watch_item); + strcpy(tmp_name, watch_item); + strcpy(&tmp_name[tmp_strlen - sty_strlen], json_suffix); + tmp_name[tmp_strlen - sty_strlen + strlen(json_suffix)] = '\0'; + printf("version name %s\n", tmp_name); + file = res_fopen(tmp_name, "r"); + if (!file) { + printf("open_jsonfile fail %s\n", tmp_name); + return -1; + } + memset(tmp_name, 0, sizeof(tmp_name)); + res_fread(file, tmp_name, sizeof(tmp_name)); + res_fclose(file); + /* printf("json buf : %s\n", tmp_name); */ + tmp_name[26] = '\0'; + version = &tmp_name[22]; + /* printf("ve %s\n", version); */ + + for (i = 0; i < strlen(WATCH_VERSION_LIST); i += 5) { + tver = &WATCH_VERSION_LIST[i]; + /* printf("ver %s, %d\n", tver, strlen(version)); */ + if (strncmp(version, tver, strlen(version)) == 0) { + return 0; + } + } + + printf("juge watch version err\n"); + + return -1; +} + + +int watch_set_style_by_name(char *name) +{ + u32 i; + u32 ret; + printf("watch find %s\n", name); + + for (i = 0; i < watch_items; i++) { + /* printf("watch finding %s\n", watch_res[i]); */ + if (strncmp(name, watch_res[i], strlen(name)) == 0) { + printf("find watch style %d, %s\n\n\n", i, watch_res[i]); + + ret = watch_version_juge(watch_res[i]); + if (ret != 0) { + break; + } + watch_set_style(i); + return 0; + } + } + + printf("watch find faile\n"); + return -1; +} + + +int watch_get_style() +{ + return watch_style; +} + +int watch_get_items_num() +{ + return watch_items; +} + +char *watch_get_cur_path() +{ + char path[16]; + u8 i; + char *tmp = &watch_res[watch_style][strlen(RES_PATH)]; + + path[0] = '/'; + for (i = 0; i < 15; i++) { + if (tmp[i] == '/') { + break; + } + path[i + 1] = tmp[i]; + putchar(tmp[i]); + } + path[i + 1] = '\0'; + + ASCII_ToUpper(path, strlen(path)); + /* printf("cur : %s, %s, %d\n", tmp, path, i); */ + + /* return watch_res[watch_style]; */ + return path; +} + +int watch_get_cur_path_len() +{ + return strlen(watch_get_cur_path()) + 1; + + /* char *path = watch_res[watch_style]; */ + /* u32 i; */ + + /* for (i = strlen(path) - 1; i > 0; i--) { */ + /* if (path[i] == '/') { */ + /* break; */ + /* } */ + /* } */ + + /* return i + 1; */ +} + + +int watch_add_item(char *s) +{ + char *new_item = NULL; + /* char watch_name[16]; */ + u32 len; + char *suffix = ".sty"; + + + char *root_path = RES_PATH; + char watch[64]; + + ASSERT(((strlen(s) + strlen(root_path) + 1) < sizeof(watch)), "err name3 %s\n", s); + /* if ((strlen(s) + strlen(root_path) + 1) >= sizeof(watch)) { */ + /* printf("err name3 %s\n", s); */ + /* while (1); */ + /* } */ + + ASCII_ToLower(s, strlen(s)); + strcpy(watch, root_path); + strcpy(&watch[strlen(root_path)], &s[1]); + s = watch; + + printf("watch_path %s\n", s); + + ASSERT(((watch_items + 1) < WATCH_ITEMS_LIMIT), "watch items overflow %d\n\n\n\n", watch_items); + /* if ((watch_items + 1) >= WATCH_ITEMS_LIMIT) { */ + /* printf("watch items overflow %d\n\n\n\n", watch_items); */ + /* while (1); */ + /* } */ + len = strlen(s) - strlen(RES_PATH); + /* printf("test len %d, %d, %d, %s, %s\n", strlen(s), strlen(RES_PATH), len, RES_PATH, s, s[len]); */ + + /* strcpy(watch_name, &s[strlen(s) - len]); */ + /* printf("end str %s\n", watch_name); */ + + new_item = malloc(strlen(s) + 1 + len + strlen(suffix) + 1); + if (new_item == NULL) { + printf("watch add item fail\n"); + return -1; + } + strcpy(new_item, s); + new_item[strlen(s)] = '/'; + strcpy(&new_item[strlen(s) + 1], &s[strlen(s) - len]); + strcpy(&new_item[strlen(s) + 1 + len], suffix); + new_item[strlen(s) + 1 + len + strlen(suffix)] = '\0'; + + watch_res[watch_items] = new_item; + watch_items++; + + printf("watch add item succ %d, %s\n", watch_items, new_item); + + return 0; +} + +int watch_del_item(char *s) +{ + u32 i; + char *item; + u32 cur_items = watch_items; + + char *root_path = RES_PATH; + char watch[64]; + char *cur_watch = watch_res[watch_style]; + + ASSERT(((strlen(s) + strlen(root_path) + 1) < sizeof(watch)), "err name5 %s\n", s); + /* if ((strlen(s) + strlen(root_path) + 1) >= sizeof(watch)) { */ + /* printf("err name5 %s\n", s); */ + /* while (1); */ + /* } */ + ASCII_ToLower(s, strlen(s)); + strcpy(watch, root_path); + strcpy(&watch[strlen(root_path)], &s[1]); + s = watch; + + printf("watch_path %s\n", s); + + if (watch_items <= 2) { + return -1; + } + + for (i = 0; i < cur_items; i++) { + if (strncmp(s, watch_res[i], strlen(s)) == 0) { + item = watch_res[i]; + watch_res[i] = NULL; + free(item); + watch_items--; + + watch_bgp_related[i] = NULL; + break; + } + } + + for (; i < cur_items; i++) { + if (watch_res[i + 1] != NULL) { + watch_res[i] = watch_res[i + 1]; + + watch_bgp_related[i] = watch_bgp_related[i + 1]; + } else { + watch_res[i] = NULL; + + watch_bgp_related[i] = NULL; + break; + } + } + + for (i = 0; i < watch_items; i++) { + if (cur_watch == watch_res[i]) { + printf("del set style %d, %s\n", i, watch_res[i]); + watch_set_style(i); + break; + } + } + if (i == watch_items) { + printf("end style\n"); + watch_set_style(0); + } + + /* watch_mem_bgp_related(); */ + + for (i = 0; i < watch_items; i++) { + printf("cur watch item %d, %s\n", watch_items, watch_res[i]); + } + + return 0; +} + +void watch_select_mem() +{ +#if UI_WATCH_RES_ENABLE + syscfg_write(VM_WATCH_SELECT, &watch_style, sizeof(watch_style)); +#endif +} + +extern void virfat_flash_get_dirinfo(void *file_buf, u32 *file_num); +int watch_set_init() +{ +#if UI_WATCH_RES_ENABLE + u32 i, j; + u32 len; + u32 file_num; + char *fname_buf; + char *suffix = ".sty"; + u8 root_path_len = strlen(RES_PATH); + u8 suffix_len = strlen(suffix); + u8 fname_len; + char *fname; + + + for (i = 0; i < WATCH_ITEMS_LIMIT; i++) { + if (watch_res[i] != NULL) { + free(watch_res[i]); + watch_res[i] = NULL; + } + } + watch_style = 0; + watch_items = 0; + + + for (i = 0; i < BGP_ITEMS_LIMIT; i++) { + if (watch_bgp[i]) { + free(watch_bgp[i]); + watch_bgp[i] = NULL; + } + } + watch_bgp_items = 0; + + + virfat_flash_get_dirinfo(NULL, &file_num); + + fname_buf = zalloc(file_num * 12); + /* ASSERT((fname_buf != NULL), "fname_buf zalloc faile\n"); */ + if (fname_buf == NULL) { + printf("fname_buf zalloc faile %d\n", file_num); + /* while (1); */ + return -1; + } + + virfat_flash_get_dirinfo(fname_buf, &file_num); + + /* printf("fnum %d\n", file_num); */ + /* ASSERT((file_num < WATCH_ITEMS_LIMIT), "file num overflow %d\n", file_num); */ + /* if (file_num >= WATCH_ITEMS_LIMIT) { */ + if (file_num >= BGP_ITEMS_LIMIT) { + printf("file num overflow %d\n", file_num); + /* while (1); */ + return -1; + } + + for (i = 0; i < file_num; i++) { + fname = &fname_buf[i * 12]; + for (j = 0; j < 12; j++) { + /* printf("j %x, %x\n", j, fname[j]); */ + if (fname[j] == ' ') { + fname[j] = '\0'; + break; + } + } + /* ASSERT((j != 12), "\n\n\n\nfname overflow\n\n\n\n\n"); */ + if (j == 12) { + printf("\n\n\n\nfname overflow\n\n\n\n\n"); + /* while (1); */ + return -1; + } + fname_len = strlen(fname); + ASCII_ToLower(fname, fname_len); + //printf("fname %d, %d, %s\n", j, fname_len, fname); + /* if (strncmp(fname, "watch", strlen("watch")) != 0) { */ + /* continue; */ + /* } */ + + if (strncmp(fname, "watch", strlen("watch")) == 0) { + len = root_path_len + fname_len + 1 + fname_len + suffix_len; + watch_res[watch_items] = malloc(len + 1); + /* ASSERT((watch_res[watch_items] != NULL), "\n\nmalloc watch list err\n\n"); */ + if (watch_res[watch_items] == NULL) { + printf("\n\nmalloc watch list err\n\n"); + /* while (1); */ + return -1; + } + strcpy(watch_res[watch_items], RES_PATH); + strcpy(&watch_res[watch_items][root_path_len], fname); + watch_res[watch_items][root_path_len + fname_len] = '/'; + strcpy(&watch_res[watch_items][root_path_len + fname_len + 1], fname); + strcpy(&watch_res[watch_items][root_path_len + fname_len + 1 + fname_len], suffix); + watch_res[watch_items][len] = '\0'; + + printf("watch list : %s, %d, %d\n", watch_res[watch_items], watch_items, len); + + watch_items++; + + } else if (strncmp(fname, "bgp_w", strlen("bgp_w")) == 0) { + watch_bgp_add(fname); + } + + } + + + free(fname_buf); + + if (watch_bgp_related_init() != 0) { + printf("bgp_related_init fail\n"); + } else { + printf("bgp_related_init succ\n"); + } + + if ((sizeof(watch_style) != syscfg_read(VM_WATCH_SELECT, &watch_style, sizeof(watch_style))) || (watch_style >= watch_items)) { + watch_style = 0; + } + + + /* if (wmem_test_flag == 1) { */ + /* watch_bgp_set_related("bgp_w0", 0); */ + /* watch_bgp_set_related("bgp_w2", 1); */ + /* watch_bgp_set_related("bgp_w1", 2); */ + /* watch_bgp_set_related("bgp_w0", 3); */ + /* watch_bgp_set_related("bgp_w1", 5); */ + /* } */ + + + /* watch_bgp_add("dial0.bin"); */ + /* watch_bgp_add("dial1.bin"); */ + /* watch_bgp_add("dial2.bin"); */ + + + /* watch_bgp_del("dial1.bin"); */ + + /* watch_bgp_set_related("dial0.bin", 0); */ + /* watch_bgp_set_related("dial2.bin", 1); */ + /* watch_bgp_set_related("dial1.bin", 2); */ + /* watch_bgp_set_related("dial2.bin", 3); */ + /* watch_bgp_set_related("dial1.bin", 4); */ + /* watch_bgp_set_related("dial0.bin", 5); */ + +#endif + + return 0; +} + + + + + + + +AT_UI_RAM +static void *br23_load_widget_info(void *__head, u8 page) +{ + struct ui_file_head head ALIGNED(4); + static union ui_control_info info ALIGNED(4) = {0}; + static const int rotate[] = {0, 90, 180, 270}; + static int last_page = -1; + int head_len; + int retry = 10; + u32 offset; + u32 _head = ((u32)__head) & 0xffff; + + + if ((((u32)__head >> 29) & 0x7)) { + if ((((u32)__head >> 29) & 0x7) == 1) { + /* printf("%s \n",watch_res[watch_style]); */ + ui_set_sty_path_by_pj_id(1, watch_res[watch_style]); + /* printf(" >>>>>>>>%s %d %x\n",__FUNCTION__,__LINE__,(int)__head >> 29); */ + } + ui_file = ui_load_sty_by_pj_id((((u32)__head >> 29) & 0x7)); + + } else { + ui_file = ui_file1; + } + + if (!_head) { + struct ui_style style = {0}; + +#if UI_WATCH_RES_ENABLE + int load_style = 0; + if (last_page == -1) { //第一次上电未初始化 + if (page == 0) { //表盘界面 + style.file = watch_res[watch_style]; + } else {//其他界面 + style.file = RES_PATH"JL/JL.sty"; + } + load_style = 1; + } else if ((page == 0) && (last_page == 0)) { // 表盘 -> 表盘 + style.file = watch_res[watch_style]; + load_style = 1; + } else if ((page == 0) && (last_page > 0)) { //其他 -> 表盘 + style.file = watch_res[watch_style]; + load_style = 1; + } else if ((page > 0) && (last_page == 0)) {//表盘 -> 其他 + style.file = RES_PATH"JL/JL.sty"; + load_style = 1; + } + + last_page = page; +#if UI_UPGRADE_RES_ENABLE//升级模式加载资源 + if (app_get_curr_task() == APP_WATCH_UPDATE_TASK || + app_get_curr_task() == APP_SMARTBOX_ACTION_TASK) { + ui_set_sty_path_by_pj_id(1, NULL); + style.file = UPGRADE_PATH"upgrade.sty"; + load_style = 1; + last_page = -1;//下次能重新加载资源 + if (page) { + printf("NOW IS UPGRADE MODE ,CAN NOT SHOW OTHER PAGE...\n"); + page = 0; + } + } +#endif + +#else + int load_style = 1; + last_page = page; +#endif + + if (load_style && platform_api->load_style) { + if (platform_api->load_style(&style)) { + return NULL; + } + load_style = 0; + } + if (!ui_file) { + return NULL; + } + + /* last_page = page; */ + res_fseek(ui_file, 0, SEEK_SET); + res_fread(ui_file, &head, sizeof(struct ui_file_head)); + ui_rotate = rotate[head.rotate]; + ui_core_set_rotate(ui_rotate); + switch (head.rotate) { + case 1: /* 旋转90度 */ + ui_hori_mirror = true; + ui_vert_mirror = false; + break; + case 3:/* 旋转270度 */ + ui_hori_mirror = false; + ui_vert_mirror = true; + break; + default: + ui_hori_mirror = false; + ui_vert_mirror = false; + break; + } + if (page != (u8) - 1) { + res_fseek(ui_file, sizeof(struct ui_file_head) + sizeof(struct window_head)*page, SEEK_SET); + res_fread(ui_file, &__this->window_offset, sizeof(__this->window_offset)); + } + } + + ASSERT((u32)_head <= ui_file_len, ",_head invalid! _head : 0x%x ui_file_len : 0x%x\n", (u32)_head, ui_file_len); + + if ((u32)_head > ui_file_len) { + return NULL; + } + + if ((u32)__head >= 0x10000) { + page = ((u32)__head >> 22) & 0x7f; + res_fseek(ui_file, sizeof(struct ui_file_head) + sizeof(struct window_head)*page, SEEK_SET); + res_fread(ui_file, &offset, sizeof(__this->window_offset)); + } else { + offset = __this->window_offset; + } + + res_fseek(ui_file, offset + (u32)_head, SEEK_SET); + if ((u32)_head == 0) { + res_fread(ui_file, &info, sizeof(struct window_info)); + } else { + res_fread(ui_file, &info.head, sizeof(struct ui_ctrl_info_head)); + head_len = info.head.len - sizeof(struct ui_ctrl_info_head); + if ((head_len > 0) && (head_len <= sizeof(union ui_control_info))) { + res_fread(ui_file, &((u8 *)&info)[sizeof(struct ui_ctrl_info_head)], head_len); + } + } + + return &info; +} + +AT_UI_RAM +static void *br23_load_css(u8 page, void *_css) +{ + u32 rets; + __asm__ volatile("%0 = rets":"=r"(rets)); + + + static struct element_css1 css ALIGNED(4) = {0}; + u32 offset; + + + /* printf(" >>>>>>>>%s %d %x %x\n",__FUNCTION__,__LINE__,((u32)_css) >> 29,rets); */ + if ((((u32)_css >> 29) & 0x7)) { + ui_file = ui_load_sty_by_pj_id((((u32)_css >> 29) & 0x7)); + } else { + ui_file = ui_file1; + } + + /* printf(" >>>>>>>>%s %d file = %x\n",__FUNCTION__,__LINE__,ui_file); */ + + if ((u32)_css >= 0x10000) { + /* offset = ((u32)_css) >> 16; */ + page = ((u32)_css >> 22) & 0x7f; + res_fseek(ui_file, sizeof(struct ui_file_head) + sizeof(struct window_head)*page, SEEK_SET); + res_fread(ui_file, &offset, sizeof(offset)); + } else { + res_fseek(ui_file, sizeof(struct ui_file_head) + sizeof(struct window_head)*page, SEEK_SET); + res_fread(ui_file, &offset, sizeof(offset)); + /* offset = __this->window_offset; */ + } + ASSERT((u32)_css <= ui_file_len, ", _css invalid! _css : 0x%x , ui_file_len : 0x%x\n", _css, ui_file_len); + + + res_fseek(ui_file, offset/* __this->window_offset */ + ((u32)_css & 0xffff), SEEK_SET); + res_fread(ui_file, &css, sizeof(struct element_css1)); + + return &css; +} + +AT_UI_RAM +static void *br23_load_image_list(u8 page, void *_list) +{ + u16 image[32] ALIGNED(4); + static struct ui_image_list_t list ALIGNED(4) = {0}; + int retry = 10; + u32 offset; + + /* printf(" >>>>>>>>%s %d %x\n",__FUNCTION__,__LINE__,(int)_list >> 29); */ + if ((((u32)_list >> 29) & 0x7)) { + ui_file = ui_load_sty_by_pj_id((((u32)_list >> 29) & 0x7)); + } else { + ui_file = ui_file1; + } + if ((u32)_list >= 0x10000) { + /* offset = ((u32)_list) >> 16; */ + page = ((u32)_list >> 22) & 0x7f; + res_fseek(ui_file, sizeof(struct ui_file_head) + sizeof(struct window_head)*page, SEEK_SET); + res_fread(ui_file, &offset, sizeof(__this->window_offset)); + } else { + /* offset = __this->window_offset; */ + res_fseek(ui_file, sizeof(struct ui_file_head) + sizeof(struct window_head)*page, SEEK_SET); + res_fread(ui_file, &offset, sizeof(offset)); + } + + if ((u32)_list == 0) { + return NULL; + } + + ASSERT((u32)_list <= ui_file_len, ", _list invalid! _list : 0x%x, ui_file_len : 0x%x\n", (u32)_list, ui_file_len); + + do { + memset(&list, 0x00, sizeof(struct ui_image_list)); + + + res_fseek(ui_file, offset/* __this->window_offset */ + ((u32)_list & 0xffff), SEEK_SET); + res_fread(ui_file, &list.num, sizeof(list.num)); + if (list.num == 0) { + printf("list.num : %d\n", list.num); + return NULL; + } + if (list.num < 32) { + res_fread(ui_file, image, list.num * sizeof(list.image[0])); + memcpy(list.image, image, list.num * sizeof(list.image[0])); + } else { + printf("list.num = %d\n", list.num); + printf("load_image_list error,retry %d!\n", retry); + if (retry == 0) { + return NULL; + } + } + } while (retry--); + + return &list; +} + + +AT_UI_RAM +static void *br23_load_text_list(u8 page, void *__list) +{ + u8 buf[16 * 2] ALIGNED(4); + static struct ui_text_list_t _list ALIGNED(4) = {0}; + struct ui_text_list_t *list; + int retry = 10; + int i; + u32 offset; + + + + /* printf(" >>>>>>>>%s %d %x\n",__FUNCTION__,__LINE__,(u32)__list >> 29); */ + if ((((u32)__list >> 29) & 0x7)) { + ui_file = ui_load_sty_by_pj_id((((u32)__list >> 29) & 0x7)); + } else { + ui_file = ui_file1; + } + + + if (!ui_file) { + return NULL; + } + + + if ((u32)__list >= 0x10000) { + /* offset = ((u32)__list) >> 16; */ + page = ((u32)__list >> 22) & 0x7f; + res_fseek(ui_file, sizeof(struct ui_file_head) + sizeof(struct window_head)*page, SEEK_SET); + res_fread(ui_file, &offset, sizeof(__this->window_offset)); + } else { + /* offset = __this->window_offset; */ + res_fseek(ui_file, sizeof(struct ui_file_head) + sizeof(struct window_head)*page, SEEK_SET); + res_fread(ui_file, &offset, sizeof(offset)); + } + + if ((u32)__list == 0) { + return NULL; + } + + ASSERT((u32)__list <= ui_file_len, ", __list invalid! _list : 0x%x, ui_file_len : 0x%x\n", (u32)__list, ui_file_len); + + list = &_list; + do { + memset(list, 0x00, sizeof(struct ui_text_list_t)); + + + res_fseek(ui_file, offset/* __this->window_offset */ + ((u32)__list & 0xffff), SEEK_SET); + res_fread(ui_file, &list->num, sizeof(list->num)); + if (list->num == 0) { + return NULL; + } + if (list->num <= 16) { + res_fread(ui_file, buf, list->num * 2); + for (i = 0; i < list->num; i++) { + ASSERT(buf[2 * i] < 0x100); + list->str[i] = buf[2 * i]; + } + } else { + printf("list->num = %d\n", list->num); + printf("load_text_list error, retry %d!\n", retry); + if (retry == 0) { + return NULL; + } + } + } while (retry--); + return list; +} + + + +static void *br23_load_window(int id) +{ + u8 *ui; + int i; + u32 *ptr; + u16 *ptr_table; + struct ui_file_head head ALIGNED(4); + struct window_head window ALIGNED(4); + int len = sizeof(struct ui_file_head); + int retry; + static const int rotate[] = {0, 90, 180, 270}; + + + if (!ui_file) { + printf("ui_file : 0x%x\n", ui_file); + return NULL; + } + ui_platform_ok(); + + for (retry = 0; retry < set_retry_cnt(); retry++) { + res_fseek(ui_file, 0, SEEK_SET); + res_fread(ui_file, &head, len); + + if (id >= head.window_num) { + return NULL; + } + + res_fseek(ui_file, sizeof(struct window_head)*id, SEEK_CUR); + res_fread(ui_file, &window, sizeof(struct window_head)); + + u16 crc = CRC16(&window, (u32) & (((struct window_head *)0)->crc_data)); + if (crc == window.crc_head) { + ui_rotate = rotate[head.rotate]; + ui_core_set_rotate(ui_rotate); + switch (head.rotate) { + case 1: /* 旋转90度 */ + ui_hori_mirror = true; + ui_vert_mirror = false; + break; + case 3:/* 旋转270度 */ + ui_hori_mirror = false; + ui_vert_mirror = true; + break; + default: + ui_hori_mirror = false; + ui_vert_mirror = false; + break; + } + goto __read_data; + } + } + + return NULL; + +__read_data: + ui = (u8 *)__this->api->malloc(window.len); + if (!ui) { + return NULL; + } + for (retry = 0; retry < set_retry_cnt(); retry++) { + res_fseek(ui_file, window.offset, SEEK_SET); + res_fread(ui_file, ui, window.len); + + u16 crc = CRC16(ui, window.len); + if (crc == window.crc_data) { + goto __read_table; + } + } + + __this->api->free(ui); + return NULL; + +__read_table: + ptr_table = (u16 *)__this->api->malloc(window.ptr_table_len); + if (!ptr_table) { + __this->api->free(ui); + return NULL; + } + for (retry = 0; retry < set_retry_cnt(); retry++) { + res_fseek(ui_file, window.ptr_table_offset, SEEK_SET); + res_fread(ui_file, ptr_table, window.ptr_table_len); + + u16 crc = CRC16(ptr_table, window.ptr_table_len); + if (crc == window.crc_table) { + u16 *offset = ptr_table; + for (i = 0; i < window.ptr_table_len; i += 2) { + ptr = (u32 *)(ui + *offset++); + if (*ptr != 0) { + *ptr += (u32)ui; + } + } + __this->api->free(ptr_table); + return ui; + } + } + + __this->api->free(ui); + __this->api->free(ptr_table); + + return NULL; +} + +static void br23_unload_window(void *ui) +{ + if (ui) { + __this->api->free(ui); + } +} + + +static int br23_load_style(struct ui_style *style) +{ + int err; + int i, j; + int len; + struct vfscan *fs; + char name[64]; + char style_name[16]; + static char cur_style = 0xff; + + + if (!style->file && cur_style == 0) { + return 0; + } + + if (ui_file1) { + fclose(ui_file1); + ui_file1 = NULL; + } + + if (style->file == NULL) { + cur_style = 0; + err = open_resource_file(); + if (err) { + return -EINVAL; + } +#if 0 + fs = fscan("mnt/spiflash/res", "-t*.sty"); + if (!fs) { + printf("open mnt/spiflash/res fail!\n"); + return -EFAULT; + } + ui_file1 = fselect(fs, FSEL_FIRST_FILE, 0); + if (!ui_file1) { + fscan_release(fs); + return -ENOENT; + } + len = fget_name(ui_file1, (u8 *)name, 16); + if (len) { + style_name[len - 4] = 0; + memcpy(style_name, name, len - 4); + ui_core_set_style(style_name); + } + + fscan_release(fs); +#else + ui_file1 = res_fopen(RES_PATH"JL.sty", "r"); + if (!ui_file1) { + return -ENOENT; + } + ui_file_len = res_flen(ui_file1); + len = 6; + strcpy(style_name, "JL.sty"); + if (len) { + style_name[len - 4] = 0; + ui_core_set_style(style_name); + } +#endif + } else { + cur_style = 1; + ui_file1 = res_fopen(style->file, "r"); + printf("open stylefile %s\n", style->file); + if (!ui_file1) { + return -EINVAL; + } + + + /* if (!ui_file2) { */ + /* ui_file2 = fopen(RES_PATH"sidebar/sidebar.sty", "r"); */ + /* } */ + + ui_file = ui_file1; + + ui_file_len = 0xffffffff;//res_flen(ui_file1); + for (i = 0; style->file[i] != '.'; i++) { + name[i] = style->file[i]; + } + name[i++] = '.'; + name[i++] = 'r'; + name[i++] = 'e'; + name[i++] = 's'; + name[i] = '\0'; + open_resfile(name); + printf("open resfile %s\n", name); + + name[--i] = 'r'; + name[--i] = 't'; + name[--i] = 's'; + open_str_file(name); + printf("open strfile %s\n", name); + name[i++] = 'a'; + name[i++] = 's'; + name[i++] = 'i'; + font_ascii_init(RES_PATH"font/ascii.res"); + printf("open asciifile %s\n", name); + + for (i = strlen(style->file) - 5; i >= 0; i--) { + if (style->file[i] == '/') { + break; + } + } + + for (i++, j = 0; style->file[i] != '\0'; i++) { + if (style->file[i] == '.') { + name[j] = '\0'; + break; + } + name[j++] = style->file[i]; + } + ASCII_ToUpper(name, j); + if (!strncmp(name, "WATCH", strlen("WATCH"))) { + strcpy(name, "DIAL"); + } + err = ui_core_set_style(name); + if (err) { + printf("style_err: %s\n", name); + } + } + + return 0; + +__err2: + close_resfile(); +__err1: + fclose(ui_file1); + ui_file1 = NULL; + + return err; +} + +static int br23_open_draw_context(struct draw_context *dc) +{ + dc->buf_num = 1; + if (__this->lcd->buffer_malloc) { + u8 *buf; + u32 len; + __this->lcd->buffer_malloc(&buf, &len); + dc->buf0 = buf; +#if UI_USED_DOUBLE_BUFFER + dc->buf1 = &buf[len / 2]; + dc->len = len / 2; +#else + dc->buf1 = NULL; + dc->len = len; +#endif + dc->buf = dc->buf0; + /* __this->lcd->buffer_malloc(&dc->buf, &dc->len); */ + } + + if (__this->lcd->get_screen_info) { + __this->lcd->get_screen_info(&__this->info); + dc->width = __this->info.width; + dc->height = __this->info.height; + dc->col_align = __this->info.col_align; + dc->row_align = __this->info.row_align; + dc->lines = dc->len / dc->width / 2; + if (dc->lines > (dc->height / 10)) { + dc->lines = dc->height / 10; + } + printf("dc->width : %d, dc->lines : %d\n", dc->width, dc->lines); + } + switch (__this->info.color_format) { + case LCD_COLOR_RGB565: + if (dc->data_format != DC_DATA_FORMAT_OSD16) { + ASSERT(0, "The color format of layer don't match the lcd driver,page %d please select OSD16!", dc->page); + } + break; + case LCD_COLOR_MONO: + if (dc->data_format != DC_DATA_FORMAT_MONO) { + ASSERT(0, "The color format of layer don't match the lcd driver,page %d please select OSD1!", dc->page); + } + break; + } + if (dc->data_format == DC_DATA_FORMAT_OSD16) { + dc->fbuf_len = __this->info.width * (3 + 3 * dc->lines) + 0x80; + dc->fbuf = (u8 *)__this->api->malloc(dc->fbuf_len); + } else if (dc->data_format == DC_DATA_FORMAT_MONO) { + dc->fbuf_len = __this->info.width * 2; + dc->fbuf = (u8 *)__this->api->malloc(dc->fbuf_len); + } + + return 0; +} + +static int br23_get_draw_context(struct draw_context *dc) +{ +#if UI_USED_DOUBLE_BUFFER + if (dc->buf == dc->buf0) { + dc->buf = dc->buf1; + } else { + dc->buf = dc->buf0; + } +#endif + + dc->disp.left = dc->need_draw.left; + dc->disp.width = dc->need_draw.width; + if (dc->data_format == DC_DATA_FORMAT_OSD16) { + int lines = dc->len / dc->need_draw.width / 2; + + if ((dc->disp.top == 0) && (dc->disp.height == 0)) { + dc->disp.top = dc->need_draw.top; + dc->disp.height = lines > dc->need_draw.height ? dc->need_draw.height : lines; + } else { + dc->disp.top = dc->disp.top + dc->disp.height; + dc->disp.height = lines > (dc->need_draw.top + dc->need_draw.height - dc->disp.top) ? + (dc->need_draw.top + dc->need_draw.height - dc->disp.top) : lines; + } + dc->disp.height = dc->disp.height / dc->row_align * dc->row_align; + } else if (dc->data_format == DC_DATA_FORMAT_MONO) { + dc->disp.top = dc->need_draw.top; + dc->disp.height = dc->need_draw.height; + } + + return 0; +} + +static int br23_put_draw_context(struct draw_context *dc) +{ + if (__this->lcd->set_draw_area) { + __this->lcd->set_draw_area(dc->disp.left, dc->disp.left + dc->disp.width - 1, + dc->disp.top, dc->disp.top + dc->disp.height - 1); + } + + u8 wait = ((dc->need_draw.top + dc->need_draw.height) == (dc->disp.top + dc->disp.height)) ? 1 : 0; + if (__this->lcd->draw) { + if (dc->data_format == DC_DATA_FORMAT_OSD16) { + __this->lcd->draw(dc->buf, dc->disp.height * dc->disp.width * 2, wait); + } else if (dc->data_format == DC_DATA_FORMAT_MONO) { + __this->lcd->draw(dc->buf, __this->info.width * __this->info.height / 8, wait); + } + } + return 0; +} + + +static int br23_set_draw_context(struct draw_context *dc) +{ + return 0; +} + +static int br23_close_draw_context(struct draw_context *dc) +{ + if (__this->lcd->buffer_free) { + __this->lcd->buffer_free(dc->buf); + } + if (dc->fbuf) { + __this->api->free(dc->fbuf); + dc->fbuf = NULL; + dc->fbuf_len = 0; + } + + return 0; +} + +static int br23_invert_rect(struct draw_context *dc, u32 acolor) +{ + int i; + int len; + int w, h; + int color = acolor & 0xffff; + + if (dc->data_format == DC_DATA_FORMAT_MONO) { + color |= BIT(31); + for (h = 0; h < dc->draw.height; h++) { + for (w = 0; w < dc->draw.width; w++) { + if (platform_api->draw_point) { + platform_api->draw_point(dc, dc->draw.left + w, dc->draw.top + h, color); + } + } + } + } + return 0; +} + +static int br23_fill_rect(struct draw_context *dc, u32 acolor) +{ + int i; + int w, h; + u16 color = acolor & 0xffff; + + if (!dc->buf) { + return 0; + } + + if (dc->data_format == DC_DATA_FORMAT_MONO) { + color = (color == UI_RGB565(BGC_MONO_SET)) ? 0xffff : 0x55aa; + + for (h = 0; h < dc->draw.height; h++) { + for (w = 0; w < dc->draw.width; w++) { + if (platform_api->draw_point) { + platform_api->draw_point(dc, dc->draw.left + w, dc->draw.top + h, color); + } + } + } + } else { + u16 color16 = (color >> 8) | ((color & 0xff) << 8); + u32 color32 = (color16 << 16) | color16; + + h = 0; + u32 *p32 = (u32 *)&dc->buf[(dc->draw.top + h - dc->disp.top) * dc->disp.width * 2 + (dc->draw.left - dc->disp.left) * 2]; + u32 *_p32 = p32; + u32 len = dc->draw.width * 2; + if ((u32)p32 % 4) { + u16 *p16 = (u16 *)p32; + *p16++ = color16; + p32 = (u32 *)p16; + len -= 2; + ASSERT((u32)p32 % 4 == 0); + } + + u32 count = len / 4; + while (count--) { + *p32++ = color32; + } + count = (len % 4) / 2; + u16 *p16 = (u16 *)p32; + while (count--) { + *p16++ = color16; + } + + for (h = 1; h < dc->draw.height; h++) { + u32 *__p32 = (u32 *)&dc->buf[(dc->draw.top + h - dc->disp.top) * dc->disp.width * 2 + (dc->draw.left - dc->disp.left) * 2]; + memcpy(__p32, _p32, dc->draw.width * 2); + } + } + + return 0; +} + +static inline void __draw_vertical_line(struct draw_context *dc, int x, int y, int width, int height, int color, int format) +{ + int i, j; + struct rect r = {0}; + struct rect disp = {0}; + + disp.left = x; + disp.top = y; + disp.width = width; + disp.height = height; + if (!get_rect_cover(&dc->draw, &disp, &r)) { + return; + } + + switch (format) { + case DC_DATA_FORMAT_OSD16: + for (i = 0; i < r.width; i++) { + for (j = 0; j < r.height; j++) { + if (platform_api->draw_point) { + platform_api->draw_point(dc, r.left + i, r.top + j, color); + } + } + } + break; + case DC_DATA_FORMAT_MONO: + for (i = 0; i < r.width; i++) { + for (j = 0; j < r.height; j++) { + if (platform_api->draw_point) { + platform_api->draw_point(dc, r.left + i, r.top + j, color); + } + } + } + break; + + } +} + +static inline void __draw_line(struct draw_context *dc, int x, int y, int width, int height, int color, int format) +{ + int i, j; + struct rect r = {0}; + struct rect disp = {0}; + + disp.left = x; + disp.top = y; + disp.width = width; + disp.height = height; + if (!get_rect_cover(&dc->draw, &disp, &r)) { + return; + } + + switch (format) { + case DC_DATA_FORMAT_OSD16: + for (i = 0; i < r.height; i++) { + for (j = 0; j < r.width; j++) { + if (platform_api->draw_point) { + platform_api->draw_point(dc, r.left + j, r.top + i, color); + } + } + } + break; + case DC_DATA_FORMAT_MONO: + for (i = 0; i < r.height; i++) { + for (j = 0; j < r.width; j++) { + if (platform_api->draw_point) { + platform_api->draw_point(dc, r.left + j, r.top + i, color); + } + } + } + break; + } +} + +static int br23_draw_rect(struct draw_context *dc, struct css_border *border) +{ + int err; + int offset; + int color = border->color & 0xffff; + + /* draw_rect_range_check(&dc->draw, map); */ + /* draw_rect_range_check(&dc->rect, map); */ + + if (dc->data_format == DC_DATA_FORMAT_OSD16) { + color = border->color & 0xffff; + } else if (dc->data_format == DC_DATA_FORMAT_MONO) { + color = (color != UI_RGB565(RECT_MONO_CLR)) ? (color ? color : 0xffff) : 0x55aa; + } + + if (border->left) { + if (dc->rect.left >= dc->draw.left && + dc->rect.left <= rect_right(&dc->draw)) { + __draw_vertical_line(dc, dc->draw.left, dc->draw.top, + border->left, dc->draw.height, color, dc->data_format); + } + } + if (border->right) { + if (rect_right(&dc->rect) >= dc->draw.left && + rect_right(&dc->rect) <= rect_right(&dc->draw)) { + __draw_vertical_line(dc, dc->draw.left + dc->draw.width - border->right, dc->draw.top, + border->right, dc->draw.height, color, dc->data_format); + } + } + if (border->top) { + if (dc->rect.top >= dc->draw.top && + dc->rect.top <= rect_bottom(&dc->draw)) { + __draw_line(dc, dc->draw.left, dc->draw.top, + dc->draw.width, border->top, color, dc->data_format); + } + } + if (border->bottom) { + if (rect_bottom(&dc->rect) >= dc->draw.top && + rect_bottom(&dc->rect) <= rect_bottom(&dc->draw)) { + __draw_line(dc, dc->draw.left, dc->draw.top + dc->draw.height - border->bottom, + dc->draw.width, border->bottom, color, dc->data_format); + } + } + + return 0; +} + +__attribute__((always_inline_when_const_args)) +AT_UI_RAM +static u16 get_mixed_pixel(u16 backcolor, u16 forecolor, u8 alpha) +{ + u16 mixed_color; + u8 r0, g0, b0; + u8 r1, g1, b1; + u8 r2, g2, b2; + + if (alpha == 255) { + return (forecolor >> 8) | (forecolor & 0xff) << 8; + } else if (alpha == 0) { + return (backcolor >> 8) | (backcolor & 0xff) << 8; + } + + r0 = ((backcolor >> 11) & 0x1f) << 3; + g0 = ((backcolor >> 5) & 0x3f) << 2; + b0 = ((backcolor >> 0) & 0x1f) << 3; + + r1 = ((forecolor >> 11) & 0x1f) << 3; + g1 = ((forecolor >> 5) & 0x3f) << 2; + b1 = ((forecolor >> 0) & 0x1f) << 3; + + r2 = (alpha * r1 + (255 - alpha) * r0) / 255; + g2 = (alpha * g1 + (255 - alpha) * g0) / 255; + b2 = (alpha * b1 + (255 - alpha) * b0) / 255; + + mixed_color = ((r2 >> 3) << 11) | ((g2 >> 2) << 5) | (b2 >> 3); + + return (mixed_color >> 8) | (mixed_color & 0xff) << 8; +} + +static int br23_read_image_info(struct draw_context *dc, u32 id, u8 page, struct ui_image_attrs *attrs) +{ + struct image_file file; + + if (((u16) - 1 == id) || ((u32) - 1 == id)) { + return -1; + } + + select_resfile(dc->prj); + int err = open_image_by_id(NULL, &file, id, dc->page); + if (err) { + return -EFAULT; + } + attrs->width = file.width; + attrs->height = file.height; + + return 0; +} + +AT_UI_RAM +int line_update(u8 *mask, u16 y, u16 width) +{ + int i; + if (!mask) { + return true; + } + for (i = 0; i < (width + 7) / 8; i++) { + if (mask[y * ((width + 7) / 8) + i]) { + return true; + } + } + return false; +} + + +/* AT_UI_RAM */ +void select_resfile(u8 index); +void select_strfile(u8 index); +static int br23_draw_image(struct draw_context *dc, u32 src, u8 quadrant, u8 *mask) +{ + u8 *pixelbuf; + u8 *temp_pixelbuf; + u8 *alphabuf; + u8 *temp_alphabuf; + struct rect draw_r; + struct rect r = {0}; + struct rect disp = {0}; + struct image_file file; + int h, hh, w; + int buf_offset; + int id; + int page; + FILE *fp; + + if (dc->preview.file) { + fp = dc->preview.file; + id = dc->preview.id; + page = dc->preview.page; + } else { + fp = NULL; + id = src; + page = dc->page; + } + + if (((u16) - 1 == id) || ((u32) - 1 == id)) { + return -1; + } + + draw_r.left = dc->draw.left; + draw_r.top = dc->draw.top; + draw_r.width = dc->draw.width; + draw_r.height = dc->draw.height; + + /* UI_PRINTF("image draw %d, %d, %d, %d\n", dc->draw.left, dc->draw.top, dc->draw.width, dc->draw.height); */ + /* UI_PRINTF("image rect %d, %d, %d, %d\n", dc->rect.left, dc->rect.top, dc->rect.width, dc->rect.height); */ + + select_resfile(dc->prj); + + if (dc->draw_img.en) { + id = dc->draw_img.id; + page = dc->draw_img.page; + } + + int err = open_image_by_id(fp, &file, id, page); + if (err) { + return -EFAULT; + } + + int x = dc->rect.left; + int y = dc->rect.top; + + if (dc->align == UI_ALIGN_CENTER) { + x += (dc->rect.width / 2 - file.width / 2); + y += (dc->rect.height / 2 - file.height / 2); + } else if (dc->align == UI_ALIGN_RIGHT) { + x += dc->rect.width - file.width; + } + + int temp_pixelbuf_len; + int temp_alphabuf_len; + int align; + + if (dc->draw_img.en) { + disp.left = dc->draw_img.x; + disp.top = dc->draw_img.y; + } else { + disp.left = x; + disp.top = y; + } + disp.width = file.width; + disp.height = file.height; + + if (dc->data_format == DC_DATA_FORMAT_MONO) { + pixelbuf = dc->fbuf; + if (get_rect_cover(&draw_r, &disp, &r)) { + int _offset = -1; + for (h = 0; h < r.height; h++) { + if (file.compress == 0) { + int offset = (r.top + h - disp.top) / 8 * file.width + (r.left - disp.left); + if (_offset != offset) { + if (br23_read_image_data(fp, &file, pixelbuf, r.width, offset) != r.width) { + return -EFAULT; + } + _offset = offset; + } + } else { + ASSERT(0, "the compress mode not support!"); + } + + for (w = 0; w < r.width; w++) { + u8 color = (pixelbuf[w] & BIT((r.top + h - disp.top) % 8)) ? 1 : 0; + if (color) { + if (platform_api->draw_point) { + platform_api->draw_point(dc, r.left + w, r.top + h, color); + } + } + } + } + } + } else if (dc->data_format == DC_DATA_FORMAT_OSD16) { + if (get_rect_cover(&draw_r, &disp, &r)) { + u32 alpha_addr = 0; + br23_read_image_data(fp, &file, &alpha_addr, sizeof(alpha_addr), 0); + + if (alpha_addr) { + temp_pixelbuf_len = dc->width * 2 * dc->lines + 0x40 - 8; + temp_alphabuf_len = dc->width * dc->lines + 0x40 - 8; + + buf_offset = 0; + pixelbuf = &dc->fbuf[buf_offset];//2 bytes * line + buf_offset += dc->width * 2; + buf_offset = (buf_offset + 3) / 4 * 4; + alphabuf = &dc->fbuf[buf_offset];//1 bytes * line + buf_offset += dc->width; + buf_offset = (buf_offset + 3) / 4 * 4; + temp_pixelbuf = &dc->fbuf[buf_offset]; + buf_offset += temp_pixelbuf_len; + buf_offset = (buf_offset + 3) / 4 * 4; + temp_alphabuf = &dc->fbuf[buf_offset]; + + } else { + /* temp_pixelbuf_len = dc->width * 3 * dc->lines + 0x80; */ + temp_pixelbuf_len = dc->fbuf_len - dc->width * 2; + + buf_offset = 0; + pixelbuf = &dc->fbuf[buf_offset];//2 bytes * line + buf_offset += dc->width * 2; + buf_offset = (buf_offset + 3) / 4 * 4; + temp_pixelbuf = &dc->fbuf[buf_offset]; + } + + for (h = 0; h < r.height;) { + int rh = r.top + h - disp.top; + int rw = r.left - disp.left; + int vh = rh; + int vw = rw; + if (quadrant == 0) { + ; + } else if (quadrant == 1) { + vh = file.height - (r.top - disp.top + r.height - h); + } else if (quadrant == 2) { + vh = file.height - (r.top - disp.top + r.height - h); + vw = file.width - rw - r.width; + } else { + vw = file.width - rw - r.width; + } + ASSERT(vw >= 0); + ASSERT(vh >= 0); + + struct rle_line *line; + struct rle_line *alpha_line; + u8 *ptemp; + u8 *alpha_ptemp; + int lines; + + if (file.compress == 0) { + int remain = (r.height - h) > (file.height - vh) ? (file.height - vh) : (r.height - h); + int offset = 4 + vh * file.width * 2 + vw * 2; + + br23_read_image_data(fp, &file, &alpha_addr, sizeof(alpha_addr), 0); + if (!alpha_addr) { + lines = dc->fbuf_len / file.width / 2; + } else { + lines = dc->fbuf_len / file.width / 3; + } + lines = (lines > remain) ? remain : lines; + pixelbuf = dc->fbuf; + alphabuf = &dc->fbuf[(lines * file.width * 2 + 3) / 4 * 4]; + + int remain_bytes = 4 + file.width * 2 * file.height - offset; + int read_bytes = remain_bytes > (file.width * 2 * lines) ? file.width * 2 * lines : remain_bytes; + if (br23_read_image_data(fp, &file, pixelbuf, read_bytes, offset) != read_bytes) { + return -EFAULT; + } + if (alpha_addr) { + offset = alpha_addr + vh * file.width + vw; + int remain_bytes = alpha_addr + file.width * file.height - offset; + int read_bytes = remain_bytes > (file.width * lines) ? file.width * lines : remain_bytes; + if (br23_read_image_data(fp, &file, alphabuf, read_bytes, offset) != read_bytes) { + return -EFAULT; + } + } + } else if (file.compress == 1) { + int remain = (r.height - h) > (file.height - vh) ? (file.height - vh) : (r.height - h); + int headlen = sizeof(struct rle_header) + (remain * 2 + 3) / 4 * 4; + + line = (struct rle_line *)temp_pixelbuf; + ptemp = &temp_pixelbuf[headlen]; + memset(line, 0x00, sizeof(struct rle_line)); + + br23_read_image_data(fp, &file, ptemp, sizeof(struct rle_header)*remain, 4 + vh * sizeof(struct rle_header)); + + int i; + struct rle_header *rle = (struct rle_header *)ptemp; + int total_len = 0; + for (i = 0; i < remain; i++) { + if (i == 0) { + line->addr = rle[i].addr; + line->len[i] = rle[i].len; + } else { + line->len[i] = rle[i].len; + } + if ((total_len + rle[i].len) > (temp_pixelbuf_len - headlen)) { + break; + } + total_len += rle[i].len; + line->num ++; + } + br23_read_image_data(fp, &file, ptemp, total_len, 4 + line->addr); + + if (alpha_addr) { + int headlen = sizeof(struct rle_header) + (line->num * 2 + 3) / 4 * 4; + alpha_ptemp = &temp_alphabuf[headlen]; + br23_read_image_data(fp, &file, alpha_ptemp, sizeof(struct rle_header)*line->num, alpha_addr + vh * sizeof(struct rle_header)); + + struct rle_header *rle = (struct rle_header *)alpha_ptemp; + alpha_line = (struct rle_line *)temp_alphabuf; + memset(alpha_line, 0x00, sizeof(struct rle_line)); + int total_len = 0; + for (i = 0; i < line->num; i++) { + if (i == 0) { + alpha_line->addr = rle[i].addr; + alpha_line->len[i] = rle[i].len; + } else { + alpha_line->len[i] = rle[i].len; + } + if ((total_len + rle[i].len) > (temp_alphabuf_len - headlen)) { + break; + } + total_len += rle[i].len; + alpha_line->num ++; + } + + br23_read_image_data(fp, &file, alpha_ptemp, total_len, alpha_addr + alpha_line->addr); + } + } else { + ASSERT(0, "the compress mode not support!"); + } + + u8 *p0 = ptemp; + u8 *p1 = alpha_ptemp; + int line_num; + if (file.compress == 0) { + line_num = lines; + } else { + if (alpha_addr) { + line_num = (line->num > alpha_line->num) ? alpha_line->num : line->num; + } else { + line_num = line->num; + } + } + + int hs; + int he; + int hstep; + + he = h + line_num; + if ((quadrant == 1) || (quadrant == 2)) { + hs = r.height - h - 1; + hstep = -1; + } else { + hs = h; + hstep = 1; + } + + for (hh = 0, h = hs; hh < line_num; hh++, h += hstep) { + if (file.compress == 1) { + if (line_update(mask, r.top + h - dc->disp.top, dc->disp.width)) { + Rle_Decode(p0, line->len[hh], pixelbuf, file.width * 2, vw * 2, r.width * 2, 2); + p0 += line->len[hh]; + if (alpha_addr) { + Rle_Decode(p1, alpha_line->len[hh], alphabuf, file.width, vw, r.width, 1); + p1 += alpha_line->len[hh]; + } + } else { + p0 += line->len[hh]; + p1 += alpha_line->len[hh]; + continue; + } + } + + u16 *pdisp = (u16 *)dc->buf; + u16 *pixelbuf16 = (u16 *)pixelbuf; + + if (!alpha_addr) { + u16 x0 = r.left; + u16 y0 = r.top + h; + int offset = (y0 - dc->disp.top) * dc->disp.width + (x0 - dc->disp.left); + /* if ((offset * 2 + 1) < dc->len) { */ + /* pdisp[offset] = pixel; */ + /* } */ + memcpy(&pdisp[offset], pixelbuf16, r.width * 2); + if (file.compress == 0) { + pixelbuf += file.width * 2; + } + continue; + } + + for (w = 0; w < r.width; w++) { + u16 color, pixel; + u8 alpha = alpha_addr ? alphabuf[w] : 255; + + pixel = color = pixelbuf16[w]; + if (alpha) { + if (platform_api->draw_point) { + int vww = w; + if ((quadrant == 2) || (quadrant == 3)) { + vww = r.width - w - 1; + } + u16 x0 = r.left + vww; + u16 y0 = r.top + h; + + if (alpha < 255) { + u16 backcolor = platform_api->read_point(dc, x0, y0); + pixel = get_mixed_pixel((backcolor >> 8) | (backcolor & 0xff) << 8, (color >> 8) | (color & 0xff) << 8, alpha); + } + + if (mask) { + int yy = y0 - dc->disp.top; + int xx = x0 - dc->disp.left; + if (yy >= dc->disp.height) { + continue; + } + if (xx >= dc->disp.width) { + continue; + } + if (mask[yy * ((dc->disp.width + 7) / 8) + xx / 8] & BIT(xx % 8)) { + int offset = (y0 - dc->disp.top) * dc->disp.width + (x0 - dc->disp.left); + if ((offset * 2 + 1) < dc->len) { + pdisp[offset] = pixel; + } + } + } else { + int offset = (y0 - dc->disp.top) * dc->disp.width + (x0 - dc->disp.left); + if ((offset * 2 + 1) < dc->len) { + pdisp[offset] = pixel; + } + } + } + } + } + + if (file.compress == 0) { + pixelbuf += file.width * 2; + alphabuf += file.width; + } + } + h = he; + } + } + } + + return 0; +} + + +int get_multi_string_width(struct draw_context *dc, u8 *str, int *str_width, int *str_height) +{ + struct image_file file; + u8 *p = str; + int width = 0; + while (*p != 0) { + select_strfile(dc->prj); + if (open_string_pic(&file, *p)) { + return -EINVAL; + } + width += file.width; + p++; + } + *str_width = width; + *str_height = file.height; + + return 0; +} + +struct font_info *text_font_init(u8 init) +{ + static struct font_info *info = NULL; + static int language = 0; + + if (init) { + if (!info || (language != ui_language_get())) { + language = ui_language_get(); + if (info) { + font_close(info); + } + info = font_open(NULL, language); + ASSERT(info, "font_open fail!"); + } + } else { + if (info) { + font_close(info); + info = NULL; + } + } + + return info; +} + +static int br23_show_text(struct draw_context *dc, struct ui_text_attrs *text) +{ + struct rect draw_r; + struct rect r = {0}; + struct rect disp = {0}; + struct image_file file; + + + /* 控件从绝对x,y 转成相对图层的x,y */ + int x = dc->rect.left; + int y = dc->rect.top; + + /* 绘制区域从绝对x,y 转成相对图层的x,y */ + draw_r.left = dc->draw.left; + draw_r.top = dc->draw.top; + draw_r.width = dc->draw.width; + draw_r.height = dc->draw.height; + + if (text->format && !strcmp(text->format, "text")) { + struct font_info *info = text_font_init(true); + + if (info && (FT_ERROR_NONE == (info->sta & (~(FT_ERROR_NOTABFILE | FT_ERROR_NOPIXFILE))))) { + info->disp.map = 0; + info->disp.rect = &draw_r; + info->disp.format = dc->data_format; + if ((dc->data_format == DC_DATA_FORMAT_MONO) && (text->color == UI_RGB565(TEXT_MONO_INV))) { + if (__this->api->fill_rect) { + __this->api->fill_rect(dc, UI_RGB565(BGC_MONO_SET)); + } + } + if (dc->data_format == DC_DATA_FORMAT_OSD16) { + info->disp.color = text->color; + } else if (dc->data_format == DC_DATA_FORMAT_MONO) { + if (text->color == UI_RGB565(TEXT_MONO_INV)) { + info->disp.color = 0x55aa;//清显示 + } else { + info->disp.color = (text->color != UI_RGB565(TEXT_MONO_CLR)) ? (text->color ? text->color : 0xffff) : 0x55aa; + } + } + info->dc = dc; + + info->text_width = draw_r.width; + info->text_height = draw_r.height; + info->flags = text->flags; + /* info->offset = text->offset; */ + int roll = 0;//需要滚动 + int multi_line = 0; + /* FONT_SHOW_MULTI_LINE */ + if (text->encode == FONT_ENCODE_ANSI) { + int width = font_text_width(info, (u8 *)text->str, text->strlen); + int height; + + + if (info->ascpixel.size) { + height = info->ascpixel.size; + } else if (info->pixel.size) { + height = info->pixel.size; + } else { + ASSERT(0, "can't get the height of font."); + } + + if (width > dc->rect.width) { + width = dc->rect.width; + roll = 1; + multi_line = 1; + } + + + if (text->flags & FONT_SHOW_MULTI_LINE) { + height += multi_line * height; + } + + if (height > dc->rect.height) { + height = dc->rect.height; + } + + y += (dc->rect.height / 2 - height / 2); + + if (dc->align == UI_ALIGN_CENTER) { + x += (dc->rect.width / 2 - width / 2); + } else if (dc->align == UI_ALIGN_RIGHT) { + x += (dc->rect.width - width); + } + + if (dc->draw_img.en) {//指定坐标刷新 + x = dc->draw_img.x; + y = dc->draw_img.y; + } + + info->x = x; + info->y = y; + int len = font_textout(info, (u8 *)(text->str + roll * text->offset * 2), text->strlen - roll * text->offset * 2, x, y); + ASSERT(len <= 255); + text->displen = len; + } else if (text->encode == FONT_ENCODE_UNICODE) { + if (FT_ERROR_NONE == (info->sta & ~(FT_ERROR_NOTABFILE | FT_ERROR_NOPIXFILE))) { + if (text->endian == FONT_ENDIAN_BIG) { + info->bigendian = true; + } else { + info->bigendian = false; + } + int width = font_textw_width(info, (u8 *)text->str, text->strlen); + int height; + + if (info->ascpixel.size) { + height = info->ascpixel.size; + } else if (info->pixel.size) { + height = info->pixel.size; + } else { + ASSERT(0, "can't get the height of font."); + } + + if (width > dc->rect.width) { + width = dc->rect.width; + roll = 1; + multi_line = 1; + } + + if (text->flags & FONT_SHOW_MULTI_LINE) { + height += multi_line * height; + } + + + if (height > dc->rect.height) { + height = dc->rect.height; + } + + y += (dc->rect.height / 2 - height / 2); + if (dc->align == UI_ALIGN_CENTER) { + x += (dc->rect.width / 2 - width / 2); + } else if (dc->align == UI_ALIGN_RIGHT) { + x += (dc->rect.width - width); + } + + if (dc->draw_img.en) {//指定坐标刷新 + x = dc->draw_img.x; + y = dc->draw_img.y; + } + + info->x = x; + info->y = y; + int len = font_textout_unicode(info, (u8 *)(text->str + roll * text->offset * 2), text->strlen - roll * text->offset * 2, x, y); + ASSERT(len <= 255); + text->displen = len; + } + } else { + int width = font_textu_width(info, (u8 *)text->str, text->strlen); + int height; + + if (info->ascpixel.size) { + height = info->ascpixel.size; + } else if (info->pixel.size) { + height = info->pixel.size; + } else { + ASSERT(0, "can't get the height of font."); + } + + if (width > dc->rect.width) { + width = dc->rect.width; + } + if (height > dc->rect.height) { + height = dc->rect.height; + } + + y += (dc->rect.height / 2 - height / 2); + if (dc->align == UI_ALIGN_CENTER) { + x += (dc->rect.width / 2 - width / 2); + } else if (dc->align == UI_ALIGN_RIGHT) { + x += (dc->rect.width - width); + } + + if (dc->draw_img.en) {//指定坐标刷新 + x = dc->draw_img.x; + y = dc->draw_img.y; + } + + info->x = x; + info->y = y; + int len = font_textout_utf8(info, (u8 *)text->str, text->strlen, x, y); + ASSERT(len <= 255); + text->displen = len; + } + } + } else if (text->format && !strcmp(text->format, "ascii")) { + char *str; + u32 w_sum; + if (!text->str) { + return 0; + } + if ((u8)text->str[0] == 0xff) { + return 0; + } + + if (dc->align == UI_ALIGN_CENTER) { + w_sum = font_ascii_width_check(text->str); + x += (dc->rect.width / 2 - w_sum / 2); + } else if (dc->align == UI_ALIGN_RIGHT) { + w_sum = font_ascii_width_check(text->str); + x += (dc->rect.width - w_sum); + } + + if (dc->draw_img.en) {//指定坐标刷新 + x = dc->draw_img.x; + y = dc->draw_img.y; + } + + if ((dc->data_format == DC_DATA_FORMAT_MONO) && (text->color == UI_RGB565(TEXT_MONO_INV))) { + if (__this->api->fill_rect) { + __this->api->fill_rect(dc, UI_RGB565(BGC_MONO_SET)); + } + } + str = text->str; + while (*str) { + u8 *pixbuf = dc->fbuf; + int width; + int height; + int color; + font_ascii_get_pix(*str, pixbuf, dc->fbuf_len, &height, &width); + if (dc->data_format == DC_DATA_FORMAT_OSD16) { + color = text->color; + } else if (dc->data_format == DC_DATA_FORMAT_MONO) { + if (text->color == UI_RGB565(TEXT_MONO_INV)) { + color = 0x55aa;//清显示 + } else { + color = (text->color != UI_RGB565(TEXT_MONO_CLR)) ? (text->color ? text->color : 0xffff) : 0x55aa; + } + } + __font_pix_copy(dc, dc->data_format, 0, pixbuf, &draw_r, x, y, height, width, color); + x += width; + str++; + } + } else if (text->format && !strcmp(text->format, "strpic")) { + u16 id = (u8)text->str[0]; + u8 *pixbuf; + int w; + int h; + + if (id == 0xffff) { + return 0; + } + + select_strfile(dc->prj); + if (open_string_pic(&file, id)) { + return 0; + } + + y += (dc->rect.height / 2 - file.height / 2); + if (dc->align == UI_ALIGN_CENTER) { + x += (dc->rect.width / 2 - file.width / 2); + } else if (dc->align == UI_ALIGN_RIGHT) { + x += (dc->rect.width - file.width); + } + + pixbuf = dc->fbuf; + if (!pixbuf) { + return -ENOMEM; + } + + if (dc->draw_img.en) { + x = dc->draw_img.x; + y = dc->draw_img.y; + } + + disp.left = x; + disp.top = y; + disp.width = file.width; + disp.height = file.height; + + if (get_rect_cover(&draw_r, &disp, &r)) { + if ((dc->data_format == DC_DATA_FORMAT_MONO) && (text->color == UI_RGB565(TEXT_MONO_INV))) { + if (__this->api->fill_rect) { + __this->api->fill_rect(dc, UI_RGB565(BGC_MONO_SET)); + } + } + for (h = 0; h < file.height; h += 8) { + if (file.compress == 0) { + int offset = (h / 8) * file.width; + if (br23_read_str_data(&file, pixbuf, file.width, offset) != file.width) { + return -EFAULT; + } + } else { + ASSERT(0, "the compress mode not support!"); + } + int color; + if (dc->data_format == DC_DATA_FORMAT_OSD16) { + color = text->color; + } else if (dc->data_format == DC_DATA_FORMAT_MONO) { + if (text->color == UI_RGB565(TEXT_MONO_INV)) { + color = 0x55aa;//清显示 + } else { + color = (text->color != UI_RGB565(TEXT_MONO_CLR)) ? (text->color ? text->color : 0xffff) : 0x55aa; + } + } + __font_pix_copy(dc, dc->data_format, 0, pixbuf, &r, x, y + h / 8 * 8, 8, file.width, color); + } + } + } else if (text->format && !strcmp(text->format, "mulstr")) { + u16 id = (u8)text->str[0]; + u8 *pixbuf; + int w; + int h; + u8 *p = text->str; + select_strfile(dc->prj); + + if (get_multi_string_width(dc, text->str, &w, &h)) { + return -EINVAL; + } + + y += (dc->rect.height / 2 - h / 2); + if (dc->align == UI_ALIGN_CENTER) { + x += (dc->rect.width / 2 - w / 2); + } else if (dc->align == UI_ALIGN_RIGHT) { + x += (dc->rect.width - w); + } + + while (*p != 0) { + id = *p; + + if (id == 0xffff) { + return 0; + } + + select_strfile(dc->prj); + if (open_string_pic(&file, id)) { + return 0; + } + + + pixbuf = dc->fbuf; + if (!pixbuf) { + return -ENOMEM; + } + + disp.left = x; + disp.top = y; + disp.width = file.width; + disp.height = file.height; + + if (get_rect_cover(&draw_r, &disp, &r)) { + if ((dc->data_format == DC_DATA_FORMAT_MONO) && (text->color == UI_RGB565(TEXT_MONO_INV))) { + if (__this->api->fill_rect) { + __this->api->fill_rect(dc, UI_RGB565(BGC_MONO_SET)); + } + } + for (h = 0; h < file.height; h += 8) { + if (file.compress == 0) { + int offset = (h / 8) * file.width; + if (br23_read_str_data(&file, pixbuf, file.width, offset) != file.width) { + return -EFAULT; + } + } else { + ASSERT(0, "the compress mode not support!"); + } + int color; + if (dc->data_format == DC_DATA_FORMAT_OSD16) { + color = text->color; + } else if (dc->data_format == DC_DATA_FORMAT_MONO) { + if (text->color == UI_RGB565(TEXT_MONO_INV)) { + color = 0x55aa;//清显示 + } else { + color = (text->color != UI_RGB565(TEXT_MONO_CLR)) ? (text->color ? text->color : 0xffff) : 0x55aa; + } + } + __font_pix_copy(dc, dc->data_format, 0, pixbuf, &r, x, y + h / 8 * 8, 8, file.width, color); + } + } + x += file.width; + p++; + } + + } else if (text->format && !strcmp(text->format, "image")) { + u8 *pixelbuf; + u8 *temp_pixelbuf; + u8 *alphabuf; + u8 *temp_alphabuf; + u16 cnt = 0; + u16 id = ((u8)text->str[1] << 8) | (u8)text->str[0]; + u32 w, h; + int ww, hh; + + + if (image_str_size_check(dc, dc->page, text->str, &ww, &hh) != 0) { + return -EFAULT; + } + if (dc->align == UI_ALIGN_CENTER) { + x += (dc->rect.width / 2 - ww / 2); + } else if (dc->align == UI_ALIGN_RIGHT) { + x += (dc->rect.width - ww); + } + y += (dc->rect.height / 2 - hh / 2); + while ((id != 0x00ff) && (id != 0xffff)) { + select_resfile(dc->prj); + if (open_image_by_id(NULL, &file, id, dc->page) != 0) { + return -EFAULT; + } + + disp.left = x; + disp.top = y; + disp.width = file.width; + disp.height = file.height; + + if (dc->data_format == DC_DATA_FORMAT_MONO) { + pixelbuf = dc->fbuf; + if (get_rect_cover(&draw_r, &disp, &r)) { + int _offset = -1; + for (h = 0; h < r.height; h++) { + if (file.compress == 0) { + int offset = (r.top + h - disp.top) / 8 * file.width + (r.left - disp.left); + if (_offset != offset) { + if (br23_read_image_data(NULL, &file, pixelbuf, r.width, offset) != r.width) { + return -EFAULT; + } + _offset = offset; + } + } else { + ASSERT(0, "the compress mode not support!"); + } + for (w = 0; w < r.width; w++) { + u8 color = (pixelbuf[w] & BIT((r.top + h - disp.top) % 8)) ? 1 : 0; + if (color) { + if (platform_api->draw_point) { + u16 text_color; + if (text->color != 0xffffff) { + text_color = (text->color != UI_RGB565(TEXT_MONO_CLR)) ? (text->color ? text->color : 0xffff) : 0x55aa; + } else { + text_color = color; + } + platform_api->draw_point(dc, r.left + w, r.top + h, text_color); + } + } + } + } + } + } else if (dc->data_format == DC_DATA_FORMAT_OSD16) { + int temp_pixelbuf_len = dc->width * 2 * dc->lines + 0x40 - 8; + int temp_alphabuf_len = dc->width * dc->lines + 0x40 - 8; + int buf_offset; + + buf_offset = 0; + pixelbuf = &dc->fbuf[buf_offset];//2 bytes * line + buf_offset += dc->width * 2; + buf_offset = (buf_offset + 3) / 4 * 4; + alphabuf = &dc->fbuf[buf_offset];//1 bytes * line + buf_offset += dc->width; + buf_offset = (buf_offset + 3) / 4 * 4; + temp_pixelbuf = &dc->fbuf[buf_offset]; + buf_offset += temp_pixelbuf_len; + buf_offset = (buf_offset + 3) / 4 * 4; + temp_alphabuf = &dc->fbuf[buf_offset]; + + u32 alpha_addr = 0; + if (get_rect_cover(&draw_r, &disp, &r)) { + for (h = 0; h < r.height;) { + int vh = r.top + h - disp.top; + int vw = r.left - disp.left; + + struct rle_line *line; + struct rle_line *alpha_line; + u8 *ptemp; + u8 *alpha_ptemp; + + if (file.compress == 0) { + int offset = 4 + vh * file.width * 2 + vw * 2; + if (br23_read_image_data(NULL, &file, pixelbuf, r.width * 2, offset) != r.width * 2) { + return -EFAULT; + } + br23_read_image_data(NULL, &file, &alpha_addr, sizeof(alpha_addr), 0); + if (alpha_addr) { + offset = alpha_addr + vh * file.width + vw; + br23_read_image_data(NULL, &file, alphabuf, r.width, offset); + } + } else if (file.compress == 1) { + int remain = (r.height - h) > (file.height - vh) ? (file.height - vh) : (r.height - h); + int headlen = sizeof(struct rle_header) + (remain * 2 + 3) / 4 * 4; + + line = (struct rle_line *)temp_pixelbuf; + ptemp = &temp_pixelbuf[headlen]; + memset(line, 0x00, sizeof(struct rle_line)); + + int rle_header_len = sizeof(struct rle_header) * remain; + br23_read_image_data(NULL, &file, ptemp, rle_header_len, 4 + vh * sizeof(struct rle_header)); + + int i; + struct rle_header *rle = (struct rle_header *)ptemp; + int total_len = 0; + for (i = 0; i < remain; i++) { + if (i == 0) { + line->addr = rle[i].addr; + line->len[i] = rle[i].len; + } else { + line->len[i] = rle[i].len; + } + if ((total_len + rle[i].len) > (temp_pixelbuf_len - headlen)) { + break; + } + total_len += rle[i].len; + line->num ++; + } + + br23_read_image_data(NULL, &file, ptemp, total_len, 4 + line->addr); + + br23_read_image_data(NULL, &file, &alpha_addr, sizeof(alpha_addr), 0); + if (alpha_addr) { + int headlen = sizeof(struct rle_header) + (line->num * 2 + 3) / 4 * 4; + alpha_ptemp = &temp_alphabuf[headlen]; + br23_read_image_data(NULL, &file, alpha_ptemp, sizeof(struct rle_header)*line->num, alpha_addr + vh * sizeof(struct rle_header)); + + struct rle_header *rle = (struct rle_header *)alpha_ptemp; + alpha_line = (struct rle_line *)temp_alphabuf; + memset(alpha_line, 0x00, sizeof(struct rle_line)); + int total_len = 0; + for (i = 0; i < line->num; i++) { + if (i == 0) { + alpha_line->addr = rle[i].addr; + alpha_line->len[i] = rle[i].len; + } else { + alpha_line->len[i] = rle[i].len; + } + if ((total_len + rle[i].len) > (temp_alphabuf_len - headlen)) { + break; + } + total_len += rle[i].len; + alpha_line->num ++; + } + + br23_read_image_data(NULL, &file, alpha_ptemp, total_len, alpha_addr + alpha_line->addr); + } + } else { + ASSERT(0, "the compress mode not support!"); + } + + u8 *p0 = ptemp; + u8 *p1 = alpha_ptemp; + int line_num; + if (file.compress == 0) { + line_num = 1; + } else { + line_num = (line->num > alpha_line->num) ? alpha_line->num : line->num; + } + + for (hh = 0; hh < line_num; hh++, h++) { + if (file.compress == 1) { + Rle_Decode(p0, line->len[hh], pixelbuf, file.width * 2, vw * 2, r.width * 2, 2); + p0 += line->len[hh]; + Rle_Decode(p1, alpha_line->len[hh], alphabuf, file.width, vw, r.width, 1); + p1 += alpha_line->len[hh]; + } + u16 *pdisp = (u16 *)dc->buf; + u16 *pixelbuf16 = (u16 *)pixelbuf; + for (w = 0; w < r.width; w++) { + u16 color, pixel; + u8 alpha = alpha_addr ? alphabuf[w] : 255; + + pixel = color = pixelbuf16[w]; + if (alpha) { + if (platform_api->draw_point) { + int vww = w; + u16 x0 = r.left + vww; + u16 y0 = r.top + h; + + if (alpha < 255) { + u16 backcolor = platform_api->read_point(dc, x0, y0); + pixel = get_mixed_pixel((backcolor >> 8) | (backcolor & 0xff) << 8, (color >> 8) | (color & 0xff) << 8, alpha); + } + + int offset = (y0 - dc->disp.top) * dc->disp.width + (x0 - dc->disp.left); + if ((offset * 2 + 1) < dc->len) { + pdisp[offset] = pixel; + } + } + } + } + } + } + } + } + x += file.width; + cnt += 2; + id = ((u8)text->str[cnt + 1] << 8) | (u8)text->str[cnt]; + } + } + + return 0; +} + + +#include "ui/ui_circle.h" +void ui_draw_circle(struct draw_context *dc, int center_x, int center_y, + int radius_small, int radius_big, int angle_begin, + int angle_end, int color, int percent) +{ + struct circle_info info; + info.center_x = center_x; + info.center_y = center_y; + info.radius_big = radius_big; + info.radius_small = radius_small; + info.angle_begin = angle_begin; + info.angle_end = angle_end; + info.left = dc->draw.left; + info.top = dc->draw.top; + info.width = dc->draw.width; + info.height = dc->draw.height; + + info.x = 0; + info.y = 0; + info.disp_x = dc->disp.left; + info.disp_y = dc->disp.top; + + info.color = color; + info.bitmap_width = dc->disp.width; + info.bitmap_height = dc->disp.height; + info.bitmap_pitch = dc->disp.width * 2; + info.bitmap = dc->buf; + info.bitmap_size = dc->len; + info.bitmap_depth = 16; + + draw_circle_by_percent(&info, percent); +} + +AT_UI_RAM +u32 br23_read_point(struct draw_context *dc, u16 x, u16 y) +{ + u32 pixel; + u16 *pdisp = dc->buf; + if (dc->data_format == DC_DATA_FORMAT_OSD16) { + int offset = (y - dc->disp.top) * dc->disp.width + (x - dc->disp.left); + ASSERT((offset * 2 + 1) < dc->len, "dc->len:%d", dc->len); + if ((offset * 2 + 1) >= dc->len) { + return -1; + } + + pixel = pdisp[offset];//(dc->buf[offset * 2] << 8) | dc->buf[offset * 2 + 1]; + } else { + ASSERT(0); + } + + return pixel; +} + + +__attribute__((always_inline_when_const_args)) +AT_UI_RAM +int br23_draw_point(struct draw_context *dc, u16 x, u16 y, u32 pixel) +{ + if (dc->data_format == DC_DATA_FORMAT_OSD16) { + int offset = (y - dc->disp.top) * dc->disp.width + (x - dc->disp.left); + + /* ASSERT((offset * 2 + 1) < dc->len, "dc->len:%d", dc->len); */ + if ((offset * 2 + 1) >= dc->len) { + return -1; + } + + dc->buf[offset * 2 ] = pixel >> 8; + dc->buf[offset * 2 + 1] = pixel; + } else if (dc->data_format == DC_DATA_FORMAT_MONO) { + /* ASSERT(x < __this->info.width); */ + /* ASSERT(y < __this->info.height); */ + if ((x >= __this->info.width) || (y >= __this->info.height)) { + return -1; + } + + if (pixel & BIT(31)) { + dc->buf[y / 8 * __this->info.width + x] ^= BIT(y % 8); + } else if (pixel == 0x55aa) { + dc->buf[y / 8 * __this->info.width + x] &= ~BIT(y % 8); + } else if (pixel) { + dc->buf[y / 8 * __this->info.width + x] |= BIT(y % 8); + } else { + dc->buf[y / 8 * __this->info.width + x] &= ~BIT(y % 8); + } + } + + return 0; +} + +int br23_open_device(struct draw_context *dc, const char *device) +{ + return 0; +} + +int br23_close_device(int fd) +{ + return 0; +} + +int ui_fill_rect(struct draw_context *dc, int left, int top, int width, int height, u32 acolor) +{ + int i; + int w, h; + u16 color = acolor & 0xffff; + + if (!dc->buf) { + return 0; + } + + struct rect rect; + rect.left = left; + rect.top = top; + rect.width = width; + rect.height = height; + + struct rect cover; + if (!get_rect_cover(&dc->draw, &rect, &cover)) { + return 0; + } + + if (dc->data_format == DC_DATA_FORMAT_MONO) { + color = (color == UI_RGB565(BGC_MONO_SET)) ? 0xffff : 0x55aa; + for (h = 0; h < cover.height; h++) { + for (w = 0; w < cover.width; w++) { + if (platform_api->draw_point) { + platform_api->draw_point(dc, cover.left + w, cover.top + h, color); + } + } + } + } else { +#if 0 + for (h = 0; h < cover.height; h++) { + for (w = 0; w < cover.width; w++) { + if (platform_api->draw_point) { + platform_api->draw_point(dc, cover.left + w, cover.top + h, color); + } + } + } +#else + u16 color16 = (color >> 8) | ((color & 0xff) << 8); + u32 color32 = (color16 << 16) | color16; + + h = 0; + u32 *p32 = (u32 *)&dc->buf[(cover.top + h - dc->disp.top) * dc->disp.width * 2 + (cover.left - dc->disp.left) * 2]; + u32 *_p32 = p32; + u32 len = cover.width * 2; + if ((u32)p32 % 4) { + u16 *p16 = (u16 *)p32; + *p16++ = color16; + p32 = (u32 *)p16; + len -= 2; + ASSERT((u32)p32 % 4 == 0); + } + + u32 count = len / 4; + while (count--) { + *p32++ = color32; + } + count = (len % 4) / 2; + u16 *p16 = (u16 *)p32; + while (count--) { + *p16++ = color16; + } + + for (h = 1; h < cover.height; h++) { + u32 *__p32 = (u32 *)&dc->buf[(cover.top + h - dc->disp.top) * dc->disp.width * 2 + (cover.left - dc->disp.left) * 2]; + memcpy(__p32, _p32, cover.width * 2); + } +#endif + } + + return 0; +} + +int ui_draw_image(struct draw_context *dc, int page, int id, int x, int y) +{ + dc->draw_img.en = true; + dc->draw_img.x = x; + dc->draw_img.y = y; + dc->draw_img.id = id; + dc->draw_img.page = page; + return br23_draw_image(dc, id, 0, NULL); +} + + +int ui_draw_ascii(struct draw_context *dc, char *str, int strlen, int x, int y, int color) +{ + struct ui_text_attrs text = {0}; + text.str = str; + text.format = "ascii"; + text.color = color; + text.strlen = strlen; + text.flags = FONT_DEFAULT; + + dc->draw_img.en = true; + dc->draw_img.x = x; + dc->draw_img.y = y; + + return br23_show_text(dc, &text); +} + +int ui_draw_text(struct draw_context *dc, int encode, int endian, char *str, int strlen, int x, int y, int color) +{ + struct ui_text_attrs text = {0}; + text.str = str; + text.format = "text"; + text.color = color; + text.strlen = strlen; + text.encode = encode; + text.endian = endian; + text.flags = FONT_DEFAULT; + + dc->draw_img.en = true; + dc->draw_img.x = x; + dc->draw_img.y = y; + + return br23_show_text(dc, &text); +} + +int ui_draw_strpic(struct draw_context *dc, int id, int x, int y, int color) +{ + struct ui_text_attrs text = {0}; + u8 strbuf; + + strbuf = id; + text.str = &strbuf; + text.format = "strpic"; + text.color = color; + text.strlen = 0; + text.encode = 0; + text.endian = 0; + text.flags = 0; + + dc->draw_img.en = true; + dc->draw_img.x = x; + dc->draw_img.y = y; + + return br23_show_text(dc, &text); +} + +int ui_draw_set_pixel(struct draw_context *dc, int x, int y, int pixel) +{ + return platform_api->draw_point(dc, x, y, pixel); +} + +u32 ui_draw_get_pixel(struct draw_context *dc, int x, int y) +{ + return platform_api->read_point(dc, x, y); +} + +u16 ui_draw_get_mixed_pixel(u16 backcolor, u16 forecolor, u8 alpha) +{ + return get_mixed_pixel(backcolor, forecolor, alpha); +} + +static const struct ui_platform_api br23_platform_api = { + .malloc = br23_malloc, + .free = br23_free, + + .load_style = br23_load_style, + .load_window = br23_load_window, + .unload_window = br23_unload_window, + + .open_draw_context = br23_open_draw_context, + .get_draw_context = br23_get_draw_context, + .put_draw_context = br23_put_draw_context, + .set_draw_context = br23_set_draw_context, + .close_draw_context = br23_close_draw_context, + + .load_widget_info = br23_load_widget_info, + .load_css = br23_load_css, + .load_image_list = br23_load_image_list, + .load_text_list = br23_load_text_list, + + .fill_rect = br23_fill_rect, + .draw_rect = br23_draw_rect, + .draw_image = br23_draw_image, + .show_text = br23_show_text, + .read_point = br23_read_point, + .draw_point = br23_draw_point, + .invert_rect = br23_invert_rect, + + .read_image_info = br23_read_image_info, + + .open_device = br23_open_device, + .close_device = br23_close_device, + + .set_timer = br23_set_timer, + .del_timer = br23_del_timer, + + .file_browser_open = NULL, + .get_file_attrs = NULL, + .set_file_attrs = NULL, + .show_file_preview = NULL, + .move_file_preview = NULL, + .clear_file_preview = NULL, + .flush_file_preview = NULL, + .open_file = NULL, + .delete_file = NULL, + .file_browser_close = NULL, +}; + + + + +static int open_resource_file() +{ + int ret; + + printf("open_resouece_file...\n"); + + ret = open_resfile(RES_PATH"JL.res"); + if (ret) { + return -EINVAL; + } + ret = open_str_file(RES_PATH"JL.str"); + if (ret) { + return -EINVAL; + } + ret = font_ascii_init(RES_PATH"ascii.res"); + if (ret) { + return -EINVAL; + } + return 0; +} + +int __attribute__((weak)) lcd_get_scrennifo(struct fb_var_screeninfo *info) +{ + info->s_xoffset = 0; + info->s_yoffset = 0; + info->s_xres = 240; + info->s_yres = 240; + + return 0; +} + +int ui_platform_init(void *lcd) +{ + struct rect rect; + struct lcd_info info = {0}; + +#ifdef UI_BUF_CALC + INIT_LIST_HEAD(&buffer_used.list); +#endif + + __this->api = &br23_platform_api; + ASSERT(__this->api->open_draw_context); + ASSERT(__this->api->get_draw_context); + ASSERT(__this->api->put_draw_context); + ASSERT(__this->api->set_draw_context); + ASSERT(__this->api->close_draw_context); + + + __this->lcd = lcd_get_hdl(); + ASSERT(__this->lcd); + ASSERT(__this->lcd->init); + ASSERT(__this->lcd->get_screen_info); + ASSERT(__this->lcd->buffer_malloc); + ASSERT(__this->lcd->buffer_free); + ASSERT(__this->lcd->draw); + ASSERT(__this->lcd->set_draw_area); + ASSERT(__this->lcd->backlight_ctrl); + + if (__this->lcd->init) { + __this->lcd->init(lcd); + } + + if (__this->lcd->backlight_ctrl) { + __this->lcd->backlight_ctrl(true); + } + + if (__this->lcd->get_screen_info) { + __this->lcd->get_screen_info(&info); + } + rect.left = 0; + rect.top = 0; + rect.width = info.width; + rect.height = info.height; + + printf("ui_platform_init :: [%d,%d,%d,%d]\n", rect.left, rect.top, rect.width, rect.height); + + ui_core_init(__this->api, &rect); + + return 0; +} + + + +int ui_style_file_version_compare(int version) +{ + int v; + int len; + struct ui_file_head head; + static u8 checked = 0; + + if (checked == 0) { + if (!ui_file) { + puts("ui version_compare ui_file null!\n"); + ASSERT(0); + return 0; + } + res_fseek(ui_file, 0, SEEK_SET); + len = sizeof(struct ui_file_head); + res_fread(ui_file, &head, len); + printf("style file version is: 0x%x,UI_VERSION is: 0x%x\n", *(u32 *)(head.res), version); + if (*(u32 *)head.res != version) { + puts("style file version is not the same as UI_VERSION !!\n"); + ASSERT(0); + } + checked = 1; + } + return 0; +} + + + + +/* static const char *WATCH_RES_CHECK_LIST[] = { */ +/* RES_PATH"JL/JL.res", */ +/* RES_PATH"watch/watch.res", */ +/* RES_PATH"watch1/watch1.res", */ +/* RES_PATH"watch2/watch2.res", */ +/* RES_PATH"watch3/watch3.res", */ +/* RES_PATH"watch4/watch4.res", */ +/* RES_PATH"watch5/watch5.res", */ +/* }; */ + +/* static const char *WATCH_STR_CHECK_LIST[] = { */ +/* RES_PATH"JL/JL.str", */ +/* RES_PATH"watch/watch.str", */ +/* RES_PATH"watch1/watch1.str", */ +/* RES_PATH"watch2/watch2.str", */ +/* RES_PATH"watch3/watch3.str", */ +/* RES_PATH"watch4/watch4.str", */ +/* RES_PATH"watch5/watch5.str", */ +/* }; */ + +int ui_watch_poweron_update_check() +{ +#if(CONFIG_UI_STYLE == STYLE_JL_WTACH) + //如果上次表盘升级异常,直接进入表盘升级模式等待升级完成 + //加入新标志位的判断,用于升级过程中断电后开机进入升级模式的情况 + if (smartbox_eflash_flag_get() != 0 || + smartbox_eflash_update_flag_get()) { + printf("\n\ngoto watch update mode\n\n"); + + //上电后,发现上一次表盘升级异常,先初始化升级需要的蓝牙相关部分, + //再跳转到升级模式 + + watch_update_over = 2; + app_smartbox_task_prepare(0, SMARTBOX_TASK_ACTION_WATCH_TRANSFER, 0); + /* app_task_switch_to(APP_WATCH_UPDATE_TASK); */ + return -1; + /* while (watch_update_over == 2) { */ + /* os_time_dly(3); */ + /* } */ + /* watch_update_over = 0; */ + } +#endif + return 0; +} + + +int ui_upgrade_file_check_valid() +{ +#if UI_UPGRADE_RES_ENABLE + //简单实现 + //假设升级界面必须存在,调用了该接口证明资源不完整 + //需要进行升级 + smartbox_eflash_flag_set(1);//这个标志的清理需要注意 + return 0; +#endif + return -ENOENT; +} + +int ui_file_check_valid() +{ + +#if UI_WATCH_RES_ENABLE + int ret; + printf("open_resouece_file...\n"); + int i = 0; + FILE *file = NULL; + char *sty_suffix = ".sty"; + char *res_suffix = ".res"; + char *str_suffix = ".str"; + char tmp_name[100]; + /* u32 list_len = sizeof(WATCH_STY_CHECK_LIST) / sizeof(WATCH_STY_CHECK_LIST[0]); */ + u32 list_len; + u32 tmp_strlen; + u32 suffix_len; + + //如果上次表盘升级异常,直接进入表盘升级模式等待升级完成 + if (smartbox_eflash_flag_get() != 0 || + smartbox_eflash_update_flag_get()) { + printf("\n\nneed goto watch update mode\n\n"); + return -EINVAL; + } else { + ret = watch_set_init(); + if (ret != 0) { + return -EINVAL; + } + } + + list_len = watch_items; + + for (i = 0; i < list_len; i++) { + if (file) { + res_fclose(file); + file = NULL; + } + /* file = res_fopen(WATCH_STY_CHECK_LIST[i], "r"); */ + file = res_fopen(watch_res[i], "r"); + if (!file) { + return -ENOENT; + } + } + + + suffix_len = strlen(sty_suffix); + close_resfile(); + for (i = 0; i < list_len; i++) { + + memset(tmp_name, 0, sizeof(tmp_name)); + /* tmp_strlen = strlen(WATCH_STY_CHECK_LIST[i]); */ + /* strcpy(tmp_name, WATCH_STY_CHECK_LIST[i]); */ + tmp_strlen = strlen(watch_res[i]); + strcpy(tmp_name, watch_res[i]); + strcpy(&tmp_name[tmp_strlen - suffix_len], res_suffix); + tmp_name[tmp_strlen - suffix_len + strlen(res_suffix)] = '\0'; + + /* ret = open_resfile(WATCH_RES_CHECK_LIST[i]); */ + ret = open_resfile(tmp_name); + if (ret) { + return -EINVAL; + } + close_resfile(); + } + + + close_str_file(); + for (i = 0; i < list_len; i++) { + + memset(tmp_name, 0, sizeof(tmp_name)); + /* tmp_strlen = strlen(WATCH_STY_CHECK_LIST[i]); */ + /* strcpy(tmp_name, WATCH_STY_CHECK_LIST[i]); */ + tmp_strlen = strlen(watch_res[i]); + strcpy(tmp_name, watch_res[i]); + strcpy(&tmp_name[tmp_strlen - suffix_len], str_suffix); + tmp_name[tmp_strlen - suffix_len + strlen(str_suffix)] = '\0'; + + /* ret = open_str_file(WATCH_STR_CHECK_LIST[i]); */ + ret = open_resfile(tmp_name); + if (ret) { + return -EINVAL; + } + close_str_file(); + } + +#endif + return 0; +} + + +#endif + diff --git a/cpu/br23/ui_driver/lcd_seg/lcd_seg3x9_driver.c b/cpu/br23/ui_driver/lcd_seg/lcd_seg3x9_driver.c new file mode 100644 index 0000000..e929fba --- /dev/null +++ b/cpu/br23/ui_driver/lcd_seg/lcd_seg3x9_driver.c @@ -0,0 +1,603 @@ +#include "includes.h" +#include "app_config.h" + +#include "ui/ui_api.h" +#include "lcd_seg3x9_driver_cfg.h" + +#if TCFG_UI_LCD_SEG3X9_ENABLE + +//#define LCD_SEG3X9_DEBUG_ENABLE +#ifdef LCD_SEG3X9_DEBUG_ENABLE +#define lcd_seg3x9_debug(fmt, ...) printf("[LED_SEG3X9] "fmt, ##__VA_ARGS__) +#else +#define lcd_seg3x9_debug(...) +#endif /* #ifdef LCD_SEG3X9_DEBUG_ENABLE */ + +#define lcd_seg3x9_err_error(fmt, ...) printf("[LCD_SEG3X9 ERR] "fmt, ##__VA_ARGS__) + +struct ui_lcd_seg3x9_env { + u8 init; + LCD_SEG3X9_VAR lcd_seg_var; + const struct lcd_seg3x9_platform_data *user_data; + u32 flash_timer; //500ms亮灭, 周期时钟 +}; + +static struct ui_lcd_seg3x9_env _lcd_seg_env = {0}; +#define __this (&_lcd_seg_env) + +#define JL_LCDC JL_LCD + +#define LED_A BIT(0) +#define LED_B BIT(1) +#define LED_C BIT(2) +#define LED_D BIT(3) +#define LED_E BIT(4) +#define LED_F BIT(5) +#define LED_G BIT(6) +#define LED_H BIT(7) +//数字'0' ~ '9'显示段码表 +static const u8 LCD_SEG_NUMBER_2_SEG[10] = { + (u8)(LED_A | LED_B | LED_C | LED_D | LED_E | LED_F), //'0' + (u8)(LED_B | LED_C), //'1' + (u8)(LED_A | LED_B | LED_D | LED_E | LED_G), //'2' + (u8)(LED_A | LED_B | LED_C | LED_D | LED_G), //'3' + (u8)(LED_B | LED_C | LED_F | LED_G), //'4' + (u8)(LED_A | LED_C | LED_D | LED_F | LED_G), //'5' + (u8)(LED_A | LED_C | LED_D | LED_E | LED_F | LED_G), //'6' + (u8)(LED_A | LED_B | LED_C), //'7' + (u8)(LED_A | LED_B | LED_C | LED_D | LED_E | LED_F | LED_G), //'8' + (u8)(LED_A | LED_B | LED_C | LED_D | LED_F | LED_G), //'9' +}; + +//字母'A' ~ 'Z'显示段码表 +static const u8 LCD_SEG_LARGE_LETTER_2_SEG[26] = { + 0x77, 0x40, 0x39, 0x3f, 0x79, ///user_data->pin_cfg.pin_com[com]); //To CHIP connect + + //SEG -- COM0/1/2 + //IO -- DIE/HD/PD + //COM, SEG + switch (com_index) { + case LCD_COM0: + gpio_set_die(__this->user_data->pin_cfg.pin_seg[seg], value); + break; + case LCD_COM1: + gpio_set_hd0(__this->user_data->pin_cfg.pin_seg[seg], value); + break; + case LCD_COM2: + gpio_set_pull_down(__this->user_data->pin_cfg.pin_seg[seg], value); + break; + default: + break; + } +} + + +static void __lcd_seg3x9_reflash_char(u8 index) +{ + //show char + if (index >= 3) { + return; + } + + if (BIT(index) & __this->lcd_seg_var.bFlashChar) { + return; + } + + for (u8 i = 0; i < 7; i++) { + if (__this->lcd_seg_var.bShowBuff[index] & BIT(i)) { + __lcd_seg3x9_show_segN(lcd_seg3x9_seg2pin[i + index * 7].com_index, + lcd_seg3x9_seg2pin[i + index * 7].seg_index, 1); + } else { + __lcd_seg3x9_show_segN(lcd_seg3x9_seg2pin[i + index * 7].com_index, + lcd_seg3x9_seg2pin[i + index * 7].seg_index, 0); + } + } +} + +static void __lcd_seg3x9_reflash_string() +{ + u8 j = 0; + for (j = 0; j < 3; j++) { + __lcd_seg3x9_reflash_char(j); + } +} + +//刷新icon常亮显示 +static void __lcd_seg3x9_reflash_icon() +{ + //show icon + u8 i = 0; + u8 j = 0; + if (__this->lcd_seg_var.bShowIcon) { + for (j = 0; j < 32; j++) { + if (BIT(j) & __this->lcd_seg_var.bFlashIcon) { + continue; + } + if (BIT(j) & __this->lcd_seg_var.bShowIcon) { + for (i = 0; i < ARRAY_SIZE(lcd_seg3x9_icon_seg2pin); i++) { //lookup icon exist + if (BIT(j) == lcd_seg3x9_icon_seg2pin[i].icon) { + //look up the seg2pin table, set the pin should be output 0 + __lcd_seg3x9_show_segN(lcd_seg3x9_icon_seg2pin[i].seg2pin.com_index, + lcd_seg3x9_icon_seg2pin[i].seg2pin.seg_index, 1); + } else { + __lcd_seg3x9_show_segN(lcd_seg3x9_icon_seg2pin[i].seg2pin.com_index, + lcd_seg3x9_icon_seg2pin[i].seg2pin.seg_index, 0); + } + } + } + } + } +} + + +//刷新icon闪烁显示 +static void __lcd_seg3x9_flash_show_icon(u8 is_on) +{ + //show/off icon + u8 i = 0; + u8 j = 0; + if (__this->lcd_seg_var.bFlashIcon) { + for (j = 0; j < 32; j++) { + if (BIT(j) & __this->lcd_seg_var.bFlashIcon) { + for (i = 0; i < ARRAY_SIZE(lcd_seg3x9_icon_seg2pin); i++) { //lookup icon exist + if (BIT(j) == lcd_seg3x9_icon_seg2pin[i].icon) { + //look up the seg2pin table, set the pin should be output 0 + if (is_on) { + __lcd_seg3x9_show_segN(lcd_seg3x9_icon_seg2pin[i].seg2pin.com_index, + lcd_seg3x9_icon_seg2pin[i].seg2pin.seg_index, 1); + } else { + __lcd_seg3x9_show_segN(lcd_seg3x9_icon_seg2pin[i].seg2pin.com_index, + lcd_seg3x9_icon_seg2pin[i].seg2pin.seg_index, 0); + } + } + } + } + } + } +} + + +static void __lcd_seg3x9_flash_show_char(u8 is_on) +{ + //show/off icon + u8 i = 0; + u8 j = 0; + for (j = 0; j < 3; j++) { + if (__this->lcd_seg_var.bFlashChar & BIT(j)) { + if (is_on) { + for (u8 i = 0; i < 7; i++) { + if (__this->lcd_seg_var.bShowBuff[j] & BIT(i)) { + __lcd_seg3x9_show_segN(lcd_seg3x9_seg2pin[i + j * 7].com_index, + lcd_seg3x9_seg2pin[i + j * 7].seg_index, 1); + } + } + } else { + for (u8 i = 0; i < 7; i++) { + __lcd_seg3x9_show_segN(lcd_seg3x9_seg2pin[i + j * 7].com_index, + lcd_seg3x9_seg2pin[i + j * 7].seg_index, 0); + } + } + } + } +} + +static void __lcd_seg3x9_flash_show_timer_handle(void *priv) +{ + static u8 flash_on = 0; + if (__this->lcd_seg_var.bFlashIcon) { + __lcd_seg3x9_flash_show_icon(flash_on); + } + if (__this->lcd_seg_var.bFlashChar) { + __lcd_seg3x9_flash_show_char(flash_on); + } + flash_on = !flash_on; +} + + + +static void __lcd_seg3x9_reflash_screen() +{ + __lcd_seg3x9_reflash_string(); + __lcd_seg3x9_reflash_icon(); +} + + +static void __lcd_seg3x9_clear_screen() +{ + //clear all + for (u8 i = 0; i < 9; i++) { + gpio_set_die(__this->user_data->pin_cfg.pin_seg[i], 0); + gpio_set_hd0(__this->user_data->pin_cfg.pin_seg[i], 0); + gpio_set_pull_down(__this->user_data->pin_cfg.pin_seg[i], 0); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief lcd_seg 单个字符显示函数 + @param chardata:显示字符 + @return void + @note void __lcd_seg3x9_show_char(u8 chardata) + @ display: + ___ ___ ___ + |___| |___| |___| + |___| |___| |___| + ---0------1------2----> X +*/ +/*----------------------------------------------------------------------------*/ +static void __lcd_seg3x9_show_char(u8 chardata) +{ + if (__this->lcd_seg_var.bCoordinateX >= 3) { + __this->lcd_seg_var.bCoordinateX = 0; //or return + //return ; + } + if ((chardata >= '0') && (chardata <= '9')) { + __this->lcd_seg_var.bShowBuff[__this->lcd_seg_var.bCoordinateX++] = LCD_SEG_NUMBER_2_SEG[chardata - '0']; + } else if ((chardata >= 'a') && (chardata <= 'z')) { + __this->lcd_seg_var.bShowBuff[__this->lcd_seg_var.bCoordinateX++] = LCD_SEG_SMALL_LETTER_2_SEG[chardata - 'a']; + } else if ((chardata >= 'A') && (chardata <= 'Z')) { + __this->lcd_seg_var.bShowBuff[__this->lcd_seg_var.bCoordinateX++] = LCD_SEG_LARGE_LETTER_2_SEG[chardata - 'A']; + } else if (chardata == ':') { + __this->lcd_seg_var.bShowIcon |= LCD_SEG3X9_2POINT; + __this->lcd_seg_var.bFlashIcon &= (~LCD_SEG3X9_2POINT); + } else if (chardata == '.') { + /* __this->lcd_seg_var.bShowIcon |= LCD_SEG_DOT; */ + /* __this->lcd_seg_var.bFlashIcon &= (~LCD_SEG_DOT); */ + } else if (chardata == ' ') { + __this->lcd_seg_var.bShowBuff[__this->lcd_seg_var.bCoordinateX++] = 0; + } else { + __this->lcd_seg_var.bShowBuff[__this->lcd_seg_var.bCoordinateX++] = LED_G; //显示'-' + } + + __lcd_seg3x9_reflash_char(__this->lcd_seg_var.bCoordinateX - 1); +} + +///////////////// API: +void lcd_seg3x9_setX(u8 X) +{ + __this->lcd_seg_var.bCoordinateX = X; +} + +void lcd_seg3x9_clear_string(void) +{ + memset(__this->lcd_seg_var.bShowBuff, 0x00, 4); + __this->lcd_seg_var.bFlashChar = 0; + + lcd_seg3x9_setX(0); + __lcd_seg3x9_reflash_string(); +} + +void lcd_seg3x9_show_char(u8 chardata) +{ + __lcd_seg3x9_show_char(chardata); +} + +void lcd_seg3x9_show_string(u8 *str) +{ + while (*str != '\0') { + __lcd_seg3x9_show_char(*str++); + } +} + +void lcd_seg3x9_show_icon(UI_LCD_SEG3X9_ICON icon) +{ + __this->lcd_seg_var.bShowIcon |= icon; + __this->lcd_seg_var.bFlashIcon &= (~icon); //stop display + __lcd_seg3x9_reflash_icon(); +} + +void lcd_seg3x9_flash_icon(UI_LCD_SEG3X9_ICON icon) +{ + __this->lcd_seg_var.bFlashIcon |= icon; + __this->lcd_seg_var.bShowIcon &= (~icon); //stop display + __lcd_seg3x9_reflash_icon(); +} + +void lcd_seg3x9_flash_char_start(u8 index) +{ + if (index < 3) { + __this->lcd_seg_var.bFlashChar |= BIT(index); + } +} + +void lcd_seg3x9_flash_char_stop(u8 index) +{ + if (index < 3) { + __this->lcd_seg_var.bFlashChar &= ~BIT(index); + } +} + +void lcd_seg3x9_clear_icon(UI_LCD_SEG3X9_ICON icon) +{ + __this->lcd_seg_var.bShowIcon &= (~icon); + __this->lcd_seg_var.bFlashIcon &= (~icon); + __lcd_seg3x9_reflash_icon(); +} + +void lcd_seg3x9_clear_all_icon(void) +{ + __this->lcd_seg_var.bFlashIcon = 0; + __this->lcd_seg_var.bShowIcon = 0; + __lcd_seg3x9_reflash_icon(); +} + +void lcd_seg3x9_show_null(void) +{ + lcd_seg3x9_clear_string(); + lcd_seg3x9_clear_all_icon(); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 字符串显示函数, 默认左对齐, 从x = 0开始显示 + @param *str:字符串的指针 + @return void + @note void lcd_seg_show_string_left(u8 *str) +*/ +/*----------------------------------------------------------------------------*/ +void lcd_seg3x9_show_string_reset_x(u8 *str) +{ + lcd_seg3x9_clear_string(); + while (*str != '\0') { + __lcd_seg3x9_show_char(*str++); + } + __lcd_seg3x9_reflash_screen(); +} + +void lcd_seg3x9_show_string_align_right(u8 *str) +{ + u8 cnt = 0; + u8 *_str = str; + while (*_str++ != '\0') { + cnt++; + } + if (cnt > 3) { + lcd_seg3x9_err_error("show string oversize", __func__); + return; + } + lcd_seg3x9_clear_string(); + lcd_seg3x9_setX(3 - cnt); + while (*str != '\0') { + lcd_seg3x9_show_char(*str++); + } + __lcd_seg3x9_reflash_screen(); +} + +void lcd_seg3x9_show_string_align_left(u8 *str) +{ + lcd_seg3x9_show_string_reset_x(str); +} + +void lcd_seg3x9_show_number(u16 val) +{ + u8 tmp_buf[5] = {0}; + + if (val > 999) { + lcd_seg3x9_show_icon(LCD_SEG3X9_DIGIT1); + } else { + lcd_seg3x9_clear_icon(LCD_SEG3X9_DIGIT1); + } + itoa4(val, tmp_buf); + lcd_seg3x9_show_string_reset_x(&tmp_buf[1]); +} + +//数字显示函数, 高位不显示0 +void lcd_seg3x9_show_number2(u16 val) +{ + u8 i; + u8 tmp_buf[5] = {0}; + + if (val > 999) { + lcd_seg3x9_show_icon(LCD_SEG3X9_DIGIT1); + } else { + lcd_seg3x9_clear_icon(LCD_SEG3X9_DIGIT1); + } + + itoa4(val, tmp_buf); + for (i = 0; i < 2; i++) { + if (tmp_buf[i + 1] != '0') { + break; + } + } + lcd_seg3x9_show_string_align_right((u8 *) & (tmp_buf[i + 1])); +} + +//数字显示函数(追加方式) +void lcd_seg3x9_show_number_add(u16 val) +{ + u8 i; + u8 tmp_buf[5] = {0}; + + if (__this->lcd_seg_var.bCoordinateX == 0) { + if (val > 999) { + lcd_seg3x9_show_icon(LCD_SEG3X9_DIGIT1); + } else { + lcd_seg3x9_clear_icon(LCD_SEG3X9_DIGIT1); + } + } + + itoa4(val, tmp_buf); + for (i = 0; i < 3; i++) { + if (tmp_buf[i] != '0') { + break; + } + } + lcd_seg3x9_show_string((u8 *)&tmp_buf[i]); +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief LCD段码屏初始化 + @param void + @return void + @note void lcd_seg3x9_init(const struct lcd_seg3x9_platform_data *_data) +*/ +/*----------------------------------------------------------------------------*/ +void lcd_seg3x9_init(const struct lcd_seg3x9_platform_data *_data) +{ + if ((__this->init == true) || (_data == NULL)) { + return; + } + memset(__this, 0x00, sizeof(struct ui_lcd_seg3x9_env)); + //CLK_CON1[9:8] + //00b: wclk; + //01b: rtosl_clk; + //10b: lsb_clk; + //11b: lrc_clk; + SFR(JL_CLOCK->CLK_CON1, 8, 2, 0); //LCDC时钟源选择wclk 32k + + JL_LCDC->CON0 = 0; + //板级配置参数 + JL_LCDC->CON0 |= (_data->bias << 2); //[3:2]:0x01:1/2 Bias。0x02:1/3。0x03:1/4 + JL_LCDC->CON0 |= (_data->vlcd << 4); //[6:4]: VLCDS + + //固定配置参数 + JL_LCDC->CON0 |= (1 << 7); //[7]: 帧频率控制, 默认使用 32KHz / 64 + JL_LCDC->CON0 |= (0b01 << 12); //[10:11]: CHGMOD一直用强充电模式 + JL_LCDC->CON0 |= (LCD_SEG3X9_COM_NUMBER_3 << 14); //[15:14]: COM_NUMBER_3; + + //SEG使能 + JL_LCDC->SEG_IOEN0 = 0; + JL_LCDC->SEG_IOEN1 = 0; + + u8 i = 0; + u8 j = 0; + for (j = 0; j < 9; j++) { + for (i = 0; i < ARRAY_SIZE(hw_pin2seg_mapping); i++) { + if (_data->pin_cfg.pin_seg[j] == hw_pin2seg_mapping[i].pin_index) { + if (hw_pin2seg_mapping[i].pin_index >= IO_PORTC_00) { + JL_LCDC->SEG_IOEN1 |= BIT(hw_pin2seg_mapping[i].seg_index - 16); //SEG_PC口允许位 + } else { + JL_LCDC->SEG_IOEN0 |= BIT(hw_pin2seg_mapping[i].seg_index); //SEG_PA口允许位 + } + } + } + } + + JL_LCDC->CON0 |= BIT(0); //LCD_EN + + sys_timer_add(NULL, __lcd_seg3x9_flash_show_timer_handle, 500); + + __this->user_data = _data; + __this->init = true; +} + + +//=================================================================================// +// FOR TEST CODE // +//=================================================================================// +#if 0 +LCD_SEG3X9_PLATFORM_DATA_BEGIN(lcd_seg3x9_test_data) +/* .vlcd = LCD_VOLTAGE_3_3V, */ +/* .bias = LCD_BIAS_1_3, */ +.vlcd = LCD_SEG3X9_VOLTAGE_3_2V, +//.bias = LCD_BIAS_1_3, + .bias = LCD_SEG3X9_BIAS_1_2, + .pin_cfg.pin_com[0] = IO_PORTC_05, + .pin_cfg.pin_com[1] = IO_PORTC_04, + .pin_cfg.pin_com[2] = IO_PORTC_03, + + .pin_cfg.pin_seg[0] = IO_PORTA_00, + .pin_cfg.pin_seg[1] = IO_PORTA_01, + .pin_cfg.pin_seg[2] = IO_PORTA_02, + .pin_cfg.pin_seg[3] = IO_PORTA_03, + .pin_cfg.pin_seg[4] = IO_PORTA_04, + .pin_cfg.pin_seg[5] = IO_PORTA_07, + .pin_cfg.pin_seg[6] = IO_PORTA_12, + .pin_cfg.pin_seg[7] = IO_PORTA_10, + .pin_cfg.pin_seg[8] = IO_PORTA_09, + LCD_SEG3X9_PLATFORM_DATA_END() + + void lcd_seg3x9_test(void) +{ + lcd_seg3x9_init(&lcd_seg3x9_test_data); + static u16 cnt = 0; + lcd_seg3x9_show_number(cnt++); + lcd_seg3x9_show_icon(LCD_SEG3X9_MHZ); +} +#endif + +#endif /* #if TCFG_UI_LCD_SEG3X9_ENABLE */ + diff --git a/cpu/br23/ui_driver/lcd_seg/lcd_seg3x9_driver_cfg.h b/cpu/br23/ui_driver/lcd_seg/lcd_seg3x9_driver_cfg.h new file mode 100644 index 0000000..edccc52 --- /dev/null +++ b/cpu/br23/ui_driver/lcd_seg/lcd_seg3x9_driver_cfg.h @@ -0,0 +1,104 @@ +#ifndef _LCD_SEG3X9_CFG_H_ +#define _LCD_SEG3X9_CFG_H_ + + +#if TCFG_UI_LCD_SEG3X9_ENABLE +//LCD_SEG3X9 真值表选择 +#define UI_LCD_SEG3X9_TRUE_TABLE1 + +enum HW_SEG_INDEX { + LCD_SEG0 = 0, + LCD_SEG1, + LCD_SEG2, + LCD_SEG3, + LCD_SEG4, + LCD_SEG5, + LCD_SEG6, + LCD_SEG7, + LCD_SEG8, + LCD_SEG9, + LCD_SEG10, + LCD_SEG11, + LCD_SEG12, + LCD_SEG13, + LCD_SEG14, + LCD_SEG15, + LCD_SEG16, + LCD_SEG17, + LCD_SEG18, + LCD_SEG19, + LCD_SEG20, + LCD_SEG21, +}; + +enum HW_COM_INDEX { + LCD_COM0 = 0, + LCD_COM1, + LCD_COM2, + LCD_COM3, + LCD_COM4, + LCD_COM5, +}; + +struct lcd_seg2pin { + enum HW_COM_INDEX com_index; + enum HW_SEG_INDEX seg_index; +}; + +struct lcd_seg_icon_seg2pin { + UI_LCD_SEG3X9_ICON icon; + struct lcd_seg2pin seg2pin; +}; + +//=================================================================================// +// LCD段码屏配置 // +//=================================================================================// +#ifdef UI_LCD_SEG3X9_TRUE_TABLE1 + +/*********** 段码屏3x9真值表**************/ +/* 0 1 2 3 4 5 6 7 8 +COM0 1D 1C "1" 2D 2C SD 3D 3C USB +COM1 1E 1G VOL 2E 2G MHz 3E 3G NONE +COM2 1F 1A 1B 2F 2A 2B 3F 3A 3B +*/ +static const struct lcd_seg2pin lcd_seg3x9_seg2pin[] = { + //com_index, seg_index + {LCD_COM0, LCD_SEG1}, //1A + {LCD_COM2, LCD_SEG2}, //1B + {LCD_COM0, LCD_SEG1}, //1C + {LCD_COM0, LCD_SEG0}, //1D + {LCD_COM1, LCD_SEG0}, //1E + {LCD_COM2, LCD_SEG0}, //1F + {LCD_COM1, LCD_SEG1}, //1G + + {LCD_COM2, LCD_SEG4}, //2A + {LCD_COM2, LCD_SEG5}, //2B + {LCD_COM0, LCD_SEG4}, //2C + {LCD_COM0, LCD_SEG3}, //2D + {LCD_COM1, LCD_SEG3}, //2E + {LCD_COM2, LCD_SEG3}, //2F + {LCD_COM1, LCD_SEG4}, //2G + + {LCD_COM2, LCD_SEG7}, //3A + {LCD_COM2, LCD_SEG8}, //3B + {LCD_COM0, LCD_SEG7}, //3C + {LCD_COM0, LCD_SEG6}, //3D + {LCD_COM1, LCD_SEG6}, //3E + {LCD_COM2, LCD_SEG6}, //3F + {LCD_COM1, LCD_SEG7}, //3G +}; + + +static const struct lcd_seg_icon_seg2pin lcd_seg3x9_icon_seg2pin[] = { + //icon com_index, seg_index + {LCD_SEG3X9_USB, {LCD_COM0, LCD_SEG8}}, + {LCD_SEG3X9_SD, {LCD_COM0, LCD_SEG5}}, + {LCD_SEG3X9_VOL, {LCD_COM1, LCD_SEG2}}, + {LCD_SEG3X9_MHZ, {LCD_COM1, LCD_SEG5}}, + {LCD_SEG3X9_DIGIT1, {LCD_COM0, LCD_SEG2}}, +}; + +#endif /* #ifdef UI_LCD_SEG3X9_TRUE_TABLE1 */ + +#endif /* #ifndef _LCD_SEG3X9_CFG_H_ */ +#endif diff --git a/cpu/br23/ui_driver/lcd_spi/lcd_drive.c b/cpu/br23/ui_driver/lcd_spi/lcd_drive.c new file mode 100644 index 0000000..432f00c --- /dev/null +++ b/cpu/br23/ui_driver/lcd_spi/lcd_drive.c @@ -0,0 +1,602 @@ +/* LCD 调试等级, + * 0只打印错误, + * 1打印错误和警告, + * 2全部内容都调试内容打印 */ +#define SPI_LCD_DEBUG_ENABLE 0 + +#include "includes.h" +#include "app_config.h" +#include "ui/ui_api.h" +#include "system/includes.h" +#include "system/timer.h" +#include "asm/spi.h" +#include "clock_cfg.h" +#include "asm/mcpwm.h" + + + +#if (TCFG_UI_ENABLE && (TCFG_SPI_LCD_ENABLE || TCFG_SIMPLE_LCD_ENABLE)) + +#include "ui/ui_sys_param.h" + +/* 选择SPIx模块作为推屏通道,0、1、2 */ +/* 但SPI0通常作为外部falsh使用,一般不用SPI0 */ +#define SPI_MODULE_CHOOSE TCFG_TFT_LCD_DEV_SPI_HW_NUM + +/* 中断使能,一般推屏不需要 */ + +#ifndef LCD_SPI_INTERRUPT_ENABLE +#define LCD_SPI_INTERRUPT_ENABLE 1 +#endif + + +#if LCD_SPI_INTERRUPT_ENABLE +#if SPI_MODULE_CHOOSE == 0 +#define IRQ_SPI_IDX IRQ_SPI0_IDX +#elif SPI_MODULE_CHOOSE == 1 +#define IRQ_SPI_IDX IRQ_SPI1_IDX +#elif SPI_MODULE_CHOOSE == 2 +#define IRQ_SPI_IDX IRQ_SPI2_IDX +#else +#error "error! SPI_MODULE_CHOOSE defien error!" +#endif +#endif + +int clk_get(const char *name); +int clk_set(const char *name, int clk); +void spi_clear_pending(spi_dev spi); +u8 spi_get_pending(spi_dev spi); +void spi_dma_set_addr_for_isr(spi_dev spi, void *buf, u32 len, u8 rw);; +void spi_dma_wait_finish(); +void wdt_clear(); +static int __lcd_backlight_ctrl(u8 on); + +/* 屏幕驱动的接口 */ +extern struct spi_lcd_init dev_drive; +struct lcd_spi_platform_data *spi_dat = NULL; +static int spi_pnd = false; +static u8 backlight_status = 0; +static u8 lcd_sleep_in = 0; +static volatile u8 is_lcd_busy = 0; +#define __this (&dev_drive) + + +#if LCD_SPI_INTERRUPT_ENABLE +/* SPI中断函数 */ +// 注:dma模式在发送数据时内部已经清理中断pnd +__attribute__((interrupt(""))) +static void spi_isr() +{ + if (spi_get_pending(spi_dat->spi_cfg)) { + /* printf("spi_isr\n"); */ + /* spi_clear_pending(spi_dat->spi_cfg); */ + if (is_lcd_busy) { + is_lcd_busy = 0; + } + spi_set_ie(spi_dat->spi_cfg, 0); + } +} +#endif + +static void clock_critical_enter() +{ + +} + +static void clock_critical_exit() +{ + if (spi_dat && spi_dat->spi_cfg) { + spi_set_baud(spi_dat->spi_cfg, spi_get_baud(spi_dat->spi_cfg)); + } +} +CLOCK_CRITICAL_HANDLE_REG(spi_lcd, clock_critical_enter, clock_critical_exit); + +static void spi_init(int spi_cfg) +{ + int err; + // spi gpio init + + err = spi_open(spi_cfg); + if (err < 0) { + lcd_e("open spi falid\n"); + } +#if LCD_SPI_INTERRUPT_ENABLE + // 配置中断优先级,中断函数 + /* spi_set_ie(spi_cfg, 1); */ + request_irq(IRQ_SPI_IDX, 3, spi_isr, 0); +#endif +} + +// io口操作 +void lcd_reset_l() +{ + gpio_direction_output((u32)spi_dat->pin_reset, 0); +} +void lcd_reset_h() +{ + gpio_direction_output((u32)spi_dat->pin_reset, 1); +} +void lcd_cs_l() +{ + gpio_direction_output((u32)spi_dat->pin_cs, 0); +} +void lcd_cs_h() +{ + gpio_direction_output((u32)spi_dat->pin_cs, 1); +} +void lcd_rs_l() +{ + gpio_direction_output((u32)spi_dat->pin_rs, 0); +} +void lcd_rs_h() +{ + gpio_direction_output((u32)spi_dat->pin_rs, 1); +} + +void lcd_bl_l() +{ + gpio_direction_output((u32)spi_dat->pin_bl, 0); +} + +void lcd_bl_h() +{ + gpio_direction_output((u32)spi_dat->pin_bl, 1); +} + + +u8 lcd_bl_io() +{ + return spi_dat->pin_bl; +} + +void spi_dma_wait_finish() +{ + if (spi_pnd) { + while (!spi_get_pending(spi_dat->spi_cfg)) { + wdt_clear(); + } + spi_clear_pending(spi_dat->spi_cfg); + spi_pnd = false; + } +} + +int __spi_dma_send(spi_dev spi, void *buf, u32 len, u8 wait) +{ + int err = 0; + + if (!wait || spi_pnd) { + spi_dma_wait_finish(); + } + spi_dma_set_addr_for_isr(spi_dat->spi_cfg, buf, len, 0); + spi_pnd = true; + asm("csync"); + + if (wait) { + spi_dma_wait_finish(); + } + + return err; +} + +void spi_dma_send_byte(u8 dat) +{ + int err = 0; + u32 _dat __attribute__((aligned(4))) = 0; + + ((u8 *)(&_dat))[0] = dat; + + if (spi_dat) { + err = __spi_dma_send(spi_dat->spi_cfg, &_dat, 1, 1); + } + + if (err < 0) { + lcd_e("spi dma send byte timeout\n"); + } +} + + +u8 lcd_spi_recv_byte() +{ + int err; + int ret; + +#if 0 + ret = spi_recv_byte_for_isr(spi_dat->spi_cfg); + asm("csync"); + spi_pnd = true; + spi_dma_wait_finish(); +#else + ret = spi_recv_byte(spi_dat->spi_cfg, &err); + spi_pnd = false; +#endif + + return ret; +} + +int lcd_spi_send_byte(u8 byte) +{ + int ret; + +#if 0 + spi_send_byte_for_isr(spi_dat->spi_cfg, byte); + asm("csync"); + spi_pnd = true; + spi_dma_wait_finish(); +#else + ret = spi_send_byte(spi_dat->spi_cfg, byte); + spi_pnd = false; +#endif + + return 0; +} + +void lcd_spi_set_bit_mode(int mode) +{ + spi_set_bit_mode(spi_dat->spi_cfg, mode); +} + +void lcd_spi_dma_send_wait(u8 *map, u32 size) +{ + int err = 0; + + if (spi_dat) { + err = __spi_dma_send(spi_dat->spi_cfg, map, size, 1); + } + + if (err < 0) { + lcd_e("spi dma send map timeout\n"); + } + +} + +void spi_dma_send_map(u8 *map, u32 size) +{ + int err = 0; + + if (spi_dat) { + err = __spi_dma_send(spi_dat->spi_cfg, map, size, 0); + } + + if (err < 0) { + lcd_e("spi dma send map timeout\n"); + } + +} + +void spi_dma_recv_data(u8 *buf, u32 size) +{ + int err = 0; + + if (spi_dat) { + err = spi_dma_recv(spi_dat->spi_cfg, buf, size); + } + + if (err < 0) { + lcd_e("spi dma recv timeout\n"); + } +} + + +static void spi_init_code(const InitCode *code, u8 cnt) +{ + u8 i, j; + + for (i = 0; i < cnt; i++) { + if (code[i].cmd == REGFLAG_DELAY) { + extern void wdt_clear(void); + wdt_clear(); + delay2ms(code[i].cnt / 2); + } else { + __this->WriteComm(code[i].cmd); + lcd_d("cmd:%x ", code[i].cmd); + for (j = 0; j < code[i].cnt; j++) { + __this->WriteData(code[i].dat[j]); + lcd_d("%02x ", code[i].dat[j]); + } + lcd_d("\n"); + } + } +} + +static void lcd_dev_init(void *p) +{ + struct ui_devices_cfg *cfg = (struct ui_devices_cfg *)p; + int err = 0; + spi_dat = (struct lcd_spi_platform_data *)cfg->private_data; + ASSERT(spi_dat, "Error! spi io not config"); + lcd_d("spi pin rest:%d, cs:%d, rs:%d, spi:%d\n", spi_dat->pin_reset, spi_dat->pin_cs, spi_dat->pin_rs, spi_dat->spi_cfg); + + + if (spi_dat->pin_reset != -1) { + gpio_direction_output((u32)spi_dat->pin_reset, 1); + } + gpio_direction_output((u32)spi_dat->pin_cs, 1); + gpio_direction_output((u32)spi_dat->pin_rs, 1); + + if (!__this->soft_spi) { + spi_init(spi_dat->spi_cfg); + } + + if (__this->Reset) { // 如果有硬件复位 + __this->Reset(); + } + + if (__this->initcode && __this->initcode_cnt) { + spi_init_code(__this->initcode, __this->initcode_cnt); // 初始化屏幕 + } else if (__this->Init) { + __this->Init(); + } + +} + +static int lcd_init(void *p) +{ + printf("lcd_init ...\n"); + lcd_dev_init(p); + return 0; +} + +static int lcd_get_screen_info(struct lcd_info *info) +{ + info->width = __this->lcd_width; + info->height = __this->lcd_height; + info->color_format = __this->color_format; + info->interface = __this->interface; + info->col_align = __this->column_addr_align; + info->row_align = __this->row_addr_align; + info->bl_status = backlight_status; + ASSERT(info->col_align, " = 0, lcd driver column address align error, default value is 1"); + ASSERT(info->row_align, " = 0, lcd driver row address align error, default value is 1"); + + return 0; +} + + +static int lcd_buffer_malloc(u8 **buf, u32 *size) +{ + *buf = __this->dispbuf; + *size = __this->bufsize; + return 0; +} + +static int lcd_buffer_free(u8 *buf) +{ + return 0; +} + +static int lcd_set_draw_area(u16 xs, u16 xe, u16 ys, u16 ye) +{ + if ((is_lcd_busy == 0x11) || lcd_sleep_in) { + return 0; + } + is_lcd_busy = 1; + spi_set_ie(spi_dat->spi_cfg, 0); + spi_dma_wait_finish(); + __this->SetDrawArea(xs, xe, ys, ye); + /* is_lcd_busy = 0; */ + return 0; +} + +static int lcd_draw(u8 *buf, u32 len, u8 wait) +{ + if ((is_lcd_busy == 0x11) || lcd_sleep_in) { + return 0; + } + /* is_lcd_busy = 1; */ + /* int clk = clk_get("sys"); */ + /* if (clk != 192000000) { */ + /* clk_set("sys", 192000000L); */ + /* } */ + + if (wait) { + __this->WriteMap(buf, len); +#if LCD_SPI_INTERRUPT_ENABLE + spi_set_ie(spi_dat->spi_cfg, 1); +#else + is_lcd_busy = 0; +#endif + } else { + __this->WriteMap(buf, len); + is_lcd_busy = 0; + } + return 0; +} + +static int lcd_draw_gage(u8 *buf, u8 page_star, u8 page_len) +{ + if ((is_lcd_busy == 0x11) || lcd_sleep_in) { + return 0; + } + __this->WritePAGE(buf, page_star, page_len); + is_lcd_busy = 0; + return 0; +} + + + + +static int lcd_clear_screen(u16 color) +{ + int i; + int buffer_lines; + int remain; + int draw_line; + int y; + + if (__this->color_format == LCD_COLOR_RGB565) { + buffer_lines = __this->bufsize / __this->lcd_width / 2; + for (i = 0; i < buffer_lines * __this->lcd_width; i++) { + __this->dispbuf[2 * i] = color >> 8; + __this->dispbuf[2 * i + 1] = color; + } + + y = 0; + remain = __this->lcd_height; + while (remain) { + draw_line = buffer_lines > remain ? remain : buffer_lines; + lcd_set_draw_area(0, __this->lcd_width - 1, y, y + draw_line - 1); + lcd_draw(__this->dispbuf, draw_line * __this->lcd_width * 2, 0); + remain -= draw_line; + y += draw_line; + } + spi_dma_wait_finish(); + } else if (__this->color_format == LCD_COLOR_MONO) { + __this->SetDrawArea(0, -1, 0, -1); + memset(__this->dispbuf, 0x00, __this->lcd_width * __this->lcd_height / 8); + __this->WriteMap(__this->dispbuf, __this->lcd_width * __this->lcd_height / 8); + } else { + ASSERT(0, "the color_format %d not support yet!", __this->color_format); + } + + return 0; +} + +int lcd_backlight_ctrl(u8 on) +{ + while (is_lcd_busy); + + is_lcd_busy = 0x11; + __lcd_backlight_ctrl(on); + is_lcd_busy = 0; + + return 0; +} + +int lcd_sleep_ctrl(u8 enter) +{ + if ((!!enter) == lcd_sleep_in) { + return -1; + } + while (is_lcd_busy); + is_lcd_busy = 0x11; + + if (enter) { + if (__this->EnterSleep) { + __this->EnterSleep(); + } + lcd_sleep_in = true; + } else { + if (__this->ExitSleep) { + __this->ExitSleep(); + } + clock_add_set(LCD_UI_CLK); + lcd_sleep_in = false; + } + + is_lcd_busy = 0; + return 0; +} + +static int __lcd_backlight_ctrl(u8 on) +{ + static u8 first_power_on = true; + + if (on) { +#if (TCFG_SPI_LCD_ENABLE) + on = get_backlight_brightness() & 0xff; +#else + on = 100; +#endif + } + + if (first_power_on) { + backlight_status = true; + lcd_clear_screen(0x0000); + backlight_status = false; + //os_time_dly(6); + first_power_on = false; + } + + if (__this->BackLightCtrl) { + if (on) { + clock_add_set(LCD_UI_CLK); + if (__this->ExitSleep) { + __this->ExitSleep(); + } + __this->BackLightCtrl(on); + } else { + __this->BackLightCtrl(false); + if (__this->EnterSleep) { + __this->EnterSleep(); + } + clock_remove_set(LCD_UI_CLK); + } + lcd_sleep_in = !!!on; + backlight_status = on; + } + + return 0; +} + +int lcd_backlight_status() +{ + return backlight_status; +} + +struct lcd_interface *lcd_get_hdl() +{ + struct lcd_interface *p; + + ASSERT(lcd_interface_begin != lcd_interface_end, "don't find lcd interface!"); + for (p = lcd_interface_begin; p < lcd_interface_end; p++) { + return p; + } + return NULL; +} + +/* + * 注意,MCPWM的输出IO可以是固定的硬件IO或者是映射到任何一个IO,但由于映射到非硬件IO需要占用一个OUTPUT_CHANNEL, + * 因此建议设计是尽量使用带MCPWM输出的硬件IO。硬件IO一共有六组,分别是 + * (IO_PORTA_00, IO_PORTA_01) + * (IO_PORTB_00, IO_PORTB_02) + * (IO_PORTB_04, IO_PORTB_06) + * (IO_PORTB_09, IO_PORTB_10) + * (IO_PORTA_09, IO_PORTA_10) + * (IO_PORTC_04, IO_PORTC_05) + * 上述五组分别对应ch0、ch1、ch2、ch3、ch4、ch5。使用对应硬件IO时,pwm_p_data.pwm_ch_num和pwm_p_data.pwm_timer_num需要改成对应的值, + * 详细请参考mcpwm.c中的mcpwm_test + */ +struct pwm_platform_data lcd_pwm_p_data; +void lcd_mcpwm_init() +{ + extern void mcpwm_init(struct pwm_platform_data * arg); + lcd_pwm_p_data.pwm_aligned_mode = pwm_edge_aligned; //边沿对齐 + lcd_pwm_p_data.frequency = 10000; //KHz + + lcd_pwm_p_data.pwm_ch_num = pwm_ch0; //通道0 + lcd_pwm_p_data.pwm_timer_num = pwm_timer0; //时基选择通道0 + lcd_pwm_p_data.duty = 0; //占空比50% + //hw + lcd_pwm_p_data.h_pin = -1;//IO_PORTA_00; //没有则填 -1。h_pin_output_ch_num无效,可不配置 + lcd_pwm_p_data.l_pin = lcd_bl_io();//TCFG_BACKLIGHT_PWM_IO; //硬件引脚,l_pin_output_ch_num无效,可不配置 + //output_channel + /* pwm_p_data.h_pin_output_ch_num = 0; //output channel0 非硬件PWM_IO时需要打开*/ + lcd_pwm_p_data.l_pin_output_ch_num = 1; //output channel1 非硬件PWM_IO时需要打开 + lcd_pwm_p_data.complementary_en = 1; //两个引脚的波形, 1: 互补, 0: 同步; + + mcpwm_init(&lcd_pwm_p_data); +} + +REGISTER_LCD_INTERFACE(lcd) = { + .init = lcd_init, + .get_screen_info = lcd_get_screen_info, + .buffer_malloc = lcd_buffer_malloc, + .buffer_free = lcd_buffer_free, + .draw = lcd_draw, + .set_draw_area = lcd_set_draw_area, + .clear_screen = lcd_clear_screen, + .backlight_ctrl = __lcd_backlight_ctrl, + .draw_page = lcd_draw_gage, +}; + +static u8 lcd_idle_query(void) +{ + return !is_lcd_busy; +} + +REGISTER_LP_TARGET(lcd_lp_target) = { + .name = "lcd", + .is_idle = lcd_idle_query, +}; + +#endif diff --git a/cpu/br23/ui_driver/lcd_spi/spi_lcd_st7735s.c b/cpu/br23/ui_driver/lcd_spi/spi_lcd_st7735s.c new file mode 100644 index 0000000..16fa7c3 --- /dev/null +++ b/cpu/br23/ui_driver/lcd_spi/spi_lcd_st7735s.c @@ -0,0 +1,145 @@ +#include "includes.h" +#include "app_config.h" +#include "ui/ui_api.h" +#include "system/includes.h" +#include "system/timer.h" +#include "asm/spi.h" +#include "asm/mcpwm.h" + +#if TCFG_LCD_ST7735S_ENABLE + +/* 初始化代码 */ +static const InitCode LcdInit_code[] = { + {0x01, 0}, // soft reset + {REGFLAG_DELAY, 120}, // delay 120ms + {0x11, 0}, // sleep out + {REGFLAG_DELAY, 120}, + {0xB1, 3, {0x02, 0x35, 0x36}}, + {0xB2, 3, {0X02, 0X35, 0X36}}, + {0XB3, 6, {0X02, 0X35, 0X36, 0X02, 0X35, 0X36}}, + {0XB4, 1, {0X03}}, + {0XC0, 3, {0XA2, 0X02, 0X84}}, + {0XC1, 1, {0XC5}}, + {0XC2, 2, {0X0D, 0X00}}, + {0XC3, 2, {0X8D, 0X2A}}, + {0XC4, 2, {0X8D, 0XEE}}, + {0XC5, 1, {0X03}}, + {0X36, 1, {0XC8}}, + {0XE0, 16, {0X04, 0X16, 0X0D, 0X14, 0X3A, 0X33, 0X2A, 0X2E, 0X2C, 0X29, 0X30, 0X3C, 0X00, 0X01, 0X01, 0X10}}, + {0XE1, 16, {0X04, 0X16, 0X0D, 0X13, 0X3A, 0X33, 0X2A, 0X2E, 0X2C, 0X28, 0X2F, 0X3B, 0X00, 0X01, 0X01, 0X10}}, + {0X3A, 1, {0X05}}, + {0X2A, 4, {0X00, 0X00, 0X00, 0X7F}}, + {0X2B, 4, {0X00, 0X00, 0X00, 0X7F}}, + {0X29, 0}, + {REGFLAG_DELAY, 20}, + {0X2C, 0}, + {REGFLAG_DELAY, 20}, +}; + + +void TFT_Write_Cmd(u8 data) +{ + lcd_cs_l(); + lcd_rs_l(); + spi_dma_send_byte(data); + lcd_cs_h(); +} + +void TFT_Write_Data(u8 data) +{ + lcd_cs_l(); + lcd_rs_h(); + spi_dma_send_byte(data); + lcd_cs_h(); +} + +void TFT_Write_Map(char *map, int size) +{ + spi_dma_send_map(map, size); +} + + +void TFT_GPIO_Init(void) +{ +} + +void TFT_Set_Draw_Area(int xs, int xe, int ys, int ye) +{ + TFT_Write_Cmd(0x2A); + TFT_Write_Data(xs >> 8); + TFT_Write_Data(xs); + TFT_Write_Data(xe >> 8); + TFT_Write_Data(xe); + + TFT_Write_Cmd(0x2B); + TFT_Write_Data(ys >> 8); + TFT_Write_Data(ys); + TFT_Write_Data(ye >> 8); + TFT_Write_Data(ye); + + TFT_Write_Cmd(0x2C); + + lcd_cs_l(); + lcd_rs_h(); +} + +static void TFT_BackLightCtrl(u8 on) +{ +#if (TCFG_BACKLIGHT_PWM_MODE == 1) + //注意:duty不能大于prd,并且prd和duty是非标准非线性的,建议用示波器看着来调 + extern int pwm_led_output_clk(u8 gpio, u8 prd, u8 duty); + if (on) { + pwm_led_output_clk(TCFG_BACKLIGHT_PWM_IO, 10, 10); + } else { + pwm_led_output_clk(TCFG_BACKLIGHT_PWM_IO, 10, 0); + } +#elif (TCFG_BACKLIGHT_PWM_MODE == 2) + static u8 first_flag = 1; + extern void mcpwm_set_duty(pwm_ch_num_type pwm_ch, pwm_timer_num_type timer_ch, u16 duty); + if (first_flag) { + first_flag = 0; + lcd_mcpwm_init(); + } + if (on) { + mcpwm_set_duty(lcd_pwm_p_data.pwm_ch_num, lcd_pwm_p_data.pwm_timer_num, 0);//duty 占空比:0 ~ 10000 对应 100% ~ 0% + } else { + mcpwm_set_duty(lcd_pwm_p_data.pwm_ch_num, lcd_pwm_p_data.pwm_timer_num, 10000);//duty 占空比:0 ~ 10000 对应 100% ~ 0% + } +#else + if (on) { + lcd_bl_h(); + } else { + lcd_bl_l(); + } +#endif +} + +#define LCD_WIDTH 132 +#define LCD_HIGHT 132 +#define LINE_BUFF_SIZE (10*2*LCD_WIDTH*2) +static u8 line_buffer[LINE_BUFF_SIZE] __attribute__((aligned(4))); + +REGISTER_LCD_DRIVE() = { + .name = "st7735s", + .lcd_width = LCD_WIDTH, + .lcd_height = LCD_HIGHT, + .color_format = LCD_COLOR_RGB565, + .interface = LCD_SPI, + .column_addr_align = 1, + .row_addr_align = 1, + .dispbuf = line_buffer, + .bufsize = LINE_BUFF_SIZE, + .initcode = LcdInit_code, + .initcode_cnt = sizeof(LcdInit_code) / sizeof(LcdInit_code[0]), + .GpioInit = TFT_GPIO_Init, + .WriteComm = TFT_Write_Cmd, + .WriteData = TFT_Write_Data, + .WriteMap = TFT_Write_Map, + .SetDrawArea = TFT_Set_Draw_Area, + .Reset = NULL, + .BackLightCtrl = TFT_BackLightCtrl, +}; + +#endif + + diff --git a/cpu/br23/ui_driver/lcd_spi/spi_lcd_st7789v.c b/cpu/br23/ui_driver/lcd_spi/spi_lcd_st7789v.c new file mode 100644 index 0000000..a302422 --- /dev/null +++ b/cpu/br23/ui_driver/lcd_spi/spi_lcd_st7789v.c @@ -0,0 +1,175 @@ +#include "includes.h" +#include "app_config.h" +#include "ui/ui_api.h" +#include "system/includes.h" +#include "system/timer.h" +#include "asm/spi.h" +#include "asm/mcpwm.h" + +#if TCFG_LCD_ST7789V_ENABLE + +static void delay_ms(unsigned int ms); + +/* 初始化代码 */ +static const InitCode LcdInit_code[] = { + {0x01, 0}, // soft reset + {REGFLAG_DELAY, 120}, // delay 120ms + {0x11, 0}, // sleep out + {REGFLAG_DELAY, 120}, + {0x36, 1, {0x00}}, + {0x3A, 1, {0x05}}, + {0xB2, 5, {0x0c, 0x0c, 0x00, 0x33, 0x33}}, + {0xB7, 1, {0x22}}, + {0xBB, 1, {0x36}}, + {0xC2, 1, {0x01}}, + {0xC3, 1, {0x19}}, + {0xC4, 1, {0x20}}, + {0xC6, 1, {0x0F}}, + {0xD0, 2, {0xA4, 0xA1}}, + /* {0xE0,14, {0x70,0x04,0x08,0x09,0x09,0x05,0x2A,0x33,0x41,0x07,0x13,0x13,0x29,0x2F}}, */ + /* {0xE1,14, {0x70,0x03,0x09,0x0A,0x09,0x06,0x2B,0x34,0x41,0x07,0x12,0x14,0x28,0x2E}}, */ + {0xE0, 14, {0xD0, 0x04, 0x0D, 0x11, 0x13, 0x2B, 0x3F, 0x54, 0x4C, 0x18, 0x0D, 0x0B, 0x1F, 0x23}}, + {0xE1, 14, {0xD0, 0x04, 0x0C, 0x11, 0x13, 0x2C, 0x3F, 0x44, 0x51, 0x2F, 0x1F, 0x1F, 0x20, 0x23}}, + {0X21, 0}, + {0X2A, 4, {0x00, 0x00, 0x00, 0xEF}}, + {0X2B, 4, {0x00, 0x00, 0x00, 0xEF}}, + {0X29, 0}, + {REGFLAG_DELAY, 20}, + {0X2C, 0}, + {REGFLAG_DELAY, 20}, +}; + + +void TFT_Write_Cmd(u8 data) +{ + lcd_cs_l(); + lcd_rs_l(); + lcd_spi_send_byte(data); + lcd_cs_h(); +} + +void TFT_Write_Data(u8 data) +{ + lcd_cs_l(); + lcd_rs_h(); + lcd_spi_send_byte(data); + lcd_cs_h(); +} + +void TFT_Write_Map(char *map, u32 size) +{ + spi_dma_send_map(map, size); +} + +void TFT_Set_Draw_Area(int xs, int xe, int ys, int ye) +{ + TFT_Write_Cmd(0x2A); + TFT_Write_Data(xs >> 8); + TFT_Write_Data(xs); + TFT_Write_Data(xe >> 8); + TFT_Write_Data(xe); + + TFT_Write_Cmd(0x2B); + TFT_Write_Data(ys >> 8); + TFT_Write_Data(ys); + TFT_Write_Data(ye >> 8); + TFT_Write_Data(ye); + + TFT_Write_Cmd(0x2C); + + lcd_cs_l(); + lcd_rs_h(); +} + +static void TFT_BackLightCtrl(u8 on) +{ +#if (TCFG_BACKLIGHT_PWM_MODE == 1) + //注意:duty不能大于prd,并且prd和duty是非标准非线性的,建议用示波器看着来调 + extern int pwm_led_output_clk(u8 gpio, u8 prd, u8 duty); + if (on) { + pwm_led_output_clk(TCFG_BACKLIGHT_PWM_IO, 10, 10); + } else { + pwm_led_output_clk(TCFG_BACKLIGHT_PWM_IO, 10, 0); + } +#elif (TCFG_BACKLIGHT_PWM_MODE == 2) + static u8 first_flag = 1; + extern void mcpwm_set_duty(pwm_ch_num_type pwm_ch, pwm_timer_num_type timer_ch, u16 duty); + if (first_flag) { + first_flag = 0; + lcd_mcpwm_init(); + } + if (on) { + mcpwm_set_duty(lcd_pwm_p_data.pwm_ch_num, lcd_pwm_p_data.pwm_timer_num, 0);//duty 占空比:0 ~ 10000 对应 100% ~ 0% + } else { + mcpwm_set_duty(lcd_pwm_p_data.pwm_ch_num, lcd_pwm_p_data.pwm_timer_num, 10000);//duty 占空比:0 ~ 10000 对应 100% ~ 0% + } +#else + if (on) { + lcd_bl_h(); + } else { + lcd_bl_l(); + } +#endif +} + +static void TFT_EnterSleep() +{ + TFT_Write_Cmd(0x28); + /* delay_ms(120); */ + TFT_Write_Cmd(0x10); + delay_ms(120); +} + +static void TFT_ExitSleep() +{ + TFT_Write_Cmd(0x11); + delay_ms(120); + TFT_Write_Cmd(0x29); + /* delay_ms(120); */ +} + +static void delay_ms(unsigned int ms) +{ + delay_2ms((ms + 1) / 2); +} + + +static void lcd_reset() +{ + lcd_reset_h(); + delay_ms(1000); + lcd_reset_l(); + delay_ms(1000); + lcd_reset_h(); +} + +#define LCD_WIDTH 240 +#define LCD_HIGHT 240 +#define LINE_BUFF_SIZE (10*2*LCD_WIDTH*2) +static u8 line_buffer[LINE_BUFF_SIZE] __attribute__((aligned(4))); + +REGISTER_LCD_DRIVE() = { + .name = "st7789v", + .lcd_width = LCD_WIDTH, + .lcd_height = LCD_HIGHT, + .color_format = LCD_COLOR_RGB565, + .interface = LCD_SPI, + .column_addr_align = 1, + .row_addr_align = 1, + .dispbuf = line_buffer, + .bufsize = LINE_BUFF_SIZE, + .initcode = LcdInit_code, + .initcode_cnt = sizeof(LcdInit_code) / sizeof(LcdInit_code[0]), + .WriteComm = TFT_Write_Cmd, + .WriteData = TFT_Write_Data, + .WriteMap = TFT_Write_Map, + .SetDrawArea = TFT_Set_Draw_Area, + .Reset = lcd_reset, + .BackLightCtrl = TFT_BackLightCtrl, + .EnterSleep = TFT_EnterSleep, + .ExitSleep = TFT_ExitSleep, +}; + +#endif + + diff --git a/cpu/br23/ui_driver/lcd_spi/spi_lcd_st7789vw.c b/cpu/br23/ui_driver/lcd_spi/spi_lcd_st7789vw.c new file mode 100644 index 0000000..68ce54b --- /dev/null +++ b/cpu/br23/ui_driver/lcd_spi/spi_lcd_st7789vw.c @@ -0,0 +1,150 @@ +#include "includes.h" +#include "app_config.h" +#include "ui/ui_api.h" +#include "system/includes.h" +#include "system/timer.h" +#include "asm/spi.h" +#include "asm/mcpwm.h" + +#if TCFG_LCD_ST7789VW_ENABLE + +#define USED_OLD 0 + + +/* 初始化代码 */ +static const InitCode LcdInit_code[] = { + {0x01, 0}, // soft reset + {REGFLAG_DELAY, 120}, // delay 120ms + {0x11, 0}, // sleep out + {REGFLAG_DELAY, 120}, +#if USED_OLD + {0x36, 1, {BIT(6) | BIT(3)}}, +#else + {0x36, 1, {0x00}}, +#endif + {0x3A, 1, {0x05}}, + {0xB2, 5, {0x0c, 0x0c, 0x00, 0x33, 0x33}}, + {0xB7, 1, {0x35}}, + {0xBB, 1, {0x19}}, + {0xC0, 1, {0x2C}}, + {0xC2, 1, {0x01}}, + {0xC3, 1, {0x12}}, + {0xC4, 1, {0x20}}, + {0xC6, 1, {0x0F}}, + {0xD0, 2, {0xA4, 0xA1}}, + {0xE0, 14, {0xD0, 0x04, 0x0D, 0x11, 0x13, 0x2B, 0x3F, 0x54, 0x4C, 0x18, 0x0D, 0x0B, 0x1F, 0x23}}, + {0xE1, 14, {0xD0, 0x04, 0x0C, 0x11, 0x13, 0x2C, 0x3F, 0x44, 0x51, 0x2F, 0x1F, 0x1F, 0x20, 0x23}}, + +#if USED_OLD + /* {0X21, 0}, */ +#else + {0X21, 0}, +#endif + {0X2A, 4, {0x00, 0x00, 0x00, 0xEF}}, + {0X2B, 4, {0x00, 0x00, 0x00, 0xEF}}, + {0X29, 0}, + {REGFLAG_DELAY, 20}, + {0X2C, 0}, + {REGFLAG_DELAY, 20}, +}; + +void TFT_Write_Cmd(u8 data) +{ + lcd_cs_l(); + lcd_rs_l(); + spi_dma_send_byte(data); + lcd_cs_h(); +} + +void TFT_Write_Data(u8 data) +{ + lcd_cs_l(); + lcd_rs_h(); + spi_dma_send_byte(data); + lcd_cs_h(); +} + +void TFT_Write_Map(char *map, int size) +{ + spi_dma_send_map(map, size); +} + +void TFT_Set_Draw_Area(int xs, int xe, int ys, int ye) +{ + TFT_Write_Cmd(0x2A); + TFT_Write_Data(xs >> 8); + TFT_Write_Data(xs); + TFT_Write_Data(xe >> 8); + TFT_Write_Data(xe); + + TFT_Write_Cmd(0x2B); + TFT_Write_Data(ys >> 8); + TFT_Write_Data(ys); + TFT_Write_Data(ye >> 8); + TFT_Write_Data(ye); + + TFT_Write_Cmd(0x2C); + + lcd_cs_l(); + lcd_rs_h(); +} + +static void TFT_BackLightCtrl(u8 on) +{ +#if (TCFG_BACKLIGHT_PWM_MODE == 1) + //注意:duty不能大于prd,并且prd和duty是非标准非线性的,建议用示波器看着来调 + extern int pwm_led_output_clk(u8 gpio, u8 prd, u8 duty); + if (on) { + pwm_led_output_clk(TCFG_BACKLIGHT_PWM_IO, 10, 10); + } else { + pwm_led_output_clk(TCFG_BACKLIGHT_PWM_IO, 10, 0); + } +#elif (TCFG_BACKLIGHT_PWM_MODE == 2) + static u8 first_flag = 1; + extern void mcpwm_set_duty(pwm_ch_num_type pwm_ch, pwm_timer_num_type timer_ch, u16 duty); + if (first_flag) { + first_flag = 0; + lcd_mcpwm_init(); + } + if (on) { + mcpwm_set_duty(lcd_pwm_p_data.pwm_ch_num, lcd_pwm_p_data.pwm_timer_num, 0);//duty 占空比:0 ~ 10000 对应 100% ~ 0% + } else { + mcpwm_set_duty(lcd_pwm_p_data.pwm_ch_num, lcd_pwm_p_data.pwm_timer_num, 10000);//duty 占空比:0 ~ 10000 对应 100% ~ 0% + } +#else + if (on) { + lcd_bl_h(); + } else { + lcd_bl_l(); + } +#endif +} + +#define LCD_WIDTH 240 +#define LCD_HIGHT 240 +#define LINE_BUFF_SIZE (10*2*LCD_WIDTH*2) +static u8 line_buffer[LINE_BUFF_SIZE] __attribute__((aligned(4))); + +REGISTER_LCD_DRIVE() = { + .name = "st7789vw", + .lcd_width = LCD_WIDTH, + .lcd_height = LCD_HIGHT, + .color_format = LCD_COLOR_RGB565, + .interface = LCD_SPI, + .column_addr_align = 1, + .row_addr_align = 1, + .dispbuf = line_buffer, + .bufsize = LINE_BUFF_SIZE, + .initcode = LcdInit_code, + .initcode_cnt = sizeof(LcdInit_code) / sizeof(LcdInit_code[0]), + .WriteComm = TFT_Write_Cmd, + .WriteData = TFT_Write_Data, + .WriteMap = TFT_Write_Map, + .SetDrawArea = TFT_Set_Draw_Area, + .Reset = NULL, + .BackLightCtrl = TFT_BackLightCtrl, +}; + +#endif + + diff --git a/cpu/br23/ui_driver/lcd_spi/spi_oled.c b/cpu/br23/ui_driver/lcd_spi/spi_oled.c new file mode 100644 index 0000000..dffb4f3 --- /dev/null +++ b/cpu/br23/ui_driver/lcd_spi/spi_oled.c @@ -0,0 +1,310 @@ +#include "includes.h" +#include "app_config.h" +#include "ui/ui_api.h" +#include "system/includes.h" +#include "system/timer.h" +#include "asm/spi.h" +#include "ui_driver/oled/oled.h" + +#if TCFG_LCD_OLED_ENABLE + +#define USED_SPI_4LINE 1 + + +void lcd_spi_dma_send_wait(u8 *map, u32 size); + +static void OLED_BackLightCtrl(u8 on) +{ + if (on) { + lcd_bl_h(); + } else { + lcd_bl_l(); + } + printf("call %s \n", __FUNCTION__); +} + +static void delay_ms(unsigned int ms) +{ + unsigned int a; + while (ms) { + a = 80; + while (a--); + ms--; + } + return; +} + + +static void OLED_WR_Cmd(u8 dat) +{ +#if USED_SPI_4LINE + lcd_cs_l(); + lcd_rs_l(); + spi_dma_send_byte(dat); + lcd_cs_h(); +#else + u8 i; + + OLED_CS_Clr(); + OLED_SCLK_Clr(); + OLED_SDIN_Clr(); + OLED_SCLK_Set(); + + for (i = 0; i < 8; i++) { + OLED_SCLK_Clr(); + if (dat & 0x80) { + OLED_SDIN_Set(); + } else { + OLED_SDIN_Clr(); + } + OLED_SCLK_Set(); + dat <<= 1; + } + OLED_CS_Set(); +#endif +} + +static void OLED_WR_Data(u8 dat) +{ +#if USED_SPI_4LINE + lcd_cs_l(); + lcd_rs_h(); + spi_dma_send_byte(dat); + lcd_cs_h(); +#else + u8 i; + OLED_CS_Clr(); + OLED_SCLK_Clr(); + OLED_SDIN_Set(); + OLED_SCLK_Set(); + + for (i = 0; i < 8; i++) { + OLED_SCLK_Clr(); + if (dat & 0x80) { + OLED_SDIN_Set(); + } else { + OLED_SDIN_Clr(); + } + OLED_SCLK_Set(); + dat <<= 1; + } + OLED_CS_Set(); +#endif +} + +static void OLED_Set_Draw_Area(int xs, int xe, int ys, int ye) +{ + OLED_WR_Cmd(0xb0 + (ys / 8) % 8); //设置页地址(0~7) + OLED_WR_Cmd(0x00 + xs & 0x0f); //设置显示位置—列低地址 + OLED_WR_Cmd(0x10 + (xs >> 4) & 0x0f); //设置显示位置—列高地址 +} + +static void OLED_Write_Cmd(u8 cmd) +{ + OLED_WR_Cmd(cmd); +} + +static void OLED_Write_Data(u8 data) +{ + OLED_WR_Data(data); +} + + + + +static void OLED_Write_PAGE(char *map, u8 page_star, u8 page_len) +{ + u8 page; + for (page = page_star; page < page_star + page_len; page++) { + OLED_WR_Cmd(0xb0 + page); + OLED_WR_Cmd(0x00); + OLED_WR_Cmd(0x10); + lcd_cs_l(); + lcd_rs_h(); + lcd_spi_dma_send_wait(map, 128); + map += 128; + lcd_cs_h(); + } +} + +static void OLED_Write_Map(char *map, int size) +{ + u8 page; + u8 col; + for (page = 0; page < 8; page++) { + OLED_WR_Cmd(0xb0 + page); + OLED_WR_Cmd(0x00); + OLED_WR_Cmd(0x10); +#if USED_SPI_4LINE + lcd_cs_l(); + lcd_rs_h(); + lcd_spi_dma_send_wait(map, 128); + map += 128; + lcd_cs_h(); +#else + for (col = 0; col < 128; col++) { + OLED_WR_Data(*map++); + } +#endif + } +} + +//向SSD1306写入一个字节。 +//dat:要写入的数据/命令 +//cmd:数据/命令标志 0,表示命令;1,表示数据; +static void OLED_WR_Byte(u8 dat, u8 cmd) +{ +#if USED_SPI_4LINE + if (cmd == OLED_CMD) { + OLED_WR_Cmd(dat); + } else { + OLED_WR_Data(dat); + } +#else + u8 i; + OLED_CS_Clr(); + OLED_SCLK_Clr(); + + if (cmd == OLED_CMD) { + /* OLED_SDIN_Set(); */ + OLED_SDIN_Clr(); + } else { + /* OLED_SDIN_Clr(); */ + OLED_SDIN_Set(); + } + + OLED_SCLK_Set(); + + for (i = 0; i < 8; i++) { + OLED_SCLK_Clr(); + if (dat & 0x80) { + OLED_SDIN_Set(); + } else { + OLED_SDIN_Clr(); + } + OLED_SCLK_Set(); + dat <<= 1; + } + OLED_CS_Set(); +#endif +} + +//清屏函数,清完屏,整个屏幕是黑色的!和没点亮一样!!! +void OLED_Clear(void) +{ + u8 i, n; + for (i = 0; i < 8; i++) { + OLED_WR_Byte(0xb0 + i, OLED_CMD); //设置页地址(0~7) + OLED_WR_Byte(0x00, OLED_CMD); //设置显示位置—列低地址 + OLED_WR_Byte(0x10, OLED_CMD); //设置显示位置—列高地址 + for (n = 0; n < 128; n++) { + OLED_WR_Byte(0x00, OLED_DATA); + } + } //更新显示 +} + +void OLED_Set_Pos(unsigned char x, unsigned char y) +{ + OLED_WR_Byte(0xb0 + y, OLED_CMD); + OLED_WR_Byte(((x & 0xf0) >> 4) | 0x10, OLED_CMD); + OLED_WR_Byte((x & 0x0f) | 0x01, OLED_CMD); +} + +//初始化SSD1306 +static void SPI_OLED_Init(void) +{ + + printf("OLED_Init...\n"); + +#if USED_SPI_4LINE + lcd_reset_h(); +#else + OLED_RST_Set(); +#endif + + delay_ms(1000); + +#if USED_SPI_4LINE + lcd_reset_l(); +#else + OLED_RST_Clr(); + +#endif + + delay_ms(1000); + delay_ms(1000); + +#if USED_SPI_4LINE + lcd_reset_h(); + delay_ms(1000); +#else + OLED_RST_Set(); + +#endif + + OLED_WR_Byte(0xAE, OLED_CMD); //--turn off oled panel + OLED_WR_Byte(0x00, OLED_CMD); //---set low column address + OLED_WR_Byte(0x10, OLED_CMD); //---set high column address + OLED_WR_Byte(0x40, OLED_CMD); //--set start line address Set Mapping RAM Display Start Line (0x00~0x3F) + OLED_WR_Byte(0x81, OLED_CMD); //--set contrast control register + OLED_WR_Byte(0xCF, OLED_CMD); // Set SEG Output Current Brightness + OLED_WR_Byte(0xA1, OLED_CMD); //--Set SEG/Column Mapping 0xa0左右反置 0xa1正常 + OLED_WR_Byte(0xC8, OLED_CMD); //Set COM/Row Scan Direction 0xc0上下反置 0xc8正常 + OLED_WR_Byte(0xA6, OLED_CMD); //--set normal display + OLED_WR_Byte(0xA8, OLED_CMD); //--set multiplex ratio(1 to 64) + OLED_WR_Byte(0x3f, OLED_CMD); //--1/64 duty + OLED_WR_Byte(0xD3, OLED_CMD); //-set display offset Shift Mapping RAM Counter (0x00~0x3F) + OLED_WR_Byte(0x00, OLED_CMD); //-not offset + OLED_WR_Byte(0xd5, OLED_CMD); //--set display clock divide ratio/oscillator frequency + OLED_WR_Byte(0x80, OLED_CMD); //--set divide ratio, Set Clock as 100 Frames/Sec + OLED_WR_Byte(0xD9, OLED_CMD); //--set pre-charge period + OLED_WR_Byte(0xF1, OLED_CMD); //Set Pre-Charge as 15 Clocks & Discharge as 1 Clock + OLED_WR_Byte(0xDA, OLED_CMD); //--set com pins hardware configuration + OLED_WR_Byte(0x12, OLED_CMD); + OLED_WR_Byte(0xDB, OLED_CMD); //--set vcomh + OLED_WR_Byte(0x40, OLED_CMD); //Set VCOM Deselect Level + OLED_WR_Byte(0x20, OLED_CMD); //-Set Page Addressing Mode (0x00/0x01/0x02) + OLED_WR_Byte(0x02, OLED_CMD); // + OLED_WR_Byte(0x8D, OLED_CMD); //--set Charge Pump enable/disable + OLED_WR_Byte(0x14, OLED_CMD); //--set(0x10) disable + OLED_WR_Byte(0xA4, OLED_CMD); // Disable Entire Display On (0xa4/0xa5) + OLED_WR_Byte(0xA6, OLED_CMD); // Disable Inverse Display On (0xa6/a7) + OLED_WR_Byte(0xAF, OLED_CMD); //--turn on oled panel + OLED_WR_Byte(0xAF, OLED_CMD); /*display ON*/ + + OLED_Clear(); + OLED_Set_Pos(0, 0); +} + +#define LCD_BUFFER_SIZE (128*64/8) + +u8 LCDBuff[8][128]; + + + +REGISTER_LCD_DRIVE() = { + .name = "oled", + .lcd_width = 128, + .lcd_height = 64, + .color_format = LCD_COLOR_MONO, + .interface = LCD_SPI, + .column_addr_align = 1, + .row_addr_align = 1, + .dispbuf = LCDBuff, + .bufsize = LCD_BUFFER_SIZE, + .initcode = NULL, + .initcode_cnt = 0, + .Init = SPI_OLED_Init, + .WriteComm = OLED_Write_Cmd, + .WriteData = OLED_Write_Data, + .WriteMap = OLED_Write_Map, + .SetDrawArea = OLED_Set_Draw_Area, + .Reset = NULL, + .BackLightCtrl = OLED_BackLightCtrl, + .WritePAGE = OLED_Write_PAGE, + +}; + +#endif + + diff --git a/cpu/br23/ui_driver/led7/led7_driver.c b/cpu/br23/ui_driver/led7/led7_driver.c new file mode 100644 index 0000000..e93cd01 --- /dev/null +++ b/cpu/br23/ui_driver/led7/led7_driver.c @@ -0,0 +1,840 @@ +#include "includes.h" +#include "app_config.h" +#include "system/device/vm.h" + +#include "ui/ui_api.h" + +#pragma const_seg(".LED_const") +#pragma code_seg(".LED_code") + +#include "led7_driver_cfg.h" + +#if TCFG_UI_LED7_ENABLE + + +#define LED7_DEBUG_ENABLE +#ifdef LED7_DEBUG_ENABLE +#define led7_debug(fmt, ...) printf("[LED7] "fmt, ##__VA_ARGS__) +#else +#define led7_debug(...) +#endif + +#define led7_error(fmt, ...) printf("[LED7 ERR] "fmt, ##__VA_ARGS__) + +//#define UI_LED7_TRUE_TABLE1 +//#define UI_LED7_TRUE_TABLE2 +#define UI_LED7_TRUE_TABLE3 + +struct ui_led7_env { + u8 init; + LED7_VAR led7_var; + const struct led7_platform_data *user_data; + u32 flash_time; + u8 lock: 1; +}; + +static struct ui_led7_env _led7_env = {0}; + +#define __this (&_led7_env) + +//数字'0' ~ '9'显示段码表 +static const u8 LED7_NUMBER_2_SEG[10] = { + (u8)(LED_A | LED_B | LED_C | LED_D | LED_E | LED_F), //'0' + (u8)(LED_B | LED_C), //'1' + (u8)(LED_A | LED_B | LED_D | LED_E | LED_G), //'2' + (u8)(LED_A | LED_B | LED_C | LED_D | LED_G), //'3' + (u8)(LED_B | LED_C | LED_F | LED_G), //'4' + (u8)(LED_A | LED_C | LED_D | LED_F | LED_G), //'5' + (u8)(LED_A | LED_C | LED_D | LED_E | LED_F | LED_G), //'6' + (u8)(LED_A | LED_B | LED_C), //'7' + (u8)(LED_A | LED_B | LED_C | LED_D | LED_E | LED_F | LED_G), //'8' + (u8)(LED_A | LED_B | LED_C | LED_D | LED_F | LED_G), //'9' +}; + +//字母'A' ~ 'Z'显示段码表 +static const u8 LED7_LARGE_LETTER_2_SEG[26] = { + 0x77, 0x40, 0x39, 0x3f, 0x79, ///led7_var.bShowIcon |= icon; + __this->led7_var.bFlashIcon &= (~icon); //stop display +} + +/*----------------------------------------------------------------------------*/ +/**@brief 显示图标类 + @param void + @return void + @author Change.tsai + @note void ui_led7_flash_icon(UI_LED7_ICON icon) +*/ +/*----------------------------------------------------------------------------*/ +void led7_flash_icon(UI_LED7_ICON icon) +{ + __this->led7_var.bFlashIcon |= icon; + __this->led7_var.bShowIcon &= (~icon); //stop display +} + +/*----------------------------------------------------------------------------*/ +/**@brief led7_drv 状态位缓存清除函数 + @param void + @return void + @author Change.tsai + @note void led7_clear_icon(void) +*/ +/*----------------------------------------------------------------------------*/ +void led7_clear_icon(UI_LED7_ICON icon) +{ + __this->led7_var.bShowIcon &= (~icon); + __this->led7_var.bFlashIcon &= (~icon); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief led7_drv 清楚所有图标显示 + @param void + @return void + @author Change.tsai + @note void led7_clear_icon(void) +*/ +/*----------------------------------------------------------------------------*/ +void led7_clear_all_icon(void) +{ + __this->led7_var.bFlashIcon = 0; + __this->led7_var.bShowIcon = 0; + __this->flash_time = jiffies_to_msecs(jiffies); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief led7_drv 显示坐标设置 + @param x:显示横坐标 + @return void + @author Change.tsai + @note void led7_setX(u8 X) +*/ +/*----------------------------------------------------------------------------*/ +void led7_setX(u8 X) +{ + __this->led7_var.bCoordinateX = X; +} + +/*----------------------------------------------------------------------------*/ +/**@brief led7_drv 清除显示数字和字母 + @param void + @return void + @author Change.tsai + @note void led7_clear_string(void) +*/ +/*----------------------------------------------------------------------------*/ +void led7_clear_string(void) +{ + memset(__this->led7_var.bShowBuff, 0x00, 4); + __this->led7_var.bFlashChar = 0; + led7_setX(0); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief LED 清屏函数 + @param void + @return void + @author Change.tsai + @note void led7_show_null(void) +*/ +/*----------------------------------------------------------------------------*/ +void led7_show_null(void) +{ + led7_clear_all_icon(); + led7_clear_string(); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief led7_drv 单个字符显示函数 + @param chardata:显示字符 + @return void + @author Change.tsai + @note void led7_show_char(u8 chardata) + @ display: + ___ ___ ___ ___ + |___| |___| |___| |___| + |___| |___| |___| |___| + ---0------1------2------3------> X +*/ +/*----------------------------------------------------------------------------*/ +void led7_show_char(u8 chardata) +{ + if (__this->led7_var.bCoordinateX >= 4) { + __this->led7_var.bCoordinateX = 0; //or return + //return ; + } + if ((chardata >= '0') && (chardata <= '9')) { + __this->led7_var.bShowBuff[__this->led7_var.bCoordinateX++] = LED7_NUMBER_2_SEG[chardata - '0']; + } else if ((chardata >= 'a') && (chardata <= 'z')) { + __this->led7_var.bShowBuff[__this->led7_var.bCoordinateX++] = LED7_SMALL_LETTER_2_SEG[chardata - 'a']; + } else if ((chardata >= 'A') && (chardata <= 'Z')) { + __this->led7_var.bShowBuff[__this->led7_var.bCoordinateX++] = LED7_LARGE_LETTER_2_SEG[chardata - 'A']; + } else if (chardata == ':') { + __this->led7_var.bShowIcon |= LED7_2POINT; + __this->led7_var.bFlashIcon &= (~LED7_2POINT); + } else if (chardata == '.') { + __this->led7_var.bShowIcon |= LED7_DOT; + __this->led7_var.bFlashIcon &= (~LED7_DOT); + } else if (chardata == ' ') { + __this->led7_var.bShowBuff[__this->led7_var.bCoordinateX++] = 0; + } else { + __this->led7_var.bShowBuff[__this->led7_var.bCoordinateX++] = LED_G; //显示'-' + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief led7_drv 某一位字符闪烁 + @param index + @return void + @author Change.tsai + @note void led7_flash_char_start(u8 index) +*/ +/*----------------------------------------------------------------------------*/ +void led7_flash_char_start(u8 index) +{ + if (index < 4) { + __this->led7_var.bFlashChar |= BIT(index); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief led7_drv 某一位取消字符闪烁 + @param index + @return void + @author Change.tsai + @note void led7_flash_char_stop(u8 index) +*/ +/*----------------------------------------------------------------------------*/ +void led7_flash_char_stop(u8 index) +{ + if (index < 4) { + __this->led7_var.bFlashChar &= ~BIT(index); + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief led7_drv 字符串显示函数, 默认左对齐, 从x = 0开始显示 + @param *str:字符串的指针 offset:显示偏移量 + @return void + @author Change.tsai + @note void led7_show_string_left(u8 *str) +*/ +/*----------------------------------------------------------------------------*/ +void led7_show_string_reset_x(u8 *str) +{ + led7_clear_string(); + while (*str != '\0') { + led7_show_char(*str++); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief led7_drv 字符串显示函数, 默认左对齐, 追加形式 + @param *str:字符串的指针 offset:显示偏移量 + @return void + @author Change.tsai + @note void led7_show_string_left(u8 *str) +*/ +/*----------------------------------------------------------------------------*/ +void led7_show_string(u8 *str) +{ + while (*str != '\0') { + led7_show_char(*str++); + } +} + +/*----------------------------------------------------------------------------*/ +/**@brief led7_drv 字符串显示函数, 左对齐, 清屏 + @param *str:字符串的指针 + @return void + @author Change.tsai + @note void led7_show_string_left(u8 *str) +*/ +/*----------------------------------------------------------------------------*/ +void led7_show_string_align_left(u8 *str) +{ + led7_show_string_reset_x(str); +} + + +/*----------------------------------------------------------------------------*/ +/**@brief led7_drv 字符串显示函数, 右对齐, 清屏 + @param *str:字符串的指针 + @return void + @author Change.tsai + @note void led7_show_string_left(u8 *str) +*/ +/*----------------------------------------------------------------------------*/ +void led7_show_string_align_right(u8 *str) +{ + u8 cnt = 0; + u8 *_str = str; + while (*_str++ != '\0') { + cnt++; + } + if (cnt > 4) { + led7_error("show string oversize", __func__); + return; + } + led7_clear_string(); + led7_setX(4 - cnt); + while (*str != '\0') { + led7_show_char(*str++); + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 数字显示函数, 默认高位显示0 + @param void + @return void + @author Change.tsai + @note void led7_show_number(u8 val) +*/ +/*----------------------------------------------------------------------------*/ +void led7_show_number(u16 val) +{ + u8 tmp_buf[5] = {0}; + + itoa4(val, tmp_buf); + led7_show_string_reset_x(tmp_buf); +} + + + +/*----------------------------------------------------------------------------*/ +/**@brief 数字显示函数, 高位不显示0 + @param val, 显示数字 + @return void + @author Change.tsai + @note void led7_show_number2(u8 val) +*/ +/*----------------------------------------------------------------------------*/ +void led7_show_number2(u16 val) +{ + u8 i; + u8 tmp_buf[5] = {0}; + + itoa4(val, tmp_buf); + for (i = 0; i < 3; i++) { + if (tmp_buf[i] != '0') { + break; + } + } + led7_show_string_align_right((u8 *) & (tmp_buf[i])); +} + +/*----------------------------------------------------------------------------*/ +/**@brief 数字显示函数(追加方式) + @param val, 显示数字 + @return void + @author Change.tsai + @note void led7_show_number_add(u8 val) +*/ +/*----------------------------------------------------------------------------*/ +void led7_show_number_add(u16 val) +{ + u8 i; + u8 tmp_buf[5] = {0}; + + itoa4(val, tmp_buf); + for (i = 0; i < 3; i++) { + if (tmp_buf[i] != '0') { + break; + } + } + led7_show_string((u8 *)&tmp_buf[i]); +} + + +static u8 __ui_led7_get_sys_halfsec(void) +{ + if (((jiffies_to_msecs(jiffies) - __this->flash_time) & 999) > 500) { + return true; + } else { + return false; + } +} + +static void __ui_led7_update_bShowbuf1(void) +{ + u8 k, i, j, temp; + k = 0; + + __this->led7_var.bShowBuff1[0] = 0; //if pin0 output 1, other output 0/1 + __this->led7_var.bShowBuff1[1] = 0; + __this->led7_var.bShowBuff1[2] = 0; + __this->led7_var.bShowBuff1[3] = 0; + __this->led7_var.bShowBuff1[4] = 0; + __this->led7_var.bShowBuff1[5] = 0; + __this->led7_var.bShowBuff1[6] = 0; + + //digit display + for (i = 0; i < 4; i++) { + temp = __this->led7_var.bShowBuff[i]; + for (j = 0; j < 7; j++) { + if (temp & BIT(j)) { + //the j seg should display + //look up the seg2pin table, set the pin should be output 0 + __this->led7_var.bShowBuff1[led7_digit_seg2pin[k].pinH] |= BIT(led7_digit_seg2pin[k].pinL); + } + k++; //max for 4 * 7 + } + } + //char flash + if (__ui_led7_get_sys_halfsec()) { //500ms display, or char off + if (__this->led7_var.bFlashChar) { + for (j = 0; j < 4; j++) { + if (BIT(j) & __this->led7_var.bFlashChar) { //某一位不显示 + //look up the seg2pin table, set the pin should be output 0 + for (i = 0; i < 7; i++) { + __this->led7_var.bShowBuff1[led7_digit_seg2pin[7 * j + i].pinH] &= ~(BIT(led7_digit_seg2pin[7 * j + i].pinL)); + } + } + } + } + } + //icon display + if (__this->led7_var.bShowIcon) { + for (j = 0; j < 32; j++) { + if (BIT(j) & __this->led7_var.bFlashIcon) { + continue; + } + if (BIT(j) & __this->led7_var.bShowIcon) { + for (i = 0; i < ARRAY_SIZE(led7_icon_seg2pin); i++) { //lookup icon exist + if (BIT(j) == led7_icon_seg2pin[i].icon) { + //look up the seg2pin table, set the pin should be output 0 + __this->led7_var.bShowBuff1[led7_icon_seg2pin[i].seg2pin.pinH] |= BIT(led7_icon_seg2pin[i].seg2pin.pinL); + } + } + } + } + } + //icon flash + if (__this->led7_var.bFlashIcon) { + if (__ui_led7_get_sys_halfsec()) { //500ms display, or seg off + for (j = 0; j < 32; j++) { + if (BIT(j) & __this->led7_var.bFlashIcon) { + for (i = 0; i < ARRAY_SIZE(led7_icon_seg2pin); i++) { //lookup icon exist + if (BIT(j) == led7_icon_seg2pin[i].icon) { + //look up the seg2pin table, set the pin should be output 0 + __this->led7_var.bShowBuff1[led7_icon_seg2pin[i].seg2pin.pinH] |= BIT(led7_icon_seg2pin[i].seg2pin.pinL); + } + } + } + } + } + } +} + + +/*----------------------------------------------------------------------------*/ +/**@brief 把所有IO设置为高阻 + @param x:显示横坐标 + @return void + @author Change.tsai + @note void led7_clear(void) +*/ +/*----------------------------------------------------------------------------*/ +static void __ui_led7_port_set_hz(u8 port) +{ + gpio_set_pull_down(port, 0); + gpio_set_pull_up(port, 0); + gpio_set_direction(port, 1); +} + +/*----------------------------------------------------------------------------*/ +/**@brief LED清屏函数, 把所有IO设置为高阻 + @param x:显示横坐标 + @return void + @author Change.tsai + @note void led7_clear(void) +*/ +/*----------------------------------------------------------------------------*/ +static void __ui_led7_clear_all(void) +{ + u8 port = 0; + u8 i; + + if (__this->user_data->pin_type == LED7_PIN7) { + for (i = 0; i < 7; i++) { + port = __this->user_data->pin_cfg.pin7.pin[i]; + __ui_led7_port_set_hz(port); + } + } + if (__this->user_data->pin_type == LED7_PIN12) { + for (i = 0; i < 7; i++) { + port = __this->user_data->pin_cfg.pin12.pin_segl[i]; + __ui_led7_port_set_hz(port); + } + for (i = 0; i < 5; i++) { + port = __this->user_data->pin_cfg.pin12.pin_comh[i]; + __ui_led7_port_set_hz(port); + } + } + + if (__this->user_data->pin_type == LED7_PIN13) { + for (i = 0; i < 7; i++) { + port = __this->user_data->pin_cfg.pin13.pin_seg[i]; + __ui_led7_port_set_hz(port); + } + for (i = 0; i < 6; i++) { + port = __this->user_data->pin_cfg.pin13.pin_com[i]; + __ui_led7_port_set_hz(port); + } + } + +} + +/*----------------------------------------------------------------------------*/ +/**@brief LED扫描函数 + @param void + @return void + @author Change.tsai + @note void led7_scan(void *param) +*/ +/*----------------------------------------------------------------------------*/ +void led7_scan(void *param) +{ + static u8 cnt = 0; + u8 seg, i; + + if (__this->init == false) { + return; + } + + __ui_led7_clear_all(); + + + if (!cnt && !__this->lock) { + __ui_led7_update_bShowbuf1(); + } + + seg = __this->led7_var.bShowBuff1[cnt]; + + if (__this->user_data->pin_type == LED7_PIN7) { + //pin cnt output H + gpio_set_hd0(__this->user_data->pin_cfg.pin7.pin[cnt], 1); + gpio_set_hd(__this->user_data->pin_cfg.pin7.pin[cnt], 1); + gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[cnt], 1); + for (i = 0; i < 7; i++) { + if (seg & BIT(i)) { + //pin i output L + gpio_set_hd0(__this->user_data->pin_cfg.pin7.pin[i], 0); + gpio_set_hd(__this->user_data->pin_cfg.pin7.pin[i], 0); + gpio_direction_output(__this->user_data->pin_cfg.pin7.pin[i], 0); + } + } + cnt = (cnt >= 6) ? 0 : cnt + 1; + } else if (__this->user_data->pin_type == LED7_PIN13) { + //pin_comh cnt output L + gpio_set_hd0(__this->user_data->pin_cfg.pin13.pin_com[cnt], 1); + gpio_set_hd(__this->user_data->pin_cfg.pin13.pin_com[cnt], 1); + gpio_direction_output(__this->user_data->pin_cfg.pin13.pin_com[cnt], 0); + for (i = 0; i < 7; i++) { + if (seg & BIT(i)) { + //pin_segl i output H + gpio_set_hd0(__this->user_data->pin_cfg.pin13.pin_seg[i], 0); + gpio_set_hd(__this->user_data->pin_cfg.pin13.pin_seg[i], 0); + gpio_direction_output(__this->user_data->pin_cfg.pin13.pin_seg[i], 1); + } + } + cnt = (cnt >= 5) ? 0 : cnt + 1; + } else { + //pin_comh cnt output H + gpio_set_hd0(__this->user_data->pin_cfg.pin12.pin_comh[cnt], 1); + gpio_set_hd(__this->user_data->pin_cfg.pin12.pin_comh[cnt], 1); + gpio_direction_output(__this->user_data->pin_cfg.pin12.pin_comh[cnt], 1); + for (i = 0; i < 7; i++) { + if (seg & BIT(i)) { + //pin_segl i output L + gpio_set_hd0(__this->user_data->pin_cfg.pin12.pin_segl[i], 0); + gpio_set_hd(__this->user_data->pin_cfg.pin12.pin_segl[i], 0); + gpio_direction_output(__this->user_data->pin_cfg.pin12.pin_segl[i], 0); + } + } + cnt = (cnt >= 4) ? 0 : cnt + 1; + } +} + + + +static void led7_setXY(u32 x, u32 y) +{ + led7_setX(x); +} + +static void led7_Flashchar(u32 arg) +{ + __this->led7_var.bFlashChar |= arg; +} + +static void led7_Clear_Flashchar(u32 arg) +{ + __this->led7_var.bFlashChar &= (~arg); +} + + +static void led7_show_pic(u32 arg) +{ + +} + +static void led7_hide_pic(u32 arg) +{ + +} + +static void led7_show_one_number(u8 number) +{ + led7_show_char(number + '0'); +} + +static void led7_show_lock(u32 en) +{ + __this->lock = !!en; +} + +static LCD_API LED7_HW = { + .clear = led7_show_null, + .setXY = led7_setXY, + .FlashChar = led7_Flashchar, + .Clear_FlashChar = led7_Clear_Flashchar, + .show_icon = led7_show_icon, + .flash_icon = led7_flash_icon, + .clear_icon = led7_clear_icon, + .show_string = led7_show_string, + .show_char = led7_show_char, + .show_number = led7_show_one_number, + .show_pic = led7_show_pic, + .hide_pic = led7_hide_pic, + .lock = led7_show_lock, +}; + + + + +/*----------------------------------------------------------------------------*/ +/**@brief led7段数码管初始化 + @param void + @return void + @author Change.tsai + @note void led7_init(void) +*/ +/*----------------------------------------------------------------------------*/ +void *led7_init(const struct led7_platform_data *_data) +{ + y_printf("========================== \n"); + led7_debug("%s", __func__); + memset(__this, 0x00, sizeof(struct ui_led7_env)); + if (_data == NULL) { + return NULL; + } + struct led7_platform_data *data = malloc(sizeof(struct led7_platform_data)); + if (!data) { + return NULL; + } + + memcpy(data, _data, sizeof(struct led7_platform_data)); + __this->user_data = data; + + __ui_led7_clear_all(); + /* sys_hi_timer_add(NULL, led7_scan, 2); //2ms */ + void app_timer_led_scan(void (*led_scan)(void *)); + app_timer_led_scan(led7_scan); + + __this->init = true; + return (void *)(&LED7_HW); +} + + +//=================================================================================// +// For Test Module // +//=================================================================================// +#if 0 //for test code +/* +LED7_PLATFORM_DATA_BEGIN(led7_test_data) + .pin_type = LED7_PIN7, + .pin_cfg.pin7.pin[0] = IO_PORTB_00, + .pin_cfg.pin7.pin[1] = IO_PORTB_01, + .pin_cfg.pin7.pin[2] = IO_PORTB_02, + .pin_cfg.pin7.pin[3] = IO_PORTB_03, + .pin_cfg.pin7.pin[4] = IO_PORTB_04, + .pin_cfg.pin7.pin[5] = IO_PORTB_05, + .pin_cfg.pin7.pin[6] = IO_PORTB_06, +LED7_PLATFORM_DATA_END() +*/ + +LED7_PLATFORM_DATA_BEGIN(led7_test_data) +.pin_type = LED7_PIN12, + .pin_cfg.pin12.pin_segl[0] = IO_PORTB_00, + .pin_cfg.pin12.pin_segl[1] = IO_PORTB_01, + .pin_cfg.pin12.pin_segl[2] = IO_PORTB_02, + .pin_cfg.pin12.pin_segl[3] = IO_PORTB_03, + .pin_cfg.pin12.pin_segl[4] = IO_PORTB_04, + .pin_cfg.pin12.pin_segl[5] = IO_PORTB_05, + .pin_cfg.pin12.pin_segl[6] = IO_PORTB_06, + + .pin_cfg.pin12.pin_comh[0] = IO_PORTA_00, + .pin_cfg.pin12.pin_comh[1] = IO_PORTB_08, + .pin_cfg.pin12.pin_comh[2] = IO_PORTB_09, + .pin_cfg.pin12.pin_comh[3] = IO_PORTB_10, + .pin_cfg.pin12.pin_comh[4] = IO_PORTA_01, + LED7_PLATFORM_DATA_END() + + void led7_scan_test(void) +{ + __ui_led7_scan(NULL); +} + +#define LED7_RTC_DISPLAY_TEST 1 +#define LED7_ICON_DISPLAY_TEST 1 +#define LED7_ICON_FLASH_TEST 0 +#define LED7_SHOW_NUMBER_TEST 0 +#define LED7_SHOW_STRING_TEST 0 +#define LED7_SHOW_MODE_MENU_TEST 0 + +void led7_test() +{ + if (__this->init == false) { + ui_led7_init(&led7_test_data); //init + } +#if LED7_RTC_DISPLAY_TEST + //test1: rtc display + static u8 Hour = 18; + static u8 Min = 52; + static u8 Sec = 0; + + Sec++; + if (Sec >= 60) { + Min++; + Sec = 0; + } + if (Min >= 60) { + Hour++; + Min = 0; + } + if (Hour >= 24) { + Hour = 0; + } + led7_debug("%d : %d", Hour, Min); + ui_led7_show_RTC_time(Hour, Min); +#endif /* #if LED7_RTC_DISPLAY_TEST */ + +#if LED7_ICON_DISPLAY_TEST + ui_led7_show_icon(LED7_PLAY); + ui_led7_show_icon(LED7_PAUSE); + ui_led7_show_icon(LED7_USB); //USB + ui_led7_show_icon(LED7_SD); //SD + ui_led7_show_icon(LED7_2POINT); // + ui_led7_show_icon(LED7_FM); + ui_led7_show_icon(LED7_DOT); // + ui_led7_show_icon(LED7_MP3); + ui_led7_show_icon(LED7_REPEAT); // + ui_led7_show_icon(LED7_CHARGE); // + ui_led7_show_icon(LED7_BT); // + ui_led7_show_icon(LED7_AUX); // + ui_led7_show_icon(LED7_WMA); // +#endif /* #if LED7_ICON_DISPLAY_TEST */ + +#if LED7_ICON_FLASH_TEST + ui_led7_flash_icon(LED7_PLAY); + ui_led7_flash_icon(LED7_PAUSE); + ui_led7_flash_icon(LED7_USB); + ui_led7_flash_icon(LED7_SD); + ui_led7_flash_icon(LED7_2POINT); + ui_led7_flash_icon(LED7_FM); + ui_led7_flash_icon(LED7_DOT); + ui_led7_flash_icon(LED7_MP3); + ui_led7_flash_icon(LED7_REPEAT); + ui_led7_flash_icon(LED7_CHARGE); + ui_led7_flash_icon(LED7_BT); + ui_led7_flash_icon(LED7_AUX); + ui_led7_flash_icon(LED7_WMA); +#endif /* #if LED7_ICON_FLASH_TEST */ + +#if LED7_SHOW_NUMBER_TEST + static u8 cnt = 0; + if (!(cnt % 5)) { + ui_led7_show_number(123); //高位显示0 + } else { + ui_led7_show_number2(123); //高位不显示0 + } + if (cnt == 0) { + ui_led7_setX(0); + } + ui_led7_show_number_add(cnt++); +#endif + +#if LED7_SHOW_STRING_TEST + /* static u8 cnt = '0'; */ + /* if (cnt < ('z' + 1)) { */ + /* ui_led7_show_char(cnt++); //显示数字 */ + /* } else { */ + /* cnt = '0'; */ + /* } */ + + /* u8 buf[3] = {0}; */ + /* if (cnt < 'z') { */ + /* buf[0] = cnt; */ + /* buf[1] = cnt + 1; */ + /* buf[2] = '\0'; */ + /* ui_led7_show_string(buf); //显示字符串 */ + /* cnt++; */ + /* } else { */ + /* cnt = '0'; */ + /* } */ +#endif + +#if LED7_SHOW_MODE_MENU_TEST + static u8 index = 0; + /* ui_led7_show_string_menu(index++); */ + /* if (index > ARRAY_SIZE(menu_string_table)) { */ + /* index = 0; */ + /* } */ + + //ui_led7_show_music_play_time(index++); + /* ui_led7_show_volume(index++); */ + /* if (index > 99) { */ + /* index = 0; */ + /* } */ + ui_led7_show_fm_station(index++); +#endif +} + +#endif /* for test code mcro */ + + +#endif /* #if TCFG_UI_LED7_ENABLE */ diff --git a/cpu/br23/ui_driver/led7/led7_driver_cfg.h b/cpu/br23/ui_driver/led7/led7_driver_cfg.h new file mode 100644 index 0000000..4a40b6c --- /dev/null +++ b/cpu/br23/ui_driver/led7/led7_driver_cfg.h @@ -0,0 +1,327 @@ +#ifndef _LED7_CFG_H_ +#define _LED7_CFG_H_ + + +#if TCFG_UI_LED7_ENABLE +//LED7真值表选择 +//7脚LED7 +// #define UI_LED7_PIN7_TRUE_TABLE1 +//#define UI_LED7_PIN7_TRUE_TABLE2 +#define UI_LED7_PIN7_TRUE_TABLE3 + +//12脚LED7 +//#define UI_LED7_PIN12_TRUE_TABLE1 +//13脚LED7 +// #define UI_LED7_PIN13_TRUE_TABLE1 + +#ifdef UI_LED7_PIN7_TRUE_TABLE1 +/*********** 数码管(7脚)真值表1 **************/ +/* + 0 1 2 3 4 5 6 +0 X 1A 1B 1E USB X X +1 1F X 2A 2B 2E 2D X +2 1G 2F X : 3B X X +3 1C 2G 3F X 3C 4E X +4 1D 2C 3G 3A X 4C 4G +5 3D SD 3E 4D 4F X 4B +6 CHARGE BT X REP DOT 4A X +*/ + +// 7断数码管通用数字类转换表 +static const struct seg2pin led7_digit_seg2pin[28] = { +//pinH, pinL + {0, 1}, //1A + {0, 2}, //1B + {3, 0}, //1C + {4, 0}, //1D + {0, 3}, //1E + {1, 0}, //1F + {2, 0}, //1G + + {1, 2}, //2A + {1, 3}, //2B + {4, 1}, //2C + {1, 5}, //2D + {1, 4}, //2E + {2, 1}, //2F + {3, 1}, //2G + + {4, 3}, //3A + {2, 4}, //3B + {3, 4}, //3C + {5, 0}, //3D + {5, 2}, //3E + {3, 2}, //3F + {4, 2}, //3G + + {6, 5}, //4A + {5, 6}, //4B + {4, 5}, //4C + {5, 3}, //4D + {3, 5}, //4E + {5, 4}, //4F + {4, 6}, //4G +}; + +// 数码管字母类转换表 +static const struct icon_seg2pin led7_icon_seg2pin[] = { + //icon pinH, pinL + {LED7_CHARGE, {6, 0}}, + {LED7_USB, {0, 4}}, + {LED7_SD, {5, 1}}, + {LED7_BT, {6, 1}}, //BT + {LED7_REPEAT, {6, 3}}, //REPEAT + {LED7_2POINT, {2, 3}}, //: + {LED7_DOT, {6, 4}} //. +}; + +#endif /* #ifdef UI_LED7_PIN7_TRUE_TABLE1 */ + + +#ifdef UI_LED7_PIN7_TRUE_TABLE2 +/*********** 数码管(7脚)真值表 2**************/ +/* 0 1 2 3 4 5 6 (L) +0 X 2A 2B 2C 2D 2E 2F +1 1A X 2G : . MHz MP3 +2 1B 1G X 4A 4B 4C 4D +3 1C PLAY 3A X 4E 4F 4G +4 1D PAUSE 3B 3E X X X +5 1E USB 3C 3F X X X +6 1F SD 3D 3G X X X */ +//(H) + +// 7断数码管通用数字类转换表 +static const struct seg2pin led7_digit_seg2pin[28] = { +//pinH, pinL + {1, 0}, //1A + {2, 0}, //1B + {3, 0}, //1C + {4, 0}, //1D + {5, 0}, //1E + {6, 0}, //1F + {2, 1}, //1G + + {0, 1}, //2A + {0, 2}, //2B + {0, 3}, //2C + {0, 4}, //2D + {0, 5}, //2E + {0, 6}, //2F + {1, 2}, //2G + + {3, 2}, //3A + {4, 2}, //3B + {5, 2}, //3C + {6, 2}, //3D + {4, 3}, //3E + {5, 3}, //3F + {6, 3}, //3G + + {2, 3}, //4A + {2, 4}, //4B + {2, 5}, //4C + {2, 6}, //4D + {3, 4}, //4E + {3, 5}, //4F + {3, 6}, //4G +}; + +// 数码管字母类转换表 +static const struct icon_seg2pin led7_icon_seg2pin[] = { + //icon pinH, pinL + {LED7_PLAY, {3, 1}}, + {LED7_PAUSE, {4, 1}}, + {LED7_USB, {5, 1}}, + {LED7_SD, {6, 1}}, + {LED7_2POINT, {1, 3}}, + {LED7_DOT, {1, 4}}, + {LED7_FM, {1, 5}}, + {LED7_MP3, {1, 6}}, +}; + +#endif /* #ifdef UI_LED7_PIN7_TRUE_TABLE2 */ + +#ifdef UI_LED7_PIN7_TRUE_TABLE3 +/*********** 数码管(7脚)真值表 2**************/ +/* 0 1 2 3 4 5 6 (L) +0 X 1A 1B 1E SD PAUSE X +1 1F X 2A 2B 2E 2D X +2 1G 2F X : 3B PLAY MP3 +3 1C 2G 3F X 3C 4E X +4 1D 2C 3G 3A X 4C 4G +5 3D USB 3E 4D 4F X 4B +6 X X FM X . 4A X */ +//(H) + +// 7断数码管通用数字类转换表 +static const struct seg2pin led7_digit_seg2pin[28] = { +//pinH, pinL + {0, 1}, //1A + {0, 2}, //1B + {3, 0}, //1C + {4, 0}, //1D + {0, 3}, //1E + {1, 0}, //1F + {2, 0}, //1G + + {1, 2}, //2A + {1, 3}, //2B + {4, 1}, //2C + {1, 5}, //2D + {1, 4}, //2E + {2, 1}, //2F + {3, 1}, //2G + + {4, 3}, //3A + {2, 4}, //3B + {3, 4}, //3C + {5, 0}, //3D + {5, 2}, //3E + {3, 2}, //3F + {4, 2}, //3G + + {6, 5}, //4A + {5, 6}, //4B + {4, 5}, //4C + {5, 3}, //4D + {3, 5}, //4E + {5, 4}, //4F + {4, 6}, //4G +}; + +// 数码管字母类转换表 +static const struct icon_seg2pin led7_icon_seg2pin[] = { + //icon pinH, pinL + {LED7_PLAY, {2, 5}}, + {LED7_PAUSE, {0, 5}}, + {LED7_USB, {5, 1}}, + {LED7_SD, {0, 4}}, + {LED7_2POINT, {2, 3}}, + {LED7_DOT, {6, 4}}, + {LED7_FM, {6, 2}}, + {LED7_MP3, {2, 6}}, +}; + +#endif /* #ifdef UI_LED7_PIN7_TRUE_TABLE2 */ + + + +#ifdef UI_LED7_PIN12_TRUE_TABLE1 +/*********** 数码管(12脚)真值表**************/ +/* 0 1 2 3 4 5 6 +COM0 1A 1B 1C 1D 1E 1F 1G +COM1 2A 2B 2C 2D 2E 2F 2G +COM2 3A 3B 3C 3D 3E 3F 3G +COM3 4A 4B 4C 4D 4E 4F 4G +COM4 AUX FM USB SD : WMA MP3 +*/ + +// 7断数码管通用数字类转换表 +static const struct seg2pin led7_digit_seg2pin[28] = { +//comH, segL + {0, 0}, //1A + {0, 1}, //1B + {0, 2}, //1C + {0, 3}, //1D + {0, 4}, //1E + {0, 5}, //1F + {0, 6}, //1G + + {1, 0}, //2A + {1, 1}, //2B + {1, 2}, //2C + {1, 3}, //2D + {1, 4}, //2E + {1, 5}, //2F + {1, 6}, //2G + + {2, 0}, //3A + {2, 1}, //3B + {2, 2}, //3C + {2, 3}, //3D + {2, 4}, //3E + {2, 5}, //3F + {2, 6}, //3G + + {3, 0}, //4A + {3, 1}, //4B + {3, 2}, //4C + {3, 3}, //4D + {3, 4}, //4E + {3, 5}, //4F + {3, 6}, //4G +}; + +//数码管字母类转换表 +static const struct icon_seg2pin led7_icon_seg2pin[] = { + //icon comH, segL + {LED7_AUX, {4, 0}}, + {LED7_FM, {4, 1}}, + {LED7_USB, {4, 2}}, + {LED7_SD, {4, 3}}, + {LED7_2POINT, {4, 4}}, + {LED7_WMA, {4, 5}}, + {LED7_MP3, {4, 6}}, +}; +#endif /* #ifdef UI_LED7_PIN12_TRUE_TABLE1 */ + +#ifdef UI_LED7_PIN13_TRUE_TABLE1 +/*********** 数码管(12脚)真值表**************/ +/* 0 1 2 3 4 5 6 +COM0 1A 1B 1C 1D 1E 1F 1G +COM1 2A 2B 2C 2D 2E 2F 2G +COM2 3A 3B 3C 3D 3E 3F 3G +COM3 4A 4B 4C 4D 4E 4F 4G +COM4 AM PM AUX FM MUSIC 24H CLK1 +COM5 CLK2 BT : BAT1 BAT2 BAT3 BAT4 +*/ + +// 7断数码管通用数字类转换表 +static const struct seg2pin led7_digit_seg2pin[28] = { +//comL, segH + {0, 0}, //1A + {0, 1}, //1B + {0, 2}, //1C + {0, 3}, //1D + {0, 4}, //1E + {0, 5}, //1F + {0, 6}, //1G + + {1, 0}, //2A + {1, 1}, //2B + {1, 2}, //2C + {1, 3}, //2D + {1, 4}, //2E + {1, 5}, //2F + {1, 6}, //2G + + {2, 0}, //3A + {2, 1}, //3B + {2, 2}, //3C + {2, 3}, //3D + {2, 4}, //3E + {2, 5}, //3F + {2, 6}, //3G + + {3, 0}, //4A + {3, 1}, //4B + {3, 2}, //4C + {3, 3}, //4D + {3, 4}, //4E + {3, 5}, //4F + {3, 6}, //4G +}; + +//数码管字母类转换表 +static const struct icon_seg2pin led7_icon_seg2pin[] = { + //icon comL, segH + {LED7_AUX, {4, 2}}, + {LED7_FM, {4, 3}}, + {LED7_BT, {5, 1}}, + {LED7_2POINT, {5, 2}}, +}; +#endif /* #ifdef UI_LED7_PIN13_TRUE_TABLE1 */ + +#endif +#endif /* #ifndef _LED7_CFG_H_ */ + diff --git a/cpu/br23/ui_driver/oled/oled.h b/cpu/br23/ui_driver/oled/oled.h new file mode 100644 index 0000000..d27ed77 --- /dev/null +++ b/cpu/br23/ui_driver/oled/oled.h @@ -0,0 +1,64 @@ +#ifndef __OLED_H +#define __OLED_H + +#include "typedef.h" + +//OLED的显存 +//存放格式如下. +//[0]0 1 2 3 ... 127 +//[1]0 1 2 3 ... 127 +//[2]0 1 2 3 ... 127 +//[3]0 1 2 3 ... 127 +//[4]0 1 2 3 ... 127 +//[5]0 1 2 3 ... 127 +//[6]0 1 2 3 ... 127 +//[7]0 1 2 3 ... 127 + +#define OLED_CMD 0 +#define OLED_DATA 1 + +#define OLED_CS_Clr() //gpio_direction_output(IO_PORTC_00, 1) +#define OLED_CS_Set() //gpio_direction_output(IO_PORTC_00, 1) + + +#define OLED_RST_Clr() gpio_direction_output(IO_PORTA_00, 0) +#define OLED_RST_Set() gpio_direction_output(IO_PORTA_00, 1) + +#define OLED_DC_Clr() //OLED_DC=0 +#define OLED_DC_Set() //OLED_DC=1 + +#define OLED_SCLK_Clr() gpio_direction_output(IO_PORTA_01, 0) +#define OLED_SCLK_Set() gpio_direction_output(IO_PORTA_01, 1) + + +#define OLED_SDIN_Clr() gpio_direction_output(IO_PORTA_03, 0) +#define OLED_SDIN_Set() gpio_direction_output(IO_PORTA_03, 1) + + + + +#define SIZE 16 +#define XLevelL 0x02 +#define XLevelH 0x10 +#define Max_Column 128 +#define Max_Row 64 +#define Brightness 0xFF +#define X_WIDTH 128 +#define Y_WIDTH 64 + +void OLED_Display_On(void); +void OLED_Display_Off(void); +void OLED_Init(void); +void OLED_Clear(void); +void OLED_DrawPoint(u8 x,u8 y,u8 t); +void OLED_Fill(u8 x1,u8 y1,u8 x2,u8 y2,u8 dot); +void OLED_ShowChar(u8 x,u8 y,u8 chr); +void OLED_ShowNum(u8 x,u8 y,u32 num,u8 len,u8 size2); +void OLED_ShowString(u8 x,u8 y, u8 *p); +void OLED_Set_Pos(unsigned char x, unsigned char y); +void OLED_ShowCHinese(u8 x,u8 y,u8 no); +void OLED_DrawBMP(unsigned char x0, unsigned char y0,unsigned char x1, unsigned char y1,unsigned char BMP[]); +#endif + + + diff --git a/cpu/br23/ui_driver/ui_common.c b/cpu/br23/ui_driver/ui_common.c new file mode 100644 index 0000000..c9a8f13 --- /dev/null +++ b/cpu/br23/ui_driver/ui_common.c @@ -0,0 +1,66 @@ +/*--------------------------------------------------------------------------*/ +/**@file UI_common.c + @brief UI 显示公共函数 + @details + @author bingquan Cai + @date 2012-8-30 + @note AC319N +*/ +/*----------------------------------------------------------------------------*/ +#include "includes.h" + +static const u8 asc_number[] = "0123456789"; ///<0~9的ASCII码表 + +/*----------------------------------------------------------------------------*/ +/**@brief 获取一个一位十进制的数的个位 + @param i:输入的一个一位十进制的数 + @return 无 + @note void itoa1(u8 i, u8 *buf) +*/ +/*----------------------------------------------------------------------------*/ +void itoa1(u8 i, u8 *buf) +{ + buf[0] = asc_number[i % 10]; +} + +/*----------------------------------------------------------------------------*/ +/**@brief 获取一个2位十进制的数的各个位 + @param i:输入的一个2位十进制的数 + @return 无 + @note void itoa2(u8 i) +*/ +/*----------------------------------------------------------------------------*/ +void itoa2(u8 i, u8 *buf) +{ + buf[0] = asc_number[(i % 100) / 10]; + buf[1] = asc_number[(i % 10)]; +} +/*----------------------------------------------------------------------------*/ +/**@brief 获取一个3位十进制数的各个位 + @param i:输入的一个3位十进制数 + @return 无 + @note void itoa3(u8 i, u8 *buf) +*/ +/*----------------------------------------------------------------------------*/ +void itoa3(u16 i, u8 *buf) +{ + buf[0] = asc_number[(i % 1000) / 100]; + buf[1] = asc_number[(i % 100) / 10]; + buf[2] = asc_number[i % 10]; +} +/*----------------------------------------------------------------------------*/ +/**@brief 获取一个4位十进制的数的各个位 + @param i:输入的一个4位十进制的数 + @return 无 + @note void itoa4(u8 i, u8 *buf) +*/ +/*----------------------------------------------------------------------------*/ +void itoa4(u16 i, u8 *buf) +{ + buf[0] = asc_number[(i % 10000) / 1000]; //千 + buf[1] = asc_number[(i % 1000) / 100]; //百 + buf[2] = asc_number[(i % 100) / 10]; //十 + buf[3] = asc_number[i % 10]; //个 +} + + diff --git a/include_lib/btctrler/ble/hci_ll.h b/include_lib/btctrler/ble/hci_ll.h new file mode 100644 index 0000000..e693890 --- /dev/null +++ b/include_lib/btctrler/ble/hci_ll.h @@ -0,0 +1,124 @@ +/********************************************************************************************* + * Filename : hci_ll.h + + * Description : 提供Vendor Host 直接调用Controller API LL Part + + * Author : Bingquan + + * Email : bingquan_cai@zh-jieli.com + + * Last modifiled : 2018-12-04 11:58 + + * Copyright:(c)JIELI 2011-2017 @ , All Rights Reserved. +*********************************************************************************************/ +#ifndef _HCI_LL_H_ +#define _HCI_LL_H_ + +#include +#include +#include + +#include "typedef.h" + +enum { + LL_EVENT_SUPERVISION_TIMEOUT, + LL_EVENT_RX, + LL_EVENT_ACL_TX_POST, +}; + +typedef struct { + u8 Own_Address_Type: 2; + u8 Adv_Filter_Policy: 2; + u8 Scan_Filter_Policy: 2; + u8 initiator_filter_policy: 2; +} hci_ll_param_t; + +//Adjust Host part API +void ll_hci_init(void); + +void ll_hci_reset(void); + +void ll_hci_destory(void); + +void ll_hci_set_event_mask(const u8 *mask); + +void ll_hci_set_name(const char *name); + +void ll_hci_adv_set_params(uint16_t adv_int_min, uint16_t adv_int_max, uint8_t adv_type, + uint8_t direct_address_type, uint8_t *direct_address, + uint8_t channel_map, uint8_t filter_policy); + +void ll_hci_adv_set_data(uint8_t advertising_data_length, uint8_t *advertising_data); + +void ll_hci_adv_scan_response_set_data(uint8_t scan_response_data_length, uint8_t *scan_response_data); + +int ll_hci_adv_enable(bool enable); + +void ll_hci_scan_set_params(uint8_t scan_type, uint16_t scan_interval, uint16_t scan_window); + +int ll_hci_scan_enable(bool enable, u8 filter_duplicates); + +int ll_hci_create_conn(u8 *conn_param, u8 *addr_param); + +int ll_hci_create_conn_cancel(void); + +int ll_hci_vendor_send_key_num(u16 con_handle, u8 num); + +int ll_vendor_latency_hold_cnt(u16 conn_handle, u16 hold_cnt); + +int ll_hci_encryption(u8 *key, u8 *plaintext_data); + +int ll_hci_get_le_rand(void); + + +int ll_hci_start_encryption(u16 handle, u32 rand_low, u32 rand_high, u16 peer_ediv, u8 *ltk); + +int ll_hci_long_term_key_request_reply(u16 handle, u8 *ltk); + +int ll_hci_long_term_key_request_nagative_reply(u16 handle); + +int ll_hci_connection_update(u16 handle, u16 conn_interval_min, u16 conn_interval_max, + u16 conn_latency, u16 supervision_timeout, + u16 minimum_ce_length, u16 maximum_ce_length); + +u16 ll_hci_get_acl_data_len(void); + +u16 ll_hci_get_acl_total_num(void); + +void ll_hci_set_random_address(u8 *addr); + +int ll_hci_disconnect(u16 handle, u8 reason); + +int ll_hci_read_local_p256_pb_key(void); + +int ll_hci_generate_dhkey(const u8 *data, u32 size); + +//Adjust Controller part API +void ll_hci_cmd_handler(int *cmd); + +void ll_event_handler(int *msg); + +void ll_hci_private_free_dma_rx(u8 *rx_head); + +void ll_hci_set_data_length(u16 conn_handle, u16 tx_octets, u16 tx_time); + +hci_ll_param_t *ll_hci_param_config_get(void); +void hci_ll_get_device_address(uint8_t *addr_type, u8 *addr); + +// ble5 +void ll_hci_set_ext_adv_params(u8 *data, u32 size); +void ll_hci_set_ext_adv_data(u8 *data, u32 size); +void ll_hci_set_ext_adv_enable(u8 *data, u32 size); +void ll_hci_set_phy(u16 conn_handle, u8 all_phys, u8 tx_phy, u8 rx_phy, u16 phy_options); +void ll_hci_set_ext_scan_params(u8 *data, u32 size); +void ll_hci_set_ext_scan_enable(u8 *data, u32 size); +void ll_hci_ext_create_conn(u8 *data, u32 size); +void ll_hci_set_periodic_adv_params(u8 *data, u32 size); +void ll_hci_set_periodic_adv_data(u8 *data, u32 size); +void ll_hci_set_periodic_adv_enable(u8 *data, u32 size); +void ll_hci_periodic_adv_creat_sync(u8 *data, u32 size); +void ll_hci_set_host_channel_classification(u8 *channel_map); + +int le_controller_set_mac(void *addr); + +#endif diff --git a/include_lib/btctrler/ble/ll_config.h b/include_lib/btctrler/ble/ll_config.h new file mode 100644 index 0000000..69a95b5 --- /dev/null +++ b/include_lib/btctrler/ble/ll_config.h @@ -0,0 +1,177 @@ +/********************************************************************************************* + * Filename : ll_config.h + + * Description : Lto 优化Macro 定义 + + * Author : Bingquan + + * Email : bingquan_cai@zh-jieli.com + + * Last modifiled : 2018-12-19 16:12 + + * Copyright:(c)JIELI 2011-2017 @ , All Rights Reserved. +*********************************************************************************************/ +#ifndef _LL_CONFIG_H_ +#define _LL_CONFIG_H_ +#include //for UINT64_C + +/* + *-------------------LE FEATURE SUPPORT + * brief : 运行时优化(LTO)下,代码空间优化; + */ + +/* --- Core Spec 4.0 --- */ +#define LL_FEAT_ENCRYPTION (UINT64_C(1) << ( 0)) /*!< Encryption supported. */ +/* --- Core Spec 4.2 --- */ +#define LL_FEAT_CONN_PARAM_REQ_PROC (UINT64_C(1) << ( 1)) /*!< Connection Parameters Request Procedure supported. */ +#define LL_FEAT_EXT_REJECT_IND (UINT64_C(1) << ( 2)) /*!< Extended Reject Indication supported. */ +#define LL_FEAT_SLV_INIT_FEAT_EXCH (UINT64_C(1) << ( 3)) /*!< Slave-Initiated Features Exchange supported. */ +#define LL_FEAT_LE_PING (UINT64_C(1) << ( 4)) /*!< LE Ping supported. */ +#define LL_FEAT_DATA_LEN_EXT (UINT64_C(1) << ( 5)) /*!< Data Length Extension supported. */ +#define LL_FEAT_PRIVACY (UINT64_C(1) << ( 6)) /*!< LL Privacy supported. */ +#define LL_FEAT_EXT_SCAN_FILT_POLICY (UINT64_C(1) << ( 7)) /*!< Extended Scan Filter Policy supported. */ +/* --- Core Spec 5.0 --- */ +#define LL_FEAT_LE_2M_PHY (UINT64_C(1) << ( 8)) /*!< LE 2M PHY supported. */ +#define LL_FEAT_STABLE_MOD_IDX_TRANSMITTER (UINT64_C(1) << ( 9)) /*!< Stable Modulation Index - Transmitter supported. */ +#define LL_FEAT_STABLE_MOD_IDX_RECEIVER (UINT64_C(1) << (10)) /*!< Stable Modulation Index - Receiver supported. */ +#define LL_FEAT_LE_CODED_PHY (UINT64_C(1) << (11)) /*!< LE Coded PHY supported. */ +#define LL_FEAT_LE_EXT_ADV (UINT64_C(1) << (12)) /*!< LE Extended Advertising supported. */ +#define LL_FEAT_LE_PER_ADV (UINT64_C(1) << (13)) /*!< LE Periodic Advertising supported. */ +#define LL_FEAT_CH_SEL_2 (UINT64_C(1) << (14)) /*!< Channel Selection Algorithm #2 supported. */ +#define LL_FEAT_LE_POWER_CLASS_1 (UINT64_C(1) << (15)) /*!< LE Power Class 1 supported. */ +#define LL_FEAT_MIN_NUM_USED_CHAN (UINT64_C(1) << (16)) /*!< Minimum Number of Used Channels supported. */ +/* --- Core Spec 5.1 --- */ +#define LL_FEAT_CONN_CTE_REQ (UINT64_C(1) << (17)) /*!< Connection CTE Request supported */ +#define LL_FEAT_CONN_CTE_RSP (UINT64_C(1) << (18)) /*!< Connection CTE Response supported */ +#define LL_FEAT_CONNLESS_CTE_TRANS (UINT64_C(1) << (19)) /*!< Connectionless CTE Transmitter supported */ +#define LL_FEAT_CONNLESS_CTE_RECV (UINT64_C(1) << (20)) /*!< Connectionless CTE Receiver supported */ +#define LL_FEAT_ANTENNA_SWITCH_AOD (UINT64_C(1) << (21)) /*!< Anetenna Switching during CTE Transmission (AoD) supported */ +#define LL_FEAT_ANTENNA_SWITCH_AOA (UINT64_C(1) << (22)) /*!< Anetenna Switching during CTE Reception (AoA) supported */ +#define LL_FEAT_RECV_CTE (UINT64_C(1) << (23)) /*!< Receive Constant Tone Extension supported */ +#define LL_FEAT_PAST_SENDER (UINT64_C(1) << (24)) /*!< Periodic Advertising Sync Transfer – Sender supported. */ +#define LL_FEAT_PAST_RECIPIENT (UINT64_C(1) << (25)) /*!< Periodic Advertising Sync Transfer – Recipient supported. */ +#define LL_FEAT_SCA_UPDATE (UINT64_C(1) << (26)) /*!< Sleep Clock Accuracy Updates supported. */ +#define LL_FEAT_REMOTE_PUB_KEY_VALIDATION (UINT64_C(1) << (27)) /*!< Remote Public Key Validation supported. */ +/* --- Core Spec 5.2 --- */ +#define LL_FEAT_CIS_MASTER_ROLE (UINT64_C(1) << (28)) /*!< Connected Isochronous Stream Master Role supported. */ +#define LL_FEAT_CIS_SLAVE_ROLE (UINT64_C(1) << (29)) /*!< Connected Isochronous Stream Slave Role supported. */ +#define LL_FEAT_ISO_BROADCASTER (UINT64_C(1) << (30)) /*!< Isochronous Broadcaster Role supported. */ +#define LL_FEAT_ISO_SYNC (UINT64_C(1) << (31)) /*!< Isochronous Synchronizer Role supported. */ +#define LL_FEAT_ISO_HOST_SUPPORT (UINT64_C(1) << (32)) /*!< Host support for ISO Channels. */ +#define LL_FEAT_POWER_CONTROL_REQUEST (UINT64_C(1) << (33)) /*!< Power control requests supported. */ +#define LL_FEAT_POWER_CHANGE_IND (UINT64_C(1) << (34)) /*!< Power control power change indication supported. */ +#define LL_FEAT_PATH_LOSS_MONITOR (UINT64_C(1) << (35)) /*!< Path loss monitoring supported. */ + +#define LE_ENCRYPTION LL_FEAT_ENCRYPTION +#define CONNECTION_PARAMETER_REQUEST LL_FEAT_CONN_PARAM_REQ_PROC +#define EXTENDED_REJECT_INDICATION LL_FEAT_EXT_REJECT_IND +#define LE_SLAVE_INIT_FEATURES_EXCHANGE LL_FEAT_SLV_INIT_FEAT_EXCH +#define LE_PING LL_FEAT_LE_PING +#define LE_DATA_PACKET_LENGTH_EXTENSION LL_FEAT_DATA_LEN_EXT +#define LL_PRIVACY LL_FEAT_PRIVACY +#define EXTENDED_SCANNER_FILTER_POLICIES LL_FEAT_EXT_SCAN_FILT_POLICY +#define LE_2M_PHY LL_FEAT_LE_2M_PHY +#define LE_CODED_PHY LL_FEAT_LE_CODED_PHY +#define LE_EXTENDED_ADVERTISING LL_FEAT_LE_EXT_ADV +#define LE_PERIODIC_ADVERTISING LL_FEAT_LE_PER_ADV +#define CHANNEL_SELECTION_ALGORITHM_2 LL_FEAT_CH_SEL_2 + + +#define LE_CORE_V50_FEATURES \ +( \ + LE_2M_PHY | \ + LE_CODED_PHY | \ + LE_EXTENDED_ADVERTISING | \ + LE_PERIODIC_ADVERTISING | \ + CHANNEL_SELECTION_ALGORITHM_2 | \ + 0 \ +) + +#if (LE_CORE_V50_FEATURES & LE_PERIODIC_ADVERTISING) +#if ((LE_CORE_V50_FEATURES & LE_EXTENDED_ADVERTISING) == 0) +#error "enable must enable at the same time" +#endif +#endif + +#define LE_FEATURES_CONST_TONE (LL_FEAT_CONN_CTE_REQ | \ + LL_FEAT_CONN_CTE_RSP | \ + LL_FEAT_CONNLESS_CTE_TRANS | \ + LL_FEAT_CONNLESS_CTE_RECV | \ + LL_FEAT_ANTENNA_SWITCH_AOD | \ + LL_FEAT_ANTENNA_SWITCH_AOA | \ + LL_FEAT_RECV_CTE) + +#define LE_FEATURES_CIS (LL_FEAT_CIS_MASTER_ROLE | \ + LL_FEAT_CIS_SLAVE_ROLE | \ + LL_FEAT_ISO_HOST_SUPPORT) + +#define LE_FEATURES_BIS (LL_FEAT_ISO_BROADCASTER | \ + LL_FEAT_ISO_SYNC | \ + LL_FEAT_ISO_HOST_SUPPORT) + +#define LE_FEATURES_ISO (LE_FEATURES_BIS|LE_FEATURES_CIS) + +#define LE_FEATURES_POWER_CONTROL (LL_FEAT_POWER_CONTROL_REQUEST | \ + LL_FEAT_POWER_CHANGE_IND | \ + LL_FEAT_PATH_LOSS_MONITOR) + +extern const uint64_t config_btctler_le_features; +#define LE_FEATURES_IS_SUPPORT(x) (config_btctler_le_features & (x)) + +#define LE_FEATURES_IS_SUPPORT_OPTIMIZE(x) if (LE_FEATURES_IS_SUPPORT(x) == 0x0) return +/*-----------------------------------------------------------*/ + +/* + *-------------------LE ROLES SUPPORT + * brief : 运行时优化(LTO)下,代码空间优化; + */ +#define LE_MASTER BIT(0) +#define LE_SLAVE BIT(1) +#define LE_ADV BIT(2) +#define LE_SCAN BIT(3) +#define LE_INIT BIT(4) + +/*! \brief Combination */ +#define LE_CONN (LE_MASTER|LE_SLAVE) + +extern const int config_btctler_le_roles; +#define LE_ROLES_IS_SUPPORT(x) (config_btctler_le_roles & x) + +#define LE_ROLES_IS_SUPPORT_OPTIMIZE(x) if (LE_ROLES_IS_SUPPORT(x) == 0x0) return +/*-----------------------------------------------------------*/ + +extern const int config_btctler_le_tws; +#define LE_TWS_IS_SUPPORT() (config_btctler_le_tws) + + +/*-----------------------------------------------------------*/ + +extern const int config_btctler_le_afh_en; +#define LE_AFH_IS_SUPPORT() (config_btctler_le_afh_en) + +#define LE_AFH_IS_SUPPORT_OPTIMIZE(x) if (LE_AFH_IS_SUPPORT() == 0x0) return + +/* + *-------------------LE PARAM CHECK + * brief : 运行时优化(LTO)下,代码空间优化; + */ +// extern const int config_btctler_le_param_check; +#define LE_PARAM_IS_CHECK() TRUE//(config_btctler_le_param_check) +/* + *-------------------LE RAM CONTROL + * + */ +extern const int config_btctler_le_hw_nums; +extern const int config_btctler_le_rx_nums; +extern const int config_btctler_le_acl_packet_length; +extern const int config_btctler_le_acl_total_nums; +extern const int config_btctler_le_slave_conn_update_winden; +/*-----------------------------------------------------------*/ + +/* + *-------------------LE Multi-link CONTROL + */ +extern const int config_btctler_le_master_multilink; +/*-----------------------------------------------------------*/ + +#endif //_LL_CONFIG_H_ diff --git a/include_lib/btctrler/btcontroller_mode.h b/include_lib/btctrler/btcontroller_mode.h new file mode 100644 index 0000000..3cae87c --- /dev/null +++ b/include_lib/btctrler/btcontroller_mode.h @@ -0,0 +1,59 @@ +/********************************************************************************************* + * Filename : btcontroller_modules.h + + * Description : Lto 优化Macro 定义 + + * Author : Bingquan + + * Email : bingquan_cai@zh-jieli.com + + * Last modifiled : 2018-12-19 16:38 + + * Copyright:(c)JIELI 2011-2017 @ , All Rights Reserved. +*********************************************************************************************/ +#ifndef _BTCONTROLLER_MODE_H_ +#define _BTCONTROLLER_MODE_H_ + +/* +ble 测试串口默认使用usb口,代码要确保usb口没有其他地方使用 +开启测试模式,uart0 key 等一些功能默认关闭,请看特殊情况 +自行处理 + +1、提供实验室测试rf bqb的时候配 BT_BQB + +2、提供实验室测试rf fcc的时候配 BT_FCC + +3、如果要定频测试配BT_FRE 频点:2402 , 发射功率最大 + +4、性能测试配BT_PER,使用仪器直接连接测试即可,测试完毕后 +需要复位或者上电开机才会恢复正常流程,不复位或上电的话只支持链接一个设备 + +量产测试性能可直接配BT_NORMAL 然后通过某个外部操作来 +调用 void bredr_set_dut_enble(u8 en,u8 phone ) +en 1 :使能 bredr dut 测试然后就可以使用仪器链接测试 +phone: 1 可以被手机连接,0 不可以被手机连接上 + +如果样机通过按键等操作进入dut测试调用bredr_set_dut_enble使能可以被仪器链接, +同时调用下面函数,关闭耳机快速链接,开启可发现可链接 + tws_cancle_all_noconn() ; + user_send_cmd_prepare(USER_CTRL_WRITE_SCAN_ENABLE, 0, NULL); + user_send_cmd_prepare(USER_CTRL_WRITE_CONN_ENABLE, 0, NULL); + + +5、可以调用 void bt_fix_fre_api() 函数实现经典蓝牙定频测试,频点2402,发射功率最大, +调用后不可恢复之前状态,只是用来量产测试,测试完需要复位或重新上电开机! + +6、可以调用 void ble_fix_fre_api()函数实现ble定频测试,发射功率最大, + +*/ + +#define BT_NORMAL 0x01 +#define BT_BQB 0x02 +#define BT_FCC 0x04 +#define BT_FRE 0x10 +#define BT_PER 0x20 + + +#define CONFIG_BT_MODE BT_NORMAL + +#endif diff --git a/include_lib/btctrler/btcontroller_modules.h b/include_lib/btctrler/btcontroller_modules.h new file mode 100644 index 0000000..ac2410e --- /dev/null +++ b/include_lib/btctrler/btcontroller_modules.h @@ -0,0 +1,224 @@ +/********************************************************************************************* + * Filename : btcontroller_modules.h + + * Description : Lto 优化Macro 定义 + + * Author : Bingquan + + * Email : bingquan_cai@zh-jieli.com + + * Last modifiled : 2018-12-19 16:38 + + * Copyright:(c)JIELI 2011-2017 @ , All Rights Reserved. +*********************************************************************************************/ +#ifndef _BTCONTROLLER_H_ +#define _BTCONTROLLER_H_ + +#include "hci_transport.h" +#include "btcontroller_mode.h" + +#include "ble/hci_ll.h" + +#include "classic/hci_lmp.h" + + +/* app 层修改蓝牙版本,可在BT_STATUS_INIT_OK case + 调用 set_bt_version 函数更改蓝牙版本号 +*/ +#define BLUETOOTH_CORE_SPEC_42 0x08 +#define BLUETOOTH_CORE_SPEC_50 0x09 +#define BLUETOOTH_CORE_SPEC_51 0x0a +#define BLUETOOTH_CORE_SPEC_52 0x0b +extern void set_bt_version(u8 version); + + +/* + *-------------------Module SUPPORT + * brief : 运行时优化(LTO)下,代码空间优化; + */ +#define BT_MODULE_CLASSIC BIT(0) +#define BT_MODULE_LE BIT(1) + +extern const int config_btctler_modules; +#define BT_MODULES_IS_SUPPORT(x) (config_btctler_modules & (x)) +/*-----------------------------------------------------------*/ +extern const int config_stack_modules; +#define STACK_MODULES_IS_SUPPORT(x) (config_stack_modules & (x)) + +/* + *-------------------Mode SELECT + * brief : 运行时优化(LTO)下,代码空间优化; + */ +extern const int config_btctler_mode; +#define BT_MODE_IS(x) (config_btctler_mode & (x)) + +/*-----------------------------------------------------------*/ + +extern const int config_btctler_hci_standard; +#define BT_HCI_STANDARD_IS_SUPPORT(x) (config_btctler_hci_standard) + + +extern const int config_bt_function ; +#define BT_ENCTRY_TASK BIT(0) +#define BT_MASTER_AFH BIT(1) +#define BT_MASTER_QOS BIT(2) + + +#define BT_FUNCTION_IS(x) (config_bt_function & (x)) + + +extern const int CONFIG_TEST_DUT_CODE; +extern const int CONFIG_TEST_FCC_CODE; +extern const int CONFIG_TEST_DUT_ONLY_BOX_CODE; +extern const int CONFIG_BREDR_INQUIRY; + +extern const int CONFIG_INQUIRY_PAGE_OFFSET_ADJUST ; + +extern const int CONFIG_LMP_NAME_REQ_ENABLE ; +extern const int CONFIG_LMP_PASSKEY_ENABLE ; +extern const int CONFIG_LMP_MASTER_ESCO_ENABLE ; +extern const int config_btctler_bredr_master ; +extern const int config_bredr_afh_user ; +extern const int config_bredr_master_afh ; +extern const int CONFIG_ESCO_MUX_RX_BULK_ENABLE ; +extern const int config_bt_temperature_pll_trim ; +extern const int CONFIG_WIFI_DETECT_ENABLE; +/********************************************************************************/ +/* + * API + * + */ + +/* --------------------------------------------------------------------------*/ +/** + * @brief rf_set_24g_hackable_coded + * + * @param coded 2.4G 配对码 + */ +/* ----------------------------------------------------------------------------*/ +void rf_set_24g_hackable_coded(int coded); + + +/* --------------------------------------------------------------------------*/ +/** + * @brief bt_pll_para + * + * @param osc + * @param sys + * @param low_power + * @param xosc + */ +/* ----------------------------------------------------------------------------*/ +void bt_pll_para(u32 osc, u32 sys, u8 low_power, u8 xosc); + + +/* --------------------------------------------------------------------------*/ +/** + * @brief bt_production_test + * + * @param en + */ +/* ----------------------------------------------------------------------------*/ +void bt_production_test(u8 en); + +/* --------------------------------------------------------------------------*/ +/** + * @brief bt_set_rxtx_status_enable + * + * @param en + * + * + + TX RX + AI800x PA13 PA12 + AC692x PA13 PA12 + AC693x PA8 PA9 + AC695x PA9 PA10 + AC696x PC1 PC2 + AC694x PB1 PB2 + AC697x PC2 PC3 + AC631x PA7 PA8 + + */ +/* ----------------------------------------------------------------------------*/ +void bt_set_rxtx_status_enable(u8 en); + +/* --------------------------------------------------------------------------*/ +/** + * @brief bt_osc_offset_ext_save + * + * @param offset + * + * 更新并且保存频偏 + */ +/* ----------------------------------------------------------------------------*/ +void bt_osc_offset_ext_save(s32 offset); + +/* --------------------------------------------------------------------------*/ +/** + * @brief bt_osc_offset_ext_updata + * + * @param offset + * + * 更新频偏 + */ +/* ----------------------------------------------------------------------------*/ +void bt_osc_offset_ext_updata(s32 offset); + +/* --------------------------------------------------------------------------*/ +/** + * @brief 初始化配置蓝牙发射功率最大值范围 + * + * @param pwr edr 连接后发射功率(range:0~9) + * @param pg_pwr edr page 可连接状态发射功率 + * @param iq_pwr edr inquiry 可发现状态发射功率 + * @param ble_pwr ble 发射功率 + */ +/* ----------------------------------------------------------------------------*/ +void bt_max_pwr_set(u8 pwr, u8 pg_pwr, u8 iq_pwr, u8 ble_pwr); + +/* --------------------------------------------------------------------------*/ +/** + * @brief bt_set_ldos + * + * @param mode + */ +/* ----------------------------------------------------------------------------*/ +void bt_set_ldos(u8 mode); + +/* --------------------------------------------------------------------------*/ +/** + * @brief ble_set_fix_pwr + * + * @param fix (0~max) + * 动态调整BLE的发射功率 + */ +/* ----------------------------------------------------------------------------*/ +void ble_set_fix_pwr(u8 fix); + + +/* --------------------------------------------------------------------------*/ +/** + * @brief bredr_set_fix_pwr + * + * @param fix (0~max) + * 动态调整EDR的发射功率 + */ +/* ----------------------------------------------------------------------------*/ +void bredr_set_fix_pwr(u8 fix); + +/* --------------------------------------------------------------------------*/ +/** + * @brief ble_rf_vendor_fixed_channel + * + * @param channel_index: range 0~39 fixed freq, or 0xff --close fixed + * @param pktcnt: range 1~3 + * 配置ble 的 adv、scan、init 状态定频 + */ +/* ----------------------------------------------------------------------------*/ +bool ble_rf_vendor_fixed_channel(u8 channel_index, u8 pktcnt); + +void set_bt_afh_classs_enc(u8 afh_class); +void set_bt_enhanced_power_control(u8 en); + +#endif diff --git a/include_lib/btctrler/btctler_lib_bss.ld b/include_lib/btctrler/btctler_lib_bss.ld new file mode 100644 index 0000000..eff71b5 --- /dev/null +++ b/include_lib/btctrler/btctler_lib_bss.ld @@ -0,0 +1,63 @@ + + btctler_bss_start = .; + + BTCTLER_CONTROLLER_BSS_START = .; + + *(.bd_base) + *(.bredr_rxtx_bulk) + acl_tx_pool = .; + *(.bredr_tx_bulk) +#ifdef CONFIG_BT_TX_BUFF_SIZE + acl_tx_pool_end = acl_tx_pool + CONFIG_BT_TX_BUFF_SIZE; +#else + acl_tx_pool_end = acl_tx_pool; +#endif + . = acl_tx_pool_end; + + *(.protect_ram) + + acl_rx_pool = .; + *(.bredr_rx_bulk) +#ifdef CONFIG_BT_RX_BUFF_SIZE + acl_rx_pool_end = acl_rx_pool + CONFIG_BT_RX_BUFF_SIZE; +#else + acl_rx_pool_end = acl_rx_pool; +#endif + . = acl_rx_pool_end; + + tws_bulk_pool = .; +#ifdef CONFIG_TWS_BULK_POOL_SIZE + tws_bulk_pool_end = tws_bulk_pool + CONFIG_TWS_BULK_POOL_SIZE; +#else + tws_bulk_pool_end = tws_bulk_pool; +#endif + . = tws_bulk_pool_end; + + *(.bt_rf_bss) + *(.hci_controller_bss) + *(.hci_interface_bss) + *(.device_manager_bss) + *(.vendor_manager_bss) + BTCTLER_CONTROLLER_BSS_SIZE = ABSOLUTE(. - BTCTLER_CONTROLLER_BSS_START); + + BTCTLER_LE_CONTROLLER_BSS_START = .; + *(.ble_hci_bss) + *(.ble_ll_bss) + *(.ble_rf_bss) + BTCTLER_LE_CONTROLLER_BSS_SIZE = ABSOLUTE(. - BTCTLER_LE_CONTROLLER_BSS_START); + + BTCTLER_CL_BSS_START = .; + *(.classic_rf_bss) + *(.classic_lmp_bss) + *(.classic_lmp_auth_bss) + *(.classic_lmp_bigint_bss) + *(.classic_lmp_crypt_bss) + *(.classic_lmp_ecdh_bss) + *(.classic_lmp_linkbulk_bss) + *(.classic_lmp_hmac_bss) + *(.classic_bb_bss) + *(.classic_hci_bss) + BTCTLER_CL_BSS_SIZE = ABSOLUTE(. - BTCTLER_CL_BSS_START); + + btctler_bss_end = .; + diff --git a/include_lib/btctrler/btctler_lib_data.ld b/include_lib/btctrler/btctler_lib_data.ld new file mode 100644 index 0000000..0ff1ed1 --- /dev/null +++ b/include_lib/btctrler/btctler_lib_data.ld @@ -0,0 +1,33 @@ + + btctler_data_start = .; + + BTCTLER_CONTROLLER_DATA_START = .; + *(.bt_rf_data) + *(.vendor_manager_data) + *(.device_manager_data) + *(.hci_controller_data) + *(.hci_interface_data) + BTCTLER_CONTROLLER_DATA_SIZE = ABSOLUTE(. - BTCTLER_CONTROLLER_DATA_START); + + BTCTLER_LE_CONTROLLER_DATA_START = .; + *(.ble_ll_data) + *(.ble_hci_data) + *(.classic_hci_data) + *(.ble_rf_data) + BTCTLER_LE_CONTROLLER_DATA_SIZE = ABSOLUTE(. - BTCTLER_LE_CONTROLLER_DATA_START); + + BTCTLER_CL_DATA_START = .; + *(.classic_lmp_data) + *(.classic_lmp_auth_data) + *(.classic_lmp_bigint_data) + *(.classic_lmp_crypt_data) + *(.classic_lmp_ecdh_data) + *(.classic_lmp_linkbulk_data) + *(.classic_lmp_hmac_data) + *(.classic_rf_data) + *(.classic_bb_data) + BTCTLER_CL_DATA_SIZE = ABSOLUTE(. - BTCTLER_CL_DATA_START); + + btctler_data_end = .; + + diff --git a/include_lib/btctrler/btctler_lib_text.ld b/include_lib/btctrler/btctler_lib_text.ld new file mode 100644 index 0000000..662bb77 --- /dev/null +++ b/include_lib/btctrler/btctler_lib_text.ld @@ -0,0 +1,118 @@ + + + btctler_code_start = .; + + BTCTLER_CONTROLLER_CODE_START = .; + *(.bt_rf_const) + *(.bt_rf_code) + *(.vendor_manager_const) + *(.vendor_manager_code) + *(.device_manager_const) + *(.device_manager_code) + *(.hci_controller_const) + *(.hci_controller_code) + *(.hci_interface_const) + *(.hci_interface_code) + BTCTLER_CONTROLLER_CODE_SIZE = ABSOLUTE(. - BTCTLER_CONTROLLER_CODE_START); + + BTCTLER_LE_CONTROLLER_CODE_START = .; + *(.ble_rf_const) + *(.ble_rf_code) + + *(.ble_ll_const) + *(.ble_ll_code) + *(.ble_hci_const) + *(.ble_hci_code) + BTCTLER_LE_CONTROLLER_CODE_SIZE = ABSOLUTE(. - BTCTLER_LE_CONTROLLER_CODE_START); + + BTCTLER_CL_CODE_START = .; + *(.bredr_irq) + *(.bredr_irq_code) + *(.bredr_irq_const) + + *(.classic_lmp_const) + *(.classic_lmp_linkbulk_const) + *(.classic_lmp_code) + *(.classic_lmp_linkbulk_code) + *(.classic_hci_const) + *(.classic_hci_code) + + LMP_ENC_CODE_START = .; + *(.classic_lmp_auth_const) + *(.classic_lmp_bigint_const) + *(.classic_lmp_crypt_const) + *(.classic_lmp_ecdh_const) + *(.classic_lmp_hmac_const) + *(.classic_lmp_auth_code) + *(.classic_lmp_bigint_code) + *(.classic_lmp_crypt_code) + *(.classic_lmp_ecdh_code) + *(.classic_lmp_hmac_code) + LMP_ENC_CODE_SIZE = ABSOLUTE(. - LMP_ENC_CODE_START); + + *(.classic_rf_const) + *(.classic_rf_code) + *(.classic_bb_const) + *(.classic_bb_code) + BTCTLER_CL_CODE_SIZE = ABSOLUTE(. - BTCTLER_CL_CODE_START); + + . = ALIGN(4); + *(.classic_tws_const) + *(.classic_tws_code) + *(.classic_tws_code.esco) + + *(.tws_media_sync_code) + *(.tws_media_sync_const) + + *(.tws_data_forward_code) + *(.tws_data_forward_const) + + . = ALIGN(4); + tws_func_stub_begin = .; + KEEP(*(.tws_func_stub)) + tws_func_stub_end = .; + + *(.lmp_irq_code) + *(.link_bulk_code) + *(.frame_irq_code) + + . = ALIGN(4); + *(.link_task_const) + *(.link_task_code) + + . = ALIGN(4); + *(.classic_irq_const) + *(.classic_irq_code) + + . = ALIGN(4); + *(.tws_irq_code) + + . = ALIGN(4); + tws_sync_call_begin = .; + KEEP(*(.tws_sync_call)) + tws_sync_call_end = .; + + + . = ALIGN(4); + tws_sync_channel_begin = .; + KEEP(*(.tws_sync_channel.0)) + KEEP(*(.tws_sync_channel.1)) + KEEP(*(.tws_sync_channel.2)) + KEEP(*(.tws_sync_channel.3)) + KEEP(*(.tws_sync_channel.4)) + KEEP(*(.tws_sync_channel.5)) + KEEP(*(.tws_sync_channel.6)) + KEEP(*(.tws_sync_channel.7)) + KEEP(*(.tws_sync_channel.8)) + KEEP(*(.tws_sync_channel.9)) + KEEP(*(.tws_sync_channel.10)) + KEEP(*(.tws_sync_channel.11)) + KEEP(*(.tws_sync_channel.12)) + KEEP(*(.tws_sync_channel.13)) + tws_sync_channel_end = .; + + btctler_code_end = .; + + . = ALIGN(4); + + diff --git a/include_lib/btctrler/btctrler_task.h b/include_lib/btctrler/btctrler_task.h new file mode 100644 index 0000000..3c18d8b --- /dev/null +++ b/include_lib/btctrler/btctrler_task.h @@ -0,0 +1,75 @@ +#ifndef BTCTRLER_TASK_H +#define BTCTRLER_TASK_H + +#include "typedef.h" +#include "system/task.h" + +enum { + LMP_EVENT = Q_USER + 1, + LMP_HCI_CMD, + LMP_HCI_CMD_TO_CONN, + HCI_COMMON_CMD, + LL_EVENT, + HCI_CMD_TO_LL, + TWS_LMP_EVENT, + MSG_BT_UPDATA_START, + MSG_BT_UPDATE_LOADER_DOWNLOAD_START, + MSG_BLE_TEST_UPDATA_START, + MSG_BLE_TEST_OTA_LOADER_DOWNLOAD_START, + MSG_TASK_READY, + MSG_TASK_DEL, +}; + +enum { + BTCTRLER_EVENT_RESUME_REQ = 1, +}; + +#define SYS_EVENT_FROM_CTRLER (('C' << 24) | ('T' << 16) | ('R' << 8) | '\0') + + + + +int bredr_link_event(void *link, int argc, ...); + +int bredr_tws_link_event(void *link, int argc, ...); + +int btctrler_hci_cmd_to_task(int cmd, int argc, ...); + +int lmp_hci_cmd_to_conn_for_handle(u16 handle, int argc, ...); + +int lmp_hci_cmd_to_conn_for_addr(u8 *addr, int argc, ...); + +int lmp_hci_cmd_to_conn(void *conn, int argc, ...); + + +#define lmp_hci_cmd_to_task(argc, ...) btctrler_hci_cmd_to_task(LMP_HCI_CMD, argc, ## __VA_ARGS__) + +#define ll_hci_cmd_to_task(argc, ...) btctrler_hci_cmd_to_task(HCI_CMD_TO_LL, argc, ## __VA_ARGS__) + + +int btctrler_task_init(const void *transport, const void *config); + +void btctrler_resume_req(); + +void btctrler_resume(); + +int btctrler_suspend(u8 suepend_rx_bulk); + +int btctrler_task_ready(); + +int btctrler_task_exit(); + +int btctrler_task_close_bredr(); +void btctrler_task_init_bredr(); + +void set_idle_period_slot(u16 slot); +enum { + TESTBOX_INFO_VBAT_VALUE = 0, //(u16 (*handle)(void)) + TESTBOX_INFO_VBAT_PERCENT, //(u8 (*handle)(void)) + TESTBOX_INFO_BURN_CODE, //(u8 *(*handle)(u8 *len)) + TESTBOX_INFO_SDK_VERSION, //(u8 *(*handle)(u8 *len)) +}; + +void bt_testbox_ex_info_get_handle_register(u8 info_type, void *handle); +u8 bredr_bulk_change_rx_bulk(u8 mode); +#endif diff --git a/include_lib/btctrler/classic/hci_lmp.h b/include_lib/btctrler/classic/hci_lmp.h new file mode 100644 index 0000000..c1679a3 --- /dev/null +++ b/include_lib/btctrler/classic/hci_lmp.h @@ -0,0 +1,219 @@ +#ifndef LMP_API_H +#define LMP_API_H + + + + + + +int lmp_private_is_clearing_a2dp_packet(void *_conn); + +int lmp_private_a2dp_channel_exist(void *_conn); + +int lmp_private_get_sbc_remain_time(void *_conn, u8 include_tws); + +void *lmp_private_open_sbc_channel(u8 *addr, u16 channel, u8 codec_type); + +void lmp_private_free_sbc_packet(void *_conn, void *packet); + +int lmp_private_get_sbc_data_len(void *_conn); + +int lmp_private_get_rx_buffer_size(); + +void lmp_private_set_max_rx_buf_persent(u8 *addr, int persent); + +void *lmp_private_fetch_sbc_packet(void *_conn, int *len, void *_prev, int); + +int lmp_private_get_sbc_packet_num(void *_conn); +void lmp_private_close_sbc_channel(void *_conn); + +int lmp_private_get_sbc_packet(void *_conn, u8 **frame, int block); + +u8 *lmp_private_get_tx_packet_buffer(int size); + +int lmp_private_clear_a2dp_packet(void *_conn, u16 seqn_number); + +int lmp_private_send_esco_packet(void *priv, u8 *packet, int len); + +u8 *lmp_private_remote_addr_for_handler(int handle); + +u16 lmp_private_handler_for_remote_addr(u8 *addr, int link_type); + +int lmp_private_get_rx_buffer_total_size(void *_conn); + +int lmp_private_get_rx_buffer_remain_size(void *_conn); + +void lmp_hci_private_hold_acl_packet(u8 *packet); + +void lmp_hci_private_free_acl_packet(u8 *packet); + +void lmp_hci_private_try_free_acl_packet(u8 *packet); + +int lmp_hci_send_packet(u8 *packet, int len); + +int lmp_hci_send_packet_standard(const u8 *packet, int len); + +int lmp_hci_reset(); + +int lmp_hci_write_scan_enable(u8 enable); + +void lmp_hci_write_class_of_device(int dev_class); + +void lmp_hci_write_local_name(const char *name); +void lmp_hci_write_local_priv_version(const char *ic_verson, const char *priv_version, u8 *tws_local_addr); + +void lmp_hci_write_local_address(const u8 *addr); + +void lmp_hci_write_simple_pairing_mode(u8 enable); + +void lmp_hci_write_super_timeout(u16 timeout); +void lmp_hci_write_page_timeout(u16 timeout); +void lmp_hci_write_tws_internal_addr(u8 *internal_addr_local, u8 *internal_addr_remote); + +void lmp_hci_write_link_supervision_timeout(u16 handle, int); + +int lmp_hci_write_le_host_support(int features); + +int lmp_hci_read_pin_type(); + +void lmp_hci_set_pin_code(const char *code, u8 len); + +void lmp_hci_pin_code_request_reply(u8 *addr, u8 len, u8 *pin_code); + +void lmp_hci_pin_code_request_negative_reply(u8 *addr); + +int lmp_hci_write_pin_type(u8 type); + +int lmp_hci_set_connection_encryption(u16 handle, int enable); + +void lmp_hci_io_capability_request_reply(u8 *addr, u8 io_cap, u8 oob_data, u8 auth_req); + +void lmp_hci_user_confirmation_request_reply(u8 *address); + +void lmp_hci_user_confirmation_request_negative_reply(u8 *addr); + +int lmp_hci_disconnect(u16 handle, u8 reason); +int lmp_hci_test_key_cmd(u8 cmd, u16 handle); + +void lmp_hci_accept_connection_request(u8 *addr, u8 role); + +void lmp_hci_accept_sco_connection_request(u8 *addr, u32 tx_bandwidth, + u32 rx_bandwidth, u16 max_latency, u16 content_format, + u8 retransmission, u16 packey_type); + +void lmp_hci_reject_connection_request(u8 *addr, u8 reason); + +void lmp_hci_switch_role_command(u8 *addr, u8 role); + +void lmp_hci_authentication_requested(u16 handler); + +void lmp_hci_link_key_request_reply(u8 *addr, u8 *link_key); + +void lmp_hci_link_key_request_negative_reply(u8 *addr); + +void lmp_hci_write_default_link_policy_settings(u16 setting); + +void lmp_hci_release_packet(u8 *packet); + +void lmp_hci_create_connection(const u8 *addr, u16 packet_type, + u8 repetition_mode, u8 reserved, + u16 clk_offset, u8 allow_role_switch); + +void lmp_hci_connection_cancel(u8 *addr);; + +void lmp_hci_cancel_page(); +void lmp_hci_inquiry(int lap, u8 length, u8 num); +void lmp_hci_cancel_inquiry(); +void lmp_hci_sniff_mode_command(u16 handle, u16 max_interval, u16 min_interval, u16 attempt, u16 timeout); +void lmp_hci_exit_sniff_mode_command(u16 handle); + +void lmp_hci_host_num_of_completed_packets(u16 handle, u16 num_of_completed_packet); + +int lmp_hci_read_remote_version_information(u16 handle); + +void lmp_hci_read_remote_supported_features(u16 handle); + +void lmp_hci_read_remote_extended_features(u16 handle); + +void lmp_hci_role_discovery(u16 handle); + +void lmp_hci_read_clock_offset(u16 handle); + +void lmp_hci_read_link_policy_settings(u16 handle); +void lmp_hci_write_link_policy_settings(u16 handle, u16 policy); + +void lmp_hci_remote_name_request(u8 *addr, u8 page_scan_repetition_mode, u16 clk_offset); + +void lmp_set_sniff_establish_by_remote(u8 enable); + +void lmp_set_sniff_disable(void); + + +u8 lmp_hci_read_local_supported_features(int octet); + +void lmp_hci_write_local_supported_features(u8 features, int octet); + + +u8 lmp_standard_connect_check(void); + +void lmp_hci_send_keypress_notification(u8 *addr, u8 key); +void lmp_hci_user_keypress_request_reply(u8 *addr, u32 key); +void lmp_hci_user_keypress_request_negative_reply(u8 *addr, u8 key); + + +void lmp_hci_set_role_switch_supported(bool enable); +void lmp_hci_tx_channel_chassification(u8 *map); + + + +u8 *get_tws_internal_addr(int channel); + +extern int lmp_private_esco_suspend_resume(int flag);; + +void user_set_tws_box_mode(u8 mode); + + +void bt_set_tx_power(u8 txpower); + + +void bredr_bulk_change(u8 mode); + + +extern u8 get_bredr_link_state(); + +extern u32 get_bt_slot_time(u8 type, u32 time, int *ret_time, int (*local_us_time)(void)); +extern u32 get_sync_rec_instant_us_time(); +extern u8 tws_remote_state_check(void); +extern void tws_remote_state_clear(void); +extern void user_set_tws_box_mode(u8 mode); + + +extern void bredr_fcc_init(u8 mode, u8 fre); +extern void bredr_set_dut_enble(u8 en, u8 phone); + +extern int a2dp_media_clear_packet_before_seqn(u16 seqn_number); + + +struct link_fix_rx_result { + u32 rx_err_b; //接收到err bit + u32 rx_sum_b; //接收到正确bit + u32 rx_perr_p; //接收到crc 错误 包数 + u32 rx_herr_p; //接收到crc 以外其他错误包数 + u32 rx_invail_p; //接收到crc错误bit太多的包数,丢弃不统计到err bit中 +}; + +#define DH1_1 0 +#define DH3_1 1 +#define DH5_1 2 +#define DH1_2 3 +#define DH3_2 4 +#define DH5_2 5 + +int link_fix_tx_enable(u8 *remote_addr, u8 fre, u8 packet_type, u16 payload); +int link_fix_rx_enable(u8 *remote_addr, u8 fre, u8 packet_type, u16 payload); +void link_fix_txrx_disable(); +void link_fix_rx_update_result(struct link_fix_rx_result *result); +void link_fix_rx_dump_result(); + + +#endif diff --git a/include_lib/btctrler/classic/lmp_config.h b/include_lib/btctrler/classic/lmp_config.h new file mode 100644 index 0000000..e5339bb --- /dev/null +++ b/include_lib/btctrler/classic/lmp_config.h @@ -0,0 +1,18 @@ +/********************************************************************************************* + * Filename : lmp_config.h + + * Description : Lto 优化Macro 定义 + + * Author : Bingquan + + * Email : bingquan_cai@zh-jieli.com + + * Last modifiled : 2018-12-19 16:38 + + * Copyright:(c)JIELI 2011-2017 @ , All Rights Reserved. +*********************************************************************************************/ +#ifndef _LMP_CONFIG_H_ +#define _LMP_CONFIG_H_ + +#endif + diff --git a/include_lib/btctrler/classic/tws_api.h b/include_lib/btctrler/classic/tws_api.h new file mode 100644 index 0000000..c0e308b --- /dev/null +++ b/include_lib/btctrler/classic/tws_api.h @@ -0,0 +1,238 @@ +#ifndef TWS_API_H +#define TWS_API_H + +#include "typedef.h" + +#include "classic/tws_event.h" +#include "classic/tws_local_media_sync.h" +#include "classic/tws_data_trans.h" + +#define TWS_ROLE_MASTER 0 +#define TWS_ROLE_SLAVE 1 + +/* + * tws 状态 + */ +#define TWS_STA_SIBLING_DISCONNECTED 0x00000001 //tws未连接 +#define TWS_STA_SIBLING_CONNECTED 0x00000002 //tws已连接 +#define TWS_STA_PHONE_DISCONNECTED 0x00000004 //手机未连接 +#define TWS_STA_PHONE_CONNECTED 0x00000008 //手机已连接 +#define TWS_STA_ESCO_OPEN 0x00000010 //正在打电话 +#define TWS_STA_SBC_OPEN 0x00000020 //正在播歌 +#define TWS_STA_MONITOR_START 0x00000040 //tws从机开始监听手机链路 +#define TWS_STA_LOCAL_TWS_OPEN 0x00000080 //开启local_tws +#define TWS_STA_ESCO_OPEN_LINK 0x00000100 //正在打电话,create link + +#define TWS_SYNC_CALL_TX 1 +#define TWS_SYNC_CALL_RX 2 + +struct tws_sync_call { + int uuid; + void (*func)(int priv, int err); + const char *task_name; +}; + +extern const struct tws_sync_call tws_sync_call_begin[]; +extern const struct tws_sync_call tws_sync_call_end[]; + +#define list_for_each_tws_sync_call(p) \ + for (p = tws_sync_call_begin; p < tws_sync_call_end; p++) + + +#define TWS_SYNC_CALL_REGISTER(sync_call) \ + static const struct tws_sync_call __tws_##sync_call sec(.tws_sync_call) + + +#define TWS_FUNC_ID(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) + +typedef void (*tws_func_t)(void *data, u16 len, bool rx); + +struct tws_func_stub { + u32 func_id; + tws_func_t func; //call from irq +}; + +#define REGISTER_TWS_FUNC_STUB(stub) \ + static const struct tws_func_stub stub sec(.tws_func_stub) + +extern const struct tws_func_stub tws_func_stub_begin[]; +extern const struct tws_func_stub tws_func_stub_end[]; + +static inline tws_func_t tws_function_get_by_id(u32 id) +{ + const struct tws_func_stub *p; + + for (p = tws_func_stub_begin; p < tws_func_stub_end; p++) { + if (p->func_id == id) { + return p->func; + } + } + return NULL; +} + +static inline void tws_function_call_by_id(u32 id, void *data, u16 len, bool rx) +{ + const struct tws_func_stub *p; + + for (p = tws_func_stub_begin; p < tws_func_stub_end; p++) { + if (p->func_id == id) { + p->func(data, len, rx); + break; + } + } +} + + +/* + * 通过搜索码搜索tws设备 + */ +int tws_api_search_sibling_by_code(u16 code, int timeout_ms); + +/* + *打开可发现, 可连接,可被手机和tws搜索到 + */ +int tws_api_wait_pair_by_code(u16 code, const char *name, int timeout_ms); +int tws_api_wait_pair_by_ble(u16 code, const char *name, int timeout_ms); + +int tws_api_wait_tws_pair(int code, const char *name); + +int tws_api_wait_phone_pair(int code, const char *name); + + +int tws_wait_tws_pair(u16 code, const char *name); + +int tws_wait_phone_pair(u16 code, const char *name); + + +/* + *取消可发现, 可连接,可被tws搜索到 + */ +int tws_api_cancle_wait_pair(); + + + +/* + * 搜索并连接已经配对过的tws + * timeout: 单位ms, 0 表示不超时 + * 返回值: 0: 函数调用成功 + */ +int tws_api_create_connection(int timeout); + + +/* + * 取消搜索已配对的tws + */ +int tws_api_cancle_create_connection(); + + +/* + * 打开可发现,可连接, 可以被手机和已配对过的tws连接 + */ +int tws_api_wait_connection(); + + +/* + * 断开tws直接的连接 + * reason: 断开原因 + */ +int tws_api_detach(enum tws_detach_reason reason); + +/* + * 获取主从, 播歌和打电话状态下结果不可靠,请勿调用 + */ +int tws_api_get_role(); + +/* + * 获取tws 连接的状态 + * 返回值: 详见顶部TWS_STA_** + */ +int tws_api_get_tws_state(); + +/* + * 设置tws对方地址 + */ +int tws_api_set_sibling_addr(u8 *addr); + +/* + * 获取tws对方地址 + */ +int tws_api_get_sibling_addr(u8 *addr); + + +/* + * 获取tws本地地址 + */ +int tws_api_get_local_addr(u8 *addr); + +/* + *发送解除配对命令给对方, 成功后会收到TWS_EVENT_REMOVE_PAIRS事件 + */ +int tws_api_remove_pairs(); + + +/* + * 设置本地声道 + * 'L': 左声道 + * 'R': 右声道 + * 'U': 双声道合并 + */ +void tws_api_set_local_channel(char channel); + +/* + * 获取本地声道 + */ +char tws_api_get_local_channel(); + +/* + * 通过uuid,主从同步调用相同函数 + */ +int tws_api_sync_call_by_uuid(int uuid, int priv, int delay_ms); + +/* + * tws 数据发送函数, 要求 len <= 512 + */ +int tws_api_send_data_to_sibling(void *data, u16 len, u32 func_id); + +int tws_api_send_data_to_slave(void *data, int len, u32 func_id); + +int tws_profile_init(); +int tws_profile_exit(); + + + +int tws_api_connect_in_esco(); +int tws_api_cancle_connect_in_esco(); + +/* + * 使能对耳自动主从切换 + */ +void tws_api_auto_role_switch_enable(); + +/* + * 关闭对耳自动主从切换 + */ +void tws_api_auto_role_switch_disable(); + +int tws_api_get_low_latency_state(); + +int tws_api_low_latency_enable(bool enable); + + +void tws_api_set_quick_connect_addr(u8 *addr); + +u8 *tws_api_get_quick_connect_addr(); + +void tws_api_common_addr_en(u8 en); + +void tws_api_pair_all_way(u8 en); + +int tws_api_power_saving_mode_enable(); + +int tws_api_power_saving_mode_disable(); + +int tws_api_enter_pure_monitor_mode(); + +void tws_try_connect_disable(void); + +extern void tws_conn_switch_role(); +#endif diff --git a/include_lib/btctrler/classic/tws_data_trans.h b/include_lib/btctrler/classic/tws_data_trans.h new file mode 100644 index 0000000..a1042af --- /dev/null +++ b/include_lib/btctrler/classic/tws_data_trans.h @@ -0,0 +1,47 @@ +#ifndef TWS_DATA_TRANS_H +#define TWS_DATA_TRANS_H + +#include "generic/typedef.h" + +enum { + TWS_DATA_TRANS_SOURCE, + TWS_DATA_TRANS_SINK, +}; + +enum tws_data_trans_attr { + TWS_DTC_LOCAL_MEDIA, + TWS_DTC_MIC_REC, +}; + +u8 tws_api_data_trans_open(u8 channel, enum tws_data_trans_attr attr, u16 buf_size); + + +int tws_api_data_trans_start(u8 channel, u8 *arg, u8 len); + + +int tws_api_data_trans_stop(u8 channel); + + +int tws_api_data_trans_close(u8 channel); + + +void tws_api_data_trans_auto_drop(u8 channel, int enable); + +int tws_api_data_trans_send(u8 channel, u8 *buf, int len); + +void *tws_api_data_trans_buf_alloc(u8 channel, int len); + +int tws_api_data_trans_push(u8 channel, void *_frame, int len); + +void *tws_api_data_trans_pop(u8 channel, int *len); + +void tws_api_data_trans_free(u8 channel, void *_frame); + +void *tws_api_data_trans_fetch(u8 channel, void *_prev, int *len); + +void tws_api_data_trans_clear(u8 channel); + +int tws_api_data_trans_check(u8 channel, u16 *ready_len, u16 *total_len); + +#endif + diff --git a/include_lib/btctrler/classic/tws_event.h b/include_lib/btctrler/classic/tws_event.h new file mode 100644 index 0000000..b3ef7e9 --- /dev/null +++ b/include_lib/btctrler/classic/tws_event.h @@ -0,0 +1,94 @@ +#ifndef TWS_EVENT_H +#define TWS_EVENT_H + +#define KEY_EVENT_FROM_TWS (('T' << 24) | ('W' << 16) | ('S' << 8) | '\0') +#define SYS_BT_EVENT_FROM_TWS (('T' << 24) | ('W' << 16) | ('S' << 8) | '\0') + +enum { + TWS_STA_WAIT_SIBLING_PAIR = 1, + TWS_STA_SEARCH_SIBLING, + TWS_STA_CREATE_CONNECTION_BREDR, + TWS_STA_CREATE_CONNECTION_BLE, + TWS_STA_WAIT_CONNECTION_BREDR, + TWS_STA_WAIT_CONNECTION_BLE, + TWS_STA_DISCONNECTION, + TWS_STA_CONNECTION, + TWS_STA_START_MONITOR, + TWS_STA_MONITOR, + TWS_STA_WAIT_PHONE_PAIR, + TWS_STA_WAIT_PAIR, +}; + +enum { + LOCAL_REMOTE_ADDR = 0, + TWS_PAIR_REMOTE_ADDR_STATE_OK, + TWS_PAIR_REMOTE_ADDR_STATE_NOT, +}; + +enum tws_detach_reason { + TWS_DETACH_BY_SUPER_TIMEOUT = 8, + TWS_DETACH_BY_LOCAL, + TWS_DETACH_BY_REMOTE, + TWS_DETACH_BY_POWEROFF, + TWS_DETACH_BY_REMOVE_PAIRS, + TWS_DETACH_BY_TESTBOX_CON, + TWS_DETACH_BY_REMOVE_NO_RECONN, +}; + + +#define TWS_CONN_CHANNEL 0 +#define TWS_LINK_SYNC_CHANNEL 1 +#define TWS_LMP_SYNC_CHANNEL 2 +#define TWS_AFH_SYNC_CHANNEL 3 +#define TWS_TX_SYNC_CHANNEL 4 +#define TWS_LOW_LATENCY_CHANNEL 5 +#define TWS_DATA_SYNC_CHANNEL 6 +#define TWS_SBC_SYNC_CHANNEL 7 +#define TWS_EVENT_SYNC_CHANNEL 8 +#define TWS_SYNC_CALL_CHANNEL 9 +#define TWS_POWER_BALANCE_CHANNEL 10 +#define TWS_CI_DATA_SYNC_CHANNEL 11 +#define TWS_LOCAL_MEIDA_SYNC_CHANNEL 12 +#define TWS_LMP_SLOT_CHANNEL 13 +#define TWS_DATA_TRANS_CHANNEL 14 + +enum { + TWS_EVENT_SEARCH_TIMEOUT = 1, + TWS_EVENT_CONNECTED, + TWS_EVENT_CONNECTION_TIMEOUT, + TWS_EVENT_CONNECTION_DETACH, + TWS_EVENT_REMOVE_PAIRS, + TWS_EVENT_PHONE_LINK_DETACH, + TWS_EVENT_SYNC_FUN_CMD, + TWS_EVENT_SYNC_FUN_TRANID, + TWS_EVENT_CONNECT_TEST, + TWS_EVENT_ROLE_SWITCH, + TWS_EVENT_LOCAL_MEDIA_START, + TWS_EVENT_LOCAL_MEDIA_STOP, + TWS_EVENT_ESCO_ADD_CONNECT, + TWS_EVENT_SETUP_MONITOR_LINK, + TWS_EVENT_MONITOR_START, + TWS_EVENT_DATA_TRANS_OPEN, + TWS_EVENT_DATA_TRANS_START, + TWS_EVENT_DATA_TRANS_STOP, + TWS_EVENT_DATA_TRANS_CLOSE, + + TWS_EVENT_MODE_CHANGE, //sniff without phone + + TWS_EVENT_TONE_TEST = 0xff, +}; + + + + + + + + + + + + + +#endif + diff --git a/include_lib/btctrler/classic/tws_local_media_sync.h b/include_lib/btctrler/classic/tws_local_media_sync.h new file mode 100644 index 0000000..c50daf5 --- /dev/null +++ b/include_lib/btctrler/classic/tws_local_media_sync.h @@ -0,0 +1,46 @@ +#ifndef TWS_LOCAL_MEDIA_SYNC_H +#define TWS_LOCAL_MEDIA_SYNC_H + +#include "generic/list.h" +#include "generic/typedef.h" + + + +void tws_api_local_media_trans_start(); + +void tws_api_local_media_trans_set_buf(void *buf, int size); + +void *tws_api_local_media_trans_alloc(int len); + +void tws_api_local_media_trans_free(void *frame); + +void tws_api_local_media_trans_push(void *frame, int len); + +void *tws_api_local_media_trans_pop(int *len); + +void *tws_api_local_media_trans_fetch(void *prev, int *len); + +void tws_api_local_media_trans_stop(); + +void tws_api_local_media_trans_packet_del(void *_frame); +int tws_api_local_media_trans_check_total(u8 head); +int tws_api_local_media_trans_check_ready_total(void); +void tws_api_local_media_trans_clear(void); +int tws_api_local_media_packet_cnt(u8 *rx_packet_cnt, u8 *wait_send_pcaket_cnt); + +// 填数超过了一定值才可以发送 +void tws_api_local_media_set_limit_size(int size); + +int tws_api_local_media_trans_bulk_push(u8 *buf, int len); + +int tws_api_local_media_push_with_sequence(u8 *buf, int len, u16 seqn); + +int tws_api_local_media_trans_open(u16 buf_size); + +int tws_api_local_media_dec_start(u8 *arg, u8 len); + +int tws_api_local_media_dec_stop(); + +void tws_api_auto_drop_frame_enable(int enable); +#endif + diff --git a/include_lib/btctrler/classic/tws_pair.h b/include_lib/btctrler/classic/tws_pair.h new file mode 100644 index 0000000..26643a9 --- /dev/null +++ b/include_lib/btctrler/classic/tws_pair.h @@ -0,0 +1,60 @@ +#ifndef TWS_PAIR_H +#define TWS_PAIR_H + + +void tws_pair_init(); + +int tws_pair_wait_connection(int timeout); + +int tws_pair_create_connection(int timeout); + +int tws_pair_cancle_create_connection(); + +int tws_pair_search_sibling_by_code(int code, int timeout_ms); + +int tws_pair_wait_pair_by_code(int code, const char *name); + +int tws_pair_cancle_wait_pair(); + +int tws_pair_wait_connect_in_esco(); + +int tws_pair_cancle_wait_connect_in_esco(); + +void tws_pair_conntion_suss_irq(int role); + + + +int tws_open_tws_wait_pair(u16 code, const char *name); +int tws_open_tws_wait_conn(int timeout); +int tws_open_tws_conn(int timeout); + +int tws_open_phone_wait_pair(u16 code, const char *name); + + +int tws_close_tws_pair(); +int tws_close_phone_wait_pair(); + + +int tws_remove_tws_pairs(); +int tws_disconnect(); + + + + + + + + + + + + + + + + + + + + +#endif diff --git a/include_lib/btctrler/hci_transport.h b/include_lib/btctrler/hci_transport.h new file mode 100644 index 0000000..79ccfc9 --- /dev/null +++ b/include_lib/btctrler/hci_transport.h @@ -0,0 +1,249 @@ +/********************************************************************************************* + * Filename : hci_transport.h + + * Description : + + * Author : Bingquan + + * Email : bingquan_cai@zh-jieli.com + + * Last modifiled : 2017-01-17 15:14 + + * Copyright:(c)JIELI 2011-2016 @ , All Rights Reserved. +*********************************************************************************************/ +#ifndef __BTCONTROLLER_HCI_TRANSPORT_H +#define __BTCONTROLLER_HCI_TRANSPORT_H + +//#include +#include "generic/typedef.h" + +#if defined __cplusplus +extern "C" { +#endif + + /* API_START */ + typedef struct { + uint32_t baudrate; + int flowcontrol; + const char *device_name; + } btstack_uart_config_t; + + typedef enum { + // UART active, sleep off + BTSTACK_UART_SLEEP_OFF = 0, + // used for eHCILL + BTSTACK_UART_SLEEP_RTS_HIGH_WAKE_ON_CTS_PULSE, + // used for H5 and for eHCILL without support for wake on CTS pulse + BTSTACK_UART_SLEEP_RTS_LOW_WAKE_ON_RX_EDGE, + + } btstack_uart_sleep_mode_t; + + typedef enum { + BTSTACK_UART_SLEEP_MASK_RTS_HIGH_WAKE_ON_CTS_PULSE = 1 << BTSTACK_UART_SLEEP_RTS_HIGH_WAKE_ON_CTS_PULSE, + BTSTACK_UART_SLEEP_MASK_RTS_LOW_WAKE_ON_RX_EDGE = 1 << BTSTACK_UART_SLEEP_RTS_LOW_WAKE_ON_RX_EDGE + } btstack_uart_sleep_mode_mask_t; + + typedef struct { + /** + * init transport + * @param uart_config + */ + int (*init)(const btstack_uart_config_t *uart_config); + + /** + * open transport connection + */ + int (*open)(void); + + /** + * close transport connection + */ + int (*close)(void); + + /** + * set callback for block received. NULL disables callback + */ + void (*set_block_received)(void (*block_handler)(void)); + + /** + * set callback for sent. NULL disables callback + */ + void (*set_block_sent)(void (*block_handler)(void)); + + /** + * set baudrate + */ + int (*set_baudrate)(uint32_t baudrate); + + /** + * set parity + */ + int (*set_parity)(int parity); + + /** + * set flowcontrol + */ + int (*set_flowcontrol)(int flowcontrol); + + /** + * receive block + */ + void (*receive_block)(uint8_t *buffer, uint16_t len); + + /** + * send block + */ + void (*send_block)(const uint8_t *buffer, uint16_t length); + + // support for sleep modes in TI's H4 eHCILL and H5 + + /** + * query supported wakeup mechanisms + * @return supported_sleep_modes mask + */ + int (*get_supported_sleep_modes)(void); + + /** + * set UART sleep mode - allows to turn off UART and it's clocks to save energy + * Supported sleep modes: + * - off: UART active, RTS low if receive_block was called and block not read yet + * - RTS high, wake on CTS: RTS should be high. On CTS pulse, UART gets enabled again and RTS goes to low + * - RTS low, wake on RX: data on RX will trigger UART enable, bytes might get lost + */ + void (*set_sleep)(btstack_uart_sleep_mode_t sleep_mode); + + /** + * set wakeup handler - needed to notify hci transport of wakeup requests by Bluetooth controller + * Called upon CTS pulse or RX data. See sleep modes. + */ + void (*set_wakeup_handler)(void (*wakeup_handler)(void)); + + } btstack_uart_block_t; + +// common implementations + const btstack_uart_block_t *btstack_uart_block_posix_instance(void); + const btstack_uart_block_t *btstack_uart_block_windows_instance(void); + const btstack_uart_block_t *btstack_uart_block_embedded_instance(void); + const btstack_uart_block_t *btstack_uart_block_freertos_instance(void); + + /* HCI packet types */ + typedef struct { + /** + * transport name + */ + const char *name; + + /** + * init transport + * @param transport_config + */ + void (*init)(const void *transport_config); + + /** + * open transport connection + */ + int (*open)(void); + + /** + * close transport connection + */ + int (*close)(void); + + /** + * register packet handler for HCI packets: ACL, SCO, and Events + */ + void (*register_packet_handler)(void (*handler)(int packet_type, const u8 *packet, int size)); + + /** + * support async transport layers, e.g. IRQ driven without buffers + */ + int (*can_send_packet_now)(uint8_t packet_type); + + /** + * send packet + */ + int (*send_packet)(int packet_type, const u8 *packet, int size); + + /** + * extension for UART transport implementations + */ + int (*set_baudrate)(uint32_t baudrate); + + /** + * extension for UART H5 on CSR: reset BCSP/H5 Link + */ + void (*reset_link)(void); + + /** + * extension for USB transport implementations: config SCO connections + */ + void (*set_sco_config)(uint16_t voice_setting, int num_connections); + + } hci_transport_t; + + typedef enum { + HCI_TRANSPORT_CONFIG_UART, + HCI_TRANSPORT_CONFIG_USB + } hci_transport_config_type_t; + + typedef struct { + hci_transport_config_type_t type; + } hci_transport_config_t; + + typedef struct { + hci_transport_config_type_t type; // == HCI_TRANSPORT_CONFIG_UART + uint32_t baudrate_init; // initial baud rate + uint32_t baudrate_main; // = 0: same as initial baudrate + int flowcontrol; // + const char *device_name; + } hci_transport_config_uart_t; + + +// inline various hci_transport_X.h files + + /* + * @brief Setup H4 instance with uart_driver + * @param uart_driver to use + */ + const hci_transport_t *hci_transport_h4_instance(const btstack_uart_block_t *uart_driver); + + /* + * @brief Setup H5 instance with uart_driver + * @param uart_driver to use + */ + const hci_transport_t *hci_transport_h5_instance(const btstack_uart_block_t *uart_driver); + + /* + * @brief Enable H5 Low Power Mode: enter sleep mode after x ms of inactivity + * @param inactivity_timeout_ms or 0 for off + */ + void hci_transport_h5_set_auto_sleep(uint16_t inactivity_timeout_ms); + + /* + * @brief Enable BSCP mode H5, by enabling event parity + */ + void hci_transport_h5_enable_bcsp_mode(void); + + /* + * @brief + */ + const hci_transport_t *hci_transport_usb_instance(void); + + const hci_transport_t *hci_transport_uart_instance(void); + + const hci_transport_t *hci_transport_h4_controller_instance(void); + + const hci_transport_t *hci_transport_h4_host_instance(void); + /** + * @brief Specify USB Bluetooth device via port numbers from root to device + */ + void hci_transport_usb_set_path(int len, uint8_t *port_numbers); + + /* API_END */ + extern const hci_transport_t *hci_transport; + +#if defined __cplusplus +} +#endif + +#endif // __HCI_TRANSPORT_H diff --git a/include_lib/btctrler/port/br23/btcontroller_config.h b/include_lib/btctrler/port/br23/btcontroller_config.h new file mode 100644 index 0000000..fae3924 --- /dev/null +++ b/include_lib/btctrler/port/br23/btcontroller_config.h @@ -0,0 +1,56 @@ +/********************************************************************************************* + * Filename : btcontroller_config.h + + * Description : 优化代码需要,libs 依赖app 定义变量,由app 定义变量值决定libs 优化 + + * Author : Bingquan + + * Email : bingquan_cai@zh-jieli.com + + * Last modifiled : 2018-12-19 16:10 + + * Copyright:(c)JIELI 2011-2017 @ , All Rights Reserved. +*********************************************************************************************/ +#ifndef _BTCONTROLLER_CONFIG_H_ +#define _BTCONTROLLER_CONFIG_H_ + +#include "btcontroller_modules.h" + +#include "ble/ll_config.h" + +// #define CONFIG_LE_FEATURES \ +(\ + LE_ENCRYPTION | \ + LE_CORE_V50_FEATURES \ +) + +#define CONFIG_LE_FEATURES 0//(LE_ENCRYPTION) + +// #define CONFIG_LE_ROLES (LE_ADV|LE_SCAN|LE_INIT|LE_SLAVE|LE_MASTER) +// #define CONFIG_LE_ROLES (LE_ADV|LE_SCAN) +#define CONFIG_LE_ROLES (LE_ADV) + +#include "classic/lmp_config.h" + +#define CONFIG_CL_FEATURES + +#define CONFIG_CL_EX_FEATURES + + +#define TWS_BLE_ESCO_CONNECT //通话过程进行连接使能 + + +/* + *------------------- + * 蓝牙基带运行的模式 + */ + +struct lp_ws_t { + u16 lrc_ws_inc; + u16 lrc_ws_init; + u16 bt_osc_ws_inc; + u16 bt_osc_ws_init; + u8 osc_change_mode; +}; + +#endif diff --git a/include_lib/btstack/a2dp_media_codec.h b/include_lib/btstack/a2dp_media_codec.h new file mode 100644 index 0000000..344a38a --- /dev/null +++ b/include_lib/btstack/a2dp_media_codec.h @@ -0,0 +1,52 @@ +#ifndef A2DP_MEDIA_CODEC_H +#define A2DP_MEDIA_CODEC_H + + +#include "generic/typedef.h" + +#define seqn_after(a, b) ((s16)((s16)(b) - (s16)(a)) < 0) +#define seqn_before(a, b) seqn_after(b, a) + +extern int a2dp_media_get_packet(u8 **frame); + +extern int a2dp_media_try_get_packet(u8 **frame); + +extern int a2dp_media_get_remain_buffer_size(); + +extern int a2dp_media_get_remain_play_time(u8 include_tws); + +extern int a2dp_media_get_total_data_len(); + +extern int a2dp_media_get_packet_num(); + +extern int a2dp_media_clear_packet_before_seqn(u16 seqn_number); + +extern void *a2dp_media_fetch_packet(int *len, void *prev_packet); + +extern void *a2dp_media_fetch_packet_and_wait(int *len, void *prev_packet, int msec); + +extern void a2dp_media_free_packet(void *_packet); + +extern int a2dp_media_channel_exist(void); + +extern int a2dp_media_is_clearing_frame(void); + +extern int a2dp_media_get_codec_type(); + + + + + + + + + + + + + + + + + +#endif diff --git a/include_lib/btstack/avctp_user.h b/include_lib/btstack/avctp_user.h new file mode 100644 index 0000000..5dad9e4 --- /dev/null +++ b/include_lib/btstack/avctp_user.h @@ -0,0 +1,641 @@ +#ifndef __AVCTP_USER_H__ +#define __AVCTP_USER_H__ + + +#include "typedef.h" +#include "btstack_typedef.h" + + + +///***注意:该文件的枚举与库编译密切相关,主要是给用户提供调用所用。用户不能自己在中间添加值。*/ +////----user (command) codes----//// +typedef enum { + /* + 使用user_send_cmd_prepare(USER_CMD_TYPE cmd,u16 param_len,u8 *param)发送命令 + //返回0表支持参数个数正确,返回1表不支持,2是参数错误 + 要三个参数,没参数说明的命令参数param_len传0,param传NULL + 例子A、USER_CTRL_HFP_CALL_SET_VOLUME命令需要1个参数的使用例子: + u8 vol = 8; + user_send_cmd_prepare(USER_CTRL_HFP_CALL_SET_VOLUME,1, &vol); + + 例子B、USER_CTRL_DIAL_NUMBER 参数要用数组先存起来,param_len是号码长度,param可传参数数组指针, + user_val->income_phone_num已经存好号码 + user_send_cmd_prepare(USER_CTRL_DIAL_NUMBER,user_val->phone_num_len,user_val->income_phone_num); + + */ + + //链路操作部分 + //回连,使用的是VM的地址,一般按键操作不使用该接口 + USER_CTRL_START_CONNECTION, + //通过地址去连接,如果知道地址想去连接使用该接口 + USER_CTRL_START_CONNEC_VIA_ADDR, + //通过指定地址手动回连,该地址是最后一个断开设备的地址 + USER_CTRL_START_CONNEC_VIA_ADDR_MANUALLY, + //通过地址去连接spp,如果知道地址想去连接使用该接口 + USER_CTRL_START_CONNEC_SPP_VIA_ADDR, + + //断开连接,断开当前所有蓝牙连接 + USER_CTRL_DISCONNECTION_HCI, + + //取消链接 + USER_CTRL_CONNECTION_CANCEL, + + //读取远端名字 + USER_CTRL_READ_REMOTE_NAME, + //连接或断开SCO或esco,选择这个命令会自动判断要断开还是连接sco + USER_CTRL_PAUSE_MUSIC, + //连接或断开SCO或esco,选择这个命令会自动判断要断开还是连接sco + USER_CTRL_SCO_LINK, + //连接SCO或esco + USER_CTRL_CONN_SCO, + //断开sco或esco + USER_CTRL_DISCONN_SCO, + //断开SDP,一般按键操作不使用该接口 + USER_CTRL_DISCONN_SDP_MASTER, + + //关闭蓝牙可发现 + USER_CTRL_WRITE_SCAN_DISABLE, + //打开蓝牙可发现 + USER_CTRL_WRITE_SCAN_ENABLE, +// USER_CTRL_WRITE_SCAN_ENABLE_KEY , + //关闭蓝牙可连接 + USER_CTRL_WRITE_CONN_DISABLE, + //打开蓝牙可连接 + USER_CTRL_WRITE_CONN_ENABLE, + // USER_CTRL_WRITE_CONN_ENABLE_KEY , + //控制蓝牙搜索,需要搜索附件设备做功能的连续说明情况在补充完善功能 + USER_CTRL_SEARCH_DEVICE, + //取消搜索 + USER_CTRL_INQUIRY_CANCEL, + //取消配对 + USER_CTRL_PAGE_CANCEL, + ///进入sniff模式,一般按键操作不使用该接口 + USER_CTRL_SNIFF_IN, + USER_CTRL_SNIFF_EXIT, + USER_CTRL_ALL_SNIFF_EXIT, + + //hfp链路部分 + //控制打电话音量,注意可能有些手机进度条有变化音量大小没变化,同步要设置样机DAC音量 + /*跟电话音量操作有关的操作最终都执行回调函数call_vol_change*/ + USER_CTRL_HFP_CMD_BEGIN, + USER_CTRL_HFP_CALL_VOLUME_UP, /*音量加1,手机可以同步显示*/ + USER_CTRL_HFP_CALL_VOLUME_DOWN, /*音量减1,手机可以同步显示*/ + USER_CTRL_HFP_CALL_SET_VOLUME, /*设置固定值,手机可以同步显示,需要传1个音量值*/ + USER_CTRL_HFP_CALL_GET_VOLUME, /*获取音量,默认从call_vol_change返回*/ + + //来电接听电话 + USER_CTRL_HFP_CALL_ANSWER, + //挂断电话 + USER_CTRL_HFP_CALL_HANGUP, + //回拨上一个打出电话 + USER_CTRL_HFP_CALL_LAST_NO, + //获取当前通话电话号码 + USER_CTRL_HFP_CALL_CURRENT, + //通话过程中根据提示输入控制 + /*例子 + char num = '1'; + user_send_cmd_prepare(USER_CTRL_HFP_DTMF_TONES,1,(u8 *)&num); + */ + //发送打电话时的信号选择DTMF tones ,有一个参数,参数支持{0-9, *, #, A, B, C, D} + USER_CTRL_HFP_DTMF_TONES, + //根据电话号码拨号 + /**USER_CTRL_DIAL_NUMBER命令有参数,参数要用数组先存起来, + param_len是号码长度,param可传参数数组指针*/ + USER_CTRL_DIAL_NUMBER, + //发送电量 /**要连接上HFP才有用*/ + USER_CTRL_SEND_BATTERY, + //*控制siri状态*//*可以注册回调函数获取返回值*/ + USER_CTRL_HFP_GET_SIRI_STATUS, + //*开启siri*/ + USER_CTRL_HFP_GET_SIRI_OPEN, + //*关闭siri,一般说完话好像自动关闭了,如果要提前终止可调用*/ + USER_CTRL_HFP_GET_SIRI_CLOSE, + /*获取手机的日期和时间,苹果可以,一般安卓机好像都不行*/ + USER_CTRL_HFP_GET_PHONE_DATE_TIME, + USER_CTRL_HFP_CMD_SEND_BIA, + /*获取手机厂商的命令 */ + USER_CTRL_HFP_CMD_GET_MANUFACTURER, + /*更新当前的电量给手机*/ + USER_CTRL_HFP_CMD_UPDATE_BATTARY, + //三方通话操作 + //应答 + USER_CTRL_HFP_THREE_WAY_ANSWER1, //挂断当前去听另一个(未接听或者在保留状态都可以) + USER_CTRL_HFP_THREE_WAY_ANSWER2, //保留当前去接听, 或者用于两个通话的切换 + USER_CTRL_HFP_THREE_WAY_ANSWER1X, + USER_CTRL_HFP_THREE_WAY_ANSWER2X, + USER_CTRL_HFP_THREE_WAY_ANSWER3, + //拒听 + USER_CTRL_HFP_THREE_WAY_REJECT, //拒绝后台来电 + USER_CTRL_HFP_DISCONNECT, //断开HFP连接 + USER_CTRL_HFP_CMD_END, + + //音乐控制部分 + USER_CTRL_AVCTP_CMD_BEGIN, + //音乐播放 + USER_CTRL_AVCTP_OPID_PLAY, + //音乐暂停 + USER_CTRL_AVCTP_OPID_PAUSE, + //音乐停止 + USER_CTRL_AVCTP_OPID_STOP, + //音乐下一首 + USER_CTRL_AVCTP_OPID_NEXT, + //音乐上一首 + USER_CTRL_AVCTP_OPID_PREV, + //音乐快进 + USER_CTRL_AVCTP_OPID_FORWARD, + //音乐快退 + USER_CTRL_AVCTP_OPID_REWIND, + //音乐循环模式 + USER_CTRL_AVCTP_OPID_REPEAT_MODE, + USER_CTRL_AVCTP_OPID_SHUFFLE_MODE, + //获取播放歌曲总时间和当前时间接口 + USER_CTRL_AVCTP_OPID_GET_PLAY_TIME, + + //同步音量接口 + USER_CTRL_AVCTP_OPID_SEND_VOL, +// //AVCTP断开,是音乐控制链路,一般不使用 + USER_CTRL_AVCTP_DISCONNECT, +// //AVCTP连接,是音乐控制链路,一般不使用 + USER_CTRL_AVCTP_CONN, + + USER_CTRL_AVCTP_CMD_END, + + //高级音频部分 + USER_CTRL_A2DP_CMD_BEGIN, + //有判断条件的,回连过程连接高级音频,避免手机连也自动发起连接,一般按键操作不使用该接口 + USER_CTRL_AUTO_CONN_A2DP, + //连接高级音频,回来最后一个断开设备的地址 + USER_CTRL_CONN_A2DP, + //断开高级音频,只断开高级音频链路,如果有电话还会保留 + USER_CTRL_DISCONN_A2DP, + //maybe BQB test will use + USER_CTRL_A2DP_CMD_START , + USER_CTRL_A2DP_CMD_CLOSE , + USER_CTRL_A2DP_CMD_SUSPEND , + USER_CTRL_A2DP_CMD_GET_CONFIGURATION , + USER_CTRL_A2DP_CMD_ABORT , + USER_CTRL_A2DP_CMD_END, + //蓝牙关闭 + USER_CTRL_POWER_OFF, + //蓝牙开启 + USER_CTRL_POWER_ON, + ///*hid操作定义*/ + USER_CTRL_HID_CMD_BEGIN, + //按键连接 + USER_CTRL_HID_CONN, +// //只发一个按键,安卓手机使用 + USER_CTRL_HID_ANDROID, + //只发一个按键,苹果和部分安卓手机适用 + USER_CTRL_HID_IOS, +// //发两个拍照按键 + USER_CTRL_HID_BOTH, + //HID断开 + USER_CTRL_HID_DISCONNECT, + //Home Key,apply to IOS and Android + USER_CTRL_HID_HOME , + //Return Key,only support Android + USER_CTRL_HID_RETURN , + //LeftArrow Key + USER_CTRL_HID_LEFTARROW , + //RightArrow Key + USER_CTRL_HID_RIGHTARROW , + //Volume Up + USER_CTRL_HID_VOL_UP , + //Volume Down + USER_CTRL_HID_VOL_DOWN , + + USER_CTRL_HID_SEND_DATA , + + USER_CTRL_HID_CMD_END, + + /*对箱操作命令*/ + USER_CTRL_TWS_CMD_BEGIN, + USER_CTRL_SYNC_TRAIN, + USER_CTRL_SYNC_TRAIN_SCAN, + USER_CTRL_MONITOR, + USER_CTRL_TWS_CONNEC_VIA_ADDR, + USER_CTRL_TWS_COTROL_CDM, + //清除对箱连接信息 + USER_CTRL_TWS_CLEAR_INFO, + //断开对箱连接 + USER_CTRL_TWS_DISCONNECTION_HCI, + //发起对箱连接 + USER_CTRL_TWS_START_CONNECTION, + USER_CTRL_TWS_SYNC_CDM, + USER_CTRL_TWS_SYNC_SBC_CDM, + USER_CTRL_TWS_RESTART_SBC_CDM, + USER_CTRL_SYNC_TRAIN_CANCEL, + USER_CTRL_SYNC_TRAIN_SCAN_CANCEL, + USER_CTRL_TWS_SYNC_CDM_FUN, + USER_CTRL_TWS_LINEIN_START, + USER_CTRL_TWS_LINEIN_CLOSE, + USER_CTRL_TWS_CMD_END, + + ///蓝牙串口发送命令 + USER_CTRL_SPP_CMD_BEGIN, + /**USER_CTRL_SPP_SEND_DATA命令有参数,参数会先存起来, + param_len是数据长度,param发送数据指针 + 返回0,表示准备成功,会PENDing发完才返回 + 3表示上一包数据没发完,*/ + USER_CTRL_SPP_SEND_DATA, //len <= 512 + USER_CTRL_SPP_TRY_SEND_DATA,// + USER_CTRL_SPP_UPDATA_DATA, + //serial port profile disconnect command + USER_CTRL_SPP_DISCONNECT, + USER_CTRL_SPP_CMD_END, + + +///pbg发送命令 + USER_CTRL_PBG_CMD_BEGIN, + USER_CTRL_PBG_SEND_DATA,//len <= 512 + USER_CTRL_PBG_TRY_SEND_DATA,// + USER_CTRL_PBG_CMD_END, + +///adt 发送命令 + USER_CTRL_ADT_CMD_BEGIN, + USER_CTRL_ADT_CONNECT, + USER_CTRL_ADT_KEY_MIC_OPEN, + USER_CTRL_ADT_SEND_DATA,//len <= 512 + USER_CTRL_ADT_TRY_SEND_DATA,// + USER_CTRL_ADT_CMD_END, + + ///蓝牙电话本功能发送命令 + USER_CTRL_PBAP_CMD_BEGIN, + //电话本功能读取通话记录的前n条 + USER_CTRL_PBAP_READ_PART, + //电话本功能读全部记录 + USER_CTRL_PBAP_READ_ALL, + //电话本功能中断读取记录 + USER_CTRL_PBAP_STOP_READING, + + USER_CTRL_PBAP_CMD_END, + + + //蓝牙其他操作 +// //删除最新的一个设备记忆 +// USER_CTRL_DEL_LAST_REMOTE_INFO , +// //删除所有设备记忆 + USER_CTRL_DEL_ALL_REMOTE_INFO, + USER_CTRL_TEST_KEY, + + USER_CTRL_KEYPRESS, + USER_CTRL_PAIR, + USER_CTRL_AFH_CHANNEL, + USER_CTRL_HALF_SEC_LOOP_CREATE, + USER_CTRL_HALF_SEC_LOOP_DEL, + + USER_CTRL_CMD_SYNC_VOL_INC, + USER_CTRL_CMD_SYNC_VOL_DEC, + USER_CTRL_CMD_CHANGE_PROFILE_MODE, + USER_CTRL_CMD_RESERVE_INDEX4, + USER_CTRL_CMD_RESUME_STACK, + USER_CTRL_AVCTP_OPID_GET_MUSIC_INFO, + USER_CTRL_LAST +} USER_CMD_TYPE; + + +////----反馈给客户使用的状态----//// +typedef enum { + /*下面是一些即时反馈的状态,无法重复获取的状态*/ + BT_STATUS_POWER_ON = 1, /*上电*/ + BT_STATUS_POWER_OFF = 2, + BT_STATUS_INIT_OK, /*初始化完成*/ + BT_STATUS_EXIT_OK, /*蓝牙退出完成*/ + BT_STATUS_START_CONNECTED, /*开始连接*/ + BT_STATUS_FIRST_CONNECTED, /*连接成功*/ + BT_STATUS_SECOND_CONNECTED, /*连接成功*/ + BT_STATUS_ENCRY_COMPLETE, /*加密完成*/ + BT_STATUS_FIRST_DISCONNECT, /*断开连接*/ + BT_STATUS_SECOND_DISCONNECT, /*断开连接*/ + BT_STATUS_PHONE_INCOME, /*来电*/ + BT_STATUS_PHONE_NUMBER, /*来电话号码*/ + BT_STATUS_PHONE_MANUFACTURER, /*获取手机的厂商*/ + + BT_STATUS_PHONE_OUT, /*打出电话*/ + BT_STATUS_PHONE_ACTIVE, /*接通电话*/ + BT_STATUS_PHONE_HANGUP, /*挂断电话*/ + BT_STATUS_BEGIN_AUTO_CON, /*发起回连*/ + BT_STATUS_MUSIC_SOUND_COME, /*库中加入auto mute判断音乐播放开始*/ + BT_STATUS_MUSIC_SOUND_GO, /*库中加入auto mute判断音乐播放暂停*/ + BT_STATUS_RESUME, /*后台有效,手动切回蓝牙*/ + BT_STATUS_RESUME_BTSTACK, /*后台有效,后台时来电切回蓝牙*/ + BT_STATUS_SUSPEND, /*蓝牙挂起,退出蓝牙*/ + BT_STATUS_LAST_CALL_TYPE_CHANGE, /*最后拨打电话的类型,只区分打入和打出两种状态*/ + + BT_STATUS_CALL_VOL_CHANGE, /*通话过程中设置音量会产生这个状态变化*/ + BT_STATUS_SCO_STATUS_CHANGE, /*当esco/sco连接或者断开时会产生这个状态变化*/ + BT_STATUS_CONNECT_WITHOUT_LINKKEY, /*判断是首次连接还是配对后的连接,主要依据要不要简易配对或者pin code*/ + BT_STATUS_PHONE_BATTERY_CHANGE, /*电话电量变化,该状态仅6个等级,0-5*/ + BT_STATUS_RECONNECT_LINKKEY_LOST, /*回连时发现linkkey丢失了,即手机取消配对了*/ + BT_STATUS_RECONN_OR_CONN, /*回连成功还是被连接*/ + BT_STATUS_BT_TEST_BOX_CMD, /*蓝牙收到测试盒消息。1-升级,2-fast test*/ + BT_STATUS_BT_TWS_CONNECT_CMD, + BT_STATUS_SNIFF_STATE_UPDATE, /*SNIFF STATE UPDATE*/ + BT_STATUS_TONE_BY_FILE_NAME, /*直接使用文件名播放提示音*/ + + BT_STATUS_PHONE_DATE_AND_TIME, /*获取到手机的时间和日期,注意会有兼容性问题*/ + BT_STATUS_INBAND_RINGTONE, + BT_STATUS_VOICE_RECOGNITION, + BT_STATUS_AVRCP_INCOME_OPID, /*收到远端设备发过来的AVRCP命令*/ + BT_STATUS_HFP_SERVICE_LEVEL_CONNECTION_OK, + BT_STATUS_CONN_A2DP_CH, + BT_STATUS_CONN_HFP_CH, + BT_STATUS_INQUIRY_TIMEOUT, + /*下面是1个持续的状态,是get_stereo_bt_connect_status获取*/ + + /*下面是6个持续的状态,是get_bt_connect_status()获取*/ + BT_STATUS_INITING, /*正在初始化*/ + BT_STATUS_WAITINT_CONN, /*等待连接*/ + BT_STATUS_AUTO_CONNECTINT, /*正在回连*/ + BT_STATUS_CONNECTING, /*已连接,没有电话和音乐在活动*/ + BT_STATUS_TAKEING_PHONE, /*正在电话*/ + BT_STATUS_PLAYING_MUSIC, /*正在音乐*/ + BT_STATUS_A2DP_MEDIA_START, + BT_STATUS_A2DP_MEDIA_STOP, + + + BT_STATUS_BROADCAST_STATE,/*braoadcaset中*/ + + BT_STATUS_TRIM_OVER, /*测试盒TRIM完成*/ +} STATUS_FOR_USER; + +typedef enum { + BT_CALL_BATTERY_CHG = 0, //电池电量改变 + BT_CALL_SIGNAL_CHG, //网络信号改变 + BT_CALL_INCOMING, //电话打入 + BT_CALL_OUTGOING, //电话打出 + BT_CALL_ACTIVE, //接通电话 + BT_CALL_HANGUP, //电话挂断 + BT_CALL_ALERT, //远端reach + BT_CALL_VOL_CHANGED, +} BT_CALL_IND_STA; + +typedef enum { + BT_MUSIC_STATUS_IDLE = 0, + BT_MUSIC_STATUS_STARTING, + BT_MUSIC_STATUS_SUSPENDING, +} BT_MUSIC_STATE; //音乐状态 + +#define SYS_BT_EVENT_TYPE_CON_STATUS (('C' << 24) | ('O' << 16) | ('N' << 8) | '\0') +#define SYS_BT_EVENT_TYPE_HCI_STATUS (('H' << 24) | ('C' << 16) | ('I' << 8) | '\0') + + + +#define REMOTE_DEFAULT 0x00 +#define REMOTE_SINK 0x01 +#define REMOTE_SOURCE 0x02 + + +#define SPP_CH 0x01 +#define HFP_CH 0x02 +#define A2DP_CH 0x04 //media +#define AVCTP_CH 0x08 +#define HID_CH 0x10 +#define AVDTP_CH 0x20 +#define PBAP_CH 0x40 +#define HFP_AG_CH 0x80 +#define A2DP_SRC_CH 0x2000 +struct sniff_ctrl_config_t { + u16 sniff_max_interval; + u16 sniff_mix_interval; + u16 sniff_attemp; + u16 sniff_timeout; + u8 sniff_addr[6]; +}; +extern u32 user_send_cmd_prepare(USER_CMD_TYPE cmd, u16 param_len, u8 *param); +extern u32 user_emitter_cmd_prepare(USER_CMD_TYPE cmd, u16 param_len, u8 *param); +u8 get_emitter_connect_status(void); +u16 get_emitter_curr_channel_state(); +u8 get_emitter_a2dp_status(void); + + +/* +u16 get_curr_channel_state(); 与 channel 判断区分 +主动获取当前链路的连接状态,可以用来判断有哪些链路连接上了 +*/ +extern u16 get_curr_channel_state(); +/* +u8 get_call_status(); 与BT_CALL_IND_STA 枚举的值判断 +用于获取当前蓝牙电话的状态 +*/ +extern u8 get_call_status(); +extern void user_cmd_ctrl_init(void *var); + +/******当前连接的设备是jl测试盒**********/ +extern bool get_remote_test_flag(); +extern void set_remote_test_flag(u8 own_remote_test); +extern void bt_fast_test_handle_register(void (*handle)(void)); +extern void bt_dut_test_handle_register(void (*handle)(u8)); +extern void inquiry_result_handle_register(void (*handle)(char *name, u8 name_len, u8 *addr, u32 dev_class, char rssi)); + +/*个性化参数设置*/ +/*用户调试设置地址,6个byte*/ +extern void __set_bt_mac_addr(u8 *addr); + +/*用户调试设置name,最长32个字符*/ +extern void __set_host_name(const char *name, u8 len); +/*用户调试设置pin code*/ +extern void __set_pin_code(const char *code); +/*该接口用于设置上电回连需要依次搜索设备的个数。*/ +extern void __set_auto_conn_device_num(u8 num); + +/*//回连的超时设置。ms单位。但是对手机发起的连接是没作用的*/ +extern void __set_super_timeout_value(u16 time); +/*外部设置支持什么协议*/ +extern void bt_cfg_default_init(u8 support); + +/*设置电量显示发送更新的周期时间,为0表示关闭电量显示功能*/ +extern void __bt_set_update_battery_time(u8 time); +/*给用户设置蓝牙支持连接的个数,主要用于控制控制可发现可连接和回连流程*/ +extern void __set_user_ctrl_conn_num(u8 num); +/*提供接口外部设置要保留hfp不要蓝牙通话*/ +extern void __set_disable_sco_flag(bool flag); + +/*提供接口外部设置简易配对参数*/ +extern void __set_simple_pair_param(u8 io_cap, u8 oob_data, u8 mitm); + +/*有些自选接口用来实现个性化功能流程,回调函数注册,记得常来看看哟*/ +extern void get_battery_value_register(int (*handle)(void)); /*电量发送时获取电量等级的接口注册*/ +extern void music_vol_change_handle_register(void (*handle)(int vol), int (*handle2)(void)); /*手机更样机音乐模式的音量同步*/ +extern void read_remote_name_handle_register(void (*handle)(u8 status, u8 *addr, u8 *name)); /*获取到名字后的回调函数接口注册函数*/ +extern void spp_data_deal_handle_register(void (*handler)(u8 packet_type, u16 channel, u8 *packet, u16 size)); /*支持串口功能的数据处理接口*/ +extern void discon_complete_handle_register(void (*handle)(u8 *addr, int reason)); /*断开或者连接上会调用的函数,给客户反馈信息*/ + +extern void update_bt_current_status(u8 *addr, u8 new_status, u8 conn_status); +extern u8 get_bt_connect_status(void); +extern u8 a2dp_get_status(void); + +/*//回连的超时设置。ms单位。但是对手机发起的连接是没作用的*/ +extern void __set_super_timeout_value(u16 time); +/*//回连page的超时设置。ms单位*/ +extern void __set_page_timeout_value(u16 time); +/*上电自动搜索设备的个数*/ +extern u8 get_current_poweron_memory_search_index(u8 *temp_mac_addr); +extern void clear_current_poweron_memory_search_index(u8 inc); + +extern void __set_user_background_goback(u8 en); + +extern bool user_sniff_check_req(u8 sniff_cnt_time); + +extern int tws_updata_phone_wait_con_addr(u8 *addr); +extern int tws_updata_internal_addr(u8 *internal_addr_local, u8 *internal_addr_remote); + + +extern void bt_discon_complete_handle(u8 *addr, int reason); + +extern bool is_1t2_connection(void); +extern u8 get_total_connect_dev(void); +extern u8 is_bt_conn_hfp_hangup(u8 *addr); + +extern void infor_2_user_handle_register(int (*handle)(u8 *info, u16 len), u8 *buffer_ptr); +extern void bt_music_info_handle_register(void (*handler)(u8 type, u32 time, u8 *info, u16 len)); +extern void set_bt_vm_interface(u32 vm_index, void *interface); +extern void bredr_stack_init(void); +extern u8 get_a2dp_decoder_status(); +extern bool bt_api_conn_mode_check(u8 enable, u8 *addr); +extern u8 bt_api_enter_sniff_status_check(u16 time_cnt, u8 *addr); +extern void user_cmd_timer_init(); +extern void remove_user_cmd_timer(); +extern u8 get_auto_connect_state(u8 *addr); +extern u8 get_esco_coder_busy_flag(); +extern u8 hci_standard_connect_check(void); +extern void set_stack_exiting(u8 exit); +extern int a2dp_media_packet_codec_type(u8 *data); +extern void lib_make_ble_address(u8 *ble_address, u8 *edr_address); +extern u8 connect_last_device_from_vm(); +extern u8 hci_standard_connect_check(void); +extern void __bt_set_hid_independent_flag(bool flag); +extern bool get_esco_busy_flag(); +extern int btstack_exit(); +extern int sbc_energy_check(u8 *packet, u16 size); +extern int a2dp_source_init(void *buf, u16 len, int deal_flag); +extern int hfp_ag_buf_init(void *buf, int size, int deal_flag); +extern void __set_emitter_enable_flag(u8 flag); +extern void hci_cancel_inquiry(); +extern u8 hci_standard_connect_check(void); +extern int __emitter_send_media_toggle(u8 *addr, u8 toggle); +extern u8 is_a2dp_source_dev_null(); +extern u8 get_total_connect_dev(void); +extern u8 get_remote_dev_info_index(); +extern u8 check_tws_le_aa(void); +extern u8 get_esco_coder_busy_flag(); +extern void tws_api_set_connect_aa(int); +extern void tws_le_acc_generation_init(void); +extern void tws_api_clear_connect_aa(); +extern void clear_sniff_cnt(void); +extern u8 delete_last_device_from_vm(); + +#define BD_CLASS_WEARABLE_HEADSET 0x240404/*ios10.2 display headset icon*/ +#define BD_CLASS_HANDS_FREE 0x240408/*ios10.2 display bluetooth icon*/ +#define BD_CLASS_MICROPHONE 0x240410 +#define BD_CLASS_LOUDSPEAKER 0x240414 +#define BD_CLASS_HEADPHONES 0x240418 +#define BD_CLASS_CAR_AUDIO 0x240420 +#define BD_CLASS_HIFI_AUDIO 0x240428 +#define BD_CLASS_PHONEBOOK 0x340404 +#define BD_CLASS_PAN_DEV 0X020118 +#define BD_CLASS_SMART_PHONE 0x40020C +#define BD_CLASS_SMART_PHONE_2 0x5A020C + +#define BD_CLASS_MOUSE 0x002580 +#define BD_CLASS_KEYBOARD 0x002540 +#define BD_CLASS_KEYBOARD_MOUSE 0x0025C0 + +#define BD_CLASS_TRANSFER_HEALTH 0x10091C + +extern void __change_hci_class_type(u32 class); +extern void __set_support_msbc_flag(bool flag); +extern void __set_support_aac_flag(bool flag); + +/*设置1拖2时电话是否抢断标识*/ +extern void __set_hfp_switch(u8 switch_en); +/* + *设置1拖2时电话是否恢复标识 + *通话结束的时候,如果还有手机在通话,自动切到蓝牙端 + */ +extern void __set_hfp_restore(u8 restore_en); +/*当前设备被打断时是否自动暂停*/ +extern void __set_auto_pause_flag(u8 flag); +/*当前设备被打断时是否自动暂停*/ +extern void __set_auto_pause_flag(u8 flag); +/*高级音频设置标志是否允许后者打断前者*/ +extern void __set_music_break_in_flag(u8 flag); +/*高级音频打断检测数据包阈值设置*/ +extern void __set_a2dp_sound_detect_counter(u8 sound_come, u8 sound_go); +/*pan的控制接口和发数接口, + addr指定就按指定的查找,NULL就默认正在使用那个 + cmd 下面定义的宏用户可以使用 + param 传参数需要的值或者data包的长度 + data 传的是要发数据的包指针 + */ +#define USER_PAN_CMD_SEND_DATA 0xff +int user_pan_send_cmd(u8 *addr, u32 cmd, u32 param, u8 *data); + +enum { + BD_ESCO_IDLE = 0, /*当前没有设备通话中*/ + BD_ESCO_BUSY_CURRENT, /*当前地址对应的设备通话中*/ + BD_ESCO_BUSY_OTHER, /*通话中的设备非当前地址*/ +}; +extern u8 check_esco_state_via_addr(u8 *addr); +/*判断是否主动回连*/ +extern u8 get_auto_connect_state(u8 *addr); + +typedef struct __hid_sdp_info { + u16 vid_private; + u16 pid_private; + u16 ver_private; + + u8 sub_class; + u8 country_code; + bool virtual_cable; + bool reconnect_initiate; + bool sdp_disable; + bool battery_power; + bool remote_wake; + bool normally_connectable; + bool boot_device; + u16 version; + u16 parser_version; + u16 profile_version; + u16 supervision_timeout; + u16 language; + u16 bt_string_offset; + u16 descriptor_len; + u8 *descriptor; + char *service_name; + char *service_description; + char *provide_name; + void (*sdp_request_respone_callback)(u8 type); + u8 *extra_buf; + u8 extra_len; +} hid_sdp_info_t; + + +typedef struct { + u16 chl_id; + u16 data_len; + u8 *data_ptr; +} hid_s_param_t; + +extern u16 sdp_create_diy_device_ID_service(u8 *buffer, u16 buffer_size); +extern u16 sdp_create_diy_hid_service(u8 *buffer, u16 buffer_size, const u8 *hid_descriptor, u16 hid_descriptor_size); +u8 get_remote_vol_sync(void); +void set_start_search_spp_device(u8 spp); + + +u8 restore_remote_device_info_opt(bd_addr_t *mac_addr, u8 conn_device_num, u8 id); +u8 restore_remote_device_info_profile(bd_addr_t *mac_addr, u8 device_num, u8 id, u8 profile); +/*remote dev type*/ +/*0:unknow,1-android,2:apple_inc,0x03-xiaomi*/ +enum { + REMOTE_DEV_UNKNOWN = 0, + REMOTE_DEV_ANDROID , + REMOTE_DEV_IOS , + REMOTE_DEV_XIAOMI , +}; +u8 remote_dev_company_ioctrl(bd_addr_t dev_addr, u8 op_flag, u8 value); +u8 hci_standard_link_check(void); +extern void XM_status_update(u8 status); +u8 __bt_emitter_pp(u8 pp); + +#endif diff --git a/include_lib/btstack/bluetooth.h b/include_lib/btstack/bluetooth.h new file mode 100644 index 0000000..73ef0d6 --- /dev/null +++ b/include_lib/btstack/bluetooth.h @@ -0,0 +1,563 @@ +#ifndef _BLUETOOTH_H_ +#define _BLUETOOTH_H_ + +#include "typedef.h" + + +//LE +#include "le/ble_data_types.h" +#include "le/ble_api.h" +#include "le/le_user.h" +#include "le/att.h" +#include "le/gatt.h" +#include "le/sm.h" + + +//Classic + + + +//Common +#include "btstack_event.h" + + +#define HCI_COMMAND_DATA_PACKET 0x01 +#define HCI_ACL_DATA_PACKET 0x02 +#define HCI_SCO_DATA_PACKET 0x03 +#define HCI_EVENT_PACKET 0x04 + +// OGFs +#define OGF_LINK_CONTROL 0x01 +#define OGF_LINK_POLICY 0x02 +#define OGF_CONTROLLER_BASEBAND 0x03 +#define OGF_INFORMATIONAL_PARAMETERS 0x04 +#define OGF_STATUS_PARAMETERS 0x05 +#define OGF_TESTING 0x06 +#define OGF_LE_CONTROLLER 0x08 +#define OGF_VENDOR_LE_CONTROLLER 0x3e +#define OGF_VENDOR 0x3f + + +// Events from host controller to host + +/** + * @format 1 + * @param status + */ +#define HCI_EVENT_INQUIRY_COMPLETE 0x01 + +/** + * @format 1B11132 + * @param num_responses + * @param bd_addr + * @param page_scan_repetition_mode + * @param reserved1 + * @param reserved2 + * @param class_of_device + * @param clock_offset + */ +#define HCI_EVENT_INQUIRY_RESULT 0x02 + +/** + * @format 12B11 + * @param status + * @param connection_handle + * @param bd_addr + * @param link_type + * @param encryption_enabled + */ +#define HCI_EVENT_CONNECTION_COMPLETE 0x03 +/** + * @format B31 + * @param bd_addr + * @param class_of_device + * @param link_type + */ +#define HCI_EVENT_CONNECTION_REQUEST 0x04 +/** + * @format 121 + * @param status + * @param connection_handle + * @param reason + */ +#define HCI_EVENT_DISCONNECTION_COMPLETE 0x05 +/** + * @format 12 + * @param status + * @param connection_handle + */ +#define HCI_EVENT_AUTHENTICATION_COMPLETE 0x06 +/** + * @format 1BN + * @param status + * @param bd_addr + * @param remote_name + */ +#define HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE 0x07 +/** + * @format 121 + * @param status + * @param connection_handle + * @param encryption_enabled + */ +#define HCI_EVENT_ENCRYPTION_CHANGE 0x08 +/** + * @format 12 + * @param status + * @param connection_handle + */ +#define HCI_EVENT_CHANGE_CONNECTION_LINK_KEY_COMPLETE 0x09 +/** + * @format 121 + * @param status + * @param connection_handle + * @param key_flag + */ +#define HCI_EVENT_MASTER_LINK_KEY_COMPLETE 0x0A + +#define HCI_EVENT_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE 0x0B + +#define HCI_EVENT_READ_REMOTE_VERSION_INFORMATION_COMPLETE 0x0C + +#define HCI_EVENT_QOS_SETUP_COMPLETE 0x0D + +/** + * @format 12R + * @param num_hci_command_packets + * @param command_opcode + * @param return_parameters + */ +#define HCI_EVENT_COMMAND_COMPLETE 0x0E +/** + * @format 112 + * @param status + * @param num_hci_command_packets + * @param command_opcode + */ +#define HCI_EVENT_COMMAND_STATUS 0x0F + +/** + * @format 1 + * @param hardware_code + */ +#define HCI_EVENT_HARDWARE_ERROR 0x10 + +#define HCI_EVENT_FLUSH_OCCURRED 0x11 + +/** + * @format 1B1 + * @param status + * @param bd_addr + * @param role + */ +#define HCI_EVENT_ROLE_CHANGE 0x12 + +// TODO: number_of_handles 1, connection_handle[H*i], hc_num_of_completed_packets[2*i] +#define HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS 0x13 + +/** + * @format 1H12 + * @param status + * @param handle + * @param mode + * @param interval + */ +#define HCI_EVENT_MODE_CHANGE_EVENT 0x14 + +// TODO: num_keys, bd_addr[B*i], link_key[16 octets * i] +#define HCI_EVENT_RETURN_LINK_KEYS 0x15 + +/** + * @format B + * @param bd_addr + */ +#define HCI_EVENT_PIN_CODE_REQUEST 0x16 + +/** + * @format B + * @param bd_addr + */ +#define HCI_EVENT_LINK_KEY_REQUEST 0x17 + +// TODO: bd_addr B, link_key 16octets, key_type 1 +#define HCI_EVENT_LINK_KEY_NOTIFICATION 0x18 + +/** + * @format 1 + * @param link_type + */ +#define HCI_EVENT_DATA_BUFFER_OVERFLOW 0x1A + +/** + * @format H1 + * @param handle + * @param lmp_max_slots + */ +#define HCI_EVENT_MAX_SLOTS_CHANGED 0x1B + +/** + * @format 1H2 + * @param status + * @param handle + * @param clock_offset + */ +#define HCI_EVENT_READ_CLOCK_OFFSET_COMPLETE 0x1C + +/** + * @format 1H2 + * @param status + * @param handle + * @param packet_types + * @pnote packet_type is in plural to avoid clash with Java binding Packet.getPacketType() + */ +#define HCI_EVENT_CONNECTION_PACKET_TYPE_CHANGED 0x1D + +#define HCI_EVENT_PAGE_SCAN_REPETITION_MODE_CHANGE 0x20 +/** + * @format 1B11321 + * @param num_responses + * @param bd_addr + * @param page_scan_repetition_mode + * @param reserved + * @param class_of_device + * @param clock_offset + * @param rssi + */ +#define HCI_EVENT_INQUIRY_RESULT_WITH_RSSI 0x22 + +#define HCI_EVENT_READ_REMOTE_EXTERNED_FEATURES_COMPLETE 0x23 +/** + * @format 1HB111221 + * @param status + * @param handle + * @param bd_addr + * @param link_type + * @param transmission_interval + * @param retransmission_interval + * @param rx_packet_length + * @param tx_packet_length + * @param air_mode + */ +#define HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE 0x2C + +// TODO: serialize extended_inquiry_response and provide parser +/** + * @format 1B11321 + * @param num_responses + * @param bd_addr + * @param page_scan_repetition_mode + * @param reserved + * @param class_of_device + * @param clock_offset + * @param rssi + */ +#define HCI_EVENT_EXTENDED_INQUIRY_RESPONSE 0x2F +#define HCI_EVENT_EXTENDED_INQUIRY_RESULT 0x2F + +/** + * @format 1H + * @param status + * @param handle + */ +#define HCI_EVENT_ENCRYPTION_KEY_REFRESH_COMPLETE 0x30 + +#define HCI_EVENT_IO_CAPABILITY_REQUEST 0x31 +#define HCI_EVENT_IO_CAPABILITY_RESPONSE 0x32 + +/** + * @format B4 + * @param bd_addr + * @param numeric_value + */ +#define HCI_EVENT_USER_CONFIRMATION_REQUEST 0x33 + +/** + * @format B + * @param bd_addr + */ +#define HCI_EVENT_USER_PASSKEY_REQUEST 0x34 + +/** + * @format B + * @param bd_addr + */ +#define HCI_EVENT_REMOTE_OOB_DATA_REQUEST 0x35 + +/** + * @format 1B + * @param status + * @param bd_addr + */ +#define HCI_EVENT_SIMPLE_PAIRING_COMPLETE 0x36 +#define HCI_EVENT_LINK_SUPPERVISION_TIMEOUT_CHANGE_EVENT 0x38 + +#define HCI_EVENT_USER_PRESSKEY_NOTIFICATION 0x3B +#define HCI_EVENT_REMOTE_KEYPRESS_NOTIFICATION 0x3C +#define HCI_EVENT_REMOTE_SUPPORTED_FEATURES_NOTIFICATION 0x3D +#define HCI_EVENT_LE_META 0x3E + +// last used HCI_EVENT in 2.1 is 0x3d +// last used HCI_EVENT in 4.1 is 0x57 + + +#define HCI_EVENT_VENDOR_FRE_OFFSET_TRIM 0xF6 +#define HCI_EVENT_VENDOR_ENCRY_COMPLETE 0xF7 +#define HCI_EVENT_VENDOR_NO_RECONN_ADDR 0xF8 +#define HCI_EVENT_VENDOR_SETUP_COMPLETE 0xF9 +#define HCI_EVENT_VENDOR_DUT 0xFA +#define HCI_EVENT_VENDOR_OSC_INTERNAL 0xFB +#define HCI_EVENT_VENDOR_FAST_TEST 0xFC +#define HCI_EVENT_VENDOR_REMOTE_UPDATE 0xFD +#define HCI_EVENT_VENDOR_REMOTE_TEST 0xFE +#define HCI_EVENT_VENDOR_SPECIFIC 0xFF + +#define BTSTACK_EVENT_HCI_CONNECTIONS_DELETE 0x6D + +/** + * @format 11H11B2221 + * @param subevent_code + * @param status + * @param connection_handle + * @param role + * @param peer_address_type + * @param peer_address + * @param conn_interval + * @param conn_latency + * @param supervision_timeout + * @param master_clock_accuracy + */ +#define HCI_SUBEVENT_LE_CONNECTION_COMPLETE 0x01 + +// array of advertisements, not handled by event accessor generator +#define HCI_SUBEVENT_LE_ADVERTISING_REPORT 0x02 + +/** + * @format 11H222 + * @param subevent_code + * @param status + * @param connection_handle + * @param conn_interval + * @param conn_latency + * @param supervision_timeout + */ +#define HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE 0x03 + +/** + * @format 1HD2 + * @param subevent_code + * @param connection_handle + * @param random_number + * @param encryption_diversifier + */ +#define HCI_SUBEVENT_LE_READ_REMOTE_USED_FEATURES_COMPLETE 0x04 + +/** + * @format 1HD2 + * @param subevent_code + * @param connection_handle + * @param random_number + * @param encryption_diversifier + */ +#define HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST 0x05 + +/** + * @format 1H2222 + * @param subevent_code + * @param connection_handle + * @param interval_min + * @param interval_max + * @param latency + * @param timeout + */ +#define HCI_SUBEVENT_LE_REMOTE_CONNECTION_PARAMETER_REQUEST 0x06 + +/** + * @format 1H2222 + * @param subevent_code + * @param connection_handle + * @param max_tx_octets + * @param max_tx_time + * @param max_rx_octets + * @param max_rx_time + */ +#define HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE 0x07 + +/** + * @format 11QQ + * @param subevent_code + * @param status + * @param dhkey_x x coordinate of P256 public key + * @param dhkey_y y coordinate of P256 public key + */ +#define HCI_SUBEVENT_LE_READ_LOCAL_P256_PUBLIC_KEY_COMPLETE 0x08 +/** +* @format 11Q +* @param subevent_code +* @param status +* @param dhkey Diffie-Hellman key +*/ +#define HCI_SUBEVENT_LE_GENERATE_DHKEY_COMPLETE 0x09 + +/** + * @format 11H11BBB2221 + * @param subevent_code + * @param status + * @param connection_handle + * @param role + * @param peer_address_type + * @param perr_addresss + * @param local_resolvable_private_addres + * @param peer_resolvable_private_addres + * @param conn_interval + * @param conn_latency + * @param supervision_timeout + * @param master_clock_accuracy + */ +#define HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE 0x0A + +// array of advertisements, not handled by event accessor generator +#define HCI_SUBEVENT_LE_DIRECT_ADVERTISING_REPORT 0x0B + +/** + * @format 11211 + * @param subevent_code + * @param status + * @param connection_handle + * @param TX_PHY + * @param RX_PHY + */ +#define HCI_SUBEVENT_LE_PHY_UPDATE_COMPLETE 0x0C + +// array of advertisements, not handled by event accessor generator +#define HCI_SUBEVENT_LE_EXTENDED_ADVERTISING_REPORT 0x0D + +#define HCI_SUBEVENT_LE_PERIODIC_ADVERTISING_SYNC_ESTABLISHED 0x0E + +/** + * @format 1211111B + * @param subevent_code + * @param sync_handle + * @param tx_power + * @param rssi + * @param unused + * @param data_status + * @param data_length + * @param data + */ +#define HCI_SUBEVENT_LE_PERIODIC_ADVERTISING_REPORT 0x0F + +/** + * @format 2 + * @param sync_handle +*/ +#define HCI_SUBEVENT_LE_PERIODIC_ADVERTISING_SYNC_LOST 0x10 + +/** + * @format +*/ +#define HCI_SUBEVENT_LE_SCAN_TIMEOUT 0x11 + +/** + * @format 1121 + * @param subevent_code + * @param status + * @param advertising_handle + * @param connection_handle + * @param num_completed_extended_advertising_events + */ +#define HCI_SUBEVENT_LE_ADVERTISING_SET_TERMINATED 0x12 + +/** + * @format 1116 + * @param subevent_code + * @param advertising_handle + * @param scanner_address_type + * @param scanner_address + */ +#define HCI_SUBEVENT_LE_SCAN_REQUEST_RECEIVED 0x13 + +/** + * @format 21 + * @param subevent_code + * @param connection_handle + * @param channel_selection_algorithm + */ +#define HCI_SUBEVENT_LE_CHANNEL_SELECTION_ALGORITHM 0x14 + + +#define HCI_SUBEVENT_LE_VENDOR_INTERVAL_COMPLETE 0xF0 + +/** + * @format +*/ +#define HCI_EVENT_ANCS_META 0xEA + + +/** + * compact HCI Command packet description + */ +typedef struct { + uint16_t opcode; + const char *format; +} hci_cmd_t; + +int hci_send_cmd(const hci_cmd_t *cmd, ...); + + +extern const hci_cmd_t hci_reset; +extern const hci_cmd_t hci_read_bd_addr; +extern const hci_cmd_t hci_read_local_supported_features; +extern const hci_cmd_t hci_read_buffer_size; +extern const hci_cmd_t hci_read_local_supported_commands; +extern const hci_cmd_t hci_read_local_version_information; +extern const hci_cmd_t hci_read_le_host_supported; +extern const hci_cmd_t hci_read_local_name; +extern const hci_cmd_t hci_write_class_of_device; +extern const hci_cmd_t hci_write_local_name; +extern const hci_cmd_t hci_write_scan_enable; +extern const hci_cmd_t hci_set_event_mask; +extern const hci_cmd_t hci_le_add_device_to_white_list; +extern const hci_cmd_t hci_le_clear_white_list; +extern const hci_cmd_t hci_le_connection_update; +extern const hci_cmd_t hci_le_create_connection; +extern const hci_cmd_t hci_le_create_connection_cancel; +extern const hci_cmd_t hci_le_encrypt; +extern const hci_cmd_t hci_le_generate_dhkey; +extern const hci_cmd_t hci_le_long_term_key_negative_reply; +extern const hci_cmd_t hci_le_long_term_key_request_reply; +extern const hci_cmd_t hci_le_rand; +extern const hci_cmd_t hci_le_read_advertising_channel_tx_power; +extern const hci_cmd_t hci_le_read_buffer_size; +extern const hci_cmd_t hci_le_read_channel_map; +extern const hci_cmd_t hci_le_read_local_p256_public_key; +extern const hci_cmd_t hci_le_read_maximum_data_length; +extern const hci_cmd_t hci_le_read_remote_used_features; +extern const hci_cmd_t hci_le_read_suggested_default_data_length; +extern const hci_cmd_t hci_le_read_supported_features; +extern const hci_cmd_t hci_le_read_supported_states; +extern const hci_cmd_t hci_le_read_white_list_size; +extern const hci_cmd_t hci_le_receiver_test; +extern const hci_cmd_t hci_le_remove_device_from_white_list; +extern const hci_cmd_t hci_le_set_advertise_enable; +extern const hci_cmd_t hci_le_set_advertising_data; +extern const hci_cmd_t hci_le_set_advertising_parameters; +extern const hci_cmd_t hci_le_set_data_length; +extern const hci_cmd_t hci_le_set_event_mask; +extern const hci_cmd_t hci_le_set_host_channel_classification; +extern const hci_cmd_t hci_le_set_random_address; +extern const hci_cmd_t hci_le_set_scan_enable; +extern const hci_cmd_t hci_le_set_scan_parameters; +extern const hci_cmd_t hci_le_set_scan_response_data; +extern const hci_cmd_t hci_le_start_encryption; +extern const hci_cmd_t hci_le_test_end; +extern const hci_cmd_t hci_le_transmitter_test; +extern const hci_cmd_t hci_le_write_suggested_default_data_length; +extern const hci_cmd_t hci_le_set_phy; + +extern const hci_cmd_t hci_le_set_ext_advertising_parameters; +extern const hci_cmd_t hci_le_set_ext_advertising_data; +extern const hci_cmd_t hci_le_set_ext_advertise_enable; +extern const hci_cmd_t hci_le_set_ext_scan_parameters; +extern const hci_cmd_t hci_le_set_ext_scan_enable; + +#endif diff --git a/include_lib/btstack/bt_profile_config.h b/include_lib/btstack/bt_profile_config.h new file mode 100644 index 0000000..0f1a665 --- /dev/null +++ b/include_lib/btstack/bt_profile_config.h @@ -0,0 +1,38 @@ +/********************************************************************************************* + * Filename : bt_profile_config.h + + * Description : + + * Author : Tongai + + * Email : laotongai@zh-jieli.com + + * Last modifiled : 2020-07-01 16:31 + + * Copyright:(c)JIELI 2011-2019 @ , All Rights Reserved. +*********************************************************************************************/ +#ifndef BT_PROFILE_H +#define BT_PROFILE_H + + +#define BT_BTSTACK_CLASSIC BIT(0) +#define BT_BTSTACK_LE_ADV BIT(1) +#define BT_BTSTACK_LE BIT(2) + +extern const int config_stack_modules; +#define STACK_MODULES_IS_SUPPORT(x) (config_stack_modules & (x)) + + + +extern u8 app_bredr_pool[]; +extern u8 app_le_pool[]; +extern u8 app_l2cap_pool[]; +extern u8 app_bredr_profile[]; + +extern u16 get_bredr_pool_len(void); +extern u16 get_le_pool_len(void); +extern u16 get_l2cap_stack_len(void); +extern u16 get_profile_pool_len(void); + + +#endif diff --git a/include_lib/btstack/btstack_error.h b/include_lib/btstack/btstack_error.h new file mode 100644 index 0000000..b3187dd --- /dev/null +++ b/include_lib/btstack/btstack_error.h @@ -0,0 +1,38 @@ +#ifndef BTSTACK_ERROR_H +#define BTSTACK_ERROR_H + + +#define ERROR_CODE_SUCCESS 0x00 +#define ERROR_CODE_PAGE_TIMEOUT 0x04 +#define ERROR_CODE_AUTHENTICATION_FAILURE 0x05 +#define ERROR_CODE_PIN_OR_KEY_MISSING 0x06 +#define ERROR_CODE_CONNECTION_TIMEOUT 0x08 +#define ERROR_CODE_SYNCHRONOUS_CONNECTION_LIMIT_TO_A_DEVICE_EXCEEDED 0x0A +#define ERROR_CODE_ACL_CONNECTION_ALREADY_EXISTS 0x0B +#define ERROR_CODE_CONNECTION_REJECTED_DUE_TO_LIMITED_RESOURCES 0x0D +#define ERROR_CODE_CONNECTION_REJECTED_DUE_TO_UNACCEPTABLE_BD_ADDR 0x0F +#define ERROR_CODE_CONNECTION_ACCEPT_TIMEOUT_EXCEEDED 0x10 +#define ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION 0x13 +#define ERROR_CODE_CONNECTION_TERMINATED_BY_LOCAL_HOST 0x16 + +#define CUSTOM_BB_AUTO_CANCEL_PAGE 0xFD //// app cancle page +#define BB_CANCEL_PAGE 0xFE //// bb cancle page + + + + + + + + + + + + + + + + + +#endif + diff --git a/include_lib/btstack/btstack_event.h b/include_lib/btstack/btstack_event.h new file mode 100644 index 0000000..a2cd867 --- /dev/null +++ b/include_lib/btstack/btstack_event.h @@ -0,0 +1,6625 @@ +/********************************************************************************************* + * Filename : btstack_event.h + + * Description : + + * Author : Tongai + + * Email : laotongai@zh-jieli.com + + * Last modifiled : 2020-07-01 16:23 + + * Copyright:(c)JIELI 2011-2019 @ , All Rights Reserved. +*********************************************************************************************/ + +#ifndef __BTSTACK_EVENT_H +#define __BTSTACK_EVENT_H + +#if defined __cplusplus +extern "C" { +#endif + +#include "btstack/btstack_typedef.h" +#include + +#define ENABLE_BLE + +#ifdef ENABLE_BLE +#include "le/gatt.h" +#endif + + /* API_START */ + + /** + * @brief Get event type + * @param event + * @return type of event + */ + static inline uint8_t hci_event_packet_get_type(const uint8_t *event) + { + return event[0]; + } + + /*** + * @brief Get subevent code for ancs event + * @param event packet + * @return subevent_code + */ + static inline uint8_t hci_event_ancs_meta_get_subevent_code(const uint8_t *event) + { + return event[2]; + } + /*** + * @brief Get subevent code for avdtp event + * @param event packet + * @return subevent_code + */ + static inline uint8_t hci_event_avdtp_meta_get_subevent_code(const uint8_t *event) + { + return event[2]; + } + /*** + * @brief Get subevent code for a2dp event + * @param event packet + * @return subevent_code + */ + static inline uint8_t hci_event_a2dp_meta_get_subevent_code(const uint8_t *event) + { + return event[2]; + } + /*** + * @brief Get subevent code for avrcp event + * @param event packet + * @return subevent_code + */ + static inline uint8_t hci_event_avrcp_meta_get_subevent_code(const uint8_t *event) + { + return event[2]; + } + /*** + * @brief Get subevent code for goep event + * @param event packet + * @return subevent_code + */ + static inline uint8_t hci_event_goep_meta_get_subevent_code(const uint8_t *event) + { + return event[2]; + } + /*** + * @brief Get subevent code for hfp event + * @param event packet + * @return subevent_code + */ + static inline uint8_t hci_event_hfp_meta_get_subevent_code(const uint8_t *event) + { + return event[2]; + } + /*** + * @brief Get subevent code for hsp event + * @param event packet + * @return subevent_code + */ + static inline uint8_t hci_event_hsp_meta_get_subevent_code(const uint8_t *event) + { + return event[2]; + } + /*** + * @brief Get subevent code for pbap event + * @param event packet + * @return subevent_code + */ + static inline uint8_t hci_event_pbap_meta_get_subevent_code(const uint8_t *event) + { + return event[2]; + } + /*** + * @brief Get subevent code for le event + * @param event packet + * @return subevent_code + */ + static inline uint8_t hci_event_le_meta_get_subevent_code(const uint8_t *event) + { + return event[2]; + } + /*** + * @brief Get subevent code for hid event + * @param event packet + * @return subevent_code + */ + static inline uint8_t hci_event_hid_meta_get_subevent_code(const uint8_t *event) + { + return event[2]; + } + /*** + * @brief Get subevent code for hids event + * @param event packet + * @return subevent_code + */ + static inline uint8_t hci_event_hids_meta_get_subevent_code(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field status from event HCI_EVENT_INQUIRY_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_inquiry_complete_get_status(const uint8_t *event) + { + return event[2]; + } + + /** + * @brief Get field num_responses from event HCI_EVENT_INQUIRY_RESULT + * @param event packet + * @return num_responses + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_inquiry_result_get_num_responses(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field bd_addr from event HCI_EVENT_INQUIRY_RESULT + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hci_event_inquiry_result_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[3], bd_addr); + } + /** + * @brief Get field page_scan_repetition_mode from event HCI_EVENT_INQUIRY_RESULT + * @param event packet + * @return page_scan_repetition_mode + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_inquiry_result_get_page_scan_repetition_mode(const uint8_t *event) + { + return event[9]; + } + /** + * @brief Get field reserved1 from event HCI_EVENT_INQUIRY_RESULT + * @param event packet + * @return reserved1 + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_inquiry_result_get_reserved1(const uint8_t *event) + { + return event[10]; + } + /** + * @brief Get field reserved2 from event HCI_EVENT_INQUIRY_RESULT + * @param event packet + * @return reserved2 + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_inquiry_result_get_reserved2(const uint8_t *event) + { + return event[11]; + } + /** + * @brief Get field class_of_device from event HCI_EVENT_INQUIRY_RESULT + * @param event packet + * @return class_of_device + * @note: btstack_type 3 + */ + static inline uint32_t hci_event_inquiry_result_get_class_of_device(const uint8_t *event) + { + return little_endian_read_24(event, 12); + } + /** + * @brief Get field clock_offset from event HCI_EVENT_INQUIRY_RESULT + * @param event packet + * @return clock_offset + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_inquiry_result_get_clock_offset(const uint8_t *event) + { + return little_endian_read_16(event, 15); + } + + /** + * @brief Get field status from event HCI_EVENT_CONNECTION_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_connection_complete_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field connection_handle from event HCI_EVENT_CONNECTION_COMPLETE + * @param event packet + * @return connection_handle + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_connection_complete_get_connection_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field bd_addr from event HCI_EVENT_CONNECTION_COMPLETE + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hci_event_connection_complete_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[5], bd_addr); + } + /** + * @brief Get field link_type from event HCI_EVENT_CONNECTION_COMPLETE + * @param event packet + * @return link_type + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_connection_complete_get_link_type(const uint8_t *event) + { + return event[11]; + } + /** + * @brief Get field encryption_enabled from event HCI_EVENT_CONNECTION_COMPLETE + * @param event packet + * @return encryption_enabled + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_connection_complete_get_encryption_enabled(const uint8_t *event) + { + return event[12]; + } + + /** + * @brief Get field bd_addr from event HCI_EVENT_CONNECTION_REQUEST + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hci_event_connection_request_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[2], bd_addr); + } + /** + * @brief Get field class_of_device from event HCI_EVENT_CONNECTION_REQUEST + * @param event packet + * @return class_of_device + * @note: btstack_type 3 + */ + static inline uint32_t hci_event_connection_request_get_class_of_device(const uint8_t *event) + { + return little_endian_read_24(event, 8); + } + /** + * @brief Get field link_type from event HCI_EVENT_CONNECTION_REQUEST + * @param event packet + * @return link_type + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_connection_request_get_link_type(const uint8_t *event) + { + return event[11]; + } + + /** + * @brief Get field status from event HCI_EVENT_DISCONNECTION_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_disconnection_complete_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field connection_handle from event HCI_EVENT_DISCONNECTION_COMPLETE + * @param event packet + * @return connection_handle + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_disconnection_complete_get_connection_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field reason from event HCI_EVENT_DISCONNECTION_COMPLETE + * @param event packet + * @return reason + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_disconnection_complete_get_reason(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field status from event HCI_EVENT_AUTHENTICATION_COMPLETE_EVENT + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_authentication_complete_event_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field connection_handle from event HCI_EVENT_AUTHENTICATION_COMPLETE_EVENT + * @param event packet + * @return connection_handle + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_authentication_complete_event_get_connection_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field status from event HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_remote_name_request_complete_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field bd_addr from event HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hci_event_remote_name_request_complete_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[3], bd_addr); + } + /** + * @brief Get field remote_name from event HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE + * @param event packet + * @return remote_name + * @note: btstack_type N + */ + static inline const char *hci_event_remote_name_request_complete_get_remote_name(const uint8_t *event) + { + return (const char *) &event[9]; + } + + /** + * @brief Get field status from event HCI_EVENT_ENCRYPTION_CHANGE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_encryption_change_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field connection_handle from event HCI_EVENT_ENCRYPTION_CHANGE + * @param event packet + * @return connection_handle + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_encryption_change_get_connection_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field encryption_enabled from event HCI_EVENT_ENCRYPTION_CHANGE + * @param event packet + * @return encryption_enabled + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_encryption_change_get_encryption_enabled(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field status from event HCI_EVENT_CHANGE_CONNECTION_LINK_KEY_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_change_connection_link_key_complete_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field connection_handle from event HCI_EVENT_CHANGE_CONNECTION_LINK_KEY_COMPLETE + * @param event packet + * @return connection_handle + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_change_connection_link_key_complete_get_connection_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field status from event HCI_EVENT_MASTER_LINK_KEY_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_master_link_key_complete_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field connection_handle from event HCI_EVENT_MASTER_LINK_KEY_COMPLETE + * @param event packet + * @return connection_handle + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_master_link_key_complete_get_connection_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field key_flag from event HCI_EVENT_MASTER_LINK_KEY_COMPLETE + * @param event packet + * @return key_flag + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_master_link_key_complete_get_key_flag(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field num_hci_command_packets from event HCI_EVENT_COMMAND_COMPLETE + * @param event packet + * @return num_hci_command_packets + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_command_complete_get_num_hci_command_packets(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field command_opcode from event HCI_EVENT_COMMAND_COMPLETE + * @param event packet + * @return command_opcode + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_command_complete_get_command_opcode(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field return_parameters from event HCI_EVENT_COMMAND_COMPLETE + * @param event packet + * @return return_parameters + * @note: btstack_type R + */ + static inline const uint8_t *hci_event_command_complete_get_return_parameters(const uint8_t *event) + { + return &event[5]; + } + + /** + * @brief Get field status from event HCI_EVENT_COMMAND_STATUS + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_command_status_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field num_hci_command_packets from event HCI_EVENT_COMMAND_STATUS + * @param event packet + * @return num_hci_command_packets + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_command_status_get_num_hci_command_packets(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field command_opcode from event HCI_EVENT_COMMAND_STATUS + * @param event packet + * @return command_opcode + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_command_status_get_command_opcode(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + + /** + * @brief Get field hardware_code from event HCI_EVENT_HARDWARE_ERROR + * @param event packet + * @return hardware_code + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_hardware_error_get_hardware_code(const uint8_t *event) + { + return event[2]; + } + + /** + * @brief Get field status from event HCI_EVENT_ROLE_CHANGE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_role_change_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field bd_addr from event HCI_EVENT_ROLE_CHANGE + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hci_event_role_change_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[3], bd_addr); + } + /** + * @brief Get field role from event HCI_EVENT_ROLE_CHANGE + * @param event packet + * @return role + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_role_change_get_role(const uint8_t *event) + { + return event[9]; + } + + /** + * @brief Get field status from event HCI_EVENT_MODE_CHANGE_EVENT + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_mode_change_event_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field handle from event HCI_EVENT_MODE_CHANGE_EVENT + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hci_event_mode_change_event_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field mode from event HCI_EVENT_MODE_CHANGE_EVENT + * @param event packet + * @return mode + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_mode_change_event_get_mode(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field interval from event HCI_EVENT_MODE_CHANGE_EVENT + * @param event packet + * @return interval + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_mode_change_event_get_interval(const uint8_t *event) + { + return little_endian_read_16(event, 6); + } + + /** + * @brief Get field bd_addr from event HCI_EVENT_PIN_CODE_REQUEST + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hci_event_pin_code_request_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[2], bd_addr); + } + + /** + * @brief Get field bd_addr from event HCI_EVENT_LINK_KEY_REQUEST + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hci_event_link_key_request_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[2], bd_addr); + } + + /** + * @brief Get field link_type from event HCI_EVENT_DATA_BUFFER_OVERFLOW + * @param event packet + * @return link_type + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_data_buffer_overflow_get_link_type(const uint8_t *event) + { + return event[2]; + } + + /** + * @brief Get field handle from event HCI_EVENT_MAX_SLOTS_CHANGED + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hci_event_max_slots_changed_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field lmp_max_slots from event HCI_EVENT_MAX_SLOTS_CHANGED + * @param event packet + * @return lmp_max_slots + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_max_slots_changed_get_lmp_max_slots(const uint8_t *event) + { + return event[4]; + } + + /** + * @brief Get field status from event HCI_EVENT_READ_CLOCK_OFFSET_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_read_clock_offset_complete_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field handle from event HCI_EVENT_READ_CLOCK_OFFSET_COMPLETE + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hci_event_read_clock_offset_complete_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field clock_offset from event HCI_EVENT_READ_CLOCK_OFFSET_COMPLETE + * @param event packet + * @return clock_offset + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_read_clock_offset_complete_get_clock_offset(const uint8_t *event) + { + return little_endian_read_16(event, 5); + } + + /** + * @brief Get field status from event HCI_EVENT_CONNECTION_PACKET_TYPE_CHANGED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_connection_packet_type_changed_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field handle from event HCI_EVENT_CONNECTION_PACKET_TYPE_CHANGED + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hci_event_connection_packet_type_changed_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field packet_types from event HCI_EVENT_CONNECTION_PACKET_TYPE_CHANGED + * @param event packet + * @return packet_types + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_connection_packet_type_changed_get_packet_types(const uint8_t *event) + { + return little_endian_read_16(event, 5); + } + + /** + * @brief Get field num_responses from event HCI_EVENT_INQUIRY_RESULT_WITH_RSSI + * @param event packet + * @return num_responses + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_inquiry_result_with_rssi_get_num_responses(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field bd_addr from event HCI_EVENT_INQUIRY_RESULT_WITH_RSSI + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hci_event_inquiry_result_with_rssi_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[3], bd_addr); + } + /** + * @brief Get field page_scan_repetition_mode from event HCI_EVENT_INQUIRY_RESULT_WITH_RSSI + * @param event packet + * @return page_scan_repetition_mode + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_inquiry_result_with_rssi_get_page_scan_repetition_mode(const uint8_t *event) + { + return event[9]; + } + /** + * @brief Get field reserved from event HCI_EVENT_INQUIRY_RESULT_WITH_RSSI + * @param event packet + * @return reserved + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_inquiry_result_with_rssi_get_reserved(const uint8_t *event) + { + return event[10]; + } + /** + * @brief Get field class_of_device from event HCI_EVENT_INQUIRY_RESULT_WITH_RSSI + * @param event packet + * @return class_of_device + * @note: btstack_type 3 + */ + static inline uint32_t hci_event_inquiry_result_with_rssi_get_class_of_device(const uint8_t *event) + { + return little_endian_read_24(event, 11); + } + /** + * @brief Get field clock_offset from event HCI_EVENT_INQUIRY_RESULT_WITH_RSSI + * @param event packet + * @return clock_offset + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_inquiry_result_with_rssi_get_clock_offset(const uint8_t *event) + { + return little_endian_read_16(event, 14); + } + /** + * @brief Get field rssi from event HCI_EVENT_INQUIRY_RESULT_WITH_RSSI + * @param event packet + * @return rssi + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_inquiry_result_with_rssi_get_rssi(const uint8_t *event) + { + return event[16]; + } + + /** + * @brief Get field status from event HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_synchronous_connection_complete_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field handle from event HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hci_event_synchronous_connection_complete_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field bd_addr from event HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hci_event_synchronous_connection_complete_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[5], bd_addr); + } + /** + * @brief Get field link_type from event HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE + * @param event packet + * @return link_type + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_synchronous_connection_complete_get_link_type(const uint8_t *event) + { + return event[11]; + } + /** + * @brief Get field transmission_interval from event HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE + * @param event packet + * @return transmission_interval + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_synchronous_connection_complete_get_transmission_interval(const uint8_t *event) + { + return event[12]; + } + /** + * @brief Get field retransmission_interval from event HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE + * @param event packet + * @return retransmission_interval + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_synchronous_connection_complete_get_retransmission_interval(const uint8_t *event) + { + return event[13]; + } + /** + * @brief Get field rx_packet_length from event HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE + * @param event packet + * @return rx_packet_length + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_synchronous_connection_complete_get_rx_packet_length(const uint8_t *event) + { + return little_endian_read_16(event, 14); + } + /** + * @brief Get field tx_packet_length from event HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE + * @param event packet + * @return tx_packet_length + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_synchronous_connection_complete_get_tx_packet_length(const uint8_t *event) + { + return little_endian_read_16(event, 16); + } + /** + * @brief Get field air_mode from event HCI_EVENT_SYNCHRONOUS_CONNECTION_COMPLETE + * @param event packet + * @return air_mode + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_synchronous_connection_complete_get_air_mode(const uint8_t *event) + { + return event[18]; + } + + /** + * @brief Get field num_responses from event HCI_EVENT_EXTENDED_INQUIRY_RESPONSE + * @param event packet + * @return num_responses + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_extended_inquiry_response_get_num_responses(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field bd_addr from event HCI_EVENT_EXTENDED_INQUIRY_RESPONSE + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hci_event_extended_inquiry_response_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[3], bd_addr); + } + /** + * @brief Get field page_scan_repetition_mode from event HCI_EVENT_EXTENDED_INQUIRY_RESPONSE + * @param event packet + * @return page_scan_repetition_mode + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_extended_inquiry_response_get_page_scan_repetition_mode(const uint8_t *event) + { + return event[9]; + } + /** + * @brief Get field reserved from event HCI_EVENT_EXTENDED_INQUIRY_RESPONSE + * @param event packet + * @return reserved + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_extended_inquiry_response_get_reserved(const uint8_t *event) + { + return event[10]; + } + /** + * @brief Get field class_of_device from event HCI_EVENT_EXTENDED_INQUIRY_RESPONSE + * @param event packet + * @return class_of_device + * @note: btstack_type 3 + */ + static inline uint32_t hci_event_extended_inquiry_response_get_class_of_device(const uint8_t *event) + { + return little_endian_read_24(event, 11); + } + /** + * @brief Get field clock_offset from event HCI_EVENT_EXTENDED_INQUIRY_RESPONSE + * @param event packet + * @return clock_offset + * @note: btstack_type 2 + */ + static inline uint16_t hci_event_extended_inquiry_response_get_clock_offset(const uint8_t *event) + { + return little_endian_read_16(event, 14); + } + /** + * @brief Get field rssi from event HCI_EVENT_EXTENDED_INQUIRY_RESPONSE + * @param event packet + * @return rssi + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_extended_inquiry_response_get_rssi(const uint8_t *event) + { + return event[16]; + } + + /** + * @brief Get field status from event HCI_EVENT_ENCRYPTION_KEY_REFRESH_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_encryption_key_refresh_complete_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field handle from event HCI_EVENT_ENCRYPTION_KEY_REFRESH_COMPLETE + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hci_event_encryption_key_refresh_complete_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field bd_addr from event HCI_EVENT_USER_CONFIRMATION_REQUEST + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hci_event_user_confirmation_request_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[2], bd_addr); + } + /** + * @brief Get field numeric_value from event HCI_EVENT_USER_CONFIRMATION_REQUEST + * @param event packet + * @return numeric_value + * @note: btstack_type 4 + */ + static inline uint32_t hci_event_user_confirmation_request_get_numeric_value(const uint8_t *event) + { + return little_endian_read_32(event, 8); + } + + /** + * @brief Get field bd_addr from event HCI_EVENT_USER_PASSKEY_REQUEST + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hci_event_user_passkey_request_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[2], bd_addr); + } + + /** + * @brief Get field bd_addr from event HCI_EVENT_REMOTE_OOB_DATA_REQUEST + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hci_event_remote_oob_data_request_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[2], bd_addr); + } + + /** + * @brief Get field status from event HCI_EVENT_SIMPLE_PAIRING_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_simple_pairing_complete_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field bd_addr from event HCI_EVENT_SIMPLE_PAIRING_COMPLETE + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hci_event_simple_pairing_complete_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[3], bd_addr); + } + + /** + * @brief Get field state from event BTSTACK_EVENT_STATE + * @param event packet + * @return state + * @note: btstack_type 1 + */ + static inline uint8_t btstack_event_state_get_state(const uint8_t *event) + { + return event[2]; + } + + /** + * @brief Get field number_connections from event BTSTACK_EVENT_NR_CONNECTIONS_CHANGED + * @param event packet + * @return number_connections + * @note: btstack_type 1 + */ + static inline uint8_t btstack_event_nr_connections_changed_get_number_connections(const uint8_t *event) + { + return event[2]; + } + + + /** + * @brief Get field discoverable from event BTSTACK_EVENT_DISCOVERABLE_ENABLED + * @param event packet + * @return discoverable + * @note: btstack_type 1 + */ + static inline uint8_t btstack_event_discoverable_enabled_get_discoverable(const uint8_t *event) + { + return event[2]; + } + + /** + * @brief Get field active from event HCI_EVENT_TRANSPORT_SLEEP_MODE + * @param event packet + * @return active + * @note: btstack_type 1 + */ + static inline uint8_t hci_event_transport_sleep_mode_get_active(const uint8_t *event) + { + return event[2]; + } + + /** + * @brief Get field handle from event HCI_EVENT_SCO_CAN_SEND_NOW + * @param event packet + * @param Pointer to storage for handle + * @note: btstack_type B + */ + static inline void hci_event_sco_can_send_now_get_handle(const uint8_t *event, bd_addr_t handle) + { + reverse_bd_addr(&event[2], handle); + } + + /** + * @brief Get field status from event L2CAP_EVENT_CHANNEL_OPENED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t l2cap_event_channel_opened_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field address from event L2CAP_EVENT_CHANNEL_OPENED + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void l2cap_event_channel_opened_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[3], address); + } + /** + * @brief Get field handle from event L2CAP_EVENT_CHANNEL_OPENED + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t l2cap_event_channel_opened_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 9); + } + /** + * @brief Get field psm from event L2CAP_EVENT_CHANNEL_OPENED + * @param event packet + * @return psm + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_channel_opened_get_psm(const uint8_t *event) + { + return little_endian_read_16(event, 11); + } + /** + * @brief Get field local_cid from event L2CAP_EVENT_CHANNEL_OPENED + * @param event packet + * @return local_cid + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_channel_opened_get_local_cid(const uint8_t *event) + { + return little_endian_read_16(event, 13); + } + /** + * @brief Get field remote_cid from event L2CAP_EVENT_CHANNEL_OPENED + * @param event packet + * @return remote_cid + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_channel_opened_get_remote_cid(const uint8_t *event) + { + return little_endian_read_16(event, 15); + } + /** + * @brief Get field local_mtu from event L2CAP_EVENT_CHANNEL_OPENED + * @param event packet + * @return local_mtu + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_channel_opened_get_local_mtu(const uint8_t *event) + { + return little_endian_read_16(event, 17); + } + /** + * @brief Get field remote_mtu from event L2CAP_EVENT_CHANNEL_OPENED + * @param event packet + * @return remote_mtu + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_channel_opened_get_remote_mtu(const uint8_t *event) + { + return little_endian_read_16(event, 19); + } + /** + * @brief Get field flush_timeout from event L2CAP_EVENT_CHANNEL_OPENED + * @param event packet + * @return flush_timeout + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_channel_opened_get_flush_timeout(const uint8_t *event) + { + return little_endian_read_16(event, 21); + } + /** + * @brief Get field incoming from event L2CAP_EVENT_CHANNEL_OPENED + * @param event packet + * @return incoming + * @note: btstack_type 1 + */ + static inline uint8_t l2cap_event_channel_opened_get_incoming(const uint8_t *event) + { + return event[23]; + } + + /** + * @brief Get field local_cid from event L2CAP_EVENT_CHANNEL_CLOSED + * @param event packet + * @return local_cid + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_channel_closed_get_local_cid(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + + /** + * @brief Get field address from event L2CAP_EVENT_INCOMING_CONNECTION + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void l2cap_event_incoming_connection_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[2], address); + } + /** + * @brief Get field handle from event L2CAP_EVENT_INCOMING_CONNECTION + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t l2cap_event_incoming_connection_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 8); + } + /** + * @brief Get field psm from event L2CAP_EVENT_INCOMING_CONNECTION + * @param event packet + * @return psm + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_incoming_connection_get_psm(const uint8_t *event) + { + return little_endian_read_16(event, 10); + } + /** + * @brief Get field local_cid from event L2CAP_EVENT_INCOMING_CONNECTION + * @param event packet + * @return local_cid + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_incoming_connection_get_local_cid(const uint8_t *event) + { + return little_endian_read_16(event, 12); + } + /** + * @brief Get field remote_cid from event L2CAP_EVENT_INCOMING_CONNECTION + * @param event packet + * @return remote_cid + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_incoming_connection_get_remote_cid(const uint8_t *event) + { + return little_endian_read_16(event, 14); + } + + /** + * @brief Get field handle from event L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_REQUEST + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t l2cap_event_connection_parameter_update_request_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field interval_min from event L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_REQUEST + * @param event packet + * @return interval_min + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_connection_parameter_update_request_get_interval_min(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field interval_max from event L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_REQUEST + * @param event packet + * @return interval_max + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_connection_parameter_update_request_get_interval_max(const uint8_t *event) + { + return little_endian_read_16(event, 6); + } + /** + * @brief Get field latencey from event L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_REQUEST + * @param event packet + * @return latencey + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_connection_parameter_update_request_get_latencey(const uint8_t *event) + { + return little_endian_read_16(event, 8); + } + /** + * @brief Get field timeout_multiplier from event L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_REQUEST + * @param event packet + * @return timeout_multiplier + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_connection_parameter_update_request_get_timeout_multiplier(const uint8_t *event) + { + return little_endian_read_16(event, 10); + } + + /** + * @brief Get field handle from event L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t l2cap_event_connection_parameter_update_response_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field result from event L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE + * @param event packet + * @return result + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_connection_parameter_update_response_get_result(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + + /** + * @brief Get field local_cid from event L2CAP_EVENT_CAN_SEND_NOW + * @param event packet + * @return local_cid + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_can_send_now_get_local_cid(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + + /** + * @brief Get field address_type from event L2CAP_EVENT_LE_INCOMING_CONNECTION + * @param event packet + * @return address_type + * @note: btstack_type 1 + */ + static inline uint8_t l2cap_event_le_incoming_connection_get_address_type(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field address from event L2CAP_EVENT_LE_INCOMING_CONNECTION + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void l2cap_event_le_incoming_connection_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[3], address); + } + /** + * @brief Get field handle from event L2CAP_EVENT_LE_INCOMING_CONNECTION + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t l2cap_event_le_incoming_connection_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 9); + } + /** + * @brief Get field psm from event L2CAP_EVENT_LE_INCOMING_CONNECTION + * @param event packet + * @return psm + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_le_incoming_connection_get_psm(const uint8_t *event) + { + return little_endian_read_16(event, 11); + } + /** + * @brief Get field local_cid from event L2CAP_EVENT_LE_INCOMING_CONNECTION + * @param event packet + * @return local_cid + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_le_incoming_connection_get_local_cid(const uint8_t *event) + { + return little_endian_read_16(event, 13); + } + /** + * @brief Get field remote_cid from event L2CAP_EVENT_LE_INCOMING_CONNECTION + * @param event packet + * @return remote_cid + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_le_incoming_connection_get_remote_cid(const uint8_t *event) + { + return little_endian_read_16(event, 15); + } + /** + * @brief Get field remote_mtu from event L2CAP_EVENT_LE_INCOMING_CONNECTION + * @param event packet + * @return remote_mtu + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_le_incoming_connection_get_remote_mtu(const uint8_t *event) + { + return little_endian_read_16(event, 17); + } + + /** + * @brief Get field status from event L2CAP_EVENT_LE_CHANNEL_OPENED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t l2cap_event_le_channel_opened_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field address_type from event L2CAP_EVENT_LE_CHANNEL_OPENED + * @param event packet + * @return address_type + * @note: btstack_type 1 + */ + static inline uint8_t l2cap_event_le_channel_opened_get_address_type(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field address from event L2CAP_EVENT_LE_CHANNEL_OPENED + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void l2cap_event_le_channel_opened_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[4], address); + } + /** + * @brief Get field handle from event L2CAP_EVENT_LE_CHANNEL_OPENED + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t l2cap_event_le_channel_opened_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 10); + } + /** + * @brief Get field incoming from event L2CAP_EVENT_LE_CHANNEL_OPENED + * @param event packet + * @return incoming + * @note: btstack_type 1 + */ + static inline uint8_t l2cap_event_le_channel_opened_get_incoming(const uint8_t *event) + { + return event[12]; + } + /** + * @brief Get field psm from event L2CAP_EVENT_LE_CHANNEL_OPENED + * @param event packet + * @return psm + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_le_channel_opened_get_psm(const uint8_t *event) + { + return little_endian_read_16(event, 13); + } + /** + * @brief Get field local_cid from event L2CAP_EVENT_LE_CHANNEL_OPENED + * @param event packet + * @return local_cid + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_le_channel_opened_get_local_cid(const uint8_t *event) + { + return little_endian_read_16(event, 15); + } + /** + * @brief Get field remote_cid from event L2CAP_EVENT_LE_CHANNEL_OPENED + * @param event packet + * @return remote_cid + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_le_channel_opened_get_remote_cid(const uint8_t *event) + { + return little_endian_read_16(event, 17); + } + /** + * @brief Get field local_mtu from event L2CAP_EVENT_LE_CHANNEL_OPENED + * @param event packet + * @return local_mtu + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_le_channel_opened_get_local_mtu(const uint8_t *event) + { + return little_endian_read_16(event, 19); + } + /** + * @brief Get field remote_mtu from event L2CAP_EVENT_LE_CHANNEL_OPENED + * @param event packet + * @return remote_mtu + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_le_channel_opened_get_remote_mtu(const uint8_t *event) + { + return little_endian_read_16(event, 21); + } + + /** + * @brief Get field local_cid from event L2CAP_EVENT_LE_CHANNEL_CLOSED + * @param event packet + * @return local_cid + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_le_channel_closed_get_local_cid(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + + /** + * @brief Get field local_cid from event L2CAP_EVENT_LE_CAN_SEND_NOW + * @param event packet + * @return local_cid + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_le_can_send_now_get_local_cid(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + + /** + * @brief Get field local_cid from event L2CAP_EVENT_LE_PACKET_SENT + * @param event packet + * @return local_cid + * @note: btstack_type 2 + */ + static inline uint16_t l2cap_event_le_packet_sent_get_local_cid(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + + /** + * @brief Get field status from event RFCOMM_EVENT_CHANNEL_OPENED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t rfcomm_event_channel_opened_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field bd_addr from event RFCOMM_EVENT_CHANNEL_OPENED + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void rfcomm_event_channel_opened_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[3], bd_addr); + } + /** + * @brief Get field con_handle from event RFCOMM_EVENT_CHANNEL_OPENED + * @param event packet + * @return con_handle + * @note: btstack_type 2 + */ + static inline uint16_t rfcomm_event_channel_opened_get_con_handle(const uint8_t *event) + { + return little_endian_read_16(event, 9); + } + /** + * @brief Get field server_channel from event RFCOMM_EVENT_CHANNEL_OPENED + * @param event packet + * @return server_channel + * @note: btstack_type 1 + */ + static inline uint8_t rfcomm_event_channel_opened_get_server_channel(const uint8_t *event) + { + return event[11]; + } + /** + * @brief Get field rfcomm_cid from event RFCOMM_EVENT_CHANNEL_OPENED + * @param event packet + * @return rfcomm_cid + * @note: btstack_type 2 + */ + static inline uint16_t rfcomm_event_channel_opened_get_rfcomm_cid(const uint8_t *event) + { + return little_endian_read_16(event, 12); + } + /** + * @brief Get field max_frame_size from event RFCOMM_EVENT_CHANNEL_OPENED + * @param event packet + * @return max_frame_size + * @note: btstack_type 2 + */ + static inline uint16_t rfcomm_event_channel_opened_get_max_frame_size(const uint8_t *event) + { + return little_endian_read_16(event, 14); + } + /** + * @brief Get field incoming from event RFCOMM_EVENT_CHANNEL_OPENED + * @param event packet + * @return incoming + * @note: btstack_type 1 + */ + static inline uint8_t rfcomm_event_channel_opened_get_incoming(const uint8_t *event) + { + return event[16]; + } + + /** + * @brief Get field rfcomm_cid from event RFCOMM_EVENT_CHANNEL_CLOSED + * @param event packet + * @return rfcomm_cid + * @note: btstack_type 2 + */ + static inline uint16_t rfcomm_event_channel_closed_get_rfcomm_cid(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + + /** + * @brief Get field bd_addr from event RFCOMM_EVENT_INCOMING_CONNECTION + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void rfcomm_event_incoming_connection_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[2], bd_addr); + } + /** + * @brief Get field server_channel from event RFCOMM_EVENT_INCOMING_CONNECTION + * @param event packet + * @return server_channel + * @note: btstack_type 1 + */ + static inline uint8_t rfcomm_event_incoming_connection_get_server_channel(const uint8_t *event) + { + return event[8]; + } + /** + * @brief Get field rfcomm_cid from event RFCOMM_EVENT_INCOMING_CONNECTION + * @param event packet + * @return rfcomm_cid + * @note: btstack_type 2 + */ + static inline uint16_t rfcomm_event_incoming_connection_get_rfcomm_cid(const uint8_t *event) + { + return little_endian_read_16(event, 9); + } + + /** + * @brief Get field rfcomm_cid from event RFCOMM_EVENT_REMOTE_LINE_STATUS + * @param event packet + * @return rfcomm_cid + * @note: btstack_type 2 + */ + static inline uint16_t rfcomm_event_remote_line_status_get_rfcomm_cid(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field line_status from event RFCOMM_EVENT_REMOTE_LINE_STATUS + * @param event packet + * @return line_status + * @note: btstack_type 1 + */ + static inline uint8_t rfcomm_event_remote_line_status_get_line_status(const uint8_t *event) + { + return event[4]; + } + + /** + * @brief Get field rfcomm_cid from event RFCOMM_EVENT_REMOTE_MODEM_STATUS + * @param event packet + * @return rfcomm_cid + * @note: btstack_type 2 + */ + static inline uint16_t rfcomm_event_remote_modem_status_get_rfcomm_cid(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field modem_status from event RFCOMM_EVENT_REMOTE_MODEM_STATUS + * @param event packet + * @return modem_status + * @note: btstack_type 1 + */ + static inline uint8_t rfcomm_event_remote_modem_status_get_modem_status(const uint8_t *event) + { + return event[4]; + } + + /** + * @brief Get field rfcomm_cid from event RFCOMM_EVENT_CAN_SEND_NOW + * @param event packet + * @return rfcomm_cid + * @note: btstack_type 2 + */ + static inline uint16_t rfcomm_event_can_send_now_get_rfcomm_cid(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + + /** + * @brief Get field status from event SDP_EVENT_QUERY_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t sdp_event_query_complete_get_status(const uint8_t *event) + { + return event[2]; + } + + /** + * @brief Get field rfcomm_channel from event SDP_EVENT_QUERY_RFCOMM_SERVICE + * @param event packet + * @return rfcomm_channel + * @note: btstack_type 1 + */ + static inline uint8_t sdp_event_query_rfcomm_service_get_rfcomm_channel(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field name from event SDP_EVENT_QUERY_RFCOMM_SERVICE + * @param event packet + * @return name + * @note: btstack_type T + */ + static inline const char *sdp_event_query_rfcomm_service_get_name(const uint8_t *event) + { + return (const char *) &event[3]; + } + + /** + * @brief Get field record_id from event SDP_EVENT_QUERY_ATTRIBUTE_BYTE + * @param event packet + * @return record_id + * @note: btstack_type 2 + */ + static inline uint16_t sdp_event_query_attribute_byte_get_record_id(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field attribute_id from event SDP_EVENT_QUERY_ATTRIBUTE_BYTE + * @param event packet + * @return attribute_id + * @note: btstack_type 2 + */ + static inline uint16_t sdp_event_query_attribute_byte_get_attribute_id(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field attribute_length from event SDP_EVENT_QUERY_ATTRIBUTE_BYTE + * @param event packet + * @return attribute_length + * @note: btstack_type 2 + */ + static inline uint16_t sdp_event_query_attribute_byte_get_attribute_length(const uint8_t *event) + { + return little_endian_read_16(event, 6); + } + /** + * @brief Get field data_offset from event SDP_EVENT_QUERY_ATTRIBUTE_BYTE + * @param event packet + * @return data_offset + * @note: btstack_type 2 + */ + static inline uint16_t sdp_event_query_attribute_byte_get_data_offset(const uint8_t *event) + { + return little_endian_read_16(event, 8); + } + /** + * @brief Get field data from event SDP_EVENT_QUERY_ATTRIBUTE_BYTE + * @param event packet + * @return data + * @note: btstack_type 1 + */ + static inline uint8_t sdp_event_query_attribute_byte_get_data(const uint8_t *event) + { + return event[10]; + } + + /** + * @brief Get field record_id from event SDP_EVENT_QUERY_ATTRIBUTE_VALUE + * @param event packet + * @return record_id + * @note: btstack_type 2 + */ + static inline uint16_t sdp_event_query_attribute_value_get_record_id(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field attribute_id from event SDP_EVENT_QUERY_ATTRIBUTE_VALUE + * @param event packet + * @return attribute_id + * @note: btstack_type 2 + */ + static inline uint16_t sdp_event_query_attribute_value_get_attribute_id(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field attribute_length from event SDP_EVENT_QUERY_ATTRIBUTE_VALUE + * @param event packet + * @return attribute_length + * @note: btstack_type L + */ + static inline int sdp_event_query_attribute_value_get_attribute_length(const uint8_t *event) + { + return little_endian_read_16(event, 6); + } + /** + * @brief Get field attribute_value from event SDP_EVENT_QUERY_ATTRIBUTE_VALUE + * @param event packet + * @return attribute_value + * @note: btstack_type V + */ + static inline const uint8_t *sdp_event_query_attribute_value_get_attribute_value(const uint8_t *event) + { + return &event[8]; + } + + /** + * @brief Get field total_count from event SDP_EVENT_QUERY_SERVICE_RECORD_HANDLE + * @param event packet + * @return total_count + * @note: btstack_type 2 + */ + static inline uint16_t sdp_event_query_service_record_handle_get_total_count(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field record_index from event SDP_EVENT_QUERY_SERVICE_RECORD_HANDLE + * @param event packet + * @return record_index + * @note: btstack_type 2 + */ + static inline uint16_t sdp_event_query_service_record_handle_get_record_index(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field record_handle from event SDP_EVENT_QUERY_SERVICE_RECORD_HANDLE + * @param event packet + * @return record_handle + * @note: btstack_type 4 + */ + static inline uint32_t sdp_event_query_service_record_handle_get_record_handle(const uint8_t *event) + { + return little_endian_read_32(event, 6); + } + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event GATT_EVENT_QUERY_COMPLETE + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t gatt_event_query_complete_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field status from event GATT_EVENT_QUERY_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t gatt_event_query_complete_get_status(const uint8_t *event) + { + return event[4]; + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event GATT_EVENT_SERVICE_QUERY_RESULT + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t gatt_event_service_query_result_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field service from event GATT_EVENT_SERVICE_QUERY_RESULT + * @param event packet + * @param Pointer to storage for service + * @note: btstack_type X + */ + static inline void gatt_event_service_query_result_get_service(const uint8_t *event, gatt_client_service_t *service) + { + gatt_client_deserialize_service(event, 4, service); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event GATT_EVENT_CHARACTERISTIC_QUERY_RESULT + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t gatt_event_characteristic_query_result_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field characteristic from event GATT_EVENT_CHARACTERISTIC_QUERY_RESULT + * @param event packet + * @param Pointer to storage for characteristic + * @note: btstack_type Y + */ + static inline void gatt_event_characteristic_query_result_get_characteristic(const uint8_t *event, gatt_client_characteristic_t *characteristic) + { + gatt_client_deserialize_characteristic(event, 4, characteristic); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event GATT_EVENT_INCLUDED_SERVICE_QUERY_RESULT + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t gatt_event_included_service_query_result_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field include_handle from event GATT_EVENT_INCLUDED_SERVICE_QUERY_RESULT + * @param event packet + * @return include_handle + * @note: btstack_type 2 + */ + static inline uint16_t gatt_event_included_service_query_result_get_include_handle(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field service from event GATT_EVENT_INCLUDED_SERVICE_QUERY_RESULT + * @param event packet + * @param Pointer to storage for service + * @note: btstack_type X + */ + static inline void gatt_event_included_service_query_result_get_service(const uint8_t *event, gatt_client_service_t *service) + { + gatt_client_deserialize_service(event, 6, service); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t gatt_event_all_characteristic_descriptors_query_result_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field characteristic_descriptor from event GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT + * @param event packet + * @param Pointer to storage for characteristic_descriptor + * @note: btstack_type Z + */ + static inline void gatt_event_all_characteristic_descriptors_query_result_get_characteristic_descriptor(const uint8_t *event, gatt_client_characteristic_descriptor_t *characteristic_descriptor) + { + gatt_client_deserialize_characteristic_descriptor(event, 4, characteristic_descriptor); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t gatt_event_characteristic_value_query_result_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field value_handle from event GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT + * @param event packet + * @return value_handle + * @note: btstack_type 2 + */ + static inline uint16_t gatt_event_characteristic_value_query_result_get_value_handle(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field value_length from event GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT + * @param event packet + * @return value_length + * @note: btstack_type L + */ + static inline int gatt_event_characteristic_value_query_result_get_value_length(const uint8_t *event) + { + return little_endian_read_16(event, 6); + } + /** + * @brief Get field value from event GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT + * @param event packet + * @return value + * @note: btstack_type V + */ + static inline const uint8_t *gatt_event_characteristic_value_query_result_get_value(const uint8_t *event) + { + return &event[8]; + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t gatt_event_long_characteristic_value_query_result_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field value_handle from event GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT + * @param event packet + * @return value_handle + * @note: btstack_type 2 + */ + static inline uint16_t gatt_event_long_characteristic_value_query_result_get_value_handle(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field value_offset from event GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT + * @param event packet + * @return value_offset + * @note: btstack_type 2 + */ + static inline uint16_t gatt_event_long_characteristic_value_query_result_get_value_offset(const uint8_t *event) + { + return little_endian_read_16(event, 6); + } + /** + * @brief Get field value_length from event GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT + * @param event packet + * @return value_length + * @note: btstack_type L + */ + static inline int gatt_event_long_characteristic_value_query_result_get_value_length(const uint8_t *event) + { + return little_endian_read_16(event, 8); + } + /** + * @brief Get field value from event GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT + * @param event packet + * @return value + * @note: btstack_type V + */ + static inline const uint8_t *gatt_event_long_characteristic_value_query_result_get_value(const uint8_t *event) + { + return &event[10]; + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event GATT_EVENT_NOTIFICATION + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t gatt_event_notification_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field value_handle from event GATT_EVENT_NOTIFICATION + * @param event packet + * @return value_handle + * @note: btstack_type 2 + */ + static inline uint16_t gatt_event_notification_get_value_handle(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field value_length from event GATT_EVENT_NOTIFICATION + * @param event packet + * @return value_length + * @note: btstack_type L + */ + static inline int gatt_event_notification_get_value_length(const uint8_t *event) + { + return little_endian_read_16(event, 6); + } + /** + * @brief Get field value from event GATT_EVENT_NOTIFICATION + * @param event packet + * @return value + * @note: btstack_type V + */ + static inline const uint8_t *gatt_event_notification_get_value(const uint8_t *event) + { + return &event[8]; + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event GATT_EVENT_INDICATION + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t gatt_event_indication_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field value_handle from event GATT_EVENT_INDICATION + * @param event packet + * @return value_handle + * @note: btstack_type 2 + */ + static inline uint16_t gatt_event_indication_get_value_handle(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field value_length from event GATT_EVENT_INDICATION + * @param event packet + * @return value_length + * @note: btstack_type L + */ + static inline int gatt_event_indication_get_value_length(const uint8_t *event) + { + return little_endian_read_16(event, 6); + } + /** + * @brief Get field value from event GATT_EVENT_INDICATION + * @param event packet + * @return value + * @note: btstack_type V + */ + static inline const uint8_t *gatt_event_indication_get_value(const uint8_t *event) + { + return &event[8]; + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event GATT_EVENT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t gatt_event_characteristic_descriptor_query_result_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field descriptor_handle from event GATT_EVENT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT + * @param event packet + * @return descriptor_handle + * @note: btstack_type 2 + */ + static inline uint16_t gatt_event_characteristic_descriptor_query_result_get_descriptor_handle(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field descriptor_length from event GATT_EVENT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT + * @param event packet + * @return descriptor_length + * @note: btstack_type L + */ + static inline int gatt_event_characteristic_descriptor_query_result_get_descriptor_length(const uint8_t *event) + { + return little_endian_read_16(event, 6); + } + /** + * @brief Get field descriptor from event GATT_EVENT_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT + * @param event packet + * @return descriptor + * @note: btstack_type V + */ + static inline const uint8_t *gatt_event_characteristic_descriptor_query_result_get_descriptor(const uint8_t *event) + { + return &event[8]; + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event GATT_EVENT_LONG_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t gatt_event_long_characteristic_descriptor_query_result_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field descriptor_offset from event GATT_EVENT_LONG_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT + * @param event packet + * @return descriptor_offset + * @note: btstack_type 2 + */ + static inline uint16_t gatt_event_long_characteristic_descriptor_query_result_get_descriptor_offset(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field descriptor_length from event GATT_EVENT_LONG_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT + * @param event packet + * @return descriptor_length + * @note: btstack_type L + */ + static inline int gatt_event_long_characteristic_descriptor_query_result_get_descriptor_length(const uint8_t *event) + { + return little_endian_read_16(event, 6); + } + /** + * @brief Get field descriptor from event GATT_EVENT_LONG_CHARACTERISTIC_DESCRIPTOR_QUERY_RESULT + * @param event packet + * @return descriptor + * @note: btstack_type V + */ + static inline const uint8_t *gatt_event_long_characteristic_descriptor_query_result_get_descriptor(const uint8_t *event) + { + return &event[8]; + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event GATT_EVENT_MTU + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t gatt_event_mtu_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field MTU from event GATT_EVENT_MTU + * @param event packet + * @return MTU + * @note: btstack_type 2 + */ + static inline uint16_t gatt_event_mtu_get_MTU(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } +#endif + + /** + * @brief Get field handle from event ATT_EVENT_MTU_EXCHANGE_COMPLETE + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t att_event_mtu_exchange_complete_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field MTU from event ATT_EVENT_MTU_EXCHANGE_COMPLETE + * @param event packet + * @return MTU + * @note: btstack_type 2 + */ + static inline uint16_t att_event_mtu_exchange_complete_get_MTU(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + + /** + * @brief Get field status from event ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t att_event_handle_value_indication_complete_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field conn_handle from event ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE + * @param event packet + * @return conn_handle + * @note: btstack_type H + */ + static inline hci_con_handle_t att_event_handle_value_indication_complete_get_conn_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field attribute_handle from event ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE + * @param event packet + * @return attribute_handle + * @note: btstack_type 2 + */ + static inline uint16_t att_event_handle_value_indication_complete_get_attribute_handle(const uint8_t *event) + { + return little_endian_read_16(event, 5); + } + + + /** + * @brief Get field status from event BNEP_EVENT_SERVICE_REGISTERED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t bnep_event_service_registered_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field service_uuid from event BNEP_EVENT_SERVICE_REGISTERED + * @param event packet + * @return service_uuid + * @note: btstack_type 2 + */ + static inline uint16_t bnep_event_service_registered_get_service_uuid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field status from event BNEP_EVENT_CHANNEL_OPENED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t bnep_event_channel_opened_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field bnep_cid from event BNEP_EVENT_CHANNEL_OPENED + * @param event packet + * @return bnep_cid + * @note: btstack_type 2 + */ + static inline uint16_t bnep_event_channel_opened_get_bnep_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field source_uuid from event BNEP_EVENT_CHANNEL_OPENED + * @param event packet + * @return source_uuid + * @note: btstack_type 2 + */ + static inline uint16_t bnep_event_channel_opened_get_source_uuid(const uint8_t *event) + { + return little_endian_read_16(event, 5); + } + /** + * @brief Get field destination_uuid from event BNEP_EVENT_CHANNEL_OPENED + * @param event packet + * @return destination_uuid + * @note: btstack_type 2 + */ + static inline uint16_t bnep_event_channel_opened_get_destination_uuid(const uint8_t *event) + { + return little_endian_read_16(event, 7); + } + /** + * @brief Get field mtu from event BNEP_EVENT_CHANNEL_OPENED + * @param event packet + * @return mtu + * @note: btstack_type 2 + */ + static inline uint16_t bnep_event_channel_opened_get_mtu(const uint8_t *event) + { + return little_endian_read_16(event, 9); + } + /** + * @brief Get field remote_address from event BNEP_EVENT_CHANNEL_OPENED + * @param event packet + * @param Pointer to storage for remote_address + * @note: btstack_type B + */ + static inline void bnep_event_channel_opened_get_remote_address(const uint8_t *event, bd_addr_t remote_address) + { + reverse_bd_addr(&event[11], remote_address); + } + + /** + * @brief Get field bnep_cid from event BNEP_EVENT_CHANNEL_CLOSED + * @param event packet + * @return bnep_cid + * @note: btstack_type 2 + */ + static inline uint16_t bnep_event_channel_closed_get_bnep_cid(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field source_uuid from event BNEP_EVENT_CHANNEL_CLOSED + * @param event packet + * @return source_uuid + * @note: btstack_type 2 + */ + static inline uint16_t bnep_event_channel_closed_get_source_uuid(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field destination_uuid from event BNEP_EVENT_CHANNEL_CLOSED + * @param event packet + * @return destination_uuid + * @note: btstack_type 2 + */ + static inline uint16_t bnep_event_channel_closed_get_destination_uuid(const uint8_t *event) + { + return little_endian_read_16(event, 6); + } + /** + * @brief Get field remote_address from event BNEP_EVENT_CHANNEL_CLOSED + * @param event packet + * @param Pointer to storage for remote_address + * @note: btstack_type B + */ + static inline void bnep_event_channel_closed_get_remote_address(const uint8_t *event, bd_addr_t remote_address) + { + reverse_bd_addr(&event[8], remote_address); + } + + /** + * @brief Get field bnep_cid from event BNEP_EVENT_CHANNEL_TIMEOUT + * @param event packet + * @return bnep_cid + * @note: btstack_type 2 + */ + static inline uint16_t bnep_event_channel_timeout_get_bnep_cid(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field source_uuid from event BNEP_EVENT_CHANNEL_TIMEOUT + * @param event packet + * @return source_uuid + * @note: btstack_type 2 + */ + static inline uint16_t bnep_event_channel_timeout_get_source_uuid(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field destination_uuid from event BNEP_EVENT_CHANNEL_TIMEOUT + * @param event packet + * @return destination_uuid + * @note: btstack_type 2 + */ + static inline uint16_t bnep_event_channel_timeout_get_destination_uuid(const uint8_t *event) + { + return little_endian_read_16(event, 6); + } + /** + * @brief Get field remote_address from event BNEP_EVENT_CHANNEL_TIMEOUT + * @param event packet + * @param Pointer to storage for remote_address + * @note: btstack_type B + */ + static inline void bnep_event_channel_timeout_get_remote_address(const uint8_t *event, bd_addr_t remote_address) + { + reverse_bd_addr(&event[8], remote_address); + } + /** + * @brief Get field channel_state from event BNEP_EVENT_CHANNEL_TIMEOUT + * @param event packet + * @return channel_state + * @note: btstack_type 1 + */ + static inline uint8_t bnep_event_channel_timeout_get_channel_state(const uint8_t *event) + { + return event[14]; + } + + /** + * @brief Get field bnep_cid from event BNEP_EVENT_CAN_SEND_NOW + * @param event packet + * @return bnep_cid + * @note: btstack_type 2 + */ + static inline uint16_t bnep_event_can_send_now_get_bnep_cid(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field source_uuid from event BNEP_EVENT_CAN_SEND_NOW + * @param event packet + * @return source_uuid + * @note: btstack_type 2 + */ + static inline uint16_t bnep_event_can_send_now_get_source_uuid(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field destination_uuid from event BNEP_EVENT_CAN_SEND_NOW + * @param event packet + * @return destination_uuid + * @note: btstack_type 2 + */ + static inline uint16_t bnep_event_can_send_now_get_destination_uuid(const uint8_t *event) + { + return little_endian_read_16(event, 6); + } + /** + * @brief Get field remote_address from event BNEP_EVENT_CAN_SEND_NOW + * @param event packet + * @param Pointer to storage for remote_address + * @note: btstack_type B + */ + static inline void bnep_event_can_send_now_get_remote_address(const uint8_t *event, bd_addr_t remote_address) + { + reverse_bd_addr(&event[8], remote_address); + } + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event SM_EVENT_JUST_WORKS_REQUEST + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t sm_event_just_works_request_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field addr_type from event SM_EVENT_JUST_WORKS_REQUEST + * @param event packet + * @return addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_just_works_request_get_addr_type(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field address from event SM_EVENT_JUST_WORKS_REQUEST + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void sm_event_just_works_request_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[5], address); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event SM_EVENT_JUST_WORKS_CANCEL + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t sm_event_just_works_cancel_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field addr_type from event SM_EVENT_JUST_WORKS_CANCEL + * @param event packet + * @return addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_just_works_cancel_get_addr_type(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field address from event SM_EVENT_JUST_WORKS_CANCEL + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void sm_event_just_works_cancel_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[5], address); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event SM_EVENT_PASSKEY_DISPLAY_NUMBER + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t sm_event_passkey_display_number_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field addr_type from event SM_EVENT_PASSKEY_DISPLAY_NUMBER + * @param event packet + * @return addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_passkey_display_number_get_addr_type(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field address from event SM_EVENT_PASSKEY_DISPLAY_NUMBER + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void sm_event_passkey_display_number_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[5], address); + } + /** + * @brief Get field passkey from event SM_EVENT_PASSKEY_DISPLAY_NUMBER + * @param event packet + * @return passkey + * @note: btstack_type 4 + */ + static inline uint32_t sm_event_passkey_display_number_get_passkey(const uint8_t *event) + { + return little_endian_read_32(event, 11); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event SM_EVENT_PASSKEY_DISPLAY_CANCEL + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t sm_event_passkey_display_cancel_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field addr_type from event SM_EVENT_PASSKEY_DISPLAY_CANCEL + * @param event packet + * @return addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_passkey_display_cancel_get_addr_type(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field address from event SM_EVENT_PASSKEY_DISPLAY_CANCEL + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void sm_event_passkey_display_cancel_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[5], address); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event SM_EVENT_PASSKEY_INPUT_NUMBER + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t sm_event_passkey_input_number_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field addr_type from event SM_EVENT_PASSKEY_INPUT_NUMBER + * @param event packet + * @return addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_passkey_input_number_get_addr_type(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field address from event SM_EVENT_PASSKEY_INPUT_NUMBER + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void sm_event_passkey_input_number_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[5], address); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event SM_EVENT_PASSKEY_INPUT_CANCEL + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t sm_event_passkey_input_cancel_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field addr_type from event SM_EVENT_PASSKEY_INPUT_CANCEL + * @param event packet + * @return addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_passkey_input_cancel_get_addr_type(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field address from event SM_EVENT_PASSKEY_INPUT_CANCEL + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void sm_event_passkey_input_cancel_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[5], address); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event SM_EVENT_NUMERIC_COMPARISON_REQUEST + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t sm_event_numeric_comparison_request_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field addr_type from event SM_EVENT_NUMERIC_COMPARISON_REQUEST + * @param event packet + * @return addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_numeric_comparison_request_get_addr_type(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field address from event SM_EVENT_NUMERIC_COMPARISON_REQUEST + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void sm_event_numeric_comparison_request_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[5], address); + } + /** + * @brief Get field passkey from event SM_EVENT_NUMERIC_COMPARISON_REQUEST + * @param event packet + * @return passkey + * @note: btstack_type 4 + */ + static inline uint32_t sm_event_numeric_comparison_request_get_passkey(const uint8_t *event) + { + return little_endian_read_32(event, 11); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event SM_EVENT_NUMERIC_COMPARISON_CANCEL + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t sm_event_numeric_comparison_cancel_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field addr_type from event SM_EVENT_NUMERIC_COMPARISON_CANCEL + * @param event packet + * @return addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_numeric_comparison_cancel_get_addr_type(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field address from event SM_EVENT_NUMERIC_COMPARISON_CANCEL + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void sm_event_numeric_comparison_cancel_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[5], address); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event SM_EVENT_IDENTITY_RESOLVING_STARTED + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t sm_event_identity_resolving_started_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field addr_type from event SM_EVENT_IDENTITY_RESOLVING_STARTED + * @param event packet + * @return addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_identity_resolving_started_get_addr_type(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field address from event SM_EVENT_IDENTITY_RESOLVING_STARTED + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void sm_event_identity_resolving_started_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[5], address); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event SM_EVENT_IDENTITY_RESOLVING_FAILED + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t sm_event_identity_resolving_failed_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field addr_type from event SM_EVENT_IDENTITY_RESOLVING_FAILED + * @param event packet + * @return addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_identity_resolving_failed_get_addr_type(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field address from event SM_EVENT_IDENTITY_RESOLVING_FAILED + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void sm_event_identity_resolving_failed_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[5], address); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t sm_event_identity_resolving_succeeded_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field addr_type from event SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED + * @param event packet + * @return addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_identity_resolving_succeeded_get_addr_type(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field address from event SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void sm_event_identity_resolving_succeeded_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[5], address); + } + /** + * @brief Get field identity_addr_type from event SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED + * @param event packet + * @return identity_addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_identity_resolving_succeeded_get_identity_addr_type(const uint8_t *event) + { + return event[11]; + } + /** + * @brief Get field identity_address from event SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED + * @param event packet + * @param Pointer to storage for identity_address + * @note: btstack_type B + */ + static inline void sm_event_identity_resolving_succeeded_get_identity_address(const uint8_t *event, bd_addr_t identity_address) + { + reverse_bd_addr(&event[12], identity_address); + } + /** + * @brief Get field index_internal from event SM_EVENT_IDENTITY_RESOLVING_SUCCEEDED + * @param event packet + * @return index_internal + * @note: btstack_type 2 + */ + static inline uint16_t sm_event_identity_resolving_succeeded_get_index_internal(const uint8_t *event) + { + return little_endian_read_16(event, 18); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event SM_EVENT_AUTHORIZATION_REQUEST + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t sm_event_authorization_request_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field addr_type from event SM_EVENT_AUTHORIZATION_REQUEST + * @param event packet + * @return addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_authorization_request_get_addr_type(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field address from event SM_EVENT_AUTHORIZATION_REQUEST + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void sm_event_authorization_request_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[5], address); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event SM_EVENT_AUTHORIZATION_RESULT + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t sm_event_authorization_result_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field addr_type from event SM_EVENT_AUTHORIZATION_RESULT + * @param event packet + * @return addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_authorization_result_get_addr_type(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field address from event SM_EVENT_AUTHORIZATION_RESULT + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void sm_event_authorization_result_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[5], address); + } + /** + * @brief Get field authorization_result from event SM_EVENT_AUTHORIZATION_RESULT + * @param event packet + * @return authorization_result + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_authorization_result_get_authorization_result(const uint8_t *event) + { + return event[11]; + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event SM_EVENT_KEYPRESS_NOTIFICATION + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t sm_event_keypress_notification_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field action from event SM_EVENT_KEYPRESS_NOTIFICATION + * @param event packet + * @return action + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_keypress_notification_get_action(const uint8_t *event) + { + return event[4]; + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event SM_EVENT_IDENTITY_CREATED + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t sm_event_identity_created_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field addr_type from event SM_EVENT_IDENTITY_CREATED + * @param event packet + * @return addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_identity_created_get_addr_type(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field address from event SM_EVENT_IDENTITY_CREATED + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void sm_event_identity_created_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[5], address); + } + /** + * @brief Get field identity_addr_type from event SM_EVENT_IDENTITY_CREATED + * @param event packet + * @return identity_addr_type + * @note: btstack_type 1 + */ + static inline uint8_t sm_event_identity_created_get_identity_addr_type(const uint8_t *event) + { + return event[11]; + } + /** + * @brief Get field identity_address from event SM_EVENT_IDENTITY_CREATED + * @param event packet + * @param Pointer to storage for identity_address + * @note: btstack_type B + */ + static inline void sm_event_identity_created_get_identity_address(const uint8_t *event, bd_addr_t identity_address) + { + reverse_bd_addr(&event[12], identity_address); + } +#endif + + /** + * @brief Get field handle from event GAP_EVENT_SECURITY_LEVEL + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t gap_event_security_level_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 2); + } + /** + * @brief Get field security_level from event GAP_EVENT_SECURITY_LEVEL + * @param event packet + * @return security_level + * @note: btstack_type 1 + */ + static inline uint8_t gap_event_security_level_get_security_level(const uint8_t *event) + { + return event[4]; + } + + /** + * @brief Get field status from event GAP_EVENT_DEDICATED_BONDING_COMPLETED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t gap_event_dedicated_bonding_completed_get_status(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field address from event GAP_EVENT_DEDICATED_BONDING_COMPLETED + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void gap_event_dedicated_bonding_completed_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[3], address); + } + + /** + * @brief Get field advertising_event_type from event GAP_EVENT_ADVERTISING_REPORT + * @param event packet + * @return advertising_event_type + * @note: btstack_type 1 + */ + static inline uint8_t gap_event_advertising_report_get_advertising_event_type(const uint8_t *event) + { + return event[2]; + } + /** + * @brief Get field address_type from event GAP_EVENT_ADVERTISING_REPORT + * @param event packet + * @return address_type + * @note: btstack_type 1 + */ + static inline uint8_t gap_event_advertising_report_get_address_type(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field address from event GAP_EVENT_ADVERTISING_REPORT + * @param event packet + * @param Pointer to storage for address + * @note: btstack_type B + */ + static inline void gap_event_advertising_report_get_address(const uint8_t *event, bd_addr_t address) + { + reverse_bd_addr(&event[4], address); + } + /** + * @brief Get field rssi from event GAP_EVENT_ADVERTISING_REPORT + * @param event packet + * @return rssi + * @note: btstack_type 1 + */ + static inline uint8_t gap_event_advertising_report_get_rssi(const uint8_t *event) + { + return event[10]; + } + /** + * @brief Get field data_length from event GAP_EVENT_ADVERTISING_REPORT + * @param event packet + * @return data_length + * @note: btstack_type J + */ + static inline int gap_event_advertising_report_get_data_length(const uint8_t *event) + { + return event[11]; + } + /** + * @brief Get field data from event GAP_EVENT_ADVERTISING_REPORT + * @param event packet + * @return data + * @note: btstack_type V + */ + static inline const uint8_t *gap_event_advertising_report_get_data(const uint8_t *event) + { + return &event[12]; + } + + /** + * @brief Get field bd_addr from event GAP_EVENT_INQUIRY_RESULT + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void gap_event_inquiry_result_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[2], bd_addr); + } + /** + * @brief Get field page_scan_repetition_mode from event GAP_EVENT_INQUIRY_RESULT + * @param event packet + * @return page_scan_repetition_mode + * @note: btstack_type 1 + */ + static inline uint8_t gap_event_inquiry_result_get_page_scan_repetition_mode(const uint8_t *event) + { + return event[8]; + } + /** + * @brief Get field class_of_device from event GAP_EVENT_INQUIRY_RESULT + * @param event packet + * @return class_of_device + * @note: btstack_type 3 + */ + static inline uint32_t gap_event_inquiry_result_get_class_of_device(const uint8_t *event) + { + return little_endian_read_24(event, 9); + } + /** + * @brief Get field clock_offset from event GAP_EVENT_INQUIRY_RESULT + * @param event packet + * @return clock_offset + * @note: btstack_type 2 + */ + static inline uint16_t gap_event_inquiry_result_get_clock_offset(const uint8_t *event) + { + return little_endian_read_16(event, 12); + } + /** + * @brief Get field rssi_available from event GAP_EVENT_INQUIRY_RESULT + * @param event packet + * @return rssi_available + * @note: btstack_type 1 + */ + static inline uint8_t gap_event_inquiry_result_get_rssi_available(const uint8_t *event) + { + return event[14]; + } + /** + * @brief Get field rssi from event GAP_EVENT_INQUIRY_RESULT + * @param event packet + * @return rssi + * @note: btstack_type 1 + */ + static inline uint8_t gap_event_inquiry_result_get_rssi(const uint8_t *event) + { + return event[15]; + } + /** + * @brief Get field name_available from event GAP_EVENT_INQUIRY_RESULT + * @param event packet + * @return name_available + * @note: btstack_type 1 + */ + static inline uint8_t gap_event_inquiry_result_get_name_available(const uint8_t *event) + { + return event[16]; + } + /** + * @brief Get field name_len from event GAP_EVENT_INQUIRY_RESULT + * @param event packet + * @return name_len + * @note: btstack_type J + */ + static inline int gap_event_inquiry_result_get_name_len(const uint8_t *event) + { + return event[17]; + } + /** + * @brief Get field name from event GAP_EVENT_INQUIRY_RESULT + * @param event packet + * @return name + * @note: btstack_type V + */ + static inline const uint8_t *gap_event_inquiry_result_get_name(const uint8_t *event) + { + return &event[18]; + } + + /** + * @brief Get field status from event GAP_EVENT_INQUIRY_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t gap_event_inquiry_complete_get_status(const uint8_t *event) + { + return event[2]; + } + + /** + * @brief Get field status from event HCI_SUBEVENT_LE_CONNECTION_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_subevent_le_connection_complete_get_status(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field connection_handle from event HCI_SUBEVENT_LE_CONNECTION_COMPLETE + * @param event packet + * @return connection_handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hci_subevent_le_connection_complete_get_connection_handle(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field role from event HCI_SUBEVENT_LE_CONNECTION_COMPLETE + * @param event packet + * @return role + * @note: btstack_type 1 + */ + static inline uint8_t hci_subevent_le_connection_complete_get_role(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field peer_address_type from event HCI_SUBEVENT_LE_CONNECTION_COMPLETE + * @param event packet + * @return peer_address_type + * @note: btstack_type 1 + */ + static inline uint8_t hci_subevent_le_connection_complete_get_peer_address_type(const uint8_t *event) + { + return event[7]; + } + /** + * @brief Get field peer_address from event HCI_SUBEVENT_LE_CONNECTION_COMPLETE + * @param event packet + * @param Pointer to storage for peer_address + * @note: btstack_type B + */ + static inline void hci_subevent_le_connection_complete_get_peer_address(const uint8_t *event, bd_addr_t peer_address) + { + reverse_bd_addr(&event[8], peer_address); + } + /** + * @brief Get field conn_interval from event HCI_SUBEVENT_LE_CONNECTION_COMPLETE + * @param event packet + * @return conn_interval + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_connection_complete_get_conn_interval(const uint8_t *event) + { + return little_endian_read_16(event, 14); + } + /** + * @brief Get field conn_latency from event HCI_SUBEVENT_LE_CONNECTION_COMPLETE + * @param event packet + * @return conn_latency + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_connection_complete_get_conn_latency(const uint8_t *event) + { + return little_endian_read_16(event, 16); + } + /** + * @brief Get field supervision_timeout from event HCI_SUBEVENT_LE_CONNECTION_COMPLETE + * @param event packet + * @return supervision_timeout + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_connection_complete_get_supervision_timeout(const uint8_t *event) + { + return little_endian_read_16(event, 18); + } + /** + * @brief Get field master_clock_accuracy from event HCI_SUBEVENT_LE_CONNECTION_COMPLETE + * @param event packet + * @return master_clock_accuracy + * @note: btstack_type 1 + */ + static inline uint8_t hci_subevent_le_connection_complete_get_master_clock_accuracy(const uint8_t *event) + { + return event[20]; + } + + /** + * @brief Get field status from event HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_subevent_le_connection_update_complete_get_status(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field connection_handle from event HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE + * @param event packet + * @return connection_handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hci_subevent_le_connection_update_complete_get_connection_handle(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field conn_interval from event HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE + * @param event packet + * @return conn_interval + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_connection_update_complete_get_conn_interval(const uint8_t *event) + { + return little_endian_read_16(event, 6); + } + /** + * @brief Get field conn_latency from event HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE + * @param event packet + * @return conn_latency + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_connection_update_complete_get_conn_latency(const uint8_t *event) + { + return little_endian_read_16(event, 8); + } + /** + * @brief Get field supervision_timeout from event HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE + * @param event packet + * @return supervision_timeout + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_connection_update_complete_get_supervision_timeout(const uint8_t *event) + { + return little_endian_read_16(event, 10); + } + + /** + * @brief Get field connection_handle from event HCI_SUBEVENT_LE_READ_REMOTE_USED_FEATURES_COMPLETE + * @param event packet + * @return connection_handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hci_subevent_le_read_remote_used_features_complete_get_connection_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field random_number from event HCI_SUBEVENT_LE_READ_REMOTE_USED_FEATURES_COMPLETE + * @param event packet + * @return random_number + * @note: btstack_type D + */ + static inline const uint8_t *hci_subevent_le_read_remote_used_features_complete_get_random_number(const uint8_t *event) + { + return (const uint8_t *) &event[5]; + } + /** + * @brief Get field encryption_diversifier from event HCI_SUBEVENT_LE_READ_REMOTE_USED_FEATURES_COMPLETE + * @param event packet + * @return encryption_diversifier + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_read_remote_used_features_complete_get_encryption_diversifier(const uint8_t *event) + { + return little_endian_read_16(event, 13); + } + + /** + * @brief Get field connection_handle from event HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST + * @param event packet + * @return connection_handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hci_subevent_le_long_term_key_request_get_connection_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field random_number from event HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST + * @param event packet + * @return random_number + * @note: btstack_type D + */ + static inline const uint8_t *hci_subevent_le_long_term_key_request_get_random_number(const uint8_t *event) + { + return (const uint8_t *) &event[5]; + } + /** + * @brief Get field encryption_diversifier from event HCI_SUBEVENT_LE_LONG_TERM_KEY_REQUEST + * @param event packet + * @return encryption_diversifier + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_long_term_key_request_get_encryption_diversifier(const uint8_t *event) + { + return little_endian_read_16(event, 13); + } + + /** + * @brief Get field connection_handle from event HCI_SUBEVENT_LE_REMOTE_CONNECTION_PARAMETER_REQUEST + * @param event packet + * @return connection_handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hci_subevent_le_remote_connection_parameter_request_get_connection_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field interval_min from event HCI_SUBEVENT_LE_REMOTE_CONNECTION_PARAMETER_REQUEST + * @param event packet + * @return interval_min + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_remote_connection_parameter_request_get_interval_min(const uint8_t *event) + { + return little_endian_read_16(event, 5); + } + /** + * @brief Get field interval_max from event HCI_SUBEVENT_LE_REMOTE_CONNECTION_PARAMETER_REQUEST + * @param event packet + * @return interval_max + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_remote_connection_parameter_request_get_interval_max(const uint8_t *event) + { + return little_endian_read_16(event, 7); + } + /** + * @brief Get field latency from event HCI_SUBEVENT_LE_REMOTE_CONNECTION_PARAMETER_REQUEST + * @param event packet + * @return latency + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_remote_connection_parameter_request_get_latency(const uint8_t *event) + { + return little_endian_read_16(event, 9); + } + /** + * @brief Get field timeout from event HCI_SUBEVENT_LE_REMOTE_CONNECTION_PARAMETER_REQUEST + * @param event packet + * @return timeout + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_remote_connection_parameter_request_get_timeout(const uint8_t *event) + { + return little_endian_read_16(event, 11); + } + + /** + * @brief Get field connection_handle from event HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE + * @param event packet + * @return connection_handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hci_subevent_le_data_length_change_get_connection_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field max_tx_octets from event HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE + * @param event packet + * @return max_tx_octets + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_data_length_change_get_max_tx_octets(const uint8_t *event) + { + return little_endian_read_16(event, 5); + } + /** + * @brief Get field max_tx_time from event HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE + * @param event packet + * @return max_tx_time + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_data_length_change_get_max_tx_time(const uint8_t *event) + { + return little_endian_read_16(event, 7); + } + /** + * @brief Get field max_rx_octets from event HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE + * @param event packet + * @return max_rx_octets + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_data_length_change_get_max_rx_octets(const uint8_t *event) + { + return little_endian_read_16(event, 9); + } + /** + * @brief Get field max_rx_time from event HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE + * @param event packet + * @return max_rx_time + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_data_length_change_get_max_rx_time(const uint8_t *event) + { + return little_endian_read_16(event, 11); + } + + /** + * @brief Get field status from event HCI_SUBEVENT_LE_READ_LOCAL_P256_PUBLIC_KEY_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_subevent_le_read_local_p256_public_key_complete_get_status(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field dhkey_x from event HCI_SUBEVENT_LE_READ_LOCAL_P256_PUBLIC_KEY_COMPLETE + * @param event packet + * @param Pointer to storage for dhkey_x + * @note: btstack_type Q + */ + static inline void hci_subevent_le_read_local_p256_public_key_complete_get_dhkey_x(const uint8_t *event, uint8_t *dhkey_x) + { + reverse_bytes(&event[4], dhkey_x, 32); + } + /** + * @brief Get field dhkey_y from event HCI_SUBEVENT_LE_READ_LOCAL_P256_PUBLIC_KEY_COMPLETE + * @param event packet + * @param Pointer to storage for dhkey_y + * @note: btstack_type Q + */ + static inline void hci_subevent_le_read_local_p256_public_key_complete_get_dhkey_y(const uint8_t *event, uint8_t *dhkey_y) + { + reverse_bytes(&event[36], dhkey_y, 32); + } + + /** + * @brief Get field status from event HCI_SUBEVENT_LE_GENERATE_DHKEY_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_subevent_le_generate_dhkey_complete_get_status(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field dhkey from event HCI_SUBEVENT_LE_GENERATE_DHKEY_COMPLETE + * @param event packet + * @param Pointer to storage for dhkey + * @note: btstack_type Q + */ + static inline void hci_subevent_le_generate_dhkey_complete_get_dhkey(const uint8_t *event, uint8_t *dhkey) + { + reverse_bytes(&event[4], dhkey, 32); + } + + /** + * @brief Get field status from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hci_subevent_le_enhanced_connection_complete_get_status(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field connection_handle from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE + * @param event packet + * @return connection_handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hci_subevent_le_enhanced_connection_complete_get_connection_handle(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field role from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE + * @param event packet + * @return role + * @note: btstack_type 1 + */ + static inline uint8_t hci_subevent_le_enhanced_connection_complete_get_role(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field peer_address_type from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE + * @param event packet + * @return peer_address_type + * @note: btstack_type 1 + */ + static inline uint8_t hci_subevent_le_enhanced_connection_complete_get_peer_address_type(const uint8_t *event) + { + return event[7]; + } + /** + * @brief Get field perr_addresss from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE + * @param event packet + * @param Pointer to storage for perr_addresss + * @note: btstack_type B + */ + static inline void hci_subevent_le_enhanced_connection_complete_get_peer_addresss(const uint8_t *event, bd_addr_t perr_addresss) + { + reverse_bd_addr(&event[8], perr_addresss); + } + static inline uint8_t *hci_subevent_le_enhanced_connection_complete_get_peer_addresss_ptr(const uint8_t *event) + { + return (uint8_t *)&event[8]; + } + /** + * @brief Get field local_resolvable_private_addres from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE + * @param event packet + * @param Pointer to storage for local_resolvable_private_addres + * @note: btstack_type B + */ + static inline void hci_subevent_le_enhanced_connection_complete_get_local_resolvable_private_addres(const uint8_t *event, bd_addr_t local_resolvable_private_addres) + { + reverse_bd_addr(&event[14], local_resolvable_private_addres); + } + /** + * @brief Get field peer_resolvable_private_addres from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE + * @param event packet + * @param Pointer to storage for peer_resolvable_private_addres + * @note: btstack_type B + */ + static inline void hci_subevent_le_enhanced_connection_complete_get_peer_resolvable_private_addres(const uint8_t *event, bd_addr_t peer_resolvable_private_addres) + { + reverse_bd_addr(&event[20], peer_resolvable_private_addres); + } + /** + * @brief Get field conn_interval from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE + * @param event packet + * @return conn_interval + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_enhanced_connection_complete_get_conn_interval(const uint8_t *event) + { + return little_endian_read_16(event, 26); + } + /** + * @brief Get field conn_latency from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE + * @param event packet + * @return conn_latency + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_enhanced_connection_complete_get_conn_latency(const uint8_t *event) + { + return little_endian_read_16(event, 28); + } + /** + * @brief Get field supervision_timeout from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE + * @param event packet + * @return supervision_timeout + * @note: btstack_type 2 + */ + static inline uint16_t hci_subevent_le_enhanced_connection_complete_get_supervision_timeout(const uint8_t *event) + { + return little_endian_read_16(event, 30); + } + /** + * @brief Get field master_clock_accuracy from event HCI_SUBEVENT_LE_ENHANCED_CONNECTION_COMPLETE + * @param event packet + * @return master_clock_accuracy + * @note: btstack_type 1 + */ + static inline uint8_t hci_subevent_le_enhanced_connection_complete_get_master_clock_accuracy(const uint8_t *event) + { + return event[32]; + } + + /** + * @brief Get field status from event HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hsp_subevent_rfcomm_connection_complete_get_status(const uint8_t *event) + { + return event[3]; + } + + /** + * @brief Get field status from event HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hsp_subevent_rfcomm_disconnection_complete_get_status(const uint8_t *event) + { + return event[3]; + } + + /** + * @brief Get field status from event HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hsp_subevent_audio_connection_complete_get_status(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field handle from event HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hsp_subevent_audio_connection_complete_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + + /** + * @brief Get field status from event HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hsp_subevent_audio_disconnection_complete_get_status(const uint8_t *event) + { + return event[3]; + } + + + /** + * @brief Get field gain from event HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED + * @param event packet + * @return gain + * @note: btstack_type 1 + */ + static inline uint8_t hsp_subevent_microphone_gain_changed_get_gain(const uint8_t *event) + { + return event[3]; + } + + /** + * @brief Get field gain from event HSP_SUBEVENT_SPEAKER_GAIN_CHANGED + * @param event packet + * @return gain + * @note: btstack_type 1 + */ + static inline uint8_t hsp_subevent_speaker_gain_changed_get_gain(const uint8_t *event) + { + return event[3]; + } + + /** + * @brief Get field value_length from event HSP_SUBEVENT_HS_COMMAND + * @param event packet + * @return value_length + * @note: btstack_type J + */ + static inline int hsp_subevent_hs_command_get_value_length(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field value from event HSP_SUBEVENT_HS_COMMAND + * @param event packet + * @return value + * @note: btstack_type V + */ + static inline const uint8_t *hsp_subevent_hs_command_get_value(const uint8_t *event) + { + return &event[4]; + } + + /** + * @brief Get field value_length from event HSP_SUBEVENT_AG_INDICATION + * @param event packet + * @return value_length + * @note: btstack_type J + */ + static inline int hsp_subevent_ag_indication_get_value_length(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field value from event HSP_SUBEVENT_AG_INDICATION + * @param event packet + * @return value + * @note: btstack_type V + */ + static inline const uint8_t *hsp_subevent_ag_indication_get_value(const uint8_t *event) + { + return &event[4]; + } + + /** + * @brief Get field status from event HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_service_level_connection_established_get_status(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field con_handle from event HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED + * @param event packet + * @return con_handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hfp_subevent_service_level_connection_established_get_con_handle(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field bd_addr from event HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hfp_subevent_service_level_connection_established_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[6], bd_addr); + } + + + /** + * @brief Get field status from event HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_audio_connection_established_get_status(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field handle from event HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hfp_subevent_audio_connection_established_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 4); + } + /** + * @brief Get field bd_addr from event HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hfp_subevent_audio_connection_established_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[6], bd_addr); + } + /** + * @brief Get field negotiated_codec from event HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED + * @param event packet + * @return negotiated_codec + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_audio_connection_established_get_negotiated_codec(const uint8_t *event) + { + return event[12]; + } + + + /** + * @brief Get field status from event HFP_SUBEVENT_COMPLETE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_complete_get_status(const uint8_t *event) + { + return event[3]; + } + + /** + * @brief Get field indicator_index from event HFP_SUBEVENT_AG_INDICATOR_STATUS_CHANGED + * @param event packet + * @return indicator_index + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_ag_indicator_status_changed_get_indicator_index(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field indicator_status from event HFP_SUBEVENT_AG_INDICATOR_STATUS_CHANGED + * @param event packet + * @return indicator_status + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_ag_indicator_status_changed_get_indicator_status(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field indicator_name from event HFP_SUBEVENT_AG_INDICATOR_STATUS_CHANGED + * @param event packet + * @return indicator_name + * @note: btstack_type T + */ + static inline const char *hfp_subevent_ag_indicator_status_changed_get_indicator_name(const uint8_t *event) + { + return (const char *) &event[5]; + } + + /** + * @brief Get field network_operator_mode from event HFP_SUBEVENT_NETWORK_OPERATOR_CHANGED + * @param event packet + * @return network_operator_mode + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_network_operator_changed_get_network_operator_mode(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field network_operator_format from event HFP_SUBEVENT_NETWORK_OPERATOR_CHANGED + * @param event packet + * @return network_operator_format + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_network_operator_changed_get_network_operator_format(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field network_operator_name from event HFP_SUBEVENT_NETWORK_OPERATOR_CHANGED + * @param event packet + * @return network_operator_name + * @note: btstack_type T + */ + static inline const char *hfp_subevent_network_operator_changed_get_network_operator_name(const uint8_t *event) + { + return (const char *) &event[5]; + } + + /** + * @brief Get field error from event HFP_SUBEVENT_EXTENDED_AUDIO_GATEWAY_ERROR + * @param event packet + * @return error + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_extended_audio_gateway_error_get_error(const uint8_t *event) + { + return event[3]; + } + + + + + /** + * @brief Get field number from event HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER + * @param event packet + * @return number + * @note: btstack_type T + */ + static inline const char *hfp_subevent_place_call_with_number_get_number(const uint8_t *event) + { + return (const char *) &event[3]; + } + + + /** + * @brief Get field number from event HFP_SUBEVENT_NUMBER_FOR_VOICE_TAG + * @param event packet + * @return number + * @note: btstack_type T + */ + static inline const char *hfp_subevent_number_for_voice_tag_get_number(const uint8_t *event) + { + return (const char *) &event[3]; + } + + /** + * @brief Get field dtmf from event HFP_SUBEVENT_TRANSMIT_DTMF_CODES + * @param event packet + * @return dtmf + * @note: btstack_type T + */ + static inline const char *hfp_subevent_transmit_dtmf_codes_get_dtmf(const uint8_t *event) + { + return (const char *) &event[3]; + } + + + + + /** + * @brief Get field status from event HFP_SUBEVENT_SPEAKER_VOLUME + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_speaker_volume_get_status(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field gain from event HFP_SUBEVENT_SPEAKER_VOLUME + * @param event packet + * @return gain + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_speaker_volume_get_gain(const uint8_t *event) + { + return event[4]; + } + + /** + * @brief Get field status from event HFP_SUBEVENT_MICROPHONE_VOLUME + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_microphone_volume_get_status(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field gain from event HFP_SUBEVENT_MICROPHONE_VOLUME + * @param event packet + * @return gain + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_microphone_volume_get_gain(const uint8_t *event) + { + return event[4]; + } + + /** + * @brief Get field type from event HFP_SUBEVENT_CALL_WAITING_NOTIFICATION + * @param event packet + * @return type + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_call_waiting_notification_get_type(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field number from event HFP_SUBEVENT_CALL_WAITING_NOTIFICATION + * @param event packet + * @return number + * @note: btstack_type T + */ + static inline const char *hfp_subevent_call_waiting_notification_get_number(const uint8_t *event) + { + return (const char *) &event[4]; + } + + /** + * @brief Get field type from event HFP_SUBEVENT_CALLING_LINE_IDENTIFICATION_NOTIFICATION + * @param event packet + * @return type + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_calling_line_identification_notification_get_type(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field number from event HFP_SUBEVENT_CALLING_LINE_IDENTIFICATION_NOTIFICATION + * @param event packet + * @return number + * @note: btstack_type T + */ + static inline const char *hfp_subevent_calling_line_identification_notification_get_number(const uint8_t *event) + { + return (const char *) &event[4]; + } + + /** + * @brief Get field clcc_idx from event HFP_SUBEVENT_ENHANCED_CALL_STATUS + * @param event packet + * @return clcc_idx + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_enhanced_call_status_get_clcc_idx(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field clcc_dir from event HFP_SUBEVENT_ENHANCED_CALL_STATUS + * @param event packet + * @return clcc_dir + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_enhanced_call_status_get_clcc_dir(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field clcc_status from event HFP_SUBEVENT_ENHANCED_CALL_STATUS + * @param event packet + * @return clcc_status + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_enhanced_call_status_get_clcc_status(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field clcc_mpty from event HFP_SUBEVENT_ENHANCED_CALL_STATUS + * @param event packet + * @return clcc_mpty + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_enhanced_call_status_get_clcc_mpty(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field bnip_type from event HFP_SUBEVENT_ENHANCED_CALL_STATUS + * @param event packet + * @return bnip_type + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_enhanced_call_status_get_bnip_type(const uint8_t *event) + { + return event[7]; + } + /** + * @brief Get field bnip_number from event HFP_SUBEVENT_ENHANCED_CALL_STATUS + * @param event packet + * @return bnip_number + * @note: btstack_type T + */ + static inline const char *hfp_subevent_enhanced_call_status_get_bnip_number(const uint8_t *event) + { + return (const char *) &event[8]; + } + + /** + * @brief Get field status from event HFP_SUBEVENT_SUBSCRIBER_NUMBER_INFORMATION + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_subscriber_number_information_get_status(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field bnip_type from event HFP_SUBEVENT_SUBSCRIBER_NUMBER_INFORMATION + * @param event packet + * @return bnip_type + * @note: btstack_type 1 + */ + static inline uint8_t hfp_subevent_subscriber_number_information_get_bnip_type(const uint8_t *event) + { + return event[4]; + } + /** + * @brief Get field bnip_number from event HFP_SUBEVENT_SUBSCRIBER_NUMBER_INFORMATION + * @param event packet + * @return bnip_number + * @note: btstack_type T + */ + static inline const char *hfp_subevent_subscriber_number_information_get_bnip_number(const uint8_t *event) + { + return (const char *) &event[5]; + } + + /** + * @brief Get field value from event HFP_SUBEVENT_RESPONSE_AND_HOLD_STATUS + * @param event packet + * @return value + * @note: btstack_type T + */ + static inline const char *hfp_subevent_response_and_hold_status_get_value(const uint8_t *event) + { + return (const char *) &event[3]; + } + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event ANCS_SUBEVENT_CLIENT_CONNECTED + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t ancs_subevent_client_connected_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event ANCS_SUBEVENT_CLIENT_NOTIFICATION + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t ancs_subevent_client_notification_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field attribute_id from event ANCS_SUBEVENT_CLIENT_NOTIFICATION + * @param event packet + * @return attribute_id + * @note: btstack_type 2 + */ + static inline uint16_t ancs_subevent_client_notification_get_attribute_id(const uint8_t *event) + { + return little_endian_read_16(event, 5); + } + /** + * @brief Get field text from event ANCS_SUBEVENT_CLIENT_NOTIFICATION + * @param event packet + * @return text + * @note: btstack_type T + */ + static inline const char *ancs_subevent_client_notification_get_text(const uint8_t *event) + { + return (const char *) &event[7]; + } +#endif + +#ifdef ENABLE_BLE + /** + * @brief Get field handle from event ANCS_SUBEVENT_CLIENT_DISCONNECTED + * @param event packet + * @return handle + * @note: btstack_type H + */ + static inline hci_con_handle_t ancs_subevent_client_disconnected_get_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } +#endif + + /** + * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_ACCEPT + * @param event packet + * @return avdtp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_signaling_accept_get_avdtp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event AVDTP_SUBEVENT_SIGNALING_ACCEPT + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_accept_get_local_seid(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field signal_identifier from event AVDTP_SUBEVENT_SIGNALING_ACCEPT + * @param event packet + * @return signal_identifier + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_accept_get_signal_identifier(const uint8_t *event) + { + return event[6]; + } + + /** + * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_REJECT + * @param event packet + * @return avdtp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_signaling_reject_get_avdtp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event AVDTP_SUBEVENT_SIGNALING_REJECT + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_reject_get_local_seid(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field signal_identifier from event AVDTP_SUBEVENT_SIGNALING_REJECT + * @param event packet + * @return signal_identifier + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_reject_get_signal_identifier(const uint8_t *event) + { + return event[6]; + } + + /** + * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT + * @param event packet + * @return avdtp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_signaling_general_reject_get_avdtp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_general_reject_get_local_seid(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field signal_identifier from event AVDTP_SUBEVENT_SIGNALING_GENERAL_REJECT + * @param event packet + * @return signal_identifier + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_general_reject_get_signal_identifier(const uint8_t *event) + { + return event[6]; + } + + /** + * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED + * @param event packet + * @return avdtp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_signaling_connection_established_get_avdtp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field bd_addr from event AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void avdtp_subevent_signaling_connection_established_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[5], bd_addr); + } + /** + * @brief Get field status from event AVDTP_SUBEVENT_SIGNALING_CONNECTION_ESTABLISHED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_connection_established_get_status(const uint8_t *event) + { + return event[11]; + } + + /** + * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_CONNECTION_RELEASED + * @param event packet + * @return avdtp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_signaling_connection_released_get_avdtp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_SEP_FOUND + * @param event packet + * @return avdtp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_signaling_sep_found_get_avdtp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field remote_seid from event AVDTP_SUBEVENT_SIGNALING_SEP_FOUND + * @param event packet + * @return remote_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_sep_found_get_remote_seid(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field in_use from event AVDTP_SUBEVENT_SIGNALING_SEP_FOUND + * @param event packet + * @return in_use + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_sep_found_get_in_use(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field media_type from event AVDTP_SUBEVENT_SIGNALING_SEP_FOUND + * @param event packet + * @return media_type + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_sep_found_get_media_type(const uint8_t *event) + { + return event[7]; + } + /** + * @brief Get field sep_type from event AVDTP_SUBEVENT_SIGNALING_SEP_FOUND + * @param event packet + * @return sep_type + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_sep_found_get_sep_type(const uint8_t *event) + { + return event[8]; + } + + /** + * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY + * @param event packet + * @return avdtp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_signaling_media_codec_sbc_capability_get_avdtp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_local_seid(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field remote_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY + * @param event packet + * @return remote_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_remote_seid(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field media_type from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY + * @param event packet + * @return media_type + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_media_type(const uint8_t *event) + { + return event[7]; + } + /** + * @brief Get field sampling_frequency_bitmap from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY + * @param event packet + * @return sampling_frequency_bitmap + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_sampling_frequency_bitmap(const uint8_t *event) + { + return event[8]; + } + /** + * @brief Get field channel_mode_bitmap from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY + * @param event packet + * @return channel_mode_bitmap + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_channel_mode_bitmap(const uint8_t *event) + { + return event[9]; + } + /** + * @brief Get field block_length_bitmap from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY + * @param event packet + * @return block_length_bitmap + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_block_length_bitmap(const uint8_t *event) + { + return event[10]; + } + /** + * @brief Get field subbands_bitmap from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY + * @param event packet + * @return subbands_bitmap + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_subbands_bitmap(const uint8_t *event) + { + return event[11]; + } + /** + * @brief Get field allocation_method_bitmap from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY + * @param event packet + * @return allocation_method_bitmap + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_allocation_method_bitmap(const uint8_t *event) + { + return event[12]; + } + /** + * @brief Get field min_bitpool_value from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY + * @param event packet + * @return min_bitpool_value + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_min_bitpool_value(const uint8_t *event) + { + return event[13]; + } + /** + * @brief Get field max_bitpool_value from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CAPABILITY + * @param event packet + * @return max_bitpool_value + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_capability_get_max_bitpool_value(const uint8_t *event) + { + return event[14]; + } + + /** + * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY + * @param event packet + * @return avdtp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_signaling_media_codec_other_capability_get_avdtp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_other_capability_get_local_seid(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field remote_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY + * @param event packet + * @return remote_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_other_capability_get_remote_seid(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field media_type from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY + * @param event packet + * @return media_type + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_other_capability_get_media_type(const uint8_t *event) + { + return event[7]; + } + /** + * @brief Get field media_codec_type from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY + * @param event packet + * @return media_codec_type + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_signaling_media_codec_other_capability_get_media_codec_type(const uint8_t *event) + { + return little_endian_read_16(event, 8); + } + /** + * @brief Get field media_codec_information_len from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY + * @param event packet + * @return media_codec_information_len + * @note: btstack_type L + */ + static inline int avdtp_subevent_signaling_media_codec_other_capability_get_media_codec_information_len(const uint8_t *event) + { + return little_endian_read_16(event, 10); + } + /** + * @brief Get field media_codec_information from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CAPABILITY + * @param event packet + * @return media_codec_information + * @note: btstack_type V + */ + static inline const uint8_t *avdtp_subevent_signaling_media_codec_other_capability_get_media_codec_information(const uint8_t *event) + { + return &event[12]; + } + + /** + * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return avdtp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_avdtp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_local_seid(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field remote_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return remote_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_remote_seid(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field reconfigure from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return reconfigure + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(const uint8_t *event) + { + return event[7]; + } + /** + * @brief Get field media_type from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return media_type + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_media_type(const uint8_t *event) + { + return event[8]; + } + /** + * @brief Get field sampling_frequency from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return sampling_frequency + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(const uint8_t *event) + { + return little_endian_read_16(event, 9); + } + /** + * @brief Get field channel_mode from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return channel_mode + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(const uint8_t *event) + { + return event[11]; + } + /** + * @brief Get field num_channels from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return num_channels + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(const uint8_t *event) + { + return event[12]; + } + /** + * @brief Get field block_length from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return block_length + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_block_length(const uint8_t *event) + { + return event[13]; + } + /** + * @brief Get field subbands from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return subbands + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_subbands(const uint8_t *event) + { + return event[14]; + } + /** + * @brief Get field allocation_method from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return allocation_method + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(const uint8_t *event) + { + return event[15]; + } + /** + * @brief Get field min_bitpool_value from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return min_bitpool_value + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(const uint8_t *event) + { + return event[16]; + } + /** + * @brief Get field max_bitpool_value from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return max_bitpool_value + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(const uint8_t *event) + { + return event[17]; + } + + /** + * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return avdtp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_signaling_media_codec_other_configuration_get_avdtp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_other_configuration_get_local_seid(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field remote_seid from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return remote_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_other_configuration_get_remote_seid(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field reconfigure from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return reconfigure + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_other_configuration_get_reconfigure(const uint8_t *event) + { + return event[7]; + } + /** + * @brief Get field media_type from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return media_type + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_signaling_media_codec_other_configuration_get_media_type(const uint8_t *event) + { + return event[8]; + } + /** + * @brief Get field media_codec_type from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return media_codec_type + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_signaling_media_codec_other_configuration_get_media_codec_type(const uint8_t *event) + { + return little_endian_read_16(event, 9); + } + /** + * @brief Get field media_codec_information_len from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return media_codec_information_len + * @note: btstack_type L + */ + static inline int avdtp_subevent_signaling_media_codec_other_configuration_get_media_codec_information_len(const uint8_t *event) + { + return little_endian_read_16(event, 11); + } + /** + * @brief Get field media_codec_information from event AVDTP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return media_codec_information + * @note: btstack_type V + */ + static inline const uint8_t *avdtp_subevent_signaling_media_codec_other_configuration_get_media_codec_information(const uint8_t *event) + { + return &event[13]; + } + + /** + * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED + * @param event packet + * @return avdtp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_streaming_connection_established_get_avdtp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field bd_addr from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void avdtp_subevent_streaming_connection_established_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[5], bd_addr); + } + /** + * @brief Get field local_seid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_streaming_connection_established_get_local_seid(const uint8_t *event) + { + return event[11]; + } + /** + * @brief Get field remote_seid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED + * @param event packet + * @return remote_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_streaming_connection_established_get_remote_seid(const uint8_t *event) + { + return event[12]; + } + /** + * @brief Get field status from event AVDTP_SUBEVENT_STREAMING_CONNECTION_ESTABLISHED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_streaming_connection_established_get_status(const uint8_t *event) + { + return event[13]; + } + + /** + * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_RELEASED + * @param event packet + * @return avdtp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_streaming_connection_released_get_avdtp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event AVDTP_SUBEVENT_STREAMING_CONNECTION_RELEASED + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_streaming_connection_released_get_local_seid(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field avdtp_cid from event AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW + * @param event packet + * @return avdtp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_streaming_can_send_media_packet_now_get_avdtp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t avdtp_subevent_streaming_can_send_media_packet_now_get_local_seid(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field sequence_number from event AVDTP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW + * @param event packet + * @return sequence_number + * @note: btstack_type 2 + */ + static inline uint16_t avdtp_subevent_streaming_can_send_media_packet_now_get_sequence_number(const uint8_t *event) + { + return little_endian_read_16(event, 6); + } + + /** + * @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW + * @param event packet + * @return a2dp_cid + * @note: btstack_type 2 + */ + static inline uint16_t a2dp_subevent_streaming_can_send_media_packet_now_get_a2dp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_streaming_can_send_media_packet_now_get_local_seid(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field a2dp_cid from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return a2dp_cid + * @note: btstack_type 2 + */ + static inline uint16_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_a2dp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field int_seid from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return int_seid + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_int_seid(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field acp_seid from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return acp_seid + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_acp_seid(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field reconfigure from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return reconfigure + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_reconfigure(const uint8_t *event) + { + return event[7]; + } + /** + * @brief Get field media_type from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return media_type + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_media_type(const uint8_t *event) + { + return event[8]; + } + /** + * @brief Get field sampling_frequency from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return sampling_frequency + * @note: btstack_type 2 + */ + static inline uint16_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_sampling_frequency(const uint8_t *event) + { + return little_endian_read_16(event, 9); + } + /** + * @brief Get field channel_mode from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return channel_mode + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(const uint8_t *event) + { + return event[11]; + } + /** + * @brief Get field num_channels from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return num_channels + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_num_channels(const uint8_t *event) + { + return event[12]; + } + /** + * @brief Get field block_length from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return block_length + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_block_length(const uint8_t *event) + { + return event[13]; + } + /** + * @brief Get field subbands from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return subbands + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_subbands(const uint8_t *event) + { + return event[14]; + } + /** + * @brief Get field allocation_method from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return allocation_method + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(const uint8_t *event) + { + return event[15]; + } + /** + * @brief Get field min_bitpool_value from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return min_bitpool_value + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(const uint8_t *event) + { + return event[16]; + } + /** + * @brief Get field max_bitpool_value from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION + * @param event packet + * @return max_bitpool_value + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(const uint8_t *event) + { + return event[17]; + } + + /** + * @brief Get field a2dp_cid from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return a2dp_cid + * @note: btstack_type 2 + */ + static inline uint16_t a2dp_subevent_signaling_media_codec_other_configuration_get_a2dp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field int_seid from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return int_seid + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_signaling_media_codec_other_configuration_get_int_seid(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field acp_seid from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return acp_seid + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_signaling_media_codec_other_configuration_get_acp_seid(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field reconfigure from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return reconfigure + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_signaling_media_codec_other_configuration_get_reconfigure(const uint8_t *event) + { + return event[7]; + } + /** + * @brief Get field media_type from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return media_type + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_signaling_media_codec_other_configuration_get_media_type(const uint8_t *event) + { + return event[8]; + } + /** + * @brief Get field media_codec_type from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return media_codec_type + * @note: btstack_type 2 + */ + static inline uint16_t a2dp_subevent_signaling_media_codec_other_configuration_get_media_codec_type(const uint8_t *event) + { + return little_endian_read_16(event, 9); + } + /** + * @brief Get field media_codec_information_len from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return media_codec_information_len + * @note: btstack_type L + */ + static inline int a2dp_subevent_signaling_media_codec_other_configuration_get_media_codec_information_len(const uint8_t *event) + { + return little_endian_read_16(event, 11); + } + /** + * @brief Get field media_codec_information from event A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_OTHER_CONFIGURATION + * @param event packet + * @return media_codec_information + * @note: btstack_type V + */ + static inline const uint8_t *a2dp_subevent_signaling_media_codec_other_configuration_get_media_codec_information(const uint8_t *event) + { + return &event[13]; + } + + /** + * @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_ESTABLISHED + * @param event packet + * @return a2dp_cid + * @note: btstack_type 2 + */ + static inline uint16_t a2dp_subevent_stream_established_get_a2dp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field bd_addr from event A2DP_SUBEVENT_STREAM_ESTABLISHED + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void a2dp_subevent_stream_established_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[5], bd_addr); + } + /** + * @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_ESTABLISHED + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_stream_established_get_local_seid(const uint8_t *event) + { + return event[11]; + } + /** + * @brief Get field remote_seid from event A2DP_SUBEVENT_STREAM_ESTABLISHED + * @param event packet + * @return remote_seid + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_stream_established_get_remote_seid(const uint8_t *event) + { + return event[12]; + } + /** + * @brief Get field status from event A2DP_SUBEVENT_STREAM_ESTABLISHED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_stream_established_get_status(const uint8_t *event) + { + return event[13]; + } + + /** + * @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_STARTED + * @param event packet + * @return a2dp_cid + * @note: btstack_type 2 + */ + static inline uint16_t a2dp_subevent_stream_started_get_a2dp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_STARTED + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_stream_started_get_local_seid(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_SUSPENDED + * @param event packet + * @return a2dp_cid + * @note: btstack_type 2 + */ + static inline uint16_t a2dp_subevent_stream_suspended_get_a2dp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_SUSPENDED + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_stream_suspended_get_local_seid(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_STOPPED + * @param event packet + * @return a2dp_cid + * @note: btstack_type 2 + */ + static inline uint16_t a2dp_subevent_stream_stopped_get_a2dp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_STOPPED + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_stream_stopped_get_local_seid(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field a2dp_cid from event A2DP_SUBEVENT_STREAM_RELEASED + * @param event packet + * @return a2dp_cid + * @note: btstack_type 2 + */ + static inline uint16_t a2dp_subevent_stream_released_get_a2dp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event A2DP_SUBEVENT_STREAM_RELEASED + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_stream_released_get_local_seid(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field a2dp_cid from event A2DP_SUBEVENT_COMMAND_ACCEPTED + * @param event packet + * @return a2dp_cid + * @note: btstack_type 2 + */ + static inline uint16_t a2dp_subevent_command_accepted_get_a2dp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event A2DP_SUBEVENT_COMMAND_ACCEPTED + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_command_accepted_get_local_seid(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field signal_identifier from event A2DP_SUBEVENT_COMMAND_ACCEPTED + * @param event packet + * @return signal_identifier + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_command_accepted_get_signal_identifier(const uint8_t *event) + { + return event[6]; + } + + /** + * @brief Get field a2dp_cid from event A2DP_SUBEVENT_COMMAND_REJECTED + * @param event packet + * @return a2dp_cid + * @note: btstack_type 2 + */ + static inline uint16_t a2dp_subevent_command_rejected_get_a2dp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field local_seid from event A2DP_SUBEVENT_COMMAND_REJECTED + * @param event packet + * @return local_seid + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_command_rejected_get_local_seid(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field signal_identifier from event A2DP_SUBEVENT_COMMAND_REJECTED + * @param event packet + * @return signal_identifier + * @note: btstack_type 1 + */ + static inline uint8_t a2dp_subevent_command_rejected_get_signal_identifier(const uint8_t *event) + { + return event[6]; + } + + /** + * @brief Get field a2dp_cid from event A2DP_SUBEVENT_INCOMING_CONNECTION_ESTABLISHED + * @param event packet + * @return a2dp_cid + * @note: btstack_type 2 + */ + static inline uint16_t a2dp_subevent_incoming_connection_established_get_a2dp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field bd_addr from event A2DP_SUBEVENT_INCOMING_CONNECTION_ESTABLISHED + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void a2dp_subevent_incoming_connection_established_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[5], bd_addr); + } + + /** + * @brief Get field a2dp_cid from event A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED + * @param event packet + * @return a2dp_cid + * @note: btstack_type 2 + */ + static inline uint16_t a2dp_subevent_signaling_connection_released_get_a2dp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field status from event AVRCP_SUBEVENT_CONNECTION_ESTABLISHED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_connection_established_get_status(const uint8_t *event) + { + return event[3]; + } + /** + * @brief Get field bd_addr from event AVRCP_SUBEVENT_CONNECTION_ESTABLISHED + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void avrcp_subevent_connection_established_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[4], bd_addr); + } + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_CONNECTION_ESTABLISHED + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_connection_established_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 10); + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_CONNECTION_RELEASED + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_connection_released_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_SHUFFLE_AND_REPEAT_MODE + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_shuffle_and_repeat_mode_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_SHUFFLE_AND_REPEAT_MODE + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_shuffle_and_repeat_mode_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field repeat_mode from event AVRCP_SUBEVENT_SHUFFLE_AND_REPEAT_MODE + * @param event packet + * @return repeat_mode + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_shuffle_and_repeat_mode_get_repeat_mode(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field shuffle_mode from event AVRCP_SUBEVENT_SHUFFLE_AND_REPEAT_MODE + * @param event packet + * @return shuffle_mode + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_shuffle_and_repeat_mode_get_shuffle_mode(const uint8_t *event) + { + return event[7]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_PLAY_STATUS + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_play_status_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_PLAY_STATUS + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_play_status_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field song_length from event AVRCP_SUBEVENT_PLAY_STATUS + * @param event packet + * @return song_length + * @note: btstack_type 4 + */ + static inline uint32_t avrcp_subevent_play_status_get_song_length(const uint8_t *event) + { + return little_endian_read_32(event, 6); + } + /** + * @brief Get field song_position from event AVRCP_SUBEVENT_PLAY_STATUS + * @param event packet + * @return song_position + * @note: btstack_type 4 + */ + static inline uint32_t avrcp_subevent_play_status_get_song_position(const uint8_t *event) + { + return little_endian_read_32(event, 10); + } + /** + * @brief Get field play_status from event AVRCP_SUBEVENT_PLAY_STATUS + * @param event packet + * @return play_status + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_play_status_get_play_status(const uint8_t *event) + { + return event[14]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOTIFICATION_PLAYBACK_STATUS_CHANGED + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_notification_playback_status_changed_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_NOTIFICATION_PLAYBACK_STATUS_CHANGED + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_notification_playback_status_changed_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field play_status from event AVRCP_SUBEVENT_NOTIFICATION_PLAYBACK_STATUS_CHANGED + * @param event packet + * @return play_status + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_notification_playback_status_changed_get_play_status(const uint8_t *event) + { + return event[6]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOTIFICATION_TRACK_CHANGED + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_notification_track_changed_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_NOTIFICATION_TRACK_CHANGED + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_notification_track_changed_get_command_type(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOTIFICATION_NOW_PLAYING_CONTENT_CHANGED + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_notification_now_playing_content_changed_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_NOTIFICATION_NOW_PLAYING_CONTENT_CHANGED + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_notification_now_playing_content_changed_get_command_type(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOTIFICATION_AVAILABLE_PLAYERS_CHANGED + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_notification_available_players_changed_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_NOTIFICATION_AVAILABLE_PLAYERS_CHANGED + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_notification_available_players_changed_get_command_type(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_notification_volume_changed_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_notification_volume_changed_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field absolute_volume from event AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED + * @param event packet + * @return absolute_volume + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_notification_volume_changed_get_absolute_volume(const uint8_t *event) + { + return event[6]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_SET_ABSOLUTE_VOLUME_RESPONSE + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_set_absolute_volume_response_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_SET_ABSOLUTE_VOLUME_RESPONSE + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_set_absolute_volume_response_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field absolute_volume from event AVRCP_SUBEVENT_SET_ABSOLUTE_VOLUME_RESPONSE + * @param event packet + * @return absolute_volume + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_set_absolute_volume_response_get_absolute_volume(const uint8_t *event) + { + return event[6]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_ENABLE_NOTIFICATION_COMPLETE + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_enable_notification_complete_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_ENABLE_NOTIFICATION_COMPLETE + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_enable_notification_complete_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field notification_id from event AVRCP_SUBEVENT_ENABLE_NOTIFICATION_COMPLETE + * @param event packet + * @return notification_id + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_enable_notification_complete_get_notification_id(const uint8_t *event) + { + return event[6]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_OPERATION_START + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_operation_start_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_OPERATION_START + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_operation_start_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field operation_id from event AVRCP_SUBEVENT_OPERATION_START + * @param event packet + * @return operation_id + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_operation_start_get_operation_id(const uint8_t *event) + { + return event[6]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_OPERATION_COMPLETE + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_operation_complete_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_OPERATION_COMPLETE + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_operation_complete_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field operation_id from event AVRCP_SUBEVENT_OPERATION_COMPLETE + * @param event packet + * @return operation_id + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_operation_complete_get_operation_id(const uint8_t *event) + { + return event[6]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_PLAYER_APPLICATION_VALUE_RESPONSE + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_player_application_value_response_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_PLAYER_APPLICATION_VALUE_RESPONSE + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_player_application_value_response_get_command_type(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_COMPANY_IDS_QUERY + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_company_ids_query_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_EVENT_IDS_QUERY + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_event_ids_query_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_PLAY_STATUS_QUERY + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_play_status_query_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_OPERATION + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_operation_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field operation_id from event AVRCP_SUBEVENT_OPERATION + * @param event packet + * @return operation_id + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_operation_get_operation_id(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field operands_length from event AVRCP_SUBEVENT_OPERATION + * @param event packet + * @return operands_length + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_operation_get_operands_length(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field operand from event AVRCP_SUBEVENT_OPERATION + * @param event packet + * @return operand + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_operation_get_operand(const uint8_t *event) + { + return event[7]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOW_PLAYING_TRACK_INFO + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_now_playing_track_info_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_NOW_PLAYING_TRACK_INFO + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_now_playing_track_info_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field track from event AVRCP_SUBEVENT_NOW_PLAYING_TRACK_INFO + * @param event packet + * @return track + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_now_playing_track_info_get_track(const uint8_t *event) + { + return event[6]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOW_PLAYING_TOTAL_TRACKS_INFO + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_now_playing_total_tracks_info_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_NOW_PLAYING_TOTAL_TRACKS_INFO + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_now_playing_total_tracks_info_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field total_tracks from event AVRCP_SUBEVENT_NOW_PLAYING_TOTAL_TRACKS_INFO + * @param event packet + * @return total_tracks + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_now_playing_total_tracks_info_get_total_tracks(const uint8_t *event) + { + return event[6]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOW_PLAYING_SONG_LENGTH_MS_INFO + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_now_playing_song_length_ms_info_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_NOW_PLAYING_SONG_LENGTH_MS_INFO + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_now_playing_song_length_ms_info_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field song_length from event AVRCP_SUBEVENT_NOW_PLAYING_SONG_LENGTH_MS_INFO + * @param event packet + * @return song_length + * @note: btstack_type 4 + */ + static inline uint32_t avrcp_subevent_now_playing_song_length_ms_info_get_song_length(const uint8_t *event) + { + return little_endian_read_32(event, 6); + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOW_PLAYING_TITLE_INFO + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_now_playing_title_info_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_NOW_PLAYING_TITLE_INFO + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_now_playing_title_info_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field value_len from event AVRCP_SUBEVENT_NOW_PLAYING_TITLE_INFO + * @param event packet + * @return value_len + * @note: btstack_type J + */ + static inline int avrcp_subevent_now_playing_title_info_get_value_len(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field value from event AVRCP_SUBEVENT_NOW_PLAYING_TITLE_INFO + * @param event packet + * @return value + * @note: btstack_type V + */ + static inline const uint8_t *avrcp_subevent_now_playing_title_info_get_value(const uint8_t *event) + { + return &event[7]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOW_PLAYING_ARTIST_INFO + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_now_playing_artist_info_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_NOW_PLAYING_ARTIST_INFO + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_now_playing_artist_info_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field value_len from event AVRCP_SUBEVENT_NOW_PLAYING_ARTIST_INFO + * @param event packet + * @return value_len + * @note: btstack_type J + */ + static inline int avrcp_subevent_now_playing_artist_info_get_value_len(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field value from event AVRCP_SUBEVENT_NOW_PLAYING_ARTIST_INFO + * @param event packet + * @return value + * @note: btstack_type V + */ + static inline const uint8_t *avrcp_subevent_now_playing_artist_info_get_value(const uint8_t *event) + { + return &event[7]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOW_PLAYING_ALBUM_INFO + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_now_playing_album_info_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_NOW_PLAYING_ALBUM_INFO + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_now_playing_album_info_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field value_len from event AVRCP_SUBEVENT_NOW_PLAYING_ALBUM_INFO + * @param event packet + * @return value_len + * @note: btstack_type J + */ + static inline int avrcp_subevent_now_playing_album_info_get_value_len(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field value from event AVRCP_SUBEVENT_NOW_PLAYING_ALBUM_INFO + * @param event packet + * @return value + * @note: btstack_type V + */ + static inline const uint8_t *avrcp_subevent_now_playing_album_info_get_value(const uint8_t *event) + { + return &event[7]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOW_PLAYING_GENRE_INFO + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_now_playing_genre_info_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_NOW_PLAYING_GENRE_INFO + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_now_playing_genre_info_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field value_len from event AVRCP_SUBEVENT_NOW_PLAYING_GENRE_INFO + * @param event packet + * @return value_len + * @note: btstack_type J + */ + static inline int avrcp_subevent_now_playing_genre_info_get_value_len(const uint8_t *event) + { + return event[6]; + } + /** + * @brief Get field value from event AVRCP_SUBEVENT_NOW_PLAYING_GENRE_INFO + * @param event packet + * @return value + * @note: btstack_type V + */ + static inline const uint8_t *avrcp_subevent_now_playing_genre_info_get_value(const uint8_t *event) + { + return &event[7]; + } + + /** + * @brief Get field avrcp_cid from event AVRCP_SUBEVENT_NOW_PLAYING_INFO_DONE + * @param event packet + * @return avrcp_cid + * @note: btstack_type 2 + */ + static inline uint16_t avrcp_subevent_now_playing_info_done_get_avrcp_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field command_type from event AVRCP_SUBEVENT_NOW_PLAYING_INFO_DONE + * @param event packet + * @return command_type + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_now_playing_info_done_get_command_type(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field status from event AVRCP_SUBEVENT_NOW_PLAYING_INFO_DONE + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t avrcp_subevent_now_playing_info_done_get_status(const uint8_t *event) + { + return event[6]; + } + + /** + * @brief Get field goep_cid from event GOEP_SUBEVENT_CONNECTION_OPENED + * @param event packet + * @return goep_cid + * @note: btstack_type 2 + */ + static inline uint16_t goep_subevent_connection_opened_get_goep_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field status from event GOEP_SUBEVENT_CONNECTION_OPENED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t goep_subevent_connection_opened_get_status(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field bd_addr from event GOEP_SUBEVENT_CONNECTION_OPENED + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void goep_subevent_connection_opened_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[6], bd_addr); + } + /** + * @brief Get field con_handle from event GOEP_SUBEVENT_CONNECTION_OPENED + * @param event packet + * @return con_handle + * @note: btstack_type H + */ + static inline hci_con_handle_t goep_subevent_connection_opened_get_con_handle(const uint8_t *event) + { + return little_endian_read_16(event, 12); + } + /** + * @brief Get field incoming from event GOEP_SUBEVENT_CONNECTION_OPENED + * @param event packet + * @return incoming + * @note: btstack_type 1 + */ + static inline uint8_t goep_subevent_connection_opened_get_incoming(const uint8_t *event) + { + return event[14]; + } + + /** + * @brief Get field goep_cid from event GOEP_SUBEVENT_CONNECTION_CLOSED + * @param event packet + * @return goep_cid + * @note: btstack_type 2 + */ + static inline uint16_t goep_subevent_connection_closed_get_goep_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field goep_cid from event GOEP_SUBEVENT_CAN_SEND_NOW + * @param event packet + * @return goep_cid + * @note: btstack_type 2 + */ + static inline uint16_t goep_subevent_can_send_now_get_goep_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field pbap_cid from event PBAP_SUBEVENT_CONNECTION_OPENED + * @param event packet + * @return pbap_cid + * @note: btstack_type 2 + */ + static inline uint16_t pbap_subevent_connection_opened_get_pbap_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field status from event PBAP_SUBEVENT_CONNECTION_OPENED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t pbap_subevent_connection_opened_get_status(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field bd_addr from event PBAP_SUBEVENT_CONNECTION_OPENED + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void pbap_subevent_connection_opened_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[6], bd_addr); + } + /** + * @brief Get field con_handle from event PBAP_SUBEVENT_CONNECTION_OPENED + * @param event packet + * @return con_handle + * @note: btstack_type H + */ + static inline hci_con_handle_t pbap_subevent_connection_opened_get_con_handle(const uint8_t *event) + { + return little_endian_read_16(event, 12); + } + /** + * @brief Get field incoming from event PBAP_SUBEVENT_CONNECTION_OPENED + * @param event packet + * @return incoming + * @note: btstack_type 1 + */ + static inline uint8_t pbap_subevent_connection_opened_get_incoming(const uint8_t *event) + { + return event[14]; + } + + /** + * @brief Get field goep_cid from event PBAP_SUBEVENT_CONNECTION_CLOSED + * @param event packet + * @return goep_cid + * @note: btstack_type 2 + */ + static inline uint16_t pbap_subevent_connection_closed_get_goep_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field goep_cid from event PBAP_SUBEVENT_OPERATION_COMPLETED + * @param event packet + * @return goep_cid + * @note: btstack_type 2 + */ + static inline uint16_t pbap_subevent_operation_completed_get_goep_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field status from event PBAP_SUBEVENT_OPERATION_COMPLETED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t pbap_subevent_operation_completed_get_status(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field hid_cid from event HID_SUBEVENT_CONNECTION_OPENED + * @param event packet + * @return hid_cid + * @note: btstack_type 2 + */ + static inline uint16_t hid_subevent_connection_opened_get_hid_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field status from event HID_SUBEVENT_CONNECTION_OPENED + * @param event packet + * @return status + * @note: btstack_type 1 + */ + static inline uint8_t hid_subevent_connection_opened_get_status(const uint8_t *event) + { + return event[5]; + } + /** + * @brief Get field bd_addr from event HID_SUBEVENT_CONNECTION_OPENED + * @param event packet + * @param Pointer to storage for bd_addr + * @note: btstack_type B + */ + static inline void hid_subevent_connection_opened_get_bd_addr(const uint8_t *event, bd_addr_t bd_addr) + { + reverse_bd_addr(&event[6], bd_addr); + } + /** + * @brief Get field con_handle from event HID_SUBEVENT_CONNECTION_OPENED + * @param event packet + * @return con_handle + * @note: btstack_type H + */ + static inline hci_con_handle_t hid_subevent_connection_opened_get_con_handle(const uint8_t *event) + { + return little_endian_read_16(event, 12); + } + /** + * @brief Get field incoming from event HID_SUBEVENT_CONNECTION_OPENED + * @param event packet + * @return incoming + * @note: btstack_type 1 + */ + static inline uint8_t hid_subevent_connection_opened_get_incoming(const uint8_t *event) + { + return event[14]; + } + + /** + * @brief Get field hid_cid from event HID_SUBEVENT_CONNECTION_CLOSED + * @param event packet + * @return hid_cid + * @note: btstack_type 2 + */ + static inline uint16_t hid_subevent_connection_closed_get_hid_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field hid_cid from event HID_SUBEVENT_CAN_SEND_NOW + * @param event packet + * @return hid_cid + * @note: btstack_type 2 + */ + static inline uint16_t hid_subevent_can_send_now_get_hid_cid(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field con_handle from event HIDS_SUBEVENT_CAN_SEND_NOW + * @param event packet + * @return con_handle + * @note: btstack_type 2 + */ + static inline uint16_t hids_subevent_can_send_now_get_con_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + + /** + * @brief Get field con_handle from event HIDS_SUBEVENT_PROTOCOL_MODE + * @param event packet + * @return con_handle + * @note: btstack_type 2 + */ + static inline uint16_t hids_subevent_protocol_mode_get_con_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field protocol_mode from event HIDS_SUBEVENT_PROTOCOL_MODE + * @param event packet + * @return protocol_mode + * @note: btstack_type 1 + */ + static inline uint8_t hids_subevent_protocol_mode_get_protocol_mode(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field con_handle from event HIDS_SUBEVENT_BOOT_MOUSE_INPUT_REPORT_ENABLE + * @param event packet + * @return con_handle + * @note: btstack_type 2 + */ + static inline uint16_t hids_subevent_boot_mouse_input_report_enable_get_con_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field enable from event HIDS_SUBEVENT_BOOT_MOUSE_INPUT_REPORT_ENABLE + * @param event packet + * @return enable + * @note: btstack_type 1 + */ + static inline uint8_t hids_subevent_boot_mouse_input_report_enable_get_enable(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field con_handle from event HIDS_SUBEVENT_BOOT_KEYBOARD_INPUT_REPORT_ENABLE + * @param event packet + * @return con_handle + * @note: btstack_type 2 + */ + static inline uint16_t hids_subevent_boot_keyboard_input_report_enable_get_con_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field enable from event HIDS_SUBEVENT_BOOT_KEYBOARD_INPUT_REPORT_ENABLE + * @param event packet + * @return enable + * @note: btstack_type 1 + */ + static inline uint8_t hids_subevent_boot_keyboard_input_report_enable_get_enable(const uint8_t *event) + { + return event[5]; + } + + /** + * @brief Get field con_handle from event HIDS_SUBEVENT_INPUT_REPORT_ENABLE + * @param event packet + * @return con_handle + * @note: btstack_type 2 + */ + static inline uint16_t hids_subevent_input_report_enable_get_con_handle(const uint8_t *event) + { + return little_endian_read_16(event, 3); + } + /** + * @brief Get field enable from event HIDS_SUBEVENT_INPUT_REPORT_ENABLE + * @param event packet + * @return enable + * @note: btstack_type 1 + */ + static inline uint8_t hids_subevent_input_report_enable_get_enable(const uint8_t *event) + { + return event[5]; + } + + + static inline uint8_t hci_event_le_meta_get_phy_update_complete_status(const uint8_t *event) + { + return event[3]; + } + static inline uint8_t hci_event_le_meta_get_phy_update_complete_tx_phy(const uint8_t *event) + { + return event[6]; + } + static inline uint8_t hci_event_le_meta_get_phy_update_complete_rx_phy(const uint8_t *event) + { + return event[7]; + } + + + /* API_END */ + +#if defined __cplusplus +} +#endif + +#endif // __BTSTACK_EVENT_H diff --git a/include_lib/btstack/btstack_lib_bss.ld b/include_lib/btstack/btstack_lib_bss.ld new file mode 100644 index 0000000..b239878 --- /dev/null +++ b/include_lib/btstack/btstack_lib_bss.ld @@ -0,0 +1,17 @@ + + btstack_bss_start = .; + *(.bt_stack_bss) + *(.ble_db_bss) + *(.ble_sm_bss) + *(.ble_att_bss) + *(.ble_gatt_bss) + *(.btstack_pool) + + /*mesh*/ + BTSTACK_LE_HOST_MESH_BSS_START = .; + *(.ble_mesh_bss) + *(.ble_mesh_tinycrypt_bss) + BTSTACK_LE_HOST_MESH_BSS_SIZE = ABSOLUTE(. - BTSTACK_LE_HOST_MESH_BSS_START); + + btstack_bss_end = .; + diff --git a/include_lib/btstack/btstack_lib_data.ld b/include_lib/btstack/btstack_lib_data.ld new file mode 100644 index 0000000..ef6af0a --- /dev/null +++ b/include_lib/btstack/btstack_lib_data.ld @@ -0,0 +1,22 @@ + + btstack_data_start = .; + *(.bt_stack_data) + *(.ble_db_data) + *(.ble_sm_data) + *(.ble_att_data) + *(.ble_gatt_data) + + /*mesh*/ + BTSTACK_LE_HOST_MESH_DATA_START = .; + . = (. +3) & ~ 3; + _net_buf_pool_list = .; + *(._net_buf_pool.static.*) + + *(.ble_mesh_data) + *(.ble_mesh_tinycrypt_data) + BTSTACK_LE_HOST_MESH_DATA_SIZE = ABSOLUTE(. - BTSTACK_LE_HOST_MESH_DATA_START); + + + btstack_data_end = .; + + diff --git a/include_lib/btstack/btstack_lib_text.ld b/include_lib/btstack/btstack_lib_text.ld new file mode 100644 index 0000000..42eae74 --- /dev/null +++ b/include_lib/btstack/btstack_lib_text.ld @@ -0,0 +1,57 @@ + + + btstack_code_start = .; + + . = ALIGN(4); + + a2dp_source_media_codec_begin = .; + KEEP(*(.a2dp_source_media_codec)) + a2dp_source_media_codec_end = .; + a2dp_sink_media_probe_begin = .; + KEEP(*(.a2dp_sink_media_probe)) + a2dp_sink_media_probe_end = .; + + a2dp_sink_media_codec_begin = .; + KEEP(*(.a2dp_sink_media_codec)) + a2dp_sink_media_codec_end = .; + + a2dp_event_handler_begin = .; + KEEP(*(.a2dp_event_handler)) + a2dp_event_handler_end = .; + + sdp_record_item_begin = .; + KEEP(*(.sdp_record_item)) + sdp_record_item_end = .; + + bt_sleep_begin = .; + KEEP(*(.bt_sleep)) + bt_sleep_end = .; + + *(.bt_stack_const) + *(.bt_stack_code) + *(.ble_db_const) + *(.ble_db_code) + *(.ble_sm_const) + *(.ble_sm_code) + *(.ble_att_const) + *(.ble_att_code) + *(.ble_gatt_const) + *(.ble_gatt_code) + + /*mesh*/ + BTSTACK_LE_HOST_MESH_CODE_START = .; + *(.ble_mesh_code) + *(.ble_mesh_tinycrypt_code) + + *(.ble_mesh_const) + *(.ble_mesh_tinycrypt_const) + BTSTACK_LE_HOST_MESH_CODE_SIZE = ABSOLUTE(. - BTSTACK_LE_HOST_MESH_CODE_START); + + btstack_code_end = .; + . = ALIGN(4); + + + BTSTACK_CODE_TOTAL_SIZE = btstack_code_end - btstack_code_start; + + + diff --git a/include_lib/btstack/btstack_task.h b/include_lib/btstack/btstack_task.h new file mode 100644 index 0000000..3f7bd08 --- /dev/null +++ b/include_lib/btstack/btstack_task.h @@ -0,0 +1,9 @@ +#ifndef BTSTACK_TASK_H +#define BTSTACK_TASK_H + +int btstack_init(); +int btstack_exit(); + +void ble_bqb_test_thread_init(void); + +#endif diff --git a/include_lib/btstack/btstack_typedef.h b/include_lib/btstack/btstack_typedef.h new file mode 100644 index 0000000..462e709 --- /dev/null +++ b/include_lib/btstack/btstack_typedef.h @@ -0,0 +1,26 @@ +#ifndef _BTSTACK_TYPEDEF_H_ +#define _BTSTACK_TYPEDEF_H_ + +#include "typedef.h" + +#define BD_ADDR_LEN 6 +typedef uint8_t bd_addr_t[BD_ADDR_LEN]; + +typedef uint16_t hci_con_handle_t; + +typedef int (*sm_stack_packet_handler_t)(uint8_t packet_type, uint8_t *packet, uint16_t size); + +typedef void (*btstack_packet_handler_t)(u8 packet_type, u16 channel, u8 *packet, u16 size); + +typedef void (*ble_cbk_handler_t)(void); + +void reverse_bd_addr(const bd_addr_t src, bd_addr_t dest); + +void reverse_bytes(const u8 *src, u8 *dst, u32 len); + +uint16_t little_endian_read_16(const uint8_t *buffer, int pos); +uint32_t little_endian_read_24(const uint8_t *buffer, int pos); +uint32_t little_endian_read_32(const uint8_t *buffer, int pos); + + +#endif diff --git a/include_lib/btstack/le/att.h b/include_lib/btstack/le/att.h new file mode 100644 index 0000000..9e5efd5 --- /dev/null +++ b/include_lib/btstack/le/att.h @@ -0,0 +1,141 @@ +/********************************************************************************************* + * Filename : att.h + + * Description : + + * Author : minxian + + * Email : liminxian@zh-jieli.com + + * Last modifiled : 2020-07-01 16:33 + + * Copyright:(c)JIELI 2011-2020 @ , All Rights Reserved. +*********************************************************************************************/ +#ifndef _BT_ATT_H_ +#define _BT_ATT_H_ + +#include "typedef.h" +#include "btstack/btstack_typedef.h" + +#if defined __cplusplus +extern "C" { +#endif + +// Minimum/default MTU +#define ATT_DEFAULT_MTU 23 + +#define ATT_EVENT_MTU_EXCHANGE_COMPLETE 0xB5 +#define ATT_EVENT_HANDLE_VALUE_INDICATION_COMPLETE 0xB6 +#define ATT_EVENT_CAN_SEND_NOW 0xB7 + +#define ATT_TRANSACTION_MODE_NONE 0x0 +#define ATT_TRANSACTION_MODE_ACTIVE 0x1 +#define ATT_TRANSACTION_MODE_EXECUTE 0x2 +#define ATT_TRANSACTION_MODE_CANCEL 0x3 +#define ATT_TRANSACTION_MODE_VALIDATE 0x4 + +#define ATT_PROPERTY_BROADCAST 0x01 +#define ATT_PROPERTY_READ 0x02 +#define ATT_PROPERTY_WRITE_WITHOUT_RESPONSE 0x04 +#define ATT_PROPERTY_WRITE 0x08 +#define ATT_PROPERTY_NOTIFY 0x10 +#define ATT_PROPERTY_INDICATE 0x20 + + + typedef enum { + ATT_OP_AUTO_READ_CCC = 0, + ATT_OP_NOTIFY = 1, + ATT_OP_INDICATE = 2, + ATT_OP_READ, + ATT_OP_READ_LONG, + ATT_OP_WRITE, + ATT_OP_WRITE_WITHOUT_RESPOND, + //add here + + ATT_OP_CMD_MAX = 15, + } att_op_type_e; + +//------ + typedef struct { + uint16_t start_group_handle; + uint16_t end_group_handle; + uint16_t uuid16; + uint8_t uuid128[16]; + } service_report_t; //==le_service_t + + typedef struct { + uint16_t start_handle; + uint16_t value_handle; + uint16_t end_handle; + uint16_t properties; + uint16_t uuid16; + uint8_t uuid128[16]; + } charact_report_t; //==le_characteristic_t + + typedef struct { + u16 packet_type; + u16 value_handle; + u16 value_offset; + u16 blob_length; + u8 *blob; + u16 conn_handle; + } att_data_report_t; + + + typedef struct { + service_report_t services; + charact_report_t characteristic; + u16 service_index; + u16 characteristic_index; + } search_result_t; + + typedef struct { + u16 handle; + u16 uuid16; + u8 uuid128[16]; + } charact_descriptor_t; + + + void att_ccc_config_init(void); + + void att_set_ccc_config(uint16_t handle, uint16_t cfg); + + uint16_t att_get_ccc_config(uint16_t handle); + + void att_server_set_exchange_mtu(u16 con_handle); + + void att_set_db(uint8_t const *db);//change profile_data + +// ATT Client Read Callback for Dynamic Data +// - if buffer == NULL, don't copy data, just return size of value +// - if buffer != NULL, copy data and return number bytes copied +// @param con_handle of hci le connection +// @param attribute_handle to be read +// @param offset defines start of attribute value +// @param buffer +// @param buffer_size + typedef uint16_t (*att_read_callback_t)(uint16_t con_handle, uint16_t attribute_handle, uint16_t offset, uint8_t *buffer, uint16_t buffer_size); + +// ATT Client Write Callback for Dynamic Data +// @param con_handle of hci le connection +// @param attribute_handle to be written +// @param transaction - ATT_TRANSACTION_MODE_NONE for regular writes, ATT_TRANSACTION_MODE_ACTIVE for prepared writes and ATT_TRANSACTION_MODE_EXECUTE +// @param offset into the value - used for queued writes and long attributes +// @param buffer +// @param buffer_size +// @param signature used for signed write commmands +// @returns 0 if write was ok, ATT_ERROR_PREPARE_QUEUE_FULL if no space in queue, ATT_ERROR_INVALID_OFFSET if offset is larger than max buffer + typedef int (*att_write_callback_t)(uint16_t con_handle, uint16_t attribute_handle, uint16_t transaction_mode, uint16_t offset, uint8_t *buffer, uint16_t buffer_size); + + void ble_att_server_setup_init(const u8 *profile_db, att_read_callback_t read_cbk, att_write_callback_t write_cbk); + + void att_server_request_can_send_now_event(hci_con_handle_t con_handle); + + int att_server_notify(hci_con_handle_t con_handle, uint16_t attribute_handle, uint8_t *value, uint16_t value_len); + + int att_server_indicate(hci_con_handle_t con_handle, uint16_t attribute_handle, uint8_t *value, uint16_t value_len); + + extern void att_server_init(uint8_t const *db, att_read_callback_t read_callback, att_write_callback_t write_callback); + extern void att_server_register_packet_handler(btstack_packet_handler_t handler); + +#endif diff --git a/include_lib/btstack/le/ble_api.h b/include_lib/btstack/le/ble_api.h new file mode 100644 index 0000000..1d0f25b --- /dev/null +++ b/include_lib/btstack/le/ble_api.h @@ -0,0 +1,1079 @@ +/********************************************************************************************* + * Filename : ble_api.h + + * Description : + + * Author : mx + + * Email : lmx@zh-jieli.com + + * Last modifiled : 2020-07-01 16:36 + + * Copyright:(c)JIELI 2011-2020 @ , All Rights Reserved. +*********************************************************************************************/ +#ifndef __BLE_API_H__ +#define __BLE_API_H__ + + +#include "typedef.h" +#include "btstack/btstack_typedef.h" + + +///***注意:该文件的枚举与库编译密切相关,主要是给用户提供调用所用。用户不能自己在中间添加值。*/ +////----user (command) codes----//// + +/** + * @brief hci connection handle type + */ + +typedef enum { + /* + */ + BLE_CMD_ADV_ENABLE = 1, + BLE_CMD_ADV_PARAM, + BLE_CMD_ADV_DATA, + BLE_CMD_RSP_DATA, + BLE_CMD_DISCONNECT, + BLE_CMD_REGIEST_THREAD, + BLE_CMD_ATT_SEND_INIT, + BLE_CMD_ATT_MTU_SIZE, + BLE_CMD_ATT_VAILD_LEN, + BLE_CMD_ATT_SEND_DATA, + BLE_CMD_REQ_CONN_PARAM_UPDATE, + + BLE_CMD_SCAN_ENABLE, + BLE_CMD_SCAN_PARAM, + BLE_CMD_STACK_EXIT, + BLE_CMD_CREATE_CONN, + BLE_CMD_CREATE_CONN_CANCEL, + + BLE_CMD_ADV_PARAM_EXT, + BLE_CMD_SEND_TEST_KEY_NUM, + BLE_CMD_LATENCY_HOLD_CNT, + BLE_CMD_SET_DATA_LENGTH, + BLE_CMD_SET_HCI_CFG, + BLE_CMD_SCAN_ENABLE2, + BLE_CMD_ATT_SERVER_REQ_RESUME, + + //MULTI API,多机接口 + BLE_CMD_MULTI_ATT_SEND_INIT, + BLE_CMD_MULTI_ATT_SET_CONN_HANDLE, + BLE_CMD_MULTI_ATT_SEND_DATA, + BLE_CMD_MULTI_ATT_MTU_SIZE, + BLE_CMD_MULTI_ATT_VAILD_LEN, + + //sm + BLE_CMD_SM_REQ_RESUME, + + //< ble5 + BLE_CMD_EXT_ADV_PARAM = 0x40, + BLE_CMD_EXT_ADV_DATA, + BLE_CMD_EXT_RSP_DATA, + BLE_CMD_EXT_ADV_ENABLE, + BLE_CMD_SET_PHY, + BLE_CMD_EXT_SCAN_PARAM, + BLE_CMD_EXT_SCAN_ENABLE, + BLE_CMD_EXT_CREATE_CONN, + BLE_CMD_PERIODIC_ADV_PARAM, + BLE_CMD_PERIODIC_ADV_DATA, + BLE_CMD_PERIODIC_ADV_ENABLE, + BLE_CMD_PERIODIC_ADV_CREAT_SYNC, + + //client + BLE_CMD_SEARCH_PROFILE = 0x80, + BLE_CMD_WRITE_CCC, + BLE_CMD_ONNN_PARAM_UPDATA, +} ble_cmd_type_e; + +typedef enum { + BLE_CMD_RET_SUCESS = 0, //执行成功 + BLE_CMD_RET_BUSY = -100, //命令处理忙 + BLE_CMD_PARAM_OVERFLOW, //传数溢出 + BLE_CMD_OPT_FAIL, //操作失败 + BLE_BUFFER_FULL, //缓存满了 + BLE_BUFFER_ERROR, //缓存出错 + BLE_CMD_PARAM_ERROR, //传参出错 + BLE_CMD_STACK_NOT_RUN, //协议栈没有运行 + BLE_CMD_CCC_FAIL, //没有使能通知,导致NOTIFY或INDICATE发送失败, +} ble_cmd_ret_e; + +//-------------------------------------------- +ble_cmd_ret_e ble_user_cmd_prepare(ble_cmd_type_e cmd, int argc, ...); + +struct conn_update_param_t { + u16 interval_min; //(unit:0.625ms) + u16 interval_max; //(unit:0.625ms) + u16 latency; //(unit: interval) + u16 timeout; //(unit:10ms) +}; + +typedef enum { + PFL_SERVER_UUID16 = 1, //指定16bit UUID搜索方式 + PFL_SERVER_UUID128, //指定128bit UUID搜索方式 + PFL_SERVER_ALL, //搜索所有的UUID +} search_profile_type_e; + + +//------ +struct create_conn_param_t { + u16 conn_interval; //0--public address,1--random address + u16 conn_latency; //(unit: interval) + u16 supervision_timeout; //(unit:10ms) + u8 peer_address_type; //0--public address,1--random address + u8 peer_address[6]; +} _GNU_PACKED_; + +typedef struct { + u8 event_type; //0--ADV_IND,1--ADV_DIRECT_IND,2--ADV_SCAN_IND,3--ADV_NONCONN_IND,4--SCAN_RSP + u8 address_type; //0--public address,1--random address + u8 address[6]; //peer_address + s8 rssi; //range:-127 ~128 dbm + u8 length; //广播包长度 + u8 data[0]; //广播包内容 +} adv_report_t; + +typedef struct { + //base info + u8 type; //< See SM_... + u8 size; + u16 con_handle; //connection 's handle, >0 + u8 addr_type; //0--public address,1--random address + u8 address[6]; + //extend info + u8 data[4]; +} sm_just_event_t; + +//BLE_CMD_SET_HCI_CFG +typedef enum { + HCI_CFG_OWN_ADDRESS_TYPE = 0, // + HCI_CFG_ADV_FILTER_POLICY, // + HCI_CFG_SCAN_FILTER_POLICY, // + HCI_CFG_INITIATOR_FILTER_POLICY, // + //add here +} hci_cfg_par_e; + +typedef enum { + REMOTE_TYPE_UNKNOWN = 0,//未查询or查询对方未响应 + REMOTE_TYPE_ANDROID, + REMOTE_TYPE_IOS, +} remote_type_e; + +//----------------------------------------------------------------------------------------------------------------- +//----------------------------------------------------------------------------------------------------------------- +//----------------------------------------------------------------------------------------------------------------- +//----------------------------------------------------------------------------------------------------------------- + +/********************************************************************************** + @function gatt client 角色 初始化 + @return + *********************************************************************************/ +void gatt_client_init(void); + +/********************************************************************************** + @function 注册gatt client 角色,事件回调处理 + @param [in] handler 事件处理函数 + @return + *********************************************************************************/ +void gatt_client_register_packet_handler(btstack_packet_handler_t handler); + +/********************************************************************************** + @function 初始化配对表 + @param [in] + @return + note:上电初始化一次 + *********************************************************************************/ +void le_device_db_init(void); + +/********************************************************************************** + @function 注册passkey 输入回调 + @param [in] + @return + *********************************************************************************/ +void reset_PK_cb_register(void (*reset_pk)(u32 *)); + +/********************************************************************************** + @function 设置ble的蓝牙public地址 + @param [in] addr + @return 0--success ,非0--fail + note:可以结合接口 ble_op_set_own_address_type 配置选择地址类型 + note:修改地址必须在ble非工作状态下才能生效(没有scan,没有adv,没connected) + *********************************************************************************/ +int le_controller_set_mac(void *addr); + +/********************************************************************************** + @function 获取ble的蓝牙public地址 + @param [out] addr + @return 0--success ,非0--fail + *********************************************************************************/ +int le_controller_get_mac(void *addr); + +/********************************************************************************** + @function 初始化ble的蓝牙random地址 + @param [in] addr + @return 0--success ,非0--fail + note:可以结合接口 ble_op_set_own_address_type 配置选择地址类型 + note:修改地址必须在ble非工作状态下才能生效(没有scan,没有adv,没connected) + *********************************************************************************/ +int le_controller_set_random_mac(void *addr); + +/********************************************************************************** + @function 获取ble的蓝牙random地址 + @param [out] addr + @return 0--success ,非0--fail + *********************************************************************************/ +int le_controller_get_random_mac(void *addr); + +/********************************************************************************** + @function 配置协议栈 GATT 角色处理,default server + @param [in] role 0--server, or 1--client,or 2--server+client + @return + *********************************************************************************/ +void ble_stack_gatt_role(u8 role); + +/********************************************************************************** + @function client 连接后初始化 + @param [in] handle 连接 con_handle,range:>0 + @param [in] buffer 配置缓存地址 + @param [in] buffer_size 缓存大小 + @return + *********************************************************************************/ +void user_client_init(u16 handle, u8 *buffer, u16 buffer_size); + +/********************************************************************************** + @function 获取链路对方的信号强度 + @param [in] con_handle 连接handle, range:>0 + @return rssi 强度, range:-127 ~128 dbm + *********************************************************************************/ +s8 ble_vendor_get_peer_rssi(u16 conn_handle); + +/********************************************************************************** + @function 使能周期interval事件上报 + @param [in] con_handle 连接handle, range:>0 + @param [in] enable 1 or 0 + @return true or false + *********************************************************************************/ +bool ble_vendor_interval_event_enable(u16 conn_handle, int enable); + + +/********************************************************************************** + @function 配置协议栈ATT默认的MTU 大小 + @param [in] mtu_size, range: 23~517 + @return 配置后的mtu_size值 + *********************************************************************************/ +u16 ble_vendor_set_default_att_mtu(u16 mtu_size); + +/********************************************************************************** + @function 设置 搜索结束 + @param [in] + @return + *********************************************************************************/ +void user_client_set_search_complete(void); + +/********************************************************************************** + @function 提供生成 ble对应的类型地址 + @param [out] address + @param [in] type + 1--STATIC_DEVICE_ADDR + 2--NON_RESOLVABLE_PRIVATE_ADDR + 3--RESOLVABLE_PRIVATE_ADDR + @return + *********************************************************************************/ +void ble_vendor_address_generate(u8 *address, u8 type); + +/********************************************************************************** + @function 根据提供的edr地址生成唯一对应ble地址 + @param [out] ble_address + @param [in] edr_address + @return + *********************************************************************************/ +void lib_make_ble_address(u8 *ble_address, u8 *edr_address); + +/********************************************************************************** + @function 配置设备的地址类型,默认为 0--public address + @param [in] address_type Range: 0x00 to 0x03 + @return see ble_cmd_ret_e + !!!注意:设置的时候必须在 设置广播参数 或者扫描参数 或者创建连接参数 前配置好 + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_own_address_type(u8 address_type) */ +#define ble_op_set_own_address_type(address_type) \ + ble_user_cmd_prepare(BLE_CMD_SET_HCI_CFG, 2,HCI_CFG_OWN_ADDRESS_TYPE,(int)address_type) + +/********************************************************************************** + @function 开关BLE广播, !!!注意:开广播前必现先配置好广播的参数 + @param [in] enable 0 or 1 + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_adv_enable(int enable) */ +#define ble_op_adv_enable(enable) \ + ble_user_cmd_prepare(BLE_CMD_ADV_ENABLE, 1, (int)enable) + +/********************************************************************************** + @function 配置adv filter policy, default 0 + @param [in] type Range: 0x00 to 0x03 + @return see ble_cmd_ret_e + !!!注意:设置的时候必须在 设置广播参数 前配置好 + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_adv_filter_policy(u8 type) */ +#define ble_op_set_adv_filter_policy(type) \ + ble_user_cmd_prepare(BLE_CMD_SET_HCI_CFG, 2,HCI_CFG_ADV_FILTER_POLICY,type) + +/********************************************************************************** + + @function 配置广播参数,!!!注意:设置的时候必现在广播关闭的状态下 + @param [in] adv_interval 广播周期,Range: 0x0020 to 0x4000 (unit: 0.625ms) + @param [in] adv_type 广播类型,Range: 0x00 to 0x04 + @param [in] adv_channel 广播类型通道,range:Range: 0x01 to 0x07 + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_adv_param(u16 adv_interval,u8 adv_type) */ +#define ble_op_set_adv_param(adv_interval,adv_type,adv_channel) \ + ble_user_cmd_prepare(BLE_CMD_ADV_PARAM, 3, (int)adv_interval, (int)adv_type, (int)adv_channel) + + +/********************************************************************************** + @function 配置广播参数,!!!注意:设置的时候必现在广播关闭的状态下 + @param [in] adv_interval 广播周期,Range: 0x0020 to 0x4000 (unit: 0.625ms) + @param [in] adv_type 广播类型,Range: 0x00 to 0x04 + @param [in] adv_channel 广播类型通道,range:Range: 0x01 to 0x07 + @param [in] peer_info (全局变量地址),定向广播时,填入对方的地址信息, + peer_info[0]--地址类型range 0~1,peer_info[1~7]--地址内容 + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_adv_param_ext(u16 adv_interval,u8 adv_type,u8 adv_channel,const u8 *peer_info) */ +#define ble_op_set_adv_param_ext(adv_interval,adv_type,adv_channel,peer_info) \ + ble_user_cmd_prepare(BLE_CMD_ADV_PARAM_EXT, 4, (int)adv_interval, (int)adv_type, (int)adv_channel, (void*)peer_info) + + +/********************************************************************************** + + @function 配置广播 Advertising Data内容,!!!注意:设置的时候必现在广播关闭的状态下 + @param [in] adv_len adv 数据包长度,Range: 0x00 to 0x1f + @param [in] adv_data (全局变量地址),adv数据包地址 + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_adv_data(u8 adv_len,const *u8 adv_data) */ +#define ble_op_set_adv_data(adv_len,adv_data) \ + ble_user_cmd_prepare(BLE_CMD_ADV_DATA, 2, (int)adv_len, (void*)adv_data) + + +/********************************************************************************** + + @function 配置广播 Scan Response Data内容,!!!注意:设置的时候必现在广播关闭的状态下 + @param [in] rsp_len rsp 数据包长度,Range: 0x00 to 0x1f + @param [in] rsp_data (全局变量地址),rsp数据包地址 + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_rsp_data(u8 rsp_len,const *u8 rsp_data) */ +#define ble_op_set_rsp_data(rsp_len,rsp_data) \ + ble_user_cmd_prepare(BLE_CMD_RSP_DATA, 2, (int)rsp_len, (void*)rsp_data) + + +/********************************************************************************** + + @function 请求断开 ble 连接 + @param [in] con_handle 连接handle,range:>0 + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_disconnect(u16 con_handle) */ +#define ble_op_disconnect(con_handle) \ + ble_user_cmd_prepare(BLE_CMD_DISCONNECT, 1, (int)con_handle) + +/********************************************************************************** + + @function 配置ATT发送模块RAM大小 + @param [in] con_handle 连接 con_handle,range:>0 + @param [in] att_ram_addr 传入ATT发送模块ram地址,地址按4字节对齐 + @param [in] att_ram_size 传入ATT发送模块ram大小 + @param [in] att_payload_size 发送ATT包payload的最大长度 <= MTU,range:20 to MTU size + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_att_send_init(u16 con_handle,u8 *att_ram_addr,int att_ram_size,int att_payload_size) */ +#define ble_op_att_send_init(con_handle,att_ram_addr,att_ram_size,att_payload_size) \ + ble_user_cmd_prepare(BLE_CMD_ATT_SEND_INIT, 4, con_handle,att_ram_addr,att_ram_size,att_payload_size) + + +/********************************************************************************** + + @function MULTI API: 配置ATT发送模块初始化 + @param [in] att_ram_addr 传入ATT发送模块ram地址,地址按4字节对齐 + @param [in] att_ram_size 传入ATT发送模块ram大小 + @param [in] att_payload_size 发送ATT包payload的最大长度 <= MTU,range:20 to MTU size + @return see ble_cmd_ret_e + note:多机处理,只需要初始化一次就可以 + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_multi_att_send_init(u8 *att_ram_addr,int att_ram_size,int att_payload_size) */ +#define ble_op_multi_att_send_init(att_ram_addr,att_ram_size,att_payload_size) \ + ble_user_cmd_prepare(BLE_CMD_MULTI_ATT_SEND_INIT, 3, att_ram_addr,att_ram_size,att_payload_size) + + +/********************************************************************************** + + @function MULTI API: 配置ATT 连接handle + @param [in] con_handle 连接 con_handle,range:>0 + @param [in] handle_index range:0~7 //多连接的hanlde id + @param [in] role range:0-slave,1-master + @return see ble_cmd_ret_e + note:多机处理 + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_multi_att_send_conn_handle(u16 con_handle,int handle_index,int role) */ +#define ble_op_multi_att_send_conn_handle(con_handle,handle_index,role) \ + ble_user_cmd_prepare(BLE_CMD_MULTI_ATT_SET_CONN_HANDLE, 3, con_handle,handle_index,role) + +/********************************************************************************** + + @function 根据对方的接收MTU大小,配置本地可发送的MTU的大小 + @param [in]mtu 对方mtu payload的大小 + @param [in] + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_att_set_send_mtu(u16 mtu) */ +#define ble_op_att_set_send_mtu(mtu) \ + ble_user_cmd_prepare(BLE_CMD_ATT_MTU_SIZE, 1, mtu); + + +/********************************************************************************** + + @function MULTI API: 根据对方的接收MTU大小,配置本地可发送的MTU的大小 + @param [in] con_handle 连接 con_handle,range:>0 + @param [in] mtu 对方mtu payload的大小 + @param [in] + @param [in] + @param [in] + @return see ble_cmd_ret_e + note:多机处理 + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_multi_att_set_send_mtu(u16 con_handle,u16 mtu) */ +#define ble_op_multi_att_set_send_mtu(con_handle,mtu) \ + ble_user_cmd_prepare(BLE_CMD_MULTI_ATT_MTU_SIZE, 2, con_handle,mtu); + + +/********************************************************************************** + + @function 获取ATT发送模块,cbuffer 可写入数据的长度 + @param [out] remain_size_ptr 输出可写入长度值 + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_att_get_remain(int *remain_size_ptr) */ +#define ble_op_att_get_remain(remain_size_ptr) \ + ble_user_cmd_prepare(BLE_CMD_ATT_VAILD_LEN, 1, remain_size_ptr) + +/********************************************************************************** + + @function MULTI API: 获取ATT发送模块,cbuffer 可写入数据的长度 + @param [in] con_handle 连接 con_handle,range:>0 + @param [out] remain_size_ptr 输出可写入长度值 + @return see ble_cmd_ret_e + note:多机处理 + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_multi_att_get_remain(u16 con_handle,int *remain_size_ptr) */ +#define ble_op_multi_att_get_remain(con_handle,remain_size_ptr) \ + ble_user_cmd_prepare(BLE_CMD_MULTI_ATT_VAILD_LEN, 2,con_handle, remain_size_ptr) + +/********************************************************************************** + + @function ATT操作handle发送数据 + @param [in] att_handle att 操handle + @param [in] data 数据地址 + @param [in] len 数据长度 <= cbuffer 可写入的长度 + @param [in] att_op_type see att_op_type_e (att.h) + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_att_send_data(u16 att_handle,u8 *data,u16 len, att_op_type_e att_op_type) */ +#define ble_op_att_send_data(att_handle,data,len,att_op_type) \ + ble_user_cmd_prepare(BLE_CMD_ATT_SEND_DATA, 4, att_handle, data, len, att_op_type) + + +/********************************************************************************** + + @function MULTI API: ATT操作handle发送数据 + @param [in] con_handle 连接 con_handle,range:>0 + @param [in] att_handle att 操handle + @param [in] data 数据地址 + @param [in] len 数据长度 <= cbuffer 可写入的长度 + @param [in] att_op_type see att_op_type_e (att.h) + @return see ble_cmd_ret_e + note:多机处理 + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_multi_att_send_data(u16 con_handle,u16 att_handle,u8 *data,u16 len, att_op_type_e att_op_type) */ +#define ble_op_multi_att_send_data(con_handle,att_handle,data,len,att_op_type) \ + ble_user_cmd_prepare(BLE_CMD_MULTI_ATT_SEND_DATA, 5, con_handle,att_handle, data, len, att_op_type) + + + +/********************************************************************************** + + @function 请求更新连接参数 + @param [in] con_handle 连接 con_handle,range:>0 + @param [in] con_param (全局变量地址),连接参数 + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_conn_param_request(u16 con_handle,const struct conn_update_param_t *con_param) */ +#define ble_op_conn_param_request(con_handle,con_param) \ + ble_user_cmd_prepare(BLE_CMD_REQ_CONN_PARAM_UPDATE, 2, con_handle, (void*)con_param) + +/********************************************************************************** + + @function 发起data length 交换 + @param [in] tx_octets + @param [in] tx_time + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_data_length(u16 con_handle,u16 tx_octets,u16 tx_time) */ +#define ble_op_set_data_length(con_handle,tx_octets,tx_time) \ + ble_user_cmd_prepare(BLE_CMD_SET_DATA_LENGTH, 3, con_handle, tx_octets, tx_time) + + +/********************************************************************************** + + @function ble5.0 配置 广播参数 + @param [in] param 广播参数 + @param [in] param_len 参数长度 + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_ext_adv_param(u8 *param,u16 param_len) */ +#define ble_op_set_ext_adv_param(param,param_len) \ + ble_user_cmd_prepare(BLE_CMD_EXT_ADV_PARAM, 2, param, param_len) + +/********************************************************************************** + + @function ble5.0 配置 adv 数据包 + @param [in]data 数据包内容 + @param [in]data_len 数据包长度 + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_ext_adv_data(u8 *data,u16 data_len) */ +#define ble_op_set_ext_adv_data(data,data_len) \ + ble_user_cmd_prepare(BLE_CMD_EXT_ADV_DATA, 2, data, data_len) + + +/********************************************************************************** + + @function ble5.0 配置 respond 数据包 + @param [in]data 数据包内容 + @param [in]data_len 数据包长度 + @param [in] + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_ext_rsp_data(u8 *data,u16 data_len) */ +#define ble_op_set_ext_rsp_data(data,data_len) \ + ble_user_cmd_prepare(BLE_CMD_EXT_RSP_DATA, 2, data, data_len) + + + +/********************************************************************************** + + @function ble5.0 开关广播 + @param [in] cmd 命令信息 + @param [in] cmd_len 命令长度 + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_ext_adv_enable(u8 *cmd,u16 cmd_le) */ +#define ble_op_set_ext_adv_enable(cmd,len) \ + ble_user_cmd_prepare(BLE_CMD_EXT_ADV_ENABLE, 2, cmd, cmd_len) + + +/********************************************************************************** + + @function ble5.0 配置phy + @param [in]con_handle 连接 con_handle,range:>0 + @param [in]all_phys + @param [in]tx_phy + @param [in]rx_phy + @param [in]phy_options + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_ext_phy(u16 con_handle,u16 all_phys,u16 tx_phy,u16 rx_phy,u16 phy_options) */ +#define ble_op_set_ext_phy(con_handle,all_phys,tx_phy,rx_phy,phy_options) \ + ble_user_cmd_prepare(BLE_CMD_SET_PHY, 5, con_handle, all_phys, tx_phy, rx_phy, phy_options) + + +/********************************************************************************** + + @function ble5.0 配置 主机scan 参数 + @param [in]param 参数内容 + @param [in]param_len 参数长度 + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_ext_scan_param(u8 *param,u16 param_le) */ +#define ble_op_set_ext_scan_param(param,param_len) \ + ble_user_cmd_prepare(BLE_CMD_EXT_SCAN_PARAM, 2, param, param_len) + + +/********************************************************************************** + + @function ble5.0 配置 主机scan 开关 + @param [in] cmd 命令信息 + @param [in] cmd_len 命令长度 + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_ext_scan_enable(u8 *cmd,u16 cmd_le) */ +#define ble_op_ext_scan_enable(cmd,cmd_len) \ + ble_user_cmd_prepare(BLE_CMD_EXT_SCAN_ENABLE, 2, cmd, cmd_len) + + +/********************************************************************************** + + @function ble5.0 配置 主机创建连接监听 + @param [in]conn_param 连接参数信息 + @param [in]param_len 参数长度 + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_ext_create_conn(u8 *conn_param,u16 param_len_len) */ +#define ble_op_ext_create_conn(conn_param,param_len) \ + ble_user_cmd_prepare(BLE_CMD_EXT_CREATE_CONN, 2, conn_param, param_len) + + +/********************************************************************************** + + @function 忽略进入latency 的次数。!!!注意:让设备不进入latency模式,加快响应速度,但会耗电 + @param [in] con_handle 连接 con_handle,range:>0 + @param [in] skip_interval 忽略的interval的次数 + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_latency_skip(u16 con_handle,u16 skip_interval) */ +#define ble_op_latency_skip(con_handle,skip_interval) \ + ble_user_cmd_prepare(BLE_CMD_LATENCY_HOLD_CNT, 2, con_handle, skip_interval) + +/********************************************************************************** + + @function 测试盒识别按键测试 + @param [in] con_handle 连接 con_handle,range:>0 + @param [in] key_num 按键 + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_test_key_num(u16 con_handle,u8 key_num) */ +#define ble_op_test_key_num(con_handle,key_num) \ + ble_user_cmd_prepare(BLE_CMD_SEND_TEST_KEY_NUM, 2, con_handle, key_num) + +/********************************************************************************** + + @function 退出ble协议栈 + @param [in] control : 0--退出stack(default),1--退出stack + controller + @param [in] + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_stack_exit(u8 control) */ +#define ble_op_stack_exit(control) \ + ble_user_cmd_prepare(BLE_CMD_STACK_EXIT, 1, control) + +/********************************************************************************** + + @function 挂载协议栈线程调用 + @param [in] thread_callback 回调函数 + @param [in] + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_regist_thread_call(void (*thread_callback)(void)) */ +#define ble_op_regist_thread_call(thread_callback) \ + ble_user_cmd_prepare(BLE_CMD_REGIEST_THREAD, 1, thread_callback) + +/********************************************************************************** + + @function + @param [in] + @param [in] + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ + + + +/********************************************************************************** + + @function 开关BLE搜索扫描,!!!注意:开搜索前必现先配置好搜索的参数 + @param [in] enable 0 or 1 + @param [in] + @param [in] + @param [in] + @return see ble_cmd_ret_e + note:filter_duplicate 默认 为 1 + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_scan_enable(u8 enable) */ +#define ble_op_scan_enable(enable) \ + ble_user_cmd_prepare(BLE_CMD_SCAN_ENABLE, 1, enable) + +/********************************************************************************** + + @function 开关BLE搜索扫描,!!!注意:开搜索前必现先配置好搜索的参数 + @param [in] enable 0 or 1 + @param [in] filter_duplicate 0 or 1 + @param [in] + @param [in] + @return see ble_cmd_ret_e + note:filter_duplicate 默认 为 1 + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_scan_enable2(u8 enable,u8 filter_duplicate) */ +#define ble_op_scan_enable2(enable,filter_duplicate) \ + ble_user_cmd_prepare(BLE_CMD_SCAN_ENABLE2, 2, enable,filter_duplicate) + +/********************************************************************************** + @function 配置scan filter policy,default 0 + @param [in] type Range: 0x00 to 0x03 + @return see ble_cmd_ret_e + !!!注意:设置的时候必须在 设置扫描参数 ble_op_set_scan_param 前配置好 + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_scan_filter_policy(u8 type) */ +#define ble_op_set_scan_filter_policy(type) \ + ble_user_cmd_prepare(BLE_CMD_SET_HCI_CFG, 2,HCI_CFG_SCAN_FILTER_POLICY,type) + +/********************************************************************************** + + @function 配置搜索参数 + @param [in] scan_type 搜索类型 Range: 0x00 to 0x01 (unit: 0.625ms) + @param [in] scan_interval 搜索周期 Range: 0x0004 to 0x4000 (unit: 0.625ms) >= scan_window + @param [in] scan_window 搜索窗口 Range: 0x0004 to 0x4000 (unit: 0.625ms), <= scan_interval + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_scan_param(u8 scan_type,u16 scan_interval,u16 scan_window) */ +#define ble_op_set_scan_param(scan_type,scan_interval,scan_window) \ + ble_user_cmd_prepare(BLE_CMD_SCAN_PARAM, 3, scan_type, scan_interval, scan_window) + +/********************************************************************************** + @function 配置creat filter policy,default 0 + @param [in] type Range: 0x00 to 0x03 + @return see ble_cmd_ret_e + !!!注意:设置的时候必须在 设置创建连接参数 ble_op_create_connection 前配置好 + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_set_create_filter_policy(u8 type) */ +#define ble_op_set_create_filter_policy(type) \ + ble_user_cmd_prepare(BLE_CMD_SET_HCI_CFG, 2,HCI_CFG_INITIATOR_FILTER_POLICY,type) + +/********************************************************************************** + + @function 建立BLE创建连接监听 + @param [in] create_conn_param 连接参数 + @param [in] + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_create_connection(struct create_conn_param_t * create_conn_param) */ +#define ble_op_create_connection(create_conn_param) \ + ble_user_cmd_prepare(BLE_CMD_CREATE_CONN, 1, create_conn_param) + +/********************************************************************************** + + @function 取消BLE连接监听 + @param [in] + @param [in] + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_create_connection_cancel(void) */ +#define ble_op_create_connection_cancel() \ + ble_user_cmd_prepare(BLE_CMD_CREATE_CONN_CANCEL,0) + +/********************************************************************************** + + @function ble 主机搜索所有服务 + @param [in] + @param [in] + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_search_profile_all(void) */ +#define ble_op_search_profile_all() \ + ble_user_cmd_prepare(BLE_CMD_SEARCH_PROFILE, 2, PFL_SERVER_ALL, 0) + +/********************************************************************************** + + @function ble 主机搜索指定UUID16服务 + @param [in] uuid16 uuid + @param [in] + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_search_profile_uuid16(u16 uuid16) */ +#define ble_op_search_profile_uuid16(uuid16) \ + ble_user_cmd_prepare(BLE_CMD_SEARCH_PROFILE, 2, PFL_SERVER_UUID16, uuid16) + +/********************************************************************************** + + @function ble 主机搜索指定UUID128服务 + @param [in] uuid16 uuid128 + @param [in] + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_search_profile_uuid128(const u8 *uuid128_pt) */ +#define ble_op_search_profile_uuid128(uuid128_pt) \ + ble_user_cmd_prepare(BLE_CMD_SEARCH_PROFILE, 2, PFL_SERVER_UUID128, uuid128_pt) + +/********************************************************************************** + + @function ble 主机 更新连接参数 + @param [in] con_handle 连接 con_handle,range:>0 + @param [in] con_param (全局变量地址),连接参数 + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ +/* ble_cmd_ret_e ble_op_conn_param_update(u16 con_handle,struct conn_update_param_t *con_param) */ +#define ble_op_conn_param_update(con_handle,con_param) \ + ble_user_cmd_prepare(BLE_CMD_ONNN_PARAM_UPDATA, 2, con_handle, con_param) + + +/********************************************************************************** + + @function + @param [in] + @param [in] + @param [in] + @param [in] + @return see ble_cmd_ret_e + *********************************************************************************/ + + +/********************************************************************************** + + @function ble master&slave 配置配对表(可以不设置,使用sdk默认值) + @param [in] pair_devices_count 记录配对设备 range: 0~10,默认10 + 若配置为0:则不使用配对表记录管理,不限制配对个数 + @param [in] is_allow_cover 是否允许循环覆盖记录 1 or 0,默认1 + @param [in] + @param [in] + @return true or false + note: 上电调用配置,若配置的个数跟之前不一样,默认清所有的配对表数据 + note: VM 掉电记录保护 + note: 主从机共用一个配对表 + *********************************************************************************/ +void ble_list_config_reset(u8 pair_devices_count, u8 is_allow_cover); + + +/********************************************************************************** + + @function 配置是否接受新设备请求配对,记录在VM,(可以不设置,使用sdk默认值) + @param [in] enable 允许新设备配对开关, 1 or 0,默认1 + @param [in] + @param [in] + @param [in] + @return true or false + note:VM 掉电记录保护 + note:是否覆盖是由接口 ble_list_config_reset 的参数 is_allow_cover 决定 + *********************************************************************************/ +bool ble_list_pair_accept(u8 enable); + + +/********************************************************************************** + + @function 获取配对表已有配对个数 + @param [in] + @param [in] + @return 0~10 +note: + *********************************************************************************/ +u16 ble_list_get_count(void); + + +/********************************************************************************** + @function 绑定已配对的指定设备,清除其他配对设备 + @param [in] conn_addr 对方地址6bytes + @param [in] conn_addr_type 对方地址类型range: 0~1 + @param [in] + @param [in] + @return true or false + note:VM 掉电记录保护 + *********************************************************************************/ +bool ble_list_bonding_remote(u8 *conn_addr, u8 conn_addr_type); + + +/********************************************************************************** + + @function ble 清空配对表 + @param [in] + @param [in] + @return true or false + note: + *********************************************************************************/ +bool ble_list_clear_all(void); + +/********************************************************************************** + + @function ble 检测连接地址是否在已配对表中 + @param [in] conn_addr 对方地址6bytes + @param [in] conn_addr_type 对方地址类型range: 0~1 + @param [in] + @param [in] + @return true or false + note: + *********************************************************************************/ +bool ble_list_check_addr_is_exist(u8 *conn_addr, u8 conn_addr_type); + + +/********************************************************************************** + + @function ble 把设备从配对表中删除 + @param [in] conn_addr 对方连接地址6bytes + @param [in] conn_addr_type 对方连接地址类型range: 0~1 + @param [in] + @param [in] + @return true or false + note: + *********************************************************************************/ +bool ble_list_delete_device(u8 *conn_addr, u8 conn_addr_type); + + +/********************************************************************************** + + @function ble 获取配对表中最后连接设备的 id_address (public address) + @param [out] id_addr + @param [in] + @param [in] + @return true or false + note: + *********************************************************************************/ +bool ble_list_get_last_id_addr(u8 *id_addr); + + +/********************************************************************************** + + @function ble 获取已配对设备连接地址对应的 id_address (public address) + @param [in] conn_addr 对方连接地址6bytes + @param [in] conn_addr_type 对方连接地址类型range: 0~1 + @param [out] id_addr + @param [in] + @param [in] + @return true or false + note: + *********************************************************************************/ +bool ble_list_get_id_addr(u8 *conn_addr, u8 conn_addr_type, u8 *id_addr); + +/********************************************************************************** + + @function ble 获取已配对设备的系统类型 + @param [in] conn_addr 对方连接地址6bytes + @param [in] conn_addr_type 对方连接地址类型range: 0~1 + @param [out] output_type 见 remote_type_e 定义 + @param [in] + @param [in] + @return true or false + note: 只支持作为从机获取手机类型 + *********************************************************************************/ +bool ble_list_get_remote_type(u8 *conn_addr, u8 conn_addr_type, u8 *output_type); + +/********************************************************************************** + @function ble slave: att server 连接后主动发起请求MTU交换流程 + @param [in] handle 连接 con_handle,range:>0 + @param [in] + @param [in] + @return + *********************************************************************************/ +void att_server_set_exchange_mtu(u16 con_handle); + +/********************************************************************************** + @function ble slave: att server 使能流控功能 + @param [in] handle 连接 con_handle,range:>0 + @param [in] enable: 1 or 0 + @param [in] + @return + note: 蓝牙初始化后可调用 + *********************************************************************************/ +void att_server_flow_enable(u8 enable); + +/********************************************************************************** + @function ble slave: att server 控制收数流控 + @param [in] handle 连接 con_handle,range:>0 + @param [in] hold_flag:1--停止收发数据,0--开始正常收发数 + @param [in] + @return + note: 必须先调用 att_server_flow_enable 使能流控控制,接口才能生效 + *********************************************************************************/ +void att_server_flow_hold(hci_con_handle_t con_handle, u8 hold_flag); + +/********************************************************************************** + @function ble slave: server 配对连接时,检查对方操作系统 + @param [in] handle 连接 con_handle,range:>0 + @param [in] callback 检查完回调 + @param [in] + @return + note: 在第一次配对连接时调用,HCI_EVENT_ENCRYPTION_CHANGE 事件后 + *********************************************************************************/ +void att_server_set_check_remote(u16 con_handle, void (*callback)(u16 con_handle, remote_type_e remote_type)); + + +/********************************************************************************** + @function 检测att模块是否支持多机 + @param [in] server_max + @param [in] client_max + @param [in] + @return 0--success ,非0--fail + note: + *********************************************************************************/ +int att_send_check_multi_dev(u8 server_max, u8 client_max); + + + +/********************************************************************************** + @function 可修改GATT服务的profile + @param [in] profile_data + @param [in] + @param [in] + @return 0--success ,非0--fail + note: 蓝牙未连接状态下调用修改 + *********************************************************************************/ +int att_server_change_profile(u8 const *profile_data); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +#endif + diff --git a/include_lib/btstack/le/ble_data_types.h b/include_lib/btstack/le/ble_data_types.h new file mode 100644 index 0000000..9a63772 --- /dev/null +++ b/include_lib/btstack/le/ble_data_types.h @@ -0,0 +1,57 @@ +/********************************************************************************************* + * Filename : bluetooth_data_types.h + + * Description : + + * Author : +*********************************************************************************************/ + +/** + */ + +#ifndef __BLUETOOTH_DATA_TYPES_H +#define __BLUETOOTH_DATA_TYPES_H + +#define BLUETOOTH_DATA_TYPE_FLAGS 0x01 // Flags +#define BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS 0x02 // Incomplete List of 16-bit Service Class UUIDs +#define BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS 0x03 // Complete List of 16-bit Service Class UUIDs +#define BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS 0x04 // Incomplete List of 32-bit Service Class UUIDs +#define BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_32_BIT_SERVICE_CLASS_UUIDS 0x05 // Complete List of 32-bit Service Class UUIDs +#define BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS 0x06 // Incomplete List of 128-bit Service Class UUIDs +#define BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS 0x07 // Complete List of 128-bit Service Class UUIDs +#define BLUETOOTH_DATA_TYPE_SHORTENED_LOCAL_NAME 0x08 // Shortened Local Name +#define BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME 0x09 // Complete Local Name +#define BLUETOOTH_DATA_TYPE_TX_POWER_LEVEL 0x0A // Tx Power Level +#define BLUETOOTH_DATA_TYPE_CLASS_OF_DEVICE 0x0D // Class of Device +#define BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C 0x0E // Simple Pairing Hash C +#define BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C_192 0x0E // Simple Pairing Hash C-192 +#define BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R 0x0F // Simple Pairing Randomizer R +#define BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R_192 0x0F // Simple Pairing Randomizer R-192 +#define BLUETOOTH_DATA_TYPE_DEVICE_ID 0x10 // Device ID +#define BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_TK_VALUE 0x10 // Security Manager TK Value +#define BLUETOOTH_DATA_TYPE_SECURITY_MANAGER_OUT_OF_BAND_FLAGS 0x11 // Security Manager Out of Band Flags +#define BLUETOOTH_DATA_TYPE_SLAVE_CONNECTION_INTERVAL_RANGE 0x12 // Slave Connection Interval Range +#define BLUETOOTH_DATA_TYPE_LIST_OF_16_BIT_SERVICE_SOLICITATION_UUIDS 0x14 // List of 16-bit Service Solicitation UUIDs +#define BLUETOOTH_DATA_TYPE_LIST_OF_32_BIT_SERVICE_SOLICITATION_UUIDS 0x1F // List of 32-bit Service Solicitation UUIDs +#define BLUETOOTH_DATA_TYPE_LIST_OF_128_BIT_SERVICE_SOLICITATION_UUIDS 0x15 // List of 128-bit Service Solicitation UUIDs +#define BLUETOOTH_DATA_TYPE_SERVICE_DATA 0x16 // Service Data +#define BLUETOOTH_DATA_TYPE_SERVICE_DATA_16_BIT_UUID 0x16 // Service Data - 16-bit UUID +#define BLUETOOTH_DATA_TYPE_SERVICE_DATA_32_BIT_UUID 0x20 // Service Data - 32-bit UUID +#define BLUETOOTH_DATA_TYPE_SERVICE_DATA_128_BIT_UUID 0x21 // Service Data - 128-bit UUID +#define BLUETOOTH_DATA_TYPE_LE_SECURE_CONNECTIONS_CONFIRMATION_VALUE 0x22 // LE Secure Connections Confirmation Value +#define BLUETOOTH_DATA_TYPE_LE_SECURE_CONNECTIONS_RANDOM_VALUE 0x23 // LE Secure Connections Random Value +#define BLUETOOTH_DATA_TYPE_URI 0x24 // URI +#define BLUETOOTH_DATA_TYPE_INDOOR_POSITIONING 0x25 // Indoor Positioning +#define BLUETOOTH_DATA_TYPE_TRANSPORT_DISCOVERY_DATA 0x26 // Transport Discovery Data +#define BLUETOOTH_DATA_TYPE_PUBLIC_TARGET_ADDRESS 0x17 // Public Target Address +#define BLUETOOTH_DATA_TYPE_RANDOM_TARGET_ADDRESS 0x18 // Random Target Address +#define BLUETOOTH_DATA_TYPE_APPEARANCE 0x19 // Appearance +#define BLUETOOTH_DATA_TYPE_ADVERTISING_INTERVAL 0x1A // Advertising Interval +#define BLUETOOTH_DATA_TYPE_LE_BLUETOOTH_DEVICE_ADDRESS 0x1B // LE Bluetooth Device Address +#define BLUETOOTH_DATA_TYPE_LE_ROLE 0x1C // LE Role +#define BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_HASH_C_256 0x1D // Simple Pairing Hash C-256 +#define BLUETOOTH_DATA_TYPE_SIMPLE_PAIRING_RANDOMIZER_R_256 0x1E // Simple Pairing Randomizer R-256 +#define BLUETOOTH_DATA_TYPE_3D_INFORMATION_DATA 0x3D // 3D Information Data +#define BLUETOOTH_DATA_TYPE_MANUFACTURER_SPECIFIC_DATA 0xFF // Manufacturer Specific Data + +#endif diff --git a/include_lib/btstack/le/gatt.h b/include_lib/btstack/le/gatt.h new file mode 100644 index 0000000..4172c78 --- /dev/null +++ b/include_lib/btstack/le/gatt.h @@ -0,0 +1,58 @@ +/********************************************************************************************* + * Filename : btstack_event.h + + * Description : + + * Author : Minxian + + * Email : liminxian@zh-jieli.com + + * Last modifiled : 2020-07-01 16:23 + + * Copyright:(c)JIELI 2011-2020 @ , All Rights Reserved. +*********************************************************************************************/ +#ifndef __BT_GATT_H +#define __BT_GATT_H + +#include "typedef.h" + +typedef struct { + uint16_t start_group_handle; + uint16_t end_group_handle; + uint16_t uuid16; + uint8_t uuid128[16]; +} le_service_t, gatt_client_service_t; + + +typedef struct { + uint16_t start_handle; + uint16_t value_handle; + uint16_t end_handle; + uint16_t properties; + uint16_t uuid16; + uint8_t uuid128[16]; +} le_characteristic_t, gatt_client_characteristic_t; + +typedef struct { + uint16_t handle; + uint16_t uuid16; + uint8_t uuid128[16]; +} gatt_client_characteristic_descriptor_t; + +void gatt_client_deserialize_service(const uint8_t *packet, int offset, gatt_client_service_t *service); + +void gatt_client_deserialize_characteristic(const uint8_t *packet, int offset, gatt_client_characteristic_t *characteristic); + +void gatt_client_deserialize_characteristic_descriptor(const uint8_t *packet, int offset, gatt_client_characteristic_descriptor_t *descriptor); + +uint8_t gatt_client_read_long_value_of_characteristic_using_value_handle_with_offset(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t characteristic_value_handle, uint16_t offset); + +uint8_t gatt_client_read_value_of_characteristic_using_value_handle(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle); + +uint8_t gatt_client_write_value_of_characteristic_without_response(hci_con_handle_t con_handle, uint16_t value_handle, uint16_t value_length, uint8_t *value); + +uint8_t gatt_client_write_value_of_characteristic(btstack_packet_handler_t callback, hci_con_handle_t con_handle, uint16_t value_handle, uint16_t value_length, uint8_t *data); + +void gatt_client_request_can_send_now_event(hci_con_handle_t con_handle); + +#endif diff --git a/include_lib/btstack/le/le_user.h b/include_lib/btstack/le/le_user.h new file mode 100644 index 0000000..48f4746 --- /dev/null +++ b/include_lib/btstack/le/le_user.h @@ -0,0 +1,125 @@ + +#ifndef _LE_USER_H_ +#define _LE_USER_H_ + +#include "typedef.h" +#include "btstack/btstack_typedef.h" +#include "ble_api.h" + +#if defined __cplusplus +extern "C" { +#endif + + + +#define BT_NAME_LEN_MAX 29 +#define ADV_RSP_PACKET_MAX 31 + +// hci con handles (12 bit): 0x0000..0x0fff +#define HCI_CON_HANDLE_INVALID 0xffff + +#define BTSTACK_EVENT_STATE 0x60 +#define L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE 0x77 + + +#define SM_EVENT_JUST_WORKS_REQUEST 0xD0 +#define SM_EVENT_PASSKEY_DISPLAY_NUMBER 0xD2 + + + +#define GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NONE 0 +#define GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_NOTIFICATION 1 +#define GATT_CLIENT_CHARACTERISTICS_CONFIGURATION_INDICATION 2 + + +#define GATT_EVENT_NOTIFICATION 0xA7 +#define GATT_EVENT_INDICATION 0xA8 +#define GATT_EVENT_CHARACTERISTIC_VALUE_QUERY_RESULT 0xA5 +#define GATT_EVENT_LONG_CHARACTERISTIC_VALUE_QUERY_RESULT 0xA6 +// #define GATT_EVENT_SERVICE_QUERY_RESULT 0xA1 +// #define GATT_EVENT_CHARACTERISTIC_QUERY_RESULT 0xA2 +// #define GATT_EVENT_QUERY_COMPLETE 0xA0 +#define GAP_EVENT_ADVERTISING_REPORT 0xE2 + +// Authentication requirement flags +#define SM_AUTHREQ_NO_BONDING 0x00 +#define SM_AUTHREQ_BONDING 0x01 +#define SM_AUTHREQ_MITM_PROTECTION 0x04 +#define SM_AUTHREQ_SECURE_CONNECTION 0x08 +#define SM_AUTHREQ_KEYPRESS 0x10 + + +#define L2CAP_EVENT_CONNECTION_PARAMETER_UPDATE_RESPONSE 0x77 + + +#define BT_OP_SUCCESS 0x00 +#define BT_ERR_ADVERTISING_TIMEOUT 0x3C + + +//-------------------------------------------- + + struct ble_server_operation_t { + int(*adv_enable)(void *priv, u32 enable); + int(*disconnect)(void *priv); + int(*get_buffer_vaild)(void *priv); + int(*send_data)(void *priv, void *buf, u16 len); + int(*regist_wakeup_send)(void *priv, void *cbk); + int(*regist_recieve_cbk)(void *priv, void *cbk); + int(*regist_state_cbk)(void *priv, void *cbk); + int(*latency_enable)(void *priv, u32 enable); + }; + + void ble_get_server_operation_table(struct ble_server_operation_t **interface_pt); + +//-------------------------------------------- + + struct ble_client_operation_t { + int(*scan_enable)(void *priv, u32 enable); + int(*disconnect)(void *priv); + int(*get_buffer_vaild)(void *priv); + int(*write_data)(void *priv, void *buf, u16 len); + int(*read_do)(void *priv); + int(*regist_wakeup_send)(void *priv, void *cbk); + int(*regist_recieve_cbk)(void *priv, void *cbk); + int(*regist_state_cbk)(void *priv, void *cbk); + int (*init_config)(void *priv, void *cfg); + int (*opt_comm_send)(u16 handle, u8 *data, u16 len, u8 att_op_type); + int (*set_force_search)(u8 onoff, s8 rssi); + int (*create_connect)(u8 *addr, u8 addr_type, u8 mode); + int (*create_connect_cannel)(void); + int (*get_work_state)(void); + int (*opt_comm_send_ext)(u16 conn_handle, u16 handle, u8 *data, u16 len, u8 att_op_type); + }; + + struct ble_client_operation_t *ble_get_client_operation_table(void); + + + static inline uint32_t ble_min(uint32_t a, uint32_t b) + { + return a < b ? a : b; + } + +//--------------------------------------------------------------------------------------------------- + + +//---------------------------------------- +//---------------------------------------- + + + + extern int get_ble_btstack_state(void); + extern int get_indicate_state(void); + + + extern u8 get_ble_local_name(u8 *name_buf); + extern u8 get_ble_local_name_len(); + + + + + extern void hci_event_callback_set(void(*cbk_ph)(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)); + extern void ll_hci_connection_updata(u8 *data); + +#endif + + diff --git a/include_lib/btstack/le/sm.h b/include_lib/btstack/le/sm.h new file mode 100644 index 0000000..b8daad3 --- /dev/null +++ b/include_lib/btstack/le/sm.h @@ -0,0 +1,55 @@ +/********************************************************************************************* + * Filename : sm.h + + * Description : + + * Author : Minxian + + * Email : liminxian@zh-jieli.com + + * Last modifiled : 2020-07-01 16:36 + + * Copyright:(c)JIELI 2011-2020 @ , All Rights Reserved. +*********************************************************************************************/ +#ifndef _BT_SM_H_ +#define _BT_SM_H_ + +#include "typedef.h" + +// IO Capability Values +typedef enum { + IO_CAPABILITY_DISPLAY_ONLY = 0, + IO_CAPABILITY_DISPLAY_YES_NO, + IO_CAPABILITY_KEYBOARD_ONLY, + IO_CAPABILITY_NO_INPUT_NO_OUTPUT, + IO_CAPABILITY_KEYBOARD_DISPLAY, // not used by secure simple pairing +} io_capability_t; + +void ble_sm_setup_init(io_capability_t io_type, u8 auth_req, uint8_t min_key_size, u8 security_en); + +void ble_cbk_handler_register(btstack_packet_handler_t packet_cbk, sm_stack_packet_handler_t sm_cbk); + +void sm_just_works_confirm(hci_con_handle_t con_handle); + +void sm_init(void); + +void sm_set_io_capabilities(io_capability_t io_capability); + +void sm_set_authentication_requirements(uint8_t auth_req); + +void sm_set_encryption_key_size_range(uint8_t min_size, uint8_t max_size); + +void sm_set_request_security(int enable); + +void sm_event_callback_set(void(*cbk_sm_ph)(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)); + +//配从机默认发请求加密命令 +void sm_set_request_security(int enable); + +//配主机默认发加密请求命令 +void sm_set_master_request_pair(int enable); + +//指定链接发加密请求命令 +bool sm_api_request_pairing(hci_con_handle_t con_handle); + +#endif diff --git a/include_lib/btstack/third_party/app_protocol_event.h b/include_lib/btstack/third_party/app_protocol_event.h new file mode 100644 index 0000000..aee32cb --- /dev/null +++ b/include_lib/btstack/third_party/app_protocol_event.h @@ -0,0 +1,123 @@ + + +#ifndef _3TH_PROTOCOL_EVENT_H +#define _3TH_PROTOCOL_EVENT_H + +//该文件只定义库里面和库外面都需要用得的第三方APP协议的消息和状态 +#include +#include +#include "typedef.h" + +#define DEMO_HANDLER_ID 0x300 /*作为一个使用的例子,同时也可作为客户自己添加协议的ID*/ +#define GMA_HANDLER_ID 0x400 /*阿里天猫协议接口ID*/ +#define MMA_HANDLER_ID 0x500 /*小米MMA协议接口ID*/ +#define DMA_HANDLER_ID 0x600 /*百度DMA协议接口ID*/ +#define TME_HANDLER_ID 0x700 /*腾讯酷狗TME协议接口ID*/ +#define AMA_HANDLER_ID 0x800 /*亚马逊的AMA协议接口ID*/ +//app protocol公共消息 +enum { + APP_PROTOCOL_COMMON_NOTICE = 0, + APP_PROTOCOL_CONNECTING, /*保留,暂未使用*/ + APP_PROTOCOL_CONNECTED_BLE, /*APP通过BLE连接成功状态更新*/ + APP_PROTOCOL_CONNECTED_SPP, /*APP通过SPP连接成功状态更新*/ + APP_PROTOCOL_DISCONNECT, /*APP连接断开状态更新*/ + APP_PROTOCOL_AUTH_PASS, /*连接认证通过标识更新*/ + APP_PROTOCOL_SPEECH_ENCODER_TYPE, + APP_PROTOCOL_SPEECH_START, /*语音识别功能启动状态*/ + APP_PROTOCOL_SPEECH_STOP, /*语音识别功能停止状态*/ + APP_PROTOCOL_SET_VOLUME, /*app配置音量*/ + APP_PROTOCOL_GET_VOLUME, /*app读取音量*/ + APP_PROTOCOL_GET_AUX_STATUS, /*保留,暂未使用*/ + APP_PROTOCOL_LIB_TWS_DATA_SYNC, /*需要更新给另一端tws数据*/ + APP_PROTOCOL_COMMON_NOTICE_END = 0x14F, +}; +//OTA消息 +enum { + APP_PROTOCOL_OTA_COMMON_NOTICE = APP_PROTOCOL_COMMON_NOTICE_END + 1, + APP_PROTOCOL_OTA_CHECK, + APP_PROTOCOL_OTA_GET_APP_VERSION, + APP_PROTOCOL_OTA_CHECK_CRC, + APP_PROTOCOL_OTA_BEGIN, + APP_PROTOCOL_OTA_TRANS_DATA, + APP_PROTOCOL_OTA_PERCENT, + APP_PROTOCOL_OTA_END, + APP_PROTOCOL_OTA_SUCCESS, + APP_PROTOCOL_OTA_FAIL, + APP_PROTOCOL_OTA_CANCLE, + APP_PROTOCOL_OTA_REBOOT, + APP_PROTOCOL_OTA_COMMON_NOTICE_END = 0x1FF, +}; +//GMA私有消息 +enum { + APP_PROTOCOL_GMA_NOTICE_BEGIN = GMA_HANDLER_ID, + APP_PROTOCOL_GMA_FMTX_SETFRE, /*样机支持FM功能的APP配置fm参数*/ + APP_PROTOCOL_GMA_FMTX_GETFRE, /*app获取当前的fm配置参数*/ + APP_PROTOCOL_GMA_NOTICE_END = GMA_HANDLER_ID + 0xFF, +}; +//MMA私有消息 +enum { + APP_PROTOCOL_MMA_NOTICE = MMA_HANDLER_ID, + APP_PROTOCOL_MMA_SAVE_INFO, //库里面不直接访问VM接口,有些信息保存外面做 + APP_PROTOCOL_MMA_READ_INFO, + APP_PROTOCOL_MMA_SAVE_ADV_COUNTER, + APP_PROTOCOL_MMA_READ_ADV_COUNTER, + APP_PROTOCOL_MMA_NOTICE_END = MMA_HANDLER_ID + 0xFF, +}; + +//DMA私有消息 +enum { + APP_PROTOCOL_DMA_NOTICE = DMA_HANDLER_ID, + APP_PROTOCOL_DMA_SAVE_RAND, //库里面不直接访问VM接口,有些信息保存外面做 + APP_PROTOCOL_DMA_READ_RAND, + APP_PROTOCOL_DMA_TWS_SNED_RAND, + APP_PROTOCOL_DMA_TTS_TYPE, + APP_PROTOCOL_DMA_SAVE_OTA_INFO, //库里面不直接访问VM接口,有些信息保存外面做 + APP_PROTOCOL_DMA_READ_OTA_INFO, + APP_PROTOCOL_DMA_NOTICE_END = DMA_HANDLER_ID + 0xFF, +}; +//APP_PROTOCOL获取电量的类型 +#define APP_PROTOCOL_BAT_T_CHARGE_FLAG 0 +#define APP_PROTOCOL_BAT_T_MAIN 1 +#define APP_PROTOCOL_BAT_T_BOX 2 +#define APP_PROTOCOL_BAT_T_TWS_LEFT 3 +#define APP_PROTOCOL_BAT_T_TWS_RIGHT 4 +#define APP_PROTOCOL_BAT_T_TWS_SIBLING 5 +#define APP_PROTOCOL_BAT_T_LOW_POWER 6 +#define APP_PROTOCOL_BAT_T_MAX 8 + +typedef struct _ota_frame_info_t { + u16 max_pkt_len; + u16 frame_crc; + u32 frame_size; +} ota_frame_info; + +//*****// +typedef enum { + USER_NOTIFY_STATE_CONNECTED = 0, /**< 手机APP与设备建立连接 */ + USER_NOTIFY_STATE_DISCONNECTED, /**< 手机APP与设备的连接断开 */ + USER_NOTIFY_STATE_MOBILE_CONNECTED, /**< 手机与设备建立BT连接(A2DP、HFP、AVRCP) */ + USER_NOTIFY_STATE_MOBILE_DISCONNECTED, /**< 手机与设备BT连接(A2DP、HFP、AVRCP)断开 */ + USER_NOTIFY_STATE_SEND_PREPARE_DONE, /**< 设备端进入可向手机发送数据的状态 */ + USER_NOTIFY_STATE_TWS_CONNECT, /**< TWS类设备两端连接成功 */ + USER_NOTIFY_STATE_TWS_DISCONNECT, /**< TWS类设备两端断开连接 */ + USER_NOTIFY_STATE_BOX_OPEN, /**< 盒仓开启 */ + USER_NOTIFY_STATE_BOX_CLOSE, /**< 盒仓关闭 */ + USER_NOTIFY_STATE_ROLE_SWITCH_START, /**< TWS类设备开始进入主从切换流程 */ + USER_NOTIFY_STATE_ROLE_SWITCH_FINISH, /**< TWS类设备主从切换完成 */ + USER_NOTIFY_STATE_ROLE_SWITCH_REQUEST, /**< TWS类设备向APP发起主从切换请求 */ + USER_NOTIFY_STATE_DOUBLE_CLICK, /**< 设备双击按键 */ + USER_NOTIFY_STATE_KEYWORD_DETECTED, /**< 设备语音唤醒 */ + USER_NOTIFY_STATE_BATTERY_LEVEL_UPDATE, /**< 通知耳机电量更新 */ + USER_NOTIFY_STATE_ONE_CLICK, /**< 设备单击按键 */ +} USER_NOTIFY_STATE; + +typedef enum { + /*尽量返回简单的1或者0*/ + CHECK_STATUS_TWS_MASTER, + CHECK_STATUS_TWS_SLAVE, + CHECK_STATUS_TWS_PAIR_STA, /*1是tws已经配对了,0是未配对*/ + CHECK_STATUS_TWS_SIDE, /*0是单耳,1是左耳,2是右耳*/ + CHECK_STATUS_TWS_REV, + CHECK_STATUS_TWS_REV1, +} CHECK_STATUS; +#endif diff --git a/include_lib/btstack/third_party/app_protocol_libs_api.h b/include_lib/btstack/third_party/app_protocol_libs_api.h new file mode 100644 index 0000000..d143fc4 --- /dev/null +++ b/include_lib/btstack/third_party/app_protocol_libs_api.h @@ -0,0 +1,124 @@ + +#ifndef __APP_PRO_LIBS_API_H__ +#define __APP_PRO_LIBS_API_H__ + +#include "typedef.h" + + +///***************************************/// +//GMA的函数接口汇集,begin +int gma_prev_init(void); +int gma_opus_voice_mic_send(uint8_t *voice_buf, uint16_t voice_len); +/*gma的总初始化函数**/ +void gma_all_init(void); +/*gma的总的释放函数**/ +void gma_all_exit(void); +bool gma_connect_success(void); +void gma_set_active_ali_para(void *addr); +/*TWS的公共地址配置*/ +void gma_set_sibling_mac_para(void *mac); +void gma_ble_adv_enable(u8 enable); +void gma_ble_ibeacon_adv(u8 enable); +//gma接收的数据处理函数 +int gma_rx_loop(void); +/*gma命令和数据发送处理*/ +int tm_data_send_process_thread(void); +int gma_start_voice_recognition(int flag); + + +int gma_disconnect(void *addr); + +void gma_message_callback_register(int (*handler)(int opcode, u8 *data, u32 len)); +void gma_is_tws_master_callback_register(bool (*handler)(void)); +void gma_tx_resume_register(bool (*handler)(void)); +void gma_rx_resume_register(bool (*handler)(void)); +/*注册电量的获取回调函数*/ +void gma_get_battery_callback_register(bool (*handler)(u8 battery_type, u8 *value)); + +//ota interface +int gma_ota_requset_next_packet(void *priv, u32 offset, u16 len); +void gma_replay_ota_result(u8 result); + +int tws_ota_get_data_from_sibling(u8 opcode, u8 *data, u8 len); +u8 tws_ota_control(int type, ...); +void tws_ota_app_event_deal(u8 evevt); +//gma apis ends + +///***************************************/// +//DMA apis begin +extern int dueros_process(); +extern int dma_all_init(void); +extern int dma_all_exit(void); +extern void dma_message_callback_register(int (*handler)(int id, int opcode, u8 *data, u32 len)); +extern void dma_check_status_callback_register(int (*handler)(int state_flag)); +extern void dma_tx_resume_register(bool (*handler)(void)); +extern void dma_rx_resume_register(bool (*handler)(void)); +extern void dma_ble_adv_enable(u8 enable); +extern u16 dma_speech_data_send(u8 *buf, u16 len); +extern int dueros_send_process(void); +extern void dma_set_product_id_key(void *data); +extern bool dma_pair_state(); +extern int dma_start_voice_recognition(u8 en); +extern void dueros_dma_manufacturer_info_init(); +extern int dma_disconnect(void *addr); +extern int dma_update_tws_state_to_lib(int state); +extern void dma_get_battery_callback_register(bool (*handler)(u8 battery_type, u8 *value)); +extern void dma_set_pid(u32 pid); +extern void dma_tws_data_deal(u8 *data, int len); + + +//DMA apis ends + +///***************************************/// +//TME apis begins +extern void tme_get_battery_callback_register(bool (*handler)(u8 battery_type, u8 *value)); +extern void tme_message_callback_register(int (*handler)(int id, int opcode, const u8 *data, u32 len)); +extern void tme_is_tws_master_callback_register(bool (*handler)(void)); +extern void tme_tx_resume_register(bool (*handler)(void)); +extern void tme_rx_resume_register(bool (*handler)(void)); +extern void TME_protocol_process(void *parm); +extern int tme_all_init(void); +extern int tme_all_exit(void); +/* extern u16 tme_speech_data_send(buf, len); */ +extern void tme_ble_adv_enable(u8 enable); +extern void TME_send_packet_process(void); +extern void TME_recieve_packet_parse_process(void); +extern bool tme_connect_success(void); +extern int tme_send_voice_data(void *buf, u16 len); +extern int tme_start_voice_recognition(int flag); +extern void tme_set_configuration_info(void *addr); +extern int tme_protocol_disconnect(void *priv); +extern void tme_set_pid(u32 pid); +extern void tme_set_bid(u32 bid); +extern u32 TME_request_ota_data(void *priv, u32 offset, u16 len); +extern void TME_notify_file_size(u32 file_size); + +//TME api ends + +///***************************************/// +//MMA api begins +extern void mma_all_init(void); +extern void mma_all_exit(void); +extern void mma_ble_adv_enable(u8 enable); +extern int XM_speech_data_send(u8 *buf, u16 len); +extern bool XM_protocal_auth_pass(void); +extern int mma_start_voice_recognition(int ctrl); +extern void mma_message_callback_register(int (*handler)(int id, int opcode, u8 *data, u32 len)); +extern void mma_is_tws_master_callback_register(bool (*handler)(void)); +extern void mma_tx_resume_register(void (*handler)(void)); +extern void mma_rx_resume_register(void (*handler)(void)); +extern void mma_set_verdor_id(u16 pid); +extern void mma_set_product_id(u16 pid); +extern void mma_set_local_version(u16 version); +extern int mma_protocol_loop_process(); +extern u32 mma_request_ota_data(void *priv, u32 offset, u16 len); +extern int mma_notify_file_size(u32 size); +extern u32 mma_report_ota_status(u8 state); +extern int mma_disconnect(void *addr); +extern void mma_tws_data_deal(u8 *data, int len); +extern void mma_get_battery_callback_register(bool (*handler)(u8 battery_type, u8 *value)); + +//MMA API END +#endif /* __APP_PRO_LIBS_API_H__ */ + + diff --git a/include_lib/btstack/third_party/common/ble_config.h b/include_lib/btstack/third_party/common/ble_config.h new file mode 100644 index 0000000..b38e9bb --- /dev/null +++ b/include_lib/btstack/third_party/common/ble_config.h @@ -0,0 +1,15 @@ +#ifndef __BLE_CONFIG_H__ +#define __BLE_CONFIG_H__ + +#include "typedef.h" +#include "ble_user.h" + +bool bt_3th_ble_ready(void *priv); +s32 bt_3th_ble_send(void *priv, void *data, u16 len); +void bt_3th_ble_callback_set(void (*resume)(void), void (*recieve)(void *, void *, u16), void (*status)(void *, ble_state_e)); +void bt_3th_ble_status_callback(void *priv, ble_state_e status); +int bt_3th_ble_data_send(void *priv, u8 *buf, u16 len); +void bt_3th_ble_get_operation_table(void); +ble_state_e bt_3th_get_jl_ble_status(void); + +#endif//__BLE_CONFG_H__ diff --git a/include_lib/btstack/third_party/common/ble_user.h b/include_lib/btstack/third_party/common/ble_user.h new file mode 100644 index 0000000..2fe78a5 --- /dev/null +++ b/include_lib/btstack/third_party/common/ble_user.h @@ -0,0 +1,43 @@ +#ifndef __BLE_USER_H__ +#define __BLE_USER_H__ + +#include "typedef.h" + +typedef enum { + BLE_ST_NULL = 0, + BLE_ST_INIT_OK, //协议栈初始化ok + BLE_ST_IDLE, //关闭广播或扫描状态 + BLE_ST_CONNECT, //链路刚连上 + BLE_ST_SEND_DISCONN, //发送断开命令,等待链路断开 + BLE_ST_DISCONN, //链路断开状态 + BLE_ST_CONNECT_FAIL, //连接失败 + BLE_ST_CONNECTION_UPDATE_OK,//更新连接参数完成 + + BLE_ST_ADV = 0x20, //设备处于广播状态 + BLE_ST_NOTIFY_IDICATE, //设备已连上,允许发数(已被主机使能通知) + + BLE_ST_SCAN = 0x40, //设备处于搜索状态 + BLE_ST_CREATE_CONN, //发起设备连接 + BLE_ST_SEND_CREATE_CONN_CANNEL, //取消发起设备连接 + BLE_ST_SEARCH_COMPLETE, //链路连上,已搜索完profile,可以发送数据操作 + + BLE_ST_SEND_STACK_EXIT = 0x60, //发送退出协议栈命令,等待完成 + BLE_ST_STACK_EXIT_COMPLETE, //协议栈退出成功 + +} ble_state_e; + +enum { + APP_BLE_NO_ERROR = 0, + APP_BLE_BUFF_FULL, //buffer 满,会丢弃当前发送的数据包 + APP_BLE_BUFF_ERROR, // + APP_BLE_OPERATION_ERROR, //操作错误 + APP_BLE_IS_DISCONN, //链路已断开 + APP_BLE_NO_WRITE_CCC, //主机没有 write Client Characteristic Configuration +}; + +struct BLE_CONFIG_VAR { + ble_state_e JL_ble_status; + struct ble_server_operation_t *rcsp_ble; +}; + +#endif//__BLE_USER_H__ diff --git a/include_lib/btstack/third_party/common/btstack_3th_protocol_user.h b/include_lib/btstack/third_party/common/btstack_3th_protocol_user.h new file mode 100644 index 0000000..4ba32e0 --- /dev/null +++ b/include_lib/btstack/third_party/common/btstack_3th_protocol_user.h @@ -0,0 +1,72 @@ +#ifndef __BTSTACK_3TH_PROTOCAL_H__ +#define __BTSTACK_3TH_PROTOCAL_H__ + +#include "spp_config.h" +#include "ble_config.h" +#include "JL_rcsp_api.h" +#include "JL_rcsp_protocol.h" +#include "JL_rcsp_packet.h" +#include "attr.h" + + +#define APP_TYPE_RCSP 0x01 +#define APP_TYPE_DUEROS 0x02 +#define APP_TYPE_BTSTACK 0xFF + + +#define BT_CONFIG_BLE BIT(0) +#define BT_CONFIG_SPP BIT(1) + +typedef enum { + BT_3TH_EVENT_COMMON_INIT, + BT_3TH_EVENT_COMMON_BLE_STATUS, + BT_3TH_EVENT_COMMON_SPP_STATUS, + + BT_3TH_EVENT_RCSP_DEV_SELECT = 100, + + + + + BT_3TH_EVENT_DUEROS_CONNECT = 200, + + +} BT_3TH_EVENT_TYPE; + +enum { + RCSP_BLE, + RCSP_SPP, +}; + + +typedef struct __BT_3TH_USER_CB { + int type; + int bt_config; + JL_PRO_CB bt_3th_handler; + void (*BT_3TH_event_handler)(u16 opcode, u8 *packet, int size); + void (*BT_3TH_data_handler)(u8 *packet, int size); + int (*BT_3TH_spp_state_specific)(u8 type); +} BT_3TH_USER_CB; + +typedef struct __BT_3TH_PROTOCOL_CB { + int type; + void (*BT_3TH_type_dev_select)(u8 type); + void (*resume)(void); + void (*recieve)(void *, void *, u16); +} BT_3TH_PROTOCOL_CB; + +int btstack_3th_protocol_user_init(BT_3TH_USER_CB *protocol_callback); +int btstack_3th_protocol_lib_init(BT_3TH_PROTOCOL_CB *protocol_lib_callback); + +JL_PRO_CB *bt_3th_get_spp_callback(void); +void bt_3th_set_spp_callback_priv(void *priv); +JL_PRO_CB *bt_3th_get_ble_callback(void); +void bt_3th_set_ble_callback_priv(void *priv); +void bt_3th_dev_type_spp(void); +void bt_3th_type_dev_select(u8 type); +u8 bt_3th_get_cur_bt_channel_sel(void); +void bt_3th_spp_state_handle(u8 type); +void bt_3th_event_send_to_user(u16 opcode, u8 *packet, int size); +void bt_3th_data_send_to_user(u8 *packet, int size); +#endif// __BTSTACK_3TH_PROTOCAL_H__ + + diff --git a/include_lib/btstack/third_party/common/spp_config.h b/include_lib/btstack/third_party/common/spp_config.h new file mode 100644 index 0000000..cc7e4ce --- /dev/null +++ b/include_lib/btstack/third_party/common/spp_config.h @@ -0,0 +1,15 @@ +#ifndef __SPP_CONFIG_H__ +#define __SPP_CONFIG_H__ + +#include "typedef.h" + +bool bt_3th_spp_fw_ready(void *priv); +s32 bt_3th_spp_send(void *priv, void *data, u16 len); +void bt_3th_spp_callback_set(void (*resume)(void), void (*recieve)(void *, void *, u16), void (*status)(u8)); +u8 bt_3th_get_jl_spp_status(void); +void bt_3th_spp_status_callback(u8 status); +int bt_3th_spp_data_send(void *priv, u8 *buf, u16 len); +void bt_3th_spp_init(void); +void bt_3th_spp_get_operation_table(void); + +#endif//__SPP_CONFIG_H__ diff --git a/include_lib/btstack/third_party/common/spp_user.h b/include_lib/btstack/third_party/common/spp_user.h new file mode 100644 index 0000000..f951288 --- /dev/null +++ b/include_lib/btstack/third_party/common/spp_user.h @@ -0,0 +1,36 @@ +#ifndef __SPP_USER_H__ +#define __SPP_USER_H__ + +#include "typedef.h" + +extern void (*spp_state_cbk)(u8 state); +extern void (*spp_recieve_cbk)(void *priv, u8 *buf, u16 len); +extern void user_spp_data_handler(u8 packet_type, u16 ch, u8 *packet, u16 size); + +struct spp_operation_t { + int(*disconnect)(void *priv); + int(*send_data)(void *priv, void *buf, u16 len); + int(*regist_wakeup_send)(void *priv, void *cbk); + int(*regist_recieve_cbk)(void *priv, void *cbk); + int(*regist_state_cbk)(void *priv, void *cbk); + int(*busy_state)(void); +}; + +enum { + SPP_USER_ERR_NONE = 0x0, + SPP_USER_ERR_SEND_BUFF_BUSY, + SPP_USER_ERR_SEND_OVER_LIMIT, + SPP_USER_ERR_SEND_FAIL, +}; + +enum { + SPP_USER_ST_NULL = 0x0, + SPP_USER_ST_CONNECT, + SPP_USER_ST_DISCONN, + SPP_USER_ST_WAIT_DISC, +}; + +void spp_get_operation_table(struct spp_operation_t **interface_pt); +void dma_spp_init(void); + +#endif//__SPP_USER_H__ diff --git a/include_lib/btstack/third_party/rcsp/JL_rcsp_api.h b/include_lib/btstack/third_party/rcsp/JL_rcsp_api.h new file mode 100644 index 0000000..27d9fe4 --- /dev/null +++ b/include_lib/btstack/third_party/rcsp/JL_rcsp_api.h @@ -0,0 +1,43 @@ + +#ifndef _JL_RCSP_LIB_API_H_ +#define _JL_RCSP_LIB_API_H_ + +#include "typedef.h" +#include "uart.h" + +#define USE_LITTLE_ENDIAN 0 +#define USE_BIG_ENDIAN 1 + +#define USE_ENDIAN_TYPE USE_LITTLE_ENDIAN + + +#define AI_LICENCE_LEN 16 + +enum { + TULING = 0, + DEEPBRAIN, +}; + +#pragma pack(1) +struct _AI_platform { + u8 platform; + u8 license[AI_LICENCE_LEN]; +}; +#pragma pack() + +u16 app_htons(u16 n); +u16 app_ntohs(u16 n); + +u32 app_htonl(u32 n); +u32 app_ntohl(u32 n); + +void JL_rcsp_auth_init(int (*send)(void *, u8 *, u16), u8 *link_key, u8 *addr); +void JL_rcsp_auth_reset(void); +u8 JL_rcsp_get_auth_flag(void); +void JL_rcsp_set_auth_flag(u8 auth_flag); +void JL_rcsp_auth_recieve(u8 *buffer, u16 len); + +u8 get_rcsp_version(void); +void get_ai_platform(struct _AI_platform *p, u8 platform); +void smart_auth_res_pass(void); +#endif //_JL_RCSP_LIB_H_ diff --git a/include_lib/btstack/third_party/rcsp/JL_rcsp_packet.h b/include_lib/btstack/third_party/rcsp/JL_rcsp_packet.h new file mode 100644 index 0000000..974ab6c --- /dev/null +++ b/include_lib/btstack/third_party/rcsp/JL_rcsp_packet.h @@ -0,0 +1,102 @@ +#ifndef __JL_PACKET_H__ +#define __JL_PACKET_H__ + +#include "typedef.h" + + +#define READ_BIG_U16(a) ((*((u8*)(a)) <<8) + *((u8*)(a)+1)) +#define READ_BIG_U32(a) ((*((u8*)(a)) <<24) + (*((u8*)(a)+1)<<16) + (*((u8*)(a)+2)<<8) + *((u8*)(a)+3)) + +#define READ_LIT_U16(a) (*((u8*)(a)) + (*((u8*)(a)+1)<<8)) +#define READ_LIT_U32(a) (*((u8*)(a)) + (*((u8*)(a)+1)<<8) + (*((u8*)(a)+2)<<16) + (*((u8*)(a)+3)<<24)) + + +#define WRITE_BIG_U16(a,src) {*((u8*)(a)+0) = (u8)(src>>8); *((u8*)(a)+1) = (u8)(src&0xff); } +#define WRITE_BIG_U32(a,src) {*((u8*)(a)+0) = (u8)((src)>>24); *((u8*)(a)+1) = (u8)(((src)>>16)&0xff);*((u8*)(a)+2) = (u8)(((src)>>8)&0xff);*((u8*)(a)+3) = (u8)((src)&0xff);} + +#define WRITE_LIT_U16(a,src) {*((u8*)(a)+1) = (u8)(src>>8); *((u8*)(a)+0) = (u8)(src&0xff); } +#define WRITE_LIT_U32(a,src) {*((u8*)(a)+3) = (u8)((src)>>24); *((u8*)(a)+2) = (u8)(((src)>>16)&0xff);*((u8*)(a)+1) = (u8)(((src)>>8)&0xff);*((u8*)(a)+0) = (u8)((src)&0xff);} + + +#pragma pack(1) +typedef union __HEAD_BIT { + struct { + u16 _OpCode: 8; //OpCode val + u16 _unsed : 6; //unsed + u16 _resp : 1; //request for response + u16 _type : 1; //command or response + } _i; + u16 _t; +} HEAD_BIT; + +struct __JL_PACKET { + u8 tag[3]; + HEAD_BIT head; + u16 length; + u8 data[0]; +}; +#pragma pack() +typedef struct __JL_PACKET JL_PACKET; + + +#define JL_PACK_START_TAG0 (0xfe) +#define JL_PACK_START_TAG1 (0xdc) +#define JL_PACK_START_TAG2 (0xba) +#define JL_PACK_END_TAG (0xef) +#define JL_ONE_PACKET_LEN(n) (sizeof(JL_PACKET) + n + 1) + +#ifdef JL_RCSP_UBOOT_LIB +#define JL_MTU_RESV (540L) +#define JL_MTU_SEND (128L) +#define JL_RECIEVE_BUF_SIZE ((JL_MTU_RESV + sizeof(JL_PACKET))*2) +#define JL_CMD_POOL_SIZE (JL_MTU_SEND) +#define JL_RESP_POOL_SIZE (JL_MTU_SEND*2) +#define JL_WAIT_RESP_POOL_SIZE (JL_MTU_SEND) +#else +#define JL_MTU_RESV (540L) +#define JL_MTU_SEND (128L) +#define JL_RECIEVE_BUF_SIZE (JL_MTU_RESV + sizeof(JL_PACKET) + 128) +#define JL_CMD_POOL_SIZE (JL_MTU_SEND*4) +#define JL_RESP_POOL_SIZE (JL_MTU_SEND*2) +#define JL_WAIT_RESP_POOL_SIZE (JL_MTU_SEND*2) +#endif + +void set_jl_rcsp_recieve_buf_size(u16 size); +u16 rcsp_packet_write_alloc_len(void); + +u32 rcsp_packet_need_buf_size(void); +u32 rcsp_packet_buf_init(u8 *buf, u32 len); + +u16 JL_packet_get_rx_max_mtu(void); +u16 JL_packet_get_tx_max_mtu(void); +u16 JL_packet_set_mtu(u16 mtu); +void JL_packet_recieve(void *buf, u16 len); +u32 JL_pack_data_read_all(void *buf, u16 len); +void JL_packet_clear_all_data(void); +bool JL_packet_find(u8 *r_buf, JL_PACKET **packet); +void JL_packet_init(void); +void JL_packet_clear(void); + +void JL_packet_packing( + JL_PACKET *packet, + u8 OpCode, + u8 type, + u8 request_rsp, + u8 *extra_param, + u16 extra_len, + u8 *data, + u16 len); + +void set_jl_mtu_resv(u16 jl_mtu_resv_var); +void set_jl_mtu_send(u16 jl_mtu_send_var); + +extern u16 jl_mtu_resv; +extern u16 jl_mtu_send; +extern u16 jl_recieve_buf_size; +extern u16 jl_cmd_pool_size; +extern u16 jl_rcsp_pool_size; +extern u16 jl_wait_rcsp_pool_size; + +#endif//__JL_PACKET_H__ + + diff --git a/include_lib/btstack/third_party/rcsp/JL_rcsp_protocol.h b/include_lib/btstack/third_party/rcsp/JL_rcsp_protocol.h new file mode 100644 index 0000000..3be4137 --- /dev/null +++ b/include_lib/btstack/third_party/rcsp/JL_rcsp_protocol.h @@ -0,0 +1,195 @@ +#ifndef __JL_PROTOCOL_H__ +#define __JL_PROTOCOL_H__ + +#include "typedef.h" +#include "JL_rcsp_packet.h" + +#define ATTR_TYPE_PROTOCOL_VERSION (0) +#define ATTR_TYPE_SYS_INFO (1) +#define ATTR_TYPE_EDR_ADDR (2) +#define ATTR_TYPE_PLATFORM (3) +#define ATTR_TYPE_FUNCTION_INFO (4) +#define ATTR_TYPE_DEV_VERSION (5) +#define ATTR_TYPE_SDK_TYPE (6) +#define ATTR_TYPE_UBOOT_VERSION (7) +#define ATTR_TYPE_DOUBLE_PARITION (8) +#define ATTR_TYPE_UPDATE_STATUS (9) +#define ATTR_TYPE_DEV_VID_PID (10) +#define ATTR_TYPE_DEV_AUTHKEY (11) +#define ATTR_TYPE_DEV_PROCODE (12) +#define ATTR_TYPE_DEV_MAX_MTU (13) +#define ATTR_TEYP_BLE_ADDR (17) +#define ATTR_TYPE_MD5_GAME_SUPPORT (19) + + + +#define COMMON_INFO_ATTR_BATTERY (0) +#define COMMON_INFO_ATTR_VOL (1) +#define COMMON_INFO_ATTR_DEV (2) +#define COMMON_INFO_ATTR_ERR_REPORT (3) +#define COMMON_INFO_ATTR_EQ (4) +#define COMMON_INFO_ATTR_FILE_BROWSE_TYPE (5) +#define COMMON_INFO_ATTR_FUN_TYPE (6) +#define COMMON_INFO_ATTR_LIGHT (7) +#define COMMON_INFO_ATTR_FMTX (8) +#define COMMON_INFO_ATTR_HIGH_LOW_SET (11) +#define COMMON_INFO_ATTR_PRE_FETCH_ALL_EQ_INFO (12) +#define COMMON_INFO_ATTR_PHONE_SCO_STATE_INFO (15) + + + +#define BT_INFO_ATTR_MUSIC_TITLE (0) +#define BT_INFO_ATTR_MUSIC_ARTIST (1) +#define BT_INFO_ATTR_MUSIC_ALBUM (2) +#define BT_INFO_ATTR_MUSIC_NUMBER (3) +#define BT_INFO_ATTR_MUSIC_TOTAL (4) +#define BT_INFO_ATTR_MUSIC_GENRE (5) +#define BT_INFO_ATTR_MUSIC_TIME (6) +#define BT_INFO_ATTR_MUSIC_STATE (7) +#define BT_INFO_ATTR_MUSIC_CURR_TIME (8) + +#define BT_INFO_ATTR_01 (0) + +#define MUSIC_INFO_ATTR_STATUS (0) +#define MUSIC_INFO_ATTR_FILE_NAME (1) +#define MUSIC_INFO_ATTR_FILE_PLAY_MODE (2) + +#define RTC_INFO_ATTR_RTC_TIME (0) +#define RTC_INFO_ATTR_RTC_ALRAM (1) + +#define LINEIN_INFO_ATTR_STATUS (0) + + +/***************************************/ +/* 注意:不能在这个枚举里加代码 */ +/* 注意:不能在这个枚举里加代码 */ +/* 注意:不能在这个枚举里加代码 */ +/***************************************/ +enum { + JL_OPCODE_DATA = 0x01, + JL_OPCODE_GET_TARGET_FEATURE_MAP = 0x02, + JL_OPCODE_GET_TARGET_FEATURE = 0x03, + // JL_OPCODE_SWITCH_DEVICE = 0x04, + JL_OPCODE_DISCONNECT_EDR = 0x06, + JL_OPCODE_SYS_INFO_GET = 0x07, + JL_OPCODE_SYS_INFO_SET = 0x08, + JL_OPCODE_SYS_INFO_AUTO_UPDATE = 0x09, + JL_OPCODE_CALL_REQUEST = 0xa, + JL_OPCODE_SWITCH_DEVICE = 0x0b, + JL_OPCODE_FILE_BROWSE_REQUEST_START = 0x0C, + JL_OPCODE_FILE_BROWSE_REQUEST_STOP = 0x0D, + JL_OPCODE_FUNCTION_CMD = 0x0E, + + JL_OPCODE_SYS_OPEN_BT_SCAN = 0x12, + JL_OPCODE_SYS_UPDATE_BT_STATUS = 0X13, + JL_OPCODE_SYS_STOP_BT_SCAN = 0X14, + JL_OPCODE_SYS_BT_CONNECT_SPEC = 0X15, + JL_OPCODE_SYS_EMITTER_BT_CONNECT_STATUS = 0XD3, // 临时调整, 被遗忘的指令 + JL_OPCODE_SYS_FIND_DEVICE = 0X19, + + JL_OPCODE_EXTRA_FLASH_OPT = 0X1A, + + //文件传输相关命令 + JL_OPCODE_FILE_TRANSFER_START = 0X1B, + JL_OPCODE_FILE_TRANSFER_END = 0X1C, + JL_OPCODE_FILE_TRANSFER = 0X1D, + JL_OPCODE_FILE_TRANSFER_CANCEL = 0X1E, + JL_OPCODE_FILE_DELETE = 0X1F, + JL_OPCODE_FILE_RENAME = 0X20, + + JL_OPCODE_ACTION_PREPARE = 0X21,//APP操作预处理 + JL_OPCODE_DEVICE_FORMAT = 0X22,//设备格式化 + JL_OPCODE_ONE_FILE_DELETE = 0x23,//删除一个文件 + JL_OPCODE_ONE_FILE_TRANS_BACK = 0x24,//回传一个文件 + + JL_OPCODE_GET_MD5 = 0xD4, + JL_OPCODE_LOW_LATENCY_PARAM = 0xD5, + JL_OPTCODE_EXTRA_FLASH_INFO = 0XD6, + + JL_OPCODE_CUSTOMER_USER = 0xFF, +}; +/***************************************/ +/***************************************/ + +enum { + JL_NOT_NEED_RESPOND = 0, + JL_NEED_RESPOND, +}; + +enum { + JL_AUTH_NOTPASS = 0, + JL_AUTH_PASS, +}; + +typedef enum __JL_ERR { + JL_ERR_NONE = 0x0, + JL_ERR_SEND_DATA_OVER_LIMIT, + JL_ERR_SEND_BUSY, + JL_ERR_SEND_NOT_READY, + JL_ERR_EXIT, +} JL_ERR; + +typedef enum __JL_PRO_STATUS { + JL_PRO_STATUS_SUCCESS = 0x0, + JL_PRO_STATUS_FAIL, + JL_PRO_STATUS_UNKOWN_CMD, + JL_PRO_STATUS_BUSY, + JL_PRO_STATUS_NO_RESPONSE, + JL_PRO_STATUS_CRC_ERR, + JL_PRO_STATUS_ALL_DATA_CRC_ERR, + JL_PRO_STATUS_PARAM_ERR, + JL_PRO_STATUS_RESP_DATA_OVER_LIMIT, + +} JL_PRO_STATUS; + +///*< JL_CMD、JL_CMD_response、JL_DATA、JL_DATA_response packet send functions>*/ +JL_ERR JL_CMD_send(u8 OpCode, u8 *data, u16 len, u8 request_rsp); +JL_ERR JL_CMD_response_send(u8 OpCode, u8 status, u8 sn, u8 *data, u16 len); +JL_ERR JL_DATA_send(u8 OpCode, u8 CMD_OpCode, u8 *data, u16 len, u8 request_rsp); +JL_ERR JL_DATA_response_send(u8 OpCode, u8 status, u8 sn, u8 CMD_OpCode, u8 *data, u16 len); + +///**/ +typedef struct __JL_PRO_CB { + /*send function callback, SPP or ble*/ + void *priv; + bool (*fw_ready)(void *priv); + s32(*fw_send)(void *priv, void *buf, u16 len); + /*JL_CMD、JL_CMD_response、JL_DATA、JL_DATA_response packet recieve callback*/ + void (*CMD_resp)(void *priv, u8 OpCode, u8 OpCode_SN, u8 *data, u16 len); + void (*DATA_resp)(void *priv, u8 OpCode_SN, u8 CMD_OpCode, u8 *data, u16 len); + void (*CMD_no_resp)(void *priv, u8 OpCode, u8 *data, u16 len); + void (*DATA_no_resp)(void *priv, u8 CMD_OpCode, u8 *data, u16 len); + void (*CMD_recieve_resp)(void *priv, u8 OpCode, u8 status, u8 *data, u16 len); + void (*DATA_recieve_resp)(void *priv, u8 status, u8 CMD_OpCode, u8 *data, u16 len); + u8(*wait_resp_timeout)(void *priv, u8 OpCode, u8 counter); + void (*auth_pass_callback)(void *priv); +} JL_PRO_CB; + + +extern u32 rcsp_fw_ready(void); +extern u32 rcsp_protocol_need_buf_size(void); + +extern void JL_protocol_init(u8 *buf, u32 len); +extern void JL_protocol_exit(void); + +extern void JL_protocol_dev_switch(const JL_PRO_CB *cb); + +extern void JL_protocol_data_recieve(void *priv, void *buf, u16 len); +extern void JL_protocol_resume(void); + +extern void JL_protocol_process(void); + +extern void set_auth_pass(u8 auth_pass); + +extern void JL_set_cur_tick(u16 tick); + +extern bool rcsp_send_list_is_empty(void); + + +extern void JL_send_packet_process(void); +extern void JL_recieve_packet_parse_process(void); + + +#endif//__JL_PROTOCOL_H__ + + diff --git a/include_lib/btstack/third_party/rcsp/attr.h b/include_lib/btstack/third_party/rcsp/attr.h new file mode 100644 index 0000000..6b1a8ba --- /dev/null +++ b/include_lib/btstack/third_party/rcsp/attr.h @@ -0,0 +1,14 @@ +#ifndef __ATTR_H__ +#define __ATTR_H__ +#include "typedef.h" + +typedef u32(*attr_get_func)(void *priv, u8 attr, u8 *buf, u16 buf_size, u32 offset); +typedef void (*attr_set_func)(void *priv, u8 attr, u8 *data, u16 len); + +u8 add_one_attr(u8 *buf, u16 max_len, u8 offset, u8 type, u8 *data, u8 size); +u8 add_one_attr_ex(u8 *buf, u16 max_len, u8 offset, u8 type, u8 *data, u8 size, u8 att_size); +u8 add_one_attr_continue(u8 *buf, u16 max_len, u8 offset, u8 type, u8 *data, u8 size); +u32 attr_get(void *priv, u8 *buf, u16 buf_size, const attr_get_func *func_tab, u8 attr_max, u32 mask); +void attr_set(void *priv, u8 *data, u16 len, const attr_set_func *func_tab, u8 attr_max); + +#endif//__ATTR_H__ diff --git a/include_lib/driver/cpu/br23/asm/adc_api.h b/include_lib/driver/cpu/br23/asm/adc_api.h new file mode 100644 index 0000000..6bd7a2c --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/adc_api.h @@ -0,0 +1,96 @@ +#ifndef __ADC_API_H__ +#define __ADC_API_H__ + + +//AD channel define +#define AD_CH_PA1 (0x0) +#define AD_CH_PA5 (0x1) +#define AD_CH_PA6 (0x2) +#define AD_CH_PA10 (0x3) +#define AD_CH_PA12 (0x4) +#define AD_CH_PB1 (0x5) +#define AD_CH_PB3 (0x6) +#define AD_CH_PB4 (0x7) +#define AD_CH_PB8 (0x8) +#define AD_CH_PB10 (0x9) +#define AD_CH_PC4 (0xA) +#define AD_CH_PC6 (0xB) +#define AD_CH_DP (0xC) +#define AD_CH_PC5 (0xD) +#define AD_CH_RTC (0xE) //RTC to ADC + +#define AD_CH_MUX (0xF) //PLL/PMU/AUDIO/BT/FM to ADC + +//AD_CH_MUX +#define AD_OF_PMU ((0x0<<16) | AD_CH_MUX) +#define AD_OF_AUDIO ((0x1<<16) | AD_CH_MUX) +#define AD_OF_PLL ((0x2<<16) | AD_CH_MUX) +#define AD_OF_FM ((0x3<<16) | AD_CH_MUX) +#define AD_OF_BT ((0x4<<16) | AD_CH_MUX) + +//PMU +#define AD_CH_PMU_VBG ((0x0<<20) | AD_OF_PMU) +#define AD_CH_VDC13 ((0x1<<20) | AD_OF_PMU) +#define AD_CH_SYSVDD ((0x2<<20) | AD_OF_PMU) +#define AD_CH_DTEMP ((0x3<<20) | AD_OF_PMU) +#define AD_CH_PROGF ((0x4<<20) | AD_OF_PMU) +#define AD_CH_VBAT ((0x5<<20) | AD_OF_PMU) //1/4vbat +#define AD_CH_LDO5V ((0x6<<20) | AD_OF_PMU) //1/4 LDO5V +#define AD_CH_WVDD ((0x7<<20) | AD_OF_PMU) +//AUDIO +#define AD_CH_F_VOUTL ((0x0<<20) | AD_OF_AUDIO) +#define AD_CH_F_VOUTR ((0x1<<20) | AD_OF_AUDIO) +#define AD_CH_MICLDO ((0x2<<20) | AD_OF_AUDIO) +#define AD_CH_CTADCREF ((0x3<<20) | AD_OF_AUDIO) +#define AD_CH_DACVDD ((0x4<<20) | AD_OF_AUDIO) +#define AD_CH_R_VOUTL ((0x5<<20) | AD_OF_AUDIO) +#define AD_CH_R_VOUTR ((0x6<<20) | AD_OF_AUDIO) +//PLL +#define AD_CH_BIAS ((0x0<<20) | AD_OF_PLL) +#define AD_CH_ANALOG ((0x1<<20) | AD_OF_PLL) +#define AD_CH_DIGITAL ((0x2<<20) | AD_OF_PLL) +#define AD_CH_480MEG ((0x3<<20) | AD_OF_PLL) +//FM +#define AD_CH_FMTX_SEL ((0x0<<20) | AD_OF_FM) +//BT +#define AD_CH_BT_SEL ((0x0<<20) | AD_OF_BT) + +#define AD_CH_LDOREF AD_CH_PMU_VBG + + +#define ADC_MAX_CH 10 + + +extern void adc_init(); +extern void adc_vbg_init(); +//p33 define + +extern void adc_pmu_ch_select(u32 ch); +extern void adc_pmu_detect_en(u32 ch); +extern void adc_vdc13_save(); +extern void adc_vdc13_restore(); + +// +u32 adc_get_value(u32 ch); + +u32 adc_add_sample_ch(u32 ch); + +u32 adc_remove_sample_ch(u32 ch); + +u32 adc_get_voltage(u32 ch); +u32 adc_check_vbat_lowpower(); + +void check_pmu_voltage(u8 tieup); + +extern void adc_enter_occupy_mode(u32 ch); +extern void adc_exit_occupy_mode(); +extern u32 adc_occupy_run(); +extern u32 adc_get_occupy_value(); +u32 adc_sample(u32 ch); +u32 adc_value_to_voltage(u32 adc_vbg, u32 adc_ch_val); + +char get_vddiom_trim(); +char get_vddiow_trim(); +void check_pmu_voltage(u8 tieup); + +#endif diff --git a/include_lib/driver/cpu/br23/asm/br23.h b/include_lib/driver/cpu/br23/asm/br23.h new file mode 100644 index 0000000..3e62d05 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/br23.h @@ -0,0 +1,865 @@ + +#ifndef __BR23__ +#define __BR23__ + +//===============================================================================// +// +// sfr define +// +//===============================================================================// + +#define hs_base 0x1f0000 +#define ls_base 0x1e0000 + +#define __RW volatile // read write +#define __RO volatile const // only read +#define __WO volatile // only write + +#define __u8 unsigned int // u8 to u32 special for struct +#define __u16 unsigned int // u16 to u32 special for struct +#define __u32 unsigned int +#define __s16 short + +// #define __s8(x) char(x); char(reserved_1_##x); char(reserved_2_##x); char(reserved_3_##x) +// #define __s16(x) short(x); short(reserved_1_##x) +// #define __s32(x) int(x) + +#define map_adr(grp, adr) ((64 * grp + adr) * 4) // grp(0x0-0xff), adr(0x0-0x3f) + +//===============================================================================// +// +// high speed sfr address define +// +//===============================================================================// + +//............. 0x0200 - 0x02ff............ for sfc +typedef struct { + __RW __u32 CON; + __WO __u32 BAUD; + __WO __u32 CODE; + __WO __u32 BASE_ADR; + __WO __u32 QUCNT; +} JL_SFC_TypeDef; + +#define JL_SFC_BASE (hs_base + map_adr(0x02, 0x00)) +#define JL_SFC ((JL_SFC_TypeDef *)JL_SFC_BASE) + +//............. 0x0300 - 0x03ff............ for sfc encrypt +typedef struct { + __RW __u8 CON; + __RW __u16 KEY; + __WO __u32 UNENC_ADRH; + __WO __u32 UNENC_ADRL; + __WO __u32 LENC_ADRH; + __WO __u32 LENC_ADRL; +} JL_SFCENC_TypeDef; + +#define JL_SFCENC_BASE (hs_base + map_adr(0x03, 0x00)) +#define JL_SFCENC ((JL_SFCENC_TypeDef *)JL_SFCENC_BASE) + +//............. 0x0500 - 0x05ff............ for psram +typedef struct { + __RW __u32 CON; + __WO __u32 BAUD; + __WO __u32 QUCNT; +} JL_PSRAM_TypeDef; + +#define JL_PSRAM_BASE (hs_base + map_adr(0x05, 0x00)) +#define JL_PSRAM ((JL_PSRAM_TypeDef *)JL_PSRAM_BASE) + +//............. 0x1300 - 0x13ff............ for dcp +typedef struct { + __RW __u32 CON; + __RW __u32 ADR; +} JL_DCP_TypeDef; + +#define JL_DCP_BASE (hs_base + map_adr(0x13, 0x00)) +#define JL_DCP ((JL_DCP_TypeDef *)JL_DCP_BASE) + + +//............. 0x1500 - 0x15ff............ for eq +typedef struct { + __RW __u32 CON0; + __RW __u32 CON1; + __RW __u32 DATAI_ADR; + __RW __u32 DATAO_ADR; + __RW __u32 DATA_LEN; + __RW __u32 FLT_ADR; + +} JL_EQ_TypeDef; + +#define JL_EQ_BASE (hs_base + map_adr(0x15, 0x00)) +#define JL_EQ ((JL_EQ_TypeDef *)JL_EQ_BASE) + +//............. 0x1600 - 0x16ff............ for src +typedef struct { + __RW __u32 CON0; + __RW __u32 CON1; + __RW __u32 CON2; + __RW __u32 CON3; + __RW __u32 IDAT_ADR; + __RW __u32 IDAT_LEN; + __RW __u32 ODAT_ADR; + __RW __u32 ODAT_LEN; + __RW __u32 FLTB_ADR; +} JL_SRC_TypeDef; + +#define JL_SRC_BASE (hs_base + map_adr(0x16, 0x00)) +#define JL_SRC ((JL_SRC_TypeDef *)JL_SRC_BASE) + +//............. 0x1700 - 0x17ff............ for fm +typedef struct { + __RW __u32 CON; + __RW __u32 BASE; + __RW __u32 ADC_CON; + __RW __u32 ADC_CON1; + __RW __u32 HF_CON0; + __RW __u32 HF_CON1; + __RW __u32 HF_CRAM; + __RW __u32 HF_CRAM2; + __RW __u32 HF_DRAM; + __RW __u32 LF_CON; + __RW __u32 LF_RES; + __RW __u32 FMRX_CON4; + __RW __u32 FMRX_CON5; + + + __RW __u32 TX_CON0; + __RW __u32 TX_CON1; + __RW __u32 TX_PILOT; + __RW __u32 TX_SYN_GAIN; + __RW __u32 TX_MUL; + __RW __u32 TX_ADR; + __RW __u32 TX_LEN; + __RW __u32 TX_FREQ; + __RW __u32 TX_BASE_ADR; +} JL_FM_TypeDef; + +#define JL_FM_BASE (hs_base + map_adr(0x17, 0x00)) +#define JL_FM ((JL_FM_TypeDef *)JL_FM_BASE) + + +//............. 0x1800 - 0x18ff............ for wireless +typedef struct { + __RW __u32 CON0; + __RW __u32 CON3; + __RW __u32 LOFC_CON; + __RW __u32 LOFC_RES; +} JL_WL_TypeDef; + +#define JL_WL_BASE (hs_base + map_adr(0x18, 0x00)) +#define JL_WL ((JL_WL_TypeDef *)JL_WL_BASE) + +//===============================================================================// +// +// low speed sfr address define +// +//===============================================================================// + +//............. 0x0000 - 0x00ff............ for syscfg +typedef struct { + __RW __u32 PWR_CON; + __RW __u32 HTC_CON; + __RW __u32 SYS_DIV; + __RW __u32 CLK_CON0; + __RW __u32 CLK_CON1; + __RW __u32 CLK_CON2; + __RW __u32 CLK_CON3; + __RW __u32 RESERVED0[0x10 - 0x6 - 1]; + __RW __u32 PLL_CON; + __RW __u32 PLL_CON1; + __RW __u32 PLL_INTF; + __RW __u32 PLL_DMAX; + __RW __u32 PLL_DMIN; + __RW __u32 PLL_DSTP; +} JL_CLOCK_TypeDef; + +#define JL_CLOCK_BASE (ls_base + map_adr(0x00, 0x00)) +#define JL_CLOCK ((JL_CLOCK_TypeDef *)JL_CLOCK_BASE) + +typedef struct { + __RW __u32 SRC; +} JL_RST_TypeDef; + +#define JL_RST_BASE (ls_base + map_adr(0x00, 0x30)) +#define JL_RST ((JL_RST_TypeDef *)JL_RST_BASE) + +//............. 0x0100 - 0x01ff............ +typedef struct { + __RW __u32 MODE_CON; +} JL_MODE_TypeDef; + +#define JL_MODE_BASE (ls_base + map_adr(0x01, 0x00)) +#define JL_MODE ((JL_MODE_TypeDef *)JL_MODE_BASE) + +//............. 0x0200 - 0x02ff............ +typedef struct { + __WO __u32 CHIP_ID; + __RW __u32 MBIST_CON; +} JL_SYSTEM_TypeDef; + +#define JL_SYSTEM_BASE (ls_base + map_adr(0x02, 0x00)) +#define JL_SYSTEM ((JL_SYSTEM_TypeDef *)JL_SYSTEM_BASE) + +//............. 0x0400 - 0x07ff............ +typedef struct { + __RW __u32 CON; + __RW __u32 CNT; + __RW __u32 PRD; + __RW __u32 PWM; +} JL_TIMER_TypeDef; + +#define JL_TIMER0_BASE (ls_base + map_adr(0x04, 0x00)) +#define JL_TIMER0 ((JL_TIMER_TypeDef *)JL_TIMER0_BASE) + +#define JL_TIMER1_BASE (ls_base + map_adr(0x05, 0x00)) +#define JL_TIMER1 ((JL_TIMER_TypeDef *)JL_TIMER1_BASE) + +#define JL_TIMER2_BASE (ls_base + map_adr(0x06, 0x00)) +#define JL_TIMER2 ((JL_TIMER_TypeDef *)JL_TIMER2_BASE) + +#define JL_TIMER3_BASE (ls_base + map_adr(0x07, 0x00)) +#define JL_TIMER3 ((JL_TIMER_TypeDef *)JL_TIMER3_BASE) + + +//............. 0x1000 - 0x10ff............ +typedef struct { + __RW __u32 CON; + __RW __u32 VAL; +} JL_PCNT_TypeDef; + +#define JL_PCNT_BASE (ls_base + map_adr(0x10, 0x00)) +#define JL_PCNT ((JL_PCNT_TypeDef *)JL_PCNT_BASE) + +//............. 0x1100 - 0x11ff............ +typedef struct { + __RW __u32 CON; + __RO __u32 NUM; +} JL_GPCNT_TypeDef; + +#define JL_GPCNT_BASE (ls_base + map_adr(0x11, 0x00)) +#define JL_GPCNT ((JL_GPCNT_TypeDef *)JL_GPCNT_BASE) + + +//............. 0x1400 - 0x17ff............ +typedef struct { + __RW __u32 CON0; + __RW __u32 CON1; + __RW __u32 CON2; + __WO __u32 CPTR; + __WO __u32 DPTR; + __RW __u32 CTU_CON; + __WO __u32 CTU_CNT; +} JL_SD_TypeDef; + +#define JL_SD0_BASE (ls_base + map_adr(0x14, 0x00)) +#define JL_SD0 ((JL_SD_TypeDef *)JL_SD0_BASE) + +#define JL_SD1_BASE (ls_base + map_adr(0x15, 0x00)) +#define JL_SD1 ((JL_SD_TypeDef *)JL_SD1_BASE) + +//............. 0x1800 - 0x18ff............ +typedef struct { + __RW __u32 CON0; + __RW __u32 CON1; + __WO __u32 EP0_CNT; + __WO __u32 EP1_CNT; + __WO __u32 EP2_CNT; + __WO __u32 EP3_CNT; + __WO __u32 EP4_CNT; + __WO __u32 EP0_ADR; + __WO __u32 EP1_TADR; + __WO __u32 EP1_RADR; + __WO __u32 EP2_TADR; + __WO __u32 EP2_RADR; + __WO __u32 EP3_TADR; + __WO __u32 EP3_RADR; + __WO __u32 EP4_TADR; + __WO __u32 EP4_RADR; +} JL_USB_TypeDef; + +#define JL_USB_BASE (ls_base + map_adr(0x18, 0x00)) +#define JL_USB ((JL_USB_TypeDef *)JL_USB_BASE) + +//............. 0x1900 - 0x19ff............ +typedef struct { + __RW __u32 WLA_CON0 ; + __RW __u32 WLA_CON1 ; + __RW __u32 WLA_CON2 ; + __RW __u32 WLA_CON3 ; + __RW __u32 WLA_CON4 ; + __RW __u32 WLA_CON5 ; + __RW __u32 WLA_CON6 ; + __RW __u32 WLA_CON7 ; + __RW __u32 WLA_CON8 ; + __RW __u32 WLA_CON9 ; + __RW __u32 WLA_CON10; + __RW __u32 WLA_CON11; + __RW __u32 WLA_CON12; + __RW __u32 WLA_CON13; + __RW __u32 WLA_CON14; + __RW __u32 WLA_CON15; + __RW __u32 WLA_CON16; + __RW __u32 WLA_CON17; + __RW __u32 WLA_CON18; + __RW __u32 WLA_CON19; + __RW __u32 WLA_CON20; + __RW __u32 WLA_CON21; + __RW __u32 WLA_CON22; + __RW __u32 WLA_CON23; + __RW __u32 WLA_CON24; + __RW __u32 WLA_CON25; + __RW __u32 WLA_CON26; + __RW __u32 WLA_CON27; + __RW __u32 WLA_CON28; + __RW __u32 WLA_CON29; + __RO __u32 WLA_CON30; + __RO __u32 WLA_CON31; + __RO __u32 WLA_CON32; + __RO __u32 WLA_CON33; + __RO __u32 WLA_CON34; + __RO __u32 WLA_CON35; + __RO __u32 WLA_CON36; + __RO __u32 WLA_CON37; + __RO __u32 WLA_CON38; + __RO __u32 WLA_CON39; + __RO __u32 RESERVED0[0x30 - 0x27 - 1]; + __RW __u32 DAA_CON0; + __RW __u32 DAA_CON1; + __RW __u32 DAA_CON2; + __RW __u32 DAA_CON3; + __RO __u32 RESERVED1[0x37 - 0x33 - 1]; + __RW __u32 DAA_CON7; + __RW __u32 ADA_CON0; + __RW __u32 ADA_CON1; + __RW __u32 ADA_CON2; + __RW __u32 ADA_CON3; + __RW __u32 ADA_CON4; +} JL_ANA_TypeDef; + +#define JL_ANA_BASE (ls_base + map_adr(0x19, 0x00)) +#define JL_ANA ((JL_ANA_TypeDef *)JL_ANA_BASE) + +//............. 0x1c00 - 0x1eff............ +typedef struct { + __RW __u32 CON; + __WO __u32 BAUD; + __RW __u32 BUF; + __WO __u32 ADR; + __WO __u32 CNT; +} JL_SPI_TypeDef; + +#define JL_SPI0_BASE (ls_base + map_adr(0x1c, 0x00)) +#define JL_SPI0 ((JL_SPI_TypeDef *)JL_SPI0_BASE) + +#define JL_SPI1_BASE (ls_base + map_adr(0x1d, 0x00)) +#define JL_SPI1 ((JL_SPI_TypeDef *)JL_SPI1_BASE) + +#define JL_SPI2_BASE (ls_base + map_adr(0x1e, 0x00)) +#define JL_SPI2 ((JL_SPI_TypeDef *)JL_SPI2_BASE) + +//............. 0x2000 - 0x22ff............ +typedef struct { + __RW __u16 CON0; + __RW __u16 CON1; + __WO __u16 BAUD; + __RW __u8 BUF; + __RW __u32 OTCNT; + __RW __u32 TXADR; + __WO __u16 TXCNT; + __RW __u32 RXSADR; + __RW __u32 RXEADR; + __RW __u32 RXCNT; + __RO __u16 HRXCNT; +} JL_UART_TypeDef; + +#define JL_UART0_BASE (ls_base + map_adr(0x20, 0x00)) +#define JL_UART0 ((JL_UART_TypeDef *)JL_UART0_BASE) + +#define JL_UART1_BASE (ls_base + map_adr(0x21, 0x00)) +#define JL_UART1 ((JL_UART_TypeDef *)JL_UART1_BASE) + +#define JL_UART2_BASE (ls_base + map_adr(0x22, 0x00)) +#define JL_UART2 ((JL_UART_TypeDef *)JL_UART2_BASE) + +//............. 0x2400 - 0x24ff............ +typedef struct { + __RW __u16 CON0; + __RW __u8 BUF; + __WO __u8 BAUD; + __RW __u16 CON1; +} JL_IIC_TypeDef; + +#define JL_IIC_BASE (ls_base + map_adr(0x24, 0x00)) +#define JL_IIC ((JL_IIC_TypeDef *)JL_IIC_BASE) + +//............. 0x2800 - 0x28ff............ +typedef struct { + __RW __u32 CON; + __WO __u32 DAT0; + __WO __u32 DAT1; + __RW __u32 BUF; + __WO __u32 ADR; + __WO __u32 CNT; +} JL_PAP_TypeDef; + +#define JL_PAP_BASE (ls_base + map_adr(0x28, 0x00)) +#define JL_PAP ((JL_PAP_TypeDef *)JL_PAP_BASE) + +//............. 0x2b00 - 0x2bff............ +typedef struct { + __RW __u32 CON; + __RO __u32 SR_CNT; + __RW __u32 IO_CON; + __RW __u32 DMA_CON; + __RW __u32 DMA_LEN; + __WO __u32 DAT_ADR; + __WO __u32 INF_ADR; + __RO __u32 CSB0; + __RO __u32 CSB1; + __RO __u32 CSB2; + __RO __u32 CSB3; + __RO __u32 CSB4; + __RO __u32 CSB5; +} JL_SS_TypeDef; + +#define JL_SS_BASE (ls_base + map_adr(0x2b, 0x00)) +#define JL_SS ((JL_SS_TypeDef *)JL_SS_BASE) + +//............. 0x2c00 - 0x2cff............ +typedef struct { + __RW __u8 CON; + __RW __u8 DAT; +} JL_RDEC_TypeDef; + +#define JL_RDEC0_BASE (ls_base + map_adr(0x2c, 0x00)) +#define JL_RDEC0 ((JL_RDEC_TypeDef *)JL_RDEC0_BASE) + +#define JL_RDEC1_BASE (ls_base + map_adr(0x44, 0x00)) +#define JL_RDEC1 ((JL_RDEC_TypeDef *)JL_RDEC1_BASE) + +#define JL_RDEC2_BASE (ls_base + map_adr(0x45, 0x00)) +#define JL_RDEC2 ((JL_RDEC_TypeDef *)JL_RDEC2_BASE) + +//............. 0x2d00 - 0x2dff............ +typedef struct { + __RW __u16 CON; + __RW __u8 SMR; + __RW __u32 ADR; + __RW __u32 LEN; +} JL_PLNK_TypeDef; + +#define JL_PLNK_BASE (ls_base + map_adr(0x2d, 0x00)) +#define JL_PLNK ((JL_PLNK_TypeDef *)JL_PLNK_BASE) + + +//............. 0x2e00 - 0x2eff............ +typedef struct { + __RW __u16 CON0; + __RW __u16 CON1; + __RW __u8 CON2; + __RW __u8 CON3; + __WO __u32 ADR0; + __WO __u32 ADR1; + __WO __u32 ADR2; + __WO __u32 ADR3; + __WO __u16 LEN; +} JL_ALNK_TypeDef; + +#define JL_ALNK0_BASE (ls_base + map_adr(0x2e, 0x00)) +#define JL_ALNK0 ((JL_ALNK_TypeDef *)JL_ALNK0_BASE) + +#define JL_ALNK1_BASE (ls_base + map_adr(0x33, 0x00)) +#define JL_ALNK1 ((JL_ALNK_TypeDef *)JL_ALNK1_BASE) + +//............. 0x2f00 - 0x2fff............ +typedef struct { + __RW __u32(DAC_CON); + __RW __u32(DAC_ADR); + __RW __u16(DAC_LEN); + __RW __u16(DAC_PNS); + __RW __u16(DAC_HRP); + __RW __u16(DAC_SWP); + __RW __u16(DAC_SWN); + __RO __u32(RESERVED7); + __RW __u32(DAC_VL0); + __RW __u32(DAC_VL1); + __RW __u32(DAC_TM0); + __RW __u32(DAC_TM1); + __RW __s16 DAC_DTV; + __RW __s16 RESERVEDah; + __RW __s16 DAC_DTB; + __RW __s16 RESERVEDbh; + __WO __u32(DAC_DPD); + __WO __u16(DAC_COP); + __RW __u32(ADC_CON); + __RW __u32(ADC_ADR); + __RW __u16(ADC_LEN); + __RW __u16(ADC_PNS); + __RW __u16(ADC_HWP); + __RW __u16(ADC_SRP); + __RW __u16(ADC_SRN); +} JL_AUDIO_TypeDef; + +#define JL_AUDIO_BASE (ls_base + map_adr(0x2f, 0x00)) +#define JL_AUDIO ((JL_AUDIO_TypeDef *)JL_AUDIO_BASE) + +//............. 0x3000 - 0x30ff............ +typedef struct { + __RW __u32 TMR0_CON; + __RW __u32 TMR0_CNT; + __RW __u32 TMR0_PR; + __RW __u32 TMR1_CON; + __RW __u32 TMR1_CNT; + __RW __u32 TMR1_PR; + __RW __u32 TMR2_CON; + __RW __u32 TMR2_CNT; + __RW __u32 TMR2_PR; + __RW __u32 TMR3_CON; + __RW __u32 TMR3_CNT; + __RW __u32 TMR3_PR; + __RW __u32 TMR4_CON; + __RW __u32 TMR4_CNT; + __RW __u32 TMR4_PR; + __RW __u32 TMR5_CON; + __RW __u32 TMR5_CNT; + __RW __u32 TMR5_PR; + __RW __u32 TMR6_CON; + __RW __u32 TMR6_CNT; + __RW __u32 TMR6_PR; + __RW __u32 TMR7_CON; + __RW __u32 TMR7_CNT; + __RW __u32 TMR7_PR; + __RW __u32 FPIN_CON; + __RW __u32 CH0_CON0; + __RW __u32 CH0_CON1; + __RW __u32 CH0_CMPH; + __RW __u32 CH0_CMPL; + __RW __u32 CH1_CON0; + __RW __u32 CH1_CON1; + __RW __u32 CH1_CMPH; + __RW __u32 CH1_CMPL; + __RW __u32 CH2_CON0; + __RW __u32 CH2_CON1; + __RW __u32 CH2_CMPH; + __RW __u32 CH2_CMPL; + __RW __u32 CH3_CON0; + __RW __u32 CH3_CON1; + __RW __u32 CH3_CMPH; + __RW __u32 CH3_CMPL; + __RW __u32 CH4_CON0; + __RW __u32 CH4_CON1; + __RW __u32 CH4_CMPH; + __RW __u32 CH4_CMPL; + __RW __u32 CH5_CON0; + __RW __u32 CH5_CON1; + __RW __u32 CH5_CMPH; + __RW __u32 CH5_CMPL; + __RW __u32 CH6_CON0; + __RW __u32 CH6_CON1; + __RW __u32 CH6_CMPH; + __RW __u32 CH6_CMPL; + __RW __u32 CH7_CON0; + __RW __u32 CH7_CON1; + __RW __u32 CH7_CMPH; + __RW __u32 CH7_CMPL; + __RW __u32 MCPWM_CON0; +} JL_MCPWM_TypeDef; + +#define JL_MCPWM_BASE (ls_base + map_adr(0x30, 0x00)) +#define JL_MCPWM ((JL_MCPWM_TypeDef *)JL_MCPWM_BASE) + +//............. 0x3100 - 0x31ff............ +typedef struct { + __RW __u32 CON; + __RO __u32 RES; +} JL_ADC_TypeDef; + +#define JL_ADC_BASE (ls_base + map_adr(0x31, 0x00)) +#define JL_ADC ((JL_ADC_TypeDef *)JL_ADC_BASE) + +//............. 0x3200 - 0x32ff............ +typedef struct { + __RW __u32 RFLT_CON; +} JL_IR_TypeDef; + +#define JL_IR_BASE (ls_base + map_adr(0x32, 0x00)) +#define JL_IR ((JL_IR_TypeDef *)JL_IR_BASE) + +//............. 0x3300 - 0x33ff............ +// Used by ALNK1 + +//............. 0x3400 - 0x34ff............ +typedef struct { + __RW __u32 CON; +} JL_OSA_TypeDef; + +#define JL_OSA_BASE (ls_base + map_adr(0x34, 0x00)) +#define JL_OSA ((JL_OSA_TypeDef *)JL_OSA_BASE) + +//............. 0x3500 - 0x35ff............ +typedef struct { + __WO __u32 FIFO; + __RW __u32 REG; +} JL_CRC_TypeDef; + +#define JL_CRC_BASE (ls_base + map_adr(0x35, 0x00)) +#define JL_CRC ((JL_CRC_TypeDef *)JL_CRC_BASE) + + +//............. 0x3600 - 0x36ff............ +typedef struct { + __WO __u32 CON; + __RW __u32 NUM; +} JL_LRCT_TypeDef; + +#define JL_LRCT_BASE (ls_base + map_adr(0x36, 0x00)) +#define JL_LRCT ((JL_LRCT_TypeDef *)JL_LRCT_BASE) + +//............. 0x3700 - 0x37ff............ +typedef struct { + __WO __u32 CON; + __RO __u32 RESERVED[8 - 0 - 1]; + __WO __u32 ME; +} JL_EFUSE_TypeDef; + +#define JL_EFUSE_BASE (ls_base + map_adr(0x37, 0x00)) +#define JL_EFUSE ((JL_EFUSE_TypeDef *)JL_EFUSE_BASE) + +//............. 0x3b00 - 0x3bff............ +typedef struct { + __RO __u32 R64L; + __RO __u32 R64H; +} JL_RAND_TypeDef; + +#define JL_RAND_BASE (ls_base + map_adr(0x3b, 0x00)) +#define JL_RAND ((JL_RAND_TypeDef *)JL_RAND_BASE) + +//............. 0x3c00 - 0x3cff............ +typedef struct { + __RW __u32 CON0; + __RW __u16 CON1; + __RW __u32 ADR; +} JL_CTM_TypeDef; + +#define JL_CTM_BASE (ls_base + map_adr(0x3c, 0x00)) +#define JL_CTM ((JL_CTM_TypeDef *)JL_CTM_BASE) + + +//............. 0x3e00 - 0x3eff............ for p33 +typedef struct { + __RW __u32 PMU_CON; + __RW __u32 RTC_CON; + __RW __u32 SPI_CON; + __RW __u32 SPI_DAT; +} JL_P33_TypeDef; + +#define JL_P33_BASE (ls_base + map_adr(0x3e, 0x00)) +#define JL_P33 ((JL_P33_TypeDef *)JL_P33_BASE) + +//............. 0x3f00 - 0x3fff............ for dma +typedef struct { + __RW __u32 PRI0; + __RW __u32 PRI1; + __RW __u32 PRI2; + __RW __u32 PRI3; + __RW __u32 RESERVED0[0x08 - 0x03 - 1]; + __RW __u32 MSG; + __RO __u32 MSG_CH; + __RW __u32 RDL; + __RW __u32 RDH; + __RW __u32 WRL; + __RW __u32 WRH; + +} JL_DMA_TypeDef; + +#define JL_DMA_BASE (ls_base + map_adr(0x3f, 0x00)) +#define JL_DMA ((JL_DMA_TypeDef *)JL_DMA_BASE) + +//............. 0x4000 - 0x40ff............ + +//............. 0x4100 - 0x41ff............ for lsb peri(spi0/sd0) +typedef struct { + __RW __u8 ENCCON ; + __WO __u16 ENCKEY ; + __WO __u16 ENCADR ; +} JL_PERIENC_TypeDef; + +#define JL_PERIENC_BASE (ls_base + map_adr(0x41, 0x00)) +#define JL_PERIENC ((JL_PERIENC_TypeDef *)JL_PERIENC_BASE) + +//............. 0x4200 - 0x42ff............ for sbc +typedef struct { + __RW __u32 CON0; + __WO __u32 DEC_SRC_ADR; + __WO __u32 DEC_DST_ADR; + __WO __u32 DEC_PCM_WCNT; + __WO __u32 DEC_INBUF_LEN; + __WO __u32 ENC_SRC_ADR; + __WO __u32 ENC_DST_ADR; + __RO __u32 DEC_DST_BASE; + +} JL_SBC_TypeDef; + +#define JL_SBC_BASE (ls_base + map_adr(0x42, 0x00)) +#define JL_SBC ((JL_SBC_TypeDef *)JL_SBC_BASE) + +//............. 0x4300 - 0x43ff............ for aes +typedef struct { + __RW __u32 CON; + __RW __u32 DATIN; + __WO __u32 KEY; + __RW __u32 ENCRES0; + __RW __u32 ENCRES1; + __RW __u32 ENCRES2; + __RW __u32 ENCRES3; + __WO __u32 NONCE; + __WO __u8 HEADER; + __WO __u32 SRCADR; + __WO __u32 DSTADR; + __WO __u32 CTCNT; + __WO __u32 TAGLEN; + __RO __u32 TAGRES0; + __RO __u32 TAGRES1; + __RO __u32 TAGRES2; + __RO __u32 TAGRES3; +} JL_AES_TypeDef; + +#define JL_AES_BASE (ls_base + map_adr(0x43, 0x00)) +#define JL_AES ((JL_AES_TypeDef *)JL_AES_BASE) + +//............. 0x4400 - 0x44ff............ +//Used by rdec1 + +//............. 0x4500 - 0x45ff............ +//Used by rdec2 + + + + + + + +//............. 0x0100 - 0x01ff............ for port +typedef struct { + __RW __u32 OUT; + __RO __u32 IN; + __RW __u32 DIR; + __RW __u32 DIE; + __RW __u32 PU; + __RW __u32 PD; + __RW __u32 HD0; + __RW __u32 HD; + __RW __u32 DIEH; +} JL_PORT_FLASH_TypeDef; + +#define JL_PORTA_BASE (ls_base + map_adr(0x50, 0x00)) +#define JL_PORTA ((JL_PORT_FLASH_TypeDef *)JL_PORTA_BASE) + +#define JL_PORTB_BASE (ls_base + map_adr(0x50, 0x10)) +#define JL_PORTB ((JL_PORT_FLASH_TypeDef *)JL_PORTB_BASE) + +#define JL_PORTC_BASE (ls_base + map_adr(0x50, 0x20)) +#define JL_PORTC ((JL_PORT_FLASH_TypeDef *)JL_PORTC_BASE) + +#define JL_PORTD_BASE (ls_base + map_adr(0x50, 0x30)) +#define JL_PORTD ((JL_PORT_FLASH_TypeDef *)JL_PORTD_BASE) + +typedef struct { + __RW __u32 CON0; + __RW __u32 CON1; +} JL_USB_IO_TypeDef; + +#define JL_USB_IO_BASE (ls_base + map_adr(0x51, 0x00)) +#define JL_USB_IO ((JL_USB_IO_TypeDef *)JL_USB_IO_BASE) + + +typedef struct { + __RW __u32 CON0; + __RW __u32 CON1; + __RW __u32 CON2; + __RW __u32 CON3; +} JL_WAKEUP_TypeDef; + +#define JL_WAKEUP_BASE (ls_base + map_adr(0x51, 0x02)) +#define JL_WAKEUP ((JL_WAKEUP_TypeDef *)JL_WAKEUP_BASE) + +typedef struct { + __RW __u32 CON0; + __RW __u32 CON1; + __RW __u32 CON2; + __RW __u32 CON3; + __RW __u32 CON4; + __RW __u32 CON5; +} JL_IOMAP_TypeDef; + +#define JL_IOMAP_BASE (ls_base + map_adr(0x51, 0x06)) +#define JL_IOMAP ((JL_IOMAP_TypeDef *)JL_IOMAP_BASE) + +typedef struct { + __RW __u32 CON0; + __RW __u32 CON1; + __RW __u32 CON2; + __RW __u32 CON3; + __RW __u32 BRI_PRDL; + __RW __u32 BRI_PRDH; + __RW __u32 BRI_DUTY0L; + __RW __u32 BRI_DUTY0H; + __RW __u32 BRI_DUTY1L; + __RW __u32 BRI_DUTY1H; + __RW __u32 PRD_DIVL; + __RW __u32 DUTY0; + __RW __u32 DUTY1; + __RW __u32 DUTY2; + __RW __u32 DUTY3; + __RO __u32 CNT_RD; +} JL_PLED_TypeDef; + +#define JL_PLED_BASE (ls_base + map_adr(0x52, 0x00)) +#define JL_PLED ((JL_PLED_TypeDef *)JL_PLED_BASE) + +typedef struct { + __RW __u32 CON0; + __RW __u32 SEG_IOEN0; + __RW __u32 SEG_IOEN1; +} JL_LCD_TypeDef; + +#define JL_LCD_BASE (ls_base + map_adr(0x53, 0x00)) +#define JL_LCD ((JL_LCD_TypeDef *)JL_LCD_BASE) +//............. Full Speed USB ................... +#define FADDR 0x00 +#define POWER 0x01 +#define INTRTX1 0x02 +#define INTRTX2 0x03 +#define INTRRX1 0x04 +#define INTRRX2 0x05 +#define INTRUSB 0x06 +#define INTRTX1E 0x07 +#define INTRTX2E 0x08 +#define INTRRX1E 0x09 +#define INTRRX2E 0x0a +#define INTRUSBE 0x0b +#define FRAME1 0x0c +#define FRAME2 0x0d +#define INDEX 0x0e +#define DEVCTL 0x0f +#define TXMAXP 0x10 +#define CSR0 0x11 +#define TXCSR1 0x11 +#define TXCSR2 0x12 +#define RXMAXP 0x13 +#define RXCSR1 0x14 +#define RXCSR2 0x15 +#define COUNT0 0x16 +#define RXCOUNT1 0x16 +#define RXCOUNT2 0x17 +#define TXTYPE 0x18 +#define TXINTERVAL 0x19 +#define RXTYPE 0x1a +#define RXINTERVAL 0x1b + +#endif + + + + diff --git a/include_lib/driver/cpu/br23/asm/charge.h b/include_lib/driver/cpu/br23/asm/charge.h new file mode 100644 index 0000000..c0a5bc0 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/charge.h @@ -0,0 +1,113 @@ +#ifndef _CHARGE_H_ +#define _CHARGE_H_ + +#include "typedef.h" + +/*------充满电电压选择 3.869V-4.567V-------*/ +#define CHARGE_FULL_V_3869 0 +#define CHARGE_FULL_V_3907 1 +#define CHARGE_FULL_V_3946 2 +#define CHARGE_FULL_V_3985 3 +#define CHARGE_FULL_V_4026 4 +#define CHARGE_FULL_V_4068 5 +#define CHARGE_FULL_V_4122 6 +#define CHARGE_FULL_V_4157 7 +#define CHARGE_FULL_V_4202 8 +#define CHARGE_FULL_V_4249 9 +#define CHARGE_FULL_V_4295 10 +#define CHARGE_FULL_V_4350 11 +#define CHARGE_FULL_V_4398 12 +#define CHARGE_FULL_V_4452 13 +#define CHARGE_FULL_V_4509 14 +#define CHARGE_FULL_V_4567 15 +#define CHARGE_FULL_V_MAX 16 +/*****************************************/ + +/*充满电电流选择 2mA-30mA*/ +#define CHARGE_FULL_mA_2 0 +#define CHARGE_FULL_mA_5 1 +#define CHARGE_FULL_mA_7 2 +#define CHARGE_FULL_mA_10 3 +#define CHARGE_FULL_mA_15 4 +#define CHARGE_FULL_mA_20 5 +#define CHARGE_FULL_mA_25 6 +#define CHARGE_FULL_mA_30 7 + +/* + 充电电流选择 + 恒流:20-320mA +*/ +#define CHARGE_mA_20 0 +#define CHARGE_mA_40 1 +#define CHARGE_mA_60 2 +#define CHARGE_mA_80 3 +#define CHARGE_mA_100 4 +#define CHARGE_mA_120 5 +#define CHARGE_mA_140 6 +#define CHARGE_mA_160 7 +#define CHARGE_mA_180 8 +#define CHARGE_mA_200 9 +#define CHARGE_mA_220 10 +#define CHARGE_mA_240 11 +#define CHARGE_mA_260 12 +#define CHARGE_mA_280 13 +#define CHARGE_mA_300 14 +#define CHARGE_mA_320 15 + +#define CHARGE_CCVOL_V 300 //最低充电电流档转向用户设置充电电流档的电压转换点(AC693X无涓流充电,电池电压低时采用最低电流档,电池电压大于设置的值时采用用户设置的充电电流档) + +#define DEVICE_EVENT_FROM_CHARGE (('C' << 24) | ('H' << 16) | ('G' << 8) | '\0') + + +struct charge_platform_data { + u8 charge_en; //内置充电使能 + u8 charge_poweron_en; //开机充电使能 + u8 charge_full_V; //充满电电压大小 + u8 charge_full_mA; //充满电电流大小 + u8 charge_mA; //充电电流大小 + u8 ldo5v_pulldown_en; //ldo5v的100K下拉电阻使能,若充电舱需要更大的负载才能检测到插入时,请将该变量置1 + u16 ldo5v_off_filter; //ldo5v拔出过滤值,过滤时间 = (filter*2 + 20)ms,ldoin<0.6V且时间大于过滤时间才认为拔出,对于充满直接从5V掉到0V的充电仓,该值必须设置成0,对于充满由5V先掉到0V之后再升压到xV的充电仓,需要根据实际情况设置该值大小 +}; + +#define CHARGE_PLATFORM_DATA_BEGIN(data) \ + struct charge_platform_data data = { + +#define CHARGE_PLATFORM_DATA_END() \ +}; + + +enum { + CHARGE_FULL_33V = 0, //充满标记位 + TERMA_33V, //模拟测试信号 + VBGOK_33V, //模拟测试信号 + CICHARGE_33V, //涓流转恒流信号 +}; + +enum { + CHARGE_EVENT_CHARGE_START, + CHARGE_EVENT_CHARGE_CLOSE, + CHARGE_EVENT_CHARGE_FULL, + CHARGE_EVENT_LDO5V_KEEP, + CHARGE_EVENT_LDO5V_IN, + CHARGE_EVENT_LDO5V_OFF, + CHARGE_EVENT_USB_CHARGE_IN, + CHARGE_EVENT_USB_CHARGE_OFF, +}; + + +extern void set_charge_online_flag(u8 flag); +extern u8 get_charge_online_flag(void); +extern u8 get_charge_poweron_en(void); +extern void charge_start(void); +extern void charge_close(void); +extern u8 get_charge_mA_config(void); +extern void set_charge_mA(u8 charge_mA); +extern u8 get_ldo5v_pulldown_en(void); +extern u8 get_ldo5v_online_hw(void); +extern u8 get_lvcmp_det(void); +extern void charge_check_and_set_pinr(u8 mode); +extern u16 get_charge_full_value(void); +int charge_api_init(void *arg); +extern const struct device_operations charge_dev_ops; + +#endif //_CHARGE_H_ diff --git a/include_lib/driver/cpu/br23/asm/chargestore.h b/include_lib/driver/cpu/br23/asm/chargestore.h new file mode 100644 index 0000000..bd0e053 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/chargestore.h @@ -0,0 +1,53 @@ +#ifndef __BR22_CHARGESTORE_H__ +#define __BR22_CHARGESTORE_H__ + +enum { + CMD_COMPLETE, + CMD_RECVDATA, +}; + +enum { + MODE_RECVDATA, + MODE_SENDDATA, +}; + +enum { + TYPE_NORMAL, + TYPE_F95, +}; + +struct chargestore_platform_data { + u32 baudrate; + u32 io_port; + u8 uart_irq; + void (*init)(const struct chargestore_platform_data *); + void (*open)(u8 mode); + void (*close)(void); + void (*write)(u8 *, u8); +}; + +#define CHARGESTORE_PLATFORM_DATA_BEGIN(data) \ + static const struct chargestore_platform_data data = { + +#define CHARGESTORE_PLATFORM_DATA_END() \ + .baudrate = 9600, \ + .init = chargestore_init, \ + .open = chargestore_open, \ + .close = chargestore_close, \ + .write = chargestore_write, \ +}; + +extern void chargestore_open(u8 mode); +extern void chargestore_close(void); +extern void chargestore_write(u8 *data, u8 len); +extern void chargestore_init(const struct chargestore_platform_data *); +extern void chargestore_set_update_ram(void); +extern u8 chargestore_get_det_level(u8 chip_type); + +//app层使用的接口 +extern void chargestore_api_close(void); +extern int chargestore_api_write(u8 *buf, u8 len); +extern void chargestore_api_init(const struct chargestore_platform_data *arg); +extern void chargestore_api_wait_complete(void); + +#endif diff --git a/include_lib/driver/cpu/br23/asm/clock.h b/include_lib/driver/cpu/br23/asm/clock.h new file mode 100644 index 0000000..c00b331 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/clock.h @@ -0,0 +1,122 @@ +#ifndef _CPU_CLOCK_ +#define _CPU_CLOCK_ + +#include "typedef.h" + +#include "clock_hw.h" +#include "asm/clock_define.h" + +/* +typedef enum { + ///原生时钟源作系统时钟源 + SYS_CLOCK_INPUT_RC, + SYS_CLOCK_INPUT_BT_OSC, //BTOSC 双脚(12-26M) + SYS_CLOCK_INPUT_RTOSCH, + SYS_CLOCK_INPUT_RTOSCL, + SYS_CLOCK_INPUT_PAT, + + ///衍生时钟源作系统时钟源 + SYS_CLOCK_INPUT_PLL_RCL, + SYS_CLOCK_INPUT_PLL_RCH, + SYS_CLOCK_INPUT_PLL_BT_OSC, + SYS_CLOCK_INPUT_PLL_RTOSCH, + SYS_CLOCK_INPUT_PLL_PAT, +} SYS_CLOCK_INPUT; +*/ + +typedef enum { + SYS_ICLOCK_INPUT_BTOSC, //BTOSC 双脚(12-26M) + SYS_ICLOCK_INPUT_RTOSCH, + SYS_ICLOCK_INPUT_RTOSCL, + SYS_ICLOCK_INPUT_PAT, +} SYS_ICLOCK_INPUT; + +typedef enum { + PA0_CLOCK_OUTPUT = 0, + PA0_CLOCK_OUT_BT_OSC, + PA0_CLOCK_OUT_RTOSCH, + PA0_CLOCK_OUT_NULL, + + PA0_CLOCK_OUT_LSB = 4, + PA0_CLOCK_OUT_HSB, + PA0_CLOCK_OUT_SFC, + PA0_CLOCK_OUT_PLL, +} PA0_CLK_OUT; + +typedef enum { + PB8_CLOCK_OUTPUT = 0, + PB8_CLOCK_OUT_RC, + PB8_CLOCK_OUT_LRC, + PB8_CLOCK_OUT_NULL, + + PB8_CLOCK_OUT_PLL75M = 4, + PB8_CLOCK_OUT_XOSC_FSCK, + PB8_CLOCK_OUT_PLL320, + PB8_CLOCK_OUT_PLL107, +} PB8_CLK_OUT; + +/* + * system enter critical and exit critical handle + * */ +struct clock_critical_handler { + void (*enter)(); + void (*exit)(); +}; + +#define CLOCK_CRITICAL_HANDLE_REG(name, enter, exit) \ + const struct clock_critical_handler clock_##name \ + SEC_USED(.clock_critical_txt) = {enter, exit}; + +extern struct clock_critical_handler clock_critical_handler_begin[]; +extern struct clock_critical_handler clock_critical_handler_end[]; + +#define list_for_each_loop_clock_critical(h) \ + for (h=clock_critical_handler_begin; hCLK_CON0, 0, 1, x) +#define RCH_EN(x) SFR(JL_CLOCK->CLK_CON0, 1, 1, x) +//for MACRO - RCH_EN +enum { + RCH_EN_250K = 0, + RCH_EN_16M, +}; + +#define TEST_SEL(x) SFR(JL_CLOCK->CLK_CON0, 2, 2, x) +//for MACRO - TS_SEL +enum { + TS_SEL_IN_MAIN = 0, + TS_SEL_IN_PAT, +}; + +#define OSC_CLOCK_IN(x) SFR(JL_CLOCK->CLK_CON0, 4, 2, x) +//for MACRO - OSC_CLOCK_IN +enum { + OSC_CLOCK_IN_BT_OSC = 0, + OSC_CLOCK_IN_XOSC_FSCK, + OSC_CLOCK_IN_RTOSC_L, + OSC_CLOCK_IN_PAT, +}; + +#define MAIN_CLOCK_SEL(x) SFR(JL_CLOCK->CLK_CON0, 6, 3, x) +//for MACRO - CLOCK_IN +enum { + MAIN_CLOCK_IN_RC = 0, + + MAIN_CLOCK_IN_BTOSC = 4, + MAIN_CLOCK_IN_RESERVED, + MAIN_CLOCK_IN_RTOSC_L, + MAIN_CLOCK_IN_PLL, +}; + +#define SFR_MODE(x) SFR(JL_CLOCK->CLK_CON0, 9, 1, x) +enum { + SFR_CLOCK_IDLE = 0, + SFR_CLOCK_ALWAYS_ON, +}; +#define PA0_CLOCK_OUT(x) SFR(JL_CLOCK->CLK_CON0, 10, 3, x) +#define PB8_CLOCK_OUT(x) SFR(JL_CLOCK->CLK_CON0, 13, 3, x) + + +#define USB_CLOCK_IN(x) SFR(JL_CLOCK->CLK_CON1, 0, 2, x) + +//for MACRO - USB_CLOCK_IN +enum { + USB_CLOCK_IN_PLL48M = 0, + USB_CLOCK_IN_OSC, + USB_CLOCK_IN_LSB, + USB_CLOCK_IN_DISABLE, +}; +#define AUDIO_CLOCK_IN(x) SFR(JL_CLOCK->CLK_CON1, 2, 2, x) +//for MACRO - AUDIO_CLOCK_IN +enum { + AUDIO_CLOCK_IN_PLL48M = 0, + AUDIO_CLOCK_IN_OSC, + AUDIO_CLOCK_IN_LSB, + AUDIO_CLOCK_IN_DISABLE, +}; +#define GPCNT_CLOCK_IN(x) SFR(JL_CLOCK->CLK_CON1, 4, 3, x) +//for MACRO - DAC_CLOCK_IN +enum { + GPCNT_CLOCK_IN_LSB = 0, + GPCNT_CLOCK_IN_OSC, + GPCNT_CLOCK_IN_CAP_MUX, + GPCNT_CLOCK_IN_CLK_MUX, + GPCNT_CLOCK_IN_NULL0, + GPCNT_CLOCK_IN_AUDIO, + GPCNT_CLOCK_IN_WL, + GPCNT_CLOCK_IN_USB, +}; + +#define UART_CLOCK_IN(x) SFR(JL_CLOCK->CLK_CON1, 10, 2, x) +//for MACRO - UART_CLOCK_IN +enum { + UART_CLOCK_IN_PLL48M = 0, + UART_CLOCK_IN_OSC, + UART_CLOCK_IN_LSB, + UART_CLOCK_IN_DISABLE, +}; +#define BT_CLOCK_IN(x) SFR(JL_CLOCK->CLK_CON1, 14, 2, x) +//for MACRO - BT_CLOCK_IN +enum { + BT_CLOCK_IN_PLL48M = 0, + BT_CLOCK_IN_HSB, + BT_CLOCK_IN_LSB, + BT_CLOCK_IN_DISABLE, +}; + +#define SFC_SCKE(x) SFR(JL_CLOCK->CLK_CON1, 17, 1, x) + +#define WL2ADC_CLOCK_IN(x) SFR(JL_CLOCK->CLK_CON1, 18, 2, x) +//for MACRO - WL2ADC_CLOCK_IN +enum { + WL2ADC_CLOCK_IN_PLL96M = 0, + WL2ADC_CLOCK_IN_HSB, + WL2ADC_CLOCK_IN_LSB, + WL2ADC_CLOCK_IN_DISABLE, +}; + +#define WL2DAC_CLOCK_IN(x) SFR(JL_CLOCK->CLK_CON1, 21, 2, x) +//for MACRO - WL2DAC_CLOCK_IN +enum { + WL2DAC_CLOCK_IN_PLL96M = 0, + WL2DAC_CLOCK_IN_HSB, + WL2DAC_CLOCK_IN_LSB, + WL2DAC_CLOCK_IN_DISABLE, +}; + + +#define SFC_CLOCK_DELAY(x) SFR(JL_CLOCK->CLK_CON1, 28, 2, x) + + +#define PLL_SYS_SEL(x) SFR(JL_CLOCK->CLK_CON2, 0, 2, x) +//for MACRO - PLL_SYS_SEL +enum { + PLL_SYS_SEL_PLL192M = 0, + PLL_SYS_SEL_PLL137M, + PLL_SYS_SEL_PLL320M, + PLL_SYS_SEL_PLL480M, +}; +#define PLL_SYS_DIV(x) SFR(JL_CLOCK->CLK_CON2, 2, 4, x) +//for MACRO - PLL_SYS_DIV +enum { + PLL_SYS_DIV1 = 0, + PLL_SYS_DIV3, + PLL_SYS_DIV5, + PLL_SYS_DIV7, + + PLL_SYS_DIV1X2 = 4, + PLL_SYS_DIV3X2, + PLL_SYS_DIV5X2, + PLL_SYS_DIV7X2, + + PLL_SYS_DIV1X4 = 8, + PLL_SYS_DIV3X4, + PLL_SYS_DIV5X4, + PLL_SYS_DIV7X4, + + PLL_SYS_DIV1X8 = 12, + PLL_SYS_DIV3X8, + PLL_SYS_DIV5X8, + PLL_SYS_DIV7X8, +}; + +#define PLL_ALNK_EN(x) SFR(JL_CLOCK->CLK_CON2, 6, 1, x) +#define PLL_ALNK_SEL(x) SFR(JL_CLOCK->CLK_CON2, 7, 1, x) +//for MACRO - PLL_ALNK_SEL +enum { + PLL_ALNK_192M_DIV17 = 0, + PLL_ALNK_480M_DIV39, +}; + +#define PLL_FM_SEL(x) SFR(JL_CLOCK->CLK_CON2, 12, 2, x) +//for MACRO - PLL_APC_SEL +enum { + PLL_APC_SEL_PLL192M = 0, + PLL_APC_SEL_PLL137M, + PLL_APC_SEL_PLL107M, + PLL_APC_SEL_DISABLE, +}; +#define PLL_FM_DIV(x) SFR(JL_CLOCK->CLK_CON2, 14, 4, x) +//for MACRO - PLL_APC_DIV +enum { + PLL_FM_DIV1 = 0, + PLL_FM_DIV3, + PLL_FM_DIV5, + PLL_FM_DIV7, + + PLL_FM_DIV1X2 = 4, + PLL_FM_DIV3X2, + PLL_FM_DIV5X2, + PLL_FM_DIV7X2, + + PLL_FM_DIV1X4 = 8, + PLL_FM_DIV3X4, + PLL_FM_DIV5X4, + PLL_FM_DIV7X4, + + PLL_FM_DIV1X8 = 12, + PLL_FM_DIV3X8, + PLL_FM_DIV5X8, + PLL_FM_DIV7X8, +}; + +#define DPLL_UDEN(x) SFR(JL_CLOCK->CLK_CON2, 30, 1, x) + +// #define DSP_RESET(x) SFR(JL_CLOCK->CLK_CON3, 0, 1, x) + +// #define DSP_POWER_RESET(x) SFR(JL_CLOCK->CLK_CON3, 1, 1, x) + +#define PLL_EN(x) SFR(JL_CLOCK->PLL_CON, 0, 1, x) +#define PLL_REST(x) SFR(JL_CLOCK->PLL_CON, 1, 1, x) +#define PLL_DIVn(x) SFR(JL_CLOCK->PLL_CON, 2, 7, x) +#define PLL_REF_SEL(x) SFR(JL_CLOCK->PLL_CON, 9, 1, x) +//for MACRO - PLL_REF_SEL +enum { + PLL_REF_SEL_BTOSC = 0, //btosc + PLL_REF_SEL_RCLK, +}; + +#define PLL_TEST(x) SFR(JL_CLOCK->PLL_CON, 10, 1, x) + +#define PLL_DSMS(x) SFR(JL_CLOCK->PLL_CON, 11, 1, x) +#define PLL_TSEL(x) SFR(JL_CLOCK->PLL_CON, 12, 4, x) +#define PLL_RSEL(x) SFR(JL_CLOCK->PLL_CON, 16, 2, x) +#define PLL_MSEL(x) SFR(JL_CLOCK->PLL_CON, 18, 2, x) + +#define PLL_DIVS(x) SFR(JL_CLOCK->PLL_CON, 20, 2, x) +#define PLL_PFD(x) SFR(JL_CLOCK->PLL_CON, 22, 2, x) +#define PLL_ICP(x) SFR(JL_CLOCK->PLL_CON, 24, 3, x) +#define PLL_LPFR2(x) SFR(JL_CLOCK->PLL_CON, 27, 3, x) + + +#define PLL_REF_SEL1(x) SFR(JL_CLOCK->PLL_CON, 30, 2, x) +//for MACRO - PLL_RSEL +enum { + PLL_RSEL_RCLK = 0, // + PLL_RSEL_RCH, + PLL_RSEL_DPLL_CLK, + PLL_RSEL_PAT_CLK, +}; + +#define PLL_FBDS(x) SFR(JL_CLOCK->PLL_CON1, 0, 12, x) +#define PLL_IVCO(x) SFR(JL_CLOCK->PLL_CON1, 12, 3, x) +#define PLL_LDO_BYPASS(x) SFR(JL_CLOCK->PLL_CON1, 15, 1, x) +#define PLL_TSSEL(x) SFR(JL_CLOCK->PLL_CON1, 16, 2, x) +#define PLL_TSOE(x) SFR(JL_CLOCK->PLL_CON1, 18, 1, x) + +#define PLL_LDO12A(x) SFR(JL_CLOCK->PLL_CON1, 20, 2, x) +#define PLL_DIVn_EN(x) SFR(JL_CLOCK->PLL_CON1, 22, 2, x) +//for MACRO - PLL_DIVn_EN +enum { + PLL_DIVn_EN_X2 = 0, + PLL_DIVn_DIS_DIV1, + PLL_DIVn_EN2_33, +}; + +#define PLL_CLK480M_OE(x) SFR(JL_CLOCK->PLL_CON1, 24, 1, x) +#define PLL_CLK320M_OE(x) SFR(JL_CLOCK->PLL_CON1, 25, 1, x) +#define PLL_CLK192M_OE(x) SFR(JL_CLOCK->PLL_CON1, 26, 1, x) +#define PLL_CLK137M_OE(x) SFR(JL_CLOCK->PLL_CON1, 27, 1, x) +#define PLL_CLK107M_OE(x) SFR(JL_CLOCK->PLL_CON1, 28, 1, x) + +#define PLL_DAC_OE(x) SFR(JL_CLOCK->PLL_CON1, 30, 1, x) + +#define HSB_CLK_DIV(x) SFR(JL_CLOCK->SYS_DIV, 0, 8, x) +#define LSB_CLK_DIV(x) SFR(JL_CLOCK->SYS_DIV, 8, 3, x) +#define SFC_CLK_DIV(x) SFR(JL_CLOCK->SYS_DIV, 12, 3, x) + + +#define GPCNT_EN(x) SFR(JL_GPCNT->CON, 0, 1, x) +#define GPCNT_CSS(x) SFR(JL_GPCNT->CON, 1, 3, x) +//for MACRO - GPCNT_CSS +enum { + GPCNT_CSS_LSB = 0, + GPCNT_CSS_OSC, + GPCNT_CSS_CAP_MUX, + GPCNT_CSS_CLK_MUX, + GPCNT_CSS_GPCFD, + GPCNT_CSS_RING, + GPCNT_CSS_PLL480M, + GPCNT_CSS_IRFLT, +}; + +#define GPCNT_CLR_PEND(x) SFR(JL_GPCNT->CON, 6, 1, x) +#define GPCNT_GTS(x) SFR(JL_GPCNT->CON, 8, 4, x) + +#define GPCNT_GSS(x) SFR(JL_GPCNT->CON, 12, 3, x) +//for MACRO - GPCNT_CSS +enum { + GPCNT_GSS_LSB = 0, + GPCNT_GSS_OSC, + GPCNT_GSS_CAP_MUX, + GPCNT_GSS_CLK_MUX, + GPCNT_GSS_GPCFD, + GPCNT_GSS_RING, + GPCNT_GSS_PLL480M, + GPCNT_GSS_IRFLT, +}; + +/********************************************************************************/ + +#define lrc_con1_init \ + /* */ (0 << 7) |\ + /* */ (0 << 6) |\ + /* */ (0 << 5) |\ + /*RC32K_CAP_S2_33v */ (1 << 4) |\ + /*RC32K_CAP_S1_33v */ (0 << 3) |\ + /*RC32K_CAP_S0_33v */ (0 << 2) |\ + /* */ (0 << 1) |\ + /*RC32K_RNPS_S1_33v */ (0 << 0) + +#define lrc_con0_init \ + /*RC32K_RNPS_S0_33v */ (1 << 7) |\ + /* */ (0 << 6) |\ + /*RC32K_RPPS_S1_33v */ (0 << 5) |\ + /*RC32K_RPPS_S0_33v */ (1 << 4) |\ + /* */ (0 << 3) |\ + /* */ (0 << 2) |\ + /*RC32K_RN_TRIM_33v */ (0 << 1) |\ + /*RC32K_EN_33v */ (1 << 0) + + +#define lrc_pll_con1 \ + /*ref_sel 2 bit*/ ( 0b00 << 30 ) |\ + /*SYSPLL_CKOUT_D4P5_OE 1 bit*/ ( 1 << 28 ) |\ + /*SYSPLL_CKOUT_D3P5_OE 1 bit*/ ( 1 << 27 ) |\ + /*SYSPLL_CKOUT_D2P5_OE 1 bit*/ ( 1 << 26 ) |\ + /*SYSPLL_CKOUT_D1P5_OE 1 bit*/ ( 1 << 25 ) |\ + /*SYSPLL_CKOUT_D1_OE 1 bit*/ ( 1 << 24 ) |\ + /*SYSPLL_REFDSEN(1-0 2 bit*/ ( 0b01 << 22 ) |\ + /*SYSPLL_LDO12A_S(1-0) 2 bit*/ ( 0b10 << 20 ) |\ + /*reserved 1 bit*/ ( 0 << 19 ) |\ + /*SYSPLL_TEST_EN 1 bit*/ ( 0 << 18 ) |\ + /*SYSPLL_TEST_S(1-0) 2 bit*/ ( 0 << 16 ) |\ + /*SYSPLL_LDO_BYPASS 1 bit*/ ( 0 << 15 ) |\ + /*SYSPLL_IVCOS(2-0) 3 bit*/ ( 0b011 << 12 ) |\ + /*SYSPLL_DS(11-0) 12 bit*/ (((480000000/(32000*8))-2)<< 0) + +#define lrc_pll_con \ + /*SYSPLL_LPFR2S(1-0) 3 bit*/ ( 0b111 << 27 ) |\ + /*SYSPLL_ICPS(1-0) 3 bit*/ ( 0 << 24 ) |\ + /*SYSPLL_PFDS(1-0) 2 bit*/ ( 1 << 22 ) |\ + /*SYSPLL_DIVS(1-0) 2 bit*/ ( 0 << 20 ) |\ + /*SYSPLL_TSCK480M_OE 1 bit*/ ( 0 << 10 ) |\ + /*SYSPLL_REFSEL 1 bit*/ ( 1 << 9 ) |\ + /*SYSPLL_REFDS(6-0) 7 bit*/ ( 0 << 2 ) |\ + /*SYSPLL_RN 1 bit*/ ( 0 << 1 ) |\ + /*SYSPLL_EN 1 bit*/ ( 0 << 0 ) + + +#endif +#endif diff --git a/include_lib/driver/cpu/br23/asm/cpu.h b/include_lib/driver/cpu/br23/asm/cpu.h new file mode 100644 index 0000000..484cd1a --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/cpu.h @@ -0,0 +1,268 @@ + +#ifndef ASM_CPU_H +#define ASM_CPU_H + + +#include "br23.h" +#include "csfr.h" + +#ifndef __ASSEMBLY__ + +typedef unsigned char u8, bool, BOOL; +typedef char s8; +typedef unsigned short u16; +typedef signed short s16; +typedef unsigned int u32; +typedef signed int s32; +typedef unsigned long long u64; +typedef u32 FOURCC; +typedef long long s64; +typedef unsigned long long u64; + + +#endif + + +#define ___trig __asm__ volatile ("trigger") + + +#ifndef BIG_ENDIAN +#define BIG_ENDIAN 0x3021 +#endif +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 0x4576 +#endif +#define CPU_ENDIAN LITTLE_ENDIAN + + +#define CPU_CORE_NUM 1 + +///屏蔽的优先级 +#define IRQ_IPMASK 6 + +#define CPU_TASK_CLR(a) +#define CPU_TASK_SW(a) \ + do { \ + q32DSP(0)->ILAT_SET |= BIT(7-a); \ + clr_wdt(); \ + } while (0) + + +#define CPU_INT_NESTING 2 + + +#ifndef __ASSEMBLY__ + +extern void clr_wdt(); + +#if CPU_CORE_NUM > 1 +static inline int current_cpu_id() +{ + unsigned id; + asm volatile("%0 = cnum" : "=r"(id) ::); + return id ; +} +#else +static inline int current_cpu_id() +{ + return 0; +} +#endif + +static inline int cpu_in_irq() +{ + int flag; + __asm__ volatile("%0 = icfg" : "=r"(flag)); + return flag & 0xff; +} + +static inline int cpu_irq_disabled() +{ + int flag; + __asm__ volatile("%0 = icfg" : "=r"(flag)); + return (flag & 0x300) != 0x300 || ((q32DSP(0)->IPMASK) == IRQ_IPMASK); +} + +#if 0 +static inline int data_sat_s16(int ind) +{ + if (ind > 32767) { + ind = 32767; + } else if (ind < -32768) { + ind = -32768; + } + return ind; +} + +#else +__attribute__((always_inline)) +static int data_sat_s16(int ind) +{ + __asm__ volatile( + " %0 = sat16(%0)(s) \t\n" + : "=&r"(ind) + : "0"(ind) + :); + return ind; +} +#endif + + +static inline u32 reverse_u32(u32 data32) +{ +#if 0 + u8 *dataptr = (u8 *)(&data32); + data32 = (((u32)dataptr[0] << 24) | ((u32)dataptr[1] << 16) | ((u32)dataptr[2] << 8) | (u32)dataptr[3]); +#else + __asm__ volatile("%0 = rev8(%0) \t\n" : "=&r"(data32) : "0"(data32) :); +#endif + return data32; +} + +static inline u32 reverse_u16(u16 data16) +{ + u32 retv; +#if 0 + u8 *dataptr = (u8 *)(&data16); + retv = (((u32)dataptr[0] << 8) | ((u32)dataptr[1])); +#else + retv = ((u32)data16) << 16; + __asm__ volatile("%0 = rev8(%0) \t\n" : "=&r"(retv) : "0"(retv) :); +#endif + return retv; +} + +static inline u32 rand32() +{ + return JL_RAND->R64L; +} + +#define __asm_sine(s64, precision) \ + ({ \ + u64 ret; \ + u8 sel = (0x00 << 2) | (precision); \ + __asm__ volatile ("%0 = copex(%1) (%2)" : "=r"(ret) : "r"(s64), "i"(sel)); \ + ret; \ + }) + +void p33_soft_reset(void); +static inline void cpu_reset(void) +{ + // JL_CLOCK->PWR_CON |= (1 << 4); + p33_soft_reset(); +} + +#define __asm_csync() \ + do { \ + asm volatile("csync;"); \ + } while (0) + +#include "asm/irq.h" +#include "generic/printf.h" +#include "system/generic/log.h" + + +#define arch_atomic_read(v) \ + ({ \ + __asm_csync(); \ + (*(volatile int *)&(v)->counter); \ + }) +#if 0 +extern volatile int cpu_lock_cnt[]; +extern volatile int irq_lock_cnt[]; + +static inline void local_irq_disable() +{ + __builtin_pi32v2_cli(); + irq_lock_cnt[current_cpu_id()]++; + q32DSP(0)->IPMASK = 7; + __builtin_pi32v2_sti(); +} + + +static inline void local_irq_enable() +{ + if (--irq_lock_cnt[current_cpu_id()] == 0) { + q32DSP(0)->IPMASK = 0; + // __builtin_pi32v2_sti(); + } +} +#else + +extern void local_irq_disable(); +extern void local_irq_enable(); +extern void __local_irq_enable(); +#endif + + +#define arch_spin_trylock(lock) \ + do { \ + __asm_csync(); \ + while ((lock)->rwlock); \ + (lock)->rwlock = 1; \ + }while(0) + +#define arch_spin_lock(lock) \ + do { \ + int ret = false; \ + __asm_csync(); \ + if (!(lock)->rwlock) { \ + ret = true; \ + (lock)->rwlock = 1; \ + } \ + if (ret) \ + break; \ + }while(1) + +#define arch_spin_unlock(lock) \ + do { \ + (lock)->rwlock = 0; \ + }while(0) + + + + +#define CPU_SR_ALLOC() \ +// int flags + +#define CPU_CRITICAL_ENTER() \ + do { \ + local_irq_disable(); \ + __asm_csync(); \ + }while(0) + + +#define CPU_CRITICAL_EXIT() \ + do { \ + local_irq_enable(); \ + }while(0) + + + +extern void cpu_assert_debug(); +extern const int config_asser; + +#define ASSERT(a,...) \ + do { \ + if(config_asser){\ + if(!(a)){ \ + printf("file:%s, line:%d", __FILE__, __LINE__); \ + printf("ASSERT-FAILD: "#a" "__VA_ARGS__); \ + cpu_assert_debug(); \ + } \ + }else {\ + if(!(a)){ \ + cpu_reset(); \ + }\ + }\ + }while(0); + + + + + +#endif //__ASSEMBLY__ + + +#endif + diff --git a/include_lib/driver/cpu/br23/asm/crc16.h b/include_lib/driver/cpu/br23/asm/crc16.h new file mode 100644 index 0000000..35c7ae8 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/crc16.h @@ -0,0 +1,35 @@ +#ifndef __CPU_CRC16_H__ +#define __CPU_CRC16_H__ + + +#include "typedef.h" + + + +u16 CRC16(const void *ptr, u32 len); + +/* i_val: CRC校验初值 */ +u16 CRC16_with_initval(const void *ptr, u32 len, u16 i_val); + +u16 CRC16_with_code(const void *ptr, u32 len, u16 code); + +void spi_crc16_set(u16 crc); +u16 spi_crc16_get(void); + +void CrcDecode(void *buf, u16 len); + +u16 get_page_efuse(u32 page, u32 delay_cnt); +void init_enc_key(u8 cmd); +u32 get_sfc_enc_key(void); + + + + + + + + + +#endif + + diff --git a/include_lib/driver/cpu/br23/asm/csfr.h b/include_lib/driver/cpu/br23/asm/csfr.h new file mode 100644 index 0000000..1663baf --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/csfr.h @@ -0,0 +1,313 @@ +//*********************************************************************************// +// Module name : csfr.h // +// Description : q32DSP core sfr define // +// By Designer : zequan_liu // +// Dat changed : // +//*********************************************************************************// + +#ifndef __Q32DSP_CSFR__ +#define __Q32DSP_CSFR__ + +#define __RW volatile // read write +#define __RO volatile const // only read +#define __WO volatile // only write + +#define __u8 unsigned int // u8 to u32 special for struct +#define __u16 unsigned int // u16 to u32 special for struct +#define __u32 unsigned int + +//********************************************************************************* +// +// hcore_sfr +// +//********************************************************************************* + +#define csfr_base 0x100000 + +//............. 0x0000 - 0x00ff............ +// typedef struct { +// __RO __u32 SOFT_INT; +// __WO __u32 SOFT_SET; +// __WO __u32 SOFT_CLR; +// __RW __u32 CON; +// } JL_CMNG_TypeDef; +// +// #define JL_CMNG_BASE (csfr_base + map_adr(0x00, 0x00)) +// #define JL_CMNG ((JL_CMNG_TypeDef *)JL_CMNG_BASE) + +//............. 0x0100 - 0x01ff............ +typedef struct { + __RW __u32 CON; + __RW __u32 KEY; +} JL_SDTAP_TypeDef; + +#define JL_SDTAP_BASE (csfr_base + map_adr(0x01, 0x00)) +#define JL_SDTAP ((JL_SDTAP_TypeDef *)JL_SDTAP_BASE) + +//............. 0x0200 - 0x02ff............ +typedef struct { + __RW __u32 MBISTCTL; + __RO __u32 MBISTSOGO; +} JL_MBIS_TypeDef; + +#define JL_MBIS_BASE (csfr_base + map_adr(0x02, 0x00)) +#define JL_MBIS ((JL_MBIS_TypeDef *)JL_MBIS_BASE) + +//............. 0x0300 - 0x03ff............ for mmu +/* __attribute__((packed)) +typedef struct { + short page: 13; + short vld: 1; + short reserved: 2; +} JL_MMU_TLB1_TypeDef; + +#define JL_MMU_TLB1 ((JL_MMU_TLB1_TypeDef *)(JL_MMU->TLB1_BEG)) */ + +typedef struct { + __RW __u32 CON; + __RW __u32 TLB1_BEG; + __RW __u32 TLB1_END; +} JL_MMU_TypeDef; + +#define JL_MMU_BASE (csfr_base + map_adr(0x03, 0x00)) +#define JL_MMU ((JL_MMU_TypeDef *)JL_MMU_BASE) + +//............. 0x1000 - 0x10ff............ for debug +typedef struct { + __RW __u32 CON; + __RW __u32 RING_OSC; + __RW __u32 CPASS_CON; + __RW __u32 CPASS_ADRH; + __RW __u32 CPASS_ADRL; + __RW __u32 CPASS_BUF_LAST; + __RW __u32 CPREFETCH_ADRH; + __RW __u32 CPREFETCH_ADRL; + __RO __u32 CACHE_MSG_CH; +} JL_DSP_TypeDef; + +#define JL_DSP_BASE (csfr_base + map_adr(0x10, 0x00)) +#define JL_DSP ((JL_DSP_TypeDef*)JL_DSP_BASE) + +typedef struct { + __RW __u32 DSP_BF_CON; + __RW __u32 WR_EN; + __RO __u32 MSG; + __WO __u32 MSG_CLR; + __RW __u32 DSP_EX_LIMH; + __RW __u32 DSP_EX_LIML; + __RW __u32 PRP_EX_LIMH; + __RW __u32 PRP_EX_LIML; + __RO __u32 PRP_MMU_MSG; + __RO __u32 LSB_MMU_MSG_CH; + __RO __u32 PRP_WR_LIMIT_MSG; + __RO __u32 LSB_WR_LIMIT_CH; + __RW __u32 DSP_PC_LIMH0; + __RW __u32 DSP_PC_LIML0; + __RW __u32 DSP_PC_LIMH1; + __RW __u32 DSP_PC_LIML1; + __RW __u32 PRP_SRM_INV_MSG; + __RW __u32 LSB_SRM_INV_CH; +} JL_DEBUG_TypeDef; + +#define JL_DEBUG_BASE (csfr_base + map_adr(0x10, 0x10)) +#define JL_DEBUG ((JL_DEBUG_TypeDef *)JL_DEBUG_BASE) + +//............. 0x2000 - 0x20ff............ for fft +typedef struct { + __RW __u32 CON; + __RW __u32 CADR; + __RW __u32 TEST0; + __RW __u32 TEST1; +} JL_FFT_TypeDef; + +#define JL_FFT_BASE (csfr_base + map_adr(0x20, 0x00)) +#define JL_FFT ((JL_FFT_TypeDef *)JL_FFT_BASE) + +//********************************************************************************* +// +// q32DSP_sfr +// +//********************************************************************************* + +//---------------------------------------------// +// q32DSP define +//---------------------------------------------// + +#define q32DSP_sfr_offset 0x010000 +#define q32DSP_sfr_base (csfr_base + 0xf000) + +#define q32DSP_cpu_base (q32DSP_sfr_base + 0x00) +#define q32DSP_mpu_base (q32DSP_sfr_base + 0x80) + +#define q32DSP(n) ((JL_TypeDef_q32DSP *)(q32DSP_sfr_base + q32DSP_sfr_offset*n)) +#define q32DSP_mpu(n) ((JL_TypeDef_q32DSP_MPU *)(q32DSP_mpu_base + q32DSP_sfr_offset*n)) + +//---------------------------------------------// +// q32DSP core sfr +//---------------------------------------------// + +typedef struct { + /* 00 */ __RO __u32 DR00; + /* 01 */ __RO __u32 DR01; + /* 02 */ __RO __u32 DR02; + /* 03 */ __RO __u32 DR03; + /* 04 */ __RO __u32 DR04; + /* 05 */ __RO __u32 DR05; + /* 06 */ __RO __u32 DR06; + /* 07 */ __RO __u32 DR07; + /* 08 */ __RO __u32 DR08; + /* 09 */ __RO __u32 DR09; + /* 0a */ __RO __u32 DR10; + /* 0b */ __RO __u32 DR11; + /* 0c */ __RO __u32 DR12; + /* 0d */ __RO __u32 DR13; + /* 0e */ __RO __u32 DR14; + /* 0f */ __RO __u32 DR15; + + /* 10 */ __RO __u32 RETI; + /* 11 */ __RO __u32 RETE; + /* 12 */ __RO __u32 RETX; + /* 13 */ __RO __u32 RETS; + /* 14 */ __RO __u32 SR04; + /* 15 */ __RO __u32 PSR; + /* 16 */ __RO __u32 CNUM; + /* 17 */ __RO __u32 SR07; + /* 18 */ __RO __u32 SR08; + /* 19 */ __RO __u32 SR09; + /* 1a */ __RO __u32 SR10; + /* 1b */ __RO __u32 ICFG; + /* 1c */ __RO __u32 USP; + /* 1d */ __RO __u32 SSP; + /* 1e */ __RO __u32 SP; + /* 1f */ __RO __u32 PCRS; + + /* 20 */ __RW __u32 BPCON; + /* 21 */ __RW __u32 BSP; + /* 22 */ __RW __u32 BP0; + /* 23 */ __RW __u32 BP1; + /* 24 */ __RW __u32 BP2; + /* 25 */ __RW __u32 BP3; + /* 26 */ __WO __u32 CMD_PAUSE; + /* */ __RO __u32 REV_30_26[0x30 - 0x26 - 1]; + + /* 30 */ __RW __u32 PMU_CON; + /* */ __RO __u32 REV_34_30[0x34 - 0x30 - 1]; + /* 34 */ __RW __u32 EMU_CON; + /* 35 */ __RW __u32 EMU_MSG; + /* 36 */ __RW __u32 EMU_SSP_H; + /* 37 */ __RW __u32 EMU_SSP_L; + /* 38 */ __RW __u32 EMU_USP_H; + /* 39 */ __RW __u32 EMU_USP_L; + /* */ __RO __u32 REV_3b_39[0x3b - 0x39 - 1]; + /* 3b */ __RW __u8 TTMR_CON; + /* 3c */ __RW __u32 TTMR_CNT; + /* 3d */ __RW __u32 TTMR_PRD; + /* 3e */ __RW __u32 BANK_CON; + /* 3f */ __RW __u32 BANK_NUM; + + /* 40 */ __RW __u32 ICFG00; + /* 41 */ __RW __u32 ICFG01; + /* 42 */ __RW __u32 ICFG02; + /* 43 */ __RW __u32 ICFG03; + /* 44 */ __RW __u32 ICFG04; + /* 45 */ __RW __u32 ICFG05; + /* 46 */ __RW __u32 ICFG06; + /* 47 */ __RW __u32 ICFG07; + /* 48 */ __RW __u32 ICFG08; + /* 49 */ __RW __u32 ICFG09; + /* 4a */ __RW __u32 ICFG10; + /* 4b */ __RW __u32 ICFG11; + /* 4c */ __RW __u32 ICFG12; + /* 4d */ __RW __u32 ICFG13; + /* 4e */ __RW __u32 ICFG14; + /* 4f */ __RW __u32 ICFG15; + + /* 50 */ __RW __u32 ICFG16; + /* 51 */ __RW __u32 ICFG17; + /* 52 */ __RW __u32 ICFG18; + /* 53 */ __RW __u32 ICFG19; + /* 54 */ __RW __u32 ICFG20; + /* 55 */ __RW __u32 ICFG21; + /* 56 */ __RW __u32 ICFG22; + /* 57 */ __RW __u32 ICFG23; + /* 58 */ __RW __u32 ICFG24; + /* 59 */ __RW __u32 ICFG25; + /* 5a */ __RW __u32 ICFG26; + /* 5b */ __RW __u32 ICFG27; + /* 5c */ __RW __u32 ICFG28; + /* 5d */ __RW __u32 ICFG29; + /* 5e */ __RW __u32 ICFG30; + /* 5f */ __RW __u32 ICFG31; + + /* 60 */ __RO __u32 IPND0; + /* 61 */ __RO __u32 IPND1; + /* 62 */ __RO __u32 IPND2; + /* 63 */ __RO __u32 IPND3; + /* 64 */ __RO __u32 IPND4; + /* 65 */ __RO __u32 IPND5; + /* 66 */ __RO __u32 IPND6; + /* 67 */ __RO __u32 IPND7; + /* 68 */ __WO __u32 ILAT_SET; + /* 69 */ __WO __u32 ILAT_CLR; + /* 6a */ __RW __u32 IPMASK; + /* */ __RO __u32 REV_70_6a[0x70 - 0x6a - 1]; + + /* 70 */ __RW __u32 ETM_CON; + /* 71 */ __RO __u32 ETM_PC0; + /* 72 */ __RO __u32 ETM_PC1; + /* 73 */ __RO __u32 ETM_PC2; + /* 74 */ __RO __u32 ETM_PC3; + /* 75 */ __RW __u32 WP0_ADRH; + /* 76 */ __RW __u32 WP0_ADRL; + /* 77 */ __RW __u32 WP0_DATH; + /* 78 */ __RW __u32 WP0_DATL; + /* 79 */ __RW __u32 WP0_PC; +} JL_TypeDef_q32DSP; + +#undef __RW +#undef __RO +#undef __WO + +#undef __u8 +#undef __u16 +#undef __u32 + +typedef struct _CPU_REGS { + unsigned int reti; + unsigned int rets; + unsigned int psr; + unsigned int r0; + unsigned int r1; + unsigned int r2; + unsigned int r3; + unsigned int r4; + unsigned int r5; + unsigned int r6; + unsigned int r7; + unsigned int r8; + unsigned int r9; + unsigned int r10; + unsigned int r11; + unsigned int r12; + unsigned int r13; + unsigned int r14; + unsigned int r15; +} CPU_REGS; + +#define TICK_CON (q32DSP(0)->TTMR_CON) +#define TICK_PRD (q32DSP(0)->TTMR_PRD) +#define TICK_CNT (q32DSP(0)->TTMR_CNT) + +#define SOFT_CLEAR_PENDING (q32DSP(0)->ILAT_CLR) + +#define CPU_MSG (q32DSP(0)->EMU_MSG) +#define CPU_CON (q32DSP(0)->EMU_CON) + +#endif + +//*********************************************************************************// +// // +// end of this module // +// // +//*********************************************************************************// + diff --git a/include_lib/driver/cpu/br23/asm/ctmu.h b/include_lib/driver/cpu/br23/asm/ctmu.h new file mode 100644 index 0000000..c884d06 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/ctmu.h @@ -0,0 +1,45 @@ +#ifndef _CTMU_DRV_H_ +#define _CTMU_DRV_H_ + +#include "typedef.h" + +#define CTMU_KEY_CH_MAX 3 + +typedef struct _CTMU_KEY_VAR { + s32 touch_release_buf[CTMU_KEY_CH_MAX]; //按键释放值滤波器buffer + u16 touch_cnt_buf[CTMU_KEY_CH_MAX]; //按键计数值滤波器buffer + s16 FLT1CFG1; //滤波器1配置参数1 + s16 FLT1CFG2; //滤波器1配置参数2, 等于(-RELEASECFG0)<2k~16k +void fm_inside_deempasis_set(u8 set);// set[0/1], 0:50us, 1:75us +#endif + diff --git a/include_lib/driver/cpu/br23/asm/gpio.h b/include_lib/driver/cpu/br23/asm/gpio.h new file mode 100644 index 0000000..36de8cc --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/gpio.h @@ -0,0 +1,562 @@ +/** + * @file gpio.h + * @brief + * @author @zh-jieli.com + * @version 1.0.0 + * @date 2018-10-11 + */ + +#ifndef __GPIO_H__ +#define __GPIO_H__ +#include "typedef.h" +enum { + CH0_UT0_TX, + CH0_UT1_TX, + CH0_T0_PWM_OUT, + CH0_T1_PWM_OUT, + CH0_RTOSH_CLK, + CH0_BTOSC_CLK, + CH0_PLL_12M, + CH0_UT2_TX, + CH0_CH0_PWM_H, + CH0_CH0_PWM_L, + CH0_CH1_PWM_H, + CH0_CH1_PWM_L, + CH0_CH2_PWM_H, + CH0_CH2_PWM_L, + CH0_WLC_BT_FREQ, + CH0_T3_PWM_OUT, + + CH1_UT0_TX = 0x10, + CH1_UT1_TX, + CH1_T0_PWM_OUT, + CH1_WLC_BT_PRO, + CH1_RTOSL_CLK, + CH1_BTOSC_CLK, + CH1_SPDIF_DO, + CH1_UT2_TX, + CH1_CH0_PWM_H, + CH1_CH0_PWM_L, + CH1_CH1_PWM_H, + CH1_CH1_PWM_L, + CH1_CH2_PWM_H, + CH1_CH2_PWM_L, + CH1_T2_PWM_OUT, + CH1_T3_PWM_OUT, + + CH2_UT1_RTS = 0x20, + CH2_UT1_TX, + CH2_WLC_BT_ACTIVE, + CH2_T1_PWM_OUT, + CH2_PLNK_SCLK, + CH2_BTOSC_CLK, + CH2_PLL_24M, + CH2_UT2_TX, + CH2_CH0_PWM_H, + CH2_CH0_PWM_L, + CH2_CH1_PWM_H, + CH2_CH1_PWM_L, + CH2_CH2_PWM_H, + CH2_CH2_PWM_L, + CH2_T2_PWM_OUT, + CH2_T3_PWM_OUT, +}; + + +#define IO_GROUP_NUM 16 + + +#define IO_PORTA_00 (IO_GROUP_NUM * 0 + 0) +#define IO_PORTA_01 (IO_GROUP_NUM * 0 + 1) +#define IO_PORTA_02 (IO_GROUP_NUM * 0 + 2) +#define IO_PORTA_03 (IO_GROUP_NUM * 0 + 3) +#define IO_PORTA_04 (IO_GROUP_NUM * 0 + 4) +#define IO_PORTA_05 (IO_GROUP_NUM * 0 + 5) +#define IO_PORTA_06 (IO_GROUP_NUM * 0 + 6) +#define IO_PORTA_07 (IO_GROUP_NUM * 0 + 7) +#define IO_PORTA_08 (IO_GROUP_NUM * 0 + 8) +#define IO_PORTA_09 (IO_GROUP_NUM * 0 + 9) +#define IO_PORTA_10 (IO_GROUP_NUM * 0 + 10) +#define IO_PORTA_11 (IO_GROUP_NUM * 0 + 11) +#define IO_PORTA_12 (IO_GROUP_NUM * 0 + 12) +#define IO_PORTA_13 (IO_GROUP_NUM * 0 + 13) +#define IO_PORTA_14 (IO_GROUP_NUM * 0 + 14) +#define IO_PORTA_15 (IO_GROUP_NUM * 0 + 15) + +#define IO_PORTB_00 (IO_GROUP_NUM * 1 + 0) +#define IO_PORTB_01 (IO_GROUP_NUM * 1 + 1) +#define IO_PORTB_02 (IO_GROUP_NUM * 1 + 2) +#define IO_PORTB_03 (IO_GROUP_NUM * 1 + 3) +#define IO_PORTB_04 (IO_GROUP_NUM * 1 + 4) +#define IO_PORTB_05 (IO_GROUP_NUM * 1 + 5) +#define IO_PORTB_06 (IO_GROUP_NUM * 1 + 6) +#define IO_PORTB_07 (IO_GROUP_NUM * 1 + 7) +#define IO_PORTB_08 (IO_GROUP_NUM * 1 + 8) +#define IO_PORTB_09 (IO_GROUP_NUM * 1 + 9) +#define IO_PORTB_10 (IO_GROUP_NUM * 1 + 10) +#define IO_PORTB_11 (IO_GROUP_NUM * 1 + 11) +#define IO_PORTB_12 (IO_GROUP_NUM * 1 + 12) +#define IO_PORTB_13 (IO_GROUP_NUM * 1 + 13) +#define IO_PORTB_14 (IO_GROUP_NUM * 1 + 14) +#define IO_PORTB_15 (IO_GROUP_NUM * 1 + 15) + +#define IO_PORTC_00 (IO_GROUP_NUM * 2 + 0) +#define IO_PORTC_01 (IO_GROUP_NUM * 2 + 1) +#define IO_PORTC_02 (IO_GROUP_NUM * 2 + 2) +#define IO_PORTC_03 (IO_GROUP_NUM * 2 + 3) +#define IO_PORTC_04 (IO_GROUP_NUM * 2 + 4) +#define IO_PORTC_05 (IO_GROUP_NUM * 2 + 5) +#define IO_PORTC_06 (IO_GROUP_NUM * 2 + 6) +#define IO_PORTC_07 (IO_GROUP_NUM * 2 + 7) +#define IO_PORTC_08 (IO_GROUP_NUM * 2 + 8) +#define IO_PORTC_09 (IO_GROUP_NUM * 2 + 9) +#define IO_PORTC_10 (IO_GROUP_NUM * 2 + 10) +#define IO_PORTC_11 (IO_GROUP_NUM * 2 + 11) +#define IO_PORTC_12 (IO_GROUP_NUM * 2 + 12) +#define IO_PORTC_13 (IO_GROUP_NUM * 2 + 13) +#define IO_PORTC_14 (IO_GROUP_NUM * 2 + 14) +#define IO_PORTC_15 (IO_GROUP_NUM * 2 + 15) + +#define IO_PORTD_00 (IO_GROUP_NUM * 3 + 0) +#define IO_PORTD_01 (IO_GROUP_NUM * 3 + 1) +#define IO_PORTD_02 (IO_GROUP_NUM * 3 + 2) +#define IO_PORTD_03 (IO_GROUP_NUM * 3 + 3) +#define IO_PORTD_04 (IO_GROUP_NUM * 3 + 4) +#define IO_PORTD_05 (IO_GROUP_NUM * 3 + 5) +#define IO_PORTD_06 (IO_GROUP_NUM * 3 + 6) +#define IO_PORTD_07 (IO_GROUP_NUM * 3 + 7) + + +#define IO_MAX_NUM (IO_PORTD_07+1) + + +#define IO_PORT_PR_00 (IO_MAX_NUM + 0) +#define IO_PORT_PR_01 (IO_MAX_NUM + 1) +#define IO_PORT_PR_02 (IO_MAX_NUM + 2) +#define IO_PORT_PR_03 (IO_MAX_NUM + 3) +#define IO_PORT_PR_04 (IO_MAX_NUM + 4) + +#define USB_IO_OFFSET 5 +#define IO_PORT_DP (IO_MAX_NUM + USB_IO_OFFSET) +#define IO_PORT_DM (IO_MAX_NUM + USB_IO_OFFSET + 1) + +#define P33_IO_OFFSET 7 +#define IO_LDOIN_DET (IO_MAX_NUM + P33_IO_OFFSET) +#define IO_LVCMP_DET (IO_MAX_NUM + P33_IO_OFFSET + 1) + +#define IO_PORT_MAX (IO_LVCMP_DET + 1) + +#define GPIOA (IO_GROUP_NUM * 0) +#define GPIOB (IO_GROUP_NUM * 1) +#define GPIOC (IO_GROUP_NUM * 2) +#define GPIOD (IO_GROUP_NUM * 3) +#define GPIOR (IO_MAX_NUM) +#define GPIOUSB (IO_MAX_NUM + USB_IO_OFFSET) +#define GPIOP33 (IO_MAX_NUM + P33_IO_OFFSET) + +#define MIC_HW_IO IO_PORTC_06 + +enum { + INPUT_CH0, + INPUT_CH1, + INPUT_CH2, + INPUT_CH3, +}; + +enum gpio_op_mode { + GPIO_SET = 1, + GPIO_AND, + GPIO_OR, + GPIO_XOR, +}; +enum gpio_direction { + GPIO_OUT = 0, + GPIO_IN = 1, +}; +struct gpio_reg { + volatile unsigned int out; + volatile unsigned int in; + volatile unsigned int dir; + volatile unsigned int die; + volatile unsigned int pu; + volatile unsigned int pd; + volatile unsigned int hd0; + volatile unsigned int hd; + volatile unsigned int dieh; +}; + +struct gpio_platform_data { + unsigned int gpio; +}; + +#define GPIO_PLATFORM_DATA_BEGIN(data) \ + static const struct gpio_platform_data data = { \ + + +#define GPIO_PLATFORM_DATA_END() \ + }; +#if 0 +#define IO_DEBUG_0(i,x) {JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT &= ~BIT(x);} +#define IO_DEBUG_1(i,x) {JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT |= BIT(x);} +#define IO_DEBUG_TOGGLE(i,x) {JL_PORT##i->DIR &= ~BIT(x), JL_PORT##i->OUT ^= BIT(x);} + + +#else +#define IO_DEBUG_0(i,x) {} +#define IO_DEBUG_1(i,x) {} +#define IO_DEBUG_TOGGLE(i,x) {} + +#endif +/** + * @brief usb_iomode + * + * @param enable 1,使能;0,关闭 + */ +void usb_iomode(u32 enable); +/** + * @brief gpio_direction_input + * + * @param gpio 参考宏IO_PORTx_xx,如IO_PORTA_00 + * @param dir 1,输入;0,输出 + * + * @return + */ +int gpio_set_direction(u32 gpio, u32 dir); + + +/** + * @brief gpio_direction_input + * + * @param gpio 参考宏IO_PORTx_xx,如IO_PORTA_00 + * @param value 1,输出1, 0,输出0 + * + * @return + */ +int gpio_set_output_value(u32 gpio, u32 dir); + +/** + * @brief gpio_dir + * + * @param gpio [GPIOA GPIOB GPIOC GPIOD GPIOR GPIOUSB] + * @param start [0-15],GPIOR[0-3],GPIOUSB[0-1] + * @param len [0-15],GPIOR[0-3],GPIOUSB[0-1] + * @param dat 1,输入;0,输出 + * + * @return + */ +u32 gpio_dir(u32 gpio, u32 start, u32 len, u32 dat, enum gpio_op_mode op); + +/** + * @brief gpio_direction_output + * + * @param gpio 参考宏IO_PORTx_xx,如IO_PORTA_00 + * @param value 1,输出1;0,输出0 + * + * @return + */ +int gpio_direction_output(u32 gpio, int value); + +/** + * @brief gpio_out + * + * @param gpio [GPIOA GPIOB GPIOC GPIOD GPIOR GPIOUSB] + * @param start [0-15],GPIOR[0-3],GPIOUSB[0-1] + * @param len [0-15],GPIOR[0-3],GPIOUSB[0-1] + * @param dat 1,输入;0,输出 + * + * @return + */ +u32 gpio_out(u32 gpio, u32 start, u32 len, u32 dat); + +/** + * @brief gpio_set_pull_up + * + * @param gpio 参考宏IO_PORTx_xx,如IO_PORTA_00 + * @param value 1,上拉;0,不上拉 + * + * @return + */ +int gpio_set_pull_up(u32 gpio, int value); + + +/** + * @brief gpio_set_pu + * + * @param gpio [GPIOA GPIOB GPIOC GPIOD GPIOR GPIOUSB] + * @param start [0-15],GPIOR[0-3],GPIOUSB[0-1] + * @param len [0-15],GPIOR[0-3],GPIOUSB[0-1] + * @param dat 1,上拉;0,不上拉 + * + * @return + */ +u32 gpio_set_pu(u32 gpio, u32 start, u32 len, u32 dat, enum gpio_op_mode op); + +/** + * @brief gpio_set_pull_down + * + * @param gpio 参考宏IO_PORTx_xx,如IO_PORTA_00 + * @param value 1,下拉;0,不下拉 + * + * @return + */ +int gpio_set_pull_down(u32 gpio, int value); + +/** + * @brief gpio_set_pd + * + * @param gpio [GPIOA GPIOB GPIOC GPIOD GPIOR GPIOUSB] + * @param start [0-15],GPIOR[0-3],GPIOUSB[0-1] + * @param len [0-15],GPIOR[0-3],GPIOUSB[0-1] + * @param dat 1,下拉;0,不下拉 + * + * @return + */ +u32 gpio_set_pd(u32 gpio, u32 start, u32 len, u32 dat, enum gpio_op_mode op); + +/** + * @brief gpio_set_hd0 + * + * @param gpio 参考宏IO_PORTx_xx,如IO_PORTA_00 + * @param value 1,增强输出;0,不增强输出 + * + * @return + */ +u32 gpio_set_hd0(u32 gpio, u32 value); + +/** + * @brief gpio_set_hd + * + * @param gpio 参考宏IO_PORTx_xx,如IO_PORTA_00 + * @param value 1,增强输出;0,不增强输出 + * + * @return + */ +int gpio_set_hd(u32 gpio, int value); + +/** + * @brief gpio_set_die + * + * @param gpio 参考宏IO_PORTx_xx,如IO_PORTA_00 + * @param value 1,IO普通输入;0,IO模拟输入 + * + * @return + */ +int gpio_set_die(u32 gpio, int value); + +/** + * @brief gpio_set_dieh + * + * @param gpio 参考宏IO_PORTx_xx,如IO_PORTA_00 + * @param value 1,IO普通输入;0,IO模拟输入 + * + * @return + */ +u32 gpio_set_dieh(u32 gpio, u32 value); + +/** + * @brief gpio_die + * + * @param gpio [GPIOA GPIOB GPIOC GPIOD GPIOR GPIOUSB] + * @param start [0-15],GPIOR[0-3],GPIOUSB[0-1] + * @param len [0-15],GPIOR[0-3],GPIOUSB[0-1] + * @param dat 1,IO普通输入;0,IO模拟输入 + * + * @return + */ +u32 gpio_die(u32 gpio, u32 start, u32 len, u32 dat, enum gpio_op_mode op); + +/** + * @brief gpio_dieh + * + * @param gpio [GPIOA GPIOB GPIOC GPIOD GPIOR GPIOUSB] + * @param start [0-15],GPIOR[0-3],GPIOUSB[0-1] + * @param len [0-15],GPIOR[0-3],GPIOUSB[0-1] + * @param dat 1,IO普通输入;0,IO模拟输入 + * + * @return + */ +u32 gpio_dieh(u32 gpio, u32 start, u32 len, u32 dat, enum gpio_op_mode op); + +/** + * @brief gpio_set_output_channle + * + * @param gpio 参考宏IO_PORTx_xx,如IO_PORTA_00 + * @param clk 参考枚举CHx_UTx_TX,如CH0_UT0_TX + * + * @return + */ +u32 gpio_output_channle(u32 gpio, u32 clk); + +/** + * @brief gpio_read + * + * @param gpio 参考宏IO_PORTx_xx,如IO_PORTA_00 + * + * @return + */ +int gpio_read(u32 gpio); + +/** + * @brief gpio_in + * + * @param gpio [GPIOA GPIOB GPIOC GPIOD GPIOR GPIOUSB] + * + * @return + */ +u32 gpio_in(u32 gpio); +/** + * @brief gpio_write + * + * @param gpio 参考宏IO_PORTx_xx,如IO_PORTA_00 + * @param value 1,输出1;0,输出0 + * + * @return + */ +u32 gpio_write(u32 gpio, u32 value); + +/** + * @brief gpio_wakeup0 use IN_CHNL0_SEL + * + * @param gpio 参考宏IO_PORTx_xx,如IO_PORTA_00 + * + * @return + */ +u32 gpio_wakeup0(u32 gpio); + +/** + * @brief gpio_irflt_in use IN_CHNL1_SEL + * + * @param gpio 参考宏IO_PORTx_xx,如IO_PORTA_00 + * + * @return + */ +u32 gpio_irflt_in(u32 gpio); + +/** + * @brief gpio_cap_mux use IN_CHNL2_SEL + * + * @param gpio 参考宏IO_PORTx_xx,如IO_PORTA_00 + * + * @return + */ +u32 gpio_cap_mux(u32 gpio); + + +/** + * @brief gpio_uart_rx_input + * + * @param gpio + * @param ut + * @param ch + * + * @return + */ +u32 gpio_uart_rx_input(u32 gpio, u32 ut, u32 ch); + +/** + * @brief + * + * @return + */ +u32 gpio_close_uart0(void); + +/** + * @brief + * + * @return + */ +u32 gpio_close_uart1(void); + +/** + * @brief + * + * @return + */ +u32 gpio_close_uart2(void); + +/** + * @brief gpio_set_uart0 + * + * @param ch 0:3 选择对应IO br22 + * |ch|tx|rx| + * |- |- |- | + * |0|PA5_TX|PA6_RX| + * |1|PB7_TX|PB8_RX| + * |2|PA7_TX|PA8_RX| + * |3|预留|预留| + * |-1|关闭对应的IO口串口功能|no| + * + * @return + */ +u32 gpio_set_uart0(u32 ch); +/** + * @brief gpio_set_uart1 + * + * @param ch 0:3 选择对应IO br22 + * |ch|tx|rx| + * |- |- |- | + * |0|PB5_TX|PB6_RX| + * |1|预留|预留| + * |2|PA1_TX|PA2_RX| + * |3|USBDP |USBDM | + * |-1|关闭对应的IO口串口功能|no| + * + * @return + */ +u32 gpio_set_uart1(u32 ch); +/** + * @brief gpio_set_uart2 + * + * @param ch 0:3 选择对应IO br22 + * |ch|tx|rx| + * |- |- |- | + * |0|PA3_TX|PA4_RX| + * |1|预留|预留| + * |2|预留|预留| + * |3|PA9_TX|PA10_RX| + * |-1|关闭对应的IO口串口功能|no| + * + * @return + */ +u32 gpio_set_uart2(u32 ch); + +enum { + IRFLT_LSB, + IRFLT_RC, + IRFLT_OSC, + IRFLT_PLL48M, +}; +enum { + IRFLT_DIV1, + IRFLT_DIV2, + IRFLT_DIV4, + IRFLT_DIV8, + IRFLT_DIV16, + IRFLT_DIV32, + IRFLT_DIV64, + IRFLT_DIV128, + IRFLT_DIV256, + IRFLT_DIV512, + IRFLT_DIV1024, + IRFLT_DIV2048, + IRFLT_DIV4096, + IRFLT_DIV8192, + IRFLT_DIV16384, + IRFLT_DIV32768, +}; +/* u32 irflt_config(u32 osc, u32 div); */ + +/** + * @brief gpio_irflt_to_timer + * + * @param t: [0-3] + * + * @return + */ +u32 gpio_irflt_to_timer(u32 t); + + +u32 get_gpio(const char *p); + + +#endif /*GPIO_H*/ diff --git a/include_lib/driver/cpu/br23/asm/hwi.h b/include_lib/driver/cpu/br23/asm/hwi.h new file mode 100644 index 0000000..3244395 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/hwi.h @@ -0,0 +1,97 @@ +#ifndef HWI_H +#define HWI_H + + +#define IRQ_EMUEXCPT_IDX 0 //0 +#define IRQ_EXCEPTION_IDX 1 //0 +#define IRQ_SYSCALL_IDX 2 //0 +#define IRQ_TICK_TMR_IDX 3 //0 + +#define IRQ_TIME0_IDX 4 //0 +#define IRQ_TIME1_IDX 5 //0 +#define IRQ_TIME2_IDX 6 //0 +#define IRQ_TIME3_IDX 7 //0 +#define IRQ_USB_SOF_IDX 8 //1 +#define IRQ_USB_CTRL_IDX 9 //1 +#define IRQ_RTC_WDT_IDX 10 //0 +#define IRQ_ALINK0_IDX 11 //1 +#define IRQ_AUDIO_IDX 12 //1 +#define IRQ_PORT_IDX 13 //0 +#define IRQ_SPI0_IDX 14 //0 +#define IRQ_SPI1_IDX 15 //0 +#define IRQ_SD0_IDX 16 //0 +#define IRQ_SD1_IDX 17 //0 +#define IRQ_UART0_IDX 18 //0 +#define IRQ_UART1_IDX 19 //0 +#define IRQ_UART2_IDX 20 //0 +#define IRQ_PAP_IDX 21 //0 +#define IRQ_IIC_IDX 22 //0 +#define IRQ_SARADC_IDX 23 //0 +#define IRQ_PDM_LINK_IDX 24 //1 +#define IRQ_RDEC0_IDX 25 //1 +#define IRQ_LRCT_IDX 26 //1 +#define IRQ_BREDR_IDX 27 //2 +#define IRQ_BT_CLKN_IDX 28 //2 +#define IRQ_BT_DBG_IDX 29 //1 +#define IRQ_WL_LOFC_IDX 30 //2 +#define IRQ_SRC_IDX 31 //1 +#define IRQ_FFT_IDX 32 //1 +#define IRQ_EQ_IDX 33 //1 +#define IRQ_LP_TIMER0_IDX 34 +#define IRQ_LP_TIMER1_IDX 35 +#define IRQ_ALINK1_IDX 36 +#define IRQ_OSA_IDX 37 +#define IRQ_BLE_RX_IDX 38 //2 +#define IRQ_BLE_EVENT_IDX 39 //1 +#define IRQ_AES_IDX 40 +#define IRQ_MCTMRX_IDX 41 +#define IRQ_CHX_PWM_IDX 42 +#define IRQ_FMRX_IDX 43 +#define IRQ_SPI2_IDX 44 +#define IRQ_SBC_IDX 45 //1 +#define IRQ_GPC_IDX 46 //1 +#define IRQ_FMTX_IDX 47 //1 +#define IRQ_DCP_IDX 48 //1 +#define IRQ_RDEC1_IDX 49 //1 +#define IRQ_RDEC2_IDX 50 //1 +#define IRQ_SPDIF_IDX 51 //1 +#define IRQ_PWM_LED_IDX 52 //1 +#define IRQ_CTM_IDX 53 //1 +#define IRQ_SOFT0_IDX 60 +#define IRQ_SOFT1_IDX 61 +#define IRQ_SOFT2_IDX 62 +#define IRQ_SOFT3_IDX 63 + +#define IRQ_MEM_ADDR 0x2BF00 +#define MAX_IRQ_ENTRY_NUM 64 + +void interrupt_init(); + +void request_irq(u8 index, u8 priority, void (*handler)(void), u8 cpu_id); + +void unrequest_irq(u8 index); + +void bit_clr_ie(unsigned char index); +void bit_set_ie(unsigned char index); +bool irq_read(u32 index); + +#define irq_disable(x) bit_clr_ie(x) +#define irq_enable(x) bit_set_ie(x) + +#ifdef IRQ_TIME_COUNT_EN +void irq_handler_enter(int irq); + +void irq_handler_exit(int irq); + +void irq_handler_times_dump(); +#else + +#define irq_handler_enter(irq) do { }while(0) +#define irq_handler_exit(irq) do { }while(0) +#define irq_handler_times_dump() do { }while(0) + +#endif + + +#endif + diff --git a/include_lib/driver/cpu/br23/asm/iic_hw.h b/include_lib/driver/cpu/br23/asm/iic_hw.h new file mode 100644 index 0000000..b3c0da2 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/iic_hw.h @@ -0,0 +1,82 @@ +#ifndef _IIC_HW_H_ +#define _IIC_HW_H_ + +#include "system/generic/typedef.h" + +#define IIC_HW_NUM 1 +#define IIC_PORT_GROUP_NUM 4 + +#define iic_enable(reg) (reg->CON0 |= BIT(0)) +#define iic_disable(reg) (reg->CON0 &= ~BIT(0)) +#define iic_role_host(reg) (reg->CON0 &= ~BIT(1)) +#define iic_role_slave(reg) (reg->CON0 |= BIT(1)) +#define iic_cfg_done(reg) (reg->CON0 |= BIT(2)) +#define iic_dir_out(reg) (reg->CON0 &= ~BIT(3)) +#define iic_dir_in(reg) (reg->CON0 |= BIT(3)) +#define iic_preset_end(reg) (reg->CON0 |= BIT(4)) +#define iic_preset_restart(reg) (reg->CON0 |= BIT(5)) +#define iic_recv_ack(reg) (reg->CON0 &= ~BIT(6)) +#define iic_recv_nack(reg) (reg->CON0 |= BIT(6)) +#define iic_send_is_ack(reg) (!(reg->CON0 & BIT(7))) +#define iic_isel_direct(reg) (reg->CON0 &= ~BIT(9)) +#define iic_isel_filter(reg) (reg->CON0 |= BIT(9)) +#define iic_si_mode_en(reg) (reg->CON1 |= BIT(13)) +#define iic_si_mode_dis(reg) (reg->CON1 &= ~BIT(13)) + +#define iic_set_ie(reg) (reg->CON0 |= BIT(8)) +#define iic_clr_ie(reg) (reg->CON0 &= ~BIT(8)) +#define iic_pnd(reg) (reg->CON0 & BIT(15)) +#define iic_pnd_clr(reg) (reg->CON0 |= BIT(14)) + +#define iic_set_end_ie(reg) (reg->CON0 |= BIT(10)) +#define iic_clr_end_ie(reg) (reg->CON0 &= BIT(10)) +#define iic_end_pnd(reg) (reg->CON0 & BIT(13)) +#define iic_end_pnd_clr(reg) (reg->CON0 |= BIT(12)) + +#define iic_start_pnd(reg) (reg->CON1 & BIT(15)) +#define iic_start_pnd_clr(reg) (reg->CON1 |= BIT(14)) + +#define iic_baud_reg(reg) (reg->BAUD) +#define iic_buf_reg(reg) (reg->BUF) + + +typedef const int hw_iic_dev; + +enum {IIC_MASTER, IIC_SLAVE}; + +struct hw_iic_config { + u8 port; //example: 'A', 'B', 'C', 'D' + u32 baudrate; + u8 hdrive; + u8 io_filter; + u8 io_pu; + u8 role; +}; + +extern const struct hw_iic_config hw_iic_cfg[]; + +int hw_iic_init(hw_iic_dev iic); +void hw_iic_uninit(hw_iic_dev iic); +void hw_iic_suspend(hw_iic_dev iic); +void hw_iic_resume(hw_iic_dev iic); +void hw_iic_start(hw_iic_dev iic); +void hw_iic_stop(hw_iic_dev iic); +u8 hw_iic_tx_byte(hw_iic_dev iic, u8 byte); +u8 hw_iic_rx_byte(hw_iic_dev iic, u8 ack); +int hw_iic_read_buf(hw_iic_dev iic, void *buf, int len); +int hw_iic_write_buf(hw_iic_dev iic, const void *buf, int len); +int hw_iic_set_baud(hw_iic_dev iic, u32 baud); + +void hw_iic_set_ie(hw_iic_dev iic, u8 en); +u8 hw_iic_get_pnd(hw_iic_dev iic); +void hw_iic_clr_pnd(hw_iic_dev iic); +void hw_iic_set_end_ie(hw_iic_dev iic, u8 en); +u8 hw_iic_get_end_pnd(hw_iic_dev iic); +void hw_iic_clr_end_pnd(hw_iic_dev iic); +void hw_iic_slave_set_addr(hw_iic_dev iic, u8 addr, u8 addr_ack); +void hw_iic_slave_rx_prepare(hw_iic_dev iic, u8 ack); +u8 hw_iic_slave_rx_byte(hw_iic_dev iic, bool *is_start_addr); +void hw_iic_slave_tx_byte(hw_iic_dev iic, u8 byte); +u8 hw_iic_slave_tx_check_ack(hw_iic_dev iic); + +#endif diff --git a/include_lib/driver/cpu/br23/asm/iic_soft.h b/include_lib/driver/cpu/br23/asm/iic_soft.h new file mode 100644 index 0000000..af58255 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/iic_soft.h @@ -0,0 +1,28 @@ +#ifndef _IIC_SOFT_H_ +#define _IIC_SOFT_H_ + +#include "generic/typedef.h" + +typedef const int soft_iic_dev; + +struct soft_iic_config { + int scl; + int sda; + u32 delay; + u8 io_pu; +}; + +extern const struct soft_iic_config soft_iic_cfg[]; + +int soft_iic_init(soft_iic_dev iic); +void soft_iic_uninit(soft_iic_dev iic); +void soft_iic_suspend(soft_iic_dev iic); +void soft_iic_resume(soft_iic_dev iic); +void soft_iic_start(soft_iic_dev iic); +void soft_iic_stop(soft_iic_dev iic); +u8 soft_iic_tx_byte(soft_iic_dev iic, u8 byte); +u8 soft_iic_rx_byte(soft_iic_dev iic, u8 ack); +int soft_iic_read_buf(soft_iic_dev iic, void *buf, int len); +int soft_iic_write_buf(soft_iic_dev iic, const void *buf, int len); +#endif + diff --git a/include_lib/driver/cpu/br23/asm/iis.h b/include_lib/driver/cpu/br23/asm/iis.h new file mode 100644 index 0000000..97bbc4a --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/iis.h @@ -0,0 +1,40 @@ +#ifndef __IIS_H__ +#define __IIS_H__ + +#include "generic/typedef.h" + +#define ALINK_PORT_TO_MODULE(port) ((port < 2) ? 0 : 1) + +#define ALINK_SEL(idx, reg) (((JL_ALNK_TypeDef *)(((u8 *)JL_ALNK0) + idx*(JL_ALNK1_BASE - JL_ALNK0_BASE)))->reg) +//#define ALINK_SEL(idx, reg) ((JL_ALNK0 + idx)->reg) + +#define ALNK_CON_RESET(idx) do {ALINK_SEL(idx, CON0) = 0; ALINK_SEL(idx, CON1) = 0; ALINK_SEL(idx, CON2) = 0; ALINK_SEL(idx, CON3) = 0;} while(0) + +#define ALINK_DSPE(idx, x) SFR(ALINK_SEL(idx, CON0), 6, 1, x) +#define ALINK_SOE(idx, x) SFR(ALINK_SEL(idx, CON0), 7, 1, x) +#define ALINK_MOE(idx, x) SFR(ALINK_SEL(idx, CON0), 8, 1, x) +#define F32_EN(idx, x) SFR(ALINK_SEL(idx, CON0), 9, 1, x) +#define SCLKINV(idx, x) SFR(ALINK_SEL(idx, CON0),10, 1, x) +#define ALINK_EN(idx, x) SFR(ALINK_SEL(idx, CON0),11, 1, x) +#define ALINK_24BIT_MODE(idx) (ALINK_SEL(idx, CON1) |= (BIT(2) | BIT(6) | BIT(10) | BIT(14))) +#define ALINK_16BIT_MODE(idx) (ALINK_SEL(idx, CON1) &= (~(BIT(2) | BIT(6) | BIT(10) | BIT(14)))) + +#define ALINK_IIS_MODE(idx) (ALINK_SEL(idx, CON1) |= (BIT(2) | BIT(6) | BIT(10) | BIT(14))) + +#define ALINK_CHx_DIR_TX_MODE(idx, ch) (ALINK_SEL(idx, CON1) &= (~(1 << (3 + 4 * ch)))) +#define ALINK_CHx_DIR_RX_MODE(idx, ch) (ALINK_SEL(idx, CON1) |= (1 << (3 + 4 * ch))) + +#define ALINK_CHx_MODE_SEL(idx, val, ch) (ALINK_SEL(idx, CON1) |= (val << (0 + 4 * ch))) +#define ALINK_CHx_CLOSE(idx, val, ch) (ALINK_SEL(idx, CON1) &= ~(val << (0 + 4 * ch))) + + +#define ALINK_CLR_CH0_PND(idx) (ALINK_SEL(idx, CON2) |= BIT(0)) +#define ALINK_CLR_CH1_PND(idx) (ALINK_SEL(idx, CON2) |= BIT(1)) +#define ALINK_CLR_CH2_PND(idx) (ALINK_SEL(idx, CON2) |= BIT(2)) +#define ALINK_CLR_CH3_PND(idx) (ALINK_SEL(idx, CON2) |= BIT(3)) + +#define ALINK_MSRC(idx, x) SFR(ALINK_SEL(idx, CON3), 0, 2, x) +#define ALINK_MDIV(idx, x) SFR(ALINK_SEL(idx, CON3), 2, 3, x) +#define ALINK_LRDIV(idx, x) SFR(ALINK_SEL(idx, CON3), 5, 3, x) + +#endif diff --git a/include_lib/driver/cpu/br23/asm/includes.h b/include_lib/driver/cpu/br23/asm/includes.h new file mode 100644 index 0000000..1ed74fb --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/includes.h @@ -0,0 +1,28 @@ +#ifndef ASM_INCLUDES_H +#define ASM_INCLUDES_H + +#include "asm/cpu.h" +#include "asm/crc16.h" +#include "asm/clock.h" +#include "asm/uart.h" +#include "asm/uart_dev.h" +#include "asm/gpio.h" +#include "asm/spiflash.h" +#include "asm/csfr.h" +#include "asm/power_interface.h" +#include "asm/efuse.h" +#include "asm/wdt.h" +#include "asm/timer.h" + + + + + + + + + + + + +#endif diff --git a/include_lib/driver/cpu/br23/asm/irflt.h b/include_lib/driver/cpu/br23/asm/irflt.h new file mode 100644 index 0000000..7ca6043 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/irflt.h @@ -0,0 +1,229 @@ +#ifndef __KEY_DRV_IR_H__ +#define __KEY_DRV_IR_H__ + +#define IR_PORTA(x) (0x00 + x) +#define IR_PORTB(x) (0x10 + x) +#define IR_PORTC(x) (0x20 + x) +#define IR_PORTD(x) (0x30 + x) +#define IR_USBDP (0x3d) +#define IR_USBDM (0x3e) + +// #define IR_IO IR_PORTA(9) + +/*ir key define*/ +#define IR_00 0 +#define IR_01 1 +#define IR_02 2 +#define IR_03 3 +#define IR_04 4 +#define IR_05 5 +#define IR_06 6 +#define IR_07 7 +#define IR_08 8 +#define IR_09 9 +#define IR_10 10 +#define IR_11 11 +#define IR_12 12 +#define IR_13 13 +#define IR_14 14 +#define IR_15 15 +#define IR_16 16 +#define IR_17 17 +#define IR_18 18 +#define IR_19 19 +#define IR_20 20 +#define IR_21 21 +#define IR_22 22 + +////////////////////////////////// +#define NKEY_00 0xff +#define NKEY_01 0xff +#define NKEY_02 0xff +#define NKEY_03 0xff +#define NKEY_04 0xff +#define NKEY_05 0xff +#define NKEY_06 0xff +#define NKEY_07 0xff +#define NKEY_08 0xff +#define NKEY_09 0xff +#define NKEY_0A 0xff +#define NKEY_0B 0xff +#define NKEY_0C 0xff +#define NKEY_0D 0xff +#define NKEY_0E 0xff +#define NKEY_0F 0xff +#define NKEY_10 0xff +#define NKEY_11 0xff +#define NKEY_12 0xff +#define NKEY_13 0xff +#define NKEY_14 0xff +#define NKEY_15 0xff +#define NKEY_16 0xff +#define NKEY_17 0xff +#define NKEY_18 0xff +#define NKEY_19 0xff +#define NKEY_1A 0xff +#define NKEY_1B 0xff +#define NKEY_1C 0xff +#define NKEY_1D 0xff +#define NKEY_1E 0xff +#define NKEY_1F 0xff +#define NKEY_20 0xff +#define NKEY_21 0xff +#define NKEY_22 0xff +#define NKEY_23 0xff +#define NKEY_24 0xff +#define NKEY_25 0xff +#define NKEY_26 0xff +#define NKEY_27 0xff +#define NKEY_28 0xff +#define NKEY_29 0xff +#define NKEY_2A 0xff +#define NKEY_2B 0xff +#define NKEY_2C 0xff +#define NKEY_2D 0xff +#define NKEY_2E 0xff +#define NKEY_2F 0xff +#define NKEY_30 0xff +#define NKEY_31 0xff +#define NKEY_32 0xff +#define NKEY_33 0xff +#define NKEY_34 0xff +#define NKEY_35 0xff +#define NKEY_36 0xff +#define NKEY_37 0xff +#define NKEY_38 0xff +#define NKEY_39 0xff +#define NKEY_3A 0xff +#define NKEY_3B 0xff +#define NKEY_3C 0xff +#define NKEY_3D 0xff +#define NKEY_3E 0xff +#define NKEY_3F 0xff +#define NKEY_40 0xff +#define NKEY_41 0xff +#define NKEY_42 0xff +#define NKEY_43 0xff +#define NKEY_44 0xff +#define NKEY_45 0xff +#define NKEY_46 0xff +#define NKEY_47 0xff +#define NKEY_48 0xff +#define NKEY_49 0xff +#define NKEY_4A 0xff +#define NKEY_4B 0xff +#define NKEY_4C 0xff +#define NKEY_4D 0xff +#define NKEY_4E 0xff +#define NKEY_4F 0xff +#define NKEY_50 0xff +#define NKEY_51 0xff +#define NKEY_52 0xff +#define NKEY_53 0xff +#define NKEY_54 0xff +#define NKEY_55 0xff +#define NKEY_56 0xff +#define NKEY_57 0xff +#define NKEY_58 0xff +#define NKEY_59 0xff +#define NKEY_5A 0xff +#define NKEY_5B 0xff +#define NKEY_5C 0xff +#define NKEY_5D 0xff +#define NKEY_5E 0xff +#define NKEY_5F 0xff +#define NKEY_60 0xff +#define NKEY_61 0xff +#define NKEY_62 0xff +#define NKEY_63 0xff +#define NKEY_64 0xff +#define NKEY_65 0xff +#define NKEY_66 0xff +#define NKEY_67 0xff +#define NKEY_68 0xff +#define NKEY_69 0xff +#define NKEY_6A 0xff +#define NKEY_6B 0xff +#define NKEY_6C 0xff +#define NKEY_6D 0xff +#define NKEY_6E 0xff +#define NKEY_6F 0xff +#define NKEY_70 0xff +#define NKEY_71 0xff +#define NKEY_72 0xff +#define NKEY_73 0xff +#define NKEY_74 0xff +#define NKEY_75 0xff +#define NKEY_76 0xff +#define NKEY_77 0xff +#define NKEY_78 0xff +#define NKEY_79 0xff +#define NKEY_7A 0xff +#define NKEY_7B 0xff +#define NKEY_7C 0xff +#define NKEY_7D 0xff +#define NKEY_7E 0xff +#define NKEY_7F 0xff +#define NKEY_80 0xff +#define NKEY_81 0xff +#define NKEY_82 0xff +#define NKEY_83 0xff +#define NKEY_84 0xff +#define NKEY_85 0xff +#define NKEY_86 0xff +#define NKEY_87 0xff +#define NKEY_88 0xff +#define NKEY_89 0xff +#define NKEY_8A 0xff +#define NKEY_8B 0xff +#define NKEY_8C 0xff +#define NKEY_8D 0xff +#define NKEY_8E 0xff +#define NKEY_8F 0xff +#define NKEY_90 0xff +#define NKEY_91 0xff +#define NKEY_92 0xff +#define NKEY_93 0xff +#define NKEY_94 0xff +#define NKEY_95 0xff + + +typedef struct _IR_CODE { + u16 wData; //<键值 + u16 wUserCode; //<用户码 + u16 timer_pad; + u8 bState; //<接收状态 + u8 boverflow; //<红外信号超时 +} IR_CODE; + +enum timer_sel { + TIMER0 = 0x4, + TIMER1 = 0x5, + TIMER2 = 0x6, + TIMER3 = 0x7, +}; + +struct irflt_platform_data { + u8 irflt_io; + u8 timer; +}; + +#define IRFLT_PLATFORM_DATA_BEGIN(data) \ + static const struct irflt_platform_data data = { + +#define IRFLT_PLATFORM_DATA_END() \ +}; + + +extern const struct device_operations irflt_dev_ops; + +void set_ir_clk(void); +void ir_input_io_sel(u8 port); +void ir_output_timer_sel(); +void ir_timeout_set(void); +void irflt_config(); +void log_irflt_info(); +u8 get_irflt_value(void); + +#endif + diff --git a/include_lib/driver/cpu/br23/asm/irq.h b/include_lib/driver/cpu/br23/asm/irq.h new file mode 100644 index 0000000..ddb458a --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/irq.h @@ -0,0 +1,16 @@ +#ifndef CPU_IRQ_H +#define CPU_IRQ_H + + +#include "asm/hwi.h" + +#define ___interrupt __attribute__((interrupt(""))) + + + + +#endif + + + + diff --git a/include_lib/driver/cpu/br23/asm/mcpwm.h b/include_lib/driver/cpu/br23/asm/mcpwm.h new file mode 100644 index 0000000..f4b685b --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/mcpwm.h @@ -0,0 +1,78 @@ +#ifndef _MCPWM_H_ +#define _MCPWM_H_ + + +#include "typedef.h" + + +/* 对齐方式选择 */ +typedef enum { + pwm_edge_aligned, ///< 边沿对齐模式 + pwm_center_aligned, ///< 中心对齐模式 +} pwm_aligned_mode_type; + +/* pwm通道选择 */ +typedef enum { + pwm_ch0, + pwm_ch1, + pwm_ch2, + pwm_ch3, + pwm_ch4, + pwm_ch5, + pwm_ch_max, +} pwm_ch_num_type; + +/* pwm timer通道选择 */ +typedef enum { + pwm_timer0, + pwm_timer1, + pwm_timer2, + pwm_timer3, + pwm_timer4, + pwm_timer5, + pwm_timer_max, +} pwm_timer_num_type; + +/* MCPWM TIMER寄存器 */ +typedef struct _pwm_timer_reg { + volatile u32 tmr_con; + volatile u32 tmr_cnt; + volatile u32 tmr_pr; +} PWM_TIMER_REG; + +/* MCPWM通道寄存器 */ +typedef struct _pwm_ch_reg { + volatile u32 ch_con0; + volatile u32 ch_con1; + volatile u32 ch_cmph; + volatile u32 ch_cmpl; +} PWM_CH_REG; + +/* 初始化要用的参数结构体 */ +struct pwm_platform_data { + u32 frequency; ///< 初始共同频率,CH0, CH, CH2, CH3, CH4 + pwm_ch_num_type pwm_ch_num; ///< 选择pwm通道 + pwm_timer_num_type pwm_timer_num; ///< 选择timer时基 + u16 duty; ///< 初始占空比,0~10000 对应 0%~100% 。每个通道可以有不同的占空比。互补模式的占空比体现在高引脚的波形上。 + pwm_aligned_mode_type pwm_aligned_mode; ///< PWM对齐方式选择 + u8 h_pin; ///< 一个通道的高引脚,建议选择硬件引脚。填入-1 表示没有此引脚。当选择非硬件引脚时,不仅该引脚会输出波形,对应的硬件引脚也会有波形输出。 + u8 l_pin; ///< 一个通道的低引脚,建议选择硬件引脚。填入-1 表示没有此引脚。当选择非硬件引脚时,不仅该引脚会输出波形,对应的硬件引脚也会有波形输出。 + u8 h_pin_output_ch_num; ///< 当高引脚选择了非硬件引脚时,该参数才有效。选用第几个gpio_output_channle, 值:0~2。 + u8 l_pin_output_ch_num; ///< 当高引脚选择了非硬件引脚时,该参数才有效。选用第几个gpio_output_channle, 值:0~2。不能与h_pin_output_ch_num的值一样。 + u8 complementary_en; ///< 该通道的两个引脚输出的波形是否需要互补。1: 同步, 0: 互补 +}; + +//枚举触发模式 +typedef enum { + rising_edge_trigger, //上升沿触发 + falling_edge_trigger, //下降沿触发 +} trigger_mode_type; + +typedef void (*IO_ISR_FUNC)(void); + + +int timer_pwm_init(JL_TIMER_TypeDef *JL_TIMERx, u32 fre, u32 duty, u32 port, int output_ch); +void set_timer_pwm_duty(JL_TIMER_TypeDef *JL_TIMERx, u32 duty); + +#endif + diff --git a/include_lib/driver/cpu/br23/asm/plcnt.h b/include_lib/driver/cpu/br23/asm/plcnt.h new file mode 100644 index 0000000..8e78e5a --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/plcnt.h @@ -0,0 +1,30 @@ +#ifndef _PLCNT_DRV_H_ +#define _PLCNT_DRV_H_ + +#define TOUCH_KEY_CH_MAX 3 + +typedef struct _CTM_KEY_VAR { + s32 touch_release_buf[TOUCH_KEY_CH_MAX]; //按键释放值滤波器buffer + u16 touch_cnt_buf[TOUCH_KEY_CH_MAX]; //按键计数值滤波器buffer + s16 FLT1CFG1; //滤波器1配置参数1 + s16 FLT1CFG2; //滤波器1配置参数2, 等于(-RELEASECFG0)<SPI_CON |= BIT(0)|BIT(8);}\ + else{JL_P33->SPI_CON &= ~BIT(8);JL_P33->SPI_CON |= BIT(0);}}while(0) + +#define p33_cs_l do{JL_P33->SPI_CON &= ~(BIT(0)|BIT(8));local_irq_enable();}while(0) + + + +#define P33_OR 0b001 +#define P33_AND 0b010 +#define P33_XOR 0b011 +//===============================================================================// +// +// +// +//===============================================================================// +//............. 0x0000 - 0x000f............ for analog control +#define P3_ANA_CON0 0x00 +#define P3_ANA_CON1 0x01 +#define P3_ANA_CON2 0x02 +#define P3_ANA_CON3 0x03 +#define P3_ANA_CON4 0x04 +#define P3_ANA_CON5 0x05 +#define P3_ANA_CON6 0x06 +#define P3_ANA_CON7 0x07 +#define P3_ANA_CON8 0x08 +#define P3_ANA_CON9 0x09 + +#define P3_L5V_CON0 0x0c +#define P3_L5V_CON1 0x0d +#define P3_SDPG_CON 0x0e +#define P3_FSPG_CON 0x0f + + +//............. 0x0010 - 0x001f............ for analog others +#define P3_PLVD_CON 0x10 +#define P3_VLVD_CON 0x11 +#define P3_RST_SRC 0x12 +#define P3_LRC_CON0 0x13 +#define P3_LRC_CON1 0x14 +#define P3_RST_CON0 0x15 +#define P3_ANA_KEEP 0x16 +#define P3_VLD_KEEP 0x17 +#define P3_CHG_WKUP 0x18 +#define P3_CHG_READ 0x19 +#define P3_CHG_CON0 0x1a +#define P3_CHG_CON1 0x1b +#define P3_CHG_CON2 0x1c +#define P3_CHG_CON3 0x1d + +//............. 0x0020 - 0x002f............ for reserved + +//............. 0x0030 - 0x003f............ for PMU manager +#define P3_PMU_CON0 0x30 +#define P3_PMU_CON1 0x31 +#define P3_PMU_CON2 0x32 +#define P3_PMU_CON3 0x33 +#define P3_PMU_CON4 0x34 +#define P3_PMU_CON5 0x35 +#define P3_LP_PRP0 0x36 +#define P3_LP_PRP1 0x37 +#define P3_LP_STB0_STB1 0x38 +#define P3_LP_STB2_STB3 0x39 +#define P3_LP_STB4_STB5 0x3a +#define P3_LP_STB6 0x3b + +//............. 0x0040 - 0x005f............ for PMU timer +#define P3_LP_RSC00 0x40 +#define P3_LP_RSC01 0x41 +#define P3_LP_RSC02 0x42 +#define P3_LP_RSC03 0x43 +#define P3_LP_PRD00 0x44 +#define P3_LP_PRD01 0x45 +#define P3_LP_PRD02 0x46 +#define P3_LP_PRD03 0x47 +#define P3_LP_RSC10 0x48 +#define P3_LP_RSC11 0x49 +#define P3_LP_RSC12 0x4a +#define P3_LP_RSC13 0x4b +#define P3_LP_PRD10 0x4c +#define P3_LP_PRD11 0x4d +#define P3_LP_PRD12 0x4e +#define P3_LP_PRD13 0x4f +// +#define P3_LP_TMR0_CLK 0x54 +#define P3_LP_TMR0_CON 0x58 +#define P3_LP_TMR1_CON 0x59 + +//............. 0x0060 - 0x006f............ for PMU others +#define P3_LP_CNTRD0 0x60 +#define P3_LP_CNTRD1 0x61 +#define P3_LP_CNT0 0x62 +#define P3_LP_CNT1 0x63 +#define P3_LP_CNT2 0x64 +#define P3_LP_CNT3 0x65 + +//............. 0x0070 - 0x007f............ for PMU others +#define P3_MSTM_RD 0x70 +#define P3_IVS_RD 0x71 +#define P3_IVS_SET 0x72 +#define P3_IVS_CLR 0x73 +#define P3_WLDO12_AUTO 0x74 +#define P3_WLDO06_AUTO 0x75 + +//............. 0x0080 - 0x008f............ for RTC +#define P3_WDT_CON 0x80 + +//............. 0x0090 - 0x009f............ for PORT and clock reset power control +#define P3_WKUP_EN 0x90 +#define P3_WKUP_EDGE 0x91 +#define P3_WKUP_CPND 0x92 +#define P3_WKUP_PND 0x93 +#define P3_PINR_CON 0x94 +#define P3_WKUP_FLEN 0x95 +#define P3_PCNT_CON 0x96 +#define P3_PCNT_VLUE 0x97 + + +//............. 0x00a0 - 0x00af............ +#define P3_PR_PWR 0xa0 +#define P3_LDO5V_CON 0xa1 +#define P3_LVCMP_CON 0xa2 +#define P3_L5DEM_CON 0xa3 +#define P3_L5DEM_FLT 0xa4 +#define P3_OSL_CON 0xa5 +#define P3_CLK_CON0 0xa6 + +#define P3_WKUP_SRC 0xa8 +#define P3_WKUP_SUB 0xa9 +#define P3_PORT_FLT 0xaa + +#define P3_ANA_LAT 0xaf + +//............. 0x00b0 - 0x00bf............ for EFUSE +#define P3_EFUSE_CON0 0xb0 +#define P3_EFUSE_CON1 0xb1 +#define P3_EFUSE_RDAT 0xb2 + +//............. 0x00c0 - 0x00cf............ for rtc +#define P3_PORT_SEL10 0xc0 +#define P3_PORT_SEL11 0xc1 +#define P3_PORT_SEL12 0xc2 +#define P3_PORT_SEL13 0xc3 +#define P3_PORT_SEL14 0xc4 +#define P3_PORT_SEL15 0xc5 +#define P3_PORT_SEL16 0xc6 +#define P3_PORT_SEL17 0xc7 + +//............. others ............ +#define P3_SOFT_FLAG P3_PMU_CON2 +#define P3_SOFT_FLAG1 P3_PMU_CON3 + + +//===============================================================================// +// +// p33 rtcvdd +// +//===============================================================================// +#define RTC_SFR_BEGIN 0x8000 + + + +//............. 0x0080 - 0x008f............ for RTC +#define R3_ALM_CON (0x80 | RTC_SFR_BEGIN) + +#define R3_RTC_CON0 (0x84 | RTC_SFR_BEGIN) +#define R3_RTC_CON1 (0x85 | RTC_SFR_BEGIN) +#define R3_RTC_DAT0 (0x86 | RTC_SFR_BEGIN) +#define R3_RTC_DAT1 (0x87 | RTC_SFR_BEGIN) +#define R3_RTC_DAT2 (0x88 | RTC_SFR_BEGIN) +#define R3_RTC_DAT3 (0x89 | RTC_SFR_BEGIN) +#define R3_RTC_DAT4 (0x8a | RTC_SFR_BEGIN) + +//............. 0x0090 - 0x009f............ for PORT control +#define R3_WKUP_EN (0x90 | RTC_SFR_BEGIN) +#define R3_WKUP_EDGE (0x91 | RTC_SFR_BEGIN) +#define R3_WKUP_CPND (0x92 | RTC_SFR_BEGIN) +#define R3_WKUP_PND (0x93 | RTC_SFR_BEGIN) +#define R3_WKUP_FLEN (0x94 | RTC_SFR_BEGIN) +#define R3_PORT_FLT (0x95 | RTC_SFR_BEGIN) + +#define R3_PR_IN (0x98 | RTC_SFR_BEGIN) +#define R3_PR_OUT (0x99 | RTC_SFR_BEGIN) +#define R3_PR_DIR (0x9a | RTC_SFR_BEGIN) +#define R3_PR_DIE (0x9b | RTC_SFR_BEGIN) +#define R3_PR_PU (0x9c | RTC_SFR_BEGIN) +#define R3_PR_PD (0x9d | RTC_SFR_BEGIN) +#define R3_PR_HD (0x9e | RTC_SFR_BEGIN) + +//............. 0x00a0 - 0x00af............ for system +#define R3_TIME_CON (0xa0 | RTC_SFR_BEGIN) +#define R3_TIME_CPND (0xa1 | RTC_SFR_BEGIN) +#define R3_TIME_PND (0xa2 | RTC_SFR_BEGIN) + +#define R3_ADC_CON (0xa4 | RTC_SFR_BEGIN) +#define R3_OSL_CON (0xa5 | RTC_SFR_BEGIN) + +#define R3_WKUP_SRC (0xa8 | RTC_SFR_BEGIN) +#define R3_RST_SRC (0xa9 | RTC_SFR_BEGIN) + +#define R3_RST_CON (0xab | RTC_SFR_BEGIN) +#define R3_CLK_CON (0xac | RTC_SFR_BEGIN) + + + +//others +#define P3_SOFT_FLAT P3_PMU_CON2 +//Soft flag +//[0] : 0-None +// : 1-BT_OSC init ensable +// +//[1] : 0-None +// : 1-RTC_OSC init ensable +// +//[2:3] : 0-none +// : 1-boot SPI PORTD_A +// : 2-boot SPI PORTD_B +// : 3-boot SPI PORTD_A & B +// +//[4] : 0-none +// : 1-switch to OSC_CLK +// +// + +enum { + SOFT_FLAG_BT_OSC_ENABLE = BIT(0), + SOFT_FLAG_RTC_OSC_ENABLE = BIT(1), + SOFT_FLAG_BOOT_SPI_PORTD_A = BIT(2), + SOFT_FLAG_BOOT_SPI_PORTD_B = BIT(3), + SOFT_FLAG_BOOT_SPI_ALL = BIT(2) | BIT(3), + SOFT_FLAG_SWITCH_OSC_CLK = BIT(4), + SOFT_FLAG_BOOT_OTP = BIT(5), +}; + +#define P3_SOFT_FLAT1 P3_PMU_CON3 +//Soft flag1 +//[0] : 0-open wdt +// : 1-none +// +//[1] : 0-usb None +// : 1-usb dp close pd +// +//[2] : 0-None +// : 1-usb dp open pu +// +//[3] : 0-usb None +// : 1-usb dm close pd +// +//[4] : 0-None +// : 1-usb dm open pu + +//[5] : 0-None +// : 1-enter power off flow +// +//[6] : 0-None +// : 1- btosc fast boot en +// +#define SOFT_FLAG_WDT_NONE BIT(0) +#define SOFT_FLAG_USB_DP_PD_DISABLE BIT(1) +#define SOFT_FLAG_USB_DP_PU_ENABLE BIT(2) +#define SOFT_FLAG_USB_DM_PD_DISABLE BIT(3) +#define SOFT_FLAG_USB_DM_PU_ENABLE BIT(4) +#define SOFT_FLAG_POWEROFF_ENABLE BIT(5) +#define SOFT_FLAG_BTOSC_FT_ENABLE BIT(6) + +//ROM +u8 p33_buf(u8 buf); + +void p33_xor_1byte(u16 addr, u8 data0); + +void p33_and_1byte(u16 addr, u8 data0); + +void p33_or_1byte(u16 addr, u8 data0); + +void p33_tx_1byte(u16 addr, u8 data0); + +u8 p33_rx_1byte(u16 addr); + +void P33_CON_SET(u16 addr, u8 start, u8 len, u8 data); + +void SET_WVDD_LEV(u8 lev); + +void RESET_MASK_SW(u8 sw); + +void NV_RAM_POWER_GATE(u8 sw); + +void close_32K(u8 keep_osci_flag); + +_INLINE_ +static u8 P33_CON_GET(u8 addr) +{ + u8 reg = 0; + reg = p33_rx_1byte(addr); + return reg; +} + +_INLINE_ +static void P33_TX_NBIT(u16 addr, u8 data0, u8 en) +{ + if (en) { + p33_or_1byte(addr, data0); + } else { + p33_and_1byte(addr, ~data0); + } +} + +_INLINE_ +static void P33_CON_DEBUG(void) +{ + u8 i = 0; + for (i = 0; i < P3_VLD_KEEP + 1; i++) { + // printf("--%x : %x--\n", i, P33_CON_GET(i)); + } +} + +/* + *-------------------P3_ANA_CON0 + */ +#define VDD13TO12_SYS_EN(en) P33_TX_NBIT(P3_ANA_CON0, BIT(0), en) + +#define LDO13_EN(en) P33_TX_NBIT(P3_ANA_CON0, BIT(2), en) + +// #define DCDC13_EN(en) P33_TX_NBIT(P3_ANA_CON0, BIT(3), en) + +#define PW_GATE_EN(en) P33_TX_NBIT(P3_ANA_CON0, BIT(5), en) + +#define RC_250k_EN(en) P33_TX_NBIT(P3_ANA_CON0, BIT(7), en) +/*******************************************************************/ + +/* + *-------------------P3_ANA_CON1 + */ +#define BTDCDC_V17_PDEN(en) P33_TX_NBIT(P3_ANA_CON1, BIT(0), en) + +#define BTDCDC_RAMP_EN(en) P33_TX_NBIT(P3_ANA_CON1, BIT(1), en) + +#define BTDCDC_PFM_MODE(en) P33_TX_NBIT(P3_ANA_CON1, BIT(2), en) + +#define WLDO06_EN(en) P33_TX_NBIT(P3_ANA_CON1, BIT(3), en) + +#define VDC13_LOAD_EN(en) P33_TX_NBIT(P3_ANA_CON1, BIT(4), en) + +#define VDC13_DESHOT_EN(en) P33_TX_NBIT(P3_ANA_CON1, BIT(5), en) + +#define SYSVDD_RES_SHORT_EN(en) P33_TX_NBIT(P3_ANA_CON1, BIT(6), en) + +#define SYSVDD_BYPASS_EN(en) P33_TX_NBIT(P3_ANA_CON1, BIT(7), en) +/*******************************************************************/ + +/* + *-------------------P3_ANA_CON2 + */ +#define VCM_DET_EN(en) P33_TX_NBIT(P3_ANA_CON2, BIT(3), en) + +#define D2SH_EN_SW(en) P33_TX_NBIT(P3_ANA_CON2, BIT(4), en) + +#define FAST_UP_EN(en) P33_TX_NBIT(P3_ANA_CON2, BIT(5), en) + +#define VDDOK_DIS(dis) P33_TX_NBIT(P3_ANA_CON2, BIT(6), dis) + +#define SWVLD_AUTO_EN(en) P33_TX_NBIT(P3_ANA_CON2, BIT(7), en) +/*******************************************************************/ + +/* + *-------------------P3_ANA_CON3 + */ +#define FORCE_BYPASS_EN(en) P33_TX_NBIT(P3_ANA_CON3, BIT(2), en) + +#define IVBATL_EN(en) P33_TX_NBIT(P3_ANA_CON3, BIT(1), en) +/*******************************************************************/ + +/* + *-------------------P3_ANA_CON4 + */ +#define PMU_DET_EN(en) P33_TX_NBIT(P3_ANA_CON4, BIT(0), en) + +#define ADC_CHANNEL_SEL(ch) P33_CON_SET(P3_ANA_CON4, 1, 3, ch) +//Macro for ADC_CHANNEL_SEL +enum { + ADC_CHANNEL_SEL_VBG = 0, + ADC_CHANNEL_SEL_VDC13, + ADC_CHANNEL_SEL_SYSVDD, + ADC_CHANNEL_SEL_VTEMP, + ADC_CHANNEL_SEL_PROGF, + ADC_CHANNEL_SEL_VBAT1_4, + ADC_CHANNEL_SEL_LDO5V1_4, + ADC_CHANNEL_SEL_WVDD, +}; +/*******************************************************************/ + + +/* + *-------------------P3_ANA_CON5 + */ +#define VDDIOM_VOL_SEL(lev) P33_CON_SET(P3_ANA_CON5, 0, 3, lev) + +#define GET_VDDIOM_VOL() (P33_CON_GET(P3_ANA_CON5) & 0xf) + +#define VDDIOW_VOL_SEL(lev) P33_CON_SET(P3_ANA_CON5, 4, 2, lev) + +#define GET_VDDIOW_VOL() (P33_CON_GET(P3_ANA_CON5)>>4 & 0x3) + +#define VDDIO_HD_SEL(cur) P33_CON_SET(P3_ANA_CON5, 6, 2, cur) + +/*******************************************************************/ + +/* + *-------------------P3_ANA_CON6 + */ +#define VDC13_VOL_SEL(sel) P33_CON_SET(P3_ANA_CON6, 0, 3, sel) +//Macro for VDC13_VOL_SEL +enum { + VDC13_VOL_SEL_105V = 0, + VDC13_VOL_SEL_110V, + VDC13_VOL_SEL_115V, + VDC13_VOL_SEL_120V, + VDC13_VOL_SEL_125V, + VDC13_VOL_SEL_130V, + VDC13_VOL_SEL_135V, + VDC13_VOL_SEL_140V, +}; + +#define GET_VD13_HD_SEL() (P33_CON_GET(P3_ANA_CON6) & 0x7) +#define GET_VD13_VOL_SEL() (P33_CON_GET(P3_ANA_CON6) & 0x7) + +#define VD13_HD_SEL(sel) P33_CON_SET(P3_ANA_CON6, 0, 2, sel) + +/*******************************************************************/ + +/* + *-------------------P3_ANA_CON7 + */ +#define BTDCDC_BIAS_HD_SEL(sel) P33_CON_SET(P3_ANA_CON7, 0, 2, sel) +//Macro for BTDCDC_BIAS_HD_SEL +enum { + BTDCDC_BIAS_HD_SEL_1uA = 0, + BTDCDC_BIAS_HD_SEL_1P5uA, + BTDCDC_BIAS_HD_SEL_2uA, + BTDCDC_BIAS_HD_SEL_2P5uA, +}; + +#define BTDCDC_DUTY_SEL(sel) P33_CON_SET(P3_ANA_CON7, 2, 2, sel) + +#define BTDCDC_OSC_SEL(sel) P33_CON_SET(P3_ANA_CON7, 4, 2, sel) +//Macro for BTDCDC_OSC_SEL +enum { + BTDCDC_OSC_SEL0537MHz = 0, + BTDCDC_OSC_SEL0789MHz, + BTDCDC_OSC_SEL1030MHz, + BTDCDC_OSC_SEL1270MHz, + BTDCDC_OSC_SEL1720MHz, + BTDCDC_OSC_SEL1940MHz, + BTDCDC_OSC_SEL2150MHz, + BTDCDC_OSC_SEL2360MHz, +}; +/*******************************************************************/ + +/* + *-------------------P3_ANA_CON9 + */ +#define SYSVDD_VOL_SEL(sel) P33_CON_SET(P3_ANA_CON9, 0, 4, sel) +//Macro for SYSVDD_VOL_SEL +enum { + SYSVDD_VOL_SEL_084V = 0, + SYSVDD_VOL_SEL_087V, + SYSVDD_VOL_SEL_090V, + SYSVDD_VOL_SEL_093V, + SYSVDD_VOL_SEL_096V, + SYSVDD_VOL_SEL_099V, + SYSVDD_VOL_SEL_102V, + SYSVDD_VOL_SEL_105V, + SYSVDD_VOL_SEL_108V, + SYSVDD_VOL_SEL_111V, + SYSVDD_VOL_SEL_114V, + SYSVDD_VOL_SEL_117V, + SYSVDD_VOL_SEL_120V, + SYSVDD_VOL_SEL_123V, + SYSVDD_VOL_SEL_126V, + SYSVDD_VOL_SEL_129V, +}; + +#define GET_SYSVDD_VOL_SEL() (P33_CON_GET(P3_ANA_CON9) & 0xf) + +#define SYSVDD_VOL_HD_SEL(sel) P33_CON_SET(P3_ANA_CON9, 4, 2, sel) +/*******************************************************************/ + + +/* + *-------------------P3_VLVD_CON + */ +#define P33_VLVD_EN(en) P33_TX_NBIT(P3_VLVD_CON, BIT(0), en) + +#define P33_VLVD_PS(en) P33_TX_NBIT(P3_VLVD_CON, BIT(1), en) + +#define P33_VLVD_OE(en) P33_TX_NBIT(P3_VLVD_CON, BIT(2), en) + +#define VLVD_SEL(lev) P33_CON_SET(P3_VLVD_CON, 3, 3, lev) + +#define GET_VLVD_SEL() ((P33_CON_GET(P3_VLVD_CON) & 0x70 )>> 3) + + +//Macro for VLVD_SEL +enum { + VLVD_SEL_19V = 0, + VLVD_SEL_20V, + VLVD_SEL_21V, + VLVD_SEL_22V, + VLVD_SEL_23V, + VLVD_SEL_24V, + VLVD_SEL_25V, + VLVD_SEL_26V, +}; + +#define VLVD_PND_CLR(clr) P33_TX_NBIT(P3_VLVD_CON, BIT(6), clr) + +#define VLVD_PND(pend) P33_TX_NBIT(P3_VLVD_CON, BIT(7), pend) +/*******************************************************************/ + +/* + *-------------------P3_RST_CON0 + */ +#define VLVD_RST_EN(en) P33_TX_NBIT(P3_RST_CON0, BIT(2), en) + +#define VLVD_WKUP_EN(en) P33_TX_NBIT(P3_RST_CON0, BIT(3), en) +/*******************************************************************/ + +/* + *-------------------P3_LRC_CON0 + */ +#define RC32K_EN(en) P33_TX_NBIT(P3_LRC_CON0, BIT(0), en) + +#define RC32K_RN_TRIM(en) P33_TX_NBIT(P3_LRC_CON0, BIT(1), en) + +#define RC32K_RPPS_SEL(sel) P33_CON_SET(P3_LRC_CON0, 4, 2, sel) + +#define RC32K_RNPS_SEL(sel) P33_TX_NBIT(P3_LRC_CON0, BIT(7), (sel & BIT(0))); \ + P33_CON_SET(P3_LRC_CON1, 0, 2, (sel>>1)) +/*******************************************************************/ + +/* + *-------------------P3_LRC_CON1 + */ +//#define RC32K_PNPS_SEL(sel) P33_CON_SET(P3_LRC_CON1, 0, 2, sel) + +#define RC32K_CAP_SEL(sel) P33_CON_SET(P3_LRC_CON1, 2, 3, sel) + +#define RC32K_LDO_SEL(sel) P33_CON_SET(P3_LRC_CON1, 5, 2, sel) +/*******************************************************************/ + +/* + *-------------------P3_ANA_KEEP + */ +#define PDIO_KEEP(a) P33_TX_NBIT(P3_ANA_KEEP, BIT(6), a) +/*******************************************************************/ + +/* + *-------------------P3_VLD_KEEP + */ +#define CLOCK_KEEP(a) P33_TX_NBIT(P3_VLD_KEEP, BIT(0), a) + +#define WKUP_KEEP(a) P33_TX_NBIT(P3_VLD_KEEP, BIT(1), a) + +#define FLASH_KEEP(a) P33_TX_NBIT(P3_VLD_KEEP, BIT(2), a) + +#define PWM_LED_KEEP(a) P33_TX_NBIT(P3_VLD_KEEP, BIT(3), a) + +#define SYS_RST_KEEP(a) P33_TX_NBIT(P3_VLD_KEEP, BIT(4), a) + +#define SYS_VDD_KEEP(a) P33_TX_NBIT(P3_VLD_KEEP, BIT(5), a) + +#define WDT_EXPT_EN(a) P33_TX_NBIT(P3_VLD_KEEP, BIT(6), a) +/*******************************************************************/ + +/* + *-------------------P3_CLK_CON0 + */ +#define PWM_LED_SEL(a) P33_CON_SET(P3_CLK_CON0, 0, 2, a) + +#define SYSPLL_DPLL_REF(a) P33_TX_NBIT(P3_VLVD_KEEP, BIT(2), a) + +/*******************************************************************/ + + +void chg_reg_set(u8 addr, u8 start, u8 len, u8 data); +u8 chg_reg_get(u8 addr); + +/* + *-------------------P3_CHG_WKUP + */ +// #define CHARGE_LEVEL_DETECT_EN(a) P33_CON_SET(P3_CHG_WKUP, 0, 1, a) +#define CHARGE_LEVEL_DETECT_EN(a) chg_reg_set(P3_CHG_WKUP, 0, 1, a) + +// #define CHARGE_EDGE_DETECT_EN(a) P33_CON_SET(P3_CHG_WKUP, 1, 1, a) +#define CHARGE_EDGE_DETECT_EN(a) chg_reg_set(P3_CHG_WKUP, 1, 1, a) + +// #define CHARGE_WKUP_SOURCE_SEL(a) P33_CON_SET(P3_CHG_WKUP, 2, 2, a) +#define CHARGE_WKUP_SOURCE_SEL(a) chg_reg_set(P3_CHG_WKUP, 2, 2, a) + +// #define CHARGE_WKUP_EN(a) P33_CON_SET(P3_CHG_WKUP, 4, 1, a) +#define CHARGE_WKUP_EN(a) chg_reg_set(P3_CHG_WKUP, 4, 1, a) + +// #define CHARGE_WKUP_EDGE_SEL(a) P33_CON_SET(P3_CHG_WKUP, 5, 1, a) +#define CHARGE_WKUP_EDGE_SEL(a) chg_reg_set(P3_CHG_WKUP, 5, 1, a) + +// #define CHARGE_WKUP_PND_CLR() P33_CON_SET(P3_CHG_WKUP, 6, 1, 1) +#define CHARGE_WKUP_PND_CLR() chg_reg_set(P3_CHG_WKUP, 6, 1, 1) + +/* + *-------------------P3_CHG_READ 该寄存器不可读 + */ +// #define CHARGE_FULL_FLAG_GET() ((P33_CON_GET(P3_CHG_READ) & BIT(0)) ? 1: 0 ) + +/* + *-------------------P3_CHG_CON0 + */ +// #define CHARGE_EN(en) P33_CON_SET(P3_CHG_CON0, 0, 1, en) +#define CHARGE_EN(en) chg_reg_set(P3_CHG_CON0, 0, 1, en) + +// #define CHGBG_EN(en) P33_CON_SET(P3_CHG_CON0, 1, 1, en) +#define CHGBG_EN(en) chg_reg_set(P3_CHG_CON0, 1, 1, en) + +// #define IS_CHARGE_EN() ((P33_CON_GET(P3_CHG_CON0) & BIT(0)) ? 1: 0 ) +#define IS_CHARGE_EN() ((chg_reg_get(P3_CHG_CON0) & BIT(0)) ? 1: 0 ) + +/* + *-------------------P3_CHG_CON1 + */ +// #define CHARGE_FULL_V_SEL(a) P33_CON_SET(P3_CHG_CON1, 0, 4, a) +#define CHARGE_FULL_V_SEL(a) chg_reg_set(P3_CHG_CON1, 0, 4, a) + +// #define CHARGE_mA_SEL(a) P33_CON_SET(P3_CHG_CON1, 4, 4, a) +#define CHARGE_mA_SEL(a) chg_reg_set(P3_CHG_CON1, 4, 4, a) + +/* + *-------------------P3_CHG_CON2 + */ +// #define CHARGE_FULL_mA_SEL(a) P33_CON_SET(P3_CHG_CON2, 4, 3, a) +#define CHARGE_FULL_mA_SEL(a) chg_reg_set(P3_CHG_CON2, 4, 3, a) + +/* + *-------------------P3_LDO5V_CON + */ +#define LDO5V_EN(a) P33_CON_SET(P3_LDO5V_CON, 0, 1, a) + +#define LDO5V_IS_EN() ((P33_CON_GET(P3_LDO5V_CON) & BIT(0)) ? 1: 0 ) + +#define LDO5V_EDGE_SEL(a) P33_CON_SET(P3_LDO5V_CON, 1, 1, a) + +#define LDO5V_EDGE_GET() ((P33_CON_GET(P3_LDO5V_CON) & BIT(1)) ? 1: 0 ) + +#define LDO5V_LEVEL_WKUP_EN(a) P33_CON_SET(P3_LDO5V_CON, 2, 1, a) + +#define LDO5V_EDGE_WKUP_EN(a) P33_CON_SET(P3_LDO5V_CON, 3, 1, a) + +#define LDO5V_EDGE_WKUP_IS_EN() ((P33_CON_GET(P3_LDO5V_CON) & BIT(3)) ? 1: 0 ) + +#define LDO5V_DET_GET() ((P33_CON_GET(P3_LDO5V_CON) & BIT(5)) ? 1: 0 ) + +#define LDO5V_PND_CLR() P33_CON_SET(P3_LDO5V_CON, 6, 1, 1) + +/* + *-------------------P3_LVCMP_CON + */ +#define LVCMP_EN(a) P33_CON_SET(P3_LVCMP_CON, 0, 1, a) + +#define LVCMP_EDGE_SEL(a) P33_CON_SET(P3_LVCMP_CON, 1, 1, a) + +#define LVCMP_LEVEL_WKUP_EN(a) P33_CON_SET(P3_LVCMP_CON, 2, 1, a) + +#define LVCMP_EDGE_WKUP_EN(a) P33_CON_SET(P3_LVCMP_CON, 3, 1, a) + +#define LVCMP_CMP_SEL(a) P33_CON_SET(P3_LVCMP_CON, 4, 1, a) + +#define LVCMP_DET_GET() ((P33_CON_GET(P3_LVCMP_CON) & BIT(5)) ? 1: 0 ) + +#define LVCMP_PND_CLR() P33_CON_SET(P3_LVCMP_CON, 6, 1, 1) + +/* + *-------------------P3_L5DEM_CON + */ +#define L5DEM_EN(a) P33_CON_SET(P3_L5DEM_CON, 0, 1, a) + +#define L5DEM_EDGE_SEL(a) P33_CON_SET(P3_L5DEM_CON, 1, 1, a) + +#define L5DEM_LEVEL_WKUP_EN(a) P33_CON_SET(P3_L5DEM_CON, 2, 1, a) + +#define L5DEM_EDGE_WKUP_EN(a) P33_CON_SET(P3_L5DEM_CON, 3, 1, a) + +#define L5DEM_DET_GET() ((P33_CON_GET(P3_L5DEM_CON) & BIT(5)) ? 1: 0 ) + +#define L5DEM_PND_CLR() P33_CON_SET(P3_L5DEM_CON, 6, 1, 1) + +/* + *-------------------P3_L5DEM_FLT + */ +#define L5DEM_FIT_SEL(a) P33_CON_SET(P3_L5DEM_FLT, 0, 3, a) + +/* + *-------------------P3_WKUP_SUB + */ +#define IS_LVCMP_WKUP() ((P33_CON_GET(P3_WKUP_SUB) & BIT(0)) ? 1: 0 ) + +#define IS_LDO5V_WKUP() ((P33_CON_GET(P3_WKUP_SUB) & BIT(1)) ? 1: 0 ) + +#define IS_L5DEM_WKUP() ((P33_CON_GET(P3_WKUP_SUB) & BIT(2)) ? 1: 0 ) + +/* + *-------------------P3_L5V_CON0 + */ +#define L5V_LOAD_EN(a) P33_CON_SET(P3_L5V_CON0, 0, 1, a) + +#define L5V_RES_DET_EN(a) P33_CON_SET(P3_L5V_CON0, 1, 1, a) + +#define L5V_VM_EN(a) P33_CON_SET(P3_L5V_CON0, 2, 1, a) + +#define L5V_IM_EN(a) P33_CON_SET(P3_L5V_CON0, 3, 1, a) + +#define L5V_IM_S_SEL(a) P33_CON_SET(P3_L5V_CON0, 4, 2, a) + +/* + *-------------------P3_L5V_CON1 + */ +#define L5V_RES_DET_S_SEL(a) P33_CON_SET(P3_L5V_CON1, 0, 2, a) + +#define L5V_VM_S_SEL(a) P33_CON_SET(P3_L5V_CON1, 4, 2, a) + + +//是否需要保持强LDO判断宏 +#define IS_NEED_KEEP_POWER() (IS_CHARGE_EN() || LVCMP_DET_GET()) + + +/*******************************************************************/ + +//Macro for P3_WLDO06_AUTO +enum { + WLDO_LEVEL_050V = 0, + WLDO_LEVEL_054V, + WLDO_LEVEL_058V, + WLDO_LEVEL_062V, + WLDO_LEVEL_066V, + WLDO_LEVEL_070V, + WLDO_LEVEL_085V, + WLDO_LEVEL_133V, +}; + +//===============================================================================// +// +// p33 rtcvdd +// +//===============================================================================// + +/* + *-------------------R3_ALM_CON + */ +#define ALM_ALMOUT(a) P33_CON_SET(R3_ALM_CON, 7, 1, a) + +#define ALM_CLK_SEL(a) P33_CON_SET(R3_ALM_CON, 2, 2, a) + +#define ALM_ALMEN(a) P33_CON_SET(R3_ALM_CON, 0, 1, a) + + + +//Macro for CLK_SEL +enum { + CLK_SEL_32K = 1, + CLK_SEL_12M, + CLK_SEL_24M, +}; + + + +/* + *-------------------R3_RTC_CON0 + */ +#define RTC_ALM_RDEN(a) P33_CON_SET(R3_RTC_CON0, 5, 1, a) + +#define RTC_RTC_RDEN(a) P33_CON_SET(R3_RTC_CON0, 4, 1, a) + +#define RTC_ALM_WREN(a) P33_CON_SET(R3_RTC_CON0, 1, 1, a) + +#define RTC_RTC_WREN(a) P33_CON_SET(R3_RTC_CON0, 0, 1, a) + + + +/* + *-------------------R3_OSL_CON + */ +#define OSL_X32XS(a) P33_CON_SET(R3_OSL_CON, 4, 2, a) + +#define OSL_X32TS(a) P33_CON_SET(R3_OSL_CON, 2, 1, a) + +#define OSL_X32OS(a) P33_CON_SET(R3_OSL_CON, 1, 1, a) + +#define OSL_X32ES(a) P33_CON_SET(R3_OSL_CON, 0, 1, a) + + +/* + *-------------------R3_TIME_CPND + */ +#define TIME_256HZ_CPND(a) P33_CON_SET(R3_TIME_CPND, 0, 1, a) + +#define TIME_64HZ_CPND(a) P33_CON_SET(R3_TIME_CPND, 1, 1, a) + +#define TIME_2HZ_CPND(a) P33_CON_SET(R3_TIME_CPND, 2, 1, a) + +#define TIME_1HZ_CPND(a) P33_CON_SET(R3_TIME_CPND, 3, 1, a) + +#endif + diff --git a/include_lib/driver/cpu/br23/asm/power_interface.h b/include_lib/driver/cpu/br23/asm/power_interface.h new file mode 100644 index 0000000..b2685d2 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/power_interface.h @@ -0,0 +1,300 @@ +#ifndef POWER_INTERFACE_H +#define POWER_INTERFACE_H + +// #include "asm/hwi.h" +// +#include "generic/typedef.h" +#define NEW_BASEBAND_COMPENSATION 0 + +#define AT_VOLATILE_RAM AT(.volatile_ram) +#define AT_VOLATILE_RAM_CODE AT(.volatile_ram_code) +#define AT_NON_VOLATILE_RAM AT(.non_volatile_ram) +#define AT_NON_VOLATILE_RAM_CODE AT(.non_volatile_ram_code) + +extern u32 nvbss_begin; +extern u32 nvbss_length; +extern u32 nvdata_begin; +extern u32 nvdata_size; +extern u32 nvdata_addr; + +#define NV_RAM_START &nvbss_begin +#define NV_RAM_SIZE &nvbss_length +#define NV_RAM_END (NV_RAM_START + NV_RAM_SIZE) + +enum { + MAGIC_ADDR = 2, + ENTRY_ADDR = 3, +}; +#define RAM1_MAGIC_ADDR (NV_RAM_END - MAGIC_ADDR*4) +#define RAM1_ENTRY_ADDR (NV_RAM_END - ENTRY_ADDR*4) + +#define SLEEP_EN BIT(2) +#define SLEEP_SAVE_TIME_US 1L +#define BT_SLEEP_RECOVER_TIME_US 2500L +#define LRC_SLEEP_RECOVER_TIME_US 4500L + +#define DEEP_SLEEP_EN BIT(1) +#define DSLEEP_SAVE_BEFORE_ENTER_MS 1 +#define DSLEEP_RECOVER_AFTER_EXIT_MS 10 +#define DEEP_SLEEP_TIMEOUT_MIN_US (60*625L) //间隔至少要60slot以上才进入power off + +#define SLEEP_TICKS_UNIT (10*1000L) // +#define DEEP_SLEEP_TICKS_UNIT (20*1000L) // + + +enum { + OSC_TYPE_LRC = 0, + OSC_TYPE_RTC, + OSC_TYPE_BT_OSC, +}; + +enum { + PWR_NO_CHANGE = 0, + PWR_LDO33, + PWR_LDO15, + PWR_DCDC15, +}; + +enum { + LONG_4S_RESET = 0, + LONG_8S_RESET, +}; + +//Macro for VDDIOM_VOL_SEL +enum { + VDDIOM_VOL_22V = 0, + VDDIOM_VOL_24V, + VDDIOM_VOL_26V, + VDDIOM_VOL_28V, + VDDIOM_VOL_30V, + VDDIOM_VOL_32V, + VDDIOM_VOL_34V, + VDDIOM_VOL_36V, +}; + +//Macro for VDDIOW_VOL_SEL +enum { + VDDIOW_VOL_21V = 0, + VDDIOW_VOL_24V, + VDDIOW_VOL_28V, + VDDIOW_VOL_32V, +}; + +struct low_power_param { + u8 osc_type; + u32 btosc_hz; + u8 delay_us; + u8 config; + u8 btosc_disable; + u8 dcdc_port; + + u8 vddiom_lev; + u8 vddiow_lev; + u8 pd_wdvdd_lev; + u8 vddio_keep; + u8 vdc13_keep; //如果进入低功耗时哒哒声,可以将该标志置1。该位置1时,会同时keep住vddio,单耳功耗会大100ua左右,对耳会大200ua左右。(哒哒声是由于电容的效应导致的) + + u32 osc_delay_us; + u8 virtual_rtc; + u8 rtc_clk; +}; + +#define BLUETOOTH_RESUME BIT(1) + +#define RISING_EDGE 0 +#define FALLING_EDGE 1 + +typedef enum { + PORT_FLT_NULL = 0, + PORT_FLT_32us, + PORT_FLT_64us, + PORT_FLT_128us, + PORT_FLT_256us, + PORT_FLT_512us, + PORT_FLT_1ms, + PORT_FLT_2ms, +} PORT_FLT; + +struct port_wakeup { + u8 pullup_down_enable; // + u8 edge; //[0]: Rising / [1]: Falling + u8 attribute; //Relate operation bitmap OS_RESUME | BLUETOOTH_RESUME + u8 iomap; //Port Group-Port Index + u8 filter_enable; +}; + +struct charge_wakeup { + u8 attribute; //Relate operation bitmap OS_RESUME | BLUETOOTH_RESUME +}; + +struct alarm_wakeup { + u8 attribute; //Relate operation bitmap OS_RESUME | BLUETOOTH_RESUME +}; + +struct lvd_wakeup { + u8 attribute; //Relate operation bitmap OS_RESUME | BLUETOOTH_RESUME +}; + +struct sub_wakeup { + u8 attribute; //Relate operation bitmap OS_RESUME | BLUETOOTH_RESUME +}; + +//亮->灭, 单位ms +#define CFG_LED0_BREATH_BRIGHT 300 //呼吸亮度, 范围: 0 ~ 500 +#define CFG_LED1_BREATH_BRIGHT 300 //呼吸亮度, 范围: 0 ~ 500 +#define CFG_LED_BREATH_BLINK_TIME 1000 //灭灯延时, 单位ms +#endif + +enum pwm_led_clk_source { + PWM_LED_CLK_RESERVED0, //PWM_LED_CLK_OSC32K, no use + PWM_LED_CLK_RC32K, //use + PWM_LED_CLK_RESERVED1, //PWM_LED_CLK_BTOSC_12M, no use + PWM_LED_CLK_RESERVED2, //PWM_LED_CLK_RCLK_250K, no use + PWM_LED_CLK_BTOSC_24M, //use +}; + +enum pwm_led_mode { + PWM_LED_MODE_START, + + PWM_LED_ALL_OFF, //mode1: 全灭 + PWM_LED_ALL_ON, //mode2: 全亮 + + PWM_LED0_ON, //mode3: 蓝亮 + PWM_LED0_OFF, //mode4: 蓝灭 + PWM_LED0_SLOW_FLASH, //mode5: 蓝慢闪 + PWM_LED0_FAST_FLASH, //mode6: 蓝快闪 + PWM_LED0_DOUBLE_FLASH_5S, //mode7: 蓝灯5秒连闪两下 + PWM_LED0_ONE_FLASH_5S, //mode8: 蓝灯5秒连闪1下 + + PWM_LED1_ON, //mode9: 红亮 + PWM_LED1_OFF, //mode10: 红灭 + PWM_LED1_SLOW_FLASH, //mode11: 红慢闪 + PWM_LED1_FAST_FLASH, //mode12: 红快闪 + PWM_LED1_DOUBLE_FLASH_5S, //mode13: 红灯5秒连闪两下 + PWM_LED1_ONE_FLASH_5S, //mode14: 红灯5秒闪1下 + + PWM_LED0_LED1_FAST_FLASH, //mode15: 红蓝交替闪(快闪) + PWM_LED0_LED1_SLOW_FLASH, //mode16: 红蓝交替闪(慢闪) + + PWM_LED0_BREATHE, //mode17: 蓝灯呼吸灯模式 + PWM_LED1_BREATHE, //mode18: 红灯呼吸灯模式 + PWM_LED0_LED1_BREATHE, //mode19: 红蓝交替呼吸灯模式 + + PWM_LED_MODE_END, + + PWM_LED1_FLASH_THREE, //自定义状态,不能通过pmd_led_mode去设置 + PWM_LED0_FLASH_THREE, //自定义状态,不能通过pmd_led_mode去设置 + + PWM_LED_USER_DEFINE_BEGIN = 0x50, + PWM_LED_USER_DEFINE_MODE0, //用户自定义模式0: + PWM_LED_USER_DEFINE_END, + + PWM_LED_NULL = 0xFF, +}; + +/************************************************** + * pwm led para + * ***********************************************/ +typedef struct { + u16 led0_bright;//led0_bright, LED0亮度: 0 ~ 500 + u16 led1_bright;//led1_bright, LED1亮度: 0 ~ 500 +} pwm_led_on_para; + +typedef struct { + u16 led0_bright;//led0_bright: led0亮度(0 ~ 500), + u16 led1_bright;//led1_bright: led1亮度(0 ~ 500), + u32 period;//period: 闪灯周期(ms), 多少ms闪一下(100 ~ 20000), 100ms - 20S, + u32 start_light_time;//start_light_time: 在周期中开始亮灯的时间, -1: 周期最后亮灯, 默认填-1即可, + u32 light_time;//light_time: 灯亮持续时间, +} pwm_led_one_flash_para; + +typedef struct { + u16 led0_bright;//led0_bright: led0亮度, + u16 led1_bright;//led1_bright: led1亮度, + u32 period;//period: 闪灯周期(ms), 多少ms闪一下 + u32 first_light_time;//first_light_time: 第一次亮灯持续时间, + u32 gap_time;//gap_time: 两次亮灯时间间隔, + u32 second_light_time;//second_light_time: 第二次亮灯持续时间, +} pwm_led_double_flash_para; + +typedef struct { + u16 breathe_time;//breathe_time: 呼吸周期(灭->最亮->灭), 设置范围: 500ms以上; + u16 led0_bright;//led0_bright: led0呼吸到最亮的亮度(0 ~ 500); + u16 led1_bright;//led1_bright: led1呼吸到最亮的亮度(0 ~ 500); + u32 led0_light_delay_time;//led0_light_delay_time: led0最高亮度延时(0 ~ 100ms); + u32 led1_light_delay_time;//led1_light_delay_time: led1最高亮度延时(0 ~ 100ms); + u32 led_blink_delay_time;//led_blink_delay_time: led0和led1灭灯延时(0 ~ 20000ms), 0 ~ 20S; +} pwm_led_breathe_para; + +typedef union { + pwm_led_on_para on; + pwm_led_one_flash_para one_flash; + pwm_led_double_flash_para double_flash; + pwm_led_breathe_para breathe; +} pwm_led_para; +/**************************************************/ + +struct pwm_led_two_io_mode { + u8 two_io_mode_enable; + u8 led0_pin; + u8 led1_pin; +}; +enum led_io_mode { + LED_ONE_IO_MODE, + LED_TWO_IO_MODE, +}; + +struct one_io_cfg { + u8 pin; +}; + +struct two_io_cfg { + u8 pin0; + u8 pin1; +}; + +union io_mode_cfg { + struct one_io_cfg one_io; + struct two_io_cfg two_io; +}; + +struct led_platform_data { + enum led_io_mode io_mode; + union io_mode_cfg io_cfg; +}; + +#define LED_PLATFORM_DATA_BEGIN(data) \ + const struct led_platform_data data = { + +#define LED_PLATFORM_DATA_END() \ +}; + +/*********************** LED 初始化 ******************************/ +void pwm_led_init(const struct led_platform_data *user_data); + +/********************** LED 闪烁模式切换 ************************/ +void pwm_led_mode_set(u8 fre_mode); +void pwm_led_mode_set_with_para(u8 display, pwm_led_para para); + +/***************************************************************** + LED时钟源切换, support: + PWM_LED_CLK_RC32K + PWM_LED_CLK_BTOSC_24M +*********************************************************************/ +void pwm_led_clk_set(enum pwm_led_clk_source src); + +/***************** 闪烁状态复位, 重新开始一个周期 ******************/ +void pwm_led_display_mode_reset(void); + +/***************** 获取led当前的闪烁模式 ***************************/ +enum pwm_led_mode pwm_led_display_mode_get(void); + +/******************************************************************** + 修改LED灯IO口驱动能力, 挡位: 0 ~ 3 + 0: 2.4mA(8mA mos + 120Ωres) + 1: 8mA(8mA mos) + 2: 18.4mA(24mA mos + 120Ωres) + 3: 24mA(24mA mos) +*********************************************************************/ +void pwm_led_io_max_drive_set(u8 strength); + +/******************* PWM 模块开关 *********************/ +void pwm_led_set_on(void); +void pwm_led_set_off(void); + +/******************* PWM 模块是否开启 *********************/ +u8 is_pwm_led_on(void); + +//=================================================================================// +//@brief: 自定义设置单灯闪状态 +//@input: void +// led_index: 0: led0, 1:led1, 2:led0 & led1(互闪) +// led0_bright, LED0亮度: 0 ~ 500 +// led1_bright, LED1亮度: 0 ~ 500 +// led1_bright: led1亮度, +// period: 闪灯周期(ms), 多少ms闪一下, +// start_light_time: 在周期中开始亮灯的时间, -1: 周期最后亮灯 +// light_time: 灯亮持续时间, +//@return: void +//@note: +//=================================================================================// +void pwm_led_one_flash_display(u8 led_index, u16 led0_bright, u16 led1_bright, + u32 period, u32 start_light_time, u32 light_time); + +//=================================================================================// +//@brief: 自定义设置单灯双闪状态 +//@input: +// led_index: 0: led0, 1:led1, 3:led0 & led1(互闪) +// led0_bright, LED0亮度: 0 ~ 500 +// led1_bright, LED1亮度: 0 ~ 500 +// period: 闪灯周期(ms), 多少ms闪一下 +// first_light_time: 第一次亮灯持续时间, +// second_light_time: 第二次亮灯持续时间, +// gap_time: 两次亮灯时间间隔, +//@return: void +//@note: +//=================================================================================// +void pwm_led_double_flash_display(u8 led_index, u16 led0_bright, u16 led1_bright, + u32 period, u32 first_light_time, u32 gap_time, u32 second_light_time); + + +//=================================================================================// +//@brief: 自定义设置呼吸模式 +//@input: +// led_index: 0: led0, 1:led1, 2:led0 & led1(交互呼吸) +// breathe_time: 呼吸周期(灭->最亮->灭), 设置范围: 500ms以上; +// led0_bright: led0呼吸到最亮的亮度(0 ~ 500); +// led1_bright: led1呼吸到最亮的亮度(0 ~ 500); +// led0_light_delay_time: led0最高亮度延时(0 ~ 100ms); +// led1_light_delay_time: led1最高亮度延时(0 ~ 100ms); +// led_blink_delay_time: led0和led1灭灯延时(0 ~ 20000ms), 0 ~ 20S; +//@return: void +//@note: +//=================================================================================// +void pwm_led_breathe_display(u8 led_index, u16 breathe_time, u16 led0_bright, u16 led1_bright, + u32 led0_light_delay_time, u32 led1_light_delay_time, u32 led_blink_delay_time); + +//=================================================================================// +//@brief: 注册LED周期中断函数, 每个LED周期结束后会调用一次, 可以统计指定状态闪烁多少次 +//@input: +//@return: void +//@note: +//=================================================================================// +void pwm_led_register_irq(void (*func)(void)); + + +#endif //_PWM_LED_H_ + + diff --git a/include_lib/driver/cpu/br23/asm/rdec.h b/include_lib/driver/cpu/br23/asm/rdec.h new file mode 100644 index 0000000..dd5d1ea --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/rdec.h @@ -0,0 +1,37 @@ +#ifndef _RDEC_H_ +#define _RDEC_H_ + +#define DEVICE_EVENT_FROM_RDEC (('R' << 24) | ('D' << 16) | ('E' << 8) | '\0') + +enum rdec_index { + RDEC0, + RDEC1, + RDEC2, +}; + +struct rdec_device { + enum rdec_index index; + u8 sin_port0; //采样信号端口0 + u8 sin_port1; //采样信号端口1 + u8 key_value0; //键值1 + u8 key_value1; //键值2 +}; + +struct rdec_platform_data { + u8 enable; + u8 num; //rdec数量 + const struct rdec_device *rdec; +}; + +#define RDEC_PLATFORM_DATA_BEGIN(data) \ + static const struct rdec_platform_data data = { + +#define RDEC_PLATFORM_DATA_END() \ +}; + +/*********************** rdec 初始化 ******************************/ +int rdec_init(const struct rdec_platform_data *user_data); +s8 get_rdec_rdat(int i); + +#endif + diff --git a/include_lib/driver/cpu/br23/asm/rtc.h b/include_lib/driver/cpu/br23/asm/rtc.h new file mode 100644 index 0000000..fbde125 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/rtc.h @@ -0,0 +1,61 @@ +#ifndef __RTC_H__ +#define __RTC_H__ + +#include "typedef.h" + +#define IOCTL_PORT_PR_IN _IOR('R', 'T'+0, 0) +#define IOCTL_PORT_PR_OUT _IOW('R', 'T'+1, 0) +#define IOCTL_PORT_PR_PU _IOR('R', 'T'+2, 0) +#define IOCTL_PORT_PR_PD _IOR('R', 'T'+3, 0) +#define IOCTL_PORT_PR_HD _IOW('R', 'T'+4, 0) +#define IOCTL_PORT_PR_DIE _IOW('R', 'T'+5, 0) +#define IOCTL_PORT_PR_READ _IOR('R', 'T'+6, 0) + +#define WKUP_IO_PR0 0x01 +#define WKUP_IO_PR1 0x02 +#define WKUP_IO_PR2 0x04 +#define WKUP_IO_PR3 0x08 +#define WKUP_ALARM 0x10 +#define BAT_POWER_FIRST 0x20 +#define ABNORMAL_RESET 0x40 +#define WKUP_SHORT_KEY 0x80 + + +#define LEADING_EDGE 0 +#define FALLING_EDGE 1 + + +struct rtc_dev_data { + u8 port; + u8 edge; //0 leading edge, 1 falling edge + u8 port_en; + u8 rtc_ldo; + u8 clk_res; +}; + + +extern const struct device_operations rtc_dev_ops; +extern const struct device_operations rtc_simulate_ops; + +int rtc_port_pr_in(u8 port); + +int rtc_port_pr_read(u8 port); + +int rtc_port_pr_out(u8 port, bool on); + +int rtc_port_pr_hd(u8 port, bool on); + +int rtc_port_pr_pu(u8 port, bool on); + +int rtc_port_pr_pd(u8 port, bool on); + +int rtc_port_pr_die(u8 port, bool on); + +int rtc_port_pr_wkup_en_port(u8 port, bool en); + +int rtc_port_pr_wkup_edge(u8 port, bool up_down); + +int rtc_port_pr_wkup_clear_pnd(u8 port); + +int __rtc_port_pr_wkup_clear_pnd(); +#endif // __RTC_API_H__ diff --git a/include_lib/driver/cpu/br23/asm/sdmmc.h b/include_lib/driver/cpu/br23/asm/sdmmc.h new file mode 100644 index 0000000..4e237ec --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/sdmmc.h @@ -0,0 +1,78 @@ +#ifndef ARCH_SDMMC_H +#define ARCH_SDMMC_H + + +#include "device/sdmmc.h" + +struct sdmmc_platform_data { + char port; + u8 irq; + u8 data_width; + u8 priority; + u8 detect_mode; + u8 detect_io; + u8 detect_io_level; + u8 detect_time_interval; + u32 detect_timeout; + u32 speed; + volatile u16 *sfr; + int (*detect_func)(const struct sdmmc_platform_data *); + void (*port_init)(const struct sdmmc_platform_data *, int mode); + void (*power)(int on); +}; + +#define SD0_PLATFORM_DATA_BEGIN(data) \ + static const struct sdmmc_platform_data data = { + + +#define SD0_PLATFORM_DATA_END() \ + .irq = IRQ_SD0_IDX, \ + .sfr = (volatile u16 *)JL_SD0, \ + .port_init = sdmmc_0_port_init, \ + .detect_time_interval = 250, \ + .detect_timeout = 1000, \ +}; + +extern const struct device_operations sd0_dev_ops; + +extern void sdmmc_0_port_init(const struct sdmmc_platform_data *, int mode); +extern int sdmmc_0_clk_detect(const struct sdmmc_platform_data *); +extern int sdmmc_0_io_detect(const struct sdmmc_platform_data *); + +extern int sdmmc_cmd_detect(const struct sdmmc_platform_data *); + +extern void sd_set_power(u8 enable); + + +#define SD1_PLATFORM_DATA_BEGIN(data) \ + static const struct sdmmc_platform_data data = { + + +#define SD1_PLATFORM_DATA_END() \ + .irq = IRQ_SD1_IDX, \ + .sfr = (volatile u16 *)JL_SD1, \ + .port_init = sdmmc_1_port_init, \ + .detect_time_interval = 250, \ + .detect_timeout = 1000, \ +}; + +extern const struct device_operations sd_dev_ops; + +extern void sdmmc_1_port_init(const struct sdmmc_platform_data *, int mode); +extern int sdmmc_1_clk_detect(const struct sdmmc_platform_data *); +extern int sdmmc_1_io_detect(const struct sdmmc_platform_data *); + + + +extern void sdmmc_2_port_init(const struct sdmmc_platform_data *, int mode); +extern int sdmmc_2_clk_detect(const struct sdmmc_platform_data *); + +extern u8 sd_io_suspend(u8 sdx, u8 sd_io); +extern u8 sd_io_resume(u8 sdx, u8 sd_io); + + + + + +#endif + diff --git a/include_lib/driver/cpu/br23/asm/sfc_norflash_api.h b/include_lib/driver/cpu/br23/asm/sfc_norflash_api.h new file mode 100644 index 0000000..9034933 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/sfc_norflash_api.h @@ -0,0 +1,14 @@ +#ifndef __SFC_NORFLASH_API_H__ +#define __SFC_NORFLASH_API_H__ + +#include "typedef.h" + +int norflash_init(const struct dev_node *node, void *arg); +int norflash_open(const char *name, struct device **device, void *arg); +int norflash_read(struct device *device, void *buf, u32 len, u32 offset); +int norflash_write(struct device *device, void *buf, u32 len, u32 offset); +int norflash_dma_write(struct device *device, void *buf, u32 len, u32 offset); +int norflash_ioctl(struct device *device, u32 cmd, u32 arg); + + +#endif diff --git a/include_lib/driver/cpu/br23/asm/spi.h b/include_lib/driver/cpu/br23/asm/spi.h new file mode 100644 index 0000000..da4d57e --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/spi.h @@ -0,0 +1,78 @@ +#ifndef _SPI_INTERFACE_H_ +#define _SPI_INTERFACE_H_ +#include "typedef.h" +#include "generic/ioctl.h" + + +/*enum spi_mode { + SPI_2WIRE_MODE, + SPI_ODD_MODE, + SPI_DUAL_MODE, + SPI_QUAD_MODE, +};*/ +enum spi_mode { + SPI_MODE_BIDIR_1BIT, //支持SPIx(x=0,1,2),全双工,di接收,do发送 + SPI_MODE_UNIDIR_1BIT, //支持SPIx(x=0,1,2),半双工,do分时发送/接收 + SPI_MODE_UNIDIR_2BIT, //支持SPIx(x=0),半双工,di & do共2bit分时发送/接收 + SPI_MODE_UNIDIR_4BIT, //支持SPIx(x=0),半双工,di & do & d2 & d3共4bit分时发送/接收 +}; + +enum { + SPI0, + SPI1, + SPI2, + SPI_MAX_HW_NUM, +}; + +#define SPI_MAX_IO_GROUP 4 + +struct spi_io { + u8 cs_pin; + u8 di_pin; + u8 do_pin; + u8 clk_pin; + u8 d2_pin; + u8 d3_pin; +}; + +struct spi_io_mapping { + u32 num; //可选端口数量 + struct spi_io io[SPI_MAX_IO_GROUP]; +}; + +enum spi_role { + SPI_ROLE_MASTER, + SPI_ROLE_SLAVE, +}; + +struct spi_platform_data { + u8 port; //端口,可选'A', 'B','C' + u8 mode; //模式,选项为enum spi_mode中的枚举常量 + u8 role; //角色,选项为enum spi_role中的枚举常量 + u32 clk; //波特率 +}; + +extern const struct spi_platform_data spi0_p_data; +extern const struct spi_platform_data spi1_p_data; +extern const struct spi_platform_data spi2_p_data; + +typedef const int spi_dev; + +int spi_open(spi_dev spi); +int spi_dma_recv(spi_dev spi, void *buf, u32 len); +int spi_dma_send(spi_dev spi, const void *buf, u32 len); +void spi_dma_set_addr_for_isr(spi_dev spi, void *buf, u32 len, u8 rw); +void spi_set_ie(spi_dev spi, u8 en); +u8 spi_get_pending(spi_dev spi); +void spi_clear_pending(spi_dev spi); +void spi_set_bit_mode(spi_dev spi, int mode); +u8 spi_recv_byte(spi_dev spi, int *err); +u8 spi_recv_byte_for_isr(spi_dev spi); +int spi_send_byte(spi_dev spi, u8 byte); +void spi_send_byte_for_isr(spi_dev spi, u8 byte); +u8 spi_send_recv_byte(spi_dev spi, u8 byte, int *err); +int spi_set_baud(spi_dev spi, u32 baud); +u32 spi_get_baud(spi_dev spi); +void spi_close(spi_dev spi); + +#endif diff --git a/include_lib/driver/cpu/br23/asm/spiflash.h b/include_lib/driver/cpu/br23/asm/spiflash.h new file mode 100644 index 0000000..a2c62e3 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/spiflash.h @@ -0,0 +1,29 @@ +#ifndef ASM_SPIFLASH_H +#define ASM_SPIFLASH_H + + + +#include "device/device.h" +#include "device/spiflash.h" + + + + + + + + + + + + +extern const struct device_operations spiflash_dev_ops; +extern const struct device_operations sfcflash_dev_ops; +extern const struct device_operations sdfile_dev_ops; + + + + + +#endif + diff --git a/include_lib/driver/cpu/br23/asm/timer.h b/include_lib/driver/cpu/br23/asm/timer.h new file mode 100644 index 0000000..ced6b45 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/timer.h @@ -0,0 +1,10 @@ +#ifndef __TIMER_H__ +#define __TIMER_H__ + +#include "typedef.h" + +void delay_2ms(int cnt); +u32 timer_get_sec(void); +u32 timer_get_ms(void); + +#endif diff --git a/include_lib/driver/cpu/br23/asm/uart.h b/include_lib/driver/cpu/br23/asm/uart.h new file mode 100644 index 0000000..a09c6e1 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/uart.h @@ -0,0 +1,56 @@ +#ifndef ASM_UART_H +#define ASM_UART_H + + +#define UART_NUM 3 +#define UART_OUTPORT_NUM 4 + + +#include "device/uart.h" +#include "device/device.h" + +#define UART0_PLATFORM_DATA_BEGIN(data) \ + static const struct uart_platform_data data = { + + +#define UART0_PLATFORM_DATA_END() \ + .irq = IRQ_UART0_IDX, \ +}; + + +#define UART1_PLATFORM_DATA_BEGIN(data) \ + static const struct uart_platform_data data = { + + +#define UART1_PLATFORM_DATA_END() \ + .irq = IRQ_UART1_IDX, \ +}; + + +#define UART2_PLATFORM_DATA_BEGIN(data) \ + static const struct uart_platform_data data = { + +#define UART2_PLATFORM_DATA_END() \ + .irq = IRQ_UART2_IDX, \ +}; + + +// #define UART3_PLATFORM_DATA_BEGIN(data) \ +// static const struct uart_platform_data data = { + +// #define UART3_PLATFORM_DATA_END() \ +// .irq = UART3_INT, \ +// }; + + + + +extern const struct device_operations uart_dev_ops; + + +extern int uart_init(const struct uart_platform_data *); + + +#endif + + diff --git a/include_lib/driver/cpu/br23/asm/uart_dev.h b/include_lib/driver/cpu/br23/asm/uart_dev.h new file mode 100644 index 0000000..4b89883 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/uart_dev.h @@ -0,0 +1,175 @@ +#ifndef _UART_DEV_H_ +#define _UART_DEV_H_ + +#include "typedef.h" +#include "os/os_api.h" +#include "jiffies.h" +#include "irq.h" +/* #include "jtime.h" */ + +#define CONFIG_ENABLE_UART_SEM 1 +#define SET_INTERRUPT ___interrupt +#define irq_disable(x) bit_clr_ie(x) +#define irq_enable(x) bit_set_ie(x) + +#ifndef time_after +#define time_after(a,b) (((long)(b) - (long)(a)) < 0) +#endif + +#ifndef time_before +#define time_before(a,b) time_after(b,a) +#endif + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + +static inline u32 ut_get_jiffies(void) +{ +#if 1 + return jiffies; +#endif +#if 0 + return Jtime_updata_jiffies(); +#endif +} + +static inline u32 ut_msecs_to_jiffies(u32 msecs) +{ + if (msecs >= 10) { + msecs /= 10; + } else if (msecs) { + msecs = 1; + } + return msecs; +} + +#if CONFIG_ENABLE_UART_SEM +typedef OS_SEM UT_Semaphore ; +static inline void UT_OSSemCreate(UT_Semaphore *sem, u32 count) +{ + os_sem_create(sem, count); +} +static inline void UT_OSSemPost(UT_Semaphore *sem) +{ + os_sem_post(sem); +} +static inline u32 UT_OSSemPend(UT_Semaphore *sem, u32 timeout) +{ + return os_sem_pend(sem, timeout); +} +static inline void UT_OSSemSet(UT_Semaphore *sem, u32 count) +{ + os_sem_set(sem, count); +} +static inline void UT_OSSemClose(UT_Semaphore *sem) +{ + +} +static inline void ut_sleep() +{ + os_time_dly(1); +} + +#else +typedef volatile u32 UT_Semaphore; +static inline void UT_OSSemCreate(UT_Semaphore *sem, u32 count) +{ + *sem = count; +} +static inline void UT_OSSemPost(UT_Semaphore *sem) +{ + (*sem)++; +} +static inline u32 UT_OSSemPend(UT_Semaphore *sem, u32 timeout) +{ + u32 _timeout = timeout + ut_get_jiffies(); + extern void clr_wdt(); + while (1) { + if (*sem) { + (*sem) --; + break; + } + if ((timeout != 0) && time_before(_timeout, ut_get_jiffies())) { + return -1; + } + clr_wdt(); + } + return 0; +} +static inline void UT_OSSemSet(UT_Semaphore *sem, u32 count) +{ + *sem = count; +} +static inline void UT_OSSemClose(UT_Semaphore *sem) +{ + +} +static inline void ut_sleep() +{ + extern void clr_wdt(); + clr_wdt(); +} +#endif + + +typedef void (*ut_isr_cbfun)(void *ut_bus, u32 status); +struct uart_platform_data_t { + u8 tx_pin; ///< 作为发送引脚的引脚号,可从参考gpio.h枚举中选,当引脚为空时,则填 -1 + u8 rx_pin; ///< 作为接收引脚的引脚号,可从参考gpio.h枚举中选,当引脚为空时,则填 -1 + void *rx_cbuf; ///< 如果使用中断DMA接收,则写入循环buf的首地址,ut中断使能;如果不使用,则写入NULL,无中断 + u32 rx_cbuf_size; ///< 循环buf的大小,必须为2的多少几次幂,如果不用循环buf,该值无效,可写NULL + u32 frame_length; ///< 产生RT中断的字节数,如无中断,该值无效 + u32 rx_timeout; ///< 产生OT中断的时间值,单位ms,如无中断,该值无效 + ut_isr_cbfun isr_cbfun; ///< ut中断的回调函数句柄,不用回调函数则写入NULL,如无中断,句柄无效 + void *argv; ///< ut中断的回调函数的一个扩展形参,可供用户设定,如无回调函数,此参数无效 + u32 is_9bit: 1; ///< ut九位模式使能位,0:关闭;1:使能 + u32 baud: 24; ///< ut的波特率 +}; + +/** + * @brief 循环buf结构体类型定义 + */ +typedef struct { + u8 *buffer; ///<循环buf的首地址 + u32 buf_size; ///<循环buf的大小 + u32 buf_in; ///<循环buf的写偏移量 + u32 buf_out; ///<循环buf的读偏移量 +} KFIFO; + +enum { + UT_TX = 1, + UT_RX, + UT_RX_OT +}; + +/** + * @brief ut初始化函数的返回结构体,含各函数指针,供外部使用 + */ +typedef struct { + ut_isr_cbfun isr_cbfun; ///< ut中断的回调函数句柄,不用回调函数则写入NULL,如无中断,句柄无效 + void *argv; ///< ut中断的回调函数的一个扩展形参,在此返回 + void (*putbyte)(char a); ///< ut发送一个byte + u8(*getbyte)(u8 *buf, u32 timeout); ///< ut接收一个byte,buf:字节存放地址;timeout:超时时间,单位ms;返回0:失败;返回1:成功 + u32(*read)(u8 *inbuf, u32 len, u32 timeout); ///< ut接收一个字符串,inbuf:字符串存放首地址;len:预接收长度;timeout:超时时间,单位ms;返回实际接收的长度 + void (*write)(const u8 *outbuf, u32 len); ///< ut发送一个字符串,outbuf:字符串首地址;len:发送的字符串长度; + void (*set_baud)(u32 baud); ///< ut设置波特率,baud:波特率值 + u32 frame_length; + u32 rx_timeout; + KFIFO kfifo; ///< ut用的循环buf结构体的指针 + UT_Semaphore sem_rx; + UT_Semaphore sem_tx; +} uart_bus_t; + + +const uart_bus_t *uart_dev_open(const struct uart_platform_data_t *arg); +u32 uart_dev_close(uart_bus_t *ut); + +//////////////////////////////////////////////////////////////////////////////// +#endif + + diff --git a/include_lib/driver/cpu/br23/asm/usb.h b/include_lib/driver/cpu/br23/asm/usb.h new file mode 100644 index 0000000..ea0c341 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/usb.h @@ -0,0 +1,170 @@ +#ifndef _USB_H_ +#define _USB_H_ +#include "typedef.h" +#include "generic/ioctl.h" + + +#ifndef min +#define min(a,b) ((a)<(b) ? (a) : (b)) +#endif +#ifndef USB_DIR_OUT +#define USB_DIR_OUT 0 /* to device */ +#endif +#ifndef USB_DIR_IN +#define USB_DIR_IN 0x80 /* to host */ +#endif + +#define FUSB_MODE 1 +#define EP0_SETUP_LEN 0x40 +#define USB_MAX_HW_EPNUM 5 + + +//USB_CON0 +#define PHY_ON 0 +#define LOW_SPEED 1 +#define USB_NRST 2 +#define TM1 3 +#define CID 4 +#define VBUS 5 +#define USB_TEST 6 +#define PDCHKDP 9 +#define SOFIE 10 +#define SIEIE 11 +#define CLR_SOF_PND 12 +#define SOF_PND 13 +#define SIE_PND 14 +#define CHKDPO 15 +#define DM_SE 16 +#define DP_SE 17 + +//USB_CON1 +#define MC_RNW 14 +#define MACK 15 + +//USB_IO_CON0 +#define DPOUT 0 +#define DMOUT 1 +#define DPIE 2 +#define DMIE 3 +#define DPPD 4 +#define DMPD 5 +#define DPPU 6 +#define DMPU 7 +#define IO_PU_MODE 8 +#define DPDIE 9 +#define DMDIE 10 +#define IO_MODE 11 +#define SR 12 +#define DPDIEH 13 +#define DMDIEH 14 + +enum { + USB0, +}; + +#define USB_MAX_HW_NUM 1 + + +struct usb_ep_addr_t { + u32 ep0_addr; + u32 ep_usage ; + u32 ep_taddr[4]; + u32 ep_dual_taddr[4]; + u32 ep_raddr[4]; + u32 ep_dual_raddr[4]; + u32 ep_tsize[4]; + u32 ep_rsize[4]; +} __attribute__((aligned(4))); + + +typedef u8 usb_dev; + +u16 musb_read_sofframe(const usb_dev id); +u32 musb_read_usb(const usb_dev usb_id, u32 addr); +void musb_write_usb(const usb_dev usb_id, u32 addr, u32 data); +u32 usb_dev_con0(const usb_dev usb_id); +void usb_sie_enable(const usb_dev usb_id); +void usb_sie_disable(const usb_dev id); +void usb_write_ep_cnt(const usb_dev usb_id, u32 ep, u32 len); +u32 usb_g_dev_status(const usb_dev usb_id); +u32 usb_h_dev_status(const usb_dev usb_id); +void usb_set_low_speed(const usb_dev usb_id, u8 flag); +void usb_write_ep0(const usb_dev usb_id, const u8 *ptr, u32 len); +void usb_read_ep0(const usb_dev usb_id, u8 *ptr, u32 len); +void *usb_get_dma_taddr(const usb_dev usb_id, u32 ep); +u32 usb_get_dma_size(const usb_dev usb_id, u32 ep); +void usb_set_dma_tsize(const usb_dev usb_id, u32 ep, u32 size); +void usb_set_dma_rsize(const usb_dev usb_id, u32 ep, u32 size); +void usb_set_dma_taddr(const usb_dev usb_id, u32 ep, void *ptr); +void *usb_get_dma_raddr(const usb_dev usb_id, u32 ep); +void usb_set_dma_raddr(const usb_dev usb_id, u32 ep, void *ptr); +void usb_set_dma_dual_raddr(const usb_dev usb_id, u32 ep, void *ptr); +void musb_write_index(const usb_dev usb_id, u32 endpoint); +void usb_write_power(const usb_dev usb_id, u32 value); +u32 usb_read_power(const usb_dev usb_id); +u32 usb_read_devctl(const usb_dev usb_id); +void usb_write_devctl(const usb_dev usb_id, u32 value); +u32 usb_read_csr0(const usb_dev usb_id); +void usb_write_csr0(const usb_dev usb_id, u32 csr0); +void usb_ep0_ClrRxPktRdy(const usb_dev usb_id); +void usb_ep0_TxPktEnd(const usb_dev usb_id); +void usb_ep0_RxPktEnd(const usb_dev usb_id); +void usb_ep0_Set_Stall(const usb_dev usb_id); +u32 usb_read_count0(const usb_dev usb_id); +void usb_read_intre(const usb_dev usb_id, + u32 *const intr_usbe, + u32 *const intr_txe, + u32 *const intr_rxe); + +void usb_read_intr(const usb_dev usb_id, + u32 *const intr_usb, + u32 *const intr_tx, + u32 *const intr_rx); +void usb_write_intr_usbe(const usb_dev usb_id, u32 intr_usbe); +void usb_set_intr_txe(const usb_dev usb_id, const u32 ep); +void usb_clr_intr_txe(const usb_dev usb_id, const u32 ep); +void usb_set_intr_rxe(const usb_dev usb_id, const u32 ep); +void usb_clr_intr_rxe(const usb_dev usb_id, const u32 ep); +void usb_write_faddr(const usb_dev usb_id, u32 addr); +void usb_write_txcsr(const usb_dev usb_id, const u32 ep, u32 txcsr); +u32 usb_read_txcsr(const usb_dev usb_id, const u32 ep); +void usb_write_rxcsr(const usb_dev usb_id, const u32 ep, u32 rxcsr); +u32 usb_read_rxcsr(const usb_dev usb_id, const u32 ep); +void usb_write_rxmaxp(const usb_dev usb_id, const u32 ep, u32 value); +void usb_write_txmaxp(const usb_dev usb_id, const u32 ep, u32 value); +void usb_write_rxtype(const usb_dev usb_id, const u32 ep, u32 value); +void usb_write_txtype(const usb_dev usb_id, const u32 ep, u32 value); +u32 usb_read_rxcount(const usb_dev usb_id, u32 ep); +u32 usb_g_ep_config(const usb_dev usb_id, const u32 ep, u32 type, u32 ie, u8 *ptr, u32 dma_size); +u32 usb_g_ep_read64byte_fast(const usb_dev usb_id, const u32 ep, u8 *ptr, u32 len); +u32 usb_g_ep_read(const usb_dev usb_id, const u32 ep, u8 *ptr, u32 len, u32 block); +u32 usb_g_ep_write(const usb_dev usb_id, u32 ep, const u8 *ptr, u32 len); +u32 usb_g_ep_config(const usb_dev usb_id, u32 ep, u32 type, u32 ie, u8 *ptr, u32 dma_size); +void usb_g_sie_init(const usb_dev usb_id); +void usb_g_hold(const usb_dev usb_id); +u32 usb_get_ep_num(const usb_dev usb_id, u32 ep_dir, u32 type); +u32 usb_h_ep_config(const usb_dev usb_id, u32 ep, u32 type, u32 ie, u32 interval, u8 *ptr, u32 dma_size); +void usb_mdelay(unsigned int ms); +u32 usb_h_ep_write(const usb_dev usb_id, u8 host_ep, u16 txmaxp, u8 target_ep, const u8 *ptr, u32 len, u32 xfer); +int usb_h_ep_write_async(const usb_dev id, u8 host_ep, u16 txmaxp, u8 target_ep, const u8 *ptr, u32 len, u32 xfer, u32 kstart); +u32 usb_h_ep_read(const usb_dev usb_id, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *ptr, u32 len, u32 xfer); +int usb_h_ep_read_async(const usb_dev id, u8 host_ep, u8 target_ep, u8 *ptr, u32 len, u32 xfer, u32 kstart); +void usb_h_sie_init(const usb_dev usb_id); +void usb_h_sie_close(const usb_dev usb_id); +void usb_h_sie_reset(const usb_dev usb_id); +void usb_hotplug_disable(const usb_dev usb_id); +void usb_hotplug_enable(const usb_dev usb_id, u32 mode); +void usb_sie_close(const usb_dev usb_id); +void usb_sie_close_all(void); +void usb_io_reset(const usb_dev usb_id); +void usb_var_init(const usb_dev usb_id, void *ptr); +void usb_var_release(const usb_dev usb_id); +void usb_enable_ep(const usb_dev usb_id, u32 eps); +void usb_disable_ep(const usb_dev usb_id, u32 eps); + +void usb_sofie_enable(const usb_dev id); +void usb_sofie_disable(const usb_dev id); +void usb_sof_clr_pnd(const usb_dev id); +void usb_ep0_Set_ignore(const usb_dev id, u32 addr); +void usb_recover_io_status(const usb_dev id); +#endif diff --git a/include_lib/driver/cpu/br23/asm/wdt.h b/include_lib/driver/cpu/br23/asm/wdt.h new file mode 100644 index 0000000..b7d8fe7 --- /dev/null +++ b/include_lib/driver/cpu/br23/asm/wdt.h @@ -0,0 +1,30 @@ +#ifndef __BR22_WDT_H__ +#define __BR22_WDT_H__ + +#define WDT_1MS 0x00 +#define WDT_2MS 0x01 +#define WDT_4MS 0x02 +#define WDT_8MS 0x03 +#define WDT_16MS 0x04 +#define WDT_32MS 0x05 +#define WDT_64MS 0x06 +#define WDT_128MS 0x07 +#define WDT_256MS 0x08 +#define WDT_512MS 0x09 +#define WDT_1S 0x0A +#define WDT_2S 0x0B +#define WDT_4S 0x0C +#define WDT_8S 0x0D +#define WDT_16S 0x0E +#define WDT_32S 0x0F + +void wdt_init(u8 time); +void wdt_close(void); +void wdt_clear(void); + +void wdt_enable(void); +void wdt_disable(void); + +u32 wdt_get_time(void);//ms + +#endif diff --git a/include_lib/driver/cpu/br23/driver_lib.ld b/include_lib/driver/cpu/br23/driver_lib.ld new file mode 100644 index 0000000..df7c59c --- /dev/null +++ b/include_lib/driver/cpu/br23/driver_lib.ld @@ -0,0 +1,75 @@ +SECTIONS +{ + .data : ALIGN(4) + { + driver_data_start = .; + + CLOCK_DATA_START = .; + *(.clock_data) + CLOCK_DATA_SIZE = ABSOLUTE(. - CLOCK_DATA_START); + + *(.debug_data) + *(.power_data) + + *(.uart_data) + + + driver_data_end = .; + + } > ram0 + + .bss (NOLOAD) :ALIGN(4) + { + driver_bss_start = .; + + CLOCK_BSS_START = .; + *(.clock_bss) + CLOCK_BSS_SIZE = ABSOLUTE(. - CLOCK_BSS_START); + + *(.debug_bss) + *(.power_bss) + + *(.uart_bss) + + *(.sd_var) + + driver_bss_end = .; + } > ram0 + + .text : ALIGN(4) + { + driver_code_start = .; + + . = ALIGN(4); + _SPI_CODE_START = . ; + *(.spi_code) + . = ALIGN(4); + _SPI_CODE_END = . ; + + clock_critical_handler_begin = .; + KEEP(*(.clock_critical_txt)) + clock_critical_handler_end = .; + + + CLOCK_CODE_START = .; + *(.clock_code) + *(.clock_const) + CLOCK_CODE_SIZE = ABSOLUTE(. - CLOCK_CODE_START); + + *(.debug_code) + *(.debug_const) + + *(.power_code) + *(.power_const) + + *(.uart_code) + *(.uart_const) + + driver_code_end = .; + . = ALIGN(4); + } > code0 + + /*代码统计 Code & RAM */ + DRIVER_RAM_TOTAL = (driver_data_end - driver_data_start) + (driver_bss_end - driver_bss_start); + DRIVER_CODE_TOTAL = (driver_code_end - driver_code_start); +} diff --git a/include_lib/driver/device/chargebox.h b/include_lib/driver/device/chargebox.h new file mode 100644 index 0000000..5e7b2ca --- /dev/null +++ b/include_lib/driver/device/chargebox.h @@ -0,0 +1,101 @@ +#ifndef __chargebox_H__ +#define __chargebox_H__ + +#include "typedef.h" + +#define DEVICE_EVENT_FROM_CHARGEBOX (('C' << 24) | ('H' << 16) | ('B' << 8) | '\0') + +enum { + CMD_COMPLETE, + CMD_RECVDATA, + CMD_RECVBYTE, +}; + +enum { + MODE_RECVDATA, + MODE_SENDDATA, +}; + +enum { + EAR_L, + EAR_R, +}; + +struct chargebox_platform_data { + u32 baudrate; + u32 L_port; + u32 R_port; + void (*init)(const struct chargebox_platform_data *); + void (*open)(u8 l_r, u8 mode); + void (*close)(u8 l_r); + u8(*write)(u8 l_r, u8 *data, u8 len); + void (*set_baud)(u8 l_r, u32 baudrate); +}; + +/////handshake部分 +enum { + HS_CMD0, + HS_CMD1, + HS_CMD2, + HS_CMD3, +}; + +enum { + HS_DELAY_48M, + HS_DELAY_60M, + HS_DELAY_80M, + HS_DELAY_96M, + HS_DELAY_120M, + HS_DELAY_160M, + HS_DELAY_192M, + HS_DELAY_240M, +}; + +enum { + HS_DELAY_2US, + HS_DELAY_3US, + HS_DELAY_4US, + HS_DELAY_7US, + HS_DELAY_8US, + HS_DELAY_14US, + HS_DELAY_16US, +}; + +//自定义指令 +enum { + CMD_USER = 0xC0, + /*可添加自定义指令*/ +}; + +struct _hs_hdl { + u32 port; + void (*send_delay_us)(u8 us); +}; +//handshake +extern void handshake_ctrl_init(struct _hs_hdl *hs); +extern void handshake_send_app(u8 cmd); + +//app层使用的接口 +extern bool chargebox_api_write_read(u8 l_r, u8 *buf, u8 len, u8 timeout); +extern void chargebox_api_init(const struct chargebox_platform_data *arg); +extern void chargebox_api_uninit(void); +extern void chargebox_api_set_baud(u8 l_r, u32 baudrate); +extern void chargebox_api_shutdown_port(u8 l_r); +extern void chargebox_api_close_port(u8 l_r); +extern void chargebox_api_open_port(u8 l_r); +extern void chargebox_api_reset(void);//左右耳掉线时调用 + +//协议层api +extern u8 chargebox_get_power(u8 lr); +extern u8 chargebox_send_power_close(u8 lr, u8 power, u8 is_charge, u8 other_power); +extern u8 chargebox_send_power_open(u8 lr, u8 power, u8 is_charge, u8 other_power); +extern u8 chargebox_send_shut_down(u8 lr); +extern u8 chargebox_send_restore_sys(u8 lr); +extern u8 chargebox_send_enter_dut(u8 lr); +extern u8 chargebox_send_close_cid(u8 lr, u8 data); +extern u8 chargebox_delete_tws_addr(u8 lr); +extern u8 chargebox_delete_phone_addr(u8 lr); +extern u8 chargebox_delete_all_addr(u8 lr); +extern u8 chargebox_send_L_or_R(u8 lr); +extern u8 chargebox_exchange_addr(void (*get_addr_cb)(u8 lr, u8 *inbuf), void (*exchange_succ_cb)(void)); +#endif diff --git a/include_lib/driver/device/sdio_host_init.h b/include_lib/driver/device/sdio_host_init.h new file mode 100644 index 0000000..888b905 --- /dev/null +++ b/include_lib/driver/device/sdio_host_init.h @@ -0,0 +1,72 @@ +#ifndef _SDIO_HOST_INIT_H_ +#define _SDIO_HOST_INIT_H_ + +/* +SDIO_GRP_0|SDIO_PORT_0: PA1-PA4->CMD,CLK,D2,D0; PH13,PH15->D3,D1 +SDIO_GRP_0|SDIO_PORT_1: PH6-PH11->D3,CMD,CLK,D2,D0,D1 +SDIO_GRP_0|SDIO_PORT_2: PC8-PC13->D2,D3,CMD,CLK,D0,D1 +SDIO_GRP_0|SDIO_PORT_3: PG8-PG13->D2,D3,CMD,CLK,D0,D1 +SDIO_GRP_1|SDIO_PORT_0: PF4-PF9->D2,D3,CMD,CLK,D0,D1 +SDIO_GRP_1|SDIO_PORT_1: PG0-PG5->D2,D3,CMD,CLK,D0,D1 +SDIO_GRP_1|SDIO_PORT_2: PD6-PD11->D2,D3,CMD,CLK,D0,D1 +SDIO_GRP_1|SDIO_PORT_3: PA10-PA15->D2,D3,CMD,CLK,D0,D1 +*/ + +//选择SDIO0? SDIO1? 作为输出,默认为SDIO1 +#define SDIO_GRP_0 0 +#define SDIO_GRP_1 (1 << 31) +#define SDIO_GRP_2 (1 << 30) +#define SDIO_GRP_MASK (1 << 31|1 << 30) + +//选择SDIOx的哪个出口作为输出,默认为出口0 +#define SDIO_PORT_0 0 +#define SDIO_PORT_1 (1 << 29) +#define SDIO_PORT_2 (1 << 28) +#define SDIO_PORT_3 (1 << 29|1 << 28) +#define SDIO_PORT_MASK (1 << 29|1 << 28) + +//是否使用四线模式, 默认为单线模式 +#define SDIO_1_BIT_DATA 0 +#define SDIO_4_BIT_DATA (1 << 27) +#define SDIO_4_BIT_DATA_MASK (1 << 27) + +//是否使用硬件中断检测外设事件,例如接收到数据. , 默认使用轮询方式查询事件, //对接收速度不敏感使用SDIO_POLLING即可 ,使用SDIO_DATA1_IRQ如果接收数据量过大会导致CPU不足的问题. +#define SDIO_POLLING 0 +#define SDIO_DATA1_IRQ (1 << 26) +#define SDIO_DATA1_IRQ_MASK (1 << 26) + +//配置SDIO时钟(HZ), 默认为40MHZ +#define SDIO_MAX_CLK_MASK ((1 << 26)-1) + +#define SDIO_CLOCK_80M (0) //80M 写0 +#define SDIO_CLOCK_40M (40 * 1000000) +#define SDIO_CLOCK_26M (26 * 1000000) +#define SDIO_CLOCK_20M (20 * 1000000) +#define SDIO_CLOCK_16M (16 * 1000000) +#define SDIO_CLOCK_8M (8 * 1000000) +#define SDIO_CLOCK_4M (4 * 1000000) +#define SDIO_CLOCK_2M (2 * 1000000) + +/* +sdio_host_init(0); +sdio_host_init(SDIO_GRP_1|SDIO_4_BIT_DATA); +sdio_host_init(SDIO_GRP_1|SDIO_PORT_1|SDIO_DATA1_IRQ); +sdio_host_init(SDIO_GRP_0|SDIO_PORT_0|SDIO_4_BIT_DATA|SDIO_DATA1_IRQ|(10*1000000)); +*/ + +extern void sdio_host_init(unsigned int parm); +extern unsigned char *SDIO_GET_CMD_BUF(void); +extern void SDIO_SET_GRP_PORT(u32 grp, u32 port); +extern void cpu_sdio_host_uninit(void); +extern void sdio_dat1_irq_uninit(void); +extern void sdio_dat1_irq_init(void); +extern void host_set_timing(void *host, unsigned int timing); +extern void mmc_set_bus_width(void *host, unsigned int width); +extern void mmc_set_clock(void *host, unsigned int hz); +extern void SDIO_CONTROLLER_RESET(void); +extern void SDIO_IDLE_CLK_EN(u8 enable) ; +extern void SDIO_CONTROLLER_START(void); +extern void SDIO_CONTROLLER_SET_IRQ(void); +extern void SDIO_SET_4WIRE_MODE(u8 enable); + +#endif //_SDIO_HOST_INIT_H_ diff --git a/include_lib/driver/device/sdmmc.h b/include_lib/driver/device/sdmmc.h new file mode 100644 index 0000000..5489f03 --- /dev/null +++ b/include_lib/driver/device/sdmmc.h @@ -0,0 +1,27 @@ +#ifndef SDMMC_MODULE_H +#define SDMMC_MODULE_H + + +#include "generic/typedef.h" +#include "generic/ioctl.h" + + +#define SD_CMD_DECT 0 +#define SD_CLK_DECT 1 +#define SD_IO_DECT 2 + +#define SD_CLASS_0 0 +#define SD_CLASS_2 1 +#define SD_CLASS_4 2 +#define SD_CLASS_6 3 +#define SD_CLASS_10 4 + +#define SD_IOCTL_GET_CLASS _IOR('S', 0, 4) + + + + + + +#endif + diff --git a/include_lib/driver/device/spiflash.h b/include_lib/driver/device/spiflash.h new file mode 100644 index 0000000..9e87d6c --- /dev/null +++ b/include_lib/driver/device/spiflash.h @@ -0,0 +1,125 @@ +#ifndef __SPIFLASH_H__ +#define __SPIFLASH_H__ + + + +#include "typedef.h" +#include "generic/list.h" +#include "generic/ioctl.h" +#include "device/device.h" +#include "system/task.h" + + +struct spi_device; + +enum spiflash_bit_mode { + SPI_2WIRE_MODE, + SPI_ODD_MODE, + SPI_DUAL_MODE, + SPI_QUAD_MODE, +}; + +enum spiflash_read_mode { + FAST_READ_OUTPUT_MODE, + FAST_READ_IO_MODE, + FAST_READ_IO_CONTINUOUS_READ_MODE, +}; + +enum sfc_run_mode { + //1bit mode + SFC_READ_DATA_MODE = (1 << 0), + SFC_FAST_READ_MODE = (1 << 1), + //2bit mode + SFC_FAST_READ_DUAL_IO_NORMAL_READ_MODE = (1 << 2), + SFC_FAST_READ_DUAL_IO_CONTINUOUS_READ_MODE = (1 << 3), + SFC_FAST_READ_DUAL_OUTPUT_MODE = (1 << 4), + //4bit mode + SFC_FAST_READ_QUAD_IO_NORMAL_READ_MODE = (1 << 5), + SFC_FAST_READ_QUAD_IO_CONTINUOUS_READ_MODE = (1 << 6), + SFC_FAST_READ_QUAD_OUTPUT_MODE = (1 << 7), + +}; +struct spi_ops { + int (*set_cs)(int); + int (*init)(void *); + u8(*read_byte)(int *err); + int (*read)(u8 *, u32 len, u8 mode); + int (*write_byte)(u8 cmd); + int (*write_cmd)(u8 *cmd, u32 len); + int (*write)(u8 *, u32 len); + u8(*get_bit_mode)(); +}; + + +struct sf_info { + u32 id; + u16 page_size; //byte + u16 block_size; //KByte + u32 chip_size; //KByte +}; + +enum sf_erase_type { + SF_SECTOR_ERASE, + SF_BLOCK_ERASE, + SF_CHIP_ERASE, +}; + +//struct sf_erase { +//enum sf_erase_type type; +//u32 addr; +//}; + + +//struct sf_wp { +//u8 enable; +//u8 cmd; +//}; + + +struct spi_device { + const char *name; + const struct spi_ops *ops; +}; + +struct spiflash_platform_data { + const char *name; + enum spiflash_read_mode mode; + enum sfc_run_mode sfc_run_mode; + void *private_data; +}; + + +struct spiflash { + struct list_head entry; + void *device; + struct device dev; + struct sf_info info; + const struct spiflash_platform_data *pd; + const char *name; + OS_MUTEX mutext; + u8 inited; + u8 read_mode; + u8 read_cmd_mode; + u8 write_cmd_mode; + u8 continuous_read_mode; +}; + + +#define REGISTER_SPIFLASH_DEVICE(dev) \ + static const struct spi_device dev sec(.spi_device) + + +extern struct spi_device spi_device_begin[]; +extern struct spi_device spi_device_end[]; + + + + +extern struct spiflash *__get_spiflash(const char *name); + + + + + +#endif + diff --git a/include_lib/driver/device/uart.h b/include_lib/driver/device/uart.h new file mode 100644 index 0000000..18d6e52 --- /dev/null +++ b/include_lib/driver/device/uart.h @@ -0,0 +1,131 @@ +#ifndef DEVICE_UART_H +#define DEVICE_UART_H + +#include "typedef.h" +#include "device/device.h" +#include "generic/ioctl.h" +#include "system/task.h" + +#define UART_DISABLE 0x00000000 +#define UART_DMA_SUPPORT 0x00000001 +#define UART_TX_USE_DMA 0x00000003 +#define UART_RX_USE_DMA 0x00000005 +#define UART_DEBUG 0x00000008 + +struct uart_outport { + u8 tx_pin; + u8 rx_pin; + u16 value; +}; + +extern void putbyte(char a); + + + + +enum uart_clk_src { + LSB_CLK, + OSC_CLK, + PLL_48M, +}; + + +enum _uart_port_out { + //uart0 + PORTC_0_1 = 0x00001000, + PORTG_6_7 = 0x00002000, + PORTH_12_13 = 0x00003000, + PORTB_14_15 = 0x00004000, + //uart1 + PORTC_2_3 = 0x00005000, + PORTH_2_5 = 0x00006000, + PORTH_14_15 = 0x00007000, + PORTC_6_7 = 0x00008000, + //uart3 + PORTE_0_1 = 0x00009000, + PORTB_4_3 = 0x0000A000, + PORTD_9_10 = 0x0000B000, + PORTD_14_15 = 0x0000C000, + + PORT_REMAP = 0x0000D000, +}; + +struct uart_platform_data { + u8 *name; + + u8 irq; + u8 tx_pin; + u8 rx_pin; + u32 flags; + u32 baudrate; + + enum _uart_port_out port; + void (*port_remap_func)(void); + u32 max_continue_recv_cnt; + u32 idle_sys_clk_cnt; + enum uart_clk_src clk_src; +}; + +enum { + UART_CIRCULAR_BUFFER_WRITE_OVERLAY = -1, + UART_RECV_TIMEOUT = -2, + UART_RECV_EXIT = -3, +}; + +#define UART_MAGIC 'U' +#define UART_FLUSH _IO(UART_MAGIC,1) +#define UART_SET_RECV_ALL _IOW(UART_MAGIC,2,bool) +#define UART_SET_RECV_BLOCK _IOW(UART_MAGIC,3,bool) +#define UART_SET_RECV_TIMEOUT _IOW(UART_MAGIC,4,u32) +#define UART_SET_RECV_TIMEOUT_CB _IOW(UART_MAGIC,5,int (*)(void)) +#define UART_GET_RECV_CNT _IOR(UART_MAGIC,6,u32) +#define UART_START _IO(UART_MAGIC,7) +#define UART_SET_CIRCULAR_BUFF_ADDR _IOW(UART_MAGIC,8,void *) +#define UART_SET_CIRCULAR_BUFF_LENTH _IOW(UART_MAGIC,9,u32) + + +#define UART_PLATFORM_DATA_BEGIN(data) \ + static const struct uart_platform_data data = { + + +#define UART_PLATFORM_DATA_END() \ + }; + + +struct uart_device { + char *name; + const struct uart_operations *ops; + struct device dev; + const struct uart_platform_data *priv; + OS_MUTEX mutex; +}; + + + + +struct uart_operations { + int (*init)(struct uart_device *); + int (*read)(struct uart_device *, void *buf, u32 len); + int (*write)(struct uart_device *, void *buf, u16 len); + int (*ioctl)(struct uart_device *, u32 cmd, u32 arg); + int (*close)(struct uart_device *); +}; + + + +#define REGISTER_UART_DEVICE(dev) \ + static struct uart_device dev sec(.uart) + +extern struct uart_device uart_device_begin[], uart_device_end[]; + +#define list_for_each_uart_device(p) \ + for (p=uart_device_begin; p [> __u8 etc <] +// #include [> le16_to_cpu <] +#include "typedef.h" + +/* #define __le16_to_cpu(x) x */ +/*-------------------------------------------------------------------------*/ + +/* CONTROL REQUEST SUPPORT */ + +/* + * USB directions + * + * This bit flag is used in endpoint descriptors' bEndpointAddress field. + * It's also one of three fields in control requests bRequestType. + */ +#define USB_DIR_OUT 0 /* to device */ +#define USB_DIR_IN 0x80 /* to host */ + +/* + * USB types, the second of three bRequestType fields + */ +#define USB_TYPE_MASK (0x03 << 5) +#define USB_TYPE_STANDARD (0x00 << 5) +#define USB_TYPE_CLASS (0x01 << 5) +#define USB_TYPE_VENDOR (0x02 << 5) +#define USB_TYPE_RESERVED (0x03 << 5) + +/* + * USB recipients, the third of three bRequestType fields + */ +#define USB_RECIP_MASK 0x1f +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 +/* From Wireless USB 1.0 */ +#define USB_RECIP_PORT 0x04 +#define USB_RECIP_RPIPE 0x05 + +/* + * Standard requests, for the bRequest field of a SETUP packet. + * + * These are qualified by the bRequestType field, so that for example + * TYPE_CLASS or TYPE_VENDOR specific feature flags could be retrieved + * by a GET_STATUS request. + */ +#define USB_REQ_GET_STATUS 0x00 +#define USB_REQ_CLEAR_FEATURE 0x01 +#define USB_REQ_SET_FEATURE 0x03 +#define USB_REQ_SET_ADDRESS 0x05 +#define USB_REQ_GET_DESCRIPTOR 0x06 +#define USB_REQ_SET_DESCRIPTOR 0x07 +#define USB_REQ_GET_CONFIGURATION 0x08 +#define USB_REQ_SET_CONFIGURATION 0x09 +#define USB_REQ_GET_INTERFACE 0x0A +#define USB_REQ_SET_INTERFACE 0x0B +#define USB_REQ_SYNCH_FRAME 0x0C +#define USB_REQ_SET_SEL 0x30 +#define USB_REQ_SET_ISOCH_DELAY 0x31 + +#define USB_REQ_SET_ENCRYPTION 0x0D /* Wireless USB */ +#define USB_REQ_GET_ENCRYPTION 0x0E +#define USB_REQ_RPIPE_ABORT 0x0E +#define USB_REQ_SET_HANDSHAKE 0x0F +#define USB_REQ_RPIPE_RESET 0x0F +#define USB_REQ_GET_HANDSHAKE 0x10 +#define USB_REQ_SET_CONNECTION 0x11 +#define USB_REQ_SET_SECURITY_DATA 0x12 +#define USB_REQ_GET_SECURITY_DATA 0x13 +#define USB_REQ_SET_WUSB_DATA 0x14 +#define USB_REQ_LOOPBACK_DATA_WRITE 0x15 +#define USB_REQ_LOOPBACK_DATA_READ 0x16 +#define USB_REQ_SET_INTERFACE_DS 0x17 + +/* The Link Power Management (LPM) ECN defines USB_REQ_TEST_AND_SET command, + * used by hubs to put ports into a new L1 suspend state, except that it + * forgot to define its number ... + */ + +/* + * USB feature flags are written using USB_REQ_{CLEAR,SET}_FEATURE, and + * are read as a bit array returned by USB_REQ_GET_STATUS. (So there + * are at most sixteen features of each type.) Hubs may also support a + * new USB_REQ_TEST_AND_SET_FEATURE to put ports into L1 suspend. + */ +#define USB_DEVICE_SELF_POWERED 0 /* (read only) */ +#define USB_DEVICE_REMOTE_WAKEUP 1 /* dev may initiate wakeup */ +#define USB_DEVICE_TEST_MODE 2 /* (wired high speed only) */ +#define USB_DEVICE_BATTERY 2 /* (wireless) */ +#define USB_DEVICE_B_HNP_ENABLE 3 /* (otg) dev may initiate HNP */ +#define USB_DEVICE_WUSB_DEVICE 3 /* (wireless)*/ +#define USB_DEVICE_A_HNP_SUPPORT 4 /* (otg) RH port supports HNP */ +#define USB_DEVICE_A_ALT_HNP_SUPPORT 5 /* (otg) other RH port does */ +#define USB_DEVICE_DEBUG_MODE 6 /* (special devices only) */ + +/* + * Test Mode Selectors + * See USB 2.0 spec Table 9-7 + */ +#define TEST_J 1 +#define TEST_K 2 +#define TEST_SE0_NAK 3 +#define TEST_PACKET 4 +#define TEST_FORCE_EN 5 + +/* + * New Feature Selectors as added by USB 3.0 + * See USB 3.0 spec Table 9-7 + */ +#define USB_DEVICE_U1_ENABLE 48 /* dev may initiate U1 transition */ +#define USB_DEVICE_U2_ENABLE 49 /* dev may initiate U2 transition */ +#define USB_DEVICE_LTM_ENABLE 50 /* dev may send LTM */ +#define USB_INTRF_FUNC_SUSPEND 0 /* function suspend */ + +#define USB_INTR_FUNC_SUSPEND_OPT_MASK 0xFF00 +/* + * Suspend Options, Table 9-8 USB 3.0 spec + */ +#define USB_INTRF_FUNC_SUSPEND_LP (1 << (8 + 0)) +#define USB_INTRF_FUNC_SUSPEND_RW (1 << (8 + 1)) + +/* + * Interface status, Figure 9-5 USB 3.0 spec + */ +#define USB_INTRF_STAT_FUNC_RW_CAP 1 +#define USB_INTRF_STAT_FUNC_RW 2 + +#define USB_ENDPOINT_HALT 0 /* IN/OUT will STALL */ + +/* Bit array elements as returned by the USB_REQ_GET_STATUS request. */ +#define USB_DEV_STAT_U1_ENABLED 2 /* transition into U1 state */ +#define USB_DEV_STAT_U2_ENABLED 3 /* transition into U2 state */ +#define USB_DEV_STAT_LTM_ENABLED 4 /* Latency tolerance messages */ + +/** + * struct usb_ctrlrequest - SETUP data for a USB device control request + * @bRequestType: matches the USB bmRequestType field + * @bRequest: matches the USB bRequest field + * @wValue: matches the USB wValue field (le16 byte order) + * @wIndex: matches the USB wIndex field (le16 byte order) + * @wLength: matches the USB wLength field (le16 byte order) + * + * This structure is used to send control requests to a USB device. It matches + * the different fields of the USB 2.0 Spec section 9.3, table 9-2. See the + * USB spec for a fuller description of the different fields, and what they are + * used for. + * + * Note that the driver for any interface can issue control requests. + * For most devices, interfaces don't coordinate with each other, so + * such requests may be made at any time. + */ +struct usb_ctrlrequest { + u8 bRequestType; + u8 bRequest; + u16 wValue; + u16 wIndex; + u16 wLength; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* + * STANDARD DESCRIPTORS ... as returned by GET_DESCRIPTOR, or + * (rarely) accepted by SET_DESCRIPTOR. + * + * Note that all multi-byte values here are encoded in little endian + * byte order "on the wire". Within the kernel and when exposed + * through the Linux-USB APIs, they are not converted to cpu byte + * order; it is the responsibility of the client code to do this. + * The single exception is when device and configuration descriptors (but + * not other descriptors) are read from usbfs (i.e. /proc/bus/usb/BBB/DDD); + * in this case the fields are converted to host endianness by the kernel. + */ + +/* + * Descriptor types ... USB 2.0 spec table 9.5 + */ +#define USB_DT_DEVICE 0x01 +#define USB_DT_CONFIG 0x02 +#define USB_DT_STRING 0x03 +#define USB_DT_INTERFACE 0x04 +#define USB_DT_ENDPOINT 0x05 +#define USB_DT_DEVICE_QUALIFIER 0x06 +#define USB_DT_OTHER_SPEED_CONFIG 0x07 +#define USB_DT_INTERFACE_POWER 0x08 + +#define USB_DT_HUB (USB_TYPE_CLASS | 0x09) + +/* these are from a minor usb 2.0 revision (ECN) */ +#define USB_DT_OTG 0x09 +#define USB_DT_DEBUG 0x0a +#define USB_DT_INTERFACE_ASSOCIATION 0x0b +/* these are from the Wireless USB spec */ +#define USB_DT_SECURITY 0x0c +#define USB_DT_KEY 0x0d +#define USB_DT_ENCRYPTION_TYPE 0x0e +#define USB_DT_BOS 0x0f +#define USB_DT_DEVICE_CAPABILITY 0x10 +#define USB_DT_WIRELESS_ENDPOINT_COMP 0x11 +#define USB_DT_WIRE_ADAPTER 0x21 +#define USB_DT_RPIPE 0x22 +#define USB_DT_CS_RADIO_CONTROL 0x23 +/* From the T10 UAS specification */ +#define USB_DT_PIPE_USAGE 0x24 +/* From the USB 3.0 spec */ +#define USB_DT_SS_ENDPOINT_COMP 0x30 + +/* Conventional codes for class-specific descriptors. The convention is + * defined in the USB "Common Class" Spec (3.11). Individual class specs + * are authoritative for their usage, not the "common class" writeup. + */ +#define USB_DT_CS_DEVICE (USB_TYPE_CLASS | USB_DT_DEVICE) +#define USB_DT_CS_CONFIG (USB_TYPE_CLASS | USB_DT_CONFIG) +#define USB_DT_CS_STRING (USB_TYPE_CLASS | USB_DT_STRING) +#define USB_DT_CS_INTERFACE (USB_TYPE_CLASS | USB_DT_INTERFACE) +#define USB_DT_CS_ENDPOINT (USB_TYPE_CLASS | USB_DT_ENDPOINT) + +/* All standard descriptors have these 2 fields at the beginning */ +struct usb_descriptor_header { + u8 bLength; + u8 bDescriptorType; +} __attribute__((packed)); + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEVICE: Device descriptor */ +struct usb_device_descriptor { + u8 bLength; + u8 bDescriptorType; + + u16 bcdUSB; + u8 bDeviceClass; + u8 bDeviceSubClass; + u8 bDeviceProtocol; + u8 bMaxPacketSize0; + u16 idVendor; + u16 idProduct; + u16 bcdDevice; + u8 iManufacturer; + u8 iProduct; + u8 iSerialNumber; + u8 bNumConfigurations; +} __attribute__((packed)); + +#define USB_DT_DEVICE_SIZE 18 + + +/* + * Device and/or Interface Class codes + * as found in bDeviceClass or bInterfaceClass + * and defined by www.usb.org documents + */ +#define USB_CLASS_PER_INTERFACE 0 /* for DeviceClass */ +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_COMM 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_PHYSICAL 5 +#define USB_CLASS_STILL_IMAGE 6 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_CDC_DATA 0x0a +#define USB_CLASS_CSCID 0x0b /* chip+ smart card */ +#define USB_CLASS_CONTENT_SEC 0x0d /* content security */ +#define USB_CLASS_VIDEO 0x0e +#define USB_CLASS_WIRELESS_CONTROLLER 0xe0 +#define USB_CLASS_MISC 0xef +#define USB_CLASS_APP_SPEC 0xfe +#define USB_CLASS_VENDOR_SPEC 0xff +#define USB_CLASS_UNKOWN 0x1ff + +#define USB_CLASS_ADB 0x42 +#define USB_CLASS_AOA 0x43 +#define USB_SUBCLASS_VENDOR_SPEC 0xff +#define PC_PROTOCOL_UNDEFINED 0x00 +/*-------------------------------------------------------------------------*/ + +/* USB_DT_CONFIG: Configuration descriptor information. + * + * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the + * descriptor type is different. Highspeed-capable devices can look + * different depending on what speed they're currently running. Only + * devices with a USB_DT_DEVICE_QUALIFIER have any OTHER_SPEED_CONFIG + * descriptors. + */ +struct usb_config_descriptor { + u8 bLength; + u8 bDescriptorType; + + u16 wTotalLength; + u8 bNumInterfaces; + u8 bConfigurationValue; + u8 iConfiguration; + u8 bmAttributes; + u8 bMaxPower; +} __attribute__((packed)); + +#define USB_DT_CONFIG_SIZE 9 + +/* from config descriptor bmAttributes */ +#define USB_CONFIG_ATT_ONE (1 << 7) /* must be set */ +#define USB_CONFIG_ATT_SELFPOWER (1 << 6) /* self powered */ +#define USB_CONFIG_ATT_WAKEUP (1 << 5) /* can wakeup */ +#define USB_CONFIG_ATT_BATTERY (1 << 4) /* battery powered */ + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_STRING: String descriptor */ +struct usb_string_descriptor { + u8 bLength; + u8 bDescriptorType; + + u16 wData[1]; /* UTF-16LE encoded */ +} __attribute__((packed)); + +/* note that "string" zero is special, it holds language codes that + * the device supports, not Unicode characters. + */ + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_INTERFACE: Interface descriptor */ +struct usb_interface_descriptor { + u8 bLength; + u8 bDescriptorType; + + u8 bInterfaceNumber; + u8 bAlternateSetting; + u8 bNumEndpoints; + u8 bInterfaceClass; + u8 bInterfaceSubClass; + u8 bInterfaceProtocol; + u8 iInterface; +} __attribute__((packed)); + +#define USB_DT_INTERFACE_SIZE 9 + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_ENDPOINT: Endpoint descriptor */ +struct usb_endpoint_descriptor { + u8 bLength; + u8 bDescriptorType; + + u8 bEndpointAddress; + u8 bmAttributes; + u16 wMaxPacketSize; + u8 bInterval; + + /* NOTE: these two are _only_ in audio endpoints. */ + /* use USB_DT_ENDPOINT*_SIZE in bLength, not sizeof. */ + u8 bRefresh; + u8 bSynchAddress; +} __attribute__((packed)); + +#define USB_DT_ENDPOINT_SIZE 7 +#define USB_DT_ENDPOINT_AUDIO_SIZE 9 /* Audio extension */ + + +/* + * Endpoints + */ +#define USB_ENDPOINT_NUMBER_MASK 0x0f /* in bEndpointAddress */ +#define USB_ENDPOINT_DIR_MASK 0x80 + +#define USB_ENDPOINT_XFERTYPE_MASK 0x03 /* in bmAttributes */ +#define USB_ENDPOINT_XFER_CONTROL 0 +#define USB_ENDPOINT_XFER_ISOC 1 +#define USB_ENDPOINT_XFER_BULK 2 +#define USB_ENDPOINT_XFER_INT 3 +#define USB_ENDPOINT_MAX_ADJUSTABLE 0x80 + +/* The USB 3.0 spec redefines bits 5:4 of bmAttributes as interrupt ep type. */ +#define USB_ENDPOINT_INTRTYPE 0x30 +#define USB_ENDPOINT_INTR_PERIODIC (0 << 4) +#define USB_ENDPOINT_INTR_NOTIFICATION (1 << 4) + +#define USB_ENDPOINT_SYNCTYPE 0x0c +#define USB_ENDPOINT_SYNC_NONE (0 << 2) +#define USB_ENDPOINT_SYNC_ASYNC (1 << 2) +#define USB_ENDPOINT_SYNC_ADAPTIVE (2 << 2) +#define USB_ENDPOINT_SYNC_SYNC (3 << 2) + +#define USB_ENDPOINT_USAGE_MASK 0x30 +#define USB_ENDPOINT_USAGE_DATA 0x00 +#define USB_ENDPOINT_USAGE_FEEDBACK 0x10 +#define USB_ENDPOINT_USAGE_IMPLICIT_FB 0x20 /* Implicit feedback Data endpoint */ + +/*-------------------------------------------------------------------------*/ + +/** + * usb_endpoint_num - get the endpoint's number + * @epd: endpoint to be checked + * + * Returns @epd's number: 0 to 15. + */ +static __inline__ int usb_endpoint_num(const struct usb_endpoint_descriptor *epd) +{ + return epd->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; +} + +/** + * usb_endpoint_type - get the endpoint's transfer type + * @epd: endpoint to be checked + * + * Returns one of USB_ENDPOINT_XFER_{CONTROL, ISOC, BULK, INT} according + * to @epd's transfer type. + */ +static __inline__ int usb_endpoint_type(const struct usb_endpoint_descriptor *epd) +{ + return epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; +} + +/** + * usb_endpoint_dir_in - check if the endpoint has IN direction + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type IN, otherwise it returns false. + */ +static __inline__ int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN); +} + +/** + * usb_endpoint_dir_out - check if the endpoint has OUT direction + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type OUT, otherwise it returns false. + */ +static __inline__ int usb_endpoint_dir_out( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT); +} + +/** + * usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type bulk, otherwise it returns false. + */ +static __inline__ int usb_endpoint_xfer_bulk( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_BULK); +} + +/** + * usb_endpoint_xfer_control - check if the endpoint has control transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type control, otherwise it returns false. + */ +static __inline__ int usb_endpoint_xfer_control( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_CONTROL); +} + +/** + * usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type interrupt, otherwise it returns + * false. + */ +static __inline__ int usb_endpoint_xfer_int( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_INT); +} + +/** + * usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type + * @epd: endpoint to be checked + * + * Returns true if the endpoint is of type isochronous, otherwise it returns + * false. + */ +static __inline__ int usb_endpoint_xfer_isoc( + const struct usb_endpoint_descriptor *epd) +{ + return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == + USB_ENDPOINT_XFER_ISOC); +} + +/** + * usb_endpoint_is_bulk_in - check if the endpoint is bulk IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has bulk transfer type and IN direction, + * otherwise it returns false. + */ +static __inline__ int usb_endpoint_is_bulk_in( + const struct usb_endpoint_descriptor *epd) +{ + return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd); +} + +/** + * usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has bulk transfer type and OUT direction, + * otherwise it returns false. + */ +static __inline__ int usb_endpoint_is_bulk_out( + const struct usb_endpoint_descriptor *epd) +{ + return usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd); +} + +/** + * usb_endpoint_is_int_in - check if the endpoint is interrupt IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has interrupt transfer type and IN direction, + * otherwise it returns false. + */ +static __inline__ int usb_endpoint_is_int_in( + const struct usb_endpoint_descriptor *epd) +{ + return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd); +} + +/** + * usb_endpoint_is_int_out - check if the endpoint is interrupt OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has interrupt transfer type and OUT direction, + * otherwise it returns false. + */ +static __inline__ int usb_endpoint_is_int_out( + const struct usb_endpoint_descriptor *epd) +{ + return usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd); +} + +/** + * usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN + * @epd: endpoint to be checked + * + * Returns true if the endpoint has isochronous transfer type and IN direction, + * otherwise it returns false. + */ +static __inline__ int usb_endpoint_is_isoc_in( + const struct usb_endpoint_descriptor *epd) +{ + return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd); +} + +/** + * usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT + * @epd: endpoint to be checked + * + * Returns true if the endpoint has isochronous transfer type and OUT direction, + * otherwise it returns false. + */ +static __inline__ int usb_endpoint_is_isoc_out( + const struct usb_endpoint_descriptor *epd) +{ + return usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd); +} + +/** + * usb_endpoint_maxp - get endpoint's max packet size + * @epd: endpoint to be checked + * + * Returns @epd's max packet + */ + +/* static __inline__ int usb_endpoint_maxp(const struct usb_endpoint_descriptor *epd) */ +/* { */ +/* return __le16_to_cpu(epd->wMaxPacketSize); */ +/* } */ + +static __inline__ int usb_endpoint_interrupt_type( + const struct usb_endpoint_descriptor *epd) +{ + return epd->bmAttributes & USB_ENDPOINT_INTRTYPE; +} + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_SS_ENDPOINT_COMP: SuperSpeed Endpoint Companion descriptor */ +struct usb_ss_ep_comp_descriptor { + u8 bLength; + u8 bDescriptorType; + + u8 bMaxBurst; + u8 bmAttributes; + u16 wBytesPerInterval; +} __attribute__((packed)); + +#define USB_DT_SS_EP_COMP_SIZE 6 + +/* Bits 4:0 of bmAttributes if this is a bulk endpoint */ +static __inline__ int +usb_ss_max_streams(const struct usb_ss_ep_comp_descriptor *comp) +{ + int max_streams; + + if (!comp) { + return 0; + } + + max_streams = comp->bmAttributes & 0x1f; + + if (!max_streams) { + return 0; + } + + max_streams = 1 << max_streams; + + return max_streams; +} + +/* Bits 1:0 of bmAttributes if this is an isoc endpoint */ +#define USB_SS_MULT(p) (1 + ((p) & 0x3)) + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEVICE_QUALIFIER: Device Qualifier descriptor */ +struct usb_qualifier_descriptor { + u8 bLength; + u8 bDescriptorType; + + u16 bcdUSB; + u8 bDeviceClass; + u8 bDeviceSubClass; + u8 bDeviceProtocol; + u8 bMaxPacketSize0; + u8 bNumConfigurations; + u8 bRESERVED; +} __attribute__((packed)); + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_OTG (from OTG 1.0a supplement) */ +struct usb_otg_descriptor { + u8 bLength; + u8 bDescriptorType; + + u8 bmAttributes; /* support for HNP, SRP, etc */ +} __attribute__((packed)); + +/* from usb_otg_descriptor.bmAttributes */ +#define USB_OTG_SRP (1 << 0) +#define USB_OTG_HNP (1 << 1) /* swap host/device roles */ + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEBUG: for special highspeed devices, replacing serial console */ +struct usb_debug_descriptor { + u8 bLength; + u8 bDescriptorType; + + /* bulk endpoints with 8 byte maxpacket */ + u8 bDebugInEndpoint; + u8 bDebugOutEndpoint; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_INTERFACE_ASSOCIATION: groups interfaces */ +struct usb_interface_assoc_descriptor { + u8 bLength; + u8 bDescriptorType; + + u8 bFirstInterface; + u8 bInterfaceCount; + u8 bFunctionClass; + u8 bFunctionSubClass; + u8 bFunctionProtocol; + u8 iFunction; +} __attribute__((packed)); +#define USB_DT_INTERFACE_ASSOCIATION_SIZE 8 + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_SECURITY: group of wireless security descriptors, including + * encryption types available for setting up a CC/association. + */ +struct usb_security_descriptor { + u8 bLength; + u8 bDescriptorType; + + u16 wTotalLength; + u8 bNumEncryptionTypes; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_KEY: used with {GET,SET}_SECURITY_DATA; only public keys + * may be retrieved. + */ +struct usb_key_descriptor { + u8 bLength; + u8 bDescriptorType; + + u8 tTKID[3]; + u8 bReserved; + u8 bKeyData[0]; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_ENCRYPTION_TYPE: bundled in DT_SECURITY groups */ +struct usb_encryption_descriptor { + u8 bLength; + u8 bDescriptorType; + + u8 bEncryptionType; +#define USB_ENC_TYPE_UNSECURE 0 +#define USB_ENC_TYPE_WIRED 1 /* non-wireless mode */ +#define USB_ENC_TYPE_CCM_1 2 /* aes128/cbc session */ +#define USB_ENC_TYPE_RSA_1 3 /* rsa3072/sha1 auth */ + u8 bEncryptionValue; /* use in SET_ENCRYPTION */ + u8 bAuthKeyIndex; +} __attribute__((packed)); + + +/*-------------------------------------------------------------------------*/ + +/* USB_DT_BOS: group of device-level capabilities */ +struct usb_bos_descriptor { + u8 bLength; + u8 bDescriptorType; + + u16 wTotalLength; + u8 bNumDeviceCaps; +} __attribute__((packed)); + +#define USB_DT_BOS_SIZE 5 +/*-------------------------------------------------------------------------*/ + +/* USB_DT_DEVICE_CAPABILITY: grouped with BOS */ +struct usb_dev_cap_header { + u8 bLength; + u8 bDescriptorType; + u8 bDevCapabilityType; +} __attribute__((packed)); + +#define USB_CAP_TYPE_WIRELESS_USB 1 + +struct usb_wireless_cap_descriptor { /* Ultra Wide Band */ + u8 bLength; + u8 bDescriptorType; + u8 bDevCapabilityType; + + u8 bmAttributes; +#define USB_WIRELESS_P2P_DRD (1 << 1) +#define USB_WIRELESS_BEACON_MASK (3 << 2) +#define USB_WIRELESS_BEACON_SELF (1 << 2) +#define USB_WIRELESS_BEACON_DIRECTED (2 << 2) +#define USB_WIRELESS_BEACON_NONE (3 << 2) + u16 wPHYRates; /* bit rates, Mbps */ +#define USB_WIRELESS_PHY_53 (1 << 0) /* always set */ +#define USB_WIRELESS_PHY_80 (1 << 1) +#define USB_WIRELESS_PHY_107 (1 << 2) /* always set */ +#define USB_WIRELESS_PHY_160 (1 << 3) +#define USB_WIRELESS_PHY_200 (1 << 4) /* always set */ +#define USB_WIRELESS_PHY_320 (1 << 5) +#define USB_WIRELESS_PHY_400 (1 << 6) +#define USB_WIRELESS_PHY_480 (1 << 7) + u8 bmTFITXPowerInfo; /* TFI power levels */ + u8 bmFFITXPowerInfo; /* FFI power levels */ + u16 bmBandGroup; + u8 bReserved; +} __attribute__((packed)); + +/* USB 2.0 Extension descriptor */ +#define USB_CAP_TYPE_EXT 2 + +struct usb_ext_cap_descriptor { /* Link Power Management */ + u8 bLength; + u8 bDescriptorType; + u8 bDevCapabilityType; + u32 bmAttributes; +#define USB_LPM_SUPPORT (1 << 1) /* supports LPM */ +#define USB_BESL_SUPPORT (1 << 2) /* supports BESL */ +#define USB_BESL_BASELINE_VALID (1 << 3) /* Baseline BESL valid*/ +#define USB_BESL_DEEP_VALID (1 << 4) /* Deep BESL valid */ +#define USB_GET_BESL_BASELINE(p) (((p) & (0xf << 8)) >> 8) +#define USB_GET_BESL_DEEP(p) (((p) & (0xf << 12)) >> 12) +} __attribute__((packed)); + +#define USB_DT_USB_EXT_CAP_SIZE 7 + +/* + * SuperSpeed USB Capability descriptor: Defines the set of SuperSpeed USB + * specific device level capabilities + */ +#define USB_SS_CAP_TYPE 3 +struct usb_ss_cap_descriptor { /* Link Power Management */ + u8 bLength; + u8 bDescriptorType; + u8 bDevCapabilityType; + u8 bmAttributes; +#define USB_LTM_SUPPORT (1 << 1) /* supports LTM */ + u16 wSpeedSupported; +#define USB_LOW_SPEED_OPERATION (1) /* Low speed operation */ +#define USB_FULL_SPEED_OPERATION (1 << 1) /* Full speed operation */ +#define USB_HIGH_SPEED_OPERATION (1 << 2) /* High speed operation */ +#define USB_5GBPS_OPERATION (1 << 3) /* Operation at 5Gbps */ + u8 bFunctionalitySupport; + u8 bU1devExitLat; + u16 bU2DevExitLat; +} __attribute__((packed)); + +#define USB_DT_USB_SS_CAP_SIZE 10 + +/* + * Container ID Capability descriptor: Defines the instance unique ID used to + * identify the instance across all operating modes + */ +#define CONTAINER_ID_TYPE 4 +struct usb_ss_container_id_descriptor { + u8 bLength; + u8 bDescriptorType; + u8 bDevCapabilityType; + u8 bReserved; + u8 ContainerID[16]; /* 128-bit number */ +} __attribute__((packed)); + +#define USB_DT_USB_SS_CONTN_ID_SIZE 20 +/*-------------------------------------------------------------------------*/ + +/* USB_DT_WIRELESS_ENDPOINT_COMP: companion descriptor associated with + * each endpoint descriptor for a wireless device + */ +struct usb_wireless_ep_comp_descriptor { + u8 bLength; + u8 bDescriptorType; + + u8 bMaxBurst; + u8 bMaxSequence; + u16 wMaxStreamDelay; + u16 wOverTheAirPacketSize; + u8 bOverTheAirInterval; + u8 bmCompAttributes; +#define USB_ENDPOINT_SWITCH_MASK 0x03 /* in bmCompAttributes */ +#define USB_ENDPOINT_SWITCH_NO 0 +#define USB_ENDPOINT_SWITCH_SWITCH 1 +#define USB_ENDPOINT_SWITCH_SCALE 2 +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_REQ_SET_HANDSHAKE is a four-way handshake used between a wireless + * host and a device for connection set up, mutual authentication, and + * exchanging short lived session keys. The handshake depends on a CC. + */ +struct usb_handshake { + u8 bMessageNumber; + u8 bStatus; + u8 tTKID[3]; + u8 bReserved; + u8 CDID[16]; + u8 nonce[16]; + u8 MIC[8]; +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB_REQ_SET_CONNECTION modifies or revokes a connection context (CC). + * A CC may also be set up using non-wireless secure channels (including + * wired USB!), and some devices may support CCs with multiple hosts. + */ +struct usb_connection_context { + u8 CHID[16]; /* persistent host id */ + u8 CDID[16]; /* device id (unique w/in host context) */ + u8 CK[16]; /* connection key */ +} __attribute__((packed)); + +/*-------------------------------------------------------------------------*/ + +/* USB 2.0 defines three speeds, here's how Linux identifies them */ + +enum usb_device_speed { + USB_SPEED_UNKNOWN = 0, /* enumerating */ + USB_SPEED_LOW, USB_SPEED_FULL, /* usb 1.1 */ + USB_SPEED_HIGH, /* usb 2.0 */ + USB_SPEED_WIRELESS, /* wireless (usb 2.5) */ + USB_SPEED_SUPER, /* usb 3.0 */ +}; + + +enum usb_device_state { + /* NOTATTACHED isn't in the USB spec, and this state acts + * the same as ATTACHED ... but it's clearer this way. + */ + USB_STATE_NOTATTACHED = 0, + + /* chapter 9 and authentication (wireless) device states */ + USB_STATE_ATTACHED, + USB_STATE_POWERED, /* wired */ + USB_STATE_RECONNECTING, /* auth */ + USB_STATE_UNAUTHENTICATED, /* auth */ + USB_STATE_DEFAULT, /* limited function */ + USB_STATE_ADDRESS, + USB_STATE_CONFIGURED, /* most functions */ + + USB_STATE_SUSPENDED + + /* NOTE: there are actually four different SUSPENDED + * states, returning to POWERED, DEFAULT, ADDRESS, or + * CONFIGURED respectively when SOF tokens flow again. + * At this level there's no difference between L1 and L2 + * suspend states. (L2 being original USB 1.1 suspend.) + */ +}; + +enum usb3_link_state { + USB3_LPM_U0 = 0, + USB3_LPM_U1, + USB3_LPM_U2, + USB3_LPM_U3 +}; + +/* + * A U1 timeout of 0x0 means the parent hub will reject any transitions to U1. + * 0xff means the parent hub will accept transitions to U1, but will not + * initiate a transition. + * + * A U1 timeout of 0x1 to 0x7F also causes the hub to initiate a transition to + * U1 after that many microseconds. Timeouts of 0x80 to 0xFE are reserved + * values. + * + * A U2 timeout of 0x0 means the parent hub will reject any transitions to U2. + * 0xff means the parent hub will accept transitions to U2, but will not + * initiate a transition. + * + * A U2 timeout of 0x1 to 0xFE also causes the hub to initiate a transition to + * U2 after N*256 microseconds. Therefore a U2 timeout value of 0x1 means a U2 + * idle timer of 256 microseconds, 0x2 means 512 microseconds, 0xFE means + * 65.024ms. + */ +#define USB3_LPM_DISABLED 0x0 +#define USB3_LPM_U1_MAX_TIMEOUT 0x7F +#define USB3_LPM_U2_MAX_TIMEOUT 0xFE +#define USB3_LPM_DEVICE_INITIATED 0xFF + +struct usb_set_sel_req { + u8 u1_sel; + u8 u1_pel; + u16 u2_sel; + u16 u2_pel; +} __attribute__((packed)); + +/* + * The Set System Exit Latency control transfer provides one byte each for + * U1 SEL and U1 PEL, so the max exit latency is 0xFF. U2 SEL and U2 PEL each + * are two bytes long. + */ +#define USB3_LPM_MAX_U1_SEL_PEL 0xFF +#define USB3_LPM_MAX_U2_SEL_PEL 0xFFFF + +/*-------------------------------------------------------------------------*/ + +/* + * As per USB compliance update, a device that is actively drawing + * more than 100mA from USB must report itself as bus-powered in + * the GetStatus(DEVICE) call. + * http://compliance.usb.org/index.asp?UpdateFile=Electrical&Format=Standard#34 + */ +#define USB_SELF_POWER_VBUS_MAX_DRAW 100 + +#endif /* __LINUX_USB_CH9_H */ diff --git a/include_lib/driver/device/usb/device/descriptor.h b/include_lib/driver/device/usb/device/descriptor.h new file mode 100644 index 0000000..baf4c5a --- /dev/null +++ b/include_lib/driver/device/usb/device/descriptor.h @@ -0,0 +1,16 @@ +#ifndef __DESCRIPTOR_H__ +#define __DESCRIPTOR_H__ + +#include "asm/usb.h" + +void get_device_descriptor(u8 *ptr); +void get_language_str(u8 *ptr); +void get_manufacture_str(u8 *ptr); +void get_product_str(u8 *ptr); +void get_iserialnumber_str(u8 *ptr); +void get_string_ee(u8 *ptr); + +u32 set_descriptor(const usb_dev usb_id, u32 class_config, u8 *p, u32 max_len); + + +#endif /*DESCRIPTOR_H*/ diff --git a/include_lib/driver/device/usb/device/hid.h b/include_lib/driver/device/usb/device/hid.h new file mode 100644 index 0000000..d812448 --- /dev/null +++ b/include_lib/driver/device/usb/device/hid.h @@ -0,0 +1,131 @@ +#ifndef __USB_HID_H__ +#define __USB_HID_H__ + +#include "typedef.h" +#include "asm/usb.h" + +//do not add brace to the macro outside +#define SHORT_ITEMS(prefix, _len, ...) \ + ((prefix) | (((_len) > 0) ? 1 << ((_len) - 1) : 0)), ##__VA_ARGS__ + +/*Main Items*/ +#define INPUT(len, ...) SHORT_ITEMS(0x80, len, ##__VA_ARGS__) +#define OUTPUT(len, ...) SHORT_ITEMS(0x90, len, ##__VA_ARGS__) +#define COLLECTION(len, ...) SHORT_ITEMS(0xA0, len, ##__VA_ARGS__) +#define FEATURE(len, ...) SHORT_ITEMS(0xB0, len, ##__VA_ARGS__) +#define END_COLLECTION 0xC0 + +/*Golbal Items*/ +#define USAGE_PAGE(len, ...) SHORT_ITEMS(0x04, len, ##__VA_ARGS__) +#define LOGICAL_MIN(len, ...) SHORT_ITEMS(0x14, len, ##__VA_ARGS__) +#define LOGICAL_MAX(len, ...) SHORT_ITEMS(0x24, len, ##__VA_ARGS__) +#define PHYSICAL_MIN(len, ...) SHORT_ITEMS(0x34, len, ##__VA_ARGS__) +#define PHYSICAL_MAX(len, ...) SHORT_ITEMS(0x44, len, ##__VA_ARGS__) +#define UNIT_EXPONENT(len, ...) SHORT_ITEMS(0x54, len, ##__VA_ARGS__) +#define UNIT(len, ...) SHORT_ITEMS(0x64, len, ##__VA_ARGS__) +#define REPORT_SIZE(len, ...) SHORT_ITEMS(0x74, len, ##__VA_ARGS__) +#define REPORT_ID(len, ...) SHORT_ITEMS(0x84, len, ##__VA_ARGS__) +#define REPORT_COUNT(len, ...) SHORT_ITEMS(0x94, len, ##__VA_ARGS__) +#define PUSH SHORT_ITEMS(0xA4, 0) +#define POP SHORT_ITEMS(0xB4, 0) + +/*Local Items*/ +#define USAGE(len, ...) SHORT_ITEMS(0x08, len, ##__VA_ARGS__) +#define USAGE_MIN(len, ...) SHORT_ITEMS(0x18, len, ##__VA_ARGS__) +#define USAGE_MAX(len, ...) SHORT_ITEMS(0x28, len, ##__VA_ARGS__) +#define DESIGNATOR_INDEX(len, ...) SHORT_ITEMS(0x38, len, ##__VA_ARGS__) +#define DESIGNATOR_MIN(len, ...) SHORT_ITEMS(0x48, len, ##__VA_ARGS__) +#define DESIGNATOR_MAX(len, ...) SHORT_ITEMS(0x58, len, ##__VA_ARGS__) +#define STRING_INDEX(len, ...) SHORT_ITEMS(0x78, len, ##__VA_ARGS__) +#define STRING_MIN(len, ...) SHORT_ITEMS(0x88, len, ##__VA_ARGS__) +#define STRING_MAX(len, ...) SHORT_ITEMS(0x98, len, ##__VA_ARGS__) +#define DELIMITER(len, ...) SHORT_ITEMS(0xA8, len, ##__VA_ARGS__) + + +/*Consumer Page*/ +#define CONSUMER_PAGE 0x0C +#define CONSUMER_CONTROL 0x01 +#define GENERIC_DESKTOP_CTRLS 0x01 + +/*Usage*/ +#define POINTER 0x01 +#define MOUSE 0x02 +#define BUTTON 0x09 +#define X_AXIS 0x30 +#define Y_AXIS 0x31 + +//Collection +#define PHYSICAL 0x00 +#define APPLICATION 0x01 +#define LOGICAL 0x02 +#define REPORT 0x03 + +#define USB_HID_DT_HID (USB_TYPE_CLASS | 0x01) +#define USB_HID_DT_REPORT (USB_TYPE_CLASS | 0x02) +#define USB_HID_DT_PHYSICAL (USB_TYPE_CLASS | 0x03) +/* + * * HID requests + * */ +#define USB_REQ_GET_REPORT 0x01 +#define USB_REQ_GET_IDLE 0x02 +#define USB_REQ_GET_PROTOCOL 0x03 +#define USB_REQ_SET_REPORT 0x09 +#define USB_REQ_SET_IDLE 0x0A +#define USB_REQ_SET_PROTOCOL 0x0B + + + + +#define PLAY 0xB0 +#define PAUSE 0xB1 +#define RECORD 0xB2 +#define FAST_FORWARD 0xB3 +#define REWIND 0xB4 +#define SCAN_NEXT_TRACK 0xB5 +#define SCAN_PREV_TRACK 0xB6 +#define STOP 0xB7 +#define FRAME_FORWARD 0xC0 +#define FRAME_BACK 0xC1 +#define TRACKING_INC 0xCA +#define TRACKING_DEC 0xCB +#define STOP_EJECT 0xCC +#define PLAY_PAUSE 0xCD +#define PLAY_SKIP 0xCE +#define VOLUME 0xE0 +#define BALANCE 0xE1 +#define MUTE 0xE2 +#define BASS 0xE3 +#define VOLUME_INC 0xE9 +#define VOLUME_DEC 0xEA +#define BALANCE_LEFT 0x50, 0x01 +#define BALANCE_RIGHT 0x51, 0x01 +#define CHANNEL_LEFT 0x61, 0x01 +#define CHANNEL_RIGHT 0x62, 0x01 + + +//---------------------------------- +// HID key for audio +//---------------------------------- +#define USB_AUDIO_NONE 0 +#define USB_AUDIO_VOLUP BIT(0) +#define USB_AUDIO_VOLDOWN BIT(1) +#define USB_AUDIO_MUTE BIT(2) +#define USB_AUDIO_PP BIT(3) +#define USB_AUDIO_NEXTFILE BIT(4) +#define USB_AUDIO_PREFILE BIT(5) +#define USB_AUDIO_FASTFORWARD BIT(5) +#define USB_AUDIO_STOP BIT(7) + +#define USB_AUDIO_TRACKING_INC BIT(8) +#define USB_AUDIO_TRACKING_DEC BIT(9) +#define USB_AUDIO_STOP_EJECT BIT(10) +#define USB_AUDIO_VOLUME BIT(11) +#define USB_AUDIO_BALANCE_RIGHT BIT(12) +#define USB_AUDIO_BALANCE_LEFT BIT(13) +#define USB_AUDIO_PLAY BIT(14) +#define USB_AUDIO_PAUSE BIT(15) + +u32 hid_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num); +void hid_key_handler(struct usb_device_t *usb_device, u32 hid_key); +u32 hid_send_data(const void *p, u32 len); +#endif diff --git a/include_lib/driver/device/usb/device/msd.h b/include_lib/driver/device/usb/device/msd.h new file mode 100644 index 0000000..8341422 --- /dev/null +++ b/include_lib/driver/device/usb/device/msd.h @@ -0,0 +1,34 @@ +#ifndef __USBD_MSD_H__ +#define __USBD_MSD_H__ + +#include "asm/usb.h" +#include "usb_stack.h" + +#define MAX_MSD_DEV 2 +#define MSD_DEV_NAME_LEN 12 + +struct msd_info { + u8 bError; + u8 bSenseKey; + u8 bAdditionalSenseCode; + u8 bAddiSenseCodeQualifier; + u8 bDisk_popup[MAX_MSD_DEV]; + void *dev_handle[MAX_MSD_DEV]; + char dev_name[MAX_MSD_DEV][MSD_DEV_NAME_LEN]; + void (*msd_wakeup_handle)(struct usb_device_t *usb_device); + void (*msd_reset_wakeup_handle)(struct usb_device_t *usb_device, u32 itf_num); +}; + + + +u32 msd_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num); +void USB_MassStorage(const struct usb_device_t *usb_device); +u32 msd_set_wakeup_handle(void (*handle)(struct usb_device_t *usb_device)); +u32 msd_register_disk(const char *name, void *arg); +u32 msd_unregister_disk(const char *name); +u32 msd_unregister_all(); +u32 msd_register(); +u32 msd_release(); +void msd_set_reset_wakeup_handle(void (*handle)(struct usb_device_t *usb_device, u32 itf_num)); +void msd_reset(struct usb_device_t *usb_device, u32 itf_num); +#endif /*USBD_MSD_H*/ diff --git a/include_lib/driver/device/usb/device/uac_audio.h b/include_lib/driver/device/usb/device/uac_audio.h new file mode 100644 index 0000000..328d4dd --- /dev/null +++ b/include_lib/driver/device/usb/device/uac_audio.h @@ -0,0 +1,470 @@ +/** + * -- USB Audio definitions. + * + * Copyright (C) 2006 Thumtronics Pty Ltd. + * Developed for Thumtronics by Grey Innovation + * Ben Williamson + * + * This software is distributed under the terms of the GNU General Public + * License ("GPL") version 2, as published by the Free Software Foundation. + * + * This file holds USB constants and structures defined + * by the USB Device Class Definition for Audio Devices. + * Comments below reference relevant sections of that document: + * + * http://www.usb.org/developers/devclass_docs/audio10.pdf + * + * Types and defines in this file are either specific to version 1.0 of + * this standard or common for newer versions. + */ + +#ifndef __LINUX_USB_AUDIO_H +#define __LINUX_USB_AUDIO_H + +#ifdef __cplusplus +extern "C" { +#endif +#define __le16 u16 + +#define u8 unsigned char // u8 to u32 special for struct +#define u16 unsigned short // u16 to u32 special for struct +#ifndef __s16 +#define s16 short // only s16 +#endif +#define u32 unsigned int + +/* A.8. Audio Class-Specific Request Codes */ +#define UAC_RC_UNDEFINED 0x00 +#define UAC_SET_CUR 0x01 +#define UAC_GET_CUR 0x81 +#define UAC_GET_MIN 0x82 +#define UAC_GET_MAX 0x83 +#define UAC_GET_RES 0x84 +#define UAC_GET_LEN 0x85 +#define UAC_GET_INFO 0x86 +#define UAC_GET_DEF 0x87 + + +/** bInterfaceProtocol values to denote the version of the standard used */ +#define UAC_VERSION_1 0x00 +#define UAC_VERSION_2 0x20 + +/** A.2 Audio Interface Subclass Codes */ +#define USB_SUBCLASS_AUDIOCONTROL 0x01 +#define USB_SUBCLASS_AUDIOSTREAMING 0x02 +#define USB_SUBCLASS_MIDISTREAMING 0x03 + +/** A.5 Audio Class-Specific AC Interface Descriptor Subtypes */ +#define UAC_HEADER 0x01 +#define UAC_INPUT_TERMINAL 0x02 +#define UAC_OUTPUT_TERMINAL 0x03 +#define UAC_MIXER_UNIT 0x04 +#define UAC_SELECTOR_UNIT 0x05 +#define UAC_FEATURE_UNIT 0x06 +#define UAC1_PROCESSING_UNIT 0x07 +#define UAC1_EXTENSION_UNIT 0x08 + +/** A.6 Audio Class-Specific AS Interface Descriptor Subtypes */ +#define UAC_AS_GENERAL 0x01 +#define UAC_FORMAT_TYPE 0x02 +#define UAC_FORMAT_SPECIFIC 0x03 + +/** A.7 Processing Unit Process Types */ +#define UAC_PROCESS_UNDEFINED 0x00 +#define UAC_PROCESS_UP_DOWNMIX 0x01 +#define UAC_PROCESS_DOLBY_PROLOGIC 0x02 +#define UAC_PROCESS_STEREO_EXTENDER 0x03 +#define UAC_PROCESS_REVERB 0x04 +#define UAC_PROCESS_CHORUS 0x05 +#define UAC_PROCESS_DYN_RANGE_COMP 0x06 + +/** A.8 Audio Class-Specific Endpoint Descriptor Subtypes */ +#define UAC_EP_GENERAL 0x01 + +/** A.9 Audio Class-Specific Request Codes */ + +#define UAC_GET_STAT 0xff + +/** A.10 Control Selector Codes */ + +/** A.10.1 Terminal Control Selectors */ +#define UAC_TERM_COPY_PROTECT 0x01 + +/** A.10.2 Feature Unit Control Selectors */ +#define UAC_FU_MUTE 0x01 +#define UAC_FU_VOLUME 0x02 +#define UAC_FU_BASS 0x03 +#define UAC_FU_MID 0x04 +#define UAC_FU_TREBLE 0x05 +#define UAC_FU_GRAPHIC_EQUALIZER 0x06 +#define UAC_FU_AUTOMATIC_GAIN 0x07 +#define UAC_FU_DELAY 0x08 +#define UAC_FU_BASS_BOOST 0x09 +#define UAC_FU_LOUDNESS 0x0a + +#define UAC_CONTROL_BIT(CS) (1 << ((CS) - 1)) + +/** A.10.3.1 Up/Down-mix Processing Unit Controls Selectors */ +#define UAC_UD_ENABLE 0x01 +#define UAC_UD_MODE_SELECT 0x02 + +/** A.10.3.2 Dolby Prologic (tm) Processing Unit Controls Selectors */ +#define UAC_DP_ENABLE 0x01 +#define UAC_DP_MODE_SELECT 0x02 + +/** A.10.3.3 3D Stereo Extender Processing Unit Control Selectors */ +#define UAC_3D_ENABLE 0x01 +#define UAC_3D_SPACE 0x02 + +/** A.10.3.4 Reverberation Processing Unit Control Selectors */ +#define UAC_REVERB_ENABLE 0x01 +#define UAC_REVERB_LEVEL 0x02 +#define UAC_REVERB_TIME 0x03 +#define UAC_REVERB_FEEDBACK 0x04 + +/** A.10.3.5 Chorus Processing Unit Control Selectors */ +#define UAC_CHORUS_ENABLE 0x01 +#define UAC_CHORUS_LEVEL 0x02 +#define UAC_CHORUS_RATE 0x03 +#define UAC_CHORUS_DEPTH 0x04 + +/** A.10.3.6 Dynamic Range Compressor Unit Control Selectors */ +#define UAC_DCR_ENABLE 0x01 +#define UAC_DCR_RATE 0x02 +#define UAC_DCR_MAXAMPL 0x03 +#define UAC_DCR_THRESHOLD 0x04 +#define UAC_DCR_ATTACK_TIME 0x05 +#define UAC_DCR_RELEASE_TIME 0x06 + +/** A.10.4 Extension Unit Control Selectors */ +#define UAC_XU_ENABLE 0x01 + +/** MIDI - A.1 MS Class-Specific Interface Descriptor Subtypes */ +#define UAC_MS_HEADER 0x01 +#define UAC_MIDI_IN_JACK 0x02 +#define UAC_MIDI_OUT_JACK 0x03 + +/** MIDI - A.1 MS Class-Specific Endpoint Descriptor Subtypes */ +#define UAC_MS_GENERAL 0x01 + +/** Terminals - 2.1 USB Terminal Types */ +#define UAC_TERMINAL_UNDEFINED 0x0100 +#define UAC_TERMINAL_STREAMING 0x0101 +#define UAC_TERMINAL_VENDOR_SPEC 0x01FF + +/** Terminal Control Selectors */ +/** 4.3.2 Class-Specific AC Interface Descriptor */ +struct uac1_ac_header_descriptor { + u8 bLength; /** 8 + n */ + u8 bDescriptorType; /** USB_DT_CS_INTERFACE */ + u8 bDescriptorSubtype; /** UAC_MS_HEADER */ + __le16 bcdADC; /** 0x0100 */ + __le16 wTotalLength; /** includes Unit and Terminal desc. */ + u8 bInCollection; /** n */ + u8 baInterfaceNr[]; /** [n] */ +} __attribute__((packed)); + +#define UAC_DT_AC_HEADER_SIZE(n) (8 + (n)) + +/** As above, but more useful for defining your own descriptors: */ +#define DECLARE_UAC_AC_HEADER_DESCRIPTOR(n) \ + struct uac1_ac_header_descriptor_##n { \ + u8 bLength; \ + u8 bDescriptorType; \ + u8 bDescriptorSubtype; \ + __le16 bcdADC; \ + __le16 wTotalLength; \ + u8 bInCollection; \ + u8 baInterfaceNr[n]; \ + } __attribute__ ((packed)) + +/** 4.3.2.1 Input Terminal Descriptor */ +struct uac_input_terminal_descriptor { + u8 bLength; /** in bytes: 12 */ + u8 bDescriptorType; /** CS_INTERFACE descriptor type */ + u8 bDescriptorSubtype; /** INPUT_TERMINAL descriptor subtype */ + u8 bTerminalID; /** Constant uniquely terminal ID */ + __le16 wTerminalType; /** USB Audio Terminal Types */ + u8 bAssocTerminal; /** ID of the Output Terminal associated */ + u8 bNrChannels; /** Number of logical output channels */ + __le16 wChannelConfig; + u8 iChannelNames; + u8 iTerminal; +} __attribute__((packed)); + +#define UAC_DT_INPUT_TERMINAL_SIZE 12 + +/** Terminals - 2.2 Input Terminal Types */ +#define UAC_INPUT_TERMINAL_UNDEFINED 0x200 +#define UAC_INPUT_TERMINAL_MICROPHONE 0x201 +#define UAC_INPUT_TERMINAL_DESKTOP_MICROPHONE 0x202 +#define UAC_INPUT_TERMINAL_PERSONAL_MICROPHONE 0x203 +#define UAC_INPUT_TERMINAL_OMNI_DIR_MICROPHONE 0x204 +#define UAC_INPUT_TERMINAL_MICROPHONE_ARRAY 0x205 +#define UAC_INPUT_TERMINAL_PROC_MICROPHONE_ARRAY 0x206 + +/** Terminals - control selectors */ + +#define UAC_TERMINAL_CS_COPY_PROTECT_CONTROL 0x01 + +/** 4.3.2.2 Output Terminal Descriptor */ +struct uac1_output_terminal_descriptor { + u8 bLength; /** in bytes: 9 */ + u8 bDescriptorType; /** CS_INTERFACE descriptor type */ + u8 bDescriptorSubtype; /** OUTPUT_TERMINAL descriptor subtype */ + u8 bTerminalID; /** Constant uniquely terminal ID */ + __le16 wTerminalType; /** USB Audio Terminal Types */ + u8 bAssocTerminal; /** ID of the Input Terminal associated */ + u8 bSourceID; /** ID of the connected Unit or Terminal*/ + u8 iTerminal; +} __attribute__((packed)); + +#define UAC_DT_OUTPUT_TERMINAL_SIZE 9 + +/** Terminals - 2.3 Output Terminal Types */ +#define UAC_OUTPUT_TERMINAL_UNDEFINED 0x300 +#define UAC_OUTPUT_TERMINAL_SPEAKER 0x301 +#define UAC_OUTPUT_TERMINAL_HEADPHONES 0x302 +#define UAC_OUTPUT_TERMINAL_HEAD_MOUNTED_DISPLAY_AUDIO 0x303 +#define UAC_OUTPUT_TERMINAL_DESKTOP_SPEAKER 0x304 +#define UAC_OUTPUT_TERMINAL_ROOM_SPEAKER 0x305 +#define UAC_OUTPUT_TERMINAL_COMMUNICATION_SPEAKER 0x306 +#define UAC_OUTPUT_TERMINAL_LOW_FREQ_EFFECTS_SPEAKER 0x307 +#define UAC_OUTPUT_TERMINAL_HEADSET 0x0402 + +/** Set bControlSize = 2 as default setting */ +#define UAC_DT_FEATURE_UNIT_SIZE(ch) (7 + ((ch) + 1) * 2) + +/** As above, but more useful for defining your own descriptors: */ +#define DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(ch) \ + struct uac_feature_unit_descriptor_##ch { \ + u8 bLength; \ + u8 bDescriptorType; \ + u8 bDescriptorSubtype; \ + u8 bUnitID; \ + u8 bSourceID; \ + u8 bControlSize; \ + __le16 bmaControls[ch + 1]; \ + u8 iFeature; \ + } __attribute__ ((packed)) + +/** 4.3.2.3 Mixer Unit Descriptor */ +struct uac_mixer_unit_descriptor { + u8 bLength; + u8 bDescriptorType; + u8 bDescriptorSubtype; + u8 bUnitID; + u8 bNrInPins; + u8 baSourceID[]; +} __attribute__((packed)); + + + +/** 4.3.2.4 Selector Unit Descriptor */ +struct uac_selector_unit_descriptor { + u8 bLength; + u8 bDescriptorType; + u8 bDescriptorSubtype; + u8 bUintID; + u8 bNrInPins; + u8 baSourceID[]; +} __attribute__((packed)); + + + +/** 4.3.2.5 Feature Unit Descriptor */ +struct uac_feature_unit_descriptor { + u8 bLength; + u8 bDescriptorType; + u8 bDescriptorSubtype; + u8 bUnitID; + u8 bSourceID; + u8 bControlSize; + u8 bmaControls[0]; /** variable length */ +} __attribute__((packed)); + + + +/** 4.3.2.6 Processing Unit Descriptors */ +struct uac_processing_unit_descriptor { + u8 bLength; + u8 bDescriptorType; + u8 bDescriptorSubtype; + u8 bUnitID; + u16 wProcessType; + u8 bNrInPins; + u8 baSourceID[]; +} __attribute__((packed)); + + + + +/** 4.5.2 Class-Specific AS Interface Descriptor */ +struct uac1_as_header_descriptor { + u8 bLength; /** in bytes: 7 */ + u8 bDescriptorType; /** USB_DT_CS_INTERFACE */ + u8 bDescriptorSubtype; /** AS_GENERAL */ + u8 bTerminalLink; /** Terminal ID of connected Terminal */ + u8 bDelay; /** Delay introduced by the data path */ + __le16 wFormatTag; /** The Audio Data Format */ +} __attribute__((packed)); + +#define UAC_DT_AS_HEADER_SIZE 7 + +/** Formats - A.1.1 Audio Data Format Type I Codes */ +#define UAC_FORMAT_TYPE_I_UNDEFINED 0x0 +#define UAC_FORMAT_TYPE_I_PCM 0x1 +#define UAC_FORMAT_TYPE_I_PCM8 0x2 +#define UAC_FORMAT_TYPE_I_IEEE_FLOAT 0x3 +#define UAC_FORMAT_TYPE_I_ALAW 0x4 +#define UAC_FORMAT_TYPE_I_MULAW 0x5 + +struct uac_format_type_i_continuous_descriptor { + u8 bLength; /** in bytes: 8 + (ns * 3) */ + u8 bDescriptorType; /** USB_DT_CS_INTERFACE */ + u8 bDescriptorSubtype; /** FORMAT_TYPE */ + u8 bFormatType; /** FORMAT_TYPE_1 */ + u8 bNrChannels; /** physical channels in the stream */ + u8 bSubframeSize; /** */ + u8 bBitResolution; + u8 bSamFreqType; + u8 tLowerSamFreq[3]; + u8 tUpperSamFreq[3]; +} __attribute__((packed)); + +#define UAC_FORMAT_TYPE_I_CONTINUOUS_DESC_SIZE 14 + +struct uac_format_type_i_discrete_descriptor { + u8 bLength; /** in bytes: 8 + (ns * 3) */ + u8 bDescriptorType; /** USB_DT_CS_INTERFACE */ + u8 bDescriptorSubtype; /** FORMAT_TYPE */ + u8 bFormatType; /** FORMAT_TYPE_1 */ + u8 bNrChannels; /** physical channels in the stream */ + u8 bSubframeSize; /** */ + u8 bBitResolution; + u8 bSamFreqType; + u8 tSamFreq[][3]; +} __attribute__((packed)); + +#define DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(n) \ + struct uac_format_type_i_discrete_descriptor_##n { \ + u8 bLength; \ + u8 bDescriptorType; \ + u8 bDescriptorSubtype; \ + u8 bFormatType; \ + u8 bNrChannels; \ + u8 bSubframeSize; \ + u8 bBitResolution; \ + u8 bSamFreqType; \ + u8 tSamFreq[n][3]; \ + } __attribute__ ((packed)) + +#define UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(n) (8 + (n * 3)) + +struct uac_format_type_i_ext_descriptor { + u8 bLength; + u8 bDescriptorType; + u8 bDescriptorSubtype; + u8 bFormatType; + u8 bSubslotSize; + u8 bBitResolution; + u8 bHeaderLength; + u8 bControlSize; + u8 bSideBandProtocol; +} __attribute__((packed)); + +/** Formats - Audio Data Format Type I Codes */ + +#define UAC_FORMAT_TYPE_II_MPEG 0x1001 +#define UAC_FORMAT_TYPE_II_AC3 0x1002 + +struct uac_format_type_ii_discrete_descriptor { + u8 bLength; + u8 bDescriptorType; + u8 bDescriptorSubtype; + u8 bFormatType; + __le16 wMaxBitRate; + __le16 wSamplesPerFrame; + u8 bSamFreqType; + u8 tSamFreq[][3]; +} __attribute__((packed)); + +struct uac_format_type_ii_ext_descriptor { + u8 bLength; + u8 bDescriptorType; + u8 bDescriptorSubtype; + u8 bFormatType; + u16 wMaxBitRate; + u16 wSamplesPerFrame; + u8 bHeaderLength; + u8 bSideBandProtocol; +} __attribute__((packed)); + +/** type III */ +#define UAC_FORMAT_TYPE_III_IEC1937_AC3 0x2001 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG1_LAYER1 0x2002 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_NOEXT 0x2003 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_EXT 0x2004 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER1_LS 0x2005 +#define UAC_FORMAT_TYPE_III_IEC1937_MPEG2_LAYER23_LS 0x2006 + +/** Formats - A.2 Format Type Codes */ +#define UAC_FORMAT_TYPE_UNDEFINED 0x0 +#define UAC_FORMAT_TYPE_I 0x1 +#define UAC_FORMAT_TYPE_II 0x2 +#define UAC_FORMAT_TYPE_III 0x3 +#define UAC_EXT_FORMAT_TYPE_I 0x81 +#define UAC_EXT_FORMAT_TYPE_II 0x82 +#define UAC_EXT_FORMAT_TYPE_III 0x83 + +struct uac_iso_endpoint_descriptor { + u8 bLength; /** in bytes: 7 */ + u8 bDescriptorType; /** USB_DT_CS_ENDPOINT */ + u8 bDescriptorSubtype; /** EP_GENERAL */ + u8 bmAttributes; + u8 bLockDelayUnits; + __le16 wLockDelay; +} __attribute__((packed)); +#define UAC_ISO_ENDPOINT_DESC_SIZE 7 + +#define UAC_EP_CS_ATTR_SAMPLE_RATE 0x01 +#define UAC_EP_CS_ATTR_PITCH_CONTROL 0x02 +#define UAC_EP_CS_ATTR_FILL_MAX 0x80 + +/** status word format (3.7.1.1) */ + +#define UAC1_STATUS_TYPE_ORIG_MASK 0x0f +#define UAC1_STATUS_TYPE_ORIG_AUDIO_CONTROL_IF 0x0 +#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_IF 0x1 +#define UAC1_STATUS_TYPE_ORIG_AUDIO_STREAM_EP 0x2 + +#define UAC1_STATUS_TYPE_IRQ_PENDING (1 << 7) +#define UAC1_STATUS_TYPE_MEM_CHANGED (1 << 6) + +#include "asm/usb.h" +struct uac1_status_word { + u8 bStatusType; + u8 bOriginator; +} __attribute__((packed)); + +u32 uac_setup_endpoint(struct usb_device_t *usb_device, struct usb_ctrlrequest *req); +u32 uac_spk_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num); +void uac_speaker_stream_write(const u8 *obuf, u32 len); +void uac_speaker_stream_open(u32 samplerate, u32 ch); +void uac_speaker_stream_close(); + +u32 uac_mic_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num); +u32 uac_mic_stream_open(u32 samplerate, u32 frame_len, u32 ch); +int uac_mic_stream_read(u8 *buf, u32 len); +void uac_mic_stream_close(); +void uac_mute_volume(u32 type, u32 l_vol, u32 r_vol); +int uac_get_spk_vol(); +u32 uac_audio_desc_config(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num); +void uac_audio_disable(const usb_dev usb_id); +const u8 *uac_get_string(u32 id); +u32 uac_register(); +void uac_release(const usb_dev usb_id); +#ifdef __cplusplus +} +#endif +#endif /** __LINUX_USB_AUDIO_H */ diff --git a/include_lib/driver/device/usb/device/usb_stack.h b/include_lib/driver/device/usb/device/usb_stack.h new file mode 100644 index 0000000..d4fcb80 --- /dev/null +++ b/include_lib/driver/device/usb/device/usb_stack.h @@ -0,0 +1,97 @@ +#ifndef __USB_STACK_H__ +#define __USB_STACK_H__ +#include "typedef.h" +#include "asm/usb.h" +#include "usb/ch9.h" +#include "usb/usb_phy.h" +#include "usb/otg.h" + + +#define MAX_INTERFACE_NUM 6 + +#define USB_SETUP_SIZE (512) + +#if 0 +#define USB_ATTACHED BIT(0) +#define USB_POWERED BIT(1) +#define USB_DEFAULT BIT(2) +#define USB_ADDRESS BIT(3) +#define USB_CONFIGURED BIT(4) +#define USB_SUSPENDED BIT(5) +#else +enum { + USB_ATTACHED, + USB_POWERED, + USB_DEFAULT, + USB_ADDRESS, + USB_CONFIGURED, + USB_SUSPENDED +}; +#endif +struct usb_device_t { + u8 baddr; + u8 bsetup_phase; //ep0 setup状态机 + u16 wDataLength; //ep0 setup data stage数据长度 + + u8 *setup_buffer; //本次传输的bufer地址 + u8 *setup_ptr; //当前传输的位置 + u32(*setup_hook)(struct usb_device_t *, struct usb_ctrlrequest *); + u32(*setup_recv)(struct usb_device_t *, struct usb_ctrlrequest *); + + u8 bDeviceStates; + u8 bDataOverFlag; //ep0 0包标识 + u8 wDeviceClass; // 设备类 + u8 bRemoteWakup: 1; +#if USB_MAX_HW_NUM == 2 + u8 usb_id: 1; + u8 res: 6; +#else + u8 res: 7; +#endif +}; + +typedef u32(*itf_hander)(struct usb_device_t *usb_device, struct usb_ctrlrequest *); +typedef void(*itf_reset_hander)(struct usb_device_t *, u32 itf); +typedef void(*usb_interrupt)(struct usb_device_t *, u32 ep); +typedef u32(*desc_config)(const usb_dev usb_id, u8 *ptr, u32 *cur_itf_num); + +struct usb_setup_t { + struct usb_device_t usb_device; + struct usb_ctrlrequest request; + itf_hander interface_hander[MAX_INTERFACE_NUM]; + itf_reset_hander reset_hander[MAX_INTERFACE_NUM]; +} __attribute__((aligned(4))); + +const usb_dev usb_device2id(const struct usb_device_t *usb_device); +struct usb_device_t *usb_id2device(const usb_dev usb_id); +void usb_control_transfer(struct usb_device_t *usb_device); +void usb_device_set_class(struct usb_device_t *usb_device, u32 class_config); +u32 usb_g_set_intr_hander(const usb_dev usb_id, u32 ep, usb_interrupt hander); +u32 usb_set_interface_hander(const usb_dev usb_id, u32 itf_num, itf_hander hander); +void usb_add_desc_config(const usb_dev usb_id, u32 index, const desc_config desc); +const u8 *usb_get_config_desc(); +u32 usb_set_reset_hander(const usb_dev usb_id, u32 itf_num, itf_reset_hander hander); +void usb_reset_interface(struct usb_device_t *usb_device); +void usb_set_setup_recv(struct usb_device_t *usb_device, void *recv); +void usb_set_setup_hook(struct usb_device_t *usb_device, void *hook); +int usb_device_mode(const usb_dev usb_id, const u32 class); +void usb_otg_sof_check_init(const usb_dev id); +void usb_setup_init(const usb_dev usb_id, void *ptr, u8 *setup_buffer); +u32 usb_setup_release(const usb_dev usb_id); +u8 *usb_set_data_payload(struct usb_device_t *usb_device, struct usb_ctrlrequest *req, const void *data, u32 len); +void usb_set_setup_phase(struct usb_device_t *usb_device, u8 setup_phase); +void dump_setup_request(const struct usb_ctrlrequest *request); +void user_setup_filter_install(struct usb_device_t *usb_device); +void usb_ep_enable(const usb_dev usb_id, u32 ep, u32 is_enable); +void *usb_get_setup_buffer(const struct usb_device_t *usb_device); +u32 usb_root2_testing(); + +extern void usb_start(); +extern void usb_stop(); +extern void usb_pause(); +extern void usb_cdc_background_run(); + +/* #define usb_add_desc_config(fn) \ */ +/* const desc_config usb_desc_config##fn sec(.usb.desc_config) = fn */ + +#endif /*USB_STACK_H*/ diff --git a/include_lib/driver/device/usb/host/usb_host.h b/include_lib/driver/device/usb/host/usb_host.h new file mode 100644 index 0000000..3fd5d0d --- /dev/null +++ b/include_lib/driver/device/usb/host/usb_host.h @@ -0,0 +1,90 @@ +#ifndef __USB_HOST_H__ +#define __USB_HOST_H__ +#include "system/task.h" +#include "device/device.h" +#include "asm/usb.h" +#include "usb/ch9.h" +#include "usb/usb_phy.h" +// #include "usb_config.h" + + +#define HUSB_MODE 0 +#define USB_HUB 0 +struct usb_private_data { + usb_dev usb_id; + u8 status; + u8 devnum; + u8 ep0_max_packet_size; + /* + u8 speed; + u16 vendor_id; + u16 product_id; + u16 language; + u8 manufacturer[64]; + u8 product[64]; + */ +}; + +struct usb_host_device; +struct interface_ctrl { + u8 interface_class; + int (*set_power)(struct usb_host_device *host_dev, u32 value); + int (*get_power)(struct usb_host_device *host_dev, u32 value); + int (*ioctl)(struct usb_host_device *host_dev, u32 cmd, u32 arg); +}; +struct usb_interface_info { + struct interface_ctrl *ctrl; + union { + struct mass_storage *disk; + struct adb_device_t *adb; + struct hid_device_t *hid; + struct aoa_device_t *aoa; + struct audio_device_t *audio; + void *p; + } dev; +}; +#define MAX_HOST_INTERFACE 4 +struct usb_host_device { +#if USB_HUB + struct usb_host_device *father; +#endif + OS_SEM *sem; + struct usb_private_data private_data; + const struct usb_interface_info *interface_info[MAX_HOST_INTERFACE]; +}; + + +#define device_to_usbdev(device) ((struct usb_host_device *)((device)->private_data)) + +u32 host_device2id(const struct usb_host_device *host_dev); + +int host_dev_status(const struct usb_host_device *host_dev); + +const struct usb_host_device *host_id2device(const usb_dev id); + +#define check_usb_mount(ret) \ + if(ret == -DEV_ERR_OFFLINE){\ + log_error("%s() @ %d DEV_ERR_OFFLINE\n", __func__, __LINE__);\ + goto __exit_fail;\ + } else if(ret){\ + log_error("%s() @ %d %x\n", __func__, __LINE__, ret);\ + continue;\ + } + + +typedef void(*usb_h_interrupt)(struct usb_host_device *, u32 ep); + +int usb_sem_init(struct usb_host_device *host_dev); +int usb_sem_pend(struct usb_host_device *host_dev, u32 timeout); +int usb_sem_post(struct usb_host_device *host_dev); +int usb_sem_del(struct usb_host_device *host_dev); + +void usb_h_set_ep_isr(struct usb_host_device *host_dev, u32 ep, usb_h_interrupt hander, void *p); +u32 usb_h_set_intr_hander(const usb_dev usb_id, u32 ep, usb_h_interrupt hander); +u32 usb_host_mount(const usb_dev usb_id, u32 retry, u32 reset_delay, u32 mount_timeout); +u32 usb_host_unmount(const usb_dev usb_id); +u32 usb_host_remount(const usb_dev usb_id, u32 retry, u32 delay, u32 ot, u8 notify); +void usb_host_suspend(const usb_dev usb_id); +void usb_host_resume(const usb_dev usb_id); + +#endif /*USB_HOST_H*/ diff --git a/include_lib/driver/device/usb/otg.h b/include_lib/driver/device/usb/otg.h new file mode 100644 index 0000000..d54c6af --- /dev/null +++ b/include_lib/driver/device/usb/otg.h @@ -0,0 +1,48 @@ +#ifndef __OTG_H__ +#define __OTG_H__ + +#include "asm/usb.h" + +enum { + IDLE_MODE = 0, + DISCONN_MODE = 1, + HOST_MODE = 2, + PRE_SLAVE_MODE, + SLAVE_MODE_WAIT_CONFIRMATION, + SLAVE_MODE, + CHARGE_MODE, +}; + +enum { + OTG_OP_NULL = 0, + OTG_UNINSTALL = 1, + OTG_KEEP_STATE, +}; + +#define OTG_HOST_MODE BIT(0) +#define OTG_SLAVE_MODE BIT(1) +#define OTG_CHARGE_MODE BIT(2) +#define OTG_DET_DP_ONLY BIT(3) + +struct otg_dev_data { + u8 usb_dev_en; + u8 slave_online_cnt; + u8 slave_offline_cnt; + u8 host_online_cnt; + u8 host_offline_cnt; + u8 detect_mode; + u8 detect_time_interval; +}; + + +u32 usb_otg_online(const usb_dev usb_id); +// u32 usb_otg_init(u32 mode); +void usb_otg_io_suspend(usb_dev usb_id); +void usb_otg_io_resume(usb_dev usb_id); +void usb_otg_suspend(usb_dev usb_id, u8 op_mode); +void usb_otg_resume(usb_dev usb_id); + +extern const struct device_operations usb_dev_ops; + + +#endif /*OTG_H*/ diff --git a/include_lib/driver/device/usb/scsi.h b/include_lib/driver/device/usb/scsi.h new file mode 100644 index 0000000..a7cc5d4 --- /dev/null +++ b/include_lib/driver/device/usb/scsi.h @@ -0,0 +1,251 @@ +#ifndef __SCSI_H__ +#define __SCSI_H__ + +#define USB_MSD_MAX_LUN 0xfe +#define USB_MSD_RESET 0xff + + +/* + * SCSI opcodes + */ +#define TEST_UNIT_READY 0x00 +#define REZERO_UNIT 0x01 +#define REQUEST_SENSE 0x03 +#define FORMAT_UNIT 0x04 +#define READ_BLOCK_LIMITS 0x05 +#define REASSIGN_BLOCKS 0x07 +#define INITIALIZE_ELEMENT_STATUS 0x07 +#define READ_6 0x08 +#define WRITE_6 0x0a +#define SEEK_6 0x0b +#define READ_REVERSE 0x0f +#define WRITE_FILEMARKS 0x10 +#define SPACE 0x11 +#define INQUIRY 0x12 +#define RECOVER_BUFFERED_DATA 0x14 +#define MODE_SELECT 0x15 +#define RESERVE 0x16 +#define RELEASE 0x17 +#define COPY 0x18 +#define ERASE 0x19 +#define MODE_SENSE 0x1a +#define START_STOP 0x1b +#define RECEIVE_DIAGNOSTIC 0x1c +#define SEND_DIAGNOSTIC 0x1d +#define ALLOW_MEDIUM_REMOVAL 0x1e + +#define READ_FORMAT_CAPACITIES 0x23 +#define SET_WINDOW 0x24 +#define READ_CAPACITY 0x25 +#define READ_10 0x28 +#define WRITE_10 0x2a +#define SEEK_10 0x2b +#define POSITION_TO_ELEMENT 0x2b +#define WRITE_VERIFY 0x2e +#define VERIFY 0x2f +#define SEARCH_HIGH 0x30 +#define SEARCH_EQUAL 0x31 +#define SEARCH_LOW 0x32 +#define SET_LIMITS 0x33 +#define PRE_FETCH 0x34 +#define READ_POSITION 0x34 +#define SYNCHRONIZE_CACHE 0x35 +#define LOCK_UNLOCK_CACHE 0x36 +#define READ_DEFECT_DATA 0x37 +#define MEDIUM_SCAN 0x38 +#define COMPARE 0x39 +#define COPY_VERIFY 0x3a +#define WRITE_BUFFER 0x3b +#define READ_BUFFER 0x3c +#define UPDATE_BLOCK 0x3d +#define READ_LONG 0x3e +#define WRITE_LONG 0x3f +#define CHANGE_DEFINITION 0x40 +#define WRITE_SAME 0x41 +#define UNMAP 0x42 +#define READ_TOC 0x43 +#define READ_HEADER 0x44 +#define GET_EVENT_STATUS_NOTIFICATION 0x4a +#define LOG_SELECT 0x4c +#define LOG_SENSE 0x4d +#define XDWRITEREAD_10 0x53 +#define MODE_SELECT_10 0x55 +#define RESERVE_10 0x56 +#define RELEASE_10 0x57 +#define MODE_SENSE_10 0x5a +#define PERSISTENT_RESERVE_IN 0x5e +#define PERSISTENT_RESERVE_OUT 0x5f +#define VARIABLE_LENGTH_CMD 0x7f +#define REPORT_LUNS 0xa0 +#define SECURITY_PROTOCOL_IN 0xa2 +#define MAINTENANCE_IN 0xa3 +#define MAINTENANCE_OUT 0xa4 +#define MOVE_MEDIUM 0xa5 +#define EXCHANGE_MEDIUM 0xa6 +#define READ_12 0xa8 +#define WRITE_12 0xaa +#define READ_MEDIA_SERIAL_NUMBER 0xab +#define WRITE_VERIFY_12 0xae +#define VERIFY_12 0xaf +#define SEARCH_HIGH_12 0xb0 +#define SEARCH_EQUAL_12 0xb1 +#define SEARCH_LOW_12 0xb2 +#define SECURITY_PROTOCOL_OUT 0xb5 +#define READ_ELEMENT_STATUS 0xb8 +#define SEND_VOLUME_TAG 0xb6 +#define WRITE_LONG_2 0xea +#define EXTENDED_COPY 0x83 +#define RECEIVE_COPY_RESULTS 0x84 +#define ACCESS_CONTROL_IN 0x86 +#define ACCESS_CONTROL_OUT 0x87 +#define READ_16 0x88 +#define WRITE_16 0x8a +#define READ_ATTRIBUTE 0x8c +#define WRITE_ATTRIBUTE 0x8d +#define VERIFY_16 0x8f +#define SYNCHRONIZE_CACHE_16 0x91 +#define WRITE_SAME_16 0x93 +#define SERVICE_ACTION_IN 0x9e + +/* + * SENSE KEYS + */ + +#define NO_SENSE 0x00 +#define RECOVERED_ERROR 0x01 +#define NOT_READY 0x02 +#define MEDIUM_ERROR 0x03 +#define HARDWARE_ERROR 0x04 +#define ILLEGAL_REQUEST 0x05 +#define UNIT_ATTENTION 0x06 +#define DATA_PROTECT 0x07 +#define BLANK_CHECK 0x08 +#define COPY_ABORTED 0x0a +#define ABORTED_COMMAND 0x0b +#define VOLUME_OVERFLOW 0x0d +#define MISCOMPARE 0x0e +/* Additional Sense code definition*/ +#define ASC_NO_ADDITIONAL_SENSE_INFORMATION 0x00 +#define ASC_RECOVERED_DATA_WITH_RETRIES 0x17 +#define ASC_RECOVERED_DATA_WITH_ECC 0x18 +#define ASC_MEDIUM_PRESENT 0x3A +#define ASC_LOGICAL_DRIVE_NOT_READY_BEING_READY 0x04 +#define ASC_LOGICAL_DRIVE_NOT_READY_FMT_IN_PRGS 0x04 +#define ASC_NO_REFERENCE_POSITION_FOUND 0x06 +#define ASC_NO_SEEK_COMPLETE 0x02 +#define ASC_WRITE_FAULT 0x03 +#define ASC_ID_CRC_ERROR 0x10 +#define ASC_UNRECOVERED_READ_ERROR 0x11 +#define ASC_ADDRESS_MARK_NOT_FOUND_FOR_ID_FIELD 0x12 +#define ASC_RECORDED_ENTITY_NOT_FOUND 0x14 +#define ASC_INCOMPATIBLE_MEDIUM_INSTALLED 0x30 +#define ASC_CANNOT_READ_MEDIUM_INCOMPATIBLE_FMT 0x30 +#define ASC_CANNOT_READ_MEDIUM_UNKNOWN_FORMAT 0x30 +#define ASC_FORMAT_COMMAND_FAILED 0x31 +#define ASC_INVALID_COMMAND_OPERATION_CODE 0x20 +#define ASC_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x21 +#define ASC_INVALID_FIELD_IN_COMMAND_PACKET 0x24 +#define ASC_LOGICAL_UNIT_NOT_SUPPORTED 0x25 +#define ASC_INVALID_FIELD_IN_PARAMETER_LIST 0x26 +#define ASC_MEDIUM_REMOVAL_PREVENTED 0x53 +#define ASC_NOT_READY_TO_READY_TRANSIT_MDI_CHNG 0x28 +#define ASC_POWER_ON_OR_BUS_DEVICE_RESET 0x29 +#define ASC_WRITE_PROTECTED_MEDIA 0x27 +#define ASC_OVERLAPPED_COMMAND_ATTEMPTED 0x4E + +/* Definition of additional sense code qualifier*/ +/* Additional Sense code definition */ +#define ASCQ_NO_ADDITIONAL_SENSE_INFORMATION 0x00 +#define ASCQ_RECOVERED_DATA_WITH_RETRIES 0x01 +#define ASCQ_RECOVERED_DATA_WITH_ECC 0x00 +#define ASCQ_MEDIUM_PRESENT 0x00 +#define ASCQ_LOGICAL_DRIVE_NOT_READY_BEING_READY 0x01 +#define ASCQ_LOGICAL_DRIVE_NOT_READY_FMT_IN_PRGS 0x04 +#define ASCQ_NO_REFERENCE_POSITION_FOUND 0x00 +#define ASCQ_NO_SEEK_COMPLETE 0x00 +#define ASCQ_WRITE_FAULT 0x00 +#define ASCQ_ID_CRC_ERROR 0x00 +#define ASCQ_UNRECOVERED_READ_ERROR 0x00 +#define ASCQ_ADDRESS_MARK_NOT_FOUND_FOR_ID_FIELD 0x00 +#define ASCQ_RECORDED_ENTITY_NOT_FOUND 0x00 +#define ASCQ_INCOMPATIBLE_MEDIUM_INSTALLED 0x00 +#define ASCQ_CANNOT_READ_MEDIUM_INCOMPATIBLE_FMT 0x02 +#define ASCQ_CANNOT_READ_MEDIUM_UNKNOWN_FORMAT 0x01 +#define ASCQ_FORMAT_COMMAND_FAILED 0x01 +#define ASCQ_INVALID_COMMAND_OPERATION_CODE 0x00 +#define ASCQ_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x00 +#define ASCQ_INVALID_FIELD_IN_COMMAND_PACKET 0x00 +#define ASCQ_LOGICAL_UNIT_NOT_SUPPORTED 0x00 +#define ASCQ_INVALID_FIELD_IN_PARAMETER_LIST 0x00 +#define ASCQ_MEDIUM_REMOVAL_PREVENTED 0x02 +#define ASCQ_NOT_READY_TO_READY_TRANSIT_MDI_CHNG 0x00 +#define ASCQ_POWER_ON_OR_BUS_DEVICE_RESET 0x00 +#define ASCQ_WRITE_PROTECTED_MEDIA 0x00 +#define ASCQ_OVERLAPPED_COMMAND_ATTEMPTED 0x00 +#define USB_LITTLE_ENDIAN +#ifdef USB_LITTLE_ENDIAN +#define CBW_SIGNATURE 0x43425355L +#define CSW_SIGNATURE 0x53425355L +#define CBW_TAG 0x34675326L +#elif defined(USB_BIG_ENDIAN) +#define CBW_SIGNATURE 0x55534243L +#define CSW_SIGNATURE 0x55534253L +#define CBW_TAG 0x26536734L +#else +#error not define endian +#endif + +struct usb_scsi_cbw { + u32 dCBWSignature; //[3:0] + u32 dCBWTag; //[7:4] + u32 dCBWDataTransferLength; //[11:8] + u8 bmCBWFlags; //[12] + u8 bCBWLUN; //[13] lun=[3:0] res=[7:4] + u8 bCBWLength; //[14] len=[4:0] res=[7:5] + u8 operationCode; + u8 lun; //> 8) |(((u16)(X) & 0x00ff) << 8)) + +#define ___ntohs(X) ((((u32)(X) & 0xff000000) >> 24) | \ + (((u32)(X) & 0x00ff0000) >> 8) | \ + (((u32)(X) & 0x0000ff00) << 8) | \ + (((u32)(X) & 0x000000ff) << 24)) + +#if defined(cpu_to_be16) || defined(cpu_to_be32) || defined(be16_to_cpu) || defined(be32_to_cpu) +#error #define cpu_to_be16 +#endif + +#define cpu_to_be16(v16) ___ntohl(v16) +#define cpu_to_be32(v32) ___ntohs(v32) + +#define be16_to_cpu(v16) cpu_to_be16(v16) +#define be32_to_cpu(v32) cpu_to_be32(v32) +#define __le16_to_cpu(v16) (v16) +#define __le32_to_cpu(v32) (v32) + +#if defined(cpu_to_le16) || defined(cpu_to_le32) || defined(le16_to_cpu) || defined(le32_to_cpu) +#error #define cpu_to_be16 +#endif + +#define cpu_to_le16(v16) (v16) +#define cpu_to_le32(v32) (v32) + +#define le16_to_cpu(v16) cpu_to_le16(v16) +#define le32_to_cpu(v32) cpu_to_le32(v32) + +#define LOWORD(l) ((u16)(l)) +#define HIWORD(l) ((u16)(((u32)(l) >> 16) & 0xFFFF)) + +#define LOBYTE(w) ((u8)(w)) +#define HIBYTE(w) ((u8)(((u16)(w) >> 8) & 0xFF)) + +#define DW1BYTE(dw) (LOBYTE(LOWORD(dw))) +#define DW2BYTE(dw) (HIBYTE(LOWORD(dw))) +#define DW3BYTE(dw) (LOBYTE(HIWORD(dw))) +#define DW4BYTE(dw) (HIBYTE(HIWORD(dw))) + +//............. Full Speed USB ................... +#define MUSB_FADDR 0x00 +#define MUSB_POWER 0x01 +#define MUSB_INTRTX1 0x02 +#define MUSB_INTRTX2 0x03 +#define MUSB_INTRRX1 0x04 +#define MUSB_INTRRX2 0x05 +#define MUSB_INTRUSB 0x06 +#define MUSB_INTRTX1E 0x07 +#define MUSB_INTRTX2E 0x08 +#define MUSB_INTRRX1E 0x09 +#define MUSB_INTRRX2E 0x0a +#define MUSB_INTRUSBE 0x0b +#define MUSB_FRAME1 0x0c +#define MUSB_FRAME2 0x0d +#define MUSB_INDEX 0x0e +#define MUSB_DEVCTL 0x0f +#define MUSB_TXMAXP 0x10 +#define MUSB_CSR0 0x11 +#define MUSB_TXCSR1 0x11 +#define MUSB_TXCSR2 0x12 +#define MUSB_RXMAXP 0x13 +#define MUSB_RXCSR1 0x14 +#define MUSB_RXCSR2 0x15 +#define MUSB_COUNT0 0x16 +#define MUSB_RXCOUNT1 0x16 +#define MUSB_RXCOUNT2 0x17 +#define MUSB_TXTYPE 0x18 +#define MUSB_TXINTERVAL 0x19 +#define MUSB_RXTYPE 0x1a +#define MUSB_RXINTERVAL 0x1b + +/*****MUSB SFR BitMap******/ +/*INTRUSB mode*/ +#define INTRUSB_SUSPEND BIT(0) +#define INTRUSB_RESUME BIT(1) +#define INTRUSB_RESET_BABBLE BIT(2) +#define INTRUSB_SOF BIT(3) +#define INTRUSB_CONNECT BIT(4) +#define INTRUSB_DISCONNECT BIT(5) +#define INTRUSB_SESS_REQ BIT(6) +#define INTRUSB_VBUS_ERROR BIT(7) + +/*CSR0 peripheral mode*/ +#define CSR0P_RxPktRdy 0x01 +#define CSR0P_TxPktRdy 0x02 +#define CSR0P_SentStall 0x04 +#define CSR0P_DataEnd 0x08 +#define CSR0P_SetupEnd 0x10 +#define CSR0P_SendStall 0x20 +#define CSR0P_ClrRxPktRdy 0x40 +#define CSR0P_ClrSetupEnd 0x80 + + +/*TXCSR1 peripheral mode*/ +#define TXCSRP_TxPktRdy 0x01 +#define TXCSRP_FIFONotEmpty 0x02 +#define TXCSRP_UnderRun 0x04 +#define TXCSRP_FlushFIFO 0x08 +#define TXCSRP_SendStall 0x10 +#define TXCSRP_SentStall 0x20 +#define TXCSRP_ClrDataTog 0x40 +#define TXCSRP_DIR (BIT(13)) +#define TXCSRP_ISOCHRONOUS (BIT(14)) + +/*RXCSR1 peripheral mode*/ +#define RXCSRP_RxPktRdy 0x01 +#define RXCSRP_FIFOFull 0x02 +#define RXCSRP_OverRun 0x04 +#define RXCSRP_DataError 0x08 +#define RXCSRP_FlushFIFO 0x10 +#define RXCSRP_SendStall 0x20 +#define RXCSRP_SentStall 0x40 +#define RXCSRP_ClrDataTog 0x80 +#define RXCSRP_IncompRx (BIT(8)) +#define RXCSRP_ISOCHRONOUS (BIT(14)) + +/*CSR0 host mode*/ +#define CSR0H_RxPktRdy 0x01 +#define CSR0H_TxPktRdy 0x02 +#define CSR0H_RxStall 0x04 +#define CSR0H_SetupPkt 0x08 +#define CSR0H_Error 0x10 +#define CSR0H_ReqPkt 0x20 +#define CSR0H_StatusPkt 0x40 +#define CSR0H_DISPING (BIT(11)) + +/*TXCSR1 host mode*/ +#define TXCSRH_TxPktRdy 0x01 +#define TXCSRH_FIFONotEmpty 0x02 +#define TXCSRH_Error 0x04 +#define TXCSRH_FlushFIFO 0x08 +#define TXCSRH_RxStall 0x20 +#define TXCSRH_ClrDataTog 0x40 +#define TXCSRH_NAK 0x80 + +/*RXCSR1 host mode*/ +#define RXCSRH_RxPktRdy 0x01 +#define RXCSRH_FIFOFull 0x02 +#define RXCSRH_Error 0x04 +#define RXCSRH_DataError 0x08 +#define RXCSRH_FlushFIFO 0x10 +#define RXCSRH_ReqPkt 0x20 +#define RXCSRH_RxStall 0x40 +#define RXCSRH_ClrDataTog 0x80 +#define RXCSRH_IncompRx BIT(8) +#define RXCSRH_PIDError BIT(12) + + +///USB Slave 控制传输各阶段 +#define USB_EP0_STAGE_SETUP 0 +#define USB_EP0_STAGE_IN 1 +#define USB_EP0_STAGE_OUT 2 +#define USB_EP0_SET_STALL 3 +#define USB_EP0_IGNORE 4 + +/* common api */ +u32 get_jiffies(); +u32 usb_host_timeout(u32 ot); +u16 usb_read_sofframe(const usb_dev id); + +/* slave api */ +u32 usb_g_bulk_read64byte_fast(const usb_dev usb_id, u32 ep, u8 *ptr, u32 len); +u32 usb_g_bulk_read(const usb_dev usb_id, u32 ep, u8 *ptr, u32 len, u32 block); +u32 usb_g_bulk_write(const usb_dev usb_id, u32 ep, const u8 *ptr, u32 len); +u32 usb_g_intr_read(const usb_dev usb_id, u32 ep, u8 *ptr, u32 len, u32 block); +u32 usb_g_intr_write(const usb_dev usb_id, u32 ep, const u8 *ptr, u32 len); +u32 usb_g_iso_read(const usb_dev usb_id, u32 ep, u8 *ptr, u32 len, u32 block); +u32 usb_g_iso_write(const usb_dev usb_id, u32 ep, const u8 *ptr, u32 len); +void usb_slave_init(const usb_dev usb_id); + +/* host api */ + +u32 usb_h_bulk_read(const usb_dev usb_id, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *ptr, u32 len); +u32 usb_h_bulk_write(const usb_dev usb_id, u8 host_ep, u16 txmaxp, u8 target_ep, u8 *ptr, u32 len); +u32 usb_h_intr_read(const usb_dev usb_id, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *ptr, u32 len); +u32 usb_h_intr_write(const usb_dev usb_id, u8 host_ep, u16 txmaxp, u8 target_ep, u8 *ptr, u32 len); +u32 usb_h_iso_read(const usb_dev usb_id, u8 host_ep, u16 rxmaxp, u8 target_ep, u8 *ptr, u32 len); +u32 usb_h_iso_write(const usb_dev usb_id, u8 host_ep, u16 txmaxp, u8 target_ep, u8 *ptr, u32 len); +void usb_h_entry_suspend(const usb_dev usb_id); +void usb_h_resume(const usb_dev usb_id); +u32 usb_host_init(const usb_dev usb_id, u32 reset_delay, u32 timeout); +u32 usb_host_reset(const usb_dev usb_id, u32 reset_delay, u32 timeout); +u32 usb_h_force_reset(const usb_dev usb_id); +// u32 usb_h_sie_init(u32 reset_delay, u32 timeout); +// void usb_h_sie_close(); + +#endif /*USB_PHY_H*/ diff --git a/include_lib/driver/device/wireless_charge.h b/include_lib/driver/device/wireless_charge.h new file mode 100644 index 0000000..10d8e65 --- /dev/null +++ b/include_lib/driver/device/wireless_charge.h @@ -0,0 +1,53 @@ +#ifndef __WIRELESS_H__ +#define __WIRELESS_H__ + +#include "asm/includes.h" + +enum { + IO_LOW, //低 + IO_HIGH, //高 + IO_OVERTURN, //翻转 + IO_OPEN, //打开 + IO_DIR_IN,//高阻 + IO_INIT, //初始化 +}; + +struct _wireless_info { + volatile u8 busy: 1; + volatile u8 open: 1; + volatile u8 flag: 1; + volatile u8 dcdc_en: 1; + volatile u8 bit_totle: 4; + volatile u8 bit_num: 4; + volatile u8 byte_num: 4; + volatile u8 data_number: 4; + volatile u8 error_count: 4; + volatile u8 bit_count; + volatile u8 nex_packet; + }; + + typedef struct _wireless_hdl_ { + u16(*get_wl_power)(void); + void (*dcdc_en_set)(u8 en); + void (*wpc_set)(u8 en); + u16 *send_buff; + u16 voltage_max; + u16 voltage_min; + u8 err_packet_fast_cnt; + struct _wireless_info info; +} _wireless_hdl; + + +//库C函数声明 +void wireless_250us_run(void); +void wireless_open(u16 min, u16 max); +void wireless_close(void); +void get_signal_value(void); +void get_configuration(void); +void get_identification(void); +void wireless_100ms_run(void); +void wireless_lib_init(_wireless_hdl *wldata, u16 min, u16 max); + + +#endif/*__WIRELESS_H__*/ + diff --git a/include_lib/liba/br23/DynamicEQ.a b/include_lib/liba/br23/DynamicEQ.a new file mode 100644 index 0000000..8cdc94e Binary files /dev/null and b/include_lib/liba/br23/DynamicEQ.a differ diff --git a/include_lib/liba/br23/SpectrumShow.a b/include_lib/liba/br23/SpectrumShow.a new file mode 100644 index 0000000..f3bb24f Binary files /dev/null and b/include_lib/liba/br23/SpectrumShow.a differ diff --git a/include_lib/liba/br23/VirtualBass.a b/include_lib/liba/br23/VirtualBass.a new file mode 100644 index 0000000..f1000f7 Binary files /dev/null and b/include_lib/liba/br23/VirtualBass.a differ diff --git a/include_lib/liba/br23/aec.a b/include_lib/liba/br23/aec.a new file mode 100644 index 0000000..478de8a Binary files /dev/null and b/include_lib/liba/br23/aec.a differ diff --git a/include_lib/liba/br23/agreement.a b/include_lib/liba/br23/agreement.a new file mode 100644 index 0000000..b268a88 Binary files /dev/null and b/include_lib/liba/br23/agreement.a differ diff --git a/include_lib/liba/br23/amr_dec_lib.a b/include_lib/liba/br23/amr_dec_lib.a new file mode 100644 index 0000000..0dc423f Binary files /dev/null and b/include_lib/liba/br23/amr_dec_lib.a differ diff --git a/include_lib/liba/br23/ape_dec_lib.a b/include_lib/liba/br23/ape_dec_lib.a new file mode 100644 index 0000000..d4fa891 Binary files /dev/null and b/include_lib/liba/br23/ape_dec_lib.a differ diff --git a/include_lib/liba/br23/bfilterfun_lib.a b/include_lib/liba/br23/bfilterfun_lib.a new file mode 100644 index 0000000..2d03470 Binary files /dev/null and b/include_lib/liba/br23/bfilterfun_lib.a differ diff --git a/include_lib/liba/br23/bt_hash_enc.a b/include_lib/liba/br23/bt_hash_enc.a new file mode 100644 index 0000000..ca8700e Binary files /dev/null and b/include_lib/liba/br23/bt_hash_enc.a differ diff --git a/include_lib/liba/br23/btctrler.a b/include_lib/liba/br23/btctrler.a new file mode 100644 index 0000000..c3bdd9f Binary files /dev/null and b/include_lib/liba/br23/btctrler.a differ diff --git a/include_lib/liba/br23/btstack.a b/include_lib/liba/br23/btstack.a new file mode 100644 index 0000000..aa11a3b Binary files /dev/null and b/include_lib/liba/br23/btstack.a differ diff --git a/include_lib/liba/br23/coeff_calculate.a b/include_lib/liba/br23/coeff_calculate.a new file mode 100644 index 0000000..941165c Binary files /dev/null and b/include_lib/liba/br23/coeff_calculate.a differ diff --git a/include_lib/liba/br23/compressor.a b/include_lib/liba/br23/compressor.a new file mode 100644 index 0000000..039b42f Binary files /dev/null and b/include_lib/liba/br23/compressor.a differ diff --git a/include_lib/liba/br23/cpu.a b/include_lib/liba/br23/cpu.a new file mode 100644 index 0000000..0d07117 Binary files /dev/null and b/include_lib/liba/br23/cpu.a differ diff --git a/include_lib/liba/br23/crossover_coff.a b/include_lib/liba/br23/crossover_coff.a new file mode 100644 index 0000000..a76ee83 Binary files /dev/null and b/include_lib/liba/br23/crossover_coff.a differ diff --git a/include_lib/liba/br23/crypto_toolbox_Ospeed.a b/include_lib/liba/br23/crypto_toolbox_Ospeed.a new file mode 100644 index 0000000..fc077c0 Binary files /dev/null and b/include_lib/liba/br23/crypto_toolbox_Ospeed.a differ diff --git a/include_lib/liba/br23/drc.a b/include_lib/liba/br23/drc.a new file mode 100644 index 0000000..44a0e8c Binary files /dev/null and b/include_lib/liba/br23/drc.a differ diff --git a/include_lib/liba/br23/dts_dec_lib.a b/include_lib/liba/br23/dts_dec_lib.a new file mode 100644 index 0000000..e158317 Binary files /dev/null and b/include_lib/liba/br23/dts_dec_lib.a differ diff --git a/include_lib/liba/br23/dueros_stack.a b/include_lib/liba/br23/dueros_stack.a new file mode 100644 index 0000000..920a1fe Binary files /dev/null and b/include_lib/liba/br23/dueros_stack.a differ diff --git a/include_lib/liba/br23/filtparam_cal_lib.a b/include_lib/liba/br23/filtparam_cal_lib.a new file mode 100644 index 0000000..acae7c5 Binary files /dev/null and b/include_lib/liba/br23/filtparam_cal_lib.a differ diff --git a/include_lib/liba/br23/flac_dec_lib.a b/include_lib/liba/br23/flac_dec_lib.a new file mode 100644 index 0000000..d636586 Binary files /dev/null and b/include_lib/liba/br23/flac_dec_lib.a differ diff --git a/include_lib/liba/br23/font.a b/include_lib/liba/br23/font.a new file mode 100644 index 0000000..a6a25e5 Binary files /dev/null and b/include_lib/liba/br23/font.a differ diff --git a/include_lib/liba/br23/gma_stack.a b/include_lib/liba/br23/gma_stack.a new file mode 100644 index 0000000..de8f2af Binary files /dev/null and b/include_lib/liba/br23/gma_stack.a differ diff --git a/include_lib/liba/br23/howling.a b/include_lib/liba/br23/howling.a new file mode 100644 index 0000000..a047b59 Binary files /dev/null and b/include_lib/liba/br23/howling.a differ diff --git a/include_lib/liba/br23/libAptFilt_pi32v2_OnChip.a b/include_lib/liba/br23/libAptFilt_pi32v2_OnChip.a new file mode 100644 index 0000000..bcfcba6 Binary files /dev/null and b/include_lib/liba/br23/libAptFilt_pi32v2_OnChip.a differ diff --git a/include_lib/liba/br23/libDelayEstimate_pi32v2_OnChip.a b/include_lib/liba/br23/libDelayEstimate_pi32v2_OnChip.a new file mode 100644 index 0000000..030d355 Binary files /dev/null and b/include_lib/liba/br23/libDelayEstimate_pi32v2_OnChip.a differ diff --git a/include_lib/liba/br23/libEchoSuppress_pi32v2_OnChip.a b/include_lib/liba/br23/libEchoSuppress_pi32v2_OnChip.a new file mode 100644 index 0000000..f6df827 Binary files /dev/null and b/include_lib/liba/br23/libEchoSuppress_pi32v2_OnChip.a differ diff --git a/include_lib/liba/br23/libFFT_pi32v2_OnChip.a b/include_lib/liba/br23/libFFT_pi32v2_OnChip.a new file mode 100644 index 0000000..9610ba3 Binary files /dev/null and b/include_lib/liba/br23/libFFT_pi32v2_OnChip.a differ diff --git a/include_lib/liba/br23/libNoiseSuppress_pi32v2_OnChip.a b/include_lib/liba/br23/libNoiseSuppress_pi32v2_OnChip.a new file mode 100644 index 0000000..34b1f5c Binary files /dev/null and b/include_lib/liba/br23/libNoiseSuppress_pi32v2_OnChip.a differ diff --git a/include_lib/liba/br23/libOpcore_maskrom_pi32v2_OnChip.a b/include_lib/liba/br23/libOpcore_maskrom_pi32v2_OnChip.a new file mode 100644 index 0000000..1ae0e4b Binary files /dev/null and b/include_lib/liba/br23/libOpcore_maskrom_pi32v2_OnChip.a differ diff --git a/include_lib/liba/br23/libSMS_TDE_pi32v2_OnChip.a b/include_lib/liba/br23/libSMS_TDE_pi32v2_OnChip.a new file mode 100644 index 0000000..a3553b7 Binary files /dev/null and b/include_lib/liba/br23/libSMS_TDE_pi32v2_OnChip.a differ diff --git a/include_lib/liba/br23/libSingleMicSystem_pi32v2_OnChip.a b/include_lib/liba/br23/libSingleMicSystem_pi32v2_OnChip.a new file mode 100644 index 0000000..28c490b Binary files /dev/null and b/include_lib/liba/br23/libSingleMicSystem_pi32v2_OnChip.a differ diff --git a/include_lib/liba/br23/libSplittingFilter_pi32v2_OnChip.a b/include_lib/liba/br23/libSplittingFilter_pi32v2_OnChip.a new file mode 100644 index 0000000..7577a90 Binary files /dev/null and b/include_lib/liba/br23/libSplittingFilter_pi32v2_OnChip.a differ diff --git a/include_lib/liba/br23/lib_adpcm_code.a b/include_lib/liba/br23/lib_adpcm_code.a new file mode 100644 index 0000000..b8d7b06 Binary files /dev/null and b/include_lib/liba/br23/lib_adpcm_code.a differ diff --git a/include_lib/liba/br23/lib_adpcm_ima_code.a b/include_lib/liba/br23/lib_adpcm_ima_code.a new file mode 100644 index 0000000..7dd5ff3 Binary files /dev/null and b/include_lib/liba/br23/lib_adpcm_ima_code.a differ diff --git a/include_lib/liba/br23/lib_dns.a b/include_lib/liba/br23/lib_dns.a new file mode 100644 index 0000000..5f1a819 Binary files /dev/null and b/include_lib/liba/br23/lib_dns.a differ diff --git a/include_lib/liba/br23/lib_esco_repair.a b/include_lib/liba/br23/lib_esco_repair.a new file mode 100644 index 0000000..20ddaa9 Binary files /dev/null and b/include_lib/liba/br23/lib_esco_repair.a differ diff --git a/include_lib/liba/br23/lib_g726_code.a b/include_lib/liba/br23/lib_g726_code.a new file mode 100644 index 0000000..7691ff4 Binary files /dev/null and b/include_lib/liba/br23/lib_g726_code.a differ diff --git a/include_lib/liba/br23/lib_g726_decode.a b/include_lib/liba/br23/lib_g726_decode.a new file mode 100644 index 0000000..5b1050e Binary files /dev/null and b/include_lib/liba/br23/lib_g726_decode.a differ diff --git a/include_lib/liba/br23/lib_howlings_phf.a b/include_lib/liba/br23/lib_howlings_phf.a new file mode 100644 index 0000000..dc73b65 Binary files /dev/null and b/include_lib/liba/br23/lib_howlings_phf.a differ diff --git a/include_lib/liba/br23/lib_midi_dec.a b/include_lib/liba/br23/lib_midi_dec.a new file mode 100644 index 0000000..670d1a4 Binary files /dev/null and b/include_lib/liba/br23/lib_midi_dec.a differ diff --git a/include_lib/liba/br23/lib_mp2_code.a b/include_lib/liba/br23/lib_mp2_code.a new file mode 100644 index 0000000..d7e8a47 Binary files /dev/null and b/include_lib/liba/br23/lib_mp2_code.a differ diff --git a/include_lib/liba/br23/lib_pitch_speed.a b/include_lib/liba/br23/lib_pitch_speed.a new file mode 100644 index 0000000..e70607a Binary files /dev/null and b/include_lib/liba/br23/lib_pitch_speed.a differ diff --git a/include_lib/liba/br23/lib_resample_cal.a b/include_lib/liba/br23/lib_resample_cal.a new file mode 100644 index 0000000..6b84a71 Binary files /dev/null and b/include_lib/liba/br23/lib_resample_cal.a differ diff --git a/include_lib/liba/br23/lib_resample_fast_cal.a b/include_lib/liba/br23/lib_resample_fast_cal.a new file mode 100644 index 0000000..b92e755 Binary files /dev/null and b/include_lib/liba/br23/lib_resample_fast_cal.a differ diff --git a/include_lib/liba/br23/lib_reverb_cal.a b/include_lib/liba/br23/lib_reverb_cal.a new file mode 100644 index 0000000..331c70e Binary files /dev/null and b/include_lib/liba/br23/lib_reverb_cal.a differ diff --git a/include_lib/liba/br23/lib_rmono2stereo.a b/include_lib/liba/br23/lib_rmono2stereo.a new file mode 100644 index 0000000..9fd84dd Binary files /dev/null and b/include_lib/liba/br23/lib_rmono2stereo.a differ diff --git a/include_lib/liba/br23/lib_sur_cal.a b/include_lib/liba/br23/lib_sur_cal.a new file mode 100644 index 0000000..cbd1f00 Binary files /dev/null and b/include_lib/liba/br23/lib_sur_cal.a differ diff --git a/include_lib/liba/br23/lib_usbaudio_plc.a b/include_lib/liba/br23/lib_usbaudio_plc.a new file mode 100644 index 0000000..2d75cc1 Binary files /dev/null and b/include_lib/liba/br23/lib_usbaudio_plc.a differ diff --git a/include_lib/liba/br23/lib_voiceChager.a b/include_lib/liba/br23/lib_voiceChager.a new file mode 100644 index 0000000..c826406 Binary files /dev/null and b/include_lib/liba/br23/lib_voiceChager.a differ diff --git a/include_lib/liba/br23/lib_word_ana.a b/include_lib/liba/br23/lib_word_ana.a new file mode 100644 index 0000000..edb2a76 Binary files /dev/null and b/include_lib/liba/br23/lib_word_ana.a differ diff --git a/include_lib/liba/br23/limiter.a b/include_lib/liba/br23/limiter.a new file mode 100644 index 0000000..00a15c2 Binary files /dev/null and b/include_lib/liba/br23/limiter.a differ diff --git a/include_lib/liba/br23/limiter_noiseGate.a b/include_lib/liba/br23/limiter_noiseGate.a new file mode 100644 index 0000000..db8b96b Binary files /dev/null and b/include_lib/liba/br23/limiter_noiseGate.a differ diff --git a/include_lib/liba/br23/loudness.a b/include_lib/liba/br23/loudness.a new file mode 100644 index 0000000..1951f6d Binary files /dev/null and b/include_lib/liba/br23/loudness.a differ diff --git a/include_lib/liba/br23/m4a_tws_lib.a b/include_lib/liba/br23/m4a_tws_lib.a new file mode 100644 index 0000000..d072178 Binary files /dev/null and b/include_lib/liba/br23/m4a_tws_lib.a differ diff --git a/include_lib/liba/br23/math.a b/include_lib/liba/br23/math.a new file mode 100644 index 0000000..ea91e89 Binary files /dev/null and b/include_lib/liba/br23/math.a differ diff --git a/include_lib/liba/br23/media.a b/include_lib/liba/br23/media.a new file mode 100644 index 0000000..f2dc81a Binary files /dev/null and b/include_lib/liba/br23/media.a differ diff --git a/include_lib/liba/br23/media_app.a b/include_lib/liba/br23/media_app.a new file mode 100644 index 0000000..b3d0684 Binary files /dev/null and b/include_lib/liba/br23/media_app.a differ diff --git a/include_lib/liba/br23/mp3_dec_lib.a b/include_lib/liba/br23/mp3_dec_lib.a new file mode 100644 index 0000000..281a4d8 Binary files /dev/null and b/include_lib/liba/br23/mp3_dec_lib.a differ diff --git a/include_lib/liba/br23/mp3_decstream_lib.a b/include_lib/liba/br23/mp3_decstream_lib.a new file mode 100644 index 0000000..bd8c6e9 Binary files /dev/null and b/include_lib/liba/br23/mp3_decstream_lib.a differ diff --git a/include_lib/liba/br23/mp3_enc_lib.a b/include_lib/liba/br23/mp3_enc_lib.a new file mode 100644 index 0000000..551be48 Binary files /dev/null and b/include_lib/liba/br23/mp3_enc_lib.a differ diff --git a/include_lib/liba/br23/mp3tsy_dec_lib.a b/include_lib/liba/br23/mp3tsy_dec_lib.a new file mode 100644 index 0000000..4112a37 Binary files /dev/null and b/include_lib/liba/br23/mp3tsy_dec_lib.a differ diff --git a/include_lib/liba/br23/noisegate.a b/include_lib/liba/br23/noisegate.a new file mode 100644 index 0000000..b949cf5 Binary files /dev/null and b/include_lib/liba/br23/noisegate.a differ diff --git a/include_lib/liba/br23/opus_enc_lib.a b/include_lib/liba/br23/opus_enc_lib.a new file mode 100644 index 0000000..323a81b Binary files /dev/null and b/include_lib/liba/br23/opus_enc_lib.a differ diff --git a/include_lib/liba/br23/pemafrow.a b/include_lib/liba/br23/pemafrow.a new file mode 100644 index 0000000..db92240 Binary files /dev/null and b/include_lib/liba/br23/pemafrow.a differ diff --git a/include_lib/liba/br23/rcsp_stack.a b/include_lib/liba/br23/rcsp_stack.a new file mode 100644 index 0000000..4350a82 Binary files /dev/null and b/include_lib/liba/br23/rcsp_stack.a differ diff --git a/include_lib/liba/br23/res.a b/include_lib/liba/br23/res.a new file mode 100644 index 0000000..d61e9ee Binary files /dev/null and b/include_lib/liba/br23/res.a differ diff --git a/include_lib/liba/br23/rms.a b/include_lib/liba/br23/rms.a new file mode 100644 index 0000000..5fac503 Binary files /dev/null and b/include_lib/liba/br23/rms.a differ diff --git a/include_lib/liba/br23/sbc_eng_lib.a b/include_lib/liba/br23/sbc_eng_lib.a new file mode 100644 index 0000000..5f83efe Binary files /dev/null and b/include_lib/liba/br23/sbc_eng_lib.a differ diff --git a/include_lib/liba/br23/shiftPhase.a b/include_lib/liba/br23/shiftPhase.a new file mode 100644 index 0000000..9d3842d Binary files /dev/null and b/include_lib/liba/br23/shiftPhase.a differ diff --git a/include_lib/liba/br23/speex_enc_lib.a b/include_lib/liba/br23/speex_enc_lib.a new file mode 100644 index 0000000..22810cc Binary files /dev/null and b/include_lib/liba/br23/speex_enc_lib.a differ diff --git a/include_lib/liba/br23/system.a b/include_lib/liba/br23/system.a new file mode 100644 index 0000000..53e763f Binary files /dev/null and b/include_lib/liba/br23/system.a differ diff --git a/include_lib/liba/br23/tme_stack.a b/include_lib/liba/br23/tme_stack.a new file mode 100644 index 0000000..72cd7b7 Binary files /dev/null and b/include_lib/liba/br23/tme_stack.a differ diff --git a/include_lib/liba/br23/ui_dot.a b/include_lib/liba/br23/ui_dot.a new file mode 100644 index 0000000..79c6cac Binary files /dev/null and b/include_lib/liba/br23/ui_dot.a differ diff --git a/include_lib/liba/br23/ui_s.a b/include_lib/liba/br23/ui_s.a new file mode 100644 index 0000000..57f7a36 Binary files /dev/null and b/include_lib/liba/br23/ui_s.a differ diff --git a/include_lib/liba/br23/update.a b/include_lib/liba/br23/update.a new file mode 100644 index 0000000..dc65f2f Binary files /dev/null and b/include_lib/liba/br23/update.a differ diff --git a/include_lib/liba/br23/wav_dec_lib.a b/include_lib/liba/br23/wav_dec_lib.a new file mode 100644 index 0000000..0b029d5 Binary files /dev/null and b/include_lib/liba/br23/wav_dec_lib.a differ diff --git a/include_lib/liba/br23/wma_dec_lib.a b/include_lib/liba/br23/wma_dec_lib.a new file mode 100644 index 0000000..38f5c71 Binary files /dev/null and b/include_lib/liba/br23/wma_dec_lib.a differ diff --git a/include_lib/liba/br23/wma_decstream_lib.a b/include_lib/liba/br23/wma_decstream_lib.a new file mode 100644 index 0000000..9befc6e Binary files /dev/null and b/include_lib/liba/br23/wma_decstream_lib.a differ diff --git a/include_lib/liba/br23/wtg_dec_lib.a b/include_lib/liba/br23/wtg_dec_lib.a new file mode 100644 index 0000000..b442e84 Binary files /dev/null and b/include_lib/liba/br23/wtg_dec_lib.a differ diff --git a/include_lib/liba/br23/wtgv2_dec_lib.a b/include_lib/liba/br23/wtgv2_dec_lib.a new file mode 100644 index 0000000..7d5138d Binary files /dev/null and b/include_lib/liba/br23/wtgv2_dec_lib.a differ diff --git a/include_lib/media/DynamicEQ_Detection_api.h b/include_lib/media/DynamicEQ_Detection_api.h new file mode 100644 index 0000000..435a9cb --- /dev/null +++ b/include_lib/media/DynamicEQ_Detection_api.h @@ -0,0 +1,32 @@ +#ifndef DYNAMICEQDETECTION_API_H +#define DYNAMICEQDETECTION_API_H + +#ifdef WIN32 + +#define AT_DYNAMICEQ_DETECT(x) +#define AT_DYNAMICEQ_DETECT_CODE +#define AT_DYNAMICEQ_DETECT_CONST +#define AT_DYNAMICEQ_DETECT_SPARSE_CODE +#define AT_DYNAMICEQ_DETECT_SPARSE_CONST + +#else + +#define AT_DYNAMICEQ_DETECT(x) __attribute((section(#x))) +#define AT_DYNAMICEQ_DETECT_CODE AT_DYNAMICEQ_DETECT(.dynamic_eq_detect_code) +#define AT_DYNAMICEQ_DETECT_CONST AT_DYNAMICEQ_DETECT(.dynamic_eq_detect_const) +#define AT_DYNAMICEQ_DETECT_SPARSE_CODE AT_DYNAMICEQ_DETECT(.dynamic_eq_detect_sparse_code) +#define AT_DYNAMICEQ_DETECT_SPARSE_CONST AT_DYNAMICEQ_DETECT(.dynamic_eq_detect_sparse_const) + +#endif +typedef struct _DynamicEQDetectionParam { + int fc; //中心频率 与动态eq参数中的fc一致 +} DynamicEQDetectionParam; //检测参数 + +int getDynamicEQDetectionBuf(int nSection, int channel); +int *getDynamicEQDetectionCoeff(void *WorkBuf); +void DynamicEQDetectionInit(void *WorkBuf, DynamicEQDetectionParam *pram, int nSection, int channel, int SampleRate); +void DynamicEQDetectionUpdate(void *WorkBuf, DynamicEQDetectionParam *pram); +int DynamicEQDetectionRun(void *WorkBuf, short *indata, int *outdata, int per_channel_npoint); + +#endif // !DYNAMICEQDETECTION_API_H + diff --git a/include_lib/media/DynamicEQ_api.h b/include_lib/media/DynamicEQ_api.h new file mode 100644 index 0000000..27556a3 --- /dev/null +++ b/include_lib/media/DynamicEQ_api.h @@ -0,0 +1,78 @@ +#ifndef DYNAMICEQ_API_H +#define DYNAMICEQ_API_H + +#include "asm/hw_eq.h" +#ifdef WIN32 + +#define AT_DYNAMICEQ(x) +#define AT_DYNAMICEQ_CODE +#define AT_DYNAMICEQ_CONST +#define AT_DYNAMICEQ_SPARSE_CODE +#define AT_DYNAMICEQ_SPARSE_CONST + +#else + +#define AT_DYNAMICEQ(x) __attribute((section(#x))) +#define AT_DYNAMICEQ_CODE AT_DYNAMICEQ(.dynamic_eq_code) +#define AT_DYNAMICEQ_CONST AT_DYNAMICEQ(.dynamic_eq_const) +#define AT_DYNAMICEQ_SPARSE_CODE AT_DYNAMICEQ(.dynamic_eq_sparse_code) +#define AT_DYNAMICEQ_SPARSE_CONST AT_DYNAMICEQ(.dynamic_eq_sparse_const) + +#endif +typedef enum { + DYNAMIC_EQ_IIR_TYPE_BAND_PASS = EQ_IIR_TYPE_BAND_PASS, + //DYNAMIC_EQ_IIR_TYPE_HIGH_SHELF, +// DYNAMIC_EQ_IIR_TYPE_LOW_SHELF +} DYNAMIC_EQ_IIR_TYPE; + + + +/* enum { */ +// PEAK = 0, +// RMS +// }; + +// enum { +// PERPOINT = 0, +// TWOPOINT +// }; + +enum { + SHORT = 0, + INT +}; + +typedef struct _DynamicEQEffectParam { + int fc; //中心频率 + float Q; // Q值 + float gain; //衰减最大增益或者增强最大增益,当gain < 0时衰减模式,当gain > 0时增强模式 + int type; //类型 只支持EQ_IIR_TYPE_BAND_PASS + int attackTime; //启动时间 + int releaseTime; //释放时间 + int rmsTime; // rmsTime algorithm为RMS时有效 + float threshold; // 启动阈值 衰减模式为大于阈值启动 增强模式小于阈值启动 + float ratio; // 比率 衰减模式ratio > 1[1,30] 增强模式 ratio < 1 [0.1,1] + float noisegate_threshold; //噪声门限阈值,低于噪声门限阈值不启动 + float fixGain; // 在中心频率fc处的固定增益 + unsigned char algorithm; //算法 PEAK或者RMS + +} DynamicEQEffectParam; + +typedef struct _DynamicEQParam { + int nSection; //段数 + int channel; //通道 + int SampleRate; //采样率 + int detect_mode; //检测模式 PERPOINT或者TWOPOINT 对应工具的Precision+与Precision + int DetectdataInc; //检测数据相同通道下一点的步进 例如左右左右 为2 + int IndataInc; //输入数据相同通道下一点的步进 + int OutdataInc; // 输出数据相同通道下一点的步进 +} DynamicEQParam; + + +int getDynamicEQBuf(DynamicEQEffectParam *effectParam, DynamicEQParam *param); //bufsize 与nSection rmsTime algorithm channel SampleRate 有关 +void DynamicEQInit(void *WorkBuf, DynamicEQEffectParam *effectParam, DynamicEQParam *param); +void DynamicEQUpdate(void *WorkBuf, DynamicEQEffectParam *effectParam, DynamicEQParam *param); +int DynamicEQRun(void *WorkBuf, int *detectdata, int *indata, int *outdata, int per_channel_npoint); + +#endif // !DYNAMICEQ_API_H + diff --git a/include_lib/media/VirtualBass_api.h b/include_lib/media/VirtualBass_api.h new file mode 100644 index 0000000..490e6f4 --- /dev/null +++ b/include_lib/media/VirtualBass_api.h @@ -0,0 +1,36 @@ +#ifndef VIRTUALBASS_API_H +#define VIRTUALBASS_API_H + + +#ifdef WIN32 + +#define AT_VBSS(x) +#define AT_VBSS_CODE +#define AT_VBSS_CONST +#define AT_VBSS_SPARSE_CODE +#define AT_VBSS_SPARSE_CONST + +#else +#define AT_VBSS(x) __attribute((section(#x))) +#define AT_VBSS_CODE AT_VBSS(.vbss_code) +#define AT_VBSS_CONST AT_VBSS(.vbss_const) +#define AT_VBSS_SPARSE_CODE AT_VBSS(.vbss_sparse_code) +#define AT_VBSS_SPARSE_CONST AT_VBSS(.vbss_sparse_const) +#endif + + +typedef struct _VirtualBassParam { + int ratio; + int boost; + int fc; + int channel; + int SampleRate; +} VirtualBassParam; + +int getVirtualBassBuf(); +void VirtualBassInit(void *WorkBuf, VirtualBassParam *param); +void VirtualBassUpdate(void *WorkBuf, VirtualBassParam *param); +int VirtualBassRun(void *WorkBuf, int *tmpbuf, short *in, short *out, int per_channel_npoint); + +#endif // !VIRTUALBASS_API_H + diff --git a/include_lib/media/audio_drc.h b/include_lib/media/audio_drc.h new file mode 100644 index 0000000..85856e6 --- /dev/null +++ b/include_lib/media/audio_drc.h @@ -0,0 +1,158 @@ + +#ifndef _DRC_API_H_ +#define _DRC_API_H_ + +#include "typedef.h" +#include "media/sw_drc.h" +#include "media/audio_stream.h" + +#define CROSSOVER_EN BIT(0) //多带分频器使能 +#define MORE_BAND_EN BIT(1) //多带分频后,再做一次全带处理使能 +struct audio_drc_filter_info { + CrossOverParam_TOOL_SET *crossover; + wdrc_struct_TOOL_SET *wdrc; + // struct drc_ch *pch; //左声道系数 + // struct drc_ch *R_pch; //右声道系数 +}; + +typedef int (*audio_drc_filter_cb)(void *drc, struct audio_drc_filter_info *info); + +struct audio_drc_param { + u32 channels : 8; //通道数 (channels|(L_wdrc))或(channels|(R_wdrc)) + u32 online_en : 1; //是否支持在线调试 + u32 remain_en : 1; //写1 + u32 stero_div : 1; //是否左右声道 拆分的 drc效果,一般写0 + u32 reserved : 21; + audio_drc_filter_cb cb; //系数更新的回调函数,用户赋值 + u32 sr; //数据采样率 + u8 drc_name; //在线调试是,根据drc_name区分更新系数,一般写0 + u8 out_32bit; //是否支持32bit 的输入数据处理 1:使能 0:不使能 + u8 nband; //多带之后,再使能一次 全带处理 + CrossOverParam_TOOL_SET *crossover; + wdrc_struct_TOOL_SET *wdrc;//[0]low [1]mid [2]high [3]whole + // struct drc_ch *parm; //系数输入 +}; + +struct audio_drc { + CrossOverParam_TOOL_SET *crossover_inside;// + wdrc_struct_TOOL_SET *wdrc_inside; + // struct drc_ch sw_drc[2]; //软件drc 系数地址 + // struct drc_ch *drc_param; //在线调试暂存软件drc系数地址,由外部赋值 + CrossOverParam_TOOL_SET *crossover;// + wdrc_struct_TOOL_SET *wdrc; + + u32 sr; //采样率 + u32 channels : 8; //通道数(channels|(L_wdrc))或(channels|(R_wdrc)) + u32 remain_flag : 1; //输出数据支持remain + u32 updata : 1; //系数更标志 + u32 online_en : 1; //是否支持在线更新系数 + u32 remain_en : 1; //是否支持remain输出 + u32 start : 1; //无效 + u32 run32bit : 8; //是否使能32bit位宽数据处理1:使能 0:不使能 + u32 need_restart : 1; //是否需要重更新系数 1:是 0:否 + u32 stero_div : 1; //是否左右声道拆分的drc效果,1:是 0:否 + u8 other_band; + audio_drc_filter_cb cb; //系数更新回调 + void *hdl; //软件drc句柄 + void *output_priv; //输出回调私有指针 + int (*output)(void *priv, void *data, u32 len);//输出回调函数 + u32 drc_name; //drc标识 + struct list_head hentry; // + u8 *file_path; //离线效果文件路径 + + + struct audio_stream_entry entry; // 音频流入口 +}; + + + +/*----------------------------------------------------------------------------*/ +/**@brief drc打开 + @param drc:句柄 + @param param:drc打开传入参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_drc_open(struct audio_drc *drc, struct audio_drc_param *param); +/*----------------------------------------------------------------------------*/ +/**@brief drc设置输出数据回调 + @param drc:句柄 + @param *output:输出回调 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_drc_set_output_handle(struct audio_drc *drc, int (*output)(void *priv, void *data, u32 len), void *output_priv); +/*----------------------------------------------------------------------------*/ +/**@brief drc设置采样率 + @param drc:句柄 + @param sr:采样率 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_drc_set_samplerate(struct audio_drc *drc, int sr); +/*----------------------------------------------------------------------------*/ +/**@brief drc设置是否处理32bit输入数据 + @param drc:句柄 + @param run_32bit:1:32bit 0:16bit + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_drc_set_32bit_mode(struct audio_drc *drc, u8 run_32bit); +/*----------------------------------------------------------------------------*/ +/**@brief drc启动 + @param drc:句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_drc_start(struct audio_drc *drc); +/*----------------------------------------------------------------------------*/ +/**@brief drc数据处理 + @param drc:句柄 + @param *data:输入数据地址 + @param len:输入数据长度 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_drc_run(struct audio_drc *drc, s16 *data, u32 len); +/*----------------------------------------------------------------------------*/ +/**@brief drc关闭 + @param drc:句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_drc_close(struct audio_drc *drc); + + +/*----------------------------------------------------------------------------*/ +/**@brief audio_drc_open重新封装,简化使用,该接口不接入audio_stream流处理 + @param *parm: drc参数句柄,参数详见结构体struct audio_drc_param + @return eq句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +struct audio_drc *audio_dec_drc_open(struct audio_drc_param *parm); +/*----------------------------------------------------------------------------*/ +/**@brief audio_drc_close重新封装,简化使用,该接口不接入audio_stream流处理 + @param drc句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_dec_drc_close(struct audio_drc *drc); + + +int audio_dec_drc_run(struct audio_drc *drc, s16 *data, u32 len); +void cur_crossover_set_update(u32 drc_name, CrossOverParam_TOOL_SET *crossover_parm); +void cur_drc_set_update(u32 drc_name, u8 type, void *wdrc_parm); +void cur_drc_set_bypass(u32 drc_name, u8 tar, u8 bypass); +void audio_drc_init(void); +int drc_get_filter_info(void *_drc, struct audio_drc_filter_info *info); +#endif + diff --git a/include_lib/media/audio_echo_reverb.h b/include_lib/media/audio_echo_reverb.h new file mode 100644 index 0000000..c933fde --- /dev/null +++ b/include_lib/media/audio_echo_reverb.h @@ -0,0 +1,107 @@ +#ifndef reverb_echo_h__ +#define reverb_echo_h__ + +#include "media/reverb_api.h" +/* + * 打开声卡混响模块 + */ +REVERBN_API_STRUCT *open_reverb(REVERBN_PARM_SET *reverb_seting, u16 sample_rate); +/* + * 声卡混响处理 + */ +void run_reverb(REVERBN_API_STRUCT *reverb_api_obj, short *in, short *out, int len); +/* + * 关闭声卡混响模块 + */ +void close_reverb(REVERBN_API_STRUCT *reverb_api_obj); +/* + * 暂停声卡混响处理 + */ +void pause_reverb(REVERBN_API_STRUCT *reverb_api_obj, u8 run_mark); +/* + * 声卡混响参数更新 + */ +void update_reverb_parm(REVERBN_API_STRUCT *reverb_api_obj, REVERBN_PARM_SET *reverb_seting); + +void reverb_update_bypass(REVERBN_API_STRUCT *hdl, int bypass); + + +/* + * 打开快速声卡混响模块 + */ +REVERB0_API_STRUCT *open_fast_reverb(EF_REVERB0_PARM *reverb_seting, u16 sample_rate); +/* + * 快速声卡混响处理 + */ +void run_fast_reverb(REVERB0_API_STRUCT *reverb_api_obj, short *in, short *out, int len); +/* + * 关闭快速声卡混响模块 + */ +void close_fast_reverb(REVERB0_API_STRUCT *reverb_api_obj); +/* + * 暂停快速声卡混响处理 + */ +void pause_fast_reverb(REVERB0_API_STRUCT *reverb_api_obj, u8 run_mark); +/* + * 快速声卡混响参数更新 + */ +void update_fast_reverb_parm(REVERB0_API_STRUCT *reverb_api_obj, EF_REVERB0_PARM *reverb_seting); + +void fast_reverb_update_bypass(REVERB0_API_STRUCT *hdl, int bypass); + + + +/* + * 打开plate声卡混响模块 + */ +PLATE_REVERB_API_STRUCT *open_plate_reverb(Plate_reverb_parm *reverb_seting, u16 sample_rate); +/* + * plate声卡混响处理 + */ +void run_plate_reverb(PLATE_REVERB_API_STRUCT *reverb_api_obj, short *in, short *out, int len); +/* + * 关闭plate声卡混响模块 + */ +void close_plate_reverb(PLATE_REVERB_API_STRUCT *reverb_api_obj); +/* + * 暂停plate声卡混响处理 + */ +void pause_plate_reverb(PLATE_REVERB_API_STRUCT *reverb_api_obj, u8 run_mark); +/* + * plate声卡混响参数更新 + */ +void update_plate_reverb_parm(PLATE_REVERB_API_STRUCT *reverb_api_obj, Plate_reverb_parm *reverb_seting); + +void plate_reverb_update_bypass(PLATE_REVERB_API_STRUCT *hdl, int bypass); + + + + +/* + * 打开echo混响模块 + */ +ECHO_API_STRUCT *open_echo(ECHO_PARM_SET *echo_seting, EF_REVERB_FIX_PARM *fix_parm); +/* + * echo混响处理 + */ +void run_echo(ECHO_API_STRUCT *p_echo_obj, short *in, short *out, int len); +/* + * 关闭echo混响模块 + */ +void close_echo(ECHO_API_STRUCT *echo_api_obj); +/* + * 暂停echo混响处理 + */ +void pause_echo(ECHO_API_STRUCT *echo_api_obj, u8 run_mark); +/* + * 更新echo混响通用参数 + */ +void update_echo_parm(ECHO_API_STRUCT *echo_api_obj, ECHO_PARM_SET *echo_seting); +/* + * 更新echo混响gain参数 + */ +void update_echo_gain(ECHO_API_STRUCT *echo_api_obj, int wetgain, int drygain); + + +void echo_update_bypass(ECHO_API_STRUCT *hdl, int bypass); +#endif // reverb_echo_h__ diff --git a/include_lib/media/audio_eq.h b/include_lib/media/audio_eq.h new file mode 100644 index 0000000..9cebc8a --- /dev/null +++ b/include_lib/media/audio_eq.h @@ -0,0 +1,299 @@ +#ifndef _EQ_API_H_ +#define _EQ_API_H_ + +#include "typedef.h" +#include "asm/hw_eq.h" +#include "media/audio_stream.h" +#include "system/timer.h" + +#define EQ_CHANNEL_MAX 2 + +#define EQ_SR_IDX_MAX 9 + +#define AUDIO_EQ_HIGH 2 +#define AUDIO_EQ_BASS 3 + +/*eq type*/ +typedef enum { + EQ_MODE_NORMAL = 0, + EQ_MODE_ROCK, + EQ_MODE_POP, + EQ_MODE_CLASSIC, + EQ_MODE_JAZZ, + EQ_MODE_COUNTRY, + EQ_MODE_CUSTOM,//自定义 + EQ_MODE_MAX, +} EQ_MODE; + +/*eq type*/ +typedef enum { + EQ_TYPE_FILE = 0x01, + EQ_TYPE_ONLINE, + EQ_TYPE_MODE_TAB, +} EQ_TYPE; + +#define audio_eq_filter_info eq_coeff_info + +typedef int (*audio_eq_filter_cb)(void *eq, int sr, struct audio_eq_filter_info *info); + +struct audio_eq_param { + u8 no_wait : 1; //是否使能异步eq, 1:使能 0:不使能 + u8 max_nsection : 6;//最大的eq段数,根据使用填写,要小于等于EQ_SECTION_MAX + u8 nsection : 6; //实际需要的eq段数,需小于等于max_nsection + u8 out_32bit : 1; //是否支持32bit eq输出,仅在 no_wait 写1时,out_32bit 才能写1 + u8 channels : 2; //通道数 + u8 fade: 1; //系数更新是否需要淡入 + float fade_step; //淡入步进(0.1f~1.0f) + audio_eq_filter_cb cb;//获取eq系数的回调函数 + u32 eq_name; //eq名字,在线调试时,用于区分不同eq更新系数 播歌一般写song_eq_mode + u32 sr; //采样率,更根据当前数据实际采样率填写 + + float global_gain; + struct eq_seg_info *seg;// + float global_gain_r; + struct eq_seg_info *seg_r;// + + + void *priv; //私有指针 + int (*output)(void *priv, void *data, u32 len);//异步eq输出回调,节点方式使用时,output 配NULL + void (*irq_callback)(void *priv);//总段回调函数,数据流激活 +}; +struct audio_eq_fade { + u8 nsection; + u16 timer; + float cur_global_gain; + float use_global_gain; + struct eq_seg_info *cur_seg; + struct eq_seg_info *use_seg; +} ; + +struct high_bass { + int freq; //频率写0, 内部会用默认125hz 和12khz + int gain; //增益范围 -12~12 +}; + + +#ifdef CONFIG_EQ_SUPPORT_ASYNC +struct audio_eq_async { + u16 ptr; + u16 len; + u16 buf_len; + u8 clear; + u8 out_stu; + char *buf; +}; +#endif + +struct audio_eq { + void *eq_ch; //硬件eq句柄 + u8 updata; //系数是否需要更新 + u8 start; //eq start标识 + u8 max_nsection; //eq最大段数 + u8 cur_nsection; //当前eq段数 + u8 check_hw_running; //检测到硬件正在运行时不等待其完成1:设置检查 0:不检查 + u8 async_en; + u8 out_32bit; + u8 ch_num; + u32 sr; //采样率 + u32 eq_name; //eq标识 + u32 mask[2]; + float global_gain; + float global_gain_r; + s16 *eq_out_buf;//同步方式,32bit输出,当out为NULL时,内部申请eq_out_buf + int out_buf_size; + int eq_out_points; + int eq_out_total; + struct audio_stream_entry entry; // 音频流入口 + +#ifdef CONFIG_EQ_SUPPORT_ASYNC + void *run_buf; + void *run_out_buf; + int run_len; + struct audio_eq_async async; //异步eq 输出管理 +#endif + u32 mute_cnt_l; //左声道eq mem清除计数 + u32 mute_cnt_r; //右声道eq mem清除计数 + u32 mute_cnt_max; //记录最大点数,超过该点数,清eq mem + + audio_eq_filter_cb cb; //系数回调 + void *output_priv; //私有指针 + int (*output)(void *priv, void *data, u32 len); //输出回调 + + struct eq_seg_info *eq_seg_tab; //运算前系数表,特殊应用时,可使用 + struct eq_seg_info *seg; //运算前系数表,由audio_eq_param初始化时指定 + struct eq_seg_info *seg_r; //运算前系数表,由audio_eq_param初始化时指定 + int *eq_coeff_tab; //运算后系数表 + struct list_head hentry; // + const char *event_owner; //记录data_handler所处的任务 + struct audio_eq_fade *fade; + float fade_step; +}; + +/*----------------------------------------------------------------------------*/ +/**@brief eq模块初始化 + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_eq_init(void); +void audio_eq_init_new(int eq_section_num); +/*----------------------------------------------------------------------------*/ +/**@brief eq 打开 + @param *param: eq参数句柄,参数详见结构体struct audio_eq_param + @return eq句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_eq_open(struct audio_eq *eq, struct audio_eq_param *param); +/*----------------------------------------------------------------------------*/ +/**@brief 异步eq设置输出回调 + @param eq:句柄 + @param *output:回调函数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_eq_set_output_handle(struct audio_eq *eq, int (*output)(void *priv, void *data, u32 len), void *output_priv); +/*----------------------------------------------------------------------------*/ +/**@brief 同步eq设置输出buf + @param eq:句柄 + @param *output:回调函数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_eq_set_output_buf(struct audio_eq *eq, s16 *buf, u32 len); +/*----------------------------------------------------------------------------*/ +/**@brief eq设置采样率 + @param eq:句柄 + @param sr:采样率 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_eq_set_samplerate(struct audio_eq *eq, int sr); +/*----------------------------------------------------------------------------*/ +/**@brief eq设置输入输出通道数 + @param eq:句柄 + @param channel:通道数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_eq_set_channel(struct audio_eq *eq, u8 channel); + +/*----------------------------------------------------------------------------*/ +/**@brief 设置检查eq是否正在运行 + @param eq:句柄 + @param check_hw_running: 1:设置检查 0:不检查 + @return + @note 检测到硬件正在运行时不等待其完成,直接返回, 仅异步EQ有效 +*/ +/*----------------------------------------------------------------------------*/ +int audio_eq_set_check_running(struct audio_eq *eq, u8 check_hw_running); +/*----------------------------------------------------------------------------*/ +/**@brief 设置eq信息 + @param eq:句柄 + @param channels:设置输入输出通道数 + @param out_32bit:使能eq输出32bit数据,1:输出32bit数据, 0:输出16bit是数据 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_eq_set_info(struct audio_eq *eq, u8 channels, u8 out_32bit); + +/*----------------------------------------------------------------------------*/ +/**@brief 设置eq信息 + @param eq:句柄 + @param channels:设置入输出通道数 + @param in_mode:使能eq输入32bit数据,2:float, 1:输入32bit数据, 0:输入16bit是数据 + @param out_mode:使能eq输出32bit数据,2:float, 1:输出32bit数据, 0:输出16bit是数据 + @param run_mode:运行模式,0:normal, 1:mono, 2:stero + @param data_in_mode:输入数据存放方式 0:块模式 1:序列模式 + @param data_out_mode:输入数据存放方式 0:块模式 1:序列模式 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_eq_set_info_new(struct audio_eq *eq, u8 channels, u8 in_mode, u8 out_mode, u8 run_mode, u8 data_in_mode, u8 data_out_mode); + +/*----------------------------------------------------------------------------*/ +/**@brief eq启动 + @param eq:句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_eq_start(struct audio_eq *eq); +/*----------------------------------------------------------------------------*/ +/**@brief eq的数据处理 + @param eq:句柄 + @param *data:输入数据地址 + @param len:输入数据长度 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_eq_run(struct audio_eq *eq, s16 *data, u32 len); +/*----------------------------------------------------------------------------*/ +/**@brief eq关闭 + @param eq:句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_eq_close(struct audio_eq *eq); + + +#ifdef CONFIG_EQ_SUPPORT_ASYNC +/*----------------------------------------------------------------------------*/ +/**@brief 清除异步eq剩余的数据 + @param eq:句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_eq_async_data_clear(struct audio_eq *eq); +#endif +/*----------------------------------------------------------------------------*/ +/**@brief 获取异步eq剩余的数据 + @param eq:句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_eq_data_len(struct audio_eq *eq); + + +/*----------------------------------------------------------------------------*/ +/**@brief audio_eq_open重新封装,简化使用,该接口不接入audio_stream流处理 + @param *parm: eq参数句柄,参数详见结构体struct audio_eq_param + @return eq句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +struct audio_eq *audio_dec_eq_open(struct audio_eq_param *parm); +/*----------------------------------------------------------------------------*/ +/**@brief audio_eq_close重新封装,简化使用,该接口不接入audio_stream流处理 + @param eq句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_dec_eq_close(struct audio_eq *eq); + + +int audio_dec_eq_run(struct audio_eq *eq, s16 *data, s16 *out, u16 len); + + +void cur_eq_set_global_gain(u32 eq_name, float g_Gain); +void cur_eq_set_update(u32 eq_name, struct eq_seg_info *seg, u32 nsection, u32 design); + +void cur_eq_right_ch_set_global_gain(u32 eq_name, float g_Gain); +void cur_eq_right_ch_set_update(u32 eq_name, struct eq_seg_info *seg, u32 nsection, u32 design); + +int eq_get_filter_info(void *_eq, int sr, struct audio_eq_filter_info *info); +struct audio_eq *get_cur_eq_hdl_by_name(u32 eq_name); +#endif + diff --git a/include_lib/media/audio_eq_drc_apply.h b/include_lib/media/audio_eq_drc_apply.h new file mode 100644 index 0000000..5c015fb --- /dev/null +++ b/include_lib/media/audio_eq_drc_apply.h @@ -0,0 +1,115 @@ +#ifndef _EQ_APPLY_H_ +#define _EQ_APPLY_H_ + +#include "system/includes.h" +#include "media/audio_stream.h" +#include "media/audio_eq.h" + +#if 0 +#include "media/eq_config.h" + +#define DECREASE_MEM 1 //减少输出buf占用 +struct audio_eq_drc_parm { + u8 eq_en: 1; //eq是否使能 1:使能 0:关闭 + u8 drc_en: 1; //drc是否使能 1:使能 0:关闭 + u8 high_bass: 1; //高低音是否使能, 1:使能 0:关闭 + u8 async_en: 1; //是否使能异步eq 1:使能 0:关闭 + u8 out_32bit: 1; //eq后是否输出32bit 1:使能: 0关闭 + u8 divide_en: 1; //各个声道eq drc效果是否独立,0:使用同个效果 + u8 mode_en: 1; //没离线文件时,是否支持使用默认系数表做eq + u8 online_en: 1; //是否支持在线调试 1:支持 0:不支持 + u8 ch_num: 3; //输入数据通道数 + u8 process_split: 1; //eq、drc是否单独处理 1:节点内各自单独处理并输出 0:节点内一起处理(先处理eq再做drc后输出) + u8 reserved: 4; + u8 nsection : 6;//最大的eq段数,根据使用填写,要小于等于EQ_SECTION_MAX + u8 eq_name; //FL FR通道的eq_name 普通音乐eq 使用song_eq_mode,通话下行eq 使用call_eq_mode + u32 sr; //采样率 + float global_gain ; + struct eq_seg_info *seg; + + audio_eq_filter_cb eq_cb; //获取eq系数的回调函数 + audio_drc_filter_cb drc_cb;//获取drc系数的回调 +}; + + + +/* +*cmd : +*/ +#define AUDIO_EQ_SET_CH 0 +#define AUDIO_EQ_CLR_DAT 1 +#define AUDIO_EQ_HIGH 2 +#define AUDIO_EQ_BASS 3 +#define AUDIO_EQ_GET_DATA_LEN 4 +#define AUDIO_EQ_HIGH_BASS_DIS 5 + + +struct high_bass { + int freq; //频率写0, 内部会用默认125hz 和12khz + int gain; //增益范围 -12~12 +}; + +typedef struct eq_fade { + u16 tmr; +#ifdef EQ_CORE_V1 + float cur_gain[2]; + float use_gain[2]; +#else + int cur_gain[2]; + int use_gain[2]; +#endif +} audio_eq_fade_cfg; + + +struct audio_eq_drc { + struct audio_eq *eq; + struct audio_drc *drc; + struct eq_fade *fade_cfg;//高低音系数表 + + s16 *eq_out_buf; + int out_buf_size; + int eq_out_points; + int eq_out_total; + u8 high_bass_dis; + + struct audio_eq_drc_parm parm; + struct audio_stream_entry entry; // 音频流入口 +}; + + +/*----------------------------------------------------------------------------*/ +/**@brief 打开eq drc,支持接入audio_stream + @param parm: 功能使用参数,详见结构体定义 + @return 返回eq drc句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +struct audio_eq_drc *audio_eq_drc_open(struct audio_eq_drc_parm *parm); +/*----------------------------------------------------------------------------*/ +/**@brief eq drc接入音频流,数据处理回调 + @param entry: 数据流节点 + @param in:输入数据结构 + @param out:输出数据结构 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_eq_drc_close(struct audio_eq_drc *hdl); + +/*----------------------------------------------------------------------------*/ +/**@brief 参数更新 + @param hdl:句柄 + @param cmd:命令 + @param parm:参数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_eq_drc_parm_update(struct audio_eq_drc *hdl, u32 cmd, void *parm); + +/* + *非数据流方式,eq、drc的run处理接口 + * */ +int audio_eq_drc_run(struct audio_eq_drc *hdl, s16 *data, u16 len); +#endif +#endif diff --git a/include_lib/media/audio_equalloudness.h b/include_lib/media/audio_equalloudness.h new file mode 100644 index 0000000..a706cf6 --- /dev/null +++ b/include_lib/media/audio_equalloudness.h @@ -0,0 +1,68 @@ + +#ifndef _AUDIO_LOUDNESS_API_H_ +#define _AUDIO_LOUDNESS_API_H_ + +#include "system/includes.h" +#include "media/includes.h" +#include "equalloudness/loudness_api.h" + +typedef struct _equalloudness_open_parm { + u16 sr; //采样率 + u8 channel; //通道数 + u8 threadhold_vol; //触发等响度软件数字音量阈值 + + int (*alpha_cb)(float *alpha, u8 *volume, u8 threadhold_vol);//该函数根据,系统软件的数字音量,参数返回 alpha值 +} equalloudness_open_parm; + +typedef struct _equalloudness_update_parm { + u8 threadhold_vol; //触发等响度软件数字音量阈值 +} equalloudness_update_parm; + + +typedef struct _equalloudness_hdl { + void *work_buf; //软件等响度 运行句柄及buf + OS_MUTEX mutex; //互斥锁 + + /*输出的偏移*/ + u32 out_buf_size; //输出buf大小 + s16 *out_buf; //输出buf地址 + u32 out_points; //当前已输出的点数 + u32 out_total; //输出buf总点数 + + void *buf; //输入buf + cbuffer_t cbuf; //软件等响度,每次处理固定长度的数据,此处使用cbuf管理输入 + u8 init_ok: 1; //是否初始化完成 + u8 prev_vol; //记录当前数据流入的数字音量 + + equalloudness_open_parm o_parm; //打开时,传入参数 + + struct audio_stream_entry entry; // 音频流入口 +} equal_loudness_hdl; + +/*----------------------------------------------------------------------------*/ +/**@brief audio_equal_loudness_open, 等响度 打开 + @param *_parm: 等响度初始化参数,详见结构体equalloudness_open_parm + @return 等响度句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +equal_loudness_hdl *audio_equal_loudness_open(equalloudness_open_parm *_parm); +/*----------------------------------------------------------------------------*/ +/**@brief audio_equal_loudness_parm_update 等响度 参数更新 + @param cmd:命令 + @param *_parm:参数指针 + @return 0:成功 -1: 失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_equal_loudness_parm_update(equal_loudness_hdl *_hdl, u32 cmd, equalloudness_update_parm *_parm); +/*----------------------------------------------------------------------------*/ +/**@brief audio_equal_loudness_close 等响度关闭处理 + @param _hdl:句柄 + @return 0:成功 -1:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_equal_loudness_close(equal_loudness_hdl *_hdl); +#endif + diff --git a/include_lib/media/audio_equalloudness_eq.h b/include_lib/media/audio_equalloudness_eq.h new file mode 100644 index 0000000..b1d706b --- /dev/null +++ b/include_lib/media/audio_equalloudness_eq.h @@ -0,0 +1,47 @@ + +#ifndef _AUDIO_LOUDNESS_EQ_API_H_ +#define _AUDIO_LOUDNESS_EQ_API_H_ + +#include "media/audio_eq.h" + +/* + *等响度使用eq实现,同个数据流中,如需要打开等响度,请打开开eq总使能,关闭其其他eq,例如蓝牙模式eq + * */ +typedef struct _equalloudness_open_parm { + u16 sr; //采样率 + u8 ch_num; //通道数 + u8 threadhold_vol; //触发等响度软件数字音量阈值 + int (*vol_cb)(void); //该函数获取系统软件的数字音量 +} loudness_open_parm; + + +#define LOUDNESS_THREADHOLD_VOL (15) + +typedef struct _equalloudness_hdl { + struct audio_eq *loudness; //使用eq实现等响度 句柄 + u16 loudness_timer; //定时查询是否需要触发等响度 timer + u8 loudness_en; //等响度使能 + u8 prev_status; //记录模块上一状态 + + loudness_open_parm o_parm; //打开传入的参数 +} loudness_hdl; + +/*----------------------------------------------------------------------------*/ +/**@brief audio_equal_loudness_open, 等响度 打开 + @param *_parm: 等响度初始化参数,详见结构体loudness_open_parm + @return 等响度句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +loudness_hdl *audio_equal_loudness_open(loudness_open_parm *parm); + +/*----------------------------------------------------------------------------*/ +/**@brief audio_equal_loudness_close 等响度关闭处理 + @param _hdl:句柄 + @return 0:成功 -1:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_equal_loudness_close(loudness_hdl *hdl); +#endif + diff --git a/include_lib/media/audio_gain_process.h b/include_lib/media/audio_gain_process.h new file mode 100644 index 0000000..cd00bf8 --- /dev/null +++ b/include_lib/media/audio_gain_process.h @@ -0,0 +1,40 @@ +#ifndef __AUDIO_GAIN_PORCESS__H +#define __AUDIO_GAIN_PORCESS__H + +#include "media/audio_stream.h" + +#ifndef RUN_NORMAL +#define RUN_NORMAL 0 +#endif + +#ifndef RUN_BYPASS +#define RUN_BYPASS 1 +#endif + +struct aud_gain_parm { + float gain;//增加多少dB + u8 channel;//通道数 + u8 indata_inc;//channel ==1 ?1:2; + u8 outdata_inc;//channel ==1 ?1:2; + u8 bit_wide;//0:16bit 1:32bit + u16 gain_name; +}; +struct aud_gain_parm_update { + float gain;//增加多少dB +}; +struct aud_gain_process { + struct audio_stream_entry entry; // 音频流入口 + struct list_head hentry; // + struct aud_gain_parm parm; + u8 status; //内部运行状态机 + u8 update; //设置参数更新标志 +}; + + +struct aud_gain_process *audio_gain_process_open(struct aud_gain_parm *parm); +void audio_gain_process_run(struct aud_gain_process *hdl, s16 *data, int len); +void audio_gain_process_close(struct aud_gain_process *hdl); +void audio_gain_process_update(u16 gain_name, struct aud_gain_parm_update *parm); +void audio_gain_process_bypass(u16 gain_name, u8 bypass); + +#endif diff --git a/include_lib/media/audio_howling.h b/include_lib/media/audio_howling.h new file mode 100644 index 0000000..3135a3e --- /dev/null +++ b/include_lib/media/audio_howling.h @@ -0,0 +1,57 @@ +#ifndef _AUDIO_HOWLING_API_H +#define _AUDIO_HOWLING_API_H + +#include "media/howling_api.h" + + +#define TRAP_MODE 0 +#define SHIFT_PITCH_MODE 1 +#define PEMAFROW_MODE 2 +#define SHIFT_PHASE_MODE 3 + +#define HOWLING_MODE SHIFT_PITCH_MODE + +#if (HOWLING_MODE == TRAP_MODE) +#define REVERB_RUN_POINT_NUM 160 //固定160个点 +#elif (HOWLING_MODE == SHIFT_PHASE_MODE) // +#define REVERB_RUN_POINT_NUM 256 //固定256个点 +#elif (HOWLING_MODE == PEMAFROW_MODE) +#define REVERB_RUN_POINT_NUM 128 //固定128 +#else +#define REVERB_RUN_POINT_NUM 0 //无限制 +#endif + + +/*----------------------------------------------------------------------------*/ +/**@brief 啸叫抑制模块打开 + @param howl_para:陷波模式时为啸叫抑制参数 ,pemafrow模式为DAC输出数据buf,; + sample_rate:输入数据采样率; + channels: 输入数据通道数; + mode: 0 陷波模式;1 移频模式 2 pemafrow模式 + @return 啸叫抑制句柄, + @note 陷波模式 要外部保证每次运算数据为160点,pemafrow 为128个点 + 对应模式需外部使能,默认只开 移频模式 + const int config_howling_enable_pemafrow_mode = 1; + const int config_howling_enable_trap_mode = 1; + const int config_howling_enable_pitchps_mode = 1; +*/ +/*----------------------------------------------------------------------------*/ +HOWLING_API_STRUCT *open_howling(void *howl_para, u16 sample_rate, u8 channel, u8 mode); +/* + * 啸叫抑制模块数据处理 + */ +void run_howling(HOWLING_API_STRUCT *howling_hdl, short *in, short *out, int len); +/* + * 啸叫抑制模块关闭 + */ +void close_howling(HOWLING_API_STRUCT *holing_hdl); +/* + * 啸叫抑制模块暂停处理 + */ +void pause_howling(HOWLING_API_STRUCT *holing_hdl, u8 run_mark); + +void howling_update_bypass(HOWLING_API_STRUCT *hdl, u8 bypass); + +void update_howling_parm(HOWLING_API_STRUCT *howling_hdl, void *parm); +#endif + diff --git a/include_lib/media/audio_noisegate.h b/include_lib/media/audio_noisegate.h new file mode 100644 index 0000000..86c6b37 --- /dev/null +++ b/include_lib/media/audio_noisegate.h @@ -0,0 +1,31 @@ +#ifndef _AUDIO_NOISEGATE_API_H +#define _AUDIO_NOISEGATE_API_H + +#include "media/audio_stream.h" +#include "media/noisegate_api.h" + +typedef struct _NOISEGATE_API_STRUCT_ { + void *workbuf; //运算buf指针 + NoiseGateParam parm; //参数 + + struct audio_stream_entry entry; // 音频流入口 + u8 status; + u8 update; +} NOISEGATE_API_STRUCT; + + +NOISEGATE_API_STRUCT *open_noisegate(NoiseGateParam *noisegate_parm); +int run_noisegate(NOISEGATE_API_STRUCT *noisegate_hdl, short *in, short *out, int len); +void close_noisegate(NOISEGATE_API_STRUCT *noisegate_hdl); +// void pause_noisegate(NOISEGATE_API_STRUCT *noisegate_hdl, u8 run_mark); +void update_noisegate(NOISEGATE_API_STRUCT *noisegate_hdl, NoiseGateParam *parm); +void noisegate_bypass(NOISEGATE_API_STRUCT *hdl, u8 bypass); +#ifndef RUN_NORMAL +#define RUN_NORMAL 0 +#endif + +#ifndef RUN_BYPASS +#define RUN_BYPASS 1 +#endif +#endif + diff --git a/include_lib/media/audio_stream.h b/include_lib/media/audio_stream.h new file mode 100644 index 0000000..6724e9d --- /dev/null +++ b/include_lib/media/audio_stream.h @@ -0,0 +1,321 @@ +#ifndef AUDIO_STREAM_H +#define AUDIO_STREAM_H + +#include "generic/includes.h" +#include "media/audio_base.h" + + +// 数据流IOCTRL命令 +#define AUDIO_STREAM_IOCTRL_CMD_CHECK_ACTIVE (1) // 检查数据流是否活动 + + +struct audio_stream_entry; +struct audio_frame_copy; + + +/* + * 数据流中的传输内容 + */ +struct audio_data_frame { + u8 channel; // 通道数 + u16 stop : 1; // 数据流停止标志 + u16 data_sync : 1; // 数据流同步标志 + u16 no_subsequent : 1; // 1-不再执行后续的数据流;0-正常执行 + u32 sample_rate; // 采样率 + u16 offset; // 数据偏移 + u16 data_len; // 数据长度 + s16 *data; // 数据地址 +}; + + +/* + * 数据流 + * 多个数据流节点组成一个数据流 + */ +struct audio_stream { + struct audio_stream_entry *entry; // 数据流节点 + void *priv; // resume私有参数 + void (*resume)(void *priv); // 激活回调接口 +}; + + +/* + * 数据流群组 + * 用于串联多个数据流,在调用resume/clear等操作时依次处理各个数据流 + * 如数据流stream0最后一个节点是entry0_n,数据流1最后一个节点是entry1_n + * 把这两个数据流加入到群组test_group中 + * audio_stream_group_add_entry(&test_group, &entry0_n); + * audio_stream_group_add_entry(&test_group, &entry1_n); + * 另一个数据流streamX的第一个节点是entryX_0,把群组关联到streamX数据流 + * entryX_0.group = &test_group; + * 那么调用streamX中的resume就会依次调用stream0和stream1的resume了 + */ +struct audio_stream_group { + struct audio_stream_entry *entry; // 数据流节点 +}; + +/* + * 数据流节点 + * 数据流节点依次串联,数据依次往后传递 + */ +struct audio_stream_entry { + u8 pass_by; // 1-同步处理(即往后传的buf就是上层传入的buf); + // 0-异步处理(数据存到其他buf再往后传) + u8 remain; // 1-上次数据没输出完。0-上次数据输出完 + u16 offset; // 同步处理时的数据偏移 + struct audio_stream *stream; // 所属的数据流 + struct audio_stream_entry *input; // 上一个节点 + struct audio_stream_entry *output; // 下一个节点 + struct audio_stream_entry *sibling; // 数据流群组中的数据流节点链表 + struct audio_stream_group *group; // 数据流群组节点 + struct audio_frame_copy *frame_copy; // 数据分支节点 + int (*prob_handler)(struct audio_stream_entry *, struct audio_data_frame *in); // 预处理 + int (*data_handler)(struct audio_stream_entry *, struct audio_data_frame *in, + struct audio_data_frame *out); // 数据处理 + void (*data_process_len)(struct audio_stream_entry *, int len); // 后级返回使用的数据长度 + void (*data_clear)(struct audio_stream_entry *); // 清除节点数据 + int (*ioctrl)(struct audio_stream_entry *, int cmd, int *param); // 节点IOCTRL +}; + +/* + * 数据流分支 + * 支持一传多(分支)功能,内部自动生成struct audio_frame_copy来处理多个分支 + * 有多少个分支就会申请多少个空间,数据分别拷贝到对应分支空间然后往后传递 + */ +struct audio_frame_copy { + struct list_head head; // 链表。用于连接各个分支 + struct audio_data_frame frame; // 保存上层的传输内容 + struct audio_stream_entry entry; // 连接上层的节点 +}; + + + +/* +********************************************************************* +* Audio Stream Open +* Description: 创建一个数据流 +* Arguments : *priv resume回调的私有参数 +* resume 模块唤醒数据流时的回调函数 +* Return : 数据流句柄 +* Note(s) : None. +********************************************************************* +*/ +struct audio_stream *audio_stream_open(void *priv, void (*resume)(void *priv)); + +/* +********************************************************************* +* Audio Stream Add First +* Description: 添加第一个数据流节点 +* Arguments : *stream 数据流句柄 +* *entry 数据流节点句柄 +* Return : None. +* Note(s) : 第一个节点一般为解码输出 +********************************************************************* +*/ +void audio_stream_add_first(struct audio_stream *stream, + struct audio_stream_entry *entry); + +/* +********************************************************************* +* Audio Stream Add Head +* Description: 将节点插入到数据流的first节点后面 +* Arguments : *stream 数据流句柄 +* *entry 数据流节点句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_stream_add_head(struct audio_stream *stream, + struct audio_stream_entry *entry); + +/* +********************************************************************* +* Audio Stream Add Tail +* Description: 将节点放到数据流的最后 +* Arguments : *stream 数据流句柄 +* *entry 数据流节点句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_stream_add_tail(struct audio_stream *stream, + struct audio_stream_entry *entry); + +/* +********************************************************************* +* Audio Stream Add Entry +* Description: 将output节点添加到input节点之后 +* Arguments : *input 数据流节点句柄 +* *output 需要添加的数据流节点句柄 +* Return : None. +* Note(s) : 如果input节点后面已经连接有节点,将创建数据流分支处理 +********************************************************************* +*/ +void audio_stream_add_entry(struct audio_stream_entry *input, + struct audio_stream_entry *output); + +/* +********************************************************************* +* Audio Stream Add List +* Description: 将entry数组中节点按顺序添加到数据流中 +* Arguments : *stream 数据流句柄 +* *entry[] 数据流节点数组 +* num 节点总个数 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_stream_add_list(struct audio_stream *stream, + struct audio_stream_entry *entry[], int num); + +/* +********************************************************************* +* Audio Stream Delete Entry +* Description: 将节点从数据流中删除 +* Arguments : *entry 数据流节点句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_stream_del_entry(struct audio_stream_entry *entry); + + +/* +********************************************************************* +* Audio Stream Delete List Entry +* Description: 依次将数组中的节点删除 +* Arguments : *entry[] 数据流节点数组 +* num 节点总个数 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_stream_del_list(struct audio_stream_entry *entry[], int num); + + +/* +********************************************************************* +* Audio Stream Group Add Entry +* Description: 将节点加入到群组之中 +* Arguments : *group 数据流群组句柄 +* *entry 数据流节点句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_stream_group_add_entry(struct audio_stream_group *group, + struct audio_stream_entry *entry); + +/* +********************************************************************* +* Audio Stream Group Delete Entry +* Description: 将节点从群组之中删除 +* Arguments : *group 数据流群组句柄 +* *entry 数据流节点句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_stream_group_del_entry(struct audio_stream_group *group, + struct audio_stream_entry *entry); + +/* +********************************************************************* +* Audio Stream Group Get Entry Number +* Description: 获取群组中的节点个数 +* Arguments : *group 数据流群组句柄 +* Return : 节点个数 +* Note(s) : None. +********************************************************************* +*/ +int audio_stream_group_entry_num(struct audio_stream_group *group); + +/* +********************************************************************* +* Audio Stream Run +* Description: 数据处理接口 +* Arguments : *entry 数据流节点句柄 +* *input 输入数据 +* Return : 负数-出错 +* Note(s) : 数据流依次递归往后传输。直到最后一个节点,或者no_subsequent==1, +* 或者prob_handler/data_handler处理错误返回负数 +********************************************************************* +*/ +int audio_stream_run(struct audio_stream_entry *from, struct audio_data_frame *input); + + +/* +********************************************************************* +* Audio Stream Resume +* Description: 唤醒数据流 +* Arguments : *entry 数据流节点句柄 +* Return : 0-成功 +* Note(s) : 最终会递归调用到struct audio_stream结构体中的.resume回调接口 +********************************************************************* +*/ +int audio_stream_resume(struct audio_stream_entry *entry); + + +/* +********************************************************************* +* Audio Stream Clear From Entry +* Description: 清除指定节点及后续所有节点的数据 +* Arguments : *entry 数据流节点句柄 +* Return : None. +* Note(s) : 会清除offset/pass_by等记录,并且调用data_clear回调接口清除用户数据 +********************************************************************* +*/ +void audio_stream_clear_from(struct audio_stream_entry *entry); + +/* +********************************************************************* +* Audio Stream Clear +* Description: 清除数据流所有节点数据 +* Arguments : *stream 数据流句柄 +* Return : None. +* Note(s) : 会清除offset/pass_by等记录,并且调用data_clear回调接口清除用户数据 +********************************************************************* +*/ +void audio_stream_clear(struct audio_stream *stream); + +/* +********************************************************************* +* Audio Stream Clear By Entry +* Description: 通过数据流某个节点清除数据流所有节点数据 +* Arguments : *entry 数据流节点句柄 +* Return : None. +* Note(s) : 先找到数据流起始位置,再调用audio_stream_clear()清除所有节点 +********************************************************************* +*/ +void audio_stream_clear_by_entry(struct audio_stream_entry *entry); + + +/* +********************************************************************* +* Audio Stream Check Active From Entry +* Description: 检测指定节点及后续节点是否有活动情况 +* Arguments : *entry 数据流节点句柄 +* Return : true 活动 +* Note(s) : 只要中间有某个节点活动就会返回数据流活动 +********************************************************************* +*/ +int audio_stream_check_active_from(struct audio_stream_entry *entry); + + +/* +********************************************************************* +* Audio Stream Close +* Description: 关闭数据流 +* Arguments : *stream 数据流句柄 +* Return : None. +* Note(s) : 需关闭所有数据流节点之后才能调用该函数 +********************************************************************* +*/ +void audio_stream_close(struct audio_stream *stream); + +#endif + + + + + diff --git a/include_lib/media/audio_surround.h b/include_lib/media/audio_surround.h new file mode 100644 index 0000000..7a04bfd --- /dev/null +++ b/include_lib/media/audio_surround.h @@ -0,0 +1,182 @@ + +#ifndef _AUDIO_SURROUND_API_H_ +#define _AUDIO_SURROUND_API_H_ + +#include "system/includes.h" +#include "media/includes.h" +#include "media/effect_sur_api.h" + +typedef struct _surround_update_parm { + int surround_type; //音效类型 + int rotatestep; //旋转速度 + int damping; //高频衰减速度 + int feedback; //整体衰减速度 + int roomsize; //空间大小 +} surround_update_parm; + +typedef struct _surround_open_parm { + u32 sur_name; + u8 channel; //通道数立体声配2, 左声道配EFFECT_CH_L, 右声道配EFFECT_CH_R + u8 surround_effect_type; //默认的环绕音效类型 +} surround_open_parm; + + +typedef struct _surround_hdl { + SUR_FUNC_API *ops; //环绕音效底层io + void *work_buf; //底层模块运行的句柄及buf + + surround_open_parm parm; //打开模块传入的参数 + u8 status; //内部运行状态机 + u8 update; //设置参数更新标志 + u8 eff_type; + + struct audio_stream_entry entry; // 音频流入口 + struct list_head hentry; // + +} surround_hdl; + +/*cmd*/ +enum { + EFFECT_3D_PANORAMA = 0, //3d全景 + EFFECT_3D_ROTATES, //3d环绕 + EFFECT_FLOATING_VOICE, //流动人声 + EFFECT_GLORY_OF_KINGS, //王者荣耀 + EFFECT_FOUR_SENSION_BATTLEFIELD, //四季战场 + + EFFECT_SUR2, //一种新的环绕声(仿某耳机的环绕音效)需将const_surround_en|BIT(2) + /*如使用以下效果,需将const_surround_en|BIT(1), mips占用 55M ram33k*/ + EFFECT_3D_PANORAMA2, //3d全景另一种效果 + EFFECT_KTV, //ktv模式 + EFFECT_3DTHE, //3D影院 + EFFECT_HALL, //音乐厅 + EFFECT_VOICE, //清澈人声 + EFFECT_SUR, //全景环绕 + + EFFECT_OFF2, //音效开关(数据会经过模块,但不做处理,保证数据延续,避免由音效开关引起的哒哒音,) + EFFECT_OFF, //音效开关(数据直接不经过模块) +}; + + +//{EFFECT_3D_TYPE1, 2, 120, 110, 128},//3D全景 +//{EFFECT_3D_ROTATE, 2, 60, 70, 128},//3D旋转, step旋转速度 建议1~8 +//{EFFECT_3D_LRDRIFT, 140, 120, 95, 128}, //流动人声,step流动速度 建议40~400 +//{EFFECT_3D_TYPE0, 2, 120, 95, 128},//王者荣耀 +//{EFFECT_3D_TYPE1, 2, 60, 100, 30},//四季战场,同全景,但把整体调小了 +//以上是内置默认效果 + + +#if 0 +//如启用多效果调节,需将const_surround_en|BIT(1),调用update接口传参使用。 +//{EFFECT_3D_TYPE2, 2, 90, 100, 100},//3d全景的另一效果,该效果,mips占用 55M ram33k. +//第一个参数2是无效参数. +//第2个参数90调节反馈强度范围是1到150,大点的话空间感比较强。 +//第3个参数是 湿声增益,可调范围是0到128。 +//第4个参数调节空间大小,范围是0-100,是反馈参数,有效范围0到100。 + +//例如: +surround_update_parm parm = {0}; +parm.surround_type = EFFECT_3D_TYPE2; +parm.rotatestep = 2; +parm.damping = 90; +parm.feedback = 100; +parm.roomsize = 100; +audio_surround_parm_update(hdl, EFFECT_3D_PANORAMA2, &parm); +#endif + +#if 0 +//如需要自定义 ktv模式、3d影院、音乐厅、清澈人声、全景环绕 +//参数顺序 +//dry,wet,delay,rot60,Erwet,Erfactor,Ewidth,Ertolate,predelay,width,diffusion,dampinglpf,basslpf,bassB +const static int surmode_present[][14] = { + {55, 70, 35, 8000, 80, 80, 80, 80, 20, 100, 70, 6500, 4000, 18}, //EFFECT_KTV + {60, 60, 90, 9030, 90, 90, 90, 90, 18, 100, 75, 7000, 1000, 29}, //EFFECT_3DTHE + {50, 70, 100, 12000, 100, 100, 100, 100, 20, 100, 72, 9000, 50, 3}, //EFFECT_HALL + {40, 70, 20, 2010, 100, 70, 70, 100, 15, 100, 70, 5500, 3500, 60}, //EFFECT_VOICE + {60, 70, 100, 9000, 80, 80, 80, 90, 10, 100, 72, 8000, 500, 15}, //EFFECT_SUR +}; + +parm.surround_type = EFFECT_3D_TYPE2; +parm.rotatestep = 2; +parm.damping = -1; +parm.feedback = 100; +parm.roomsize = (int)surmode_present[0]; +audio_surround_parm_update(hdl, EFFECT_KTV, &parm); + +//如使用默认的 ktv模式、3d影院、音乐厅、清澈人声、全景环绕 +audio_surround_parm_update(hdl, EFFECT_KTV, NULL); +audio_surround_parm_update(hdl, EFFECT_3DTHE, NULL); +audio_surround_parm_update(hdl, EFFECT_HALL, NULL); +audio_surround_parm_update(hdl, EFFECT_VOICE, NULL); +audio_surround_parm_update(hdl, EFFECT_SUR, NULL); +#endif + + +/*----------------------------------------------------------------------------*/ +/**@brief audio_surround_open 环绕音效打开 + @param *parm: 环绕音效始化参数,详见结构体surround_open_parm + @return 句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +surround_hdl *audio_surround_open(surround_open_parm *parm); + +/*----------------------------------------------------------------------------*/ +/**@brief audio_surround_parm_update 环绕音效参数更新 + @param cmd:EFFECT_3D_PANORAMA,EFFECT_3D_ROTATES,EFFECT_FLOATING_VOICE,EFFECT_GLORY_OF_KINGS,EFFECT_FOUR_SENSION_BATTLEFIELD + @param *parm:参数指针,NULL则使用默认德参数,否则传入自定义参数 + @return 0:成功 -1: 失败 + @note 对耳时,左右声道效果,须设置保持一致 +*/ +/*----------------------------------------------------------------------------*/ +int audio_surround_parm_update(u32 sur_name, u32 cmd, surround_update_parm *parm); + +/* surround_update_parm parm = {0}; */ +// parm.surround_type = EFFECT_3D_TYPE1; +// parm.rotatestep = 2;//旋转速度 +// parm.damping = 120;//高频衰减速度 +// parm.feedback = 110;//整体衰减速度 +// parm.roomsize = 128;//空间大小 +/* audio_surround_parm_update(hdl, EFFECT_3D_PANORAMA, &parm); */ +/*----------------------------------------------------------------------------*/ +/**@brief audio_surround_close 环绕音效关闭处理 + @param _hdl:句柄 + @return 0:成功 -1:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_surround_close(surround_hdl *_hdl); + +/*----------------------------------------------------------------------------*/ +/**@brief audio_surround_run 环绕音效处理 + @param _hdl:句柄 + @param data:需要处理的数据 + @param len:数据长度 + @return 0:成功 -1:失败 + @note 无数据流节点时,直接使用改接口进行环绕音效的处理 +*/ +/*----------------------------------------------------------------------------*/ +int audio_surround_run(surround_hdl *_hdl, void *data, u32 len); + + +/*----------------------------------------------------------------------------*/ +/**@brief audio_surround_switch_nch 通道切换 + @param _hdl:句柄 + @param nch:通道数 2 4 或者EFFECT_CH_L EFFECT_CH_R + @return 0:成功 -1:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_surround_switch_nch(surround_hdl *_hdl, int nch); +void audio_surround_bypass(u32 sur_name, u8 bypass); + +#ifndef RUN_NORMAL +#define RUN_NORMAL 0 +#endif + +#ifndef RUN_BYPASS +#define RUN_BYPASS 1 +#endif + + + +#endif diff --git a/include_lib/media/audio_vbass.h b/include_lib/media/audio_vbass.h new file mode 100644 index 0000000..caa9e4e --- /dev/null +++ b/include_lib/media/audio_vbass.h @@ -0,0 +1,43 @@ + +#ifndef _AUDIO_VBASS_API_H_ +#define _AUDIO_VBASS_API_H_ +#include "system/includes.h" +#include "media/audio_stream.h" +#include "media/VirtualBass_api.h" + + +typedef struct _VirtualBassUdateParam { + int ratio; + int boost; + int fc; +} VirtualBassUdateParam; + + +typedef struct _vbass_hdl { + struct audio_stream_entry entry; // 音频流入口 + struct list_head hentry; // + void *workbuf; //vbass 运行句柄及buf + VirtualBassParam parm; + u32 vbass_name; + u8 status; //内部运行状态机 + u8 update; //设置参数更新标志 +} vbass_hdl; + + +vbass_hdl *audio_vbass_open(u32 vbass_name, VirtualBassParam *parm); +int audio_vbass_close(vbass_hdl *hdl); + +int audio_vbass_parm_update(u32 vbass_name, VirtualBassUdateParam *parm); +void audio_vbass_bypass(u32 vbass_name, u8 bypass); + +#ifndef RUN_NORMAL +#define RUN_NORMAL 0 +#endif + +#ifndef RUN_BYPASS +#define RUN_BYPASS 1 +#endif + + +#endif + diff --git a/include_lib/media/audio_voice_changer.h b/include_lib/media/audio_voice_changer.h new file mode 100644 index 0000000..fd22130 --- /dev/null +++ b/include_lib/media/audio_voice_changer.h @@ -0,0 +1,53 @@ + +#ifndef _AUDIO_PITCH_API_H_ +#define _AUDIO_PITCH_API_H_ + +#include "media/voiceChanger_api.h" +#include "media/audio_stream.h" +typedef struct _voice_changer_hdl { + VOICECHANGER_FUNC_API *ops; + void *workbuf; + VOICECHANGER_PARM parm; + + struct audio_stream_entry entry; // 音频流入口 + struct list_head hentry; // + u32 sample_rate; + u32 voice_changer_name; + u8 update; + u8 status; +} voice_changer_hdl; +/* + * 获取变声模块默认参数;open时不传默认参数会使用内部默认参数 + * 仅用于获取初值。实时参数存放在open的返回句柄parm中 + */ +extern VOICECHANGER_FUNC_API *get_voiceChanger_func_api(); +/* + * 变声模块打开 + */ +voice_changer_hdl *audio_voice_changer_open(VOICECHANGER_PARM *param, u32 sample_rate, u32 voice_changer_name); +/* + * 变声模块关闭 + */ +void audio_voice_changer_close(voice_changer_hdl *hdl); +/* + * 变声模块参数更新 + */ +void audio_voice_changer_update_parm(u32 voice_changer_name, VOICECHANGER_PARM *parm); +/* + * 变声模块数据处理 + */ +int audio_voice_changer_run(voice_changer_hdl *hdl, s16 *indata, s16 *outdata, int len, u8 ch_num); +/* + * 变声模块暂停处理 + */ +void audio_voice_changer_bypass(u32 voice_changer_name, u32 bypass); +#endif + +#ifndef RUN_NORMAL +#define RUN_NORMAL 0 +#endif + +#ifndef RUN_BYPASS +#define RUN_BYPASS 1 +#endif + diff --git a/include_lib/media/convert_data.h b/include_lib/media/convert_data.h new file mode 100644 index 0000000..5ac0a40 --- /dev/null +++ b/include_lib/media/convert_data.h @@ -0,0 +1,25 @@ +#ifndef __CONVERT_DATA_H +#define __CONVERT_DATA_H + +#include "system/includes.h" +#include "media/audio_stream.h" + +struct convert_data { + struct audio_stream_entry entry; // 音频流入口 + u16 dat_len; + u16 dat_total; + u16 buf_len; + u16 *buf; + u8 type; +}; + +struct convert_data *convet_data_open(int type, u32 buf_len); +void convet_data_close(struct convert_data *hdl); + +void user_sat16(s32 *in, s16 *out, u32 npoint); + +//type +#define CONVERT_32_TO_16 0 +#define CONVERT_16_TO_32 1 + +#endif/*__CONVERT_DATA_H*/ diff --git a/include_lib/media/drc_api.h b/include_lib/media/drc_api.h new file mode 100644 index 0000000..95032f4 --- /dev/null +++ b/include_lib/media/drc_api.h @@ -0,0 +1,139 @@ +#ifndef DRC_API_H +#define DRC_API_H + +#ifdef WIN32 + +#define AT_DRC(x) +#define AT_DRC_CODE +#define AT_DRC_CONST +#define AT_DRC_SPARSE_CODE +#define AT_DRC_SPARSE_CONST + +#else +#define AT_DRC(x) __attribute((section(#x))) +#define AT_DRC_CODE AT_DRC(.drc_code) +#define AT_DRC_CONST AT_DRC(.drc_const) +#define AT_DRC_SPARSE_CODE AT_DRC(.drc_sparse_code) +#define AT_DRC_SPARSE_CONST AT_DRC(.drc_sparse_const) +#endif + + +enum { + DATA_IN_SHORT = 0, //输入数据类型,输入short时,输出不能为int + DATA_IN_INT, +}; +enum { + DATA_OUT_SHORT = 0, //输出数据类型,输入short时,输出不能为int + DATA_OUT_INT +}; + +enum { + PEAK = 0, //算法类型 + RMS +}; + +enum { + PERPOINT = 0, //mode 模式 + TWOPOINT +}; + +typedef struct _DrcParam { + /* + int *attackTime; //启动时间 + int *releaseTime; //释放时间 + float *threshold; //阈值{x1,y1,x2,y2} 最多5组十个数据 + int *ThresholdNum; //阈值的组数 + int *rmsTime; // rms时间 algorithm为RMS有效 + float *InputGain; // 输入增益(db) + float *OutputGain; // 输出数据增益(db) + unsigned char algorithm; // PEAK或者RMS + unsigned char mode; // 模式 + unsigned char intype; // 输入数据类型 + unsigned char outtype; // 输出数据类型 + */ + int channel; + int sampleRate; + int attackTime; //启动时间 + int releaseTime; //释放时间 + float *threshold; //阈值{x1,y1,x2,y2} 最多5组十个数据 + int ThresholdNum; //阈值的组数 + int rmsTime; // rms时间 algorithm为RMS有效 + float InputGain; // 输入增益(db) + float OutputGain; // 输出数据增益(db) + unsigned char algorithm; // PEAK或者RMS + unsigned char mode; // 模式 + unsigned char intype; // 输入数据类型 + unsigned char outtype; // 输出数据类型 + int IndataInc; // 输入数据同个通道下个点的步进 例如左右左右 步进为2 + int OutdataInc; // 输出数据同个通道下个点的步进 例如左右左右 步进为2 +} DrcParam; + +//int GetDrcBuf(int algorithm, int *rmsTime, int channel, int sampleRate); +int GetDrcBuf(DrcParam *param); // bufsize 与 algorithm,rmsTime channel、 sampleRate有关 +//void DrcInit(void *WorkBuf, DrcParam *param, int channel, int sampleRate); +void DrcInit(void *WorkBuf, DrcParam *param); +void DrcUpdate(void *WorkBuf, DrcParam *param); +int DrcRun(void *WorkBuf, void *indata, void *outdata, int per_channel_npoint); +/* InputGain 输入数据放大或者缩小的db数(正数放大,负数缩小) */ +// inputgain 配2,表示总体增加2dB +/* OutputGain 输出数据放大或者缩小的db数(正数放大,负数缩小) */ +#if 0 +int GetDrcBuf(int algorithm, int *rmsTime, int channel, int sampleRate); +获取buf大小 +参数说明: +algorithm:算法类型,PEAK或者RMS +rmsTime: +rms时间ms,算法类型为RMS时有效 +channel: 通道数 +sampleRate: +采样率 + +void DrcInit(void *WorkBuf, int *attackTime, int *releaseTime, float *threshold, int *ThresholdNum, int *rmsTime, int channel, int sampleRate, int algorithm, int mode, int intype, int outtype); +初始化 +参数说明: +WorkBuf: +运行buf +attackTime: +启动时间ms +releaseTime: +释放时间ms +threshold: +信号输入与对应的输出[in1, out1, in2, out2 ***排列] 最多5组数据, 3个阈值,4段 +ThresholdNum: +信号输入与对应的输出组数 +rmsTime: +rms时间ms +channel: +通道 +sampleRate:采样率 +algorithm:算法类型 +mode:模式 +intype:输入数据类型,DATA_IN_SHORT或者DATA_IN_INT +outtype: +输出数据类型,DATA_OUT_SHOR或者DATA_OUT_INT;若输入数据类型为DATA_IN_SHORT,输出类型只能设置为DATA_OUT_SHOR + +void DrcUpdate(void *WorkBuf, int *attackTime, int *releaseTime, float *threshold, int *ThresholdNum, int channel, int sampleRate); +更新参数:使用rms算法时,当rmsTime fs变化时因为buf会产生变化,只能初始化更新 +参数说明: +WorkBuf: +运行buf +attackTime: +启动时间ms +releaseTime: +释放时间ms +threshold: +信号输入与对应的输出[in1, out1, in2, out2 ***排列] 最多5组数据, 3个阈值,4段 +ThresholdNum: +信号输入与对应的输出组数 + +int DrcRun(void *WorkBuf, void *indata, void *outdata, int per_channel_npoint); +运行:输入输出数据类型,要跟初始化配置的数据类型对应 +WorkBuf: +运行buf +indata:输入数据 +outdata:输出数据 +per_channel_npoint:每个通道的样点数 +#endif + +#endif // !DRC_API_H + diff --git a/include_lib/media/dynamic_eq.h b/include_lib/media/dynamic_eq.h new file mode 100644 index 0000000..bdf9582 --- /dev/null +++ b/include_lib/media/dynamic_eq.h @@ -0,0 +1,206 @@ +#ifndef __DYNAMIC_EQ_H__ +#define __DYNAMIC_EQ_H__ + +#include "system/includes.h" +#include "media/audio_stream.h" +#include "media/DynamicEQ_api.h" +#include "media/DynamicEQ_Detection_api.h" +#include "media/audio_eq.h" +#include "media/drc_api.h" + +#define RUN_NORMAL 0 +#define RUN_BYPASS 1 + + + + +struct dynamic_eq_detection { + struct audio_stream_entry entry; // 音频流入口 + void *workbuf; //算法运行buf + int *out_buf; //模块运行输出的buf 32bit位宽 + int out_len; //输出buf的长度 + int len; //输出buf的长度 + DynamicEQDetectionParam parm[2]; //算法相关配置参数 + struct audio_eq *eq[2]; + u32 sample_rate; //采样率 + u8 nsection; //eq段数 + u8 channel; //通道数 + u8 status; //内部运行状态机 + u8 update; //设置参数更新标志 + + u8 in_32bit; // + s16 *in_buf; + u16 in_len; +}; +/* +********************************************************************* +* dynamic_eq_detection_open +* Description: 动态eq检测模块打开 +* Arguments :*parm 检测模块相关参数(中心截止频率)、若有2段,则parm[0], parm[1],参数连续存方 +* nesection:动态eq检测模块支持的段数 +* channel:输入数据通道数 +* sample_rate:输入数据采样率 +* Return : 模块句柄. +* Note(s) : None. +********************************************************************* +*/ +struct dynamic_eq_detection *dynamic_eq_detection_open(DynamicEQDetectionParam *parm, u8 nsection, u8 channel, u32 sample_rate); + +/* +********************************************************************* +* dynamic_eq_detection_run +* Description: 动态eq检测模块数据处理,不改变源数据 +* Arguments :*hdl:模块句柄 +* data:输入数据地址,16bit位宽 +* len:输入数据长度,byte +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +int dynamic_eq_detection_run(struct dynamic_eq_detection *hdl, short *data, int len); +/* +********************************************************************* +* get_dynamic_eq_detection_parm +* Description: 获取动态eq检测模块的结果 +* Arguments :*hdl:模块句柄 +* **out:检测模块的结果输出地址,32bit位宽 +* *out_len:检测模块结果数据长度byte +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +int get_dynamic_eq_detection_parm(struct dynamic_eq_detection *hdl, int **out, int *out_len); + +/* +********************************************************************* +* dynamic_eq_detection_bypass +* Description: 动态eq检测模块设置直通、正常处理 +* Arguments :*hdl:模块句柄 +* bypass:设置直通(RUN_BYPASS)、正常处理(RUN_NORMAL) +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void dynamic_eq_detection_bypass(struct dynamic_eq_detection *hdl, u8 bypass); + +/* +********************************************************************* +* dynamic_eq_detection_update +* Description: 动态eq检测模块设置直通、正常处理 +* Arguments :*hdl:模块句柄 +* bypass:设置直通(RUN_BYPASS)、正常处理(RUN_NORMAL) +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void dynamic_eq_detection_update(struct dynamic_eq_detection *hdl, DynamicEQDetectionParam *param); + +/* +********************************************************************* +* dynamic_eq_detection_close +* Description: 动态eq检测模块关闭 +* Arguments :*hdl:模块句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void dynamic_eq_detection_close(struct dynamic_eq_detection *hdl); + + + + +struct dynamic_eq { + struct audio_stream_entry entry; //音频流入口 + void *workbuf; //算法运行buf + DynamicEQEffectParam *effectParam; + DynamicEQParam parm; //算法相关配置参数 + // u32 sample_rate; //采样率 + // u8 nsection; //eq段数 + // u8 channel; //通道数 + u8 status; //内部运行状态机 + u8 update; //设置参数更新标志 + struct dynamic_eq_detection *priv; //私有指针 + int (*get_detect_parm)(struct dynamic_eq_detection *priv, int **out_data, int *out_len);//该回调,由dynamic_eq_detection 模块实现 +}; +/* +********************************************************************* +* dynamic_eq_open +* Description: 动态eq打开 +* Arguments :*parm 检测模块相关参数、若有2段,则parm[0], parm[1],参数连续存方 +* nesection:动态eq检测模块支持的段数 +* channel:输入数据通道数 +* sample_rate:输入数据采样率 +* Return : 模块句柄. +* Note(s) : None. +********************************************************************* +*/ +// struct dynamic_eq *dynamic_eq_open(DynamicEQParam *parm, u8 nsection, u8 channel,u32 sample_rate); +struct dynamic_eq *dynamic_eq_open(DynamicEQEffectParam *effectParam, DynamicEQParam *parm);//, u8 nsection, u8 channel, u32 sample_rate) + +/* +********************************************************************* +* dynamic_eq_set_detection_callback +* Description: 动态eq 设置检测模块的结果回调 +* Arguments :*hdl:模块句柄 +* priv:私有指针 +* get_detect_parm:检测模块的输出回调 +* Return : 模块句柄. +* Note(s) : None. +********************************************************************* +*/ +void dynamic_eq_set_detection_callback(struct dynamic_eq *hdl, void *priv, int (*get_detect_parm)(struct dynamic_eq_detection *priv, int **out_data, int *out_len)); +/* +********************************************************************* +* dynamic_eq_run +* Description: 动态eq模块数据处理 +* Arguments :*hdl:模块句柄 +* data:输入数据地址,32bit位宽 +* len:输入数据长度,byte +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +int dynamic_eq_run(struct dynamic_eq *hdl, int *data, int len); +/* +********************************************************************* +* dynamic_eq_bypass +* Description: 动态eq模块设置直通、正常处理 +* Arguments :*hdl:模块句柄 +* bypass:设置直通(RUN_BYPASS)、正常处理(RUN_NORMAL) +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void dynamic_eq_bypass(struct dynamic_eq *hdl, u8 bypass); + +/* +********************************************************************* +* dynamic_eq_bypass +* Description: 动态eq模块设置直通、正常处理 +* Arguments :*hdl:模块句柄 +* bypass:设置直通(RUN_BYPASS)、正常处理(RUN_NORMAL) +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +// void dynamic_eq_update(struct dynamic_eq *hdl, DynamicEQParam *param); +void dynamic_eq_update(struct dynamic_eq *hdl, DynamicEQEffectParam *effectParam, DynamicEQParam *param); + + +/* +********************************************************************* +* dynamic_eq_close +* Description: 动态eq检块关闭 +* Arguments :*hdl:模块句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void dynamic_eq_close(struct dynamic_eq *hdl); + + + + + + +#endif/*__DYNAMIC_EQ_H__*/ diff --git a/include_lib/media/effect_sur_api.h b/include_lib/media/effect_sur_api.h new file mode 100644 index 0000000..c971691 --- /dev/null +++ b/include_lib/media/effect_sur_api.h @@ -0,0 +1,108 @@ +#ifndef effectSUR_api_h__ +#define effectSUR_api_h__ + +/*单耳输入时,channel设置*/ +enum { + EFFECT_CH_L = 0x10, //单声道输入,输出左声道 + EFFECT_CH_R = 0x20, //单声道输入,输出右声道 + EFFECT_CH2_L = 0x30, //双声道输入,输出2个左声道 + EFFECT_CH2_R = 0x40, //双声道输入,输出2个右声道 +}; + +enum { + EFFECT_3D_TYPE0 = 0x01, + EFFECT_3D_TYPE1 = 0x02, //这2个2选1 :如果都置上,优先用EFFECT_3D_TYPE1 + EFFECT_3D_LRDRIFT = 0x04, + EFFECT_3D_ROTATE = 0x08, //这2个2选1 : 如果都置上,优先用EFFECT_3D_ROTATE + EFFECT_3D_TYPE2 = 0x10, + EFFECT_3D_LRDRIFT2 = 0x20, +}; + + +typedef struct __SUR_FUNC_API_ { + unsigned int (*need_buf)(int flag); + unsigned int (*open)(unsigned int *ptr, int effectflag, int nch); + unsigned int (*init)(unsigned int *ptr, int rotatestep, int damping, int feedback, int roomsize); + unsigned int (*run)(unsigned int *ptr, short *inbuf, int len); // len是对点 + unsigned int (*switch_effect)(unsigned int *ptr, int effectflag, int rotatestep, int damping, int feedback, int roomsize);//新增的切换音效参数接口 + unsigned int (*switch_nch)(unsigned int *ptr, int nch);//新增的声道修改接口 +} SUR_FUNC_API; + + +extern SUR_FUNC_API *get_sur_func_api(); + + + +#if 0 +因为复用其他音效的参数接口,所以还是用了4个参数,EFFECT_3D_TYPE2具体参数对应名称应该是 : { + int rotatestep; //无效参数 + int rot60_100ms; //范围0到150 + int wetgain ; //范围0到100 + int delay ; //范围0到100 +} + +默认参数可以用 FFECT_3D_TYPE2 {2, 90, 70, 100}, + +// 由于原本预留参数有些没留出来,为了可以调节频响之类的多效果,所以在原基础上通过把参数列表指针当做其中一个参数传进来 +// 如果 rot60_100ms小于0,wetgain=100的话, 那最后一个参数就是参数列表,这样就可以支持配置更多参数。 + +设置如下: + +flag = EFFECT_3D_TYPE2; +{ {2, -1, 100, surmode_present[MODE_SUR_KTV]}, + {2, -1, 100, surmode_present[MODE_SUR_3DTHE]}, + {2, -1, 100, surmode_present[MODE_SUR_HALL]}, + {2, -1, 100, surmode_present[MODE_SUR_VOICE]}, + {2, -1, 100, surmode_present[MODE_SUR_SUR]} +} + + +//其中参数示例: + +enum { + MODE_SUR_KTV = 0, //ktv模式 + MODE_SUR_3DTHE, //3D影院 + MODE_SUR_HALL, //音乐厅 + MODE_SUR_VOICE, //清澈人声 + MODE_SUR_SUR, //全景环绕 + MODE_SUR_MAX +}; + +//dry,wet,delay,rot60,Erwet,Erfactor,Ewidth,Ertolate,predelay,width,diffusion,dampinglpf,basslpf,bassB +const static int surmode_present[MODE_SUR_MAX][14] = { + {80, 100, 35, 9000, 80, 80, 80, 80, 20, 100, 70, 6500, 4000, 18}, + {80, 100, 90, 10030, 90, 90, 90, 90, 18, 100, 75, 7000, 1000, 29}, + {80, 100, 100, 13000, 100, 100, 100, 100, 20, 100, 72, 9000, 50, 3}, + {80, 100, 20, 5010, 100, 70, 70, 100, 15, 100, 70, 5500, 3500, 60}, + {80, 100, 100, 10000, 80, 80, 80, 90, 10, 100, 72, 8000, 500, 15}, +}; + + +//dry,wet,delay,Erwet,Erfactor,Ewitdh,Ertolate,width,diffusion 范围都是 0到 100 +//rot60 范围是 0到15000, 单位ms +//basslpf: 低频增强频率,范围 0到10000 +//dampinglpf: 高频衰减频率,范围 0到 10000 +//bassB: 低频增强比例 + + +混响调参说明: +1.dry: 干声增益 +2.wet: +整体效果声增益 +3.delay: 反射时间间隔,影响整体空间大小 +4.rot60: +衰减60dB需要的时间, 即衰减速度,如果空间里面的物体吸声厉害,或者比较空旷,衰减比较快 +5.Erwet:早反射声的增益, 早反射声的存在 会让混响听起来更真实。但是不同的增益会影响听感上距离感,空间构造 +6.Erfactor: 早反射声的一个密集程度。 这个值大,早反射声之间间隔比较大。构造的空间感也会相对较大。 较小的话,就反射比较密集。空间感变小。 +7.Ewidth:影响早反射声左右声道的声音差异 +8.Ertolate: +影响漫反射声音反馈的大小 +9.predelay:干声跟效果声的时间间隔。也会影响整体空间感。 +10.width:左右声道的差异,左右声道的差异,会产生立体感。(某些版本的sdk上该参数无效) +11.diffusion: 发散程度, 影响 漫反射声音的变形程度。 +12.dampinglpf:高频衰减过度频率。反射声的一个频率衰减,这是一个斜着往下掉的曲线,影响了反射声中的高频分量。高频分量越多,整体音色越亮,但是成分太多,声音有些乱 +13.basslpf:反射声中的低频增强分量过度频率 +14.bassB: +低频增强比例。 这里的低频增强,其实是压了高频。为了使整体频响不超过1,不引起反馈发散。所以加大了这个值感觉混响弱了。可以适量加大rot60或者Ertolate +#endif +#endif // reverb_api_h__ diff --git a/include_lib/media/effects_adj.h b/include_lib/media/effects_adj.h new file mode 100644 index 0000000..d60ffc3 --- /dev/null +++ b/include_lib/media/effects_adj.h @@ -0,0 +1,383 @@ +#ifndef __EFFECTS_ADJ__H +#define __EFFECTS_ADJ__H + + +#include "system/includes.h" +#include "config/config_interface.h" +#include "asm/crc16.h" +#include "generic/log.h" +#include "media/audio_eq.h" +#include "media/audio_drc.h" +#include "media/howling_api.h" +#include "media/sw_drc.h" +#include "media/DynamicEQ_api.h" +#include "media/DynamicEQ_Detection_api.h" +#include "media/reverb_api.h" +#include "media/noisegate_api.h" +#include "media/audio_gain_process.h" +#include "media/voiceChanger_api.h" +#include "media/audio_vbass.h" + +#define GAIN_PROCESS_EN 0 + +struct effect_adj { + u8 eq_type; + uint8_t password_ok; + struct __effect_mode_cfg *parm; + struct __tool_callback *cb; +}; + +typedef struct { + int cmd; /// byass 0 -> no bypass + REVERBN_PARM_SET parm; +} REVERBN_PARM_TOOL_SET; + +//reverb_palte 模块: +typedef struct _Plate_reverb_TOOL_SET_ { + int is_bypass; // 1-> byass 0 -> no bypass + Plate_reverb_parm parm; +} Plate_reverb_TOOL_SET; + +//reverb_filter模块: +typedef struct _EF_REVERB0__TOOL_SET_ { + int is_bypass; // 1-> byass 0 -> no bypass + EF_REVERB0_PARM parm; +} EF_REVERB0_TOOL_SET; + +//echo模块: +typedef struct _EF_ECHO_TOOL_SET_ { + int is_bypass; // 1-> byass 0 -> no bypass + ECHO_PARM_SET parm; +} EF_ECHO_TOOL_SET; + +//移频模块 HowlingPitchShift: +typedef struct _HowlingPs_PARM_TOOL_SET_ { + int is_bypass; // 1-> byass 0 -> no bypass + HOWLING_PITCHSHIFT_PARM parm; +} HowlingPs_PARM_TOOL_SET; + +typedef struct _NotchHowlingParam_TOOL_SET { + int is_bypass; // 1-> byass 0 -> no bypass + NotchHowlingParam parm; +} NotchHowlingParam_TOOL_SET; + +typedef struct _VoiceChangerParam_TOOL_SET { + int is_bypass; // 1-> byass 0 -> no bypass + VOICECHANGER_PARM parm; +} VoiceChangerParam_TOOL_SET; + + +typedef struct _NoiseGateParam_TOOL_SET { + int is_bypass; // 1-> byass 0 -> no bypass + noisegate_update_param parm; +} NoiseGateParam_TOOL_SET; + +typedef struct _gain_process_TOOL_SET { + int is_bypass; // 1-> byass 0 -> no bypass + struct aud_gain_parm_update parm; +} Gain_Process_TOOL_SET; + + +struct advance_iir { + int fc; + int order; + int type; +}; +// #低通 LowPass: +typedef struct _LowPassParam_TOOL_SET { + int is_bypass; // 1-> byass 0 -> no bypass + struct advance_iir low_pass; +} LowPassParam_TOOL_SET; + +// #高通 HighPass: +typedef struct _HighPassParam_TOOL_SET { + int is_bypass; // 1-> byass 0 -> no bypass + struct advance_iir high_pass; +} HighPassParam_TOOL_SET; + +//虚拟低音 +typedef struct _VirtualBass_TOOL_SET { + int is_bypass; // 1-> byass 0 -> no bypass + VirtualBassUdateParam parm; +} VirtualBass_TOOL_SET; + +//动态EQ DynamicEQ: +typedef struct _DynamicEQParam_TOOL_SET { + int is_bypass; // 1-> byass 0 -> no bypass + DynamicEQEffectParam effect_param[4]; + int nSection; //段数 + int detect_mode; //检测模式 +} DynamicEQParam_TOOL_SET; //实际发送这个结构体 + +#define OTHER_SECTION_MAX (5) +struct eq_tool { + float global_gain; + int seg_num; //eq效果文件存储的段数 + int enable_section; // + struct eq_seg_info seg[OTHER_SECTION_MAX]; //eq系数存储地址 +}; + +#define mSECTION_MAX (20) +struct music_eq_tool { + float global_gain; + int seg_num; //eq效果文件存储的段数 + int enable_section; // + struct eq_seg_info seg[mSECTION_MAX]; //eq系数存储地址 +}; + +#define mSECTION_MAX2 (10) +struct music_eq2_tool { + float global_gain; + int seg_num; //eq效果文件存储的段数 + int enable_section; // + struct eq_seg_info seg[mSECTION_MAX2]; //eq系数存储地址 +}; + + +struct phone_parm_tool_set { + struct eq_tool eq_parm; + wdrc_struct_TOOL_SET drc_parm; +}; + +struct nband_drc { + CrossOverParam_TOOL_SET crossover; + wdrc_struct_TOOL_SET wdrc_parm[4];//[0]low [1]mid [2]high [3]多带之后附加的全带 +}; + + +struct music_parm_tool_set { + struct music_eq_tool eq_parm; + struct nband_drc drc_parm; +}; + +struct eff_parm { + NoiseGateParam_TOOL_SET noise_gate_parm; + HowlingPs_PARM_TOOL_SET howlingps_parm; + NotchHowlingParam_TOOL_SET notchhowling_parm; + VoiceChangerParam_TOOL_SET voicechanger_parm; + Plate_reverb_TOOL_SET plate_reverb_parm; + EF_ECHO_TOOL_SET echo_parm; + struct eq_tool eq_parm[5]; + wdrc_struct_TOOL_SET drc_parm[5]; +#if GAIN_PROCESS_EN + Gain_Process_TOOL_SET gain_parm;//增益 +#endif +}; + + +void get_eff_mode(u16 mode_id, u16 group_id, u8 *mode_index, u8 *drc_index);//获取混响模式的index +int get_phone_mode(u16 group_id); +int get_group_id(u16 mode_name, u8 tar); +int get_eq_nsection(u16 module_name); + +void noisegate_update_parm(void *parm, int bypass); +void plate_reverb_update_parm(void *parm, int bypass); +void echo_updata_parm(void *parm, int bypass); +void howling_pitch_shift_update_parm(void *parm, int bypass); +void notchhowline_update_parm(void *parm, int bypass); +void audio_dynamic_eq_update_parm(void *parm, void *parm2, int bypass); +void audio_dynamic_eq_detection_update_parm(void *parm, int bypas); +void mic_gain_update_parm(u16 gain_name, void *parm, int bypass); +void set_mic_reverb_mode_by_id(u8 mode); + +void phone_eff_default_parm(void); +void music_eff_default_parm(void); +void mic_eff_default_parm(u8 index); +void linein_eff_default_parm(void); +void cp_eq_file_seg_to_custom_tab(); + + +struct cmd_interface { + u32 cmd; + int (*cmd_deal)(EFF_ONLINE_PACKET *packet, u8 id, u8 sq); +}; + +#define REGISTER_CMD_TARGET(cmd_eff) \ + const struct cmd_interface cmd_eff sec(.eff_cmd) + +extern const struct cmd_interface cmd_interface_begin[]; +extern const struct cmd_interface cmd_interface_end[]; + +#define list_for_each_cmd_interface(p) \ + for (p = (struct cmd_interface *)cmd_interface_begin; p < (struct cmd_interface *)cmd_interface_end; p++) + +#define phone_eq_nsection OTHER_SECTION_MAX +#define music_eq_nsection 10 +#define music_eq2_nsection 10 +#define mic_eq_nsection OTHER_SECTION_MAX + + + +#endif/*__EFFECTS_ADJ__H*/ diff --git a/include_lib/media/eq_config.h b/include_lib/media/eq_config.h new file mode 100644 index 0000000..0d89e6b --- /dev/null +++ b/include_lib/media/eq_config.h @@ -0,0 +1,685 @@ +#ifndef _EQ_CONFIG_H_ +#define _EQ_CONFIG_H_ + +#include "media/audio_eq.h" +#include "media/audio_drc.h" +#include "spinlock.h" +#include "math.h" +#if 0 +/*-----------------------------------------------------------*/ +/*eq online cmd*/ +enum { + EQ_ONLINE_CMD_SECTION = 1, + EQ_ONLINE_CMD_GLOBAL_GAIN, + EQ_ONLINE_CMD_LIMITER, + EQ_ONLINE_CMD_INQUIRE, + EQ_ONLINE_CMD_GETVER, + EQ_ONLINE_CMD_GET_SOFT_SECTION,//br22专用 + EQ_ONLINE_CMD_GET_SECTION_NUM = 0x7,//工具查询 小机需要的eq段数 + EQ_ONLINE_CMD_GLOBAL_GAIN_SUPPORT_FLOAT = 0x8, + + + EQ_ONLINE_CMD_PASSWORD = 0x9, + EQ_ONLINE_CMD_VERIFY_PASSWORD = 0xA, + EQ_ONLINE_CMD_FILE_SIZE = 0xB, + EQ_ONLINE_CMD_FILE = 0xC, + EQ_EQ_ONLINE_CMD_GET_SECTION_NUM = 0xD,//该命令新加与 0x7功能一样 + EQ_EQ_ONLINE_CMD_CHANGE_MODE = 0xE,//切模式 + + EQ_ONLINE_CMD_MODE_COUNT = 0x100,//模式个数a 1 + EQ_ONLINE_CMD_MODE_NAME = 0x101,//模式的名字a eq + EQ_ONLINE_CMD_MODE_GROUP_COUNT = 0x102,//模式下组的个数,4个字节 1 + EQ_ONLINE_CMD_MODE_GROUP_RANGE = 0x103,//模式下组的id内容 0x11 + EQ_ONLINE_CMD_EQ_GROUP_COUNT = 0x104,//eq组的id个数 1 + EQ_ONLINE_CMD_EQ_GROUP_RANGE = 0x105,//eq组的id内容 0x11 + EQ_ONLINE_CMD_MODE_SEQ_NUMBER = 0x106,//mode的编号 magic num + + + EQ_ONLINE_CMD_PARAMETER_SEG = 0x11, + EQ_ONLINE_CMD_PARAMETER_TOTAL_GAIN, + EQ_ONLINE_CMD_PARAMETER_LIMITER, + EQ_ONLINE_CMD_PARAMETER_DRC, + EQ_ONLINE_CMD_PARAMETER_CHANNEL,//通道切换 + + EQ_ONLINE_CMD_WRITE_FILE_SIZE = 0x20, //准备写入文件 + EQ_ONLINE_CMD_WRITE_FILE_CHANNEL = 0x21, + + EQ_ONLINE_CMD_SONG_EQ_SEG = 0x2001, + EQ_ONLINE_CMD_CALL_EQ_SEG = 0x2002, + EQ_ONLINE_CMD_AEC_EQ_SEG = 0x2003, + + EQ_ONLINE_CMD_SONG_EQ_V1_SEG = 0x2011,// float gain, float q + EQ_ONLINE_CMD_CALL_EQ_V1_SEG = 0x2012, + EQ_ONLINE_CMD_AEC_EQ_V1_SEG = 0x2013, + + + EQ_ONLINE_CMD_SONG_DRC = 0x2101, + EQ_ONLINE_CMD_SONG_WDRC = 0x2102, +//add xx here + + EQ_ONLINE_CMD_MAX,//最后一个 +}; + +#define CONSTRAINT_OP_DRC_L_R_CH 0x01 +#define CONSTRAINT_OP_DRC_WDRC_SINGLE_CH 0x02 +#define CONSTRAINT_OP_DRC_WDRC_DUAL_CH 0x03 + + +/*eq online packet*/ +typedef struct { + int cmd; ///eq_seg_tab) { + int size = sizeof(your_audio_out_eq_tab); + eq->eq_seg_tab = zalloc(size); + memcpy(eq->eq_seg_tab, your_audio_out_eq_tab, size); + } + if (!eq->eq_coeff_tab) { + eq->eq_coeff_tab = zalloc(sizeof(int) * 5 * nsection); + } + for (int i = 0; i < nsection; i++) { + eq_seg_design(&eq->eq_seg_tab[i], sr, &eq->eq_coeff_tab[5 * i]); + } + + local_irq_enable(); + info->L_coeff = info->R_coeff = (void *)eq->eq_coeff_tab; + info->L_gain = info->R_gain = 0; + info->nsection = nsection; +#else + local_irq_disable(); + u8 nsection = ARRAY_SIZE(your_audio_out_eq_tab); + for (int i = 0; i < nsection; i++) { + eq_seg_design(&your_audio_out_eq_tab[i], sr, &your_eq_coeff_tab[i]); + } + local_irq_enable(); + info->L_coeff = info->R_coeff = (void *)your_eq_coeff_tab;//系数指针赋值 + info->L_gain = info->R_gain = 0;//总增益填写,用户可修改(-20~20db) + info->nsection = nsection;//eq段数,根据提供给的系数表来填写,例子是2 + +#endif + return 0; +} + +struct drc_ch drc_fliter = {0}; +#define your_threshold (0) +/*----------------------------------------------------------------------------*/ +/**@brief 自定义限幅器系数回调 + @param *drc: 句柄 + @param *info: 系数结构地址 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int drc_get_filter_info_demo(void *drc, struct audio_drc_filter_info *info) +{ + int th = your_threshold;//-60 ~0db + int threshold = round(pow(10.0, th / 20.0) * 32768); // 0db:32768, -60db:33 + + drc_fliter.nband = 1; + drc_fliter.type = 1; + drc_fliter._p.limiter[0].attacktime = 5; + drc_fliter._p.limiter[0].releasetime = 300; + drc_fliter._p.limiter[0].threshold[0] = threshold; + drc_fliter._p.limiter[0].threshold[1] = 32768; + + info->pch = info->R_pch = &drc_fliter; + return 0; +} + + + + +struct drc_ch drc_fliter2 = {0}; +#define your_threshold1 (0) +#define your_threshold2 (0) +/*----------------------------------------------------------------------------*/ +/**@brief 自定义压缩器系数回调 + @param *drc: 句柄 + @param *info: 系数结构地址 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int drc_get_filter_info_demo2(void *drc, struct audio_drc_filter_info *info) +{ + int th1 = your_threshold1;//-60 ~0db + int th2 = your_threshold2;//-60 ~0db + + int your_ratio0 = 800;//100~1000 + int your_ratio1 = 900;//100~1000 + + + if (th2 < th1) { //阈值2需大于等于阈值1 + th2 = th1; + } + if (your_ratio1 < your_ratio0) { //压缩比2需要大于等于压缩比1 + your_ratio1 = your_ratio0; + } + + int threshold0 = round(pow(10.0, th1 / 20.0) * 32768); // 0db:32768, -60db:33 + int threshold1 = round(pow(10.0, th2 / 20.0) * 32768); // 0db:32768, -60db:33 + + drc_fliter2.nband = 1;//全带 + drc_fliter2.type = 2;//压缩器 + drc_fliter2._p.compressor[0].attacktime = 5; + drc_fliter2._p.compressor[0].releasetime = 300; + drc_fliter2._p.compressor[0].threshold[0] = threshold0; + drc_fliter2._p.compressor[0].threshold[1] = threshold1; + drc_fliter2._p.compressor[0].threshold[2] = 32768; + + drc_fliter2._p.compressor[0].ratio[0] = 100; + drc_fliter2._p.compressor[0].ratio[1] = your_ratio0; + drc_fliter2._p.compressor[0].ratio[2] = your_ratio1; + + info->pch = info->R_pch = &drc_fliter2; + return 0; +} + +//修改自定义模式eq系数表,更新系数到eq 方法 +// 板极头文件中 这两宏 配0 +#define TCFG_EQ_ONLINE_ENABLE 0 //支持在线EQ调试, +#define TCFG_USE_EQ_FILE 0 //离线eq使用配置文件还是默认系数表 1:使用文件 0 使用默认系数表 + + +// 在sdk中实现以下接函数 +/*----------------------------------------------------------------------------*/ +/**@brief 设置用户自定义模式每段eq信息 + @param + @param + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int eq_mode_set_custom_info_user(struct eq_seg_info *seg) +{ + if (!config_audio_eq_file_en) { + if (!seg) { + return 0; + } + u16 index = seg->index; //第几段eq + EQ_CFG *eq_cfg = get_eq_cfg_hdl(); + if (index >= eq_cfg->section_max) { + return 0; + } + int *tmp = (int *)eq_cfg->eq_type_tab; + EQ_CFG_SEG *tab_custom = (EQ_CFG_SEG *)tmp[EQ_MODE_CUSTOM]; + + index = eq_cfg->eq_mode_use_idx[index]; + memcpy(&tab_custom[index], seg, sizeof(struct eq_seg_info));//更新参数到自定义模式系数表 + + /* log_debug("idx:%d, iir:%d, freq:%d, gain:%d, q:%d ", seg->index, seg->iir_type, seg->freq, seg->gain, seg->q); */ + } + return 0; +} +/*----------------------------------------------------------------------------*/ +/**@brief 获取某个模式eq表内,某一段eq的信息 + @param + @param + @return 返回eq信息 + @note +*/ +/*----------------------------------------------------------------------------*/ +struct eq_seg_info *eq_mode_get_custom_info_user(EQ_MODE mode, u8 index) +{ + if (!config_audio_eq_file_en) { + EQ_CFG *eq_cfg = get_eq_cfg_hdl(); + if (index >= eq_cfg->section_max) { + return 0; + } + int *tmp = (int *)eq_cfg->eq_type_tab; + EQ_CFG_SEG *seg = (EQ_CFG_SEG *)tmp[mode]; + + index = eq_cfg->eq_mode_use_idx[index]; + /* log_debug("idx:%d, iir:%d, freq:%d, gain:%d, q:%d ", seg->index, seg->iir_type, seg->freq, seg->gain, seg->q); */ + return &seg[index]; + } + return 0; +} +/*设置总增益后,需要设置更新*/ +void update_global_gain_demo(float global_gain) +{ + EQ_CFG *eq_cfg = get_eq_cfg_hdl(); + set_global_gain(eq_cfg, song_eq_mode, global_gain);//设置总增益, + eq_mode_set(EQ_MODE_CUSTOM);//设置自定义模式、更新系数以及总增益 +} + +/*设置参数后,需要设置更新*/ +void update_eq_seg_info_demo(struct eq_seg_info *seg) +{ + eq_mode_set_custom_info_user(seg);//更新参数到自定义模式系数表 + eq_mode_set(EQ_MODE_CUSTOM);//设置自定义模式、更新系数以及总增益 +} +void update_custom_info_demo2(u16 index, int freq, int gain) +{ + eq_mode_set_custom_info(index, freq, gain);/*改某一段eq的的中心截止频率 以及增益*/ + eq_mode_set(EQ_MODE_CUSTOM);//设置自定义模式、更新系数以及总增益 +} + +#endif + +#endif +#endif diff --git a/include_lib/media/eq_func_define.h b/include_lib/media/eq_func_define.h new file mode 100644 index 0000000..1076146 --- /dev/null +++ b/include_lib/media/eq_func_define.h @@ -0,0 +1,69 @@ +#ifndef _EQ_FUNC_DEFINE_H +#define _EQ_FUNC_DEFINE_H + +#include "generic/typedef.h" + +extern u32 EQ_PRIV_SECTION_NUM; +extern u32 EQ_SECTION_NUM; +extern const int const_eq_debug; +extern const int config_audio_drc_en; +extern const int config_audio_eq_en; +enum { + EQ_EN = BIT(0),//eq模式使能 + EQ_SUPPORT_OLD_VER_EN = BIT(1),//ac700N,使能该bit可版本0.7.1.0, 0.7.1.1 + EQ_LITE_VER_EN = BIT(2),//精简版版本eq驱动,不支持异步,不支持默认效果切换接口,仅支持文件解析 + EQ_ONLINE_EN = BIT(3), //在线调试模块使能 + EQ_FILE_EN = BIT(4),//打开支持文件解析,关闭则只能使用默认效果表做eq + EQ_FILE_SWITCH_EN = BIT(5),//打开支持eq_cfg_hw.bin文件切换更新效果 + EQ_HIGH_BASS_EN = BIT(6),//eq内部集成的高低音接口使能 + EQ_HIGH_BASS_FADE_EN = BIT(7),//eq内部集成高低音淡入淡出效果方式使能,配合config_audio_eq_fade_step使用 + EQ_FILTER_COEFF_FADE_EN = BIT(8),//eq默认系数表效果切换,或者在线调试效果更新,使用淡入淡出方式,避免增益跳跃引起的杂音问题 + EQ_FILTER_COEFF_LIMITER_ZERO_EN = BIT(9),// + EQ_HW_UPDATE_COEFF_ONLY_EN = BIT(10),// 有空闲的段可以使用,就不需要切换系数 */ + EQ_HW_LR_ALONE = BIT(11),//// 左右声道分开处理与bit(10),同时使能或关闭 + EQ_SUPPORT_32BIT_SYNC_EN = BIT(12),//// 支持同步方式32biteq + EQ_SUPPORT_MULIT_CHANNEL_EN = BIT(13),//AC699N、AC700N eq是否支持多声道(3~8) 打开:支持 关闭:仅支持1~2声道 + EQ_HW_CROSSOVER_TYPE0_EN = BIT(14),//支持硬件分频器,且分频器使用序列进序列出,需使能BIT(13) + EQ_HW_CROSSOVER_TYPE1_EN = BIT(15),//硬件分频器使用使用块出方式,会增加mem(该方式仅支持单声道处理) + EQ_LR_DIVIDE_EN = BIT(16),//eq左右声道效果拆分,四声道时可能会使用 + EQ_ONLINE_FILE_SAVE = BIT(17),//eq在线调试保存到vm使能 + EQ_DRC_PROCESS_SPLIT = BIT(18),//eq/drc节点处理,支持拆分 +}; + +#define config_audio_eq_online_en (config_audio_eq_en & EQ_ONLINE_EN) +#define config_audio_eq_file_en (config_audio_eq_en & EQ_FILE_EN) +#define config_audio_eq_file_sw_en (config_audio_eq_en & EQ_FILE_SWITCH_EN) +#define config_filter_coeff_fade_en (config_audio_eq_en & EQ_FILTER_COEFF_FADE_EN) +#define config_high_bass_en (config_audio_eq_en & EQ_HIGH_BASS_EN) +#define config_audio_eq_fade_en (config_audio_eq_en & EQ_HIGH_BASS_FADE_EN) +#define config_filter_coeff_limit_zero (config_audio_eq_en & EQ_FILTER_COEFF_LIMITER_ZERO_EN) +#define HW_EQ_UPDATE_COEFF_ONLY_EN (config_audio_eq_en & EQ_HW_UPDATE_COEFF_ONLY_EN) +#define HW_EQ_LR_ALONE (config_audio_eq_en & EQ_HW_LR_ALONE) +#define SUPPORT_32BIT_SYNC_EQ (config_audio_eq_en & EQ_SUPPORT_32BIT_SYNC_EN) +#define hw_eq_support_multi_channels (config_audio_eq_en & EQ_SUPPORT_MULIT_CHANNEL_EN) +#define hw_crossover_type0 (config_audio_eq_en & EQ_HW_CROSSOVER_TYPE0_EN) +#define hw_crossover_type1 (config_audio_eq_en & EQ_HW_CROSSOVER_TYPE1_EN) +#define config_eq_lite_en (config_audio_eq_en & EQ_LITE_VER_EN) +#define config_eq_support_old_ver_en (config_audio_eq_en & EQ_SUPPORT_OLD_VER_EN) +#define config_divide_en (config_audio_eq_en & EQ_LR_DIVIDE_EN) +#define config_eq_online_file_save (config_audio_eq_en & EQ_ONLINE_FILE_SAVE) +#define config_eq_drc_process_split (config_audio_eq_en & EQ_DRC_PROCESS_SPLIT) + +extern const int config_audio_drc_en; +enum { + DRC_EN = BIT(0), //drc 使能 + DRC_NBAND_MERGING_ASM_EN = BIT(1),//drc 多带处理完后,多带合并使用汇编加速 + DRC_NBAND_DIS = BIT(2),//关闭drc多带 + DRC_LIMITER_DIS = BIT(3),//关闭drc限幅器 + DRC_COMPRESSOF_DIS = BIT(4),//关闭drc压缩器 + WDRC_TYPE_EN = BIT(5),//wdrc使能 +}; + +#define config_drc_limiter_en (!(config_audio_drc_en & DRC_LIMITER_DIS)) +#define config_drc_compressor_en (!(config_audio_drc_en & DRC_COMPRESSOF_DIS)) +#define config_drc_nband_en (!(config_audio_drc_en & DRC_NBAND_DIS)) +#define config_drc_nband_merg_asm_en (!(config_audio_drc_en & DRC_NBAND_MERGING_ASM_EN)) +#define config_wdrc_en (config_audio_drc_en & WDRC_TYPE_EN) + + +#endif diff --git a/include_lib/media/howling_api.h b/include_lib/media/howling_api.h new file mode 100644 index 0000000..29db6f9 --- /dev/null +++ b/include_lib/media/howling_api.h @@ -0,0 +1,53 @@ +#ifndef HOWLING_API_H +#define HOWLING_API_H + +#include "media/howling_pitchshifter_api.h" +// #include "shiftPhase_api.h" +#include "pemafrow_api.h" +#include "media/audio_stream.h" +typedef struct s_howling_para { + float notch_Q;//陷波器 Q值 + float notch_gain;//陷波器gain值 + int fade_time; //fade time + float threshold; //初始化阈值 + // int depth; //陷波器深度 + // int bandwidth;//陷波器带宽 + int sample_rate; + int channel; + // float mode;//陷波器是否降采样 +} HOWLING_PARM_SET; + +//啸叫抑制 NotchHowling: +typedef struct _NotchHowlingParam { + float Q; //Q值 + float gain; //增益 + int fade_n; //启动释放时间 + float threshold; +} NotchHowlingParam; + + + +typedef struct _HOWLING_API_STRUCT_ { + HOWLING_PARM_SET parm; //陷波参数 + void *ptr; //运算buf指针 + HOWLING_PITCHSHIFT_PARM parm_2; //移频参数 + HOWLING_PITCHSHIFT_FUNC_API *func_api; //移频函数指针 + struct audio_stream_entry entry; // 音频流入口 + s16 *pre_buf; + u32 sample_rate; + u8 run_en; + u8 mode; + u8 update; +} HOWLING_API_STRUCT; + +// int get_howling_buf(void); +// void howling_init(void *workbuf, int threshold, int depth, int bandwidth, int attackTime, int releaseTime, int Noise_threshold, int low_th_gain, int sampleRate, int channel); +// int howling_run(void *workbuf, short *in, short *out, int len); +int get_howling_buf(int sampleRate); +// void howling_init(void *workbuf, int fade_n,float notch_gain,float notch_Q, int mode, int sampleRate); +// void howling_init(void *workbuf, int fade_time, float notch_gain, float notch_Q, int sampleRate); +void howling_init(void *workbuf, int fade_time, float notch_gain, float notch_Q, float threshold, int sampleRate); +// void howling_run(void *workbuf, short *in, short *out, int len); +int howling_run(void *workbuf, short *in, short *out, int len); + +#endif diff --git a/include_lib/media/howling_pitchshifter_api.h b/include_lib/media/howling_pitchshifter_api.h new file mode 100644 index 0000000..0af32f4 --- /dev/null +++ b/include_lib/media/howling_pitchshifter_api.h @@ -0,0 +1,63 @@ + +#ifndef HOWLING_pitchshifer_api_h__ +#define HOWLING_pitchshifer_api_h__ + +#ifndef u8 +#define u8 unsigned char +#endif + +#ifndef u16 +#define u16 unsigned short +#endif + +#ifndef s16 +#define s16 short +#endif + + +#ifndef u32 +#define u32 unsigned int +#endif + + +#ifndef s32 +#define s32 int +#endif + +#ifndef s16 +#define s16 signed short +#endif + +/*#define EFFECT_OLD_RECORD 0x01 +#define EFFECT_MOYIN 0x0*/ +//#define EFFECT_ROBORT_FLAG 0X04 + +enum { + EFFECT_HOWLING_PS = 0x01, //1.5《=》12 ms + EFFECT_HOWLING_HE = 0x02, + EFFECT_HOWLING_FS = 0x04, +}; + +enum { + PLATFORM_BR30 = 0, + PLATFORM_BR36 = 1 +}; + +typedef struct HOWLING_PITCHSHIFT_PARM_ { + s16 ps_parm; + s16 fe_parm; + u32 effect_v; +} HOWLING_PITCHSHIFT_PARM; + + + +typedef struct _HOWLING_PITCHSHIFT_FUNC_API_ { + u32(*need_buf)(int flag); + void (*open)(void *ptr, u32 sr, HOWLING_PITCHSHIFT_PARM *pitchshift_obj); //中途改变参数,可以调init + void (*run)(void *ptr, short *indata, short *outdata, int len); //len是多少个byte +} HOWLING_PITCHSHIFT_FUNC_API; + +extern HOWLING_PITCHSHIFT_FUNC_API *get_howling_ps_func_api(); + +#endif // reverb_api_h__ + diff --git a/include_lib/media/lfwordana_enc.h b/include_lib/media/lfwordana_enc.h new file mode 100644 index 0000000..cea2647 --- /dev/null +++ b/include_lib/media/lfwordana_enc.h @@ -0,0 +1,21 @@ +#ifndef __LF_WORDANA_ENC__ +#define __LF_WORDANA_ENC__ +#include "system/includes.h" +#include "media/audio_encoder.h" +#include "generic/includes.h" +#include "media/w2s_handle_api.h" +#include "asm/audio_adc.h" + +struct lfwordana_encoder { + void *buf_ptr; + w2s_ana_ops *ops; + REC_W2S_STUCT w2s_parmIn; + MIDI_W2S_STRUCT w2s_parmOut; +}; + +struct lfwordana_encoder *lfwordana_encoder_open(REC_W2S_STUCT *parm); +int lfwordana_encoder_run(struct lfwordana_encoder *ana, void *data, u32 len); +void lfwordana_encoder_close(struct lfwordana_encoder *ana); + + +#endif /* __LF_WORDANA_ENC__ */ diff --git a/include_lib/media/localtws_decoder.h b/include_lib/media/localtws_decoder.h new file mode 100644 index 0000000..c7df764 --- /dev/null +++ b/include_lib/media/localtws_decoder.h @@ -0,0 +1,59 @@ +#ifndef LOCALTWS_DECODER_H +#define LOCALTWS_DECODER_H + + +#include "media/includes.h" + +enum { + LOCALTWS_DEC_STATUS_STOP = 0, // 解码停止 + LOCALTWS_DEC_STATUS_PLAY, // 正在解码 +}; + +struct localtws_decoder { + u32 ch_num : 4; // 声道数 + u32 output_ch_num : 4; // 输出声道数 + u32 output_ch_type : 4; // 输出声道类型 + u32 status : 3; // 解码状态 + u32 read_en : 1; // 开始解码 + u32 tmp_pause : 1; // 被其他解码打断,临时暂停 + u32 need_get_fmt : 1; // 需要获取音频信息 + u32 sync_step : 3; + u32 preempt_state : 4; + u32 remain_flag : 1; // 输出剩余标记 + u32 fade_out : 1; // 淡出 + s16 fade_step; // 淡入淡出步进数 + s16 fade_value; // 淡入淡出记录值 + u32 fade_out_mute_points; // 淡出后静音点数 + u32 wait_time; + int begin_delay_time; + void *sync; + u16 resume_timeout; + // u16 drop_samples; + u32 dec_type; // 解码类型 + u16 sample_rate; // 采样率 + u16 sbc_header_len; // sbc头部长度 + u8 *tws_ptr; // tws数据 + u32 tws_len; // tws数据长度 + u32 tws_ulen; // tws数据使用长度 + struct audio_decoder_task *decode_task; // 解码任务 + enum audio_channel ch_type; // 输出类型 + struct audio_decoder decoder; // 解码句柄 + u8(*tws_master)(void); +}; + + +int localtws_decoder_open(struct localtws_decoder *, struct audio_decoder_task *decode_task); + +void localtws_decoder_close(struct localtws_decoder *dec); + +void localtws_decoder_set_output_channel(struct localtws_decoder *dec); + +void localtws_decoder_stream_sync_enable(struct localtws_decoder *dec, + void *sync, + int delay_time, + u8(*master)(void)); + +void localtws_decoder_resume_pre(void); + +#endif /*A2DP_DECODER_H*/ + diff --git a/include_lib/media/media_develop/media/MIDI_CTRL_API.h b/include_lib/media/media_develop/media/MIDI_CTRL_API.h new file mode 100644 index 0000000..e9fa743 --- /dev/null +++ b/include_lib/media/media_develop/media/MIDI_CTRL_API.h @@ -0,0 +1,52 @@ +#ifndef MIDI_CTRL_API_h__ +#define MIDI_CTRL_API_h__ + +#include "MIDI_DEC_API.h" + +#include "typedef.h" + + +typedef struct _EVENT_CONTEXT_ { + u8 msg; + u8 val1; + u8 val2; + u8 trk_num; + u16 delta; +} EVENT_CONTEXT; + +typedef struct _MIDI_CTRL_PARM_ { + char track_num; //0-15支持音轨的最大个数 + unsigned int tempo; //tempo + void *priv; //模块内部使用 + u32(*output)(void *priv, void *data, int len);//模块内部使用 +} MIDI_CTRL_PARM; + +typedef struct _MIDI_CTRL_CONTEXT_ { + u32(*need_workbuf_size)() ; //<获取需要的buffer + u32(*open)(void *work_buf, void *dec_parm, void *parm); //跟解码一样的配置 + u32(*run)(void *work_buf); //播放 + u32(*set_prog)(void *work_buf, u8 prog, u8 trk_num); //设置乐器号, 音轨0~15 + u32(*note_on)(void *work_buf, u8 nkey, u8 nvel, u8 chn); //指定播放单个音符,nkey跟nvel的有效值是0-127,chn 0~15 + u32(*note_off)(void *work_buf, u8 nkey, u8 chn); //指定播放单个音符,nkey跟nvel的有效值是0-127 + u32(*pitch_bend)(void *work_buf, u16 pitch_val, u8 chn); //弯音轮值pitch_val 1 - 65535 ;256是正常值,对音高有作用 + u32(*ctl_confing)(void *work_buf, u32 cmd, void *parm); +} MIDI_CTRL_CONTEXT; + + +#define MIDI_CTRLC_NOTEOFF 0x80 //按键松开 +#define MIDI_CTRLC_NOTEON 0x90 //按键按下 +#define MIDI_CTRLC_CTLCHG 0xB0 +#define MIDI_CTRLC_PRGCHG 0xC0 //改变乐器 +#define MIDI_CTRLC_PWCHG 0xE0 + +#define MIDI_CTRLC_VOL 0x07 +#define MIDI_CTRLC_EXPR 0x0B +#define MIDI_CTRLC_SFT_ON 0x43 + + + +extern MIDI_CTRL_CONTEXT *get_midi_ctrl_ops(); + + +#endif // MIDI_CTRL_API_h__ + diff --git a/include_lib/media/media_develop/media/MIDI_DEC_API.h b/include_lib/media/media_develop/media/MIDI_DEC_API.h new file mode 100644 index 0000000..4e23aa7 --- /dev/null +++ b/include_lib/media/media_develop/media/MIDI_DEC_API.h @@ -0,0 +1,319 @@ + +#ifndef MIDI_DEC_API_h__ +#define MIDI_DEC_API_h__ +#include "w2s_handle_api.h" + +#define test_or32_midi_n 0 +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +//sdk添加const int MAX_PLAYER_CNT = 18;同时发声可配置的最大数[1,32] + +typedef struct _MIDI_CONFIG_PARM_ { + + unsigned int spi_pos; // sdk添加 const int MIDI_TONE_MODE = 0; 这个变量控制是0用音色地址,还是1读音色文件。 + unsigned char sample_rate; // 采样率0 - 8 对应采样率表{48000,44100,32000,24000,22050,16000,12000,11025,8000} + short player_t; // 最多同时发声的key数,最大值为MAX_PLAYER_CNT + + int(*fread)(void *file, void *buf, u32 len); + int(*fseek)(void *file, u32 offset, int seek_mode); +} MIDI_CONFIG_PARM; + + + +#define VOL_Norm_Bit 12 + +#define CTRL_CHANNEL_NUM 16 + +typedef struct _EX_CH_VOL_PARM_ { + unsigned short cc_vol[CTRL_CHANNEL_NUM]; //16个通道或轨道的音量 <=>4096等于原音量 + unsigned char ex_vol_use_chn; //ex_vol_use_chn = 0 轨道音量;ex_vol_use_chn = 1 通道音量 +} EX_CH_VOL_PARM; + + +typedef struct _EX_INFO_STRUCT_ { + void *priv; + u32(*mark_trigger)(void *priv, u8 *val, u8 len); //标记回调,val 标记名称 len 字节数 +} EX_INFO_STRUCT; + + +typedef struct _EX_TmDIV_STRUCT_ { //小节回调 + void *priv; + u32(*timeDiv_trigger)(void *priv); +} EX_TmDIV_STRUCT; + +typedef struct _EX_BeatTrig_STRUCT_ { //节拍回调/*val1 一节多少拍, val2每拍多少分音符*/ + void *priv; + u32(*beat_trigger)(void *priv, u8 val1, u8 val2); +} EX_BeatTrig_STRUCT; + +typedef struct _EX_MELODY_STRUCT_ { //主旋律音符回调 vel 为按键力度 + void *priv; + u32(*melody_trigger)(void *priv, u8 key, u8 vel); +} EX_MELODY_STRUCT; + + +typedef struct _EX_MELODY_STOP_STRUCT_ { //主旋律音符停止回调 + void *priv; + u32(*melody_stop_trigger)(void *priv, u8 key); +} EX_MELODY_STOP_STRUCT; + +#define CMD_MODE4_PLAY_END 0x09 + +enum { + CMD_MIDI_SEEK_BACK_N = 0xa0, //小节回调 MIDI_SEEK_BACK_STRUCT 变量 + CMD_MIDI_SET_CHN_PROG, //配置主通道乐器或者所有的通道乐器 MIDI_PROG_CTRL_STRUCT 变量 + CMD_MIDI_CTRL_TEMPO, //配置节奏及衰减 MIDI_PLAY_CTRL_TEMPO 变量 + CMD_MIDI_GOON, //okon 发声 参数为空 + CMD_MIDI_CTRL_MODE, //配置midi模式 MIDI_PLAY_CTRL_MODE 变量 + CMD_MIDI_SET_SWITCH, //配置使能 MIDI_SET_SWITCH 变量 + CMD_MIDI_SET_EX_VOL, //配置外部音量 EX_CH_VOL_PARM 变量 + CMD_INIT_CONFIG, //初始化配置 MIDI_INIT_STRUCT 变量 + CMD_MIDI_OKON_MODE //配置OKON模式 MIDI_OKON_MODE 变量 +}; + +enum { + CMD_MIDI_CTRL_MODE_0 = 0X00, // 正常解码 + CMD_MIDI_CTRL_MODE_1 = 0X01, //OKON 模式 + CMD_MIDI_CTRL_MODE_2, // 只推消息,不出声 + CMD_MIDI_CTRL_MODE_W2S //外部音源 +}; + +enum { + CMD_MIDI_OKON_MODE_0 = 0x00, //主旋 okon + CMD_MIDI_OKON_MODE_1 //主副旋一起 okon +}; + +enum { + CMD_MIDI_MELODY_KEY_0 = 0x00, //melody_trigger 回调当前音符 + CMD_MIDI_MELODY_KEY_1 // melody_trigger 回调下一个音符 +}; + + +typedef struct _MIDI_PLAY_CTRL_MODE_ { + u8 mode; +} MIDI_PLAY_CTRL_MODE; //用于配置midi模式 + +typedef struct _MIDI_OKON_MODE_ { + u8 Melody_Key_Mode; + u8 OKON_Mode; +} MIDI_OKON_MODE; //用于配置OKON模式 + +typedef struct _MIDI_PLAY_CTRL_TEMPO_ { + u16 tempo_val; + u16 decay_val[CTRL_CHANNEL_NUM]; //1024 低11bit有效 + u32 mute_threshold; +} MIDI_PLAY_CTRL_TEMPO; //用于配置节奏及衰减 + + + +typedef struct _MIDI_CHNNEL_CTRL_STRUCT_ { + u8 chn; +} MIDI_CHNNEL_CTRL_STRUCT; + +typedef struct _MIDI_PROG_CTRL_STRUCT_ { + u8 prog; //乐器号 + u8 replace_mode; //replace_mode==1,就是 替换所有通道; 否则替换主通道 + u16 ex_vol; //1024是跟原来一样大, 变化为原来的(ex_vol/1024)倍 +} MIDI_PROG_CTRL_STRUCT; //用于配置主通道乐器或者替换所有的通道 + +typedef struct _MIDI_SEEK_BACK_STRUCT_ { + s8 seek_back_n; +} MIDI_SEEK_BACK_STRUCT; //回调多少小节 + + +enum { + MARK_ENABLE = 0x0001, //mark回调的使能 + MELODY_ENABLE = 0x0002, //主旋律音符回调的使能 + TIM_DIV_ENABLE = 0x0004, //小节回调的使能 + MUTE_ENABLE = 0x0008, //mute住解码的使能 + SAVE_DIV_ENBALE = 0x0010, //小节保存的使能 + EX_VOL_ENABLE = 0x0020, //外部音量控制使能 + SET_PROG_ENABLE = 0x0040, //主轨道设置成固定乐器使能 + MELODY_PLAY_ENABLE = 0x0080, //主轨道播放使能 + BEAT_TRIG_ENABLE = 0x0100, //每拍回调的使能 + MELODY_STOP_ENABLE = 0x200, //主旋律音符停止回调使能 + MARK_LOOP_ENABLE = 0x400 //使用mark做循环播放使能 + +}; + + +typedef struct _MIDI_INIT_STRUCT_ { + MIDI_CONFIG_PARM init_info; //初始化参数 + MIDI_PLAY_CTRL_MODE mode_info; //控制模式 + MIDI_PLAY_CTRL_TEMPO tempo_info; //节奏参数 + EX_CH_VOL_PARM vol_info; //外部音量控制 + MIDI_PROG_CTRL_STRUCT prog_info; //主轨道乐器参数 + MIDI_CHNNEL_CTRL_STRUCT mainTrack_info; //主轨道设置参数 sdk添加 const int MAINTRACK_USE_CHN = 0; 这个变量控制是0用track号来区分主通道,还是1用chn的编号来区分主通道。 + EX_INFO_STRUCT mark_info; //mark回调函数 + EX_MELODY_STRUCT moledy_info; //melody回调函数 + EX_TmDIV_STRUCT tmDiv_info; //小节回调参数 + EX_BeatTrig_STRUCT beat_info; //每拍回调参数 + MIDI_OKON_MODE okon_info; //OKON参数 + EX_MELODY_STOP_STRUCT moledy_stop_info; //melody_stop回调函数 +#if 1 + MIDI_W2S_STRUCT w2s_info; +#endif + u32 switch_info; //初始化一些使能位,默认为0 +} MIDI_INIT_STRUCT; + + +#if 0 + +void init_midi_info_val(MIDI_INIT_STRUCT *midi_init_info_v) //midi 配置 +{ + //midi初始化表 + midi_init_info_v->init_info.player_t = 8; + midi_init_info_v->init_info.sample_rate = 5; + midi_init_info_v->init_info.spi_pos = spi_memory; //音色地址或音色文件 + + //midi的模式初始化 + midi_init_info_v->mode_info.mode = 0; + + //midi节奏初始化 + midi_init_info_v->tempo_info.tempo_val = 1024; + for (int i = 0; i < 16; i++) { + midi_init_info_v->tempo_info.decay_val[i] = ((u16)31 << 11) | 1024; + } + + midi_init_info_v->tempo_info.mute_threshold = (u16)1L << 29; + + //midi主轨道初始化 + midi_init_info_v->mainTrack_info.chn = 0; //把哪个轨道当成主轨道 + + //midi外部音量初始化 + { + u32 tmp_i; + for (tmp_i = 0; tmp_i < 16; tmp_i++) { + midi_init_info_v->vol_info.cc_vol[tmp_i] = 4096; //4096即原来的音量 + } + } + + //midi的主轨道乐器设置 + midi_init_info_v->prog_info.prog = 0; + midi_init_info_v->prog_info.ex_vol = 1024; + midi_init_info_v->prog_info.replace_mode = 0; + + //OKON模式设置 + midi_init_info_v->okon_info.Melody_Key_Mode = CMD_MIDI_MELODY_KEY_0; + midi_init_info_v->okon_info.OKON_Mode = CMD_MIDI_MELODY_KEY_0; + + //midi的mark控制初始化 + midi_init_info_v->mark_info.priv = &file_mark; + midi_init_info_v->mark_info.mark_trigger = tmark_trigger; + + //midi的melody控制初始化 + midi_init_info_v->moledy_info.priv = &file_melody; + midi_init_info_v->moledy_info.melody_trigger = melody_trigger; + + //midi的melody stop控制初始化 + midi_init_info_v->moledy_stop_info.priv = &file_melody_stop; + midi_init_info_v->moledy_stop_info.melody_stop_trigger = melody_stop_trigger; + + //midi的melody stop控制初始化 + midi_init_info_v->moledy_stop_info.priv = NULL; + midi_init_info_v->moledy_stop_info.melody_stop_trigger = melody_stop_trigger; + + //midi的小节回调控制初始化 + midi_init_info_v->tmDiv_info.priv = NULL; + midi_init_info_v->tmDiv_info.timeDiv_trigger = timDiv_trigger; + + //midi的小拍回调控制初始化 + midi_init_info_v->beat_info.priv = NULL; + midi_init_info_v->beat_info.beat_trigger = beat_trigger; + + //使能位控制 + midi_init_info_v->switch_info = 0; +} + +void midi_w2s_parm(MIDI_INIT_STRUCT *midi_init_info_v) +{ +#if 1 + + FILE *fpt = fopen("parmout.raw", "rb"); + + if (fpt != NULL) { + fread(&midi_init_info_v->w2s_info, 1, sizeof(midi_init_info_v->w2s_info), fpt);//录音预处理后的输出参数 + + fclose(fpt); + } + midi_init_info_v->w2s_info.key_diff = -7; //与音高成反比 + midi_init_info_v->w2s_info.rec_data = dataw2s; //录音预处理后的输出pcm数据地址或录音预处理后输出pcm数据保存的文件地址 + +#endif + +} + + +{ + MIDI_OKON_MODE okon_mode; + MIDI_PLAY_CTRL_MODE ctrl_mode_obj; + + ctrl_mode_obj.mode = CMD_MIDI_CTRL_MODE_1; + okon_mode.OKON_Mode = CMD_MIDI_OKON_MODE_1; + okon_mode.Melody_Key_Mode = CMD_MIDI_MELODY_KEY_0; + + init_midi_info_val(&midi_init_parm); + midi_w2s_parm(&midi_init_parm); + + { + u32 switch_val_in; + audio_decoder_ops *test_pos = get_midi_ops(); //获取句柄 + buflen = test_pos->need_dcbuf_size(); //获取midi buf + buflen = buflen; + bufptr = malloc(buflen); + test_pos->open(bufptr, &my_dec_io0, 0); // 打开midi + + test_pos->dec_confing(bufptr, CMD_INIT_CONFIG, &midi_init_parm); //初始化 +// test_pos->dec_confing(bufptr, CMD_MIDI_CTRL_MODE, &ctrl_mode_obj); //更改midi模式为okon +// test_pos->dec_confing(bufptr, CMD_MIDI_OKON_MODE, &okon_mode); //更改okon的模式 + + +// ctrl_mode_obj.mode = CMD_MIDI_CTRL_MODE_W2S; +// test_pos->dec_confing(bufptr, CMD_MIDI_CTRL_MODE, &mode_parm);//更改midi模式为外部音源 + + int cj = 0; + if (!test_pos->format_check(bufptr)) { //检查midi文件格式 + + testing_cnt = 0; + while (!retv) { + retv = test_pos->run(bufptr, 0); + + /*testing_cnt++; + if (testing_cnt == 800) + { + + test_pos->dec_confing(bufptr, CMD_MIDI_GOON, NULL); //okon 模式需要调用CMD_MIDI_GOON + testing_cnt = 0; + }*/ + } + } + + +#endif + +#if 0 + 外挂flash baud跑 40M ,midi读数解码 110M. + 外挂flash baud跑 60M ,midi读数解码80M. +// midi采样率表sample_rate 0 对应48000, 4对应22050,采样率越大mips消耗越大 + const int smpl_rate_tab[9] = { + 48000, + 44100, + 32000, + 24000, + 22050, + 16000, + 12000, + 11025, + 8000 + }; + + int swtic_cc = MARK_ENABLE | MELODY_ENABLE; + audio_decoder_ioctrl(hdl, CMD_MIDI_SET_SWITCH, &swtic_cc); //调用接口跟其它解码一致,但是需要调用这个函数 + + +#endif + +#endif // MIDI_DEC_API_h__ + diff --git a/include_lib/media/media_develop/media/PLC.h b/include_lib/media/media_develop/media/PLC.h new file mode 100644 index 0000000..103a10b --- /dev/null +++ b/include_lib/media/media_develop/media/PLC.h @@ -0,0 +1,11 @@ +#ifndef _PLC_H_ +#define _PLC_H_ + +#include "generic/typedef.h" + +u32 PLC_query(void); +s8 PLC_init(void *pbuf); +void PLC_exit(void); +void PLC_run(s16 *inbuf, s16 *outbuf, u16 point, u8 repair_flag); + +#endif diff --git a/include_lib/media/media_develop/media/a2dp_decoder.h b/include_lib/media/media_develop/media/a2dp_decoder.h new file mode 100644 index 0000000..455fa8c --- /dev/null +++ b/include_lib/media/media_develop/media/a2dp_decoder.h @@ -0,0 +1,58 @@ +#ifndef A2DP_DECODER_H +#define A2DP_DECODER_H + + +#include "media/includes.h" + + + +#define A2DP_CODEC_SBC 0x00 +#define A2DP_CODEC_MPEG12 0x01 +#define A2DP_CODEC_MPEG24 0x02 + + +struct a2dp_decoder { + u8 start; // 解码开始 + u8 ch; // 解码声道数 + u8 output_ch_num; // 解码输出声道数 + u8 output_ch_type; // 解码输出声道类型 + u8 header_len; // 帧头长度 + u8 sync_step; + u8 fetch_lock; + u8 join_tws; + u8 state; + u8 wait_bt_resume; + u16 seqn; // 帧序号 + s16 drop_samples; + u16 sample_rate; + u16 resume_tmr_id; + u32 resume_time; + u32 pending_time; + int wait_time; + int delay_time; + int coding_type; // 解码类型 + enum audio_channel ch_type; // 声道类型 + struct audio_decoder decoder; // 解码器 + void *sync; +}; + +// 打开a2dp解码 +int a2dp_decoder_open(struct a2dp_decoder *, struct audio_decoder_task *decode_task); +// 关闭a2dp解码 +void a2dp_decoder_close(struct a2dp_decoder *dec); +// 设置a2dp解码输出声道 +void a2dp_decoder_set_output_channel(struct a2dp_decoder *dec, u8 ch_num, u8 ch_type); +// 开始a2dp传输中止 +void a2dp_drop_frame_start(); +// 停止a2dp传输中止 +void a2dp_drop_frame_stop(); + +void a2dp_decoder_stream_sync_enable(struct a2dp_decoder *dec, void *sync, int sample_rate, int delay_time); + +void a2dp_decoder_join_tws(struct a2dp_decoder *dec); + +void a2dp_decoder_resume_from_bluetooth(struct a2dp_decoder *dec); + + + +#endif diff --git a/include_lib/media/media_develop/media/apple_dock/iAP.h b/include_lib/media/media_develop/media/apple_dock/iAP.h new file mode 100644 index 0000000..663dfcc --- /dev/null +++ b/include_lib/media/media_develop/media/apple_dock/iAP.h @@ -0,0 +1,141 @@ +/*************************************************************/ +/** @file: usb_device.h + @brief: USB 从机驱动重写,加入iAP协议 + @details: + @author: Bingquan Cai + @date: 2013-10-11,09:34 + @note: +*/ +/*************************************************************/ + +#ifndef _IAP_H_ +#define _IAP_H_ + +#include "generic/typedef.h" +// #include "string.h" +// #include "usb/usb_slave_api.h" + +#define IAP2_LINK_EN 1 + +#define IAP_USE_USB_HID_EN 1 + +//USB +#define MAXP_SIZE_INTERRUPT_IN 0x40 +//IIC crack +#define AUTHENTICATION_CONTROL_STATUS 0x10 +#define SIGNATURE_DATA_LENGTH 0x11 +#define SIGNATURE_DATA 0x12 +#define CHALLENGE_DATA_LENGTH 0x20 +#define CHALLENGE_DATA 0x21 +#define ACCESSORY_CERTIFICATE_DATA_LENGTH 0x30 +#define ACCESSORY_CERTIFICATE_DATA 0x31 +//iAP1 and iAP2 COMMON +#define IAP2_VERSIONS 0x02 +#define IAP1_VERSIONS 0x01 +#define DEFAULT_SEQUENCE_NUM 0x0 +#define EXTRA_SEQUENCE_NUM 0x1 +//"Dock speaker" +#define ACCESSORY_NAME 0x44, 0x6f, 0x63, 0x6b, 0x20, 0x73, 0x70, 0x65, 0x61, 0x6b, 0x65, 0x72, 0x00 +//"IPDLI13" +#define ACCESSORY_MODEL_IDENTIFIER 0x49, 0x50, 0x44, 0x4c, 0x49, 0x31, 0x33, 0x00 +//"I want it" +#define ACCESSORY_MANUFACTURER 0x49, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, 0x69, 0x74, 0x00 +//"iAP Interface" +#define ACCESSORY_SERIALNUMBER 0x69, 0x41, 0x50, 0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, 0x00 + +//< hid +#define HID_PREV_FILE USB_AUDIO_PREFILE +#define HID_NEXT_FILE USB_AUDIO_NEXTFILE +#define HID_PP USB_AUDIO_PP +#define HID_PLAY USB_AUDIO_PLAY +#define HID_PAUSE USB_AUDIO_PAUSE +#define HID_VOL_DOWN USB_AUDIO_VOLDOWN +#define HID_VOL_UP USB_AUDIO_VOLUP + + +//>8) +#define SW16(x) (((u16)(x) & 0x00ffU)<<8 | ((u16)(x) & 0xff00U)>>8) + +#endif /* _IAP_H_ */ diff --git a/include_lib/media/media_develop/media/apple_dock/iAP2.h b/include_lib/media/media_develop/media/apple_dock/iAP2.h new file mode 100644 index 0000000..4379b5a --- /dev/null +++ b/include_lib/media/media_develop/media/apple_dock/iAP2.h @@ -0,0 +1,171 @@ +#ifndef _IAP2_H_ +#define _IAP2_H_ + +#include "generic/typedef.h" + +#define iAP2_LINK_PACKET_HEADER_LEN 9 +#define iAP2_MESSAGE_LEN 6 +#define iAP2_MESSAGE_PARAMETERS_LEN 4 + +#define MAX_PACKET_PAYLOAD 0x65525L //means 65535 +#define IAP2_START_OF_PACKET 0xFF5AL +#define START_OF_MESSAGE 0x4040L +#define PACKET_TOTAL_LEN(X) (iAP2_LINK_PACKET_HEADER_LEN+sizeof(X)+0x1) +#define MESSAGE_TOTAL_LEN(X) (sizeof(X)) +///IAP2 HID Usage ID +#define IAP2_HID_PLAY 0xB0 +#define IAP2_HID_PAUSE 0xB1 +#define IAP2_HID_NEXT 0xB5 +#define IAP2_HID_PRE 0xB6 +#define IAP2_HID_SHUFFLE 0xB9 +#define IAP2_HID_REPEAT 0xBC +#define IAP2_HID_PP 0xCD +#define IAP2_HID_MUTE 0xE2 +#define IAP2_HID_VOLUP 0xE9 +#define IAP2_HID_VOLDOWN 0xEA +///APPLE HID Control bit +#define APPLE_HID_VOLUP BIT(0) +#define APPLE_HID_VOLDOWN BIT(1) +#define APPLE_HID_PP BIT(2) +// #define APPLE_HID_SHUFFLE BIT(2) +#define APPLE_HID_REPEAT BIT(3) +#define APPLE_HID_NEXT BIT(4) +#define APPLE_HID_PRE BIT(5) +#define APPLE_HID_PLAY BIT(6) +#define APPLE_HID_PAUSE BIT(7) + + + +//Name--can alter +#define IAP2_ACCESSORY_NAME 'D','o','c','k',' ','s','p','e','a','k','e','r','\0' +#define IAP2_ACCESSORY_NAME_LEN sizeof("Dock speaker") + +//ModelIdentifier(模式描述符)--can alter +#define IAP2_ACCESSORY_MODEL_IDENTIFIER 'I','P','D','L','I','1','3','\0' +#define IAP2_ACCESSORY_MODEL_IDENTIFIER_LEN sizeof("IPDLI13") + +//Manufacturer(制造商)--can alter +#define IAP2_ACCESSORY_MANUFACTURER 'I',' ','w','a','n','t',' ','i','t','\0' +#define IAP2_ACCESSORY_MANUFACTURER_LEN sizeof("I want it") + +//SerialNumber(序列号)--can alter +#define IAP2_ACCESSORY_SERIALNUMBER 'i','A','P',' ','I','n','t','e','r','f','a','c','e','\0' +#define IAP2_ACCESSORY_SERIALNUMBER_LEN sizeof("iAP Interface") + +//FirmwareVersion(固件版本)--can alter +#define IAP2_ACCESSORY_FIRMWARE_VER '1','.','0','.','0','\0' +#define IAP2_ACCESSORY_FIRMWARE_VER_LEN sizeof("1.0.0") + +//HardwareVersion(硬件版本)--can alter +#define IAP2_ACCESSORY_HARDWARE_VER '1','.','0','.','0','\0' +#define IAP2_ACCESSORY_HARDWARE_VER_LEN sizeof("1.0.0") + +//CurrentLanguage--can not alter +#define IAP2_CUR_LANGUAGE 'e','n','\0' +#define IAP2_CUR_LANGUAGE_LEN sizeof("en") + +//SupportedLanguage--can not alter +#define IAP2_SUP_LANGUAGE 'e','n','\0' +#define IAP2_SUP_LANGUAGE_LEN sizeof("en") + +//USB device transport Component +#define IAP2_TRANSPORT_NAME 'i','A','P','2','H','\0' +#define IAP2_TRANSPORT_NAME_LEN sizeof("iAP2H") + +//iAP2HIDComponent +#define IAP2_HID_IDENTIFIER 1 +#define IAP2_HID_NAME 'R','e','m','o','t','e','\0' +#define IAP2_HID_NAME_LEN sizeof("Remote") + + + +///variable +typedef enum { + iAP2_SLP = 3, + iAP2_RST, + iAP2_EAK, + iAP2_ACK, + iAP2_SYN, +} iAP2_CONTROL_BYTE; + +typedef enum { + //Header + STARTOFPACKET = 0, + PACKETLENGTH = 2, + CONTROLBYTE = 4, + PACKETSEQUENCENUMBER, + PACKETACKNUMBER, + SESSIONIDENTIFIER, + HEADERCHECKSUM, + //Payload + LINKVERSION, + MAXNUMOFOUTSTANDINGPKTS, + MAXPKTLENGTH = 11, + RETRANSMISSIONTIMEOUT = 13, + CUMULATIVEASKTIMEOUT = 15, + MAXNUMOFRETRANSMISSIONS = 17, + MAXCUMULATIVEACK, + + STARTOFMESSAGE = 9, + MESSAGELENGTH = 11, + MESSAGEID = 13, +} iAP2_PKT_INDEX; + +typedef enum { + CONTROL_SESSION = 0, + FILE_TRANSFER_SESSION, + EXTERNAL_ACCESSORY_SESSION, +} iAP2_SESSION_TYPE; + +typedef union _U16_U8 { + u16 wWord; + u8 bByte[2]; +} U16_U8; + + +typedef struct _iAP2_LINK_PACKET_HEADER { + U16_U8 sStartofPacket; + U16_U8 sPacketLength; + u8 bControlByte; + u8 bPacketSequenceNum; + u8 bPacketAckNum; + u8 bSessionIdentifier; + u8 bHeaderChecksum; +} iAP2_LINK_PACKET_HEADER; + +typedef struct _iAP2_SESSION { + u8 bSessionIdentifier; + u8 bSessionType; + u8 bSessionVersion; +} iAP2_SESSION; + +typedef struct _iAP2_LINK_PACKET_PAYLOAD { + u8 bLinkVersion; //both device & accessory must agree on !!! + u8 bMaxNumofOutstandingPkts; + U16_U8 sMaxPktLength; + U16_U8 sRetransmissionTimeout; //both device & accessory must agree on !!! + U16_U8 sCumulativeAckTimeout; //both device & accessory must agree on !!! + u8 bMaxNumofRetransmissions; //both device & accessory must agree on !!! + u8 bMaxCumulativeAck; //both device & accessory must agree on !!! +} iAP2_LINK_PACKET_PAYLOAD; + +typedef struct _iAP2_MESSAGE { + U16_U8 sStartofMessage; + U16_U8 sMessageLength; + U16_U8 sMessageID; +} iAP2_MESSAGE; + +typedef struct _iAP2_MESSAGE_PARAMETERS { + u16 wParameterLength; + u16 wParameterId; +} iAP2_MESSAGE_PARAMETERS; + + +///inside call + +///outside call +bool iAP2_link(void); +void iap2_hid_key(u16 key); + + +#endif /* _IAP2_H_ */ diff --git a/include_lib/media/media_develop/media/apple_dock/iAP_device.h b/include_lib/media/media_develop/media/apple_dock/iAP_device.h new file mode 100644 index 0000000..ca8ad99 --- /dev/null +++ b/include_lib/media/media_develop/media/apple_dock/iAP_device.h @@ -0,0 +1,50 @@ +/*************************************************************/ +/** @file: usb_device.h + @brief: USB 从机驱动重写,加入iAP协议 + @details: + @author: Bingquan Cai + @date: 2013-10-11,09:34 + @note: +*/ +/*************************************************************/ +#ifndef _IAP_DEVICE_H_ +#define _IAP_DEVICE_H_ + +#include "generic/typedef.h" + +enum { + IAP_DEVICE_DESCRIPTOR = 0x0, + IAP_CONFIG_DESCRIPTOR, + IAP_IMANU, + IAP_IPRODUCT, + IAP_ISERIAL, +}; +typedef struct _IAP_USB_DEVICE_STRING { + u8 *pString; + u8 bLen; +} IAP_USB_DEVICE_STRING; +extern const IAP_USB_DEVICE_STRING IAP_USB_string_set[]; + +extern const u8 MFi_iManufacturer[20]; +extern const u8 MFi_iProduct[26]; +extern const u8 MFi_iSerialNumber[28]; +extern const u8 MFi_Configuration_Descriptor[140]; + +#define IAP_TRANSPORT_ZLP 0 +#define IAP_TRANSPORT_IN 1 +#define IAP_TRANSPORT_OUT 2 +#define IAP_TRANSPORT_OUT_LEN 7 + +// void iAP_ZLP(void); +// bool iAP_bulk_in_process(void); +// u8 iAP_bulk_out_process(void); +extern u8 iAP_link_checksum(u8 *pkt, u16 len); +extern u8 iAP_transport(u8 type); +extern u16 iAP_iic_crack(u8 *TxBuf, u8 *RxBuf, u8 len); +extern u16 iAP_iic_X509(u8 *RxBuf, u16 max_len); + +///outside call + + +#endif /* _IAP_H_ */ + diff --git a/include_lib/media/media_develop/media/apple_dock/iAP_iic.h b/include_lib/media/media_develop/media/apple_dock/iAP_iic.h new file mode 100644 index 0000000..b2dbbc2 --- /dev/null +++ b/include_lib/media/media_develop/media/apple_dock/iAP_iic.h @@ -0,0 +1,48 @@ +#ifndef _IAP_IIC_H_ +#define _IAP_IIC_H_ + +#include "generic/typedef.h" + +#define IAP_CRACK_CP20 0 +#define IAP_CRACK_CP30 1 + +#define IAP_CRACK_CHIP IAP_CRACK_CP20 // IAP_CRACK_CP30 + +///解密芯片地址 +#if (IAP_CRACK_CHIP==IAP_CRACK_CP30) +#define WRITE_ADDR 0x20 +#define READ_ADDR 0x21 +#else +#define WRITE_ADDR 0x22 +#define READ_ADDR 0x23 +#endif +//Authentication Coprocessor 2.0C register map +#define ADDR_DEVICE_VERSION 0x00 //read only +#define ADDR_FIRMWARE_VERSION 0x01 //read only +#define ADDR_AUTHENTICATION_PROTOCOL_MAJOR_VERSION 0x02 //read only +#define ADDR_AUTHENTICATION_PROTOCOL_MINOR_VERSION 0x03 //read only +#define ADDR_DEVICE_ID 0x04 //read only + + +//MFI CHIP ONLINE STATUS +enum { + MFI_CHIP_OFFLINE = 0, + MFI_CHIP_ONLINE, + MFI_DV_ERROR, + MFI_FV_ERROR, + MFI_AP_MAJOR_V_ERROR, + MFI_AP_MINOR_V_ERROR, + MFI_DEVICE_ID_ERROR, +}; + +///inside call +///outside call +void iAP_iic_write(u8 iic_addr, u8 iic_dat); +void iAP_iic_writen(u8 iic_addr, u8 *iic_dat, u8 len); +u8 iAP_iic_read(u8 iic_addr); +void iAP_iic_readn(u8 iic_addr, u8 *iic_dat, u8 len); +u8 apple_mfi_chip_online_check_api(void); +#define iAP_iic_errcode_check() iAP_iic_read(0x05) + + +#endif /* _IAP_IIC_H_ */ diff --git a/include_lib/media/media_develop/media/application/audio_bfilt.h b/include_lib/media/media_develop/media/application/audio_bfilt.h new file mode 100644 index 0000000..a077093 --- /dev/null +++ b/include_lib/media/media_develop/media/application/audio_bfilt.h @@ -0,0 +1,35 @@ + +#ifndef _AUDIO_BFILT_API_H_ +#define _AUDIO_BFILT_API_H_ +#include "typedef.h" +#include "application/filtparm_api.h" + +typedef struct _bfilt_open_parm { + u32 sr; //输入音频采样率 +} bfilt_open_parm; + +typedef struct _bfilt_update_parm { + int freq;//滤波器中心频率 + int bandwidth; //带宽 + s16 iir_type;//滤波器类型 + s16 filt_num;//第几个滤波 + + int *filt_tar_tab;//滤波器系数表输出目标地址 + int gain;//增益 +} audio_bfilt_update_parm; + + +typedef struct _bfilt_hdl { + BFILT_FUNC_API *ops; + void *work_buf; + u8 bfilt_en: 1; + u8 update: 1; + bfilt_open_parm parm; +} audio_bfilt_hdl; + +audio_bfilt_hdl *audio_bfilt_open(bfilt_open_parm *parm); +void audio_bfilt_close(audio_bfilt_hdl *hdl); +void audio_bfilt_init_cal(audio_bfilt_hdl *hdl, audio_bfilt_update_parm *parm); +void audio_bfilt_cal_coeff(audio_bfilt_hdl *hdl, audio_bfilt_update_parm *parm); +#endif + diff --git a/include_lib/media/media_develop/media/application/audio_buf_sync.h b/include_lib/media/media_develop/media/application/audio_buf_sync.h new file mode 100644 index 0000000..7d567e7 --- /dev/null +++ b/include_lib/media/media_develop/media/application/audio_buf_sync.h @@ -0,0 +1,120 @@ +/***********************************Jieli tech************************************************ + File : audio_buf_sync.c + By : Huxi + brief: 跟随buf变化动态同步调整采样率 + Email: huxi@zh-jieli.com + date : 2020-06-11 +********************************************************************************************/ + +#ifndef _AUDIO_BUF_SYNC_H_ +#define _AUDIO_BUF_SYNC_H_ + +#include "asm/includes.h" +#include "generic/includes.h" +#include "system/includes.h" +// #include "media/includes.h" +#include "asm/cpu_includes.h" +#include "asm/audio_src.h" +#include "media/audio_decoder.h" +#include "media/audio_encoder.h" + + +// buf_sync调整参数 +struct audio_buf_sync_open_param { + int total_len; // buf总长度 + int begin_per; // 起始百分比,默认60 + int top_per; // 最大百分比,默认80 + int bottom_per; // 最小百分比,默认30 + int in_sr; // 输入采样率 + int out_sr; // 输出采样率 + u8 inc_step; // 每次调整增加步伐,默认5 + u8 dec_step; // 每次调整减少步伐,默认5 + u16 max_step; // 最大调整步伐,默认80 + u8 check_in_out; // 检测in和out是否相同,默认不检测 + u8 ch_num; // 通道数 + void *output_hdl; + int (*output_handler)(void *hdl, void *, int); +}; + +/* + * 跟随buf中的数据量动态调整 + * 数据量小于bottom_size时输出采样率增加inc_step,最多调整max_step + * 数据量大于top_size时输出采样率减小dec_step,最多调整max_step + * 数据量处于bottom_size和top_size之间时,adjust_step逐步回归于0 + * 建议buf使用大空间,避免总是超出bottom_size、top_size + */ +struct audio_buf_sync_hdl { + int begin_size; // 数据量起始大小 + int top_size; // 数据量限定范围最大值 + int bottom_size; // 数据量限定范围最小值 + int sample_rate; // 输入采样率 + int audio_new_rate; // 输出采样率 + int rate_offset; // 采样偏移 + s16 adjust_step; // 动态采样调整值 + u16 max_step; // 采样率调整最大值 + u8 inc_step; // 采样率调整增加复读 + u8 dec_step; // 采样率调整减小复读 + u8 start; // 启动采样率调整标志 + struct audio_src_handle *src_sync; +}; + +/* +********************************************************************* +* Audio Buf Sync Open +* Description: 按参数配置创建句柄 +* Arguments : *sync buf同步句柄 +* *param 参数 +* Return : true 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_buf_sync_open(struct audio_buf_sync_hdl *sync, struct audio_buf_sync_open_param *param); +/* +********************************************************************* +* Audio Buf Sync Close +* Description: 关闭句柄 +* Arguments : *sync buf同步句柄 +* Return : true 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_buf_sync_close(struct audio_buf_sync_hdl *sync); + +/* +********************************************************************* +* Audio Buf Sync Adjust +* Description: 跟随数据量动态调整 +* Arguments : *sync buf同步句柄 +* data_size 当前数据量大小 +* Return : true 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_buf_sync_adjust(struct audio_buf_sync_hdl *sync, int data_size); +/* +********************************************************************* +* Audio Buf Sync Follow Rate +* Description: 跟随输入输出采样变化动态调整 +* Arguments : *sync buf同步句柄 +* in_rate 跟随的输入采样率 +* out_rate 跟随的输出采样率 +* Return : true 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_buf_sync_follow_rate(struct audio_buf_sync_hdl *sync, int in_rate, int out_rate); + +/* +********************************************************************* +* Audio Buf Sync Update out Sample Rate +* Description: 重新设置输出采样率 +* Arguments : *sync buf同步句柄 +* out_rate 输出采样率 +* Return : true 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_buf_sync_update_out_sr(struct audio_buf_sync_hdl *sync, int out_sr); + +#endif /*_AUDIO_BUF_SYNC_H_*/ + diff --git a/include_lib/media/media_develop/media/application/audio_dec_app.h b/include_lib/media/media_develop/media/application/audio_dec_app.h new file mode 100644 index 0000000..e58d4ed --- /dev/null +++ b/include_lib/media/media_develop/media/application/audio_dec_app.h @@ -0,0 +1,506 @@ + +#ifndef _AUDIO_DEC_APP_H_ +#define _AUDIO_DEC_APP_H_ + +#include "asm/includes.h" +#include "media/includes.h" +#include "media/audio_stream.h" +#include "system/includes.h" +#include "channel_switch.h" + +////////////////////////////////////////////////////////////////////////////// +// 标签 +#define AUDIO_DEC_APP_MASK (('A' << 24) | ('D' << 16) | ('P' << 8) | ('M' << 8)) + +////////////////////////////////////////////////////////////////////////////// +// 解码状态 +enum audio_dec_app_status { + AUDIO_DEC_APP_STATUS_STOP = 0, + AUDIO_DEC_APP_STATUS_PLAY, + AUDIO_DEC_APP_STATUS_PAUSE, +}; + +// 解码事件 +enum audio_dec_app_event { + AUDIO_DEC_APP_EVENT_NULL = 0, + /* + * Description: 解码预处理 + * Arguments : None. + * Return : 0-正常,非0-挂起 + * Note(s) : (struct audio_dec_app_hdl*)hdl->handler->dec_probe中调用 + * 返回0后正常执行后续的audio_dec_app_probe_evt_cb_after()弱函数 + */ + AUDIO_DEC_APP_EVENT_DEC_PROBE, + /* + * Description: 解码输出 + * Arguments : int parm[2]; param[0]:data, param[1]:len + * Return : 不判断 + * Note(s) : (struct audio_dec_app_hdl*)hdl->decoder.entry.data_handler中调用 + * 仅用于查看更改内容,不改变数据长度,后续正常执行audio_stream_run() + */ + AUDIO_DEC_APP_EVENT_DEC_OUTPUT, + /* + * Description: 解码后处理 + * Arguments : None. + * Return : 同.dec_post接口返回 + * Note(s) : (struct audio_dec_app_hdl*)hdl->handler->dec_post中调用 + */ + AUDIO_DEC_APP_EVENT_DEC_POST, + /* + * Description: 解码停止 + * Arguments : None. + * Return : 同.dec_stop接口返回 + * Note(s) : (struct audio_dec_app_hdl*)hdl->handler->dec_stop中调用 + */ + AUDIO_DEC_APP_EVENT_DEC_STOP, + /* + * Description: 解码初始化完成 + * Arguments : None. + * Return : 不判断 + * Note(s) : 解码start()函数中audio_decoder_start()函数前调用 + */ + AUDIO_DEC_APP_EVENT_START_INIT_OK, + /* + * Description: 解码播放正常 + * Arguments : None. + * Return : 不判断 + * Note(s) : 解码start()函数中audio_decoder_start()函数后调用 + */ + AUDIO_DEC_APP_EVENT_START_OK, + /* + * Description: 解码播放失败 + * Arguments : None. + * Return : 不判断 + * Note(s) : 解码start()函数中解码失败后调用 + */ + AUDIO_DEC_APP_EVENT_START_ERR, + /* + * Description: 解码关闭 + * Arguments : None. + * Return : 不判断 + * Note(s) : audio_dec_app_close()函数中各功能关闭后,audio_stream_close()之前调用 + */ + AUDIO_DEC_APP_EVENT_DEC_CLOSE, + /* + * Description: 解码结束消息 + * Arguments : None. + * Return : 不判断 + * Note(s) : + */ + AUDIO_DEC_APP_EVENT_PLAY_END, + /* + * Description: 打开自定义数据流节点 + * Arguments : struct audio_dec_stream_entries_hdl *entries_hdl + * Return : 不判断 + * Note(s) : 添加节点后需要更新entries_hdl->entries_cnt + */ + AUDIO_DEC_APP_EVENT_STREAM_OPEN, + /* + * Description: 关闭自定义数据流节点 + * Arguments : None. + * Return : 不判断 + * Note(s) : + */ + AUDIO_DEC_APP_EVENT_STREAM_CLOSE, +}; + +/* + * 文件操作结构体 + */ +struct audio_dec_app_file_hdl { + int (*read)(void *hdl, void *buf, u32 len); + int (*seek)(void *hdl, int offset, int orig); + int (*len)(void *hdl); +}; + +/* + * dec_app解码 + */ +struct audio_dec_app_hdl { + u32 mask; // 固定为AUDIO_DEC_APP_MASK + u32 id; // 唯一标识符,随机值 + struct list_head list_entry; // 链表 + struct audio_stream *stream; // 音频流 + struct audio_decoder decoder; + struct audio_res_wait wait; + struct channel_switch *ch_switch;//声道变换 + struct audio_mixer_ch mix_ch; + enum audio_channel ch_type; + volatile enum audio_dec_app_status status; + u32 ch_num : 4; // channel通道数 + u32 out_ch_num : 4; // 输出声道数 + u32 tmp_pause : 1; + u32 dec_mix : 1; // 1:叠加模式 + u32 remain : 1; + u32 frame_type : 1; // 1:frame格式;0:file格式 + u32 close_by_res_put : 1; //被打断就自动close + + u16 frame_pkt_len; // frame格式帧长 + u16 frame_data_len; // frame格式当前数据长度 + u8 *frame_buf; // frame格式帧buf + + u32 dec_type; // 指定解码格式,start后为实际解码格式 + u16 sample_rate; // 指定采样率,start后为实际解码采样率 + u16 resume_tmr_id; + + struct audio_decoder_task *p_decode_task; // 解码任务句柄 + // 需要在audio_dec_app_create_param_init()弱函数中赋值 + struct audio_mixer *p_mixer; // mixer句柄,使用mixer的情况下 + // 需要在audio_dec_app_create_param_init()弱函数中赋值 + + struct audio_stream_entry **entries; // 自定义数据流节点,在AUDIO_DEC_APP_EVENT_STREAM_OPEN的节点之前使用 + // 可以在audio_dec_app_create_param_init()弱函数中赋值 + + int (*evt_cb)(void *, enum audio_dec_app_event event, int *param); // 事件回调 + void *evt_priv; + + struct audio_dec_input dec_input; + struct audio_dec_input *input; // 指定使用input接口 + struct audio_dec_handler *handler; // 指定使用handler接口 + + void *file_hdl; + struct audio_dec_app_file_hdl *file; + + int sync_confirm_time; // tws同步时间,0:不同步 + void *sync; + + void *app_hdl; // 指向上一级句柄 +}; + +// 解码的种类。比如用该值来区分音量等 +#define AUDIO_DEC_FILE_FLAG_AUDIO_STATE_TONE (0) +#define AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MUSIC (1) +#define AUDIO_DEC_FILE_FLAG_AUDIO_STATE_MASK (0x000000ff) + +/* + * 通过文件后缀名匹配解码类型 + */ +struct audio_dec_format_hdl { + const char *fmt; // 后缀名 + u32 coding_type; // 解码类型 +}; + +/* + * 文件解码 + */ +struct audio_dec_file_app_hdl { + struct audio_dec_app_hdl *dec; + struct audio_dec_format_hdl *format; + u32 flag; // 标签,可用于设置audio通道等 + void *file_hdl; + void *priv; // 私有参数 +}; + +/* + * 正弦波参数头部 + */ +struct audio_sine_param_head { + u16 repeat_time; + u8 set_cnt; + u8 cur_cnt; +}; + +/* + * 正弦波参数 + */ +struct audio_sin_param { + //int idx_increment; + int freq; + int points; + int win; + int decay; +}; + +/* + * 正弦波解码 + */ +#define AUDIO_DEC_SINE_APP_NUM_MAX 8 +struct audio_dec_sine_app_hdl { + struct audio_dec_app_hdl *dec; + void *sin_maker; + struct audio_sin_param sin_parm[AUDIO_DEC_SINE_APP_NUM_MAX]; + struct audio_sin_param *sin_src; + u8 sin_num; + u8 sin_repeat; + u16 sin_default_sr; + u32 sin_volume; + u32 flag; // 标签,可用于设置audio通道等 + void *file_hdl; + void *priv; +}; + +/* + * 自定义数据流节点 + */ +struct audio_dec_stream_entries_hdl { + struct audio_stream_entry **entries_addr; + u16 entries_cnt; + u16 entries_total; +}; + +////////////////////////////////////////////////////////////////////////////// +/* +********************************************************************* +* Audio Decoder App Get Format By Name +* Description: 通过名字判断解码类型 +* Arguments : *name 名字 +* *format 解码类型映射 +* Return : 解码类型 +* Note(s) : 查询不到返回AUDIO_CODING_UNKNOW +********************************************************************* +*/ +u32 audio_dec_app_get_format_by_name(char *name, struct audio_dec_format_hdl *format); + +/* +********************************************************************* +* Audio Decoder App Create +* Description: 创建一个dec_app解码 +* Arguments : *priv 事件回调私有参数 +* *evt_cb 事件回调接口 +* mix 1-叠加播放,0-抢占播放 +* Return : dec_app句柄 +* Note(s) : mix==1默认参数:dec->wait.protect = 1; +* mix==0默认参数:dec->wait.preemption = 1; +********************************************************************* +*/ +struct audio_dec_app_hdl *audio_dec_app_create(void *priv, int (*evt_cb)(void *, enum audio_dec_app_event event, int *param), u8 mix); + +/* +********************************************************************* +* Audio Decoder App Open +* Description: 打开dec_app解码 +* Arguments : *dec dec_app句柄 +* Return : true 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_dec_app_open(struct audio_dec_app_hdl *dec); + +/* +********************************************************************* +* Audio Decoder App Close +* Description: 关闭dec_app解码 +* Arguments : *dec dec_app句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_dec_app_close(struct audio_dec_app_hdl *dec); + +/* +********************************************************************* +* Audio Decoder App Set File Info +* Description: 设置dec_app文件信息 +* Arguments : *dec dec_app句柄 +* *file_hdl 文件句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_dec_app_set_file_info(struct audio_dec_app_hdl *dec, void *file_hdl); + +/* +********************************************************************* +* Audio Decoder App Set Frame Info +* Description: 设置dec_app流数据信息 +* Arguments : *dec dec_app句柄 +* pkt_len 帧长 +* coding_type 流数据类型 +* Return : None. +* Note(s) : 会申请一块pkt_len长度的空间做缓存 +********************************************************************* +*/ +void audio_dec_app_set_frame_info(struct audio_dec_app_hdl *dec, u16 pkt_len, u32 coding_type); + +/* +********************************************************************* +* Audio Decoder App Pause/Play +* Description: dec_app解码暂停播放 +* Arguments : *dec dec_app句柄 +* Return : true 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_dec_app_pp(struct audio_dec_app_hdl *dec); + +/* +********************************************************************* +* Audio Decoder App Get Status +* Description: 获取dec_app解码状态 +* Arguments : *dec dec_app句柄 +* Return : enum audio_dec_app_status +* Note(s) : 错误时返回 负数 +********************************************************************* +*/ +int audio_dec_app_get_status(struct audio_dec_app_hdl *dec); + +/* +********************************************************************* +* Audio Decoder App Check Handler Live +* Description: 检测解码句柄是否存在 +* Arguments : *dec dec_app句柄 +* Return : true 句柄存在 +* Note(s) : None. +********************************************************************* +*/ +int audio_dec_app_check_hdl(struct audio_dec_app_hdl *dec); + +/* +********************************************************************* +* Audio Decoder App File Decoder Create +* Description: 创建一个文件解码 +* Arguments : *name 文件名 +* mix 1-叠加播放,0-抢断播放 +* Return : 文件解码句柄 +* Note(s) : 默认开启被打断就自动close功能,hdl->dec->close_by_res_put=1; +* 默认开启可抢断同优先级解码,hdl->dec->wait.snatch_same_prio=1; +* 其他默认配置见audio_dec_app_create()函数说明 +********************************************************************* +*/ +struct audio_dec_file_app_hdl *audio_dec_file_app_create(char *name, u8 mix); + +/* +********************************************************************* +* Audio Decoder App File Decoder Open +* Description: 打开文件解码 +* Arguments : *file_dec 文件解码句柄 +* Return : true 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_dec_file_app_open(struct audio_dec_file_app_hdl *file_dec); + +/* +********************************************************************* +* Audio Decoder App File Decoder close +* Description: 关闭文件解码 +* Arguments : *file_dec 文件解码句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_dec_file_app_close(struct audio_dec_file_app_hdl *file_dec); + +/* +********************************************************************* +* Audio Decoder App Sine File Decoder Create +* Description: 创建一个正弦波文件解码 +* Arguments : *name 文件名 +* mix 1-叠加播放,0-抢断播放 +* Return : 正弦波解码句柄 +* Note(s) : 默认开启被打断就自动close功能,hdl->dec->close_by_res_put=1; +* 默认开启可抢断同优先级解码,hdl->dec->wait.snatch_same_prio=1; +* 其他默认配置见audio_dec_app_create()函数说明 +********************************************************************* +*/ +struct audio_dec_sine_app_hdl *audio_dec_sine_app_create(char *name, u8 mix); + +/* +********************************************************************* +* Audio Decoder App Sine Param Decoder Create +* Description: 创建一个正弦波数组解码 +* Arguments : *sin 数组地址 +* sin_num 数组数量 +* mix 1-叠加播放,0-抢断播放 +* Return : 正弦波解码句柄 +* Note(s) : 默认开启被打断就自动close功能,hdl->dec->close_by_res_put=1; +* 默认开启可抢断同优先级解码,hdl->dec->wait.snatch_same_prio=1; +* 其他默认配置见audio_dec_app_create()函数说明 +********************************************************************* +*/ +struct audio_dec_sine_app_hdl *audio_dec_sine_app_create_by_parm(struct audio_sin_param *sin, u8 sin_num, u8 mix); + +/* +********************************************************************* +* Audio Decoder App Sine Decoder Open +* Description: 打开正弦波解码 +* Arguments : *sine_dec 正弦波解码句柄 +* Return : true 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_dec_sine_app_open(struct audio_dec_sine_app_hdl *sine_dec); + +/* +********************************************************************* +* Audio Decoder App Sine Decoder Close +* Description: 关闭正弦波解码 +* Arguments : *sine_dec 正弦波解码句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_dec_sine_app_close(struct audio_dec_sine_app_hdl *sine_dec); + +/* +********************************************************************* +* Audio Decoder App Sine Probe Deal +* Description: 正弦波解码参数预处理 +* Arguments : *sine_dec 正弦波解码句柄 +* Return : None. +* Note(s) : 正弦波解码需要先预处理一下参数 +********************************************************************* +*/ +void audio_dec_sine_app_probe(struct audio_dec_sine_app_hdl *sine_dec); + +/* +********************************************************************* +* Audio Decoder App Sync Open +* Description: 打开dec_app解码同步功能 +* Arguments : *dec dec_app解码句柄 +* sample_rate 解码采样率 +* output_sample_rate 输出采样率 +* channels 声道数 +* confirm_time sync确认时间 +* Return : 同步句柄 +* Note(s) : None. +********************************************************************* +*/ +void *audio_dec_app_sync_open(struct audio_dec_app_hdl *dec, int sample_rate, int output_sample_rate, u8 channels, int confirm_time); + +/* +********************************************************************* +* Audio Decoder App Sync Close +* Description: 关闭dec_app解码同步功能 +* Arguments : *sync 同步句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_dec_app_sync_close(void *sync); + +/* +********************************************************************* +* Audio Decoder App Sync Get Entry +* Description: 获取同步数据流节点 +* Arguments : *sync 同步句柄 +* Return : 数据流节点 +* Note(s) : None. +********************************************************************* +*/ +struct audio_stream_entry *audio_dec_app_sync_get_entry(void *sync); + +/* +********************************************************************* +* Audio Decoder App Sync Get Resample Entry +* Description: 获取同步变采样数据流节点 +* Arguments : *sync 同步句柄 +* Return : 变采样数据流节点 +* Note(s) : None. +********************************************************************* +*/ +struct audio_stream_entry *audio_dec_app_sync_get_resample_entry(void *sync); + +/* +********************************************************************* +* Audio Decoder App Sync Probe Deal +* Description: 同步预处理 +* Arguments : *sync 同步句柄 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_dec_app_sync_probe(void *sync); + +#endif /*_AUDIO_DEC_APP_H_*/ + diff --git a/include_lib/media/media_develop/media/application/audio_dig_vol.h b/include_lib/media/media_develop/media/application/audio_dig_vol.h new file mode 100644 index 0000000..69294e4 --- /dev/null +++ b/include_lib/media/media_develop/media/application/audio_dig_vol.h @@ -0,0 +1,226 @@ +/******************************************************************************************* + File : audio_dig_vol.h + By : LinHaibin + brief: 数据数字音量与分组管理 + mem : sizeof(audio_dig_vol_hdl) + 12 * channels (Byte) + mips: 6MHz / 44100 points / 2ch / sec (soft) + 3MHz / 44100 points / 2ch / sec (asm) + Email: linhaibin@zh-jieli.com + date : Fri, 24 Jul 2020 18:00:39 +0800 +********************************************************************************************/ +#ifndef _AUDIO_DIG_VOL_H_ +#define _AUDIO_DIG_VOL_H_ + + +#define AUDIO_DIG_VOL_CH(x) (BIT(x)) +#define AUDIO_DIG_VOL_ALL_CH (0xFFFF) + +typedef struct _audio_dig_vol_param { + u8 vol_start; // 打开数字音量后的起始音量等级 + u8 vol_max; // 数字音量的最大音量等级 + u8 ch_total; // 音频数据通道总数 + u8 fade_en; // 淡入淡出使能 + u16 fade_points_step; // 淡入淡出点数步长 + u16 fade_gain_step; // 淡入淡出增益步长 + u16 *vol_list; // 自定义音量等级增益映射表,NULL则使用默认 +} audio_dig_vol_param; + +/******************************************************* +* Function name : audio_dig_vol_entry_get +* Description : 获取数字音量数据流entry句柄 +* Parameter : +* @_hdl 数字音量句柄 +* Return : 返回句柄, NULL:失败 +*******************************************************/ +extern void *audio_dig_vol_entry_get(void *_hdl); + +/******************************************************* +* Function name : audio_dig_vol_open +* Description : 新建数字音量句柄 +* Parameter : +* @param 配置 +* Return : 返回句柄, NULL:打开失败 +*******************************************************/ +extern void *audio_dig_vol_open(audio_dig_vol_param *param); + +/******************************************************* +* Function name : audio_dig_vol_run +* Description : 数字音量计算 +* Parameter : +* @_hdl 句柄 +* @data 数据地址 +* @len 数据字节长度 +* Return : 0:正常 other:出错 +********************************************************/ +extern int audio_dig_vol_run(void *hdl, s16 *data, u32 len); + +/******************************************************* +* Function name : audio_dig_vol_set +* Description : 数字音量音量等级设置 +* Parameter : +* @_hdl 句柄 +* @channel 通道(BIT(0)对应通道0,支持多个同时设置) +* @vol 音量等级 +* Return : 0:正常 other:出错 +********************************************************/ +extern int audio_dig_vol_set(void *hdl, u32 channel, u8 vol); + +/******************************************************* +* Function name : audio_dig_vol_get +* Description : 数字音量等级获取 +* Parameter : +* @_hdl 句柄 +* @channel 通道(BIT(0)对应通道0,如此类推) +* Return : 通道的音量等级 -1:出错 +********************************************************/ +extern int audio_dig_vol_get(void *hdl, u32 channel); + +/******************************************************* +* Function name : audio_dig_vol_skip +* Description : 数字音量跳过计算(不对数据运算) +* Parameter : +* @_hdl 句柄 +* @channel 通道(BIT(0)对应通道0,如此类推) +* @skip_en 1:跳过 0:正常计算 +* Return : 0:正常 other:出错 +********************************************************/ +extern int audio_dig_vol_skip(void *hdl, u32 channel, u8 skip_en); + +/******************************************************* +* Function name : audio_dig_vol_fade +* Description : 数字音量淡入淡出使能 +* Parameter : +* @_hdl 句柄 +* @channel 通道(BIT(0)对应通道0,如此类推) +* @fade_en 1:使能 0:不使能 +* Return : 0:正常 other:出错 +********************************************************/ +extern int audio_dig_vol_fade(void *hdl, u32 channel, u8 fade_en); + + +/******************************************************* +* Function name : audio_dig_vol_close +* Description : 数字音量句柄关闭 +* Parameter : +* @_hdl 句柄 +* Return : 0:正常 other:出错 +********************************************************/ +extern int audio_dig_vol_close(void *_hdl); + + +/****************************************************************************** + audio digital vol 接入 audio stream demo + +INCLUDE: + #include "application/audio_dig_vol.h" + void *digvol_last = NULL; + void *digvol_last_entry = NULL; + +OPEN: + audio_dig_vol_param digvol_last_param = { + .vol_start = 30, + .vol_max = 30, + .ch_total = 2, + .fade_en = 1, + .fade_points_step = 5, + .fade_gain_step = 10, + .vol_list = NULL, + }; + digvol_last = audio_dig_vol_open(&digvol_last_param); + digvol_last_entry = audio_dig_vol_entry_get(digvol_last); + entries[entry_cnt++] = digvol_last_entry; + +SET: + audio_dig_vol_set(digvol_last, AUDIO_DIG_VOL_CH(0), vol); + +CLOSE: + audio_stream_del_entry(digvol_last_entry); + audio_dig_vol_close(digvol_last); + +******************************************************************************/ + +/******************************************************* +* Function name : audio_dig_vol_group_open +* Description : 新建数字音量组 +* Parameter : +* Return : 返回句柄, NULL:打开失败 +********************************************************/ +extern void *audio_dig_vol_group_open(void); + +/******************************************************* +* Function name : audio_dig_vol_group_add +* Description : 增加一个数字音量成员 +* Parameter : +* @group_head 数字音量组句柄 +* @dig_vol_hdl 数字音量成员的句柄 +* @logo 成员标识字符串 +* Return : 0:正常 other:出错 +********************************************************/ +extern int audio_dig_vol_group_add(void *group_head, void *dig_vol_hdl, char *logo); + +/******************************************************* +* Function name : audio_dig_vol_group_del +* Description : 删除一个数字音量成员 +* Parameter : +* @group_head 数字音量组句柄 +* @logo 成员标识字符串 +* Return : 0:正常 other:出错 +********************************************************/ +extern int audio_dig_vol_group_del(void *group_head, char *logo); + +/******************************************************* +* Function name : audio_dig_vol_group_close +* Description : 数字音量组解散 +* Parameter : +* @group_head 数字音量组句柄 +* Return : 0:正常 other:出错 +********************************************************/ +extern int audio_dig_vol_group_close(void *group_head); + +/******************************************************* +* Function name : audio_dig_vol_group_hdl_get +* Description : 获取数字音量成员的数字音量句柄 +* Parameter : +* @group_head 数字音量组句柄 +* @logo 成员标识字符串 +* Return : 返回句柄 NULL:出错 +********************************************************/ +extern void *audio_dig_vol_group_hdl_get(void *group_head, char *logo); + +/******************************************************* +* Function name : audio_dig_vol_group_dodge +* Description : 闪避 +* Parameter : +* @group_head 数字音量组句柄 +* @logo 指定成员标识字符串 +* @weight 指定成员权重 +* @other_weight 其他成员权重 +* Return : 0:正常 other:出错 +********************************************************/ +extern int audio_dig_vol_group_dodge(void *group_head, char *logo, u8 weight, u8 other_weight); + +/****************************************************************************** + audio digital group demo + +OPEN: + void *dig_vol_group1; + dig_vol_group1 = audio_dig_vol_group_open(); + +ADD: + audio_dig_vol_group_add(dig_vol_group1, dig_vol_hdl1 ,"dig_vol_1"); + audio_dig_vol_group_add(dig_vol_group1, dig_vol_hdl2 ,"dig_vol_2"); + audio_dig_vol_group_add(dig_vol_group1, dig_vol_hdl3 ,"dig_vol_3"); + +DEL: + audio_dig_vol_group_del(dig_vol_group1, "dig_vol_2"); + +CLOSE: + audio_dig_vol_group_close(dig_vol_group1); + +DODGE: + audio_dig_vol_group_dodge(dig_vol_group1, "dig_vol_1", 100, 0); // dodge + audio_dig_vol_group_dodge(dig_vol_group1, "dig_vol_1", 100, 100); // no dodge + +******************************************************************************/ + +#endif // #ifndef _AUDIO_DIG_VOL_H_ diff --git a/include_lib/media/media_develop/media/application/audio_echo_src.h b/include_lib/media/media_develop/media/application/audio_echo_src.h new file mode 100644 index 0000000..a70427e --- /dev/null +++ b/include_lib/media/media_develop/media/application/audio_echo_src.h @@ -0,0 +1,30 @@ +#ifndef _AUDIO_ECHO_SRC_API_H +#define _AUDIO_ECHO_SRC_API_H + +#include "asm/Resample_api.h" +// #include "asm/howling_api.h" + +typedef struct _ECHO_SRC_API_STRUCT_ { + RS_PARA_STRUCT parm; //参数 + void *ptr; //运算buf指针 + RS_STUCT_API *src_api; + struct audio_stream_entry entry; // 音频流入口 + s16 *out_buf; + int out_len; + int process_len; + u8 run_en; + s16 src_adj_step; + u32 original_out_src; + u32 out_buf_len; +} ECHO_SRC_API_STRUCT; + + + + + +ECHO_SRC_API_STRUCT *open_echo_src(int in_sr, int out_sr, u8 channel); +int run_echo_src(ECHO_SRC_API_STRUCT *echo_src_hdl, short *in, short *out, int len); +void close_echo_src(ECHO_SRC_API_STRUCT *echo_src_hdl); +void pause_echo_src(ECHO_SRC_API_STRUCT *echo_src_hdl, u8 run_mark); +#endif + diff --git a/include_lib/media/media_develop/media/application/audio_energy_detect.h b/include_lib/media/media_develop/media/application/audio_energy_detect.h new file mode 100644 index 0000000..38fa79f --- /dev/null +++ b/include_lib/media/media_develop/media/application/audio_energy_detect.h @@ -0,0 +1,137 @@ +/******************************************************************************************* + File : audio_energy_detect.h + By : LinHaibin + brief: 数据能量检测 + mem : 148 + 56 * channels (Byte) + mips: 8MHz / 44100 points / sec + Email: linhaibin@zh-jieli.com + date : Fri, 24 Jul 2020 18:11:37 +0800 +********************************************************************************************/ +#ifndef _AUDIO_ENERGY_DETECT_H_ +#define _AUDIO_ENERGY_DETECT_H_ + +#include "typedef.h" + +#define AUDIO_E_DET_UNMUTE (0x00) +#define AUDIO_E_DET_MUTE (0x01) + +typedef struct _audio_energy_detect_param { + s16 mute_energy; // mute 阈值 + s16 unmute_energy; // unmute 阈值 + u16 mute_time_ms; // 能量低于mute阈值进入mute状态时间 + u16 unmute_time_ms; // 能量高于unmute阈值进入unmute状态时间 + u32 sample_rate; // 采样率 + void (*event_handler)(u8, u8); // 事件回调函数 event channel + u16 count_cycle_ms; // 能量计算的时间周期 + u8 ch_total; // 通道总数 + u8 pcm_mute: 1; // 保留,未使用 + u8 onoff: 1; // 保留,未使用 + u8 skip: 1; // 1:数据不处理 0:处理 + u8 dcc: 1; // 1:去直流打开 0:关闭 +} audio_energy_detect_param; + +/******************************************************* +* Function name : audio_energy_detect_entry_get +* Description : 获取能量计算句柄的数据流entry节点 +* Parameter : +* @_hdl 能量获取句柄 +* Return : 返回entry NULL:新建失败 +********************************************************/ +extern void *audio_energy_detect_entry_get(void *_hdl); + +/******************************************************* +* Function name : audio_energy_detect_open +* Description : 新建能量计算句柄 +* Parameter : +* @param 能量获取配置参数 +* Return : 返回句柄 NULL:新建失败 +********************************************************/ +extern void *audio_energy_detect_open(audio_energy_detect_param *param); + +/******************************************************* +* Function name : audio_energy_detect_run +* Description : 能量计算运算 +* Parameter : +* @_hdl 能量获取句柄 +* @data 数据起始地址 +* @len 数据字节长度 +* Return : 返回处理长度 -1:出错 +********************************************************/ +extern int audio_energy_detect_run(void *_hdl, s16 *data, u32 len); + +/******************************************************* +* Function name : audio_energy_detect_close +* Description : 关闭能量获取句柄 +* Parameter : +* @_hdl 能量获取句柄 +* Return : 0:正常 other:出错 +********************************************************/ +extern int audio_energy_detect_close(void *_hdl); + +/******************************************************* +* Function name : audio_energy_detect_skip +* Description : 能量获取跳过计算(不生效) +* Parameter : +* @_hdl 能量获取句柄 +* @channel 通道(BIT(0)对应通道0,如此类推) +* @skip 1:跳过 0:正常计算 +* Return : 0:正常 other:出错 +********************************************************/ +extern int audio_energy_detect_skip(void *_hdl, u32 channel, u8 skip); + +/******************************************************* +* Function name : audio_energy_detect_energy_get +* Description : 获取计算出来通道的能量 +* Parameter : +* @_hdl 能量获取句柄 +* @ch 通道(BIT(0)对应通道0,如此类推) +* Return : 返回能量值 -1:出错 +********************************************************/ +extern int audio_energy_detect_energy_get(void *_hdl, u8 ch); + +/******************************************************* +* Function name : audio_energy_detect_sample_rate_update +* Description : 能量获取更新数据采样率 +* Parameter : +* @_hdl 能量获取句柄 +* @sample_rate 采样率 +* Return : 0:正常 other:出错 +********************************************************/ +extern int audio_energy_detect_sample_rate_update(void *_hdl, u32 sample_rate); + + +/****************************************************************************** + audio energy detect 接入 audio stream demo + +INCLUDE: + #include "application/audio_energy_detect.h" + void *audio_e_det_hdl = NULL; + struct list_head *audio_e_det_entry = NULL; + void test_e_det_handler(u8 event, u8 ch) + { + printf(">>>> ch:%d %s\n", ch, event ? ("MUTE") : ("UNMUTE")); + } + +OPEN: + audio_energy_detect_param e_det_param = {0}; + e_det_param.mute_energy = 5; + e_det_param.unmute_energy = 10; + e_det_param.mute_time_ms = 100; + e_det_param.unmute_time_ms = 50; + e_det_param.count_cycle_ms = 100; + e_det_param.sample_rate = 44100; + e_det_param.event_handler = test_e_det_handler; + e_det_param.ch_total = 2; + e_det_param.dcc = 1; + audio_e_det_hdl = audio_energy_detect_open(&e_det_param); + audio_e_det_entry = audio_energy_detect_entry_get(audio_e_det_hdl); + + entries[entry_cnt++] = audio_e_det_entry; + +CLOSE: + audio_energy_detect_close(audio_e_det_hdl); + +******************************************************************************/ + +#endif // #ifndef _AUDIO_ENERGY_DETECT_H_ + diff --git a/include_lib/media/media_develop/media/application/audio_localtws.h b/include_lib/media/media_develop/media/application/audio_localtws.h new file mode 100644 index 0000000..3041217 --- /dev/null +++ b/include_lib/media/media_develop/media/application/audio_localtws.h @@ -0,0 +1,202 @@ +/***********************************Jieli tech************************************************ + File : audio_localtws.c + By : Huxi + brief: + Email: huxi@zh-jieli.com + date : 2020-06 +********************************************************************************************/ + +#ifndef _AUDIO_LOCALTWS_H_ +#define _AUDIO_LOCALTWS_H_ + +#include "asm/includes.h" +#include "system/includes.h" +#include "media/mixer.h" + +#define LOCALTWS_SBC_ENC_IN_SIZE 512 +#define LOCALTWS_SBC_ENC_OUT_SIZE 256 + +#define LOCALTWS_CODE_CONVERT_BUF_LEN (2 * 1024) + +#define LOCALTWS_MEDIA_INFO_LEN (1) +#define LOCALTWS_MEDIA_FMT_LEN (LOCALTWS_MEDIA_INFO_LEN+sizeof(u16)) // B0:INFO, B[1-2]:SEQN + +#define LOCALTWS_MEDIA_INFO_STOP (0) // 特殊包,停止 +#define LOCALTWS_MEDIA_INFO_PAUSE (0xff) // 特殊包,暂停 + + +enum { + LOCALTWS_GLOBLE_EVENT_MEDIA_START = 1, // localtws启动事件 + LOCALTWS_GLOBLE_EVENT_MEDIA_STOP, // localtws停止事件 + LOCALTWS_GLOBLE_EVENT_MEDIA_TIMEOUT, // localtws超时事件 +}; + +enum { + LOCALTWS_MEDIA_SEND_PAUSE_START = 1, // 发送暂停命令 + LOCALTWS_MEDIA_SEND_PAUSE_END, // 发送完成 + LOCALTWS_MEDIA_DEC_PAUSE, // 暂停 + LOCALTWS_MEDIA_DEC_PAUSE_RECOVER, // 暂停恢复 +}; + +extern const u16 LOCALTWS_MEDIA_BUF_LEN; +extern const u16 LOCALTWS_MEDIA_BUF_LIMIT_LEN; +extern const u16 LOCALTWS_MIXER_BUF_LEN; +extern const u16 LOCALTWS_MEDIA_TO_MS; + + +// 数据推送到tws +struct localtws_push_hdl { + u16 resume_tmr_id; + u8 wait_resume; + struct audio_stream_entry entry; // 音频流入口 +}; + +// localtws +struct localtws_globle_hdl { + u16 tmrout; // 接受超时 + u16 drop_timer; // 中止传输定时 + u16 seqn; // 传输包序号 + u32 media_value; // 当前localtws媒体信息 + u32 drop_frame_start : 1; // 中止数据传输 + u32 tws_send_pause : 3; // localtws正在发送暂停命令 + u32 tws_stop : 1; // localtws正在停止 + // u32 mixer_init : 1; // mixer初始化ok + u32 media_buf_malloc : 1; // 1:使用malloc。0:使用固定地址 + u8 fade_ms; // 淡入淡出时长 + u8 fade_out_mute_ms; // 淡出后静音时长 + void *media_buf; // buf地址 + int (*event_cb)(int event, int *parm); + int (*check_active)(); // 检查是否是活动设备 + void (*resume)(); // 激活解码 + int (*dec_restart)(); // 解码重新开始 + int (*data_abandon)(); // 抛弃数据 + int (*frame_drop)(); // 中断传输 + OS_MUTEX mutex; // 互斥 + + u8 *mixer_buf; // 混合使用的buf + struct audio_mixer mixer; // 混合输出 + + struct localtws_push_hdl push; // 数据推送 +}; +extern struct localtws_globle_hdl g_localtws; + +// localtws压缩为sbc或者mp3 +// sbc直接传输;mp3会转换成localtws可用的格式再传输 +struct localtws_enc_hdl { + struct audio_encoder encoder; // 编码器 + struct audio_encoder_task *encode_task; // 编码任务 + s16 *output_frame; // 编码输出帧 + int output_frame_len; // 编码输出帧长 + int pcm_frame[LOCALTWS_SBC_ENC_IN_SIZE / 4]; // 音频编码读数据缓存 + u8 *output_buf; // 音频缓存 + int output_buf_len; // 音频缓存长度 + cbuffer_t output_cbuf; // 音频缓存cbuf + u32 status : 1; // 编码状态 + u32 dec_is_start : 1; // 后级是否已经开始解码 + u32 dec_check_start_ok : 1; // 判断后级解码完成 + + u8 sbc_fame_cnt; // sbc帧打包计数 + u8 *sbc_out_buf; // sbc帧缓存 + u16 sbc_fame_len; // sbc帧长 + u16 sbc_fame_sn; // sbc帧计数 + void *p_sbc_param; // sbc编码参数 + + int (*check_dec_start)(void); // 检测后级是否开始解码 + u32 dec_start_delay_ms; // 开始解码后静音延迟多久 + unsigned long dec_start_time; // 延迟时间戳 + + u8 *out_data; // 数据流 + int out_data_total; // 数据流总长 + int out_data_len; // 数据流输出长 + struct audio_stream_entry entry; // 音频流入口 +}; +extern struct localtws_enc_hdl *localtws_enc; + +// 把mp3或者wma等数据转换为可供localtws使用的数据 +struct localtws_code_convert_hdl { + struct audio_decoder decoder; // 解码器 + struct audio_decoder_task *decode_task; // 解码任务 + u8 file_buf[LOCALTWS_CODE_CONVERT_BUF_LEN]; // 解码数据缓存 + cbuffer_t file_cbuf; // 解码数据cbuf + u32 status : 1; // 解码状态 + + u8 *out_data; // 数据流 + int out_data_total; // 数据流总长 + int out_data_len; // 数据流输出长 + struct audio_stream_entry entry; // 音频流入口 +}; +extern struct localtws_code_convert_hdl *localtws_code_convert; + + +// localtws底层收数处理 +int localtws_tws_rx_handler_notify(u8 *data, int len, u8 rx); + +// localtws设置事件回调接口(非活动设备才回调。活动设备由上层主动控制) +void localtws_globle_set_event_cb(int (*event_cb)(int event, int *parm)); +// localtws设置检测活动设备接口 +void localtws_globle_set_check_active(int (*check_active)()); +// localtws设置激活接口 +void localtws_globle_set_resume(void (*resume)()); +// localtws设置解码重启接口 +void localtws_globle_set_dec_restart(int (*dec_restart)()); +// localtws设置数据抛弃判断接口(data_abandon返回true代表抛弃该数据) +void localtws_globle_set_data_abandon(int (*data_abandon)()); +// localtws设置中断传输判断接口(frame_drop返回true代表中断传输) +void localtws_globle_set_frame_drop(int (*frame_drop)()); + +// localtws媒体使能(申请空间,使能tws底层传输) +void localtws_media_enable(void); +// localtws媒体关闭使能(关闭tws底层传输,释放空间) +void localtws_media_disable(void); +// localtws把音频信息转换为传输信息 +int localtws_media_set_info(u8 *data, struct audio_fmt *pfmt); +// localtws把传输信息转换为音频信息 +int localtws_media_get_info(u8 *data, struct audio_fmt *pfmt); + +// localtws推送音频数据 +int localtws_media_push_data(struct audio_fmt *pfmt, s16 *data, int len); +// localtws推送一个byte(超时等待推送) +int localtws_media_push_byte(u8 info, int tmrout); +// localtws推送一个end消息(超时等待推送) +int localtws_media_send_end(int tmrout); +// localtws推送一个暂停消息(超时等待推送) +int localtws_media_send_pause(int tmrout); + +// 打开localtws音频数据推送 +int localtws_push_open(void); +// 关闭localtws音频数据推送 +void localtws_push_close(void); + +// 打开localtws音频转换解码 +int localtws_code_convert_open(struct audio_fmt *pfmt); +// 关闭localtws音频转换解码 +void localtws_code_convert_close(void); +// localtws转换激活 +void localtws_code_convert_resume(void); +// localtws转换写入数据 +int localtws_code_convert_wfile(struct audio_fmt *pfmt, s16 *data, int len); + +// 打开localtws音频编码 +int localtws_enc_open(struct audio_fmt *pfmt); +// 关闭localtws音频编码 +void localtws_enc_close(); +// localtws编码设置数据源为流数据的处理 +// 数据源为流数据时需要先传输静音数据,避免开始播放时的丢数杂音 +void localtws_enc_set_stream_data_ctrl(int (*check_dec)(void), u32 dly_ms); +// localtws音频编码激活 +void localtws_enc_resume(void); +// localtws编码数据写入 +int localtws_enc_write(void *priv, s16 *data, int len); +// localtws音频编码清除数据 +void localtws_enc_clear(void); + +// localtws获取sbc编码支持的采样率 +int localtws_enc_sbc_sample_rate_select(int rate, u8 high); + +// 启动localtws传输中止 +void localtws_drop_frame_start(); +// 关闭localtws传输中止 +void localtws_drop_frame_stop(); + +#endif /*_AUDIO_LOCALTWS_H_*/ + diff --git a/include_lib/media/media_develop/media/application/audio_output_dac.h b/include_lib/media/media_develop/media/application/audio_output_dac.h new file mode 100644 index 0000000..ec5cd13 --- /dev/null +++ b/include_lib/media/media_develop/media/application/audio_output_dac.h @@ -0,0 +1,19 @@ +#ifndef _AUDIO_OUTPUT_DAC_H_ +#define _AUDIO_OUTPUT_DAC_H_ + +#include "typedef.h" + +struct audio_stream_dac_out { + struct audio_stream_entry entry; +}; +extern struct audio_stream_dac_out *audio_stream_dac_out_open(void); +extern void audio_stream_dac_out_close(struct audio_stream_dac_out *dac_out); + +#define TYPE_DAC_AGAIN (0x01) +#define TYPE_DAC_DGAIN (0x02) + +extern int audio_dac_vol_set(u8 type, u32 ch, u16 gain, u8 fade_en); +extern int audio_dac_vol_mute(u8 mute, u8 fade); +extern int audio_dac_vol_mute_lock(u8 lock); + +#endif // _AUDIO_OUTPUT_DAC_H_ diff --git a/include_lib/media/media_develop/media/application/audio_pemafrow.h b/include_lib/media/media_develop/media/application/audio_pemafrow.h new file mode 100644 index 0000000..9b1c138 --- /dev/null +++ b/include_lib/media/media_develop/media/application/audio_pemafrow.h @@ -0,0 +1,14 @@ +#ifndef _AUDIO_PEMAFROW_API_H +#define _AUDIO_PEMAFROW_API_H + +#include "asm/pemafrow_api.h" + + +PEMAFROW_API_STRUCT *open_pemafrow(void); +void run_pemafrow(PEMAFROW_API_STRUCT *pemafrow_hdl, short *in, short *pre_out, short *out); +// void run_pemafrow(PEMAFROW_API_STRUCT *pemafrow_hdl, short *in, short *out, int len); +void close_pemafrow(PEMAFROW_API_STRUCT *pemafrow_hdl); +void pause_pemafrow(PEMAFROW_API_STRUCT *pemafrow_hdl, u8 run_mark); + +#endif + diff --git a/include_lib/media/media_develop/media/application/audio_pitchspeed.h b/include_lib/media/media_develop/media/application/audio_pitchspeed.h new file mode 100644 index 0000000..a0f68b6 --- /dev/null +++ b/include_lib/media/media_develop/media/application/audio_pitchspeed.h @@ -0,0 +1,33 @@ + +#ifndef _AUDIO_PITCHSPEED_API_H_ +#define _AUDIO_PITCHSPEED_API_H_ + +#include "asm/includes.h" +#include "media/includes.h" +#include "system/includes.h" + +#include "asm/ps_cal_api.h" + +typedef struct _s_pitchspeed_hdl { + PS69_API_CONTEXT *ops; + PS69_CONTEXT_CONF param; + unsigned char *ptr; //运算buf指针 + PS69_audio_IO speed_IO; + u8 updata_mark; + + struct audio_stream_entry entry; // 音频流入口 + int out_len; + int process_len; + u8 run_en; + s16 *out_buf; + int out_buf_len; +} s_pitchspeed_hdl; + + + +s_pitchspeed_hdl *open_pitchspeed(PS69_CONTEXT_CONF *param, PS69_audio_IO *speed_IO); +int run_pitchspeed(s_pitchspeed_hdl *ps_hdl, s16 *indata, int len); +void close_pitchspeed(s_pitchspeed_hdl *ps_hdl); +void updat_pitchspeed_parm(s_pitchspeed_hdl *ps_hdl, PS69_CONTEXT_CONF *param); + +#endif //_AUDIO_PITCHSPEED_API_H_ diff --git a/include_lib/media/media_develop/media/application/audio_vocal_remove.h b/include_lib/media/media_develop/media/application/audio_vocal_remove.h new file mode 100644 index 0000000..0b18016 --- /dev/null +++ b/include_lib/media/media_develop/media/application/audio_vocal_remove.h @@ -0,0 +1,48 @@ + +#ifndef _AUDIO_VOCAL_REMOVE_API_H_ +#define _AUDIO_VOCAL_REMOVE_API_H_ + +#include "system/includes.h" +#include "media/includes.h" + +typedef struct _vocal_remove_open_parm { + u8 channel;//输入音频声道数 +} vocal_remove_open_parm; + + +typedef struct _vocal_remove_hdl { + u32 vocal_remove_dis: 1; + vocal_remove_open_parm o_parm; + struct audio_stream_entry entry; // 音频流入口 +} vocal_remove_hdl; +/*----------------------------------------------------------------------------*/ +/**@brief audio_vocal_remove_open 人声消除打开 + @param *_parm: 始化参数,详见结构体vocal_remove_open_parm + @return 句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +vocal_remove_hdl *audio_vocal_remove_open(vocal_remove_open_parm *_parm); + +/*----------------------------------------------------------------------------*/ +/**@brief audio_vocal_remove_close 人声关闭处理 + @param _hdl:句柄 + @return 0:成功 -1:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_vocal_remove_close(vocal_remove_hdl *_hdl); + + +/*----------------------------------------------------------------------------*/ +/**@brief audio_vocal_remove_sw 运行过程开关处理 + @param _hdl:句柄 + @param dis: 0:人声消除有效 1:人声消除无效 + @return 0:成功 -1:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_vocal_remove_sw(vocal_remove_hdl *_hdl, u32 dis); + +#endif + diff --git a/include_lib/media/media_develop/media/application/audio_vocal_tract_synthesis.h b/include_lib/media/media_develop/media/application/audio_vocal_tract_synthesis.h new file mode 100644 index 0000000..28add73 --- /dev/null +++ b/include_lib/media/media_develop/media/application/audio_vocal_tract_synthesis.h @@ -0,0 +1,99 @@ + +#ifndef _AUDIO_VOCAL_TRACT_API_H_ +#define _AUDIO_VOCAL_TRACT_API_H_ + +#include "system/includes.h" +#include "media/includes.h" + +#define FL_FR (BIT(0)|BIT(1)) +#define RL_RR (BIT(2)|BIT(3)) + +struct audio_vocal_tract { + struct list_head head; // 链表头 + s16 *output; // 输出buf + u16 points; // 输出buf总点数 + u16 remain_points; // 输出剩余点数 + u32 process_len; // 输出了多少 + u8 channel_num; // 声道数 + u8 sample_sync; //记录同步模块句柄 + u32 sample_rate; // 当前采样率 + volatile u8 active; // 活动标记。1-正在运行 + + struct audio_stream *stream; // 音频流 + struct audio_stream_entry entry; // 音频流入口,后级接mixer +}; + +struct audio_vocal_tract_ch { + u32 start : 1; // 启动标记。1-已经启动。输出时标记一次 + u32 open : 1; // 打开标记。1-已经打开。输出标记为1,reset标记为0 + u32 pause : 1; // 暂停标记。1-暂停 + u32 wait_resume : 1; + u16 offset; // 当前通道在输出buf中的偏移位置 + u32 synthesis_tar; //输入目标声道 FL:bit0, FR:bit1, RL:bit2, RR:bit3 + + struct list_head list_entry; + struct audio_vocal_tract *vocal_tract; + struct audio_stream_entry entry; // 音频流入口,通道后面不应该再接其他的音频流,最后由mixer合并后输出 +}; + +/*----------------------------------------------------------------------------*/ +/**@brief 打开声道合并 + @param *vocal_tract: 句柄 + @param len:声道合并buf长度 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_vocal_tract_open(struct audio_vocal_tract *vocal_tract, u32 len); + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭声道合并 + @param *vocal_tract: 句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_vocal_tract_close(struct audio_vocal_tract *vocal_tract); + + +/*----------------------------------------------------------------------------*/ +/**@brief 声道合并的通道数 + @param *vocal_tract: 句柄 + @param channel_num:输出通道数,支持(四声道) + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_vocal_tract_set_channel_num(struct audio_vocal_tract *vocal_tract, u8 channel_num); + +/*----------------------------------------------------------------------------*/ +/**@brief 声道合并数据流激活 + @param *priv: 句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_vocal_tract_stream_resume(void *priv); + + +/*----------------------------------------------------------------------------*/ +/**@brief 声道合并输入源通道打开 + @param *ch: 源通道句柄 + @param *vocal_tract:声道合并句柄 + @param synthesis_tar:输出的目标声道 FL_FR、RL_RR + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_vocal_tract_synthesis_open(struct audio_vocal_tract_ch *ch, struct audio_vocal_tract *vocal_tract, u32 synthesis_tar); + +/*----------------------------------------------------------------------------*/ +/**@brief 声道合并输入源通道关闭 + @param *ch:声道输入源句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_vocal_tract_synthesis_close(struct audio_vocal_tract_ch *ch); +#endif + diff --git a/include_lib/media/media_develop/media/application/filtparm_api.h b/include_lib/media/media_develop/media/application/filtparm_api.h new file mode 100644 index 0000000..c376cfd --- /dev/null +++ b/include_lib/media/media_develop/media/application/filtparm_api.h @@ -0,0 +1,30 @@ +#ifndef FILTPARM_CAL_api_h__ +#define FILTPARM_CAL_api_h__ + + +enum { + TYPE_LOWPASS = 0x01, + TYPE_HIGHPASS, + TYPE_BANDPASS, + TYPE_NORTCH, + TYPE_LOWPASS_A, + TYPE_HIGHPASS_A, + TYPE_NULL +}; + + + + + +typedef struct __BFILT_FUNC_API_ { + int (*needbuf)(); //开了3个的空间 + int (*open)(void *ptr); + int (*init)(void *ptr, int freq, int bw, int filt_type, int samplerate, int filtNUM); //滤波器中心频率,带宽,滤波器类型,第几个滤波 + int (*cal_coef)(void *ptr, int *filtTab, int gain, int filtNUM); //传入增益,计算到的滤波器表 + void (*run)(void *ptr, short *data, int len); +} BFILT_FUNC_API; + + +extern BFILT_FUNC_API *get_bfiltTAB_func_api(); + +#endif // reverb_api_h__ diff --git a/include_lib/media/media_develop/media/audio_base.h b/include_lib/media/media_develop/media/audio_base.h new file mode 100644 index 0000000..5ff0b7e --- /dev/null +++ b/include_lib/media/media_develop/media/audio_base.h @@ -0,0 +1,87 @@ +#ifndef AUDIO_BASE_H +#define AUDIO_BASE_H + + + +#define AUDIO_CODING_UNKNOW 0x00000000 +#define AUDIO_CODING_MP3 0x00000001 +#define AUDIO_CODING_WMA 0x00000002 +#define AUDIO_CODING_WAV 0x00000004 +#define AUDIO_CODING_SBC 0x00000010 +#define AUDIO_CODING_MSBC 0x00000020 +#define AUDIO_CODING_G729 0x00000040 +#define AUDIO_CODING_CVSD 0x00000080 +#define AUDIO_CODING_PCM 0x00000100 +#define AUDIO_CODING_AAC 0x00000200 +#define AUDIO_CODING_MTY 0x00000400 +#define AUDIO_CODING_FLAC 0x00000800 +#define AUDIO_CODING_APE 0x00001000 +#define AUDIO_CODING_M4A 0x00002000 +#define AUDIO_CODING_AMR 0x00004000 +#define AUDIO_CODING_DTS 0x00008000 +#define AUDIO_CODING_APTX 0x00010000 +#define AUDIO_CODING_LDAC 0x00020000 +#define AUDIO_CODING_G726 0x00040000 +#define AUDIO_CODING_MIDI 0x00080000 +#define AUDIO_CODING_OPUS 0x00100000 +#define AUDIO_CODING_SPEEX 0x00200000 +#define AUDIO_CODING_ALAC 0x00400000 +#define AUDIO_CODING_MIDI_CTRL 0x00800000 +#define AUDIO_CODING_WTGV2 0x01000000 + +#define AUDIO_CODING_STU_PICK 0x10000000 +#define AUDIO_CODING_STU_APP 0x20000000 + +#define AUDIO_CODING_FAME_MASK (AUDIO_CODING_MSBC | AUDIO_CODING_CVSD | AUDIO_CODING_SBC) + +#define AUDIO_INPUT_FILE 0x01 +#define AUDIO_INPUT_FRAME 0x02 + + +enum audio_channel { + AUDIO_CH_LR = 0, //立体声 + AUDIO_CH_L, //左声道(单声道) + AUDIO_CH_R, //右声道(单声道) + AUDIO_CH_DIFF, //差分(单声道) + AUDIO_CH_DUAL_L, //双声道都为左 + AUDIO_CH_DUAL_R, //双声道都为右 + AUDIO_CH_DUAL_LR, //双声道为左右混合 + AUDIO_CH_QUAD, //四声道(LRLR) + + AUDIO_CH_MAX = 0xff, +}; + +#define AUDIO_CH_IS_MONO(ch) (((ch)==AUDIO_CH_L) || ((ch)==AUDIO_CH_R) || ((ch)==AUDIO_CH_DIFF)) +#define AUDIO_CH_IS_DUAL(ch) (((ch)==AUDIO_CH_LR) || ((ch)==AUDIO_CH_DUAL_L) || ((ch)==AUDIO_CH_DUAL_R)) +#define AUDIO_CH_IS_QUAD(ch) (((ch)==AUDIO_CH_QUAD)) + + +struct audio_fmt { + u8 channel; + u8 frame_len; + u32 sample_rate; + u32 coding_type; + u32 bit_rate; + u32 total_time; + u32 quality; + u32 complexity; + void *priv; +}; + + + + + + + + + + + + + + + + +#endif + diff --git a/include_lib/media/media_develop/media/audio_cfifo.h b/include_lib/media/media_develop/media/audio_cfifo.h new file mode 100644 index 0000000..8a33bec --- /dev/null +++ b/include_lib/media/media_develop/media/audio_cfifo.h @@ -0,0 +1,206 @@ +/***************************************************************** +>file name : audio_cfifo.h +>author : lichao +>create time : Tue 10 Nov 2020 02:22:37 PM CST +*****************************************************************/ +#ifndef _AUDIO_CFIFO_H_ +#define _AUDIO_CFIFO_H_ +#include "generic/list.h" +#include "typedef.h" + +#define WRITE_MODE_BLOCK 0 +#define WRITE_MODE_FORCE 1 + +struct audio_cfifo { + u8 sample_channel; /*fifo采样声道数*/ + s16 *addr; /*fifo首地址*/ + u16 sample_size; /*fifo采样长度*/ + u16 wp; /*fifo写偏移*/ + u16 rp; /*fifo读偏移*/ + u16 lock_rp; /*fifo不可擦写的已读偏移*/ + u16 free_samples; /*fifo可写入样点个数*/ + s16 unread_samples; /*fifo未读样点个数*/ + int sample_rate; /*fifo对应的音频采样率*/ + struct list_head head; /*子通道数据链表头*/ +}; + +struct audio_cfifo_channel { + u8 write_mode; /*写入模式*/ + u16 delay_time; /*最大延时(ms)*/ + u16 rsp; /*读偏移*/ + u16 wsp; /*写偏移*/ + s16 unread_samples; /*通道未读样点个数*/ + u16 max_samples; /*通道缓冲最大样点个数*/ + struct audio_cfifo *fifo; /*主fifo指针*/ + struct list_head entry; /*通道接入entry*/ +}; + +/************************************************************************* + * Audio cfifo主fifo初始化 + * INPUT : fifo - 主fifo结构指针, + * buf - fifo缓冲地址 + * len - fifo缓冲长度 + * sample_rate - fifo音频采样率 + * channel - fifo音频声道数 + * OUTPUT : 0 - 成功,非0 - 失败. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_cfifo_init(struct audio_cfifo *fifo, void *buf, int len, int sample_rate, u8 channel); + +/************************************************************************* + * Audio cfifo主fifo复位 + * INPUT : fifo - 主fifo结构指针, + * buf - fifo缓冲地址 + * len - fifo缓冲长度 + * sample_rate - fifo音频采样率 + * channel - fifo音频声道数 + * OUTPUT : 0 - 成功,非0 - 失败. + * WARNINGS : 这里与audio_cfifo_init类似但意义不一样,不可以当作init使用. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_cfifo_reset(struct audio_cfifo *fifo, void *buf, int len, int sample_rate, u8 channel); + +/************************************************************************* + * 添加fifo子通道 + * INPUT : fifo - 主fifo结构指针, + * ch - fifo子通道 + * delay_time - 子通道延时 + * write_mode - 子通道写入模式 + * OUTPUT : 0 - 成功,非0 - 失败. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_cfifo_channel_add(struct audio_cfifo *fifo, struct audio_cfifo_channel *ch, int delay_time, u8 write_mode); + +/************************************************************************* + * 删除fifo子通道 + * INPUT : ch - fifo子通道 + * OUTPUT : 无. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +void audio_cfifo_channel_del(struct audio_cfifo_channel *ch); + +/************************************************************************* + * 主fifo读数更新 + * INPUT : fifo - 主fifo结构指针, samples - 读取的样点个数 + * OUTPUT : 成功更新的样点个数. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_cfifo_read_update(struct audio_cfifo *fifo, int samples); + +/************************************************************************* + * fifo子通道数据写入 + * INPUT : ch - fifo子通道, data - 数据指针, len - 数据长度 + * OUTPUT : 写入fifo的长度. + * WARNINGS : 强制写入模式无论是否可以写入都将返回预期写入长度. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_cfifo_channel_write(struct audio_cfifo_channel *ch, void *data, int len); + +/************************************************************************* + * fifo子通道写入直流数据 + * INPUT : ch - fifo子通道, data - 直流值, len - 长度 + * OUTPUT : 写入fifo的长度. + * WARNINGS : 强制写入模式无论是否可以写入都将返回预期写入长度. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_cfifo_channel_write_fixed_data(struct audio_cfifo_channel *ch, s16 data, int len); + +/************************************************************************* + * fifo子通道擦除 + * INPUT : ch - fifo子通道 + * OUTPUT : 未知. + * WARNINGS : 待开发. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_cfifo_channel_clear(struct audio_cfifo_channel *ch); + +/************************************************************************* + * 主fifo获取写偏移 + * INPUT : fifo - 主fifo结构指针 + * OUTPUT : fifo写入偏移. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_cfifo_get_write_offset(struct audio_cfifo *fifo); + +/************************************************************************* + * 主fifo获取未读样点查询 + * INPUT : fifo - 主fifo结构指针 + * OUTPUT : 样点个数. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_cfifo_get_unread_samples(struct audio_cfifo *fifo); + +/************************************************************************* + * 主fifo与子fifo未读样点个数差值 + * INPUT : ch - fifo子通道 + * OUTPUT : 样点个数. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_cfifo_channel_unread_diff_samples(struct audio_cfifo_channel *ch); + +/************************************************************************* + * 主fifo通道个数 + * INPUT : fifo - 主fifo结构指针 + * OUTPUT : 通道个数. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_cfifo_channel_num(struct audio_cfifo *fifo); + +/************************************************************************* + * 主fifo设置已读样点不可擦除区域 + * INPUT : fifo - 主fifo结构指针, samples - 不可擦除样点个数 + * OUTPUT : 无. + * WARNINGS : 特殊处理,无需理解,仅作为开发人员使用. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +void audio_cfifo_set_readlock_samples(struct audio_cfifo *fifo, int samples); + +/************************************************************************* + * fifo使用回调读取通道的有效混合数据 + * INPUT : fifo - 主fifo结构指针 + * offset - 读偏移 + * samples - 读取样点个数 + * priv - 回调私有指针 + * read_callback - 读回调 + * OUTPUT : 读取长度. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_cfifo_read_with_callback(struct audio_cfifo *fifo, int offset, int samples, + void *priv, int (*read_callback)(void *priv, void *data, int len)); + +/************************************************************************* + * fifo子通道未读样点查询 + * INPUT : ch - fifo子通道 + * OUTPUT : 样点个数. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_cfifo_channel_unread_samples(struct audio_cfifo_channel *ch); + +/************************************************************************* + * fifo子通道获取写偏移 + * INPUT : ch - fifo子通道 + * OUTPUT : 偏移. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_cfifo_channel_write_offset(struct audio_cfifo_channel *ch); + +/************************************************************************* + * fifo获取缓冲最小的子通道 + * INPUT : fifo - 主fifo结构指针 + * OUTPUT : fifo子通道指针. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +struct audio_cfifo_channel *audio_cfifo_min_samples_channel(struct audio_cfifo *fifo); +#endif diff --git a/include_lib/media/media_develop/media/audio_decoder.h b/include_lib/media/media_develop/media/audio_decoder.h new file mode 100644 index 0000000..a823a72 --- /dev/null +++ b/include_lib/media/media_develop/media/audio_decoder.h @@ -0,0 +1,862 @@ +#ifndef AUDIO_DECODER_H +#define AUDIO_DECODER_H + +#include "generic/typedef.h" +#include "generic/list.h" +#include "media/audio_base.h" +#include "media/audio_stream.h" +#include "os/os_api.h" + + + +// 解码事件 +enum { + AUDIO_DEC_EVENT_CURR_TIME = 0x20, + AUDIO_DEC_EVENT_END, + AUDIO_DEC_EVENT_ERR, + AUDIO_DEC_EVENT_SUSPEND, + AUDIO_DEC_EVENT_RESUME, + AUDIO_DEC_EVENT_START, +}; + +// 资源回调事件 +enum { + AUDIO_RES_GET, + AUDIO_RES_PUT, +}; + +// 解码状态 +enum { + DEC_STA_TRY_START, + DEC_STA_START, + DEC_STA_WAIT_STOP, + DEC_STA_WAIT_SUSPEND, + DEC_STA_WAIT_RESUME, + DEC_STA_WAIT_PAUSE, +}; + +// AB点复读模式 +enum { + AB_REPEAT_MODE_BP_A = 0x01, + AB_REPEAT_MODE_BP_B, + AB_REPEAT_MODE_CUR, +}; + +// 解码器命令 +enum { + AUDIO_IOCTRL_CMD_SET_BREAKPOINT_A = 0x08, // 设置复读A点 + AUDIO_IOCTRL_CMD_SET_BREAKPOINT_B, // 设置复读B点 + AUDIO_IOCTRL_CMD_SET_BREAKPOINT_MODE, // 设置AB点复读模式 + + AUDIO_IOCTRL_CMD_REPEAT_PLAY = 0x90, // 设置循环播放 + AUDIO_IOCTRL_CMD_SET_DEST_PLAYPOS = 0x93, // 设置指定位置播放 + AUDIO_IOCTRL_CMD_GET_PLAYPOS = 0x94, // 获取毫秒级时间 +}; + +/* + * 指定位置播放 + * 设置后跳到start_time开始播放, + * 播放到dest_time后如果callback_func存在,则调用callback_func, + * 可以在callback_func回调中实现对应需要的动作 + */ +struct audio_dest_time_play_param { + u32 start_time; // 要跳转过去播放的起始时间。单位:ms + u32 dest_time; // 要跳转过去播放的目标时间。单位:ms + u32(*callback_func)(void *priv); // 到达目标时间后回调 + void *callback_priv; // 回调参数 +}; + +/* + * 获取毫秒级解码时间 + */ +struct audio_get_play_ms_time_param { + u32 time_ms; +}; + +/* + * ab点复读模式结构体 + */ +struct audio_ab_repeat_mode_param { + u32 value; +}; + +/* + * 循环播放fifo + */ +struct fixphase_repair_obj { + short fifo_buf[18 + 12][32][2]; +}; + +/* + * 循环播放结构体 + * 每次播放会根据headcut_frame和tailcut_frame来砍掉一些不需要的帧 + * 在repeat_callback()回调中可以自主控制播放次数,返回非0即结束循环 + */ +struct audio_repeat_mode_param { + int flag; + int headcut_frame; // 砍掉前面几帧,仅mp3格式有效 + int tailcut_frame; // 砍掉后面几帧,仅mp3格式有效 + int (*repeat_callback)(void *); // 循环播放回调,返回0-正常循环;返回非0-结束循环 + void *callback_priv; + struct fixphase_repair_obj *repair_buf; +}; + +/* + *解码任务cpu占用率跟踪: + *跟踪周期trace_period内,如果解码任务空闲时间统计少于 + *期望值(idle_expect),就会触发饱和保护机制。默认是挂起自 + *身pend_time.如果想要自己做处理,只需注册trace_hdl即可 + */ +struct audio_decoder_occupy { + u8 pend_time; //挂起时间,os_time_dly(pend_time) + u16 idle_expect; //跟踪周期内期望idle时间 + u16 trace_period; //跟踪周期,单位:ms + int (*trace_hdl)(void *priv, u32 idle_total); //跟踪回调函数 +}; + +/* + * 资源处理结构体 + * res会先挂载到链表中,然后依据以下规律依次执行: + * protect置1时,马上开始播放(叠加播放),不会结束其他的res + * preemption置1时,马上开始播放(抢占播放),会结束当前非protect模式的res + * protect和preemption为0时,依据priority优先级播放 + * 按优先级排序的情况下,由snatch_same_prio决定是否放在同优先级的前面 + * preemption方式和priority优先级方式,同一时刻只会有一个解码 + * preemption方式的全部播放完后才开始播放按priority优先级排序的 + */ +struct audio_res_wait { + struct list_head list_entry; // 链表。用于多个解码抢占/排序等 + u8 priority; // 优先级 + u8 preemption : 1; // 抢占 + u8 protect : 1; // 保护(叠加) + u8 only_del : 1; // 仅删除 + u8 snatch_same_prio : 1; // 放在同优先级的前面 + u8 is_work : 1; // 已经运行 + u32 format; // 格式锁 + int (*handler)(struct audio_res_wait *, int event); // 回调 +}; + +/* + * 解码任务结构体 + * 链接所有的解码,按list链表循环执行 + */ +struct audio_decoder_task { + struct list_head head; // 用于解码任务中的轮询处理 + struct list_head wait; // 用于多个解码抢占/排序等 + struct audio_decoder_occupy occupy;// + const char *name; // 解码任务名称 + int wakeup_timer; // 定时唤醒 + int fmt_lock; // 格式锁 + u16 is_add_wait : 1; // 正在添加res资源 + u16 step_cnt : 8; + u16 step_timer; + void *out_task; // 使用单独任务做输出 +}; + + +/* + * 解码断点结构体 + */ +struct audio_dec_breakpoint { + int len; + u32 fptr; + int data_len; + u8 data[0]; + // u8 data[128]; +}; + +struct audio_decoder; + + +/* + * 解码输入接口 + * 用于获取音频数据,分为音频文件和音频流 + */ +struct audio_dec_input { + u32 coding_type; + // 定义在p_more_coding_type数组中的解码器会依照顺序依次检测 + // 先检测coding_type再检测p_more_coding_type + u32 *p_more_coding_type; + u32 data_type : 8; + union { + struct { // data_type == AUDIO_INPUT_FILE + int (*fread)(struct audio_decoder *, void *buf, u32 len); + int (*fseek)(struct audio_decoder *, u32 offset, int seek_mode); + int (*ftell)(struct audio_decoder *); + int (*flen)(struct audio_decoder *); + } file; + + struct { // data_type == AUDIO_INPUT_FRAME + int (*fget)(struct audio_decoder *, u8 **frame); + void (*fput)(struct audio_decoder *, u8 *frame); + int (*ffetch)(struct audio_decoder *, u8 **frame); + } frame; + } ops; +}; + +/* + * 解码处理过程中的回调 + */ +struct audio_dec_handler { + int (*dec_probe)(struct audio_decoder *); // 预处理。返回非0值不跑后续的解码run + // 解码输出。解码会自动输出到数据流中,上层不必要实现该函数 + int (*dec_output)(struct audio_decoder *, s16 *data, int len, void *priv); + int (*dec_post)(struct audio_decoder *); // 后处理 + int (*dec_stop)(struct audio_decoder *); // 解码结束 +}; + +/* + * 数据流解码信息 + */ +struct stream_codec_info { + int time; + int frame_num; + u32 frame_len; + int frame_points; + int sequence_number; + u32 sample_rate; + u8 channel; +}; + +/* + * 解码器结构体 + * 所有挂载到解码的解码器都需要该结构体 + * 至少需要实现open/start/run/close等函数 + */ +struct audio_decoder_ops { + u32 coding_type; + void *(*open)(void *priv); // 打开解码器,获取句柄 + int (*start)(void *); // 启动解码 + int (*get_fmt)(void *, struct audio_fmt *fmt); // 获取解码信息 + int (*set_output_channel)(void *, enum audio_channel); // 设置输出声道 + int (*get_play_time)(void *); // 获取当前解码时间 + int (*fast_forward)(void *, int step_s); // 快进,step单位:秒 + int (*fast_rewind)(void *, int step_s); // 快退,step单位:秒 + int (*get_breakpoint)(void *, struct audio_dec_breakpoint *); // 获取断点信息 + int (*set_breakpoint)(void *, struct audio_dec_breakpoint *); // 设置断点buf + int (*stream_info_scan)(void *, struct stream_codec_info *info, void *data, int len); // 数据流信息检测 + int (*set_tws_mode)(void *, int); // 设置tws解码模式 + int (*run)(void *, u8 *); // 运行解码 + int (*stop)(void *); // 停止解码 + int (*close)(void *); // 关闭解码,释放空间 + int (*reset)(void *); // 重启解码 + int (*ioctrl)(void *, u32 cmd, void *parm); // 解码控制。如设置AB点复读等 +}; + +#define REGISTER_AUDIO_DECODER(ops) \ + const struct audio_decoder_ops ops SEC(.audio_decoder) + +extern const struct audio_decoder_ops audio_decoder_begin[]; +extern const struct audio_decoder_ops audio_decoder_end[]; + +#define list_for_each_audio_decoder(p) \ + for (p = audio_decoder_begin; p < audio_decoder_end; p++) + + +/* + * 解码通道 + */ +struct audio_decoder { + struct list_head list_entry; // 链表。用于解码任务中轮询处理 + struct audio_decoder_task *task; // 解码任务 + struct audio_fmt fmt; // 解码格式 + const char *evt_owner; // 用于接受消息的任务名称 + const struct audio_dec_input *input; // 解码输入接口 + const struct audio_decoder_ops *dec_ops; // 解码器接口 + const struct audio_dec_handler *dec_handler; // 解码处理回调 + void (*evt_handler)(struct audio_decoder *dec, int, int *); // 事件回调 + void *dec_priv; // 解码器对应句柄 + void *bp; // 断点 + // u16 id; // ID号 + u16 pick : 1; // 本地拆包解码标记 + u16 tws : 1; // 本地tws解码标记 + u16 output_err : 1; // 解码输出错误 + u16 read_err : 1; // 解码读取错误 + u16 open_step : 4; + u8 run_max; // 正常解码最大次数 + // u8 output_channel; // 输出通道 + u8 state; // 解码状态 + u8 err; // 解码结束错误类型标记 + u8 remain; // 解码输出完成标记 + volatile u8 resume_flag;// 解码激活标记 + u32 magic; // 事件回调的私有标记 + u32 process_len; // 数据流处理长度 + struct audio_stream_entry entry; // 音频流入口 + void *out_task_ch; // 使用单独任务做输出 +}; + +// 解码输出声道类型 +#define AUDIO_DEC_ORIG_CH AUDIO_CH_LR +#define AUDIO_DEC_L_CH AUDIO_CH_L +#define AUDIO_DEC_R_CH AUDIO_CH_R +#define AUDIO_DEC_MONO_LR_CH AUDIO_CH_DIFF +#define AUDIO_DEC_DUAL_L_CH AUDIO_CH_DUAL_L +#define AUDIO_DEC_DUAL_R_CH AUDIO_CH_DUAL_R +#define AUDIO_DEC_DUAL_LR_CH AUDIO_CH_DUAL_LR + +#define AUDIO_DEC_IS_MONO(ch) (((ch)==AUDIO_DEC_L_CH) || ((ch)==AUDIO_DEC_R_CH) || ((ch)==AUDIO_DEC_MONO_LR_CH)) + +/* +********************************************************************* +* Audio Decoder Task Create +* Description: 创建解码任务 +* Arguments : *task 任务句柄 +* *name 任务名 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_decoder_task_create(struct audio_decoder_task *task, const char *name); + +/* +********************************************************************* +* Audio Decoder Task Add ResWait +* Description: 解码任务增加解码通道资源 +* Arguments : *task 解码任务句柄 +* *wait 解码资源句柄 +* Return : 0 成功 +* Note(s) : 加入链表后,按*wait配置信息播放 +********************************************************************* +*/ +int audio_decoder_task_add_wait(struct audio_decoder_task *task, struct audio_res_wait *wait); + +/* +********************************************************************* +* Audio Decoder Task Delete ResWait +* Description: 解码任务删除解码通道资源 +* Arguments : *task 解码任务句柄 +* *wait 解码资源句柄 +* Return : None. +* Note(s) : 当前的删除后,如果链表中还有res,按规则继续播放 +********************************************************************* +*/ +void audio_decoder_task_del_wait(struct audio_decoder_task *task, struct audio_res_wait *wait); + +/* +********************************************************************* +* Audio Decoder Get Task ResWait state +* Description: 获取解码任务链表中的资源数量 +* Arguments : *task 解码任务句柄 +* Return : ResWait数量 +* Note(s) : None. +********************************************************************* +*/ +int audio_decoder_task_wait_state(struct audio_decoder_task *task); + +/* +********************************************************************* +* Audio Decoder Resume All Decoder Channel +* Description: 激活解码任务链表中的所有解码 +* Arguments : *task 解码任务句柄 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_decoder_resume_all(struct audio_decoder_task *task); + +/* +********************************************************************* +* Audio Decoder Add Format Lock +* Description: 解码任务资源添加格式锁 +* Arguments : *task 解码任务句柄 +* fmt 解码格式 +* Return : 0 成功 +* Note(s) : 锁定后,后续的解码将不能使用该解码 +********************************************************************* +*/ +int audio_decoder_fmt_lock(struct audio_decoder_task *task, int fmt); + +/* +********************************************************************* +* Audio Decoder Add Format Unlock +* Description: 解码任务资源格式锁解锁 +* Arguments : *task 解码任务句柄 +* fmt 解码格式 +* Return : 0 成功 +* Note(s) : 解锁后,后续的解码可以使用该解码 +********************************************************************* +*/ +int audio_decoder_fmt_unlock(struct audio_decoder_task *task, int fmt); + + +/* +********************************************************************* +* Audio Decoder Output +* Description: 解码输出 +* Arguments : *_dec 解码句柄 +* *buf 输出buf +* len 输出长度 +* *priv 私有参数 +* Return : 输出了多少数据 +* Note(s) : 解码输出不了会被挂起,需要调用resume激活该解码 +********************************************************************* +*/ +int audio_decoder_put_output_buff(void *_dec, void *buff, int len, void *priv); + +/* +********************************************************************* +* Audio Decoder Read Data +* Description: 解码读数 +* Arguments : *_dec 解码句柄 +* *buf 输出buf +* len 输出长度 +* offset 读数偏移 +* Return : 读到了多长(错误返回负数) +* Note(s) : 仅文件解码可用 +********************************************************************* +*/ +int audio_decoder_read_data(void *_dec, u8 *data, int len, u32 offset); + +/* +********************************************************************* +* Audio Decoder Get Input Len +* Description: 获取解码文件长度 +* Arguments : *_dec 解码句柄 +* Return : 文件长度 +* Note(s) : 仅文件解码可用 +********************************************************************* +*/ +int audio_decoder_get_input_data_len(void *_dec); + +/* +********************************************************************* +* Audio Decoder Get Frame Data +* Description: 获取流数据帧内容 +* Arguments : *_dec 解码句柄 +* **frame 返回帧信息 +* Return : 帧长度 +* Note(s) : 仅流数据解码可用 +********************************************************************* +*/ +int audio_decoder_get_frame(void *_dec, u8 **frame); + +/* +********************************************************************* +* Audio Decoder Fetch Frame +* Description: 检查流数据帧内容 +* Arguments : *_dec 解码句柄 +* **frame 返回帧信息 +* Return : 帧长度 +* Note(s) : 仅流数据解码可用。数据没有读走,仅查看内容 +********************************************************************* +*/ +int audio_decoder_fetch_frame(void *_dec, u8 **frame); + +/* +********************************************************************* +* Audio Decoder Put Frame +* Description: 流数据帧使用完 +* Arguments : *_dec 解码句柄 +* *frame 帧信息 +* Return : None. +* Note(s) : 仅流数据解码可用 +********************************************************************* +*/ +void audio_decoder_put_frame(void *_dec, u8 *frame); + +/* +********************************************************************* +* Audio Decoder Open Channel +* Description: 打开一个解码通道 +* Arguments : *dec 解码句柄 +* *input: 解码输入参数信息 +* *task: 解码任务句柄 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_decoder_open(struct audio_decoder *dec, const struct audio_dec_input *input, + struct audio_decoder_task *task); + +/* +********************************************************************* +* Audio Decoder Get Data Type +* Description: 获取配置的解码类型 +* Arguments : *_dec 解码句柄 +* Return : 解码类型AUDIO_INPUT_FILE或者AUDIO_INPUT_FRAME +* Note(s) : None. +********************************************************************* +*/ +int audio_decoder_data_type(void *_dec); + +/* +********************************************************************* +* Audio Decoder Get Format +* Description: 获取解码器格式信息 +* Arguments : *_dec 解码句柄 +* **fmt 获取到的格式信息 +* Return : 0 成功 +* Note(s) : 解码器没有打开时,尝试打开解码器 +********************************************************************* +*/ +int audio_decoder_get_fmt(struct audio_decoder *dec, struct audio_fmt **fmt); + +/* +********************************************************************* +* Audio Decoder Set Format +* Description: 设置解码的格式信息 +* Arguments : *_dec 解码句柄 +* *fmt 格式信息 +* Return : 0 成功 +* Note(s) : 直接指定解码格式,如sbc解码等 +********************************************************************* +*/ +int audio_decoder_set_fmt(struct audio_decoder *dec, struct audio_fmt *fmt); + +/* +********************************************************************* +* Audio Decoder Get Format Info +* Description: 实时获取解码器格式信息 +* Arguments : *dec 解码句柄 +* *fmt 获取到的格式信息 +* Return : 0 成功 +* Note(s) : 需要在解码成功后才能调用。函数中调用解码器get_fmt()接口 +********************************************************************* +*/ +int audio_decoder_get_fmt_info(struct audio_decoder *dec, struct audio_fmt *fmt); + +/* +********************************************************************* +* Audio Decoder Set Deal Handler +* Description: 设置解码处理handler +* Arguments : *dec 解码句柄 +* *handler 解码处理handler +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_decoder_set_handler(struct audio_decoder *dec, const struct audio_dec_handler *handler); + + +/* +********************************************************************* +* Audio Decoder Set Event Handler +* Description: 设置解码事件回调 +* Arguments : *dec 解码句柄 +* *handler 回调函数 +* maigc 私有标识 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_decoder_set_event_handler(struct audio_decoder *dec, + void (*handler)(struct audio_decoder *, int, int *), u32 magic); + + +/* +********************************************************************* +* Audio Decoder Set Output Channel +* Description: 设置解码输出声道类型 +* Arguments : *dec 解码句柄 +* channel 声道类型 +* Return : 0 成功 +* Note(s) : 函数中调用解码器set_output_channel()接口 +********************************************************************* +*/ +int audio_decoder_set_output_channel(struct audio_decoder *dec, enum audio_channel); + +/* +********************************************************************* +* Audio Decoder Start +* Description: 启动解码 +* Arguments : *dec 解码句柄 +* Return : 0 成功 +* Note(s) : 函数中调用解码器start()接口 +********************************************************************* +*/ +int audio_decoder_start(struct audio_decoder *dec); + +/* +********************************************************************* +* Audio Decoder Stop +* Description: 停止解码 +* Arguments : *dec 解码句柄 +* Return : 0 成功 +* Note(s) : None +********************************************************************* +*/ +int audio_decoder_stop(struct audio_decoder *dec); + +/* +********************************************************************* +* Audio Decoder Pause +* Description: 解码暂停 +* Arguments : *dec 解码句柄 +* Return : 0 成功 +* Note(s) : None +********************************************************************* +*/ +int audio_decoder_pause(struct audio_decoder *dec); + +/* +********************************************************************* +* Audio Decoder Suspend +* Description: 解码挂起 +* Arguments : *dec 解码句柄 +* Return : 0 成功 +* Note(s) : None +********************************************************************* +*/ +int audio_decoder_suspend(struct audio_decoder *dec); + +/* +********************************************************************* +* Audio Decoder Resume +* Description: 解码挂起激活 +* Arguments : *dec 解码句柄 +* Return : 0 成功 +* Note(s) : None +********************************************************************* +*/ +int audio_decoder_resume(struct audio_decoder *dec); + +/* +********************************************************************* +* Audio Decoder Close +* Description: 关闭解码 +* Arguments : *dec 解码句柄 +* Return : 0 成功 +* Note(s) : None +********************************************************************* +*/ +int audio_decoder_close(struct audio_decoder *dec); + +/* +********************************************************************* +* Audio Decoder Reset +* Description: 解码器reset +* Arguments : *dec 解码句柄 +* Return : 0 成功 +* Note(s) : 函数中调用解码器reset()接口 +********************************************************************* +*/ +int audio_decoder_reset(struct audio_decoder *dec); + +/* +********************************************************************* +* Audio Decoder Set Breakpoint Handler +* Description: 设置解码断点句柄 +* Arguments : *dec 解码句柄 +* *bp 断点句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_decoder_set_breakpoint(struct audio_decoder *dec, struct audio_dec_breakpoint *bp); + +/* +********************************************************************* +* Audio Decoder Get Breakpoint +* Description: 获取解码断点信息 +* Arguments : *dec 解码句柄 +* *bp 断点句柄 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_decoder_get_breakpoint(struct audio_decoder *dec, struct audio_dec_breakpoint *bp); + +/* +********************************************************************* +* Audio Decoder Forward +* Description: 解码快进 +* Arguments : *dec 解码句柄 +* step_s 快进步伐(按秒计数) +* Return : 0 成功 +* Note(s) : 函数中调用解码器fast_forward()接口 +********************************************************************* +*/ +int audio_decoder_forward(struct audio_decoder *dec, int step_s); + +/* +********************************************************************* +* Audio Decoder Rewind +* Description: 解码快退 +* Arguments : *dec 解码句柄 +* step_s 快退步伐(按秒计数) +* Return : 0 成功 +* Note(s) : 函数中调用解码器fast_rewind()接口 +********************************************************************* +*/ +int audio_decoder_rewind(struct audio_decoder *dec, int step_s); + +/* +********************************************************************* +* Audio Decoder Get Total Time +* Description: 获取解码总时间 +* Arguments : *dec 解码句柄 +* Return : 解码总时间 +* Note(s) : None. +********************************************************************* +*/ +int audio_decoder_get_total_time(struct audio_decoder *dec); + +/* +********************************************************************* +* Audio Decoder Get Play Time +* Description: 获取解码当前时间 +* Arguments : *dec 解码句柄 +* Return : 解码当前时间 +* Note(s) : 函数中调用解码器get_play_time()接口 +********************************************************************* +*/ +int audio_decoder_get_play_time(struct audio_decoder *dec); + +/* +********************************************************************* +* Audio Decoder Set Pick Status +* Description: 设置解码拆包模式 +* Arguments : *dec 解码句柄 +* pick 拆包使能 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_decoder_set_pick_stu(struct audio_decoder *dec, u8 pick); + +/* +********************************************************************* +* Audio Decoder Get Pick Status +* Description: 获取解码拆包模式 +* Arguments : *dec 解码句柄 +* Return : 1 拆包 +* Note(s) : None. +********************************************************************* +*/ +int audio_decoder_get_pick_stu(struct audio_decoder *dec); + +/* +********************************************************************* +* Audio Decoder Set Tws Status +* Description: 设置解码tws模式 +* Arguments : *dec 解码句柄 +* tws tws模式使能 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_decoder_set_tws_stu(struct audio_decoder *dec, u8 tws); + +/* +********************************************************************* +* Audio Decoder Get Tws Status +* Description: 获取解码tws模式 +* Arguments : *dec 解码句柄 +* Return : 1 tws模式 +* Note(s) : None. +********************************************************************* +*/ +int audio_decoder_get_tws_stu(struct audio_decoder *dec); + +/* +********************************************************************* +* Audio Decoder Set Max Run Number +* Description: 设置解码每次轮询可执行的最大次数 +* Arguments : *dec 解码句柄 +* run_max 最大次数 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_decoder_set_run_max(struct audio_decoder *dec, u8 run_max); + +/* +********************************************************************* +* Audio Decoder Dual Channel Switch To Other +* Description: 双声道转换为其他声道 +* Arguments : ch_type 输出声道类型 +* half_lr 合并声道是否除2 +* *data 数据 +* len 数据长度 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_decoder_dual_switch(u8 ch_type, u8 half_lr, s16 *data, int len); + +/* +********************************************************************* +* Audio Decoder Find Coding Type Have Used +* Description: 检查解码器是否已经使用 +* Arguments : *task 解码任务句柄 +* coding_type 解码器类型 +* Return : 1 已经使用 +* Note(s) : None. +********************************************************************* +*/ +int audio_decoder_find_coding_type(struct audio_decoder_task *task, u32 coding_type); + +/* +********************************************************************* +* Audio Decoder Check Running Decoder Number +* Description: 统计正在运行的解码数 +* Arguments : *task 解码任务句柄 +* Return : 正在运行的解码数 +* Note(s) : 统计解码状态为DEC_STA_START或者DEC_STA_WAIT_RESUME +********************************************************************* +*/ +int audio_decoder_running_number(struct audio_decoder_task *task); + +/* +********************************************************************* +* Audio Decoder Ioctrl +* Description: 解码器控制 +* Arguments : *dec 解码句柄 +* cmd 控制命令 +* *parm 控制参数 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_decoder_ioctrl(struct audio_decoder *dec, u32 cmd, void *parm); + + +/* +********************************************************************* +* Audio Decoder Output Task Create +* Description: 创建解码输出任务 +* Arguments : *task 任务句柄 +* *out_task_name 解码输出任务名 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_decoder_out_task_create(struct audio_decoder_task *task, const char *out_task_name); + +/* +********************************************************************* +* Audio Decoder Output Task Destroy +* Description: 删除解码输出任务 +* Arguments : *task 任务句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_decoder_out_task_destroy(struct audio_decoder_task *task); + +/* +********************************************************************* +* Audio Decoder Output Task Channel Enable +* Description: 设置解码输出任务使能 +* Arguments : *dec 解码句柄 +* len 输出缓存长度 +* Return : 0 成功 +* Note(s) : 当解码输出长度大于设置的长度时,会关闭该通道输出任务使能 +********************************************************************* +*/ +int audio_decoder_out_task_ch_enable(struct audio_decoder *dec, int len); + +/* +********************************************************************* +* Audio Decoder Resume Output Task +* Description: 激活解码输出任务 +* Arguments : *dec 解码句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_decoder_resume_out_task(struct audio_decoder *dec); + + +#endif + diff --git a/include_lib/media/media_develop/media/audio_encoder.h b/include_lib/media/media_develop/media/audio_encoder.h new file mode 100644 index 0000000..b097765 --- /dev/null +++ b/include_lib/media/media_develop/media/audio_encoder.h @@ -0,0 +1,354 @@ +#ifndef AUDIO_ENCODER_H +#define AUDIO_ENCODER_H + +#include "generic/typedef.h" +#include "generic/list.h" +#include "generic/circular_buf.h" +#include "media/audio_base.h" + + +// 编码事件 +enum { + AUDIO_ENC_EVENT_CURR_TIME = 0x20, + AUDIO_ENC_EVENT_END, + AUDIO_ENC_EVENT_ERR, + AUDIO_ENC_EVENT_SUSPEND, + AUDIO_ENC_EVENT_RESUME, +}; + + +/* + * 编码任务结构体 + * 链接所有的编码,按list链表循环执行 + */ +struct audio_encoder_task { + struct list_head head; + const char *name; +}; + + +struct audio_encoder; + + +/* + * 编码输入接口 + * 用于获取PCM数据 + */ +struct audio_enc_input { + int (*fget)(struct audio_encoder *, s16 **frame, u16 frame_len); + void (*fput)(struct audio_encoder *, s16 *frame); +}; + +/* + * 编码处理过程中的回调 + */ +struct audio_enc_handler { + int (*enc_probe)(struct audio_encoder *); + int (*enc_output)(struct audio_encoder *, u8 *data, int len); + int (*enc_post)(struct audio_encoder *); + int (*enc_close)(struct audio_encoder *);//add by wuxu 20200221 +}; + +/* + * 编码器结构体 + * 所有挂载到编码的编码器都需要该结构体 + * 至少需要实现open/start/run/close等函数 + */ +struct audio_encoder_ops { + u32 coding_type; + void *(*open)(void *priv); + int (*start)(void *); + int (*set_fmt)(void *, struct audio_fmt *fmt); + int (*run)(void *); + int (*stop)(void *); + int (*close)(void *); + int (*ioctrl)(void *, int argc, int argv[]); +}; + +#define REGISTER_AUDIO_ENCODER(ops) \ + const struct audio_encoder_ops ops SEC(.audio_encoder) + +extern const struct audio_encoder_ops audio_encoder_begin[]; +extern const struct audio_encoder_ops audio_encoder_end[]; + +#define list_for_each_audio_encoder(p) \ + for (p = audio_encoder_begin; p < audio_encoder_end; p++) + + +#define AUDIO_ENC_OS_MUTEX_EN 1 + +#if (AUDIO_ENC_OS_MUTEX_EN) +#include "os/os_api.h" +#endif//AUDIO_ENC_OS_MUTEX_EN + +/* + * 编码通道 + */ +struct audio_encoder { + struct list_head entry; // 链表。用于编码任务中轮询处理 + struct audio_encoder_task *task; // 编码任务 + struct audio_fmt fmt; // 编码格式 + const char *evt_owner; // 用于接受消息的任务名称 + const struct audio_enc_input *input; // 编码输入接口 + const struct audio_encoder_ops *enc_ops; // 编码器接口 + const struct audio_enc_handler *enc_handler; // 编码处理回调 + void (*evt_handler)(struct audio_encoder *enc, int, int *); // 事件回调 + void *enc_priv; // 编码器对应句柄 + // u32 pend_timeout; + s16 *pcm_frame; // 编码的帧数据 + u16 pcm_remain; // 帧数据剩余长度 + u16 pcm_len; // 帧数据长度 + s16 *output_buffs; // 输出用的buf + u16 output_buff_size; // 输出buf大小 + u8 output_buff_num; // 输出buf数量 + u8 curr_output_buff; // 当前用的输出buf + // u8 output_channel; + u8 state; // 编码状态 + u8 err; // 编码结束错误类型标记 + volatile u8 resume_flag;// 编码激活标记 + u32 magic; // 事件回调的私有标记 +#if (AUDIO_ENC_OS_MUTEX_EN) + OS_MUTEX mutex; // 互斥 +#endif//AUDIO_ENC_OS_MUTEX_EN +}; + +// 编码器命令 +enum { + AUDIO_ENCODER_IOCTRL_CMD_GET_HEAD_INFO = 0x0, + AUDIO_ENCODER_IOCTRL_CMD_GET_TIME, +}; + +/* +********************************************************************* +* Audio Encoder Task Create +* Description: 创建编码任务 +* Arguments : *task 任务句柄 +* *name 任务名 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_encoder_task_create(struct audio_encoder_task *task, const char *name); + +/* +********************************************************************* +* Audio Encoder Delete Task +* Description: 删除编码任务 +* Arguments : *task 任务句柄 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_encoder_task_del(struct audio_encoder_task *task); + +/* +********************************************************************* +* Audio Encoder Resume All Encoder Channel +* Description: 激活编码任务链表中的所有编码 +* Arguments : *task 任务句柄 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_encoder_resume_all(struct audio_encoder_task *task); + +/* +********************************************************************* +* Audio Encoder Get Output Buff +* Description: 获取编码输出buf +* Arguments : *_enc 编码句柄 +* **buf 输出buf +* Return : 输出buf长度 +* Note(s) : None. +********************************************************************* +*/ +int audio_encoder_get_output_buff(void *_enc, s16 **buf); + +/* +********************************************************************* +* Audio Encoder Put Output Buff +* Description: 编码输出 +* Arguments : *_enc 编码句柄 +* **buf 输出buf +* len 输出长度 +* Return : 输出了多少数据 +* Note(s) : None. +********************************************************************* +*/ +int audio_encoder_put_output_buff(void *_enc, void *buff, int len); + +/* +********************************************************************* +* Audio Encoder Get Frame +* Description: 获取帧数据 +* Arguments : *_enc 编码句柄 +* **frame 返回帧信息 +* frame_len 获取帧最大长度 +* Return : 实际帧长 +* Note(s) : None. +********************************************************************* +*/ +int audio_encoder_get_frame(void *_enc, s16 **frame, u16 len); + +/* +********************************************************************* +* Audio Encoder Put Frame +* Description: 数据帧使用完 +* Arguments : *_enc 编码句柄 +* *frame 帧信息 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_encoder_put_frame(void *_enc, s16 *frame); + +/* +********************************************************************* +* Audio Encoder Open Channel +* Description: 打开一个编码通道 +* Arguments : *enc 编码句柄 +* *input 编码输入参数信息 +* *task 编码任务句柄 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_encoder_open(struct audio_encoder *enc, const struct audio_enc_input *input, + struct audio_encoder_task *task); + +/* +********************************************************************* +* Audio Encoder Get Format +* Description: 获取编码器格式信息 +* Arguments : *enc 编码句柄 +* **fmt 获取到的格式信息 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_encoder_get_fmt(struct audio_encoder *enc, struct audio_fmt **fmt); + +/* +********************************************************************* +* Audio Encoder Set Format +* Description: 设置编码的格式信息 +* Arguments : *enc 编码句柄 +* *fmt 格式信息 +* Return : 0 成功 +* Note(s) : 编码器没有打开时,尝试打开编码器 +********************************************************************* +*/ +int audio_encoder_set_fmt(struct audio_encoder *enc, struct audio_fmt *fmt); + +/* +********************************************************************* +* Audio Encoder Set Deal Handler +* Description: 设置编码处理handler +* Arguments : *enc 编码句柄 +* *handler 编码处理handler +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_encoder_set_handler(struct audio_encoder *enc, const struct audio_enc_handler *handler); + + +/* +********************************************************************* +* Audio Encoder Set Event Handler +* Description: 设置编码事件回调 +* Arguments : *enc 编码句柄 +* *handler 回调函数 +* maigc 私有标识 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_encoder_set_event_handler(struct audio_encoder *enc, + void (*handler)(struct audio_encoder *, int, int *), u32 maigc); + +/* +********************************************************************* +* Audio Encoder Set Output Buff +* Description: 设置编码输出buf +* Arguments : *enc 编码句柄 +* *buffs 输出buf +* buff_size 单个buf大小 +* buff_num 总共多少个buf +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_encoder_set_output_buffs(struct audio_encoder *enc, s16 *buffs, + u16 buff_size, u8 buff_num); + +/* +********************************************************************* +* Audio Encoder Start +* Description: 启动编码 +* Arguments : *enc 编码句柄 +* Return : 0 成功 +* Note(s) : 函数中调用编码器start()接口 +********************************************************************* +*/ +int audio_encoder_start(struct audio_encoder *enc); + +/* +********************************************************************* +* Audio Encoder Stop +* Description: 停止编码 +* Arguments : *enc 编码句柄 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_encoder_stop(struct audio_encoder *enc); + +/* +********************************************************************* +* Audio Encoder Suspend +* Description: 编码挂起 +* Arguments : *enc 编码句柄 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_encoder_suspend(struct audio_encoder *enc, int timeout_ms); + +/* +********************************************************************* +* Audio Encoder Resume +* Description: 编码挂起激活 +* Arguments : *enc 编码句柄 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_encoder_resume(struct audio_encoder *enc); + +/* +********************************************************************* +* Audio Encoder Close +* Description: 关闭编码 +* Arguments : *enc 编码句柄 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_encoder_close(struct audio_encoder *enc); + +/* +********************************************************************* +* Audio Encoder Ioctrl +* Description: 编码器控制 +* Arguments : *enc 编码句柄 +* argc 控制参数 +* Return : -EINVAL 错误。其他 控制器返回 +* Note(s) : 函数中调用编码器ioctrl()接口 +********************************************************************* +*/ +int audio_encoder_ioctrl(struct audio_encoder *enc, int argc, ...); + + +#endif + diff --git a/include_lib/media/media_develop/media/audio_resample.h b/include_lib/media/media_develop/media/audio_resample.h new file mode 100644 index 0000000..92918f3 --- /dev/null +++ b/include_lib/media/media_develop/media/audio_resample.h @@ -0,0 +1,85 @@ +/***************************************************************** +>file name : include_lib/media/media_develop/media/audio_resample.h +>author : lichao +>create time : Fri 07 Aug 2020 11:32:47 AM CST +*****************************************************************/ +#ifndef _AUDIO_RESAMPLE_H_ +#define _AUDIO_RESAMPLE_H_ +#include "typedef.h" +#include "media/audio_stream.h" + +#define AUDIO_HARDWARE_RESAMPLER 0 +#define AUDIO_SOFTWARE_RESAMPLER 1 + +struct audio_resampler; + +struct audio_resample_context { + u8 channel; + int in_sample_rate; + int out_sample_rate; + void *output_buff; + void *remain_addr; + u16 output_size; + u16 remain_len; + u16 process_len; + const struct audio_resampler *resampler; + void *priv; + struct audio_stream_entry entry; + int (*data_flush)(struct audio_resample_context *ctx, void *data, int len); + void *output_priv; + int (*output_handler)(void *priv, void *data, int len); +}; + + +struct audio_resample_data; + +struct audio_resampler { + u8 type; + int (*open)(struct audio_resample_context *ctx, u8 channel); + int (*resample)(struct audio_resample_context *ctx, + struct audio_resample_data *in, + struct audio_resample_data *out); + int (*write)(struct audio_resample_context *ctx, void *data, int len); + int (*reset_sample_rate)(struct audio_resample_context *ctx, int in_sample_rate, int out_sample_rate); + int (*stop)(struct audio_resample_context *ctx); + void (*close)(struct audio_resample_context *ctx); +}; + +/* + * 变采样输入输出数据 + */ +struct audio_resample_data { + void *buffer; //变采样数据缓冲地址 + int sample_rate; //采样率 + int sample_num; //缓冲内样点个数 + int offset; //已处理的样点偏移 + u8 ch_num; //样点的通道个数 +}; + +struct audio_resample_context *audio_resample_open(u8 ch_num, + u8 hardware_first, + void *output_priv, + int (*output_handler)(void *priv, void *data, int len)); + +int audio_resample_set_sample_rate(struct audio_resample_context *ctx, int in_sample_rate, int out_sample_rate); + +int audio_resample_set_sample_sync(struct audio_resample_context *ctx, int in_correct_rate, int out_correct_rate); + +int audio_resample(struct audio_resample_context *ctx, + struct audio_resample_data *in, + struct audio_resample_data *out); + +int audio_resample_stream_write(struct audio_resample_context *ctx, void *data, int len); + +void audio_resample_close(struct audio_resample_context *ctx); + +extern struct audio_resampler audio_resampler_begin[]; +extern struct audio_resampler audio_resampler_end[]; + +#define list_for_each_resampler(p) \ + for (p = audio_resampler_begin; p < audio_resampler_end; p++) + +#define REGISTER_AUDIO_RESAMPLER(resampler) \ + const struct audio_resampler resampler SEC(.audio_resampler) = { + +#endif diff --git a/include_lib/media/media_develop/media/audio_splicing.h b/include_lib/media/media_develop/media/audio_splicing.h new file mode 100644 index 0000000..e13fb34 --- /dev/null +++ b/include_lib/media/media_develop/media/audio_splicing.h @@ -0,0 +1,51 @@ +/* + **************************************************************** + *File : audio_splicing.h + *note : l-双声道0左 + * r-双声道1右 + * fl/q0-四声道0左 + * fr/q1-四声道1右 + * rl/q2-四声道2左 + * rr/q3-四声道3右 + * N-数据不变 + * + **************************************************************** + */ + +#ifndef _AUDIO_SPLICING_H_ +#define _AUDIO_SPLICING_H_ + +#include "generic/typedef.h" + +// 单声道转双声道 +void pcm_single_to_dual(void *out, void *in, u16 len); +// 单声道转四声道 +void pcm_single_to_qual(void *out, void *in, u16 len); +// 双声道转四声道(L,R,L,R) +void pcm_dual_to_qual(void *out, void *in, u16 len); +// 双声道合并(L+R,L+R) +void pcm_dual_mix_to_dual(void *out, void *in, u16 len); +// 双声道转单声道(L+R) +void pcm_dual_to_single(void *out, void *in, u16 len); +// 四声道转单声道(q0+q1+q2+q3) +void pcm_qual_to_single(void *out, void *in, u16 len); +// 四声道转双声道(q0+q2,q1+q3) +void pcm_qual_to_dual(void *out, void *in, u16 len); +// 两个单声道合并成双声道 +void pcm_single_l_r_2_dual(void *out, void *in_l, void *in_r, u16 in_len); +// 四个单声道合并成四声道 +void pcm_fl_fr_rl_rr_2_qual(void *out, void *in_fl, void *in_fr, void *in_rl, void *in_rr, u16 in_len); +// 两个双声道合并成四声道(fl,fr,rl,rr) +void pcm_flfr_rlrr_2_qual(void *out, void *in_flfr, void *in_rlrr, u16 in_len); +// 双声道填到四声道的01(fl,fr,N,N) +void pcm_fill_flfr_2_qual(void *out, void *in_flfr, u16 in_len); +// 双声道填到四声道的23(N,N,rl,rr) +void pcm_fill_rlrr_2_qual(void *out, void *in_rlrr, u16 in_len); +// 输入数据合并到输出 +void pcm_mix_buf(s32 *obuf, s16 *ibuf, u16 len); +// 音频数据溢出处理 +void pcm_mix_buf_limit(s16 *obuf, s32 *ibuf, u16 len); +// 双声道数据转换成单声道或者其他双声道 +void pcm_dual_to_dual_or_single(u8 ch_type, u8 half_lr, s16 *odata, s16 *idata, int len); + +#endif/*_AUDIO_SPLICING_H_*/ diff --git a/include_lib/media/media_develop/media/audio_track.h b/include_lib/media/media_develop/media/audio_track.h new file mode 100644 index 0000000..88a6db2 --- /dev/null +++ b/include_lib/media/media_develop/media/audio_track.h @@ -0,0 +1,14 @@ +/***************************************************************** +>file name : audio_track.h +>author : lichao +>create time : Tue 22 Dec 2020 04:18:39 PM CST +*****************************************************************/ +#ifndef _AUDIO_TRACK_H_ +#define _AUDIO_TRACK_H_ + +void *audio_local_sample_track_open(u8 channel, int sample_rate, int period); +int audio_local_sample_track_in_period(void *c, int samples); +int audio_local_sample_track_rate(void *c); +void audio_local_sample_track_close(void *c); + +#endif diff --git a/include_lib/media/media_develop/media/automute.h b/include_lib/media/media_develop/media/automute.h new file mode 100644 index 0000000..1d6dd62 --- /dev/null +++ b/include_lib/media/media_develop/media/automute.h @@ -0,0 +1,60 @@ +#ifndef AUDIO_AUTOMUTE_H +#define AUDIO_AUTOMUTE_H + +#include "generic/typedef.h" +#include "generic/list.h" + +#define AUDIO_EVENT_AUTO_MUTE 0x10 +#define AUDIO_EVENT_AUTO_UNMUTE 0x11 + +#define AUTOMUTE_CH 4 + +enum mute_value { + AUDIO_MUTE_DEFAULT = 0, + AUDIO_UNMUTE_DEFAULT, + AUDIO_MUTE_L_CH, + AUDIO_UNMUTE_L_CH, + AUDIO_MUTE_R_CH, + AUDIO_UNMUTE_R_CH, +}; + +struct pcm_energy { + u32 points; //计算多少个点 + u32 point_count; + s32 total_value; + /*void *priv;*/ + /*void (*output)(void *, u16, u8);*/ + s16 average_value; +}; + +struct automute_filter { + u32 mute_number; + u32 unmute_number; + u32 mute_count; + u32 unmute_count; +}; + +struct audio_automute { + struct pcm_energy energy[AUTOMUTE_CH]; + void (*handler)(u8 event, u8 channel); + u8 channels; + u8 pcm_mute; + u8 mute_channel; + u8 mute; + u32 mute_energy; + u32 unmute_energy; + u32 filt_points; + u32 filt_mute_number; + u32 filt_unmute_number; + struct automute_filter filt[AUTOMUTE_CH]; + u8 on; + u8 skip; +}; + +int audio_automute_open(struct audio_automute *automute); +void audio_automute_run(struct audio_automute *automute, void *data, int len); +void audio_automute_close(struct audio_automute *automute); +int audio_automute_onoff(struct audio_automute *automute, u8 onoff, u8 need_cb); +void audio_automute_skip(struct audio_automute *automute, u8 skip); + +#endif diff --git a/include_lib/media/media_develop/media/channel_switch.h b/include_lib/media/media_develop/media/channel_switch.h new file mode 100644 index 0000000..a975e2a --- /dev/null +++ b/include_lib/media/media_develop/media/channel_switch.h @@ -0,0 +1,21 @@ + +#ifndef _CHANNEL_SWITCH_H_ +#define _CHANNEL_SWITCH_H_ + +#include "media/audio_stream.h" + +struct channel_switch { + u8 out_ch_num; + enum audio_channel out_ch_type; // 声道类型 + struct audio_stream_entry entry; // 音频流入口 + u8 data_sync; + u16 dat_len; + u16 dat_total; + u16 buf_len; + u8 buf[0]; +}; + +struct channel_switch *channel_switch_open(enum audio_channel out_ch_type, int buf_len); +void channel_switch_close(struct channel_switch **); + +#endif/*_AUDIO_SPLICING_H_*/ diff --git a/include_lib/media/media_develop/media/cpu/br23/asm/Resample_api.h b/include_lib/media/media_develop/media/cpu/br23/asm/Resample_api.h new file mode 100644 index 0000000..7738703 --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/asm/Resample_api.h @@ -0,0 +1,27 @@ +#ifndef __RESAMPLE_API_H__ +#define __RESAMPLE_API_H__ + +// #include "br18_dsp_Ecommon.h" + +typedef struct _RS_IO_CONTEXT_ { + void *priv; + int(*output)(void *priv, void *data, int len); +} RS_IO_CONTEXT; + +typedef struct _RS_PARA_STRUCT_ { + unsigned int new_insample; + unsigned int new_outsample; + int nch; +} RS_PARA_STRUCT; + +typedef struct _RS_STUCT_API_ { + unsigned int(*need_buf)(); + void (*open)(unsigned int *ptr, RS_PARA_STRUCT *rs_para); + void (*set_sr)(unsigned int *ptr, int newsrI); + int(*run)(unsigned int *ptr, short *inbuf, int len, short *obuf); //len是n个点,返回n个点 +} RS_STUCT_API; + +RS_STUCT_API *get_rs16_context(); +RS_STUCT_API *get_rsfast_context(); + +#endif diff --git a/include_lib/media/media_develop/media/cpu/br23/asm/audio_adc.h b/include_lib/media/media_develop/media/cpu/br23/asm/audio_adc.h new file mode 100644 index 0000000..6c559b9 --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/asm/audio_adc.h @@ -0,0 +1,422 @@ +#ifndef AUDIO_ADC_H +#define AUDIO_ADC_H + +#include "generic/typedef.h" +#include "generic/list.h" +#include "generic/atomic.h" + +/*无电容电路*/ +#define SUPPORT_MIC_CAPLESS 1 + +#define LADC_STATE_INIT 1 +#define LADC_STATE_OPEN 2 +#define LADC_STATE_START 3 +#define LADC_STATE_STOP 4 + +#define FPGA_BOARD 0 + +#define LADC_MIC 0 +#define LADC_LINEIN0 1 +#define LADC_LINEIN1 2 +#define LADC_LINEIN 3 + + +/* 通道选择 */ +#define AUDIO_ADC_MIC_L BIT(0) +#define AUDIO_ADC_MIC_R BIT(1) +#define AUDIO_ADC_LINE0_L BIT(2) +#define AUDIO_ADC_LINE0_R BIT(3) +#define AUDIO_ADC_LINE1_L BIT(4) +#define AUDIO_ADC_LINE1_R BIT(5) +#define AUDIO_ADC_LINE2_L BIT(6) +#define AUDIO_ADC_LINE2_R BIT(7) +#define AUDIO_ADC_MIC_CH BIT(0) + +#define AUDIO_ADC_LINE0_LR (AUDIO_ADC_LINE0_L | AUDIO_ADC_LINE0_R) +#define AUDIO_ADC_LINE1_LR (AUDIO_ADC_LINE1_L | AUDIO_ADC_LINE1_R) +#define AUDIO_ADC_LINE2_LR (AUDIO_ADC_LINE2_L | AUDIO_ADC_LINE2_R) + +#define LADC_CH_MIC_L BIT(0) +#define LADC_CH_MIC_R BIT(1) +#define LADC_CH_LINE0_L BIT(2) +#define LADC_CH_LINE0_R BIT(3) +#define LADC_CH_LINE1_L BIT(4) +#define LADC_CH_LINE1_R BIT(5) + +#define LADC_MIC_MASK (BIT(0) | BIT(1)) +#define LADC_LINE0_MASK (BIT(2) | BIT(3)) +#define LADC_LINE1_MASK (BIT(4) | BIT(5)) + +/*LINEIN通道定义*/ +#define AUDIO_LIN0L_CH BIT(0)//PA0 +#define AUDIO_LIN0R_CH BIT(1)//PA1 +#define AUDIO_LIN1L_CH BIT(2)//PB7 +#define AUDIO_LIN1R_CH BIT(3)//PB8 +#define AUDIO_LIN2L_CH BIT(4)//PB9 +#define AUDIO_LIN2R_CH BIT(5)//PB10 +#define AUDIO_LIN_DACL_CH BIT(6) +#define AUDIO_LIN_DACR_CH BIT(7) +#define AUDIO_LIN0_LR (AUDIO_LIN0L_CH | AUDIO_LIN0R_CH) +#define AUDIO_LIN1_LR (AUDIO_LIN1L_CH | AUDIO_LIN1R_CH) +#define AUDIO_LIN2_LR (AUDIO_LIN2L_CH | AUDIO_LIN2R_CH) + +struct ladc_port { + u8 channel; +}; + +struct adc_platform_data { + u8 mic_channel; + u8 mic_ldo_isel; //MIC通道电流档位选择 + u8 mic_capless; //MIC免电容方案 + u8 mic_bias_res; //MIC免电容方案需要设置,影响MIC的偏置电压 1:16K 2:7.5K 3:5.1K 4:6.8K 5:4.7K 6:3.5K 7:2.9K 8:3K 9:2.5K 10:2.1K 11:1.9K 12:2K 13:1.8K 14:1.6K 15:1.5K 16:1K 31:0.6K + u8 mic_ldo_vsel : 2;//00:2.3v 01:2.5v 10:2.7v 11:3.0v + u8 mic_bias_inside : 1;//MIC电容隔直模式使用内部mic偏置(PC7) + u8 mic_bias_keep : 1;//保持内部mic偏置输出 + u8 reserved: 4; + u8 ladc_num; + const struct ladc_port *ladc; +}; + +struct capless_low_pass { + u16 bud; //快调边界 + u16 count; + u16 pass_num; + u16 tbidx; +}; + +struct audio_adc_output_hdl { + struct list_head entry; + void *priv; + void (*handler)(void *, s16 *, int); +}; + +/*Audio adc模块的数据结构*/ +struct audio_adc_hdl { + struct list_head head;//采样数据输出链表头 + const struct adc_platform_data *pd;//adc硬件相关配置 + atomic_t ref; //adc模块引用记录 + u8 channel; //adc打开通道统计 + u8 input; //adc输入记录 + u8 state; //adc状态 + u8 mic_ldo_state : 1;//当前micldo是否打开 + //省电容mic数据结构 +#if SUPPORT_MIC_CAPLESS + struct capless_low_pass lp; + int last_dacr32; +#endif/*SUPPORT_MIC_CAPLESS*/ +}; + +struct adc_mic_ch { + u8 gain; + u8 buf_num; + u16 buf_size; + u16 sample_rate; + s16 *bufs; + struct audio_adc_hdl *hdl; + //void (*handler)(struct adc_mic_ch *, s16 *, u16); +}; + +/*Audio adc通道数据结构*/ +struct audio_adc_ch { + u8 gain; //adc通道的增益 + u8 buf_num; //adc buf数量 + u8 ch; //adc 通道索引 + u16 buf_size; //adc buf大小 + u16 sample_rate;//adc通道采样率 + s16 *bufs; //adc buf地址 + struct audio_adc_hdl *hdl;//adc模块句柄 + //void (*handler)(struct audio_adc_ch *, s16 *, u16); +}; + +/* +********************************************************************* +* Audio ADC Initialize +* Description: 初始化Audio_ADC模块的相关数据结构 +* Arguments : adc ADC模块操作句柄 +* pd ADC模块硬件相关配置参数 +* Note(s) : None. +********************************************************************* +*/ +void audio_adc_init(struct audio_adc_hdl *, const struct adc_platform_data *); + +/* +********************************************************************* +* Audio ADC Output Callback +* Description: 注册adc采样输出回调函数 +* Arguments : adc adc模块操作句柄 +* output 采样输出回调 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_adc_add_output_handler(struct audio_adc_hdl *, struct audio_adc_output_hdl *); + +/* +********************************************************************* +* Audio ADC Output Callback +* Description: 删除adc采样输出回调函数 +* Arguments : adc adc模块操作句柄 +* output 采样输出回调 +* Return : None. +* Note(s) : 采样通道关闭的时候,对应的回调也要同步删除,防止内存释 +* 放出现非法访问情况 +********************************************************************* +*/ +void audio_adc_del_output_handler(struct audio_adc_hdl *adc, + struct audio_adc_output_hdl *output); + +/* +********************************************************************* +* Audio ADC IRQ Handler +* Description: Audio ADC中断回调函数 +* Arguments : adc adc模块操作句柄 +* Return : None. +* Note(s) : (1)仅供Audio_ADC中断使用 +* (2)ADC(3通道)数据组织结构: +* adc0(0) adc1(0) +* adc2(0) adc0(1) +* adc1(1) adc2(1) +* ... adc0(n) +* adc1(n) adc2(n) +********************************************************************* +*/ +void audio_adc_irq_handler(struct audio_adc_hdl *adc); + +/* +********************************************************************* +* Audio ADC Mic Open +* Description: 打开mic采样通道 +* Arguments : mic mic采样通道句柄 +* ch mic通道索引 +* hdl adc模块操作句柄 +* Return : 0 成功 其他 失败 +* Note(s) : None. +********************************************************************* +*/ +int audio_adc_mic_open(struct adc_mic_ch *mic, int ch, struct audio_adc_hdl *adc); + +/* +********************************************************************* +* Audio ADC Mic Sample Rate +* Description: 设置mic采样率 +* Arguments : mic mic操作句柄 +* sample_rate 采样率 +* Return : 0 成功 其他 失败 +* Note(s) : None. +********************************************************************* +*/ +int audio_adc_mic_set_sample_rate(struct adc_mic_ch *mic, int sample_rate); + +/* +********************************************************************* +* Audio ADC Mic Gain +* Description: 设置mic增益 +* Arguments : mic mic操作句柄 +* gain mic增益 +* Return : 0 成功 其他 失败 +* Note(s) : MIC增益范围:0(0dB)~14(28dB),step:2dB +********************************************************************* +*/ +int audio_adc_mic_set_gain(struct adc_mic_ch *mic, int gain); + +/* +********************************************************************* +* Audio ADC Mic Buffer +* Description: 设置采样buf和采样长度 +* Arguments : mic mic操作句柄 +* bufs 采样buf地址 +* buf_size 采样buf长度,即一次采样中断数据长度 +* buf_num 采样buf的数量 +* Return : 0 成功 其他 失败 +* Note(s) : (1)需要的总buf大小 = buf_size * ch_num * buf_num +* (2)buf_num = 2表示,第一次数据放在buf0,第二次数据放在 +* buf1,第三次数据放在buf0,依此类推。如果buf_num = 0则表 +* 示,每次数据都是放在buf0 +********************************************************************* +*/ +int audio_adc_mic_set_buffs(struct adc_mic_ch *mic, s16 *bufs, u16 buf_size, u8 buf_num); + +/* +********************************************************************* +* Audio ADC Mic Start +* Description: 启动mic采样 +* Arguments : mic mic操作句柄 +* Return : 0 成功 其他 失败 +* Note(s) : None. +********************************************************************* +*/ +int audio_adc_mic_start(struct adc_mic_ch *mic); + +/* +********************************************************************* +* Audio ADC Mic Close +* Description: 关闭mic采样 +* Arguments : mic mic操作句柄 +* Return : 0 成功 其他 失败 +* Note(s) : None. +********************************************************************* +*/ +int audio_adc_mic_close(struct adc_mic_ch *mic); + +/* +********************************************************************* +* Audio MIC Mute +* Description: mic静音使能控制 +* Arguments : mute 静音使能 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_set_mic_mute(u8 mute); + +/* +********************************************************************* +* Audio ADC Linein Open +* Description: 打开linein采样通道 +* Arguments : adc adc采样通道句柄 +* ch linein通道索引 +* hdl adc采样模块操作句柄 +* Return : 0 成功 其他 失败 +* Note(s) : None. +********************************************************************* +*/ +int audio_adc_linein_open(struct audio_adc_ch *adc, int ch, struct audio_adc_hdl *hdl); + +/* +********************************************************************* +* Audio ADC Linein Sample Rate +* Description: 设置linein采样率 +* Arguments : ch linein采样通道操作句柄 +* sample_rate 采样率 +* Return : 0 成功 其他 失败 +* Note(s) : None. +********************************************************************* +*/ +int audio_adc_linein_set_sample_rate(struct audio_adc_ch *ch, int sample_rate); + +/* +********************************************************************* +* Audio ADC Linein Gain +* Description: 设置linein增益 +* Arguments : ch linein采样通道操作句柄 +* sample_rate 采样率 +* Return : 0 成功 其他 失败 +* Note(s) : (1)linein adc的增益范围:0(-8dB)~15(7dB),8(0dB),step:1dB +* (2)增益设置规则: +* A:默认linein两个通道的增益一致: +* audio_adc_linein_set_gain(ch,gain); +* B:如果要分开设置,可以把参数gain分成高低16bit来设置: +* audio_adc_linein_set_gain(ch,(gain_l | (gain_r << 16))); +********************************************************************* +*/ +int audio_adc_linein_set_gain(struct audio_adc_ch *ch, int gain); + +/* +********************************************************************* +* Audio ADC Linein Start +* Description: 启动linein采样 +* Arguments : adc adc采样通道句柄 +* ch linein通道索引 +* hdl adc采样模块操作句柄 +* Return : 0 成功 其他 失败 +* Note(s) : None. +********************************************************************* +*/ +int audio_adc_linein_start(struct audio_adc_ch *ch); + +/* +********************************************************************* +* Audio ADC Linein Close +* Description: 关闭linein采样 +* Arguments : adc adc采样通道句柄 +* Return : 0 成功 其他 失败 +* Note(s) : None. +********************************************************************* +*/ +int audio_adc_linein_close(struct audio_adc_ch *ch); + +/* +********************************************************************* +* Audio ADC Buffer +* Description: 设置采样buf和采样长度 +* Arguments : ch adc通道操作句柄 +* bufs 采样buf地址 +* buf_size 采样buf长度,即一次采样中断数据长度 +* buf_num 采样buf的数量 +* Return : 0 成功 其他 失败 +* Note(s) : (1)需要的总buf大小 = buf_size * ch_num * buf_num +* (2)buf_num = 2表示,第一次数据放在buf0,第二次数据放在 +* buf1,第三次数据放在buf0,依此类推。如果buf_num = 0则表 +* 示,每次数据都是放在buf0 +********************************************************************* +*/ +int audio_adc_set_buffs(struct audio_adc_ch *ch, s16 *bufs, u16 buf_size, u8 buf_num); + +/* +********************************************************************* +* Audio ADC Start +* Description: 启动audio adc采样 +* Arguments : linein_ch linein采样通道句柄 +* mic_ch mic采样通道句柄 +* Return : 0 成功 其他 失败 +* Note(s) : 该接口支持同时操作mic和linein采样通道 +********************************************************************* +*/ +int audio_adc_start(struct audio_adc_ch *linein_ch, struct adc_mic_ch *mic_ch); + +/* +********************************************************************* +* Audio ADC Close +* Description: 关闭linein采样 +* Arguments : linein_ch linein采样通道句柄 +* mic_ch mic采样通道句柄 +* Return : 0 成功 其他 失败 +* Note(s) : 该接口支持同时操作mic和linein采样通道 +********************************************************************* +*/ +int audio_adc_close(struct audio_adc_ch *linein_ch, struct adc_mic_ch *mic_ch); + +/* +********************************************************************* +* Audio ADC Mic Pre_Gain +* Description: 设置mic第一级/前级增益 +* Arguments : en 前级增益使能(0:6dB 1:0dB) +* Return : None. +* Note(s) : 前级增益只有0dB和6dB两个档位,使能即为0dB,否则为6dB +********************************************************************* +*/ +void audio_mic_0dB_en(bool en); + +/* +********************************************************************* +* Audio ADC MIC Control +* Description: mic通道使能控制 +* Arguments : en 使能控制位 +* Return : None. +* Note(s) : 扩展接口,GPIO使用冲突 +********************************************************************* +*/ +void audio_adc_mic_ctl(u8 en); + + +/* +********************************************************************* +* Audio ADC MIC LDO EN +* Description: mic ldo使能 +* Arguments : en 使能控制位 pd adc结构体 +* Return : None. +* Note(s) : 开关mic的ldo +********************************************************************* +*/ + +int audio_mic_ldo_en(u8 en, struct adc_platform_data *pd); + + + + + + + + + +#endif/*AUDIO_ADC_H*/ diff --git a/include_lib/media/media_develop/media/cpu/br23/asm/audio_iis.h b/include_lib/media/media_develop/media/cpu/br23/asm/audio_iis.h new file mode 100644 index 0000000..f698418 --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/asm/audio_iis.h @@ -0,0 +1,101 @@ +/***************************************************************** +>file name : audio_iis.h +>author : lichao +>create time : Fri 29 May 2020 01:52:36 PM CST +*****************************************************************/ +#ifndef _ASM_AUDIO_IIS_H_ +#define _ASM_AUDIO_IIS_H_ +#include "generic/typedef.h" + +#define IIS_MAX_POSITION_NUM 3 + +struct audio_iis_irq_position { + u32 buf_counter; + u32 pcm_position; + u32 clkn; + u32 clkoffset; + u16 clkn_phase; + s16 bitoff; + u32 buf_num; +}; + +struct audio_iis_buffer { + void *addr; + u32 len; +}; + +struct audio_iis_sync_handle { + u8 start; + u8 channel; + u8 fast_align; + u8 index; + u8 align_start; + int points; + int start_points; + int fast_points; + u32 pcm_position; + u32 input_num; + u32 buf_num; + u32 buf_counter; + u16 in_rate; + u16 out_rate; + struct audio_iis_irq_position position[IIS_MAX_POSITION_NUM]; + struct audio_src_base_handle *src_base; + void *priv; + int (*handler)(void *priv, u8 device, u8 state); +}; + +struct audio_iis_handle { + u8 channel; + struct audio_iis_sync_handle sync; + void *priv; + int (*buf_handler)(void *priv, u8 state, struct audio_iis_buffer *buf); +}; + +#define AUDIO_IIS_GET_OUTPUT_BUFFER 0 +#define AUDIO_IIS_PUT_OUTPUT_BUFFER 1 + +void audio_iis_set_channel(void *iis, u8 channel); + +int audio_iis_sync_open(void *iis); + +int audio_iis_sync_connect_open(void *_iis, + void *priv, + int (*handler)(void *priv, u8 state, struct audio_iis_buffer *buf)); + +void audio_iis_set_sync_handler(void *iis, void *priv, int (*handler)(void *priv, u8 device, u8 state)); + +int audio_iis_sync_set_channel(void *iis, u8 channel); + +int audio_iis_sync_start(void *iis); + +int audio_iis_sync_stop(void *iis); + +void audio_iis_sync_input_num_correct(void *iis, int num); + +int audio_iis_sync_fast_align(void *iis, int in_rate, int out_rate, int fast_output_points, s16 phase_diff); + +int audio_iis_sync_flush_data(void *iis); + +int audio_iis_sync_write(void *_iis, void *data, int len); + +int audio_iis_sync_set_rate(void *iis, u16 in_rate, u16 out_rate); + +u32 audio_iis_sync_pcm_position(void *iis, u32 bt_time, u32 bt_time_phase); + +void audio_iis_sync_close(void *iis); + +void audio_iis_bt_location_lock_read(void *iis, u32 *dabuf, u32 *bt_time, u16 *bt_time_phase, int *clkoffset, int *bitoff); + +u32 audio_iis_buf_counter_number(void *iis, u32 bt_time, u32 bt_time_phase); + +int audio_iis_sync_set_start_points(void *_iis, int start_points); + +int audio_iis_sync_reset(void *_iis); + +u8 audio_iis_sync_align_start(void *_iis); + +int audio_iis_sync_len_update(struct audio_iis_handle *iis, int len); + +bool audio_iis_is_working(void *_iis); +#endif diff --git a/include_lib/media/media_develop/media/cpu/br23/asm/audio_linein.h b/include_lib/media/media_develop/media/cpu/br23/asm/audio_linein.h new file mode 100644 index 0000000..7c137de --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/asm/audio_linein.h @@ -0,0 +1,42 @@ +#ifndef _AUDIO_LINEIN_H_ +#define _AUDIO_LINEIN_H_ + +#include "generic/typedef.h" +#include "asm/audio_adc.h" + +/* + *ch:使能对应的输入通道(控制输入) + *amux_en:是否将linein输入直通到dac(控制输出) + */ +int audio_linein0_open(u8 ch, u8 amux_en); +int audio_linein0_close(u8 ch, u8 amux_en); +int audio_linein1_open(u8 ch, u8 amux_en); +int audio_linein1_close(u8 ch, u8 amux_en); +int audio_linein2_open(u8 ch, u8 amux_en); +int audio_linein2_close(u8 ch, u8 amux_en); +int audio_linein_via_dac_open(u8 ch, u8 amux_en); +int audio_linein_via_dac_close(u8 ch, u8 amux_en); + +/* + *linein mute控制 + */ +void audio_linein_mute(u8 mute); + +/* + *linein输入级增益控制,只有0或者1两级 + *0:正常增益 + *1:增益X2 + */ +void audio_linein_gain(u8 gain); + +void audio_linein_bias(u8 ch, u8 en); +void audio_linein_amux_bias(u8 amux_bias); + +/* + *linein单声道模拟输入的时候,如果dac是两个声道的,想要 + *两个声道都有声音出来,需要将amux通道合并一下,即: + *call:audio_linein_ch_combine(1,1); + */ +void audio_linein_ch_combine(u8 LR_2_L, u8 LR_2_R); + +#endif diff --git a/include_lib/media/media_develop/media/cpu/br23/asm/audio_spdif.h b/include_lib/media/media_develop/media/cpu/br23/asm/audio_spdif.h new file mode 100644 index 0000000..6c09735 --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/asm/audio_spdif.h @@ -0,0 +1,109 @@ +#ifndef AUDIO_SPDIF_H +#define AUDIO_SPDIF_H + +#include "generic/typedef.h" +#include "generic/list.h" + +#define SPDIF_STATE_INIT 1 +#define SPDIF_STATE_OPEN 2 +#define SPDIF_STATE_START 3 +#define SPDIF_STATE_STOP 4 + + + +#define SPDIF_IN_PORT_A BIT(0) //PA9 +#define SPDIF_IN_PORT_B BIT(1) //PA10 +#define SPDIF_IN_PORT_C BIT(2) //PB0 +#define SPDIF_IN_PORT_D BIT(3) //PB1 +#define SPDIF_IN_IOMAP_A ( BIT(4) | BIT(0)) //input_ch 11 +#define SPDIF_IN_IOMAP_B ( BIT(4) | BIT(1)) //input_ch 10 +#define SPDIF_IN_IOMAP_C ( BIT(4) | BIT(2)) //input_ch 8 +#define SPDIF_IN_IOMAP_D ( BIT(4) | BIT(3)) //input_ch 9 + +#define SPDIF_OUT_PORT_A BIT(0) //PB11 +#define SPDIF_OUT_PORT_B BIT(1) // ?? +#define SPDIF_OUT_PORT_C BIT(2) //? +#define SPDIF_OUT_PORT_D BIT(3) //? + + +#define SPDIF_CHANNEL_NUMBER 2 +#define SPDIF_DATA_DAM_LEN 96 +#define SPDIF_INFO_LEN 6 + +#define INFO_VALIDITY_BIT BIT(0) +#define INFO_USER_DATA_BIT BIT(1) +#define INFO_CHANNEL_STA_BIT BIT(2) +#define INFO_PARITY_BIT BIT(3) + + +#define SS_START (JL_SS->CON |= BIT(1)) +#define SS_EN_ISR (JL_SS->CON |= BIT(2)) +#define D_PND_CLR (JL_SS->CON |= BIT(3)) +#define D_PND (JL_SS->CON & BIT(4)) +#define I_PND_CLR (JL_SS->CON |= BIT(5)) +#define I_PND (JL_SS->CON & BIT(6)) +#define ERR_CLR (JL_SS->CON |= BIT(7)) +#define CSB_PND_CLR (JL_SS->DMA_CON |= BIT(13)) +#define CSB_PND (JL_SS->DMA_CON & BIT(14)) + + +#define IS_PND (JL_SS->IO_CON & BIT(17)) +#define IS_PND_CLR (JL_SS->IO_CON | BIT(16)) +#define ET_PND (JL_SS->IO_CON & BIT(19)) +#define ET_PND_CLR (JL_SS->IO_CON | BIT(18)) + + +#define USING_BUF_INDEX (JL_SS->CON & BIT(12)) +#define USING_INF_BUF_INDEX (JL_SS->CON & BIT(13)) +#define ERROR_VALUE ((JL_SS->CON &(BIT(8)|BIT(9)|BIT(10)|BIT(11)))>>8) + +#define SYNCWORD1 0xF872 +#define SYNCWORD2 0x4E1F +#define BURST_HEADER_SZIE 0x8 + +enum IEC61937DataType { + IEC61937_AC3 = 0x01, + IEC61937_MPEG1_LAYER1 = 0x04, + IEC61937_MPEG1_LAYER23 = 0x05, + IEC61937_MPEG2_EXT = 0x06, + IEC61937_MPEG2_AAC = 0x07, + IEC61937_MPEG2_LAYER1_LSF = 0x08, + IEC61937_MPEG2_LAYER2_LSF = 0x09, + IEC61937_MPEG2_LAYER3_LSF = 0x0A, + IEC61937_DTS1 = 0x0B, + IEC61937_DTS2 = 0x0C, + IEC61937_DTS3 = 0x0D, + IEC61937_ATRAC = 0x0E, + IEC61937_ATRAC3 = 0x0F, + IEC61937_ATRACX = 0x10, + IEC61937_DTSHD = 0x11, + IEC61937_WMAPRO = 0x12, + IEC61937_MPEG2_AAC_LSF_2048 = 0x13, + IEC61937_MPEG2_AAC_LSF_4096 = 0x14, + IEC61937_EAC3 = 0x15, +}; + +struct audio_spdif_hdl { + u8 status; + OS_SEM sem; + u8 channel; + u32 sample_rate; + volatile u8 validity_bit_flag; + volatile u8 error_flag; + // s32(*p_info_buf)[SPDIF_INFO_LEN]; + void *p_spdif_info_buf[2]; + void *p_spdif_data_buf[2]; + // u16 output_buf_len; + u8 input_port; + u8 output_port; + u8 find_sync_word; + u16 decoder_type; + int length_code; +}; + +void audio_spdif_slave_init(struct audio_spdif_hdl *spdif_hdl); +void audio_spdif_slave_open(struct audio_spdif_hdl *spdif_hdl); +void audio_spdif_slave_start(struct audio_spdif_hdl *spdif_hdl); +void audio_spdif_slave_close(struct audio_spdif_hdl *spdif_hdl); +int audio_spdif_slave_switch_port(struct audio_spdif_hdl *spdif_hdl, u8 port); +#endif diff --git a/include_lib/media/media_develop/media/cpu/br23/asm/audio_src.h b/include_lib/media/media_develop/media/cpu/br23/asm/audio_src.h new file mode 100644 index 0000000..5541bec --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/asm/audio_src.h @@ -0,0 +1,165 @@ +/***************************************************************** +>file name : audio_src.h +>author : lichao +>create time : Fri 14 Dec 2018 03:05:49 PM CST +*****************************************************************/ +#ifndef _AUDIO_SRC_H_ +#define _AUDIO_SRC_H_ +#include "media/audio_stream.h" +#include "audio_resample.h" + + +#define SRC_DATA_MIX 0//各通道数据交叉存放 +#define SRC_DATA_SEP 1//各通道数据连续存放 + +#define SRC_CHI 2 +#define SRC_FILT_POINTS 24 + +#define SRC_MODE_DEFAULT 0 +#define SRC_MODE_FULL_INPUT 1 +#define SRC_MODE_FULL_OUTPUT 2 + +#define SRC_TYPE_RESAMPLE SRC_MODE_DEFAULT + +enum audio_src_event { + SRC_EVENT_INPUT_DONE = 0x0, + SRC_EVENT_OUTPUT_DONE, + SRC_EVENT_ALL_DONE, + SRC_EVENT_GET_OUTPUT_BUF, + SRC_EVENT_RATE_UPDATE, + SRC_EVENT_RISE_IRQ, + SRC_EVENT_RISE_IRQ_NEEDRUN, +}; + +enum audio_src_error_code { + SRC_BASE_NO_ERROR = 0x0, + SRC_OUTPUT_NO_BUFF = 0x4, + SRC_OUTPUT_NOT_COMPLETED, +}; + +#define HW_RESAMPLE_RATE_MATCH_TO_16BIT(in, out) \ + while (in >= 65535L || out >= 65535L) { \ + in >>= 1;out >>= 1; \ + } + +struct audio_src_rate { + u16 irate; + u16 orate; +}; + +struct audio_src_buffer { + void *addr; + int len; +}; +/* + * SRC BASE模块接口 + */ + +// *INDENT-OFF* +struct audio_src_base_handle { + u8 channels; + u8 state; + volatile u8 active; + u8 mode; + u8 wait_irq; + u8 input_malloc; + u8 rate_update; + //u8 filt_index; + //u32 tuned_points; + u8 filt_cnt; + struct audio_src_rate rate; + struct audio_src_buffer input; + struct audio_src_buffer output; + struct list_head entry; + void *event_priv; + int (*event_handler)(void *priv, enum audio_src_event event, void *); + JL_SRC_TypeDef regs; +}; +// *INDENT-ON* +int audio_src_base_filt_init(void *filt, int len); + +int audio_src_base_open(struct audio_src_base_handle *src, u8 channel, u8 type); + +int audio_src_base_set_rate(struct audio_src_base_handle *src, int in_rate, int out_rate); + +int audio_src_base_get_rate(struct audio_src_base_handle *src, u16 *in_rate, u16 *out_rate); + +int audio_src_base_set_channel(struct audio_src_base_handle *src, u8 channel); + +void audio_src_base_set_event_handler(struct audio_src_base_handle *src, void *priv, + int (*handler)(void *priv, enum audio_src_event event, void *)); + +int audio_src_base_set_input_buff(struct audio_src_base_handle *src, void *buf, int len); + +int audio_src_base_write(struct audio_src_base_handle *src, void *data, int len); + +int audio_src_base_try_write(struct audio_src_base_handle *src, void *data, int len); + +int audio_src_base_data_flush_out(struct audio_src_base_handle *src); + +int audio_src_base_sub_phase(struct audio_src_base_handle *src, int sub_phase); + +int audio_src_base_get_phase(struct audio_src_base_handle *src); + +int audio_src_base_stop(struct audio_src_base_handle *src); + +int audio_src_base_idata_len(struct audio_src_base_handle *s); + +int audio_src_base_data_len(struct audio_src_base_handle *s); + +int audio_src_base_resample(struct audio_src_base_handle *s, + struct audio_resample_data *in, + struct audio_resample_data *out); + +void audio_src_base_close(struct audio_src_base_handle *src); + +//int audio_src_is_running(struct audio_src_base_handle *src); +int audio_src_ch_is_running(struct audio_src_base_handle *src); + +// *INDENT-OFF* +struct audio_src_handle { + struct audio_src_base_handle base; + struct audio_src_buffer output; + void *output_priv; + int (*output_handler)(void *priv, void *data, int len); + void *rise_irq_priv; + void (*rise_irq_handler)(void *priv); + u8 *remain_addr; + int remain_len; + int in_sample_rate; + int out_sample_rate; + u8 channel; + u8 output_malloc; + u8 check_hw_running; + struct audio_stream_entry entry; +}; +// *INDENT-ON* + +int audio_hw_src_open(struct audio_src_handle *src, u8 channel, u8 type); + +int audio_hw_src_set_rate(struct audio_src_handle *src, int in_sample_rate, int out_sample_rate); + +int audio_hw_src_correct_rate(struct audio_src_handle *src, int in_step, int out_step); + +int audio_src_resample_write(struct audio_src_handle *src, void *data, int len); + +void audio_src_set_output_handler(struct audio_src_handle *src, void *priv, + int (*handler)(void *, void *, int)); + +void audio_src_set_rise_irq_handler(struct audio_src_handle *src, void *priv, + void (*handler)(void *)); + +int audio_hw_src_set_input_buffer(struct audio_src_handle *src, void *addr, int len); + +int audio_hw_src_set_output_buffer(struct audio_src_handle *src, void *addr, int len); + +int audio_hw_src_stop(struct audio_src_handle *src); + +void audio_hw_src_close(struct audio_src_handle *src); + +// 检测到硬件正在运行时不等待其完成,直接返回 +int audio_hw_src_set_check_running(struct audio_src_handle *src, u8 check_hw_running); + +int audio_hw_src_active(struct audio_src_handle *src); + +#endif diff --git a/include_lib/media/media_develop/media/cpu/br23/asm/audio_sync.h b/include_lib/media/media_develop/media/cpu/br23/asm/audio_sync.h new file mode 100644 index 0000000..d281532 --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/asm/audio_sync.h @@ -0,0 +1,442 @@ +/***************************************************************** +>file name : audio_sync.h +>author : lichao +>create time : Fri 29 May 2020 11:11:23 AM CST +*****************************************************************/ +#ifndef _ASM_AUDIO_SYNC_H_ +#define _ASM_AUDIO_SYNC_H_ +#include "media/audio_stream.h" + +#define AUDIO_SYNC_OUTPUT_IDLE 0 +#define AUDIO_SYNC_OUTPUT_PROBE 1 //输出前处理 +#define AUDIO_SYNC_OUTPUT_START 2 //输出开始 +#define AUDIO_SYNC_OUTPUT_MISS_DATA 3 //输出采样丢失样点 +#define AUDIO_SYNC_OUTPUT_ALIGN_COMPLETE 4 //输出对齐完成 + +#define AUDIO_SYNC_DAC 0 +#define AUDIO_SYNC_IIS 1 + +#define PCM_PHASE_BIT 8 + +#define AUDIO_STANDARD_STREAM 1 +#define AUDIO_OUTPUT_STREAM 2 + + +#define SAMP_STREAM_FRAME_OUTPUT 0 +#define SAMP_STREAM_CBUF_OUTPUT 1 + +#define SAMPLE_SYNC_DEVICE_IDLE 0 +#define SAMPLE_SYNC_DEVICE_START 1 + +#define BT_AHB_BASE_ADR 0x1c0000L + +#define SAMPLECLK (*(volatile unsigned long *)(BT_AHB_BASE_ADR + 0x7 *4)) +#define SLOTCLK (*(volatile unsigned long *)(BT_AHB_BASE_ADR + 0x8 *4)) +#define FINETIMECNT (*(volatile unsigned long *)(BT_AHB_BASE_ADR + 0x9 *4)) + +#define BT_SLOT_CLKN() ({u32 slot_clk;SAMPLECLK = 1;while(SAMPLECLK);slot_clk = SLOTCLK;slot_clk;}) +#define BT_FINETIME_CNT() (FINETIMECNT) + +struct audio_bt_position { + u32 sample_counter; + u32 pcm_position; + u32 bt_time; + u32 clkoffset; + u16 bt_time_phase; + s16 bitoff; + u32 buf_num; +}; + +struct audio_output_position { + u32 out_samples; //输出样点个数 + u32 bt_time; //蓝牙时间 + u16 bt_time_phase; //蓝牙时间相位 +}; + +struct audio_input_position { + u32 buf_num; //输出buf当前缓冲样点个数 + u32 bt_time; //蓝牙时间 + u32 clkoffset; //与主机的偏差 + int bitoff; //与主机偏差值的相位 + u16 bt_time_phase; //蓝牙时间的相位 + u32 pcm_position; //样点输入位置 +}; + +struct resample_output_cbuf { + s16 *(*write_alloc)(void *buffer, int *len); + int (*write_update)(void *buffer, int len); +}; + +struct resample_output_frame { + u8 free; + void *addr; + int len; + void *remain_addr; + int remain_len; + int (*output)(void *buffer, void *data, int len); +}; + +struct sample_sync_device_ops { + int (*data_len)(void *priv); /*设备音频缓冲数据长度*/ + int (*state_query)(void *priv); /*设备输出状态查询*/ +}; + +struct audio_sample_output { + u8 mode; /*输出模式*/ + void *priv; + /* + union { + struct resample_output_cbuf cbuf; + struct resample_output_frame frame; + } u; + */ + u8 free; /*是否关闭时释放*/ + void *addr; /*输出缓冲地址*/ + int len; /*输出缓冲长度*/ + void *remain_addr; /*输出剩余缓冲地址*/ + int remain_len; /*输出剩余缓冲长度*/ + struct sample_sync_device_ops device; /*输出设备管理*/ +}; + +/************************************************************************* + * 音频变采样同步结构 + * + * HISTORY : + * 2020/6/18 by LC. + *=======================================================================*/ +struct audio_sample_sync { + u8 start; /*模块start标志*/ + u8 bt_time_enable; /*蓝牙时间设置起始使能(待删除)*/ + u8 fixed_sample_rate; /*固定输出采样率*/ + u8 channels; /*变采样音频声道数*/ + u8 quick_align; /*快速调整对齐*/ + u8 position_num; /*位置信息个数*/ + u8 block_start; /*阻塞起始(待删除*/ + s8 index; /*位置保存id*/ + int quick_output_count; /*快速调整变采样输出样点数*/ + int sample_rate; /*采样率*/ + int input_sample_rate; /*输入采样率*/ + u16 in_rate; /*保存的变采样in采样率*/ + u16 out_rate; /*保存的变采样out采样率*/ + u32 pcm_position; /*已变采样的输入位置*/ + u32 input_num; /*样点输入(包含未变采样)个数*/ + u32 sample_counter; /*变采样输出计数器*/ + u32 output_counter; /*输出设备样点计数器*/ + u32 bt_clkn; /*蓝牙时钟*/ + s16 bt_clkn_phase; /*蓝牙时钟相位*/ + struct audio_sample_output output; /*变采样输出管理*/ + struct audio_bt_position *position; /*蓝牙音频位置信息*/ + void *event_priv; /*事件处理私有数据*/ + int (*event_handler)(void *priv, void *output, u8 event); /*事件处理函数*/ + struct audio_stream_entry entry; /*audio stream节点*/ + struct audio_src_base_handle *src; /*SRC模块指针*/ + void *irq_priv; /*中断响应私有数据*/ + void (*irq_callback)(void *priv); /*中断响应回调*/ +}; + +/************************************************************************* + * 音频变采样同步打开 + * INPUT : stream_mode - 数据流模式(暂时无意义) + * OUTPUT : 非NULL - 打开成功,NULL - 打开失败. + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +struct audio_sample_sync *audio_sample_sync_open(u8 stream_mode); + +/************************************************************************* + * 音频变采样同步初始化变采样信息 + * INPUT : s - 同步变采样结构指针 + * input_sample_rate - 输入采样率 + * sample_rate - 输出采样率(标准) + * data_channels - 数据流声道数 + * position_num - 位置信息个数 + * OUTPUT : 0 - 初始化成功,非0 - 初始化失败. + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_init_resample(struct audio_sample_sync *s, + int input_sample_rate, + int sample_rate, + u8 data_channels, + u8 position_num); + +/************************************************************************* + * 音频变采样同步模块关闭 + * INPUT : s - 同步变采样结构指针 + * OUTPUT : 无. + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +void audio_sample_sync_close(struct audio_sample_sync *s); + +/************************************************************************* + * 音频变采样同步模fifo输出设置 + * INPUT : s - 同步变采样结构指针 + * priv - fifo私有数据 + * fifo - fifo输出结构 + * OUTPUT : 无. + * WARNINGS : 待开发和验证. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_set_fifo_output(struct audio_sample_sync *s, + void *priv, + struct resample_output_cbuf *fifo); + +/************************************************************************* + * 音频变采样同步关联输出设备 + * INPUT : s - 同步变采样结构指针 + * priv - 设备私有数据 + * device - 关联的设备操作函数 + * OUTPUT : 0 -成功,非0 - 失败. + * WARNINGS : 设置变采样同步的必要函数之一. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_set_device(struct audio_sample_sync *s, + void *priv, + struct sample_sync_device_ops *device); + +/************************************************************************* + * 音频变采样同步关联输出设备 + * INPUT : s - 同步变采样结构指针 + * priv - 设备私有数据 + * device - 关联的设备操作函数 + * OUTPUT : 0 -成功,非0 - 失败. + * WARNINGS : 设置变采样同步的必要函数之一. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +void audio_sample_sync_set_event_handler(struct audio_sample_sync *s, + void *priv, + int (*handler)(void *priv, void *ch, u8 event)); + +/************************************************************************* + * 音频变采样同步中断响应处理设置 + * INPUT : s - 同步变采样结构指针 + * priv - 中断响应私有数据 + * handler - 中断响应操作函数 + * OUTPUT : 无. + * WARNINGS : Audio stream结构下使用, 用于非节点的数据流唤醒类的注册. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +void audio_sample_sync_set_irq_handler(struct audio_sample_sync *s, void *priv, void (*handler)(void *)); +#if 0 +/*AUDIO 样点同步设置普通buffer的输出*/ +int audio_sample_sync_set_output_handler(struct audio_sample_sync *s, + void *priv, + int (*data_len)(void *priv); + int (*output)(void *priv, void *data, int len)); +#endif +/************************************************************************* + * 音频变采样同步刷新数据输出 + * INPUT : s - 同步变采样结构指针 + * OUTPUT : 0 - 刷出成功,非0 - 未成功刷出(不重要). + * WARNINGS : 不推荐在audio stream节点下使用,若有需求请告知开发人员. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_flush_data(struct audio_sample_sync *s); + +//int audio_sample_sync_start(struct audio_sample_sync *s); + +/************************************************************************* + * 音频变采样同步停止 + * INPUT : s - 同步变采样结构指针 + * OUTPUT : 无. + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_stop(struct audio_sample_sync *s); + +/*AUDIO 样点同步写函数,用于接入到数据流程中*/ +//int audio_sample_sync_write(struct audio_sample_sync *s, void *buf, int len); + +/************************************************************************* + * 音频变采样同步设置蓝牙起始时间 + * INPUT : s - 同步变采样结构指针 + * bt_clkn - 蓝牙时钟 + * phase - 时钟相位 + * OUTPUT : 无. + * WARNINGS : 此函数通过同步控制模块进行设置,最终由输出设备来查询. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_set_bt_time(struct audio_sample_sync *s, u32 bt_clkn, int phase); + +/************************************************************************* + * 音频变采样同步根据蓝牙时间确定起始 + * INPUT : s - 同步变采样结构指针 + * priv - 回调私有数据 + * callback - 回调函数 + * OUTPUT : 无. + * WARNINGS : 此函数通过输出设备调用,非外部可用接口. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_start_by_sync_time(struct audio_sample_sync *s, void *priv, void (*callback)(void *)); + +/************************************************************************* + * 音频变采样同步根据蓝牙时间确定起始 + * INPUT : s - 同步变采样结构指针 + * OUTPUT : 距离蓝牙起始时间的距离(us). + * WARNINGS : 此函数通过输出设备调用,非外部可用接口. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_us_time_distance(struct audio_sample_sync *s); + +/************************************************************************* + * 音频变采样同步蓝牙起始时间使能关闭 + * INPUT : s - 同步变采样结构指针 + * OUTPUT : 无. + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_bt_time_disable(struct audio_sample_sync *s); + +/************************************************************************* + * 音频变采样同步更新输出样点 + * INPUT : s - 同步变采样结构指针 + * points - 样点个数 + * OUTPUT : 无. + * WARNINGS : 由输出设备调用该接口更新缓冲样点个数. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_update_count(struct audio_sample_sync *s, int points); + +/*AUDIO 样点同步查询输入位置(某个时间和对应具体某个样点位置)*/ +/************************************************************************* + * 音频变采样同步获取当前变采样输入位置(已变采样) + * INPUT : s - 同步变采样结构指针 + * pos - 输入位置结构指针 + * OUTPUT : 0 - 获取成功, 非0 - 获取失败(目前不存在失败情况). + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_get_in_position(struct audio_sample_sync *s, struct audio_input_position *pos); + +/************************************************************************* + * 音频变采样同步查询设备输出位置 + * INPUT : s - 同步变采样结构指针 + * pos - 输出位置结构指针 + * OUTPUT : 0 - 获取成功, 非0 - 获取失败(目前不存在失败情况). + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_get_out_position(struct audio_sample_sync *s, struct audio_output_position *pos); + +/************************************************************************* + * 音频变采样同步缓冲剩余长度 + * INPUT : s - 同步变采样结构指针 + * OUTPUT : 长度. + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_out_remain_len(struct audio_sample_sync *s); + +/************************************************************************* + * 音频变采样同步输出设备采样起始 + * INPUT : s - 同步变采样结构指针 + * samples - 起始缓冲样点个数 + * sample_rate - 输出采样率 + * OUTPUT : 无. + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_output_begin(struct audio_sample_sync *s, int samples, int sample_rate); + +/************************************************************************* + * 音频变采样同步输出采样率查询 + * INPUT : s - 同步变采样结构指针 + * OUTPUT : 采样率. + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_output_rate(struct audio_sample_sync *s); + +/************************************************************************* + * 音频变采样同步输出设备丢失样点 + * INPUT : s - 同步变采样结构指针 + * OUTPUT : 无. + * WARNINGS : 调用处用来通知变采样同步漏样点. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_output_miss_data(struct audio_sample_sync *s); + +/************************************************************************* + * 音频变采样同步位置修正 + * INPUT : s - 同步变采样结构指针 + * num - 修正样点个数 + * OUTPUT : 无. + * WARNINGS : 关系到具体的位置不可随意使用. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +void audio_sample_sync_position_correct(struct audio_sample_sync *s, int num); + +/************************************************************************* + * 音频变采样同步位置调整对齐 + * INPUT : s - 同步变采样结构指针 + * in_rate - 调整阶段输入采样率 + * out_rate - 调整阶段输出采样率 + * points - 调整阶段输出样点个数 + * phase_diff - 相位差(暂时不使用) + * OUTPUT : 无. + * WARNINGS : 关系到具体的位置不可随意使用. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_align_control(struct audio_sample_sync *s, int in_rate, int out_rate, int points, s16 phase_diff); + +/************************************************************************* + * 音频变采样同步速度调整 + * INPUT : s - 同步变采样结构指针 + * in_rate - 调整输入采样率 + * out_rate - 调整输出采样率 + * OUTPUT : 无. + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_rate_control(struct audio_sample_sync *s, int in_rate, int out_rate); + +/************************************************************************* + * 中断模式设备更新中断消耗样点位置 + * INPUT : s - 同步变采样结构指针 + * irq_sample_num - 中断样点个数 + * OUTPUT : 无. + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_irq_update_sample_sync_position(struct audio_sample_sync *s, int irq_sample_num); + + +/************************************************************************* + * 音频变采样同步蓝牙目标时间距离获取(ms) + * INPUT : s - 同步变采样结构指针 + * OUTPUT : 距离时间(ms). + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_time_distance(struct audio_sample_sync *s); + +/************************************************************************* + * 音频变采样同步关联设备输出状态查询 + * INPUT : s - 同步变采样结构指针 + * OUTPUT : SAMPLE_SYNC_DEVICE_IDLE - 输出空闲 + * SAMPLE_SYNC_DEVICE_START - 输出开启 + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_output_query(struct audio_sample_sync *s); + +/************************************************************************* + * 音频变采样同步是否在工作 + * INPUT : s - 同步变采样结构指针 + * OUTPUT : 1 - 是, 0 - 否 + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +int audio_sample_sync_is_working(struct audio_sample_sync *s); + +/************************************************************************* + * 音频变采样同步已输入的整点个数 + * INPUT : s - 同步变采样结构指针 + * OUTPUT : 样点个数. + * WARNINGS : 无. + * HISTORY : 2020/6/18 by LC. + *=======================================================================*/ +u32 audio_sample_sync_input_pcm_num(struct audio_sample_sync *s); + +#endif diff --git a/include_lib/media/media_develop/media/cpu/br23/asm/cpu_includes.h b/include_lib/media/media_develop/media/cpu/br23/asm/cpu_includes.h new file mode 100644 index 0000000..ac7184f --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/asm/cpu_includes.h @@ -0,0 +1,19 @@ +/***************************************************************** +>file name : include_lib/media/cpu/br30/includes.h +>author : lichao +>create time : Fri 29 Nov 2019 02:24:47 PM CST +*****************************************************************/ +#ifndef _ASM_MEDIA_INCLUDES_H_ +#define _ASM_MEDIA_INCLUDES_H_ + +#include "asm/audio_adc.h" +#include "asm/audio_linein.h" +#include "asm/audio_src.h" +// #include "asm/audio_src_sync.h" +#include "dac.h" +#include "asm/hw_eq.h" +#include "audio_sync.h" +#include "audio_iis.h" + + +#endif diff --git a/include_lib/media/media_develop/media/cpu/br23/asm/dac.h b/include_lib/media/media_develop/media/cpu/br23/asm/dac.h new file mode 100644 index 0000000..36b0cbd --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/asm/dac.h @@ -0,0 +1,473 @@ +#ifndef __CPU_DAC_H__ +#define __CPU_DAC_H__ + + +#include "generic/typedef.h" +#include "generic/atomic.h" +#include "os/os_api.h" +#include "media/audio_stream.h" +#include "media/audio_cfifo.h" + + +#define DAC_44_1KHZ 0 +#define DAC_48KHZ 1 +#define DAC_32KHZ 2 +#define DAC_22_05KHZ 3 +#define DAC_24KHZ 4 +#define DAC_16KHZ 5 +#define DAC_11_025KHZ 6 +#define DAC_12KHZ 7 +#define DAC_8KHZ 8 + +#define DAC_ISEL_FULL_PWR 4 +#define DAC_ISEL_HALF_PWR 2 +#define DAC_ISEL_THREE_PWR 1 + +#define DACVDD_LDO_2_40V 0 +#define DACVDD_LDO_2_50V 1 +#define DACVDD_LDO_2_60V 2 +#define DACVDD_LDO_2_70V 3 +#define DACVDD_LDO_2_80V 4 +#define DACVDD_LDO_2_90V 5 +#define DACVDD_LDO_3_00V 6 +#define DACVDD_LDO_3_10V 7 + +#define DAC_OUTPUT_MONO_L 0 //左声道 +#define DAC_OUTPUT_MONO_R 1 //右声道 +#define DAC_OUTPUT_LR 2 //立体声 +#define DAC_OUTPUT_MONO_LR_DIFF 3 //单声道差分输出 + +#define DAC_OUTPUT_DUAL_LR_DIFF 6 //双声道差分 +#define DAC_OUTPUT_FRONT_LR_REAR_L 7 //三声道单端输出 前L+前R+后L (不可设置vcmo公共端) +#define DAC_OUTPUT_FRONT_LR_REAR_R 8 //三声道单端输出 前L+前R+后R (可设置vcmo公共端) +#define DAC_OUTPUT_FRONT_LR_REAR_LR 9 //四声道单端输出 + +#define AUDIO_DAC_SYNC_IDLE 0 +#define AUDIO_DAC_SYNC_PROBE 1 +#define AUDIO_DAC_SYNC_START 2 +#define AUDIO_DAC_SYNC_NO_DATA 3 +#define AUDIO_DAC_SYNC_ALIGN_COMPLETE 4 + +#define DAC_DSM_DEFAULT 0 +#define DAC_DSM_6MHz 1 +#define DAC_DSM_12MHz 2 + +#define FADE_OUT_IN 1 +#define PCM_PHASE_BIT 8 + +#define DA_LEFT 0 +#define DA_RIGHT 1 +#define DA_REAR_LEFT 2 +#define DA_REAR_RIGHT 3 +#define DA_FRONT_LR 5 +#define DA_REAR_LR 6 +#define DA_ALL_CH 7 + +#define DA_SOUND_NORMAL 0x0 +#define DA_SOUND_RESET 0x1 +#define DA_SOUND_WAIT_RESUME 0x2 + +#define AUDIO_DAC_MULTI_CHANNEL_ENABLE 1 + +enum { + DAC_EVENT_START, + DAC_EVENT_SAMPLE_BEGIN, + DAC_EVENT_SAMPLE_STOP, + DAC_EVENT_SAMPLE_MISS_DATA, + DAC_EVENT_CLOSE, +}; + +struct dac_platform_data { + void (*analog_open_cb)(struct audio_dac_hdl *); + void (*analog_close_cb)(struct audio_dac_hdl *); + u32 output : 4; //DAC输出模式 + u32 ldo_volt : 4; //DACVDD_LDO电压档选择 + u32 ldo_isel : 4; //LDO偏置电流选择档位, 0:5u, 1:10u, 2:15u, 3:20u, 4:25u, 5:30u, 6:35u, 7:40u + u32 lpf_isel : 4; //LPF bias电流选择, 0:无, 1:0.3125u, 2:0.625u, 3:0.9375, 4:1.25u, 5:1.5625, 6:1.875u, 7:2.1875u, 8:2.5u, 9:2.8125u, 10:3.125u, 11:3.4375u, 12:3.75u, 13:4.0625u, 14:4.375u, 15:4.6875u + u32 ldo_fb_isel : 2; //LDO负载电流选择, 0:15u, 1:48u, 2:81u, 3:114u + u32 vcmo_en : 1; //VCMO直推使能 + u32 keep_vcmo : 1; + u32 dsm_clk : 1; + u32 vcm_risetime : 1; //VCM上电快慢选择 + u32 zero_cross_detect : 1; //模拟增益过零检测配置 + u32 vdd_setting_enable : 1; //通过接口设置DACVDD电压的使能 +}; + + +struct analog_module { + /*模拟相关的变量*/ + u8 inited; + u8 vdd_volt; + u16 dac_test_volt; +}; +struct audio_dac_trim { + s16 left; + s16 right; + s16 rear_left; + s16 rear_right; +}; + + +struct audio_dac_hdl { + struct analog_module analog; + // const + struct dac_platform_data *pd; /*DAC 板级配置*/ + OS_SEM sem; + struct audio_dac_trim trim; /*DAC trim值*/ + volatile u8 mute; + volatile u8 state; /*DAC运行状态*/ + u8 gain_l; + u8 gain_r; + u8 gain_rl; + u8 gain_rr; + u8 vol_l; + u8 vol_r; + u8 vol_rl; + u8 vol_rr; + + u8 channel; /*DAC声道数*/ + u16 max_d_volume; /*DAC数字最大音量*/ + u16 d_volume[4]; /*DAC数字音量*/ + u32 sample_rate; /*DAC采样率*/ + u16 start_ms; /*起始延时(保留待删除)*/ + u16 delay_ms; /*最大延时(保留待删除)*/ + u16 start_points; /*起始样点数(保留待删除*/ + u16 delay_points; /*最大延时样点数(保留待删除)*/ + u16 unread_samples; /*未读样点个数*/ + + u16 irq_points; /*DAC普通中断样点个数*/ + + s16 *output_buf; /*DAC缓冲地址*/ + u16 output_buf_len; /*DAC缓冲长度*/ + u8 rr_rl_channel_close; + u8 protect_fadein; /*延时保护淡入*/ + u16 irq_timeout; /*非模块硬件的超时*/ + s16 read_offset; /*DAC读设置偏移*/ + u16 protect_pns; /*DAC延时保护最小样点*/ + s16 fade_vol; /*淡入淡出音量*/ + //struct audio_stream_entry entry; + struct audio_cfifo fifo; /*DAC cfifo结构管理*/ + struct list_head ch_head; /*DAC 子设备表头*/ + OS_MUTEX ch_mutex; /*DAC 子设备锁*/ +}; + +struct audio_dac_channel_attr { + u8 write_mode; /*DAC写入模式*/ + u16 delay_time; /*DAC通道延时*/ + u16 protect_time; /*DAC延时保护时间*/ +}; + +struct audio_dac_channel { + u8 state; /*DAC状态*/ + u8 pause; + u8 samp_sync_step; /*数据流驱动的采样同步步骤*/ + u8 wait_resume; /*数据流激活wait设置*/ + struct audio_dac_channel_attr attr; /*DAC通道属性*/ + struct audio_sample_sync *samp_sync; /*样点同步句柄*/ + struct audio_dac_hdl *dac; /*DAC设备*/ + struct audio_cfifo_channel fifo; /*DAC cfifo通道管理*/ + struct list_head ch_entry; /*DAC设备entry*/ + struct audio_stream_entry entry; /*DAC数据流节点*/ +}; + +/************************************************************************* + * 创建一个新的DAC + * INPUT : dac - DAC设备句柄, ch - 新的DAC通道 + * OUTPUT : 0 - 创建成功,非0 - 创建失败. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_dac_new_channel(struct audio_dac_hdl *dac, struct audio_dac_channel *ch); + +/************************************************************************* + * 释放一个DAC + * INPUT : ch - DAC通道 + * OUTPUT : 无. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +void audio_dac_free_channel(struct audio_dac_channel *ch); + +/************************************************************************* + * 获取DAC的属性配置 + * INPUT : ch - DAC通道,attr - DAC通道属性 + * OUTPUT : 0 - 成功, 非0 - 出错. + * WARNINGS : 用于设置属性前的初始化配置. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_dac_channel_get_attr(struct audio_dac_channel *ch, struct audio_dac_channel_attr *attr); + +/************************************************************************* + * 设置DAC的属性配置 + * INPUT : ch - DAC通道,attr - DAC通道属性 + * OUTPUT : 0 - 成功, 非0 - 出错. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_dac_channel_set_attr(struct audio_dac_channel *ch, struct audio_dac_channel_attr *attr); + +/************************************************************************* + * 暂停DAC的数据流输出 + * INPUT : ch - DAC通道,pause - 暂停/非暂停 + * OUTPUT : 0 - 成功, 非0 - 出错. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Zhuodengliang. + *=======================================================================*/ +int audio_dac_channel_set_pause(struct audio_dac_channel *ch, u8 pause); + +/************************************************************************* + * DAC播放同步使能 + * INPUT : ch - DAC通道,samp_sync - 采样同步句柄 + * OUTPUT : 0 - 成功, 非0 - 出错. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_dac_channel_sync_enable(struct audio_dac_channel *ch, struct audio_sample_sync *samp_sync); + +/************************************************************************* + * DAC播放同步使能关闭 + * INPUT : ch - DAC通道,samp_sync - 采样同步句柄 + * OUTPUT : 0 - 成功, 非0 - 出错. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_dac_channel_sync_disable(struct audio_dac_channel *ch, struct audio_sample_sync *samp_sync); + +/************************************************************************* + * DAC驱动模块初始化 + * INPUT : dac - DAC设备句柄,pd - DAC配置数据 + * OUTPUT : 0 - 成功, 非0 - 出错. + * WARNINGS : 1、初始化必须放在DAC设备使用之前;2、仅初始化一次不可重复操作. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_dac_init(struct audio_dac_hdl *dac, const struct dac_platform_data *pd); + +/************************************************************************* + * DAC省电容DTB设置 + * INPUT : dac - DAC设备句柄,dacr32 - DTB值 + * OUTPUT : 无. + * WARNINGS : 无需理解,由省电容开发人员设置. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +void audio_dac_set_capless_DTB(struct audio_dac_hdl *dac, s16 dacr32); + +/************************************************************************* + * DAC模块输出偏置电压校准 + * INPUT : dac - DAC设备句柄,dac_trim - DAC trim校准值参数, + * fast_trim - 加速模式,部分芯片不支持加速, 不建议使用, + * 详情请咨询开发人员. + * OUTPUT : 0 - 成功, 非0 - 出错. + * WARNINGS : 1、如非必要,trim在第一次上电/或者保存值丢失情况下调用; + * 2、该函数有时间开销,trim值应保留在存储单元重复使用,可避免上电trim. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_dac_do_trim(struct audio_dac_hdl *dac, struct audio_dac_trim *dac_trim, u8 fast_trim); + +/************************************************************************* + * DAC模块trim值设置 + * INPUT : dac - DAC设备句柄,dac_trim - DAC trim校准值参数 + * OUTPUT : 0 - 成功, 非0 - 出错. + * WARNINGS : 用于trim后或者读取存储值后设置给DAC模块,不可随意配置. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_dac_set_trim_value(struct audio_dac_hdl *dac, struct audio_dac_trim *dac_trim); + +int audio_dac_set_delay_time(struct audio_dac_hdl *dac, int start_ms, int max_ms); + +/************************************************************************* + * DAC中断处理函数 + * INPUT : dac - DAC设备句柄 + * OUTPUT : 无. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +void audio_dac_irq_handler(struct audio_dac_hdl *dac); + +/************************************************************************* + * DAC缓冲区内存设置 + * INPUT : dac - DAC设备句柄,buf - 缓冲区地址, len - 缓冲区长度(byte) + * OUTPUT : 0 - 成功, 非0 - 出错. + * WARNINGS : 接口设计为DAC初始化的配置,不建议任意位置使用. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_dac_set_buff(struct audio_dac_hdl *dac, s16 *buf, int len); + + +int audio_dac_write(struct audio_dac_channel *ch, void *buf, int len); + +s16 *audio_dac_get_write_ptr(struct audio_dac_hdl *dac, int *len); + +int audio_dac_update_write_ptr(struct audio_dac_hdl *dac, int len); + +/************************************************************************* + * DAC驱动模块初始化 + * INPUT : dac - DAC设备句柄,pd - DAC配置数据 + * OUTPUT : 0 - 成功, 非0 - 出错. + * WARNINGS : 1、初始化必须放在DAC设备使用之前;2、仅初始化一次不可重复操作. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_dac_set_sample_rate(struct audio_dac_hdl *dac, int sample_rate); + +int audio_dac_get_sample_rate(struct audio_dac_hdl *dac); + +int audio_dac_get_channel(struct audio_dac_hdl *dac); + +int audio_dac_set_channel(struct audio_dac_hdl *dac, u8 channel); + +int audio_dac_get_pd_output(struct audio_dac_hdl *dac); + +int audio_dac_set_pd_output(struct audio_dac_hdl *dac, u8 output); + +int audio_dac_set_digital_vol(struct audio_dac_hdl *dac, u16 vol); + +int audio_dac_set_analog_vol(struct audio_dac_hdl *dac, u16 vol); + +int audio_dac_mix_ch_get_datasize(struct audio_dac_hdl *dac); +/* + *example : audio_dac_ch_set_analog_vol(&dac_hdl, DA_RIGHT, 10); + */ +int audio_dac_ch_set_analog_vol(struct audio_dac_hdl *dac, u8 channel, u16 vol); + +int audio_dac_start(struct audio_dac_hdl *dac); + +int audio_dac_stop(struct audio_dac_hdl *dac); + +int audio_dac_channel_stop(struct audio_dac_channel *ch); + +int audio_dac_idle(struct audio_dac_hdl *dac); + +void audio_dac_mute(struct audio_dac_hdl *hdl, u8 mute); + +int audio_dac_open(struct audio_dac_hdl *dac); + +int audio_dac_close(struct audio_dac_hdl *dac); + +int audio_dac_mute_left(struct audio_dac_hdl *dac); + +int audio_dac_mute_right(struct audio_dac_hdl *dac); + +int audio_dac_set_volume(struct audio_dac_hdl *dac, u8 gain_l, u8 gain_r, u8 gain_rl, u8 gain_rr); + +int audio_dac_set_L_digital_vol(struct audio_dac_hdl *dac, u16 vol); + +int audio_dac_set_R_digital_vol(struct audio_dac_hdl *dac, u16 vol); + +void audio_dac_set_fade_handler(struct audio_dac_hdl *dac, void *priv, void (*fade_handler)(u8, u8, u8, u8)); + +int audio_dac_power_off(struct audio_dac_hdl *dac); + +int audio_dac_get_hrp(struct audio_dac_hdl *dac); + +/************************************************************************* + * DAC采样率匹配 + * INPUT : dac - DAC设备句柄,sample_rate - 采样率 + * OUTPUT : true - 匹配到, false - 匹配不到. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +bool audio_dac_sample_rate_match(struct audio_dac_hdl *dac, u32 sample_rate); + +/************************************************************************* + * DAC采样率选择 + * INPUT : dac - DAC设备句柄,sample_rate - 预期采样率, + * hign - 如果DAC不支持预期的采样率选择临近一档高于预期的采样率 + * OUTPUT : 最终选择到的采样率. + * WARNINGS : 无. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_dac_sample_rate_select(struct audio_dac_hdl *dac, u32 sample_rate, u8 high); + +int audio_dac_sound_reset(struct audio_dac_hdl *dac, u32 msecs); + +u8 audio_dac_is_working(struct audio_dac_hdl *dac); + +int audio_dac_data_time(struct audio_dac_hdl *dac); + +int audio_dac_get_status(struct audio_dac_hdl *dac); + +int audio_dac_get_max_channel(void); + +int audio_dac_ch_analog_gain_set(struct audio_dac_hdl *dac, u8 ch, u8 again); + +int audio_dac_ch_analog_gain_get(struct audio_dac_hdl *dac, u8 ch); + +int audio_dac_ch_digital_gain_set(struct audio_dac_hdl *dac, u8 ch, u32 dgain); + +int audio_dac_ch_digital_gain_get(struct audio_dac_hdl *dac, u8 ch); + +void audio_dac_ch_mute(struct audio_dac_hdl *dac, u8 ch, u8 mute); +void audio_dac_zero_detect_onoff(struct audio_dac_hdl *dac, u8 onoff); + +int audio_dac_set_RL_digital_vol(struct audio_dac_hdl *dac, u16 vol); +int audio_dac_set_RR_digital_vol(struct audio_dac_hdl *dac, u16 vol); +void audio_dac_RR_RL_stop(struct audio_dac_hdl *dac); +int audio_dac_set_analog_vol_support4way(struct audio_dac_hdl *dac, u16 FL_vol, u16 FR_vol, u16 RL_vol, u16 RR_vol); + +/*************************************************************************; + * DAC采样率选择 + * + * INPUT : dac - DAC设备句柄, volt - DACVDD 电压值(宏定义) + * + * OUTPUT : 无. + * + * WARNINGS : 根据struct dac_platform_data的vdd_setting_enable变量控制, + * 该开关为0,则函数无法真正设置电压到dac电源. + * + * HISTORY : 2021/2/18 by Lichao. + *=======================================================================*/ +void audio_dac_set_vdd_volt(struct audio_dac_hdl *dac, u8 volt); + +/************************************************************************* + * DAC模块电源关闭 + * INPUT : 无. + * OUTPUT : 无. + * WARNINGS : 若DAC电源关闭后,低功耗或其他应用不应再设置DAC电源等. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +void dac_power_off(void); + +/*关闭audio相关模块使能*/ +void audio_disable_all(void); + +/******************************************************************* + * Audio DACVDD上电接口 + * params : struct audio_dac_hdl结构指针 + * + * return : 无 + * + * warnings : 仅用作Audio初始化上电,不可在任意位置使用 + * + * example : audio_dac_vdd_power_on(&dac_hdl); + *=================================================================*/ +void audio_dac_vdd_power_on(struct audio_dac_hdl *dac); +/******************************************************************* + * Audio DACVDD断电接口 + * params : struct audio_dac_hdl结构指针 + * + * return : 无 + * + * warnings : 仅用作Audio DACVDD断电,不可在任意位置使用 + * + * example : audio_dac_vdd_power_off(&dac_hdl); + *=================================================================*/ +void audio_dac_vdd_power_off(struct audio_dac_hdl *dac); + +int audio_dac_fifo_set_read(struct audio_dac_hdl *dac, int offset); + +/* + * fifo数据读取 + * data - 数据 + * len - 长度(byte) + * channel - 读取DAC的channel, DA_LEFT/DA_RIGHT/DA_ALL_CH + */ +/************************************************************************* + * DAC模块电源关闭 + * INPUT : dac - DAC设备句柄,data - 地址,len - 长度, + * channel - 声道(DA_LEFT/DA_RIGHT/DA_ALL_CH). + * OUTPUT : 读取长度. + * WARNINGS : DAC未开启读不到任何数据. + * HISTORY : 2020/12/28 by Lichao. + *=======================================================================*/ +int audio_dac_fifo_read(struct audio_dac_hdl *dac, void *data, int len, u8 channel); +#endif + diff --git a/include_lib/media/media_develop/media/cpu/br23/asm/hw_eq.h b/include_lib/media/media_develop/media/cpu/br23/asm/hw_eq.h new file mode 100644 index 0000000..24347fc --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/asm/hw_eq.h @@ -0,0 +1,302 @@ + +#ifndef __HW_EQ_H +#define __HW_EQ_H + +#include "generic/typedef.h" +#include "generic/list.h" +#include "os/os_api.h" +#include "media/eq_func_define.h" + + +/*eq IIR type*/ +typedef enum { + EQ_IIR_TYPE_HIGH_PASS = 0x00, + EQ_IIR_TYPE_LOW_PASS, + EQ_IIR_TYPE_BAND_PASS, + EQ_IIR_TYPE_HIGH_SHELF, + EQ_IIR_TYPE_LOW_SHELF, +} EQ_IIR_TYPE; + +struct eq_seg_info_hw { + u16 index; //eq段序号 + u16 iir_type; //滤波器类型EQ_IIR_TYPE + int freq; //中心截止频率 + int gain; //增益(-12 ~12 db)*(1<<20) + int q; //q值(0.3~30)*(1<<24) +}; + +struct eq_seg_info { + u16 index; //eq段序号 + u16 iir_type; //滤波器类型EQ_IIR_TYPE + int freq; //中心截止频率 + float gain; //增益 + float q; //q值 +}; + + +struct eq_coeff_info { + u8 nsection; //eq段数 + u8 no_coeff; //不是滤波系数 +#ifdef CONFIG_EQ_NO_USE_COEFF_TABLE + u32 sr; //采样率 +#endif + int *L_coeff; //左声道滤波器系数地址 + int *R_coeff; //右声道滤波器系数地址 + float L_gain; //左声道总增益(-20~20db) + float R_gain; //右声道总增益(-20~20db) +}; + +struct hw_eq_ch; + +struct hw_eq { + struct list_head head; //链表头 + OS_MUTEX mutex; //互斥锁 + volatile struct hw_eq_ch *cur_ch; //当前需要处理的eq通道 +}; + +enum { + HW_EQ_CMD_CLEAR_MEM = 0xffffff00, + HW_EQ_CMD_CLEAR_MEM_L, + HW_EQ_CMD_CLEAR_MEM_R, +}; + +struct hw_eq_handler { + int (*eq_probe)(struct hw_eq_ch *); //eq驱动内前处理 + int (*eq_output)(struct hw_eq_ch *, s16 *, u16); //eq驱动内输出处理回调 + int (*eq_post)(struct hw_eq_ch *); //eq驱动内处理后回调 + int (*eq_input)(struct hw_eq_ch *, void **, void **); //eq驱动内输入处理回调 +}; + +struct hw_eq_ch { + unsigned char out_32bit; //是否输出32bit位宽的数据 0:16bit 1:32bit + unsigned char updata; //更新参数以及中间数据 + unsigned char updata_coeff_only; //只更新参数,不更新中间数据 + unsigned char no_wait; //是否是异步eq处理 0:同步的eq 1:异步的eq + unsigned char channels; //通道数(1或2) + unsigned char SHI; //eq运算输出数据左移位数控制,记录 + unsigned char countL; //eq运算输出数据左移位数控制临时记录 + unsigned short stage; //eq运算开始位置标识 + unsigned char nsection; //eq段数 + unsigned char no_coeff; // 非滤波系数 + volatile unsigned char active; //已启动eq处理 1:busy 0:处理结束 + volatile unsigned char need_run; //多eq同时使用时,未启动成功的eq,是否需要重新唤醒处理 1:需要 0:否 +#ifdef CONFIG_EQ_NO_USE_COEFF_TABLE + u32 sr; //采样率 +#endif + int *L_coeff; //输入给左声道系数地址 + int *R_coeff; //输入给右声道系数地址 + int L_gain; //输入给左声道总增益(-20~20) + int R_gain; //输入给右声道总增益(-20~20) + int *eq_LRmem; //eq系数地址(包含运算的中间数据) + s16 *out_buf; //输出buf地址 + s16 *in_buf; //输入buf地址 + int in_len; //输入数据长度 + void *priv; //保存eq管理层的句柄 + volatile OS_SEM sem; //信号量,用于通知驱动,当前一次处理完成 + struct list_head entry; //当前eq通道的节点 + struct hw_eq *eq; //底层eq操作句柄 + const struct hw_eq_handler *eq_handler;//eq操作的相关回调函数句柄 + void *irq_priv; //eq管理层传入的私有指针 + void (*irq_callback)(void *priv);//需要eq中断执行的回调函数 +}; + +//系数计算子函数 +/* +fc: 低通滤波器-3dB衰减频点 +fs: 采样率 +nSOS: 生成nSOS阶IIR +coeff: 输出系数地址 ( 大小为 ((nSOS & 1) + (nSOS >> 1))*5 , 顺序是按照硬件EQ摆放了 ) +段数:((nSOS & 1) + (nSOS >> 1))*/ +/* + * 多阶级低通滤波器 +fc: 低通滤波器-3dB衰减频点 +fs: 采样率 +nSOS: 生成多少个2阶IIR +coeff: 输出系数地址 ( 大小为 nSOS*5 , 顺序是按照硬件EQ摆放了 )*/ +extern void butterworth_lp_design(int fc, int fs, int nSOS, int *coeff); + +/* +fc: 通滤波器-3dB衰减频点 +fs: 采样率 +nSOS: 生成nSOS阶IIR +coeff: 输出系数地址 ( 大小为((nSOS & 1) + (nSOS >> 1))*5 , 顺序是按照硬件EQ摆放了 ) +段数:((nSOS & 1) + (nSOS >> 1))*/ +extern void butterworth_hp_design(int fc, int fs, int nSOS, int *coeff); +// +/*----------------------------------------------------------------------------*/ +/**@brief 低通滤波器 + @param fc:中心截止频率 + @param fs:采样率 + @param quality_factor:q值 + @param coeff:计算后,系数输出地址 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +extern void design_lp(int fc, int fs, int quality_factor, int *coeff); +/*----------------------------------------------------------------------------*/ +/**@brief 高通滤波器 + @param fc:中心截止频率 + @param fs:采样率 + @param quality_factor:q值 + @param coeff:计算后,系数输出地址 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +extern void design_hp(int fc, int fs, int quality_factor, int *coeff); +/*----------------------------------------------------------------------------*/ +/**@brief 带通滤波器 + @param fc:中心截止频率 + @param fs:采样率 + @param gain:增益 + @param quality_factor:q值 + @param coeff:计算后,系数输出地址 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +extern void design_pe(int fc, int fs, int gain, int quality_factor, int *coeff); +/*----------------------------------------------------------------------------*/ +/**@brief 低频搁架式滤波器 + @param fc:中心截止频率 + @param fs:采样率 + @param gain:增益 + @param quality_factor:q值 + @param coeff:计算后,系数输出地址 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +extern void design_ls(int fc, int fs, int gain, int quality_factor, int *coeff); +/*----------------------------------------------------------------------------*/ +/**@brief 高频搁架式滤波器 + @param fc:中心截止频率 + @param fs:采样率 + @param gain:增益 + @param quality_factor:q值 + @param coeff:计算后,系数输出地址 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +extern void design_hs(int fc, int fs, int gain, int quality_factor, int *coeff); +/*----------------------------------------------------------------------------*/ +/**@brief 滤波器系数检查 + @param coeff:滤波器系数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +extern int eq_stable_check(int *coeff); +/*----------------------------------------------------------------------------*/ +/**@brief 获取直通的滤波器系数 + @param coeff:滤波器系数 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +extern void eq_get_AllpassCoeff(void *Coeff); + +/*----------------------------------------------------------------------------*/ +/**@brief 滤波器计算管理函数 + @param *seg:提供给滤波器的基本信息 + @param sample_rate:采样率 + @param *coeff:计算后,系数输出地址 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int eq_seg_design(struct eq_seg_info *seg_tmp, int sample_rate, int *coeff); + + +/*----------------------------------------------------------------------------*/ +/**@brief 在EQ中断中调用 + @param *eq:句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_hw_eq_irq_handler(struct hw_eq *eq); + +/*----------------------------------------------------------------------------*/ +/**@brief EQ初始化 + @param *eq:句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_hw_eq_init(struct hw_eq *eq); + +/*----------------------------------------------------------------------------*/ +/**@brief 打开一个通道 + @param *ch:通道句柄 + @param *eq:句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_hw_eq_ch_open(struct hw_eq_ch *ch, struct hw_eq *eq); +/*----------------------------------------------------------------------------*/ +/**@brief 设置回调接口 + @param *ch:通道句柄 + @param *handler:回调的句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_hw_eq_ch_set_handler(struct hw_eq_ch *ch, struct hw_eq_handler *handler); +// +/*----------------------------------------------------------------------------*/ +/**@brief 设置通道基础信息 + @param *ch:通道句柄 + @param channels:通道数 + @param out_32bit:是否输出32bit位宽数据 1:是 0:16bit位宽 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_hw_eq_ch_set_info(struct hw_eq_ch *ch, u8 channels, u8 out_32bit); + +/*----------------------------------------------------------------------------*/ +/**@brief 设置硬件转换系数 + @param *ch:通道句柄 + @param *info:系数、增益等信息 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_hw_eq_ch_set_coeff(struct hw_eq_ch *ch, struct eq_coeff_info *info); + +/*----------------------------------------------------------------------------*/ +/**@brief 启动一次转换 + @param *ch:eq句柄 + @param *input:输入数据地址 + @param *output:输出数据地址 + @param len:输入数据长度 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_hw_eq_ch_start(struct hw_eq_ch *ch, void *input, void *output, int len); + +/*----------------------------------------------------------------------------*/ +/**@brief 关闭一个通道 + @param *ch:eq句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_hw_eq_ch_close(struct hw_eq_ch *ch); + +/*----------------------------------------------------------------------------*/ +/**@brief 获取eq是否正在运行状态 + @param *ch:eq句柄 + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_hw_eq_is_running(struct hw_eq *eq); + +#endif /*__HW_EQ_H*/ + diff --git a/include_lib/media/media_develop/media/cpu/br23/asm/pemafrow_api.h b/include_lib/media/media_develop/media/cpu/br23/asm/pemafrow_api.h new file mode 100644 index 0000000..f5a31e5 --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/asm/pemafrow_api.h @@ -0,0 +1,23 @@ +#ifndef PEMAFROW_API_H +#define PEMAFROW_API_H + +#include "media/audio_stream.h" + +#define PEMAFROW_RUN_POINT_NUM 128 //每次run固定点数 +int getPemafrowBuf(); +void pemafrowInit(void *workBuf); +//int pemafrowRun(void *workBuf, short *in, short *out, int len); +int pemafrowRun(void *workBuf, short *in, short *preOut, short *out); + +typedef struct _PEMAFROW_API_STRUCT_ { + void *ptr; //运算buf指针 + s16 pre_data[PEMAFROW_RUN_POINT_NUM]; + s16 data_buf[PEMAFROW_RUN_POINT_NUM]; + struct audio_stream_entry entry; // 音频流入口 + int out_len; + int process_len; + u16 data_len; + u8 run_en; +} PEMAFROW_API_STRUCT; + +#endif diff --git a/include_lib/media/media_develop/media/cpu/br23/asm/ps_cal_api.h b/include_lib/media/media_develop/media/cpu/br23/asm/ps_cal_api.h new file mode 100644 index 0000000..6601682 --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/asm/ps_cal_api.h @@ -0,0 +1,88 @@ + +#ifndef ps_cal_api_h__ +#define ps_cal_api_h__ + + +#ifndef u8 +#define u8 unsigned char +#endif + +#ifndef u16 +#define u16 unsigned short +#endif + +#ifndef s16 +#define s16 short +#endif + + +#ifndef u32 +#define u32 unsigned int +#endif + +#ifndef s16 +#define s16 signed short +#endif + + +enum { + PS69_SPEED_UP = 1, + PS69_SPEED_DOWN = 2 +}; + +typedef struct _PS69_CONTEXT_IO_ { + u8 *outpriv; + u32(*output)(void *priv, u8 *buf, int len); +} PS69_audio_IO; + +typedef struct _PS69_CONTEXT_CONF_ { + u16 chn; + u16 sr; + u16 speedV; + u16 pitchV; +} PS69_CONTEXT_CONF; + +typedef struct _PS69_API_CONTEXT_ { + u32(*need_size)(void); + u32(*open)(u8 *ptr, PS69_audio_IO *audio_IO); + u32(*dconfig)(u8 *ptr, PS69_CONTEXT_CONF *conf_obj); + u32(*run)(u8 *ptr, s16 *inbuf, u32 len); + u32(*run_same)(u8 *ptr, s16 *inbuf, u32 len, s16 *outdata); +} PS69_API_CONTEXT; + +#define ABS_LEN_FLAG 0x100 + +extern PS69_API_CONTEXT *get_ps_cal_api(); + +#endif // syn_ps_api_h__ + + +#if 0 + +{ + PS69_API_CONTEXT *testops = get_ps_cal_api(); + PS69_CONTEXT_CONF test_config_obj; + + test_config_obj.pitchV = 32768; + test_config_obj.sr = 44100; + test_config_obj.chn = 2; + test_config_obj.speedV = 80; + + bufsize = syn_ops->need_size(); + ptr = malloc(bufsize); + testops->open(ptr, &testIO); + testops->dconfig(ptr, &test_config_obj); + + while (1) { + if (feof(fp1)) { + break; + } + fread(test_buf, 1, TEST_LEN, fp1); + testops->run(ptr, test_buf, TEST_LEN); + } + + free(ptr); +} + +#endif + diff --git a/include_lib/media/media_develop/media/cpu/br23/commproc.h b/include_lib/media/media_develop/media/cpu/br23/commproc.h new file mode 100644 index 0000000..12ed575 --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/commproc.h @@ -0,0 +1,113 @@ +#ifndef _COMMPROC_H_ +#define _COMMPROC_H_ + +#include "generic/typedef.h" + +/*降噪版本定义*/ +#define ANS_V100 0xA1 +#define ANS_V200 0xA2 + +//aec_cfg: +typedef struct __AEC_CONFIG { + u8 mic_again; //DAC增益,default:3(0~14) + u8 dac_again; //MIC增益,default:22(0~31) + u8 aec_mode; //AEC模式,default:advance(diable(0), reduce(1), advance(2)) + u8 ul_eq_en; //上行EQ使能,default:enable(disable(0), enable(1)) + /*AGC*/ + float ndt_fade_in; //单端讲话淡入步进default: 1.3f(0.1 ~ 5 dB) + float ndt_fade_out; //单端讲话淡出步进default: 0.7f(0.1 ~ 5 dB) + float dt_fade_in; //双端讲话淡入步进default: 1.3f(0.1 ~ 5 dB) + float dt_fade_out; //双端讲话淡出步进default: 0.7f(0.1 ~ 5 dB) + float ndt_max_gain; //单端讲话放大上限,default: 12.f(0 ~ 24 dB) + float ndt_min_gain; //单端讲话放大下限,default: 0.f(-20 ~ 24 dB) + float ndt_speech_thr; //单端讲话放大阈值,default: -50.f(-70 ~ -40 dB) + float dt_max_gain; //双端讲话放大上限,default: 12.f(0 ~ 24 dB) + float dt_min_gain; //双端讲话放大下限,default: 0.f(-20 ~ 24 dB) + float dt_speech_thr; //双端讲话放大阈值,default: -40.f(-70 ~ -40 dB) + float echo_present_thr; //单端双端讲话阈值,default:-70.f(-70 ~ -40 dB) + /*AEC*/ + float aec_dt_aggress; //原音回音追踪等级, default: 1.0f(1 ~ 5) + float aec_refengthr; //进入回音消除参考值, default: -70.0f(-90 ~ -60 dB) + /*ES*/ + float es_aggress_factor;//回音前级动态压制,越小越强,default: -3.0f(-1 ~ -5) + float es_min_suppress; //回音后级静态压制,越大越强,default: 4.f(0 ~ 10) + /*ANS*/ + float ans_aggress; //噪声前级动态压制,越大越强default: 1.25f(1 ~ 2) + float ans_suppress; //噪声后级静态压制,越小越强default: 0.04f(0 ~ 1) +} _GNU_PACKED_ AEC_CONFIG; + +struct aec_s_attr { + u8 agc_en: 1; + u8 ul_eq_en: 1; + u8 wideband: 1; + u8 toggle: 1; + u8 wn_en: 1; + u8 dly_est : 1; + u8 reserved: 2; + + u8 dst_delay;/*延时估计目标延时*/ + u8 EnableBit; + u8 packet_dump; + u8 SimplexTail; + float AGC_NDT_fade_in_step; //in dB + float AGC_NDT_fade_out_step; //in dB + float AGC_NDT_max_gain; //in dB + float AGC_NDT_min_gain; //in dB + float AGC_NDT_speech_thr; //in dB + float AGC_DT_fade_in_step; //in dB + float AGC_DT_fade_out_step; //in dB + float AGC_DT_max_gain; //in dB + float AGC_DT_min_gain; //in dB + float AGC_DT_speech_thr; //in dB + float AGC_echo_present_thr; //In dB + int AGC_echo_look_ahead; //in ms + int AGC_echo_hold; // in ms + u16 hw_delay_offset;/*dac hardware delay offset*/ + u16 wn_gain;/*white_noise gain*/ + int SimplexThr; + float ES_AggressFactor; + float ES_MinSuppress; + float ES_Unconverge_OverDrive; + float ANS_AggressFactor; + float ANS_MinSuppress; + float ANS_NoiseLevel; + int (*aec_probe)(s16 *dat, u16 len); + int (*aec_post)(s16 *dat, u16 len); + int (*output_handle)(s16 *dat, u16 len); + u8 output_way; // 0:dac 1:fm + u8 ANS_mode; + u8 fm_tx_start; + u8 aec_tail_length;/*AEC复杂等级:2~10,default:5*/ + + float AEC_RefEngThr; + float AEC_DT_AggressiveFactor; + + /*Extended-Parameters*/ + u16 ref_sr; + + /*DNS Parameters*/ + float DNS_GainFloor; + float DNS_OverDrive; + float DNS_Loudness; +}; + +s32 aec_init(struct aec_s_attr *attr); +s32 aec_exit(); +u32 aec_output_read(s16 *buf, u16 npoint); +s32 aec_fill_in_data(u8 *dat, u16 len); +s32 aec_fill_ref_data(u8 *dat, u16 len); +void aec_toggle(u8 toggle); + +int sms_init(struct aec_s_attr *attr); +int sms_exit(); +int sms_fill_in_data(u8 *dat, u16 len); +int sms_fill_ref_data(u8 *dat, u16 len); +void sms_toggle(u8 toggle); + +int sms_tde_init(struct aec_s_attr *attr); +int sms_tde_exit(); +int sms_tde_fill_in_data(u8 *dat, u16 len); +int sms_tde_fill_ref_data(u8 *dat, u16 len); +void sms_tde_toggle(u8 toggle); + +#endif diff --git a/include_lib/media/media_develop/media/cpu/br23/media_lib_bss.ld b/include_lib/media/media_develop/media/cpu/br23/media_lib_bss.ld new file mode 100644 index 0000000..286c271 --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/media_lib_bss.ld @@ -0,0 +1,131 @@ + + media_bss_start = .; + . = ALIGN(4); + *(.jlsp_bss) + *(.aec_bss) + *(.res_bss) + *(.ns_bss) + *(.der_bss) + *(.nlp_bss) + *(.qmf_bss) + *(.bt_audioplc_bss) + *(.fft_bss) + *(.sms_bss) + *(.pcm_bss) + /* *(.cvsd_bss) */ + *(.g729_bss) + *(.g726_bss) + *(.wtg_dec_bss) + *(.wtgv2_bss) + *(.wtgv2dec_bss) + *(.mp3_bss) + *(.mp3_dec_bss) + *(.msbc_bss) + *(.mty_bss) + *(.mp3tsy_dec_bss) + *(.sbc_bss) + *(.sine_bss) + /* *(.wav_bss) */ + *(.wma_bss) + *(.wma_dec_bss) + /* *(.aac_bss) */ + *(.amr_bss) + *(.midi_bss) + /* *(.ape_bss) */ + *(.audio_decoder_bss) + /* *(.dts_bss) */ + /* *(.flac_bss) */ + /* *(.m4a_bss) */ + *(.mp3_encode_bss) + *(.media_device_bss) + *(.audio_encoder_bss) + *(.mixer_bss) + *(.stream_bss) + *(.dec_server_bss) + *(.rec_server_bss) + *(.auto_mute_bss) + *(.plc_bss) + *(.wireless_sync_bss) + + *(.audio_buf) + + *(.resample_cal_bss) + *(.bt_crossOver_bss) + *(.bt_compressor_bss) + *(.bt_limiter_bss) + *(.bt_limiter_sparse_bss) + *(.bt_crossOver_sparse_bss) + *(.bt_compressor_sparse_bss) + + *(.iap_bss) + *(.audio_bfilt_bss) + *(.audio_buf_sync_bss) + *(.audio_dec_app_bss) + *(.audio_dec_app_sync_bss) + *(.audio_dig_vol_bss) + *(.audio_echo_reverb_bss) + *(.echo_cal_bss) + *(.reverb_cal_bss) + *(.reverb0_bss) + *(.platereverb_bss) + *(.audio_echo_src_bss) + *(.audio_energy_detect_bss) + *(.audio_eq_bss) + *(.audio_drc_bss) + *(.audio_eq_drc_apply_bss) + *(.audio_equalloudness_bss) + *(.audio_howling_bss) + *(.howlings_phf_bss) + *(.audio_noisegate_bss) + *(.audio_output_dac_bss) + *(.audio_pemafrow_bss) + *(.audio_pitch_bss) + *(.audio_pitchspeed_bss) + *(.audio_surround_bss) + *(.audio_vbass_bss) + *(.audio_vocal_remove_bss) + *(.audio_vocal_tract_synthesis_bss) + *(.eq_config_bss) + *(.eq_config_protocol_bss) + *(.spectrum_eq_bss) + *(.spectrum_fft_bss) + *(.audio_localtws_bss) + *(.audio_dec_localtws_bss) + *(.audio_dec_a2dp_bss) + *(.audio_dec_esco_bss) + *(.audio_dec_file_bss) + *(.audio_dec_pcm_bss) + *(.audio_resample_bss) + *(.audio_splicing_bss) + *(.channel_switch_bss) + *(.sw_drc_bss) + *(.aptx_decoder_bss) + *(.ldac_decoder_bss) + *(.speex_encoder_bss) + *(.sbc_encoder_bss) + *(.opus_encoder_bss) + *(.prevent_task_fill_bss) + *(.audio_cfifo_bss) + *(.audio_track_bss) + *(.audio_adc_bss) + *(.audio_dac_bss) + *(.audio_linein_bss) + *(.audio_link_bss) + *(.audio_sample_sync_bss) + *(.audio_wireless_sync_bss) + *(.audio_spdif_bss) + *(.audio_src_bss) + *(.audio_src_base_bss) + *(.effectrs_sync_bss) + *(.eq_design_bss) + *(.hw_eq_bss) + *(.iic_bss) + *(.mic_cap_bss) + *(.sbc_hwaccel_bss) + *(.resample_fastcal_bss) + *(.lfwordana_bss) + media_bss_end = .; + + + + diff --git a/include_lib/media/media_develop/media/cpu/br23/media_lib_data.ld b/include_lib/media/media_develop/media/cpu/br23/media_lib_data.ld new file mode 100644 index 0000000..85e6ec7 --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/media_lib_data.ld @@ -0,0 +1,175 @@ + + + media_data_start = .; + + . = ALIGN(4); + EQ_COEFF_BASE = . ; + . = EQ_COEFF_BASE + 4 * EQ_SECTION_NUM * 14; + + . = ALIGN(4); + *(.jlsp_data) + . = ALIGN(4); + *(.dns_common_data) + *(.dns_param_data_single) + *(.dns_param_data_dual) + . = ALIGN(4); + *(.aec_data) + . = ALIGN(4); + *(.res_data) + . = ALIGN(4); + *(.ns_data) + . = ALIGN(4); + *(.der_data) + . = ALIGN(4); + *(.nlp_data) + . = ALIGN(4); + *(.qmf_data) + . = ALIGN(4); + *(.fft_data) + . = ALIGN(4); + *(.bt_audioplc_data) + *(.sms_data) + + *(.pcm_data) + /* *(.cvsd_data) */ + *(.g729_data) + *(.g726_data) + *(.wtg_dec_data) + *(.wtgv2_data) + *(.wtgv2dec_data) + *(.mp3_data) + *(.mp3_dec_data) + *(.msbc_data) + *(.mty_data) + *(.mp3tsy_dec_data) + *(.sbc_data) + *(.sine_data) + /* *(.wav_data) */ + *(.wma_data) + *(.wma_dec_data) + /* *(.aac_data) */ + *(.amr_data) + *(.midi_data) + /* *(.ape_data) */ + *(.audio_decoder_data) + /* *(.dts_data) */ + /* *(.flac_data) */ + /* *(.m4a_data) */ + *(.mp3_encode_data) + *(.media_device_data) + *(.audio_encoder_data) + *(.mixer_data) + *(.stream_data) + *(.dec_server_data) + *(.rec_server_data) + *(.auto_mute_data) + *(.plc_data) + *(.wireless_sync_data) + + *(.resample_cal_data) + *(.bt_compressor_data) + *(.bt_crossOver_data) + *(.bt_limiter_data) + *(.bt_compressor_sparse_data) + *(.bt_limiter_sparse_data) + *(.bt_crossOver_sparse_data) + + *(.iap_data) + *(.audio_bfilt_data) + *(.audio_buf_sync_data) + *(.audio_dec_app_data) + *(.audio_dec_app_sync_data) + *(.audio_dig_vol_data) + *(.audio_echo_reverb_data) + *(.echo_cal_data) + *(.reverb_cal_data) + *(.reverb0_data) + *(.platereverb_data) + *(.audio_echo_src_data) + *(.audio_energy_detect_data) + *(.audio_eq_data) + *(.audio_drc_data) + *(.audio_eq_drc_apply_data) + *(.audio_equalloudness_data) + *(.audio_howling_data) + *(.howlings_phf_data) + *(.audio_noisegate_data) + *(.audio_output_dac_data) + *(.audio_pemafrow_data) + *(.audio_pitch_data) + *(.audio_pitchspeed_data) + *(.audio_surround_data) + *(.audio_vbass_data) + *(.audio_vocal_remove_data) + *(.audio_vocal_tract_synthesis_data) + *(.eq_config_data) + *(.eq_config_protocol_data) + *(.spectrum_eq_data) + *(.spectrum_fft_data) + *(.audio_localtws_data) + *(.audio_dec_localtws_data) + *(.audio_dec_a2dp_data) + *(.audio_dec_esco_data) + *(.audio_dec_file_data) + *(.audio_dec_pcm_data) + *(.audio_resample_data) + *(.audio_splicing_data) + *(.channel_switch_data) + *(.sw_drc_data) + *(.aptx_decoder_data) + *(.ldac_decoder_data) + *(.speex_encoder_data) + *(.sbc_encoder_data) + *(.opus_encoder_data) + *(.prevent_task_fill_data) + *(.audio_cfifo_data) + *(.audio_track_data) + *(.audio_adc_data) + *(.audio_dac_data) + *(.audio_linein_data) + *(.audio_link_data) + *(.audio_sample_sync_data) + *(.audio_wireless_sync_data) + *(.audio_spdif_data) + *(.audio_src_data) + *(.audio_src_base_data) + *(.effectrs_sync_data) + *(.eq_design_data) + *(.hw_eq_data) + *(.iic_data) + *(.mic_cap_data) + *(.sbc_hwaccel_data) + *(.resample_fastcal_data) + *(.aac_data) + *(.alac_data) + . = ALIGN(4); + *(.dec2tws_mem) + . = ALIGN(4); + *(.midi_mem) + *(.midi_ctrl_mem) + + *(.lfwordana_data) + *(.pitchshifter_data) + /* *(.crossOver_code) */ + /* *(.crossOver_const) */ + /* *(.bt_crossOver_const) */ + /* *(.bt_crossOver_code) */ + /* . = ALIGN(4); */ + + /* *(.compressor_code) */ + /* *(.compressor_const) */ + /* *(.bt_compressor_const) */ + /* *(.bt_compressor_code) */ + /* . = ALIGN(4); */ + + /* *(.limiter_code) */ + /* *(.limiter_const) */ + /* *(.bt_limiter_const) */ + /* *(.bt_limiter_code) */ + /* . = ALIGN(4); */ + + media_data_end = .; + + + + diff --git a/include_lib/media/media_develop/media/cpu/br23/media_lib_data_text.ld b/include_lib/media/media_develop/media/cpu/br23/media_lib_data_text.ld new file mode 100644 index 0000000..aad4628 --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/media_lib_data_text.ld @@ -0,0 +1,93 @@ + media_data_code_start = .; + . = ALIGN(4); +#if (SOUNDCARD_ENABLE) + *(.dvol_ram_code) + *(.reverb_cal_const) + *(.reverb_cal_code) + *(.mp3_code) + + *(.stream_code_copy_run) // 数据流分支输出处理 + *(.mixer_code_out_run) // mixer数据流叠加后输出 + +#endif + +#if (SOUNDCARD_ENABLE && !TCFG_CODE_RUN_RAM_FM_MODE) + *(.stream_code_nor_run) // 数据流普通输出处理 + *(.mixer_code_nor_run) // mixer数据流直通输出 +#endif /*(SOUNDCARD_ENABLE && !TCFG_CODE_RUN_RAM_FM_MODE)*/ + + *(.sbc_eng_code) +#if (TCFG_CODE_RUN_RAM_FM_MODE) + *(.pcm_code) + *(.pcm_const) + *(.audio_dec_pcm_code) + *(.audio_dec_pcm_const) + *(.stream_code_nor_run) // 数据流普通输出处理 + *(.mixer_code_nor_run) // mixer数据流直通输出 + *(.audio_codec_code) // 解码任务流程 + *(.audio_codec_code_read_file) // 解码读文件 + *(.audio_src_code_nor_run) // audio_src运行处理 + *(.src_base_code_nor_run) // src_base运行处理 + *(.audio_dac_code_nor_run) // audio_dac普通输出运行处理 + *(.audio_cfifo_code_nor_run) // audio_cfifo普通运行处理 + *(.audio_track_code) + *(.audio_track_const) +#endif /*(TCFG_CODE_RUN_RAM_FM_MODE)*/ + . = ALIGN(4); + + AudioEffects_data_code_begin = .; +#if AUDIO_EFFECTS_REVERB_AT_RAM + *(.platereverb_code) + *(.platereverb_const) +#endif/*AUDIO_EFFECTS_REVERB_AT_RAM*/ + +#if AUDIO_EFFECTS_AFC_AT_RAM + *(.howlings_phf_code) + *(.howlings_phf_const) + /*AFC_Lib_陷波*/ + *(.notchhowling_code) + *(.notchhowling_const) + *(.notchhowling_sparse_code) + *(.notchhowling_sparse_const) +#endif/*AUDIO_EFFECTS_AFC_AT_RAM*/ + +#if AUDIO_EFFECTS_DRC_AT_RAM + *(.audio_drc_code) + *(.audio_drc_const) + *(.drc_const) + *(.drc_code) +#endif/*AUDIO_EFFECTS_DRC_AT_RAM*/ + +#if AUDIO_EFFECTS_EQ_AT_RAM + *(.audio_eq_code) + *(.audio_eq_const) +#endif/*AUDIO_EFFECTS_EQ_AT_RAM*/ + +#if AUDIO_EFFECTS_NOISEGATE_AT_RAM + *(.audio_noisegate_code) + *(.audio_noisegate_const) + /*Lib_NoiseGate*/ + *(.noisegate_code) + *(.noisegate_const) + *(.noisegate_sparse_code) + *(.noisegate_sparse_const) +#endif/*AUDIO_EFFECTS_NOISEGATE_AT_RAM*/ + +#if AUDIO_EFFECTS_MIC_EFFECT_AT_RAM + *(.audio_mic_effect_const) + *(.audio_mic_effect_code) +#endif/*AUDIO_EFFECTS_MIC_EFFECT_AT_RAM*/ + +#if AUDIO_EFFECTS_MIC_STREAM_AT_RAM + *(.audio_mic_stream_const) + *(.audio_mic_stream_code) +#endif/*AUDIO_EFFECTS_MIC_STREAM_AT_RAM*/ + +#if AUDIO_EFFECTS_DEBUG_AT_RAM + *(.audio_effect_adj_const) + *(.audio_effect_adj_code) +#endif/*AUDIO_EFFECTS_DEBUG_AT_RAM*/ + + AudioEffects_data_code_end = .; + AudioEffects_data_code_size = AudioEffects_data_code_end - AudioEffects_data_code_begin; + media_data_code_end = .; diff --git a/include_lib/media/media_develop/media/cpu/br23/media_lib_text.ld b/include_lib/media/media_develop/media/cpu/br23/media_lib_text.ld new file mode 100644 index 0000000..7227077 --- /dev/null +++ b/include_lib/media/media_develop/media/cpu/br23/media_lib_text.ld @@ -0,0 +1,535 @@ + + media_text_start = .; + + . = ALIGN(4); + *(.dns_16k_data) + *(.dns_8k_data) + *(.jlsp_const) + *(.jlsp_code) + + *(.aec_code) + *(.aec_const) + *(.der_code) + *(.der_const) + *(.nlp_code) + *(.nlp_const) + *(.qmf_code) + *(.qmf_const) + *(.bt_audioplc_sparse_code) + *(.bt_audioplc_code) + *(.bt_audioplc_const) + + . = ALIGN(4); + *(.res_code) + *(.res_const) + + . = ALIGN(4); + *(.ns_code) + *(.ns_const) + *(.opcore_maskrom) + *(.bark_const) + + . = ALIGN(4); +#if (!TCFG_CODE_RUN_RAM_FM_MODE) + *(.pcm_code) + *(.pcm_const) +#endif /*(!TCFG_CODE_RUN_RAM_FM_MODE)*/ + /* *(.cvsd_code) */ + /* *(.cvsd_const) */ + *(.g729_code) + *(.g729_const) + *(.g726_code) + *(.g726_const) + + *(.wtg_dec_code) + *(.wtg_dec_const) + *(.wtg_dec_sparse_code) + *(.wtg_dec_sparse_const) + *(.wtgv2_code) + *(.wtgv2_const) + *(.wtgv2dec_code) + *(.wtgv2dec_const) + *(.wtgv2dec_str) + *(.wtg_decv2_sparse_code) + *(.bfilt_code) + . = ALIGN(4); +#ifndef CONFIG_MP3_WMA_LIB_SPECIAL + *(.mp3_decstream_const) + *(.mp3_decstream_code) + *(.mp3_decstream_sparse_code) + *(.mp3_decstream_sparse_const) + + *(.mp3_dec_sparse_code) + *(.mp3_dec_sparse_const) + + *(.mp3_dec_code) + *(.mp3_dec_const) + /* *(.mp3_dec_data) */ + /* *(.mp3_dec_bss) */ + + /* *(.mp3_bss) */ + /* *(.mp3_data) */ + *(.mp3_const) + +#if SOUNDCARD_ENABLE +#else + *(.mp3_code) +#endif +#endif + + *(.msbc_code) + *(.msbc_const) + *(.mty_code) + *(.mty_const) + *(.mp3tsy_dec_code) + *(.mp3tsy_dec_const) + *(.mp3tsy_dec_sparse_code) + *(.mp3tsy_dec_sparse_const) + *(.sbc_code) + *(.sbc_const) + *(.sine_code) + *(.sine_const) + /* *(.wav_code) */ + /* *(.wav_const) */ + +#ifndef CONFIG_MP3_WMA_LIB_SPECIAL + *(.wma_code) + *(.wma_const) + *(.wma_dec_code) + *(.wma_dec_const) +#endif + *(.wma_dec_sparse_code) + *(.wma_dec_sparse_const) + *(.wma_decstream_const) + *(.wma_decstream_code) + *(.wma_decstream_sparse_code) + *(.wma_decstream_sparse_const) + /* *(.aac_code) */ + /* *(.aac_const) */ + *(.amr_code) + *(.amr_const) + *(.midi_code) + *(.midi_const) + + /* *(.ape_code) */ + /* *(.ape_const) */ + *(.audio_decoder_code) + *(.audio_decoder_const) + /* *(.cvsd_code) */ + /* *(.cvsd_const) */ + /* *(.dts_code) */ + /* *(.dts_const) */ + /* *(.flac_code) */ + /* *(.flac_const) */ + /* *(.m4a_code) */ + /* *(.m4a_const) */ + *(.mp3_encode_code) + *(.mp3_encode_const) + *(.media_device_code) + *(.media_device_const) + *(.audio_encoder_code) + *(.audio_encoder_const) + *(.mixer_code) + *(.mixer_const) + *(.stream_code) + *(.stream_const) + *(.dec_server_code) + *(.dec_server_const) + *(.rec_server_code) + *(.rec_server_const) + *(.auto_mute_code) + *(.auto_mute_const) + *(.plc_code) + *(.plc_const) + *(.wireless_sync_code) + *(.wireless_sync_const) + *(.fft_code) + *(.fft_const) + + + *(.mp3_enc_code) + *(.mp3_enc_const) + *(.mp3_enc_sparse_code) + *(.mp3_enc_sparse_const) + . = ALIGN(4); + *(.mp2_encode_code) + *(.mp2_encode_const) + *(.mp2_encode_sparse_code) + *(.mp2_encode_sparse_const) + . = ALIGN(4); + *(.adpcm_encode_code) + *(.adpcm_encode_const) + *(.adpcm_encode_sparse_code) + *(.adpcm_encode_sparse_const) + . = ALIGN(4); + + + *(.m4a_dec_sparse_code) + *(.m4a_dec_sparse_const) + + *(.aac_dec_sparse_code) + *(.aac_dec_sparse_const) + *(.bt_aac_dec_core_const) + + *(.amr_dec_const) + + + *(.dts_dec_ff_const) + *(.dts_dec_sparse_code) + *(.dts_dec_sparse_const) + + *(.res_sparse_code) + *(.ns_sparse_code ) + *(.aec_sparse_code) + *(.nlp_sparse_code) + *(.der_sparse_code) + *(.qmf_sparse_code) + + *(.sms_const); + *(.sms_sparse_code); + *(.sms_code); + + + *(.resample_cal_code) + *(.resample_cal_sparse_code) + *(.resample_cal_const) + + *(.bt_compressor_sparse_const) + *(.bt_compressor_sparse_code) + *(.compressor_sparse_code) + *(.compressor_sparse_const) + + *(.bt_limiter_sparse_const) + *(.bt_limiter_sparse_code) + *(.limiter_sparse_code) + *(.limiter_sparse_const) + + *(.bt_crossOver_sparse_const) + *(.bt_crossOver_sparse_code) + *(.crossOver_sparse_code) + *(.crossOver_sparse_const) + + *(.iap_code) + *(.iap_const) + *(.audio_bfilt_code) + *(.audio_bfilt_const) + *(.audio_buf_sync_code) + *(.audio_buf_sync_const) + *(.audio_dec_app_code) + *(.audio_dec_app_const) + *(.audio_dec_app_sync_code) + *(.audio_dec_app_sync_const) + *(.audio_dec_app_event_callback) + *(.audio_dec_app_dec_run) + *(.audio_dec_app_normal_run) + *(.audio_dec_tone_event_callback) + *(.audio_dig_vol_code) + *(.audio_dig_vol_const) + *(.audio_echo_reverb_code) + *(.audio_echo_reverb_const) + *(.echo_cal_code) + *(.echo_cal_const) +#if (AUDIO_EFFECTS_REVERB_AT_RAM == 0) + *(.platereverb_code) + *(.platereverb_const) +#endif/*AUDIO_EFFECTS_REVERB_AT_RAM*/ + *(.reverb0_code) + *(.reverb0_const) + *(.reverb_cal_sparse_code) + *(.audio_echo_src_code) + *(.audio_echo_src_const) + *(.audio_energy_detect_code) + *(.audio_energy_detect_const) +#if (AUDIO_EFFECTS_EQ_AT_RAM == 0) + *(.audio_eq_code) + *(.audio_eq_const) +#endif/*AUDIO_EFFECTS_EQ_AT_RAM*/ +#if (AUDIO_EFFECTS_DRC_AT_RAM == 0) + *(.audio_drc_code) + *(.audio_drc_const) + *(.drc_const) + *(.drc_code) +#endif/*AUDIO_EFFECTS_DRC_AT_RAM*/ + *(.audio_eq_drc_apply_code) + *(.audio_eq_drc_apply_const) + *(.audio_equalloudness_code) + *(.audio_equalloudness_const) + *(.audio_howling_code) + *(.audio_howling_const) + *(.howlings_phf_sparse_code) +#if (AUDIO_EFFECTS_AFC_AT_RAM == 0) + *(.howlings_phf_code) + *(.howlings_phf_const) + /*AFC_Lib_陷波*/ + *(.notchhowling_code) + *(.notchhowling_const) + *(.notchhowling_sparse_code) + *(.notchhowling_sparse_const) +#endif/*AUDIO_EFFECTS_AFC_AT_RAM*/ + +#if (AUDIO_EFFECTS_NOISEGATE_AT_RAM == 0) + *(.audio_noisegate_code) + *(.audio_noisegate_const) + /*Lib_NoiseGate*/ + *(.noisegate_code) + *(.noisegate_const) + *(.noisegate_sparse_code) + *(.noisegate_sparse_const) +#endif/*AUDIO_EFFECTS_NOISEGATE_AT_RAM*/ + + *(.audio_output_dac_code) + *(.audio_output_dac_const) + *(.audio_pemafrow_code) + *(.audio_pemafrow_const) + *(.audio_pitch_code) + *(.audio_pitch_const) + *(.audio_pitchspeed_code) + *(.audio_pitchspeed_const) + *(.audio_surround_code) + *(.audio_surround_const) + *(.audio_vbass_code) + *(.audio_vbass_const) + *(.audio_vocal_remove_code) + *(.audio_vocal_remove_const) + *(.audio_vocal_tract_synthesis_code) + *(.audio_vocal_tract_synthesis_const) + *(.eq_config_code) + *(.eq_config_const) + *(.eq_config_protocol_code) + *(.eq_config_protocol_const) + *(.spectrum_eq_code) + *(.spectrum_eq_const) + *(.spectrum_fft_code) + *(.spectrum_fft_const) + *(.audio_localtws_code) + *(.audio_localtws_const) + *(.audio_dec_localtws_code) + *(.audio_dec_localtws_const) + *(.audio_dec_a2dp_code) + *(.audio_dec_a2dp_const) + *(.audio_dec_esco_code) + *(.audio_dec_esco_const) + *(.audio_dec_file_code) + *(.audio_dec_file_const) +#if (!TCFG_CODE_RUN_RAM_FM_MODE) + *(.audio_dec_pcm_code) + *(.audio_dec_pcm_const) +#endif /*(!TCFG_CODE_RUN_RAM_FM_MODE)*/ + *(.audio_resample_code) + *(.audio_resample_const) + *(.audio_splicing_code) + *(.audio_splicing_const) + *(.channel_switch_code) + *(.channel_switch_const) + *(.sw_drc_code) + *(.sw_drc_const) + *(.aptx_decoder_code) + *(.aptx_decoder_const) + *(.ldac_decoder_code) + *(.ldac_decoder_const) + *(.speex_encoder_code) + *(.speex_encoder_const) + *(.sbc_encoder_code) + *(.sbc_encoder_const) + *(.opus_encoder_code) + *(.opus_encoder_const) + *(.prevent_task_fill_code) + *(.prevent_task_fill_const) + *(.audio_cfifo_code) + *(.audio_cfifo_const) +#if (!TCFG_CODE_RUN_RAM_FM_MODE) + *(.audio_track_code) + *(.audio_track_const) +#endif /*(!TCFG_CODE_RUN_RAM_FM_MODE)*/ + *(.audio_adc_code) + *(.audio_adc_const) + *(.audio_dac_code) + *(.audio_dac_const) + *(.audio_linein_code) + *(.audio_linein_const) + *(.audio_link_code) + *(.audio_link_const) + *(.audio_sample_sync_code) + *(.audio_sample_sync_const) + *(.audio_wireless_sync_code) + *(.audio_wireless_sync_const) + *(.audio_spdif_code) + *(.audio_spdif_const) + *(.audio_src_code) + *(.audio_src_const) + *(.audio_src_base_code) + *(.audio_src_base_const) + *(.effectrs_sync_code) + *(.effectrs_sync_const) + *(.eq_design_code) + *(.eq_design_const) + *(.hw_eq_code) + *(.hw_eq_const) + *(.iic_code) + *(.iic_const) + *(.mic_cap_code) + *(.mic_cap_const) + *(.sbc_hwaccel_code) + *(.sbc_hwaccel_const) + + . = ALIGN(4); + _audio_decoder_begin = .; + PROVIDE(audio_decoder_begin = .); + KEEP(*(.audio_decoder)) + _audio_decoder_end = .; + PROVIDE(audio_decoder_end = .); + + _audio_encoder_begin = .; + PROVIDE(audio_encoder_begin = .); + KEEP(*(.audio_encoder)) + _audio_encoder_end = .; + PROVIDE(audio_encoder_end = .); + + _audio_package_begin = .; + PROVIDE(audio_package_begin = .); + KEEP(*(.audio_package)) + _audio_package_end = .; + PROVIDE(audio_package_end = .); + + _audio_dev_begin = .; + PROVIDE(audio_dev_begin = .); + KEEP(*(.audio_device)) + _audio_dev_end = .; + PROVIDE(audio_dev_end = .); + + _audio_hwaccel_begin = .; + PROVIDE(audio_hwaccel_begin = .); + KEEP(*(.audio_hwaccel)) + _audio_hwaccel_end = .; + PROVIDE(audio_hwaccel_end = .); + + . = ALIGN(4); + media_code_begin = .; + *(.media.*.text) + + . = ALIGN(4); + *(.crossOver_code) + *(.crossOver_const) + *(.bt_crossOver_const) + *(.bt_crossOver_code) + . = ALIGN(4); + + *(.compressor_code) + *(.compressor_const) + *(.bt_compressor_const) + *(.bt_compressor_code) + . = ALIGN(4); + + *(.limiter_code) + *(.limiter_const) + *(.bt_limiter_const) + *(.bt_limiter_code) + *(.drc_sparse_code) + *(.drc_sparse_const) + . = ALIGN(4); + *(.lib_pitchshift_code) + *(.lib_pitchshift_const) + . = ALIGN(4); + *(.sur_cal_const) + *(.sur_cal_code) + . = ALIGN(4); + *(.reverb_cal_sparse_code) +#if (SOUNDCARD_ENABLE == 0) + . = ALIGN(4); + *(.dvol_ram_code) + . = ALIGN(4); + *(.reverb_cal_const) + . = ALIGN(4); + *(.reverb_cal_code) + . = ALIGN(4); + + /* 把下面的段放入ram中,能加速数据流处理 */ +#if (!TCFG_CODE_RUN_RAM_FM_MODE) + *(.stream_code_nor_run) // 数据流普通输出处理 + *(.mixer_code_nor_run) // mixer数据流直通输出 +#endif /*(!TCFG_CODE_RUN_RAM_FM_MODE)*/ + *(.stream_code_copy_run) // 数据流分支输出处理 + *(.mixer_code_out_run) // mixer数据流叠加后输出 +#endif + +#if (!TCFG_CODE_RUN_RAM_FM_MODE) + *(.audio_codec_code) // 解码任务流程 + *(.audio_codec_code_read_file) // 解码读文件 + *(.audio_src_code_nor_run) // audio_src运行处理 + *(.src_base_code_nor_run) // src_base运行处理 + *(.audio_dac_code_nor_run) // audio_dac普通输出运行处理 + *(.audio_cfifo_code_nor_run) // audio_cfifo普通运行处理 +#endif /*(!TCFG_CODE_RUN_RAM_FM_MODE)*/ + + *(.audio_codec_code_frame_file) // 解码读流数据 + + *(.buf_sync_code_nor_run) // buf_sync采样率实时调整处理 + + *(.resample_fastcal_const) + *(.resample_fastcal_code) + *(.resample_fastcal_sparse_code) + + *(.dynamic_eq_code) + *(.dynamic_eq_const) + *(.dynamic_eq_detect_code) + *(.dynamic_eq_detect_const) + + *(.dynamic_eq_sparse_code) + *(.dynamic_eq_sparse_const) + *(.dynamic_eq_detect_sparse_code) + *(.dynamic_eq_detect_sparse_const) + +#if (AUDIO_EFFECTS_MIC_EFFECT_AT_RAM == 0) + *(.audio_mic_effect_const) + *(.audio_mic_effect_code) +#endif/*AUDIO_EFFECTS_MIC_EFFECT_AT_RAM*/ +#if (AUDIO_EFFECTS_MIC_STREAM_AT_RAM == 0) + *(.audio_mic_stream_const) + *(.audio_mic_stream_code) +#endif/*AUDIO_EFFECTS_MIC_STREAM_AT_RAM*/ +#if (AUDIO_EFFECTS_DEBUG_AT_RAM == 0) + *(.audio_effect_adj_const) + *(.audio_effect_adj_code) +#endif/*AUDIO_EFFECTS_DEBUG_AT_RAM*/ + + *(.pitchshifter_code) + *(.pitchshifter_const) + *(.pitchshifter_sparse_code) + + *(.vbss_code) + *(.vbss_sparse_code) + *(.vbss_sparse_const) + + *(.wav_dec_sparse_code) + *(.wav_dec_sparse_const) + *(.wav_dec_code) + *(.wav_dec_const) + *(.wav_dec_data) + *(.wav_data) + *(.wav_const) + *(.wav_code) + + *(.flac_dec_sparse_code) + *(.flac_dec_sparse_const) + *(.flac_dec_code) + *(.flac_dec_const) + *(.flac_dec_data) + *(.flac_data) + *(.flac_const) + *(.flac_code) + + . = ALIGN(4); + + media_code_end = .; + . = ALIGN(4); + media_code_size = media_code_end - media_code_begin; + + . = ALIGN(4); + media_text_end = .; + + media_code_total_size = media_text_end - media_text_start; + + + + + diff --git a/include_lib/media/media_develop/media/effectrs_sync.h b/include_lib/media/media_develop/media/effectrs_sync.h new file mode 100644 index 0000000..77a0011 --- /dev/null +++ b/include_lib/media/media_develop/media/effectrs_sync.h @@ -0,0 +1,239 @@ +#ifndef EFFECTRS_SYNC_H +#define EFFECTRS_SYNC_H + +#include "generic/typedef.h" +#include "generic/list.h" + +#define WL_PROTOCOL_RTP 0 +#define WL_PROTOCOL_SCO 1 +#define WL_PROTOCOL_FILE 2 + +#define SYNC_ERR_NONE 0 +#define SYNC_ERR_PLAY_REJECTED 1 +#define SYNC_ERR_PAUSE 2 +#define SYNC_ERR_DISCARD_PKT 3 +#define SYNC_ERR_PLAY_PREPARE 4 +#define SYNC_ERR_NULL_PKT 5 +#define SYNC_ERR_GRAB_AUDIO_STREAM 6 +#define SYNC_ERR_DEC_RESET 7 +enum { + SYNC_DAC_CTL = 1, + SYNC_GET_PCM_TOTAL, + SYNC_GET_SRC_IN_LEN, + SYNC_GET_SRC_STATE, + SYNC_SET_PLAY_O_POINT, + SYNC_WITE_DAC_MUTE_DATE, + SET_LOCAL_US_TIME, + SET_SYNC_RESET, + SYNC_SWITCH_N_CH, +}; +struct audio_packet_buffer { + u8 noblock; + u8 state; + u16 timeout; + u32 slot_time; + u32 len; + u32 baddr; +}; +struct audio_packet_stats { + u32 total_size; + u32 data_size; + u32 remain_size; + u8 ch; + u8 grab_audio_stream_info_num; +}; +typedef struct _SYNC_POINTER_ { + volatile int *src_in_len; + volatile int *set_sr_in; + volatile int *set_sr_out; + volatile int *more_less_points; + + volatile int *play_point; + volatile int *fake_n_points; +} CPUSYNC_POINTERS; + +/* + * 播放动态src配置,start为配置一次变点 + */ +struct audio_pcm_src { + u8 convert; //启动转换 + u8 resample;//设置为变采样 + u16 ratio_i; //转换输入 + u16 ratio_o; //转换输出 +}; + +/* + * 同步需要的DAC协定启动配置 + */ +struct audio_dac_ctl { + u8 agreement; // + u8 on; //启动/暂停 + // u8 time_unit; //时间单位(0 - us, 1 - ms, 2 - s) + u32 pre_time; + u32 time; //时间点(us) +}; +// *INDENT-OFF* +struct sync_ops_t { + void *(*open)(void); + void (*set_handler)(void *, void *priv, + void (*handler)(void *, int *, int)); + u32 (*time)(u8 type, u32 time,u32 *pre_time); + int (*send)(void *, void *buf, u32 len); + int (*master)(u8 type); + u8 (*online)(u8); + void (*role_lock)(void *, u8); + void (*close)(void *); + void *(*audio_sync_open)(void *empty_priv,void (*empty_handler)(void *, u8),u8 protocol,u16 ch,u16 sr,int (*sync_output)(void *priv, void *data, int len),void*); + int (*audio_sync_close)(void *sync); + int (*audio_sync_run)(void *_sync,void *buf, int points_per_channel); + int (*audio_sync_set_samplerate)(void *sync,int sr_in,int sr_out); + int (*audio_sync_control)(void* _priv,int cmd,u32 arg); +}; + +struct audio_sync_parm { + u8 channel; + u8 top_percent; //上限比例 + u8 start_percent; //启动比例限值 + u8 bottom_percent; //下限比例 + u8 protocol; //音频包含协议 + u32 buffer_size; + u8 sync_time; + const struct sync_ops_t *ops; + void *audio_dev; + int (*sync_output)(void *priv, void *data, int len); +}; +// *INDENT-ON* + +extern void *audio_decoder_sync_open(struct audio_decoder *dec, struct audio_sync_parm *sync_parm); +extern void audio_decoder_sync_close(void *c); +extern int audio_decodr_sync_start(void *c, struct audio_packet_stats *stats, struct audio_packet_buffer *pkt); +extern int audio_decoder_sync_run(void *c, void *buf, int len); +extern int audio_decoder_sync_do(void *c, s16 *buf, int len); +extern int audio_sync_reset(void *c); +int audio_sync_set_remain_len(void *c, int len); + +#if (defined CONFIG_CPU_BR26 || \ + defined CONFIG_CPU_BR23 || \ + defined CONFIG_CPU_BR25 || \ + defined CONFIG_CPU_BR30 || \ + defined CONFIG_CPU_BR34 || \ + defined CONFIG_CPU_BR28) +/* + * BR26同步 + */ +#define SYNC_ERR_NONE 0 +#define SYNC_ERR_DEC_NOT_ALLOWED 1 +#define SYNC_ERR_TIMEOUT 2 +#define SYNC_ERR_STREAM_PASS 3 +#define SYNC_ERR_STREAM_END 4 +#define SYNC_ERR_PREPARE 5 +#define SYNC_ERR_ALIGNED_AND_PASS 6 +#define SYNC_ERR_STREAM_RESET 7 + +/***************** the step mean to get more or less (sample_rate/step) points/sencond ********************/ +#define SRC_DEC_STEP 2 //step to speed down +#define SRC_INC_STEP 2 // step to speed up + +#define SRC_POINT_AMPLIPY 5 + +#define AUDIO_SYNC_TARGET_DAC 0 +#define AUDIO_SYNC_TARGET_FM 1 +#define AUDIO_SYNC_TARGET_IIS 2 + +#define RX_DELAY_NULL 0 //延时未抖动 +#define RX_DELAY_UP 1 //延时上浮 +#define RX_DELAY_DOWN 2 //延时下浮 + +struct rt_stream_info { + u8 noblock; + u8 rx_delay; + u16 seqn; + u16 frame_num; + u32 data_len; + u32 remain_len; + void *baddr; + int len; +}; + +struct remote_stream_info { + u8 rx_delay; //音频接收数据流延时波动 + u16 seqn; //音频数据包号信息 + u32 remain_len; //蓝牙接收buffer剩余空间 +}; + +// *INDENT-OFF* +struct audio_tws_conn_ops { + void *(*open)(void); + void (*set_handler)(void *, void *priv, + void (*handler)(void *, int *, int)); + u32 (*time)(u8 type, u32 time, u32 *pre_time); + int (*send)(void *, void *buf, u32 len); + int (*master)(u8 type); + u8 (*online)(u8); + void (*close)(void *); +}; + +struct audio_wireless_sync_info { + u8 channel; + u8 target; //本地目标设备 + u8 protocol; //音频同步协议类型 + u8 reset_enable; //内部检测异常后返回复位信息的使能 + u16 sample_rate; //解码采样率 + u16 output_rate; //输出采样率 + void *dev; + void *sample_ch; //同步采样通道 + const struct audio_tws_conn_ops *tws_ops; //TWS相关的调用接口 +}; +// *INDENT-ON* + +struct audio_wireless_sync { + struct audio_stream_entry *entry; + struct audio_stream_entry *resample_entry; + void *context; + void *sample_sync; +}; + +void *audio_wireless_sync_open(struct audio_wireless_sync_info *info, struct audio_stream_entry **entry); + +int audio_wireless_sync_add_output(void *c, struct audio_wireless_sync_info *info); + +int audio_wireless_sync_add_dev(void *c, struct audio_wireless_sync_info *info); + +int audio_wireless_sync_probe(void *c, struct rt_stream_info *info); + +void audio_wireless_sync_info_init(void *c, u32 sample_rate, u32 output_rate, u8 channel); + +int audio_sync_set_tws_together(void *c, u8 together, u32 together_time); + +int audio_wireless_sync_after_dec(void *c, s16 *data, int len); + +int audio_wireless_sync_get_rate(void *c, u16 *input_rate, u16 *output_rate); + +int audio_wireless_sync_stop(void *c); + +int audio_wireless_sync_reset(void *c); + +int audio_wireless_sync_suspend(void *c); + +void audio_wireless_sync_close(void *c); + +int audio_wireless_sync_add_output(void *c, struct audio_wireless_sync_info *info); + +int audio_wireless_sync_with_stream(void *c, struct remote_stream_info *info); + +int audio_wireless_sync_drop_samples(void *c, int samples); + +int audio_wireless_sync_set_tws_time(void *c, int time); + +int audio_wireless_sync_is_working(void *c); + +int audio_wireless_sync_sound_reset(void *c, int time); + +int audio_wireless_sync_sound_fade_in(void *c, u16 time); +#endif +/* +#if (defined CONFIG_CPU_BR26 || \ + (defined CONFIG_CPU_BR23 || \ + defined CONFIG_CPU_BR25) +*/ +#endif diff --git a/include_lib/media/media_develop/media/equalloudness/loudness_api.h b/include_lib/media/media_develop/media/equalloudness/loudness_api.h new file mode 100644 index 0000000..838d533 --- /dev/null +++ b/include_lib/media/media_develop/media/equalloudness/loudness_api.h @@ -0,0 +1,7 @@ +#ifndef EQUAL_LOUDNESS_API_H +#define EQUAL_LOUDNESS_API_H +int getEqualLoudnessBuf(); +void EqualLoudnessInit(void *workBuf, float alpha, int sampleRate, int channel); +int EqulLoudnessRun(void *workBuf, short *in, short *out, int len); +#endif // !EQUAL_LOUDNESS_API_H + diff --git a/include_lib/media/media_develop/media/esco_decoder.h b/include_lib/media/media_develop/media/esco_decoder.h new file mode 100644 index 0000000..42679a8 --- /dev/null +++ b/include_lib/media/media_develop/media/esco_decoder.h @@ -0,0 +1,44 @@ +#ifndef ESCO_DECODER_H +#define ESCO_DECODER_H + + +#include "media/includes.h" + + +struct esco_decoder { + u32 coding_type; // 解码类型 + u16 sample_rate; // 解码采样率 + u16 start : 1; // 解码开始 + u16 enc_start : 1; // 采mic上行开始 + u8 ch_num; // 解码声道数 + u8 out_ch_num; // 解码输出声道数 + u8 offset; // 帧数据偏移 + u8 data_len; // 帧数据长度 + u8 frame_len; // 帧数据解析总长 + u8 esco_len; // 帧数据包长 + u8 frame_get; // 帧数据获取到 + u8 sync_step; + u8 join_tws; + u8 preempt_state; + volatile u8 wait_resume; + u16 resume_tmr_id; + u8 *frame; // 帧数据 + u32 hash; // 帧数据标签 + int data[15]; // 帧数据缓存 /*ALIGNED(4)*/ + struct audio_decoder decoder; // 解码器 + struct audio_decoder_task *decode_task; // 解码任务 + void *sync; +}; + +// 打开esco解码 +int esco_decoder_open(struct esco_decoder *, struct audio_decoder_task *decode_task); +// 关闭esco解码 +void esco_decoder_close(struct esco_decoder *dec); +// esco解码输出(如果输出是双声道,会有声道转换) +int esco_decoder_output_handler(struct esco_decoder *dec, struct audio_data_frame *in); + +void esco_decoder_stream_sync_enable(struct esco_decoder *dec, void *sync, int sample_rate, int delay_time); + +void esco_decoder_join_tws(struct esco_decoder *dec); +#endif /*ESCO_DECODER_H*/ + diff --git a/include_lib/media/media_develop/media/file_decoder.h b/include_lib/media/media_develop/media/file_decoder.h new file mode 100644 index 0000000..a15f4b9 --- /dev/null +++ b/include_lib/media/media_develop/media/file_decoder.h @@ -0,0 +1,63 @@ +#ifndef FILE_DECODER_H +#define FILE_DECODER_H + + +#include "media/includes.h" + +enum { + FILE_DEC_STATUS_STOP = 0, // 解码停止 + FILE_DEC_STATUS_PLAY, // 正在解码 + FILE_DEC_STATUS_PAUSE, // 解码暂停 + FILE_DEC_STATUS_WAIT_PAUSE, + FILE_DEC_STATUS_WAIT_PLAY, + FILE_DEC_STATUS_PAUSE_SUCCESS, +}; + + +struct file_decoder { + u32 ch_num : 4; // 声道数 + u32 output_ch_num : 4; // 输出声道数 + u32 output_ch_type : 4; // 输出声道类型 + u32 status : 3; // 解码状态 + u32 dec_no_out_sound : 1; // 解码不直接输出声音(用于TWS转发) + u32 tmp_pause : 1; // 被其他解码打断,临时暂停 + u32 wait_pause : 8; + u32 dec_total_time; // 总共能播放多长时间 + u32 dec_cur_time; // 当前播放时间 + u32 once_out_cnt; // 解码一次的输出统计 + u16 resume_tmr_id; + u16 sample_rate; + enum audio_channel ch_type; // 输出类型 + struct audio_decoder decoder; // 解码句柄 + int remain_len; + s16 fade_step; + s16 fade_value; +}; + +int file_decoder_open(struct file_decoder *dec, + const struct audio_dec_input *input, + struct audio_decoder_task *decode_task, + struct audio_dec_breakpoint *bp, + u8 pick); + +void file_decoder_close(struct file_decoder *dec); + +void file_decoder_set_output_channel(struct file_decoder *dec); + +void file_decoder_set_event_handler(struct file_decoder *dec, + void (*handler)(struct audio_decoder *, int, int *), u32 maigc); + +bool file_decoder_is_stop(struct file_decoder *file_dec); +bool file_decoder_is_play(struct file_decoder *file_dec); +bool file_decoder_is_pause(struct file_decoder *file_dec); +int file_decoder_pp(struct file_decoder *file_dec); +int file_decoder_FF(struct file_decoder *file_dec, int step); +int file_decoder_FR(struct file_decoder *file_dec, int step); +int file_decoder_get_breakpoint(struct file_decoder *file_dec, struct audio_dec_breakpoint *bp); +int file_decoder_get_total_time(struct file_decoder *file_dec); +int file_decoder_get_cur_time(struct file_decoder *file_dec); +int file_decoder_get_cur_ms_time(struct file_decoder *file_dec); +int file_decoder_get_decoder_type(struct file_decoder *file_dec); + +#endif /*FILE_DECODER_H*/ + diff --git a/include_lib/media/media_develop/media/includes.h b/include_lib/media/media_develop/media/includes.h new file mode 100644 index 0000000..d196a6d --- /dev/null +++ b/include_lib/media/media_develop/media/includes.h @@ -0,0 +1,37 @@ +/***************************************************************** +>file name : include_lib/media/includes.h +>author : lichao +>create time : Mon 26 Nov 2018 07:47:14 PM CST +*****************************************************************/ +#ifndef __MEDIA_INCLUDES_H__ +#define __MEDIA_INCLUDES_H__ + +#ifdef CONFIG_AUDIO_ONCHIP + +#include "media/audio_decoder.h" +#include "media/audio_encoder.h" +#include "media/mixer.h" +#include "media/automute.h" +#include "effectrs_sync.h" +#include "audio_resample.h" + +#include "asm/cpu_includes.h" +/* +#include "asm/dac.h" +#include "asm/audio_adc.h" +#if (defined CONFIG_CPU_BR26 || \ + defined CONFIG_CPU_BR23 || \ + defined CONFIG_CPU_BR21 || \ + defined CONFIG_CPU_BR25 || \ + defined CONFIG_CPU_BR30) +#include "asm/audio_src.h" +#endif +*/ + +#if defined CONFIG_CPU_BR23 || \ + defined CONFIG_CPU_BR25 +#include "asm/audio_spdif.h" +#endif + +#endif/*CONFIG_AUDIO_ONCHIP*/ +#endif diff --git a/include_lib/media/media_develop/media/midi_ctrl_decoder.h b/include_lib/media/media_develop/media/midi_ctrl_decoder.h new file mode 100644 index 0000000..1692c09 --- /dev/null +++ b/include_lib/media/media_develop/media/midi_ctrl_decoder.h @@ -0,0 +1,61 @@ +#ifndef __MIDI_CTRL_DECODER_H__ +#define __MIDI_CTRL_DECODER_H__ + + +#include "media/includes.h" +#include "media/MIDI_CTRL_API.h" + +typedef struct _midi_ctrl_open_parm { + MIDI_CONFIG_PARM cfg_parm; //初始化参数 + MIDI_CTRL_PARM ctrl_parm; + u32 sample_rate; +} midi_ctrl_open_parm; + +struct set_prog_parm { + u8 prog; //乐器号 + u8 trk_num; //音轨 (0~15) +}; + +struct note_on_parm { + u8 nkey; //按键序号(0~127) + u8 nvel; //按键力度(0~127) + u8 chn; //通道(0~15) +}; + +struct note_off_parm { + u8 nkey; //按键序号(0~127) + u8 chn; //通道(0~15) +}; + +struct pitch_bend_parm { + u16 pitch_val; //弯音轮值,1 - 65535 ;256是正常值,对音高有作用 + u8 chn; //通道(0~15) +}; + +enum { +///midi 模块接口内部相关消息 + MIDI_CTRL_NOTE_ON = 0xf0, + MIDI_CTRL_NOTE_OFF, + MIDI_CTRL_SET_PROG, + MIDI_CTRL_PITCH_BEND, +}; + +struct midi_ctrl_decoder { + u16 ch_num : 4; // 声道数 + u16 output_ch_num : 4; // 输出声道数 + u16 output_ch_type : 4; // 输出声道类型 + u16 status; + u16 sample_rate; // 采样率 + struct audio_decoder decoder; // 解码句柄 +}; + +// 打开midi_ctrl解码 +int midi_ctrl_decoder_open(struct midi_ctrl_decoder *, struct audio_decoder_task *decode_task); +// 关闭midi_ctrl解码 +void midi_ctrl_decoder_close(struct midi_ctrl_decoder *dec); +// 设置midi_ctrl解码事件回调接口 +void midi_ctrl_decoder_set_event_handler(struct midi_ctrl_decoder *dec, + void (*handler)(struct audio_decoder *, int, int *), u32 maigc); + +#endif /*midi_ctrl_DECODER_H*/ + diff --git a/include_lib/media/media_develop/media/mixer.h b/include_lib/media/media_develop/media/mixer.h new file mode 100644 index 0000000..a9ab292 --- /dev/null +++ b/include_lib/media/media_develop/media/mixer.h @@ -0,0 +1,198 @@ +#ifndef AUDIO_MIXER_H +#define AUDIO_MIXER_H + +#include "generic/typedef.h" +#include "generic/list.h" +#include "media/audio_stream.h" +#include "application/audio_buf_sync.h" + +#ifdef CONFIG_MIXER_CYCLIC + +#include "mixer_cyclic.h" + +#else /*CONFIG_MIXER_CYCLIC*/ + +// mixer事件回调 +enum { + MIXER_EVENT_OPEN, // 打开一个通道 + MIXER_EVENT_CLOSE, // 关闭一个通道 + MIXER_EVENT_SR_CHANGE, // mixer采样率变化 +}; + +// mixer 通道事件回调 +enum { + MIXER_EVENT_CH_OPEN, // 通道打开 + MIXER_EVENT_CH_CLOSE, // 通道关闭 + MIXER_EVENT_CH_RESET, // 通道重新开始 + MIXER_EVENT_CH_LOSE, // 通道丢数 + MIXER_EVENT_CH_OUT_SR_CHANGE, // mixer采样率变化 +}; + +typedef enum { + MIXER_SR_MAX = 0, // 最大采样率 + MIXER_SR_MIN, // 最小采样率 + MIXER_SR_FIRST, // 第一个通道的采样率 + MIXER_SR_LAST, // 最后一个通道的采样率 + MIXER_SR_SPEC, // set指定采样率;get当前mixer采样率 +} MIXER_SR_TYPE; + +struct audio_mixer_ch_sync_info { + int begin_per; // 起始百分比 + int top_per; // 最大百分比 + int bottom_per; // 最小百分比 + u8 inc_step; // 每次调整增加步伐 + u8 dec_step; // 每次调整减少步伐 + u16 max_step; // 最大调整步伐 + void *priv; // get_total,get_size私有句柄 + int (*get_total)(void *priv); // 获取buf总长 + int (*get_size)(void *priv); // 获取buf数据长度 +}; + +struct audio_mixer; + +struct audio_mixer { + struct list_head head; // 链表头 + OS_MUTEX mutex; // 互斥 + s16 *output; // 输出buf + u16 points; // 输出buf总点数 + u16 remain_points; // 输出剩余点数 + u32 process_len; // 输出了多少 + u8 channel_num; // 声道数 + u8 change_sr_limit_ch_num; // mixer活动通道小于该值时会重新检查采样率 + u8 sample_sync : 1;// sample同步标记 + volatile u8 active; // 活动标记。1-正在运行 + u16 lose_to_id; // 超时激活ID + void *remain_ch; // 直接输出没有输出完成的通道 + u32 sample_rate; // 当前mixer的采样率 + int need_sr; // mixer想要变成的采样率 + MIXER_SR_TYPE sr_type; // 采样率设置类型 + void (*evt_handler)(struct audio_mixer *, int); // 事件返回接口 + u32(*check_sr)(struct audio_mixer *, u32 sr); // 检查采样率 + + struct audio_stream *stream; // 音频流 + struct audio_stream_entry entry; // 音频流入口,后级接dac等 + // struct audio_stream_group group; // 用于链接前级 +}; + +struct audio_mixer_ch { + u32 start : 1; // 启动标记。1-已经启动。输出时标记一次 + u32 open : 1; // 打开标记。1-已经打开。输出标记为1,reset标记为0 + u32 pause : 1; // 暂停标记。1-暂停 + u32 no_wait : 1; // 不等待有数 + u32 lose : 1; // 丢数标记 + u32 src_en : 1; // 变采样使能 + u32 src_always : 1; // 不管采样率是否相同都做变采样 + u32 sample_sync : 1;// sample同步标记 + u32 data_sync : 1; // sample同步临时保存 + u32 sync_en : 1; // buf同步使能 + u32 sync_always : 1;// 不管采样率是否相同都做buf同步 + u32 check_sr : 1; // 需要检查采样率 + u32 src_running : 1;// 执行变采样处理 + u32 wait_resume : 1; + u32 follow_resample : 1; + u32 sample_rate; // 当前通道采样率 + u16 offset; // 当前通道在输出buf中的偏移位置 + u16 lose_time; // 超过该时间还没有数据,则以为可以丢数。no_wait置1有效 + unsigned long lose_limit_time; // 丢数超时中间运算变量 + struct list_head list_entry; // 链表 + struct audio_mixer *mixer; // mixer句柄 + struct audio_src_handle *src; // 变采样 + struct audio_buf_sync_hdl sync; // 同步 + struct audio_mixer_ch_sync_info sync_info; // 同步参数 + void *priv; // 事件回调私有句柄 + void (*event_handler)(void *priv, int event, int param); // 事件回调接口 + void *follow_priv; + int (*follow_sample_rate)(void *priv); + + struct audio_stream_entry entry; // 音频流入口,通道后面不应该再接其他的音频流,最后由mixer合并后输出 +}; + + +// 打开一个mixer +int audio_mixer_open(struct audio_mixer *mixer); + +// 关闭mixer +void audio_mixer_close(struct audio_mixer *mixer); + +// 设置事件回调 +void audio_mixer_set_event_handler(struct audio_mixer *mixer, + void (*handler)(struct audio_mixer *, int)); + +// 设置采样率检测回调 +void audio_mixer_set_check_sr_handler(struct audio_mixer *mixer, + u32(*check_sr)(struct audio_mixer *, u32)); + +// 设置输出buf +void audio_mixer_set_output_buf(struct audio_mixer *mixer, s16 *buf, u16 len); + +// 设置声道数 +void audio_mixer_set_channel_num(struct audio_mixer *mixer, u8 channel_num); + +// 设置采样率类型 +void audio_mixer_set_sample_rate(struct audio_mixer *mixer, MIXER_SR_TYPE type, u32 sample_rate); +// 按条件获取采样率(原始采样率,不调用check_sr检测) +int audio_mixer_get_original_sample_rate_by_type(struct audio_mixer *mixer, MIXER_SR_TYPE type); +// 按条件获取采样率(有调用check_sr检测) +int audio_mixer_get_sample_rate_by_type(struct audio_mixer *mixer, MIXER_SR_TYPE type); +// 获取采样率(按mixer->sr_type获取) +int audio_mixer_get_sample_rate(struct audio_mixer *mixer); +// 获取mixer当前正在用的采样率 +int audio_mixer_get_cur_sample_rate(struct audio_mixer *mixer); + +// 获取通道总数 +int audio_mixer_get_ch_num(struct audio_mixer *mixer); + +// 获取非暂停通道总数 +int audio_mixer_get_active_ch_num(struct audio_mixer *mixer); + +// 获取mixer剩余长度 +int audio_mixer_data_len(struct audio_mixer *mixer); + +// mixer传送stop到数据流 +void audio_mixer_output_stop(struct audio_mixer *mixer); + +// mixer数据流激活处理 +void audio_mixer_stream_resume(void *p); + +// 打开一个mixer通道(放在链表结尾处) +int audio_mixer_ch_open(struct audio_mixer_ch *ch, struct audio_mixer *mixer); +// 打开一个mixer通道(放在链表起始处) +int audio_mixer_ch_open_head(struct audio_mixer_ch *ch, struct audio_mixer *mixer); + +// 关闭通道 +void audio_mixer_ch_close(struct audio_mixer_ch *ch); + +// 设置通道事件回调 +void audio_mixer_ch_set_event_handler(struct audio_mixer_ch *ch, void *priv, void (*handler)(void *, int, int)); + +// 设置通道采样率/变采样 +void audio_mixer_ch_set_sample_rate(struct audio_mixer_ch *ch, u32 sample_rate); + +// 设置通道变采样 +void audio_mixer_ch_set_src(struct audio_mixer_ch *ch, u8 src_en, u8 always); + +// 设置通道同步 +void audio_mixer_ch_set_sync(struct audio_mixer_ch *ch, struct audio_mixer_ch_sync_info *info, u8 sync_en, u8 always); + +// 设置通道没数据时不等待(超时直接丢数) +void audio_mixer_ch_set_no_wait(struct audio_mixer_ch *ch, u8 no_wait, u16 time_ms); + +// 通道暂停 +void audio_mixer_ch_pause(struct audio_mixer_ch *ch, u8 pause); + +// 通道重启 +int audio_mixer_ch_reset(struct audio_mixer_ch *ch); + +// 获取通道剩余长度 +int audio_mixer_ch_data_len(struct audio_mixer_ch *ch); + +// 通道数据输出 +int audio_mixer_ch_write(struct audio_mixer_ch *ch, s16 *data, int len); + +void audio_mixer_ch_sample_sync_enable(struct audio_mixer_ch *ch, u8 enable); + +void audio_mixer_ch_follow_resample_enable(struct audio_mixer_ch *ch, void *priv, int (*follow_sample_rate)(void *)); +#endif /*CONFIG_MIXER_CYCLIC*/ + +#endif + diff --git a/include_lib/media/media_develop/media/mixer_cyclic.h b/include_lib/media/media_develop/media/mixer_cyclic.h new file mode 100644 index 0000000..0badd7f --- /dev/null +++ b/include_lib/media/media_develop/media/mixer_cyclic.h @@ -0,0 +1,695 @@ +#ifndef AUDIO_MIXER_CYCLIC_H +#define AUDIO_MIXER_CYCLIC_H + +#include "generic/typedef.h" +#include "generic/list.h" +#include "media/audio_stream.h" +#include "application/audio_buf_sync.h" + +#ifdef CONFIG_MIXER_CYCLIC + +#define MIXER_AUDIO_CASK_EFFECT_EN 1 //短板效应 +#define MIXER_AUDIO_CHANNEL_NUM 4 //最大声道数 +#define MIXER_AUDIO_ENDDING_DCC 0 +#define MIXER_AUDIO_DIRECT_OUT 1 //直通输出 + +// mixer事件回调 +enum { + MIXER_EVENT_OPEN, // 打开一个通道 + MIXER_EVENT_CLOSE, // 关闭一个通道 + MIXER_EVENT_SR_CHANGE, // mixer采样率变化 +}; + +// mixer 通道事件回调 +enum { + MIXER_EVENT_CH_OPEN, // 通道打开 + MIXER_EVENT_CH_CLOSE, // 通道关闭 + MIXER_EVENT_CH_RESET, // 通道重新开始 + MIXER_EVENT_CH_LOSE, // 通道丢数 + MIXER_EVENT_CH_OUT_SR_CHANGE, // mixer采样率变化 +}; + +// mixer采样率确定方式 +typedef enum { + MIXER_SR_MAX = 0, // 链表中的最大采样率 + MIXER_SR_MIN, // 链表中的最小采样率 + MIXER_SR_FIRST, // 链表中的第一个通道的采样率 + MIXER_SR_LAST, // 链表中的最后一个通道的采样率 + MIXER_SR_SPEC, // set指定采样率;get当前mixer采样率 +} MIXER_SR_TYPE; + +/* + * mixer通道跟随缓存数据大小来变化采样率处理的参数 + * 该方法是通过判断缓存数据是否超出规定范围来逐步调节采样率,由于变采样需要一定的时间内 + * 才能把数据量调整到规定之内,此时的变采样可能是超过实际采样率的,所有后续会逐步往回调。 + * 因此可能会出现采样飘来飘去的情况,一种优化处理就是加大buf大小,减小调整步伐等来达到 + * 缓慢变化的效果。 + */ +struct audio_mixer_ch_sync_info { + int begin_per; // 起始百分比,默认60 + int top_per; // 最大百分比,默认80 + int bottom_per; // 最小百分比,默认30 + u8 inc_step; // 每次调整增加步伐,默认5 + u8 dec_step; // 每次调整减少步伐,默认5 + u16 max_step; // 最大调整步伐,默认80 + void *priv; // get_total,get_size私有句柄 + int (*get_total)(void *priv); // 获取buf总长 + int (*get_size)(void *priv); // 获取buf数据长度 +}; + +struct audio_mixer; + +/* + * mixer单独输出任务结构体 + * mixer各通道的数据合并后仅写入buf中,不马上推给后续的数据流,由该任务单独推送 + * config_mixer_task使能时有效 + */ +struct audio_mixer_task { + struct list_head head; // 链表头 + OS_SEM sem; + volatile u8 busy; + volatile u8 start; + const char *task_name; +}; + +/* + * mixer处理 + * 主要用于把各个通道的数据合并成指定采样率、指定声道的数据,然后推送到后续的数据流中 + * 支持自动变采样、自动变换声道、超时自动忽略该通道等 + * 支持长板效应和短板效应:短板效应-等待所有通道有数才能输出; + * 长板效应-只要某个通道有数就输出,不理会其他通道是否有数 + * 支持直通处理:当只有一个有效通道输出且不需要变换声道时,不经过mixer的buf,直接输出到后续的数据流 + */ +struct audio_mixer { + struct list_head head; // 链表头 + OS_MUTEX mutex; // 互斥 + struct audio_mixer_task *task; // mixer处理任务 + struct list_head list_entry; // task链表 + + s16 *output; // 输出buf + u16 points; // 输出buf总点数 + u16 remain_points; // 输出剩余点数 + u16 read_points; // 读地址 + volatile u16 points_len; // 数据长度 + u16 min_points; // 最小输出点数,默认为总buf的1/4 + u16 no_sync_points; // 非sync数据剩余点数 + u32 process_len; // 输出了多少 + volatile u8 output_state; // 输出状态 + u32 aud_ch_mask; // 声道数掩码 + u32 change_sr_limit_ch_num : 4; // mixer活动通道小于该值时会重新检查采样率 + u32 aud_ch_num : 4; // 声道数 + u32 sample_sync : 1;// sample同步标记 + u32 ending_ch_dcc : 1; +#if MIXER_AUDIO_CASK_EFFECT_EN + u32 cask_effect : 1;// 短板效应。默认1,等待所有通道有数才能输出。关闭该功能,只要某个通道有数就输出 + u16 lose_to_id; // 超时激活ID + u16 lose_to_once_ms;// 每次超时计数的时间 +#endif +#if MIXER_AUDIO_DIRECT_OUT + void *remain_ch; // 直接输出没有输出完成的通道 + u8 direct_out; // 直通使能。默认1 + u8 cur_is_direct_out; // 当前为直通输出 +#endif +#if MIXER_AUDIO_ENDDING_DCC + u16 dcc_mixed_samples; + u32 dcc_sum[MIXER_AUDIO_CHANNEL_NUM]; + s16 end_sample[MIXER_AUDIO_CHANNEL_NUM]; +#endif + u32 sample_rate; // 当前mixer的采样率 + int need_sr; // mixer想要变成的采样率 + MIXER_SR_TYPE sr_type; // 采样率设置类型 + u32(*check_sr)(struct audio_mixer *, u32 sr); // 检查采样率 + void (*evt_handler)(struct audio_mixer *, int); // 事件返回接口 + + struct audio_stream *stream; // 音频流 + struct audio_stream_entry entry; // 音频流入口,后级接dac等 +}; + +/* + * mixer通道处理 + * 支持固定变采样src_en、跟随缓存数据大小变采样sync_en、跟随外部设定采样follow_resample + * 支持各个声道单独输出配置aud_ch_out + * 支持超时自动忽略该通道no_wait + * 支持淡入淡出等 + */ +struct audio_mixer_ch { + u32 start : 1; // 启动标记。1-已经启动。输出时标记一次 + u32 open : 1; // 打开标记。1-已经打开。输出标记为1,reset标记为0 + u32 pause : 1; // 暂停标记。1-暂停 + u32 src_en : 1; // 变采样使能 + u32 src_always : 1; // 不管采样率是否相同都做变采样 + u32 sync_en : 1; // buf同步使能 + u32 sync_always : 1;// 不管采样率是否相同都做buf同步 + u32 sample_sync : 1;// sample同步标记 + u32 data_sync : 1; // sample同步临时保存 + u32 check_sr : 1; // 需要检查采样率 + u32 master_sr_change : 1; // master采样率变化 + u32 src_running : 1;// 执行变采样处理 + u32 aud_ch_num : 4; // 声道数 + u32 fade_dir : 2; // 淡入淡出状态 + u32 follow_resample : 1; // follow变采样标志 +#if MIXER_AUDIO_CASK_EFFECT_EN + u32 no_wait : 1; // 不等待有数 + u16 lose_time; // 超过该时间还没有数据,则以为可以丢数。no_wait置1有效 + u16 lose_cnt; // 超时计数 + volatile u8 lose; // 丢数标记 +#endif + volatile u8 need_resume; // 需要激活 + s16 fade_vol; // 淡入淡出值 + s16 fade_step; // 淡入淡出步进 + u16 fade_time; // 淡入淡出时长 + OS_SEM *sem_fadeout;// 淡出等待信号量 + // 声道输出控制。如,当前通道的第1个声道输出到mixer的第0和第1个声道,aud_ch_out[1] = BIT(0) | BIT(1); + // mixer单声道默认值:aud_ch_out[n] = BIT(0); 如,aud_ch_out[1] = BIT(0); + // mixer其他声道默认值:aud_ch_out[n] = BIT(n)|BIT(n+2); 如,aud_ch_out[1] = BIT(1)|BIT(3); + u8 aud_ch_out[MIXER_AUDIO_CHANNEL_NUM]; +#if MIXER_AUDIO_ENDDING_DCC + s16 end_sample[MIXER_AUDIO_CHANNEL_NUM]; +#endif + u16 points_len; // 数据长度 + u16 start_points; // 初始化数据长度。默认为mixer->points/2 + u32 sample_rate; // 当前通道采样率 + u32 sample_rate_follow; // 当前通道follow采样率。follow_resample==1有效 + struct list_head list_entry; // 链表 + struct audio_mixer *mixer; // mixer句柄 + struct audio_src_handle *src; // 变采样 + struct audio_buf_sync_hdl sync; // buf同步 + struct audio_mixer_ch_sync_info sync_info; // buf同步参数 + void *priv; // 事件回调私有句柄 + void (*event_handler)(void *priv, int event, int param); // 事件回调接口 + void *follow_priv; // follow变采样私有参数 + int (*follow_sample_rate)(void *priv); // follow变采样回调 + + struct audio_stream_entry entry; // 音频流入口,通道后面不应该再接其他的音频流,最后由mixer合并后输出 +}; + + +/* +********************************************************************* +* Audio Mixer Open +* Description: 打开一个mixer +* Arguments : *mixer 句柄 +* Return : 0 成功 +* Note(s) : 默认采样率类型为获取第一个通道的采样率;默认设置声道数1; +* 默认使用短板效应;默认开启直通功能 +********************************************************************* +*/ +int audio_mixer_open(struct audio_mixer *mixer); + +/* +********************************************************************* +* Audio Mixer Close +* Description: 关闭一个mixer +* Arguments : *mixer 句柄 +* Return : None. +* Note(s) : 所有通道关闭后才能close +********************************************************************* +*/ +void audio_mixer_close(struct audio_mixer *mixer); + +/* +********************************************************************* +* Audio Mixer Set Event Callback Handler +* Description: 设置事件回调 +* Arguments : *mixer 句柄 +* *handler 事件回调句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_set_event_handler(struct audio_mixer *mixer, + void (*handler)(struct audio_mixer *, int)); + +/* +********************************************************************* +* Audio Mixer Set Check Sample Callback Handler +* Description: 设置采样率检测回调 +* Arguments : *mixer 句柄 +* *check_sr 采样率检测回调句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_set_check_sr_handler(struct audio_mixer *mixer, + u32(*check_sr)(struct audio_mixer *, u32)); + +/* +********************************************************************* +* Audio Mixer Set Output Buf +* Description: 设置输出buf +* Arguments : *mixer 句柄 +* *buf 输出buf +* len 输出buf长度 +* Return : None. +* Note(s) : 默认设置min_points为总buf的1/4 +********************************************************************* +*/ +void audio_mixer_set_output_buf(struct audio_mixer *mixer, s16 *buf, u16 len); + +/* +********************************************************************* +* Audio Mixer Set Channel Number +* Description: 设置声道数 +* Arguments : *mixer 句柄 +* channel_num 声道数 +* Return : None. +* Note(s) : 通道可能会做变采样等,需要设置声道数 +********************************************************************* +*/ +void audio_mixer_set_channel_num(struct audio_mixer *mixer, u8 channel_num); + +/* +********************************************************************* +* Audio Mixer Set Output Min Lenght +* Description: 设置mixer数据输出最小限制值 +* Arguments : *mixer 句柄 +* min_len 最小限制值 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_set_min_len(struct audio_mixer *mixer, u16 min_len); + +/* +********************************************************************* +* Audio Mixer Set Cask Effect +* Description: 短板效应 +* Arguments : *mixer 句柄 +* cask_effect 短板效应 +* Return : None. +* Note(s) : 1 短板效应。等待所有通道有数才能输出 +* 0 长板效应。只要某个通道有数就输出,不理会其他通道是否有数 +********************************************************************* +*/ +void audio_mixer_set_cask_effect(struct audio_mixer *mixer, u8 cask_effect); + +/* +********************************************************************* +* Audio Mixer Set Direct Output Enable +* Description: 直通功能 +* Arguments : *mixer 句柄 +* direct_out_en 直通输出使能 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_set_direct_out(struct audio_mixer *mixer, u8 direct_out_en); + +/* +********************************************************************* +* Audio Mixer Set Sample Rate +* Description: 设置采样率 +* Arguments : *mixer 句柄 +* type 采样率类型 +* sample_rate 采样率 +* Return : None. +* Note(s) : 采样率类型为MIXER_SR_SPEC时固定采样,其他类型在设置通道采样率的时候重新获取 +********************************************************************* +*/ +void audio_mixer_set_sample_rate(struct audio_mixer *mixer, MIXER_SR_TYPE type, u32 sample_rate); + +/* +********************************************************************* +* Audio Mixer Get Original Sample Rate By Type +* Description: 按条件获取采样率 +* Arguments : *mixer 句柄 +* type 采样率类型 +* Return : 采样率 +* Note(s) : 原始采样率,不调用check_sr检测 +********************************************************************* +*/ +int audio_mixer_get_original_sample_rate_by_type(struct audio_mixer *mixer, MIXER_SR_TYPE type); + +/* +********************************************************************* +* Audio Mixer Get Sample Rate By Type +* Description: 按条件获取采样率 +* Arguments : *mixer 句柄 +* type 采样率类型 +* Return : 采样率 +* Note(s) : 获取原始采样率之后,再调用check_sr()做了检测 +********************************************************************* +*/ +int audio_mixer_get_sample_rate_by_type(struct audio_mixer *mixer, MIXER_SR_TYPE type); + +/* +********************************************************************* +* Audio Mixer Get Sample Rate +* Description: 获取采样率 +* Arguments : *mixer 句柄 +* Return : 采样率 +* Note(s) : 内部直接调用audio_mixer_get_sample_rate_by_type(mixer, mixer->sr_type); +********************************************************************* +*/ +int audio_mixer_get_sample_rate(struct audio_mixer *mixer); + +/* +********************************************************************* +* Audio Mixer Get Cur Sample Rate +* Description: 直接获取mixer->sample_rate的值 +* Arguments : *mixer 句柄 +* Return : 采样率 +* Note(s) : None. +********************************************************************* +*/ +int audio_mixer_get_cur_sample_rate(struct audio_mixer *mixer); + +/* +********************************************************************* +* Audio Mixer Get Channel Number +* Description: 获取通道总数 +* Arguments : *mixer 句柄 +* Return : 通道数 +* Note(s) : None. +********************************************************************* +*/ +int audio_mixer_get_ch_num(struct audio_mixer *mixer); + +/* +********************************************************************* +* Audio Mixer Get Active Channel Number +* Description: 获取活动通道总数 +* Arguments : *mixer 句柄 +* Return : 通道数 +* Note(s) : None. +********************************************************************* +*/ +int audio_mixer_get_active_ch_num(struct audio_mixer *mixer); + +/* +********************************************************************* +* Audio Mixer Get Data Lenght +* Description: 获取mixer剩余长度 +* Arguments : *mixer 句柄 +* Return : 剩余数据长度 +* Note(s) : None. +********************************************************************* +*/ +int audio_mixer_data_len(struct audio_mixer *mixer); + +/* +********************************************************************* +* Audio Mixer Push Stop To Stream +* Description: 传送stop到数据流 +* Arguments : *mixer 句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_output_stop(struct audio_mixer *mixer); + +/* +********************************************************************* +* Audio Mixer Stream Resume +* Description: 数据流激活处理 +* Arguments : *priv (struct audio_mixer *)类型句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_stream_resume(void *p); + + +/* +********************************************************************* +* Audio Mixer Channel Open +* Description: 打开一个mixer通道 +* Arguments : *ch mixer通道句柄 +* *mixer mixer句柄 +* Return : 0 成功 +* Note(s) : 放在链表结尾处 +********************************************************************* +*/ +int audio_mixer_ch_open(struct audio_mixer_ch *ch, struct audio_mixer *mixer); + +/* +********************************************************************* +* Audio Mixer Channel Open Head +* Description: 打开一个mixer通道 +* Arguments : *ch mixer通道句柄 +* *mixer mixer句柄 +* Return : 0 成功 +* Note(s) : 放在链表起始处 +********************************************************************* +*/ +int audio_mixer_ch_open_head(struct audio_mixer_ch *ch, struct audio_mixer *mixer); + +/* +********************************************************************* +* Audio Mixer Channel Close +* Description: 关闭通道 +* Arguments : *ch mixer通道句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_ch_close(struct audio_mixer_ch *ch); + +/* +********************************************************************* +* Audio Mixer Channel Set Event Callback Handler +* Description: 设置通道事件回调 +* Arguments : *ch mixer通道句柄 +* *priv 事件回调私有句柄 +* *handler 事件回调接口 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_ch_set_event_handler(struct audio_mixer_ch *ch, void *priv, void (*handler)(void *, int, int)); + +/* +********************************************************************* +* Audio Mixer Channel Set Sample Rate +* Description: 设置通道采样率 +* Arguments : *ch mixer通道句柄 +* sample_rate 采样率 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_ch_set_sample_rate(struct audio_mixer_ch *ch, u32 sample_rate); + +/* +********************************************************************* +* Audio Mixer Channel Set SRC Enable +* Description: 设置通道变采样 +* Arguments : *ch mixer通道句柄 +* src_en 变采样使能 +* always 不管输入输出采样是否相同,都做变采样处理 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_ch_set_src(struct audio_mixer_ch *ch, u8 src_en, u8 always); + +/* +********************************************************************* +* Audio Mixer Channel Set Buf Sync Enable +* Description: 设置通道跟随缓存大小变采样处理 +* Arguments : *ch mixer通道句柄 +* *info 同步参数 +* sync_en 同步使能 +* always 不管输入输出采样是否相同,都做同步处理 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_ch_set_sync(struct audio_mixer_ch *ch, struct audio_mixer_ch_sync_info *info, u8 sync_en, u8 always); + +/* +********************************************************************* +* Audio Mixer Channel Set Audio Output Channel +* Description: 设置通道声道输出 +* Arguments : *ch mixer通道句柄 +* aud_ch 设置通道的第几个声道,小于MIXER_AUDIO_CHANNEL_NUM +* aud_out 设置输出到哪些声道,如输出到第0个和第3个,aud_out=BIT(0)|BIT(3) +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_ch_set_aud_ch_out(struct audio_mixer_ch *ch, u8 aud_ch, u8 aud_out); + +/* +********************************************************************* +* Audio Mixer Channel Set No Wait +* Description: 设置通道没数据时不等待 +* Arguments : *ch mixer通道句柄 +* no_wait 不等待使能 +* time_ms 超时 +* Return : None. +* Note(s) : 超时直接丢数 +********************************************************************* +*/ +void audio_mixer_ch_set_no_wait(struct audio_mixer_ch *ch, u8 no_wait, u16 time_ms); + +/* +********************************************************************* +* Audio Mixer Channel Set Start Len +* Description: 设置通道起始填数长度 +* Arguments : *ch mixer通道句柄 +* start_len 起始长度 +* Return : None. +* Note(s) : 设置长度不超过mixer空间大小 +********************************************************************* +*/ +void audio_mixer_ch_set_start_len(struct audio_mixer_ch *ch, u16 start_len); + +/* +********************************************************************* +* Audio Mixer Channel Pause +* Description: 通道暂停 +* Arguments : *ch mixer通道句柄 +* pause 暂停 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_ch_pause(struct audio_mixer_ch *ch, u8 pause); + +/* +********************************************************************* +* Audio Mixer Channel Reset +* Description: 通道重启 +* Arguments : *ch mixer通道句柄 +* Return : 0 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_mixer_ch_reset(struct audio_mixer_ch *ch); + +/* +********************************************************************* +* Audio Mixer Channel Get Data Lenght +* Description: 获取通道剩余长度 +* Arguments : *ch mixer通道句柄 +* Return : 通道剩余数据长度 +* Note(s) : None. +********************************************************************* +*/ +int audio_mixer_ch_data_len(struct audio_mixer_ch *ch); + +/* +********************************************************************* +* Audio Mixer Channel Write Data +* Description: 通道数据输出 +* Arguments : *ch mixer通道句柄 +* *data 数据 +* len 数据长度 +* Return : 实际输出长度 +* Note(s) : 输出前会根据配置做变采样/同步处理 +********************************************************************* +*/ +int audio_mixer_ch_write(struct audio_mixer_ch *ch, s16 *data, int len); + +/* +********************************************************************* +* Audio Mixer Channel Sample Sync Enable +* Description: 设置通道sync标志 +* Arguments : *ch mixer通道句柄 +* enable 使能 +* Return : None. +* Note(s) : 蓝牙tws同步使用 +********************************************************************* +*/ +void audio_mixer_ch_sample_sync_enable(struct audio_mixer_ch *ch, u8 enable); + +/* +********************************************************************* +* Audio Mixer Channel Try Fadein +* Description: 通道淡入 +* Arguments : *ch mixer通道句柄 +* time 淡入时长 +* Return : 0 成功 +* Note(s) : 暂停、直通等情况下无效 +********************************************************************* +*/ +int audio_mixer_ch_try_fadein(struct audio_mixer_ch *ch, u16 time); + +/* +********************************************************************* +* Audio Mixer Channel Try Fadeout +* Description: 通道淡出 +* Arguments : *ch mixer通道句柄 +* time 淡出时长 +* Return : 0 成功 +* Note(s) : 暂停、直通等情况下无效。淡出后通道会暂停。 +********************************************************************* +*/ +int audio_mixer_ch_try_fadeout(struct audio_mixer_ch *ch, u16 time); + +/* +********************************************************************* +* Audio Mixer Channel Fade Close +* Description: 关闭通道淡入淡出 +* Arguments : *ch mixer通道句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_ch_fade_close(struct audio_mixer_ch *ch); + +/* +********************************************************************* +* Audio Mixer Channel Follow Resample Enable +* Description: 设置通道follow变采样 +* Arguments : *ch mixer通道句柄 +* *priv 变采样参数 +* *follow_sample_rate 变采样回调 +* Return : None. +* Note(s) : 采样率变化由回调确定 +********************************************************************* +*/ +void audio_mixer_ch_follow_resample_enable(struct audio_mixer_ch *ch, void *priv, int (*follow_sample_rate)(void *)); + +/* +********************************************************************* +* Audio Mixer Output Task Init +* Description: mixer任务初始化 +* Arguments : *mtask mixer任务句柄 +* *task_name 任务名字 +* Return : true 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_mixer_task_init(struct audio_mixer_task *mtask, const char *task_name); + +/* +********************************************************************* +* Audio Mixer Output Task Destroy +* Description: mixer任务删除 +* Arguments : *mtask mixer任务句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_task_destroy(struct audio_mixer_task *mtask); + +/* +********************************************************************* +* Audio Mixer Output Task Channel Open +* Description: mixer添加到mixer任务中 +* Arguments : *mixer mixer句柄 +* *mtask mixer任务句柄 +* Return : true 成功 +* Note(s) : None. +********************************************************************* +*/ +int audio_mixer_task_ch_open(struct audio_mixer *mixer, struct audio_mixer_task *mtask); + +/* +********************************************************************* +* Audio Mixer Output Task Channel Close +* Description: 把mixer从mixer任务中删除 +* Arguments : *mixer mixer句柄 +* Return : None. +* Note(s) : None. +********************************************************************* +*/ +void audio_mixer_task_ch_close(struct audio_mixer *mixer); + + +#endif /*CONFIG_MIXER_CYCLIC*/ + +#endif /*AUDIO_MIXER_CYCLIC_H*/ + diff --git a/include_lib/media/media_develop/media/pcm_decoder.h b/include_lib/media/media_develop/media/pcm_decoder.h new file mode 100644 index 0000000..58e08ae --- /dev/null +++ b/include_lib/media/media_develop/media/pcm_decoder.h @@ -0,0 +1,33 @@ +#ifndef PCM_DECODER_H +#define PCM_DECODER_H + + +#include "media/includes.h" + + +struct pcm_decoder { + u16 ch_num : 4; // 声道数 + u16 output_ch_num : 4; // 输出声道数 + u16 output_ch_type : 4; // 输出声道类型 + u16 dec_no_out_sound : 1; // 解码不直接输出声音(用于TWS转发) + u16 sample_rate; // 采样率 + struct audio_decoder decoder; // 解码句柄 + void *read_priv; // 数据获取私有句柄 + int (*read_data)(void *priv, void *buf, int len); // 数据获取 +}; + +// 打开pcm解码 +int pcm_decoder_open(struct pcm_decoder *, struct audio_decoder_task *decode_task); +// 关闭pcm解码 +void pcm_decoder_close(struct pcm_decoder *dec); +// 设置pcm解码事件回调接口 +void pcm_decoder_set_event_handler(struct pcm_decoder *dec, + void (*handler)(struct audio_decoder *, int, int *), u32 maigc); +// 设置pcm解码数据获取接口 +void pcm_decoder_set_read_data(struct pcm_decoder *dec, int (*read_data)(void *priv, void *buf, int len), void *read_priv); +// 设置pcm解码数据处理接口 +void pcm_decoder_set_data_handler(struct pcm_decoder *dec, + int (*data_handler)(struct audio_stream_entry *, struct audio_data_frame *in, struct audio_data_frame *out)); + +#endif /*PCM_DECODER_H*/ + diff --git a/include_lib/media/media_develop/media/sbc_enc.h b/include_lib/media/media_develop/media/sbc_enc.h new file mode 100644 index 0000000..0943400 --- /dev/null +++ b/include_lib/media/media_develop/media/sbc_enc.h @@ -0,0 +1,145 @@ +/* + * + * Bluetooth low-complexity, subband codec (SBC) library + * + * Copyright (C) 2008-2010 Nokia Corporation + * Copyright (C) 2004-2010 Marcel Holtmann + * Copyright (C) 2004-2005 Henryk Ploetz + * Copyright (C) 2005-2006 Brad Midgley + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef __SBC_ENC_H +#define __SBC_ENC_H + +#ifdef __cplusplus +extern "C" { +#endif + +//typedef unsigned char uint8 ,u8 ,U8 ,uint8_t; +//typedef unsigned short int uint16 ,UINT16 ,U16 ,u16 ,uint16_t; +//typedef unsigned int uint32 ,UINT32,U32 ,u32 ,uint32_t ,uintptr_t; +//typedef signed char sint8 ,s8 ,S8,int8 ,int8_t; +//typedef signed short int sint16 ,SINT16 ,S16 ,s16,int16,INT16,int16_t ; +//typedef signed int sint32 ,SINT32,S32 ,s32,int32 ,INT32;//,; +//typedef unsigned int size_t,ssize_t; +//typedef int int32_t ; +//typedef unsigned __int64 int64_t; +//typedef __int64 uint64_t ; + + +//#include "typedef.h" +//#include +//#include +#include +#ifndef __GNUC__ +#define SBC_ENCODE +#endif +/* sampling frequency */ +#define SBC_FREQ_16000 0x00 +#define SBC_FREQ_32000 0x01 +#define SBC_FREQ_44100 0x02 +#define SBC_FREQ_48000 0x03 + + +/* blocks */ +#define SBC_BLK_4 0x00 +#define SBC_BLK_8 0x01 +#define SBC_BLK_12 0x02 +#define SBC_BLK_16 0x03 + +/* channel mode */ +#define SBC_MODE_MONO 0x00 +#define SBC_MODE_DUAL_CHANNEL 0x01 +#define SBC_MODE_STEREO 0x02 +#define SBC_MODE_JOINT_STEREO 0x03 + +/* allocation method */ +#define SBC_AM_LOUDNESS 0x00 +#define SBC_AM_SNR 0x01 + +/* subbands */ +#define SBC_SB_4 0x00 +#define SBC_SB_8 0x01 + +/* Data endianness */ +#define SBC_LE 0x00 +#define SBC_BE 0x01 + +typedef struct sbc_struct { + unsigned int flags; + + unsigned char frequency; + unsigned char blocks; + unsigned char subbands; + unsigned char mode; + unsigned char allocation; + unsigned char bitpool; + unsigned char endian; + + void *priv; + void *priv_alloc_base; +} sbc_t; + + + + +unsigned int sbc_enc_query(void); +int sbc_init(sbc_t *sbc, unsigned long flags, void *priv); +int sbc_reinit(sbc_t *sbc, unsigned long flags); + +unsigned int sbc_parse(sbc_t *sbc, const void *input, size_t input_len); + +/* Decodes ONE input block into ONE output block */ +unsigned int sbc_decode(sbc_t *sbc, const void *input, size_t input_len, + void *output, size_t output_len, size_t *written); + +/* Encodes ONE input block into ONE output block */ +unsigned int sbc_encode(sbc_t *sbc, const void *input, size_t input_len, + void *output, size_t output_len, unsigned int *written); + +/* Returns the output block size in bytes */ +//size_t sbc_get_frame_length(sbc_t *sbc); + +/* Returns the time one input/output block takes to play in msec*/ +unsigned sbc_get_frame_duration(sbc_t *sbc); + +/* Returns the input block size in bytes */ +//size_t sbc_get_codesize(sbc_t *sbc); + +const char *sbc_get_implementation_info(sbc_t *sbc); +void sbc_finish(sbc_t *sbc); +//#define htons(x) ( ( (((unsigned short)(x)) >>8) & 0xff) | ((((unsigned short)(x)) & 0xff)<<8) ) + + + +#ifdef __cplusplus +} +#endif + +struct option { + const char *name; + int has_arg; + int *flag; + int val; +}; + + +#endif /* __SBC_ENC_H */ + + diff --git a/include_lib/media/media_develop/media/spectrum/SpectrumShow_api.h b/include_lib/media/media_develop/media/spectrum/SpectrumShow_api.h new file mode 100644 index 0000000..7c4fb92 --- /dev/null +++ b/include_lib/media/media_develop/media/spectrum/SpectrumShow_api.h @@ -0,0 +1,10 @@ +#ifndef SPECTRUMSHOW_API_H +#define SPECTRUMSHOW_API_H + +int getSpectrumShowBuf(); +void SpectrumShowInit(void *workBuf, float attackFactor, float releaseFactor, int fs, int channel, int mode, unsigned int fft_addr); +int SpectrumShowRun(void *workBuf, short *in, int len); +int getSpectrumNum(void *workBuf); +short *getSpectrumValue(void *workBuf); + +#endif // !SPECTRUMSHOW_API_H diff --git a/include_lib/media/media_develop/media/spectrum/coeff_calculate_api.h b/include_lib/media/media_develop/media/spectrum/coeff_calculate_api.h new file mode 100644 index 0000000..c44bd28 --- /dev/null +++ b/include_lib/media/media_develop/media/spectrum/coeff_calculate_api.h @@ -0,0 +1,38 @@ +#ifndef COEFF_CALCULATE_API_H +#define COEFF_CALCULATE_API_H + + +int get_coeff_calculate_buf(int section); +void coeff_calculate_init(void *ptr, int section, int fs); +void bpf_filts(void *ptr, int *in_buf_fc, int *qf); + +typedef struct spectrum { + int section; + int fs; + int *SOSMatrix; + int pool[0]; +} spec; + +#if 0 +coeff_calculate.a库说明: +该库根据给定的参数计算带通滤波器的系数; + +调用流程: +bufsize = int get_coeff_calculate_buf(section); //获取buf大小 +section:段数(可根据并联的需要进行配置) + +workbuf = malloc(bufsize); //申请内存 + +coeff_calculate_init(workbuf, section, fs); //初始化 +fs: +采样频率 + +bpf_filts(workbuf, in_buf, qf); //运行 +in_buf :输入的fc数据(定点24bit),与段数匹配 +qf:输入的q因子数据(定点24bit),与段数匹配 + +输出:每段5个系数(定点22bit)对应br23模型,系数存储在缓存SOSMatrix中; +#endif + +#endif + diff --git a/include_lib/media/media_develop/media/spectrum/rms_api.h b/include_lib/media/media_develop/media/spectrum/rms_api.h new file mode 100644 index 0000000..4e2e800 --- /dev/null +++ b/include_lib/media/media_develop/media/spectrum/rms_api.h @@ -0,0 +1,62 @@ +#ifndef RMS_API_H +#define RMS_API_H + +int get_rms_buf(int section, int time, int fs, int switch_1); +void rms_init(void *ptr, int section, int fs, int time, int switch_1, float attackFactor, float releaseFactor, int D_time, float alpha); +int rms(void *ptr, short *in_buf, int len); + + +typedef struct __spectrum_rms { + int switch_1; + float attackFactor;//平滑因子 + float releaseFactor; + float alpha;//最值的平滑因子 + int section; + int fs; + short *index;//索引 + short *cache;//缓存地址 + float *DB;//记录增益 + int time;//缓存时间,ms为单位 + int T_num;//缓存时间内的点数 + int D_time;//跟新db的时间 + int counter;//计数器 + int *max;//记录最大值 + int T;//缓存长度 + long long *add;//求和累加 + int _T; + int pool[0]; +} spec_rms; + +#if 0 +rms.a库说明: +该库计算的是经过滤波后的信号的db值,其中包括打开rms计算db和关闭rms计算db两种模式; + +调用说明: +buf_size = get_rms_buf(section, time, fs, switch_1); //获取buf大小: +section: +段数(可配置), +time: 缓存时间(单位毫秒,整形输入), +fs: +采样频率, +switch_1:模式开关(1打开rms,0关闭rms), + + +work_buf = malloc(buf_size); //申请内存 + + +rms_init(work_buf, channel, section, fs, time, switch_1, attackFactor, releaseFactor); +初始化: +channel:声道数, +attackFactor, releaseFactor:下降因子和上升因子(范围0 - 1,建议attackFactor取较大值) +attackFactor 1 releaseFactor 1不能设置成1, 设置成1永远都是0 +attackFactor取大,db值降的慢,releaseFactor取大,db值升的慢 + +rms(work_buf, in_buf, out_buf, len);//运行 +in_buf 输入数据,16bit +out_buf 输出数据,16bit +len 数据长度(其中一段滤波器的点数) +数据输出为单通道并行输出 +#endif + + +#endif diff --git a/include_lib/media/media_develop/media/spectrum/spectrum_eq.h b/include_lib/media/media_develop/media/spectrum/spectrum_eq.h new file mode 100644 index 0000000..a66fb56 --- /dev/null +++ b/include_lib/media/media_develop/media/spectrum/spectrum_eq.h @@ -0,0 +1,108 @@ +#ifndef SPECTRUM_API_H +#define SPECTRUM_API_H + +#include "spectrum/coeff_calculate_api.h" +#include "spectrum/rms_api.h" +#include "media/audio_eq_drc_apply.h" +#include "media/audio_stream.h" + + +typedef struct _spectrum_open_parm { + u32 sr; + u32 channel: 4; + u32 section: 6; + + u32 rms_en: 1; + u32 time_ms: 4; + u32 d_time: 16; //50ms~500ms + float alpha;//(0~1) + float attackFactor; + float releaseFactor; + + int *freq_center; + int *quality_factor; + + void *priv; + int (*output)(void *priv, float *db, u32 len);//user define +} spectrum_open_parm; + + +typedef struct _spectrum_hdl { + void *rms_hdl;//算db值 + int *coeff; //存放系数的地址 + struct audio_eq *eq[10]; + u32 data_len; + s16 *data;//输出数据地址 + + spectrum_open_parm parm; + struct audio_stream_entry entry; // 音频流入口 +} spectrum_hdl; + + +spectrum_hdl *audio_spectrum_open(spectrum_open_parm *parm); +int audio_spectrum_close(spectrum_hdl *hdl); +#if 0 +//例子 + + +/*----------------------------------------------------------------------------*/ +/**@brief 频响输出回调 + @param data:db值存放的首地址,连续存放 len 个 float型的db值 + @return len + @note +*/ +/*----------------------------------------------------------------------------*/ +int spectrum_output(void *priv, float *data, u32 len) +{ + u8 db_num = len; + float *tar_data = data; + for (int i = 0; i < db_num; i++) { + //输出10个 浮点db值 + /* printf("tar_data db 0x%x\n", *(int *)&tar_data[i]); */ + //printf("tar_data db %d.%d\n", (int )tar_data[i],(int)((int)(tar_data[i]*100)%100)); + } + return len; +} + +static u32 freq[] = {31, 62, 125, 250, 500, 1000, 2000, 4000, 8000, 16000}; +static u32 quality[] = { + (int)(0.7f * (1 << 24)), (int)(0.7f * (1 << 24)), + (int)(0.7f * (1 << 24)), (int)(0.7f * (1 << 24)), + (int)(0.7f * (1 << 24)), (int)(0.7f * (1 << 24)), + (int)(0.7f * (1 << 24)), (int)(0.7f * (1 << 24)), + (int)(0.7f * (1 << 24)), (int)(0.7f * (1 << 24)) +}; +/*----------------------------------------------------------------------------*/ +/**@brief 打开频响统计 + @param sr:采样率 + @return hdl:句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +spectrum_hdl *spectrum_open_demo(u32 sr) +{ +#if TCFG_EQ_ENABLE + spectrum_hdl *hdl = NULL; + spectrum_open_parm parm = {0}; + parm.sr = sr; + parm.channel = 1; + parm.section = EQ_SECTION_MAX; + parm.rms_en = 1; + parm.time_ms = 5; + parm.attackFactor = 0.9; + parm.releaseFactor = 0.9; + parm.freq_center = freq; + parm.quality_factor = quality; + parm.d_time = 100; + parm.alpha = 0.9; + parm.priv = NULL; + parm.output = spectrum_output; + hdl = audio_spectrum_open(&parm); + return hdl; +#else + return NULL; +#endif +} + +#endif +#endif diff --git a/include_lib/media/media_develop/media/spectrum/spectrum_fft.h b/include_lib/media/media_develop/media/spectrum/spectrum_fft.h new file mode 100644 index 0000000..bcf7ee3 --- /dev/null +++ b/include_lib/media/media_develop/media/spectrum/spectrum_fft.h @@ -0,0 +1,76 @@ +#ifndef SPECTRUM_FFT_API_H +#define SPECTRUM_FFT_API_H + +#include "spectrum/SpectrumShow_api.h" +#include "media/audio_stream.h" + +//该模块 mips 消耗5M +//RAM 单声道时:4.4Kbyte +//RAM 双声道时:5.4Kbyte +typedef struct _spectrum_fft_open_parm { + u32 sr; //采样率 + u32 channel: 4; //通道数 + u32 mode: 4; //模式,双声道起作用,0 计算的是第一声道的频谱值, + //1计算的是第二声道频谱值,2为第一声道与第二声道相加除2的频谱值 + + float attackFactor;//下降因子[0,1) + float releaseFactor;//上升因子[0,1) +} spectrum_fft_open_parm; + + +typedef struct _spectrum_fft_hdl { + void *work_buf; + u32 run_en: 1; + + s16 *out_buf; + u32 out_buf_size; + u32 offset; + + spectrum_fft_open_parm parm; + struct audio_stream_entry entry; // 音频流入口 +} spectrum_fft_hdl; + +/*----------------------------------------------------------------------------*/ +/**@brief 打开 + @param *_parm: 始化参数,详见结构体spectrum_fft_open_parm + @return 句柄 + @note +*/ +/*----------------------------------------------------------------------------*/ +spectrum_fft_hdl *audio_spectrum_fft_open(spectrum_fft_open_parm *parm); + +/*----------------------------------------------------------------------------*/ +/**@brief audio_spectrum_fft_close 关闭处理 + @param _hdl:句柄 + @return 0:成功 -1:失败 + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_spectrum_fft_close(spectrum_fft_hdl *hdl); + +/*----------------------------------------------------------------------------*/ +/**@brief audio_spectrum_fft_switch 运行过程做开关处理 + @param hdl:句柄 + @param en:0 关闭频响运算 1 打开频响运算 (通话模式,不支持频谱计算.通话模式已经使用fft, 需关闭频谱计算) + @return + @note +*/ +/*----------------------------------------------------------------------------*/ +void audio_spectrum_fft_switch(spectrum_fft_hdl *hdl, u8 en); +/*----------------------------------------------------------------------------*/ +/**@brief audio_spectrum_fft_get_num 获取频谱个数 + @param _hdl:句柄 + @return 返回频谱的个数 + @note +*/ +/*----------------------------------------------------------------------------*/ +int audio_spectrum_fft_get_num(spectrum_fft_hdl *hdl); +/*----------------------------------------------------------------------------*/ +/**@brief audio_spectrum_fft_get_val 获取频谱值 + @param _hdl:句柄 + @return 返回存储频谱值的地址 + @note +*/ +/*----------------------------------------------------------------------------*/ +short *audio_spectrum_fft_get_val(spectrum_fft_hdl *hdl); +#endif diff --git a/include_lib/media/media_develop/media/w2s_handle_api.h b/include_lib/media/media_develop/media/w2s_handle_api.h new file mode 100644 index 0000000..160ec38 --- /dev/null +++ b/include_lib/media/media_develop/media/w2s_handle_api.h @@ -0,0 +1,44 @@ +#ifndef w2s_handle_api_h__ +#define w2s_handle_api_h__ + +#ifndef U32 + +#endif + +#define MAX_WORD 10 + +/* typedef struct _MIDI_W2S_STRUCT_ */ +// { +// unsigned int word_cnt; //多少个字 +// unsigned int data_pos[MAX_WORD + 1]; //数据起始位置 +// unsigned int data_len[MAX_WORD + 1]; //数据长度 +// unsigned short* rec_data; +// char key_diff; +/* }MIDI_W2S_STRUCT; */ + +typedef struct _MIDI_W2S_STRUCT_ { + unsigned int word_cnt; //多少个音 + unsigned int data_pos[MAX_WORD + 1]; //每个音起始位置 + unsigned int data_len[MAX_WORD + 1]; //每个音数据长度(short) + unsigned int rec_data; //pcm 数据 MIDI_TONE_MODE变量是0时用pcm数据;是1时读pcm文件地址 + char key_diff; //与音高成反比 建议范围[-12,12] +} MIDI_W2S_STRUCT; + +typedef struct _REC_W2S_STRUCT_ { + short *rec_data; + unsigned int rec_len; + unsigned char toneadjust_enable; + unsigned char multi_enable; + unsigned short energy_thresh; +} REC_W2S_STUCT; + + +typedef struct _w2s_ana_ops_ { + unsigned int (*need_buf)(); //申请需要的buf + int (*open)(unsigned char *ptr, REC_W2S_STUCT *ptr_parm_i, MIDI_W2S_STRUCT *ptr_parm_o); //外面配置的参数 + int (*run)(unsigned char *ptr, short *data, int len); //处理外,传出处理过的函数结果 +} w2s_ana_ops; + +extern w2s_ana_ops *get_w2s_ans_ops(); + +#endif // w2s_handle_api_h__ diff --git a/include_lib/media/noisegate_api.h b/include_lib/media/noisegate_api.h new file mode 100644 index 0000000..0f99ad4 --- /dev/null +++ b/include_lib/media/noisegate_api.h @@ -0,0 +1,28 @@ +#ifndef NOISEGATE_API_H +#define NOISEGATE_API_H + +typedef struct _NoiseGateParam { + int attackTime; + int releaseTime; + int threshold; + int low_th_gain; + int sampleRate; + int channel; + int IndataInc; + int OutdataInc; +} NoiseGateParam; + +typedef struct _NoiseGate_update_Param { + int attackTime; //启动时间 + int releaseTime; //释放时间 + int threshold; //阈值mdb 例如-65.5db 例如传下来应是-65500 + int low_th_gain; //低于阈值增益 放大30bit 例如(int)(0.1 * (1 << 30)) +} noisegate_update_param; + +int noiseGate_buf(); +void noiseGate_init(void *workbuf, NoiseGateParam *param); +void noiseGate_update(void *work_buf, NoiseGateParam *param); +int noiseGate_run(void *work_buf, short *in_buf, short *out_buf, int per_channel_npoint); + +#endif // NOISEGATE_API_H + diff --git a/include_lib/media/reverb_api.h b/include_lib/media/reverb_api.h new file mode 100644 index 0000000..89660ed --- /dev/null +++ b/include_lib/media/reverb_api.h @@ -0,0 +1,198 @@ +#ifndef reverb_api_h__ +#define reverb_api_h__ + +#include "media/audio_stream.h" +typedef struct REVERBN_PARM_SET { + int dry; // 0-200% + int wet; //0-300% + int delay; //0-100ms + int rot60; //100-15000ms + int Erwet; // 5%- 400% + int Erfactor; // 50%-250% + int Ewidth; // -100% - 100% + int Ertolate; // 0- 300% + int Erbasslpf; //0-18k + int ErbassB; //-100% - 100% + int predelay; // 0- 20ms + int allpassfeedback; //0% - 100% + int diffusion; //0% - 100% + int dampinglpf; //0-18k + int basslpf; //0-1.1k + int bassB; // 0-80% + int lowcut; +} REVERBN_PARM_SET; + + +/*open 跟 run 都是 成功 返回 RET_OK,错误返回 RET_ERR*/ +/*魔音结构体*/ +typedef struct __REVERBN_FUNC_API_ { + unsigned int (*need_buf)(unsigned int *ptr, REVERBN_PARM_SET *reverb_parm, int sr); + int (*open)(unsigned int *ptr, REVERBN_PARM_SET *reverb_parm, int sr); + int (*init)(unsigned int *ptr, REVERBN_PARM_SET *reverb_parm); + int (*run)(unsigned int *ptr, short *inbuf, short *outdata, int len); +} REVERBN_FUNC_API; + +typedef struct _REVERBN_API_STRUCT_ { + // REVERBN_PARM_SET*reverb_parm_obj; //参数 + REVERBN_PARM_SET parm; //参数 + REVERBN_PARM_SET target_parm; //目标参数 + unsigned int *ptr; //运算buf指针 + REVERBN_FUNC_API *func_api; //函数指针 + struct audio_stream_entry entry; // 音频流入口 + int out_len; + int process_len; + s16 *out_buf; + u8 run_en; + u8 update; + int sr; +} REVERBN_API_STRUCT; + +extern REVERBN_FUNC_API *get_reverbn_func_api(); + + + +#if 1 + +typedef struct _EF_ECHO__PARM_ { + unsigned int delay; //回声的延时时间 0-300ms + unsigned int decayval; // 0-70% + unsigned int filt_enable; //滤波器使能标志 + unsigned int lpf_cutoff; //0-20k + unsigned int wetgain; //0-200% + unsigned int drygain; //0-100% +} ECHO_PARM_SET; + + + +typedef struct _EF_REVERB_FIX_PARM { + unsigned int sr; + unsigned int max_ms; +} EF_REVERB_FIX_PARM; + + + +/*open 跟 run 都是 成功 返回 RET_OK,错误返回 RET_ERR*/ +/*魔音结构体*/ +typedef struct __ECHO_FUNC_API_ { + unsigned int (*need_buf)(unsigned int *ptr, EF_REVERB_FIX_PARM *echo_fix_parm); + int (*open)(unsigned int *ptr, ECHO_PARM_SET *echo_parm, EF_REVERB_FIX_PARM *echo_fix_parm); + int (*init)(unsigned int *ptr, ECHO_PARM_SET *echo_parm); + int (*run)(unsigned int *ptr, short *inbuf, short *outdata, int len); + void (*reset_wetdry)(unsigned int *ptr, int wetgain, int drygain); //新增 +} ECHO_FUNC_API; + +typedef struct _EHCO_API_STRUCT_ { + ECHO_PARM_SET echo_parm_obj; //参数 + ECHO_PARM_SET target_parm; //参数 + EF_REVERB_FIX_PARM echo_fix_parm; + unsigned int *ptr; //运算buf指针 + ECHO_FUNC_API *func_api; //函数指针 + struct audio_stream_entry entry; // 音频流入口 + int out_len; + int process_len; + u8 run_en; + u8 update; +} ECHO_API_STRUCT; + +extern ECHO_FUNC_API *get_echo_func_api(); + +#endif + +#if 1 + +typedef struct _EF_REVERB0_PARM_ { + unsigned int wet; //0-300% //回声的延时时间 0-300ms + unsigned int dry; //0-200% // 0-70% + short damping; //0-100 //影响衰减的频率,值越大衰减越快 + short feedback; //0-100 //feedback越大,衰减越慢 + short roomsize; //0-100 //空间大小 + short highcut_freq;//0-18k + short lowcut_freq; //0-18k +} EF_REVERB0_PARM; + + + +typedef struct _EF_REVERB0_FIX_PARM { + unsigned int sr; +} EF_REVERB0_FIX_PARM; + + + +/*open 跟 run 都是 成功 返回 RET_OK,错误返回 RET_ERR*/ +/*魔音结构体*/ +typedef struct __REVERB0_FUNC_API_ { + unsigned int (*need_buf)(unsigned int *ptr, EF_REVERB0_FIX_PARM *echo_fix_parm); + int (*open)(unsigned int *ptr, EF_REVERB0_PARM *echo_parm, EF_REVERB0_FIX_PARM *echo_fix_parm); + int (*init)(unsigned int *ptr, EF_REVERB0_PARM *echo_parm); + int (*run)(unsigned int *ptr, short *inbuf, short *outdata, int len); +} REVERB0_FUNC_API; + + + +typedef struct _REVERB0_API_STRUCT_ { + EF_REVERB0_PARM reverb_parm_obj; + EF_REVERB0_FIX_PARM reverb_fixparm_obj; //参数 + unsigned int *ptr; //运算buf指针 + REVERB0_FUNC_API *func_api; //函数指针 + struct audio_stream_entry entry; // 音频流入口 + int out_len; + int process_len; + s16 *out_buf; + u8 run_en; + u8 update; +} REVERB0_API_STRUCT; + +extern REVERB0_FUNC_API *get_reverb0_func_api(); +#endif + + + + + +#if 1 + + +typedef struct _Plate_reverb_parm_ { + int wet; //0-300% + int dry; //0-200% + int pre_delay; //0-40ms + int highcutoff; //0-20k 高频截止 + int diffusion; //0-100% + int decayfactor; //0-100% + int highfrequencydamping; //0-100% + int modulate; // 0或1 + int roomsize; //20%-100% +} Plate_reverb_parm; + + + +typedef struct __PLATE_REVERB_FUNC_API_ { + unsigned int (*need_buf)(Plate_reverb_parm *preverb_parm); + int (*open)(unsigned int *ptr, Plate_reverb_parm *preverb_parm, EF_REVERB0_FIX_PARM *echo_fix_parm); + int (*init)(unsigned int *ptr, Plate_reverb_parm *preverb_parm); + int (*run)(unsigned int *ptr, short *inbuf, short *outdata, int len); +} PLATE_REVERB0_FUNC_API; + + + +typedef struct _PLATE_REVERB_API_STRUCT_ { + Plate_reverb_parm reverb_parm_obj; + EF_REVERB0_FIX_PARM reverb_fixparm_obj; //参数 + unsigned int *ptr; //运算buf指针 + PLATE_REVERB0_FUNC_API *func_api; //函数指针 + struct audio_stream_entry entry; // 音频流入口 + int out_len; + int process_len; + s16 *out_buf; + u8 run_en; + u8 update; +} PLATE_REVERB_API_STRUCT; + +extern PLATE_REVERB0_FUNC_API *get_plate_reverb_func_api(); + + + +#endif + + +#endif // reverb_api_h__ diff --git a/include_lib/media/sw_drc.h b/include_lib/media/sw_drc.h new file mode 100644 index 0000000..b8d3dfd --- /dev/null +++ b/include_lib/media/sw_drc.h @@ -0,0 +1,93 @@ +#ifndef __SW_DRC_H +#define __SW_DRC_H + +#include "generic/typedef.h" +#include "generic/list.h" +#include "os/os_api.h" +#include "drc_api.h" + + +//分频器 crossover: +typedef struct _CrossOverParam_TOOL_SET { + int way_num; //段数 + int N; //阶数 + int low_freq; //低中分频点 + int high_freq; //高中分频点 +} CrossOverParam_TOOL_SET; + + +struct threshold_group { + float in_threshold; + float out_threshold; +}; + +struct wdrc_struct { + u16 attacktime; //启动时间 + u16 releasetime; //释放时间 + struct threshold_group threshold[6]; + float inputgain; //wdrc输入数据放大或者缩小的db数(正数放大,负数缩小), 例如配2表示 总体增加2dB + float outputgain; //wdrc输出数据放大或者缩小的db数(正数放大,负数缩小) + u8 threshold_num; + u8 rms_time; + u8 algorithm;//0:PEAK 1:RMS + u8 mode;//0:PERPOINT 1:TWOPOINT + u16 holdtime; //预留位置 + u8 reverved[2];//预留位置 +}; + +//动态范围控制 DRC: +typedef struct _wdrc_struct_TOOL_SET { + int is_bypass; // 1-> byass 0 -> no bypass + struct wdrc_struct parm; +} wdrc_struct_TOOL_SET; + + + +/* //对耳wdrc处理,区分左右声道 */ +// #define L_wdrc 0x10 +// #define LL_wdrc 0x20 +// #define R_wdrc 0x40 +/* #define RR_wdrc 0x80 */ + +struct drc_ch { + CrossOverParam_TOOL_SET crossover; + union { + struct wdrc_struct wdrc[4];//[0]low [1]mid [2]high [3]多带之后,再做一次全带 + } _p; +}; + + +struct sw_drc { + void *work_buf[4]; //drc内部驱动句柄 + void *crossoverBuf; //分频器句柄 + int *run_tmp[3]; //多带限幅器或压缩器,运行buf + int run_tmp_len; //多带限幅器或压缩器,运行buf 长度 + u8 nband; //max<=3,1:全带 2:两段 3:三段 + u8 channel; //通道数 + u8 run32bit; //drc处理输入输出数据位宽是否是32bit 1:32bit 0:16bit + struct audio_eq *crossover[3];//多带分频器eq句柄 + u32 sample_rate; //采样率 + u8 nsection; //分频器eq段数 + u8 other_band_en; //多带限幅器之后,是否需要再做一次全带的限幅器 1:需要,0:不需要 + u8 bypass[4]; +}; +extern void *get_low_sosmatrix(); +extern void *get_high_sosmatrix(); +extern void *get_band_sosmatrix(); +extern int get_crossover_nsection(); + + +void *audio_sw_drc_open(void *crossover, void *wdrc, u32 sample_rate, u8 channel, u8 run32bit, u8 other_band_en); +extern void audio_sw_drc_close(void *hdl); +int audio_sw_drc_update(void *hdl, void *crossover, void *wdrc, u32 sample_rate, u8 channel); +extern int audio_sw_drc_run(void *hdl, s16 *in_buf, s16 *out_buf, int npoint_per_channel); +void sw_drc_set_bypass(struct sw_drc *drc, u8 tar, u8 bypass); + +void audio_hw_crossover_open(struct sw_drc *drc, int (*L_coeff)[3], u8 nsection); +void audio_hw_crossover_close(struct sw_drc *drc); +void audio_hw_crossover_run(struct sw_drc *drc, s16 *data, int len); +void audio_hw_crossover_update(struct sw_drc *drc, int (*L_coeff)[3], u8 nsection); + +void band_merging_32bit(int *in0, int *in1, int *in2, s32 *out_buf_tmp, int points, u8 nband); +void band_merging_16bit(short *in0, short *in1, short *in2, short *out_buf_tmp, int points, u8 nband); +#endif diff --git a/include_lib/media/voiceChanger_api.h b/include_lib/media/voiceChanger_api.h new file mode 100644 index 0000000..a456609 --- /dev/null +++ b/include_lib/media/voiceChanger_api.h @@ -0,0 +1,100 @@ + +#ifndef __pitchshifer_api_h__ +#define __pitchshifer_api_h__ + +#ifndef u8 +#define u8 unsigned char +#endif + +#ifndef u16 +#define u16 unsigned short +#endif + +#ifndef s16 +#define s16 short +#endif + + +#ifndef u32 +#define u32 unsigned int +#endif + + +#ifndef s32 +#define s32 int +#endif + +#ifndef s16 +#define s16 signed short +#endif + +/*#define EFFECT_OLD_RECORD 0x01 +#define EFFECT_MOYIN 0x0*/ +//#define EFFECT_ROBORT_FLAG 0X04 + +enum { + EFFECT_VOICECHANGE_PITCHSHIFT = 0x00, + EFFECT_VOICECHANGE_CARTOON = 0x01, + EFFECT_VOICECHANGE_SPECTRUM = 0x02, + EFFECT_VOICECHANGE_ROBORT = 0x03, + EFFECT_VOICECHANGE_MELODY = 0x04, + EFFECT_VOICECHANGE_WHISPER = 0x05, + EFFECT_VOICECHANGE_F0_DOMAIN = 0x06, + EFFECT_VOICECHANGE_F0_TD = 0x07, + EFFECT_VOICECHANGE_FEEDBACK = 0x08, + EFFECT_VOICECHANGE_NULL = 0xff, +}; + + +enum { + MODE_C_MAJOR = 0x0, + MODE_Cshop_MAJOR, + MODE_D_MAJOR, + MODE_Dshop_MAJOR, + MODE_E_MAJOR, + MODE_F_MAJOR, + MODE_Fshop_MAJOR, + MODE_G_MAJOR, + MODE_Gshop_MAJOR, + MODE_A_MAJOR, + MODE_Ashop_MAJOR, + MODE_B_MAJOR +}; + +enum { + PLATFORM_VOICECHANGE_CORDIC = 0, + PLATFORM_VOICECHANGE_CORDICV2 = 1 +}; + + +typedef struct _VOICECHANGER_PARM { + u32 effect_v; // + u32 shiftv; //pitch rate: 40-250 + u32 formant_shift; // 40-250 +} VOICECHANGER_PARM; + + +typedef struct _AUTOTUNE_PARM { + u32 mode; //调式 +} AUTOTUNE_PARM; + +typedef struct _AUTOTUNE_FUNC_API_ { + u32(*need_buf)(void *ptr, AUTOTUNE_PARM *vc_parm); + void (*open)(void *ptr, u32 sr, AUTOTUNE_PARM *vc_parm); //中途改变参数,可以调init + void (*run)(void *ptr, short *indata, short *outdata, int len); //len是多少个byte + void (*init)(void *ptr, AUTOTUNE_PARM *vc_parm); //中途改变参数,可以调init +} AUTOTUNE_FUNC_API; + + +typedef struct _VOICECHANGER_FUNC_API_ { + u32(*need_buf)(void *ptr, VOICECHANGER_PARM *vc_parm); + void (*open)(void *ptr, u32 sr, VOICECHANGER_PARM *vc_parm); //中途改变参数,可以调init + void (*run)(void *ptr, short *indata, short *outdata, int len); //len是多少个byte + void (*init)(void *ptr, VOICECHANGER_PARM *vc_parm); //中途改变参数,可以调init +} VOICECHANGER_FUNC_API; + +extern VOICECHANGER_FUNC_API *get_voiceChanger_func_api(); +extern AUTOTUNE_FUNC_API *get_autotune_func_api(); + +#endif // reverb_api_h__ + diff --git a/include_lib/system/app_core.h b/include_lib/system/app_core.h new file mode 100644 index 0000000..6c192a6 --- /dev/null +++ b/include_lib/system/app_core.h @@ -0,0 +1,85 @@ +#ifndef SYS_APPLICATION_H +#define SYS_APPLICATION_H + +#include "typedef.h" +#include "generic/list.h" +#include "system/event.h" + + +#define ACTION_BACK 0x0a1b2c00 +#define ACTION_STOP 0x0a1b2c01 +#define ACTION_DO_NOTHING 0x0a1b2c02 +#define ACTION_CLASS_MASK 0xfffff000 + + + +enum app_state { + APP_STA_CREATE, + APP_STA_START, + APP_STA_PAUSE, + APP_STA_RESUME, + APP_STA_STOP, + APP_STA_DESTROY, +}; + +struct application; + + +struct intent { + const char *name; + int action; + const char *data; + u32 exdata; +}; + + +struct application_operation { + int (*state_machine)(struct application *, enum app_state, struct intent *); + int (*event_handler)(struct application *, struct sys_event *); +}; + + +struct application { + u8 state; + int action; + char *data; + const char *name; + struct list_head entry; + void *private_data; + const struct application_operation *ops; +}; + + + +#define REGISTER_APPLICATION(at) \ + static struct application at sec(.app) + + +#define init_intent(it) \ + do { \ + (it)->name = NULL; \ + (it)->action= 0; \ + (it)->data = NULL; \ + (it)->exdata = 0; \ + }while (0) + + + +void register_app_event_handler(int (*handler)(struct sys_event *)); + +struct application *get_current_app(); + +struct application *get_prev_app(); + +void app_core_back_to_prev_app(); + +int start_app(struct intent *it); + +int start_app_async(struct intent *it, void (*callback)(void *p, int err), void *p); + + + + + +#endif + diff --git a/include_lib/system/app_msg.h b/include_lib/system/app_msg.h new file mode 100644 index 0000000..9e41a0c --- /dev/null +++ b/include_lib/system/app_msg.h @@ -0,0 +1,20 @@ +#ifndef SYS_APP_MSG_H +#define SYS_APP_MSG_H + + + + +//app自定义消息发送接口 +int app_task_put_usr_msg(int msg, int arg_num, ...); + +//app消息获取接口(block参数为0表示内部pend,1直接返回) +void app_task_get_msg(int *msg, int msg_size, int block); + +//app按键消息发送接口 +int app_task_put_key_msg(int msg, int value); + +//app清理按键消息接口 +void app_task_clear_key_msg(); + +#endif + diff --git a/include_lib/system/bank_switch.h b/include_lib/system/bank_switch.h new file mode 100644 index 0000000..78f3133 --- /dev/null +++ b/include_lib/system/bank_switch.h @@ -0,0 +1,178 @@ +#ifndef BANK_SWITCH_H +#define BANK_SWITCH_H + +#ifdef CONFIG_CODE_BANK_ENABLE +#define _BANK_ENTRY(num) __attribute__((section(".bank.code."#num))) __attribute__((banknum(num))) +#define __BANK_ENTRY(num) _BANK_ENTRY(num) +#define _BANK_NUM(num) __attribute__((section(".bank.code."#num))) __attribute__((banknum(num))) +#define __BANK_NUM(num) _BANK_NUM(num) +#define __BANK_COMMON() __attribute__((section(".common"))) +#else +#define __BANK_ENTRY(num) +#define __BANK_NUM(num) +#endif + + +#ifdef CONFIG_BANK_COMM +#define __BANK_EDR_RX __BANK_COMMON() +#define __BANK_EDR_TX __BANK_COMMON() +#define __BANK_TWS_LINK __BANK_COMMON() +#define __BANK_EDR_FRAME __BANK_COMMON() +#else +#define __BANK_EDR_RX +#define __BANK_EDR_TX +#define __BANK_TWS_LINK +#define __BANK_EDR_FRAME +#endif + + +#ifdef CONFIG_BANK_NUM_INIT +#define __BANK_INIT_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_INIT) +#define __BANK_INIT __BANK_NUM(CONFIG_BANK_NUM_INIT) +#else +#define __BANK_INIT_ENTRY +#define __BANK_INIT +#endif + +#ifdef CONFIG_BANK_NUM_RF +#define __BANK_RF_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_RF) +#define __BANK_RF __BANK_NUM(CONFIG_BANK_NUM_RF) +#else +#define __BANK_RF_ENTRY +#define __BANK_RF +#endif + + +#ifdef CONFIG_BANK_NUM_RF_TRIM +#define __BANK_RF_TRIM __BANK_NUM(CONFIG_BANK_NUM_RF_TRIM) +#else +#define __BANK_RF_TRIM +#endif + +#ifdef CONFIG_BANK_NUM_DUT +#define __BANK_DUT_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_DUT) +#define __BANK_DUT __BANK_NUM(CONFIG_BANK_NUM_DUT) +#else +#define __BANK_DUT_ENTRY +#define __BANK_DUT +#endif + +#ifdef CONFIG_BANK_NUM_ECDH +#define __BANK_ECDH_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_ECDH) +#define __BANK_ECDH __BANK_NUM(CONFIG_BANK_NUM_ECDH) +#else +#define __BANK_ECDH_ENTRY +#define __BANK_ECDH +#endif + +#ifdef CONFIG_BANK_NUM_ENC +#define __BANK_ENC_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_ENC) +#define __BANK_ENC __BANK_NUM(CONFIG_BANK_NUM_ENC) +#else +#define __BANK_ENC_ENTRY +#define __BANK_ENC +#endif + +#ifdef CONFIG_BANK_NUM_A2DP +#define __BANK_A2DP_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_A2DP) +#define __BANK_A2DP __BANK_NUM(CONFIG_BANK_NUM_A2DP) +#else +#define __BANK_A2DP_ENTRY +#define __BANK_A2DP +#endif + +#ifdef CONFIG_BANK_NUM_AVCTP +#define __BANK_AVCTP_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_AVCTP) +#define __BANK_AVCTP __BANK_NUM(CONFIG_BANK_NUM_AVCTP) +#else +#define __BANK_AVCTP_ENTRY +#define __BANK_AVCTP +#endif + + +#ifdef CONFIG_BANK_NUM_RFCOMM +#define __BANK_RFCOMM_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_RFCOMM) +#define __BANK_RFCOMM __BANK_NUM(CONFIG_BANK_NUM_RFCOMM) +#else +#define __BANK_RFCOMM_ENTRY +#define __BANK_RFCOMM +#endif + + +#ifdef CONFIG_BANK_NUM_SDP +#define __BANK_SDP_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_SDP) +#define __BANK_SDP __BANK_NUM(CONFIG_BANK_NUM_SDP) +#else +#define __BANK_SDP_ENTRY +#define __BANK_SDP +#endif + +#ifdef CONFIG_BANK_NUM_BT_HID +#define __BANK_BT_HID_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_BT_HID) +#define __BANK_BT_HID __BANK_NUM(CONFIG_BANK_NUM_BT_HID) +#else +#define __BANK_BT_HID_ENTRY +#define __BANK_BT_HID +#endif + +#ifdef CONFIG_BANK_NUM_BLE +#define __BANK_BLE_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_BLE) +#define __BANK_BLE __BANK_NUM(CONFIG_BANK_NUM_BLE) +#else +#define __BANK_BLE_ENTRY +#define __BANK_BLE +#endif + +#ifdef CONFIG_BANK_NUM_TWS_BLE +#define __BANK_TWS_BLE_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_TWS_BLE) +#define __BANK_TWS_BLE __BANK_NUM(CONFIG_BANK_NUM_TWS_BLE) +#else +#define __BANK_TWS_BLE_ENTRY +#define __BANK_TWS_BLE +#endif + +#ifdef CONFIG_BANK_NUM_TONE +#define __BANK_TONE_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_TONE) +#define __BANK_TONE __BANK_NUM(CONFIG_BANK_NUM_TONE) +#else +#define __BANK_TONE_ENTRY +#define __BANK_TONE +#endif + +#ifdef CONFIG_BANK_NUM_LMP_SLAVE +#define __BANK_LMP_SLAVE_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_LMP_SLAVE) +#define __BANK_LMP_SLAVE __BANK_NUM(CONFIG_BANK_NUM_LMP_SLAVE) +#else +#define __BANK_LMP_SLAVE_ENTRY +#define __BANK_LMP_SLAVE +#endif + +#ifdef CONFIG_BANK_NUM_LMP_MASTER +#define __BANK_LMP_MASTER_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_LMP_MASTER) +#define __BANK_LMP_MASTER __BANK_NUM(CONFIG_BANK_NUM_LMP_MASTER) +#else +#define __BANK_LMP_MASTER_ENTRY +#define __BANK_LMP_MASTER +#endif + + + + +#ifdef CONFIG_BANK_NUM_CLOCK +#define __BANK_CLOCK_ENTRY __BANK_ENTRY(CONFIG_BANK_NUM_CLOCK) +#define __BANK_CLOCK __BANK_NUM(CONFIG_BANK_NUM_CLOCK) +#else +#define __BANK_CLOCK_ENTRY +#define __BANK_CLOCK +#endif + + + +void load_overlay_code(int num); +void bank_syscall_entry(void); +void load_common_code(void); + + + +#endif + diff --git a/include_lib/system/boot.h b/include_lib/system/boot.h new file mode 100644 index 0000000..6eb839c --- /dev/null +++ b/include_lib/system/boot.h @@ -0,0 +1,72 @@ +#ifndef __BOOT_H__ +#define __BOOT_H__ + + +struct vm_info { +#if (USE_SDFILE_NEW == 1) + u8 align; //from uboot, 按 n * 256 对齐 +#endif + u32 vm_saddr; //from sdfile, flash addr + u32 vm_res; //reverse_bytes + u32 vm_size; //from sdfile +}; + +struct sfc_info { + u32 sfc_base_addr; //flash memory addr, from uboot + u32 app_addr; //cpu logic addr, from uboot +}; + + +#if (USE_SDFILE_NEW == 1) +struct bt_mac_addr { + u8 value[6]; + u16 value_crc; +}; + +typedef struct _boot_info { + struct vm_info vm; + struct sfc_info sfc; + u32 flash_size; //from uboot + u16 chip_id; //from uboot + u16 trim_value; //from uboot + struct bt_mac_addr mac; +} BOOT_INFO; + +//===================================== +struct flash_head { + u16 crc; + u16 size4burner; + u8 vid[4]; //u32 vm_eaddr; + u32 FlashSize; + u8 FsVersion; //flash文件结构 + u8 align; //对齐 n * 256 + u8 res; + u8 SpecialOptFlag; + u8 pid[16]; +}; + +typedef struct boot_device_info { + struct flash_head *fs_info; + struct sfc_info sfc; + u16 chip_id; //from uboot + u16 trim_value; //from uboot + u8 bt_mac_addr[8]; +} BOOT_DEVICE_INFO; + +#else + +typedef struct _boot_info { + struct vm_info vm; + struct sfc_info sfc; + u32 flash_size; //from uboot + u32 size4burner; //from uboot + u16 chip_id; //from uboot + u16 trim_value; //from uboot +} BOOT_INFO; + +#endif /* #if (USE_SDFILE_NEW == 1) */ + +extern BOOT_INFO boot_info; + +#endif + diff --git a/include_lib/system/config/config_interface.h b/include_lib/system/config/config_interface.h new file mode 100644 index 0000000..bda80ef --- /dev/null +++ b/include_lib/system/config/config_interface.h @@ -0,0 +1,30 @@ +/********************************************************************************************* + * Filename : config_interface.h + + * Description : + + * Author : Bingquan + + * Email : bingquan_cai@zh-jieli.com + + * Last modifiled : 2019-01-10 09:55 + + * Copyright:(c)JIELI 2011-2019 @ , All Rights Reserved. +*********************************************************************************************/ +#ifndef _CONFIG_INTERFACE_H_ +#define _CONFIG_INTERFACE_H_ + +#include "config/config_transport.h" +#include "config/config_target.h" + +//配置工具 0:旧工具 1:新工具 +#define NEW_CONFIG_TOOL 1 // + +void config_layer_init(const ci_transport_t *transport, void *config); + +void *config_load(int id); + +void ci_send_packet(u32 id, u8 *packet, int size); + + +#endif diff --git a/include_lib/system/config/config_target.h b/include_lib/system/config/config_target.h new file mode 100644 index 0000000..f4262f7 --- /dev/null +++ b/include_lib/system/config/config_target.h @@ -0,0 +1,43 @@ +/********************************************************************************************* + * Filename : config_target.h + + * Description : + + * Author : Bingquan + + * Email : bingquan_cai@zh-jieli.com + + * Last modifiled : 2019-01-09 19:28 + + * Copyright:(c)JIELI 2011-2017 @ , All Rights Reserved. +*********************************************************************************************/ +#ifndef _CONFIG_TARGET_H_ +#define _CONFIG_TARGET_H_ + +#include "typedef.h" + + +#define EQ_CONFIG_ID 0x0005 +#define EFFECTS_CONFIG_ID 0x0006 +#define AEC_CONFIG_ID 0x0008 + + +typedef void (*ci_packet_handler_t)(uint8_t *packet, uint16_t size); + +struct config_target { + u16 id; + ci_packet_handler_t callback; +}; + +#define REGISTER_CONFIG_TARGET(target) \ + const struct config_target target sec(.config_target) + + +extern const struct config_target config_target_begin[]; +extern const struct config_target config_target_end[]; + +#define list_for_each_config_target(p) \ + for (p = config_target_begin; p < config_target_end; p++) + + +#endif diff --git a/include_lib/system/config/config_transport.h b/include_lib/system/config/config_transport.h new file mode 100644 index 0000000..916c95e --- /dev/null +++ b/include_lib/system/config/config_transport.h @@ -0,0 +1,93 @@ +/********************************************************************************************* + * Filename : config_transport.h + + * Description : Config Interface + + * Author : Bingquan + + * Email : bingquan_cai@zh-jieli.com + + * Last modifiled : 2019-01-07 14:33 + + * Copyright:(c)JIELI 2011-2017 @ , All Rights Reserved. +*********************************************************************************************/ +#ifndef _CI_TRANSPORT_H +#define _CI_TRANSPORT_H + +#include "typedef.h" + +/* CI packet types */ +typedef struct { + /** + * transport name + */ + const char *name; + + /** + * init transport + * @param transport_config + */ + void (*init)(const void *transport_config); + + /** + * open transport connection + */ + int (*open)(void); + + /** + * close transport connection + */ + int (*close)(void); + + /** + * register packet handler for CI packets + */ + void (*register_packet_handler)(void (*handler)(const u8 *packet, int size)); + + /** + * support async transport layers, e.g. IRQ driven without buffers + */ + int (*can_send_packet_now)(uint8_t packet_type); + + /** + * send packet + */ + int (*send_packet)(const u8 *packet, int size); + + /** + * extension for UART transport implementations + */ + int (*set_baudrate)(uint32_t baudrate); +} ci_transport_t; + +typedef enum { + CI_TRANSPORT_CONFIG_UART, + CI_TRANSPORT_CONFIG_USB, + CI_TRANSPORT_CONFIG_BLE, +} ci_transport_config_type_t; + +typedef struct { + ci_transport_config_type_t type; +} ci_transport_config_t; + +typedef struct { + ci_transport_config_type_t type; // == CI_TRANSPORT_CONFIG_UART + uint32_t baudrate_init; // initial baud rate + uint32_t baudrate_main; // = 0: same as initial baudrate + int flowcontrol; // + const char *device_name; +} ci_transport_config_uart_t; + +typedef struct { + //head + u16 id; + u16 length; + + u8 payload[0]; +} _GNU_PACKED_ ci_packet_t; + +#define CI_FORMAT_HEAD sizeof(ci_packet_t) + +const ci_transport_t *ci_transport_uart_instance(void); + +#endif diff --git a/include_lib/system/crypto_toolbox/Crypto_hash.h b/include_lib/system/crypto_toolbox/Crypto_hash.h new file mode 100644 index 0000000..a75c0e7 --- /dev/null +++ b/include_lib/system/crypto_toolbox/Crypto_hash.h @@ -0,0 +1,35 @@ +#ifndef _CRYPTO_HASH_H_ +#define _CRYPTO_HASH_H_ + +#include "generic/typedef.h" + +#define HMAC_SHA_256_SUPPORT_P192 0 +#define HMAC_SHA_256_SUPPORT_P256 1 + +#define HMAC_SHA_256_SUPPORT HMAC_SHA_256_SUPPORT_P192 + +#if (HMAC_SHA_256_SUPPORT == HMAC_SHA_256_SUPPORT_P192) +#define BITS 192 +#endif + +#if (HMAC_SHA_256_SUPPORT == HMAC_SHA_256_SUPPORT_P256) +#define BITS 256 +#endif + + +void g_hash_function(u8 *U, u8 *V, u8 *X, u8 *Y, u8 *output); +void f1_hash_function(u8 *U, u8 *V, u8 *X, u8 *Z, u8 *re); +void f2_hash_function(u8 *W, u8 *N1, u8 *N2, u8 *keyID, u8 *A1, u8 *A2, u8 *re); +void f3_hash_function(u8 *W, u8 *N1, u8 *N2, u8 *R, u8 *IOcap, u8 *A1, u8 *A2, u8 *re); +void h2_hash_function(u8 *W, u8 *KeyID, u8 *L, u8 *re); +void h3_hash_function(u8 *W, u8 *keyID, u8 *A1, u8 *A2, u8 *ACO, u8 *re); +void h4_hash_function(u8 *W, u8 *keyID, u8 *A1, u8 *A2, u8 *re); +void h5_hash_function(u8 *W, u8 *R1, u8 *R2, u8 *re); +void SSP_Heap_init(u8 *p, int len); + +u32 g_function(u8 *U, u8 *V, u8 *X, u8 *Y); +void f1_function(u8 *U, u8 *V, u8 *X, u8 *Z, u8 *re); +void f2_function(u8 *W, u8 *N1, u8 *N2, u8 *A1, u8 *A2, u8 *re); +void f3_function(u8 *W, u8 *N1, u8 *N2, u8 *R, u8 *IOcap, u8 *A1, u8 *A2, u8 *re); + +#endif diff --git a/include_lib/system/crypto_toolbox/aes_cmac.h b/include_lib/system/crypto_toolbox/aes_cmac.h new file mode 100644 index 0000000..f946fef --- /dev/null +++ b/include_lib/system/crypto_toolbox/aes_cmac.h @@ -0,0 +1,10 @@ +#ifndef AES_CMAC_H +#define AES_CMAC_H + +#include +typedef uint8_t sm_key_t[16]; +void aes128_calc_cyphertext(const uint8_t key[16], const uint8_t plaintext[16], uint8_t cyphertext[16]); +void aes_cmac_calc_subkeys(sm_key_t k0, sm_key_t k1, sm_key_t k2); +void aes_cmac(sm_key_t aes_cmac, const sm_key_t key, const uint8_t *data, int sm_cmac_message_len); + +#endif diff --git a/include_lib/system/crypto_toolbox/bigint.h b/include_lib/system/crypto_toolbox/bigint.h new file mode 100644 index 0000000..5b93431 --- /dev/null +++ b/include_lib/system/crypto_toolbox/bigint.h @@ -0,0 +1,92 @@ +#ifndef BIGINT_HEADER +#define BIGINT_HEADER + + +//#include "crypto.h" +#include "bigint_impl.h" + +bigint *alloc(BI_CTX *ctx, int size); +bigint *trim(bigint *bi); +void bi_initialize(BI_CTX *ctx, char *mem_pool); +void bi_terminate(BI_CTX *ctx); +void bi_permanent(bigint *bi); +void bi_depermanent(bigint *bi); +void bi_clear_cache(BI_CTX *ctx); +void bi_free(BI_CTX *ctx, bigint *bi); +bigint *bi_copy(bigint *bi); +bigint *bi_clone(BI_CTX *ctx, const bigint *bi); +void bi_export(BI_CTX *ctx, bigint *bi, u8 *data, int size); +bigint *bi_import(BI_CTX *ctx, const u8 *data, int len); +bigint *int_to_bi(BI_CTX *ctx, comp i); + +/* the functions that actually do something interesting */ +bigint *bi_add(BI_CTX *ctx, bigint *bia, bigint *bib); +bigint *bi_subtract(BI_CTX *ctx, bigint *bia, + bigint *bib, int *is_negative); +bigint *bi_divide(BI_CTX *ctx, bigint *bia, bigint *bim, int is_mod); +bigint *bi_multiply(BI_CTX *ctx, bigint *bia, bigint *bib); +bigint *bi_mod_power(BI_CTX *ctx, bigint *bi, bigint *biexp); +bigint *bi_mod_power2(BI_CTX *ctx, bigint *bi, bigint *bim, bigint *biexp); +int bi_compare(bigint *bia, bigint *bib); +void bi_set_mod(BI_CTX *ctx, bigint *bim, int mod_offset); +void bi_free_mod(BI_CTX *ctx, int mod_offset); +bigint *comp_left_shift(bigint *biR, int num_shifts); +int exp_bit_is_one(bigint *biexp, int offset); +int find_max_exp_index(bigint *biexp); +#ifdef CONFIG_SSL_FULL_MODE +void bi_print(const char *label, bigint *bi); +bigint *bi_str_import(BI_CTX *ctx, const char *data); +#endif + +// +void bi_wirte_to_byte(bigint *bi, unsigned char *out); +bigint *bi_read_from_byte(BI_CTX *ctx, const unsigned char *buf, int len); +bigint *bi_mod_lshift(BI_CTX *ctx, bigint *x, int shift); +void bi_lshift(BI_CTX *ctx, bigint *x, int shift); +bigint *bi_mod_add(BI_CTX *ctx, bigint *a, bigint *b); +bigint *bi_mod_sub(BI_CTX *ctx, bigint *a, bigint *b); +bigint *bi_mod_sqr(BI_CTX *ctx, bigint *x); +bigint *bi_mod_mul(BI_CTX *ctx, bigint *a, bigint *b); +bigint *bi_mod_inverse(BI_CTX *ctx, bigint *x); +// +//void printf_bigint(bigint *x); + +bigint *bi_rshift(bigint *x, int shift); +int bi_is_oneORzero(bigint *x); + +/** + * @def bi_mod + * Find the residue of B. bi_set_mod() must be called before hand. + */ +#define bi_mod(A, B) bi_divide(A, B, ctx->bi_mod[ctx->mod_offset], 1) + +/** + * bi_residue() is technically the same as bi_mod(), but it uses the + * appropriate reduction technique (which is bi_mod() when doing classical + * reduction). + */ +#if defined(CONFIG_BIGINT_MONTGOMERY) +#define bi_residue(A, B) bi_mont(A, B) +bigint *bi_mont(BI_CTX *ctx, bigint *bixy); +#elif defined(CONFIG_BIGINT_BARRETT) +#define bi_residue(A, B) bi_barrett(A, B) +bigint *bi_barrett(BI_CTX *ctx, bigint *bi); +#else /* if defined(CONFIG_BIGINT_CLASSICAL) */ +#define bi_residue(A, B) bi_mod(A, B) +#endif + +#ifdef CONFIG_BIGINT_SQUARE +bigint *bi_square(BI_CTX *ctx, bigint *bi); +#else +#define bi_square(A, B) bi_multiply(A, bi_copy(B), B) +#endif + +#ifdef CONFIG_BIGINT_CRT +bigint *bi_crt(BI_CTX *ctx, bigint *bi, + bigint *dP, bigint *dQ, + bigint *p, bigint *q, + bigint *qInv); +#endif + +#endif + diff --git a/include_lib/system/crypto_toolbox/bigint_impl.h b/include_lib/system/crypto_toolbox/bigint_impl.h new file mode 100644 index 0000000..5631726 --- /dev/null +++ b/include_lib/system/crypto_toolbox/bigint_impl.h @@ -0,0 +1,112 @@ +#ifndef BIGINT_IMPL_HEADER +#define BIGINT_IMPL_HEADER +#include "generic/typedef.h" + +// #include "ssp_config.h" +#define CONFIG_BIGINT_BARRETT 1 +//#define CONFIG_BIGINT_CRT 1 +#define CONFIG_BIGINT_SQUARE 1 +//#define CONFIG_INTEGER_16BIT 1 +//#define CONFIG_BIGINT_SLIDING_WINDOW +//#define CONFIG_BIGINT_MONTGOMERY 1 +//#define CONFIG_BIGINT_KARATSUBA +//#define SQU_KARATSUBA_THRESH 32 +//#define MUL_KARATSUBA_THRESH 64 + +/* Maintain a number of precomputed variables when doing reduction */ +#define BIGINT_M_OFFSET 0 /**< Normal modulo offset. */ +#ifdef CONFIG_BIGINT_CRT +#define BIGINT_P_OFFSET 1 /**< p modulo offset. */ +#define BIGINT_Q_OFFSET 2 /**< q module offset. */ +#define BIGINT_NUM_MODS 3 /**< The number of modulus constants used. */ +#else +#define BIGINT_NUM_MODS 2 +#endif + +/* Architecture specific functions for big ints */ +#if defined(CONFIG_INTEGER_8BIT) +#define COMP_RADIX 256U /**< Max component + 1 */ +#define COMP_MAX 0xFFFFU/**< (Max dbl comp -1) */ +#define COMP_BIT_SIZE 8 /**< Number of bits in a component. */ +#define COMP_BYTE_SIZE 1 /**< Number of bytes in a component. */ +#define COMP_NUM_NIBBLES 2 /**< Used For diagnostics only. */ +typedef u8 comp; /**< A single precision component. */ +typedef u16 long_comp; /**< A double precision component. */ +typedef int16_t slong_comp; /**< A signed double precision component. */ +#elif defined(CONFIG_INTEGER_16BIT) +#define COMP_RADIX 65536U /**< Max component + 1 */ +#define COMP_MAX 0xFFFFFFFFU/**< (Max dbl comp -1) */ +#define COMP_BIT_SIZE 16 /**< Number of bits in a component. */ +#define COMP_BYTE_SIZE 2 /**< Number of bytes in a component. */ +#define COMP_NUM_NIBBLES 4 /**< Used For diagnostics only. */ +typedef u16 comp; /**< A single precision component. */ +typedef u32 long_comp; /**< A double precision component. */ +typedef s32 slong_comp; /**< A signed double precision component. */ +#else /* regular 32 bit */ +#if defined(WIN32) && !defined(__GNUC__) +#define COMP_RADIX 4294967296i64 +#define COMP_MAX 0xFFFFFFFFFFFFFFFFui64 +#else +#define COMP_RADIX 4294967296ULL /**< Max component + 1 */ +#define COMP_MAX 0xFFFFFFFFFFFFFFFFULL/**< (Max dbl comp -1) */ +#endif + +#define COMP_BIT_SIZE 32 /**< Number of bits in a component. */ +#define COMP_BYTE_SIZE 4 /**< Number of bytes in a component. */ +#define COMP_NUM_NIBBLES 8 /**< Used For diagnostics only. */ +typedef u32 comp; /**< A single precision component. */ +typedef unsigned long long long_comp; /**< A double precision component. */ +typedef long long slong_comp; /**< A signed double precision component. */ +#endif + +/** + * @struct _bigint + * @brief A big integer basic object + */ +struct _bigint { + struct _bigint *next; /**< The next bigint in the cache. */ + short size; /**< The number of components in this bigint. */ + short max_comps; /**< The heapsize allocated for this bigint */ + int refs; /**< An internal reference count. */ + comp *comps; /**< A ptr to the actual component data */ +}; + +typedef struct _bigint bigint; /**< An alias for _bigint */ + +/** + * Maintains the state of the cache, and a number of variables used in + * reduction. + */ +typedef struct { /**< A big integer "session" context. */ + bigint *active_list; /**< Bigints currently used. */ + bigint *free_list; /**< Bigints not used. */ + bigint *bi_radix; /**< The radix used. */ + bigint *bi_mod[BIGINT_NUM_MODS]; /**< modulus */ + +#if defined(CONFIG_BIGINT_MONTGOMERY) + bigint *bi_RR_mod_m[BIGINT_NUM_MODS]; /**< R^2 mod m */ + bigint *bi_R_mod_m[BIGINT_NUM_MODS]; /**< R mod m */ + comp N0_dash[BIGINT_NUM_MODS]; +#elif defined(CONFIG_BIGINT_BARRETT) + bigint *bi_mu[BIGINT_NUM_MODS]; /**< Storage for mu */ +#endif + bigint *bi_normalised_mod[BIGINT_NUM_MODS]; /**< Normalised mod storage. */ + bigint **g; /**< Used by sliding-window. */ + int window; /**< The size of the sliding window */ + int active_count; /**< Number of active bigints. */ + int free_count; /**< Number of free bigints. */ + +#ifdef CONFIG_BIGINT_MONTGOMERY + u8 use_classical; /**< Use classical reduction. */ +#endif + u8 mod_offset; /**< The mod offset we are using */ + int np_bit; + char *mem_pool; + int tol_used; +} BI_CTX; + + +#define PERMANENT 0x7FFF55AA /**< A magic number for permanents. */ + +#endif + diff --git a/include_lib/system/crypto_toolbox/crypto.h b/include_lib/system/crypto_toolbox/crypto.h new file mode 100644 index 0000000..598314b --- /dev/null +++ b/include_lib/system/crypto_toolbox/crypto.h @@ -0,0 +1,181 @@ +/** + * @file crypto.h + * @brief General definitions for cryptographic algorithms + * + * @section License + * + * Copyright (C) 2010-2014 Oryx Embedded. All rights reserved. + * + * This file is part of CycloneCrypto Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Oryx Embedded (www.oryx-embedded.com) + * @version 1.5.0 + **/ + +#ifndef _CRYPTO_H +#define _CRYPTO_H + +//Dependencies +//#include "..\ECDH\ssp_typedef.h.h" +#include "endian.h" + + +typedef int error_t; + + + + +//Maximum context size (hash functions) + +#define MAX_HASH_CONTEXT_SIZE sizeof(Sha256Context) + + +//Maximum block size (hash functions) + +#define MAX_HASH_BLOCK_SIZE SHA256_BLOCK_SIZE + + +//Maximum digest size (hash functions) + +#define MAX_HASH_DIGEST_SIZE SHA256_DIGEST_SIZE + +//Rotate left operation +#define ROL32(a, n) (((a) << (n)) | ((a) >> (32 - (n)))) +#define ROL64(a, n) (((a) << (n)) | ((a) >> (64 - (n)))) +//Rotate right operation +#define ROR32(a, n) (((a) >> (n)) | ((a) << (32 - (n)))) +#define ROR64(a, n) (((a) >> (n)) | ((a) << (64 - (n)))) + +//Shift left operation +#define SHL32(a, n) ((a) << (n)) +#define SHL64(a, n) ((a) << (n)) +//Shift right operation +#define SHR32(a, n) ((a) >> (n)) +#define SHR64(a, n) ((a) >> (n)) + + +/** + * @brief Encryption algorithm type + **/ + +//typedef enum +//{ +// CIPHER_ALGO_TYPE_STREAM = 0, +// CIPHER_ALGO_TYPE_BLOCK = 1 +//} CipherAlgoType; + + +/** + * @brief Cipher operation modes + **/ +// +//typedef enum +//{ +// CIPHER_MODE_STREAM = 0, +// CIPHER_MODE_ECB = 1, +// CIPHER_MODE_CBC = 2, +// CIPHER_MODE_CFB = 3, +// CIPHER_MODE_OFB = 4, +// CIPHER_MODE_CTR = 5, +// CIPHER_MODE_CCM = 6, +// CIPHER_MODE_GCM = 7 +//} CipherMode; + + +//Common API for hash algorithms +typedef error_t (*HashAlgoCompute)(const void *data, int length, u8 *digest); +typedef void (*HashAlgoInit)(void *context); +typedef void (*HashAlgoUpdate)(void *context, const void *data, int length); +typedef void (*HashAlgoFinal)(void *context, u8 *digest); + +////Common API for encryption algorithms +//typedef error_t (*CipherAlgoInit)(void *context, const uint8_t *key, size_t keyLength); +//typedef void (*CipherAlgoEncryptStream)(void *context, const uint8_t *input, uint8_t *output, size_t length); +//typedef void (*CipherAlgoDecryptStream)(void *context, const uint8_t *input, uint8_t *output, size_t length); +//typedef void (*CipherAlgoEncryptBlock)(void *context, const uint8_t *input, uint8_t *output); +//typedef void (*CipherAlgoDecryptBlock)(void *context, const uint8_t *input, uint8_t *output); +// +////Common API for pseudo-random number generators +//typedef error_t (*PrngAlgoInit)(void *context); +//typedef void (*PrngAlgoRelease)(void *context); +//typedef error_t (*PrngAlgoSeed)(void *context, const uint8_t *input, size_t length); +//typedef error_t (*PrngAlgoAddEntropy)(void *context, uint_t source, const uint8_t *input, size_t length, size_t entropy); +//typedef error_t (*PrngAlgoRead)(void *context, uint8_t *output, size_t length); + + +/** + * @brief Generic hash algorithm context + **/ + +typedef struct { + u8 digest[1]; +} HashContext; + + +/** + * @brief Common interface for hash algorithms + **/ + +typedef struct { + const s8 *name; + const u8 *oid; + int oidSize; + int contextSize; + int blockSize; + int digestSize; + HashAlgoCompute compute; + HashAlgoInit init; + HashAlgoUpdate update; + HashAlgoFinal final; +} HashAlgo; + + +/** + * @brief Common interface for encryption algorithms + **/ + +//typedef struct +//{ +// const char_t *name; +// size_t contextSize; +// CipherAlgoType type; +// size_t blockSize; +// CipherAlgoInit init; +// CipherAlgoEncryptStream encryptStream; +// CipherAlgoDecryptStream decryptStream; +// CipherAlgoEncryptBlock encryptBlock; +// CipherAlgoDecryptBlock decryptBlock; +//} CipherAlgo; + + +/** + * @brief Common interface for pseudo-random number generators + **/ + +//typedef struct +//{ +// const char_t *name; +// size_t contextSize; +// PrngAlgoInit init; +// PrngAlgoRelease release; +// PrngAlgoSeed seed; +// PrngAlgoAddEntropy addEntropy; +// PrngAlgoRead read; +//} PrngAlgo; + +#endif + diff --git a/include_lib/system/crypto_toolbox/ecdh.h b/include_lib/system/crypto_toolbox/ecdh.h new file mode 100644 index 0000000..98ad6f2 --- /dev/null +++ b/include_lib/system/crypto_toolbox/ecdh.h @@ -0,0 +1,41 @@ +#ifndef _ECDH_H_ +#define _ECDH_H_ + +#include "bigint_impl.h" + +#define ECDH_MEM_POOL_SIZE 0x750 + +typedef struct { + bigint *x; + bigint *y; + bigint *z; + int Z_is_one; + int Z_is_zero; +} EC_POINT; + +struct ECDH_CTX_st { + BI_CTX ctx; + EC_POINT G; + EC_POINT PubKey; + bigint *ECDHKey; + bigint *PriKey; +}; + +typedef struct ECDH_CTX_st ECDH_CTX; +//In:Prikey 24byte +//Out:PubKeyx PubKeyy 24byte +void ecdh_Generate_PublicKey(ECDH_CTX *ecdh_ctx, const unsigned char *PriKey, unsigned char *PubKeyx, unsigned char *PubKeyy); +//In:PublicKeyBx PublicKeyBy 24byte +//Out:DHKey 24byte +void ecdh_Compute_DHKey(ECDH_CTX *ecdh_ctx, unsigned char *PublicKeyBx, unsigned char *PublicKeyBy, unsigned char *DHKey); + +///由于计算和用于发送的buffer存在大小端相反问题,所以再封装一层函数 +void ecdh_PublicKey(ECDH_CTX *ecdh_ctx, const unsigned char *PriKey, unsigned char *PubKeyx, unsigned char *PubKeyy); +void ecdh_DHKey(ECDH_CTX *ecdh_ctx, unsigned char *PublicKeyBx, unsigned char *PublicKeyBy, unsigned char *DHKey); + + +//ECDH_CTX *ecdh_init(void); +void ecdh_init(ECDH_CTX *ec_ctx, char *bigint_mem_pool); +void ecdh_free(ECDH_CTX *ecdh); + +#endif diff --git a/include_lib/system/crypto_toolbox/endian.h b/include_lib/system/crypto_toolbox/endian.h new file mode 100644 index 0000000..9751aed --- /dev/null +++ b/include_lib/system/crypto_toolbox/endian.h @@ -0,0 +1,257 @@ +/** + * @file endian.h + * @brief Byte order conversion + * + * @section License + * + * Copyright (C) 2010-2014 Oryx Embedded. All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Oryx Embedded (www.oryx-embedded.com) + * @version 1.5.0 + **/ + +#ifndef _ENDIAN_H +#define _ENDIAN_H + +//Dependencies +//#include "os_port.h" + +#include "generic/typedef.h" +//#include +//#include "inttypes.h" + +//typedef uint32_t systime_t; +//Compilation flags used to enable/disable features +#define ENABLED (+1) +#define DISABLED (-1) +//Miscellaneous macros +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef LSB +#define LSB(x) ((x) & 0xFF) +#endif + +#ifndef MSB +#define MSB(x) (((x) >> 8) & 0xFF) +#endif + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + + + + +#if 0 +//Load unaligned 16-bit integer (little-endian encoding) +#define LOAD16LE(p) ((uint16_t) (((uint8_t *)(p))[0] | (((uint8_t *)(p))[1] << 8))) + +//Load unaligned 16-bit integer (big-endian encoding) +#define LOAD16BE(p) ((uint16_t) ((((uint8_t *)(p))[0] << 8) | ((uint8_t *)(p))[1])) + +//Load unaligned 24-bit integer (little-endian encoding) +#define LOAD24LE(p) ((uint32_t) (((uint8_t *)(p))[0] | \ + (((uint8_t *)(p))[1] << 8) | (((uint8_t *)(p))[2] << 16))) + +//Load unaligned 24-bit integer (big-endian encoding) +#define LOAD24BE(p) ((uint32_t) ((((uint8_t *)(p))[0] << 16) | \ + (((uint8_t *)(p))[1] << 8) | ((uint8_t *)(p))[2])) + +//Load unaligned 32-bit integer (little-endian encoding) +#define LOAD32LE(p) ((uint32_t) (((uint8_t *)(p))[0] | (((uint8_t *)(p))[1] << 8) | \ + (((uint8_t *)(p))[2] << 16) | (((uint8_t *)(p))[3] << 24))) + +//Load unaligned 32-bit integer (big-endian encoding) +#define LOAD32BE(p) ((uint32_t) ((((uint8_t *)(p))[0] << 24) | (((uint8_t *)(p))[1] << 16) | \ + (((uint8_t *)(p))[2] << 8) | ((uint8_t *)(p))[3])) + +//Store unaligned 16-bit integer (little-endian encoding) +#define STORE16LE(a, p) \ + ((uint8_t *)(p))[0] = (a) & 0xFF, \ + ((uint8_t *)(p))[1] = ((a) >> 8) & 0xFF + +//Store unaligned 32-bit integer (big-endian encoding) +#define STORE16BE(a, p) \ + ((uint8_t *)(p))[0] = ((a) >> 8) & 0xFF, \ + ((uint8_t *)(p))[1] = (a) & 0xFF + +//Store unaligned 24-bit integer (little-endian encoding) +#define STORE24LE(a, p) \ + ((uint8_t *)(p))[0] = (a) & 0xFF, \ + ((uint8_t *)(p))[1] = ((a) >> 8) & 0xFF, \ + ((uint8_t *)(p))[2] = ((a) >> 16) & 0xFF + +//Store unaligned 24-bit integer (big-endian encoding) +#define STORE24BE(a, p) \ + ((uint8_t *)(p))[0] = ((a) >> 16) & 0xFF, \ + ((uint8_t *)(p))[1] = ((a) >> 8) & 0xFF, \ + ((uint8_t *)(p))[2] = (a) & 0xFF + +//Store unaligned 32-bit integer (little-endian encoding) +#define STORE32LE(a, p) \ + ((uint8_t *)(p))[0] = (a) & 0xFF, \ + ((uint8_t *)(p))[1] = ((a) >> 8) & 0xFF, \ + ((uint8_t *)(p))[2] = ((a) >> 16) & 0xFF, \ + ((uint8_t *)(p))[3] = ((a) >> 24) & 0xFF + +//Store unaligned 32-bit integer (big-endian encoding) +#define STORE32BE(a, p) \ + ((uint8_t *)(p))[0] = ((a) >> 24) & 0xFF, \ + ((uint8_t *)(p))[1] = ((a) >> 16) & 0xFF, \ + ((uint8_t *)(p))[2] = ((a) >> 8) & 0xFF, \ + ((uint8_t *)(p))[3] = (a) & 0xFF + +#endif +//Swap a 16-bit integer +#define _SWAP16(x) ( \ + (((x) & 0x00FF) << 8) | \ + (((x) & 0xFF00) >> 8)) + +//Swap a 32-bit integer +#define _SWAP32(x) ( \ + (((x) & 0x000000FFUL) << 24) | \ + (((x) & 0x0000FF00UL) << 8) | \ + (((x) & 0x00FF0000UL) >> 8) | \ + (((x) & 0xFF000000UL) >> 24)) + +//Swap a 64-bit integer +#define _SWAP64(x) ( \ + (((x) & 0x00000000000000FFULL) << 56) | \ + (((x) & 0x000000000000FF00ULL) << 40) | \ + (((x) & 0x0000000000FF0000ULL) << 24) | \ + (((x) & 0x00000000FF000000ULL) << 8) | \ + (((x) & 0x000000FF00000000ULL) >> 8) | \ + (((x) & 0x0000FF0000000000ULL) >> 24) | \ + (((x) & 0x00FF000000000000ULL) >> 40) | \ + (((x) & 0xFF00000000000000ULL) >> 56)) + +#undef NTOHL + +//#define _BIG_ENDIAN +//Big-endian machine? +#ifdef _BIG_ENDIAN + +//Host byte order to network byte order +#define HTONS(value) (value) +#define HTONL(value) (value) +#define htons(value) (value) +#define htonl(value) (value) + +//Network byte order to host byte order +#define NTOHS(value) (value) +#define NTOHL(value) (value) +#define ntohs(value) (value) +#define ntohl(value) (value) + +//Host byte order to little-endian byte order +#define HTOLE16(value) _SWAP16(value) +#define HTOLE32(value) _SWAP32(value) +#define HTOLE64(value) _SWAP64(value) +#define htole16(value) _swap16(value) +#define htole32(value) _swap32(value) +#define htole64(value) _swap64(value) + +//Little-endian byte order to host byte order +#define LETOH16(value) _SWAP16(value) +#define LETOH32(value) _SWAP32(value) +#define LETOH64(value) _SWAP64(value) +#define letoh16(value) _swap16(value) +#define letoh32(value) _swap32(value) +#define letoh64(value) _swap64(value) + +//Host byte order to big-endian byte order +#define HTOBE16(value) (value) +#define HTOBE32(value) (value) +#define HTOBE64(value) (value) +#define htobe16(value) (value) +#define htobe32(value) (value) +#define htobe64(value) (value) + +//Big-endian byte order to host byte order +#define BETOH16(value) (value) +#define BETOH32(value) (value) +#define BETOH64(value) (value) +#define betoh16(value) (value) +#define betoh32(value) (value) +#define betoh64(value) (value) + +//Little-endian machine? +#else + +//Host byte order to network byte order +#define HTONS(value) _SWAP16(value) +#define HTONL(value) _SWAP32(value) +#define htons(value) _swap16(value) +#define htonl(value) _swap32(value) + +//Network byte order to host byte order +#define NTOHS(value) _SWAP16(value) +#define NTOHL(value) _SWAP32(value) +//#define ntohs(value) _swap16(value) +//#define ntohl(value) _swap32(value) + +//Host byte order to little-endian byte order +#define HTOLE16(value) (value) +#define HTOLE32(value) (value) +#define HTOLE64(value) (value) +#define htole16(value) (value) +#define htole32(value) (value) +#define htole64(value) (value) + +//Little-endian byte order to host byte order +#define LETOH16(value) (value) +#define LETOH32(value) (value) +#define LETOH64(value) (value) +#define letoh16(value) (value) +#define letoh32(value) (value) +#define letoh64(value) (value) + +//Host byte order to big-endian byte order +#define HTOBE16(value) _SWAP16(value) +#define HTOBE32(value) _SWAP32(value) +#define HTOBE64(value) _SWAP64(value) +#define htobe16(value) _swap16(value) +#define htobe32(value) _swap32(value) +#define htobe64(value) _swap64(value) + +//Big-endian byte order to host byte order +#define BETOH16(value) _SWAP16(value) +#define BETOH32(value) _SWAP32(value) +#define BETOH64(value) _SWAP64(value) +#define betoh16(value) _swap16(value) +#define betoh32(value) _swap32(value) +#define betoh64(value) _swap64(value) + +#endif + +//Byte order conversion functions +u16 _swap16(u16 value); +u32 _swap32(u32 value); +u64 _swap64(u64 value); + +#endif + diff --git a/include_lib/system/crypto_toolbox/hmac.h b/include_lib/system/crypto_toolbox/hmac.h new file mode 100644 index 0000000..5cfbae1 --- /dev/null +++ b/include_lib/system/crypto_toolbox/hmac.h @@ -0,0 +1,75 @@ +/** + * @file hmac.h + * @brief HMAC (Keyed-Hashing for Message Authentication) + * + * @section License + * + * Copyright (C) 2010-2014 Oryx Embedded. All rights reserved. + * + * This file is part of CycloneCrypto Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Oryx Embedded (www.oryx-embedded.com) + * @version 1.5.0 + **/ + +#ifndef _HMAC_H +#define _HMAC_H + +//Dependencies +#include "crypto.h" +#include "sha256.h" + +//Inner padding (ipad) +#define HMAC_IPAD 0x36 +//Outer padding (opad) +#define HMAC_OPAD 0x5C + + +/** + * @brief HMAC algorithm context + **/ + +typedef struct { + const HashAlgo *hash; + u8 hashContext[MAX_HASH_CONTEXT_SIZE]; + u8 key[MAX_HASH_BLOCK_SIZE]; + u8 digest[MAX_HASH_DIGEST_SIZE]; +} HmacContext; + + +//HMAC related constants +//extern const uint8_t HMAC_WITH_MD5_OID[8]; +//extern const uint8_t HMAC_WITH_TIGER_OID[8]; +//extern const uint8_t HMAC_WITH_RIPEMD160_OID[8]; +//extern const uint8_t HMAC_WITH_SHA1_OID[8]; +//extern const uint8_t HMAC_WITH_SHA224_OID[8]; +//extern const uint8_t HMAC_WITH_SHA256_OID[8]; +//extern const uint8_t HMAC_WITH_SHA384_OID[8]; +//extern const uint8_t HMAC_WITH_SHA512_OID[8]; + +//HMAC related functions +error_t hmacCompute(const HashAlgo *hash, const void *key, int keyLength, + const void *data, int dataLength, u8 *digest); + +void hmacInit(HmacContext *context, const HashAlgo *hash, + const void *key, int length); + +void hmacUpdate(HmacContext *context, const void *data, int length); +void hmacFinal(HmacContext *context, u8 *digest); + +#endif + diff --git a/include_lib/system/crypto_toolbox/micro-ecc/uECC.h b/include_lib/system/crypto_toolbox/micro-ecc/uECC.h new file mode 100644 index 0000000..8cbefe2 --- /dev/null +++ b/include_lib/system/crypto_toolbox/micro-ecc/uECC.h @@ -0,0 +1,321 @@ +/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _MICRO_ECC_H_ +#define _MICRO_ECC_H_ + +// BK +// Configuration of micro-ecc for use with BTstack +// +// We only need/use SECP256R1 for LE Secure Connections +#define uECC_CURVE uECC_secp192r1 //uECC_secp256r1 + +// optimization: size vs. speed: uECC_asm_none - uECC_asm_small - uECC_asm_fast +#ifndef uECC_ASM +#define uECC_ASM uECC_asm_none +#endif + +// don't use special square functions +#ifndef uECC_SQUARE_FUNC +#define uECC_SQUARE_FUNC 0 +#endif + + +// + +#include + +/* Platform selection options. +If uECC_PLATFORM is not defined, the code will try to guess it based on compiler macros. +Possible values for uECC_PLATFORM are defined below: */ +#define uECC_arch_other 0 +#define uECC_x86 1 +#define uECC_x86_64 2 +#define uECC_arm 3 +#define uECC_arm_thumb 4 +#define uECC_avr 5 +#define uECC_arm_thumb2 6 + +/* If desired, you can define uECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes). +If uECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your +platform. */ + +/* Inline assembly options. +uECC_asm_none - Use standard C99 only. +uECC_asm_small - Use GCC inline assembly for the target platform (if available), optimized for + minimum size. +uECC_asm_fast - Use GCC inline assembly optimized for maximum speed. */ +#define uECC_asm_none 0 +#define uECC_asm_small 1 +#define uECC_asm_fast 2 +#ifndef uECC_ASM +#define uECC_ASM uECC_asm_fast +#endif + +/* Curve selection options. */ +#define uECC_secp160r1 1 +#define uECC_secp192r1 2 +#define uECC_secp256r1 3 +#define uECC_secp256k1 4 +#define uECC_secp224r1 5 +#ifndef uECC_CURVE +#define uECC_CURVE uECC_secp160r1 +#endif + +/* uECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a specific function to be +used for (scalar) squaring instead of the generic multiplication function. This will make things +faster by about 8% but increases the code size. */ +#ifndef uECC_SQUARE_FUNC +#define uECC_SQUARE_FUNC 1 +#endif + +#define uECC_CONCAT1(a, b) a##b +#define uECC_CONCAT(a, b) uECC_CONCAT1(a, b) + +#define uECC_size_1 20 /* secp160r1 */ +#define uECC_size_2 24 /* secp192r1 */ +#define uECC_size_3 32 /* secp256r1 */ +#define uECC_size_4 32 /* secp256k1 */ +#define uECC_size_5 28 /* secp224r1 */ + +#define uECC_BYTES uECC_CONCAT(uECC_size_, uECC_CURVE) + +#ifdef __cplusplus +extern "C" +{ +#endif + +/* uECC_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 uECC_set_rng()) before calling +uECC_make_key() or uECC_sign(). + +Setting a correctly functioning RNG function improves the resistance to side-channel attacks +for uECC_shared_secret() and uECC_sign_deterministic(). + +A correct RNG function is set by default when building for Windows, Linux, or OS X. +If you are building on another POSIX-compliant system that supports /dev/random or /dev/urandom, +you can define uECC_POSIX to use the predefined RNG. For embedded platforms there is no predefined +RNG function; you must provide your own. +*/ +typedef int (*uECC_RNG_Function)(uint8_t *dest, unsigned size); + +/* uECC_set_rng() function. +Set the function that will be used to generate random bytes. The RNG function should +return 1 if the random data was generated, or 0 if the random data could not be generated. + +On platforms where there is no predefined RNG function (eg embedded platforms), this must +be called before uECC_make_key() or uECC_sign() are used. + +Inputs: + rng_function - The function that will be used to generate random bytes. +*/ +void uECC_set_rng(uECC_RNG_Function rng_function); + +/* uECC_make_key() function. +Create a public/private key pair. + +Outputs: + public_key - Will be filled in with the public key. + private_key - Will be filled in with the private key. + +Returns 1 if the key pair was generated successfully, 0 if an error occurred. +*/ +int uECC_make_key(uint8_t public_key[uECC_BYTES * 2], uint8_t private_key[uECC_BYTES]); + +/* uECC_shared_secret() function. +Compute a shared secret given your secret key and someone else's public key. +Note: It is recommended that you hash the result of uECC_shared_secret() before using it for +symmetric encryption or HMAC. + +Inputs: + public_key - The public key of the remote party. + private_key - Your private key. + +Outputs: + secret - Will be filled in with the shared secret value. + +Returns 1 if the shared secret was generated successfully, 0 if an error occurred. +*/ +int uECC_shared_secret(const uint8_t public_key[uECC_BYTES * 2], + const uint8_t private_key[uECC_BYTES], + uint8_t secret[uECC_BYTES]); + +/* uECC_sign() function. +Generate an ECDSA signature for a given hash value. + +Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to +this function along with your private key. + +Inputs: + private_key - Your private key. + message_hash - The hash of the message to sign. + +Outputs: + signature - Will be filled in with the signature value. + +Returns 1 if the signature generated successfully, 0 if an error occurred. +*/ +int uECC_sign(const uint8_t private_key[uECC_BYTES], + const uint8_t message_hash[uECC_BYTES], + uint8_t signature[uECC_BYTES * 2]); + +/* uECC_HashContext structure. +This is used to pass in an arbitrary hash function to uECC_sign_deterministic(). +The structure will be used for multiple hash computations; each time a new hash +is computed, init_hash() will be called, followed by one or more calls to +update_hash(), and finally a call to finish_hash() to prudoce the resulting hash. + +The intention is that you will create a structure that includes uECC_HashContext +followed by any hash-specific data. For example: + +typedef struct SHA256_HashContext { + uECC_HashContext uECC; + SHA256_CTX ctx; +} SHA256_HashContext; + +void init_SHA256(uECC_HashContext *base) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Init(&context->ctx); +} + +void update_SHA256(uECC_HashContext *base, + const uint8_t *message, + unsigned message_size) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Update(&context->ctx, message, message_size); +} + +void finish_SHA256(uECC_HashContext *base, uint8_t *hash_result) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Final(hash_result, &context->ctx); +} + +... when signing ... +{ + uint8_t tmp[32 + 32 + 64]; + SHA256_HashContext ctx = {{&init_SHA256, &update_SHA256, &finish_SHA256, 64, 32, tmp}}; + uECC_sign_deterministic(key, message_hash, &ctx.uECC, signature); +} +*/ +typedef struct uECC_HashContext { + void (*init_hash)(struct uECC_HashContext *context); + void (*update_hash)(struct uECC_HashContext *context, + const uint8_t *message, + unsigned message_size); + void (*finish_hash)(struct uECC_HashContext *context, uint8_t *hash_result); + unsigned block_size; /* Hash function block size in bytes, eg 64 for SHA-256. */ + unsigned result_size; /* Hash function result size in bytes, eg 32 for SHA-256. */ + uint8_t *tmp; /* Must point to a buffer of at least (2 * result_size + block_size) bytes. */ +} uECC_HashContext; + +/* uECC_sign_deterministic() function. +Generate an ECDSA signature for a given hash value, using a deterministic algorithm +(see RFC 6979). You do not need to set the RNG using uECC_set_rng() before calling +this function; however, if the RNG is defined it will improve resistance to side-channel +attacks. + +Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to +this function along with your private key and a hash context. + +Inputs: + private_key - Your private key. + message_hash - The hash of the message to sign. + hash_context - A hash context to use. + +Outputs: + signature - Will be filled in with the signature value. + +Returns 1 if the signature generated successfully, 0 if an error occurred. +*/ +int uECC_sign_deterministic(const uint8_t private_key[uECC_BYTES], + const uint8_t message_hash[uECC_BYTES], + uECC_HashContext *hash_context, + uint8_t signature[uECC_BYTES * 2]); + +/* uECC_verify() function. +Verify an ECDSA signature. + +Usage: Compute the hash of the signed data using the same hash as the signer and +pass it to this function along with the signer's public key and the signature values (r and s). + +Inputs: + public_key - The signer's public key + hash - The hash of the signed data. + signature - The signature value. + +Returns 1 if the signature is valid, 0 if it is invalid. +*/ +int uECC_verify(const uint8_t public_key[uECC_BYTES * 2], + const uint8_t hash[uECC_BYTES], + const uint8_t signature[uECC_BYTES * 2]); + +/* uECC_compress() function. +Compress a public key. + +Inputs: + public_key - The public key to compress. + +Outputs: + compressed - Will be filled in with the compressed public key. +*/ +void uECC_compress(const uint8_t public_key[uECC_BYTES * 2], uint8_t compressed[uECC_BYTES + 1]); + +/* uECC_decompress() function. +Decompress a compressed public key. + +Inputs: + compressed - The compressed public key. + +Outputs: + public_key - Will be filled in with the decompressed public key. +*/ +void uECC_decompress(const uint8_t compressed[uECC_BYTES + 1], uint8_t public_key[uECC_BYTES * 2]); + +/* uECC_valid_public_key() function. +Check to see if a public key is valid. + +Note that you are not required to check for a valid public key before using any other uECC +functions. However, you may wish to avoid spending CPU time computing a shared secret or +verifying a signature using an invalid public key. + +Inputs: + public_key - The public key to check. + +Returns 1 if the public key is valid, 0 if it is invalid. +*/ +int uECC_valid_public_key(const uint8_t public_key[uECC_BYTES * 2]); + +/* uECC_compute_public_key() function. +Compute the corresponding public key for a private key. + +Inputs: + private_key - The private key to compute the public key for + +Outputs: + public_key - Will be filled in with the corresponding public key + +Returns 1 if the key was computed successfully, 0 if an error occurred. +*/ +int uECC_compute_public_key(const uint8_t private_key[uECC_BYTES], + uint8_t public_key[uECC_BYTES * 2]); + + +/* uECC_bytes() function. +Returns the value of uECC_BYTES. Helpful for foreign-interfaces to higher-level languages. +*/ +int uECC_bytes(void); + +/* uECC_curve() function. +Returns the value of uECC_CURVE. Helpful for foreign-interfaces to higher-level languages. +*/ +int uECC_curve(void); + + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* _MICRO_ECC_H_ */ diff --git a/include_lib/system/crypto_toolbox/micro-ecc/uECC_new.h b/include_lib/system/crypto_toolbox/micro-ecc/uECC_new.h new file mode 100644 index 0000000..42766f0 --- /dev/null +++ b/include_lib/system/crypto_toolbox/micro-ecc/uECC_new.h @@ -0,0 +1,365 @@ +/* Copyright 2014, Kenneth MacKay. Licensed under the BSD 2-clause license. */ + +#ifndef _UECC_H_ +#define _UECC_H_ + +// #include + +/* Platform selection options. +If uECC_PLATFORM is not defined, the code will try to guess it based on compiler macros. +Possible values for uECC_PLATFORM are defined below: */ +#define uECC_arch_other 0 +#define uECC_x86 1 +#define uECC_x86_64 2 +#define uECC_arm 3 +#define uECC_arm_thumb 4 +#define uECC_arm_thumb2 5 +#define uECC_arm64 6 +#define uECC_avr 7 + +/* If desired, you can define uECC_WORD_SIZE as appropriate for your platform (1, 4, or 8 bytes). +If uECC_WORD_SIZE is not explicitly defined then it will be automatically set based on your +platform. */ + +/* Optimization level; trade speed for code size. + Larger values produce code that is faster but larger. + Currently supported values are 0 - 4; 0 is unusably slow for most applications. + Optimization level 4 currently only has an effect ARM platforms where more than one + curve is enabled. */ +#ifndef uECC_OPTIMIZATION_LEVEL + #define uECC_OPTIMIZATION_LEVEL 2 +#endif + +/* uECC_SQUARE_FUNC - If enabled (defined as nonzero), this will cause a specific function to be +used for (scalar) squaring instead of the generic multiplication function. This can make things +faster somewhat faster, but increases the code size. */ +#ifndef uECC_SQUARE_FUNC + #define uECC_SQUARE_FUNC 0 +#endif + +/* uECC_VLI_NATIVE_LITTLE_ENDIAN - If enabled (defined as nonzero), this will switch to native +little-endian format for *all* arrays passed in and out of the public API. This includes public +and private keys, shared secrets, signatures and message hashes. +Using this switch reduces the amount of call stack memory used by uECC, since less intermediate +translations are required. +Note that this will *only* work on native little-endian processors and it will treat the uint8_t +arrays passed into the public API as word arrays, therefore requiring the provided byte arrays +to be word aligned on architectures that do not support unaligned accesses. +IMPORTANT: Keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=1 are incompatible +with keys and signatures generated with uECC_VLI_NATIVE_LITTLE_ENDIAN=0; all parties must use +the same endianness. */ +#ifndef uECC_VLI_NATIVE_LITTLE_ENDIAN + #define uECC_VLI_NATIVE_LITTLE_ENDIAN 0 +#endif + +/* Curve support selection. Set to 0 to remove that curve. */ +#ifndef uECC_SUPPORTS_secp160r1 + #define uECC_SUPPORTS_secp160r1 1 +#endif +#ifndef uECC_SUPPORTS_secp192r1 + #define uECC_SUPPORTS_secp192r1 1 +#endif +#ifndef uECC_SUPPORTS_secp224r1 + #define uECC_SUPPORTS_secp224r1 1 +#endif +#ifndef uECC_SUPPORTS_secp256r1 + #define uECC_SUPPORTS_secp256r1 1 +#endif +#ifndef uECC_SUPPORTS_secp256k1 + #define uECC_SUPPORTS_secp256k1 1 +#endif + +/* Specifies whether compressed point format is supported. + Set to 0 to disable point compression/decompression functions. */ +#ifndef uECC_SUPPORT_COMPRESSED_POINT + #define uECC_SUPPORT_COMPRESSED_POINT 0 +#endif + +struct uECC_Curve_t; +typedef const struct uECC_Curve_t * uECC_Curve; + +#ifdef __cplusplus +extern "C" +{ +#endif + +#if uECC_SUPPORTS_secp160r1 +uECC_Curve uECC_secp160r1(void); +#endif +#if uECC_SUPPORTS_secp192r1 +uECC_Curve uECC_secp192r1(void); +#endif +#if uECC_SUPPORTS_secp224r1 +uECC_Curve uECC_secp224r1(void); +#endif +#if uECC_SUPPORTS_secp256r1 +uECC_Curve uECC_secp256r1(void); +#endif +#if uECC_SUPPORTS_secp256k1 +uECC_Curve uECC_secp256k1(void); +#endif + +/* uECC_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 uECC_set_rng()) before calling +uECC_make_key() or uECC_sign(). + +Setting a correctly functioning RNG function improves the resistance to side-channel attacks +for uECC_shared_secret() and uECC_sign_deterministic(). + +A correct RNG function is set by default when building for Windows, Linux, or OS X. +If you are building on another POSIX-compliant system that supports /dev/random or /dev/urandom, +you can define uECC_POSIX to use the predefined RNG. For embedded platforms there is no predefined +RNG function; you must provide your own. +*/ +typedef int (*uECC_RNG_Function)(uint8_t *dest, unsigned size); + +/* uECC_set_rng() function. +Set the function that will be used to generate random bytes. The RNG function should +return 1 if the random data was generated, or 0 if the random data could not be generated. + +On platforms where there is no predefined RNG function (eg embedded platforms), this must +be called before uECC_make_key() or uECC_sign() are used. + +Inputs: + rng_function - The function that will be used to generate random bytes. +*/ +void uECC_set_rng(uECC_RNG_Function rng_function); + +/* uECC_get_rng() function. + +Returns the function that will be used to generate random bytes. +*/ +uECC_RNG_Function uECC_get_rng(void); + +/* uECC_curve_private_key_size() function. + +Returns the size of a private key for the curve in bytes. +*/ +int uECC_curve_private_key_size(uECC_Curve curve); + +/* uECC_curve_public_key_size() function. + +Returns the size of a public key for the curve in bytes. +*/ +int uECC_curve_public_key_size(uECC_Curve curve); + +/* uECC_make_key() function. +Create a public/private key pair. + +Outputs: + public_key - Will be filled in with the public key. Must be at least 2 * the curve size + (in bytes) long. For example, if the curve is secp256r1, public_key must be 64 + bytes long. + private_key - Will be filled in with the private key. Must be as long as the curve order; this + is typically the same as the curve size, except for secp160r1. For example, if the + curve is secp256r1, private_key must be 32 bytes long. + + For secp160r1, private_key must be 21 bytes long! Note that the first byte will + almost always be 0 (there is about a 1 in 2^80 chance of it being non-zero). + +Returns 1 if the key pair was generated successfully, 0 if an error occurred. +*/ +int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve); + +/* uECC_shared_secret() function. +Compute a shared secret given your secret key and someone else's public key. +Note: It is recommended that you hash the result of uECC_shared_secret() before using it for +symmetric encryption or HMAC. + +Inputs: + public_key - The public key of the remote party. + private_key - Your private key. + +Outputs: + secret - Will be filled in with the shared secret value. Must be the same size as the + curve size; for example, if the curve is secp256r1, secret must be 32 bytes long. + +Returns 1 if the shared secret was generated successfully, 0 if an error occurred. +*/ +int uECC_shared_secret(const uint8_t *public_key, + const uint8_t *private_key, + uint8_t *secret, + uECC_Curve curve); + +#if uECC_SUPPORT_COMPRESSED_POINT +/* uECC_compress() function. +Compress a public key. + +Inputs: + public_key - The public key to compress. + +Outputs: + compressed - Will be filled in with the compressed public key. Must be at least + (curve size + 1) bytes long; for example, if the curve is secp256r1, + compressed must be 33 bytes long. +*/ +void uECC_compress(const uint8_t *public_key, uint8_t *compressed, uECC_Curve curve); + +/* uECC_decompress() function. +Decompress a compressed public key. + +Inputs: + compressed - The compressed public key. + +Outputs: + public_key - Will be filled in with the decompressed public key. +*/ +void uECC_decompress(const uint8_t *compressed, uint8_t *public_key, uECC_Curve curve); +#endif /* uECC_SUPPORT_COMPRESSED_POINT */ + +/* uECC_valid_public_key() function. +Check to see if a public key is valid. + +Note that you are not required to check for a valid public key before using any other uECC +functions. However, you may wish to avoid spending CPU time computing a shared secret or +verifying a signature using an invalid public key. + +Inputs: + public_key - The public key to check. + +Returns 1 if the public key is valid, 0 if it is invalid. +*/ +int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve); + +/* uECC_compute_public_key() function. +Compute the corresponding public key for a private key. + +Inputs: + private_key - The private key to compute the public key for + +Outputs: + public_key - Will be filled in with the corresponding public key + +Returns 1 if the key was computed successfully, 0 if an error occurred. +*/ +int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key, uECC_Curve curve); + +/* uECC_sign() function. +Generate an ECDSA signature for a given hash value. + +Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it in to +this function along with your private key. + +Inputs: + private_key - Your private key. + message_hash - The hash of the message to sign. + hash_size - The size of message_hash in bytes. + +Outputs: + signature - Will be filled in with the signature value. Must be at least 2 * curve size long. + For example, if the curve is secp256r1, signature must be 64 bytes long. + +Returns 1 if the signature generated successfully, 0 if an error occurred. +*/ +int uECC_sign(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + uint8_t *signature, + uECC_Curve curve); + +/* uECC_HashContext structure. +This is used to pass in an arbitrary hash function to uECC_sign_deterministic(). +The structure will be used for multiple hash computations; each time a new hash +is computed, init_hash() will be called, followed by one or more calls to +update_hash(), and finally a call to finish_hash() to produce the resulting hash. + +The intention is that you will create a structure that includes uECC_HashContext +followed by any hash-specific data. For example: + +typedef struct SHA256_HashContext { + uECC_HashContext uECC; + SHA256_CTX ctx; +} SHA256_HashContext; + +void init_SHA256(uECC_HashContext *base) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Init(&context->ctx); +} + +void update_SHA256(uECC_HashContext *base, + const uint8_t *message, + unsigned message_size) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Update(&context->ctx, message, message_size); +} + +void finish_SHA256(uECC_HashContext *base, uint8_t *hash_result) { + SHA256_HashContext *context = (SHA256_HashContext *)base; + SHA256_Final(hash_result, &context->ctx); +} + +... when signing ... +{ + uint8_t tmp[32 + 32 + 64]; + SHA256_HashContext ctx = {{&init_SHA256, &update_SHA256, &finish_SHA256, 64, 32, tmp}}; + uECC_sign_deterministic(key, message_hash, &ctx.uECC, signature); +} +*/ +typedef struct uECC_HashContext { + void (*init_hash)(const struct uECC_HashContext *context); + void (*update_hash)(const struct uECC_HashContext *context, + const uint8_t *message, + unsigned message_size); + void (*finish_hash)(const struct uECC_HashContext *context, uint8_t *hash_result); + unsigned block_size; /* Hash function block size in bytes, eg 64 for SHA-256. */ + unsigned result_size; /* Hash function result size in bytes, eg 32 for SHA-256. */ + uint8_t *tmp; /* Must point to a buffer of at least (2 * result_size + block_size) bytes. */ +} uECC_HashContext; + +/* uECC_sign_deterministic() function. +Generate an ECDSA signature for a given hash value, using a deterministic algorithm +(see RFC 6979). You do not need to set the RNG using uECC_set_rng() before calling +this function; however, if the RNG is defined it will improve resistance to side-channel +attacks. + +Usage: Compute a hash of the data you wish to sign (SHA-2 is recommended) and pass it to +this function along with your private key and a hash context. Note that the message_hash +does not need to be computed with the same hash function used by hash_context. + +Inputs: + private_key - Your private key. + message_hash - The hash of the message to sign. + hash_size - The size of message_hash in bytes. + hash_context - A hash context to use. + +Outputs: + signature - Will be filled in with the signature value. + +Returns 1 if the signature generated successfully, 0 if an error occurred. +*/ +int uECC_sign_deterministic(const uint8_t *private_key, + const uint8_t *message_hash, + unsigned hash_size, + const uECC_HashContext *hash_context, + uint8_t *signature, + uECC_Curve curve); + +/* uECC_verify() function. +Verify an ECDSA signature. + +Usage: Compute the hash of the signed data using the same hash as the signer and +pass it to this function along with the signer's public key and the signature values (r and s). + +Inputs: + public_key - The signer's public key. + message_hash - The hash of the signed data. + hash_size - The size of message_hash in bytes. + signature - The signature value. + +Returns 1 if the signature is valid, 0 if it is invalid. +*/ +int uECC_verify(const uint8_t *public_key, + const uint8_t *message_hash, + unsigned hash_size, + const uint8_t *signature, + uECC_Curve curve); + +#ifdef __cplusplus +} /* end of extern "C" */ +#endif + +#endif /* _UECC_H_ */ diff --git a/include_lib/system/crypto_toolbox/rijndael.h b/include_lib/system/crypto_toolbox/rijndael.h new file mode 100644 index 0000000..e40a1f0 --- /dev/null +++ b/include_lib/system/crypto_toolbox/rijndael.h @@ -0,0 +1,23 @@ +// =============================== RIJNDAEL.H =============================== +// from http://www.efgh.com/software/rijndael.htm, +// License: Public Domain, +// Author: Philip J. Erdelsky + +#ifndef H__RIJNDAEL +#define H__RIJNDAEL + +#include + +int rijndaelSetupEncrypt(uint32_t *rk, const uint8_t *key, int keybits); +int rijndaelSetupDecrypt(uint32_t *rk, const uint8_t *key, int keybits); +void rijndaelEncrypt(const uint32_t *rk, int nrounds, const uint8_t plaintext[16], uint8_t ciphertext[16]); +void rijndaelDecrypt(const uint32_t *rk, int nrounds, const uint8_t ciphertext[16], uint8_t plaintext[16]); + +#define KEYBITS 128 + +#define KEYLENGTH(keybits) ((keybits)/8) +#define RKLENGTH(keybits) ((keybits)/8+28) +#define NROUNDS(keybits) ((keybits)/32+6) + +#endif + diff --git a/include_lib/system/crypto_toolbox/sha256.h b/include_lib/system/crypto_toolbox/sha256.h new file mode 100644 index 0000000..f0d5991 --- /dev/null +++ b/include_lib/system/crypto_toolbox/sha256.h @@ -0,0 +1,72 @@ +/** + * @file sha256.h + * @brief SHA-256 (Secure Hash Algorithm 256) + * + * @section License + * + * Copyright (C) 2010-2014 Oryx Embedded. All rights reserved. + * + * This file is part of CycloneCrypto Open. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * @author Oryx Embedded (www.oryx-embedded.com) + * @version 1.5.0 + **/ + +#ifndef _SHA256_H +#define _SHA256_H + +//Dependencies +#include "crypto.h" + +//SHA-256 block size +#define SHA256_BLOCK_SIZE 64 +//SHA-256 digest size +#define SHA256_DIGEST_SIZE 32 +//Common interface for hash algorithms +#define SHA256_HASH_ALGO (&sha256HashAlgo) + + +/** + * @brief SHA-256 algorithm context + **/ + +typedef struct { + union { + u32 h[8]; + u8 digest[32]; + }; + union { + u32 w[64]; + u8 buffer[64]; + }; + int size; + u64 totalSize; +} Sha256Context; + + +//SHA-256 related constants +extern const HashAlgo sha256HashAlgo; + +//SHA-256 related functions +int sha256Compute(const void *data, int length, u8 *digest); +void sha256Init(Sha256Context *context); +void sha256Update(Sha256Context *context, const void *data, int length); +void sha256Final(Sha256Context *context, u8 *digest); +void sha256ProcessBlock(Sha256Context *context); + +#endif + diff --git a/include_lib/system/database.h b/include_lib/system/database.h new file mode 100644 index 0000000..bd7b2c5 --- /dev/null +++ b/include_lib/system/database.h @@ -0,0 +1,34 @@ +#ifndef DATABASE_H +#define DATABASE_H + +#include "typedef.h" + + +struct db_table { + const char *name; + u8 value_bits; + int value; +}; + + +int db_select_buffer(u8 index, char *buffer, int len); + +int db_update_buffer(u8 index, char *buffer, int len); + +int db_create(const char *store_dev); + + +int db_create_table(const struct db_table *table, int num); + +u32 db_select(const char *table); + +int db_update(const char *table, u32 value); + +int db_flush(); + +int db_reset(); + +int db_erase(); + +#endif + diff --git a/include_lib/system/debug.h b/include_lib/system/debug.h new file mode 100644 index 0000000..64c0603 --- /dev/null +++ b/include_lib/system/debug.h @@ -0,0 +1,142 @@ +#ifndef _DEBUG_H_ +#define _DEBUG_H_ + +#include "asm/cpu.h" +#include "generic/typedef.h" + +#define LOG_ASSERT_ENABLE + +void printf_buf(u8 *buf, u32 len); + +#define PRINTF(format, ...) printf(format, ## __VA_ARGS__) + +#define LOG_VERBOSE v +#define LOG_INFO i +#define LOG_DEBUG d +#define LOG_WARN w +#define LOG_ERROR e +#define LOG_CHAR c + +#define _STR(x) #x +#define STR(x) "["_STR(x)"]" + + +#define _LOG_TAG_CONST_DECLARE(level, name) extern const char log_tag_const_##level##_##name +#define LOG_TAG_CONST_DECLARE(level, name) _LOG_TAG_CONST_DECLARE(level, name) + +#define ___LOG_IS_ENABLE(level, name) (log_tag_const_##level##_##name) +#define __LOG_IS_ENABLE(level, name) ___LOG_IS_ENABLE(level, name) +#define _LOG_IS_ENABLE(level) __LOG_IS_ENABLE(level, LOG_TAG_CONST) + +#ifdef LOG_TAG_CONST +LOG_TAG_CONST_DECLARE(LOG_VERBOSE, LOG_TAG_CONST); +LOG_TAG_CONST_DECLARE(LOG_INFO, LOG_TAG_CONST); +LOG_TAG_CONST_DECLARE(LOG_DEBUG, LOG_TAG_CONST); +LOG_TAG_CONST_DECLARE(LOG_WARN, LOG_TAG_CONST); +LOG_TAG_CONST_DECLARE(LOG_ERROR, LOG_TAG_CONST); +LOG_TAG_CONST_DECLARE(LOG_CHAR, LOG_TAG_CONST); +#define _LOG_TAG STR(LOG_TAG_CONST) +#define LOG_IS_ENABLE(level) _LOG_IS_ENABLE(level) + +#else +#define _LOG_TAG LOG_TAG +#define LOG_IS_ENABLE(x) 1 +#endif + + +#define LOG_BY_MACRO 1 +#define LOG_BY_CONST 2 + +// #define LOG_MODE LOG_BY_MACRO +#define LOG_MODE LOG_BY_CONST + +/* + * LOG 通过宏控制 + */ +#if (LOG_MODE == LOG_BY_MACRO) + +#ifdef LOG_INFO_ENABLE +#define log_info(format, ...) PRINTF("[Info] :" _LOG_TAG format "\r\n", ## __VA_ARGS__) +#else +#define log_info(...) +#endif + +#ifdef LOG_DEBUG_ENABLE +#define log_debug(format, ...) PRINTF("[Debug] :" _LOG_TAG format "\r\n", ## __VA_ARGS__) +#define log_debug_hexdump(x, y) printf_buf(x, y) +#else +#define log_debug(...) +#define log_debug_hexdump(x, y) +#endif + +#ifdef LOG_ERROR_ENABLE +#define log_error(format, ...) PRINTF(" :" _LOG_TAG format "\r\n", ## __VA_ARGS__) +#define log_error_hexdump(x, y) printf_buf(x, y) +#else +#define log_error(...) +#define log_error_hexdump(...) +#endif + +#ifdef LOG_DUMP_ENABLE +#define log_info_hexdump(x,y) printf_buf(x,y) +#else +#define log_info_hexdump(...) +#endif + +#ifdef LOG_CHAR_ENABLE +#define log_char(x) putchar(x) +#else +#define log_char(x) +#endif + +/* + * LOG 通过常量控制 + */ +#elif (LOG_MODE == LOG_BY_CONST) + +#define log_info(format, ...) \ + if (LOG_IS_ENABLE(LOG_INFO)) \ + log_print(__LOG_INFO,NULL,"[Info]: " _LOG_TAG format "\r\n", ## __VA_ARGS__) + +#define log_info_hexdump(x, y) \ + if (LOG_IS_ENABLE(LOG_INFO)) \ + printf_buf(x, y) + + +#define log_debug(format, ...) \ + if (LOG_IS_ENABLE(LOG_DEBUG)) \ + log_print(__LOG_DEBUG,NULL,"[Debug]: " _LOG_TAG format "\r\n", ## __VA_ARGS__) + +#define log_debug_hexdump(x, y) \ + if (LOG_IS_ENABLE(LOG_DEBUG)) \ + printf_buf(x, y) + +#define log_error(format, ...) \ + if (LOG_IS_ENABLE(LOG_ERROR)) \ + log_print(__LOG_ERROR,NULL,": " _LOG_TAG format "\r\n", ## __VA_ARGS__) + +#define log_error_hexdump(x, y) \ + if (LOG_IS_ENABLE(LOG_ERROR)) \ + printf_buf(x, y) + +#define log_char(x) \ + if (LOG_IS_ENABLE(LOG_CHAR)) \ + putchar(x) + +#endif + + +#define traceSUPER_MODE() \ + +/*{int icfg, rets, reti; \ +__asm__ volatile("%0 = icfg" : "=r"(icfg)); \ +__asm__ volatile("%0 = rets" :"=r"(rets)); \ +__asm__ volatile("%0 = reti" :"=r"(reti)); \ +ASSERT(icfg & BIT(10), "icfg 0x%x/ rets 0x%x / reti 0x%x", icfg, rets, reti)}*/ + + +void watchdog_close(void); + + +#endif//__DEBUG_LOG_H_ + diff --git a/include_lib/system/device/adkey.h b/include_lib/system/device/adkey.h new file mode 100644 index 0000000..549a0eb --- /dev/null +++ b/include_lib/system/device/adkey.h @@ -0,0 +1,38 @@ +#ifndef DEVICE_ADKEY_H +#define DEVICE_ADKEY_H + +#include "typedef.h" +#include "asm/adc_api.h" + + +#define ADKEY_MAX_NUM 10 + +struct adkey_platform_data { + u8 enable; + u8 adkey_pin; + u8 extern_up_en; //是否用外部上拉,1:用外部上拉, 0:用内部上拉10K + u32 ad_channel; + u16 ad_value[ADKEY_MAX_NUM]; + u8 key_value[ADKEY_MAX_NUM]; +}; + +struct adkey_rtcvdd_platform_data { + u8 enable; + u8 adkey_pin; + u8 adkey_num; + u32 ad_channel; + u32 extern_up_res_value; //是否用外部上拉,1:用外部上拉, 0:用内部上拉10K + u16 res_value[ADKEY_MAX_NUM]; //电阻值, 从 [大 --> 小] 配置 + u8 key_value[ADKEY_MAX_NUM]; +}; + +//ADKEY API: +extern int adkey_init(const struct adkey_platform_data *adkey_data); +extern u8 ad_get_key_value(void); + +//RTCVDD ADKEY API: +extern int adkey_rtcvdd_init(const struct adkey_rtcvdd_platform_data *rtcvdd_adkey_data); +extern u8 adkey_rtcvdd_get_key_value(void); + +#endif + diff --git a/include_lib/system/device/device.h b/include_lib/system/device/device.h new file mode 100644 index 0000000..5cabb7b --- /dev/null +++ b/include_lib/system/device/device.h @@ -0,0 +1,79 @@ +#ifndef CHRDEV_H +#define CHRDEV_H + + +#include "generic/typedef.h" +#include "generic/list.h" +//#include "generic/ioctl.h" +#include "generic/atomic.h" +//#include "sys/task.h" +#include "device/ioctl_cmds.h" + + +struct dev_node; +struct device; + + +struct device_operations { + bool (*online)(const struct dev_node *node); + int (*init)(const struct dev_node *node, void *); + int (*open)(const char *name, struct device **device, void *arg); + int (*read)(struct device *device, void *buf, u32 len, u32); + int (*write)(struct device *device, void *buf, u32 len, u32); + int (*seek)(struct device *device, u32 offset, int orig); + int (*ioctl)(struct device *device, u32 cmd, u32 arg); + int (*close)(struct device *device); +}; + +struct dev_node { + const char *name; + const struct device_operations *ops; + void *priv_data; +}; + + +struct device { + atomic_t ref; + void *private_data; + const struct device_operations *ops; + void *platform_data; + void *driver_data; +}; + + +#define REGISTER_DEVICE(node) \ + const struct dev_node node sec(.device) + +#define REGISTER_DEVICES(node) \ + const struct dev_node node[] sec(.device) + + +int devices_init(); + +bool dev_online(const char *name); + +void *dev_open(const char *name, void *arg); + + +int dev_read(void *device, void *buf, u32 len); + + +int dev_write(void *device, void *buf, u32 len); + + +int dev_seek(void *device, u32 offset, int orig); + + +int dev_ioctl(void *device, int cmd, u32 arg); + + +int dev_close(void *device); + + +int dev_bulk_read(void *_device, void *buf, u32 offset, u32 len); + +int dev_bulk_write(void *_device, void *buf, u32 offset, u32 len); + +#endif + + diff --git a/include_lib/system/device/device_drive.h b/include_lib/system/device/device_drive.h new file mode 100644 index 0000000..8afe100 --- /dev/null +++ b/include_lib/system/device/device_drive.h @@ -0,0 +1,190 @@ +#ifndef __DEVICE_DRIVE_H__ +#define __DEVICE_DRIVE_H__ + +#include "typedef.h" +#include "errno-base.h" +#include "ioctl.h" + +#ifndef __UBOOT + +#ifndef _MANGO_OS_ +#define _MANGO_OS_ +#endif + +#endif + +#ifdef _MANGO_OS_ +#include "os/os_api.h" +#else + + +#ifndef __UBOOT + +#ifndef _WIN_DEBUG_ +#define _WIN_DEBUG_ +#endif + +#endif + +#ifdef _WIN_DEBUG_ +#include +typedef pthread_mutex_t OS_MUTEX; +typedef u32 OS_ERR; +#define OS_ERR_NONE 0 + +#else +typedef u32 OS_MUTEX, OS_ERR; +#define OS_ERR_NONE 0 + +#endif +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + +struct dev_mutex { + OS_MUTEX *write_mutex; + OS_MUTEX *read_mutex; +}; +typedef enum _dev_type { + + DEV_SDCRAD_0 = 0X10, + DEV_SDCRAD_1, + DEV_SDCRAD_2, + + DEV_UDISK_H0, + DEV_UDISK_H1, + DEV_UDISK_F0, + + DEV_NOR_FLASH, + DEV_NAND_FLASH, + + DEV_STORAGE = 0x100, + DEV_LOGIC_DISK = 0x101, + DEV_USB_SLAVE, + DEV_USB_HOST, + DEV_HID = 0x200, + DEV_NET, + DEV_AUDIO, + DEV_ISP, +} dev_type; + +// struct partition_table +// { +// int partition_addr; +// int partition_size; +// }; +typedef struct DEV_IO { + const char name[8]; + s32(*mount)(void *volatile parm); + s32(*unmount)(); + s32(*read)(u8 *volatile buf, u32 addr, u32 len); + s32(*write)(u8 *volatile buf, u32 addr, u32 len); + s32(*ioctrl)(void *volatile parm, u32 cmd); + s32(*power)(u32 mod); + s32(*detect)(); //设备状态检测 + + struct dev_mutex *mutex; + dev_type device_type; + + void *private_data;//设备私有属性,用来提供额外接口或者存储一些设备的特性 +} dev_io_t; + + + +//设备状态: +typedef enum dev_sta { + DEV_OFFLINE = 0, //--0 设备从在线切换到离线。 + DEV_ONLINE = 1, //---1 设备从离线切换到在线。 + DEV_HOLD = 2, //---2 其他值表示设备状态未改变。 + + DEV_POWER_ON = 0x10, // 0x10 – 开机 + DEV_POWER_OFF, // 0x11 -关机 + DEV_POWER_STANDBY, // 0x12 -待机 + DEV_POWER_WAKEUP, // 0x13- 唤醒 +} DEV_STA; +//设备错误代码: +typedef enum dev_err { + DEV_ERR_NONE = 0, + DEV_ERR_NOT_MOUNT, + DEV_ERR_OVER_CAPACITY, + + DEV_ERR_UNKNOW_CLASS, + + DEV_ERR_NOT_READY,//设备已经在线,但是没初始化完成 + DEV_ERR_LUN, + + DEV_ERR_TIMEOUT, + DEV_ERR_CMD_TIMEOUT, + DEV_ERR_READ_TIMEOUT,//0x08 + DEV_ERR_WRITE_TIMEOUT, + + DEV_ERR_OFFLINE,//0x0a + + DEV_ERR_CRC, + DEV_ERR_CMD_CRC, + DEV_ERR_READ_CRC, + DEV_ERR_WRITE_CRC, + + DEV_ERR_CONTROL_STALL, + DEV_ERR_RXSTALL,//0x10 + DEV_ERR_TXSTALL, + DEV_ERR_CONTROL, + + DEV_ERR_NOT_STORAGE, + DEV_ERR_INVALID_PATH, + DEV_ERR_INVALID_DATA, + DEV_ERR_OUTOFMEMORY, + DEV_ERR_HANDLE_FREE, + DEV_ERR_INVALID_HANDLE,//24 + DEV_ERR_INVALID_BUF, + DEV_ERR_INUSE, + DEV_ERR_NO_READ, + DEV_ERR_NO_WRITE, + DEV_ERR_NO_IOCTL, + DEV_ERR_NO_POWER, + DEV_ERR_NOT_EXIST, + DEV_ERR_UNKNOW, +} DEV_ERR; + + +#define DEV_GENERAL_MAGIC 0xe0 +//每个设备必须支持的命令 +#define DEV_GET_STATUS _IOR(DEV_GENERAL_MAGIC,0xe0,u32) //获取设备状态,在线、离线、power_on、power_off、standby、…… +//设备不支持下面命令时返回 -ENOTTY +#define DEV_GET_BLOCK_SIZE _IOR(DEV_GENERAL_MAGIC,0xe1,u32) //获取存储设备的块大小 +#define DEV_GET_BLOCK_NUM _IOR(DEV_GENERAL_MAGIC,0xe2,u32) //获取存储设备的块总数 +#define DEV_GET_DEV_ID _IOR(DEV_GENERAL_MAGIC,0xe3,u32) //获取设备的ID。SD/TF 卡返回“sdtf”(0x73647466) +#define DEV_SECTOR_ERASE _IOW(DEV_GENERAL_MAGIC,0xe4,u32) //设备页擦除 +#define DEV_BLOCK_ERASE _IOW(DEV_GENERAL_MAGIC,0xe5,u32) //设备块擦除 +#define DEV_CHIP_ERASE _IOW(DEV_GENERAL_MAGIC,0xe6,u32) //设备擦除 +#define DEV_GET_TYPE _IOR(DEV_GENERAL_MAGIC,0xe7,u32) //返回设备的dev_type +#define DEV_CHECK_WPSTA _IOR(DEV_GENERAL_MAGIC,0xe8,u32) //检测设备写保护状态,当参数为-1的时候返回设备的写包含状态,0的时候解除写保护,1的时候加上写保护 + +#define typecheck(type,x) \ + ({ type __dummy; \ + typeof(x) __dummy2; \ + (void)(&__dummy == &__dummy2); \ + 1; \ + }) +#ifndef time_after +#define time_after(a,b) (typecheck(u32, a) && \ + typecheck(u32, b) && \ + ((s32)(b) - (s32)(a) < 0)) +#endif + +#ifndef time_before +#define time_before(a,b) time_after(b,a) +#endif + + +#ifdef __cplusplus + +} +#endif + + +#endif + diff --git a/include_lib/system/device/includes.h b/include_lib/system/device/includes.h new file mode 100644 index 0000000..bccd788 --- /dev/null +++ b/include_lib/system/device/includes.h @@ -0,0 +1,33 @@ +#ifndef DEVICE_INCLUDES_H +#define DEVICE_INCLUDES_H + + + + +#include "device.h" +#include "ioctl_cmds.h" + +#include "key_driver.h" +#include "iokey.h" +#include "irkey.h" +#include "adkey.h" +#include "slidekey.h" +#include "touch_key.h" +#include "rdec_key.h" + + + + + + + + + + + + + + + + +#endif diff --git a/include_lib/system/device/ioctl_cmds.h b/include_lib/system/device/ioctl_cmds.h new file mode 100644 index 0000000..ce848f3 --- /dev/null +++ b/include_lib/system/device/ioctl_cmds.h @@ -0,0 +1,80 @@ +#ifndef IOCTL_INF_H +#define IOCTL_INF_H + + + + +#define IOCTL_SET_IRQ_NUM 1 +#define IOCTL_SET_PRIORITY 2 +#define IOCTL_SET_DATA_WIDTH 3 +#define IOCTL_SET_SPEED 4 +#define IOCTL_SET_DETECT_MODE 5 +#define IOCTL_SET_DETECT_FUNC 6 +#define IOCTL_SET_DETECT_TIME_INTERVAL 7 +#define IOCTL_SET_PORT 8 +#define IOCTL_SET_PORT_FUNC 9 +#define IOCTL_SET_CS_PORT_FUNC 10 +#define IOCTL_SET_READ_MODE 11 +#define IOCTL_SET_WRITE_MODE 12 +#define IOCTL_SET_WRITE_PROTECT 13 +#define IOCTL_SET_START_BIT 14 +#define IOCTL_SET_STOP_BIT 15 +#define IOCTL_FLUSH 16 +#define IOCTL_REGISTER_IRQ_HANDLER 17 +#define IOCTL_UNREGISTER_IRQ_HANDLER 18 +#define IOCTL_GET_SYS_TIME 19 +#define IOCTL_SET_SYS_TIME 20 +#define IOCTL_GET_ALARM 21 +#define IOCTL_SET_ALARM 22 +#define IOCTL_SET_CAP_LOWSPEED_CARD 23 +#define IOCTL_SET_VDD50_EN 30 +#define IOCTL_GET_WEEKDAY 32 +#define IOCTL_CLR_READ_MODE 33 +#define IOCTL_SET_READ_CRC 34 +#define IOCTL_GET_READ_CRC 35 +#define IOCTL_GET_VOLUME 36 +#define IOCTL_SET_VOLUME 37 +#define IOCTL_SET_ALARM_ENABLE 38 +#define IOCTL_CMD_RESUME 39 +#define IOCTL_CMD_SUSPEND 40 +#define IOCTL_SET_BASE_ADDR 41 +#define IOCTL_SET_ASYNC_MODE 42 +#define IOCTL_GET_SPEED 43 + +#define IOCTL_GET_ID 100 +#define IOCTL_GET_SECTOR_SIZE 101 +#define IOCTL_GET_BLOCK_SIZE 102 +#define IOCTL_GET_CAPACITY 103 +#define IOCTL_GET_WIDTH 104 +#define IOCTL_GET_HEIGHT 105 +#define IOCTL_GET_BLOCK_NUMBER 106 +#define IOCTL_CHECK_WRITE_PROTECT 107 +#define IOCTL_GET_STATUS 108 +#define IOCTL_GET_TYPE 109 +#define IOCTL_GET_MAX_LUN 110 +#define IOCTL_GET_CUR_LUN 111 +#define IOCTL_SET_CUR_LUN 112 +#define IOCTL_SET_FORCE_RESET 113 +#define IOCTL_SET_CAPACITY 114 + + +#define IOCTL_ERASE_SECTOR 200 +#define IOCTL_ERASE_BLOCK 201 +#define IOCTL_ERASE_CHIP 202 +#define IOCTL_SET_ENC_END 203 +#define IOCTL_ERASE_PAGE 204 + + +#define IOCTL_SET_DATA_CALLBACK 301 + +#define IOCTL_GET_PART_INFO 320 + +struct ioctl_irq_handler { + void *priv; + void *handler; +}; + + + +#endif + diff --git a/include_lib/system/device/iokey.h b/include_lib/system/device/iokey.h new file mode 100644 index 0000000..c9f0082 --- /dev/null +++ b/include_lib/system/device/iokey.h @@ -0,0 +1,53 @@ +#ifndef DEVICE_IOKEY_H +#define DEVICE_IOKEY_H + +#include "typedef.h" +#include "device/device.h" + + +// enum key_connect_way { +// ONE_PORT_TO_LOW, //按键一个端口接低电平, 另一个端口接IO +// ONE_PORT_TO_HIGH, //按键一个端口接高电平, 另一个端口接IO +// DOUBLE_PORT_TO_IO, //按键两个端口接IO +// }; + + +#define ONE_PORT_TO_LOW 0 //按键一个端口接低电平, 另一个端口接IO +#define ONE_PORT_TO_HIGH 1 //按键一个端口接高电平, 另一个端口接IO +#define DOUBLE_PORT_TO_IO 2 //按键两个端口接IO +#define CUST_DOUBLE_PORT_TO_IO 3 + + +struct one_io_key { + u8 port; +}; + +struct two_io_key { + u8 in_port; + u8 out_port; +}; + +union key_type { + struct one_io_key one_io; + struct two_io_key two_io; +}; + +struct iokey_port { + union key_type key_type; + u8 connect_way; + u8 key_value; +}; + +struct iokey_platform_data { + u8 enable; + u8 num; + const struct iokey_port *port; +}; + +//IOKEY API: +extern int iokey_init(const struct iokey_platform_data *iokey_data); +extern u8 io_get_key_value(void); + + +#endif + diff --git a/include_lib/system/device/irkey.h b/include_lib/system/device/irkey.h new file mode 100644 index 0000000..970da15 --- /dev/null +++ b/include_lib/system/device/irkey.h @@ -0,0 +1,15 @@ +#ifndef DEVICE_IRKEY_H +#define DEVICE_IRKEY_H + +#include "typedef.h" + +struct irkey_platform_data { + u8 enable; + u8 port; +}; + +extern u8 ir_get_key_value(void); +extern int irkey_init(const struct irkey_platform_data *irkey_data); + +#endif + diff --git a/include_lib/system/device/key_driver.h b/include_lib/system/device/key_driver.h new file mode 100644 index 0000000..252ec3f --- /dev/null +++ b/include_lib/system/device/key_driver.h @@ -0,0 +1,68 @@ +#ifndef SYS_KEY_DRIVER_H +#define SYS_KEY_DRIVER_H + +#include "typedef.h" + + + +typedef enum __KEY_DRIVER_TYPE { + KEY_DRIVER_TYPE_IO = 0x0, + KEY_DRIVER_TYPE_AD, + KEY_DRIVER_TYPE_RTCVDD_AD, + KEY_DRIVER_TYPE_IR, + KEY_DRIVER_TYPE_TOUCH, + KEY_DRIVER_TYPE_CTMU_TOUCH, + KEY_DRIVER_TYPE_RDEC, + KEY_DRIVER_TYPE_SLIDEKEY, + KEY_DRIVER_TYPE_SOFTKEY, + + KEY_DRIVER_TYPE_MAX, +} KEY_DRIVER_TYPE; + + + +#define NO_KEY 0xff + + +#define KEY_NOT_SUPPORT 0x01 + + +struct key_driver_para { + const u32 scan_time; //按键扫描频率, 单位ms + u8 last_key; //上一次get_value按键值 +//== 用于消抖类参数 + u8 filter_value; //用于按键消抖 + u8 filter_cnt; //用于按键消抖时的累加值 + const u8 filter_time; //当filter_cnt累加到base_cnt值时, 消抖有效 +//== 用于判定长按和HOLD事件参数 + const u8 long_time; //按键判定长按数量 + const u8 hold_time; //按键判定HOLD数量 + u8 press_cnt; //与long_time和hold_time对比, 判断long_event和hold_event +//== 用于判定连击事件参数 + u8 click_cnt; //单击次数 + u8 click_delay_cnt; //按键被抬起后等待连击事件延时计数 + const u8 click_delay_time; ////按键被抬起后等待连击事件延时数量 + u8 notify_value; //在延时的待发送按键值 + u8 key_type; + u8(*get_value)(void); +}; + +//组合按键映射按键值 +struct key_remap { + u8 bit_value; + u8 remap_value; +}; + +struct key_remap_data { + u8 remap_num; + const struct key_remap *table; +}; + +// key_driver API: +extern int key_driver_init(void); + + + +#endif + + diff --git a/include_lib/system/device/rdec_key.h b/include_lib/system/device/rdec_key.h new file mode 100644 index 0000000..5c3c5b8 --- /dev/null +++ b/include_lib/system/device/rdec_key.h @@ -0,0 +1,11 @@ +#ifndef RDEC_KEY_H +#define RDEC_KEY_H + +#include "typedef.h" + +#include "asm/rdec.h" + +int rdec_key_init(const struct rdec_platform_data *rdec_key_data); + +#endif + diff --git a/include_lib/system/device/slidekey.h b/include_lib/system/device/slidekey.h new file mode 100644 index 0000000..df60360 --- /dev/null +++ b/include_lib/system/device/slidekey.h @@ -0,0 +1,31 @@ +#ifndef DEVICE_SLIDEKEY_H +#define DEVICE_SLIDEKEY_H + +#include "typedef.h" +#include "device/device.h" +#include "asm/adc_api.h" + + +struct slidekey_port { + u8 io; + u8 io_up_en; //是否用外部上拉,1:用外部上拉, 0:用内部上拉10K + u32 level; + u32 ad_channel; + int msg; +}; + +struct slidekey_platform_data { + u8 enable; + u8 num; + const struct slidekey_port *port; +}; + + + +//API: +extern int slidekey_init(const struct slidekey_platform_data *slidekey_data); + + +#endif + + diff --git a/include_lib/system/device/touch_key.h b/include_lib/system/device/touch_key.h new file mode 100644 index 0000000..548ad3a --- /dev/null +++ b/include_lib/system/device/touch_key.h @@ -0,0 +1,39 @@ +#ifndef DEVICE_TOUCH_KEY_H +#define DEVICE_TOUCH_KEY_H + +#include "typedef.h" +#include "asm/plcnt.h" + +//计数参考时钟选择, 频率越高, 精度越高 +enum touch_key_clk { + TOUCH_KEY_OSC_CLK = 0, + TOUCH_KEY_MUX_IN_CLK, //外部输入, ,一般不用, 保留 + TOUCH_KEY_PLL_192M_CLK, + TOUCH_KEY_PLL_240M_CLK, +}; + +struct touch_key_port { + u8 port; //触摸按键IO + u8 key_value; //按键返回值 +}; + +struct touch_key_platform_data { + u8 num; //触摸按键个数; + u8 clock; //触摸按键选择时钟; + u8 change_gain; //变化放大倍数 + s16 press_cfg; //按下判决门限 + s16 release_cfg0; //释放判决门限0 + s16 release_cfg1; //释放判决门限1 + const struct touch_key_port *port_list; //触摸按键列表 +}; + +/* =========== touch key API ============= */ +//触摸按键初始化 +int touch_key_init(const struct touch_key_platform_data *touch_key_data); + +//获取触摸按键键值 +u8 touch_key_get_value(void); + + +#endif + diff --git a/include_lib/system/device/vm.h b/include_lib/system/device/vm.h new file mode 100644 index 0000000..51376e9 --- /dev/null +++ b/include_lib/system/device/vm.h @@ -0,0 +1,151 @@ +#ifndef _VM_H_ +#define _VM_H_ + +#include "ioctl.h" +#include "device/device.h" + +#define IOCTL_SET_VM_INFO _IOW('V', 1, 1) +#define IOCTL_GET_VM_INFO _IOW('V', 2, 1) +// enum { +// #<{(| +// * 用户自定义配置项 (0-64) +// |)}># +// #<{(| ... |)}># +// } + +// VM define and api +typedef u16 vm_hdl; + +struct vm_table { + u16 index; + u16 value_byte; + int value; //cache value which value_byte <= 4 +}; + +typedef enum _vm_err { + VM_ERR_NONE = 0, + VM_INDEX_ERR = -0x100, + VM_INDEX_EXIST, //0xFF + VM_DATA_LEN_ERR, //0xFE + VM_READ_NO_INDEX, //0xFD + VM_READ_DATA_ERR, //0xFC + VM_WRITE_OVERFLOW, //0xFB + VM_NOT_INIT, + VM_INIT_ALREADY, + VM_DEFRAG_ERR, + VM_ERR_INIT, + VM_ERR_PROTECT +} VM_ERR; + + +// vm api +/*----------------------------------------------------------------------------*/ +/**@brief VM区域擦除函数 + @param void + @note VM_ERR VM_ERR vm错误码 + */ +/*----------------------------------------------------------------------------*/ +VM_ERR vm_eraser(void); + +/* --------------------------------------------------------------------------*/ +/** + * @brief VM初始化函数,所有VM操作之前都必须先初始化 + * + * @param [in] dev_hdl NULL + * @param [in] vm_addr VM起始地址 + * @param [in] vm_len VM总大小空间 + * @param [in] vm_mode 设置最小操作单元,目前支持按sector和按page写入 + * + * @return VM_ERR vm错误码 + */ +/* --------------------------------------------------------------------------*/ +VM_ERR vm_init(void *dev_hdl, u32 vm_addr, u32 vm_len, u8 vm_mode); + + +/* --------------------------------------------------------------------------*/ +/** + * @brief 返回vm区域已经使用了多少。 + * + * @return 大小(单位:bit) + */ +/* --------------------------------------------------------------------------*/ +u32 vm_get_usage(void); +/* --------------------------------------------------------------------------*/ +/** + * @brief 按照百分比的形式返回vm区域已经使用了多少。建议设置在main函数的board_early_init函数的前面 + * + * @return 百分比(0-99) + */ +/* --------------------------------------------------------------------------*/ +u8 vm_get_usage_percent(void); + +/* --------------------------------------------------------------------------*/ +/** + * @brief 按百分比的形式设置vm模块触发区域整理的警告线高度。注:该函数应该在vm_init初始化之前调用,否则vm_init会默认设置为vm_warning_line_num默认参数(80%) + * + * @param [in] vm_warning_line_num 警告线百分比(0-100) + */ +/* --------------------------------------------------------------------------*/ +void vm_set_warning_line(u8 vm_warning_line_num); + +/*----------------------------------------------------------------------------*/ +/**@brief VM_WARNING_LINE检测函数 + @param void:默认检测单前使用区域 + @return FALSE:未到达警告线,TRUE:以到达警告 + @note 用于整理VM前检测 + */ +/*----------------------------------------------------------------------------*/ +bool vm_warning_line_check(void); + +/*----------------------------------------------------------------------------*/ +/**@brief VM检测是否到达百分比警告线,到达则整理VM区域,不到达则清除一个flash最小操作单元 + @param level:0:查询VM是否需要整理,并进行一次擦除vm未使用区域的操作 1:整理全VM区域 + @return NON + @note 当调用vm_write写入的累计内容到达百分比警告线时会触发vm整理区域机制,会长时间操作flash,因此出现系统卡顿现象。虽然vm写操作会擦除一次最小flash操作单元,但不一定能保证在vm已经使用区域大小到达警告线的时候可以完全擦除vm的未使用区域,所以外部app应该在实现流程不忙碌的时候调用vm_check_all(0)参数查询VM是否需要整理,并进行一次擦除操作。 + */ +/*----------------------------------------------------------------------------*/ +void vm_check_all(u8 level); //level : default 0 + + +/* --------------------------------------------------------------------------*/ +/** + * @brief VM不检测是否到达警告线,立即快速清除已经使用的flash空间并整理VM区域 + * + * @return VM_ERR vm错误码 + */ +/* --------------------------------------------------------------------------*/ +VM_ERR vm_defrag_used(void); + +/* --------------------------------------------------------------------------*/ +/** + * @brief VM不检测是否到达警告线,立即清除全部使用的flash空间并整理VM区域。注:该函数会擦除整块属于vm使用的flash区域,耗时较长,建议使用vm_defrag_used + * + * @return VM_ERR vm错误码 + */ +/* --------------------------------------------------------------------------*/ +VM_ERR vm_defrag_all(void); + +/*----------------------------------------------------------------------------*/ +/**@brief VM模块重置,擦除掉vm占用的flash的内容,耗时较长。 + @return VM_ERR vm错误码 + @note 用于整理VM前检测 + */ +/*----------------------------------------------------------------------------*/ +VM_ERR vm_reset(void); + +u8 get_vm_statu(void); +// io api +//s32 vm_read(vm_hdl hdl, void *data_buf, u16 len); +//s32 vm_write(vm_hdl hdl, const void *data_buf, u16 len); + + +void spi_port_hd(u8 level); + +bool sfc_erase_zone(u32 addr, u32 len); + +void vm_api_write_mult(u16 start_id, u16 end_id, void *buf, u16 len, u32 delay); +int vm_api_read_mult(u16 start_id, u16 end_id, void *buf, u16 len); + + +#endif //_VM_H_ + diff --git a/include_lib/system/event.h b/include_lib/system/event.h new file mode 100644 index 0000000..7e57849 --- /dev/null +++ b/include_lib/system/event.h @@ -0,0 +1,367 @@ +#ifndef SYS_EVENT_H +#define SYS_EVENT_H + +#include "generic/typedef.h" +#include "generic/list.h" +#include "generic/rect.h" + +#define KEY_POWER_START 0 +#define KEY_POWER 1 +#define KEY_PREV 2 +#define KEY_NEXT 3 +#define KEY_OK 4 +#define KEY_CANCLE 5 +#define KEY_MENU 6 +#define KEY_MODE 7 +#define KEY_PHOTO 8 +#define KEY_ENC 9 +#define KEY_VOLUME_DEC 10 +#define KEY_VOLUME_INC 11 +#define KEY_PHONE 12 + + +#define KEY_LEFT 37 +#define KEY_UP 38 +#define KEY_RIGHT 39 +#define KEY_DOWN 40 + +#define KEY_0 48 +#define KEY_1 49 +#define KEY_2 50 +#define KEY_3 51 +#define KEY_4 52 +#define KEY_5 53 +#define KEY_6 54 +#define KEY_7 55 +#define KEY_8 56 +#define KEY_9 57 + + +#define KEY_F1 60 + +#define SYS_ALL_EVENT 0xffff +#define SYS_KEY_EVENT 0x0001 +#define SYS_TOUCH_EVENT 0x0002 +#define SYS_DEVICE_EVENT 0x0004 +#define SYS_NET_EVENT 0x0008 +#define SYS_BT_EVENT 0x0010 +#define SYS_IR_EVENT 0x0020 +#define SYS_PBG_EVENT 0x0040 +#define SYS_BT_AI_EVENT 0x0080 +#define SYS_AI_EVENT 0x0100 +#define SYS_MATRIX_KEY_EVENT 0x0200 +#define SYS_TOUCHPAD_EVENT 0x0400 +#define SYS_ADT_EVENT 0x0800 + + + + +#define DEVICE_EVENT_FROM_AT_UART (('A' << 24) | ('T' << 16) | ('U' << 8) | '\0') +#define DEVICE_EVENT_FROM_CHARGE (('C' << 24) | ('H' << 16) | ('G' << 8) | '\0') +#define DEVICE_EVENT_FROM_SOUNDBOX_TOOL (('S' << 24) | ('B' << 16) | ('T' << 8) | '\0') +#define DEVICE_EVENT_FROM_POWER (('P' << 24) | ('O' << 16) | ('W' << 8) | '\0') +#define DEVICE_EVENT_FROM_CI_UART (('C' << 24) | ('I' << 16) | ('U' << 8) | '\0') +#define DEVICE_EVENT_FROM_CI_TWS (('C' << 24) | ('I' << 16) | ('T' << 8) | '\0') +#define DEVICE_EVENT_CHARGE_STORE (('S' << 24) | ('T' << 16) | ('O' << 8) | '\0') +#define DEVICE_EVENT_FROM_TONE (('T' << 24) | ('N' << 16) | ('E' << 8) | '\0') +#define DEVICE_EVENT_FROM_FM (('F' << 24) | ('M' << 16) | ('\0'<< 8) | '\0') +#define KEY_EVENT_FROM_TWS (('T' << 24) | ('W' << 16) | ('S' << 8) | '\0') +#define SYS_BT_EVENT_FROM_TWS (('T' << 24) | ('W' << 16) | ('S' << 8) | '\0') +#define DEVICE_EVENT_FROM_LINEIN (('A' << 24) | ('U' << 16) | ('X' << 8) | '\0') +#define DRIVER_EVENT_FROM_SD0 (('S' << 24) | ('D' << 16) | ('0' << 8) | '\0') +#define DRIVER_EVENT_FROM_SD1 (('S' << 24) | ('D' << 16) | ('1' << 8) | '\0') +#define DRIVER_EVENT_FROM_SD2 (('S' << 24) | ('D' << 16) | ('2' << 8) | '\0') +#define DEVICE_EVENT_FROM_MUSIC (('M' << 24) | ('S' << 16) | ('C' << 8) | '\0') +#define DEVICE_EVENT_FROM_USB_HOST (('U' << 24) | ('H' << 16) | '\0' | '\0') +#define DEVICE_EVENT_FROM_OTG (('O' << 24) | ('T' << 16) | ('G' << 8) | '\0') +#define DEVICE_EVENT_FROM_PC (('P' << 24) | ('C' << 16) | '\0' | '\0') +#define DEVICE_EVENT_FROM_UAC (('U' << 24) | ('A' << 16) | ('C' << 8) | '\0') +#define DEVICE_EVENT_FROM_ALM (('A' << 24) | ('L' << 16) | ('M' << 8) | '\0') +#define SYS_BT_EVENT_TYPE_CON_STATUS (('C' << 24) | ('O' << 16) | ('N' << 8) | '\0') +#define SYS_BT_EVENT_TYPE_HCI_STATUS (('H' << 24) | ('C' << 16) | ('I' << 8) | '\0') +#define SYS_BT_EVENT_BLE_STATUS (('B' << 24) | ('L' << 16) | ('E' << 8) | '\0') +#define SYS_BT_EVENT_FORM_COMMON (('C' << 24) | ('M' << 16) | ('M' << 8) | '\0') +#define DEVICE_EVENT_FROM_KEY (('K' << 24) | ('E' << 16) | ('Y' << 8) | '\0') +#define SYS_BT_AI_EVENT_TYPE_STATUS (('B' << 24) | ('A' << 16) | ('I' << 8) | '\0') +#define DEVICE_EVENT_FROM_UART_RX_OVERFLOW (('U' << 24) | ('R' << 16) | ('F' << 8) | '\0') +#define DEVICE_EVENT_FROM_UART_RX_OUTTIME (('U' << 24) | ('R' << 16) | ('T' << 8) | '\0') +#define DEVICE_EVENT_FROM_DAC (('D' << 24) | ('A' << 16) | ('C' << 8) | '\0') +#define SYS_EVENT_FROM_CTRLER (('C' << 24) | ('T' << 16) | ('R' << 8) | '\0') +#define SYS_EVENT_FROM_RECORD (('R' << 24) | ('E' << 16) | ('C' << 8) | '\0') +#define DEVICE_EVENT_FROM_ENDLESS_LOOP_DEBUG (('E' << 24) | ('L' << 16) | ('D' << 8) | '\0') +#define DEVICE_EVENT_FROM_EARTCH (('E' << 24) | ('T' << 16) | ('H' << 8) | '\0') +#define DEVICE_EVENT_ONLINE_DATA (('O' << 24) | ('L' << 16) | ('D' << 8) | '\0') +#define SYS_BT_EVENT_FROM_KEY (('K' << 24) | ('E' << 16) | ('Y' << 8) | '\0') +#define SYS_BT_EVENT_FORM_SELF (('S' << 24) | ('E' << 16) | ('F' << 8) | '\0') +#define DEVICE_EVENT_FROM_ANC (('A' << 24) | ('N' << 16) | ('C' << 8) | '\0') + +enum { + KEY_EVENT_CLICK, + KEY_EVENT_LONG, + KEY_EVENT_HOLD, + KEY_EVENT_UP, + KEY_EVENT_DOUBLE_CLICK, + KEY_EVENT_TRIPLE_CLICK, + KEY_EVENT_FOURTH_CLICK, + KEY_EVENT_FIRTH_CLICK, + KEY_EVENT_USER, + KEY_EVENT_MAX, +}; + + +enum { + DEVICE_EVENT_IN, + DEVICE_EVENT_OUT, + DEVICE_EVENT_ONLINE, + DEVICE_EVENT_OFFLINE, + DEVICE_EVENT_CHANGE, +}; + +enum { + TOUCH_EVENT_DOWN, + TOUCH_EVENT_MOVE, + TOUCH_EVENT_HOLD, + TOUCH_EVENT_UP, + TOUCH_EVENT_CLICK, + TOUCH_EVENT_DOUBLE_CLICK, +}; + +enum { + NET_EVENT_CMD, + NET_EVENT_DATA, + NET_EVENT_CONNECTED, + NET_EVENT_DISCONNECTED, + NET_EVENT_SMP_CFG_TIMEOUT, +}; + + +struct key_event { + u8 init; + u8 type; + u16 event; + u32 value; + u32 tmr; +}; + +struct ir_event { + u8 event; +}; + +struct msg_event { + u8 event; + u8 value; +}; + +#if EVENT_TOUCH_ENABLE_CONFIG +struct touch_event { + u8 event; + struct position pos; +}; +#endif + +struct device_event { + u8 event; + int value; +}; +struct chargestore_event { + u8 event; + u8 *packet ; + u8 size; +}; + +struct ancbox_event { + u8 event; + u32 value; +}; + +struct soundbox_tool_event { + u8 event; + u8 *packet ; + u8 size; +}; + +struct net_event { + u8 event; + u8 value; +}; +struct bt_event { + u8 event; + u8 args[7]; + u32 value; +}; + +struct axis_event { + u8 event; + s16 x; + s16 y; +}; + +struct codesw_event { + u8 event; + s8 value; +}; + +struct pbg_event { + u8 event; + u8 args[3]; +}; + +struct adt_event { + u8 event; + u8 args[3]; +}; + +struct uart_event { + void *ut_bus; +}; + +struct uart_cmd_event { + u8 type; + u8 cmd; +}; + +struct ai_event { + u32 value; +}; + +struct ear_event { + u8 value; +}; + +struct rcsp_event { + u8 event; + u8 args[6]; + u8 size; +}; + +struct chargebox_event { + u8 event; +}; + +struct matrix_key_event { + u16 args[6]; //最多推6个按键出来,如果需要推多个按键需要自行修改,每个u16 低八位标识row 高八位标识col + u8 *map; +}; + +struct touchpad_event { + u8 gesture_event; //手势事件 + s8 x; + s8 y; +}; + +struct sys_event { + u16 type; + u8 consumed; + void *arg; + union { + struct key_event key; + struct axis_event axis; + struct codesw_event codesw; +#if EVENT_TOUCH_ENABLE_CONFIG + struct touch_event touch; +#endif + struct device_event dev; + struct net_event net; + struct bt_event bt; + struct msg_event msg; + struct chargestore_event chargestore; + struct soundbox_tool_event soundbox_tool; + struct ir_event ir; + struct pbg_event pbg; + struct uart_event uart; + struct uart_cmd_event uart_cmd; + struct ai_event ai; + struct ear_event ear; + struct rcsp_event rcsp; + struct chargebox_event chargebox; + struct ancbox_event ancbox; + struct matrix_key_event matrix_key; + struct touchpad_event touchpad; + struct adt_event adt; + } u; +}; + + + + +struct static_event_handler { + int event_type; + void (*handler)(struct sys_event *); +}; + + +#define SYS_EVENT_HANDLER(type, fn, pri) \ + const struct static_event_handler __event_handler_##fn sec(.sys_event.pri.handler) = { \ + .event_type = type, \ + .handler = fn, \ + } + +extern struct static_event_handler sys_event_handler_begin[]; +extern struct static_event_handler sys_event_handler_end[]; + +#define list_for_each_static_event_handler(p) \ + for (p = sys_event_handler_begin; p < sys_event_handler_end; p++) + + + +int register_sys_event_handler(int event_type, int from, u8 priority, + void (*handler)(struct sys_event *)); + + +void unregister_sys_event_handler(void (*handler)(struct sys_event *)); + + +/* + * 事件通知函数,系统有事件发生时调用此函数 + */ +void sys_event_notify(struct sys_event *e); + +void sys_event_clear(struct sys_event *e); + +void sys_key_event_disable(); + + +void sys_key_event_enable(); + +void sys_key_event_filter_disable(); + +void sys_key_event_filter_enable(); + +void sys_touch_event_disable(); + + +void sys_touch_event_enable(); + +/* + *下面四个为系统事件消耗函数,调用此函数后则对应的事件不在分发给其它任务 + * + */ +void sys_event_consume(struct sys_event *e); + +void sys_key_event_consume(struct key_event *e); + +#if EVENT_TOUCH_ENABLE_CONFIG +void sys_touch_event_consume(struct touch_event *e); +#endif + +void sys_device_event_consume(struct device_event *e); + + +/* + * 下面两个函数为按键和触摸事件接管函数,调用此函数后则对应的事件只发到当前任务 + * + * on=true: 开始接管, on=false: 取消接管 + * + * once: on = false 时有效,当前这次不接管, 事件可以继续发送到其它任务 + * + */ +void sys_key_event_takeover(bool on, bool once); + +void sys_touch_event_takeover(bool on, bool once); + + +int sys_key_event_map(struct key_event *org, struct key_event *new); +int sys_key_event_unmap(struct key_event *org, struct key_event *new); + + +#endif diff --git a/include_lib/system/fs/fs.h b/include_lib/system/fs/fs.h new file mode 100644 index 0000000..7438394 --- /dev/null +++ b/include_lib/system/fs/fs.h @@ -0,0 +1,357 @@ +#ifndef __FS_H__ +#define __FS_H__ + + + +#include "generic/typedef.h" +#include "generic/list.h" +#include "generic/ioctl.h" +#include "generic/atomic.h" +#include "system/task.h" +#include "system/malloc.h" +#include "system/sys_time.h" +#include "stdarg.h" +#include "fs_file_name.h" + +#define SEEK_SET 0 /* Seek from beginning of file. */ +#define SEEK_CUR 1 /* Seek from current position. */ +#define SEEK_END 2 /* Seek from end of file. */ + +#include "sdfile.h" + +#define F_ATTR_RO 0x01 +#define F_ATTR_ARC 0x02 +#define F_ATTR_DIR 0x04 +#define F_ATTR_VOL 0x08 + +#if (VFS_ENABLE == 1) + +#ifndef FSELECT_MODE +#define FSELECT_MODE +#define FSEL_FIRST_FILE 0 +#define FSEL_LAST_FILE 1 +#define FSEL_NEXT_FILE 2 +#define FSEL_PREV_FILE 3 +#define FSEL_CURR_FILE 4 +#define FSEL_BY_NUMBER 5 +#define FSEL_BY_SCLUST 6 +#define FSEL_AUTO_FILE 7 +#define FSEL_NEXT_FOLDER_FILE 8 +#define FSEL_PREV_FOLDER_FILE 9 +#define FSEL_BY_PATH 10 +#endif + +#ifndef FCYCLE_MODE +#define FCYCLE_MODE +#define FCYCLE_LIST 0 +#define FCYCLE_ALL 1 +#define FCYCLE_ONE 2 +#define FCYCLE_FOLDER 3 +#define FCYCLE_RANDOM 4 +#define FCYCLE_MAX 5 +#endif + +enum { + FS_IOCTL_GET_FILE_NUM, + FS_IOCTL_FILE_CHECK, + FS_IOCTL_GET_ERR_CODE, //暂不支持 + FS_IOCTL_FREE_CACHE, + FS_IOCTL_SET_NAME_FILTER, //设置文件过滤 + FS_IOCTL_GET_FOLDER_INFO, //获取文件夹序号和文件夹内文件数目 + FS_IOCTL_SET_LFN_BUF, // 512 + FS_IOCTL_SET_LDN_BUF, // 512 + + FS_IOCTL_SET_EXT_TYPE, //设置后缀类型 + FS_IOCTL_OPEN_DIR, //打开目录 + FS_IOCTL_ENTER_DIR, //进入目录 + FS_IOCTL_EXIT_DIR, //退出 + FS_IOCTL_GET_DIR_INFO, //获取目录信息 + + FS_IOCTL_GETFILE_BYNAME_INDIR, //由歌曲名称获得歌词 + + FS_IOCTL_GET_DISP_INFO, //用于长文件名获取 + + FS_IOCTL_MK_DIR, //创建文件夹 + FS_IOCTL_GET_ENCFOLDER_INFO, //获取录音文件信息 + + FS_IOCTL_GET_OUTFLASH_ADDR, //获取外置flash实际物理地址(暂时用于手表case,特殊fat系统) +}; + + +struct vfs_devinfo; +struct vfscan; +struct vfs_operations; + + + +struct vfs_devinfo { + void *fd; + u32 sector_size; + void *private_data; +}; + +#define VFS_PART_DIR_MAX 16 + + +struct vfs_partition { + struct vfs_partition *next; + u32 offset; + u32 clust_size; + u32 total_size; + u8 fs_attr; + char dir[VFS_PART_DIR_MAX]; + void *private_data; +}; + +struct fiter { + u32 index; +}; + +struct ffolder { + u16 fileStart; + u16 fileTotal; +}; + + + +struct imount { + int fd; + const char *path; + struct vfs_operations *ops; + struct vfs_devinfo dev; + struct vfs_partition part; + struct list_head entry; + atomic_t ref; + OS_MUTEX mutex; + u8 avaliable; + u8 part_num; +}; + +struct vfs_attr { + u8 attr; + u32 fsize; + u32 sclust; + struct sys_time crt_time; + struct sys_time wrt_time; +}; + +typedef struct { + struct imount *mt; + struct vfs_devinfo *dev; + struct vfs_partition *part; + void *private_data; +} FILE; + + +struct vfscan { + u8 scan_file; + u8 subpath; //子目录,设置是否只扫描一层 + u8 scan_dir; + u8 attr; + u8 cycle_mode; + char sort; + char ftype[20 * 3 + 1]; + u16 file_number; + u16 file_counter; + + u16 dir_totalnumber; // 文件夹总数 + u16 musicdir_counter; // 播放文件所在文件夹序号 + u16 fileTotalInDir; //文件夹下的文件数目 + + void *priv; + struct vfs_devinfo *dev; + struct vfs_partition *part; + char filt_dir[12]; +}; + + +struct vfs_operations { + const char *fs_type; + int (*mount)(struct imount *, int); + int (*unmount)(struct imount *); + int (*format)(struct vfs_devinfo *, struct vfs_partition *); + int (*fset_vol)(struct vfs_partition *, const char *name); + int (*fget_free_space)(struct vfs_devinfo *, struct vfs_partition *, u32 *space); + int (*fopen)(FILE *, const char *path, const char *mode); + int (*fread)(FILE *, void *buf, u32 len); + int (*fread_fast)(FILE *, void *buf, u32 len); + int (*fwrite)(FILE *, void *buf, u32 len); + int (*fseek)(FILE *, int offset, int); + int (*fseek_fast)(FILE *, int offset, int); + int (*flen)(FILE *); + int (*fpos)(FILE *); + int (*fcopy)(FILE *, FILE *); + int (*fget_name)(FILE *, u8 *name, int len); + int (*fget_path)(FILE *, u8 *name, int len, u8 is_relative_path); + int (*frename)(FILE *, const char *path); + int (*fclose)(FILE *); + int (*fdelete)(FILE *); + int (*fscan)(struct vfscan *, const char *path, u8 max_deepth); + int (*fscan_interrupt)(struct vfscan *, const char *path, u8 max_deepth, int (*callback)(void)); + void (*fscan_release)(struct vfscan *); + int (*fsel)(struct vfscan *, int sel_mode, FILE *, int); + int (*fget_attr)(FILE *, int *attr); + int (*fset_attr)(FILE *, int attr); + int (*fget_attrs)(FILE *, struct vfs_attr *); + int (*fmove)(FILE *file, const char *path_dst, FILE *, int clr_attr); + int (*ioctl)(void *, int cmd, int arg); +}; + +#define REGISTER_VFS_OPERATIONS(ops) \ + const struct vfs_operations ops SEC(.vfs_operations) + + +static inline struct vfs_partition *vfs_partition_next(struct vfs_partition *p) +{ + struct vfs_partition *n = (struct vfs_partition *)zalloc(sizeof(*n)); + + if (n) { + p->next = n; + } + return n; +} + + +static inline void vfs_partition_free(struct vfs_partition *p) +{ + struct vfs_partition *n = p->next; + + while (n) { + p = n->next; + free(n); + n = p; + } +} + + + + +struct imount *mount(const char *dev_name, const char *path, const char *fs_type, + int cache_num, void *dev_arg); //挂载 + +int unmount(const char *path); + +int f_format(const char *path, const char *fs_type, u32 clust_size); //格式化接口 + +int f_free_cache(const char *path); + +/*----------------------------------------------------------------------------*/ +/** @brief: +@param: fopen 扩展功能 +@note: fopen自动打开、创建文件夹和文件。 + 说明: + 1. 设备路径+文件,其中文件传入格式:"music/test/1/2/3/pk*.wav" "JL_REC/AC69****.wav" "JL_REC/AC690000.wav" + 2. 文件名带*号,带多少个*表示多少个可变数字,最多为8+3的大小,如表示可变数字名称变为XXX0001,XXXX002这样得格式,不带*号则只创建一个文件,写覆盖。 +@date: 2020-07-22 +*/ +/*----------------------------------------------------------------------------*/ + +FILE *fopen(const char *path, const char *mode); + +int fread(FILE *file, void *buf, u32 len); + +int fwrite(FILE *file, void *buf, u32 len); + +int fseek(FILE *file, int offset, int orig); + +int fseek_fast(FILE *file, int offset, int orig);// 快速seek + +int fread_fast(FILE *file, void *buf, u32 len); //快速read + +int flen(FILE *file); + +int fpos(FILE *file); + +int fcopy(const char *format, ...); + +int fget_name(FILE *file, u8 *name, int len); + +int frename(FILE *file, const char *path); + +int fclose(FILE *file); + +int fdelete(FILE *file); +int fdelete_by_name(const char *fname); + +int fget_free_space(const char *path, u32 *space); + +int fget_path(FILE *file, u8 *name, int len, u8 is_relative_path); + +/* arg: + * -t 文件类型 + * -r 包含子目录 + * -d 扫描文件夹 + * -a 文件属性 r: 读, /: 非 + * -s 排序方式, t:按时间排序, n:按文件号排序 + */ +struct vfscan *fscan(const char *path, const char *arg, u8 max_deepth); //扫描接口,参数配置如上。 + +struct vfscan *fscan_interrupt(const char *path, const char *arg, u8 max_deepth, int (*callback)(void)); //可打断扫描 + +struct vfscan *fscan_enterdir(struct vfscan *fs, const char *path);//进入指定子目录,只扫此目录下文件信息 + +struct vfscan *fscan_exitdir(struct vfscan *fs); //返回上一层 + +void fscan_release(struct vfscan *fs); + +FILE *fselect(struct vfscan *fs, int selt_mode, int arg); //选择指定文件 + +int fdir_exist(const char *dir); //check 目录是否存在 + +int fdir(FILE *file, const char *arg, char *name, int len, struct fiter *iter);//暂无此接口 + +int fget_attr(FILE *file, int *attr); //获取文件属性 + +int fset_attr(FILE *file, int attr); //设置文件属性 + +int fget_attrs(FILE *file, struct vfs_attr *attr);//获得文件相关信息如属性、簇号、大小等 + +struct vfs_partition *fget_partition(const char *path);//获得分区part + +int fset_vol(const char *path, const char *name);//设置卷标 + +int fmove(FILE *file, const char *path_dst, FILE **newFile, int clr_attr);//暂不支持 + +int fcheck(FILE *file);//暂不支持 + +int fget_err_code(const char *path); //暂不支持 + +int fset_name_filter(const char *path, void *name_filter);//暂不支持 + +int fget_folder(struct vfscan *fs, struct ffolder *arg); //获取文件夹序号和文件夹内文件数目 + +int fset_lfn_buf(struct vfscan *fs, void *arg);//设置长文件名buf +int fset_ldn_buf(struct vfscan *fs, void *arg);//设置长文件夹名buf + +int fset_ext_type(const char *path, void *ext_type);//设置后缀类型 +int fopen_dir_info(const char *path, FILE **pp_file, void *dir_dj); //打开目录 +int fenter_dir_info(FILE *file, void *dir_dj); //进入目录 +int fexit_dir_info(FILE *file); //退出 +int fget_dir_info(FILE *file, u32 start_num, u32 total_num, void *buf_info); ////获取目录信息 + +int fget_fat_outflash_addr(FILE *file, void *buf_info);//获取外置flash实际物理地址(暂时用于手表case,特殊fat系统) + +int fget_file_byname_indir(FILE *file, FILE **newFile, void *ext_name); //由歌曲名称获得歌词 + +int fget_disp_info(FILE *file, void *arg); //用于长文件名获取 + +int fmk_dir(const char *path, char *folder, u8 mode); //创建目录 + +int fget_encfolder_info(const char *path, char *folder, char *ext, u32 *last_num, u32 *total_num); //获取录音文件信息 + +int fname_to_path(char *result, const char *path, const char *fname, int len); //把路径和文件名拼接 + +int get_last_num(void); //录音获取最后序号。 + +void set_bp_info(u32 clust, u32 fsize, u32 *flag); //扫描前设置断点参数,需要put_bp_info对应释放buf. +void put_bp_info(void); + +#endif /* VFS_ENABLE */ + +#endif /* __FS_H__ */ + + + + + + diff --git a/include_lib/system/fs/fs_file_name.h b/include_lib/system/fs/fs_file_name.h new file mode 100644 index 0000000..00c59c1 --- /dev/null +++ b/include_lib/system/fs/fs_file_name.h @@ -0,0 +1,35 @@ +#ifndef __FS_FILE_NAME_H__ +#define __FS_FILE_NAME_H__ + +#include "generic/typedef.h" + +#define D_LFN_MAX_SIZE 512 + +#define LFN_MAX_SIZE D_LFN_MAX_SIZE //不能超过512 //必须4byte对齐 + +typedef struct _LONG_FILE_NAME { + u16 lfn_cnt; + char lfn[LFN_MAX_SIZE]; //长文件名buffer +} LONG_FILE_NAME; //整理后的长文件名 + +typedef struct _FS_DIR_INFO { + u32 sclust; //dir sclust + u16 dir_type; // 0-folder,1-file + u16 fn_type; // 0-sfn,1-lfn + LONG_FILE_NAME lfn_buf; //long file name +} FS_DIR_INFO; + +typedef struct _FS_DISP_INFO { + char tpath[128]; + LONG_FILE_NAME file_name; + LONG_FILE_NAME dir_name; + u8 update_flag; +} FS_DISP_INFO; + +typedef struct _FLASH_FAT_CLUSTINFO { + u32 sclust2addr; //当前连续簇块文件起始实际物理地址 + u32 endclust2addr; //当前连续簇块结束位置 + u32 file_len; //文件长度,如 JL.res文件的 +} FLASH_FAT_CLUSTINFO; +#endif /* __FS_FILE_NAME_H__ */ + diff --git a/include_lib/system/fs/sdfile.h b/include_lib/system/fs/sdfile.h new file mode 100644 index 0000000..6ff5bdb --- /dev/null +++ b/include_lib/system/fs/sdfile.h @@ -0,0 +1,172 @@ +#ifndef _SDFILE_H_ +#define _SDFILE_H_ + +#include "typedef.h" + +/********* sdfile 文件头 **********/ +#define SDFILE_NAME_LEN 16 + +typedef struct sdfile_file_head { + u16 head_crc; + u16 data_crc; + u32 addr; + u32 len; + u8 attr; + u8 res; + u16 index; + char name[SDFILE_NAME_LEN]; +} SDFILE_FILE_HEAD; + +#if 0 +////////////////////////////sdfile_file_head成员详细说明/////////////////////////////////////// +typedef struct SDFILEJL_FILE_HEAD { + u16 u16Crc; // 结构体自身校验码 + u16 u16DataCrc; // 文件数据校验码 + u32 u32Address; // 数据存储地址 + u32 u32Length; // 数据长度 + u8 u8Attribute; // 属性 + u8 u8Res; // 保留数据 + u16 u16Index; // 文件编号,从大到小排列,编号为0时,代表后面没有文件 + char szFileName[16];// 文件名 +} JL_SDFILE_HEAD; + +////////////////////////////flash_head成员详细说明/////////////////////////////////////// +typedef struct SDFILEJL_FLASH_HEAD_V2 { + u16 u16Crc; // 结构体自身校验码 + u16 u16SizeForBurner; // 为烧写器保留的空间大小 + char vid[4]; // 存放VID信息,长度是4个byte + u32 u32FlashSize; // FLASH大小,由isd_download计算得出 + u8 u8FsVersion; // flash类型:BR18(0)/BR22(1) + u8 u8BlockAlingnModulus;// 对齐系数,对齐的值=对齐系数*256 + u8 u8Res; // 保留 + u8 u8SpecialOptFlag; // 用于标记是否需要生成2种flash格式的标记位,目前只用1位 + char pid[16]; // 存放PID信息,长度是16个byte +} SDFILEJL_FLASH_HEAD_V2; + +#endif + +struct sdfile_dir { + u16 file_num; + struct sdfile_file_head head; +}; + +enum sdfile_err_table { + SDFILE_DIR_NOT_EXIST = -0xFF, + SDFILE_FILE_NOT_EXIST, + SDFILE_MALLOC_ERR, + SDFILE_VM_NOT_FIND, + SDFILE_DATA_CRC_ERR, + SDFILE_WRITE_AREA_NEED_ERASE_ERR, + SDFILE_SUSS = 0, + SDFILE_END, +}; + +#if (VFS_ENABLE == 1) + +#if SDFILE_STORAGE +#define SDFILE_MAX_DEEPTH 2 +struct sdfile_folder { + u32 saddr; + u32 addr; + u32 len; +}; +struct sdfile_scn { + u8 subpath; + u8 cycle_mode; + u8 attr; + u8 deepth; + u16 dirCounter; + u16 fileCounter; + u16 fileNumber; // 当前文件序号 + u16 totalFileNumber; + u16 last_file_number; + u16 fileTotalInDir; // 当前目录的根下有效文件的个数 + u16 fileTotalOutDir; // 当前目录前的文件总数,目录循环模式下,需要用它来计算文件序号 + u32 sclust_id; + const char *ftypes; + struct sdfile_file_head head; + struct sdfile_folder folder[SDFILE_MAX_DEEPTH]; +}; +#endif + +typedef struct sdfile_file_t { + u32 fptr; + struct sdfile_file_head head; +#if SDFILE_STORAGE + struct sdfile_scn *pscn; +#endif +} SDFILE; + +#else + +typedef struct sdfile_file_t { + u32 fptr; + struct sdfile_file_head head; +} SDFILE, FILE; + +struct vfs_attr { + u8 attr; //属性 + u32 fsize; //文件大小 + u32 sclust; //地址 +}; + +SDFILE *sdfile_open(const char *path, const char *mode); +int sdfile_read(SDFILE *fp, void *buf, u32 len); +int sdfile_write(SDFILE *fp, void *buf, u32 len); +int sdfile_seek(SDFILE *fp, u32 offset, u32 fromwhere); +int sdfile_close(SDFILE *fp); +int sdfile_pos(SDFILE *fp); +int sdfile_len(SDFILE *fp); +int sdfile_get_name(SDFILE *fp, u8 *name, int len); +int sdfile_get_attrs(SDFILE *fp, struct vfs_attr *attr); + +#define fopen sdfile_open +#define fread sdfile_read +#define fseek sdfile_seek +#define fclose sdfile_close +#define fwrite sdfile_write +#define flen sdfile_len +#define fpos sdfile_pos +#define fget_name sdfile_get_name +#define fget_attrs sdfile_get_attrs + +#endif /* VFS_ENABLE */ + +int sdfile_delete_data(SDFILE *fp); +#define fdel_data sdfile_delete_data + +#ifndef SDFILE_MOUNT_PATH +#define SDFILE_MOUNT_PATH "mnt/sdfile" +#endif /* #ifndef SDFILE_MOUNT_PATH */ + +#if (USE_SDFILE_NEW) + +#ifndef SDFILE_APP_ROOT_PATH +#define SDFILE_APP_ROOT_PATH SDFILE_MOUNT_PATH"/app/" //app分区 +#endif /* #ifndef SDFILE_APP_ROOT_PATH */ + +#ifndef SDFILE_RES_ROOT_PATH +#define SDFILE_RES_ROOT_PATH SDFILE_MOUNT_PATH"/res/" //资源文件分区 +#endif /* #ifndef SDFILE_RES_ROOT_PATH */ + +#else +#ifndef SDFILE_RES_ROOT_PATH +#define SDFILE_RES_ROOT_PATH SDFILE_MOUNT_PATH"/C/" +#endif /* #ifndef SDFILE_RES_ROOT_PATH */ + +#endif /* #if (USE_SDFILE_NEW) */ + +//获取flash物理大小, 单位: Byte +u32 sdfile_get_disk_capacity(void); +//flash addr -> cpu addr +u32 sdfile_flash_addr2cpu_addr(u32 offset); +//cpu addr -> flash addr +u32 sdfile_cpu_addr2flash_addr(u32 offset); + +u32 decode_data_by_user_key_in_sdfile(u16 key, u8 *buff, u16 size, u32 dec_addr, u8 dec_len); + +u32 init_norsdfile_hdl(void); +int set_res_startaddr(int offset); + +#endif /* _SDFILE_H_ */ + diff --git a/include_lib/system/fs/virfat_flash.h b/include_lib/system/fs/virfat_flash.h new file mode 100644 index 0000000..72c3236 --- /dev/null +++ b/include_lib/system/fs/virfat_flash.h @@ -0,0 +1,147 @@ +#ifndef VIRTUAL_DISK_H +#define VIRTUAL_DISK_H + +#include "system/includes.h" + + +#define VIR_FILE_TYPE_MP3 1 +#define VIR_FILE_TYPE_WAV 2 + +extern const struct device_operations virfat_flash_dev_ops; + +typedef enum { + FS_FAT12 = 0x01, + FS_FAT16 = 0x02, + FS_FAT32 = 0x04, + FS_EXFAT = 0x14, +} FS_TYPE; + + +typedef struct _virfat_flash_t { + u32 fatbase; + // u32 fatbase2; + u16 fatsize; + u32 dirbase; + u32 database; + u32 clustSize; + u32 max_clust; + u32 capacity; + u8 csize; + FS_TYPE fs_type; + char re_devname[24]; +} virfat_flash_t; + +typedef struct _dir_entry { + u8 name[12]; + u32 fileSize; +} dir_entry_t; + + +#if 0 +extern void virfat_flash_rand_file_size(); +extern void virtual_disk_reduce_file_size(tu8 file_num); +extern void virtual_disk_remove_files(tu8 file_type); +extern void virtual_disk_reduce_file_size(tu8 file_num); +extern u8 virfat_flash_init(void *buf_512, void (*fun_read_file)(u32, u32, u8 *, u32)); +#endif + +#define MIN_FAT16 4086 /* Minimum number of clusters for FAT16 */ +#define MIN_FAT32 65526 /* Minimum number of clusters for FAT32 */ + +#define AM_RDO 0x01 /* Read only */ +#define AM_HID 0x02 /* Hidden */ +#define AM_SYS 0x04 /* System */ +#define AM_VOL 0x08 /* Volume label */ +#define AM_LFN 0x0F /* LFN entry */ +#define AM_DIR 0x10 /* Directory */ +#define AM_ARC 0x20 /* Archive */ +#define AM_FCH 0x80 /* exFAT下,文件簇连续标志 */ +#define AM_FRG 0x40 /* exFAT下,文件簇BITMAP 有碎片 */ +#define AM_LFN0_START 0x1 +#define AM_LFN0_LEN 10 +#define AM_LFN1_START 0xE +#define AM_LFN1_LEN 12 +#define AM_LFN2_START 0x1C +#define AM_LFN2_LEN 4 +#define AM_LFN_LEN 26 + +#define AM_EX_DIR_STRETCHED 0x08 + +#define BS_jmpBoot 0 +#define BS_OEMName 3 +#define BPB_BytsPerSec_l 11 +#define BPB_BytsPerSec_h 12 +#define BPB_SecPerClus 13 +#define BPB_RsvdSecCnt 14 +#define BPB_NumFATs 16 +#define BPB_RootEntCnt 17 +#define BPB_TotSec16 19 +#define BPB_Media 21 +#define BPB_FATSz16 22 +#define BPB_SecPerTrk 24 +#define BPB_NumHeads 26 +#define BPB_HiddSec 28 +#define BPB_TotSec32 32 +#define BS_55AA 510 + +#define BS_DrvNum 36 +#define BS_BootSig 38 +#define BS_VolID 39 +#define BS_VolLab 43 +#define BS_FilSysType 54 + +#define BPB_FATSz32 36 +#define BPB_ExtFlags 40 +#define BPB_FSVer 42 +#define BPB_RootClus 44 +#define BPB_FSInfo 48 +#define BPB_BkBootSec 50 +#define BS_DrvNum32 64 +#define BS_BootSig32 66 +#define BS_VolID32 67 +#define BS_VolLab32 71 +#define BS_FilSysType32 82 +#define BS_FileSysTypeexFAT 5 +#define BPB_FatOffset 80 +#define BPB_FatLength 84 +#define BPB_ClusterHeapOffset 88 +#define BPB_ClusterCount 92 +#define BPB_FirstClusterOfRootDirectory 96 +#define BPB_VolumeFlags 106 +#define BPB_BytesPerSectorShift 108 +#define BPB_SectorsPerClusterShift 109 +#define BPB_NumberOfFats 110 +#define MBR_Table 446 +#define FSI_LeadSig 0 /* FSI: Leading signature (4) */ +#define FSI_StrucSig 484 /* FSI: Structure signature (4) */ +#define FSI_Free_Count 488 /* FSI: Number of free clusters (4) */ +#define FSI_Nxt_Free 492 /* FSI: Last allocated cluster (4) */ + +///for FAT12/FAT16/FAT32 +#define DIR_Name 0 /* Short file name (11) */ +#define DIR_Attr 11 /* Attribute (1) */ +#define DIR_NTres 12 /* NT flag (1) */ +#define DIR_CrtTimeTenth 13 /* Created time sub-second (1) */ +#define DIR_CrtTime 14 /* Created time (2) */ +#define DIR_CrtDate 16 /* Created date (2) */ +#define DIR_LstAccDate 18 /* Last accessed date (2) */ +#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */ +#define DIR_WrtTime 22 /* Modified time (2) */ +#define DIR_WrtDate 24 /* Modified date (2) */ +#define DIR_FstClusLO 26 +#define DIR_FileSize 28 +#define LDIR_Attr 11 /* LFN attribute (1) */ +#define LDIR_Type 12 /* LFN type (1) */ +#define LDIR_Chksum 13 /* Sum of corresponding SFN entry */ +////for exFAT +#define DIR_FileChainFlags 1 +#define DIR_NameLen 3 +#define DIR_AttrexFAT 4 +#define DIR_FileSizeexFAT 8 +#define DIR_FstClustexFAT 20 +#define DIR_FileSize2exFAT 24 + + + +#endif + diff --git a/include_lib/system/generic/ascii.h b/include_lib/system/generic/ascii.h new file mode 100644 index 0000000..31e0842 --- /dev/null +++ b/include_lib/system/generic/ascii.h @@ -0,0 +1,44 @@ +#ifndef ASCII_LIB_H +#define ASCII_LIB_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#include "typedef.h" + + +void ASCII_ToLower(void *buf, u32 len); + +void ASCII_ToUpper(void *buf, u32 len); + +u32 ASCII_StrCmp(const char *src, const char *dst, u32 len); + +int ASCII_StrCmpNoCase(const char *src, const char *dst, int len); + +void ASCII_IntToStr(void *pStr, u32 intNum, u32 strLen, u32 bufLen); + +u32 ASCII_StrToInt(const void *pStr, u32 *pRint, u32 strLen); + +u32 ASCII_StrLen(void *str, u32 len); + +u32 ASCII_WStrLen(void *str, u32 len); + + + + + + + + + + + + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include_lib/system/generic/atomic.h b/include_lib/system/generic/atomic.h new file mode 100644 index 0000000..697a1f6 --- /dev/null +++ b/include_lib/system/generic/atomic.h @@ -0,0 +1,81 @@ +#ifndef ATOMIC_H +#define ATOMIC_H + +#include "cpu.h" +#include "irq.h" + +typedef struct { + int counter; +} atomic_t; + +static inline int atomic_add_return(int i, atomic_t *v) +{ + int val; + CPU_SR_ALLOC(); + + CPU_CRITICAL_ENTER(); + + val = v->counter; + v->counter = val += i; + + CPU_CRITICAL_EXIT(); + + return val; +} + + +static inline int atomic_sub_return(int i, atomic_t *v) +{ + int val; + CPU_SR_ALLOC(); + + CPU_CRITICAL_ENTER(); + + val = v->counter; + v->counter = val -= i; + + CPU_CRITICAL_EXIT(); + + return val; +} + +static inline int atomic_set(atomic_t *v, int i) +{ + int val = 0; + CPU_SR_ALLOC(); + + CPU_CRITICAL_ENTER(); + + v->counter = i; + + CPU_CRITICAL_EXIT(); + + return val; +} + + +#define DEFINE_ATOMIC(x) \ + atomic_t x = {.counter = 0} + +#define atomic_add(i, v) atomic_add_return(i, v) +#define atomic_sub(i, v) atomic_sub_return(i, v) + +#define atomic_read(v) arch_atomic_read(v) +/*#define atomic_set(v,i) (((v)->counter) = (i))*/ + +#define atomic_inc(v) atomic_add(1, v) +#define atomic_dec(v) atomic_sub(1, v) + +#define atomic_inc_and_test(v) (atomic_add_return(1, v) == 0) +#define atomic_dec_and_test(v) (atomic_sub_return(1, v) == 0) +#define atomic_inc_return(v) (atomic_add_return(1, v)) +#define atomic_dec_return(v) (atomic_sub_return(1, v)) +#define atomic_sub_and_test(i, v) (atomic_sub_return(i, v) == 0) + +#define atomic_add_negative(i,v) (atomic_add_return(i, v) < 0) + + + + +#endif + diff --git a/include_lib/system/generic/circular_buf.h b/include_lib/system/generic/circular_buf.h new file mode 100644 index 0000000..655af1e --- /dev/null +++ b/include_lib/system/generic/circular_buf.h @@ -0,0 +1,65 @@ +#ifndef CIRCULAR_BUF_INTERFACE_H +#define CIRCULAR_BUF_INTERFACE_H + +#include "typedef.h" +#include "system/spinlock.h" + + + + + +typedef struct _cbuffer { + u8 *begin; + u8 *end; + u8 *read_ptr; + u8 *write_ptr; + u8 *tmp_ptr ; + u32 tmp_len; + u32 data_len; + u32 total_len; + spinlock_t lock; +} cbuffer_t; + + +extern void cbuf_init(cbuffer_t *cbuffer, void *buf, u32 size); + +extern u32 cbuf_read(cbuffer_t *cbuffer, void *buf, u32 len); + +extern u32 cbuf_write(cbuffer_t *cbuffer, void *buf, u32 len); + +extern u32 cbuf_is_write_able(cbuffer_t *cbuffer, u32 len); + +extern void *cbuf_write_alloc(cbuffer_t *cbuffer, u32 *len); + +extern void cbuf_write_updata(cbuffer_t *cbuffer, u32 len); + +extern void *cbuf_read_alloc(cbuffer_t *cbuffer, u32 *len); + +extern void cbuf_read_updata(cbuffer_t *cbuffer, u32 len); + +extern void cbuf_clear(cbuffer_t *cbuffer); + +extern u32 cbuf_rewrite(cbuffer_t *cbuffer, void *begin, void *buf, u32 len); + +extern void cbuf_discard_prewrite(cbuffer_t *cbuffer); + +extern void cbuf_updata_prewrite(cbuffer_t *cbuffer); + +extern u32 cbuf_prewrite(cbuffer_t *cbuffer, void *buf, u32 len); + +extern void *cbuf_get_writeptr(cbuffer_t *cbuffer); + +extern u32 cbuf_get_data_size(cbuffer_t *cbuffer); + +extern void *cbuf_get_readptr(cbuffer_t *cbuffer); + +extern u32 cbuf_read_goback(cbuffer_t *cbuffer, u32 len); + +extern u32 cbuf_get_data_len(cbuffer_t *cbuffer); + +extern u32 cbuf_read_alloc_len(cbuffer_t *cbuffer, void *buf, u32 len); + +extern void cbuf_read_alloc_len_updata(cbuffer_t *cbuffer, u32 len); + +#endif + diff --git a/include_lib/system/generic/cpu.h b/include_lib/system/generic/cpu.h new file mode 100644 index 0000000..2c1c72d --- /dev/null +++ b/include_lib/system/generic/cpu.h @@ -0,0 +1,22 @@ +#ifndef GENERIC_CPU_H +#define GENERIC_CPU_H + +#include + + + + + + + + + + + + + + + + +#endif + diff --git a/include_lib/system/generic/debug_lite.h b/include_lib/system/generic/debug_lite.h new file mode 100644 index 0000000..e80e245 --- /dev/null +++ b/include_lib/system/generic/debug_lite.h @@ -0,0 +1,10 @@ +#ifndef _LITE_DEBUG_H_ +#define _LITE_DEBUG_H_ + + +extern void puts_lite(const char *out); +extern void put_buf_lite(void *_buf, u32 len); +extern int printf_lite(const char *format, ...); + +#endif /* #ifdef _LITE_DEBUG_H_ */ + diff --git a/include_lib/system/generic/errno-base.h b/include_lib/system/generic/errno-base.h new file mode 100644 index 0000000..562edfb --- /dev/null +++ b/include_lib/system/generic/errno-base.h @@ -0,0 +1,40 @@ +#ifndef _ASM_GENERIC_ERRNO_BASE_H +#define _ASM_GENERIC_ERRNO_BASE_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define ETIMEDOUT 35 /* Connection timed out */ + +#endif diff --git a/include_lib/system/generic/gpio.h b/include_lib/system/generic/gpio.h new file mode 100644 index 0000000..ba20df2 --- /dev/null +++ b/include_lib/system/generic/gpio.h @@ -0,0 +1,44 @@ +#ifndef ASM_GPIO_H +#define ASM_GPIO_H + + +#include "asm/gpio.h" + +#define GPIO2PORT(gpio) (gpio / IO_GROUP_NUM) + +void gpio_port_lock(unsigned int port); + +void gpio_port_unlock(unsigned int port); + +int __gpio_direction_input(unsigned int gpio); +int gpio_direction_input(unsigned int gpio); + +int __gpio_direction_output(unsigned int gpio, int value); +int gpio_direction_output(unsigned int gpio, int value); + +int __gpio_set_pull_up(unsigned int gpio, int value); +int gpio_set_pull_up(unsigned int gpio, int value); + +int __gpio_set_pull_down(unsigned int gpio, int value); +int gpio_set_pull_down(unsigned int gpio, int value); + +int __gpio_set_hd(unsigned int gpio, int value); +int gpio_set_hd(unsigned int gpio, int value); + +int __gpio_set_die(unsigned int gpio, int value); +int gpio_set_die(unsigned int gpio, int value); + +int __gpio_set_output_clk(unsigned int gpio, int clk); +int gpio_set_output_clk(unsigned int gpio, int clk); + +int __gpio_read(unsigned int gpio); +int gpio_read(unsigned int gpio); + + + + + + + + +#endif diff --git a/include_lib/system/generic/includes.h b/include_lib/system/generic/includes.h new file mode 100644 index 0000000..a7ed74a --- /dev/null +++ b/include_lib/system/generic/includes.h @@ -0,0 +1,36 @@ +#ifndef GENERIC_INCLUDES_H +#define GENERIC_INCLUDES_H + + +#include "errno-base.h" +#include "typedef.h" +#include "ascii.h" +#include "atomic.h" +#include "ioctl.h" +#include "cpu.h" +#include "gpio.h" +#include "irq.h" +#include "jiffies.h" +#include "list.h" +#include "printf.h" +#include "rect.h" +#include "version.h" +#include "lbuf.h" +#include "lbuf_lite.h" +#include "circular_buf.h" +#include "index.h" +#include "debug_lite.h" + + + + + + + + + + + + + +#endif diff --git a/include_lib/system/generic/index.h b/include_lib/system/generic/index.h new file mode 100644 index 0000000..f2a38f6 --- /dev/null +++ b/include_lib/system/generic/index.h @@ -0,0 +1,22 @@ +#ifndef INDEX_H +#define INDEX_H + + +#include "typedef.h" + + +#define TABLE(t) t, ARRAY_SIZE(t) + + +int index_of_table8(u8 value, const u8 *table, int table_size); + +int index_of_table16(u16 value, const u16 *table, int table_size); + +int index_of_table32(u32 value, const u32 *table, int table_size); + + + + + + +#endif diff --git a/include_lib/system/generic/ioctl.h b/include_lib/system/generic/ioctl.h new file mode 100644 index 0000000..82ad8c7 --- /dev/null +++ b/include_lib/system/generic/ioctl.h @@ -0,0 +1,106 @@ +#ifndef _ASM_GENERIC_IOCTL_H +#define _ASM_GENERIC_IOCTL_H + +/* ioctl command encoding: 32 bits total, command in lower 16 bits, + * size of the parameter structure in the lower 14 bits of the + * upper 16 bits. + * Encoding the size of the parameter structure in the ioctl request + * is useful for catching programs compiled with old versions + * and to avoid overwriting user space outside the user buffer area. + * The highest 2 bits are reserved for indicating the ``access mode''. + * NOTE: This limits the max parameter size to 16kB -1 ! + */ + +/* + * The following is for compatibility across the various Linux + * platforms. The generic ioctl numbering scheme doesn't really enforce + * a type field. De facto, however, the top 8 bits of the lower 16 + * bits are indeed used as a type field, so we might just as well make + * this explicit here. Please be sure to use the decoding macros + * below from now on. + */ +#define _IOC_NRBITS 8 +#define _IOC_TYPEBITS 8 + +/* + * Let any architecture override either of the following before + * including this file. + */ + +#ifndef _IOC_SIZEBITS +# define _IOC_SIZEBITS 14 +#endif + +#ifndef _IOC_DIRBITS +# define _IOC_DIRBITS 2 +#endif + +#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) +#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) +#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) +#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) + +#define _IOC_NRSHIFT 0 +#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) +#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) +#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) + +/* + * Direction bits, which any architecture can choose to override + * before including this file. + */ + +#ifndef _IOC_NONE +# define _IOC_NONE 0U +#endif + +#ifndef _IOC_WRITE +# define _IOC_WRITE 1U +#endif + +#ifndef _IOC_READ +# define _IOC_READ 2U +#endif + +#define _IOC(dir,type,nr,size) \ + (((dir) << _IOC_DIRSHIFT) | \ + ((type) << _IOC_TYPESHIFT) | \ + ((nr) << _IOC_NRSHIFT) | \ + ((size) << _IOC_SIZESHIFT)) + +#ifdef __KERNEL__ +/* provoke compile error for invalid uses of size argument */ +extern unsigned int __invalid_size_argument_for_IOC; +#define _IOC_TYPECHECK(t) \ + ((sizeof(t) == sizeof(t[1]) && \ + sizeof(t) < (1 << _IOC_SIZEBITS)) ? \ + sizeof(t) : __invalid_size_argument_for_IOC) +#else +#define _IOC_TYPECHECK(t) (sizeof(t)) + +#endif + +/* used to create numbers */ +#define _IO(type,nr) _IOC(_IOC_NONE,(type),(nr),0) +#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) +#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) +#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) +#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) + +/* used to decode ioctl numbers.. */ +#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) +#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) +#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) +#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) + +/* ...and for the drivers/sound files... */ + +#define IOC_IN (_IOC_WRITE << _IOC_DIRSHIFT) +#define IOC_OUT (_IOC_READ << _IOC_DIRSHIFT) +#define IOC_INOUT ((_IOC_WRITE|_IOC_READ) << _IOC_DIRSHIFT) +#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT) +#define IOCSIZE_SHIFT (_IOC_SIZESHIFT) + +#endif /* _ASM_GENERIC_IOCTL_H */ diff --git a/include_lib/system/generic/irq.h b/include_lib/system/generic/irq.h new file mode 100644 index 0000000..10a0e66 --- /dev/null +++ b/include_lib/system/generic/irq.h @@ -0,0 +1,23 @@ +#ifndef __IRQ_H_ +#define __IRQ_H_ + + +#include "asm/irq.h" + + + + + + + + + + + + + + + + +#endif + diff --git a/include_lib/system/generic/jiffies.h b/include_lib/system/generic/jiffies.h new file mode 100644 index 0000000..93a169f --- /dev/null +++ b/include_lib/system/generic/jiffies.h @@ -0,0 +1,35 @@ +#ifndef JIFFIES_H +#define JIFFIES_H +/* timer interface */ +/* Parameters used to convert the timespec values: */ +#define HZ 100L +#define MSEC_PER_SEC 1000L +#define USEC_PER_MSEC 1000L +#define NSEC_PER_USEC 1000L +#define NSEC_PER_MSEC 1000000L +#define USEC_PER_SEC 1000000L +#define NSEC_PER_SEC 1000000000L +#define FSEC_PER_SEC 1000000000000000LL + + +#ifndef __ASSEMBLY__ +extern volatile unsigned long jiffies; +extern unsigned long jiffies_msec(); +extern unsigned long jiffies_half_msec(); +#endif + +#define JIFFIES_CIRCLE 0x7FFFFFF + +#define time_after(a,b) ((long)(b) - (long)(a) < 0) +#define time_before(a,b) time_after(b,a) + +extern unsigned char jiffies_unit; + +#define msecs_to_jiffies(msec) ((msec)/jiffies_unit) +#define jiffies_to_msecs(j) ((j)*jiffies_unit) + + + + +#endif + diff --git a/include_lib/system/generic/lbuf.h b/include_lib/system/generic/lbuf.h new file mode 100644 index 0000000..890f4dc --- /dev/null +++ b/include_lib/system/generic/lbuf.h @@ -0,0 +1,68 @@ +#ifndef LBUF_H +#define LBUF_H + + +#include "typedef.h" +#include "list.h" +#include "system/spinlock.h" + + +struct lbuff_head { + int magic_a; + struct list_head head; + struct list_head free; + spinlock_t lock; + u8 align; + u16 priv_len; + u32 total_size; + u32 last_addr; + void *priv; + int magic_b; +}; + +struct lbuff_state { + u32 avaliable; + u32 fragment; + u32 max_continue_len; + int num; +}; + + + +struct lbuff_head *lbuf_init(void *buf, u32 len, int align, int priv_head_len); + +void *lbuf_alloc(struct lbuff_head *head, u32 len); + +void *lbuf_realloc(void *lbuf, int size); + +int lbuf_empty(struct lbuff_head *head); + +void lbuf_clear(struct lbuff_head *head); + +void lbuf_push(void *lbuf, u8 channel_map); + +void *lbuf_pop(struct lbuff_head *head, u8 channel); + +int lbuf_free(void *lbuf); + +void lbuf_free_check(void *lbuf, u32 rets); + +u32 lbuf_free_space(struct lbuff_head *head); + +void lbuf_state(struct lbuff_head *head, struct lbuff_state *state); + +void lbuf_dump(struct lbuff_head *head); + +int lbuf_traversal(struct lbuff_head *head); + +int lbuf_avaliable(struct lbuff_head *head, int size); + +int lbuf_real_size(void *lbuf); + +int lbuf_remain_space(struct lbuff_head *head); + +void lbuf_inc_ref(void *lbuf); + +#endif + + diff --git a/include_lib/system/generic/lbuf_lite.h b/include_lib/system/generic/lbuf_lite.h new file mode 100644 index 0000000..19628a5 --- /dev/null +++ b/include_lib/system/generic/lbuf_lite.h @@ -0,0 +1,50 @@ +#ifndef LBUF_LITE_H +#define LBUF_LITE_H + + +#include "typedef.h" +#include "list.h" +#include "system/spinlock.h" + + +struct lbuff_lite_head { + int magic_a; + struct list_head head; + struct list_head free; + spinlock_t lock; + u8 align; + u16 priv_len; + u32 total_size; + u32 last_addr; + void *priv; + int magic_b; +}; + +struct lbuff_lite_state { + u32 avaliable; + u32 fragment; + u32 max_continue_len; + int num; +}; + + + +struct lbuff_lite_head *lbuf_lite_init(void *buf, u32 len, int align, int priv_head_len); + +void *lbuf_lite_alloc(struct lbuff_lite_head *head, u32 len); + +void *lbuf_lite_realloc(void *lbuf, int size); + +void lbuf_lite_free(void *lbuf); + +u32 lbuf_lite_free_space(struct lbuff_lite_head *head); + +void lbuf_lite_state(struct lbuff_lite_head *head, struct lbuff_lite_state *state); + +void lbuf_lite_dump(struct lbuff_lite_head *head); + +int lbuf_lite_avaliable(struct lbuff_lite_head *head, int size); + +#endif + + diff --git a/include_lib/system/generic/list.h b/include_lib/system/generic/list.h new file mode 100644 index 0000000..bd16b0c --- /dev/null +++ b/include_lib/system/generic/list.h @@ -0,0 +1,291 @@ +#ifndef LIST_H +#define LIST_H + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#ifdef list_offsetof +#undef list_offsetof +#endif +#ifdef container_of +#undef container_of +#endif + +#define list_offsetof(type, memb) \ + ((unsigned long)(&((type *)0)->memb)) + +#define container_of(ptr, type, memb) \ + ((type *)((char *)(ptr) - list_offsetof(type, memb))) + + +struct list_head { + struct list_head *next, *prev; +}; + + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + + +/** + * list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + * + * Note, that list is expected to be not empty. + */ +/* REF_LIST: spi.c */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); \ + pos = pos->next) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + + +#define list_for_each_entry_reverse_safe(pos, n, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + n = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.prev, typeof(*n), member)) +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +/* REF_LIST: spi.c */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *_new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = _new; + _new->next = next; + _new->prev = prev; + prev->next = _new; +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +/* REF_LIST: spi.c */ +static inline void list_add_tail(struct list_head *_new, struct list_head *head) +{ + __list_add(_new, head->prev, head); +} + +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +static inline void __list_del_entry(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/* REF_LIST: spi.c */ +static inline void list_del(struct list_head *entry) //修改过的list_del,这里与list_del_init一样 +{ + __list_del(entry->prev, entry->next); + entry->next = entry; + entry->prev = entry; +} + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +static inline void list_del_init(struct list_head *entry) +{ + __list_del_entry(entry); + INIT_LIST_HEAD(entry); +} +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +static inline int list_is_head(struct list_head *head, struct list_head *member) +{ + return head->next == member; +} + +#if 0 +static inline void __list_splice(const struct list_head *list, + struct list_head *prev, + struct list_head *next) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + + first->prev = prev; + prev->next = first; + + last->next = next; + next->prev = last; +} + +/** + * list_splice_tail_init - join two lists and reinitialise the emptied list + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * Each of the lists is a queue. + * The list at @list is reinitialised + */ +static inline void list_splice_tail_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head->prev, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_is_singular - tests whether a list has just one entry. + * @head: the list to test. + */ +static inline int list_is_singular(const struct list_head *head) +{ + return !list_empty(head) && (head->next == head->prev); +} + +/** + * list_splice_tail - join two lists, each list being a queue + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice_tail(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head->prev, head); + } +} +#endif + +#define list_for_each_entry_from(pos, head, member) \ + for (; &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +#define list_for_each_entry_from_reverse(pos, head, member) \ + for (; &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +#endif + diff --git a/include_lib/system/generic/log.h b/include_lib/system/generic/log.h new file mode 100644 index 0000000..5f4d597 --- /dev/null +++ b/include_lib/system/generic/log.h @@ -0,0 +1,127 @@ +#ifndef __LOG_H +#define __LOG_H + + +#include "system/generic/printf.h" + +#define __LOG_VERB 0 +#define __LOG_DEBUG 1 +#define __LOG_INFO 2 +#define __LOG_WARN 3 +#define __LOG_ERROR 4 +#define __LOG_CHAR 5 + +struct logbuf { + u16 len; + u16 buf_len; + char buf[0]; +}; + +#define __LOG_ENABLE + +#ifndef __LOG_LEVEL +#define __LOG_LEVEL 0 +#endif + +#ifdef CONFIG_RELEASE_ENABLE +#undef __LOG_LEVEL +#define __LOG_LEVEL 0 +#endif + +#if __LOG_LEVEL > __LOG_VERB +#define log_v(...) do {} while (0) +#elif defined __LOG_ENABLE +#define log_v(...) log_print(__LOG_VERB, NULL, __VA_ARGS__) +#else +#define log_v(...) printf(__VA_ARGS__) +#endif + + + +#if __LOG_LEVEL > __LOG_DEBUG +#define log_d(...) do {} while (0) +#elif defined __LOG_ENABLE +#define log_d(...) log_print(__LOG_DEBUG, NULL, __VA_ARGS__); +#else +#define log_d(...) printf(__VA_ARGS__) +#endif + +#if __LOG_LEVEL > __LOG_INFO +#define log_i(...) do {} while (0) +#elif defined __LOG_ENABLE +#define log_i(...) log_print(__LOG_INFO, NULL, __VA_ARGS__); +#else +#define log_i(...) printf(__VA_ARGS__) +#endif + +#if __LOG_LEVEL > __LOG_WARN +#define log_w(...) do {} while (0) +#elif defined __LOG_ENABLE +#define log_w(...) log_print(__LOG_WARN, NULL, __VA_ARGS__); +#else +#define log_w(...) printf(__VA_ARGS__) +#endif + +#if __LOG_LEVEL > __LOG_ERROR +#define log_e(...) do {} while (0) +#elif defined __LOG_ENABLE +#define log_e(...) log_print(__LOG_ERROR, NULL, __VA_ARGS__); +#else +#define log_e(...) printf(__VA_ARGS__) +#endif + +#if __LOG_LEVEL > __LOG_CHAR +#define log_c(x) do {} while (0) +#elif defined __LOG_ENABLE +#define log_c(x) putchar(x) +#else +#define log_c(x) +#endif + +#define r_printf(x, ...) log_i("\e[31m\e[1m" x "\e[0m", ## __VA_ARGS__) +#define g_printf(x, ...) log_i("\e[32m\e[1m" x "\e[0m", ## __VA_ARGS__) +#define y_printf(x, ...) log_i("\e[33m\e[1m" x "\e[0m", ## __VA_ARGS__) +#define r_f_printf(x, ...) log_i("\e[31m\e[5m\e[1m" x "\e[0m", ## __VA_ARGS__) +#define g_f_printf(x, ...) log_i("\e[32m\e[5m\e[1m" x "\e[0m", ## __VA_ARGS__) +#define y_f_printf(x, ...) log_i("\e[33m\e[5m\e[1m" x "\e[0m", ## __VA_ARGS__) + +#ifndef __LOG_ENABLE +#define log_dump(a, b) do {} while(0) +#define log_putchar() do {} while(0) +#define log_early_init(a) do {} while(0) +#define log_level(a) do {} while(0) +#else + +int log_output_lock(); + +void log_output_unlock(); + +void log_print_time(); + +void log_early_init(int buf_size); + +void log_level(int level); + +void log_print(int level, const char *tag, const char *format, ...); + +void log_dump(const u8 *buf, int len); + +struct logbuf *log_output_start(int len); + +void log_output_end(struct logbuf *); + +void log_putchar(struct logbuf *lb, char c); + +void log_put_u8hex(struct logbuf *lb, unsigned char dat); + +void log_putbyte(char); + +void log_set_time_offset(int offset); + +int log_get_time_offset(); + +#endif + +void log_flush(); + +#endif diff --git a/include_lib/system/generic/printf.h b/include_lib/system/generic/printf.h new file mode 100644 index 0000000..e232313 --- /dev/null +++ b/include_lib/system/generic/printf.h @@ -0,0 +1,28 @@ +#ifndef _PRINTF_H_ +#define _PRINTF_H_ +#define line_inf printf("%s %s %d \r\n" ,__FILE__, __func__ , __LINE__) ; +#include +#include "typedef.h" +//#define NOFLOAT + +extern int putchar(int a); +extern int puts(const char *out); +void put_u4hex(unsigned char dat); +void put_u8hex(unsigned char dat); +void put_u16hex(unsigned short dat); +void put_u32hex(unsigned int dat); +void put_buf(const u8 *buf, int len); +int printf(const char *format, ...); +int assert_printf(const char *format, ...); +int sprintf(char *out, const char *format, ...); +int vprintf(const char *fmt, __builtin_va_list va); +int vsnprintf(char *, unsigned long, const char *, __builtin_va_list); +int snprintf(char *buf, unsigned long size, const char *fmt, ...); +int print(char **out, char *end, const char *format, va_list args); +//int snprintf(char *, unsigned long, const char *, ...); + +int sscanf(const char *buf, const char *fmt, ...); //BUG: 多个参数? 最后又空格? + +//int perror(const char *fmt, ...); + +#endif diff --git a/include_lib/system/generic/rect.h b/include_lib/system/generic/rect.h new file mode 100644 index 0000000..d8de90e --- /dev/null +++ b/include_lib/system/generic/rect.h @@ -0,0 +1,134 @@ +#ifndef RECT_H +#define RECT_H + +#include "typedef.h" + + +#define AT_UI_RAM AT(.ui_ram) + +struct position { + int x; + int y; +}; + +struct rect { + int left; + int top; + int width; + int height; +}; + +#define rect_left(r) ((r)->left) +#define rect_top(r) ((r)->top) +#define rect_right(r) ((r)->left + (r)->width) +#define rect_bottom(r) ((r)->top + (r)->height) + +//#define rect_height(v) ((v)->bottom - (v)->top) +//#define rect_width(v) ((v)->right - (v)->left) + + +static inline int in_rect(const struct rect *rect, struct position *pos) +{ + if (rect->left <= pos->x && rect_right(rect) > pos->x) { + if (rect->top <= pos->y && rect_bottom(rect) > pos->y) { + return true; + } + } + return false; +} + +AT_UI_RAM +static inline bool get_rect_cover(const struct rect *a, const struct rect *b, struct rect *c) +{ + int right, bottom; + + c->top = MAX(a->top, b->top); + c->left = MAX(a->left, b->left); + right = MIN(rect_right(a), rect_right(b)); + bottom = MIN(rect_bottom(a), rect_bottom(b)); + + if ((c->top < bottom) && (c->left < right)) { + c->width = right - c->left; + c->height = bottom - c->top; + return true; + } + + return false; +} + + +static inline bool get_rect_nocover_l(const struct rect *a, const struct rect *b, struct rect *c) +{ + int right, bottom; + + c->left = MIN(rect_left(a), rect_left(b)); + c->top = MIN(rect_top(a), rect_top(b)); + right = MAX(rect_left(a), rect_left(b)); + bottom = MAX(rect_bottom(a), rect_bottom(b)); + + if ((c->top < bottom) && (c->left < right)) { + c->width = right - c->left; + c->height = bottom - c->top; + return true; + } + + return false; +} + + +static inline bool get_rect_nocover_r(const struct rect *a, const struct rect *b, struct rect *c) +{ + int right, bottom; + + c->left = MIN(rect_right(a), rect_right(b)); + c->top = MIN(rect_top(a), rect_top(b)); + right = MAX(rect_right(a), rect_right(b)); + bottom = MAX(rect_bottom(a), rect_bottom(b)); + + if ((c->top < bottom) && (c->left < right)) { + c->width = right - c->left; + c->height = bottom - c->top; + return true; + } + + return false; +} + +static inline bool get_rect_nocover_t(const struct rect *a, const struct rect *b, struct rect *c) +{ + int right, bottom; + + c->left = MIN(rect_left(a), rect_left(b)); + c->top = MIN(rect_top(a), rect_top(b)); + right = MAX(rect_right(a), rect_right(b)); + bottom = MAX(rect_top(a), rect_top(b)); + + if ((c->top < bottom) && (c->left < right)) { + c->width = right - c->left; + c->height = bottom - c->top; + return true; + } + + return false; +} + +static inline bool get_rect_nocover_b(const struct rect *a, const struct rect *b, struct rect *c) +{ + int right, bottom; + + c->left = MIN(rect_left(a), rect_left(b)); + c->top = MIN(rect_bottom(a), rect_bottom(b)); + right = MAX(rect_right(a), rect_right(b)); + bottom = MAX(rect_bottom(a), rect_bottom(b)); + + if ((c->top < bottom) && (c->left < right)) { + c->width = right - c->left; + c->height = bottom - c->top; + return true; + } + + return false; +} + +#endif + diff --git a/include_lib/system/generic/typedef.h b/include_lib/system/generic/typedef.h new file mode 100644 index 0000000..2caed2f --- /dev/null +++ b/include_lib/system/generic/typedef.h @@ -0,0 +1,167 @@ +/************************************************************* +File: typedef.h +Author:Juntham +Discriptor: + 数据类型重定义 +Version: +Date: +*************************************************************/ +#ifndef _typedef_h_ +#define _typedef_h_ + + +#include "asm/cpu.h" + + +#if defined(__GNUC__) + +///>24)|((x>>8)&0xff00)|(x<<24)|((x&0xff00)<<8)) +//#define ntoh(x) (u16)((x>>8&0x00ff)|x<<8&0xff00) + +//#define ntohl(x) (u32)((((u32)(x))>>24) | ((((u32)(x))>>8)&0xff00) | (((u32)(x))<<24) | ((((u32)(x))&0xff00)<<8)) +//#define ntoh(x) (u16)((((u32)(x))>>8&0x00ff) | (((u32)(x))<<8&0xff00)) + +//#define NTOH(x) (x) = ntoh(x) +//#define NTOHL(x) (x) = ntohl(x) +#define LD_WORD(ptr) (u16)(*(u16*)(u8*)(ptr)) +#define LD_DWORD(ptr) (u32)(*(u32*)(u8*)(ptr)) +#define ST_WORD(ptr,val) *(u16*)(u8*)(ptr)=(u16)(val) +#define ST_DWORD(ptr,val) *(u32*)(u8*)(ptr)=(u32)(val) +#else +#define ntohl(x) (x) +#define ntoh(x) (x) +#define NTOH(x) (x) = ntoh(x) +#define NTOHL(x) (x) = ntohl(x) +#endif + + + +#undef FALSE +#define FALSE 0 + +#undef TRUE +#define TRUE 1 + +#define false 0 +#define true 1 + +#ifndef NULL +#define NULL (void *)0 +#endif + + + +#define BIT(n) (1UL << (n)) +#define BitSET(REG,POS) ((REG) |= (1L << (POS))) +#define BitCLR(REG,POS) ((REG) &= (~(1L<< (POS)))) +#define BitXOR(REG,POS) ((REG) ^= (~(1L << (POS)))) +#define BitCHK_1(REG,POS) (((REG) & (1L << (POS))) == (1L << (POS))) +#define BitCHK_0(REG,POS) (((REG) & (1L << (POS))) == 0x00) +#define testBit(REG,POS) ((REG) & (1L << (POS))) + +#define clrBit(x,y) (x) &= ~(1L << (y)) +#define setBit(x,y) (x) |= (1L << (y)) + + +#define readb(addr) *((volatile unsigned char*)(addr)) +#define readw(addr) *((volatile unsigned short *)(addr)) +#define readl(addr) *((volatile unsigned long*)(addr)) + +#define writeb(addr, val) *((volatile unsigned char*)(addr)) = (u8)(val) +#define writew(addr, val) *((volatile unsigned short *)(addr)) = (u16)(val) +#define writel(addr, val) *((volatile unsigned long*)(addr)) = (u32)(val) + +#define ALIGN_4BYTE(size) ((size+3)&0xfffffffc) + +#if CPU_ENDIAN == BIG_ENDIAN +#define __cpu_u16(lo, hi) ((lo)|((hi)<<8)) +#elif CPU_ENDIAN == LITTLE_ENDIAN +#define __cpu_u16(lo, hi) ((hi)|((lo)<<8)) +#else +#error "undefine cpu eadin" +#endif + + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif + + +#define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0])) + + +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + +#define SFR(sfr, start, len, dat) \ + (sfr = (sfr & ~((~(0xffffffff << (len))) << (start))) | \ + (((dat) & (~(0xffffffff << (len)))) << (start))) + + +#include "generic/errno-base.h" +#include "string.h" +#include "strings.h" +#include "system/malloc.h" + + +#ifdef offsetof +#undef offsetof +#endif + +#ifdef container_of +#undef container_of +#endif + +#define offsetof(type, memb) \ + ((unsigned long)(&((type *)0)->memb)) + +#define container_of(ptr, type, memb) \ + ((type *)((char *)(ptr) - offsetof(type, memb))) + +void delay(unsigned int); + +void delay_us(unsigned int); + + +#endif + + + diff --git a/include_lib/system/generic/version.h b/include_lib/system/generic/version.h new file mode 100644 index 0000000..58096a6 --- /dev/null +++ b/include_lib/system/generic/version.h @@ -0,0 +1,133 @@ +#ifndef VERSION_H +#define VERSION_H + +#include "typedef.h" + + +typedef int (*version_t)(int); + + +//定义模块的版本号,由主版本号和次版本号组成 +//如果两个模块的主版本号相同即表示兼容 +#define VERSION(major, minor) (((major)<<8) | (minor)) + +#define MAJOR(v) ((v) >> 16) +#define MINOR(v) (((v) >> 8) & 0xff) + +#define version_match(module_a, module_b) \ + ({ \ + extern int module_a##_version(int ); \ + extern int module_b##_version(int ); \ + int version_a = module_a##_version(0); \ + int version_b = module_b##_version(0); \ + MAJOR(version_a) == MAJOR(version_b);\ + }) + + + + + +#define __MODULE_VERSION_EXPORT_BEGIN(module, version) \ + int module##_version(int prt) \ + { \ + if (prt) { \ + log_i(#module": %d.%d.%d build at: %s\n", (version)>>16, \ + ((version) >> 8) & 0xff, (version) & 0xff, __DATE__); \ + } \ + +#define __MODULE_VERSION_EXPORT_END(module, version) \ + return version; \ + } \ + const version_t __version_##module \ + __attribute__((section(".lib_version"),used)) = module##_version + +#define __MODULE_VERSION_EXPORT(module, version) \ + __MODULE_VERSION_EXPORT_BEGIN(module, version) \ + __MODULE_VERSION_EXPORT_END(module, version); + + +#define __MODULE_VERSION_EXPORT_SECTION(module, version, section) \ + __MODULE_VERSION_EXPORT_BEGIN(module, version) \ + (void *)§ion; \ + __MODULE_VERSION_EXPORT_END(module, version) + +#define __MODULE_DEPEND_BEGIN(module) \ + int module##_version_check() \ + { \ + + +#define _MODULE_DEPEND_BEGIN(module) \ + __MODULE_DEPEND_BEGIN(module) + + +#define __VERSION_CHECK(module, version) \ + do { \ + int module##_version(int prt); \ + int v = module##_version(0); \ + if (MAJOR(version) != MAJOR(v) || MINOR(version) > MINOR(v)) { \ + log_i("=======version not match=======\n"); \ + module##_version(1); \ + log_i("==================================\n"); \ + while(1); \ + } \ + } while(0) +/*-------------------上面的宏请勿调用------------------------------------*/ + + + + + + +//定义当前模块的版本检测函数 +#define MODULE_VERSION_EXPORT(module, version) \ + __MODULE_VERSION_EXPORT(module, version) + +#define MODULE_VERSION_EXPORT_SECTION(module, version, section) \ + __MODULE_VERSION_EXPORT_SECTION(module, version, section) + +#define MODULE_VERSION_EXPORT_BEGIN(module, version) \ + __MODULE_VERSION_EXPORT_BEGIN(module, version) + +#define MODULE_VERSION_EXPORT_END(module, version) \ + __MODULE_VERSION_EXPORT_END(module, version) + +//以下3个宏定义当前模块依赖的其它模块列表 +#define MODULE_DEPEND_BEGIN() \ + _MODULE_DEPEND_BEGIN(THIS_MODULE) + +#define MODULE_DEPEND(module_d, version) \ + __VERSION_CHECK(module_d, version) + +#define MODULE_DEPEND_END() \ + return 0; \ + } + + +#define VERSION_CHECK(module, version) \ + __VERSION_CHECK(module, version) + + +//通过调用版本检测函数使的模块的代码能够被链接 +#define load_module(module) \ + ({ \ + int ret; \ + extern int module##_version_check(); \ + ret = module##_version_check();\ + ret; \ + }) + +extern version_t lib_version_begin[], lib_version_end[]; + +#define lib_version_check() \ + do { \ + version_t *version; \ + log_i("=========version check===========\n"); \ + for (version = lib_version_begin; version < lib_version_end; version++) { \ + (*version)(1); \ + }; \ + log_i("==================================\n\n"); \ + } while (0) + + +#endif + diff --git a/include_lib/system/includes.h b/include_lib/system/includes.h new file mode 100644 index 0000000..984a850 --- /dev/null +++ b/include_lib/system/includes.h @@ -0,0 +1,46 @@ +#ifndef SYS_INCLUDES_H +#define SYS_INCLUDES_H + + +#include "init.h" +#include "event.h" +#include "malloc.h" +#include "spinlock.h" +#include "task.h" +#include "timer.h" +#include "wait.h" +#include "app_core.h" +#include "app_msg.h" +#include "database.h" +#include "fs/fs.h" +#include "power_manage.h" +#include "syscfg_id.h" +#include "bank_switch.h" + + + +#include "generic/includes.h" +#include "device/includes.h" +#include "asm/includes.h" +#include "device/sdio_host_init.h" + +#include "crypto_toolbox/crypto.h" +#include "crypto_toolbox/Crypto_hash.h" +#include "crypto_toolbox/hmac.h" +#include "crypto_toolbox/sha256.h" +#include "crypto_toolbox/bigint.h" +#include "crypto_toolbox/bigint_impl.h" +// #include "crypto_toolbox/endian.h" +#include "crypto_toolbox/ecdh.h" + +#ifdef CONFIG_NEW_ECC_ENABLE +#include "crypto_toolbox/micro-ecc/uECC_new.h" +#else +#include "crypto_toolbox/micro-ecc/uECC.h" +#endif /* CONFIG_NEW_ECC_ENABLE */ +#include "crypto_toolbox/aes_cmac.h" +#include "crypto_toolbox/rijndael.h" + + +#endif + diff --git a/include_lib/system/init.h b/include_lib/system/init.h new file mode 100644 index 0000000..da90c8a --- /dev/null +++ b/include_lib/system/init.h @@ -0,0 +1,49 @@ +#ifndef SYS_INIT_H +#define SYS_INIT_H + + + + + + + +typedef int (*initcall_t)(void); + +#define __initcall(fn) \ + const initcall_t __initcall_##fn sec(.initcall) = fn + +#define early_initcall(fn) \ + const initcall_t __initcall_##fn sec(.early.initcall) = fn + + +#define late_initcall(fn) \ + const initcall_t __initcall_##fn sec(.late.initcall) = fn + + +#define platform_initcall(fn) \ + const initcall_t __initcall_##fn sec(.platform.initcall) = fn + + +#define module_initcall(fn) \ + const initcall_t __initcall_##fn sec(.module.initcall) = fn + + + + +#define __do_initcall(prefix) \ + do { \ + initcall_t *init; \ + extern initcall_t prefix##_begin[], prefix##_end[]; \ + for (init=prefix##_begin; init>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef INC_FREERTOS_H +#define INC_FREERTOS_H + +/* + * Include the generic headers required for the FreeRTOS port being used. + */ +//#include + +/* + * If stdint.h cannot be located then: + * + If using GCC ensure the -nostdint options is *not* being used. + * + Ensure the project's include path includes the directory in which your + * compiler stores stdint.h. + * + Set any compiler options necessary for it to support C99, as technically + * stdint.h is only mandatory with C99 (FreeRTOS does not require C99 in any + * other way). + * + The FreeRTOS download includes a simple stdint.h definition that can be + * used in cases where none is provided by the compiler. The files only + * contains the typedefs required to build FreeRTOS. Read the instructions + * in FreeRTOS/source/stdint.readme for more information. + */ +//#include /* READ COMMENT ABOVE. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Application specific configuration options. */ +#include "FreeRTOSConfig.h" + +/* Basic FreeRTOS definitions. */ +#include "projdefs.h" + +/* Definitions specific to the port being used. */ +#include "portable.h" + +/* Must be defaulted before configUSE_NEWLIB_REENTRANT is used below. */ +#ifndef configUSE_NEWLIB_REENTRANT +#define configUSE_NEWLIB_REENTRANT 0 +#endif + +/* Required if struct _reent is used. */ +#if ( configUSE_NEWLIB_REENTRANT == 1 ) +#include +#endif +/* + * Check all the required application specific macros have been defined. + * These macros are application specific and (as downloaded) are defined + * within FreeRTOSConfig.h. + */ + +#ifndef configMINIMAL_STACK_SIZE +#error Missing definition: configMINIMAL_STACK_SIZE must be defined in FreeRTOSConfig.h. configMINIMAL_STACK_SIZE defines the size (in words) of the stack allocated to the idle task. Refer to the demo project provided for your port for a suitable value. +#endif + +#ifndef configMAX_PRIORITIES +#error Missing definition: configMAX_PRIORITIES must be defined in FreeRTOSConfig.h. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_PREEMPTION +#error Missing definition: configUSE_PREEMPTION must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_IDLE_HOOK +#error Missing definition: configUSE_IDLE_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_TICK_HOOK +#error Missing definition: configUSE_TICK_HOOK must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configUSE_16_BIT_TICKS +#error Missing definition: configUSE_16_BIT_TICKS must be defined in FreeRTOSConfig.h as either 1 or 0. See the Configuration section of the FreeRTOS API documentation for details. +#endif + +#ifndef configMAX_PRIORITIES +#error configMAX_PRIORITIES must be defined to be greater than or equal to 1. +#endif + +#ifndef configUSE_CO_ROUTINES +#define configUSE_CO_ROUTINES 0 +#endif + +#ifndef INCLUDE_vTaskPrioritySet +#define INCLUDE_vTaskPrioritySet 0 +#endif + +#ifndef INCLUDE_uxTaskPriorityGet +#define INCLUDE_uxTaskPriorityGet 0 +#endif + +#ifndef INCLUDE_vTaskDelete +#define INCLUDE_vTaskDelete 0 +#endif + +#ifndef INCLUDE_vTaskSuspend +#define INCLUDE_vTaskSuspend 0 +#endif + +#ifndef INCLUDE_vTaskDelayUntil +#define INCLUDE_vTaskDelayUntil 0 +#endif + +#ifndef INCLUDE_vTaskDelay +#define INCLUDE_vTaskDelay 0 +#endif + +#ifndef INCLUDE_xTaskGetIdleTaskHandle +#define INCLUDE_xTaskGetIdleTaskHandle 0 +#endif + +#ifndef INCLUDE_xTaskAbortDelay +#define INCLUDE_xTaskAbortDelay 0 +#endif + +#ifndef INCLUDE_xQueueGetMutexHolder +#define INCLUDE_xQueueGetMutexHolder 0 +#endif + +#ifndef INCLUDE_xSemaphoreGetMutexHolder +#define INCLUDE_xSemaphoreGetMutexHolder INCLUDE_xQueueGetMutexHolder +#endif + +#ifndef INCLUDE_xTaskGetHandle +#define INCLUDE_xTaskGetHandle 0 +#endif + +#ifndef INCLUDE_uxTaskGetStackHighWaterMark +#define INCLUDE_uxTaskGetStackHighWaterMark 0 +#endif + +#ifndef INCLUDE_eTaskGetState +#define INCLUDE_eTaskGetState 0 +#endif + +#ifndef INCLUDE_xTaskResumeFromISR +#define INCLUDE_xTaskResumeFromISR 1 +#endif + +#ifndef INCLUDE_xTimerPendFunctionCall +#define INCLUDE_xTimerPendFunctionCall 0 +#endif + +#ifndef INCLUDE_xTaskGetSchedulerState +#define INCLUDE_xTaskGetSchedulerState 0 +#endif + +#ifndef INCLUDE_xTaskGetCurrentTaskHandle +#define INCLUDE_xTaskGetCurrentTaskHandle 0 +#endif + +#if configUSE_CO_ROUTINES != 0 +#ifndef configMAX_CO_ROUTINE_PRIORITIES +#error configMAX_CO_ROUTINE_PRIORITIES must be greater than or equal to 1. +#endif +#endif + +#ifndef configUSE_DAEMON_TASK_STARTUP_HOOK +#define configUSE_DAEMON_TASK_STARTUP_HOOK 0 +#endif + +#ifndef configUSE_APPLICATION_TASK_TAG +#define configUSE_APPLICATION_TASK_TAG 0 +#endif + +#ifndef configNUM_THREAD_LOCAL_STORAGE_POINTERS +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS 0 +#endif + +#ifndef configUSE_RECURSIVE_MUTEXES +#define configUSE_RECURSIVE_MUTEXES 0 +#endif + +#ifndef configUSE_MUTEXES +#define configUSE_MUTEXES 0 +#endif + +#ifndef configUSE_TIMERS +#define configUSE_TIMERS 0 +#endif + +#ifndef configUSE_COUNTING_SEMAPHORES +#define configUSE_COUNTING_SEMAPHORES 0 +#endif + +#ifndef configUSE_ALTERNATIVE_API +#define configUSE_ALTERNATIVE_API 0 +#endif + +#ifndef portCRITICAL_NESTING_IN_TCB +#define portCRITICAL_NESTING_IN_TCB 0 +#endif + +#ifndef configMAX_TASK_NAME_LEN +#define configMAX_TASK_NAME_LEN 16 +#endif + +#ifndef configIDLE_SHOULD_YIELD +#define configIDLE_SHOULD_YIELD 1 +#endif + +#if configMAX_TASK_NAME_LEN < 1 +#error configMAX_TASK_NAME_LEN must be set to a minimum of 1 in FreeRTOSConfig.h +#endif + +#ifndef configASSERT +#define configASSERT( x ) +#define configASSERT_DEFINED 0 +#else +#define configASSERT_DEFINED 1 +#endif + +/* The timers module relies on xTaskGetSchedulerState(). */ +#if configUSE_TIMERS == 1 + +#ifndef configTIMER_TASK_PRIORITY +#error If configUSE_TIMERS is set to 1 then configTIMER_TASK_PRIORITY must also be defined. +#endif /* configTIMER_TASK_PRIORITY */ + +#ifndef configTIMER_QUEUE_LENGTH +#error If configUSE_TIMERS is set to 1 then configTIMER_QUEUE_LENGTH must also be defined. +#endif /* configTIMER_QUEUE_LENGTH */ + +#ifndef configTIMER_TASK_STACK_DEPTH +#error If configUSE_TIMERS is set to 1 then configTIMER_TASK_STACK_DEPTH must also be defined. +#endif /* configTIMER_TASK_STACK_DEPTH */ + +#endif /* configUSE_TIMERS */ + +#ifndef portSET_INTERRUPT_MASK_FROM_ISR +#define portSET_INTERRUPT_MASK_FROM_ISR() 0 +#endif + +#ifndef portCLEAR_INTERRUPT_MASK_FROM_ISR +#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue ) ( void ) uxSavedStatusValue +#endif + +#ifndef portCLEAN_UP_TCB +#define portCLEAN_UP_TCB( pxTCB ) ( void ) pxTCB +#endif + +#ifndef portPRE_TASK_DELETE_HOOK +#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxYieldPending ) +#endif + +#ifndef portSETUP_TCB +#define portSETUP_TCB( pxTCB ) ( void ) pxTCB +#endif + +#ifndef configQUEUE_REGISTRY_SIZE +#define configQUEUE_REGISTRY_SIZE 0U +#endif + +#if ( configQUEUE_REGISTRY_SIZE < 1 ) +#define vQueueAddToRegistry( xQueue, pcName ) +#define vQueueUnregisterQueue( xQueue ) +#define pcQueueGetName( xQueue ) +#endif + +#ifndef portPOINTER_SIZE_TYPE +#define portPOINTER_SIZE_TYPE uint32_t +#endif + +/* Remove any unused trace macros. */ +#ifndef traceSTART +/* Used to perform any necessary initialisation - for example, open a file +into which trace is to be written. */ +#define traceSTART() +#endif + +#ifndef traceEND +/* Use to close a trace, for example close a file into which trace has been +written. */ +#define traceEND() +#endif + +#ifndef traceTASK_SWITCHED_IN +/* Called after a task has been selected to run. pxCurrentTCB holds a pointer +to the task control block of the selected task. */ +#define traceTASK_SWITCHED_IN() +#endif + +#ifndef traceINCREASE_TICK_COUNT +/* Called before stepping the tick count after waking from tickless idle +sleep. */ +#define traceINCREASE_TICK_COUNT( x ) +#endif + +#ifndef traceLOW_POWER_IDLE_BEGIN +/* Called immediately before entering tickless idle. */ +#define traceLOW_POWER_IDLE_BEGIN() +#endif + +#ifndef traceLOW_POWER_IDLE_END +/* Called when returning to the Idle task after a tickless idle. */ +#define traceLOW_POWER_IDLE_END() +#endif + +#ifndef traceTASK_SWITCHED_OUT +/* Called before a task has been selected to run. pxCurrentTCB holds a pointer +to the task control block of the task being switched out. */ +#define traceTASK_SWITCHED_OUT() +#endif + +#ifndef traceTASK_PRIORITY_INHERIT +/* Called when a task attempts to take a mutex that is already held by a +lower priority task. pxTCBOfMutexHolder is a pointer to the TCB of the task +that holds the mutex. uxInheritedPriority is the priority the mutex holder +will inherit (the priority of the task that is attempting to obtain the +muted. */ +#define traceTASK_PRIORITY_INHERIT( pxTCBOfMutexHolder, uxInheritedPriority ) +#endif + +#ifndef traceTASK_PRIORITY_DISINHERIT +/* Called when a task releases a mutex, the holding of which had resulted in +the task inheriting the priority of a higher priority task. +pxTCBOfMutexHolder is a pointer to the TCB of the task that is releasing the +mutex. uxOriginalPriority is the task's configured (base) priority. */ +#define traceTASK_PRIORITY_DISINHERIT( pxTCBOfMutexHolder, uxOriginalPriority ) +#endif + +#ifndef traceBLOCKING_ON_QUEUE_RECEIVE +/* Task is about to block because it cannot read from a +queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore +upon which the read was attempted. pxCurrentTCB points to the TCB of the +task that attempted the read. */ +#define traceBLOCKING_ON_QUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceBLOCKING_ON_QUEUE_SEND +/* Task is about to block because it cannot write to a +queue/mutex/semaphore. pxQueue is a pointer to the queue/mutex/semaphore +upon which the write was attempted. pxCurrentTCB points to the TCB of the +task that attempted the write. */ +#define traceBLOCKING_ON_QUEUE_SEND( pxQueue ) +#endif + +#ifndef configCHECK_FOR_STACK_OVERFLOW +#define configCHECK_FOR_STACK_OVERFLOW 0 +#endif + +/* The following event macros are embedded in the kernel API calls. */ + +#ifndef traceMOVED_TASK_TO_READY_STATE +#define traceMOVED_TASK_TO_READY_STATE( pxTCB ) +#endif + +#ifndef tracePOST_MOVED_TASK_TO_READY_STATE +#define tracePOST_MOVED_TASK_TO_READY_STATE( pxTCB ) +#endif + +#ifndef traceQUEUE_CREATE +#define traceQUEUE_CREATE( pxNewQueue ) +#endif + +#ifndef traceQUEUE_CREATE_FAILED +#define traceQUEUE_CREATE_FAILED( ucQueueType ) +#endif + +#ifndef traceCREATE_MUTEX +#define traceCREATE_MUTEX( pxNewQueue ) +#endif + +#ifndef traceCREATE_MUTEX_FAILED +#define traceCREATE_MUTEX_FAILED() +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE +#define traceGIVE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceGIVE_MUTEX_RECURSIVE_FAILED +#define traceGIVE_MUTEX_RECURSIVE_FAILED( pxMutex ) +#endif + +#ifndef traceTAKE_MUTEX_RECURSIVE +#define traceTAKE_MUTEX_RECURSIVE( pxMutex ) +#endif + +#ifndef traceTAKE_MUTEX_RECURSIVE_FAILED +#define traceTAKE_MUTEX_RECURSIVE_FAILED( pxMutex ) +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE +#define traceCREATE_COUNTING_SEMAPHORE() +#endif + +#ifndef traceCREATE_COUNTING_SEMAPHORE_FAILED +#define traceCREATE_COUNTING_SEMAPHORE_FAILED() +#endif + +#ifndef traceQUEUE_SEND +#define traceQUEUE_SEND( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FAILED +#define traceQUEUE_SEND_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE +#define traceQUEUE_RECEIVE( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK +#define traceQUEUE_PEEK( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK_FROM_ISR +#define traceQUEUE_PEEK_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FAILED +#define traceQUEUE_RECEIVE_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR +#define traceQUEUE_SEND_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_SEND_FROM_ISR_FAILED +#define traceQUEUE_SEND_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR +#define traceQUEUE_RECEIVE_FROM_ISR( pxQueue ) +#endif + +#ifndef traceQUEUE_RECEIVE_FROM_ISR_FAILED +#define traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_PEEK_FROM_ISR_FAILED +#define traceQUEUE_PEEK_FROM_ISR_FAILED( pxQueue ) +#endif + +#ifndef traceQUEUE_DELETE +#define traceQUEUE_DELETE( pxQueue ) +#endif + +#ifndef traceTASK_CREATE +#define traceTASK_CREATE( pxNewTCB ) +#endif + +#ifndef traceTASK_CREATE_FAILED +#define traceTASK_CREATE_FAILED() +#endif + +#ifndef traceTASK_DELETE +#define traceTASK_DELETE( pxTaskToDelete ) +#endif + +#ifndef traceTASK_DELAY_UNTIL +#define traceTASK_DELAY_UNTIL( x ) +#endif + +#ifndef traceTASK_DELAY +#define traceTASK_DELAY() +#endif + +#ifndef traceTASK_PRIORITY_SET +#define traceTASK_PRIORITY_SET( pxTask, uxNewPriority ) +#endif + +#ifndef traceTASK_SUSPEND +#define traceTASK_SUSPEND( pxTaskToSuspend ) +#endif + +#ifndef traceTASK_RESUME +#define traceTASK_RESUME( pxTaskToResume ) +#endif + +#ifndef traceTASK_RESUME_FROM_ISR +#define traceTASK_RESUME_FROM_ISR( pxTaskToResume ) +#endif + +#ifndef traceTASK_INCREMENT_TICK +#define traceTASK_INCREMENT_TICK( xTickCount ) +#endif + +#ifndef traceTIMER_CREATE +#define traceTIMER_CREATE( pxNewTimer ) +#endif + +#ifndef traceTIMER_CREATE_FAILED +#define traceTIMER_CREATE_FAILED() +#endif + +#ifndef traceTIMER_COMMAND_SEND +#define traceTIMER_COMMAND_SEND( xTimer, xMessageID, xMessageValueValue, xReturn ) +#endif + +#ifndef traceTIMER_EXPIRED +#define traceTIMER_EXPIRED( pxTimer ) +#endif + +#ifndef traceTIMER_COMMAND_RECEIVED +#define traceTIMER_COMMAND_RECEIVED( pxTimer, xMessageID, xMessageValue ) +#endif + +#ifndef traceMALLOC +#define traceMALLOC( pvAddress, uiSize ) +#endif + +#ifndef traceFREE +#define traceFREE( pvAddress, uiSize ) +#endif + +#ifndef traceEVENT_GROUP_CREATE +#define traceEVENT_GROUP_CREATE( xEventGroup ) +#endif + +#ifndef traceEVENT_GROUP_CREATE_FAILED +#define traceEVENT_GROUP_CREATE_FAILED() +#endif + +#ifndef traceEVENT_GROUP_SYNC_BLOCK +#define traceEVENT_GROUP_SYNC_BLOCK( xEventGroup, uxBitsToSet, uxBitsToWaitFor ) +#endif + +#ifndef traceEVENT_GROUP_SYNC_END +#define traceEVENT_GROUP_SYNC_END( xEventGroup, uxBitsToSet, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred +#endif + +#ifndef traceEVENT_GROUP_WAIT_BITS_BLOCK +#define traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor ) +#endif + +#ifndef traceEVENT_GROUP_WAIT_BITS_END +#define traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred ) ( void ) xTimeoutOccurred +#endif + +#ifndef traceEVENT_GROUP_CLEAR_BITS +#define traceEVENT_GROUP_CLEAR_BITS( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceEVENT_GROUP_CLEAR_BITS_FROM_ISR +#define traceEVENT_GROUP_CLEAR_BITS_FROM_ISR( xEventGroup, uxBitsToClear ) +#endif + +#ifndef traceEVENT_GROUP_SET_BITS +#define traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet ) +#endif + +#ifndef traceEVENT_GROUP_SET_BITS_FROM_ISR +#define traceEVENT_GROUP_SET_BITS_FROM_ISR( xEventGroup, uxBitsToSet ) +#endif + +#ifndef traceEVENT_GROUP_DELETE +#define traceEVENT_GROUP_DELETE( xEventGroup ) +#endif + +#ifndef tracePEND_FUNC_CALL +#define tracePEND_FUNC_CALL(xFunctionToPend, pvParameter1, ulParameter2, ret) +#endif + +#ifndef tracePEND_FUNC_CALL_FROM_ISR +#define tracePEND_FUNC_CALL_FROM_ISR(xFunctionToPend, pvParameter1, ulParameter2, ret) +#endif + +#ifndef traceQUEUE_REGISTRY_ADD +#define traceQUEUE_REGISTRY_ADD(xQueue, pcQueueName) +#endif + +#ifndef traceTASK_NOTIFY_TAKE_BLOCK +#define traceTASK_NOTIFY_TAKE_BLOCK() +#endif + +#ifndef traceTASK_NOTIFY_TAKE +#define traceTASK_NOTIFY_TAKE() +#endif + +#ifndef traceTASK_NOTIFY_WAIT_BLOCK +#define traceTASK_NOTIFY_WAIT_BLOCK() +#endif + +#ifndef traceTASK_NOTIFY_WAIT +#define traceTASK_NOTIFY_WAIT() +#endif + +#ifndef traceTASK_NOTIFY +#define traceTASK_NOTIFY() +#endif + +#ifndef traceTASK_NOTIFY_FROM_ISR +#define traceTASK_NOTIFY_FROM_ISR() +#endif + +#ifndef traceTASK_NOTIFY_GIVE_FROM_ISR +#define traceTASK_NOTIFY_GIVE_FROM_ISR() +#endif + +#ifndef configGENERATE_RUN_TIME_STATS +#define configGENERATE_RUN_TIME_STATS 0 +#endif + +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + +#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS +#error If configGENERATE_RUN_TIME_STATS is defined then portCONFIGURE_TIMER_FOR_RUN_TIME_STATS must also be defined. portCONFIGURE_TIMER_FOR_RUN_TIME_STATS should call a port layer function to setup a peripheral timer/counter that can then be used as the run time counter time base. +#endif /* portCONFIGURE_TIMER_FOR_RUN_TIME_STATS */ + +#ifndef portGET_RUN_TIME_COUNTER_VALUE +#ifndef portALT_GET_RUN_TIME_COUNTER_VALUE +#error If configGENERATE_RUN_TIME_STATS is defined then either portGET_RUN_TIME_COUNTER_VALUE or portALT_GET_RUN_TIME_COUNTER_VALUE must also be defined. See the examples provided and the FreeRTOS web site for more information. +#endif /* portALT_GET_RUN_TIME_COUNTER_VALUE */ +#endif /* portGET_RUN_TIME_COUNTER_VALUE */ + +#endif /* configGENERATE_RUN_TIME_STATS */ + +#ifndef portCONFIGURE_TIMER_FOR_RUN_TIME_STATS +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() +#endif + +#ifndef configUSE_MALLOC_FAILED_HOOK +#define configUSE_MALLOC_FAILED_HOOK 0 +#endif + +#ifndef portPRIVILEGE_BIT +#define portPRIVILEGE_BIT ( ( UBaseType_t ) 0x00 ) +#endif + +#ifndef portYIELD_WITHIN_API +#define portYIELD_WITHIN_API portYIELD +#endif + +#ifndef portSUPPRESS_TICKS_AND_SLEEP +#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) +#endif + +#ifndef configEXPECTED_IDLE_TIME_BEFORE_SLEEP +#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP 2 +#endif + +#if configEXPECTED_IDLE_TIME_BEFORE_SLEEP < 2 +#error configEXPECTED_IDLE_TIME_BEFORE_SLEEP must not be less than 2 +#endif + +#ifndef configUSE_TICKLESS_IDLE +#define configUSE_TICKLESS_IDLE 1 +#endif + +#ifndef configPRE_SLEEP_PROCESSING +#define configPRE_SLEEP_PROCESSING( x ) +#endif + +#ifndef configPOST_SLEEP_PROCESSING +#define configPOST_SLEEP_PROCESSING( x ) +#endif + +#ifndef configUSE_QUEUE_SETS +#define configUSE_QUEUE_SETS 0 +#endif + +#ifndef portTASK_USES_FLOATING_POINT +#define portTASK_USES_FLOATING_POINT() +#endif + +#ifndef configUSE_TIME_SLICING +#define configUSE_TIME_SLICING 1 +#endif + +#ifndef configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS +#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS 0 +#endif + +#ifndef configUSE_STATS_FORMATTING_FUNCTIONS +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 +#endif + +#ifndef portASSERT_IF_INTERRUPT_PRIORITY_INVALID +#define portASSERT_IF_INTERRUPT_PRIORITY_INVALID() +#endif + +#ifndef configUSE_TRACE_FACILITY +#define configUSE_TRACE_FACILITY 0 +#endif + +#ifndef mtCOVERAGE_TEST_MARKER +#define mtCOVERAGE_TEST_MARKER() +#endif + +#ifndef mtCOVERAGE_TEST_DELAY +#define mtCOVERAGE_TEST_DELAY() +#endif + +#ifndef portASSERT_IF_IN_ISR +#define portASSERT_IF_IN_ISR() +#endif + +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 +#endif + +#ifndef configAPPLICATION_ALLOCATED_HEAP +#define configAPPLICATION_ALLOCATED_HEAP 0 +#endif + +#ifndef configUSE_TASK_NOTIFICATIONS +#define configUSE_TASK_NOTIFICATIONS 1 +#endif + +#ifndef portTICK_TYPE_IS_ATOMIC +#define portTICK_TYPE_IS_ATOMIC 0 +#endif + +#ifndef configSUPPORT_STATIC_ALLOCATION +/* Defaults to 0 for backward compatibility. */ +#define configSUPPORT_STATIC_ALLOCATION 0 +#endif + +#ifndef configSUPPORT_DYNAMIC_ALLOCATION +/* Defaults to 1 for backward compatibility. */ +#define configSUPPORT_DYNAMIC_ALLOCATION 1 +#endif + +/* Sanity check the configuration. */ +#if( configUSE_TICKLESS_IDLE != 0 ) +#if( INCLUDE_vTaskSuspend != 1 ) +#error INCLUDE_vTaskSuspend must be set to 1 if configUSE_TICKLESS_IDLE is not set to 0 +#endif /* INCLUDE_vTaskSuspend */ +#endif /* configUSE_TICKLESS_IDLE */ + +#if( ( configSUPPORT_STATIC_ALLOCATION == 0 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 0 ) ) +#error configSUPPORT_STATIC_ALLOCATION and configSUPPORT_DYNAMIC_ALLOCATION cannot both be 0, but can both be 1. +#endif + +#if( ( configUSE_RECURSIVE_MUTEXES == 1 ) && ( configUSE_MUTEXES != 1 ) ) +#error configUSE_MUTEXES must be set to 1 to use recursive mutexes +#endif + +#if( portTICK_TYPE_IS_ATOMIC == 0 ) +/* Either variables of tick type cannot be read atomically, or +portTICK_TYPE_IS_ATOMIC was not set - map the critical sections used when +the tick count is returned to the standard critical section macros. */ +#define portTICK_TYPE_ENTER_CRITICAL() portENTER_CRITICAL() +#define portTICK_TYPE_EXIT_CRITICAL() portEXIT_CRITICAL() +#define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() +#define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( ( x ) ) +#else +/* The tick type can be read atomically, so critical sections used when the +tick count is returned can be defined away. */ +#define portTICK_TYPE_ENTER_CRITICAL() +#define portTICK_TYPE_EXIT_CRITICAL() +#define portTICK_TYPE_SET_INTERRUPT_MASK_FROM_ISR() 0 +#define portTICK_TYPE_CLEAR_INTERRUPT_MASK_FROM_ISR( x ) ( void ) x +#endif + +/* Definitions to allow backward compatibility with FreeRTOS versions prior to +V8 if desired. */ +#ifndef configENABLE_BACKWARD_COMPATIBILITY +#define configENABLE_BACKWARD_COMPATIBILITY 1 +#endif + +#if configENABLE_BACKWARD_COMPATIBILITY == 1 +#define eTaskStateGet eTaskGetState +#define portTickType TickType_t +#define xTaskHandle TaskHandle_t +#define xQueueHandle QueueHandle_t +#define xSemaphoreHandle SemaphoreHandle_t +#define xQueueSetHandle QueueSetHandle_t +#define xQueueSetMemberHandle QueueSetMemberHandle_t +#define xTimeOutType TimeOut_t +#define xMemoryRegion MemoryRegion_t +#define xTaskParameters TaskParameters_t +#define xTaskStatusType TaskStatus_t +#define xTimerHandle TimerHandle_t +#define xCoRoutineHandle CoRoutineHandle_t +#define pdTASK_HOOK_CODE TaskHookFunction_t +#define portTICK_RATE_MS portTICK_PERIOD_MS +#define pcTaskGetTaskName pcTaskGetName +#define pcTimerGetTimerName pcTimerGetName +#define pcQueueGetQueueName pcQueueGetName +#define vTaskGetTaskInfo vTaskGetInfo + +/* Backward compatibility within the scheduler code only - these definitions +are not really required but are included for completeness. */ +#define tmrTIMER_CALLBACK TimerCallbackFunction_t +#define pdTASK_CODE TaskFunction_t +#define xListItem ListItem_t +#define xList List_t +#endif /* configENABLE_BACKWARD_COMPATIBILITY */ + +#if( configUSE_ALTERNATIVE_API != 0 ) +#error The alternative API was deprecated some time ago, and was removed in FreeRTOS V9.0 0 +#endif + +/* Set configUSE_TASK_FPU_SUPPORT to 0 to omit floating point support even +if floating point hardware is otherwise supported by the FreeRTOS port in use. +This constant is not supported by all FreeRTOS ports that include floating +point support. */ +#ifndef configUSE_TASK_FPU_SUPPORT +#define configUSE_TASK_FPU_SUPPORT 1 +#endif + +/* + * In line with software engineering best practice, FreeRTOS implements a strict + * data hiding policy, so the real structures used by FreeRTOS to maintain the + * state of tasks, queues, semaphores, etc. are not accessible to the application + * code. However, if the application writer wants to statically allocate such + * an object then the size of the object needs to be know. Dummy structures + * that are guaranteed to have the same size and alignment requirements of the + * real objects are used for this purpose. The dummy list and list item + * structures below are used for inclusion in such a dummy structure. + */ +struct xSTATIC_LIST_ITEM { + TickType_t xDummy1; + void *pvDummy2[ 4 ]; +}; +typedef struct xSTATIC_LIST_ITEM StaticListItem_t; + +/* See the comments above the struct xSTATIC_LIST_ITEM definition. */ +struct xSTATIC_MINI_LIST_ITEM { + TickType_t xDummy1; + void *pvDummy2[ 2 ]; +}; +typedef struct xSTATIC_MINI_LIST_ITEM StaticMiniListItem_t; + +/* See the comments above the struct xSTATIC_LIST_ITEM definition. */ +typedef struct xSTATIC_LIST { + UBaseType_t uxDummy1; + void *pvDummy2; + StaticMiniListItem_t xDummy3; +} StaticList_t; + +/* + * In line with software engineering best practice, especially when supplying a + * library that is likely to change in future versions, FreeRTOS implements a + * strict data hiding policy. This means the Task structure used internally by + * FreeRTOS is not accessible to application code. However, if the application + * writer wants to statically allocate the memory required to create a task then + * the size of the task object needs to be know. The StaticTask_t structure + * below is provided for this purpose. Its sizes and alignment requirements are + * guaranteed to match those of the genuine structure, no matter which + * architecture is being used, and no matter how the values in FreeRTOSConfig.h + * are set. Its contents are somewhat obfuscated in the hope users will + * recognise that it would be unwise to make direct use of the structure members. + */ +typedef struct xSTATIC_TCB { + void *pxDummy1; + UBaseType_t uxDummy; +#if ( portUSING_MPU_WRAPPERS == 1 ) + xMPU_SETTINGS xDummy2; +#endif + StaticListItem_t xDummy3[ 2 ]; + UBaseType_t uxDummy5; + void *pxDummy6; + uint8_t ucDummy7[ configMAX_TASK_NAME_LEN ]; +#if ( portSTACK_GROWTH > 0 ) + void *pxDummy8; +#endif +#if ( portCRITICAL_NESTING_IN_TCB == 1 ) + UBaseType_t uxDummy9; +#endif +#if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy10[ 2 ]; +#endif +#if ( configUSE_MUTEXES == 1 ) + UBaseType_t uxDummy12[ 2 ]; +#endif +#if ( configUSE_APPLICATION_TASK_TAG == 1 ) + void *pxDummy14; +#endif +#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) + void *pvDummy15[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ]; +#endif +#if ( configGENERATE_RUN_TIME_STATS == 1 ) + uint32_t ulDummy16; +#endif +#if ( configUSE_NEWLIB_REENTRANT == 1 ) + struct _reent xDummy17; +#endif +#if ( configUSE_TASK_NOTIFICATIONS == 1 ) + uint32_t ulDummy18; + uint8_t ucDummy19; +#endif +#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t uxDummy20; +#endif + +} StaticTask_t; + +/* + * In line with software engineering best practice, especially when supplying a + * library that is likely to change in future versions, FreeRTOS implements a + * strict data hiding policy. This means the Queue structure used internally by + * FreeRTOS is not accessible to application code. However, if the application + * writer wants to statically allocate the memory required to create a queue + * then the size of the queue object needs to be know. The StaticQueue_t + * structure below is provided for this purpose. Its sizes and alignment + * requirements are guaranteed to match those of the genuine structure, no + * matter which architecture is being used, and no matter how the values in + * FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in the hope + * users will recognise that it would be unwise to make direct use of the + * structure members. + */ +typedef struct xSTATIC_QUEUE { + void *pvDummy1[ 3 ]; + + union { + void *pvDummy2; + UBaseType_t uxDummy2; + } u; + + StaticList_t xDummy3[ 2 ]; + UBaseType_t uxDummy4[ 3 ]; + uint8_t ucDummy5[ 2 ]; + +#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucDummy6; +#endif + +#if ( configUSE_QUEUE_SETS == 1 ) + void *pvDummy7; +#endif + +#if ( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy8; + uint8_t ucDummy9; +#endif + +} StaticQueue_t; +typedef StaticQueue_t StaticSemaphore_t; + +/* + * In line with software engineering best practice, especially when supplying a + * library that is likely to change in future versions, FreeRTOS implements a + * strict data hiding policy. This means the event group structure used + * internally by FreeRTOS is not accessible to application code. However, if + * the application writer wants to statically allocate the memory required to + * create an event group then the size of the event group object needs to be + * know. The StaticEventGroup_t structure below is provided for this purpose. + * Its sizes and alignment requirements are guaranteed to match those of the + * genuine structure, no matter which architecture is being used, and no matter + * how the values in FreeRTOSConfig.h are set. Its contents are somewhat + * obfuscated in the hope users will recognise that it would be unwise to make + * direct use of the structure members. + */ +typedef struct xSTATIC_EVENT_GROUP { + TickType_t xDummy1; + StaticList_t xDummy2; + +#if( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy3; +#endif + +#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucDummy4; +#endif + +} StaticEventGroup_t; + +/* + * In line with software engineering best practice, especially when supplying a + * library that is likely to change in future versions, FreeRTOS implements a + * strict data hiding policy. This means the software timer structure used + * internally by FreeRTOS is not accessible to application code. However, if + * the application writer wants to statically allocate the memory required to + * create a software timer then the size of the queue object needs to be know. + * The StaticTimer_t structure below is provided for this purpose. Its sizes + * and alignment requirements are guaranteed to match those of the genuine + * structure, no matter which architecture is being used, and no matter how the + * values in FreeRTOSConfig.h are set. Its contents are somewhat obfuscated in + * the hope users will recognise that it would be unwise to make direct use of + * the structure members. + */ +typedef struct xSTATIC_TIMER { + void *pvDummy1; + StaticListItem_t xDummy2; + TickType_t xDummy3; + UBaseType_t uxDummy4; + void *pvDummy5[ 2 ]; +#if( configUSE_TRACE_FACILITY == 1 ) + UBaseType_t uxDummy6; +#endif + +#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) + uint8_t ucDummy7; +#endif + +} StaticTimer_t; + +#ifdef __cplusplus +} +#endif + +#endif /* INC_FREERTOS_H */ + diff --git a/include_lib/system/os/FreeRTOS/FreeRTOSConfig.h b/include_lib/system/os/FreeRTOS/FreeRTOSConfig.h new file mode 100644 index 0000000..80f3fe1 --- /dev/null +++ b/include_lib/system/os/FreeRTOS/FreeRTOSConfig.h @@ -0,0 +1,195 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. See + * http://www.freertos.org/a00110.html + *----------------------------------------------------------*/ +#ifdef __GCC_PI32V2__ +#include "pi32v2/portmacro.h" +#endif + +#ifdef __GCC_PI32_LTO__ +#include "pi32_lto/portmacro.h" +#endif + +#ifdef __GCC_Q32S__ +#include "q32s/portmacro.h" +#endif + +#define configUSE_PREEMPTION 1 +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#define configUSE_IDLE_HOOK 1 +#define configUSE_TICK_HOOK 0 +#define configUSE_DAEMON_TASK_STARTUP_HOOK 1 +#define configTICK_RATE_HZ ( 100 ) /* In this non-real time simulated environment the tick frequency has to be at least a multiple of the Win32 tick frequency, and therefore very slow. */ +#define configMINIMAL_STACK_SIZE ( ( unsigned int) 256) /* In this simulated case, the stack only has to hold one small structure as the real stack is part of the win32 thread. */ +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 30 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 12 ) +#define configUSE_TRACE_FACILITY 1 +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 1 +#define configUSE_MUTEXES 1 +#define configCHECK_FOR_STACK_OVERFLOW 0 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configQUEUE_REGISTRY_SIZE 0 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_APPLICATION_TASK_TAG 1 +#define configUSE_COUNTING_SEMAPHORES 1 +#define configUSE_ALTERNATIVE_API 0 +#define configUSE_QUEUE_SETS 0 +#define configUSE_TASK_NOTIFICATIONS 0 +#define configSUPPORT_STATIC_ALLOCATION 1 + + + +/* Software timer related configuration options. */ +#define configUSE_TIMERS 0 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +#define configTIMER_QUEUE_LENGTH 20 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +#define configMAX_PRIORITIES ( 8 ) + +/* Run time stats gathering configuration options. */ +unsigned long ulGetRunTimeCounterValue(void); /* Prototype of function that returns run time counter. */ +void vConfigureTimerForRunTimeStats(void); /* Prototype of function that initialises the run time counter. */ +void vMainConfigureTimerForRunTimeStats(void); +unsigned long ulMainGetRunTimeCounterValue(void); +#define configGENERATE_RUN_TIME_STATS 0 +// #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats() +#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vMainConfigureTimerForRunTimeStats(); +#define portGET_RUN_TIME_COUNTER_VALUE() ulGetRunTimeCounterValue() + +/* Co-routine related configuration options. */ +#define configUSE_CO_ROUTINES 1 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* This demo makes use of one or more example stats formatting functions. These +format the raw data provided by the uxTaskGetSystemState() function in to human +readable ASCII form. See the notes in the implementation of vTaskList() within +FreeRTOS/Source/tasks.c for limitations. */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 1 + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. In most cases the linker will remove unused +functions anyway. */ +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_xTaskGetHandle 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 +#define INCLUDE_xTimerPendFunctionCall 0 +#define INCLUDE_xTaskAbortDelay 1 + +/* It is a good idea to define configASSERT() while developing. configASSERT() +uses the same semantics as the standard C assert() macro. */ +#include "printf.h" +static inline void vAssertCalled(const char *str, unsigned int ulLine) +{ + /* + if(OS_CPU_ID == 0) + { + C1_CON |=BIT(1) ; + }else + { + C0_CON |=BIT(1) ; + }*/ + local_irq_disable(); + printf("%s %d\n", str, ulLine) ; + while (1); + +} +#define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled(__func__, __LINE__) + +/* Include the FreeRTOS+Trace FreeRTOS trace macro definitions. */ +#define TRACE_ENTER_CRITICAL_SECTION() portENTER_CRITICAL() +#define TRACE_EXIT_CRITICAL_SECTION() portEXIT_CRITICAL() +//#include "trcKernelPort.h" + +#endif /* FREERTOS_CONFIG_H */ diff --git a/include_lib/system/os/FreeRTOS/deprecated_definitions.h b/include_lib/system/os/FreeRTOS/deprecated_definitions.h new file mode 100644 index 0000000..93e82b7 --- /dev/null +++ b/include_lib/system/os/FreeRTOS/deprecated_definitions.h @@ -0,0 +1,321 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef DEPRECATED_DEFINITIONS_H +#define DEPRECATED_DEFINITIONS_H + + +/* Each FreeRTOS port has a unique portmacro.h header file. Originally a +pre-processor definition was used to ensure the pre-processor found the correct +portmacro.h file for the port being used. That scheme was deprecated in favour +of setting the compiler's include path such that it found the correct +portmacro.h file - removing the need for the constant and allowing the +portmacro.h file to be located anywhere in relation to the port being used. The +definitions below remain in the code for backward compatibility only. New +projects should not use them. */ + +#ifdef OPEN_WATCOM_INDUSTRIAL_PC_PORT +#include "..\..\Source\portable\owatcom\16bitdos\pc\portmacro.h" +typedef void (__interrupt __far *pxISR)(); +#endif + +#ifdef OPEN_WATCOM_FLASH_LITE_186_PORT +#include "..\..\Source\portable\owatcom\16bitdos\flsh186\portmacro.h" +typedef void (__interrupt __far *pxISR)(); +#endif + +#ifdef GCC_MEGA_AVR +#include "../portable/GCC/ATMega323/portmacro.h" +#endif + +#ifdef IAR_MEGA_AVR +#include "../portable/IAR/ATMega323/portmacro.h" +#endif + +#ifdef MPLAB_PIC24_PORT +#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" +#endif + +#ifdef MPLAB_DSPIC_PORT +#include "../../Source/portable/MPLAB/PIC24_dsPIC/portmacro.h" +#endif + +#ifdef MPLAB_PIC18F_PORT +#include "../../Source/portable/MPLAB/PIC18F/portmacro.h" +#endif + +#ifdef MPLAB_PIC32MX_PORT +#include "../../Source/portable/MPLAB/PIC32MX/portmacro.h" +#endif + +#ifdef _FEDPICC +#include "libFreeRTOS/Include/portmacro.h" +#endif + +#ifdef SDCC_CYGNAL +#include "../../Source/portable/SDCC/Cygnal/portmacro.h" +#endif + +#ifdef GCC_ARM7 +#include "../../Source/portable/GCC/ARM7_LPC2000/portmacro.h" +#endif + +#ifdef GCC_ARM7_ECLIPSE +#include "portmacro.h" +#endif + +#ifdef ROWLEY_LPC23xx +#include "../../Source/portable/GCC/ARM7_LPC23xx/portmacro.h" +#endif + +#ifdef IAR_MSP430 +#include "..\..\Source\portable\IAR\MSP430\portmacro.h" +#endif + +#ifdef GCC_MSP430 +#include "../../Source/portable/GCC/MSP430F449/portmacro.h" +#endif + +#ifdef ROWLEY_MSP430 +#include "../../Source/portable/Rowley/MSP430F449/portmacro.h" +#endif + +#ifdef ARM7_LPC21xx_KEIL_RVDS +#include "..\..\Source\portable\RVDS\ARM7_LPC21xx\portmacro.h" +#endif + +#ifdef SAM7_GCC +#include "../../Source/portable/GCC/ARM7_AT91SAM7S/portmacro.h" +#endif + +#ifdef SAM7_IAR +#include "..\..\Source\portable\IAR\AtmelSAM7S64\portmacro.h" +#endif + +#ifdef SAM9XE_IAR +#include "..\..\Source\portable\IAR\AtmelSAM9XE\portmacro.h" +#endif + +#ifdef LPC2000_IAR +#include "..\..\Source\portable\IAR\LPC2000\portmacro.h" +#endif + +#ifdef STR71X_IAR +#include "..\..\Source\portable\IAR\STR71x\portmacro.h" +#endif + +#ifdef STR75X_IAR +#include "..\..\Source\portable\IAR\STR75x\portmacro.h" +#endif + +#ifdef STR75X_GCC +#include "..\..\Source\portable\GCC\STR75x\portmacro.h" +#endif + +#ifdef STR91X_IAR +#include "..\..\Source\portable\IAR\STR91x\portmacro.h" +#endif + +#ifdef GCC_H8S +#include "../../Source/portable/GCC/H8S2329/portmacro.h" +#endif + +#ifdef GCC_AT91FR40008 +#include "../../Source/portable/GCC/ARM7_AT91FR40008/portmacro.h" +#endif + +#ifdef RVDS_ARMCM3_LM3S102 +#include "../../Source/portable/RVDS/ARM_CM3/portmacro.h" +#endif + +#ifdef GCC_ARMCM3_LM3S102 +#include "../../Source/portable/GCC/ARM_CM3/portmacro.h" +#endif + +#ifdef GCC_ARMCM3 +#include "../../Source/portable/GCC/ARM_CM3/portmacro.h" +#endif + +#ifdef IAR_ARM_CM3 +#include "../../Source/portable/IAR/ARM_CM3/portmacro.h" +#endif + +#ifdef IAR_ARMCM3_LM +#include "../../Source/portable/IAR/ARM_CM3/portmacro.h" +#endif + +#ifdef HCS12_CODE_WARRIOR +#include "../../Source/portable/CodeWarrior/HCS12/portmacro.h" +#endif + +#ifdef MICROBLAZE_GCC +#include "../../Source/portable/GCC/MicroBlaze/portmacro.h" +#endif + +#ifdef TERN_EE +#include "..\..\Source\portable\Paradigm\Tern_EE\small\portmacro.h" +#endif + +#ifdef GCC_HCS12 +#include "../../Source/portable/GCC/HCS12/portmacro.h" +#endif + +#ifdef GCC_MCF5235 +#include "../../Source/portable/GCC/MCF5235/portmacro.h" +#endif + +#ifdef COLDFIRE_V2_GCC +#include "../../../Source/portable/GCC/ColdFire_V2/portmacro.h" +#endif + +#ifdef COLDFIRE_V2_CODEWARRIOR +#include "../../Source/portable/CodeWarrior/ColdFire_V2/portmacro.h" +#endif + +#ifdef GCC_PPC405 +#include "../../Source/portable/GCC/PPC405_Xilinx/portmacro.h" +#endif + +#ifdef GCC_PPC440 +#include "../../Source/portable/GCC/PPC440_Xilinx/portmacro.h" +#endif + +#ifdef _16FX_SOFTUNE +#include "..\..\Source\portable\Softune\MB96340\portmacro.h" +#endif + +#ifdef BCC_INDUSTRIAL_PC_PORT +/* A short file name has to be used in place of the normal +FreeRTOSConfig.h when using the Borland compiler. */ +#include "frconfig.h" +#include "..\portable\BCC\16BitDOS\PC\prtmacro.h" +typedef void (__interrupt __far *pxISR)(); +#endif + +#ifdef BCC_FLASH_LITE_186_PORT +/* A short file name has to be used in place of the normal +FreeRTOSConfig.h when using the Borland compiler. */ +#include "frconfig.h" +#include "..\portable\BCC\16BitDOS\flsh186\prtmacro.h" +typedef void (__interrupt __far *pxISR)(); +#endif + +#ifdef __GNUC__ +#ifdef __AVR32_AVR32A__ +#include "portmacro.h" +#endif +#endif + +#ifdef __ICCAVR32__ +#ifdef __CORE__ +#if __CORE__ == __AVR32A__ +#include "portmacro.h" +#endif +#endif +#endif + +#ifdef __91467D +#include "portmacro.h" +#endif + +#ifdef __96340 +#include "portmacro.h" +#endif + + +#ifdef __IAR_V850ES_Fx3__ +#include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx3__ +#include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx3_L__ +#include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Jx2__ +#include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_V850ES_Hx2__ +#include "../../Source/portable/IAR/V850ES/portmacro.h" +#endif + +#ifdef __IAR_78K0R_Kx3__ +#include "../../Source/portable/IAR/78K0R/portmacro.h" +#endif + +#ifdef __IAR_78K0R_Kx3L__ +#include "../../Source/portable/IAR/78K0R/portmacro.h" +#endif + +#endif /* DEPRECATED_DEFINITIONS_H */ + diff --git a/include_lib/system/os/FreeRTOS/list.h b/include_lib/system/os/FreeRTOS/list.h new file mode 100644 index 0000000..43e223a --- /dev/null +++ b/include_lib/system/os/FreeRTOS/list.h @@ -0,0 +1,450 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/* + * This is the list implementation used by the scheduler. While it is tailored + * heavily for the schedulers needs, it is also available for use by + * application code. + * + * list_ts can only store pointers to list_item_ts. Each ListItem_t contains a + * numeric value (xItemValue). Most of the time the lists are sorted in + * descending item value order. + * + * Lists are created already containing one list item. The value of this + * item is the maximum possible that can be stored, it is therefore always at + * the end of the list and acts as a marker. The list member pxHead always + * points to this marker - even though it is at the tail of the list. This + * is because the tail contains a wrap back pointer to the true head of + * the list. + * + * In addition to it's value, each list item contains a pointer to the next + * item in the list (pxNext), a pointer to the list it is in (pxContainer) + * and a pointer to back to the object that contains it. These later two + * pointers are included for efficiency of list manipulation. There is + * effectively a two way link between the object containing the list item and + * the list item itself. + * + * + * \page ListIntroduction List Implementation + * \ingroup FreeRTOSIntro + */ + +#ifndef INC_FREERTOS_H +#error FreeRTOS.h must be included before list.h +#endif + +#ifndef FREERTOS_LIST_H +#define FREERTOS_LIST_H + +/* + * The list structure members are modified from within interrupts, and therefore + * by rights should be declared volatile. However, they are only modified in a + * functionally atomic way (within critical sections of with the scheduler + * suspended) and are either passed by reference into a function or indexed via + * a volatile variable. Therefore, in all use cases tested so far, the volatile + * qualifier can be omitted in order to provide a moderate performance + * improvement without adversely affecting functional behaviour. The assembly + * instructions generated by the IAR, ARM and GCC compilers when the respective + * compiler's options were set for maximum optimisation has been inspected and + * deemed to be as intended. That said, as compiler technology advances, and + * especially if aggressive cross module optimisation is used (a use case that + * has not been exercised to any great extend) then it is feasible that the + * volatile qualifier will be needed for correct optimisation. It is expected + * that a compiler removing essential code because, without the volatile + * qualifier on the list structure members and with aggressive cross module + * optimisation, the compiler deemed the code unnecessary will result in + * complete and obvious failure of the scheduler. If this is ever experienced + * then the volatile qualifier can be inserted in the relevant places within the + * list structures by simply defining configLIST_VOLATILE to volatile in + * FreeRTOSConfig.h (as per the example at the bottom of this comment block). + * If configLIST_VOLATILE is not defined then the preprocessor directives below + * will simply #define configLIST_VOLATILE away completely. + * + * To use volatile list structure members then add the following line to + * FreeRTOSConfig.h (without the quotes): + * "#define configLIST_VOLATILE volatile" + */ +#ifndef configLIST_VOLATILE +#define configLIST_VOLATILE +#endif /* configSUPPORT_CROSS_MODULE_OPTIMISATION */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Macros that can be used to place known values within the list structures, +then check that the known values do not get corrupted during the execution of +the application. These may catch the list data structures being overwritten in +memory. They will not catch data errors caused by incorrect configuration or +use of FreeRTOS.*/ +#if( configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES == 0 ) +/* Define the macros to do nothing. */ +#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE +#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE +#define listFIRST_LIST_INTEGRITY_CHECK_VALUE +#define listSECOND_LIST_INTEGRITY_CHECK_VALUE +#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) +#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) +#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) +#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) +#define listTEST_LIST_ITEM_INTEGRITY( pxItem ) +#define listTEST_LIST_INTEGRITY( pxList ) +#else +/* Define macros that add new members into the list structures. */ +#define listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue1; +#define listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE TickType_t xListItemIntegrityValue2; +#define listFIRST_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue1; +#define listSECOND_LIST_INTEGRITY_CHECK_VALUE TickType_t xListIntegrityValue2; + +/* Define macros that set the new structure members to known values. */ +#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue1 = pdINTEGRITY_CHECK_VALUE +#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem ) ( pxItem )->xListItemIntegrityValue2 = pdINTEGRITY_CHECK_VALUE +#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList ) ( pxList )->xListIntegrityValue1 = pdINTEGRITY_CHECK_VALUE +#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList ) ( pxList )->xListIntegrityValue2 = pdINTEGRITY_CHECK_VALUE + +/* Define macros that will assert if one of the structure members does not +contain its expected value. */ +#define listTEST_LIST_ITEM_INTEGRITY( pxItem ) configASSERT( ( ( pxItem )->xListItemIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxItem )->xListItemIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) +#define listTEST_LIST_INTEGRITY( pxList ) configASSERT( ( ( pxList )->xListIntegrityValue1 == pdINTEGRITY_CHECK_VALUE ) && ( ( pxList )->xListIntegrityValue2 == pdINTEGRITY_CHECK_VALUE ) ) +#endif /* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES */ + + +/* + * Definition of the only type of object that a list can contain. + */ +struct xLIST_ITEM { + listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE TickType_t xItemValue; /*< The value being listed. In most cases this is used to sort the list in descending order. */ + struct xLIST_ITEM *configLIST_VOLATILE pxNext; /*< Pointer to the next ListItem_t in the list. */ + struct xLIST_ITEM *configLIST_VOLATILE pxPrevious; /*< Pointer to the previous ListItem_t in the list. */ + void *pvOwner; /*< Pointer to the object (normally a TCB) that contains the list item. There is therefore a two way link between the object containing the list item and the list item itself. */ + void *configLIST_VOLATILE pvContainer; /*< Pointer to the list in which this list item is placed (if any). */ + listSECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ +}; +typedef struct xLIST_ITEM ListItem_t; /* For some reason lint wants this as two separate definitions. */ + +struct xMINI_LIST_ITEM { + listFIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE TickType_t xItemValue; + struct xLIST_ITEM *configLIST_VOLATILE pxNext; + struct xLIST_ITEM *configLIST_VOLATILE pxPrevious; +}; +typedef struct xMINI_LIST_ITEM MiniListItem_t; + +/* + * Definition of the type of queue used by the scheduler. + */ +typedef struct xLIST { + listFIRST_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ + configLIST_VOLATILE UBaseType_t uxNumberOfItems; + ListItem_t *configLIST_VOLATILE pxIndex; /*< Used to walk through the list. Points to the last item returned by a call to listGET_OWNER_OF_NEXT_ENTRY (). */ + MiniListItem_t xListEnd; /*< List item that contains the maximum possible item value meaning it is always at the end of the list and is therefore used as a marker. */ + listSECOND_LIST_INTEGRITY_CHECK_VALUE /*< Set to a known value if configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */ +} List_t; + +/* + * Access macro to set the owner of a list item. The owner of a list item + * is the object (usually a TCB) that contains the list item. + * + * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER + * \ingroup LinkedList + */ +#define listSET_LIST_ITEM_OWNER( pxListItem, pxOwner ) ( ( pxListItem )->pvOwner = ( void * ) ( pxOwner ) ) + +/* + * Access macro to get the owner of a list item. The owner of a list item + * is the object (usually a TCB) that contains the list item. + * + * \page listSET_LIST_ITEM_OWNER listSET_LIST_ITEM_OWNER + * \ingroup LinkedList + */ +#define listGET_LIST_ITEM_OWNER( pxListItem ) ( ( pxListItem )->pvOwner ) + +/* + * Access macro to set the value of the list item. In most cases the value is + * used to sort the list in descending order. + * + * \page listSET_LIST_ITEM_VALUE listSET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listSET_LIST_ITEM_VALUE( pxListItem, xValue ) ( ( pxListItem )->xItemValue = ( xValue ) ) + +/* + * Access macro to retrieve the value of the list item. The value can + * represent anything - for example the priority of a task, or the time at + * which a task should be unblocked. + * + * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listGET_LIST_ITEM_VALUE( pxListItem ) ( ( pxListItem )->xItemValue ) + +/* + * Access macro to retrieve the value of the list item at the head of a given + * list. + * + * \page listGET_LIST_ITEM_VALUE listGET_LIST_ITEM_VALUE + * \ingroup LinkedList + */ +#define listGET_ITEM_VALUE_OF_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext->xItemValue ) + +/* + * Return the list item at the head of the list. + * + * \page listGET_HEAD_ENTRY listGET_HEAD_ENTRY + * \ingroup LinkedList + */ +#define listGET_HEAD_ENTRY( pxList ) ( ( ( pxList )->xListEnd ).pxNext ) + +/* + * Return the list item at the head of the list. + * + * \page listGET_NEXT listGET_NEXT + * \ingroup LinkedList + */ +#define listGET_NEXT( pxListItem ) ( ( pxListItem )->pxNext ) + +/* + * Return the list item that marks the end of the list + * + * \page listGET_END_MARKER listGET_END_MARKER + * \ingroup LinkedList + */ +#define listGET_END_MARKER( pxList ) ( ( ListItem_t const * ) ( &( ( pxList )->xListEnd ) ) ) + +/* + * Access macro to determine if a list contains any items. The macro will + * only have the value true if the list is empty. + * + * \page listLIST_IS_EMPTY listLIST_IS_EMPTY + * \ingroup LinkedList + */ +#define listLIST_IS_EMPTY( pxList ) ( ( BaseType_t ) ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ) + +/* + * Access macro to return the number of items in the list. + */ +#define listCURRENT_LIST_LENGTH( pxList ) ( ( pxList )->uxNumberOfItems ) + +/* + * Access function to obtain the owner of the next entry in a list. + * + * The list member pxIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list + * and returns that entry's pxOwner parameter. Using multiple calls to this + * function it is therefore possible to move through every item contained in + * a list. + * + * The pxOwner parameter of a list item is a pointer to the object that owns + * the list item. In the scheduler this is normally a task control block. + * The pxOwner parameter effectively creates a two way link between the list + * item and its owner. + * + * @param pxTCB pxTCB is set to the address of the owner of the next list item. + * @param pxList The list from which the next item owner is to be returned. + * + * \page listGET_OWNER_OF_NEXT_ENTRY listGET_OWNER_OF_NEXT_ENTRY + * \ingroup LinkedList + */ +#define listGET_OWNER_OF_NEXT_ENTRY( pxTCB, pxList ) \ +{ \ +List_t * const pxConstList = ( pxList ); \ + /* Increment the index to the next item and return the item, ensuring */ \ + /* we don't return the marker used at the end of the list. */ \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + if( ( void * ) ( pxConstList )->pxIndex == ( void * ) &( ( pxConstList )->xListEnd ) ) \ + { \ + ( pxConstList )->pxIndex = ( pxConstList )->pxIndex->pxNext; \ + } \ + ( pxTCB ) = ( pxConstList )->pxIndex->pvOwner; \ +} + + +/* + * Access function to obtain the owner of the first entry in a list. Lists + * are normally sorted in ascending item value order. + * + * This function returns the pxOwner member of the first item in the list. + * The pxOwner parameter of a list item is a pointer to the object that owns + * the list item. In the scheduler this is normally a task control block. + * The pxOwner parameter effectively creates a two way link between the list + * item and its owner. + * + * @param pxList The list from which the owner of the head item is to be + * returned. + * + * \page listGET_OWNER_OF_HEAD_ENTRY listGET_OWNER_OF_HEAD_ENTRY + * \ingroup LinkedList + */ +#define listGET_OWNER_OF_HEAD_ENTRY( pxList ) ( (&( ( pxList )->xListEnd ))->pxNext->pvOwner ) + +/* + * Check to see if a list item is within a list. The list item maintains a + * "container" pointer that points to the list it is in. All this macro does + * is check to see if the container and the list match. + * + * @param pxList The list we want to know if the list item is within. + * @param pxListItem The list item we want to know if is in the list. + * @return pdTRUE if the list item is in the list, otherwise pdFALSE. + */ +#define listIS_CONTAINED_WITHIN( pxList, pxListItem ) ( ( BaseType_t ) ( ( pxListItem )->pvContainer == ( void * ) ( pxList ) ) ) + +/* + * Return the list a list item is contained within (referenced from). + * + * @param pxListItem The list item being queried. + * @return A pointer to the List_t object that references the pxListItem + */ +#define listLIST_ITEM_CONTAINER( pxListItem ) ( ( pxListItem )->pvContainer ) + +/* + * This provides a crude means of knowing if a list has been initialised, as + * pxList->xListEnd.xItemValue is set to portMAX_DELAY by the vListInitialise() + * function. + */ +#define listLIST_IS_INITIALISED( pxList ) ( ( pxList )->xListEnd.xItemValue == portMAX_DELAY ) + +/* + * Must be called before a list is used! This initialises all the members + * of the list structure and inserts the xListEnd item into the list as a + * marker to the back of the list. + * + * @param pxList Pointer to the list being initialised. + * + * \page vListInitialise vListInitialise + * \ingroup LinkedList + */ +void vListInitialise(List_t *const pxList) PRIVILEGED_FUNCTION; + +/* + * Must be called before a list item is used. This sets the list container to + * null so the item does not think that it is already contained in a list. + * + * @param pxItem Pointer to the list item being initialised. + * + * \page vListInitialiseItem vListInitialiseItem + * \ingroup LinkedList + */ +void vListInitialiseItem(ListItem_t *const pxItem) PRIVILEGED_FUNCTION; + +/* + * Insert a list item into a list. The item will be inserted into the list in + * a position determined by its item value (descending item value order). + * + * @param pxList The list into which the item is to be inserted. + * + * @param pxNewListItem The item that is to be placed in the list. + * + * \page vListInsert vListInsert + * \ingroup LinkedList + */ +void vListInsert(List_t *const pxList, ListItem_t *const pxNewListItem) PRIVILEGED_FUNCTION; + +/* + * Insert a list item into a list. The item will be inserted in a position + * such that it will be the last item within the list returned by multiple + * calls to listGET_OWNER_OF_NEXT_ENTRY. + * + * The list member pxIndex is used to walk through a list. Calling + * listGET_OWNER_OF_NEXT_ENTRY increments pxIndex to the next item in the list. + * Placing an item in a list using vListInsertEnd effectively places the item + * in the list position pointed to by pxIndex. This means that every other + * item within the list will be returned by listGET_OWNER_OF_NEXT_ENTRY before + * the pxIndex parameter again points to the item being inserted. + * + * @param pxList The list into which the item is to be inserted. + * + * @param pxNewListItem The list item to be inserted into the list. + * + * \page vListInsertEnd vListInsertEnd + * \ingroup LinkedList + */ +void vListInsertEnd(List_t *const pxList, ListItem_t *const pxNewListItem) PRIVILEGED_FUNCTION; + +/* + * Remove an item from a list. The list item has a pointer to the list that + * it is in, so only the list item need be passed into the function. + * + * @param uxListRemove The item to be removed. The item will remove itself from + * the list pointed to by it's pxContainer parameter. + * + * @return The number of items that remain in the list after the list item has + * been removed. + * + * \page uxListRemove uxListRemove + * \ingroup LinkedList + */ +UBaseType_t uxListRemove(ListItem_t *const pxItemToRemove) PRIVILEGED_FUNCTION; + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include_lib/system/os/FreeRTOS/mpu_wrappers.h b/include_lib/system/os/FreeRTOS/mpu_wrappers.h new file mode 100644 index 0000000..2ba287b --- /dev/null +++ b/include_lib/system/os/FreeRTOS/mpu_wrappers.h @@ -0,0 +1,201 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef MPU_WRAPPERS_H +#define MPU_WRAPPERS_H + +/* This file redefines API functions to be called through a wrapper macro, but +only for ports that are using the MPU. */ +#ifdef portUSING_MPU_WRAPPERS + +/* MPU_WRAPPERS_INCLUDED_FROM_API_FILE will be defined when this file is +included from queue.c or task.c to prevent it from having an effect within +those files. */ +#ifndef MPU_WRAPPERS_INCLUDED_FROM_API_FILE + +/* + * Map standard (non MPU) API functions to equivalents that start + * "MPU_". This will cause the application code to call the MPU_ + * version, which wraps the non-MPU version with privilege promoting + * then demoting code, so the kernel code always runs will full + * privileges. + */ + +/* Map standard tasks.h API functions to the MPU equivalents. */ +#define xTaskCreate MPU_xTaskCreate +#define xTaskCreateStatic MPU_xTaskCreateStatic +#define xTaskCreateRestricted MPU_xTaskCreateRestricted +#define vTaskAllocateMPURegions MPU_vTaskAllocateMPURegions +#define vTaskDelete MPU_vTaskDelete +#define vTaskDelay MPU_vTaskDelay +#define vTaskDelayUntil MPU_vTaskDelayUntil +#define xTaskAbortDelay MPU_xTaskAbortDelay +#define uxTaskPriorityGet MPU_uxTaskPriorityGet +#define eTaskGetState MPU_eTaskGetState +#define vTaskGetInfo MPU_vTaskGetInfo +#define vTaskPrioritySet MPU_vTaskPrioritySet +#define vTaskSuspend MPU_vTaskSuspend +#define vTaskResume MPU_vTaskResume +#define vTaskSuspendAll MPU_vTaskSuspendAll +#define xTaskResumeAll MPU_xTaskResumeAll +#define xTaskGetTickCount MPU_xTaskGetTickCount +#define uxTaskGetNumberOfTasks MPU_uxTaskGetNumberOfTasks +#define pcTaskGetName MPU_pcTaskGetName +#define xTaskGetHandle MPU_xTaskGetHandle +#define uxTaskGetStackHighWaterMark MPU_uxTaskGetStackHighWaterMark +#define vTaskSetApplicationTaskTag MPU_vTaskSetApplicationTaskTag +#define xTaskGetApplicationTaskTag MPU_xTaskGetApplicationTaskTag +#define vTaskSetThreadLocalStoragePointer MPU_vTaskSetThreadLocalStoragePointer +#define pvTaskGetThreadLocalStoragePointer MPU_pvTaskGetThreadLocalStoragePointer +#define xTaskCallApplicationTaskHook MPU_xTaskCallApplicationTaskHook +#define xTaskGetIdleTaskHandle MPU_xTaskGetIdleTaskHandle +#define uxTaskGetSystemState MPU_uxTaskGetSystemState +#define vTaskList MPU_vTaskList +#define vTaskGetRunTimeStats MPU_vTaskGetRunTimeStats +#define xTaskGenericNotify MPU_xTaskGenericNotify +#define xTaskNotifyWait MPU_xTaskNotifyWait +#define ulTaskNotifyTake MPU_ulTaskNotifyTake +#define xTaskNotifyStateClear MPU_xTaskNotifyStateClear + +#define xTaskGetCurrentTaskHandle MPU_xTaskGetCurrentTaskHandle +#define vTaskSetTimeOutState MPU_vTaskSetTimeOutState +#define xTaskCheckForTimeOut MPU_xTaskCheckForTimeOut +#define xTaskGetSchedulerState MPU_xTaskGetSchedulerState + +/* Map standard queue.h API functions to the MPU equivalents. */ +#define xQueueGenericSend MPU_xQueueGenericSend +#define xQueueGenericReceive MPU_xQueueGenericReceive +#define uxQueueMessagesWaiting MPU_uxQueueMessagesWaiting +#define uxQueueSpacesAvailable MPU_uxQueueSpacesAvailable +#define vQueueDelete MPU_vQueueDelete +#define xQueueCreateMutex MPU_xQueueCreateMutex +#define xQueueCreateMutexStatic MPU_xQueueCreateMutexStatic +#define xQueueCreateCountingSemaphore MPU_xQueueCreateCountingSemaphore +#define xQueueCreateCountingSemaphoreStatic MPU_xQueueCreateCountingSemaphoreStatic +#define xQueueGetMutexHolder MPU_xQueueGetMutexHolder +#define xQueueTakeMutexRecursive MPU_xQueueTakeMutexRecursive +#define xQueueGiveMutexRecursive MPU_xQueueGiveMutexRecursive +#define xQueueGenericCreate MPU_xQueueGenericCreate +#define xQueueGenericCreateStatic MPU_xQueueGenericCreateStatic +#define xQueueCreateSet MPU_xQueueCreateSet +#define xQueueAddToSet MPU_xQueueAddToSet +#define xQueueRemoveFromSet MPU_xQueueRemoveFromSet +#define xQueueSelectFromSet MPU_xQueueSelectFromSet +#define xQueueGenericReset MPU_xQueueGenericReset + +#if( configQUEUE_REGISTRY_SIZE > 0 ) +#define vQueueAddToRegistry MPU_vQueueAddToRegistry +#define vQueueUnregisterQueue MPU_vQueueUnregisterQueue +#define pcQueueGetName MPU_pcQueueGetName +#endif + +/* Map standard timer.h API functions to the MPU equivalents. */ +#define xTimerCreate MPU_xTimerCreate +#define xTimerCreateStatic MPU_xTimerCreateStatic +#define pvTimerGetTimerID MPU_pvTimerGetTimerID +#define vTimerSetTimerID MPU_vTimerSetTimerID +#define xTimerIsTimerActive MPU_xTimerIsTimerActive +#define xTimerGetTimerDaemonTaskHandle MPU_xTimerGetTimerDaemonTaskHandle +#define xTimerPendFunctionCall MPU_xTimerPendFunctionCall +#define pcTimerGetName MPU_pcTimerGetName +#define xTimerGetPeriod MPU_xTimerGetPeriod +#define xTimerGetExpiryTime MPU_xTimerGetExpiryTime +#define xTimerGenericCommand MPU_xTimerGenericCommand + +/* Map standard event_group.h API functions to the MPU equivalents. */ +#define xEventGroupCreate MPU_xEventGroupCreate +#define xEventGroupCreateStatic MPU_xEventGroupCreateStatic +#define xEventGroupWaitBits MPU_xEventGroupWaitBits +#define xEventGroupClearBits MPU_xEventGroupClearBits +#define xEventGroupSetBits MPU_xEventGroupSetBits +#define xEventGroupSync MPU_xEventGroupSync +#define vEventGroupDelete MPU_vEventGroupDelete + +/* Remove the privileged function macro. */ +#define PRIVILEGED_FUNCTION + +#else /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ + +/* Ensure API functions go in the privileged execution section. */ +#define PRIVILEGED_FUNCTION __attribute__((section("privileged_functions"))) +#define PRIVILEGED_DATA __attribute__((section("privileged_data"))) + +#endif /* MPU_WRAPPERS_INCLUDED_FROM_API_FILE */ + +#else /* portUSING_MPU_WRAPPERS */ + +#define PRIVILEGED_FUNCTION +#define PRIVILEGED_DATA +#define portUSING_MPU_WRAPPERS 0 + +#endif /* portUSING_MPU_WRAPPERS */ + + +#endif /* MPU_WRAPPERS_H */ + diff --git a/include_lib/system/os/FreeRTOS/pi32_lto/portmacro.h b/include_lib/system/os/FreeRTOS/pi32_lto/portmacro.h new file mode 100644 index 0000000..fbacdf2 --- /dev/null +++ b/include_lib/system/os/FreeRTOS/pi32_lto/portmacro.h @@ -0,0 +1,263 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef PORTMACRO_H +#define PORTMACRO_H +#include "asm/cpu.h" +#include +/****************************************************************************** + Defines +******************************************************************************/ +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE int +#define portBASE_TYPE long +#define portPOINTER_SIZE_TYPE size_t + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + + +#if( configUSE_16_BIT_TICKS == 1 ) +typedef uint16_t TickType_t; +#define portMAX_DELAY ( TickType_t ) 0xffff +#else +typedef uint32_t TickType_t; +#define portMAX_DELAY ( TickType_t ) 0xffffffffUL + +/* 32/64-bit tick type on a 32/64-bit architecture, so reads of the tick +count do not need to be guarded with a critical section. */ +#define portTICK_TYPE_IS_ATOMIC 1 +#endif + +/* Hardware specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portINLINE __inline + +#if defined( __x86_64__) || defined( _M_X64 ) +#define portBYTE_ALIGNMENT 8 +#else +#define portBYTE_ALIGNMENT 4 +#endif +extern void vPortYield() ; +#define portYIELD() vPortYield() +#define OS_CPU_ID current_cpu_id() +extern int current_cpu_id() ; +#define OS_CPU_NUM CPU_CORE_NUM + +/* Simulated interrupts return pdFALSE if no context switch should be performed, +or a non-zero number if a context switch should be performed. */ +#define portYIELD_FROM_ISR( x ) return x +#define portEND_SWITCHING_ISR( x ) portYIELD_FROM_ISR( ( x ) ) + +void vPortCloseRunningThread(void *pvTaskToDelete, volatile BaseType_t *pxPendYield); +//void vPortDeleteThread( void *pvThreadToDelete ); +#define portCLEAN_UP_TCB( pxTCB ) //vPortDeleteThread( pxTCB ) +#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxPendYield ) //vPortCloseRunningThread( ( pvTaskToDelete ), ( pxPendYield ) ) +#define portDISABLE_INTERRUPTS() CPU_CRITICAL_ENTER() +#define portENABLE_INTERRUPTS() CPU_CRITICAL_EXIT() + + +/* Critical section handling. */ +void vPortEnterCritical(void); +void vPortExitCritical(void); +//extern void * malloc(int ) ; +//extern void free(void *) ; + +//#define pvPortMalloc malloc +//#define vPortFree free + +/* + extern volatile int cpu_lock_cnt[]; + extern volatile int irq_lock_cnt[]; +#define __asm_csync() \ + do { \ + asm volatile("csync;"); \ + asm volatile("csync;"); \ + asm volatile("csync;"); \ + asm volatile("csync;"); \ + asm volatile("csync;"); \ + } while (0) + + static inline void local_irq_disable() + { + __builtin_pi32v2_cli(); + irq_lock_cnt[current_cpu_id()]++; + } + + + static inline void local_irq_enable() + { + if (--irq_lock_cnt[current_cpu_id()] == 0) { + __builtin_pi32v2_sti(); + } + } + + + #define CPU_CRITICAL_ENTER() \ + do { \ + local_irq_disable(); \ + if(cpu_lock_cnt[current_cpu_id()]++ == 0) \ + asm volatile("lockset;"); \ + __asm_csync(); \ + }while(0) + + + #define CPU_CRITICAL_EXIT() \ + do { \ + if (--cpu_lock_cnt[current_cpu_id()] == 0) \ + asm volatile("lockclr;"); \ + local_irq_enable();\ + }while(0) + +*/ + + +#define portENTER_CRITICAL() CPU_CRITICAL_ENTER() // vPortEnterCritical() +#define portEXIT_CRITICAL() CPU_CRITICAL_EXIT() // vPortExitCritical() + + +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + +extern __attribute__((always_inline)) uint32_t ucPortCountLeadingZeros(uint32_t ulBitmap); + +/* Check the configuration. */ +#if( configMAX_PRIORITIES > 32 ) +#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. +#endif + +/* Store/clear the ready priorities in a bit map. */ +#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) +#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) \ + do { \ + ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ); \ + } while (0) + + +/*-----------------------------------------------------------*/ + +// uxTopPriority = __builtin_pi32v2_clz(uxReadyPriorities) +#ifdef __GNUC__ +#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - ucPortCountLeadingZeros( ( uxReadyPriorities ) ) ) +#else +/* BitScanReverse returns the bit position of the most significant '1' +in the word. */ +#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) _BitScanReverse( ( DWORD * ) &( uxTopPriority ), ( uxReadyPriorities ) ) +#endif /* __GNUC__ */ + +#endif /* taskRECORD_READY_PRIORITY */ + +#ifndef __GNUC__ +__pragma(warning(disable: 4211)) /* Nonstandard extension used, as extern is only nonstandard to MSVC. */ +#endif + + +/* Task function macros as described on the FreeRTOS.org WEB site. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) + +#define portINTERRUPT_YIELD ( 0UL ) +#define portINTERRUPT_TICK ( 1UL ) + +/* + * Raise a simulated interrupt represented by the bit mask in ulInterruptMask. + * Each bit can be used to represent an individual interrupt - with the first + * two bits being used for the Yield and Tick interrupts respectively. +*/ +void vPortGenerateSimulatedInterrupt(uint32_t ulInterruptNumber); + +/* + * Install an interrupt handler to be called by the simulated interrupt handler + * thread. The interrupt number must be above any used by the kernel itself + * (at the time of writing the kernel was using interrupt numbers 0, 1, and 2 + * as defined above). The number must also be lower than 32. + * + * Interrupt handler functions must return a non-zero value if executing the + * handler resulted in a task switch being required. + */ +void vPortSetInterruptHandler(uint32_t ulInterruptNumber, uint32_t (*pvHandler)(void)); + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP +extern void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime); +#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif + +#endif + diff --git a/include_lib/system/os/FreeRTOS/pi32v2/portmacro.h b/include_lib/system/os/FreeRTOS/pi32v2/portmacro.h new file mode 100644 index 0000000..48fc79f --- /dev/null +++ b/include_lib/system/os/FreeRTOS/pi32v2/portmacro.h @@ -0,0 +1,262 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef PORTMACRO_H +#define PORTMACRO_H +#include "asm/cpu.h" +#include +/****************************************************************************** + Defines +******************************************************************************/ +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE int +#define portBASE_TYPE long +#define portPOINTER_SIZE_TYPE size_t + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + + +#if( configUSE_16_BIT_TICKS == 1 ) +typedef uint16_t TickType_t; +#define portMAX_DELAY ( TickType_t ) 0xffff +#else +typedef uint32_t TickType_t; +#define portMAX_DELAY ( TickType_t ) 0xffffffffUL + +/* 32/64-bit tick type on a 32/64-bit architecture, so reads of the tick +count do not need to be guarded with a critical section. */ +#define portTICK_TYPE_IS_ATOMIC 1 +#endif + +/* Hardware specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portINLINE __inline + +#if defined( __x86_64__) || defined( _M_X64 ) +#define portBYTE_ALIGNMENT 8 +#else +#define portBYTE_ALIGNMENT 4 +#endif +extern void vPortYield() ; +#define portYIELD() vPortYield() +#define OS_CPU_ID current_cpu_id() +extern int current_cpu_id() ; +#define OS_CPU_NUM CPU_CORE_NUM + +/* Simulated interrupts return pdFALSE if no context switch should be performed, +or a non-zero number if a context switch should be performed. */ +#define portYIELD_FROM_ISR( x ) return x +#define portEND_SWITCHING_ISR( x ) portYIELD_FROM_ISR( ( x ) ) + +void vPortCloseRunningThread(void *pvTaskToDelete, volatile BaseType_t *pxPendYield); +//void vPortDeleteThread( void *pvThreadToDelete ); +#define portCLEAN_UP_TCB( pxTCB ) //vPortDeleteThread( pxTCB ) +#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxPendYield ) //vPortCloseRunningThread( ( pvTaskToDelete ), ( pxPendYield ) ) +#define portDISABLE_INTERRUPTS() CPU_CRITICAL_ENTER() +#define portENABLE_INTERRUPTS() CPU_CRITICAL_EXIT() + + +/* Critical section handling. */ +void vPortEnterCritical(void); +void vPortExitCritical(void); +//extern void * malloc(int ) ; +//extern void free(void *) ; + +//#define pvPortMalloc malloc +//#define vPortFree free + +/* + extern volatile int cpu_lock_cnt[]; + extern volatile int irq_lock_cnt[]; +#define __asm_csync() \ + do { \ + asm volatile("csync;"); \ + asm volatile("csync;"); \ + asm volatile("csync;"); \ + asm volatile("csync;"); \ + asm volatile("csync;"); \ + } while (0) + + static inline void local_irq_disable() + { + __builtin_pi32v2_cli(); + irq_lock_cnt[current_cpu_id()]++; + } + + + static inline void local_irq_enable() + { + if (--irq_lock_cnt[current_cpu_id()] == 0) { + __builtin_pi32v2_sti(); + } + } + + + #define CPU_CRITICAL_ENTER() \ + do { \ + local_irq_disable(); \ + if(cpu_lock_cnt[current_cpu_id()]++ == 0) \ + asm volatile("lockset;"); \ + __asm_csync(); \ + }while(0) + + + #define CPU_CRITICAL_EXIT() \ + do { \ + if (--cpu_lock_cnt[current_cpu_id()] == 0) \ + asm volatile("lockclr;"); \ + local_irq_enable();\ + }while(0) + +*/ + + +#define portENTER_CRITICAL() CPU_CRITICAL_ENTER() // vPortEnterCritical() +#define portEXIT_CRITICAL() CPU_CRITICAL_EXIT() // vPortExitCritical() + + +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + +/* Check the configuration. */ +#if( configMAX_PRIORITIES > 32 ) +#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. +#endif + +/* Store/clear the ready priorities in a bit map. */ +#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) +#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) \ + do { \ + ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ); \ + } while (0) + + +/*-----------------------------------------------------------*/ + +// uxTopPriority = __builtin_pi32v2_clz(uxReadyPriorities) +#ifdef __GNUC__ +#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) \ + uxTopPriority = 31- __builtin_clz(uxReadyPriorities) +#else +/* BitScanReverse returns the bit position of the most significant '1' +in the word. */ +#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) _BitScanReverse( ( DWORD * ) &( uxTopPriority ), ( uxReadyPriorities ) ) +#endif /* __GNUC__ */ + +#endif /* taskRECORD_READY_PRIORITY */ + +#ifndef __GNUC__ +__pragma(warning(disable: 4211)) /* Nonstandard extension used, as extern is only nonstandard to MSVC. */ +#endif + + +/* Task function macros as described on the FreeRTOS.org WEB site. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) + +#define portINTERRUPT_YIELD ( 0UL ) +#define portINTERRUPT_TICK ( 1UL ) + +/* + * Raise a simulated interrupt represented by the bit mask in ulInterruptMask. + * Each bit can be used to represent an individual interrupt - with the first + * two bits being used for the Yield and Tick interrupts respectively. +*/ +void vPortGenerateSimulatedInterrupt(uint32_t ulInterruptNumber); + +/* + * Install an interrupt handler to be called by the simulated interrupt handler + * thread. The interrupt number must be above any used by the kernel itself + * (at the time of writing the kernel was using interrupt numbers 0, 1, and 2 + * as defined above). The number must also be lower than 32. + * + * Interrupt handler functions must return a non-zero value if executing the + * handler resulted in a task switch being required. + */ +void vPortSetInterruptHandler(uint32_t ulInterruptNumber, uint32_t (*pvHandler)(void)); + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP +extern void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime); +#define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif + +#endif + diff --git a/include_lib/system/os/FreeRTOS/portable.h b/include_lib/system/os/FreeRTOS/portable.h new file mode 100644 index 0000000..9849a8a --- /dev/null +++ b/include_lib/system/os/FreeRTOS/portable.h @@ -0,0 +1,206 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------- + * Portable layer API. Each function must be defined for each port. + *----------------------------------------------------------*/ + +#ifndef PORTABLE_H +#define PORTABLE_H + +/* Each FreeRTOS port has a unique portmacro.h header file. Originally a +pre-processor definition was used to ensure the pre-processor found the correct +portmacro.h file for the port being used. That scheme was deprecated in favour +of setting the compiler's include path such that it found the correct +portmacro.h file - removing the need for the constant and allowing the +portmacro.h file to be located anywhere in relation to the port being used. +Purely for reasons of backward compatibility the old method is still valid, but +to make it clear that new projects should not use it, support for the port +specific constants has been moved into the deprecated_definitions.h header +file. */ +#include "deprecated_definitions.h" + +/* If portENTER_CRITICAL is not defined then including deprecated_definitions.h +did not result in a portmacro.h header file being included - and it should be +included here. In this case the path to the correct portmacro.h header file +must be set in the compiler's include path. */ +#ifndef portENTER_CRITICAL +#include "portmacro.h" +#endif + +#if portBYTE_ALIGNMENT == 32 +#define portBYTE_ALIGNMENT_MASK ( 0x001f ) +#endif + +#if portBYTE_ALIGNMENT == 16 +#define portBYTE_ALIGNMENT_MASK ( 0x000f ) +#endif + +#if portBYTE_ALIGNMENT == 8 +#define portBYTE_ALIGNMENT_MASK ( 0x0007 ) +#endif + +#if portBYTE_ALIGNMENT == 4 +#define portBYTE_ALIGNMENT_MASK ( 0x0003 ) +#endif + +#if portBYTE_ALIGNMENT == 2 +#define portBYTE_ALIGNMENT_MASK ( 0x0001 ) +#endif + +#if portBYTE_ALIGNMENT == 1 +#define portBYTE_ALIGNMENT_MASK ( 0x0000 ) +#endif + +#ifndef portBYTE_ALIGNMENT_MASK +#error "Invalid portBYTE_ALIGNMENT definition" +#endif + +#ifndef portNUM_CONFIGURABLE_REGIONS +#define portNUM_CONFIGURABLE_REGIONS 1 +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#include "mpu_wrappers.h" + +/* + * Setup the stack of a new task so it is ready to be placed under the + * scheduler control. The registers have to be placed on the stack in + * the order that the port expects to find them. + * + */ +#if( portUSING_MPU_WRAPPERS == 1 ) +StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters, BaseType_t xRunPrivileged) PRIVILEGED_FUNCTION; +#else +StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters) PRIVILEGED_FUNCTION; +#endif + +/* Used by heap_5.c. */ +typedef struct HeapRegion { + uint8_t *pucStartAddress; + size_t xSizeInBytes; +} HeapRegion_t; + +/* + * Used to define multiple heap regions for use by heap_5.c. This function + * must be called before any calls to pvPortMalloc() - not creating a task, + * queue, semaphore, mutex, software timer, event group, etc. will result in + * pvPortMalloc being called. + * + * pxHeapRegions passes in an array of HeapRegion_t structures - each of which + * defines a region of memory that can be used as the heap. The array is + * terminated by a HeapRegions_t structure that has a size of 0. The region + * with the lowest start address must appear first in the array. + */ +void vPortDefineHeapRegions(const HeapRegion_t *const pxHeapRegions) PRIVILEGED_FUNCTION; + + +/* + * Map to the memory management routines required for the port. + */ +void *pvPortMalloc(size_t xSize) PRIVILEGED_FUNCTION; +void vPortFree(void *pv) PRIVILEGED_FUNCTION; +void vPortInitialiseBlocks(void) PRIVILEGED_FUNCTION; +size_t xPortGetFreeHeapSize(void) PRIVILEGED_FUNCTION; +size_t xPortGetMinimumEverFreeHeapSize(void) PRIVILEGED_FUNCTION; + +/* + * Setup the hardware ready for the scheduler to take control. This generally + * sets up a tick interrupt and sets timers for the correct tick frequency. + */ +BaseType_t xPortStartScheduler(void) PRIVILEGED_FUNCTION; + +/* + * Undo any hardware/ISR setup that was performed by xPortStartScheduler() so + * the hardware is left in its original condition after the scheduler stops + * executing. + */ +void vPortEndScheduler(void) PRIVILEGED_FUNCTION; + +/* + * The structures and methods of manipulating the MPU are contained within the + * port layer. + * + * Fills the xMPUSettings structure with the memory region information + * contained in xRegions. + */ +#if( portUSING_MPU_WRAPPERS == 1 ) +struct xMEMORY_REGION; +void vPortStoreTaskMPUSettings(xMPU_SETTINGS *xMPUSettings, const struct xMEMORY_REGION *const xRegions, StackType_t *pxBottomOfStack, uint32_t ulStackDepth) PRIVILEGED_FUNCTION; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* PORTABLE_H */ + diff --git a/include_lib/system/os/FreeRTOS/projdefs.h b/include_lib/system/os/FreeRTOS/projdefs.h new file mode 100644 index 0000000..d73ca18 --- /dev/null +++ b/include_lib/system/os/FreeRTOS/projdefs.h @@ -0,0 +1,161 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef PROJDEFS_H +#define PROJDEFS_H + +/* + * Defines the prototype to which task functions must conform. Defined in this + * file to ensure the type is known before portable.h is included. + */ +typedef void (*TaskFunction_t)(void *); + +/* Converts a time in milliseconds to a time in ticks. This macro can be +overridden by a macro of the same name defined in FreeRTOSConfig.h in case the +definition here is not suitable for your application. */ +#ifndef pdMS_TO_TICKS +#define pdMS_TO_TICKS( xTimeInMs ) ( ( TickType_t ) ( ( ( TickType_t ) ( xTimeInMs ) * ( TickType_t ) configTICK_RATE_HZ ) / ( TickType_t ) 1000 ) ) +#endif + +#define pdFALSE ( ( BaseType_t ) 0 ) +#define pdTRUE ( ( BaseType_t ) 1 ) + +#define pdPASS ( pdTRUE ) +#define pdFAIL ( pdFALSE ) +#define errQUEUE_EMPTY ( ( BaseType_t ) 0 ) +#define errQUEUE_FULL ( ( BaseType_t ) 0 ) + +/* FreeRTOS error definitions. */ +#define errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY ( -1 ) +#define errQUEUE_BLOCKED ( -4 ) +#define errQUEUE_YIELD ( -5 ) + +/* Macros used for basic data corruption checks. */ +#ifndef configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES +#define configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES 0 +#endif + +#if( configUSE_16_BIT_TICKS == 1 ) +#define pdINTEGRITY_CHECK_VALUE 0x5a5a +#else +#define pdINTEGRITY_CHECK_VALUE 0x5a5a5a5aUL +#endif + +/* The following errno values are used by FreeRTOS+ components, not FreeRTOS +itself. */ +#define pdFREERTOS_ERRNO_NONE 0 /* No errors */ +#define pdFREERTOS_ERRNO_ENOENT 2 /* No such file or directory */ +#define pdFREERTOS_ERRNO_EINTR 4 /* Interrupted system call */ +#define pdFREERTOS_ERRNO_EIO 5 /* I/O error */ +#define pdFREERTOS_ERRNO_ENXIO 6 /* No such device or address */ +#define pdFREERTOS_ERRNO_EBADF 9 /* Bad file number */ +#define pdFREERTOS_ERRNO_EAGAIN 11 /* No more processes */ +#define pdFREERTOS_ERRNO_EWOULDBLOCK 11 /* Operation would block */ +#define pdFREERTOS_ERRNO_ENOMEM 12 /* Not enough memory */ +#define pdFREERTOS_ERRNO_EACCES 13 /* Permission denied */ +#define pdFREERTOS_ERRNO_EFAULT 14 /* Bad address */ +#define pdFREERTOS_ERRNO_EBUSY 16 /* Mount device busy */ +#define pdFREERTOS_ERRNO_EEXIST 17 /* File exists */ +#define pdFREERTOS_ERRNO_EXDEV 18 /* Cross-device link */ +#define pdFREERTOS_ERRNO_ENODEV 19 /* No such device */ +#define pdFREERTOS_ERRNO_ENOTDIR 20 /* Not a directory */ +#define pdFREERTOS_ERRNO_EISDIR 21 /* Is a directory */ +#define pdFREERTOS_ERRNO_EINVAL 22 /* Invalid argument */ +#define pdFREERTOS_ERRNO_ENOSPC 28 /* No space left on device */ +#define pdFREERTOS_ERRNO_ESPIPE 29 /* Illegal seek */ +#define pdFREERTOS_ERRNO_EROFS 30 /* Read only file system */ +#define pdFREERTOS_ERRNO_EUNATCH 42 /* Protocol driver not attached */ +#define pdFREERTOS_ERRNO_EBADE 50 /* Invalid exchange */ +#define pdFREERTOS_ERRNO_EFTYPE 79 /* Inappropriate file type or format */ +#define pdFREERTOS_ERRNO_ENMFILE 89 /* No more files */ +#define pdFREERTOS_ERRNO_ENOTEMPTY 90 /* Directory not empty */ +#define pdFREERTOS_ERRNO_ENAMETOOLONG 91 /* File or path name too long */ +#define pdFREERTOS_ERRNO_EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define pdFREERTOS_ERRNO_ENOBUFS 105 /* No buffer space available */ +#define pdFREERTOS_ERRNO_ENOPROTOOPT 109 /* Protocol not available */ +#define pdFREERTOS_ERRNO_EADDRINUSE 112 /* Address already in use */ +#define pdFREERTOS_ERRNO_ETIMEDOUT 116 /* Connection timed out */ +#define pdFREERTOS_ERRNO_EINPROGRESS 119 /* Connection already in progress */ +#define pdFREERTOS_ERRNO_EALREADY 120 /* Socket already connected */ +#define pdFREERTOS_ERRNO_EADDRNOTAVAIL 125 /* Address not available */ +#define pdFREERTOS_ERRNO_EISCONN 127 /* Socket is already connected */ +#define pdFREERTOS_ERRNO_ENOTCONN 128 /* Socket is not connected */ +#define pdFREERTOS_ERRNO_ENOMEDIUM 135 /* No medium inserted */ +#define pdFREERTOS_ERRNO_EILSEQ 138 /* An invalid UTF-16 sequence was encountered. */ +#define pdFREERTOS_ERRNO_ECANCELED 140 /* Operation canceled. */ + +/* The following endian values are used by FreeRTOS+ components, not FreeRTOS +itself. */ +#define pdFREERTOS_LITTLE_ENDIAN 0 +#define pdFREERTOS_BIG_ENDIAN 1 + +#endif /* PROJDEFS_H */ + + + diff --git a/include_lib/system/os/FreeRTOS/q32s/portmacro.h b/include_lib/system/os/FreeRTOS/q32s/portmacro.h new file mode 100644 index 0000000..898bc74 --- /dev/null +++ b/include_lib/system/os/FreeRTOS/q32s/portmacro.h @@ -0,0 +1,262 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef PORTMACRO_H +#define PORTMACRO_H +#include "asm/cpu.h" +#include +/****************************************************************************** + Defines +******************************************************************************/ +/* Type definitions. */ +#define portCHAR char +#define portFLOAT float +#define portDOUBLE double +#define portLONG long +#define portSHORT short +#define portSTACK_TYPE int +#define portBASE_TYPE long +#define portPOINTER_SIZE_TYPE size_t + +typedef portSTACK_TYPE StackType_t; +typedef long BaseType_t; +typedef unsigned long UBaseType_t; + + +#if( configUSE_16_BIT_TICKS == 1 ) +typedef uint16_t TickType_t; +#define portMAX_DELAY ( TickType_t ) 0xffff +#else +typedef uint32_t TickType_t; +#define portMAX_DELAY ( TickType_t ) 0xffffffffUL + +/* 32/64-bit tick type on a 32/64-bit architecture, so reads of the tick +count do not need to be guarded with a critical section. */ +#define portTICK_TYPE_IS_ATOMIC 1 +#endif + +/* Hardware specifics. */ +#define portSTACK_GROWTH ( -1 ) +#define portTICK_PERIOD_MS ( ( TickType_t ) 1000 / configTICK_RATE_HZ ) +#define portINLINE __inline + +#if defined( __x86_64__) || defined( _M_X64 ) +#define portBYTE_ALIGNMENT 8 +#else +#define portBYTE_ALIGNMENT 4 +#endif +extern void vPortYield() ; +#define portYIELD() vPortYield() +#define OS_CPU_ID current_cpu_id() +extern int current_cpu_id() ; +#define OS_CPU_NUM CPU_CORE_NUM + +/* Simulated interrupts return pdFALSE if no context switch should be performed, +or a non-zero number if a context switch should be performed. */ +#define portYIELD_FROM_ISR( x ) return x +#define portEND_SWITCHING_ISR( x ) portYIELD_FROM_ISR( ( x ) ) + +void vPortCloseRunningThread(void *pvTaskToDelete, volatile BaseType_t *pxPendYield); +//void vPortDeleteThread( void *pvThreadToDelete ); +#define portCLEAN_UP_TCB( pxTCB ) //vPortDeleteThread( pxTCB ) +#define portPRE_TASK_DELETE_HOOK( pvTaskToDelete, pxPendYield ) //vPortCloseRunningThread( ( pvTaskToDelete ), ( pxPendYield ) ) +#define portDISABLE_INTERRUPTS() CPU_CRITICAL_ENTER() +#define portENABLE_INTERRUPTS() CPU_CRITICAL_EXIT() + + +/* Critical section handling. */ +void vPortEnterCritical(void); +void vPortExitCritical(void); +//extern void * malloc(int ) ; +//extern void free(void *) ; + +//#define pvPortMalloc malloc +//#define vPortFree free + +/* + extern volatile int cpu_lock_cnt[]; + extern volatile int irq_lock_cnt[]; +#define __asm_csync() \ + do { \ + asm volatile("csync;"); \ + asm volatile("csync;"); \ + asm volatile("csync;"); \ + asm volatile("csync;"); \ + asm volatile("csync;"); \ + } while (0) + + static inline void local_irq_disable() + { + __builtin_pi32v2_cli(); + irq_lock_cnt[current_cpu_id()]++; + } + + + static inline void local_irq_enable() + { + if (--irq_lock_cnt[current_cpu_id()] == 0) { + __builtin_pi32v2_sti(); + } + } + + + #define CPU_CRITICAL_ENTER() \ + do { \ + local_irq_disable(); \ + if(cpu_lock_cnt[current_cpu_id()]++ == 0) \ + asm volatile("lockset;"); \ + __asm_csync(); \ + }while(0) + + + #define CPU_CRITICAL_EXIT() \ + do { \ + if (--cpu_lock_cnt[current_cpu_id()] == 0) \ + asm volatile("lockclr;"); \ + local_irq_enable();\ + }while(0) + +*/ + + +#define portENTER_CRITICAL() CPU_CRITICAL_ENTER() // vPortEnterCritical() +#define portEXIT_CRITICAL() CPU_CRITICAL_EXIT() // vPortExitCritical() + + +#ifndef configUSE_PORT_OPTIMISED_TASK_SELECTION +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 +#endif + +#if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1 + +/* Check the configuration. */ +#if( configMAX_PRIORITIES > 32 ) +#error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32. It is very rare that a system requires more than 10 to 15 difference priorities as tasks that share a priority will time slice. +#endif + +/* Store/clear the ready priorities in a bit map. */ +#define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) ) +#define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) \ + do { \ + ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) ); \ + } while (0) + + +/*-----------------------------------------------------------*/ + +// uxTopPriority = __builtin_pi32v2_clz(uxReadyPriorities) +#ifdef __GNUC__ +#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) \ + uxTopPriority = 31- __builtin_clz(uxReadyPriorities) +#else +/* BitScanReverse returns the bit position of the most significant '1' +in the word. */ +#define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) _BitScanReverse( ( DWORD * ) &( uxTopPriority ), ( uxReadyPriorities ) ) +#endif /* __GNUC__ */ + +#endif /* taskRECORD_READY_PRIORITY */ + +#ifndef __GNUC__ +__pragma(warning(disable: 4211)) /* Nonstandard extension used, as extern is only nonstandard to MSVC. */ +#endif + + +/* Task function macros as described on the FreeRTOS.org WEB site. */ +#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void * pvParameters ) +#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void * pvParameters ) + +#define portINTERRUPT_YIELD ( 0UL ) +#define portINTERRUPT_TICK ( 1UL ) + +/* + * Raise a simulated interrupt represented by the bit mask in ulInterruptMask. + * Each bit can be used to represent an individual interrupt - with the first + * two bits being used for the Yield and Tick interrupts respectively. +*/ +void vPortGenerateSimulatedInterrupt(uint32_t ulInterruptNumber); + +/* + * Install an interrupt handler to be called by the simulated interrupt handler + * thread. The interrupt number must be above any used by the kernel itself + * (at the time of writing the kernel was using interrupt numbers 0, 1, and 2 + * as defined above). The number must also be lower than 32. + * + * Interrupt handler functions must return a non-zero value if executing the + * handler resulted in a task switch being required. + */ +void vPortSetInterruptHandler(uint32_t ulInterruptNumber, uint32_t (*pvHandler)(void)); + +/* Tickless idle/low power functionality. */ +#ifndef portSUPPRESS_TICKS_AND_SLEEP +// extern void vPortSuppressTicksAndSleep(TickType_t xExpectedIdleTime); +// #define portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime ) vPortSuppressTicksAndSleep( xExpectedIdleTime ) +#endif + +#endif + diff --git a/include_lib/system/os/FreeRTOS/queue.h b/include_lib/system/os/FreeRTOS/queue.h new file mode 100644 index 0000000..a90cfca --- /dev/null +++ b/include_lib/system/os/FreeRTOS/queue.h @@ -0,0 +1,1799 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef QUEUE_H +#define QUEUE_H + +#ifndef INC_FREERTOS_H +#error "include FreeRTOS.h" must appear in source files before "include queue.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Type by which queues are referenced. For example, a call to xQueueCreate() + * returns an QueueHandle_t variable that can then be used as a parameter to + * xQueueSend(), xQueueReceive(), etc. + */ +typedef void *QueueHandle_t; + +/** + * Type by which queue sets are referenced. For example, a call to + * xQueueCreateSet() returns an xQueueSet variable that can then be used as a + * parameter to xQueueSelectFromSet(), xQueueAddToSet(), etc. + */ +typedef void *QueueSetHandle_t; + +/** + * Queue sets can contain both queues and semaphores, so the + * QueueSetMemberHandle_t is defined as a type to be used where a parameter or + * return value can be either an QueueHandle_t or an SemaphoreHandle_t. + */ +typedef void *QueueSetMemberHandle_t; + +/* For internal use only. */ +#define queueSEND_TO_BACK ( ( BaseType_t ) 0 ) +#define queueSEND_TO_FRONT ( ( BaseType_t ) 1 ) +#define queueOVERWRITE ( ( BaseType_t ) 2 ) + +/* For internal use only. These definitions *must* match those in queue.c. */ +#define queueQUEUE_TYPE_SET ( ( uint8_t ) 0U ) +#define queueQUEUE_TYPE_MUTEX ( ( uint8_t ) 1U ) +#define queueQUEUE_TYPE_COUNTING_SEMAPHORE ( ( uint8_t ) 2U ) +#define queueQUEUE_TYPE_BINARY_SEMAPHORE ( ( uint8_t ) 3U ) +#define queueQUEUE_TYPE_RECURSIVE_MUTEX ( ( uint8_t ) 4U ) +#define queueQUEUE_TYPE_BASE ( ( uint8_t ) 5U ) + +/** + * queue. h + *
+ QueueHandle_t xQueueCreate(
+							  UBaseType_t uxQueueLength,
+							  UBaseType_t uxItemSize
+						  );
+ * 
+ * + * Creates a new queue instance, and returns a handle by which the new queue + * can be referenced. + * + * Internally, within the FreeRTOS implementation, queues use two blocks of + * memory. The first block is used to hold the queue's data structures. The + * second block is used to hold items placed into the queue. If a queue is + * created using xQueueCreate() then both blocks of memory are automatically + * dynamically allocated inside the xQueueCreate() function. (see + * http://www.freertos.org/a00111.html). If a queue is created using + * xQueueCreateStatic() then the application writer must provide the memory that + * will get used by the queue. xQueueCreateStatic() therefore allows a queue to + * be created without using any dynamic memory allocation. + * + * http://www.FreeRTOS.org/Embedded-RTOS-Queues.html + * + * @param uxQueueLength The maximum number of items that the queue can contain. + * + * @param uxItemSize The number of bytes each item in the queue will require. + * Items are queued by copy, not by reference, so this is the number of bytes + * that will be copied for each posted item. Each item on the queue must be + * the same size. + * + * @return If the queue is successfully create then a handle to the newly + * created queue is returned. If the queue cannot be created then 0 is + * returned. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ };
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+	if( xQueue1 == 0 )
+	{
+		// Queue was not created and must not be used.
+	}
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue2 == 0 )
+	{
+		// Queue was not created and must not be used.
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueCreate xQueueCreate + * \ingroup QueueManagement + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +#define xQueueCreate( uxQueueLength, uxItemSize ) xQueueGenericCreate( ( uxQueueLength ), ( uxItemSize ), ( queueQUEUE_TYPE_BASE ) ) +#endif + +/** + * queue. h + *
+ QueueHandle_t xQueueCreateStatic(
+							  UBaseType_t uxQueueLength,
+							  UBaseType_t uxItemSize,
+							  uint8_t *pucQueueStorageBuffer,
+							  StaticQueue_t *pxQueueBuffer
+						  );
+ * 
+ * + * Creates a new queue instance, and returns a handle by which the new queue + * can be referenced. + * + * Internally, within the FreeRTOS implementation, queues use two blocks of + * memory. The first block is used to hold the queue's data structures. The + * second block is used to hold items placed into the queue. If a queue is + * created using xQueueCreate() then both blocks of memory are automatically + * dynamically allocated inside the xQueueCreate() function. (see + * http://www.freertos.org/a00111.html). If a queue is created using + * xQueueCreateStatic() then the application writer must provide the memory that + * will get used by the queue. xQueueCreateStatic() therefore allows a queue to + * be created without using any dynamic memory allocation. + * + * http://www.FreeRTOS.org/Embedded-RTOS-Queues.html + * + * @param uxQueueLength The maximum number of items that the queue can contain. + * + * @param uxItemSize The number of bytes each item in the queue will require. + * Items are queued by copy, not by reference, so this is the number of bytes + * that will be copied for each posted item. Each item on the queue must be + * the same size. + * + * @param pucQueueStorageBuffer If uxItemSize is not zero then + * pucQueueStorageBuffer must point to a uint8_t array that is at least large + * enough to hold the maximum number of items that can be in the queue at any + * one time - which is ( uxQueueLength * uxItemsSize ) bytes. If uxItemSize is + * zero then pucQueueStorageBuffer can be NULL. + * + * @param pxQueueBuffer Must point to a variable of type StaticQueue_t, which + * will be used to hold the queue's data structure. + * + * @return If the queue is created then a handle to the created queue is + * returned. If pxQueueBuffer is NULL then NULL is returned. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ };
+
+ #define QUEUE_LENGTH 10
+ #define ITEM_SIZE sizeof( uint32_t )
+
+ // xQueueBuffer will hold the queue structure.
+ StaticQueue_t xQueueBuffer;
+
+ // ucQueueStorage will hold the items posted to the queue.  Must be at least
+ // [(queue length) * ( queue item size)] bytes long.
+ uint8_t ucQueueStorage[ QUEUE_LENGTH * ITEM_SIZE ];
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( QUEUE_LENGTH, // The number of items the queue can hold.
+							ITEM_SIZE	  // The size of each item in the queue
+							&( ucQueueStorage[ 0 ] ), // The buffer that will hold the items in the queue.
+							&xQueueBuffer ); // The buffer that will hold the queue structure.
+
+	// The queue is guaranteed to be created successfully as no dynamic memory
+	// allocation is used.  Therefore xQueue1 is now a handle to a valid queue.
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueCreateStatic xQueueCreateStatic + * \ingroup QueueManagement + */ +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) +#define xQueueCreateStatic( uxQueueLength, uxItemSize, pucQueueStorage, pxQueueBuffer ) xQueueGenericCreateStatic( ( uxQueueLength ), ( uxItemSize ), ( pucQueueStorage ), ( pxQueueBuffer ), ( queueQUEUE_TYPE_BASE ) ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ + +/** + * queue. h + *
+ BaseType_t xQueueSendToToFront(
+								   QueueHandle_t	xQueue,
+								   const void		*pvItemToQueue,
+								   TickType_t		xTicksToWait
+							   );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). + * + * Post an item to the front of a queue. The item is queued by copy, not by + * reference. This function must not be called from an interrupt service + * routine. See xQueueSendFromISR () for an alternative which may be used + * in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSendToFront( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSendToFront( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSendToFront( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_FRONT ) + +/** + * queue. h + *
+ BaseType_t xQueueSendToBack(
+								   QueueHandle_t	xQueue,
+								   const void		*pvItemToQueue,
+								   TickType_t		xTicksToWait
+							   );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). + * + * Post an item to the back of a queue. The item is queued by copy, not by + * reference. This function must not be called from an interrupt service + * routine. See xQueueSendFromISR () for an alternative which may be used + * in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the queue + * is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSendToBack( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSendToBack( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueSend(
+							  QueueHandle_t xQueue,
+							  const void * pvItemToQueue,
+							  TickType_t xTicksToWait
+						 );
+ * 
+ * + * This is a macro that calls xQueueGenericSend(). It is included for + * backward compatibility with versions of FreeRTOS.org that did not + * include the xQueueSendToFront() and xQueueSendToBack() macros. It is + * equivalent to xQueueSendToBack(). + * + * Post an item on a queue. The item is queued by copy, not by reference. + * This function must not be called from an interrupt service routine. + * See xQueueSendFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10 ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0 );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueOverwrite(
+							  QueueHandle_t xQueue,
+							  const void * pvItemToQueue
+						 );
+ * 
+ * + * Only for use with queues that have a length of one - so the queue is either + * empty or full. + * + * Post an item on a queue. If the queue is already full then overwrite the + * value held in the queue. The item is queued by copy, not by reference. + * + * This function must not be called from an interrupt service routine. + * See xQueueOverwriteFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle of the queue to which the data is being sent. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @return xQueueOverwrite() is a macro that calls xQueueGenericSend(), and + * therefore has the same return values as xQueueSendToFront(). However, pdPASS + * is the only value that can be returned because xQueueOverwrite() will write + * to the queue even when the queue is already full. + * + * Example usage: +
+
+ void vFunction( void *pvParameters )
+ {
+ QueueHandle_t xQueue;
+ uint32_t ulVarToSend, ulValReceived;
+
+	// Create a queue to hold one uint32_t value.  It is strongly
+	// recommended *not* to use xQueueOverwrite() on queues that can
+	// contain more than one value, and doing so will trigger an assertion
+	// if configASSERT() is defined.
+	xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
+
+	// Write the value 10 to the queue using xQueueOverwrite().
+	ulVarToSend = 10;
+	xQueueOverwrite( xQueue, &ulVarToSend );
+
+	// Peeking the queue should now return 10, but leave the value 10 in
+	// the queue.  A block time of zero is used as it is known that the
+	// queue holds a value.
+	ulValReceived = 0;
+	xQueuePeek( xQueue, &ulValReceived, 0 );
+
+	if( ulValReceived != 10 )
+	{
+		// Error unless the item was removed by a different task.
+	}
+
+	// The queue is still full.  Use xQueueOverwrite() to overwrite the
+	// value held in the queue with 100.
+	ulVarToSend = 100;
+	xQueueOverwrite( xQueue, &ulVarToSend );
+
+	// This time read from the queue, leaving the queue empty once more.
+	// A block time of 0 is used again.
+	xQueueReceive( xQueue, &ulValReceived, 0 );
+
+	// The value read should be the last value written, even though the
+	// queue was already full when the value was written.
+	if( ulValReceived != 100 )
+	{
+		// Error!
+	}
+
+	// ...
+}
+ 
+ * \defgroup xQueueOverwrite xQueueOverwrite + * \ingroup QueueManagement + */ +#define xQueueOverwrite( xQueue, pvItemToQueue ) xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), 0, queueOVERWRITE ) + + +/** + * queue. h + *
+ BaseType_t xQueueGenericSend(
+									QueueHandle_t xQueue,
+									const void * pvItemToQueue,
+									TickType_t xTicksToWait
+									BaseType_t xCopyPosition
+								);
+ * 
+ * + * It is preferred that the macros xQueueSend(), xQueueSendToFront() and + * xQueueSendToBack() are used in place of calling this function directly. + * + * Post an item on a queue. The item is queued by copy, not by reference. + * This function must not be called from an interrupt service routine. + * See xQueueSendFromISR () for an alternative which may be used in an ISR. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for space to become available on the queue, should it already + * be full. The call will return immediately if this is set to 0 and the + * queue is full. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * + * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the + * item at the back of the queue, or queueSEND_TO_FRONT to place the item + * at the front of the queue (for high priority messages). + * + * @return pdTRUE if the item was successfully posted, otherwise errQUEUE_FULL. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ uint32_t ulVar = 10UL;
+
+ void vATask( void *pvParameters )
+ {
+ QueueHandle_t xQueue1, xQueue2;
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 uint32_t values.
+	xQueue1 = xQueueCreate( 10, sizeof( uint32_t ) );
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue2 = xQueueCreate( 10, sizeof( struct AMessage * ) );
+
+	// ...
+
+	if( xQueue1 != 0 )
+	{
+		// Send an uint32_t.  Wait for 10 ticks for space to become
+		// available if necessary.
+		if( xQueueGenericSend( xQueue1, ( void * ) &ulVar, ( TickType_t ) 10, queueSEND_TO_BACK ) != pdPASS )
+		{
+			// Failed to post the message, even after 10 ticks.
+		}
+	}
+
+	if( xQueue2 != 0 )
+	{
+		// Send a pointer to a struct AMessage object.  Don't block if the
+		// queue is already full.
+		pxMessage = & xMessage;
+		xQueueGenericSend( xQueue2, ( void * ) &pxMessage, ( TickType_t ) 0, queueSEND_TO_BACK );
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueSend xQueueSend + * \ingroup QueueManagement + */ +BaseType_t xQueueGenericSend(QueueHandle_t xQueue, const void *const pvItemToQueue, TickType_t xTicksToWait, const BaseType_t xCopyPosition) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueuePeek(
+							 QueueHandle_t xQueue,
+							 void *pvBuffer,
+							 TickType_t xTicksToWait
+						 );
+ * + * This is a macro that calls the xQueueGenericReceive() function. + * + * Receive an item from a queue without removing the item from the queue. + * The item is received by copy so a buffer of adequate size must be + * provided. The number of bytes copied into the buffer was defined when + * the queue was created. + * + * Successfully received items remain on the queue so will be returned again + * by the next call, or a call to xQueueReceive(). + * + * This macro must not be used in an interrupt service routine. See + * xQueuePeekFromISR() for an alternative that can be called from an interrupt + * service routine. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * xQueuePeek() will return immediately if xTicksToWait is 0 and the queue + * is empty. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ QueueHandle_t xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to peek the data from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Peek a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueuePeek( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask, but the item still remains on the queue.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +#define xQueuePeek( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdTRUE ) + +/** + * queue. h + *
+ BaseType_t xQueuePeekFromISR(
+									QueueHandle_t xQueue,
+									void *pvBuffer,
+								);
+ * + * A version of xQueuePeek() that can be called from an interrupt service + * routine (ISR). + * + * Receive an item from a queue without removing the item from the queue. + * The item is received by copy so a buffer of adequate size must be + * provided. The number of bytes copied into the buffer was defined when + * the queue was created. + * + * Successfully received items remain on the queue so will be returned again + * by the next call, or a call to xQueueReceive(). + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * \defgroup xQueuePeekFromISR xQueuePeekFromISR + * \ingroup QueueManagement + */ +BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue, void *const pvBuffer) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueueReceive(
+								 QueueHandle_t xQueue,
+								 void *pvBuffer,
+								 TickType_t xTicksToWait
+							);
+ * + * This is a macro that calls the xQueueGenericReceive() function. + * + * Receive an item from a queue. The item is received by copy so a buffer of + * adequate size must be provided. The number of bytes copied into the buffer + * was defined when the queue was created. + * + * Successfully received items are removed from the queue. + * + * This function must not be used in an interrupt service routine. See + * xQueueReceiveFromISR for an alternative that can. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. xQueueReceive() will return immediately if xTicksToWait + * is zero and the queue is empty. The time is defined in tick periods so the + * constant portTICK_PERIOD_MS should be used to convert to real time if this is + * required. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ QueueHandle_t xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Receive a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueueReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +#define xQueueReceive( xQueue, pvBuffer, xTicksToWait ) xQueueGenericReceive( ( xQueue ), ( pvBuffer ), ( xTicksToWait ), pdFALSE ) + + +/** + * queue. h + *
+ BaseType_t xQueueGenericReceive(
+									   QueueHandle_t	xQueue,
+									   void	*pvBuffer,
+									   TickType_t	xTicksToWait
+									   BaseType_t	xJustPeek
+									);
+ * + * It is preferred that the macro xQueueReceive() be used rather than calling + * this function directly. + * + * Receive an item from a queue. The item is received by copy so a buffer of + * adequate size must be provided. The number of bytes copied into the buffer + * was defined when the queue was created. + * + * This function must not be used in an interrupt service routine. See + * xQueueReceiveFromISR for an alternative that can. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param xTicksToWait The maximum amount of time the task should block + * waiting for an item to receive should the queue be empty at the time + * of the call. The time is defined in tick periods so the constant + * portTICK_PERIOD_MS should be used to convert to real time if this is required. + * xQueueGenericReceive() will return immediately if the queue is empty and + * xTicksToWait is 0. + * + * @param xJustPeek When set to true, the item received from the queue is not + * actually removed from the queue - meaning a subsequent call to + * xQueueReceive() will return the same item. When set to false, the item + * being received from the queue is also removed from the queue. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+ struct AMessage
+ {
+	char ucMessageID;
+	char ucData[ 20 ];
+ } xMessage;
+
+ QueueHandle_t xQueue;
+
+ // Task to create a queue and post a value.
+ void vATask( void *pvParameters )
+ {
+ struct AMessage *pxMessage;
+
+	// Create a queue capable of containing 10 pointers to AMessage structures.
+	// These should be passed by pointer as they contain a lot of data.
+	xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Send a pointer to a struct AMessage object.  Don't block if the
+	// queue is already full.
+	pxMessage = & xMessage;
+	xQueueSend( xQueue, ( void * ) &pxMessage, ( TickType_t ) 0 );
+
+	// ... Rest of task code.
+ }
+
+ // Task to receive from the queue.
+ void vADifferentTask( void *pvParameters )
+ {
+ struct AMessage *pxRxedMessage;
+
+	if( xQueue != 0 )
+	{
+		// Receive a message on the created queue.  Block for 10 ticks if a
+		// message is not immediately available.
+		if( xQueueGenericReceive( xQueue, &( pxRxedMessage ), ( TickType_t ) 10 ) )
+		{
+			// pcRxedMessage now points to the struct AMessage variable posted
+			// by vATask.
+		}
+	}
+
+	// ... Rest of task code.
+ }
+ 
+ * \defgroup xQueueReceive xQueueReceive + * \ingroup QueueManagement + */ +BaseType_t xQueueGenericReceive(QueueHandle_t xQueue, void *const pvBuffer, TickType_t xTicksToWait, const BaseType_t xJustPeek) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue );
+ * + * Return the number of messages stored in a queue. + * + * @param xQueue A handle to the queue being queried. + * + * @return The number of messages available in the queue. + * + * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting + * \ingroup QueueManagement + */ +UBaseType_t uxQueueMessagesWaiting(const QueueHandle_t xQueue) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue );
+ * + * Return the number of free spaces available in a queue. This is equal to the + * number of items that can be sent to the queue before the queue becomes full + * if no items are removed. + * + * @param xQueue A handle to the queue being queried. + * + * @return The number of spaces available in the queue. + * + * \defgroup uxQueueMessagesWaiting uxQueueMessagesWaiting + * \ingroup QueueManagement + */ +UBaseType_t uxQueueSpacesAvailable(const QueueHandle_t xQueue) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
void vQueueDelete( QueueHandle_t xQueue );
+ * + * Delete a queue - freeing all the memory allocated for storing of items + * placed on the queue. + * + * @param xQueue A handle to the queue to be deleted. + * + * \defgroup vQueueDelete vQueueDelete + * \ingroup QueueManagement + */ +void vQueueDelete(QueueHandle_t xQueue) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueueSendToFrontFromISR(
+										 QueueHandle_t xQueue,
+										 const void *pvItemToQueue,
+										 BaseType_t *pxHigherPriorityTaskWoken
+									  );
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). + * + * Post an item to the front of a queue. It is safe to use this macro from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendToFrontFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendToFromFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPrioritTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendToFrontFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendToFrontFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_FRONT ) + + +/** + * queue. h + *
+ BaseType_t xQueueSendToBackFromISR(
+										 QueueHandle_t xQueue,
+										 const void *pvItemToQueue,
+										 BaseType_t *pxHigherPriorityTaskWoken
+									  );
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). + * + * Post an item to the back of a queue. It is safe to use this macro from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendToBackFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendToBackFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPriorityTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendToBackFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendToBackFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueOverwriteFromISR(
+							  QueueHandle_t xQueue,
+							  const void * pvItemToQueue,
+							  BaseType_t *pxHigherPriorityTaskWoken
+						 );
+ * 
+ * + * A version of xQueueOverwrite() that can be used in an interrupt service + * routine (ISR). + * + * Only for use with queues that can hold a single item - so the queue is either + * empty or full. + * + * Post an item on a queue. If the queue is already full then overwrite the + * value held in the queue. The item is queued by copy, not by reference. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueOverwriteFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueOverwriteFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return xQueueOverwriteFromISR() is a macro that calls + * xQueueGenericSendFromISR(), and therefore has the same return values as + * xQueueSendToFrontFromISR(). However, pdPASS is the only value that can be + * returned because xQueueOverwriteFromISR() will write to the queue even when + * the queue is already full. + * + * Example usage: +
+
+ QueueHandle_t xQueue;
+
+ void vFunction( void *pvParameters )
+ {
+ 	// Create a queue to hold one uint32_t value.  It is strongly
+	// recommended *not* to use xQueueOverwriteFromISR() on queues that can
+	// contain more than one value, and doing so will trigger an assertion
+	// if configASSERT() is defined.
+	xQueue = xQueueCreate( 1, sizeof( uint32_t ) );
+}
+
+void vAnInterruptHandler( void )
+{
+// xHigherPriorityTaskWoken must be set to pdFALSE before it is used.
+BaseType_t xHigherPriorityTaskWoken = pdFALSE;
+uint32_t ulVarToSend, ulValReceived;
+
+	// Write the value 10 to the queue using xQueueOverwriteFromISR().
+	ulVarToSend = 10;
+	xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
+
+	// The queue is full, but calling xQueueOverwriteFromISR() again will still
+	// pass because the value held in the queue will be overwritten with the
+	// new value.
+	ulVarToSend = 100;
+	xQueueOverwriteFromISR( xQueue, &ulVarToSend, &xHigherPriorityTaskWoken );
+
+	// Reading from the queue will now return 100.
+
+	// ...
+
+	if( xHigherPrioritytaskWoken == pdTRUE )
+	{
+		// Writing to the queue caused a task to unblock and the unblocked task
+		// has a priority higher than or equal to the priority of the currently
+		// executing task (the task this interrupt interrupted).  Perform a context
+		// switch so this interrupt returns directly to the unblocked task.
+		portYIELD_FROM_ISR(); // or portEND_SWITCHING_ISR() depending on the port.
+	}
+}
+ 
+ * \defgroup xQueueOverwriteFromISR xQueueOverwriteFromISR + * \ingroup QueueManagement + */ +#define xQueueOverwriteFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueOVERWRITE ) + +/** + * queue. h + *
+ BaseType_t xQueueSendFromISR(
+									 QueueHandle_t xQueue,
+									 const void *pvItemToQueue,
+									 BaseType_t *pxHigherPriorityTaskWoken
+								);
+ 
+ * + * This is a macro that calls xQueueGenericSendFromISR(). It is included + * for backward compatibility with versions of FreeRTOS.org that did not + * include the xQueueSendToBackFromISR() and xQueueSendToFrontFromISR() + * macros. + * + * Post an item to the back of a queue. It is safe to use this function from + * within an interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueSendFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueSendFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPriorityTaskWoken;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWoken = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post the byte.
+		xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.
+	if( xHigherPriorityTaskWoken )
+	{
+		// Actual macro used here is port specific.
+		portYIELD_FROM_ISR ();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +#define xQueueSendFromISR( xQueue, pvItemToQueue, pxHigherPriorityTaskWoken ) xQueueGenericSendFromISR( ( xQueue ), ( pvItemToQueue ), ( pxHigherPriorityTaskWoken ), queueSEND_TO_BACK ) + +/** + * queue. h + *
+ BaseType_t xQueueGenericSendFromISR(
+										   QueueHandle_t		xQueue,
+										   const	void	*pvItemToQueue,
+										   BaseType_t	*pxHigherPriorityTaskWoken,
+										   BaseType_t	xCopyPosition
+									   );
+ 
+ * + * It is preferred that the macros xQueueSendFromISR(), + * xQueueSendToFrontFromISR() and xQueueSendToBackFromISR() be used in place + * of calling this function directly. xQueueGiveFromISR() is an + * equivalent for use by semaphores that don't actually copy any data. + * + * Post an item on a queue. It is safe to use this function from within an + * interrupt service routine. + * + * Items are queued by copy not reference so it is preferable to only + * queue small items, especially when called from an ISR. In most cases + * it would be preferable to store a pointer to the item being queued. + * + * @param xQueue The handle to the queue on which the item is to be posted. + * + * @param pvItemToQueue A pointer to the item that is to be placed on the + * queue. The size of the items the queue will hold was defined when the + * queue was created, so this many bytes will be copied from pvItemToQueue + * into the queue storage area. + * + * @param pxHigherPriorityTaskWoken xQueueGenericSendFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending to the queue caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xQueueGenericSendFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @param xCopyPosition Can take the value queueSEND_TO_BACK to place the + * item at the back of the queue, or queueSEND_TO_FRONT to place the item + * at the front of the queue (for high priority messages). + * + * @return pdTRUE if the data was successfully sent to the queue, otherwise + * errQUEUE_FULL. + * + * Example usage for buffered IO (where the ISR can obtain more than one value + * per call): +
+ void vBufferISR( void )
+ {
+ char cIn;
+ BaseType_t xHigherPriorityTaskWokenByPost;
+
+	// We have not woken a task at the start of the ISR.
+	xHigherPriorityTaskWokenByPost = pdFALSE;
+
+	// Loop until the buffer is empty.
+	do
+	{
+		// Obtain a byte from the buffer.
+		cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );
+
+		// Post each byte.
+		xQueueGenericSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWokenByPost, queueSEND_TO_BACK );
+
+	} while( portINPUT_BYTE( BUFFER_COUNT ) );
+
+	// Now the buffer is empty we can switch context if necessary.  Note that the
+	// name of the yield function required is port specific.
+	if( xHigherPriorityTaskWokenByPost )
+	{
+		taskYIELD_YIELD_FROM_ISR();
+	}
+ }
+ 
+ * + * \defgroup xQueueSendFromISR xQueueSendFromISR + * \ingroup QueueManagement + */ +BaseType_t xQueueGenericSendFromISR(QueueHandle_t xQueue, const void *const pvItemToQueue, BaseType_t *const pxHigherPriorityTaskWoken, const BaseType_t xCopyPosition) PRIVILEGED_FUNCTION; +BaseType_t xQueueGiveFromISR(QueueHandle_t xQueue, BaseType_t *const pxHigherPriorityTaskWoken) PRIVILEGED_FUNCTION; + +/** + * queue. h + *
+ BaseType_t xQueueReceiveFromISR(
+									   QueueHandle_t	xQueue,
+									   void	*pvBuffer,
+									   BaseType_t *pxTaskWoken
+								   );
+ * 
+ * + * Receive an item from a queue. It is safe to use this function from within an + * interrupt service routine. + * + * @param xQueue The handle to the queue from which the item is to be + * received. + * + * @param pvBuffer Pointer to the buffer into which the received item will + * be copied. + * + * @param pxTaskWoken A task may be blocked waiting for space to become + * available on the queue. If xQueueReceiveFromISR causes such a task to + * unblock *pxTaskWoken will get set to pdTRUE, otherwise *pxTaskWoken will + * remain unchanged. + * + * @return pdTRUE if an item was successfully received from the queue, + * otherwise pdFALSE. + * + * Example usage: +
+
+ QueueHandle_t xQueue;
+
+ // Function to create a queue and post some values.
+ void vAFunction( void *pvParameters )
+ {
+ char cValueToPost;
+ const TickType_t xTicksToWait = ( TickType_t )0xff;
+
+	// Create a queue capable of containing 10 characters.
+	xQueue = xQueueCreate( 10, sizeof( char ) );
+	if( xQueue == 0 )
+	{
+		// Failed to create the queue.
+	}
+
+	// ...
+
+	// Post some characters that will be used within an ISR.  If the queue
+	// is full then this task will block for xTicksToWait ticks.
+	cValueToPost = 'a';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
+	cValueToPost = 'b';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
+
+	// ... keep posting characters ... this task may block when the queue
+	// becomes full.
+
+	cValueToPost = 'c';
+	xQueueSend( xQueue, ( void * ) &cValueToPost, xTicksToWait );
+ }
+
+ // ISR that outputs all the characters received on the queue.
+ void vISR_Routine( void )
+ {
+ BaseType_t xTaskWokenByReceive = pdFALSE;
+ char cRxedChar;
+
+	while( xQueueReceiveFromISR( xQueue, ( void * ) &cRxedChar, &xTaskWokenByReceive) )
+	{
+		// A character was received.  Output the character now.
+		vOutputCharacter( cRxedChar );
+
+		// If removing the character from the queue woke the task that was
+		// posting onto the queue cTaskWokenByReceive will have been set to
+		// pdTRUE.  No matter how many times this loop iterates only one
+		// task will be woken.
+	}
+
+	if( cTaskWokenByPost != ( char ) pdFALSE;
+	{
+		taskYIELD ();
+	}
+ }
+ 
+ * \defgroup xQueueReceiveFromISR xQueueReceiveFromISR + * \ingroup QueueManagement + */ +BaseType_t xQueueReceiveFromISR(QueueHandle_t xQueue, void *const pvBuffer, BaseType_t *const pxHigherPriorityTaskWoken) PRIVILEGED_FUNCTION; + +/* + * Utilities to query queues that are safe to use from an ISR. These utilities + * should be used only from witin an ISR, or within a critical section. + */ +BaseType_t xQueueIsQueueEmptyFromISR(const QueueHandle_t xQueue) PRIVILEGED_FUNCTION; +BaseType_t xQueueIsQueueFullFromISR(const QueueHandle_t xQueue) PRIVILEGED_FUNCTION; +UBaseType_t uxQueueMessagesWaitingFromISR(const QueueHandle_t xQueue) PRIVILEGED_FUNCTION; + +/* + * The functions defined above are for passing data to and from tasks. The + * functions below are the equivalents for passing data to and from + * co-routines. + * + * These functions are called from the co-routine macro implementation and + * should not be called directly from application code. Instead use the macro + * wrappers defined within croutine.h. + */ +BaseType_t xQueueCRSendFromISR(QueueHandle_t xQueue, const void *pvItemToQueue, BaseType_t xCoRoutinePreviouslyWoken); +BaseType_t xQueueCRReceiveFromISR(QueueHandle_t xQueue, void *pvBuffer, BaseType_t *pxTaskWoken); +BaseType_t xQueueCRSend(QueueHandle_t xQueue, const void *pvItemToQueue, TickType_t xTicksToWait); +BaseType_t xQueueCRReceive(QueueHandle_t xQueue, void *pvBuffer, TickType_t xTicksToWait); + +/* + * For internal use only. Use xSemaphoreCreateMutex(), + * xSemaphoreCreateCounting() or xSemaphoreGetMutexHolder() instead of calling + * these functions directly. + */ +QueueHandle_t xQueueCreateMutex(const uint8_t ucQueueType) PRIVILEGED_FUNCTION; +QueueHandle_t xQueueCreateMutexStatic(const uint8_t ucQueueType, StaticQueue_t *pxStaticQueue) PRIVILEGED_FUNCTION; +QueueHandle_t xQueueCreateCountingSemaphore(const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount) PRIVILEGED_FUNCTION; +QueueHandle_t xQueueCreateCountingSemaphoreStatic(const UBaseType_t uxMaxCount, const UBaseType_t uxInitialCount, StaticQueue_t *pxStaticQueue) PRIVILEGED_FUNCTION; +void *xQueueGetMutexHolder(QueueHandle_t xSemaphore) PRIVILEGED_FUNCTION; + +/* + * For internal use only. Use xSemaphoreTakeMutexRecursive() or + * xSemaphoreGiveMutexRecursive() instead of calling these functions directly. + */ +BaseType_t xQueueTakeMutexRecursive(QueueHandle_t xMutex, TickType_t xTicksToWait) PRIVILEGED_FUNCTION; +BaseType_t xQueueGiveMutexRecursive(QueueHandle_t pxMutex) PRIVILEGED_FUNCTION; + +/* + * Reset a queue back to its original empty state. The return value is now + * obsolete and is always set to pdPASS. + */ +#define xQueueReset( xQueue ) xQueueGenericReset( xQueue, pdFALSE ) + +/* + * The registry is provided as a means for kernel aware debuggers to + * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add + * a queue, semaphore or mutex handle to the registry if you want the handle + * to be available to a kernel aware debugger. If you are not using a kernel + * aware debugger then this function can be ignored. + * + * configQUEUE_REGISTRY_SIZE defines the maximum number of handles the + * registry can hold. configQUEUE_REGISTRY_SIZE must be greater than 0 + * within FreeRTOSConfig.h for the registry to be available. Its value + * does not effect the number of queues, semaphores and mutexes that can be + * created - just the number that the registry can hold. + * + * @param xQueue The handle of the queue being added to the registry. This + * is the handle returned by a call to xQueueCreate(). Semaphore and mutex + * handles can also be passed in here. + * + * @param pcName The name to be associated with the handle. This is the + * name that the kernel aware debugger will display. The queue registry only + * stores a pointer to the string - so the string must be persistent (global or + * preferably in ROM/Flash), not on the stack. + */ +#if( configQUEUE_REGISTRY_SIZE > 0 ) +void vQueueAddToRegistry(QueueHandle_t xQueue, const char *pcName) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#endif + +/* + * The registry is provided as a means for kernel aware debuggers to + * locate queues, semaphores and mutexes. Call vQueueAddToRegistry() add + * a queue, semaphore or mutex handle to the registry if you want the handle + * to be available to a kernel aware debugger, and vQueueUnregisterQueue() to + * remove the queue, semaphore or mutex from the register. If you are not using + * a kernel aware debugger then this function can be ignored. + * + * @param xQueue The handle of the queue being removed from the registry. + */ +#if( configQUEUE_REGISTRY_SIZE > 0 ) +void vQueueUnregisterQueue(QueueHandle_t xQueue) PRIVILEGED_FUNCTION; +#endif + +/* + * The queue registry is provided as a means for kernel aware debuggers to + * locate queues, semaphores and mutexes. Call pcQueueGetName() to look + * up and return the name of a queue in the queue registry from the queue's + * handle. + * + * @param xQueue The handle of the queue the name of which will be returned. + * @return If the queue is in the registry then a pointer to the name of the + * queue is returned. If the queue is not in the registry then NULL is + * returned. + */ +#if( configQUEUE_REGISTRY_SIZE > 0 ) +const char *pcQueueGetName(QueueHandle_t xQueue) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#endif + +/* + * Generic version of the function used to creaet a queue using dynamic memory + * allocation. This is called by other functions and macros that create other + * RTOS objects that use the queue structure as their base. + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +QueueHandle_t xQueueGenericCreate(const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, const uint8_t ucQueueType) PRIVILEGED_FUNCTION; +#endif + +/* + * Generic version of the function used to creaet a queue using dynamic memory + * allocation. This is called by other functions and macros that create other + * RTOS objects that use the queue structure as their base. + */ +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) +QueueHandle_t xQueueGenericCreateStatic(const UBaseType_t uxQueueLength, const UBaseType_t uxItemSize, uint8_t *pucQueueStorage, StaticQueue_t *pxStaticQueue, const uint8_t ucQueueType) PRIVILEGED_FUNCTION; +#endif + +/* + * Queue sets provide a mechanism to allow a task to block (pend) on a read + * operation from multiple queues or semaphores simultaneously. + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * A queue set must be explicitly created using a call to xQueueCreateSet() + * before it can be used. Once created, standard FreeRTOS queues and semaphores + * can be added to the set using calls to xQueueAddToSet(). + * xQueueSelectFromSet() is then used to determine which, if any, of the queues + * or semaphores contained in the set is in a state where a queue read or + * semaphore take operation would be successful. + * + * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html + * for reasons why queue sets are very rarely needed in practice as there are + * simpler methods of blocking on multiple objects. + * + * Note 2: Blocking on a queue set that contains a mutex will not cause the + * mutex holder to inherit the priority of the blocked task. + * + * Note 3: An additional 4 bytes of RAM is required for each space in a every + * queue added to a queue set. Therefore counting semaphores that have a high + * maximum count value should not be added to a queue set. + * + * Note 4: A receive (in the case of a queue) or take (in the case of a + * semaphore) operation must not be performed on a member of a queue set unless + * a call to xQueueSelectFromSet() has first returned a handle to that set member. + * + * @param uxEventQueueLength Queue sets store events that occur on + * the queues and semaphores contained in the set. uxEventQueueLength specifies + * the maximum number of events that can be queued at once. To be absolutely + * certain that events are not lost uxEventQueueLength should be set to the + * total sum of the length of the queues added to the set, where binary + * semaphores and mutexes have a length of 1, and counting semaphores have a + * length set by their maximum count value. Examples: + * + If a queue set is to hold a queue of length 5, another queue of length 12, + * and a binary semaphore, then uxEventQueueLength should be set to + * (5 + 12 + 1), or 18. + * + If a queue set is to hold three binary semaphores then uxEventQueueLength + * should be set to (1 + 1 + 1 ), or 3. + * + If a queue set is to hold a counting semaphore that has a maximum count of + * 5, and a counting semaphore that has a maximum count of 3, then + * uxEventQueueLength should be set to (5 + 3), or 8. + * + * @return If the queue set is created successfully then a handle to the created + * queue set is returned. Otherwise NULL is returned. + */ +QueueSetHandle_t xQueueCreateSet(const UBaseType_t uxEventQueueLength) PRIVILEGED_FUNCTION; + +/* + * Adds a queue or semaphore to a queue set that was previously created by a + * call to xQueueCreateSet(). + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * Note 1: A receive (in the case of a queue) or take (in the case of a + * semaphore) operation must not be performed on a member of a queue set unless + * a call to xQueueSelectFromSet() has first returned a handle to that set member. + * + * @param xQueueOrSemaphore The handle of the queue or semaphore being added to + * the queue set (cast to an QueueSetMemberHandle_t type). + * + * @param xQueueSet The handle of the queue set to which the queue or semaphore + * is being added. + * + * @return If the queue or semaphore was successfully added to the queue set + * then pdPASS is returned. If the queue could not be successfully added to the + * queue set because it is already a member of a different queue set then pdFAIL + * is returned. + */ +BaseType_t xQueueAddToSet(QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet) PRIVILEGED_FUNCTION; + +/* + * Removes a queue or semaphore from a queue set. A queue or semaphore can only + * be removed from a set if the queue or semaphore is empty. + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * @param xQueueOrSemaphore The handle of the queue or semaphore being removed + * from the queue set (cast to an QueueSetMemberHandle_t type). + * + * @param xQueueSet The handle of the queue set in which the queue or semaphore + * is included. + * + * @return If the queue or semaphore was successfully removed from the queue set + * then pdPASS is returned. If the queue was not in the queue set, or the + * queue (or semaphore) was not empty, then pdFAIL is returned. + */ +BaseType_t xQueueRemoveFromSet(QueueSetMemberHandle_t xQueueOrSemaphore, QueueSetHandle_t xQueueSet) PRIVILEGED_FUNCTION; + +/* + * xQueueSelectFromSet() selects from the members of a queue set a queue or + * semaphore that either contains data (in the case of a queue) or is available + * to take (in the case of a semaphore). xQueueSelectFromSet() effectively + * allows a task to block (pend) on a read operation on all the queues and + * semaphores in a queue set simultaneously. + * + * See FreeRTOS/Source/Demo/Common/Minimal/QueueSet.c for an example using this + * function. + * + * Note 1: See the documentation on http://wwwFreeRTOS.org/RTOS-queue-sets.html + * for reasons why queue sets are very rarely needed in practice as there are + * simpler methods of blocking on multiple objects. + * + * Note 2: Blocking on a queue set that contains a mutex will not cause the + * mutex holder to inherit the priority of the blocked task. + * + * Note 3: A receive (in the case of a queue) or take (in the case of a + * semaphore) operation must not be performed on a member of a queue set unless + * a call to xQueueSelectFromSet() has first returned a handle to that set member. + * + * @param xQueueSet The queue set on which the task will (potentially) block. + * + * @param xTicksToWait The maximum time, in ticks, that the calling task will + * remain in the Blocked state (with other tasks executing) to wait for a member + * of the queue set to be ready for a successful queue read or semaphore take + * operation. + * + * @return xQueueSelectFromSet() will return the handle of a queue (cast to + * a QueueSetMemberHandle_t type) contained in the queue set that contains data, + * or the handle of a semaphore (cast to a QueueSetMemberHandle_t type) contained + * in the queue set that is available, or NULL if no such queue or semaphore + * exists before before the specified block time expires. + */ +QueueSetMemberHandle_t xQueueSelectFromSet(QueueSetHandle_t xQueueSet, const TickType_t xTicksToWait) PRIVILEGED_FUNCTION; + +/* + * A version of xQueueSelectFromSet() that can be used from an ISR. + */ +QueueSetMemberHandle_t xQueueSelectFromSetFromISR(QueueSetHandle_t xQueueSet) PRIVILEGED_FUNCTION; + +/* Not public API functions. */ +void vQueueWaitForMessageRestricted(QueueHandle_t xQueue, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely) PRIVILEGED_FUNCTION; +BaseType_t xQueueGenericReset(QueueHandle_t xQueue, BaseType_t xNewQueue) PRIVILEGED_FUNCTION; +void vQueueSetQueueNumber(QueueHandle_t xQueue, UBaseType_t uxQueueNumber) PRIVILEGED_FUNCTION; +UBaseType_t uxQueueGetQueueNumber(QueueHandle_t xQueue) PRIVILEGED_FUNCTION; +uint8_t ucQueueGetQueueType(QueueHandle_t xQueue) PRIVILEGED_FUNCTION; + +UBaseType_t uxQueueMessagesSet(const QueueHandle_t xQueue, int cnt); + +#ifdef __cplusplus +} +#endif + +#endif /* QUEUE_H */ + diff --git a/include_lib/system/os/FreeRTOS/semphr.h b/include_lib/system/os/FreeRTOS/semphr.h new file mode 100644 index 0000000..4ae16cf --- /dev/null +++ b/include_lib/system/os/FreeRTOS/semphr.h @@ -0,0 +1,1175 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef SEMAPHORE_H +#define SEMAPHORE_H + +#ifndef INC_FREERTOS_H +#error "include FreeRTOS.h" must appear in source files before "include semphr.h" +#endif + +#include "queue.h" + +typedef QueueHandle_t SemaphoreHandle_t; + +#define semBINARY_SEMAPHORE_QUEUE_LENGTH ( ( uint8_t ) 1U ) +#define semSEMAPHORE_QUEUE_ITEM_LENGTH ( ( uint8_t ) 0U ) +#define semGIVE_BLOCK_TIME ( ( TickType_t ) 0U ) + + +/** + * semphr. h + *
vSemaphoreCreateBinary( SemaphoreHandle_t xSemaphore )
+ * + * In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a binary semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * + * This old vSemaphoreCreateBinary() macro is now deprecated in favour of the + * xSemaphoreCreateBinary() function. Note that binary semaphores created using + * the vSemaphoreCreateBinary() macro are created in a state such that the + * first call to 'take' the semaphore would pass, whereas binary semaphores + * created using xSemaphoreCreateBinary() are created in a state such that the + * the semaphore must first be 'given' before it can be 'taken'. + * + * Macro that implements a semaphore by using the existing queue mechanism. + * The queue length is 1 as this is a binary semaphore. The data size is 0 + * as we don't want to actually store any data - we just want to know if the + * queue is empty or full. + * + * This type of semaphore can be used for pure synchronisation between tasks or + * between an interrupt and a task. The semaphore need not be given back once + * obtained, so one task/interrupt can continuously 'give' the semaphore while + * another continuously 'takes' the semaphore. For this reason this type of + * semaphore does not use a priority inheritance mechanism. For an alternative + * that does use priority inheritance see xSemaphoreCreateMutex(). + * + * @param xSemaphore Handle to the created semaphore. Should be of type SemaphoreHandle_t. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to vSemaphoreCreateBinary ().
+    // This is a macro so pass the variable in directly.
+    vSemaphoreCreateBinary( xSemaphore );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup vSemaphoreCreateBinary vSemaphoreCreateBinary + * \ingroup Semaphores + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +#define vSemaphoreCreateBinary( xSemaphore ) \ + { \ + ( xSemaphore ) = xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ); \ + if( ( xSemaphore ) != NULL ) \ + { \ + ( void ) xSemaphoreGive( ( xSemaphore ) ); \ + } \ + } +#endif + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateBinary( void )
+ * + * Creates a new binary semaphore instance, and returns a handle by which the + * new semaphore can be referenced. + * + * In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a binary semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * + * Internally, within the FreeRTOS implementation, binary semaphores use a block + * of memory, in which the semaphore structure is stored. If a binary semaphore + * is created using xSemaphoreCreateBinary() then the required memory is + * automatically dynamically allocated inside the xSemaphoreCreateBinary() + * function. (see http://www.freertos.org/a00111.html). If a binary semaphore + * is created using xSemaphoreCreateBinaryStatic() then the application writer + * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a + * binary semaphore to be created without using any dynamic memory allocation. + * + * The old vSemaphoreCreateBinary() macro is now deprecated in favour of this + * xSemaphoreCreateBinary() function. Note that binary semaphores created using + * the vSemaphoreCreateBinary() macro are created in a state such that the + * first call to 'take' the semaphore would pass, whereas binary semaphores + * created using xSemaphoreCreateBinary() are created in a state such that the + * the semaphore must first be 'given' before it can be 'taken'. + * + * This type of semaphore can be used for pure synchronisation between tasks or + * between an interrupt and a task. The semaphore need not be given back once + * obtained, so one task/interrupt can continuously 'give' the semaphore while + * another continuously 'takes' the semaphore. For this reason this type of + * semaphore does not use a priority inheritance mechanism. For an alternative + * that does use priority inheritance see xSemaphoreCreateMutex(). + * + * @return Handle to the created semaphore, or NULL if the memory required to + * hold the semaphore's data structures could not be allocated. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateBinary().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateBinary();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup xSemaphoreCreateBinary xSemaphoreCreateBinary + * \ingroup Semaphores + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +#define xSemaphoreCreateBinary() xQueueGenericCreate( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, queueQUEUE_TYPE_BINARY_SEMAPHORE ) +#endif + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateBinaryStatic( StaticSemaphore_t *pxSemaphoreBuffer )
+ * + * Creates a new binary semaphore instance, and returns a handle by which the + * new semaphore can be referenced. + * + * NOTE: In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a binary semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * + * Internally, within the FreeRTOS implementation, binary semaphores use a block + * of memory, in which the semaphore structure is stored. If a binary semaphore + * is created using xSemaphoreCreateBinary() then the required memory is + * automatically dynamically allocated inside the xSemaphoreCreateBinary() + * function. (see http://www.freertos.org/a00111.html). If a binary semaphore + * is created using xSemaphoreCreateBinaryStatic() then the application writer + * must provide the memory. xSemaphoreCreateBinaryStatic() therefore allows a + * binary semaphore to be created without using any dynamic memory allocation. + * + * This type of semaphore can be used for pure synchronisation between tasks or + * between an interrupt and a task. The semaphore need not be given back once + * obtained, so one task/interrupt can continuously 'give' the semaphore while + * another continuously 'takes' the semaphore. For this reason this type of + * semaphore does not use a priority inheritance mechanism. For an alternative + * that does use priority inheritance see xSemaphoreCreateMutex(). + * + * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t, + * which will then be used to hold the semaphore's data structure, removing the + * need for the memory to be allocated dynamically. + * + * @return If the semaphore is created then a handle to the created semaphore is + * returned. If pxSemaphoreBuffer is NULL then NULL is returned. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+ StaticSemaphore_t xSemaphoreBuffer;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateBinary().
+    // The semaphore's data structures will be placed in the xSemaphoreBuffer
+    // variable, the address of which is passed into the function.  The
+    // function's parameter is not NULL, so the function will not attempt any
+    // dynamic memory allocation, and therefore the function will not return
+    // return NULL.
+    xSemaphore = xSemaphoreCreateBinary( &xSemaphoreBuffer );
+
+    // Rest of task code goes here.
+ }
+ 
+ * \defgroup xSemaphoreCreateBinaryStatic xSemaphoreCreateBinaryStatic + * \ingroup Semaphores + */ +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) +#define xSemaphoreCreateBinaryStatic( pxStaticSemaphore ) xQueueGenericCreateStatic( ( UBaseType_t ) 1, semSEMAPHORE_QUEUE_ITEM_LENGTH, NULL, pxStaticSemaphore, queueQUEUE_TYPE_BINARY_SEMAPHORE ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ + +/** + * semphr. h + *
xSemaphoreTake(
+ *                   SemaphoreHandle_t xSemaphore,
+ *                   TickType_t xBlockTime
+ *               )
+ * + * Macro to obtain a semaphore. The semaphore must have previously been + * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting(). + * + * @param xSemaphore A handle to the semaphore being taken - obtained when + * the semaphore was created. + * + * @param xBlockTime The time in ticks to wait for the semaphore to become + * available. The macro portTICK_PERIOD_MS can be used to convert this to a + * real time. A block time of zero can be used to poll the semaphore. A block + * time of portMAX_DELAY can be used to block indefinitely (provided + * INCLUDE_vTaskSuspend is set to 1 in FreeRTOSConfig.h). + * + * @return pdTRUE if the semaphore was obtained. pdFALSE + * if xBlockTime expired without the semaphore becoming available. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ // A task that creates a semaphore.
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    xSemaphore = xSemaphoreCreateBinary();
+ }
+
+ // A task that uses the semaphore.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xSemaphore != NULL )
+    {
+        // See if we can obtain the semaphore.  If the semaphore is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the semaphore and can now access the
+            // shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource.  Release the
+            // semaphore.
+            xSemaphoreGive( xSemaphore );
+        }
+        else
+        {
+            // We could not obtain the semaphore and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreTake xSemaphoreTake + * \ingroup Semaphores + */ +#define xSemaphoreTake( xSemaphore, xBlockTime ) xQueueGenericReceive( ( QueueHandle_t ) ( xSemaphore ), NULL, ( xBlockTime ), pdFALSE ) + +/** + * semphr. h + * xSemaphoreTakeRecursive( + * SemaphoreHandle_t xMutex, + * TickType_t xBlockTime + * ) + * + * Macro to recursively obtain, or 'take', a mutex type semaphore. + * The mutex must have previously been created using a call to + * xSemaphoreCreateRecursiveMutex(); + * + * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this + * macro to be available. + * + * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * @param xMutex A handle to the mutex being obtained. This is the + * handle returned by xSemaphoreCreateRecursiveMutex(); + * + * @param xBlockTime The time in ticks to wait for the semaphore to become + * available. The macro portTICK_PERIOD_MS can be used to convert this to a + * real time. A block time of zero can be used to poll the semaphore. If + * the task already owns the semaphore then xSemaphoreTakeRecursive() will + * return immediately no matter what the value of xBlockTime. + * + * @return pdTRUE if the semaphore was obtained. pdFALSE if xBlockTime + * expired without the semaphore becoming available. + * + * Example usage: +
+ SemaphoreHandle_t xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTakeRecursive( xSemaphore, ( TickType_t ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, but instead buried in a more complex
+			// call structure.  This is just for illustrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreTakeRecursive xSemaphoreTakeRecursive + * \ingroup Semaphores + */ +#if( configUSE_RECURSIVE_MUTEXES == 1 ) +#define xSemaphoreTakeRecursive( xMutex, xBlockTime ) xQueueTakeMutexRecursive( ( xMutex ), ( xBlockTime ) ) +#endif + +/** + * semphr. h + *
xSemaphoreGive( SemaphoreHandle_t xSemaphore )
+ * + * Macro to release a semaphore. The semaphore must have previously been + * created with a call to xSemaphoreCreateBinary(), xSemaphoreCreateMutex() or + * xSemaphoreCreateCounting(). and obtained using sSemaphoreTake(). + * + * This macro must not be used from an ISR. See xSemaphoreGiveFromISR () for + * an alternative which can be used from an ISR. + * + * This macro must also not be used on semaphores created using + * xSemaphoreCreateRecursiveMutex(). + * + * @param xSemaphore A handle to the semaphore being released. This is the + * handle returned when the semaphore was created. + * + * @return pdTRUE if the semaphore was released. pdFALSE if an error occurred. + * Semaphores are implemented using queues. An error can occur if there is + * no space on the queue to post a message - indicating that the + * semaphore was not first obtained correctly. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ void vATask( void * pvParameters )
+ {
+    // Create the semaphore to guard a shared resource.
+    xSemaphore = vSemaphoreCreateBinary();
+
+    if( xSemaphore != NULL )
+    {
+        if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+        {
+            // We would expect this call to fail because we cannot give
+            // a semaphore without first "taking" it!
+        }
+
+        // Obtain the semaphore - don't block if the semaphore is not
+        // immediately available.
+        if( xSemaphoreTake( xSemaphore, ( TickType_t ) 0 ) )
+        {
+            // We now have the semaphore and can access the shared resource.
+
+            // ...
+
+            // We have finished accessing the shared resource so can free the
+            // semaphore.
+            if( xSemaphoreGive( xSemaphore ) != pdTRUE )
+            {
+                // We would not expect this call to fail because we must have
+                // obtained the semaphore to get here.
+            }
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreGive xSemaphoreGive + * \ingroup Semaphores + */ +#define xSemaphoreGive( xSemaphore ) xQueueGenericSend( ( QueueHandle_t ) ( xSemaphore ), NULL, semGIVE_BLOCK_TIME, queueSEND_TO_BACK ) + +/** + * semphr. h + *
xSemaphoreGiveRecursive( SemaphoreHandle_t xMutex )
+ * + * Macro to recursively release, or 'give', a mutex type semaphore. + * The mutex must have previously been created using a call to + * xSemaphoreCreateRecursiveMutex(); + * + * configUSE_RECURSIVE_MUTEXES must be set to 1 in FreeRTOSConfig.h for this + * macro to be available. + * + * This macro must not be used on mutexes created using xSemaphoreCreateMutex(). + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * @param xMutex A handle to the mutex being released, or 'given'. This is the + * handle returned by xSemaphoreCreateMutex(); + * + * @return pdTRUE if the semaphore was given. + * + * Example usage: +
+ SemaphoreHandle_t xMutex = NULL;
+
+ // A task that creates a mutex.
+ void vATask( void * pvParameters )
+ {
+    // Create the mutex to guard a shared resource.
+    xMutex = xSemaphoreCreateRecursiveMutex();
+ }
+
+ // A task that uses the mutex.
+ void vAnotherTask( void * pvParameters )
+ {
+    // ... Do other things.
+
+    if( xMutex != NULL )
+    {
+        // See if we can obtain the mutex.  If the mutex is not available
+        // wait 10 ticks to see if it becomes free.
+        if( xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 ) == pdTRUE )
+        {
+            // We were able to obtain the mutex and can now access the
+            // shared resource.
+
+            // ...
+            // For some reason due to the nature of the code further calls to
+			// xSemaphoreTakeRecursive() are made on the same mutex.  In real
+			// code these would not be just sequential calls as this would make
+			// no sense.  Instead the calls are likely to be buried inside
+			// a more complex call structure.
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+            xSemaphoreTakeRecursive( xMutex, ( TickType_t ) 10 );
+
+            // The mutex has now been 'taken' three times, so will not be
+			// available to another task until it has also been given back
+			// three times.  Again it is unlikely that real code would have
+			// these calls sequentially, it would be more likely that the calls
+			// to xSemaphoreGiveRecursive() would be called as a call stack
+			// unwound.  This is just for demonstrative purposes.
+            xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+			xSemaphoreGiveRecursive( xMutex );
+
+			// Now the mutex can be taken by other tasks.
+        }
+        else
+        {
+            // We could not obtain the mutex and can therefore not access
+            // the shared resource safely.
+        }
+    }
+ }
+ 
+ * \defgroup xSemaphoreGiveRecursive xSemaphoreGiveRecursive + * \ingroup Semaphores + */ +#if( configUSE_RECURSIVE_MUTEXES == 1 ) +#define xSemaphoreGiveRecursive( xMutex ) xQueueGiveMutexRecursive( ( xMutex ) ) +#endif + +/** + * semphr. h + *
+ xSemaphoreGiveFromISR(
+                          SemaphoreHandle_t xSemaphore,
+                          BaseType_t *pxHigherPriorityTaskWoken
+                      )
+ * + * Macro to release a semaphore. The semaphore must have previously been + * created with a call to xSemaphoreCreateBinary() or xSemaphoreCreateCounting(). + * + * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) + * must not be used with this macro. + * + * This macro can be used from an ISR. + * + * @param xSemaphore A handle to the semaphore being released. This is the + * handle returned when the semaphore was created. + * + * @param pxHigherPriorityTaskWoken xSemaphoreGiveFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if giving the semaphore caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xSemaphoreGiveFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the semaphore was successfully given, otherwise errQUEUE_FULL. + * + * Example usage: +
+ \#define LONG_TIME 0xffff
+ \#define TICKS_TO_WAIT	10
+ SemaphoreHandle_t xSemaphore = NULL;
+
+ // Repetitive task.
+ void vATask( void * pvParameters )
+ {
+    for( ;; )
+    {
+        // We want this task to run every 10 ticks of a timer.  The semaphore
+        // was created before this task was started.
+
+        // Block waiting for the semaphore to become available.
+        if( xSemaphoreTake( xSemaphore, LONG_TIME ) == pdTRUE )
+        {
+            // It is time to execute.
+
+            // ...
+
+            // We have finished our task.  Return to the top of the loop where
+            // we will block on the semaphore until it is time to execute
+            // again.  Note when using the semaphore for synchronisation with an
+			// ISR in this manner there is no need to 'give' the semaphore back.
+        }
+    }
+ }
+
+ // Timer ISR
+ void vTimerISR( void * pvParameters )
+ {
+ static uint8_t ucLocalTickCount = 0;
+ static BaseType_t xHigherPriorityTaskWoken;
+
+    // A timer tick has occurred.
+
+    // ... Do other time functions.
+
+    // Is it time for vATask () to run?
+	xHigherPriorityTaskWoken = pdFALSE;
+    ucLocalTickCount++;
+    if( ucLocalTickCount >= TICKS_TO_WAIT )
+    {
+        // Unblock the task by releasing the semaphore.
+        xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken );
+
+        // Reset the count so we release the semaphore again in 10 ticks time.
+        ucLocalTickCount = 0;
+    }
+
+    if( xHigherPriorityTaskWoken != pdFALSE )
+    {
+        // We can force a context switch here.  Context switching from an
+        // ISR uses port specific syntax.  Check the demo task for your port
+        // to find the syntax required.
+    }
+ }
+ 
+ * \defgroup xSemaphoreGiveFromISR xSemaphoreGiveFromISR + * \ingroup Semaphores + */ +#define xSemaphoreGiveFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueGiveFromISR( ( QueueHandle_t ) ( xSemaphore ), ( pxHigherPriorityTaskWoken ) ) + +/** + * semphr. h + *
+ xSemaphoreTakeFromISR(
+                          SemaphoreHandle_t xSemaphore,
+                          BaseType_t *pxHigherPriorityTaskWoken
+                      )
+ * + * Macro to take a semaphore from an ISR. The semaphore must have + * previously been created with a call to xSemaphoreCreateBinary() or + * xSemaphoreCreateCounting(). + * + * Mutex type semaphores (those created using a call to xSemaphoreCreateMutex()) + * must not be used with this macro. + * + * This macro can be used from an ISR, however taking a semaphore from an ISR + * is not a common operation. It is likely to only be useful when taking a + * counting semaphore when an interrupt is obtaining an object from a resource + * pool (when the semaphore count indicates the number of resources available). + * + * @param xSemaphore A handle to the semaphore being taken. This is the + * handle returned when the semaphore was created. + * + * @param pxHigherPriorityTaskWoken xSemaphoreTakeFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if taking the semaphore caused a task + * to unblock, and the unblocked task has a priority higher than the currently + * running task. If xSemaphoreTakeFromISR() sets this value to pdTRUE then + * a context switch should be requested before the interrupt is exited. + * + * @return pdTRUE if the semaphore was successfully taken, otherwise + * pdFALSE + */ +#define xSemaphoreTakeFromISR( xSemaphore, pxHigherPriorityTaskWoken ) xQueueReceiveFromISR( ( QueueHandle_t ) ( xSemaphore ), NULL, ( pxHigherPriorityTaskWoken ) ) + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateMutex( void )
+ * + * Creates a new mutex type semaphore instance, and returns a handle by which + * the new mutex can be referenced. + * + * Internally, within the FreeRTOS implementation, mutex semaphores use a block + * of memory, in which the mutex structure is stored. If a mutex is created + * using xSemaphoreCreateMutex() then the required memory is automatically + * dynamically allocated inside the xSemaphoreCreateMutex() function. (see + * http://www.freertos.org/a00111.html). If a mutex is created using + * xSemaphoreCreateMutexStatic() then the application writer must provided the + * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created + * without using any dynamic memory allocation. + * + * Mutexes created using this function can be accessed using the xSemaphoreTake() + * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and + * xSemaphoreGiveRecursive() macros must not be used. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See xSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @return If the mutex was successfully created then a handle to the created + * semaphore is returned. If there was not enough heap to allocate the mutex + * data structures then NULL is returned. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup xSemaphoreCreateMutex xSemaphoreCreateMutex + * \ingroup Semaphores + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +#define xSemaphoreCreateMutex() xQueueCreateMutex( queueQUEUE_TYPE_MUTEX ) +#endif + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateMutexStatic( StaticSemaphore_t *pxMutexBuffer )
+ * + * Creates a new mutex type semaphore instance, and returns a handle by which + * the new mutex can be referenced. + * + * Internally, within the FreeRTOS implementation, mutex semaphores use a block + * of memory, in which the mutex structure is stored. If a mutex is created + * using xSemaphoreCreateMutex() then the required memory is automatically + * dynamically allocated inside the xSemaphoreCreateMutex() function. (see + * http://www.freertos.org/a00111.html). If a mutex is created using + * xSemaphoreCreateMutexStatic() then the application writer must provided the + * memory. xSemaphoreCreateMutexStatic() therefore allows a mutex to be created + * without using any dynamic memory allocation. + * + * Mutexes created using this function can be accessed using the xSemaphoreTake() + * and xSemaphoreGive() macros. The xSemaphoreTakeRecursive() and + * xSemaphoreGiveRecursive() macros must not be used. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See xSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t, + * which will be used to hold the mutex's data structure, removing the need for + * the memory to be allocated dynamically. + * + * @return If the mutex was successfully created then a handle to the created + * mutex is returned. If pxMutexBuffer was NULL then NULL is returned. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+ StaticSemaphore_t xMutexBuffer;
+
+ void vATask( void * pvParameters )
+ {
+    // A mutex cannot be used before it has been created.  xMutexBuffer is
+    // into xSemaphoreCreateMutexStatic() so no dynamic memory allocation is
+    // attempted.
+    xSemaphore = xSemaphoreCreateMutexStatic( &xMutexBuffer );
+
+    // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
+    // so there is no need to check it.
+ }
+ 
+ * \defgroup xSemaphoreCreateMutexStatic xSemaphoreCreateMutexStatic + * \ingroup Semaphores + */ +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) +#define xSemaphoreCreateMutexStatic( pxMutexBuffer ) xQueueCreateMutexStatic( queueQUEUE_TYPE_MUTEX, ( pxMutexBuffer ) ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ + + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateRecursiveMutex( void )
+ * + * Creates a new recursive mutex type semaphore instance, and returns a handle + * by which the new recursive mutex can be referenced. + * + * Internally, within the FreeRTOS implementation, recursive mutexs use a block + * of memory, in which the mutex structure is stored. If a recursive mutex is + * created using xSemaphoreCreateRecursiveMutex() then the required memory is + * automatically dynamically allocated inside the + * xSemaphoreCreateRecursiveMutex() function. (see + * http://www.freertos.org/a00111.html). If a recursive mutex is created using + * xSemaphoreCreateRecursiveMutexStatic() then the application writer must + * provide the memory that will get used by the mutex. + * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to + * be created without using any dynamic memory allocation. + * + * Mutexes created using this macro can be accessed using the + * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The + * xSemaphoreTake() and xSemaphoreGive() macros must not be used. + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See xSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @return xSemaphore Handle to the created mutex semaphore. Should be of type + * SemaphoreHandle_t. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+    // Semaphore cannot be used before a call to xSemaphoreCreateMutex().
+    // This is a macro so pass the variable in directly.
+    xSemaphore = xSemaphoreCreateRecursiveMutex();
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup xSemaphoreCreateRecursiveMutex xSemaphoreCreateRecursiveMutex + * \ingroup Semaphores + */ +#if( ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) +#define xSemaphoreCreateRecursiveMutex() xQueueCreateMutex( queueQUEUE_TYPE_RECURSIVE_MUTEX ) +#endif + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateRecursiveMutexStatic( StaticSemaphore_t *pxMutexBuffer )
+ * + * Creates a new recursive mutex type semaphore instance, and returns a handle + * by which the new recursive mutex can be referenced. + * + * Internally, within the FreeRTOS implementation, recursive mutexs use a block + * of memory, in which the mutex structure is stored. If a recursive mutex is + * created using xSemaphoreCreateRecursiveMutex() then the required memory is + * automatically dynamically allocated inside the + * xSemaphoreCreateRecursiveMutex() function. (see + * http://www.freertos.org/a00111.html). If a recursive mutex is created using + * xSemaphoreCreateRecursiveMutexStatic() then the application writer must + * provide the memory that will get used by the mutex. + * xSemaphoreCreateRecursiveMutexStatic() therefore allows a recursive mutex to + * be created without using any dynamic memory allocation. + * + * Mutexes created using this macro can be accessed using the + * xSemaphoreTakeRecursive() and xSemaphoreGiveRecursive() macros. The + * xSemaphoreTake() and xSemaphoreGive() macros must not be used. + * + * A mutex used recursively can be 'taken' repeatedly by the owner. The mutex + * doesn't become available again until the owner has called + * xSemaphoreGiveRecursive() for each successful 'take' request. For example, + * if a task successfully 'takes' the same mutex 5 times then the mutex will + * not be available to any other task until it has also 'given' the mutex back + * exactly five times. + * + * This type of semaphore uses a priority inheritance mechanism so a task + * 'taking' a semaphore MUST ALWAYS 'give' the semaphore back once the + * semaphore it is no longer required. + * + * Mutex type semaphores cannot be used from within interrupt service routines. + * + * See xSemaphoreCreateBinary() for an alternative implementation that can be + * used for pure synchronisation (where one task or interrupt always 'gives' the + * semaphore and another always 'takes' the semaphore) and from within interrupt + * service routines. + * + * @param pxMutexBuffer Must point to a variable of type StaticSemaphore_t, + * which will then be used to hold the recursive mutex's data structure, + * removing the need for the memory to be allocated dynamically. + * + * @return If the recursive mutex was successfully created then a handle to the + * created recursive mutex is returned. If pxMutexBuffer was NULL then NULL is + * returned. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+ StaticSemaphore_t xMutexBuffer;
+
+ void vATask( void * pvParameters )
+ {
+    // A recursive semaphore cannot be used before it is created.  Here a
+    // recursive mutex is created using xSemaphoreCreateRecursiveMutexStatic().
+    // The address of xMutexBuffer is passed into the function, and will hold
+    // the mutexes data structures - so no dynamic memory allocation will be
+    // attempted.
+    xSemaphore = xSemaphoreCreateRecursiveMutexStatic( &xMutexBuffer );
+
+    // As no dynamic memory allocation was performed, xSemaphore cannot be NULL,
+    // so there is no need to check it.
+ }
+ 
+ * \defgroup xSemaphoreCreateRecursiveMutexStatic xSemaphoreCreateRecursiveMutexStatic + * \ingroup Semaphores + */ +#if( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configUSE_RECURSIVE_MUTEXES == 1 ) ) +#define xSemaphoreCreateRecursiveMutexStatic( pxStaticSemaphore ) xQueueCreateMutexStatic( queueQUEUE_TYPE_RECURSIVE_MUTEX, pxStaticSemaphore ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateCounting( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount )
+ * + * Creates a new counting semaphore instance, and returns a handle by which the + * new counting semaphore can be referenced. + * + * In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a counting semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * + * Internally, within the FreeRTOS implementation, counting semaphores use a + * block of memory, in which the counting semaphore structure is stored. If a + * counting semaphore is created using xSemaphoreCreateCounting() then the + * required memory is automatically dynamically allocated inside the + * xSemaphoreCreateCounting() function. (see + * http://www.freertos.org/a00111.html). If a counting semaphore is created + * using xSemaphoreCreateCountingStatic() then the application writer can + * instead optionally provide the memory that will get used by the counting + * semaphore. xSemaphoreCreateCountingStatic() therefore allows a counting + * semaphore to be created without using any dynamic memory allocation. + * + * Counting semaphores are typically used for two things: + * + * 1) Counting events. + * + * In this usage scenario an event handler will 'give' a semaphore each time + * an event occurs (incrementing the semaphore count value), and a handler + * task will 'take' a semaphore each time it processes an event + * (decrementing the semaphore count value). The count value is therefore + * the difference between the number of events that have occurred and the + * number that have been processed. In this case it is desirable for the + * initial count value to be zero. + * + * 2) Resource management. + * + * In this usage scenario the count value indicates the number of resources + * available. To obtain control of a resource a task must first obtain a + * semaphore - decrementing the semaphore count value. When the count value + * reaches zero there are no free resources. When a task finishes with the + * resource it 'gives' the semaphore back - incrementing the semaphore count + * value. In this case it is desirable for the initial count value to be + * equal to the maximum count value, indicating that all resources are free. + * + * @param uxMaxCount The maximum count value that can be reached. When the + * semaphore reaches this value it can no longer be 'given'. + * + * @param uxInitialCount The count value assigned to the semaphore when it is + * created. + * + * @return Handle to the created semaphore. Null if the semaphore could not be + * created. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+
+ void vATask( void * pvParameters )
+ {
+ SemaphoreHandle_t xSemaphore = NULL;
+
+    // Semaphore cannot be used before a call to xSemaphoreCreateCounting().
+    // The max value to which the semaphore can count should be 10, and the
+    // initial value assigned to the count should be 0.
+    xSemaphore = xSemaphoreCreateCounting( 10, 0 );
+
+    if( xSemaphore != NULL )
+    {
+        // The semaphore was created successfully.
+        // The semaphore can now be used.
+    }
+ }
+ 
+ * \defgroup xSemaphoreCreateCounting xSemaphoreCreateCounting + * \ingroup Semaphores + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +#define xSemaphoreCreateCounting( uxMaxCount, uxInitialCount ) xQueueCreateCountingSemaphore( ( uxMaxCount ), ( uxInitialCount ) ) +#endif + +/** + * semphr. h + *
SemaphoreHandle_t xSemaphoreCreateCountingStatic( UBaseType_t uxMaxCount, UBaseType_t uxInitialCount, StaticSemaphore_t *pxSemaphoreBuffer )
+ * + * Creates a new counting semaphore instance, and returns a handle by which the + * new counting semaphore can be referenced. + * + * In many usage scenarios it is faster and more memory efficient to use a + * direct to task notification in place of a counting semaphore! + * http://www.freertos.org/RTOS-task-notifications.html + * + * Internally, within the FreeRTOS implementation, counting semaphores use a + * block of memory, in which the counting semaphore structure is stored. If a + * counting semaphore is created using xSemaphoreCreateCounting() then the + * required memory is automatically dynamically allocated inside the + * xSemaphoreCreateCounting() function. (see + * http://www.freertos.org/a00111.html). If a counting semaphore is created + * using xSemaphoreCreateCountingStatic() then the application writer must + * provide the memory. xSemaphoreCreateCountingStatic() therefore allows a + * counting semaphore to be created without using any dynamic memory allocation. + * + * Counting semaphores are typically used for two things: + * + * 1) Counting events. + * + * In this usage scenario an event handler will 'give' a semaphore each time + * an event occurs (incrementing the semaphore count value), and a handler + * task will 'take' a semaphore each time it processes an event + * (decrementing the semaphore count value). The count value is therefore + * the difference between the number of events that have occurred and the + * number that have been processed. In this case it is desirable for the + * initial count value to be zero. + * + * 2) Resource management. + * + * In this usage scenario the count value indicates the number of resources + * available. To obtain control of a resource a task must first obtain a + * semaphore - decrementing the semaphore count value. When the count value + * reaches zero there are no free resources. When a task finishes with the + * resource it 'gives' the semaphore back - incrementing the semaphore count + * value. In this case it is desirable for the initial count value to be + * equal to the maximum count value, indicating that all resources are free. + * + * @param uxMaxCount The maximum count value that can be reached. When the + * semaphore reaches this value it can no longer be 'given'. + * + * @param uxInitialCount The count value assigned to the semaphore when it is + * created. + * + * @param pxSemaphoreBuffer Must point to a variable of type StaticSemaphore_t, + * which will then be used to hold the semaphore's data structure, removing the + * need for the memory to be allocated dynamically. + * + * @return If the counting semaphore was successfully created then a handle to + * the created counting semaphore is returned. If pxSemaphoreBuffer was NULL + * then NULL is returned. + * + * Example usage: +
+ SemaphoreHandle_t xSemaphore;
+ StaticSemaphore_t xSemaphoreBuffer;
+
+ void vATask( void * pvParameters )
+ {
+ SemaphoreHandle_t xSemaphore = NULL;
+
+    // Counting semaphore cannot be used before they have been created.  Create
+    // a counting semaphore using xSemaphoreCreateCountingStatic().  The max
+    // value to which the semaphore can count is 10, and the initial value
+    // assigned to the count will be 0.  The address of xSemaphoreBuffer is
+    // passed in and will be used to hold the semaphore structure, so no dynamic
+    // memory allocation will be used.
+    xSemaphore = xSemaphoreCreateCounting( 10, 0, &xSemaphoreBuffer );
+
+    // No memory allocation was attempted so xSemaphore cannot be NULL, so there
+    // is no need to check its value.
+ }
+ 
+ * \defgroup xSemaphoreCreateCountingStatic xSemaphoreCreateCountingStatic + * \ingroup Semaphores + */ +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) +#define xSemaphoreCreateCountingStatic( uxMaxCount, uxInitialCount, pxSemaphoreBuffer ) xQueueCreateCountingSemaphoreStatic( ( uxMaxCount ), ( uxInitialCount ), ( pxSemaphoreBuffer ) ) +#endif /* configSUPPORT_STATIC_ALLOCATION */ + +/** + * semphr. h + *
void vSemaphoreDelete( SemaphoreHandle_t xSemaphore );
+ * + * Delete a semaphore. This function must be used with care. For example, + * do not delete a mutex type semaphore if the mutex is held by a task. + * + * @param xSemaphore A handle to the semaphore to be deleted. + * + * \defgroup vSemaphoreDelete vSemaphoreDelete + * \ingroup Semaphores + */ +#define vSemaphoreDelete( xSemaphore ) vQueueDelete( ( QueueHandle_t ) ( xSemaphore ) ) + +/** + * semphr.h + *
TaskHandle_t xSemaphoreGetMutexHolder( SemaphoreHandle_t xMutex );
+ * + * If xMutex is indeed a mutex type semaphore, return the current mutex holder. + * If xMutex is not a mutex type semaphore, or the mutex is available (not held + * by a task), return NULL. + * + * Note: This is a good way of determining if the calling task is the mutex + * holder, but not a good way of determining the identity of the mutex holder as + * the holder may change between the function exiting and the returned value + * being tested. + */ +#define xSemaphoreGetMutexHolder( xSemaphore ) xQueueGetMutexHolder( ( xSemaphore ) ) + +/** + * semphr.h + *
UBaseType_t uxSemaphoreGetCount( SemaphoreHandle_t xSemaphore );
+ * + * If the semaphore is a counting semaphore then uxSemaphoreGetCount() returns + * its current count value. If the semaphore is a binary semaphore then + * uxSemaphoreGetCount() returns 1 if the semaphore is available, and 0 if the + * semaphore is not available. + * + */ +#define uxSemaphoreGetCount( xSemaphore ) uxQueueMessagesWaiting( ( QueueHandle_t ) ( xSemaphore ) ) + +#define uxSemaphoreSetCount( xSemaphore, cnt) \ + uxQueueMessagesSet((QueueHandle_t)xSemaphore, cnt) + + +#endif /* SEMAPHORE_H */ + + diff --git a/include_lib/system/os/FreeRTOS/task.h b/include_lib/system/os/FreeRTOS/task.h new file mode 100644 index 0000000..044fefa --- /dev/null +++ b/include_lib/system/os/FreeRTOS/task.h @@ -0,0 +1,2268 @@ +/* + FreeRTOS V9.0.0 - Copyright (C) 2016 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + + +#ifndef INC_TASK_H +#define INC_TASK_H + +#ifndef INC_FREERTOS_H +#error "include FreeRTOS.h must appear in source files before include task.h" +#endif + +#include "list.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*----------------------------------------------------------- + * MACROS AND DEFINITIONS + *----------------------------------------------------------*/ + +#define tskKERNEL_VERSION_NUMBER "V9.0.0" +#define tskKERNEL_VERSION_MAJOR 9 +#define tskKERNEL_VERSION_MINOR 0 +#define tskKERNEL_VERSION_BUILD 0 + +/** + * task. h + * + * Type by which tasks are referenced. For example, a call to xTaskCreate + * returns (via a pointer parameter) an TaskHandle_t variable that can then + * be used as a parameter to vTaskDelete to delete the task. + * + * \defgroup TaskHandle_t TaskHandle_t + * \ingroup Tasks + */ +typedef void *TaskHandle_t; + +/* + * Defines the prototype to which the application task hook function must + * conform. + */ +typedef BaseType_t (*TaskHookFunction_t)(void *); + +/* Task states returned by eTaskGetState. */ +typedef enum { + eRunning = 0, /* A task is querying the state of itself, so must be running. */ + eReady, /* The task being queried is in a read or pending ready list. */ + eBlocked, /* The task being queried is in the Blocked state. */ + eSuspended, /* The task being queried is in the Suspended state, or is in the Blocked state with an infinite time out. */ + eDeleted, /* The task being queried has been deleted, but its TCB has not yet been freed. */ + eInvalid /* Used as an 'invalid state' value. */ +} eTaskState; + +/* Actions that can be performed when vTaskNotify() is called. */ +typedef enum { + eNoAction = 0, /* Notify the task without updating its notify value. */ + eSetBits, /* Set bits in the task's notification value. */ + eIncrement, /* Increment the task's notification value. */ + eSetValueWithOverwrite, /* Set the task's notification value to a specific value even if the previous value has not yet been read by the task. */ + eSetValueWithoutOverwrite /* Set the task's notification value if the previous value has been read by the task. */ +} eNotifyAction; + +/* + * Used internally only. + */ +typedef struct xTIME_OUT { + BaseType_t xOverflowCount; + TickType_t xTimeOnEntering; +} TimeOut_t; + +/* + * Defines the memory ranges allocated to the task when an MPU is used. + */ +typedef struct xMEMORY_REGION { + void *pvBaseAddress; + uint32_t ulLengthInBytes; + uint32_t ulParameters; +} MemoryRegion_t; + +/* + * Parameters required to create an MPU protected task. + */ +typedef struct xTASK_PARAMETERS { + TaskFunction_t pvTaskCode; + const char *const pcName; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + uint16_t usStackDepth; + void *pvParameters; + UBaseType_t uxPriority; + StackType_t *puxStackBuffer; + MemoryRegion_t xRegions[ portNUM_CONFIGURABLE_REGIONS ]; +} TaskParameters_t; + +/* Used with the uxTaskGetSystemState() function to return the state of each task +in the system. */ +typedef struct xTASK_STATUS { + TaskHandle_t xHandle; /* The handle of the task to which the rest of the information in the structure relates. */ + const char *pcTaskName; /* A pointer to the task's name. This value will be invalid if the task was deleted since the structure was populated! */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + UBaseType_t xTaskNumber; /* A number unique to the task. */ + eTaskState eCurrentState; /* The state in which the task existed when the structure was populated. */ + UBaseType_t uxCurrentPriority; /* The priority at which the task was running (may be inherited) when the structure was populated. */ + UBaseType_t uxBasePriority; /* The priority to which the task will return if the task's current priority has been inherited to avoid unbounded priority inversion when obtaining a mutex. Only valid if configUSE_MUTEXES is defined as 1 in FreeRTOSConfig.h. */ + uint32_t ulRunTimeCounter; /* The total run time allocated to the task so far, as defined by the run time stats clock. See http://www.freertos.org/rtos-run-time-stats.html. Only valid when configGENERATE_RUN_TIME_STATS is defined as 1 in FreeRTOSConfig.h. */ + StackType_t *pxStackBase; /* Points to the lowest address of the task's stack area. */ + uint16_t usStackHighWaterMark; /* The minimum amount of stack space that has remained for the task since the task was created. The closer this value is to zero the closer the task has come to overflowing its stack. */ +} TaskStatus_t; + +/* Possible return values for eTaskConfirmSleepModeStatus(). */ +typedef enum { + eAbortSleep = 0, /* A task has been made ready or a context switch pended since portSUPPORESS_TICKS_AND_SLEEP() was called - abort entering a sleep mode. */ + eStandardSleep, /* Enter a sleep mode that will not last any longer than the expected idle time. */ + eNoTasksWaitingTimeout /* No tasks are waiting for a timeout so it is safe to enter a sleep mode that can only be exited by an external interrupt. */ +} eSleepModeStatus; + +/** + * Defines the priority used by the idle task. This must not be modified. + * + * \ingroup TaskUtils + */ +#define tskIDLE_PRIORITY ( ( UBaseType_t ) 0U ) + +/** + * task. h + * + * Macro for forcing a context switch. + * + * \defgroup taskYIELD taskYIELD + * \ingroup SchedulerControl + */ +#define taskYIELD() portYIELD() + +/** + * task. h + * + * Macro to mark the start of a critical code region. Preemptive context + * switches cannot occur when in a critical region. + * + * NOTE: This may alter the stack (depending on the portable implementation) + * so must be used with care! + * + * \defgroup taskENTER_CRITICAL taskENTER_CRITICAL + * \ingroup SchedulerControl + */ +#define taskENTER_CRITICAL() portENTER_CRITICAL() +#define taskENTER_CRITICAL_FROM_ISR() portSET_INTERRUPT_MASK_FROM_ISR() + +/** + * task. h + * + * Macro to mark the end of a critical code region. Preemptive context + * switches cannot occur when in a critical region. + * + * NOTE: This may alter the stack (depending on the portable implementation) + * so must be used with care! + * + * \defgroup taskEXIT_CRITICAL taskEXIT_CRITICAL + * \ingroup SchedulerControl + */ +#define taskEXIT_CRITICAL() portEXIT_CRITICAL() +#define taskEXIT_CRITICAL_FROM_ISR( x ) portCLEAR_INTERRUPT_MASK_FROM_ISR( x ) +/** + * task. h + * + * Macro to disable all maskable interrupts. + * + * \defgroup taskDISABLE_INTERRUPTS taskDISABLE_INTERRUPTS + * \ingroup SchedulerControl + */ +#define taskDISABLE_INTERRUPTS() portDISABLE_INTERRUPTS() + +/** + * task. h + * + * Macro to enable microcontroller interrupts. + * + * \defgroup taskENABLE_INTERRUPTS taskENABLE_INTERRUPTS + * \ingroup SchedulerControl + */ +#define taskENABLE_INTERRUPTS() portENABLE_INTERRUPTS() + +/* Definitions returned by xTaskGetSchedulerState(). taskSCHEDULER_SUSPENDED is +0 to generate more optimal code when configASSERT() is defined as the constant +is used in assert() statements. */ +#define taskSCHEDULER_SUSPENDED ( ( BaseType_t ) 0 ) +#define taskSCHEDULER_NOT_STARTED ( ( BaseType_t ) 1 ) +#define taskSCHEDULER_RUNNING ( ( BaseType_t ) 2 ) + + +/*----------------------------------------------------------- + * TASK CREATION API + *----------------------------------------------------------*/ + +/** + * task. h + *
+ BaseType_t xTaskCreate(
+							  TaskFunction_t pvTaskCode,
+							  const char * const pcName,
+							  uint16_t usStackDepth,
+							  void *pvParameters,
+							  UBaseType_t uxPriority,
+							  TaskHandle_t *pvCreatedTask
+						  );
+ * + * Create a new task and add it to the list of tasks that are ready to run. + * + * Internally, within the FreeRTOS implementation, tasks use two blocks of + * memory. The first block is used to hold the task's data structures. The + * second block is used by the task as its stack. If a task is created using + * xTaskCreate() then both blocks of memory are automatically dynamically + * allocated inside the xTaskCreate() function. (see + * http://www.freertos.org/a00111.html). If a task is created using + * xTaskCreateStatic() then the application writer must provide the required + * memory. xTaskCreateStatic() therefore allows a task to be created without + * using any dynamic memory allocation. + * + * See xTaskCreateStatic() for a version that does not use any dynamic memory + * allocation. + * + * xTaskCreate() can only be used to create a task that has unrestricted + * access to the entire microcontroller memory map. Systems that include MPU + * support can alternatively create an MPU constrained task using + * xTaskCreateRestricted(). + * + * @param pvTaskCode Pointer to the task entry function. Tasks + * must be implemented to never return (i.e. continuous loop). + * + * @param pcName A descriptive name for the task. This is mainly used to + * facilitate debugging. Max length defined by configMAX_TASK_NAME_LEN - default + * is 16. + * + * @param usStackDepth The size of the task stack specified as the number of + * variables the stack can hold - not the number of bytes. For example, if + * the stack is 16 bits wide and usStackDepth is defined as 100, 200 bytes + * will be allocated for stack storage. + * + * @param pvParameters Pointer that will be used as the parameter for the task + * being created. + * + * @param uxPriority The priority at which the task should run. Systems that + * include MPU support can optionally create tasks in a privileged (system) + * mode by setting bit portPRIVILEGE_BIT of the priority parameter. For + * example, to create a privileged task at priority 2 the uxPriority parameter + * should be set to ( 2 | portPRIVILEGE_BIT ). + * + * @param pvCreatedTask Used to pass back a handle by which the created task + * can be referenced. + * + * @return pdPASS if the task was successfully created and added to a ready + * list, otherwise an error code defined in the file projdefs.h + * + * Example usage: +
+ // Task to be created.
+ void vTaskCode( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+	 }
+ }
+
+ // Function that creates a task.
+ void vOtherFunction( void )
+ {
+ static uint8_t ucParameterToPass;
+ TaskHandle_t xHandle = NULL;
+
+	 // Create the task, storing the handle.  Note that the passed parameter ucParameterToPass
+	 // must exist for the lifetime of the task, so in this case is declared static.  If it was just an
+	 // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
+	 // the new task attempts to access it.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle );
+     configASSERT( xHandle );
+
+	 // Use the handle to delete the task.
+     if( xHandle != NULL )
+     {
+	     vTaskDelete( xHandle );
+     }
+ }
+   
+ * \defgroup xTaskCreate xTaskCreate + * \ingroup Tasks + */ +#if( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) +BaseType_t xTaskCreate(TaskFunction_t pxTaskCode, + const char *const pcName, + const uint16_t usStackDepth, + void *const pvParameters, + UBaseType_t uxPriority, + TaskHandle_t *const pxCreatedTask) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#endif + +/** + * task. h + *
+ TaskHandle_t xTaskCreateStatic( TaskFunction_t pvTaskCode,
+								 const char * const pcName,
+								 uint32_t ulStackDepth,
+								 void *pvParameters,
+								 UBaseType_t uxPriority,
+								 StackType_t *pxStackBuffer,
+								 StaticTask_t *pxTaskBuffer );
+ * + * Create a new task and add it to the list of tasks that are ready to run. + * + * Internally, within the FreeRTOS implementation, tasks use two blocks of + * memory. The first block is used to hold the task's data structures. The + * second block is used by the task as its stack. If a task is created using + * xTaskCreate() then both blocks of memory are automatically dynamically + * allocated inside the xTaskCreate() function. (see + * http://www.freertos.org/a00111.html). If a task is created using + * xTaskCreateStatic() then the application writer must provide the required + * memory. xTaskCreateStatic() therefore allows a task to be created without + * using any dynamic memory allocation. + * + * @param pvTaskCode Pointer to the task entry function. Tasks + * must be implemented to never return (i.e. continuous loop). + * + * @param pcName A descriptive name for the task. This is mainly used to + * facilitate debugging. The maximum length of the string is defined by + * configMAX_TASK_NAME_LEN in FreeRTOSConfig.h. + * + * @param ulStackDepth The size of the task stack specified as the number of + * variables the stack can hold - not the number of bytes. For example, if + * the stack is 32-bits wide and ulStackDepth is defined as 100 then 400 bytes + * will be allocated for stack storage. + * + * @param pvParameters Pointer that will be used as the parameter for the task + * being created. + * + * @param uxPriority The priority at which the task will run. + * + * @param pxStackBuffer Must point to a StackType_t array that has at least + * ulStackDepth indexes - the array will then be used as the task's stack, + * removing the need for the stack to be allocated dynamically. + * + * @param pxTaskBuffer Must point to a variable of type StaticTask_t, which will + * then be used to hold the task's data structures, removing the need for the + * memory to be allocated dynamically. + * + * @return If neither pxStackBuffer or pxTaskBuffer are NULL, then the task will + * be created and pdPASS is returned. If either pxStackBuffer or pxTaskBuffer + * are NULL then the task will not be created and + * errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY is returned. + * + * Example usage: +
+
+    // Dimensions the buffer that the task being created will use as its stack.
+    // NOTE:  This is the number of words the stack will hold, not the number of
+    // bytes.  For example, if each stack item is 32-bits, and this is set to 100,
+    // then 400 bytes (100 * 32-bits) will be allocated.
+    #define STACK_SIZE 200
+
+    // Structure that will hold the TCB of the task being created.
+    StaticTask_t xTaskBuffer;
+
+    // Buffer that the task being created will use as its stack.  Note this is
+    // an array of StackType_t variables.  The size of StackType_t is dependent on
+    // the RTOS port.
+    StackType_t xStack[ STACK_SIZE ];
+
+    // Function that implements the task being created.
+    void vTaskCode( void * pvParameters )
+    {
+        // The parameter value is expected to be 1 as 1 is passed in the
+        // pvParameters value in the call to xTaskCreateStatic().
+        configASSERT( ( uint32_t ) pvParameters == 1UL );
+
+        for( ;; )
+        {
+            // Task code goes here.
+        }
+    }
+
+    // Function that creates a task.
+    void vOtherFunction( void )
+    {
+        TaskHandle_t xHandle = NULL;
+
+        // Create the task without using any dynamic memory allocation.
+        xHandle = xTaskCreateStatic(
+                      vTaskCode,       // Function that implements the task.
+                      "NAME",          // Text name for the task.
+                      STACK_SIZE,      // Stack size in words, not bytes.
+                      ( void * ) 1,    // Parameter passed into the task.
+                      tskIDLE_PRIORITY,// Priority at which the task is created.
+                      xStack,          // Array to use as the task's stack.
+                      &xTaskBuffer );  // Variable to hold the task's data structure.
+
+        // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have
+        // been created, and xHandle will be the task's handle.  Use the handle
+        // to suspend the task.
+        vTaskSuspend( xHandle );
+    }
+   
+ * \defgroup xTaskCreateStatic xTaskCreateStatic + * \ingroup Tasks + */ +#if( configSUPPORT_STATIC_ALLOCATION == 1 ) +TaskHandle_t xTaskCreateStatic(TaskFunction_t pxTaskCode, + const char *const pcName, + const uint32_t ulStackDepth, + void *const pvParameters, + UBaseType_t uxPriority, + StackType_t *const puxStackBuffer, + StaticTask_t *const pxTaskBuffer) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ +#endif /* configSUPPORT_STATIC_ALLOCATION */ + +/** + * task. h + *
+ BaseType_t xTaskCreateRestricted( TaskParameters_t *pxTaskDefinition, TaskHandle_t *pxCreatedTask );
+ * + * xTaskCreateRestricted() should only be used in systems that include an MPU + * implementation. + * + * Create a new task and add it to the list of tasks that are ready to run. + * The function parameters define the memory regions and associated access + * permissions allocated to the task. + * + * @param pxTaskDefinition Pointer to a structure that contains a member + * for each of the normal xTaskCreate() parameters (see the xTaskCreate() API + * documentation) plus an optional stack buffer and the memory region + * definitions. + * + * @param pxCreatedTask Used to pass back a handle by which the created task + * can be referenced. + * + * @return pdPASS if the task was successfully created and added to a ready + * list, otherwise an error code defined in the file projdefs.h + * + * Example usage: +
+// Create an TaskParameters_t structure that defines the task to be created.
+static const TaskParameters_t xCheckTaskParameters =
+{
+	vATask,		// pvTaskCode - the function that implements the task.
+	"ATask",	// pcName - just a text name for the task to assist debugging.
+	100,		// usStackDepth	- the stack size DEFINED IN WORDS.
+	NULL,		// pvParameters - passed into the task function as the function parameters.
+	( 1UL | portPRIVILEGE_BIT ),// uxPriority - task priority, set the portPRIVILEGE_BIT if the task should run in a privileged state.
+	cStackBuffer,// puxStackBuffer - the buffer to be used as the task stack.
+
+	// xRegions - Allocate up to three separate memory regions for access by
+	// the task, with appropriate access permissions.  Different processors have
+	// different memory alignment requirements - refer to the FreeRTOS documentation
+	// for full information.
+	{
+		// Base address					Length	Parameters
+        { cReadWriteArray,				32,		portMPU_REGION_READ_WRITE },
+        { cReadOnlyArray,				32,		portMPU_REGION_READ_ONLY },
+        { cPrivilegedOnlyAccessArray,	128,	portMPU_REGION_PRIVILEGED_READ_WRITE }
+	}
+};
+
+int main( void )
+{
+TaskHandle_t xHandle;
+
+	// Create a task from the const structure defined above.  The task handle
+	// is requested (the second parameter is not NULL) but in this case just for
+	// demonstration purposes as its not actually used.
+	xTaskCreateRestricted( &xRegTest1Parameters, &xHandle );
+
+	// Start the scheduler.
+	vTaskStartScheduler();
+
+	// Will only get here if there was insufficient memory to create the idle
+	// and/or timer task.
+	for( ;; );
+}
+   
+ * \defgroup xTaskCreateRestricted xTaskCreateRestricted + * \ingroup Tasks + */ +#if( portUSING_MPU_WRAPPERS == 1 ) +BaseType_t xTaskCreateRestricted(const TaskParameters_t *const pxTaskDefinition, TaskHandle_t *pxCreatedTask) PRIVILEGED_FUNCTION; +#endif + +/** + * task. h + *
+ void vTaskAllocateMPURegions( TaskHandle_t xTask, const MemoryRegion_t * const pxRegions );
+ * + * Memory regions are assigned to a restricted task when the task is created by + * a call to xTaskCreateRestricted(). These regions can be redefined using + * vTaskAllocateMPURegions(). + * + * @param xTask The handle of the task being updated. + * + * @param xRegions A pointer to an MemoryRegion_t structure that contains the + * new memory region definitions. + * + * Example usage: +
+// Define an array of MemoryRegion_t structures that configures an MPU region
+// allowing read/write access for 1024 bytes starting at the beginning of the
+// ucOneKByte array.  The other two of the maximum 3 definable regions are
+// unused so set to zero.
+static const MemoryRegion_t xAltRegions[ portNUM_CONFIGURABLE_REGIONS ] =
+{
+	// Base address		Length		Parameters
+	{ ucOneKByte,		1024,		portMPU_REGION_READ_WRITE },
+	{ 0,				0,			0 },
+	{ 0,				0,			0 }
+};
+
+void vATask( void *pvParameters )
+{
+	// This task was created such that it has access to certain regions of
+	// memory as defined by the MPU configuration.  At some point it is
+	// desired that these MPU regions are replaced with that defined in the
+	// xAltRegions const struct above.  Use a call to vTaskAllocateMPURegions()
+	// for this purpose.  NULL is used as the task handle to indicate that this
+	// function should modify the MPU regions of the calling task.
+	vTaskAllocateMPURegions( NULL, xAltRegions );
+
+	// Now the task can continue its function, but from this point on can only
+	// access its stack and the ucOneKByte array (unless any other statically
+	// defined or shared regions have been declared elsewhere).
+}
+   
+ * \defgroup xTaskCreateRestricted xTaskCreateRestricted + * \ingroup Tasks + */ +void vTaskAllocateMPURegions(TaskHandle_t xTask, const MemoryRegion_t *const pxRegions) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskDelete( TaskHandle_t xTask );
+ * + * INCLUDE_vTaskDelete must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Remove a task from the RTOS real time kernel's management. The task being + * deleted will be removed from all ready, blocked, suspended and event lists. + * + * NOTE: The idle task is responsible for freeing the kernel allocated + * memory from tasks that have been deleted. It is therefore important that + * the idle task is not starved of microcontroller processing time if your + * application makes any calls to vTaskDelete (). Memory allocated by the + * task code is not automatically freed, and should be freed before the task + * is deleted. + * + * See the demo application file death.c for sample code that utilises + * vTaskDelete (). + * + * @param xTask The handle of the task to be deleted. Passing NULL will + * cause the calling task to be deleted. + * + * Example usage: +
+ void vOtherFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create the task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // Use the handle to delete the task.
+	 vTaskDelete( xHandle );
+ }
+   
+ * \defgroup vTaskDelete vTaskDelete + * \ingroup Tasks + */ +void vTaskDelete(TaskHandle_t xTaskToDelete) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * TASK CONTROL API + *----------------------------------------------------------*/ + +/** + * task. h + *
void vTaskDelay( const TickType_t xTicksToDelay );
+ * + * Delay a task for a given number of ticks. The actual time that the + * task remains blocked depends on the tick rate. The constant + * portTICK_PERIOD_MS can be used to calculate real time from the tick + * rate - with the resolution of one tick period. + * + * INCLUDE_vTaskDelay must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * + * vTaskDelay() specifies a time at which the task wishes to unblock relative to + * the time at which vTaskDelay() is called. For example, specifying a block + * period of 100 ticks will cause the task to unblock 100 ticks after + * vTaskDelay() is called. vTaskDelay() does not therefore provide a good method + * of controlling the frequency of a periodic task as the path taken through the + * code, as well as other task and interrupt activity, will effect the frequency + * at which vTaskDelay() gets called and therefore the time at which the task + * next executes. See vTaskDelayUntil() for an alternative API function designed + * to facilitate fixed frequency execution. It does this by specifying an + * absolute time (rather than a relative time) at which the calling task should + * unblock. + * + * @param xTicksToDelay The amount of time, in tick periods, that + * the calling task should block. + * + * Example usage: + + void vTaskFunction( void * pvParameters ) + { + // Block for 500ms. + const TickType_t xDelay = 500 / portTICK_PERIOD_MS; + + for( ;; ) + { + // Simply toggle the LED every 500ms, blocking between each toggle. + vToggleLED(); + vTaskDelay( xDelay ); + } + } + + * \defgroup vTaskDelay vTaskDelay + * \ingroup TaskCtrl + */ +void vTaskDelay(const TickType_t xTicksToDelay) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskDelayUntil( TickType_t *pxPreviousWakeTime, const TickType_t xTimeIncrement );
+ * + * INCLUDE_vTaskDelayUntil must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Delay a task until a specified time. This function can be used by periodic + * tasks to ensure a constant execution frequency. + * + * This function differs from vTaskDelay () in one important aspect: vTaskDelay () will + * cause a task to block for the specified number of ticks from the time vTaskDelay () is + * called. It is therefore difficult to use vTaskDelay () by itself to generate a fixed + * execution frequency as the time between a task starting to execute and that task + * calling vTaskDelay () may not be fixed [the task may take a different path though the + * code between calls, or may get interrupted or preempted a different number of times + * each time it executes]. + * + * Whereas vTaskDelay () specifies a wake time relative to the time at which the function + * is called, vTaskDelayUntil () specifies the absolute (exact) time at which it wishes to + * unblock. + * + * The constant portTICK_PERIOD_MS can be used to calculate real time from the tick + * rate - with the resolution of one tick period. + * + * @param pxPreviousWakeTime Pointer to a variable that holds the time at which the + * task was last unblocked. The variable must be initialised with the current time + * prior to its first use (see the example below). Following this the variable is + * automatically updated within vTaskDelayUntil (). + * + * @param xTimeIncrement The cycle time period. The task will be unblocked at + * time *pxPreviousWakeTime + xTimeIncrement. Calling vTaskDelayUntil with the + * same xTimeIncrement parameter value will cause the task to execute with + * a fixed interface period. + * + * Example usage: +
+ // Perform an action every 10 ticks.
+ void vTaskFunction( void * pvParameters )
+ {
+ TickType_t xLastWakeTime;
+ const TickType_t xFrequency = 10;
+
+	 // Initialise the xLastWakeTime variable with the current time.
+	 xLastWakeTime = xTaskGetTickCount ();
+	 for( ;; )
+	 {
+		 // Wait for the next cycle.
+		 vTaskDelayUntil( &xLastWakeTime, xFrequency );
+
+		 // Perform action here.
+	 }
+ }
+   
+ * \defgroup vTaskDelayUntil vTaskDelayUntil + * \ingroup TaskCtrl + */ +void vTaskDelayUntil(TickType_t *const pxPreviousWakeTime, const TickType_t xTimeIncrement) PRIVILEGED_FUNCTION; + +/** + * task. h + *
BaseType_t xTaskAbortDelay( TaskHandle_t xTask );
+ * + * INCLUDE_xTaskAbortDelay must be defined as 1 in FreeRTOSConfig.h for this + * function to be available. + * + * A task will enter the Blocked state when it is waiting for an event. The + * event it is waiting for can be a temporal event (waiting for a time), such + * as when vTaskDelay() is called, or an event on an object, such as when + * xQueueReceive() or ulTaskNotifyTake() is called. If the handle of a task + * that is in the Blocked state is used in a call to xTaskAbortDelay() then the + * task will leave the Blocked state, and return from whichever function call + * placed the task into the Blocked state. + * + * @param xTask The handle of the task to remove from the Blocked state. + * + * @return If the task referenced by xTask was not in the Blocked state then + * pdFAIL is returned. Otherwise pdPASS is returned. + * + * \defgroup xTaskAbortDelay xTaskAbortDelay + * \ingroup TaskCtrl + */ +BaseType_t xTaskAbortDelay(TaskHandle_t xTask) PRIVILEGED_FUNCTION; + +/** + * task. h + *
UBaseType_t uxTaskPriorityGet( TaskHandle_t xTask );
+ * + * INCLUDE_uxTaskPriorityGet must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Obtain the priority of any task. + * + * @param xTask Handle of the task to be queried. Passing a NULL + * handle results in the priority of the calling task being returned. + * + * @return The priority of xTask. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to obtain the priority of the created task.
+	 // It was created with tskIDLE_PRIORITY, but may have changed
+	 // it itself.
+	 if( uxTaskPriorityGet( xHandle ) != tskIDLE_PRIORITY )
+	 {
+		 // The task has changed it's priority.
+	 }
+
+	 // ...
+
+	 // Is our priority higher than the created task?
+	 if( uxTaskPriorityGet( xHandle ) < uxTaskPriorityGet( NULL ) )
+	 {
+		 // Our priority (obtained using NULL handle) is higher.
+	 }
+ }
+   
+ * \defgroup uxTaskPriorityGet uxTaskPriorityGet + * \ingroup TaskCtrl + */ +UBaseType_t uxTaskPriorityGet(TaskHandle_t xTask) PRIVILEGED_FUNCTION; + +/** + * task. h + *
UBaseType_t uxTaskPriorityGetFromISR( TaskHandle_t xTask );
+ * + * A version of uxTaskPriorityGet() that can be used from an ISR. + */ +UBaseType_t uxTaskPriorityGetFromISR(TaskHandle_t xTask) PRIVILEGED_FUNCTION; + +/** + * task. h + *
eTaskState eTaskGetState( TaskHandle_t xTask );
+ * + * INCLUDE_eTaskGetState must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Obtain the state of any task. States are encoded by the eTaskState + * enumerated type. + * + * @param xTask Handle of the task to be queried. + * + * @return The state of xTask at the time the function was called. Note the + * state of the task might change between the function being called, and the + * functions return value being tested by the calling task. + */ +eTaskState eTaskGetState(TaskHandle_t xTask) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskGetInfo( TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState );
+ * + * configUSE_TRACE_FACILITY must be defined as 1 for this function to be + * available. See the configuration section for more information. + * + * Populates a TaskStatus_t structure with information about a task. + * + * @param xTask Handle of the task being queried. If xTask is NULL then + * information will be returned about the calling task. + * + * @param pxTaskStatus A pointer to the TaskStatus_t structure that will be + * filled with information about the task referenced by the handle passed using + * the xTask parameter. + * + * @xGetFreeStackSpace The TaskStatus_t structure contains a member to report + * the stack high water mark of the task being queried. Calculating the stack + * high water mark takes a relatively long time, and can make the system + * temporarily unresponsive - so the xGetFreeStackSpace parameter is provided to + * allow the high water mark checking to be skipped. The high watermark value + * will only be written to the TaskStatus_t structure if xGetFreeStackSpace is + * not set to pdFALSE; + * + * @param eState The TaskStatus_t structure contains a member to report the + * state of the task being queried. Obtaining the task state is not as fast as + * a simple assignment - so the eState parameter is provided to allow the state + * information to be omitted from the TaskStatus_t structure. To obtain state + * information then set eState to eInvalid - otherwise the value passed in + * eState will be reported as the task state in the TaskStatus_t structure. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+ TaskStatus_t xTaskDetails;
+
+    // Obtain the handle of a task from its name.
+    xHandle = xTaskGetHandle( "Task_Name" );
+
+    // Check the handle is not NULL.
+    configASSERT( xHandle );
+
+    // Use the handle to obtain further information about the task.
+    vTaskGetInfo( xHandle,
+                  &xTaskDetails,
+                  pdTRUE, // Include the high water mark in xTaskDetails.
+                  eInvalid ); // Include the task state in xTaskDetails.
+ }
+   
+ * \defgroup vTaskGetInfo vTaskGetInfo + * \ingroup TaskCtrl + */ +void vTaskGetInfo(TaskHandle_t xTask, TaskStatus_t *pxTaskStatus, BaseType_t xGetFreeStackSpace, eTaskState eState) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskPrioritySet( TaskHandle_t xTask, UBaseType_t uxNewPriority );
+ * + * INCLUDE_vTaskPrioritySet must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Set the priority of any task. + * + * A context switch will occur before the function returns if the priority + * being set is higher than the currently executing task. + * + * @param xTask Handle to the task for which the priority is being set. + * Passing a NULL handle results in the priority of the calling task being set. + * + * @param uxNewPriority The priority to which the task will be set. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to raise the priority of the created task.
+	 vTaskPrioritySet( xHandle, tskIDLE_PRIORITY + 1 );
+
+	 // ...
+
+	 // Use a NULL handle to raise our priority to the same value.
+	 vTaskPrioritySet( NULL, tskIDLE_PRIORITY + 1 );
+ }
+   
+ * \defgroup vTaskPrioritySet vTaskPrioritySet + * \ingroup TaskCtrl + */ +void vTaskPrioritySet(TaskHandle_t xTask, UBaseType_t uxNewPriority) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskSuspend( TaskHandle_t xTaskToSuspend );
+ * + * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Suspend any task. When suspended a task will never get any microcontroller + * processing time, no matter what its priority. + * + * Calls to vTaskSuspend are not accumulative - + * i.e. calling vTaskSuspend () twice on the same task still only requires one + * call to vTaskResume () to ready the suspended task. + * + * @param xTaskToSuspend Handle to the task being suspended. Passing a NULL + * handle will cause the calling task to be suspended. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to suspend the created task.
+	 vTaskSuspend( xHandle );
+
+	 // ...
+
+	 // The created task will not run during this period, unless
+	 // another task calls vTaskResume( xHandle ).
+
+	 //...
+
+
+	 // Suspend ourselves.
+	 vTaskSuspend( NULL );
+
+	 // We cannot get here unless another task calls vTaskResume
+	 // with our handle as the parameter.
+ }
+   
+ * \defgroup vTaskSuspend vTaskSuspend + * \ingroup TaskCtrl + */ +void vTaskSuspend(TaskHandle_t xTaskToSuspend) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskResume( TaskHandle_t xTaskToResume );
+ * + * INCLUDE_vTaskSuspend must be defined as 1 for this function to be available. + * See the configuration section for more information. + * + * Resumes a suspended task. + * + * A task that has been suspended by one or more calls to vTaskSuspend () + * will be made available for running again by a single call to + * vTaskResume (). + * + * @param xTaskToResume Handle to the task being readied. + * + * Example usage: +
+ void vAFunction( void )
+ {
+ TaskHandle_t xHandle;
+
+	 // Create a task, storing the handle.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xHandle );
+
+	 // ...
+
+	 // Use the handle to suspend the created task.
+	 vTaskSuspend( xHandle );
+
+	 // ...
+
+	 // The created task will not run during this period, unless
+	 // another task calls vTaskResume( xHandle ).
+
+	 //...
+
+
+	 // Resume the suspended task ourselves.
+	 vTaskResume( xHandle );
+
+	 // The created task will once again get microcontroller processing
+	 // time in accordance with its priority within the system.
+ }
+   
+ * \defgroup vTaskResume vTaskResume + * \ingroup TaskCtrl + */ +void vTaskResume(TaskHandle_t xTaskToResume) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void xTaskResumeFromISR( TaskHandle_t xTaskToResume );
+ * + * INCLUDE_xTaskResumeFromISR must be defined as 1 for this function to be + * available. See the configuration section for more information. + * + * An implementation of vTaskResume() that can be called from within an ISR. + * + * A task that has been suspended by one or more calls to vTaskSuspend () + * will be made available for running again by a single call to + * xTaskResumeFromISR (). + * + * xTaskResumeFromISR() should not be used to synchronise a task with an + * interrupt if there is a chance that the interrupt could arrive prior to the + * task being suspended - as this can lead to interrupts being missed. Use of a + * semaphore as a synchronisation mechanism would avoid this eventuality. + * + * @param xTaskToResume Handle to the task being readied. + * + * @return pdTRUE if resuming the task should result in a context switch, + * otherwise pdFALSE. This is used by the ISR to determine if a context switch + * may be required following the ISR. + * + * \defgroup vTaskResumeFromISR vTaskResumeFromISR + * \ingroup TaskCtrl + */ +BaseType_t xTaskResumeFromISR(TaskHandle_t xTaskToResume) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * SCHEDULER CONTROL + *----------------------------------------------------------*/ + +/** + * task. h + *
void vTaskStartScheduler( void );
+ * + * Starts the real time kernel tick processing. After calling the kernel + * has control over which tasks are executed and when. + * + * See the demo application file main.c for an example of creating + * tasks and starting the kernel. + * + * Example usage: +
+ void vAFunction( void )
+ {
+	 // Create at least one task before starting the kernel.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+	 // Start the real time kernel with preemption.
+	 vTaskStartScheduler ();
+
+	 // Will not get here unless a task calls vTaskEndScheduler ()
+ }
+   
+ * + * \defgroup vTaskStartScheduler vTaskStartScheduler + * \ingroup SchedulerControl + */ +void vTaskStartScheduler(void) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskEndScheduler( void );
+ * + * NOTE: At the time of writing only the x86 real mode port, which runs on a PC + * in place of DOS, implements this function. + * + * Stops the real time kernel tick. All created tasks will be automatically + * deleted and multitasking (either preemptive or cooperative) will + * stop. Execution then resumes from the point where vTaskStartScheduler () + * was called, as if vTaskStartScheduler () had just returned. + * + * See the demo application file main. c in the demo/PC directory for an + * example that uses vTaskEndScheduler (). + * + * vTaskEndScheduler () requires an exit function to be defined within the + * portable layer (see vPortEndScheduler () in port. c for the PC port). This + * performs hardware specific operations such as stopping the kernel tick. + * + * vTaskEndScheduler () will cause all of the resources allocated by the + * kernel to be freed - but will not free resources allocated by application + * tasks. + * + * Example usage: +
+ void vTaskCode( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // At some point we want to end the real time kernel processing
+		 // so call ...
+		 vTaskEndScheduler ();
+	 }
+ }
+
+ void vAFunction( void )
+ {
+	 // Create at least one task before starting the kernel.
+	 xTaskCreate( vTaskCode, "NAME", STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
+
+	 // Start the real time kernel with preemption.
+	 vTaskStartScheduler ();
+
+	 // Will only get here when the vTaskCode () task has called
+	 // vTaskEndScheduler ().  When we get here we are back to single task
+	 // execution.
+ }
+   
+ * + * \defgroup vTaskEndScheduler vTaskEndScheduler + * \ingroup SchedulerControl + */ +void vTaskEndScheduler(void) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskSuspendAll( void );
+ * + * Suspends the scheduler without disabling interrupts. Context switches will + * not occur while the scheduler is suspended. + * + * After calling vTaskSuspendAll () the calling task will continue to execute + * without risk of being swapped out until a call to xTaskResumeAll () has been + * made. + * + * API functions that have the potential to cause a context switch (for example, + * vTaskDelayUntil(), xQueueSend(), etc.) must not be called while the scheduler + * is suspended. + * + * Example usage: +
+ void vTask1( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // ...
+
+		 // At some point the task wants to perform a long operation during
+		 // which it does not want to get swapped out.  It cannot use
+		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+		 // operation may cause interrupts to be missed - including the
+		 // ticks.
+
+		 // Prevent the real time kernel swapping out the task.
+		 vTaskSuspendAll ();
+
+		 // Perform the operation here.  There is no need to use critical
+		 // sections as we have all the microcontroller processing time.
+		 // During this time interrupts will still operate and the kernel
+		 // tick count will be maintained.
+
+		 // ...
+
+		 // The operation is complete.  Restart the kernel.
+		 xTaskResumeAll ();
+	 }
+ }
+   
+ * \defgroup vTaskSuspendAll vTaskSuspendAll + * \ingroup SchedulerControl + */ +void vTaskSuspendAll(void) PRIVILEGED_FUNCTION; + +/** + * task. h + *
BaseType_t xTaskResumeAll( void );
+ * + * Resumes scheduler activity after it was suspended by a call to + * vTaskSuspendAll(). + * + * xTaskResumeAll() only resumes the scheduler. It does not unsuspend tasks + * that were previously suspended by a call to vTaskSuspend(). + * + * @return If resuming the scheduler caused a context switch then pdTRUE is + * returned, otherwise pdFALSE is returned. + * + * Example usage: +
+ void vTask1( void * pvParameters )
+ {
+	 for( ;; )
+	 {
+		 // Task code goes here.
+
+		 // ...
+
+		 // At some point the task wants to perform a long operation during
+		 // which it does not want to get swapped out.  It cannot use
+		 // taskENTER_CRITICAL ()/taskEXIT_CRITICAL () as the length of the
+		 // operation may cause interrupts to be missed - including the
+		 // ticks.
+
+		 // Prevent the real time kernel swapping out the task.
+		 vTaskSuspendAll ();
+
+		 // Perform the operation here.  There is no need to use critical
+		 // sections as we have all the microcontroller processing time.
+		 // During this time interrupts will still operate and the real
+		 // time kernel tick count will be maintained.
+
+		 // ...
+
+		 // The operation is complete.  Restart the kernel.  We want to force
+		 // a context switch - but there is no point if resuming the scheduler
+		 // caused a context switch already.
+		 if( !xTaskResumeAll () )
+		 {
+			  taskYIELD ();
+		 }
+	 }
+ }
+   
+ * \defgroup xTaskResumeAll xTaskResumeAll + * \ingroup SchedulerControl + */ +BaseType_t xTaskResumeAll(void) PRIVILEGED_FUNCTION; + +/*----------------------------------------------------------- + * TASK UTILITIES + *----------------------------------------------------------*/ + +/** + * task. h + *
TickType_t xTaskGetTickCount( void );
+ * + * @return The count of ticks since vTaskStartScheduler was called. + * + * \defgroup xTaskGetTickCount xTaskGetTickCount + * \ingroup TaskUtils + */ +TickType_t xTaskGetTickCount(void) PRIVILEGED_FUNCTION; + +/** + * task. h + *
TickType_t xTaskGetTickCountFromISR( void );
+ * + * @return The count of ticks since vTaskStartScheduler was called. + * + * This is a version of xTaskGetTickCount() that is safe to be called from an + * ISR - provided that TickType_t is the natural word size of the + * microcontroller being used or interrupt nesting is either not supported or + * not being used. + * + * \defgroup xTaskGetTickCountFromISR xTaskGetTickCountFromISR + * \ingroup TaskUtils + */ +TickType_t xTaskGetTickCountFromISR(void) PRIVILEGED_FUNCTION; + +/** + * task. h + *
uint16_t uxTaskGetNumberOfTasks( void );
+ * + * @return The number of tasks that the real time kernel is currently managing. + * This includes all ready, blocked and suspended tasks. A task that + * has been deleted but not yet freed by the idle task will also be + * included in the count. + * + * \defgroup uxTaskGetNumberOfTasks uxTaskGetNumberOfTasks + * \ingroup TaskUtils + */ +UBaseType_t uxTaskGetNumberOfTasks(void) PRIVILEGED_FUNCTION; + +/** + * task. h + *
char *pcTaskGetName( TaskHandle_t xTaskToQuery );
+ * + * @return The text (human readable) name of the task referenced by the handle + * xTaskToQuery. A task can query its own name by either passing in its own + * handle, or by setting xTaskToQuery to NULL. + * + * \defgroup pcTaskGetName pcTaskGetName + * \ingroup TaskUtils + */ +char *pcTaskGetName(TaskHandle_t xTaskToQuery) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * task. h + *
TaskHandle_t xTaskGetHandle( const char *pcNameToQuery );
+ * + * NOTE: This function takes a relatively long time to complete and should be + * used sparingly. + * + * @return The handle of the task that has the human readable name pcNameToQuery. + * NULL is returned if no matching name is found. INCLUDE_xTaskGetHandle + * must be set to 1 in FreeRTOSConfig.h for pcTaskGetHandle() to be available. + * + * \defgroup pcTaskGetHandle pcTaskGetHandle + * \ingroup TaskUtils + */ +TaskHandle_t xTaskGetHandle(const char *pcNameToQuery) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * task.h + *
UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
+ * + * INCLUDE_uxTaskGetStackHighWaterMark must be set to 1 in FreeRTOSConfig.h for + * this function to be available. + * + * Returns the high water mark of the stack associated with xTask. That is, + * the minimum free stack space there has been (in words, so on a 32 bit machine + * a value of 1 means 4 bytes) since the task started. The smaller the returned + * number the closer the task has come to overflowing its stack. + * + * @param xTask Handle of the task associated with the stack to be checked. + * Set xTask to NULL to check the stack of the calling task. + * + * @return The smallest amount of free stack space there has been (in words, so + * actual spaces on the stack rather than bytes) since the task referenced by + * xTask was created. + */ +UBaseType_t uxTaskGetStackHighWaterMark(TaskHandle_t xTask) PRIVILEGED_FUNCTION; + +/* When using trace macros it is sometimes necessary to include task.h before +FreeRTOS.h. When this is done TaskHookFunction_t will not yet have been defined, +so the following two prototypes will cause a compilation error. This can be +fixed by simply guarding against the inclusion of these two prototypes unless +they are explicitly required by the configUSE_APPLICATION_TASK_TAG configuration +constant. */ +#ifdef configUSE_APPLICATION_TASK_TAG +#if configUSE_APPLICATION_TASK_TAG == 1 +/** + * task.h + *
void vTaskSetApplicationTaskTag( TaskHandle_t xTask, TaskHookFunction_t pxHookFunction );
+ * + * Sets pxHookFunction to be the task hook function used by the task xTask. + * Passing xTask as NULL has the effect of setting the calling tasks hook + * function. + */ +void vTaskSetApplicationTaskTag(TaskHandle_t xTask, TaskHookFunction_t pxHookFunction) PRIVILEGED_FUNCTION; + +/** + * task.h + *
void xTaskGetApplicationTaskTag( TaskHandle_t xTask );
+ * + * Returns the pxHookFunction value assigned to the task xTask. + */ +TaskHookFunction_t xTaskGetApplicationTaskTag(TaskHandle_t xTask) PRIVILEGED_FUNCTION; +#endif /* configUSE_APPLICATION_TASK_TAG ==1 */ +#endif /* ifdef configUSE_APPLICATION_TASK_TAG */ + +#if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) + +/* Each task contains an array of pointers that is dimensioned by the +configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h. The +kernel does not use the pointers itself, so the application writer can use +the pointers for any purpose they wish. The following two functions are +used to set and query a pointer respectively. */ +void vTaskSetThreadLocalStoragePointer(TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue) PRIVILEGED_FUNCTION; +void *pvTaskGetThreadLocalStoragePointer(TaskHandle_t xTaskToQuery, BaseType_t xIndex) PRIVILEGED_FUNCTION; + +#endif + +/** + * task.h + *
BaseType_t xTaskCallApplicationTaskHook( TaskHandle_t xTask, void *pvParameter );
+ * + * Calls the hook function associated with xTask. Passing xTask as NULL has + * the effect of calling the Running tasks (the calling task) hook function. + * + * pvParameter is passed to the hook function for the task to interpret as it + * wants. The return value is the value returned by the task hook function + * registered by the user. + */ +BaseType_t xTaskCallApplicationTaskHook(TaskHandle_t xTask, void *pvParameter) PRIVILEGED_FUNCTION; + +/** + * xTaskGetIdleTaskHandle() is only available if + * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h. + * + * Simply returns the handle of the idle task. It is not valid to call + * xTaskGetIdleTaskHandle() before the scheduler has been started. + */ +TaskHandle_t xTaskGetIdleTaskHandle(void) PRIVILEGED_FUNCTION; + +/** + * configUSE_TRACE_FACILITY must be defined as 1 in FreeRTOSConfig.h for + * uxTaskGetSystemState() to be available. + * + * uxTaskGetSystemState() populates an TaskStatus_t structure for each task in + * the system. TaskStatus_t structures contain, among other things, members + * for the task handle, task name, task priority, task state, and total amount + * of run time consumed by the task. See the TaskStatus_t structure + * definition in this file for the full member list. + * + * NOTE: This function is intended for debugging use only as its use results in + * the scheduler remaining suspended for an extended period. + * + * @param pxTaskStatusArray A pointer to an array of TaskStatus_t structures. + * The array must contain at least one TaskStatus_t structure for each task + * that is under the control of the RTOS. The number of tasks under the control + * of the RTOS can be determined using the uxTaskGetNumberOfTasks() API function. + * + * @param uxArraySize The size of the array pointed to by the pxTaskStatusArray + * parameter. The size is specified as the number of indexes in the array, or + * the number of TaskStatus_t structures contained in the array, not by the + * number of bytes in the array. + * + * @param pulTotalRunTime If configGENERATE_RUN_TIME_STATS is set to 1 in + * FreeRTOSConfig.h then *pulTotalRunTime is set by uxTaskGetSystemState() to the + * total run time (as defined by the run time stats clock, see + * http://www.freertos.org/rtos-run-time-stats.html) since the target booted. + * pulTotalRunTime can be set to NULL to omit the total run time information. + * + * @return The number of TaskStatus_t structures that were populated by + * uxTaskGetSystemState(). This should equal the number returned by the + * uxTaskGetNumberOfTasks() API function, but will be zero if the value passed + * in the uxArraySize parameter was too small. + * + * Example usage: +
+    // This example demonstrates how a human readable table of run time stats
+	// information is generated from raw data provided by uxTaskGetSystemState().
+	// The human readable table is written to pcWriteBuffer
+	void vTaskGetRunTimeStats( char *pcWriteBuffer )
+	{
+	TaskStatus_t *pxTaskStatusArray;
+	volatile UBaseType_t uxArraySize, x;
+	uint32_t ulTotalRunTime, ulStatsAsPercentage;
+
+		// Make sure the write buffer does not contain a string.
+		*pcWriteBuffer = 0x00;
+
+		// Take a snapshot of the number of tasks in case it changes while this
+		// function is executing.
+		uxArraySize = uxTaskGetNumberOfTasks();
+
+		// Allocate a TaskStatus_t structure for each task.  An array could be
+		// allocated statically at compile time.
+		pxTaskStatusArray = pvPortMalloc( uxArraySize * sizeof( TaskStatus_t ) );
+
+		if( pxTaskStatusArray != NULL )
+		{
+			// Generate raw status information about each task.
+			uxArraySize = uxTaskGetSystemState( pxTaskStatusArray, uxArraySize, &ulTotalRunTime );
+
+			// For percentage calculations.
+			ulTotalRunTime /= 100UL;
+
+			// Avoid divide by zero errors.
+			if( ulTotalRunTime > 0 )
+			{
+				// For each populated position in the pxTaskStatusArray array,
+				// format the raw data as human readable ASCII data
+				for( x = 0; x < uxArraySize; x++ )
+				{
+					// What percentage of the total run time has the task used?
+					// This will always be rounded down to the nearest integer.
+					// ulTotalRunTimeDiv100 has already been divided by 100.
+					ulStatsAsPercentage = pxTaskStatusArray[ x ].ulRunTimeCounter / ulTotalRunTime;
+
+					if( ulStatsAsPercentage > 0UL )
+					{
+						sprintf( pcWriteBuffer, "%s\t\t%lu\t\t%lu%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter, ulStatsAsPercentage );
+					}
+					else
+					{
+						// If the percentage is zero here then the task has
+						// consumed less than 1% of the total run time.
+						sprintf( pcWriteBuffer, "%s\t\t%lu\t\t<1%%\r\n", pxTaskStatusArray[ x ].pcTaskName, pxTaskStatusArray[ x ].ulRunTimeCounter );
+					}
+
+					pcWriteBuffer += strlen( ( char * ) pcWriteBuffer );
+				}
+			}
+
+			// The array is no longer needed, free the memory it consumes.
+			vPortFree( pxTaskStatusArray );
+		}
+	}
+	
+ */ +UBaseType_t uxTaskGetSystemState(TaskStatus_t *const pxTaskStatusArray, const UBaseType_t uxArraySize, uint32_t *const pulTotalRunTime) PRIVILEGED_FUNCTION; + +/** + * task. h + *
void vTaskList( char *pcWriteBuffer );
+ * + * configUSE_TRACE_FACILITY and configUSE_STATS_FORMATTING_FUNCTIONS must + * both be defined as 1 for this function to be available. See the + * configuration section of the FreeRTOS.org website for more information. + * + * NOTE 1: This function will disable interrupts for its duration. It is + * not intended for normal application runtime use but as a debug aid. + * + * Lists all the current tasks, along with their current state and stack + * usage high water mark. + * + * Tasks are reported as blocked ('B'), ready ('R'), deleted ('D') or + * suspended ('S'). + * + * PLEASE NOTE: + * + * This function is provided for convenience only, and is used by many of the + * demo applications. Do not consider it to be part of the scheduler. + * + * vTaskList() calls uxTaskGetSystemState(), then formats part of the + * uxTaskGetSystemState() output into a human readable table that displays task + * names, states and stack usage. + * + * vTaskList() has a dependency on the sprintf() C library function that might + * bloat the code size, use a lot of stack, and provide different results on + * different platforms. An alternative, tiny, third party, and limited + * functionality implementation of sprintf() is provided in many of the + * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note + * printf-stdarg.c does not provide a full snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() + * directly to get access to raw stats data, rather than indirectly through a + * call to vTaskList(). + * + * @param pcWriteBuffer A buffer into which the above mentioned details + * will be written, in ASCII form. This buffer is assumed to be large + * enough to contain the generated report. Approximately 40 bytes per + * task should be sufficient. + * + * \defgroup vTaskList vTaskList + * \ingroup TaskUtils + */ +void vTaskList(char *pcWriteBuffer) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * task. h + *
void vTaskGetRunTimeStats( char *pcWriteBuffer );
+ * + * configGENERATE_RUN_TIME_STATS and configUSE_STATS_FORMATTING_FUNCTIONS + * must both be defined as 1 for this function to be available. The application + * must also then provide definitions for + * portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() and portGET_RUN_TIME_COUNTER_VALUE() + * to configure a peripheral timer/counter and return the timers current count + * value respectively. The counter should be at least 10 times the frequency of + * the tick count. + * + * NOTE 1: This function will disable interrupts for its duration. It is + * not intended for normal application runtime use but as a debug aid. + * + * Setting configGENERATE_RUN_TIME_STATS to 1 will result in a total + * accumulated execution time being stored for each task. The resolution + * of the accumulated time value depends on the frequency of the timer + * configured by the portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() macro. + * Calling vTaskGetRunTimeStats() writes the total execution time of each + * task into a buffer, both as an absolute count value and as a percentage + * of the total system execution time. + * + * NOTE 2: + * + * This function is provided for convenience only, and is used by many of the + * demo applications. Do not consider it to be part of the scheduler. + * + * vTaskGetRunTimeStats() calls uxTaskGetSystemState(), then formats part of the + * uxTaskGetSystemState() output into a human readable table that displays the + * amount of time each task has spent in the Running state in both absolute and + * percentage terms. + * + * vTaskGetRunTimeStats() has a dependency on the sprintf() C library function + * that might bloat the code size, use a lot of stack, and provide different + * results on different platforms. An alternative, tiny, third party, and + * limited functionality implementation of sprintf() is provided in many of the + * FreeRTOS/Demo sub-directories in a file called printf-stdarg.c (note + * printf-stdarg.c does not provide a full snprintf() implementation!). + * + * It is recommended that production systems call uxTaskGetSystemState() directly + * to get access to raw stats data, rather than indirectly through a call to + * vTaskGetRunTimeStats(). + * + * @param pcWriteBuffer A buffer into which the execution times will be + * written, in ASCII form. This buffer is assumed to be large enough to + * contain the generated report. Approximately 40 bytes per task should + * be sufficient. + * + * \defgroup vTaskGetRunTimeStats vTaskGetRunTimeStats + * \ingroup TaskUtils + */ +void vTaskGetRunTimeStats(char *pcWriteBuffer) PRIVILEGED_FUNCTION; /*lint !e971 Unqualified char types are allowed for strings and single characters only. */ + +/** + * task. h + *
BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was + * already in the Blocked state to wait for a notification when the notification + * arrives then the task will automatically be removed from the Blocked state + * (unblocked) and the notification cleared. + * + * A task can use xTaskNotifyWait() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTake() to [optionally] block + * to wait for its notification value to have a non-zero value. The task does + * not consume any CPU time while it is in the Blocked state. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param xTaskToNotify The handle of the task being notified. The handle to a + * task can be returned from the xTaskCreate() API function used to create the + * task, and the handle of the currently running task can be obtained by calling + * xTaskGetCurrentTaskHandle(). + * + * @param ulValue Data that can be sent with the notification. How the data is + * used depends on the value of the eAction parameter. + * + * @param eAction Specifies how the notification updates the task's notification + * value, if at all. Valid values for eAction are as follows: + * + * eSetBits - + * The task's notification value is bitwise ORed with ulValue. xTaskNofify() + * always returns pdPASS in this case. + * + * eIncrement - + * The task's notification value is incremented. ulValue is not used and + * xTaskNotify() always returns pdPASS in this case. + * + * eSetValueWithOverwrite - + * The task's notification value is set to the value of ulValue, even if the + * task being notified had not yet processed the previous notification (the + * task already had a notification pending). xTaskNotify() always returns + * pdPASS in this case. + * + * eSetValueWithoutOverwrite - + * If the task being notified did not already have a notification pending then + * the task's notification value is set to ulValue and xTaskNotify() will + * return pdPASS. If the task being notified already had a notification + * pending then no action is performed and pdFAIL is returned. + * + * eNoAction - + * The task receives a notification without its notification value being + * updated. ulValue is not used and xTaskNotify() always returns pdPASS in + * this case. + * + * pulPreviousNotificationValue - + * Can be used to pass out the subject task's notification value before any + * bits are modified by the notify function. + * + * @return Dependent on the value of eAction. See the description of the + * eAction parameter. + * + * \defgroup xTaskNotify xTaskNotify + * \ingroup TaskNotifications + */ +BaseType_t xTaskGenericNotify(TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue) PRIVILEGED_FUNCTION; +#define xTaskNotify( xTaskToNotify, ulValue, eAction ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL ) +#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) + +/** + * task. h + *
BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * A version of xTaskNotify() that can be used from an interrupt service routine + * (ISR). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was + * already in the Blocked state to wait for a notification when the notification + * arrives then the task will automatically be removed from the Blocked state + * (unblocked) and the notification cleared. + * + * A task can use xTaskNotifyWait() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTake() to [optionally] block + * to wait for its notification value to have a non-zero value. The task does + * not consume any CPU time while it is in the Blocked state. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param xTaskToNotify The handle of the task being notified. The handle to a + * task can be returned from the xTaskCreate() API function used to create the + * task, and the handle of the currently running task can be obtained by calling + * xTaskGetCurrentTaskHandle(). + * + * @param ulValue Data that can be sent with the notification. How the data is + * used depends on the value of the eAction parameter. + * + * @param eAction Specifies how the notification updates the task's notification + * value, if at all. Valid values for eAction are as follows: + * + * eSetBits - + * The task's notification value is bitwise ORed with ulValue. xTaskNofify() + * always returns pdPASS in this case. + * + * eIncrement - + * The task's notification value is incremented. ulValue is not used and + * xTaskNotify() always returns pdPASS in this case. + * + * eSetValueWithOverwrite - + * The task's notification value is set to the value of ulValue, even if the + * task being notified had not yet processed the previous notification (the + * task already had a notification pending). xTaskNotify() always returns + * pdPASS in this case. + * + * eSetValueWithoutOverwrite - + * If the task being notified did not already have a notification pending then + * the task's notification value is set to ulValue and xTaskNotify() will + * return pdPASS. If the task being notified already had a notification + * pending then no action is performed and pdFAIL is returned. + * + * eNoAction - + * The task receives a notification without its notification value being + * updated. ulValue is not used and xTaskNotify() always returns pdPASS in + * this case. + * + * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set + * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the + * task to which the notification was sent to leave the Blocked state, and the + * unblocked task has a priority higher than the currently running task. If + * xTaskNotifyFromISR() sets this value to pdTRUE then a context switch should + * be requested before the interrupt is exited. How a context switch is + * requested from an ISR is dependent on the port - see the documentation page + * for the port in use. + * + * @return Dependent on the value of eAction. See the description of the + * eAction parameter. + * + * \defgroup xTaskNotify xTaskNotify + * \ingroup TaskNotifications + */ +BaseType_t xTaskGenericNotifyFromISR(TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken) PRIVILEGED_FUNCTION; +#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) ) +#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) + +/** + * task. h + *
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * A notification sent to a task will remain pending until it is cleared by the + * task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was + * already in the Blocked state to wait for a notification when the notification + * arrives then the task will automatically be removed from the Blocked state + * (unblocked) and the notification cleared. + * + * A task can use xTaskNotifyWait() to [optionally] block to wait for a + * notification to be pending, or ulTaskNotifyTake() to [optionally] block + * to wait for its notification value to have a non-zero value. The task does + * not consume any CPU time while it is in the Blocked state. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value + * will be cleared in the calling task's notification value before the task + * checks to see if any notifications are pending, and optionally blocks if no + * notifications are pending. Setting ulBitsToClearOnEntry to ULONG_MAX (if + * limits.h is included) or 0xffffffffUL (if limits.h is not included) will have + * the effect of resetting the task's notification value to 0. Setting + * ulBitsToClearOnEntry to 0 will leave the task's notification value unchanged. + * + * @param ulBitsToClearOnExit If a notification is pending or received before + * the calling task exits the xTaskNotifyWait() function then the task's + * notification value (see the xTaskNotify() API function) is passed out using + * the pulNotificationValue parameter. Then any bits that are set in + * ulBitsToClearOnExit will be cleared in the task's notification value (note + * *pulNotificationValue is set before any bits are cleared). Setting + * ulBitsToClearOnExit to ULONG_MAX (if limits.h is included) or 0xffffffffUL + * (if limits.h is not included) will have the effect of resetting the task's + * notification value to 0 before the function exits. Setting + * ulBitsToClearOnExit to 0 will leave the task's notification value unchanged + * when the function exits (in which case the value passed out in + * pulNotificationValue will match the task's notification value). + * + * @param pulNotificationValue Used to pass the task's notification value out + * of the function. Note the value passed out will not be effected by the + * clearing of any bits caused by ulBitsToClearOnExit being non-zero. + * + * @param xTicksToWait The maximum amount of time that the task should wait in + * the Blocked state for a notification to be received, should a notification + * not already be pending when xTaskNotifyWait() was called. The task + * will not consume any processing time while it is in the Blocked state. This + * is specified in kernel ticks, the macro pdMS_TO_TICSK( value_in_ms ) can be + * used to convert a time specified in milliseconds to a time specified in + * ticks. + * + * @return If a notification was received (including notifications that were + * already pending when xTaskNotifyWait was called) then pdPASS is + * returned. Otherwise pdFAIL is returned. + * + * \defgroup xTaskNotifyWait xTaskNotifyWait + * \ingroup TaskNotifications + */ +BaseType_t xTaskNotifyWait(uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait) PRIVILEGED_FUNCTION; + +/** + * task. h + *
BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro + * to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * xTaskNotifyGive() is a helper macro intended for use when task notifications + * are used as light weight and faster binary or counting semaphore equivalents. + * Actual FreeRTOS semaphores are given using the xSemaphoreGive() API function, + * the equivalent action that instead uses a task notification is + * xTaskNotifyGive(). + * + * When task notifications are being used as a binary or counting semaphore + * equivalent then the task being notified should wait for the notification + * using the ulTaskNotificationTake() API function rather than the + * xTaskNotifyWait() API function. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details. + * + * @param xTaskToNotify The handle of the task being notified. The handle to a + * task can be returned from the xTaskCreate() API function used to create the + * task, and the handle of the currently running task can be obtained by calling + * xTaskGetCurrentTaskHandle(). + * + * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the + * eAction parameter set to eIncrement - so pdPASS is always returned. + * + * \defgroup xTaskNotifyGive xTaskNotifyGive + * \ingroup TaskNotifications + */ +#define xTaskNotifyGive( xTaskToNotify ) xTaskGenericNotify( ( xTaskToNotify ), ( 0 ), eIncrement, NULL ) + +/** + * task. h + *
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro
+ * to be available.
+ *
+ * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private
+ * "notification value", which is a 32-bit unsigned integer (uint32_t).
+ *
+ * A version of xTaskNotifyGive() that can be called from an interrupt service
+ * routine (ISR).
+ *
+ * Events can be sent to a task using an intermediary object.  Examples of such
+ * objects are queues, semaphores, mutexes and event groups.  Task notifications
+ * are a method of sending an event directly to a task without the need for such
+ * an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment the task's notification value.  In that way
+ * task notifications can be used to send data to a task, or be used as light
+ * weight and fast binary or counting semaphores.
+ *
+ * vTaskNotifyGiveFromISR() is intended for use when task notifications are
+ * used as light weight and faster binary or counting semaphore equivalents.
+ * Actual FreeRTOS semaphores are given from an ISR using the
+ * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses
+ * a task notification is vTaskNotifyGiveFromISR().
+ *
+ * When task notifications are being used as a binary or counting semaphore
+ * equivalent then the task being notified should wait for the notification
+ * using the ulTaskNotificationTake() API function rather than the
+ * xTaskNotifyWait() API function.
+ *
+ * See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details.
+ *
+ * @param xTaskToNotify The handle of the task being notified.  The handle to a
+ * task can be returned from the xTaskCreate() API function used to create the
+ * task, and the handle of the currently running task can be obtained by calling
+ * xTaskGetCurrentTaskHandle().
+ *
+ * @param pxHigherPriorityTaskWoken  vTaskNotifyGiveFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
+ * task to which the notification was sent to leave the Blocked state, and the
+ * unblocked task has a priority higher than the currently running task.  If
+ * vTaskNotifyGiveFromISR() sets this value to pdTRUE then a context switch
+ * should be requested before the interrupt is exited.  How a context switch is
+ * requested from an ISR is dependent on the port - see the documentation page
+ * for the port in use.
+ *
+ * \defgroup xTaskNotifyWait xTaskNotifyWait
+ * \ingroup TaskNotifications
+ */
+void vTaskNotifyGiveFromISR(TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken) PRIVILEGED_FUNCTION;
+
+/**
+ * task. h
+ * 
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
+ * + * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this + * function to be available. + * + * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private + * "notification value", which is a 32-bit unsigned integer (uint32_t). + * + * Events can be sent to a task using an intermediary object. Examples of such + * objects are queues, semaphores, mutexes and event groups. Task notifications + * are a method of sending an event directly to a task without the need for such + * an intermediary object. + * + * A notification sent to a task can optionally perform an action, such as + * update, overwrite or increment the task's notification value. In that way + * task notifications can be used to send data to a task, or be used as light + * weight and fast binary or counting semaphores. + * + * ulTaskNotifyTake() is intended for use when a task notification is used as a + * faster and lighter weight binary or counting semaphore alternative. Actual + * FreeRTOS semaphores are taken using the xSemaphoreTake() API function, the + * equivalent action that instead uses a task notification is + * ulTaskNotifyTake(). + * + * When a task is using its notification value as a binary or counting semaphore + * other tasks should send notifications to it using the xTaskNotifyGive() + * macro, or xTaskNotify() function with the eAction parameter set to + * eIncrement. + * + * ulTaskNotifyTake() can either clear the task's notification value to + * zero on exit, in which case the notification value acts like a binary + * semaphore, or decrement the task's notification value on exit, in which case + * the notification value acts like a counting semaphore. + * + * A task can use ulTaskNotifyTake() to [optionally] block to wait for a + * the task's notification value to be non-zero. The task does not consume any + * CPU time while it is in the Blocked state. + * + * Where as xTaskNotifyWait() will return when a notification is pending, + * ulTaskNotifyTake() will return when the task's notification value is + * not zero. + * + * See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. + * + * @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's + * notification value is decremented when the function exits. In this way the + * notification value acts like a counting semaphore. If xClearCountOnExit is + * not pdFALSE then the task's notification value is cleared to zero when the + * function exits. In this way the notification value acts like a binary + * semaphore. + * + * @param xTicksToWait The maximum amount of time that the task should wait in + * the Blocked state for the task's notification value to be greater than zero, + * should the count not already be greater than zero when + * ulTaskNotifyTake() was called. The task will not consume any processing + * time while it is in the Blocked state. This is specified in kernel ticks, + * the macro pdMS_TO_TICSK( value_in_ms ) can be used to convert a time + * specified in milliseconds to a time specified in ticks. + * + * @return The task's notification count before it is either cleared to zero or + * decremented (see the xClearCountOnExit parameter). + * + * \defgroup ulTaskNotifyTake ulTaskNotifyTake + * \ingroup TaskNotifications + */ +uint32_t ulTaskNotifyTake(BaseType_t xClearCountOnExit, TickType_t xTicksToWait) PRIVILEGED_FUNCTION; + +/** + * task. h + *
BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );
+ * + * If the notification state of the task referenced by the handle xTask is + * eNotified, then set the task's notification state to eNotWaitingNotification. + * The task's notification value is not altered. Set xTask to NULL to clear the + * notification state of the calling task. + * + * @return pdTRUE if the task's notification state was set to + * eNotWaitingNotification, otherwise pdFALSE. + * \defgroup xTaskNotifyStateClear xTaskNotifyStateClear + * \ingroup TaskNotifications + */ +BaseType_t xTaskNotifyStateClear(TaskHandle_t xTask); + +/*----------------------------------------------------------- + * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES + *----------------------------------------------------------*/ + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY + * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS + * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * Called from the real time kernel tick (either preemptive or cooperative), + * this increments the tick count and checks if any tasks that are blocked + * for a finite period required removing from a blocked list and placing on + * a ready list. If a non-zero value is returned then a context switch is + * required because either: + * + A task was removed from a blocked list because its timeout had expired, + * or + * + Time slicing is in use and there is a task of equal priority to the + * currently running task. + */ +BaseType_t xTaskIncrementTick(void) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * Removes the calling task from the ready list and places it both + * on the list of tasks waiting for a particular event, and the + * list of delayed tasks. The task will be removed from both lists + * and replaced on the ready list should either the event occur (and + * there be no higher priority tasks waiting on the same event) or + * the delay period expires. + * + * The 'unordered' version replaces the event list item value with the + * xItemValue value, and inserts the list item at the end of the list. + * + * The 'ordered' version uses the existing event list item value (which is the + * owning tasks priority) to insert the list item into the event list is task + * priority order. + * + * @param pxEventList The list containing tasks that are blocked waiting + * for the event to occur. + * + * @param xItemValue The item value to use for the event list item when the + * event list is not ordered by task priority. + * + * @param xTicksToWait The maximum amount of time that the task should wait + * for the event to occur. This is specified in kernel ticks,the constant + * portTICK_PERIOD_MS can be used to convert kernel ticks into a real time + * period. + */ +void vTaskPlaceOnEventList(List_t *const pxEventList, const TickType_t xTicksToWait) PRIVILEGED_FUNCTION; +void vTaskPlaceOnUnorderedEventList(List_t *pxEventList, const TickType_t xItemValue, const TickType_t xTicksToWait) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * This function performs nearly the same function as vTaskPlaceOnEventList(). + * The difference being that this function does not permit tasks to block + * indefinitely, whereas vTaskPlaceOnEventList() does. + * + */ +void vTaskPlaceOnEventListRestricted(List_t *const pxEventList, TickType_t xTicksToWait, const BaseType_t xWaitIndefinitely) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS AN + * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED. + * + * Removes a task from both the specified event list and the list of blocked + * tasks, and places it on a ready queue. + * + * xTaskRemoveFromEventList()/xTaskRemoveFromUnorderedEventList() will be called + * if either an event occurs to unblock a task, or the block timeout period + * expires. + * + * xTaskRemoveFromEventList() is used when the event list is in task priority + * order. It removes the list item from the head of the event list as that will + * have the highest priority owning task of all the tasks on the event list. + * xTaskRemoveFromUnorderedEventList() is used when the event list is not + * ordered and the event list items hold something other than the owning tasks + * priority. In this case the event list item value is updated to the value + * passed in the xItemValue parameter. + * + * @return pdTRUE if the task being removed has a higher priority than the task + * making the call, otherwise pdFALSE. + */ +BaseType_t xTaskRemoveFromEventList(const List_t *const pxEventList) PRIVILEGED_FUNCTION; +BaseType_t xTaskRemoveFromUnorderedEventList(ListItem_t *pxEventListItem, const TickType_t xItemValue) PRIVILEGED_FUNCTION; + +/* + * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE. IT IS ONLY + * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS + * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER. + * + * Sets the pointer to the current TCB to the TCB of the highest priority task + * that is ready to run. + */ +int xTaskSwitchContext(void) PRIVILEGED_FUNCTION; + +/* + * THESE FUNCTIONS MUST NOT BE USED FROM APPLICATION CODE. THEY ARE USED BY + * THE EVENT BITS MODULE. + */ +TickType_t uxTaskResetEventItemValue(void) PRIVILEGED_FUNCTION; + +/* + * Return the handle of the calling task. + */ +TaskHandle_t xTaskGetCurrentTaskHandle(void) PRIVILEGED_FUNCTION; + +/* + * Capture the current time status for future reference. + */ +void vTaskSetTimeOutState(TimeOut_t *const pxTimeOut) PRIVILEGED_FUNCTION; + +/* + * Compare the time status now with that previously captured to see if the + * timeout has expired. + */ +BaseType_t xTaskCheckForTimeOut(TimeOut_t *const pxTimeOut, TickType_t *const pxTicksToWait) PRIVILEGED_FUNCTION; + +/* + * Shortcut used by the queue implementation to prevent unnecessary call to + * taskYIELD(); + */ +void vTaskMissedYield(void) PRIVILEGED_FUNCTION; + +/* + * Returns the scheduler state as taskSCHEDULER_RUNNING, + * taskSCHEDULER_NOT_STARTED or taskSCHEDULER_SUSPENDED. + */ +BaseType_t xTaskGetSchedulerState(void) PRIVILEGED_FUNCTION; + +/* + * Raises the priority of the mutex holder to that of the calling task should + * the mutex holder have a priority less than the calling task. + */ +void vTaskPriorityInherit(TaskHandle_t const pxMutexHolder) PRIVILEGED_FUNCTION; + +/* + * Set the priority of a task back to its proper priority in the case that it + * inherited a higher priority while it was holding a semaphore. + */ +BaseType_t xTaskPriorityDisinherit(TaskHandle_t const pxMutexHolder) PRIVILEGED_FUNCTION; + +/* + * Get the uxTCBNumber assigned to the task referenced by the xTask parameter. + */ +UBaseType_t uxTaskGetTaskNumber(TaskHandle_t xTask) PRIVILEGED_FUNCTION; + +/* + * Set the uxTaskNumber of the task referenced by the xTask parameter to + * uxHandle. + */ +void vTaskSetTaskNumber(TaskHandle_t xTask, const UBaseType_t uxHandle) PRIVILEGED_FUNCTION; + +/* + * Only available when configUSE_TICKLESS_IDLE is set to 1. + * If tickless mode is being used, or a low power mode is implemented, then + * the tick interrupt will not execute during idle periods. When this is the + * case, the tick count value maintained by the scheduler needs to be kept up + * to date with the actual execution time by being skipped forward by a time + * equal to the idle period. + */ +void vTaskStepTick(const TickType_t xTicksToJump) PRIVILEGED_FUNCTION; + +TickType_t xGetExpectedIdleTime(void) PRIVILEGED_FUNCTION; +/* + * Only avilable when configUSE_TICKLESS_IDLE is set to 1. + * Provided for use within portSUPPRESS_TICKS_AND_SLEEP() to allow the port + * specific sleep function to determine if it is ok to proceed with the sleep, + * and if it is ok to proceed, if it is ok to sleep indefinitely. + * + * This function is necessary because portSUPPRESS_TICKS_AND_SLEEP() is only + * called with the scheduler suspended, not from within a critical section. It + * is therefore possible for an interrupt to request a context switch between + * portSUPPRESS_TICKS_AND_SLEEP() and the low power mode actually being + * entered. eTaskConfirmSleepModeStatus() should be called from a short + * critical section between the timer being stopped and the sleep mode being + * entered to ensure it is ok to proceed into the sleep mode. + */ +eSleepModeStatus eTaskConfirmSleepModeStatus(void) PRIVILEGED_FUNCTION; + +/* + * For internal use only. Increment the mutex held count when a mutex is + * taken and return the handle of the task that has taken the mutex. + */ +void *pvTaskIncrementMutexHeldCount(void) PRIVILEGED_FUNCTION; + +void vPortStartFirstTask(void) ; + +// TickType_t prvGetExpectedIdleTime(void) PRIVILEGED_FUNCTION; +TickType_t xGetExpectedIdleTime(void); + +void *uxTaskStack(void *tcb); + +#ifdef __cplusplus +} +#endif +#endif /* INC_TASK_H */ + + + diff --git a/include_lib/system/os/os_api.h b/include_lib/system/os/os_api.h new file mode 100644 index 0000000..cffab3d --- /dev/null +++ b/include_lib/system/os/os_api.h @@ -0,0 +1,448 @@ +#ifndef OS_API_H +#define OS_API_H + + +#ifdef __cplusplus +extern "C" +{ +#endif + + + + +#include "generic/typedef.h" +//#include "generic/list.h" +#include "os/os_cpu.h" +#include "os/os_error.h" +#include "os/os_type.h" + + + +#define Q_MSG 0x100000 +#define Q_EVENT 0x200000 +#define Q_CALLBACK 0x300000 +#define Q_USER 0x400000 + +#define OS_DEL_NO_PEND 0u +#define OS_DEL_ALWAYS 1u + +#define OS_TASK_DEL_REQ 0x01u +#define OS_TASK_DEL_RES 0x02u +#define OS_TASK_DEL_OK 0x03u + + +#define OS_TASK_SELF (char *)0x1 +#define OS_TASK_FATHER (char *)0x2 + + +#define OS_MSG_KEY 1 +#define OS_MSG_TOUCH 2 +#define OS_MSG_EVENT 3 +#define OS_MSG_CALLBACK 4 +#define OS_MSG_DEL_REQ 5 +#define OS_MSG_MSG 6 + + +/*struct os_msg { + int type; + int msg; + int err; + u8 deleted; + char ref; + OS_SEM sem; + OS_MUTEX mutex; + struct list_head entry; + u32 data[0]; +};*/ + +/*struct os_msg_callback { + struct os_msg msg; + u8 argc; + u8 sync; + u8 arg_exp; + int argv[8]; + void *function; +};*/ + +#ifdef CONFIG_CPU_BR25 +void *os_init(); +#else +void os_init(); +#endif +void os_start(void); +void os_init_tick(int); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :创建任务 + * + * @Param task :任务回调函数 + * @Param p_arg :传递给任务回调函数的参数 + * @Param prio :任务的优先级 + * @Param stksize :任务的堆栈大小, 单位(u32) + * @Param qsize :任务的queue大小,单位(byte) + * @Param name :任务名 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_task_create(void (*task)(void *p_arg), + void *p_arg, + u8 prio, + u32 stksize, + int qsize, + const char *name); + + +/* --------------------------------------------------------------------------*/ +/** + * @brief :获取当前任务名 + * + * @Returns :当前任务名 + */ +/* ----------------------------------------------------------------------------*/ +const char *os_current_task(); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :删除任务 + * + * @Param name :任务名 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_task_del_req(const char *name); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :响应任务删除请求,标记资源已经释放,可以删除当前任 + * + * @Param name: 任务名,任务自己可以用OS_TASK_SELF + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_task_del_res(const char *name); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :删除任务 + * + * @Param name :任务名 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_task_del(const char *name); + + +/* --------------------------------------------------------------------------*/ +/** + * @brief :延时。中断函数或者关闭系统总中断的情况下不能调用此函数 + * + * @Param time_tick :延时时间 + */ +/* ----------------------------------------------------------------------------*/ +void os_time_dly(int time_tick); + + +/* --------------------------------------------------------------------------*/ +/** + * @brief :发送Q_USER类型taskq + * + * @Param name :任务名 + * @Param argc :后面传入的参数的个数。发送的最大参数个数限制为8个int类型 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_taskq_post(const char *name, int argc, ...); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :非阻塞方式查询taskq + * + * @Param argc :最大可获取的queue长度,单位(int) + * @Param argv :存放queue的buf + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_taskq_accept(int argc, int *argv); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :阻塞方式获取taskq + * + * @Param fmt :保留,传NULL + * @Param argv :存放queue的buf + * @Param argc :最大可获取的queue长度,单位(int) + * @Param tick :阻塞时长,0表示一直阻塞 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_taskq_pend(const char *fmt, int *argv, int argc); +int os_task_pend(const char *fmt, int *argv, int argc); +int __os_taskq_pend(int *argv, int argc, int tick); + + + +/* --------------------------------------------------------------------------*/ +/** + * @brief :发送指定类型的taskq + * + * @Param name :任务名 + * @Param type :queue类型 + * @Param argc :后面传入的参数的个数 + * @Param argv + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_taskq_post_type(const char *name, int type, int argc, int *argv); + + +/* --------------------------------------------------------------------------*/ +/** + * @brief :发送Q_MSG类型的taskq + * + * @Param name :任务名 + * @Param argc :后面参数的个数 + * @Param ... + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_taskq_post_msg(const char *name, int argc, ...); + + +/* --------------------------------------------------------------------------*/ +/** + * @brief :发送Q_EVENT类型的taskq + * + * @Param name :任务名 + * @Param argc :后面参数的个数 + * @Param ... + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_taskq_post_event(const char *name, int argc, ...); + + +/* --------------------------------------------------------------------------*/ +/** + * @brief :删除指定类型的taskq + * + * @Param name :任务名 + * @Param type :taskq的类型 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_taskq_del_type(const char *name, int type); +int os_taskq_del(const char *name, int type); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :清除所有taskq + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_taskq_flush(); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :创建信号量 + * + * @Param sem:信号量 + * @Param int:初始计数值 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_sem_create(OS_SEM *, int); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :非阻塞方式查询信号量 + * + * @Param sem :信号量 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_sem_accept(OS_SEM *); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :阻塞方式获取信号量 + * + * @Param sem:信号量 + * @Param timeout:等待时长,0表示一直等待 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_sem_pend(OS_SEM *, int timeout); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :发送信号量 + * + * @Param sem:信号量 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_sem_post(OS_SEM *); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :信号量删除 + * + * @Param sem:信号量 + * @Param block:保留 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_sem_del(OS_SEM *, int block); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :信号量设置 + * + * @Param sem:信号量 + * @Param cnt:计数值 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_sem_set(OS_SEM *, u16 cnt); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :信号量类型是否queueQUEUE_TYPE_COUNTING_SEMAPHORE + * + * @Param : true:信号量匹配, fail:信号量不匹配 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_sem_valid(OS_SEM *); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :判断信号量是否可用 + * + * @Param sem:信号量 + * + * @Returns :可用数量 + */ +/* ----------------------------------------------------------------------------*/ +int os_sem_query(OS_SEM *); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :创建互斥量 + * + * @Param mutex: 互斥量 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_mutex_create(OS_MUTEX *); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :非阻塞方式查询互斥量 + * + * @Param mutex:互斥量 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_mutex_accept(OS_MUTEX *); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :阻塞方式查询互斥量 + * + * @Param mutex:互斥量 + * @Param timeout:等待时间,0表示一直等待 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_mutex_pend(OS_MUTEX *, int timeout); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :发送斥量 + * + * @Param mutex:互斥量 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_mutex_post(OS_MUTEX *); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :删除斥量 + * + * @Param mutex:互斥量 + * @Param block:保留 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_mutex_del(OS_MUTEX *, int block); + +/* --------------------------------------------------------------------------*/ +/** + * @brief :互斥量类型是否queueQUEUE_TYPE_MUTEX + * + * @Param : true:互斥量匹配, fail:互斥量不匹配 + * + * @Returns :错误码 + */ +/* ----------------------------------------------------------------------------*/ +int os_mutex_valid(OS_MUTEX *); + +/*struct os_msg *os_message_create(int size); + +int os_message_receive(struct os_msg **msg, int block_time); + +int os_message_send(const char *task_name, struct os_msg *msg, int msgflg); + +int os_message_delete(struct os_msg *msg);*/ + + + +int os_q_create(OS_QUEUE *pevent, /*void **start, */QS size); + +int os_q_del(OS_QUEUE *pevent, u8 opt); + +int os_q_flush(OS_QUEUE *pevent); + +int os_q_pend(OS_QUEUE *pevent, int timeout, void *msg); + +int os_q_post(OS_QUEUE *pevent, void *msg); + +int os_q_query(OS_QUEUE *pevent); + +int os_q_valid(OS_QUEUE *pevent); + +int task_queue_post_event(const char *name, void *data, int len); + +void *os_task_get_handle(const char *name); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include_lib/system/os/os_cpu.h b/include_lib/system/os/os_cpu.h new file mode 100644 index 0000000..c5ef3ca --- /dev/null +++ b/include_lib/system/os/os_cpu.h @@ -0,0 +1,82 @@ +/***********************************Jieli tech************************************************ + File : os_cpu.h + By : Juntham + date : 2014-07-03 09:06 +********************************************************************************************/ +#ifndef _OS_CPU_H +#define _OS_CPU_H + +#include "asm/cpu.h" +#include "jiffies.h" + + +#ifndef __ASSEMBLY__ +typedef unsigned short QS; +typedef unsigned int OS_STK; /* Each stack entry is 32-bit wide*/ +typedef unsigned int OS_CPU_SR; /* Unsigned 32 bit quantity */ +typedef unsigned int OS_CPU_DATA; /* Unsigned 32 bit quantity */ +#endif + +#define OS_CPU_EXT extern +#define OS_CPU_CORE CPU_CORE_NUM + +#define OS_CPU_ID current_cpu_id() +#define OS_STK_GROWTH 1 /* Stack grows from HIGH to LOW memory*/ + +#define OS_CPU_MMU 0 + + +#define CPU_SR_ALLOC() + +#define OS_SR_ALLOC() + +#define OS_ENTER_CRITICAL() \ + CPU_CRITICAL_ENTER(); \ + +#define OS_EXIT_CRITICAL() \ + CPU_CRITICAL_EXIT() + + + + +#ifndef __ASSEMBLY__ + +/*#include "system/spinlock.h" + +extern spinlock_t os_lock; + +#define OS_ENTER_CRITICAL() \ + spin_lock(&os_lock) + +#define OS_EXIT_CRITICAL() \ + spin_unlock(&os_lock)*/ + + +void OSCtxSw(void); + +extern void EnableOtherCpu(void) ; + +#define os_ctx_sw OSCtxSw + +void OSInitTick(u32 hz); + +void InstallOSISR(void); + +void os_task_dead(const char *task_name); +#endif + +/* +********************************************************************************************************* +* DATA TYPES +* (Compiler Specific) +********************************************************************************************************* +*/ + + +#define OS_CRITICAL_METHOD 3 +#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */ +//#define CPU_SR_ALLOC() OS_CPU_SR cpu_sr +#endif + + +#endif /*_OS_CPU_H */ diff --git a/include_lib/system/os/os_error.h b/include_lib/system/os/os_error.h new file mode 100644 index 0000000..f8e06b0 --- /dev/null +++ b/include_lib/system/os/os_error.h @@ -0,0 +1,79 @@ +#ifndef __OS_ERROR_H__ +#define __OS_ERROR_H__ + +#define OS_ERR_NONE 0 + + +enum { + OS_NO_ERR = 0, + OS_TRUE, + OS_ERR_EVENT_TYPE, + OS_ERR_PEND_ISR, + OS_ERR_POST_NULL_PTR, + OS_ERR_PEVENT_NULL, + OS_ERR_POST_ISR, + OS_ERR_QUERY_ISR, + OS_ERR_INVALID_OPT, + OS_ERR_TASK_WAITING, + OS_ERR_PDATA_NULL, + OS_TIMEOUT, + OS_TIMER, + OS_TASKQ, + OS_TASK_NOT_EXIST, + OS_ERR_EVENT_NAME_TOO_LONG, + OS_ERR_FLAG_NAME_TOO_LONG, + OS_ERR_TASK_NAME_TOO_LONG, + OS_ERR_PNAME_NULL, + OS_ERR_TASK_CREATE_ISR, + OS_MBOX_FULL, + OS_Q_FULL, + OS_Q_EMPTY, + OS_Q_ERR, + OS_ERR_NO_QBUF, + OS_PRIO_EXIST, + OS_PRIO_ERR, + OS_PRIO_INVALID, + OS_SEM_OVF, + OS_TASK_DEL_ERR, + OS_TASK_DEL_IDLE, + OS_TASK_DEL_ISR, + OS_NO_MORE_TCB, + OS_TIME_NOT_DLY, + OS_TIME_INVALID_MINUTES, + OS_TIME_INVALID_SECONDS, + OS_TIME_INVALID_MILLI, + OS_TIME_ZERO_DLY, + OS_TASK_SUSPEND_PRIO, + OS_TASK_SUSPEND_IDLE, + OS_TASK_RESUME_PRIO, + OS_TASK_NOT_SUSPENDED, + OS_MEM_INVALID_PART, + OS_MEM_INVALID_BLKS, + OS_MEM_INVALID_SIZE, + OS_MEM_NO_FREE_BLKS, + OS_MEM_FULL, + OS_MEM_INVALID_PBLK, + OS_MEM_INVALID_PMEM, + OS_MEM_INVALID_PDATA, + OS_MEM_INVALID_ADDR, + OS_MEM_NAME_TOO_LONG, + OS_ERR_MEM_NO_MEM, + OS_ERR_NOT_MUTEX_OWNER, + OS_TASK_OPT_ERR, + OS_ERR_DEL_ISR, + OS_ERR_CREATE_ISR, + OS_FLAG_INVALID_PGRP, + OS_FLAG_ERR_WAIT_TYPE, + OS_FLAG_ERR_NOT_RDY, + OS_FLAG_INVALID_OPT, + OS_FLAG_GRP_DEPLETED, + OS_ERR_PIP_LOWER, + OS_ERR_MSG_POOL_EMPTY, + OS_ERR_MSG_POOL_NULL_PTR, + OS_ERR_MSG_POOL_FULL, + +}; + + +#endif + diff --git a/include_lib/system/os/os_type.h b/include_lib/system/os/os_type.h new file mode 100644 index 0000000..8267c57 --- /dev/null +++ b/include_lib/system/os/os_type.h @@ -0,0 +1,61 @@ +#ifndef __OS_TYPE_H +#define __OS_TYPE_H + + +#define OS_TICKS_PER_SEC 100 + +#if defined CONFIG_UCOS_ENABLE + + +#define OS_EVENT_TYPE_UNUSED 0u +#define OS_EVENT_TYPE_Q 1u +#define OS_EVENT_TYPE_SEM 2u +#define OS_EVENT_TYPE_MUTEX 3u + +typedef struct { + unsigned char OSEventType; + int aa; + void *bb; + unsigned char value; + unsigned char prio; + unsigned short cc; +} OS_SEM, OS_MUTEX, OS_QUEUE; + + +#elif defined CONFIG_FREE_RTOS_ENABLE + +#include "FreeRTOS/FreeRTOS.h" +#include "FreeRTOS/semphr.h" +#include "FreeRTOS/task.h" + +typedef StaticSemaphore_t OS_SEM, OS_MUTEX; +typedef StaticQueue_t OS_QUEUE; + + + + +#else +#error "no_os_defined" +#endif + + + + + + + + + + + + + + + + + + + + + +#endif diff --git a/include_lib/system/power_manage.h b/include_lib/system/power_manage.h new file mode 100644 index 0000000..f937eec --- /dev/null +++ b/include_lib/system/power_manage.h @@ -0,0 +1,103 @@ +#ifndef __POWER_MANAGE_H_ +#define __POWER_MANAGE_H_ + +#include "generic/typedef.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + DEVICE_EVENT_POWER_SHUTDOWN = 0x10, + DEVICE_EVENT_POWER_STARTUP, + DEVICE_EVENT_POWER_PERCENT, + DEVICE_EVENT_POWER_CHARGER_IN, + DEVICE_EVENT_POWER_CHARGER_OUT +}; + +#define PWR_SCAN_TIMES 3 + +#define PWR_DELAY_INFINITE 0xffffffff + +#define PWR_WKUP_PORT "wkup_port" +#define PWR_WKUP_ALARM "wkup_alarm" +#define PWR_WKUP_PWR_ON "wkup_pwr_on" +#define PWR_WKUP_ABNORMAL "wkup_abnormal" +#define PWR_WKUP_SHORT_KEY "wkup_short_key" + +struct sys_power_hal_ops { + void (*init)(void); + void (*poweroff)(void *arg); + int (*wakeup_check)(char *reason, int max_len); + int (*port_wakeup_config)(const char *port, int enable); + int (*alarm_wakeup_config)(u32 sec, int enable); + int (*get_battery_voltage)(void); + int (*get_battery_percent)(void); + int (*charger_online)(void); +}; + +extern const struct sys_power_hal_ops sys_power_hal_ops_begin[]; +extern const struct sys_power_hal_ops sys_power_hal_ops_end[]; + +#define REGISTER_SYS_POWER_HAL_OPS(ops) \ + static const struct sys_power_hal_ops ops sec(.sys_power_hal_ops) + + +void sys_power_early_init(); +/* + * @brief 断电关机,不释放资源 + */ +void sys_power_poweroff(void *arg); +/* + * @brief 软关机,触发DEVICE_EVENT_POWER_SHUTDOWN事件,app捕获事件释放资源再调用sys_power_poweroff() + */ +void sys_power_shutdown(); + +int sys_power_set_port_wakeup(const char *port, int enable); + +int sys_power_set_alarm_wakeup(u32 sec, int enable); + +const char *sys_power_get_wakeup_reason(); + +void sys_power_clr_wakeup_reason(const char *str); + +int sys_power_get_battery_voltage(); + +int sys_power_get_battery_persent(); + +int sys_power_is_charging(); + +int sys_power_charger_online(void); +/* + * @brief 倒计时自动关机 + * @parm dly_secs 延时关机时间,赋值0为永不关机 + * @return none + */ +void sys_power_auto_shutdown_start(u32 dly_secs); +void sys_power_auto_shutdown_pause(); +void sys_power_auto_shutdown_resume(); +void sys_power_auto_shutdown_clear(); +void sys_power_auto_shutdown_stop(); + + +int sys_power_low_voltage(u32 voltage); + +/* + * @brief 低电延时关机 + * @parm p_low_percent 低电电量百分比 + * @parm dly_secs 延时关机时间,赋值0为立即关机,赋值PWR_DELAY_INFINITE为永不关机 + * @return none + */ +void sys_power_low_voltage_shutdown(u32 voltage, u32 dly_secs); +/* + * @brief 插拔延时关机 + * @parm dly_secs 延时关机时间,赋值0为立即关机,赋值PWR_DELAY_INFINITE为永不关机 + * @return none + */ +void sys_power_charger_off_shutdown(u32 dly_secs); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/include_lib/system/server/server_core.h b/include_lib/system/server/server_core.h new file mode 100644 index 0000000..dada5f4 --- /dev/null +++ b/include_lib/system/server/server_core.h @@ -0,0 +1,85 @@ +#ifndef SERVER_H +#define SERVER_H + +#include "generic/typedef.h" +#include "system/task.h" +#include "spinlock.h" +#include "list.h" + + +#define REQ_COMPLETE_CALLBACK 0x01000000 +#define REQ_WAIT_COMPLETE 0x02000000 +#define REQ_HI_PRIORITY 0x04000000 + + +#define REQ_TYPE_MASK 0x00ffffff + + +struct server_req { + int type; + int err; + void *server_priv; + struct list_head entry; + struct server *server; + void *user; + const char *owner; + OS_SEM sem; + union { + int state; + void (*func)(void *, void *, int); + } complete; + u32 arg[0]; +}; + + +struct server_info { + const char *name; + u16 reqlen; + u8 reqnum; + void *(*open)(void *, void *); + void (*close)(void *); +}; + +#define REQ_BUF_LEN 512 + +struct server { + bool avaliable; + void *server; + OS_SEM sem; + OS_MUTEX mutex; + spinlock_t lock; + struct list_head *req_buf; + struct list_head free; + struct list_head pending; + const struct server_info *info; + const char *owner; + void *handler_priv; + void (*event_handler)(void *, int argc, int *argv); +}; + + + +#define SERVER_REGISTER(info) \ + const struct server_info info sec(.server_info) + + +#define server_load(server) \ + load_module(server) + +struct server *server_open(const char *name, void *arg); + +void server_register_event_handler(struct server *server, void *priv, + void (*handler)(void *, int argc, int *argv)); + +void server_close(struct server *server); + +int server_request(struct server *server, int req_type, void *arg); + +int server_request_async(struct server *server, int req_type, void *arg, ...); + +int server_req_complete(struct server_req *req); + +int server_event_handler(void *_server, int argc, int *argv); + +#endif + diff --git a/include_lib/system/spi/nor_fs.h b/include_lib/system/spi/nor_fs.h new file mode 100644 index 0000000..c245574 --- /dev/null +++ b/include_lib/system/spi/nor_fs.h @@ -0,0 +1,101 @@ +/***********************************Jieli tech************************************************ + File : nor_fs.h + By : Huxi + Email: xi_hu@zh-jieli.com + date : 2016-11-30 14:30 +********************************************************************************************/ +#ifndef _NOR_FS_H_ +#define _NOR_FS_H_ + +// #include "sdk_cfg.h" +#include "typedef.h" +// #include "system/includes.h" + +// #define SPI_REC_EN 1 + +#define NORFS_DATA_LEN 16 + +#define REC_FILE_END 0xFE + + +//文件索引 +typedef struct __RECF_INDEX_INFO { + u16 index; //文件索引号 + u16 sector; //文件所在扇区 +} RECF_INDEX_INFO ; + +#define FLASH_PAGE_SIZE 256 +//文件系统句柄 +typedef struct __RECFILESYSTEM { + RECF_INDEX_INFO index; + u8 buf[FLASH_PAGE_SIZE]; + u16 total_file; + u16 first_sector; + u16 last_sector; + // u8 *buf; + u8 sector_size; + void (*eraser)(u32 address); + s32(*read)(u8 *buf, u32 addr, u32 len); + s32(*write)(u8 *buf, u32 addr, u32 len); +} RECFILESYSTEM, *PRECFILESYSTEM ; + + + +//文件句柄 +typedef struct __REC_FILE { + RECF_INDEX_INFO index; + RECFILESYSTEM *pfs; + u32 addr; + char priv_data[NORFS_DATA_LEN]; + u32 len; + u32 w_len; + u32 rw_p; + u16 sr; +} REC_FILE; + +enum { + NOR_FS_SEEK_SET = 0, + NOR_FS_SEEK_CUR = 0x01 +}; +// enum { +// NOR_FS_SEEK_SET = 0x01, +// NOR_FS_SEEK_CUR = 0x02 +// }; + + +typedef struct __nor_fs_hdl { + u16 index; + RECFILESYSTEM *recfs; + REC_FILE *recfile; +} NOR_FS_HDL; + + +u8 recf_seek(REC_FILE *pfile, u8 type, int offsize); +u16 recf_read(REC_FILE *pfile, u8 *buff, u16 btr); +u16 recf_write(REC_FILE *pfile, u8 *buff, u16 btw); +u32 create_recfile(RECFILESYSTEM *pfs, REC_FILE *pfile); +u32 close_recfile(REC_FILE *pfile); +u32 open_recfile(u32 index, RECFILESYSTEM *pfs, REC_FILE *pfile); +void recf_save_sr(REC_FILE *pfile, u16 sr); + +int music_flash_file_set_index(u8 file_sel, u32 index); +u32 recfs_scan(RECFILESYSTEM *pfs); +void init_nor_fs(RECFILESYSTEM *pfs, u16 sector_start, u16 sector_end, u8 sector_size); + +u32 nor_fs_init(void); +int nor_fs_set_rec_capacity(int capacity); //需要先设置容量。 +int nor_fs_ops_init(void); +int recfs_scan_ex(); +u32 nor_get_capacity(void); +u32 flashinsize_rec_get_capacity(void); +int sdfile_rec_scan_ex(); +void rec_clear_norfs_fileindex(void); +void clear_norfs_fileindex(void); +u32 _sdfile_rec_init(void); +int set_rec_capacity(int capacity); //需要先设置容量。 +int sdfile_rec_ops_init(void); +u32 nor_get_index(void); +u32 flashinsize_rec_get_index(void); +int nor_set_offset_addr(int offset); + +#endif diff --git a/include_lib/system/spinlock.h b/include_lib/system/spinlock.h new file mode 100644 index 0000000..b32972b --- /dev/null +++ b/include_lib/system/spinlock.h @@ -0,0 +1,146 @@ +#ifndef SYS_SPINLOCK_H +#define SYS_SPINLOCK_H + +#include "typedef.h" +#include "cpu.h" +#include "irq.h" + + +struct __spinlock { + volatile u32 rwlock; +}; + +typedef struct __spinlock spinlock_t; + +#if CPU_CORE_NUM > 1 + + +#define preempt_disable() \ + __local_irq_disable() + +#define preempt_enable() \ + __local_irq_enable() + +#else + +#define preempt_disable() \ + local_irq_disable() + +#define preempt_enable() \ + local_irq_enable() + + + + +#endif + + +#if CPU_CORE_NUM > 1 + +#define spin_acquire(lock) \ + do { \ + arch_spin_lock(lock); \ + }while(0) + +#define spin_release(lock) \ + do { \ + arch_spin_unlock(lock); \ + }while(0) + +#else + +#define spin_acquire(lock) \ + do { \ + }while(0) + + +#define spin_release(lock) \ + do { \ + }while(0) + +#endif + + +#define DEFINE_SPINLOCK(x) \ + spinlock_t x = { .rwlock = 0 } + + +static inline void spin_lock_init(spinlock_t *lock) +{ + lock->rwlock = 0; +} +extern u32 spin_lock_cnt[]; + +#if 1 +static inline void spin_lock(spinlock_t *lock) +{ + preempt_disable(); + /*ASSERT(spin_lock_cnt[current_cpu_id()] == 0); + spin_lock_cnt[current_cpu_id()] = 1;*/ + spin_acquire(lock); +} + + +static inline void spin_unlock(spinlock_t *lock) +{ + /*spin_lock_cnt[current_cpu_id()] = 0;*/ + spin_release(lock); + preempt_enable(); +} + +#else + + +#define spin_lock(lock) \ + do { \ + preempt_disable(); \ + if (!(T2_CON & (1<<0))) { \ + T2_CNT = 0; \ + T2_PRD = 120000000 / 10; \ + T2_CON = 1; \ + } \ + spin_lock_cnt[current_cpu_id()] = T2_CNT; \ + spin_acquire(lock); \ + } while (0) + + +#define spin_unlock(lock) \ + do { \ + u32 t = T2_CNT;\ + if(t < spin_lock_cnt[current_cpu_id()]) \ + t += T2_PRD - spin_lock_cnt[current_cpu_id()]; \ + else \ + t -= spin_lock_cnt[current_cpu_id()]; \ + spin_release(lock); \ + preempt_enable(); \ + if (t > 100000) { /*120000 == 1ms*/ \ + printf("???????spinlock: %d, %s\n", t, __func__); \ + } \ + } while(0) + +#endif + +/*#define spin_lock_irqsave(lock, flags) \ + do { \ + local_irq_save(flags); \ + spin_acquire((lock)); \ + }while(0) + +#define spin_unlock_irqrestore(lock, flags) \ + do { \ + spin_release((lock)); \ + local_irq_restore(flags); \ + }while(0) */ + + + + + + + + + + + +#endif + diff --git a/include_lib/system/sys_time.h b/include_lib/system/sys_time.h new file mode 100644 index 0000000..02db2b5 --- /dev/null +++ b/include_lib/system/sys_time.h @@ -0,0 +1,50 @@ +#ifndef SYS_TIME_H +#define SYS_TIME_H + +#include "typedef.h" + + +struct sys_time { + u16 year; + u8 month; + u8 day; + u8 hour; + u8 min; + u8 sec; +}; + +#if 0 +struct tm { + int tm_sec; /* Seconds. [0-60] (1 leap second) */ + int tm_min; /* Minutes. [0-59] */ + int tm_hour; /* Hours. [0-23] */ + int tm_mday; /* Day. [1-31] */ + int tm_mon; /* Month. [0-11] */ + int tm_year; /* Year - 1900. */ + int tm_wday; /* Day of week. [0-6] */ + int tm_yday; /* Days in year.[0-365] */ + int tm_isdst; /* DST. [-1/0/1]*/ + +# ifdef __USE_MISC + long int tm_gmtoff; /* Seconds east of UTC. */ + const char *tm_zone; /* Timezone abbreviation. */ +# else + long int __tm_gmtoff; /* Seconds east of UTC. */ + const char *__tm_zone; /* Timezone abbreviation. */ +# endif +}; + +#endif + + + + + + + + + + + + +#endif diff --git a/include_lib/system/syscfg_id.h b/include_lib/system/syscfg_id.h new file mode 100644 index 0000000..c7c8434 --- /dev/null +++ b/include_lib/system/syscfg_id.h @@ -0,0 +1,220 @@ + +#ifndef __JL_CFG_DEC_H__ +#define __JL_CFG_DEC_H__ + +#include "typedef.h" + +struct btif_item { + u16 id; + u16 data_len; +}; + + +struct syscfg_operataions { + int (*init)(void); + int (*check_id)(u16 item_id); + int (*read)(u16 item_id, u8 *buf, u16 len); + int (*write)(u16 item_id, u8 *buf, u16 len); + int (*dma_write)(u16 item_id, u8 *buf, u16 len); + int (*read_string)(u16 item_id, u8 *buf, u16 len, u8 ver); + u8 *(*ptr_read)(u16 item_id, u16 *len); +}; + +#define REGISTER_SYSCFG_OPS(cfg, pri) \ + const struct syscfg_operataions cfg SEC_USED(.syscfg.pri.ops) + +//=================================================================================// +// 系统配置项(VM, BTIF, cfg_bin)读写接口 // +//接口说明: // +// 1.输入参数 // +// 1)item_id: 配置项ID号, 由本文件统一分配; // +// 2)buf: 用于存储read/write数据内容; // +// 3)len: buf的长度(byte), buf长度必须大于等于read/write数据长度; // +// 2.返回参数: // +// 1)执行正确: 返回值等于实际上所读到的数据长度(大于0); // +// 2)执行错误: 返回值小于等于0, 小于0表示相关错误码; // +// 3.读写接口使用注意事项: // +// 1)不能在中断里调用写(write)接口; // +// 2)调用本读写接口时应该习惯性判断返回值来检查read/write动作是否执行正确; // +//=================================================================================// +int syscfg_read(u16 item_id, void *buf, u16 len); + +int syscfg_read_btmac_blemac_from_bin(u16 item_id, void *buf, u16 len); + +int syscfg_write(u16 item_id, void *buf, u16 len); + +//该接口默认会以dma的方式写vm区域, 请注意buf地址需要按照4byte对齐 +int syscfg_dma_write(u16 item_id, void *buf, u16 len); + +//读取同一个配置项存在多份数据中的某一份数据, ver读取表示第几份数据, ver从 0 开始; +//典型应用: 读取配置项CFG_BT_NAME中多个蓝牙名中的某一个蓝牙名; +int syscfg_read_string(u16 item_id, void *buf, u16 len, u8 ver); + +//读取配置项, 返回: ptr: 配置项地址指针(可以用cpu直接访问); len为配置项长度 +//注: 只支持cfg_tools.bin文件中的配置项读取 +u8 *syscfg_ptr_read(u16 item_id, u16 *len); + + +//==================================================================================================// +// 配置项ID分配说明 // +// 1.配置项ID号根据存储区域进行分配; // +// 2.存储区域有3个: 1)VM区域; 2)sys_cfg.bin; 3)BTIF区域 // +// 3.配置项ID号分配如下: // +// 0)[0]: 配置项ID号0为配置项工具保留ID号; // +// 1)[ 1 ~ 49]: 共49项, 预留给用户自定义, 只存于VM区域; // +// 2)[ 50 ~ 99]: 共50项, sdk相关配置项, 只存于VM区域; // +// 3)[100 ~ 127]: 共28项, sdk相关配置项, 可以存于VM区域, sys_cfg.bin(作为默认值) 和 BTIF区域; // +// 4)[512 ~ 700]: 共188项, sdk相关配置项, 只存于sys_cfg.bin; // +//==================================================================================================// + +//=================================================================================// +// 用户自定义配置项[1 ~ 49] // +//=================================================================================// +#define CFG_USER_DEFINE_BEGIN 1 +#define CFG_USER_DEFINE_END 49 + +//=================================================================================// +// 只存VM配置项[50 ~ 99] // +//=================================================================================// +#define CFG_STORE_VM_ONLY_BEGIN 50 +#define CFG_STORE_VM_ONLY_END 99 + +//=================================================================================// +// 可以存于VM, sys_cfg.bin(默认值)和BTIF区域的配置项[100 ~ 127] // +// (VM支持扩展到511) // +//=================================================================================// +#define CFG_STORE_VM_BIN_BTIF_BEGIN 100 +#define CFG_STORE_VM_BIN_BTIF_END (VM_ITEM_MAX_NUM - 1) //在app_cfg文件中配置128/256 + +//==================================================================================================// +//ID号分配方案: +// 1) 与APP CASE 相关的ID (0 ~ 50); +// 3) lib库保留ID(蓝牙, trim 值) (范围: 61 ~ 127); //67项 +// 4) 与app_case 扩展ID号,需要更大的ram资源(128 ~ 511); +//==================================================================================================// + +//=================================================================================// +// SDK库保留配置项[61 ~ 127] // +//=================================================================================// +#define CFG_REMOTE_DB_INFO 61 +#define CFG_REMOTE_DB_00 62 +#define CFG_REMOTE_DB_01 63 +#define CFG_REMOTE_DB_02 64 +#define CFG_REMOTE_DB_03 65 +#define CFG_REMOTE_DB_04 66 +#define CFG_REMOTE_DB_05 67 +#define CFG_REMOTE_DB_06 68 +#define CFG_REMOTE_DB_07 69 +#define CFG_REMOTE_DB_08 70 +#define CFG_REMOTE_DB_09 71 +#define CFG_REMOTE_DB_10 72 +#define CFG_REMOTE_DB_11 73 +#define CFG_REMOTE_DB_12 74 +#define CFG_REMOTE_DB_13 75 +#define CFG_REMOTE_DB_14 76 +#define CFG_REMOTE_DB_15 77 +#define CFG_REMOTE_DB_16 78 +#define CFG_REMOTE_DB_17 79 +#define CFG_REMOTE_DB_18 80 +#define CFG_REMOTE_DB_19 81 +#define CFG_DAC_TEST_VOLT 82 +#define CFG_BLE_MODE_INFO 83 +#define CFG_TWS_PAIR_AA 84 +#define CFG_TWS_CONNECT_AA 85 +#define CFG_MUSIC_VOL 86 +#define CFG_CHARGESTORE_TWS_CHANNEL 87 +#define CFG_DAC_DTB 88 +#define CFG_MC_BIAS 89 +#define CFG_POR_FLAG 90 +#define CFG_MIC_LDO_VSEL 91 +#define CFG_DAC_TRIM_INFO 92 +#define CFG_BT_TRIM_INFO 93 +#define CFG_ANC_INFO 94 +#define CFG_TWS_LOCAL_ADDR 95 +#define CFG_TWS_REMOTE_ADDR 96 +#define CFG_TWS_COMMON_ADDR 97 +#define CFG_TWS_CHANNEL 98 +#define VM_PMU_VOLTAGE 99 +#define CFG_SYS_VOL 100 + +//=========== btif & cfg_tool.bin & vm ============// +#define CFG_BT_NAME 101 +#define CFG_BT_MAC_ADDR 102 +#define CFG_BLE_NAME 103 +#define CFG_BLE_MAC_ADDR 104 +#define VM_BLE_LOCAL_INFO 109 +#define CFG_BT_FRE_OFFSET 110 +#define VM_GMA_ALI_PARA 111 +#define VM_DMA_RAND 112 +#define VM_GMA_MAC 113 +#define VM_TME_AUTH_COOKIE 114 +#define VM_UPDATE_FLAG 115 + +#define VM_RTC_TRIM 116 + +#define VM_BLE_REMOTE_DB_INFO 117 +#define VM_BLE_REMOTE_DB_00 118 +#define VM_BLE_REMOTE_DB_01 119 +#define VM_BLE_REMOTE_DB_02 120 +#define VM_BLE_REMOTE_DB_03 121 +#define VM_BLE_REMOTE_DB_04 122 +#define VM_BLE_REMOTE_DB_05 123 +#define VM_BLE_REMOTE_DB_06 124 +#define VM_BLE_REMOTE_DB_07 125 +#define VM_BLE_REMOTE_DB_08 126 +#define VM_BLE_REMOTE_DB_09 127 + +//=================================================================================// +// 只存于sys_cfg.bin的配置项[512 ~ 700] // +//=================================================================================// +#define CFG_STORE_BIN_ONLY_BEGIN 512 +//硬件类配置项[513 ~ 600] +#define CFG_UART_ID 513 +#define CFG_HWI2C_ID 514 +#define CFG_SWI2C_ID 515 +#define CFG_HWSPI_ID 516 +#define CFG_SWSPI_ID 517 +#define CFG_SD_ID 518 +#define CFG_USB_ID 519 +#define CFG_LCD_ID 520 +#define CFG_TOUCH_ID 521 +#define CFG_IOKEY_ID 522 +#define CFG_ADKEY_ID 523 +#define CFG_AUDIO_ID 524 +#define CFG_VIDEO_ID 525 +#define CFG_WIFI_ID 526 +#define CFG_NIC_ID 527 +#define CFG_LED_ID 528 +#define CFG_POWER_MANG_ID 529 +#define CFG_IRFLT_ID 530 +#define CFG_PLCNT_ID 531 +#define CFG_PWMLED_ID 532 +#define CFG_RDEC_ID 533 +#define CFG_CHARGE_STORE_ID 534 +#define CFG_CHARGE_ID 535 +#define CFG_LOWPOWER_V_ID 536 +#define CFG_MIC_TYPE_ID 537 +#define CFG_COMBINE_SYS_VOL_ID 538 +#define CFG_COMBINE_CALL_VOL_ID 539 +#define CFG_LP_TOUCH_KEY_ID 540 + +//蓝牙类配置项[601 ~ 650] +#define CFG_BT_RF_POWER_ID 601 +#define CFG_TWS_PAIR_CODE_ID 602 +#define CFG_AUTO_OFF_TIME_ID 603 +#define CFG_AEC_ID 604 +#define CFG_UI_TONE_STATUS_ID 605 +#define CFG_KEY_MSG_ID 606 +#define CFG_LRC_ID 607 +#define CFG_DMS_ID 609 +#define CFG_ANC_ID 610 +#define CFG_SMS_DNS_ID 612 //单mic神经网络降噪 +#define CFG_BLE_RF_POWER_ID 615 + +//其它类配置项[651 ~ 700] +#define CFG_STORE_BIN_ONLY_END 700 + + + +#endif + diff --git a/include_lib/system/system_lib_bss.ld b/include_lib/system/system_lib_bss.ld new file mode 100644 index 0000000..f5c9180 --- /dev/null +++ b/include_lib/system/system_lib_bss.ld @@ -0,0 +1,14 @@ + + system_bss_start = .; + . = ALIGN(4); + *(.os_bss) + *(.mem_heap) + *(.memp_memory_x) + *(.mem_bss) + *(.os_port_bss) + + *(.uECC_bss) + *(.ECDH_sample_bss) + + system_bss_end = .; + diff --git a/include_lib/system/system_lib_data.ld b/include_lib/system/system_lib_data.ld new file mode 100644 index 0000000..eb21273 --- /dev/null +++ b/include_lib/system/system_lib_data.ld @@ -0,0 +1,111 @@ + + . = ALIGN(4); + system_data_start = .; + + _video_subdev_begin = .; + PROVIDE(video_subdev_begin = .); + KEEP(*(.video_subdev.0)) + KEEP(*(.video_subdev.1)) + KEEP(*(.video_subdev.2)) + KEEP(*(.video_subdev.3)) + KEEP(*(.video_subdev.4)) + KEEP(*(.video_subdev.5)) + _video_subdev_end = .; + PROVIDE(video_subdev_end = .); + + _audio_subdev_begin = .; + PROVIDE(audio_subdev_begin = .); + KEEP(*(.audio_subdev.0)) + KEEP(*(.audio_subdev.1)) + KEEP(*(.audio_subdev.2)) + KEEP(*(.audio_subdev.3)) + _audio_subdev_end = .; + PROVIDE(audio_subdev_end = .); + + _iic_device_begin = .; + PROVIDE(iic_device_begin = .); + KEEP(*(.iic)) + _iic_device_end = .; + PROVIDE(iic_device_end = .); + + _avin_spi_device_begin = .; + PROVIDE(avin_spi_device_begin = .); + KEEP(*(.sw_spi)) + _avin_spi_device_end = .; + PROVIDE(avin_spi_device_end = .); + + _video_dev_begin = .; + PROVIDE(video_dev_begin = .); + KEEP(*(.video_device)) + _video_dev_end = .; + PROVIDE(video_dev_end = .); + + _key_driver_ops_begin = .; + PROVIDE(key_driver_ops_begin = .); + KEEP(*(.key_driver_ops)) + _key_driver_ops_end = .; + PROVIDE(key_driver_ops_end = .); + + _touch_driver_begin = .; + PROVIDE(touch_driver_begin = .); + KEEP(*(.touch_driver)) + _touch_driver_end = .; + PROVIDE(touch_driver_end = .); + + _static_hi_timer_begin = .; + PROVIDE(static_hi_timer_begin = .); + KEEP(*(.hi_timer)) + _static_hi_timer_end = .; + PROVIDE(static_hi_timer_end = .); + + _sys_cpu_timer_begin = .; + PROVIDE(sys_cpu_timer_begin = .); + KEEP(*(.sys_cpu_timer)) + _sys_cpu_timer_end = .; + PROVIDE(sys_cpu_timer_end = .); + + _sys_config_begin = .; + PROVIDE(sys_config_begin = .); + KEEP(*(.sys_cfg)) + _sys_config_end = .; + PROVIDE(sys_config_end = .); + + _sys_fat_begin = .; + PROVIDE(sys_fat_begin = .); + KEEP(*(.fs_fat)) + _sys_fat_end = .; + PROVIDE(sys_fat_end = .); + + _app_begin = .; + PROVIDE(app_begin = .); + KEEP(*(.app)) + _app_end = .; + PROVIDE(app_end = .); + + _os_begin = .; + PROVIDE(os_begin = .); +/* + *(.os_code) + *(.os_const) +*/ + *(.os_str) + *(.os_data) + _os_end = .; + PROVIDE(os_end = .); + + *(.crypto_ecdh_data) + *(.crypto_data) + + *(.mem_data) + *(.os_port_data) + + *(.uECC_data) + *(.ECDH_sample_data) + + __movable_slot_start = .; + *(movable.slot.*); + __movable_slot_end = .; + + system_data_end = .; + + diff --git a/include_lib/system/system_lib_text.ld b/include_lib/system/system_lib_text.ld new file mode 100644 index 0000000..174f43c --- /dev/null +++ b/include_lib/system/system_lib_text.ld @@ -0,0 +1,175 @@ + + . = ALIGN(4); + system_text_start = .; + + _device_node_begin = .; + PROVIDE(device_node_begin = .); + KEEP(*(.device)) + _device_node_end = .; + PROVIDE(device_node_end = .); + + config_target_begin = .; + PROVIDE(config_target_begin = .); + KEEP(*(.config_target)) + config_target_end = .; + PROVIDE(config_target_end = .); + + system_code_begin = .; + KEEP(*(.system.*.text)) + system_code_end = .; + . = ALIGN(4); + system_code_size = system_code_end - system_code_begin; + + vfs_ops_begin = .; + KEEP(*(.vfs_operations)) + vfs_ops_end = .; + + _lib_version_begin = .; + PROVIDE(lib_version_begin = .); + KEEP(*(.lib_version)) + _lib_version_end = .; + PROVIDE(lib_version_end = .); + + _initcall_begin = .; + PROVIDE(initcall_begin = .); + KEEP(*(.initcall)) + _initcall_end = .; + PROVIDE(initcall_end = .); + + _early_initcall_begin = .; + PROVIDE(early_initcall_begin = .); + KEEP(*(.early.initcall)) + _early_initcall_end = .; + PROVIDE(early_initcall_end = .); + + _late_initcall_begin = .; + PROVIDE(late_initcall_begin = .); + KEEP(*(.late.initcall)) + _late_initcall_end = .; + PROVIDE(late_initcall_end = .); + + _platform_initcall_begin = .; + PROVIDE(platform_initcall_begin = .); + KEEP(*(.platform.initcall)) + _platform_initcall_end = .; + PROVIDE(platform_initcall_end = .); + + _module_initcall_begin = .; + PROVIDE(module_initcall_begin = .); + KEEP(*(.module.initcall)) + _module_initcall_end = .; + PROVIDE(module_initcall_end = .); + + _sys_event_handler_begin = .; + PROVIDE(sys_event_handler_begin = .); + KEEP(*(.sys_event.4.handler)) + KEEP(*(.sys_event.3.handler)) + KEEP(*(.sys_event.2.handler)) + KEEP(*(.sys_event.1.handler)) + KEEP(*(.sys_event.0.handler)) + _sys_event_handler_end = .; + PROVIDE(sys_event_handler_end = .); + + _syscfg_arg_begin = .; + PROVIDE(syscfg_arg_begin = .); + KEEP(*(.syscfg.arg)) + _syscfg_arg_end = .; + PROVIDE(syscfg_arg_end = .); + + _syscfg_handler_begin = .; + PROVIDE(syscfg_handler_begin = .); + KEEP(*(.syscfg.handler)) + _syscfg_handler_end = .; + PROVIDE(syscfg_handler_end = .); + + _syscfg_ops_begin = .; + PROVIDE(syscfg_ops_begin = .); + KEEP(*(.syscfg.2.ops)) + KEEP(*(.syscfg.1.ops)) + KEEP(*(.syscfg.0.ops)) + _syscfg_ops_end = .; + PROVIDE(syscfg_ops_end = .); + + _server_info_begin = .; + PROVIDE(server_info_begin = .); + KEEP(*(.server_info)) + _server_info_end = .; + PROVIDE(server_info_end = .); + + _bus_device_begin = .; + PROVIDE(bus_device_begin = .); + KEEP(*(.bus_device)) + _bus_device_end = .; + PROVIDE(bus_device_end = .); + + _sys_power_hal_ops_begin = .; + PROVIDE(sys_power_hal_ops_begin = .); + KEEP(*(.sys_power_hal_ops)) + _sys_power_hal_ops_end = .; + PROVIDE(sys_power_hal_ops_end = .); + + + . = ALIGN(4); + lp_target_begin = .; + PROVIDE(lp_target_begin = .); + KEEP(*(.lp_target)) + lp_target_end = .; + PROVIDE(lp_target_end = .); + + . = ALIGN(4); + deepsleep_target_begin = .; + PROVIDE(deepsleep_target_begin = .); + KEEP(*(.deepsleep_target)) + deepsleep_target_end = .; + PROVIDE(deepsleep_target_end = .); + + crypto_begin = .; + *(.crypto_ecdh_code) + *(.crypto_ecdh_const) + + *(.crypto_bigint_code) + *(.crypto_bigint_const) + + *(.crypto_code) + *(.crypto_const) + + *(.ECDH_sample_code) + *(.ECDH_sample_const) + + *(.uECC_code) + *(.uECC_const) + + *(.hmac_code) + *(.hmac_const) + + *(.hash_sample_code) + *(.hash_sample_const) + + *(.aes_cmac_sample_code) + *(.aes_cmac_sample_const) + crypto_end = .; + crypto_size = . - crypto_begin; + + *(.mem_code) + *(.mem_const) + + *(.os_port_code) + *(.os_port_const) + + __movable_function_start = .; + *(movable.text.*); + *(movable.stub.*); + *(movable.region.*); + /* *(.movable.code*) */ + __movable_function_end = .; + __movable_function_size = __movable_function_end - __movable_function_start; + + system_text_end = .; + + + + system_code_total_size = system_text_end - system_text_start; + + + + diff --git a/include_lib/system/task.h b/include_lib/system/task.h new file mode 100644 index 0000000..8fc3caf --- /dev/null +++ b/include_lib/system/task.h @@ -0,0 +1,41 @@ +#ifndef TASK_PRIORITY_H +#define TASK_PRIORITY_H + + +#include "os/os_api.h" + + +struct task_info { + const char *name; + u8 prio; + u16 stack_size; + u16 qsize; +}; + + + +typedef OS_SEM sem_t; +typedef OS_MUTEX mutex_t; + + +int task_create(void (*task)(void *p), void *p, const char *name); + + +int task_exit(const char *name); + +int task_delete(const char *name); + +int task_kill(const char *name); + + + + + + + + + + +#endif + + diff --git a/include_lib/system/timer.h b/include_lib/system/timer.h new file mode 100644 index 0000000..8d2ecbb --- /dev/null +++ b/include_lib/system/timer.h @@ -0,0 +1,299 @@ +#ifndef SYS_TIMER_H +#define SYS_TIMER_H + + +#include "typedef.h" +#include "generic/list.h" + + +struct static_sys_timer { + void (*func)(void *priv); + void *priv; + u32 msec; + u32 jiffies; +}; + +struct sys_usec_timer { + void (*func)(void *priv); + void *priv; + const char *owner; + struct sys_cpu_timer *timer; +}; + + +#define SYS_HI_TIMER_ADD(_func, _priv, _msec) \ + static struct static_sys_timer hi_timer sec(.hi_timer) = { \ + .func = _func, \ + .priv = _priv, \ + .msec = _msec, \ + } + +extern struct static_sys_timer static_hi_timer_begin[]; +extern struct static_sys_timer static_hi_timer_end[]; + +#define list_for_each_static_hi_timer(p) \ + for (p=static_hi_timer_begin; p>24)|((x>>8)&0xff00)|(x<<24)|((x&0xff00)<<8)) +#define font_ntoh(x) (unsigned short int )((x>>8&0x00ff)|x<<8&0xff00) + +extern const struct font_info font_info_table[]; + +#endif diff --git a/include_lib/system/ui/font/font_sdfs.h b/include_lib/system/ui/font/font_sdfs.h new file mode 100644 index 0000000..654c70d --- /dev/null +++ b/include_lib/system/ui/font/font_sdfs.h @@ -0,0 +1,23 @@ +#ifndef __UI_SDFS_H__ +#define __UI_SDFS_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "generic/typedef.h" +#include "fs/fs.h" + +#define SD_SEEK_SET 0x00 +#define SD_SEEK_CUR 0x01 + +FILE *font_sd_fopen(const char *filename, void *arg); +int font_sd_fread(FILE *fp, void *buf, u32 len); +int font_sd_fseek(FILE *fp, u8 seek_mode, u32 offset); +int font_sd_fclose(FILE *fp); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include_lib/system/ui/font/font_textout.h b/include_lib/system/ui/font/font_textout.h new file mode 100644 index 0000000..ff08732 --- /dev/null +++ b/include_lib/system/ui/font/font_textout.h @@ -0,0 +1,103 @@ +#ifndef __FONT_OUT_H__ +#define __FONT_OUT_H__ + +#include "generic/typedef.h" +#include "font/font_all.h" + +/** + * @brief 打开字库 + * + * @param info:字库信息 + * @param language:语言 + * + * @returns TRUE:打开成功 FALSE:打开失败 + */ +struct font_info *font_open(struct font_info *info, u8 language); +/** + * @brief 获取字符宽度 + * + * @param info + * @param str + * @param strlen + * + * @returns + */ +u16 font_text_width(struct font_info *info, u8 *str, u16 strlen); +u16 font_textw_width(struct font_info *info, u8 *str, u16 strlen); +u16 font_textu_width(struct font_info *info, u8 *str, u16 strlen); + +/** + * @brief 字库内码显示接口 + * + * @param info + * @param str + * @param strlen + * + * @returns + */ +u16 font_textout(struct font_info *info, u8 *str, u16 strlen, u16 x, u16 y); +/** + * @brief 字库unicode显示接口 + * + * @param info + * @param str + * @param strlen + * @param x + * @param y + * + * @returns + */ +u16 font_textout_unicode(struct font_info *info, u8 *str, u16 strlen, u16 x, u16 y); +/** + * @brief 字库utf8显示接口 + * + * @param info + * @param str + * @param strlen + * @param x + * @param y + * + * @returns + */ +u16 font_textout_utf8(struct font_info *info, u8 *str, u16 strlen, u16 x, u16 y); +/** + * @brief utf8转内码 + * + * @param info + * @param utf8 + * @param utf8len + * @param ansi + * + * @returns + */ +u16 font_utf8toansi(struct font_info *info, u8 *utf8, u16 utf8len, u8 *ansi); +/** + * @brief utf16转内码 + * + * @param info + * @param utf + * @param len + * @param ansi + * + * @returns + */ +u16 font_utf16toansi(struct font_info *info, u8 *utf, u16 len, u8 *ansi); +/** + * @brief utf8转utf16 + * + * @param info + * @param utf8 + * @param utf8len + * @param utf16 + * + * @returns + */ +u16 font_utf8toutf16(struct font_info *info, u8 *utf8, u16 utf8len, u16 *utf16); +/** + * @brief 字库关闭 + * + * @param info + */ +void font_close(struct font_info *info); + +#endif diff --git a/include_lib/system/ui/font/language_list.h b/include_lib/system/ui/font/language_list.h new file mode 100644 index 0000000..39d1f5f --- /dev/null +++ b/include_lib/system/ui/font/language_list.h @@ -0,0 +1,28 @@ +#ifndef __LANGUAGE_LIST_H__ +#define __LANGUAGE_LIST_H__ + +#define Chinese_Simplified 1 //简体中文 +#define Chinese_Traditional 2 //繁体中文 +#define Japanese 3 //日语 +#define Korean 4 //韩语 +#define English 5 //英语 +#define French 6 //法语 +#define German 7 //德语 +#define Italian 8 //意大利语 +#define Dutch 9 //荷兰语 +#define Portuguese 10 //葡萄牙语 +#define Spanish 11 //西班牙语 +#define Swedish 12 //瑞典语 +#define Czech 13 //捷克语 +#define Danish 14 //丹麦语 +#define Polish 15 //波兰语 +#define Russian 16 //俄语 +#define Turkey 17 //土耳其语 +#define Hebrew 18 //希伯来语 +#define Thai 19 //泰语 +#define Hungarian 20 //匈牙利语 +#define Romanian 21 //罗马尼亚语 +#define Arabic 22 //阿拉伯语 +#define Vietnam 23 //越南语 + +#endif diff --git a/include_lib/system/ui/includes.h b/include_lib/system/ui/includes.h new file mode 100644 index 0000000..b358564 --- /dev/null +++ b/include_lib/system/ui/includes.h @@ -0,0 +1,26 @@ +#ifndef UI_INCLUDES_H +#define UI_INCLUDES_H + + + + + +#include "ui/ui.h" + +#include "res/resfile.h" +#include "res/font_ascii.h" + + + +#define UI_TOUCH_DEBUG 1 + +#if (UI_TOUCH_DEBUG == 1) +#define UI_ONTOUCH_DEBUG log_d +#else +#define UI_ONTOUCH_DEBUG(...) +#endif + + + + +#endif diff --git a/include_lib/system/ui/res/font_ascii.h b/include_lib/system/ui/res/font_ascii.h new file mode 100644 index 0000000..e2cdf31 --- /dev/null +++ b/include_lib/system/ui/res/font_ascii.h @@ -0,0 +1,23 @@ +#ifndef FONT_ASCII_H +#define FONT_ASCII_H + + +#include "typedef.h" + + +int font_ascii_get_pix(char code, u8 *pixbuf, int buflen, int *height, int *width); + +int font_ascii_width_check(const char *str); + + + + + + + + + + + +#endif + diff --git a/include_lib/system/ui/res/resfile.h b/include_lib/system/ui/res/resfile.h new file mode 100644 index 0000000..7491b02 --- /dev/null +++ b/include_lib/system/ui/res/resfile.h @@ -0,0 +1,65 @@ +#ifndef RESFILE_H +#define RESFILE_H + +#include "typedef.h" +#include "fs/fs.h" + +#define FILE_TYPE_JPEG 5 +#define AT_UI_RAM AT(.ui_ram) + +// #define EXTERN_PATH "storage/nor_ui/C/res/" +// #define EXTERN_PATH "storage/virfat_flash/C/uires/" +struct image_file { + u8 format; + u8 compress; + u16 data_crc; + u16 width; + u16 height; + u32 offset; + u32 len; +}; + +int open_resfile(const char *name); +void close_resfile(); + +int res_file_version_compare(int res_ver); + +int open_str_file(const char *name); +void close_str_file(); +int str_file_version_compare(int str_ver); + +int open_style_file(const char *name); + +int font_ascii_init(const char *name); +int open_image_by_id(FILE *specfile, struct image_file *f, int id, int page); +int read_image_data(struct image_file *f, u8 *data, int len); +int br23_read_image_data(FILE *specfile, struct image_file *f, u8 *data, int len, int offset); +u32 image_decode(const void *pSour, void *pDest, u32 SourLen, u32 DestLen, u8 compress); +int open_string_pic(struct image_file *file, int id); +int read_str_data(struct image_file *f, u8 *data, int len); +int br23_read_str_data(struct image_file *f, u8 *data, int len, int offset); +int load_pallet_table(int id, u32 *data); +int ui_language_set(int language); +int ui_language_get(); + +FILE *res_fopen(const char *path, const char *mode); +int res_fread(FILE *_file, void *buf, u32 len); +int res_fseek(FILE *_file, int offset, int fromwhere); +int res_flen(FILE *file); +int res_fclose(FILE *file); +int _norflash_read_watch(u8 *buf, u32 addr, u32 len, u8 wait);//加速读 + +struct ui_load_info { + u8 pj_id; + const char *path; + FILE *file; + FILE *res; + FILE *str; +}; + +void *ui_load_res_by_pj_id(int pj_id); +void *ui_load_str_by_pj_id(int pj_id); +int ui_set_sty_path_by_pj_id(int pj_id, const u8 *path); +void *ui_load_sty_by_pj_id(int pj_id); + +#endif diff --git a/include_lib/system/ui/res/rle.h b/include_lib/system/ui/res/rle.h new file mode 100644 index 0000000..40adace --- /dev/null +++ b/include_lib/system/ui/res/rle.h @@ -0,0 +1,19 @@ +#ifndef __RLE_H__ +#define __RLE_H__ + +#include "system/includes.h" + +struct rle_header { + u32 addr: 22; //max 4M + u32 len: 10; //max 1024 bytes +}; + +struct rle_line { + u32 addr: 22; + u32 num: 10; + u16 len[0]; +}; + +int Rle_Decode(u8 *inbuf, int inSize, u8 *outbuf, int onuBufSize, int offset, int len, int pixel_size); + +#endif diff --git a/include_lib/system/ui/ui/control.h b/include_lib/system/ui/ui/control.h new file mode 100644 index 0000000..56220bf --- /dev/null +++ b/include_lib/system/ui/ui/control.h @@ -0,0 +1,371 @@ +#ifndef UI_CONTROL_H +#define UI_CONTROL_H + +#include "ui/ui_core.h" + +union ui_control_info; +struct layout_info; + +#define CTRL_TYPE_WINDOW 2 +#define CTRL_TYPE_LAYOUT 3 +#define CTRL_TYPE_LAYER 4 +#define CTRL_TYPE_GRID 5 +#define CTRL_TYPE_LIST 6 +#define CTRL_TYPE_BUTTON 7 +#define CTRL_TYPE_PIC 8 +#define CTRL_TYPE_BATTERY 9 +#define CTRL_TYPE_TIME 10 +#define CTRL_TYPE_CAMERA_VIEW 11 +#define CTRL_TYPE_TEXT 12 +#define CTRL_TYPE_ANIMATION 13 +#define CTRL_TYPE_PLAYER 14 +#define CTRL_TYPE_NUMBER 15 + +#define CTRL_TYPE_PROGRESS 20 +#define CTRL_PROGRESS_CHILD_BEGIN (CTRL_TYPE_PROGRESS + 1) +#define CTRL_PROGRESS_CHILD_HIGHLIGHT (CTRL_PROGRESS_CHILD_BEGIN) //21 +#define CTRL_PROGRESS_CHILD_END (CTRL_PROGRESS_CHILD_BEGIN + 1) + +#define CTRL_TYPE_MULTIPROGRESS 22 +#define CTRL_MULTIPROGRESS_CHILD_BEGIN (CTRL_TYPE_MULTIPROGRESS + 1) +#define CTRL_MULTIPROGRESS_CHILD_HIGHLIGHT (CTRL_MULTIPROGRESS_CHILD_BEGIN)//23 +#define CTRL_MULTIPROGRESS_CHILD_END (CTRL_MULTIPROGRESS_CHILD_BEGIN + 1) + +#define CTRL_TYPE_WATCH 24 +#define CTRL_WATCH_CHILD_BEGIN (CTRL_TYPE_WATCH + 1) +#define CTRL_WATCH_CHILD_HOUR (CTRL_WATCH_CHILD_BEGIN)//25 +#define CTRL_WATCH_CHILD_MIN (CTRL_WATCH_CHILD_BEGIN+1)//26 +#define CTRL_WATCH_CHILD_SEC (CTRL_WATCH_CHILD_BEGIN+2)//27 +#define CTRL_WATCH_CHILD_END (CTRL_WATCH_CHILD_BEGIN+3) + + +#define CTRL_TYPE_SLIDER 28 + +#define SLIDER_CHILD_BEGIN (CTRL_TYPE_SLIDER+1) +#define SLIDER_CHILD_UNSELECT_PIC (SLIDER_CHILD_BEGIN)//29 +#define SLIDER_CHILD_SELECTED_PIC (SLIDER_CHILD_BEGIN+1)//30 +#define SLIDER_CHILD_SLIDER_PIC (SLIDER_CHILD_BEGIN+2)//31 +#define SLIDER_CHILD_PERSENT_TEXT (SLIDER_CHILD_BEGIN+3)//32 +#define SLIDER_CHILD_END (SLIDER_CHILD_BEGIN+4) + + +#define CTRL_TYPE_VSLIDER 33 + +#define VSLIDER_CHILD_BEGIN (CTRL_TYPE_VSLIDER+1) +#define VSLIDER_CHILD_UNSELECT_PIC (VSLIDER_CHILD_BEGIN)//34 +#define VSLIDER_CHILD_SELECTED_PIC (VSLIDER_CHILD_BEGIN+1)//35 +#define VSLIDER_CHILD_SLIDER_PIC (VSLIDER_CHILD_BEGIN+2)//36 +#define VSLIDER_CHILD_PERSENT_TEXT (VSLIDER_CHILD_BEGIN+3)//37 +#define VSLIDER_CHILD_END (VSLIDER_CHILD_BEGIN+4) + + +struct ui_ctrl_info_head { + u8 type; + u8 ctrl_num; + u8 css_num; + u8 len; + u8 page; + u8 rev[3]; + int id; + struct element_css1 *css; +}; + +struct ui_image_list { + u16 num; + u16 image[0]; +}; + +struct ui_text_list { + u16 num; + char str[0]; +}; + + +struct ui_image_list_t { + u16 num; + u16 image[64]; +}; + +#define UI_TEXT_LIST_MAX_NUM 4 +struct ui_text_list_t { + u16 num; + char str[16]; +}; + +struct ui_button_info { + struct ui_ctrl_info_head head; + struct element_event_action *action; +}; + + + +struct ui_camera_info { + struct ui_ctrl_info_head head; + char device[8]; + struct element_event_action *action; +}; + +struct ui_player_info { + struct ui_ctrl_info_head head; + char device[8]; + struct element_event_action *action; +}; + +struct ui_time_info { + struct ui_ctrl_info_head head; + char source[8]; + u8 auto_cnt; + u8 rev[3]; + char format[16]; + int color; + int hi_color; + u16 number[10]; + u16 delimiter[10]; + struct element_event_action *action; +}; + +struct ui_number_info { + struct ui_ctrl_info_head head; + char source[8]; + char format[16]; + int color; + int hi_color; + u16 number[10]; + u16 delimiter[10]; + u16 space[2]; + struct element_event_action *action; +}; + + +struct ui_pic_info { + struct ui_ctrl_info_head head; + u8 highlight; + u16 cent_x; + u16 cent_y; + struct ui_image_list *normal_img; + struct ui_image_list *highlight_img; + struct element_event_action *action; +}; + + +struct ui_battery_info { + struct ui_ctrl_info_head head; + struct ui_image_list *normal_image; + struct ui_image_list *charge_image; + struct element_event_action *action; +}; + + +struct ui_text_info { + struct ui_ctrl_info_head head; + char source[8]; + char code[8]; + int color; + int highlight_color; + struct ui_text_list *str; + struct element_event_action *action; +}; + + +struct ui_grid_info { + struct ui_ctrl_info_head head; + u8 page_mode; + char highlight_index; + struct element_event_action *action; + struct layout_info *info; +}; + +struct ui_animation_info { + struct ui_ctrl_info_head head; + u16 loop_num; + u32 interval; + struct ui_image_list *img; + struct element_event_action *action; +}; + +struct ui_slider_info { + struct ui_ctrl_info_head head; + u8 step; + struct ui_ctrl_info_head *ctrl; + // struct element_event_action *action; +}; + +struct ui_vslider_info { + struct ui_ctrl_info_head head; + u8 step; + struct ui_ctrl_info_head *ctrl; + // struct element_event_action *action; +}; + +struct ui_watch_info { + struct ui_ctrl_info_head head; + char source[8]; + struct element_event_action *action; + struct ui_ctrl_info_head *ctrl; +}; + +struct ui_progress_info { + struct ui_ctrl_info_head head; + char source[8]; + struct element_event_action *action; + struct ui_ctrl_info_head *ctrl; +}; + +struct ui_multiprogress_info { + struct ui_ctrl_info_head head; + char source[8]; + struct element_event_action *action; + struct ui_ctrl_info_head *ctrl; +}; + +struct ui_browser_info { + struct ui_ctrl_info_head head; + u8 row; + u8 column; + u8 interval; + u8 scroll; + u8 auto_highlight; + struct element_event_action *action; + struct ui_ctrl_info_head *ctrl; +}; + +struct ui_fattrs_info { + struct ui_ctrl_info_head head; + struct element_event_action *action; + struct ui_ctrl_info_head *ctrl; +}; + +struct layout_info { + struct ui_ctrl_info_head head; + struct element_event_action *action; + union ui_control_info *ctrl; +}; + + +struct layer_info { + struct ui_ctrl_info_head head; + u8 format; + struct element_event_action *action; + struct layout_info *layout; +}; + + +union ui_control_info { + struct ui_ctrl_info_head head;//16 bytes + struct ui_button_info button;//20 bytes + struct ui_camera_info camera;//28 bytes + struct ui_time_info time;//84 bytes + struct ui_number_info number; + struct ui_pic_info pic;//36 bytes + struct ui_battery_info battery;//28 bytes + struct ui_text_info text;//40 bytes + struct ui_grid_info grid;//28 bytes + struct layer_info layer; + struct layout_info layout; + struct ui_watch_info watch; + struct ui_progress_info progress; + struct ui_multiprogress_info multiprogress; + struct ui_slider_info slider; + struct ui_vslider_info vslider; +};//84 bytes + +// union ui_control_info { +// struct ui_ctrl_info_head head; +// struct ui_button_info button; +// struct ui_camera_info camera; +// struct ui_time_info time; +// struct ui_number_info number; +// struct ui_pic_info pic; +// struct ui_battery_info battery; +// struct ui_text_info text; +// struct ui_grid_info grid; +// }; + + +struct window_info { + u8 type; + u8 ctrl_num; + u8 css_num; + u8 len; + u8 rev[4]; + struct rect rect; + struct layer_info *layer; +// struct element_event_action *action; +}; + +struct control_ops { + int type; + void *(*new)(const void *, struct element *); + /*int (*delete)(void *);*/ +}; + +extern const struct control_ops control_ops_begin[]; +extern const struct control_ops control_ops_end[]; + + +#define REGISTER_CONTROL_OPS(_type) \ + static const struct control_ops control_ops_##_type sec(.control_ops) __attribute__((used)) = { \ + .type = _type, + + + +#define get_control_ops_by_type(_type) \ + ({ \ + const struct control_ops *ops, *ret=NULL; \ + for (ops = control_ops_begin; ops < control_ops_end; ops++) { \ + if (ops->type == _type) { \ + ret = ops; \ + break; \ + } \ + }\ + ret; \ + }) + + +#if 0 +struct control_event_header { + int id; + int len; +}; + +extern struct control_event_header control_event_handler_begin[]; +extern struct control_event_header control_event_handler_end[]; + + +#define REGISTER_CONTROL_EVENT_HANDLER(control, _id) \ + static const struct control##_event_handler __##control##_event_handler_##_id \ + sec(.control_event_handler) = { \ + .header = { \ + .id = _id, \ + .len = sizeof(struct control##_event_handler), \ + }, \ + + + + +static inline void *control_event_handler_for_id(int id) +{ + struct control_event_header *p; + + for (p = control_event_handler_begin; p < control_event_handler_end;) { + if (p->id == id) { + return p; + } + p = (u8 *)p + p->len; + } + + return NULL; +} +#endif + + + + + + + + +#endif + + + diff --git a/include_lib/system/ui/ui/layer.h b/include_lib/system/ui/ui/layer.h new file mode 100644 index 0000000..4154292 --- /dev/null +++ b/include_lib/system/ui/ui/layer.h @@ -0,0 +1,53 @@ +#ifndef LAYER_H +#define LAYER_H + + +#include "ui/layout.h" +#include "ui/control.h" + + +struct layer { + struct element elm; //must be first + u8 hide; + u8 inited; + u8 highlight; + u8 ctrl_num; + u8 css_num; + u32 css[2]; + struct draw_context dc; + struct layout *layout; + const struct layer_info *info; + const struct element_event_handler *handler; +}; + + +#define layer_for_id(id) \ + (struct layer *)ui_core_get_element_by_id(id); + + +struct layer *layer_new(struct layer_info *info, int num, struct element *parent); + + +void layer_delete_probe(struct layer *layer, int num); + +void layer_delete(struct layer *layer, int num); + +int layer_show(int id); + +int layer_hide(int id); + +int layer_toggle(int id); + + + + + + + + + +#endif + + + + diff --git a/include_lib/system/ui/ui/layout.h b/include_lib/system/ui/ui/layout.h new file mode 100644 index 0000000..ae1bd16 --- /dev/null +++ b/include_lib/system/ui/ui/layout.h @@ -0,0 +1,54 @@ +#ifndef LAYOUT_H +#define LAYOUT_H + + +#include "ui/ui_core.h" +#include "ui/control.h" + + + + + +struct layout { + struct element elm; //must be first + u8 hide: 1; + u8 inited: 1; + u8 release: 6; + // u8 css_num:5; + // u32 css[2]; + struct layout *layout; + const struct layout_info *info; + const struct element_event_handler *handler; +}; + + + +#define layout_for_id(id) \ + (struct layout *)ui_core_get_element_by_id(id); + + +struct layout *layout_new(struct layout_info *, int, struct element *); + +void layout_delete_probe(struct layout *layout, int num); + +void layout_delete(struct layout *layout, int num); + +int layout_show(int id); + +int layout_hide(int id); + +int layout_toggle(int id); + +void layout_on_focus(struct layout *layout); +void layout_lose_focus(struct layout *layout); + + +/*int layout_current_highlight(int id);*/ + +/*int layout_onkey(struct layout *layout, struct element_key_event *e);*/ + + + +#endif + + diff --git a/include_lib/system/ui/ui/lyrics.h b/include_lib/system/ui/ui/lyrics.h new file mode 100644 index 0000000..344721d --- /dev/null +++ b/include_lib/system/ui/ui/lyrics.h @@ -0,0 +1,116 @@ +#ifndef _LYRICS_H_ +#define _LYRICS_H_ + +#include "typedef.h" +#include "system/fs/fs.h" + +#define LRC_SIZEOF_ALIN(var, al) ((((var)+(al)-1)/(al))*(al)) + +//类型声明区 +typedef struct _TIME_LABEL { /*时间标签信息[mm:ss.ms]*/ + u16 dbtime_s; //time of label,unit:s + u8 btime_100ms; //time of label,unit:ms + u8 btext_len; //the length of lrc content, 占用的实际字节数 + u32 wline_pos; //for record next (byte addr) after the (real label of time) +} TIME_LABEL; + +typedef struct __LRC_FILE_IO { + u32(*seek)(FILE *file, int offset, int orig); + u32(*read)(FILE *file, void *buf, u32 len); +} LRC_FILE_IO; + +typedef struct _LABEL_INFO { /*标签处理后信息*/ + u16 dbtime_base; //first of time + u16 dbtime_limit; //end of time + u8 base_100ms; //first of time + u8 limit_100ms; //first of time + u16 dblabel_cnt; //(real label of time) count + TIME_LABEL *g_plabel_buf; //解析过程中时间标签存储buf + u8 *plabel_buf_tmp; + u16 plabel_buf_len; //解析过程中时间标签存储buf长度 +} LABEL_INFO; + + + +typedef struct _SORTING_INFO { /*文件解析信息*/ + u16 dbnow_fp_addr;//current addr of file pointer + u8 bdata_len; //the length of lrc content + u8 bis_next_file;//jump to next file +} SORTING_INFO; + + +typedef struct __LRC_FILE { + void *hdl; + LRC_FILE_IO *_io; +} LRC_FILE; + + + +typedef struct _LRC_INFO { /// + +struct uimsg_handl { + const char *msg; + int (*handler)(const char *type, u32 args); +}; + +int ui_framework_init(void *); + +int ui_set_style_file(struct ui_style *style); + +int ui_style_file_version_compare(int version); + +int ui_redraw(int id); + +int ui_show(int id); + +int ui_hide(int id); + +int ui_set_call(int (*func)(int), int param); + +int ui_event_onkey(struct element_key_event *e); + +int ui_event_ontouch(struct element_touch_event *e); + +struct element *ui_get_highlight_child_by_id(int id); +int ui_invert_element_by_id(int id); + +int ui_no_highlight_element(struct element *elm); +int ui_no_highlight_element_by_id(int id); +int ui_highlight_element(struct element *elm); +int ui_highlight_element_by_id(int id); + +int ui_get_current_window_id(); + +int ui_register_msg_handler(int id, const struct uimsg_handl *handl); + +int ui_message_handler(int id, const char *msg, va_list); + +const char *str_substr_iter(const char *str, char delim, int *iter); + +int ui_get_child_by_id(int id, int (*event_handler_cb)(void *, int, int)); + +int ui_set_default_handler(int (*ontouch)(void *, struct element_touch_event *), + int (*onkey)(void *, struct element_key_event *), + int (*onchange)(void *, enum element_change_event, void *)); + +/* + * 锁定元素elm之外的区域,所有的触摸消息都发给elm + */ +void ui_ontouch_lock(void *elm); +void ui_ontouch_unlock(void *elm); + +/* + * 锁定控件的夫图层,先不推向imb显示 + */ +int ui_lock_layer(int id); +int ui_unlock_layer(int id); + +int ui_get_disp_status_by_id(int id); + +int create_control_by_id(char *tabfile, int page_id, int id, int parent_id); +int delete_control_by_id(int id); + + +void ui_remove_backcolor(struct element *elm); +void ui_remove_backimage(struct element *elm); +void ui_remove_border(struct element *elm); + +int ui_fill_rect(struct draw_context *dc, int left, int top, int width, int height, u32 acolor); +int ui_draw_image(struct draw_context *dc, int page, int id, int x, int y); +int ui_draw_ascii(struct draw_context *dc, char *str, int strlen, int x, int y, int color); +int ui_draw_text(struct draw_context *dc, int encode, int endian, char *str, int strlen, int x, int y, int color); +int ui_draw_strpic(struct draw_context *dc, int id, int x, int y, int color); +void ui_draw_line(void *_dc, int x0, int y0, int x1, int y1, int color); +void ui_draw_line_by_angle(void *_dc, int x, int y, int length, int angle, int color); +void ui_draw_rect(void *_dc, int x, int y, int width, int height, int color); +void ui_draw_circle(struct draw_context *dc, int center_x, int center_y, + int radius_big, int radius_small, int angle_begin, + int angle_end, int color, int percent); +int ui_draw_set_pixel(struct draw_context *dc, int x, int y, int pixel); +u32 ui_draw_get_pixel(struct draw_context *dc, int x, int y); +u16 ui_draw_get_mixed_pixel(u16 backcolor, u16 forecolor, u8 alpha); + +void *load_control_info_by_id(char *tabfile, u32 page_id, u32 id); +void *ui_control_new(void *_pos, void *parent); + + +#define ui_id2type(id) (((id)>>16) & 0x3f) + + +#endif + diff --git a/include_lib/system/ui/ui/ui.ld b/include_lib/system/ui/ui/ui.ld new file mode 100644 index 0000000..16fdea5 --- /dev/null +++ b/include_lib/system/ui/ui/ui.ld @@ -0,0 +1,37 @@ + lcd_interface_begin = .; + KEEP(*(.lcd_if_info)) + lcd_interface_end = .; + + ui_style_begin = .; + KEEP(*(.ui_style)) + ui_style_end = .; + + + elm_event_handler_begin_JL = .; + KEEP(*(.elm_event_handler_JL)) + elm_event_handler_end_JL = .; + + elm_event_handler_begin_UPGRADE = .; + KEEP(*(.elm_event_handler_UPGRADE)) + elm_event_handler_end_UPGRADE = .; + + + + elm_event_handler_begin_DIAL = .; + KEEP(*(.elm_event_handler_DIAL)) + elm_event_handler_end_DIAL = .; + + + control_event_handler_begin = .; + KEEP(*(.control_event_handler)) + control_event_handler_end = .; + + control_ops_begin = .; + KEEP(*(.control_ops)) + control_ops_end = .; + + battery_notify_begin = .; + *(.battery_notify) + battery_notify_end = .; + + diff --git a/include_lib/system/ui/ui/ui_battery.h b/include_lib/system/ui/ui/ui_battery.h new file mode 100644 index 0000000..f19a3b5 --- /dev/null +++ b/include_lib/system/ui/ui/ui_battery.h @@ -0,0 +1,29 @@ +#ifndef UI_BATTERY_H +#define UI_BATTERY_H + + +#include "ui/control.h" +#include "list.h" + + + + + + +struct ui_battery { + struct element elm; + int src; + u8 index; + u16 charge_image; + u16 normal_image; + struct list_head entry; + const struct ui_battery_info *info; + const struct element_event_handler *handler; +}; + +void ui_battery_enable(); +void ui_battery_level_change(int persent, int incharge);//改变所有电池控件 +int ui_battery_set_level_by_id(int id, int persent, int incharge);//修改指定id +int ui_battery_set_level(struct ui_battery *battery, int persent, int incharge);//初始化使用 + +#endif diff --git a/include_lib/system/ui/ui/ui_browser.h b/include_lib/system/ui/ui/ui_browser.h new file mode 100644 index 0000000..494b029 --- /dev/null +++ b/include_lib/system/ui/ui/ui_browser.h @@ -0,0 +1,92 @@ +#ifndef UI_BROWSER_H +#define UI_BROWSER_H + + + +#include "ui/ui_core.h" +#include "ui/control.h" + + + + +struct ui_browser { + struct element elm; + struct ui_file_browser *hdl; + char order; // 1 表示 正序, 非1 表示反序 + u8 inited; + u8 hide_byself; + u8 item_num; + u8 highlight; + u8 show_mode; + u16 cur_number; + u16 file_number; + struct ui_grid *grid; + const char *path; + const char *ftype; + const struct ui_browser_info *info; + const struct element_event_handler *handler; +}; + + +#define ui_file_browser_cur_item(bro) ui_grid_cur_item(((struct ui_browser *)bro)->grid) + + +int ui_file_browser_page_num(struct ui_browser *bro); + +int ui_file_browser_cur_page(struct ui_browser *bro, int *file_num); + +int ui_file_browser_set_page(struct ui_browser *bro, int page); + +int ui_file_browser_set_page_by_id(int id, int page); + +int ui_file_browser_next_page(struct ui_browser *bro); + +int ui_file_browser_next_page_by_id(int id); + +int ui_file_browser_prev_page(struct ui_browser *bro); + +int ui_file_browser_prev_page_by_id(int id); + +int ui_file_browser_set_dir(struct ui_browser *bro, const char *path, const char *ftype); + +int ui_file_browser_set_dir_by_id(int id, const char *path, const char *ftype); + +int ui_file_browser_get_file_attrs(struct ui_browser *bro, int item, + struct ui_file_attrs *attrs); + +int ui_file_browser_set_file_attrs(struct ui_browser *bro, int item, + struct ui_file_attrs *attrs); + +void *ui_file_browser_open_file(struct ui_browser *bro, int item); + + +int ui_file_browser_del_file(struct ui_browser *bro, int item); + +int ui_file_browser_highlight_item(struct ui_browser *bro, int item, bool yes); + +void *ui_file_browser_get_child_by_id(struct ui_browser *bro, int item, int id); + + + + + + + + + + + + + + + + + + + + + + + + +#endif diff --git a/include_lib/system/ui/ui/ui_button.h b/include_lib/system/ui/ui/ui_button.h new file mode 100644 index 0000000..762d2e7 --- /dev/null +++ b/include_lib/system/ui/ui/ui_button.h @@ -0,0 +1,20 @@ +#ifndef UI_BUTTON_H +#define UI_BUTTON_H + + +#include "ui/control.h" +#include "ui/ui_core.h" + +struct button { + struct element elm; + u8 image_index; + u8 css_num; + u32 css[2]; + const struct ui_button_info *info; + const struct element_event_handler *handler; +}; + +void ui_button_enable(); + +#endif + diff --git a/include_lib/system/ui/ui/ui_camera.h b/include_lib/system/ui/ui/ui_camera.h new file mode 100644 index 0000000..f29f044 --- /dev/null +++ b/include_lib/system/ui/ui/ui_camera.h @@ -0,0 +1,34 @@ +#ifndef UI_CAMERA_H +#define UI_CAMERA_H + +#include "ui/control.h" +#include "ui/ui_core.h" + + + + + + +struct ui_camera { + struct element elm; //must be first + int fd; + const struct ui_camera_info *info; + const struct element_event_handler *handler; +}; + + + +#define ui_camera_for_id(id) \ + (struct ui_camera*)ui_core_get_element_by_id(id) + + + +void register_ui_camera_handler(const struct element_event_handler *handler); + +int ui_camera_set_rect(int id, struct rect *r); + + + + +#endif + diff --git a/include_lib/system/ui/ui/ui_circle.h b/include_lib/system/ui/ui/ui_circle.h new file mode 100644 index 0000000..f2bf099 --- /dev/null +++ b/include_lib/system/ui/ui/ui_circle.h @@ -0,0 +1,66 @@ +#ifndef __CIRCLE_H__ +#define __CIRCLE_H__ + +#include "typedef.h" +#include "generic/rect.h" + +#define false 0 +#define true 1 + +#define COORD_MAX (16383) /*To avoid overflow don't let the max [-32,32k] range */ +#define COORD_MIN (-16384) +#define MATH_ABS(x) ((x)>0?(x):(-(x))) + +typedef struct { + uint16_t color; + uint16_t width; +} style_t; + +typedef struct { + uint16_t x; + uint16_t y; + uint16_t disp_x; + uint16_t disp_y; + uint16_t width; + uint16_t height; + uint16_t pitch; + uint16_t len; + uint8_t *buf; + int color; + int bitdepth; + struct rect *rect; + style_t *style; +} area_t; + +struct circle_info { + int x; + int y; + int disp_x; + int disp_y; + int center_x; + int center_y; + int radius_big; + int radius_small; + int angle_begin; + int angle_end; + int angle_curr; + int color; + int left; + int top; + int width; + int height; + int bitmap_width; + int bitmap_height; + int bitmap_pitch; + int bitmap_depth; + u8 *bitmap; + int bitmap_size; +}; + +void draw_arc(int16_t center_x, int16_t center_y, uint16_t radius, uint16_t start_angle, uint16_t end_angle, const area_t *area); + +void draw_circle_by_percent(struct circle_info *info, u8 percent); + +#endif + + diff --git a/include_lib/system/ui/ui/ui_core.h b/include_lib/system/ui/ui/ui_core.h new file mode 100644 index 0000000..45e468a --- /dev/null +++ b/include_lib/system/ui/ui/ui_core.h @@ -0,0 +1,565 @@ +#ifndef UI_ELEMENT_CORE_H +#define UI_ELEMENT_CORE_H + +#include "typedef.h" +#include "rect.h" +#include "system/event.h" +#include "fs/fs.h" + + +#define UI_CTRL_BUTTON 0 + +struct element; + + +#ifdef offsetof +#undef offsetof +#endif +#ifdef container_of +#undef container_of +#endif + +#define offsetof(type, memb) \ +((unsigned long)(&((type *)0)->memb)) + +#define container_of(ptr, type, memb) \ +((type *)((char *)ptr - offsetof(type, memb))) + +enum ui_direction { + UI_DIR_UP, + UI_DIR_DOWN, + UI_DIR_LEFT, + UI_DIR_RIGHT, +}; + +enum ui_align { + UI_ALIGN_LEFT = 0, + UI_ALIGN_CENTER, + UI_ALIGN_RIGHT, +}; + + +enum { + POSITION_ABSOLUTE = 0, + POSITION_RELATIVE = 1, +}; + +enum { + ELM_EVENT_TOUCH_DOWN, + ELM_EVENT_TOUCH_MOVE, + ELM_EVENT_TOUCH_R_MOVE, + ELM_EVENT_TOUCH_L_MOVE, + ELM_EVENT_TOUCH_D_MOVE, + ELM_EVENT_TOUCH_U_MOVE, + ELM_EVENT_TOUCH_HOLD, + ELM_EVENT_TOUCH_UP, +}; + + +enum { + ELM_EVENT_KEY_CLICK, + ELM_EVENT_KEY_LONG, + ELM_EVENT_KEY_HOLD, +}; + +enum { + ELM_STA_INITED, + //ELM_STA_SHOW_PROBE, + //ELM_STA_SHOW_POST, + ELM_STA_HIDE, + ELM_STA_SHOW, + ELM_STA_PAUSE, +}; + +enum { + ELM_FLAG_NORMAL, + ELM_FLAG_HEAD, +}; + +enum { + DC_DATA_FORMAT_OSD8 = 0, + DC_DATA_FORMAT_YUV420 = 1, + DC_DATA_FORMAT_OSD16 = 2, + DC_DATA_FORMAT_OSD8A = 3, + DC_DATA_FORMAT_MONO = 4, +}; + + +struct element_touch_event { + int event; + int xoffset; + int yoffset; + u8 hold_up; + u8 onfocus; + u8 move_dir; + struct position pos; + struct position mov; + void *private_data; +}; + +struct element_key_event { + u8 event; + u8 value; + void *private_data; +}; + +#define ELM_KEY_EVENT(e) (0x0000 | (e->event) | (e->value << 8)) +#define ELM_TOUCH_EVENT(e) (0x1000 | (e->event)) +#define ELM_CHANGE_EVENT(e) (0x2000 | (e->event)) + +enum element_change_event { + ON_CHANGE_INIT_PROBE, + ON_CHANGE_INIT, + ON_CHANGE_TRY_OPEN_DC, + ON_CHANGE_FIRST_SHOW, + ON_CHANGE_SHOW_PROBE, + ON_CHANGE_SHOW, + ON_CHANGE_SHOW_POST, + ON_CHANGE_HIDE, + ON_CHANGE_HIGHLIGHT, + ON_CHANGE_RELEASE_PROBE, + ON_CHANGE_RELEASE, + ON_CHANGE_ANIMATION_END, + ON_CHANGE_SHOW_COMPLETED, + ON_CHANGE_UPDATE_ITEM, +}; + + +struct element_event_handler { + int id; + int (*ontouch)(void *, struct element_touch_event *); + int (*onkey)(void *, struct element_key_event *); + int (*onchange)(void *, enum element_change_event, void *); +}; + +struct jaction { + u32 show; + u32 hide; +}; + +enum { + ELM_ACTION_HIDE = 0, + ELM_ACTION_SHOW, + ELM_ACTION_TOGGLE, + ELM_ACTION_HIGHLIGHT, +}; + +struct event_action { + u16 event; + u16 action; + int id; + u8 argc; + char argv[]; +}; + +struct element_event_action { + u16 num; + struct event_action action[0]; +}; + +struct image_preview { + FILE *file; + int id; + int page; +}; + + +struct image { + int x; + int y; + int id; + int page; + int en; +}; + +struct draw_context { + u8 ref; + u8 alpha; + u8 align; + u8 data_format; + u8 prj; + u8 page; + u8 buf_num; + u32 background_color; + void *handl; + struct element *elm; + struct rect rect; + struct rect draw; + void *dc; + + struct image_preview preview; + + struct rect need_draw; + struct rect disp; + u16 width; + u16 height; + u8 *fbuf; + u32 fbuf_len; + u8 *buf; + u8 *buf0; + u8 *buf1; + u32 len; + u16 lines; + u8 col_align; + u8 row_align; + + struct image draw_img; + + u8 *mask; +}; + +struct css_border { + u16 left: 4; + u16 top: 4; + u16 right: 4; + u16 bottom: 4; + u16 color: 16; +}; + +struct css_border1 { + u8 left; + u8 top; + u8 right; + u8 bottom; + int color: 24; +}; + +struct element_css { + u8 align: 2; + u8 invisible: 1; + u8 z_order: 5; + int left/* : 16 */; + int top/* : 16 */; + int width/* : 16 */; + int height/* : 16 */; + u32 background_color: 24; + u32 alpha: 8; + int background_image: 24; + int image_quadrant: 8; + struct css_border border; +}; + +struct element_css1 { + u8 align; + u8 invisible; + u8 z_order; + int left; + int top; + int width; + int height; + u32 background_color: 24; + u32 alpha: 8; + int background_image: 24; + int image_quadrant: 8; + struct css_border1 border; +}; + +struct element_ops { + int (*show)(struct element *); + int (*redraw)(struct element *, struct rect *); +}; + +struct element { + u32 highlight: 1; + u32 state: 2; + u32 ref: 5; + u32 prj: 3; + u32 page: 21; + // u32 alive; + int id; + struct element *parent; + struct list_head sibling; + struct list_head child; + struct element *focus; + struct element_css css; + struct draw_context *dc; + // const struct element_ops *ops; + const struct element_event_handler *handler; + // const struct element_event_action *action; +}; + +struct ui_style { + const char *file; + u32 version; +}; + +enum { + UI_FTYPE_VIDEO = 0, + UI_FTYPE_IMAGE, + UI_FTYPE_AUDIO, + UI_FTYPE_DIR, + UI_FTYPE_UNKNOW = 0xff, +}; + +struct ui_file_attrs { + char *format; + char fname[128]; + struct vfs_attr attr; + u8 ftype; + u16 file_num; + u32 film_len; +}; + +struct ui_image_attrs { + u16 width; + u16 height; +}; + +struct ui_text_attrs { + const char *str; + const char *format; + int color; + u16 strlen; + u16 offset; + u8 encode: 2; + u8 endian: 1; + u8 flags: 5; + // u16 offset; + u8 displen; +}; + +struct ui_file_browser { + int file_number; + u8 dev_num; + void *private_data; +}; + +#define ELEMENT_ALIVE 0x53547a7b + +#define element_born(elm) \ + elm->alive = ELEMENT_ALIVE + +#define element_alive(elm) \ + (elm->alive == ELEMENT_ALIVE) + + +#define list_for_each_child_element(p, elm) \ + list_for_each_entry(p, &(elm)->child, sibling) + +#define list_for_each_child_element_reverse(p, n, elm) \ + list_for_each_entry_reverse_safe(p, n, &(elm)->child, sibling) + +#define list_for_each_child_element_safe(p, n, elm) \ + list_for_each_entry_safe(p, n, &(elm)->child, sibling) + +struct ui_platform_api { + void *(*malloc)(int); + void (*free)(void *); + + int (*load_style)(struct ui_style *); + + void *(*load_window)(int id); + void (*unload_window)(void *); + + int (*open_draw_context)(struct draw_context *); + int (*get_draw_context)(struct draw_context *); + int (*put_draw_context)(struct draw_context *); + int (*set_draw_context)(struct draw_context *); + int (*close_draw_context)(struct draw_context *); + + int (*fill_rect)(struct draw_context *, u32 color); + int (*draw_rect)(struct draw_context *, struct css_border *border); + int (*draw_image)(struct draw_context *, u32 src, u8 quadrant, u8 *mask); + int (*draw_point)(struct draw_context *, u16 x, u16 y, u32 color); + u32(*read_point)(struct draw_context *dc, u16 x, u16 y); + int (*invert_rect)(struct draw_context *, u32 color); + + void *(*load_widget_info)(void *_head, u8 page); + void *(*load_css)(u8 page, void *_css); + void *(*load_image_list)(u8 page, void *_list); + void *(*load_text_list)(u8 page, void *__list); + + //int (*highlight)(struct draw_context *); + int (*show_text)(struct draw_context *, struct ui_text_attrs *); + int (*read_image_info)(struct draw_context *, u32, u8, struct ui_image_attrs *); + + int (*open_device)(struct draw_context *, const char *device); + int (*close_device)(int); + + void *(*set_timer)(void *, void (*callback)(void *), u32 msec); + int (*del_timer)(void *); + + struct ui_file_browser *(*file_browser_open)(struct rect *r, + const char *path, const char *ftype, int show_mode); + + int (*get_file_attrs)(struct ui_file_browser *, struct ui_file_attrs *attrs); + + int (*set_file_attrs)(struct ui_file_browser *, struct ui_file_attrs *attrs); + + int (*clear_file_preview)(struct ui_file_browser *, struct rect *r); + + int (*show_file_preview)(struct ui_file_browser *, struct rect *r, struct ui_file_attrs *attrs); + + int (*flush_file_preview)(struct ui_file_browser *); + + void *(*open_file)(struct ui_file_browser *, struct ui_file_attrs *attrs); + int (*delete_file)(struct ui_file_browser *, struct ui_file_attrs *attrs); + + int (*move_file_preview)(struct ui_file_browser *_bro, struct rect *dst, struct rect *src); + + void (*file_browser_close)(struct ui_file_browser *); + +}; + +extern /* const */ struct ui_platform_api *platform_api; + +extern /* const */ struct element_event_handler dumy_handler; + +struct janimation { + u8 persent[5]; + u8 direction; + u8 play_state; + u8 iteration_count; + u16 delay; + u16 duration; + struct element_css css[0]; +}; + + +extern struct element_event_handler *elm_event_handler_begin; +extern struct element_event_handler *elm_event_handler_end; + + +#define ___REGISTER_UI_EVENT_HANDLER(style, _id) \ + static const struct element_event_handler element_event_handler_##_id \ + sec(.elm_event_handler_##style) __attribute__((used)) = { \ + .id = _id, + +#define __REGISTER_UI_EVENT_HANDLER(style, _id) \ + ___REGISTER_UI_EVENT_HANDLER(style, _id) + +#define REGISTER_UI_EVENT_HANDLER(id) \ + __REGISTER_UI_EVENT_HANDLER(STYLE_NAME, id) + + + +struct ui_style_info { + const char *name; + struct element_event_handler *begin; + struct element_event_handler *end; +}; + +extern struct ui_style_info ui_style_begin[]; +extern struct ui_style_info ui_style_end[]; + +#define __REGISTER_UI_STYLE(style_name) \ + extern struct element_event_handler elm_event_handler_begin_##style_name[]; \ + extern struct element_event_handler elm_event_handler_end_##style_name[]; \ + static const struct ui_style_info ui_style_##style_name sec(.ui_style) __attribute__((used)) = { \ + .name = #style_name, \ + .begin = elm_event_handler_begin_##style_name, \ + .end = elm_event_handler_end_##style_name, \ + }; + +#define REGISTER_UI_STYLE(style_name) \ + __REGISTER_UI_STYLE(style_name) + + +static inline struct element_event_handler *element_event_handler_for_id(u32 id) +{ + struct element_event_handler *p; + + for (p = elm_event_handler_begin; p < elm_event_handler_end; p++) { + if (p->id == id) { + return p; + } + } + + return NULL; +} + + + + +#define ui_core_get_element_css(elm) \ + &((struct element *)(elm))->css + +#define ui_core_element_invisable(elm, i) \ + ((struct element *)(elm))->css.invisible = i + + +int ui_core_init(const struct ui_platform_api *api, struct rect *rect); + +int ui_core_set_style(const char *style); + +void ui_core_set_rotate(int _rotate); + +int ui_core_get_rotate(); + + +void *ui_core_malloc(int size); + +void ui_core_free(void *buf); + +void ui_core_element_init(struct element *, + u32 id, + u8 page, + u8 prj, + /* const */ struct element_css1 *, + const struct element_event_handler *, + const struct element_event_action *); + +void ui_core_get_element_abs_rect(struct element *elm, struct rect *rect); + +void ui_core_append_child(void *_child); + +struct element *ui_core_get_first_child(); + +void ui_core_remove_element(void *_child); + + +int ui_core_open_draw_context(struct draw_context *dc, struct element *elm); + +int ui_core_close_draw_context(struct draw_context *dc); + +int ui_core_show(void *_elm, int init); + +int ui_core_hide(void *_elm); + +struct element *get_element_by_id(struct element *elm, u32 id); + +struct element *ui_core_get_element_by_id(u32 id); +int ui_core_get_disp_status_by_id(u32 id); + +struct element *ui_core_get_up_element(struct element *elm); +struct element *ui_core_get_down_element(struct element *elm); +struct element *ui_core_get_left_element(struct element *elm); +struct element *ui_core_get_right_element(struct element *elm); + +int ui_core_element_ontouch(struct element *, struct element_touch_event *e); + +int ui_core_ontouch(struct element_touch_event *e); + +int ui_core_element_onkey(struct element *elm, struct element_key_event *e); + +int ui_core_onkey(struct element_key_event *e); + +void ui_core_element_append_child(struct element *parent, struct element *child); + +struct element_css *ui_core_set_element_css(void *_elm, const struct element_css1 *css); + +int ui_core_invert_rect(struct draw_context *dc); + +void ui_core_release_child_probe(struct element *elm); + +void ui_core_release_child(struct element *elm); + + +int ui_core_redraw(void *_elm); + +int ui_core_highlight_element(struct element *elm, int yes); + +void ui_core_element_on_focus(struct element *elm, int yes); + + +void ui_core_ontouch_lose_focus(struct element *elm); + +void ui_core_ontouch_lock(struct element *elm); + +void ui_core_ontouch_unlock(struct element *elm); + +int ui_core_get_draw_context(struct draw_context *dc, struct element *elm, struct rect *draw); +#endif + + + diff --git a/include_lib/system/ui/ui/ui_grid.h b/include_lib/system/ui/ui/ui_grid.h new file mode 100644 index 0000000..e013abf --- /dev/null +++ b/include_lib/system/ui/ui/ui_grid.h @@ -0,0 +1,138 @@ +#ifndef UI_GRID_H +#define UI_GRID_H + + +#include "ui/ui_core.h" +#include "ui/control.h" + +enum { + GRID_SCROLL_MODE, + GRID_PAGE_MODE, +}; + +enum { + SCROLL_DIRECTION_NONE, + SCROLL_DIRECTION_LR, + SCROLL_DIRECTION_UD, +}; + +struct ui_grid_item_info { + u8 row; + u8 col; + u8 page_mode; + u8 highlight_index; + u16 interval; + struct layout_info *info; +}; + +struct scroll_area { + int left; + int top; + int right; + int bottom; +}; + + +struct ui_grid_dynamic { + int dhi_index; + int dcol_num; + int drow_num; + + int min_row_index; + int max_row_index; + int min_col_index; + int max_col_index; + int min_show_row_index; + int max_show_row_index; + int min_show_col_index; + int max_show_col_index; + + int grid_xval; + int grid_yval; + u8 grid_col_num; + u8 grid_row_num; + u8 grid_show_row; + u8 grid_show_col; +}; + +struct ui_grid { + struct element elm; + // char hi_num; + char hi_index; + char touch_index; + char onfocus; + u8 page_mode; + u8 slide_direction; + u8 col_num; + u8 row_num; + u8 show_row; + u8 show_col; + u8 avail_item_num; + u8 pix_scroll; + u8 ctrl_num; + // u8 rotate; + int x_interval; + int y_interval; + int max_show_left; + int max_show_top; + int min_show_left; + int min_show_top; + int max_left; + int max_top; + int min_left; + int min_top; + // int scroll_step; + // u8 ctrl_num; + struct scroll_area *area; + struct layout *item; + struct layout_info *item_info; + // struct element elm2; + struct ui_grid_dynamic *dynamic; + struct position pos; + struct draw_context dc; + const struct ui_grid_info *info; + const struct element_event_handler *handler; +}; + +extern const struct element_event_handler grid_elm_handler; + +static inline int ui_grid_cur_item(struct ui_grid *grid) +{ + if (grid->touch_index >= 0) { + return grid->touch_index; + } + return grid->hi_index; +} + +#define ui_grid_set_item(grid, index) (grid)->hi_index = index + +void ui_grid_enable(); +void ui_grid_on_focus(struct ui_grid *grid); +void ui_grid_lose_focus(struct ui_grid *grid); +void ui_grid_state_reset(struct ui_grid *grid, int highlight_item); +int ui_grid_highlight_item(struct ui_grid *grid, int item, bool yes); +int ui_grid_highlight_item_by_id(int id, int item, bool yes); +struct ui_grid *__ui_grid_new(struct element_css1 *css, int id, struct ui_grid_item_info *info, struct element *parent); +int ui_grid_slide(struct ui_grid *grid, int direction, int steps); +int ui_grid_set_item_num(struct ui_grid *grid, int item_num); +int ui_grid_set_slide_direction(struct ui_grid *grid, int dir); +int ui_grid_slide_with_callback(struct ui_grid *grid, int direction, int steps, void(*callback)(void *ctrl)); + +int ui_grid_dynamic_slide(struct ui_grid *grid, int direction, int steps);//动态列表滚动 +int ui_grid_dynamic_create(struct ui_grid *grid, int direction, int list_total, int (*event_handler_cb)(void *, int, int, int)); //动态列表创建 +int ui_grid_dynamic_release(struct ui_grid *grid);//动态列表释放 + +int ui_grid_dynamic_cur_item(struct ui_grid *grid);//动态列表获取选项 +int ui_grid_dynamic_set_item_by_id(int id, int count);//修改动态列表数 +int ui_grid_dynamic_reset(struct ui_grid *grid, int index); //重置动态列表 +void ui_grid_set_scroll_area(struct ui_grid *grid, struct scroll_area *area); + +int ui_grid_init_dynamic(struct ui_grid *grid, int *row, int *col); +int ui_grid_add_dynamic(struct ui_grid *grid, int *row, int *col, int redraw); +int ui_grid_del_dynamic(struct ui_grid *grid, int *row, int *col, int redraw); + + +#endif + + + diff --git a/include_lib/system/ui/ui/ui_number.h b/include_lib/system/ui/ui/ui_number.h new file mode 100644 index 0000000..7cc1a2a --- /dev/null +++ b/include_lib/system/ui/ui/ui_number.h @@ -0,0 +1,44 @@ +#ifndef UI_NUMBER_H +#define UI_NUMBER_H + + +#include "ui/control.h" +#include "ui/ui_core.h" +#include "ui/p.h" + +enum { + TYPE_NUM, + TYPE_STRING, +}; + +struct unumber { + u8 numbs; + u8 type; + u32 number[2]; + u8 *num_str; +}; + +struct ui_number { + struct element_text text; + char source[8]; + u16 number[2]; + u16 buf[20]; + + int color; + int hi_color; + u8 css_num; + u8 nums: 6; + u8 type: 2; + u32 css[2]; + u8 *num_str; + const struct ui_number_info *info; + const struct element_event_handler *handler; +}; + +void ui_number_enable(); +void *new_ui_number(const void *_info, struct element *parent); +int ui_number_update(struct ui_number *number, struct unumber *n); +int ui_number_update_by_id(int id, struct unumber *n); + +#endif + diff --git a/include_lib/system/ui/ui/ui_pic.h b/include_lib/system/ui/ui/ui_pic.h new file mode 100644 index 0000000..c3a7ccb --- /dev/null +++ b/include_lib/system/ui/ui/ui_pic.h @@ -0,0 +1,29 @@ +#ifndef UI_PIC_H +#define UI_PIC_H + +#include "ui/ui_core.h" + + + + +struct ui_pic { + struct element elm; + u8 index; + // u8 css_num:2; + // u32 css[2]; + // u16 highlight_img; + // u16 normal_img; + // u16 highlight_img_num:8; + // u16 normal_img_num:8; + const struct ui_pic_info *info; + const struct element_event_handler *handler; +}; + +void ui_pic_enable(); +void *new_ui_pic(const void *_info, struct element *parent); +int ui_pic_show_image_by_id(int id, int index); +int ui_pic_set_image_index(struct ui_pic *pic, int index); +int ui_pic_get_normal_image_number_by_id(int id); +int ui_pic_get_highlgiht_image_number_by_id(int id); + +#endif diff --git a/include_lib/system/ui/ui/ui_progress.h b/include_lib/system/ui/ui/ui_progress.h new file mode 100644 index 0000000..1e89f56 --- /dev/null +++ b/include_lib/system/ui/ui/ui_progress.h @@ -0,0 +1,48 @@ +#ifndef UI_PROGRESS_H +#define UI_PROGRESS_H + + +#include "ui/control.h" +#include "ui/ui_core.h" + + +#define PROGRESS_CHILD_NUM (CTRL_PROGRESS_CHILD_END - CTRL_PROGRESS_CHILD_BEGIN) + + +struct progress_highlight_info { + struct ui_ctrl_info_head head; + u16 center_x; + u16 center_y; + u16 radius_big; + u16 radius_small; + u16 angle_begin; + u16 angle_end; + struct ui_image_list *img; +}; + +struct ui_progress { + struct element elm; + struct element child_elm[PROGRESS_CHILD_NUM]; + char source[8]; + u16 center_x; + u16 center_y; + u16 radius; + u16 angle_begin; + u16 angle_end; + u8 ctrl_num; + char percent; + u8 *mask; + u16 mask_len; + void *timer; + const struct layout_info *info; + const struct progress_highlight_info *pic_info[PROGRESS_CHILD_NUM]; + const struct element_event_handler *handler; +}; + +void ui_progress_enable(); +int ui_progress_set_persent_by_id(int id, int persent); +int ui_progress_set_persent(struct ui_progress *progress, int percent); + +#endif + + diff --git a/include_lib/system/ui/ui/ui_progress_multi.h b/include_lib/system/ui/ui/ui_progress_multi.h new file mode 100644 index 0000000..bca15d9 --- /dev/null +++ b/include_lib/system/ui/ui/ui_progress_multi.h @@ -0,0 +1,59 @@ +#ifndef UI_PROGRESS_MULTI_H +#define UI_PROGRESS_MULTI_H + + +#include "ui/control.h" +#include "ui/ui_core.h" + + +#define MULTIPROGRESS_CHILD_NUM (CTRL_MULTIPROGRESS_CHILD_END - CTRL_MULTIPROGRESS_CHILD_BEGIN) + +struct multiprogress_highlight_info { + struct ui_ctrl_info_head head; + u16 number; + u16 center_x; + u16 center_y; + u16 radius0_big; + u16 radius0_small; + u16 radius1_big; + u16 radius1_small; + u16 radius2_big; + u16 radius2_small; + u16 angle_begin; + u16 angle_end; + struct ui_image_list *img; +}; + +struct ui_multiprogress { + struct element elm; + struct element child_elm[MULTIPROGRESS_CHILD_NUM]; + char source[8]; + u16 center_x; + u16 center_y; + u16 radius; + u16 angle_begin; + u16 angle_end; + u8 ctrl_num; + char percent[3]; + u8 circle_num; + u8 index; + u8 *mask; + u16 mask_len; + void *timer; + const struct layout_info *info; + const struct multiprogress_highlight_info *pic_info[MULTIPROGRESS_CHILD_NUM]; + const struct element_event_handler *handler; +}; + +void ui_multiprogress_enable(); +int ui_multiprogress_set_persent_by_id(int id, int persent); +int ui_multiprogress_set_second_persent_by_id(int id, int percent); +int ui_multiprogress_set_third_persent_by_id(int id, int percent); + +int ui_multiprogress_set_persent(struct ui_multiprogress *multiprogress, int percent); +int ui_multiprogress_set_second_persent(struct ui_multiprogress *multiprogress, int percent); +int ui_multiprogress_set_third_persent(struct ui_multiprogress *multiprogress, int percent); + +#endif + + diff --git a/include_lib/system/ui/ui/ui_rotate.h b/include_lib/system/ui/ui/ui_rotate.h new file mode 100644 index 0000000..981f471 --- /dev/null +++ b/include_lib/system/ui/ui/ui_rotate.h @@ -0,0 +1,11 @@ +#ifndef __UI_ROTATE_H__ +#define __UI_ROTATE_H__ + +#include "rect.h" + +void rotate_0(unsigned char *src, unsigned char *src1, int sw, int sh, int cx, int cy, unsigned char *dst, int dw, int dh, int dx, int dy, struct rect *rect, int angle); +void rotate_1(unsigned char *tmp, unsigned char *src, int sw, int sh, int cx, int cy, unsigned char *dst, int dw, int dh, int dx, int dy, struct rect *rect, int angle); +void rotate_map(int sw, int sh, int scx, int scy, int *dw, int *dh, int dcx, int dcy, int angle); + +#endif + diff --git a/include_lib/system/ui/ui/ui_slider.h b/include_lib/system/ui/ui/ui_slider.h new file mode 100644 index 0000000..00e625f --- /dev/null +++ b/include_lib/system/ui/ui/ui_slider.h @@ -0,0 +1,41 @@ +#ifndef UI_SLIDER_H +#define UI_SLIDER_H + +#include "ui/ui_core.h" +#include "ui/control.h" + + +#define SLIDER_CHILD_NUM (SLIDER_CHILD_END - SLIDER_CHILD_BEGIN) + + +struct slider_text_info { + u8 move; + int min_value; + int max_value; + int text_color; +}; + + +struct ui_slider { + struct element elm; + struct element child_elm[SLIDER_CHILD_NUM]; + u8 step; + char persent; + s16 left; + s16 width; + s16 min_value; + s16 max_value; + u16 text_color; + const struct ui_slider_info *info; + const struct slider_text_info *text_info; + const struct element_event_handler *handler; +}; + +void ui_slider_enable(); +int ui_slider_set_persent_by_id(int id, int persent); +int ui_slider_set_persent(struct ui_slider *slider, int persent); + +int slider_touch_slider_move(struct ui_slider *slider, struct element_touch_event *e);//触摸滑动功能 + +#endif + diff --git a/include_lib/system/ui/ui/ui_slider_vert.h b/include_lib/system/ui/ui/ui_slider_vert.h new file mode 100644 index 0000000..6be61d1 --- /dev/null +++ b/include_lib/system/ui/ui/ui_slider_vert.h @@ -0,0 +1,40 @@ +#ifndef UI_SLIDER_VERT_H +#define UI_SLIDER_VERT_H + +#include "ui/ui_core.h" +#include "ui/control.h" + +#define VSLIDER_CHILD_NUM (VSLIDER_CHILD_END - VSLIDER_CHILD_BEGIN) + +struct vslider_text_info { + u8 move; + int min_value; + int max_value; + int text_color; +}; + + +struct ui_vslider { + struct element elm; + struct element child_elm[VSLIDER_CHILD_NUM]; + u8 step; + char persent; + s16 top; + s16 height; + u16 min_value; + u16 max_value; + u16 text_color; + const struct ui_slider_info *info; + const struct vslider_text_info *text_info; + const struct element_event_handler *handler; +}; + + +void ui_vslider_enable(); +int ui_vslider_set_persent_by_id(int id, int persent); +int ui_vslider_set_persent(struct ui_vslider *vslider, int persent); + +int vslider_touch_slider_move(struct ui_vslider *vslider, struct element_touch_event *e);//触摸滑动功能 + +#endif + diff --git a/include_lib/system/ui/ui/ui_text.h b/include_lib/system/ui/ui/ui_text.h new file mode 100644 index 0000000..ba3dcf2 --- /dev/null +++ b/include_lib/system/ui/ui/ui_text.h @@ -0,0 +1,53 @@ +#ifndef UI_TEXT_H +#define UI_TEXT_H + +#include "ui/ui_core.h" +#include "ui/control.h" +#include "font/font_all.h" + + +struct ui_text { + struct element elm; + struct ui_text_attrs attrs; + char source[8]; + void *timer; + + char _str[UI_TEXT_LIST_MAX_NUM]; + char _format[7]; + u8 str_num; + // u8 str_num:4; + // u8 css_num:4; + // u32 css[2]; + // u16 attr_color; + // u16 attr_highlight_color; + // struct ui_text_attrs attrs; + const struct ui_text_info *info; + const struct element_event_handler *handler; +}; + + + +void ui_text_enable(); +void *new_ui_text(const void *_info, struct element *parent); +/*api of format 'ascii'*/ +int ui_text_set_str(struct ui_text *text, const char *format, const char *str, int strlen, u32 flags); +int ui_text_set_str_by_id(int id, const char *format, const char *str); +/*api of format 'strpic'*/ +int ui_text_set_index(struct ui_text *text, int index); +int ui_text_show_index_by_id(int id, int index); +/*api of format 'text'*/ +void ui_text_set_text_attrs(struct ui_text *text, const char *str, int strlen, u8 encode, u8 endian, u32 flags); +int ui_text_set_text_by_id(int id, const char *str, int strlen, u32 flags); +int ui_text_set_textw_by_id(int id, const char *str, int strlen, int endian, u32 flags); +int ui_text_set_textu_by_id(int id, const char *str, int strlen, u32 flags); + +void text_release(struct ui_text *text); +/* + * 注意: + * 1.store_buf必须是全局或者静态,不能是局部,大小为index_num+1 + * 2.index_buf表示当前文本控件字符串id的序号,从0开始 + * 3.index_num表示有多少个字符串id拼起来 + * */ +int ui_text_set_combine_index(struct ui_text *text, u8 *store_buf, u8 *index_buf, int index_num); + +#endif diff --git a/include_lib/system/ui/ui/ui_time.h b/include_lib/system/ui/ui/ui_time.h new file mode 100644 index 0000000..e9f5bc2 --- /dev/null +++ b/include_lib/system/ui/ui/ui_time.h @@ -0,0 +1,44 @@ +#ifndef UI_TIME_H +#define UI_TIME_H + + +#include "ui/control.h" +#include "ui/ui_core.h" +#include "ui/p.h" + +struct utime { + u16 year; + u8 month; + u8 day; + u8 hour; + u8 min; + u8 sec; +}; + +struct ui_time { + struct element_text text; + char source[8]; + u16 year: 12; + u16 month: 4; + u8 day; + u8 hour; + u8 min; + u8 sec; + u8 css_num; + u8 auto_cnt; + u32 css[2]; + int color; + int hi_color; + u16 buf[20]; + void *timer; + const struct ui_time_info *info; + const struct element_event_handler *handler; +}; + +void ui_time_enable(); +void *new_ui_time(const void *_info, struct element *parent); + +int ui_time_update(struct ui_time *time, struct utime *t); +int ui_time_update_by_id(int id, struct utime *time); + +#endif diff --git a/include_lib/system/ui/ui/ui_watch.h b/include_lib/system/ui/ui/ui_watch.h new file mode 100644 index 0000000..dc8bc2d --- /dev/null +++ b/include_lib/system/ui/ui/ui_watch.h @@ -0,0 +1,52 @@ +#ifndef UI_WATCH_H +#define UI_WATCH_H + + +#include "ui/control.h" +#include "ui/ui_core.h" + + +#define WATCH_CHILD_NUM (CTRL_WATCH_CHILD_END - CTRL_WATCH_CHILD_BEGIN) + + +struct watch_pic_info { + struct ui_ctrl_info_head head; + u16 cent_x; + u16 cent_y; + struct ui_image_list *img; +}; + +struct watch_css_info { + int left: 16; + int top: 16; + int width: 16; + int height: 16; +}; + +struct ui_watch { + struct element elm; + struct element child_elm[WATCH_CHILD_NUM]; + struct watch_css_info child_css[WATCH_CHILD_NUM]; + char source[8]; + u8 hour; + u8 min; + u8 sec; + u8 last_hour; + u8 last_min; + u8 last_sec; + u8 updata; + u8 ctrl_num; + void *timer; + const struct layout_info *info; + const struct watch_pic_info *pic_info[WATCH_CHILD_NUM]; + const struct element_event_handler *handler; +}; + + +void ui_watch_enable(); +int ui_watch_set_time_by_id(int id, int hour, int min, int sec); +int ui_watch_set_time(struct ui_watch *watch, int hour, int min, int sec); + +#endif + + diff --git a/include_lib/system/ui/ui/window.h b/include_lib/system/ui/ui/window.h new file mode 100644 index 0000000..00a417a --- /dev/null +++ b/include_lib/system/ui/ui/window.h @@ -0,0 +1,48 @@ +#ifndef UI_WINDOW_H +#define UI_WINDOW_H + + +#include "ui/layer.h" +#include "ui/ui_core.h" +#include "ui/control.h" +#include "list.h" + + + + + +struct window { + struct element elm; //must be first + u8 busy; + u8 hide; + u8 ctrl_num; + struct list_head entry; + struct layer *layer; + const struct window_info *info; + const struct element_event_handler *handler; + void *private_data; +}; + + +extern const struct window_info *window_table; + + + +#define REGISTER_WINDOW_EVENT_HANDLER(id) \ + REGISTER_UI_EVENT_HANDLER(id) + + +int window_show(int); + +int window_hide(int id); + +int window_toggle(int id); + +int window_ontouch(struct element_touch_event *e); + +int window_onkey(struct element_key_event *e); + + +#endif + + diff --git a/include_lib/system/ui/ui_simple/ui_res.h b/include_lib/system/ui/ui_simple/ui_res.h new file mode 100644 index 0000000..b412b0f --- /dev/null +++ b/include_lib/system/ui/ui_simple/ui_res.h @@ -0,0 +1,128 @@ +/******************************************************************************************* + File Name: ap_res.h + + Version: 1.00 + + Discription: + + Author:yulin deng + + Email :flowingfeeze@163.com + + Date:星期三, 六月 22 2011 + + Copyright:(c) 2011 @ , All Rights Reserved. +*******************************************************************************************/ +#ifndef __ap_res_h +#define __ap_res_h +#include "typedef.h" + +/****************************************************************** + ************************资源头的数据结构*************************** + 资源结构: + 资源头 res_head + ------------------------------------------ + 资源目录项 res_head_Item1(picture Item head) + res_head_Item2(string Item head) + res_head_Item3(multi-string Item head) + ------------------------------------------ + 资源索引表 res_entry1(picture 1) + ................ + res_entryN(picture N) + res_entry1(lang 1) + ................ + res_entryN(lang N) + -------------------------------------------- + 资源数据 picture data 1 + ................ + picture data N + Lang ID 1 entry + ................ + Lang ID N entry + Lang 1 string data + ................ + Lang N string data + ******************************************************************/ +#define RESHEADITEM 16 //各个entry长度,统一为16uint8s +#define GROUPDEFINE 6 +#define ROW_COUNT_DEF 6 +#define TYPE_DIR 0 +#define TYPE_FILE 1 + + +#ifndef uint8 +#define uint8 u8 +#endif +#ifndef uint16 +#define uint16 u16 +#endif +#ifndef uint32 +#define uint32 u32 +#endif +#ifndef int32 +#define int32 int +#endif + + + + +typedef struct { + uint8 magic[4]; //'R', 'U', '2', 0x19 + uint16 counts; //资源的个数 +} res_head_t; //6 uint8s + + +/*资源类型索引表的数据结构*/ +typedef struct { + uint32 dwOffset; //资源内容索引表的偏移 + uint16 wCount; //资源类型总数 + uint8 bItemType; //'P'--PIC Table,'S'--String Table,'X' -- XML File + uint8 type; +} res_entry_t; + +/*资源内容信息索引的数据结构*/ +typedef struct { + uint16 wWidth; //若是图片,则代表图片宽,若是字符串,则代表ID总数 + uint16 wHeight; //若是图片,则代表图片长,若是字符串,则代表该语言的ID. + uint32 bType; //资源类型,0x01--language string ,0x02--PIC + uint32 dwOffset; //图片数据区在文件内偏移,4 uint8s + uint32 dwLength; //资源长度, 最大 4G,4 uint8s +} res_infor_t; //13 uint8s + + +/*多国语言资源ID索引表的数据结构*/ +typedef struct { + uint32 dwOffset; // 字符ID号对应字符串编码在文件内的偏移 + uint16 dwLength; // 字符串长度.即unicode编码字符串的字节数 +} res_langid_entry_t; // 6 uint8s + +typedef struct { + uint8 filetype; //文件类型 0-- 目录 1 文件 + char name[12]; + int32 DirEntry; +} file_record_m; + +// extern res_entry_t res_entry; +u8 ResOpen(const char *filename); +void *ResGetFp(); +uint16 ResShowPic(uint16 pic_id, uint8 x, uint8 y); +uint16 ResShowMultiString(uint8 x, uint8 y, uint16 StringID); +void ResClose(); +u8 InitRes(); + + + + +#define LCDPAGE 8 +#define LCDCOLUMN 128 +#define SCR_WIDTH LCDCOLUMN +#define SCR_HEIGHT (LCDPAGE*8) + +#define MENUICONWIDTH 12 //菜单项目左边图标的宽度(象素) +#define MENUITEMHEIGHT 16 //菜单项目的高度(象素) +#define SCROLLBARWIDTH 6 //垂直滚动条的宽度(象素) + +extern u8 LCDBuff[LCDPAGE][LCDCOLUMN]; + + +#endif diff --git a/include_lib/system/user_cfg.h b/include_lib/system/user_cfg.h new file mode 100644 index 0000000..429a29a --- /dev/null +++ b/include_lib/system/user_cfg.h @@ -0,0 +1,122 @@ +#ifndef __USER_CFG_H__ +#define __USER_CFG_H__ + +#include "typedef.h" +#include "app_config.h" + +#define LOCAL_NAME_LEN 32 /*BD_NAME_LEN_MAX*/ + +//bt bin结构 +typedef struct __BT_CONFIG { + u8 edr_name[LOCAL_NAME_LEN]; //经典蓝牙名 + u8 mac_addr[6]; //蓝牙MAC地址 + u8 rf_power; //发射功率 + u8 dac_analog_gain; //通话DAC模拟增益 + u8 mic_analog_gain; //通话MIC增益 + u16 tws_device_indicate; /*设置对箱搜索标识,inquiry时候用,搜索到相应的标识才允许连接*/ + u8 tws_local_addr[6]; + u8 ble_name[LOCAL_NAME_LEN]; //ble蓝牙名 + u8 ble_mac_addr[6]; //ble蓝牙MAC地址 + u8 ble_rf_power; //ble发射功率 +} _GNU_PACKED_ BT_CONFIG; + +//audio bin结构 +typedef struct __AUDIO_CONFIG { + u8 sw; + u8 max_sys_vol; //最大系统音量 + u8 default_vol; //开机默认音量 + u8 tone_vol; //提示音音量 +} _GNU_PACKED_ AUDIO_CONFIG; + +//status bin结构体 +typedef struct __STATUS { + u8 charge_start; //开始充电 + u8 charge_full; //充电完成 + u8 power_on; //开机 + u8 power_off; //关机 + u8 lowpower; //低电 + u8 max_vol; //最大音量 + u8 phone_in; //来电 + u8 phone_out; //去电 + u8 phone_activ; //通话中 + u8 bt_init_ok; //蓝牙初始化完成 + u8 bt_connect_ok; //蓝牙连接成功 + u8 bt_disconnect; //蓝牙断开 + u8 tws_connect_ok; //TWS连接成功 + u8 tws_disconnect; //TWS蓝牙断开 +} _GNU_PACKED_ STATUS; + +typedef struct __STATUS_CONFIG { + u8 sw; + STATUS led; //led status + STATUS tone; //tone status +} _GNU_PACKED_ STATUS_CONFIG; + +//charge bin结构 +typedef struct __CHARGE_CONFIG { + u8 sw; //开关 + u8 poweron_en; //支持开机充电 + u8 full_v; //充满电压 + u8 full_c; //充满电流 + u8 charge_c; //充电电流 +} _GNU_PACKED_ CHARGE_CONFIG; + +//key +typedef struct __KEY_OP { + u8 short_msg; //短按消息 + u8 long_msg; //长按消息 + u8 hold_msg; //hold 消息 + u8 up_msg; //抬键消息 + u8 double_msg; //双击消息 + u8 triple_msg; //三击消息 +} _GNU_PACKED_ KEY_OP; + +//mic type +typedef struct __MIC_TYPE_CONFIG { + u8 type; //0:不省电容模式 1:省电容模式 + //1:16K 2:7.5K 3:5.1K 4:6.8K 5:4.7K 6:3.5K 7:2.9K 8:3K 9:2.5K 10:2.1K 11:1.9K 12:2K 13:1.8K 14:1.6K 15:1.5K 16:1K 31:0.6K + u8 pull_up; + //00:2.3v 01:2.5v 10:2.7v 11:3.0v + u8 ldo_lev; +} _GNU_PACKED_ MIC_TYPE_CONFIG; + + + +//自动关机时间配置 +typedef struct __AUTO_OFF_TIME_CONFIG { + u8 auto_off_time; +} _GNU_PACKED_ AUTO_OFF_TIME_CONFIG; + +//低电压提示配置 +typedef struct __AUTO_LOWPOWER_V_CONFIG { + u16 warning_tone_v; + u16 poweroff_tone_v; +} _GNU_PACKED_ AUTO_LOWPOWER_V_CONFIG; + +//LRC配置 +typedef struct __LRC_CONFIG { + u16 lrc_ws_inc; + u16 lrc_ws_init; + u16 btosc_ws_inc; + u16 btosc_ws_init; + u8 lrc_change_mode; +} _GNU_PACKED_ LRC_CONFIG; + +void cfg_file_parse(u8 idx); +const u8 *bt_get_mac_addr(); +void bt_get_tws_local_addr(u8 *addr); + +STATUS *get_led_config(void); +STATUS *get_tone_config(void); +void get_random_number(u8 *ptr, u8 len); +extern void bt_get_vm_mac_addr(u8 *addr); +extern u8 get_max_sys_vol(void); +extern const char *bt_get_local_name(); +extern u16 bt_get_tws_device_indicate(u8 *tws_device_indicate); +const char *bt_get_local_name(); +extern void bt_update_mac_addr(u8 *addr); +extern void bt_set_local_name(char *name, u8 len); +extern void bt_reset_and_get_mac_addr(u8 *addr); +extern void bt_set_pair_code_en(u8 en); + +#endif diff --git a/include_lib/system/wait.h b/include_lib/system/wait.h new file mode 100644 index 0000000..63e0911 --- /dev/null +++ b/include_lib/system/wait.h @@ -0,0 +1,16 @@ +#ifndef WAIT_COMPLETION_H +#define WAIT_COMPLETION_H + + + + + +int wait_completion_schedule(); + +u16 wait_completion(int (*condition)(void), int (*callback)(void *), void *priv); + +int wait_completion_del(u16 id); + + + +#endif diff --git a/include_lib/update/dual_bank_updata_api.h b/include_lib/update/dual_bank_updata_api.h new file mode 100644 index 0000000..b5bf086 --- /dev/null +++ b/include_lib/update/dual_bank_updata_api.h @@ -0,0 +1,64 @@ +#ifndef _DUAL_BANK_API_H_ +#define _DUAL_BANK_API_H_ + +/* @brief:Api for getting the buffer size for temporary storage + */ +u32 get_dual_bank_passive_update_max_buf(void); + +/* @brief:Initializes the update task,and setting the crc value and file size of new fw; + * @param fw_crc:crc value of new fw file + * @param fw_size:total size of new fw file + * @param priv:reserved + * @param max_ptk_len: Supported maxium length of every programming,it decides the max size of programming every time + */ +u32 dual_bank_passive_update_init(u16 fw_crc, u32 fw_size, u16 max_pkt_len, void *priv); + +/* @brief:exit the update task + * @param priv:reserved + */ +u32 dual_bank_passive_update_exit(void *priv); + +/* @brief:Judge whether enough space for new fw file + * @note: it should be called after dual_bank_passive_update_init(...); + * @param fw_size:fw size of new fw file + */ +u32 dual_bank_update_allow_check(u32 fw_size); + + +/* @brief:copy the data to temporary buffer and notify task to write non-volatile storage + * @param data:the pointer to download data + * @param len:the length to download data + * @param write_complete_cb:callback for programming done,return 0 if no err occurred +*/ +u32 dual_bank_update_write(void *data, u16 len, int (*write_complete_cb)(void *priv)); + +/* @brief: caculate all the data had flashed,and compare with the cre value intializeed when update init; + * @crc_init_hdl:if it equals NULL,use internal implementation(CRC16-CCITT Standard);otherwise,use user's customization; + * @crc_calc_hdl:if it equals NULL,use internal implementation(CRC16-CCITT Standard);otherwise,use user's customization; + * @verify_result_hdl:when the verification completed,this callback for result notification; + * if crc_res equals 1,crc verification passed,if 0,the verification failed. +*/ +u32 dual_bank_update_verify(void (*crc_init_hdl)(void), u16(*crc_calc_hdl)(u16 init_crc, u8 *data, u32 len), int (*verify_result_hdl)(int crc_res)); + + +/* @brief:After the new fw verification succeed,call this api to program the new boot info for new fw + * @param burn_boot_info_result_hdl:this callback for error notification + * if err equals 0,the operate to burn boot info succeed,other value means to fail. + */ +u32 dual_bank_update_burn_boot_info(int (*burn_boot_info_result_hdl)(int err)); + +enum { + + CLEAR_APP_RUNNING_BANK = 0, + CLEAR_APP_UPDATE_BANK, +}; + +/* @brief:this api for erasing the boot info of specific bank,it should be called much carefully + * @param type:it decides which bank's boot info would be erased; + * clean the boot info of running bank and call system_reset,system will run the other bank if available; + */ +int flash_update_clr_boot_info(u8 type); + +u8 dual_bank_update_verify_without_crc(void); +#endif + diff --git a/include_lib/update/uart_update.h b/include_lib/update/uart_update.h new file mode 100644 index 0000000..b247e4e --- /dev/null +++ b/include_lib/update/uart_update.h @@ -0,0 +1,43 @@ +#ifndef _UART_DEV_ +#define _UART_DEV_ + +#include "typedef.h" + +#define MSG_UART_UPDATE_READY 0x1 +#define MSG_UART_UPDATE_START 0x2 +#define MSG_UART_UPDATE_START_RSP 0X3 +#define MSG_UART_UPDATE_READ_RSP 0x4 + +#define PROTOCAL_SIZE 528 +#define SYNC_SIZE 6 +#define SYNC_MARK0 0xAA +#define SYNC_MARK1 0x55 + +typedef union { + u8 raw_data[PROTOCAL_SIZE + SYNC_SIZE]; + struct { + u8 mark0; + u8 mark1; + u16 length; + u8 data[PROTOCAL_SIZE + 2]; //最后CRC16 + } data; +} protocal_frame_t; + +struct file_info { + u8 cmd; + u32 addr; + u32 len; +} __attribute__((packed)); + +typedef struct __update_io { + u16 rx; + u16 tx; + u8 input_channel; //input channel选择,根据方案选择未被使用的channel + u8 output_channel; //同input channel +} uart_update_cfg; + +void uart_update_init(uart_update_cfg *cfg); +void sava_uart_update_param(void); + +#endif + diff --git a/include_lib/update/update.h b/include_lib/update/update.h new file mode 100644 index 0000000..a328b7a --- /dev/null +++ b/include_lib/update/update.h @@ -0,0 +1,144 @@ +#ifndef _UPDATE_H_ +#define _UPDATE_H_ + +#include "typedef.h" + +extern u32 UPDATA_BEG; + +#define UPDATA_FLAG_ADDR ((void *)((u32)&UPDATA_BEG + 0x08)) +#define BOOT_STATUS_ADDR ((void *)((u32)&UPDATA_BEG)) //预留8个bytes + +#define UPDATA_MAGIC (0x5A00) //防止CRC == 0 的情况 + +typedef enum { + UPDATA_NON = UPDATA_MAGIC, + UPDATA_READY, + UPDATA_SUCC, + UPDATA_PARM_ERR, + UPDATA_DEV_ERR, + UPDATA_KEY_ERR, +} UPDATA_RESULT; + +typedef enum { + USB_UPDATA = UPDATA_MAGIC, //0x5A00 + SD0_UPDATA, //0x5A01 + SD1_UPDATA, + PC_UPDATA, + UART_UPDATA, + BT_UPDATA, + BLE_APP_UPDATA, + SPP_APP_UPDATA, + DUAL_BANK_UPDATA, + BLE_TEST_UPDATA, + NORFLASH_UPDATA, + //NOTE:以上的定义不要调整,新升级方式在此下面定义; + USER_NORFLASH_UFW_UPDATA, + + NON_DEV = 0xFFFF, +} UPDATA_TYPE; + +// sd +enum { + SD_CONTROLLER_0 = 1, + SD_CONTROLLER_1, +}; +enum { + SD0_IO_A = 1, + SD0_IO_B, + SD1_IO_A, + SD1_IO_B, + SD0_IO_C, + SD0_IO_D, + SD0_IO_E, + SD0_IO_F, +}; +typedef struct _UPDATA_SD { + u8 control_type; + u8 control_io; + u8 online_check_way; + u8 max_data_baud; + u16 wDevTimeOutMax; + u8 per_online_status; + u8 hc_mode; + u8(*io_det_func)(void); + u8 power; +} UPDATA_SD; + +// uart +typedef struct _UPDATA_UART { + u32 control_io_tx; // ram0 + + .bss (NOLOAD) :ALIGN(4) + { + update_bss_start = .; + + *(.update_bss) + update_bss_end = .; + } > ram0 + + .text : ALIGN(4) + { + update_code_start = .; + + *(.bt_updata_ram_code) + *(.update_const) + *(.update_code) + + update_code_end = .; + } > code0 + + + UPDATE_CODE_TOTAL_SIZE = update_code_end - update_code_start; +} + + diff --git a/include_lib/update/update_loader_download.h b/include_lib/update/update_loader_download.h new file mode 100644 index 0000000..6f82c06 --- /dev/null +++ b/include_lib/update/update_loader_download.h @@ -0,0 +1,176 @@ +#ifndef _UPDATE_LOADER_DOWNLOAD_H_ +#define _UPDATE_LOADER_DOWNLOAD_H_ + +#include "typedef.h" + +extern const int config_update_mode; +extern const int support_dual_bank_update_en; +#define UPDATE_MODULE_IS_SUPPORT(x) (config_update_mode & x) +#define UPDATE_SUPPORT_DEV_IS_NULL() (config_update_mode == UPDATE_DEV_NULL) +#define UPDATE_DUAL_BANK_IS_SUPPORT() (1 == support_dual_bank_update_en) + +struct __tws_ota_para { + u32 fm_size; + u16 fm_crc16; + u16 max_pkt_len; +}; + +typedef struct _ret_code { + int stu; + u8 err_code; +} update_ret_code_t; + +typedef struct _update_op_api_tws { + //for tws ota start + int (*tws_ota_start)(void *priv); + int (*tws_ota_data_send)(u8 *buf, u16 len); + int (*tws_ota_err)(u8); + u16(*enter_verfiy_hdl)(void *priv); + u16(*exit_verify_hdl)(u8 *, u8 *); + u16(*update_boot_info_hdl)(void *priv); + int (*tws_ota_result_hdl)(u8); + int (*tws_ota_data_send_pend)(void); + //for user chip update + int (*tws_ota_user_chip_update_send)(u8 cmd, u8 *buf, u16 len); +} update_op_tws_api_t; //给tws同步升级用的接口 + +typedef struct _update_op_api_t { + void (*ch_init)(void (*resume_hdl)(void *priv), int (*sleep_hdl)(void *priv)); + u16(*f_open)(void); + u16(*f_read)(void *fp, u8 *buff, u16 len); + int (*f_seek)(void *fp, u8 type, u32 offset); + u16(*f_stop)(u8 err); + int (*notify_update_content_size)(void *priv, u32 size); + void (*ch_exit)(void *priv); +} update_op_api_t; + +extern const update_op_api_t lmp_ch_update_op; +extern const update_op_api_t strg_ch_update_op; +extern const update_op_api_t rcsp_update_op; + +#define UPDATE_SEAGNMENT_EN 1 + +enum { + UPDATE_LOADER_OK = 1, + UPDATE_LOADER_ERR, +}; + +//update result code bitmap +#define UPDATE_RESULT_FLAG_BITMAP BIT(7) + +//update result code; +enum { + UPDATE_RESULT_ERR_NONE = 0, + UPDATE_RESULT_FILE_SIZE_ERR = 0x1, //文件大小错误 + UPDATE_RESULT_LOADER_SIZE_ERR = 0x2, //loader大小错误 + UPDATE_RESULT_LOADER_VERIFY_ERR, //update loader校验失败 + UPDATE_RESULT_REMOTE_FILE_HEAD_ERR, //读升级文件头错误 + + UPDATE_RESULT_LOCAL_FILE_HEAD_ERR = 0x5, //读flash文件头错误 + UPDATE_RESULT_NOT_FIND_TARGET_FILE_ERR, //找不到目标文件 + UPDATE_RESULT_FILE_OPERATION_ERR, //文件操作失败 + UPDATE_RESULT_FLASH_DATA_VERIFY_ERR, //flash数据校验失败 + + UPDATE_RESULT_UBOOT_NOT_MATCH = 0x09, //UBOOT不匹配 + UPDATE_RESULT_PRODUCT_INFO_NOT_MATCH = 0x0a, //芯片型号不匹配 + UPDATE_RESULT_EX_DSP_UPDATE_ERR, //外部IC升级出错; + UPDATE_RESULT_CFG_UPDATE_ERR, //配置升级出错 + + UPDATE_RESULT_FLASH_ERASE_ERR = 0x0d, //flash 擦失败(可能是写保护) + UPDATE_RESULT_REMOTE_FILE_NOT_MATCH, //升级文件不匹配 + UPDATE_RESULT_ANC_CFG_UPDATE_ERR, //ANC配置升级出错 + UPDATE_RESULT_ANC_COEF_UPDATE_ERR, //ANC配置升级出错 + UPDATE_RESULT_OTA_TWS_NO_RSP, //对耳同步升级传输数据没有回复 + UPDATE_RESULT_RESOURCE_LIMIT, //资源不足 + UPDATE_RESULT_OTA_TWS_START_ERR, //对耳启动升级失败 + UPDATE_RESULT_OTA_TWS_CRC_ERROR, //对耳校验失败 + UPDATE_RESULT_OTA_APP_EXIT, //升级过程APP强制退出 +}; + +#include "system/task.h" +typedef struct _update_type_info_t { + int type; + u8 task_en; + void (*cb)(void *priv, int type, u8 cmd); + void *cb_priv; + update_op_api_t *p_op_api; + void (*common_state_cbk)(int type, u32 status, u32 code); + OS_SEM update_sem; +} update_type_info_t; + +typedef struct _update_mode_info_t { + s32 type; + void (*state_cbk)(int type, u32 status, void *priv); + const update_op_api_t *p_op_api; + u8 task_en; +} update_mode_info_t; + +typedef struct _succ_report_t { + u32 loader_saddr; + u32 priv_param; + u32(*update_param_write_hdl)(u32 priv, u8 *buf, u16 len); +} succ_report_t; + +#define UPDATE_DEV_NULL 0 +#define UPDATE_BT_LMP_EN BIT(0) +#define UPDATE_STORAGE_DEV_EN BIT(1) +#define UPDATE_UART_EN BIT(2) +#define UPDATE_APP_EN BIT(3) //包括APP升级还有其他升级方式,如串口升级(非测试盒方式) +#define UPDATE_BLE_TEST_EN BIT(4) + +void bt_lmp_update_loader_download_init(void); +void ble_test_update_loader_download_init(void); +void storage_update_loader_download_init( + int type, + char *update_path, + void (*cb)(void *priv, int type, u8 cmd), + void *cb_priv, + u8 task_en +); + +typedef struct _user_chip_update_t { + u8 *file_name; + int (*update_init)(void *priv, update_op_api_t *file_ops); + int (*update_get_len)(void); + int (*update_loop)(void *priv); +} user_chip_update_t; + +typedef struct _user_chip_info_t { + union { + struct { + u32 file_addr; + }; + struct { + u32 addr; + }; + }; + u32 len; + u16 crc; + u32 dev_addr; +} user_chip_update_info_t; + +typedef struct _update_size_t { + u8 type; +} update_type_t; + +enum UPDATE_SIZE_TYPE { + UPDATE_LEN_TYPE_CONTENT = 0, + UPDATE_LEN_TYPE_LOADER, + UPDATE_LEN_TYPE_EX_IC, +}; + +void register_user_chip_update_handle(const user_chip_update_t *user_update_ins); +void rcsp_update_loader_download_init(int update_type, void (*result_cbk)(void *priv, u8 type, u8 cmd)); + +void app_update_loader_downloader_init( + int update_type, + void (*result_cbk)(void *priv, u8 type, u8 cmd), + void *cbk_priv, + update_op_api_t *p_op_api); +void update_tws_api_register(const update_op_tws_api_t *op); + +int app_active_update_task_init(update_mode_info_t *info); +int update_file_verify(u32 ufw_addr, u16(*ufw_read)(void *buf, u32 addr, u32 len)); + +#endif /*_UPDATE_LOADER_DOWNLOAD_H_*/ + diff --git a/make_prompt.bat b/make_prompt.bat new file mode 100644 index 0000000..97dcca3 --- /dev/null +++ b/make_prompt.bat @@ -0,0 +1,4 @@ +SET SCRIPT_PATH=%~dp0% +set PATH=%SCRIPT_PATH%\tools\utils;%PATH% + +cmd diff --git a/tools/make_prompt.bat b/tools/make_prompt.bat new file mode 100644 index 0000000..e42893f --- /dev/null +++ b/tools/make_prompt.bat @@ -0,0 +1,5 @@ +SET SCRIPT_PATH=%~dp0% +set PATH=%SCRIPT_PATH%\utils;%PATH% + +cd .. +cmd diff --git a/tools/utils/[.exe b/tools/utils/[.exe new file mode 100644 index 0000000..c71fba5 Binary files /dev/null and b/tools/utils/[.exe differ diff --git a/tools/utils/do_merge_libs.bat b/tools/utils/do_merge_libs.bat new file mode 100644 index 0000000..091500e --- /dev/null +++ b/tools/utils/do_merge_libs.bat @@ -0,0 +1,18 @@ +@echo off +setlocal enabledelayedexpansion +set INDIR=%1% +set MERGE=%2% +set AROUT=%3% + +echo %INDIR% +echo %MERGE% +echo %AROUT% + +set FILES= + +for /f "tokens=*" %%i in ('dir /b %INDIR%\*.a') DO SET FILES=!FILES! %INDIR%\%%i + +echo %FILES% + +%MERGE% --no-rewrite --output %AROUT% %FILES% + diff --git a/tools/utils/find.exe b/tools/utils/find.exe new file mode 100644 index 0000000..85192fb Binary files /dev/null and b/tools/utils/find.exe differ diff --git a/tools/utils/fixbat.exe b/tools/utils/fixbat.exe new file mode 100644 index 0000000..e6280d2 Binary files /dev/null and b/tools/utils/fixbat.exe differ diff --git a/tools/utils/libiconv2.dll b/tools/utils/libiconv2.dll new file mode 100644 index 0000000..747073f Binary files /dev/null and b/tools/utils/libiconv2.dll differ diff --git a/tools/utils/libintl3.dll b/tools/utils/libintl3.dll new file mode 100644 index 0000000..ec11e6b Binary files /dev/null and b/tools/utils/libintl3.dll differ diff --git a/tools/utils/ls.exe b/tools/utils/ls.exe new file mode 100644 index 0000000..96ff2e5 Binary files /dev/null and b/tools/utils/ls.exe differ diff --git a/tools/utils/make.exe b/tools/utils/make.exe new file mode 100644 index 0000000..17bfc2e Binary files /dev/null and b/tools/utils/make.exe differ diff --git a/tools/utils/merge-archives.exe b/tools/utils/merge-archives.exe new file mode 100644 index 0000000..07e1a2b Binary files /dev/null and b/tools/utils/merge-archives.exe differ diff --git a/tools/utils/mkdir_win.exe b/tools/utils/mkdir_win.exe new file mode 100644 index 0000000..f96d181 Binary files /dev/null and b/tools/utils/mkdir_win.exe differ diff --git a/tools/utils/override-seg.exe b/tools/utils/override-seg.exe new file mode 100644 index 0000000..3e759e2 Binary files /dev/null and b/tools/utils/override-seg.exe differ diff --git a/tools/utils/rm.exe b/tools/utils/rm.exe new file mode 100644 index 0000000..8e79306 Binary files /dev/null and b/tools/utils/rm.exe differ diff --git a/tools/utils/true.exe b/tools/utils/true.exe new file mode 100644 index 0000000..cb41f82 Binary files /dev/null and b/tools/utils/true.exe differ diff --git a/tools/utils/uname.exe b/tools/utils/uname.exe new file mode 100644 index 0000000..3e2f4cf Binary files /dev/null and b/tools/utils/uname.exe differ